From 6cea52b4bfa3a0f584efb08e6dcb1cf87926cb0c Mon Sep 17 00:00:00 2001 From: Richard Herman Date: Wed, 15 Apr 2026 16:10:51 +0100 Subject: [PATCH] chore: move @elgato/schemas to mono-repo --- .gitignore | 2 + packages/schemas/.prettierignore | 3 + packages/schemas/CHANGELOG.md | 248 ++ packages/schemas/README.md | 94 + packages/schemas/eslint.config.mjs | 3 + packages/schemas/jest.config.cjs | 31 + packages/schemas/package.json | 120 + packages/schemas/rollup.config.ts | 65 + packages/schemas/scripts/build.ts | 46 + packages/schemas/scripts/package.json | 3 + .../scripts/transformers/custom-keywords.ts | 140 + .../scripts/transformers/version-manifests.ts | 83 + packages/schemas/src/index.ts | 86 + .../schemas/src/streamdeck/plugins/README.md | 62 + .../src/streamdeck/plugins/device-type.ts | 74 + .../schemas/src/streamdeck/plugins/index.ts | 10 + .../schemas/src/streamdeck/plugins/json.ts | 2 + .../schemas/src/streamdeck/plugins/layout.ts | 335 ++ .../plugins/manifest/__tests__/all.test.ts | 289 ++ .../__tests__/files/Actions[].OS.json | 44 + .../files/Profiles[].AutoInstall.json | 50 + .../manifest/__tests__/files/v6.4.json | 90 + .../manifest/__tests__/files/v6.5.json | 90 + .../manifest/__tests__/files/v6.6.json | 91 + .../manifest/__tests__/files/v6.7.json | 91 + .../manifest/__tests__/files/v6.8.json | 91 + .../manifest/__tests__/files/v6.9.json | 93 + .../manifest/__tests__/files/v7.0.json | 94 + .../manifest/__tests__/files/v7.1.json | 94 + .../manifest/__tests__/files/v7.2.json | 94 + .../manifest/__tests__/files/v7.3.json | 94 + .../manifest/__tests__/files/v7.4.json | 94 + .../plugins/manifest/__tests__/v6.4.test.ts | 46 + .../plugins/manifest/__tests__/v6.5.test.ts | 46 + .../plugins/manifest/__tests__/v6.6.test.ts | 101 + .../plugins/manifest/__tests__/v6.9.test.ts | 59 + .../plugins/manifest/__tests__/v7.0.test.ts | 101 + .../plugins/manifest/__tests__/v7.1.test.ts | 84 + .../src/streamdeck/plugins/manifest/latest.ts | 752 +++++ .../src/streamdeck/plugins/manifest/v6.4.ts | 16 + .../src/streamdeck/plugins/manifest/v6.5.ts | 33 + .../src/streamdeck/plugins/manifest/v6.6.ts | 28 + .../src/streamdeck/plugins/manifest/v6.9.ts | 23 + .../src/streamdeck/plugins/manifest/v7.0.ts | 27 + .../src/streamdeck/plugins/manifest/v7.1.ts | 16 + .../schemas/src/streamdeck/plugins/schemas.ts | 29 + packages/schemas/src/utils.ts | 4 + .../schemas/tests/matchers/to-have-error.ts | 134 + packages/schemas/tests/setup.ts | 6 + packages/schemas/tests/validate.ts | 48 + packages/schemas/tsconfig.json | 17 + pnpm-lock.yaml | 2818 ++++++++++++++++- 52 files changed, 7156 insertions(+), 38 deletions(-) create mode 100644 packages/schemas/.prettierignore create mode 100644 packages/schemas/CHANGELOG.md create mode 100644 packages/schemas/README.md create mode 100644 packages/schemas/eslint.config.mjs create mode 100644 packages/schemas/jest.config.cjs create mode 100644 packages/schemas/package.json create mode 100644 packages/schemas/rollup.config.ts create mode 100644 packages/schemas/scripts/build.ts create mode 100644 packages/schemas/scripts/package.json create mode 100644 packages/schemas/scripts/transformers/custom-keywords.ts create mode 100644 packages/schemas/scripts/transformers/version-manifests.ts create mode 100644 packages/schemas/src/index.ts create mode 100644 packages/schemas/src/streamdeck/plugins/README.md create mode 100644 packages/schemas/src/streamdeck/plugins/device-type.ts create mode 100644 packages/schemas/src/streamdeck/plugins/index.ts create mode 100644 packages/schemas/src/streamdeck/plugins/json.ts create mode 100644 packages/schemas/src/streamdeck/plugins/layout.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/all.test.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/Actions[].OS.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/Profiles[].AutoInstall.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.4.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.5.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.6.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.7.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.8.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.9.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.0.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.1.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.2.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.3.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.4.json create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.4.test.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.5.test.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.6.test.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.9.test.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/v7.0.test.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/__tests__/v7.1.test.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/latest.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/v6.4.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/v6.5.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/v6.6.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/v6.9.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/v7.0.ts create mode 100644 packages/schemas/src/streamdeck/plugins/manifest/v7.1.ts create mode 100644 packages/schemas/src/streamdeck/plugins/schemas.ts create mode 100644 packages/schemas/src/utils.ts create mode 100644 packages/schemas/tests/matchers/to-have-error.ts create mode 100644 packages/schemas/tests/setup.ts create mode 100644 packages/schemas/tests/validate.ts create mode 100644 packages/schemas/tsconfig.json diff --git a/.gitignore b/.gitignore index d34c33f..d7cac3e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Node.js .turbo +.wireit node_modules/ # Tests @@ -7,6 +8,7 @@ coverage/ # Build output dist/ +packages/schemas/streamdeck # Shared package files packages/plugin/README.md diff --git a/packages/schemas/.prettierignore b/packages/schemas/.prettierignore new file mode 100644 index 0000000..3b39f82 --- /dev/null +++ b/packages/schemas/.prettierignore @@ -0,0 +1,3 @@ +.turbo +coverage +dist \ No newline at end of file diff --git a/packages/schemas/CHANGELOG.md b/packages/schemas/CHANGELOG.md new file mode 100644 index 0000000..d47e795 --- /dev/null +++ b/packages/schemas/CHANGELOG.md @@ -0,0 +1,248 @@ +# Change Log + +## 0.4.15 + +### Patch Changes + +- Add Stream Deck 7.4. + +## 0.4.14 + +### Patch Changes + +- Add Stream Deck 7.3. +- Add `Galleon100SD` device type and manifest hint. +- Add `StreamDeckPlusXL` device type and manifest hint. + +## 0.4.13 + +### Patch Changes + +- Fix release pipeline. + +## 0.4.12 + +### Patch Changes + +- Add Stream Deck 7.2. + +## 0.4.11 + +### Patch Changes + +- `Nodejs` is now correctly marked as optional in older version. + +## 0.4.10 + +### Patch Changes + +- Add Stream Deck 7.1. +- Add support for Node.js 24. + +## 0.4.9 + +### Patch Changes + +- Update recommended `SDKVersion`. + +## 0.4.8 + +### Patch Changes + +- Add `Actions[].SupportedInKeyLogicActions`. + +## 0.4.7 + +### Patch Changes + +- Add Stream Deck 7.0. +- Add `VirtualStreamDeck` device type and manifest hint. + +## 0.4.6 + +### Patch Changes + +- Fix documentation for `Icon` size requirements. + +## 0.4.5 + +### Patch Changes + +- Add `StreamDeckStudio` device type and manifest hint. + +## 0.4.4 + +### Patch Changes + +- Add `SupportURL` and `Actions[].SupportURL`. + +## 0.4.3 + +### Patch Changes + +- Add Stream Deck 6.9. + +## 0.4.2 + +### Patch Changes + +- Update iconography color guide. +- Update dependencies. + +## 0.4.1 + +### Patch Changes + +- Update manifest `Profiles[].AutoInstall` to reflect minimum Stream Deck version. +- Update manifest `Icon` to remove Marketplace reference. + +## 0.4.0 + +### Minor Changes + +- Fix package exports. + +## 0.3.9 + +### Patch Changes + +- Remove SVG reference from `Icon` documentation. + +## 0.3.8 + +### Patch Changes + +- Fix `Icon` incorrectly allowing SVG images. + +## 0.3.7 + +### Patch Changes + +- Add Stream Deck 6.8. + +## 0.3.6 + +### Patch Changes + +- Add Stream Deck 6.7. + +## 0.3.5 + +### Patch Changes + +- Add `@elgato/schemas/streamdeck/plugins/json` export. + +## 0.3.4 + +### Patch Changes + +- Fix `Version` format documentation. + +## 0.3.3 + +### Patch Changes + +- Fix patterns for `CategoryIcon`, `Icon`, `PropertyInspectorPath`, and `UUID`. +- Fix patterns for `CodePath`, `CodePathMac`, and `CodePathWin`. +- Fix patterns for an action's `Icon`, `PropertyInspectorPath`, and `UUID`. +- Fix patterns for an encoder's `Icon`, `background`, and `layout`. +- Fix patterns for a state's `Image`, and `MultiActionImage`. +- Fix pattern for a profile's `Name`. + +## 0.3.2 + +### Patch Changes + +- `Actions[].States` can now contain more than 2 states. + +## 0.3.1 + +### Patch Changes + +- Fix missing `MinimumVersion` values. + +## 0.3.0 + +### Minor Changes + +- Renamed SCUF device type to `SCUFController`. + +## 0.2.2 + +### Patch Changes + +- Add `ScufGamepad` and `StreamDeckNeo` device hints to manifest documentation. + +## 0.2.1 + +### Patch Changes + +- Add `ScufGamepad` and `StreamDeckNeo` device types. + +## 0.2.0 + +### Minor Changes + +- Add `Profiles[].AutoInstall`, introduced in Stream Deck 6.6. +- Remove `$schema` property from TypeScript types. + +## 0.1.8 + +### Patch Changes + +- Version fix. + +## 0.1.7 + +### Patch Changes + +- Update `Version` to require a major, minor, patch, and build numbers. +- Prevent `Version` from having leading zeroes, for example `1.002.3.4`; non-leading zeroes are still permitted. + +## 0.1.6 + +### Patch Changes + +- Add `Actions[].OS`, introduced in Stream Deck 6.6. + +## 0.1.5 + +### Patch Changes + +- Schemas are now accessible directly under the Elgato domain. + - [Manifest schema](https://schemas.elgato.com/streamdeck/plugins/manifest.json) + - [Layout schema](https://schemas.elgato.com/streamdeck/plugins/layout.json) + +## 0.1.4 + +### Patch Changes + +- Loosen rules on `Version` within manifest to allow more types; valid formats are now `{major}`, `{major}.{minor}`, `{major}.{minor}.{patch}`, and `{major}.{minor}.{patch}.{build}`. + +## 0.1.3 + +### Patch Changes + +- Add support for CommonJS. + +## 0.1.2 + +### Patch Changes + +- Fix pattern for identifiers (action and plugin UUIDs). + +## 0.1.1 + +### Patch Changes + +- Add `imageDimensions` schema type. + +## 0.1.0 + +### Minor Changes + +- Add JSON schema for Stream Deck plugin's manifest. +- Add TypeScript declaration for Stream Deck plugin's manifest. +- Add JSON schema for Stream Deck plugin's layout. +- Add TypeScript declaration for Stream Deck plugin's layout. +- Add custom keyword definitions. diff --git a/packages/schemas/README.md b/packages/schemas/README.md new file mode 100644 index 0000000..bf5d647 --- /dev/null +++ b/packages/schemas/README.md @@ -0,0 +1,94 @@ +
+ +[![Stream Deck SDK banner](https://images.ctfassets.net/8j9xr8kwdre8/1ihLKCwNWEfPixs27dq0c0/130be66a5173f332e4caa892a3462893/banner.png)](https://docs.elgato.com/sdk) + +# Schemas + +[![Schemas npm package](https://img.shields.io/npm/v/%40elgato/schemas?logo=npm&logoColor=white)](https://www.npmjs.com/package/@elgato/schemas) +[![SDK documentation](https://img.shields.io/badge/Documentation-2ea043?labelColor=grey&logo=gitbook&logoColor=white)](https://docs.elgato.com/sdk) +[![Join the Marketplace Makers Discord](https://img.shields.io/badge/Marketplace%20Makers-5662f6?labelColor=grey&logo=discord&logoColor=white)](https://discord.gg/GehBUcu627) +[![Elgato homepage](https://img.shields.io/badge/Elgato-3431cf?labelColor=grey&logo=elgato)](https://elgato.com) + +
+ +Collection of schemas, and TypeScript declarations, to support the creation and validation of Stream Deck SDK files. + +```bash +npm install @elgato/schemas +``` + +## Stream Deck + +### Plugin + +#### Manifest + +Manifest JSON file responsible for defining a Stream Deck plugin. + +```ts +// TypeScript type. +import { type Manifest } from "@elgato/schemas/streamdeck/plugins"; +``` + +```js +// Schema as an object. +import manifest from "@elgato/schemas/streamdeck/plugins/json"; +``` + +```js +// Schema as an object, with experimental import attributes +import manifest from "@elgato/schemas/streamdeck/plugins/manifest.json" with { type: "json" }; +``` + +``` +https://schemas.elgato.com/streamdeck/plugins/manifest.json +``` + +#### Layout + +Layout JSON file that defines the layout of an action on Stream Deck +. + +```ts +// TypeScript type. +import { type Layout } from "@elgato/schemas/streamdeck/plugins"; +``` + +```js +// Schema as an object. +import layout from "@elgato/schemas/streamdeck/plugins/json"; +``` + +```js +// Schema as an object, with experimental import attributes +import layout from "@elgato/schemas/streamdeck/plugins/layout.json" with { type: "json" }; +``` + +``` +https://schemas.elgato.com/streamdeck/plugins/layout.json +``` + +## Usage + +Schemas can be referenced directly within JSON files, providing intellisense and validation, using the `$schema` property, for example: + +```jsonc +{ + "$schema": "https://schemas.elgato.com/streamdeck/plugins/manifest.json", + "Name": "Wave Link", + "Version": "1.9.0.0", + "Author": "Elgato" + // ... +} +``` + +## Keywords + +Custom keywords used within the provided schemas can also be directly imported to assist with constructing a validator, such as `Ajv`. Please note, the custom keyword definitions will only register the keyword, and will not provide validation. + +```ts +import { keywordDefinitions } from "@elgato/schemas"; +import Ajv from "ajv"; + +// add the "filePath" keyword (excluding validation) +ajv.addKeyword(keywordDefinitions.filePath); +``` diff --git a/packages/schemas/eslint.config.mjs b/packages/schemas/eslint.config.mjs new file mode 100644 index 0000000..adc6a45 --- /dev/null +++ b/packages/schemas/eslint.config.mjs @@ -0,0 +1,3 @@ +import { config } from "@elgato/eslint-config"; + +export default config.strict; diff --git a/packages/schemas/jest.config.cjs b/packages/schemas/jest.config.cjs new file mode 100644 index 0000000..636b2d0 --- /dev/null +++ b/packages/schemas/jest.config.cjs @@ -0,0 +1,31 @@ +const config = ({ + compilerOptions: { paths } +} = require("./tsconfig.json")); + +/* + * For a detailed explanation regarding each configuration property and type check, visit: + * https://jestjs.io/docs/configuration + */ +module.exports = { + clearMocks: true, + maxWorkers: 1, + modulePathIgnorePatterns: ["/src/.+/__mocks__/.*"], + verbose: true, + roots: ["src"], + setupFilesAfterEnv: ["./tests/setup.ts"], + transform: { + "^.+\\.ts$": [ + "@swc/jest", + { + jsc: { + parser: { + syntax: "typescript", + decorators: true + }, + baseUrl: "./", + paths + } + } + ] + } +}; diff --git a/packages/schemas/package.json b/packages/schemas/package.json new file mode 100644 index 0000000..8c68059 --- /dev/null +++ b/packages/schemas/package.json @@ -0,0 +1,120 @@ +{ + "name": "@elgato/schemas", + "version": "0.4.15", + "description": "Collection of schemas, and TypeScript declarations, to support the creation and validation of Stream Deck SDK files", + "exports": { + ".": { + "import": "./dist/index.mjs", + "require": "./dist/index.cjs", + "types": "./dist/index.d.ts" + }, + "./streamdeck/plugins": { + "import": "./dist/streamdeck/plugins/index.mjs", + "require": "./dist/streamdeck/plugins/index.cjs", + "types": "./dist/streamdeck/plugins/index.d.ts" + }, + "./streamdeck/plugins/json": { + "import": "./dist/streamdeck/plugins/json.mjs", + "require": "./dist/streamdeck/plugins/json.cjs", + "types": "./dist/streamdeck/plugins/json.d.ts" + }, + "./streamdeck/plugins/layout.json": { + "default": "./streamdeck/plugins/layout.json" + }, + "./streamdeck/plugins/manifest.json": { + "default": "./streamdeck/plugins/manifest.json" + } + }, + "files": [ + "dist/" + ], + "scripts": { + "build": "wireit", + "build:exports": "wireit", + "build:schemas": "wireit", + "clean": "rm -rf ./dist/ && rm -rf ./streamdeck/", + "lint": "eslint . --ext .ts --max-warnings 0", + "test": "wireit", + "test:ci": "jest", + "test:watch": "nodemon --watch src --ext ts --exec \"npm run test\"", + "prepack": "cp ../../LICENSE ." + }, + "wireit": { + "build": { + "dependencies": [ + "build:exports", + "build:schemas" + ] + }, + "build:exports": { + "command": "rollup --config rollup.config.ts --configPlugin typescript", + "clean": true, + "output": [ + "dist/**/*{.cjs,.d.ts,.mjs}" + ], + "dependencies": [ + "build:schemas" + ] + }, + "build:schemas": { + "command": "node -r @swc-node/register ./scripts/build.ts", + "clean": true, + "output": [ + "dist/**/*.json" + ] + }, + "test": { + "command": "jest", + "dependencies": [ + "build:schemas" + ] + } + }, + "prettier": "@elgato/prettier-config", + "repository": { + "type": "git", + "url": "git+https://github.com/elgatosf/streamdeck.git" + }, + "keywords": [ + "elgato", + "stream deck", + "sdk", + "json", + "schemas" + ], + "author": { + "name": "Elgato", + "url": "https://www.elgato.com" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/elgatosf/streamdeck/issues" + }, + "homepage": "https://docs.elgato.com/sdk", + "devDependencies": { + "@elgato/eslint-config": "^0.3.2", + "@elgato/prettier-config": "^0.3.3", + "@jest/globals": "29.7.0", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^16.0.0", + "@rollup/plugin-typescript": "^12.1.2", + "@swc-node/register": "1.10.9", + "@swc/core": "^1.10.7", + "@swc/jest": "^0.2.37", + "@tsconfig/node20": "^20.1.4", + "@types/jest": "^29.5.14", + "@types/json-schema": "^7.0.15", + "@types/node": "^22.10.7", + "ajv": "^8.17.1", + "eslint": "^9.39.4", + "expect": "29.7.0", + "jest": "^29.7.0", + "nodemon": "^3.1.9", + "prettier": "^3.8.1", + "rollup": "^4.30.1", + "rollup-plugin-dts": "^6.1.1", + "ts-json-schema-generator": "^2.3.0", + "typescript": "^5.7.3", + "wireit": "^0.14.12" + } +} diff --git a/packages/schemas/rollup.config.ts b/packages/schemas/rollup.config.ts new file mode 100644 index 0000000..abdf24b --- /dev/null +++ b/packages/schemas/rollup.config.ts @@ -0,0 +1,65 @@ +import json from "@rollup/plugin-json"; +import nodeResolve from "@rollup/plugin-node-resolve"; +import typescript from "@rollup/plugin-typescript"; +import { dirname, join, parse } from "node:path"; +import { RollupOptions } from "rollup"; +import dts from "rollup-plugin-dts"; + +const banner = `/**! + * @author Elgato + * @module elgato/schemas + * @license MIT + * @copyright Copyright (c) Corsair Memory Inc. + */`; + +/** + * Gets the configuration based an input within the `src/` folder. + * @param input Partial path to the input. + * @returns Rollup configuration for the specified input. + */ +function getConfig(input: string): RollupOptions[] { + const outputDir = join("dist", dirname(input)); + input = join("src", input); + const pathWithoutExtension = join(outputDir, `${parse(input).name}`); + + return [ + { + input, + output: [ + { + file: `${pathWithoutExtension}.cjs`, + format: "cjs", + banner, + }, + { + file: `${pathWithoutExtension}.mjs`, + format: "es", + banner, + }, + ], + plugins: [ + typescript({ + exclude: ["scripts/**/*.ts", "tests/**/*.ts"], + }), + nodeResolve(), + json(), + ], + }, + { + input, + output: [ + { + file: `${pathWithoutExtension}.d.ts`, + banner, + }, + ], + plugins: [json(), dts()], + }, + ]; +} + +export default [ + ...getConfig("index.ts"), + ...getConfig("streamdeck/plugins/index.ts"), + ...getConfig("streamdeck/plugins/json.ts"), +] satisfies RollupOptions[]; diff --git a/packages/schemas/scripts/build.ts b/packages/schemas/scripts/build.ts new file mode 100644 index 0000000..dd2f3df --- /dev/null +++ b/packages/schemas/scripts/build.ts @@ -0,0 +1,46 @@ +import type { JSONSchema7 } from "json-schema"; +import { existsSync, mkdirSync, writeFileSync } from "node:fs"; +import { join } from "node:path"; +import { createGenerator } from "ts-json-schema-generator"; + +import pkg from "../package.json"; +import { customKeywordTransformer } from "./transformers/custom-keywords"; +import { versionManifests } from "./transformers/version-manifests"; + +// Prepare the output directory. +const outputDir = join(__dirname, "../streamdeck/plugins"); +if (!existsSync(outputDir)) { + mkdirSync(outputDir, { recursive: true }); +} + +generateAndWriteSchema("Manifest", [customKeywordTransformer, versionManifests]); +generateAndWriteSchema("Layout", [customKeywordTransformer]); + +/** + * Generates the JSON schema for the specified TypeScript `type`, and writes it locally to `{type}.json`. + * @param type TypeScript type whose schema should be generated. + * @param transformers Optional function used to transform the schema. + */ +function generateAndWriteSchema(type: string, transformers?: ((schema: JSONSchema7) => void)[]): void { + // Build the generator. + const path = join(__dirname, "../src/streamdeck/plugins/schemas.ts"); + const generator = createGenerator({ + extraTags: ["errorMessage", "imageDimensions", "filePath"], + path, + skipTypeCheck: true, + schemaId: `${pkg.name}/streamdeck/plugins/${type.toLowerCase()}@${pkg.version}`, + tsconfig: join(__dirname, "../tsconfig.json"), + }); + + // Generate the schema, and apply the transformers. + const schema = generator.createSchema(type); + transformers?.forEach((t) => t(schema)); + + // Determine the output path, and serialize the schema. + const outputPath = join(outputDir, `${type.toLowerCase()}.json`); + const contents = JSON.stringify(schema, null, "\t"); + + // Finally write the schema. + writeFileSync(outputPath, contents); + console.log(`Successfully generated schema for ${type}.`); +} diff --git a/packages/schemas/scripts/package.json b/packages/schemas/scripts/package.json new file mode 100644 index 0000000..1cd945a --- /dev/null +++ b/packages/schemas/scripts/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/packages/schemas/scripts/transformers/custom-keywords.ts b/packages/schemas/scripts/transformers/custom-keywords.ts new file mode 100644 index 0000000..a4539c8 --- /dev/null +++ b/packages/schemas/scripts/transformers/custom-keywords.ts @@ -0,0 +1,140 @@ +import type { JSONSchema7 } from "json-schema"; +import { Schema } from "ts-json-schema-generator"; +import type { FilePathOptions } from "../../src"; + +/** + * Applies the custom keywords, aggregating the schema to form a valid structure. + * @param schema Schema to apply the custom keywords to. + */ +export function customKeywordTransformer(schema: JSONSchema7): void { + visitNode(schema, (node, keyword, value) => { + switch (keyword) { + case "description": + node.markdownDescription = value?.toString(); + break; + + case "filePath": + validateFilePathOptions(value); + node.pattern = generatePathPattern(value); + node.errorMessage = generatePathErrorMessage(value); + + break; + } + }); +} + +/** + * Validates the specified {@link options} are an instance of {@link FilePathOptions}. + * @param options Options to validate. + */ +function validateFilePathOptions(options: unknown): asserts options is FilePathOptions { + if (options === null) { + throw new TypeError(`"filePath" options must not be null`); + } + + if (typeof options === "boolean") { + if (options === false) { + throw new TypeError(`"false" is not a valid value for "filePath", expected: "true"`); + } + + return; + } + + if (typeof options !== "object" || !("extensions" in options) || !("includeExtension" in options)) { + throw new TypeError(`${JSON.stringify(options)} is not a complete set of "filePath" options, expected: { "extensions": string[], "includeExtension": boolean }`); + } +} + +/** + * Generates the regular expression pattern of a property based file path's {@link options}. + * - {@link https://regexr.com/7qpi6 File path, with unknown extension} + * - {@link https://regexr.com/7qpj7 File path, with extension} + * - {@link https://regexr.com/7qp5k File path, without extension} + * @param options Options used to determine how the pattern should be generated. + * @returns Regular expression pattern. + */ +function generatePathPattern(options: FilePathOptions): string { + let pattern = "^(?![~\\.]*[\\\\\\/]+)"; // ensure the value doesn't start with a slash, or period followed by a slash. + + // When the file path's extension is unknown, we simply ensure the start of the string. + if (typeof options === "boolean") { + return (pattern += ".*$"); + } + + // Otherwise, construct the pattern based on the valid extensions. + const exts = options.extensions + .map((extension) => { + const chars = Array.from(extension) + .slice(1) + .map((c) => `[${c.toUpperCase()}${c.toLowerCase()}]`) + .join(""); + + return `(${chars})`; + }) + .join("|"); + + if (options.includeExtension) { + // Ensure the value ends with a valid extension + pattern += `.*\\.(${exts})$`; + } else { + // Use a negative look-ahead to ensure the extension isn't specified. + pattern += `(?!.*\\.(${exts})$).*$`; + } + + return pattern; +} + +/** + * Generates the custom error message associated with a file path. + * @param options Options that define the valid file path. + * @returns Custom error message. + */ +function generatePathErrorMessage(options: FilePathOptions): string { + if (typeof options === "boolean") { + return "String must reference file in the plugin directory."; + } + + const exts = options.extensions.reduce((prev, current, index) => { + return index === 0 ? current : index === options.extensions.length - 1 ? prev + `, or ${current}` : prev + `, ${current}`; + }, ""); + + const errorMessage = `String must reference ${exts} file in the plugin directory`; + return options.includeExtension ? `${errorMessage}.` : `${errorMessage}, with the file extension omitted.`; +} + +/** + * Traverses the specified {@link schema} and applies the visitor to each property. + * @param schema Schema to traverse + * @param visitor Visitor to each of the schema's properties. + */ +function visitNode(schema: ExtendedSchema, visitor: (schema: ExtendedSchema, keyword: keyof ExtendedSchema, value: unknown) => void): void { + if (typeof schema === "object") { + for (const [keyword, value] of Object.entries(schema)) { + if (typeof value === "object") { + visitNode(value, visitor); + } + + visitor(schema, keyword as keyof ExtendedSchema, value); + } + } +} + +/** + * Provides an extended JSON schema that includes the `markdownDescription` property. + */ +type ExtendedSchema = Schema & { + /** + * Custom error message shown when the value does not confirm to the defined schemas. + */ + errorMessage?: string; + + /** + * Determines whether the value must represent a file path. + */ + filePath?: FilePathOptions; + + /** + * Markdown representation of the description. + */ + markdownDescription?: string; +}; diff --git a/packages/schemas/scripts/transformers/version-manifests.ts b/packages/schemas/scripts/transformers/version-manifests.ts new file mode 100644 index 0000000..7f548a0 --- /dev/null +++ b/packages/schemas/scripts/transformers/version-manifests.ts @@ -0,0 +1,83 @@ +import { type JSONSchema7 } from "json-schema"; + +/** + * Versions the manifest JSON schema. + * @param schema Schema source. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function versionManifests(schema: any): void { + const { Manifest: manifest } = schema.definitions; + + // When there is only a single structure, our job here is done. + if (manifest.anyOf === undefined) { + return; + } + + // Verify there are no properties already defined on the main definition. + if (manifest.properties) { + throw new TypeError("Cannot version Manifest, the root definition contains properties"); + } + + // Keep track of the supported versions, and set the `allOf` value to default. + const versions = new Set(); + manifest.allOf = []; + + // Iterate over the manifest version references. + for (const manifestVersionDefinition of manifest.anyOf) { + // Get the minimum versions the manifest version supports. + const { + properties: { + Software: { + properties: { MinimumVersion } + } + } + } = manifestVersionDefinition; + + // Add each of the conditional statements for the versions. + for (const version of MinimumVersion.enum || [MinimumVersion.const]) { + if (versions.has(version)) { + throw new Error(`Duplicate version found: ${version}`); + } + + versions.add(version); + schema.definitions.Manifest.allOf.push({ + if: getMinimumVersionSchema(version), + then: manifestVersionDefinition + }); + } + } + + // We've replace the anyOf, so remove it; finally set type for all versions. + delete schema.definitions.Manifest.anyOf; + schema.definitions.Manifest = { + ...manifest, + ...getMinimumVersionSchema(versions) + }; +} + +/** + * Gets a JSON schema that represents an object of structure `Software.MinimumVersion`. + * @param version Version, or versions, that the `Software.MinimumVersion` can be. + * @returns The JSON schema. + */ +function getMinimumVersionSchema(version: Set | string): JSONSchema7 { + return { + type: "object", + properties: { + Software: { + type: "object", + description: "Determines the Stream Deck software requirements for this plugin.", + properties: { + MinimumVersion: { + type: "string", + description: "Minimum version of the Stream Deck application required for this plugin to run.", + const: version instanceof Set ? undefined : version, + enum: version instanceof Set ? Array.from(version) : undefined + } + }, + required: ["MinimumVersion"] + } + }, + required: ["Software"] + }; +} diff --git a/packages/schemas/src/index.ts b/packages/schemas/src/index.ts new file mode 100644 index 0000000..6902ac1 --- /dev/null +++ b/packages/schemas/src/index.ts @@ -0,0 +1,86 @@ +/** + * Custom keyword definitions. + */ +export const keywordDefinitions = { + /** + * The `markdownDescription` keyword definition; used to define descriptions with markdown syntax. + */ + markdownDescription: { + /** + * String that identifies the `markdownDescription` keyword. + */ + keyword: "markdownDescription", + + /** + * Schema type of the keyword. + */ + schemaType: "string" as const + }, + + /** + * The `errorMessage` keyword definition; used to define custom error messages. + */ + errorMessage: { + /** + * String that identifies the `errorMessage` keyword. + */ + keyword: "errorMessage", + + /** + * Schema type of the keyword. + */ + schemaType: "string" as const + }, + + /** + * The `imageDimensions` keyword definition; used to validate dimensions of images. + */ + imageDimensions: { + /** + * String that identifies the `imageDimensions` keyword. + */ + keyword: "imageDimensions", + + /** + * Schema type of the keyword. + */ + schemaType: "array" as const + }, + + /** + * The `filePath` keyword definition; used to validate strings that represent file paths. + */ + filePath: { + /** + * String that identifies the `filePath` keyword. + */ + keyword: "filePath", + + /** + * Schema type of the keyword. + */ + schemaType: ["boolean" as const, "object" as const] + } +}; + +/** + * Options associated with the {@link keywordDefinitions.filePath} keyword. + */ +export type FilePathOptions = + | true + | { + /** + * Collection of valid file extensions. + */ + extensions: string[]; + + /** + * Determines whether the extension must be present, or omitted, from the file path. + */ + includeExtension: boolean; + }; + +/** + * Options associated with the {@link keywordDefinitions.imageDimensions} keyword. + */ +export type ImageDimensions = [width: number, height: number]; diff --git a/packages/schemas/src/streamdeck/plugins/README.md b/packages/schemas/src/streamdeck/plugins/README.md new file mode 100644 index 0000000..97a77bb --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/README.md @@ -0,0 +1,62 @@ +# Stream Deck Plugin Schemas + +## Manifest + +Manifest versioning is achieved using reverse-migrations, by extending the versions successor and utilizing the `Omit` utility type to _remove_ new features, for example: + +```mermaid +classDiagram + Manifest <|-- Manifest_6_6 + Manifest_6_6 <|-- Manifest_6_5 + class Manifest { + + string: Software.MinimumVersion + ... + } + class Manifest_6_6 { + + "6.6" | "6.7": Software.MinimumVersion + // No changes introduced from 6.6 to 6.7. + } + class Manifest_6_5 { + + "6.5": Software.MinimumVersion + // Changes introduced from 6.5 to 6.6, omit new properties. + } +``` + +### Glossary + +- vLatest — The current version, with a flat `Software.MinimumVersion`. +- vCurrent — The current version, for example `v6.7.ts`. +- vNext — The new version being introduced, for example `v6.8.ts`. + +### File Structure Example + +Manifest versions, and the type responsible for generating the JSON schema, are located in the following file structure: + +``` +./src/streamdeck/plugins/ +├── manifest/ +│ ├── latest.ts # vLatest — vCurrent, with flat Software.MinimumVersion, e.g. "6.5" | "6.6" | "6.7" +| ├── v6.5.ts +| ├── v6.6.ts +| └── v6.7.ts # vCurrent, with specific Software.MinimumVersion, e.g. "6.7" +└── schemas.ts +``` + +### Adding Versions of Stream Deck + +When adding a new version of Stream Deck, its important to consider if there are manifest changes. If simply adding a new version of `Software.MinimumVersion`, vCurrent can be updated to include the new version. If there are new properties introduced, a reverse-migration is needed. + +The following flowchart depicts how to introduce a new version of Stream Deck to the manifest type and JSON schema. + +```mermaid +graph TD; + a("New version of
Stream Deck app")-->b + b{"Manifest
changes"} + b-->|Yes|y0("Add changes to ./manifest/latest.ts") + y0-->y1("Create vNext (e.g. v6.8.ts) in ./manifest/ — extend latest, and re-set Software.MinimumVersion") + y1-->y2("Update vCurrent in ./manifest/ — extend vNext, and omit changes") + y2-->y3("Update Manifest type within ./schemas/ to include vNext")-->z0 + b-->|No|n("Update vCurrent Software.MinimumVersion to include new version")-->z0 + z0("Add unit tests for new version") + z0-->z1("Fin") +``` diff --git a/packages/schemas/src/streamdeck/plugins/device-type.ts b/packages/schemas/src/streamdeck/plugins/device-type.ts new file mode 100644 index 0000000..d901add --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/device-type.ts @@ -0,0 +1,74 @@ +/** + * Stream Deck device types. + */ +export enum DeviceType { + /** + * Stream Deck, comprised of 15 customizable LCD keys in a 5 x 3 layout. + */ + StreamDeck = 0, + + /** + * Stream Deck Mini, comprised of 6 customizable LCD keys in a 3 x 2 layout. + */ + StreamDeckMini = 1, + + /** + * Stream Deck XL, comprised of 32 customizable LCD keys in an 8 x 4 layout. + */ + StreamDeckXL = 2, + + /** + * Stream Deck Mobile, for iOS and Android. + */ + StreamDeckMobile = 3, + + /** + * Corsair G Keys, available on select Corsair keyboards. + */ + CorsairGKeys = 4, + + /** + * Stream Deck Pedal, comprised of 3 customizable pedals. + */ + StreamDeckPedal = 5, + + /** + * Corsair Voyager laptop, comprising 10 buttons in a horizontal line above the keyboard. + */ + CorsairVoyager = 6, + + /** + * Stream Deck +, comprised of 8 customizable LCD keys in a 4 x 2 layout, a touch strip, and 4 dials. + */ + StreamDeckPlus = 7, + + /** + * SCUF controller G keys, available on select SCUF controllers, for example SCUF Envision. + */ + SCUFController = 8, + + /** + * Stream Deck Neo, comprised of 8 customizable LCD keys in a 4 x 2 layout, an info bar, and 2 touch points for page navigation. + */ + StreamDeckNeo = 9, + + /** + * Stream Deck Studio, comprised of 32 customizable LCD keys in a 16 x 2 layout, and 2 dials (1 on either side). + */ + StreamDeckStudio = 10, + + /** + * Virtual Stream Deck, comprised of 1 to 64 action (on-screen) on a scalable canvas, with a maximum layout of 8 x 8. + */ + VirtualStreamDeck = 11, + + /** + * High-performance gaming keyboard, with a built-in Stream Deck comprised of 12 customizable LCD keys in a 3 x 4 layout, an LCD screen, and 2 dials. + */ + Galleon100SD = 12, + + /** + * Stream Deck + XL, comprised of 36 customizable LCD keys in a 9 x 4 layout, a touch strip, and 6 dials. + */ + StreamDeckPlusXL = 13 +} diff --git a/packages/schemas/src/streamdeck/plugins/index.ts b/packages/schemas/src/streamdeck/plugins/index.ts new file mode 100644 index 0000000..6d83a37 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/index.ts @@ -0,0 +1,10 @@ +import { type Layout as LayoutJsonSchema } from "./layout"; + +export { DeviceType } from "./device-type"; +export * from "./layout"; +export * from "./manifest/latest"; + +/** + * Defines the structure of a custom layout file. + */ +export type Layout = Omit; diff --git a/packages/schemas/src/streamdeck/plugins/json.ts b/packages/schemas/src/streamdeck/plugins/json.ts new file mode 100644 index 0000000..f0a5142 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/json.ts @@ -0,0 +1,2 @@ +export { default as layout } from "../../../streamdeck/plugins/layout.json"; +export { default as manifest } from "../../../streamdeck/plugins/manifest.json"; diff --git a/packages/schemas/src/streamdeck/plugins/layout.ts b/packages/schemas/src/streamdeck/plugins/layout.ts new file mode 100644 index 0000000..15eed86 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/layout.ts @@ -0,0 +1,335 @@ +/** + * Defines the structure of a custom layout file. + */ +export type Layout = { + /** + * JSON schema responsible for describing the manifest's data format and validation. + */ + $schema?: string; + + /** + * Unique identifier associated with the layout. + */ + id: string; + + /** + * Items within the layout. + */ + items: LayoutItem[]; +}; + +/** + * A layout item. + * @discriminator type + */ +type LayoutItem = Bar | GBar | Pixmap | Text; + +/** + * Extended information used to define a layout item within a layout's JSON file. + */ +type LayoutItemBase = { + /** + * Background color represented as a named color, hexadecimal value, or gradient. Gradients can be defined by specifying multiple color-stops separated by commas, in the following + * format `[{offset}:{color}[,]]`. + * + * **Examples:** + * - "pink" + * - "#204cfe" (Elgato blue) + * - "0:#ff0000,0.5:yellow,1:#00ff00" (Gradient) + */ + background?: string; + + /** + * Determines whether the item is enabled (i.e. visible); default is `true`. + */ + enabled?: boolean; + + /** + * Unique name used to identify the layout item. When calling `setFeedback` this value should be used as the key as part of the object that represents the feedback. + * + * Note: The `key` of the layout item cannot be changed at runtime. + * @pattern + * ^[A-Za-z0-9\-_]+$ + * @errorMessage + * String must only contain alphanumeric characters (A-z, 0-9), hyphens (-), and underscores (_) + */ + key: string; + + /** + * Defines the opacity of the item being shown based on a single-decimal value ranging from `0..1`, e.g. `0.1`, `0.2`, etc. with `0` being invisible and `1` being fully visible. + * Default is `1`. + */ + opacity?: Opacity; + + /** + * Array defining the items coordinates in the format `[x, y, width, height]`; coordinates must be within canvas size of 200 x 100, e.g. [0, 0, 200, 100]. Items with the same `zOrder` + * must **not** have an overlapping `rect`. + * + * Note: The `rect` of the layout item cannot be changed at runtime. + */ + rect: Rect; + + /** + * Type of layout item this instance represents, e.g. "pixmap", "bar", etc. + * + * Note: The `type` of the layout item cannot be changed at runtime. + */ + type: T; + + /** + * Z-order of the item, used to layer items within a layout; must be between 0-700. Items with the same `zOrder` must **not** have an overlapping `rect`. Default is `0`. + */ + zOrder?: ZOrder; +}; + +/** + * Bar layout item used to render a horizontal bar with a filler, e.g. a progress bar. The amount to fill the bar by can be specified by setting the `value`. + */ +export type Bar = LayoutItemBase & { + /** + * Bar background color represented as a named color, hexadecimal value, or gradient. Default is `darkGray`. Gradients can be defined by specifying multiple color-stops separated + * by commas, in the following format `[{offset}:{color}[,]]`. + * + * **Examples:** + * - "pink" + * - "#204cfe" (Elgato blue) + * - "0:#ff0000,0.5:yellow,1:#00ff00" (Gradient) + * @example + * "darkGray" + */ + bar_bg_c?: string; + + /** + * Border color represented as a named color, or hexadecimal value. Default is `white`. + * + * **Examples:** + * - "pink" + * - "#204cfe" (Elgato blue) + * @example + * "white" + */ + bar_border_c?: string; + + /** + * Fill color of the bar represented as a named color, hexadecimal value, or gradient. Default is `white`. Gradients can be defined by specifying multiple color-stops separated + * by commas, in the following format `[{offset}:{color}[,]]`. + * + * **Examples:** + * - "pink" + * - "#204cfe" (Elgato blue) + * - "0:#ff0000,0.5:yellow,1:#00ff00" (Gradient) + * @example + * "white" + */ + bar_fill_c?: string; + + /** + * Width of the border around the bar, as a whole number. Default is `2`. + * @example + * 2 + */ + border_w?: number; + + /** + * Defines the range of the value the bar represents, e.g. 0-20, 0-100, etc. + */ + range?: Range; + + /** + * Sub-type used to determine the type of bar to render. Default is {@link BarSubType.Groove} (4). + * + * **Options** + * - Rectangle (0) + * - DoubleRectangle (1) + * - Trapezoid (2) + * - DoubleTrapezoid (3) + * - Groove (4) + */ + subtype?: (typeof BarSubType)[keyof typeof BarSubType]; + + /** + * Value used to determine how much of the bar is filled. Correlates with the item's `range` if specified in the layout's JSON definition; default range is `0..100`. + */ + value: number; +}; + +/** + * Defines the range of the value the bar represents, e.g. 0-20, 0-100, etc. + */ +export type Range = { + /** + * Minimum value of the bar. + */ + min: number; + + /** + * Maximum value of the bar. + */ + max: number; +}; + +/** + * Bar layout item used to render a horizontal bar with an indicator represented as a triangle beneath the bar. The location of the indicator can be specified by setting the `value`. + */ +export type GBar = Bar<"gbar"> & { + /** + * Height of the bar's indicator. Default is `10`. + * @example + * 10 + */ + bar_h?: number; +}; + +/** + * Image layout item used to render an image sourced from either a local file located under the plugin's folder, or base64 encoded `string`. The `value` defines the image. + */ +export type Pixmap = LayoutItemBase<"pixmap"> & { + /** + * Image to render; this can be either a path to a local file within the plugin's folder, a base64 encoded `string` with the mime type declared (e.g. PNG, JPEG, etc.), or an SVG + * `string`. + * + * **Examples:** + * - "imgs/Logo.png" + * - "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MHB0IiBoZWlnaHQ9…" + */ + value?: string; +}; + +/** + * Text layout item used to render text within a layout. **Note**, when adding a text item to the layout's JSON definition, setting the `key` to the `"title"` keyword will enable the + * user to specify the font's + * settings via the property inspector, and will cause `setTitle` to update this item. + */ +export type Text = LayoutItemBase<"text"> & { + /** + * Alignment of the text. Default is `"center"`. **Note**, when the `key` of this layout item is set to `"title"` within the layout's JSON definition, these values will be ignored + * in favour of the user's preferred title settings, as set in property inspector. + */ + alignment?: "center" | "left" | "right"; + + /** + * Color of the font represented as a named color, or hexadecimal value. Default is `white`. **Note**, when the `key` of this layout item is set to `"title"` within the layout's + * JSON definition, these values will be ignored in favour of the user's preferred title settings, as set in property inspector. + * + * **Examples:** + * - "pink" + * - "#204cfe" (Elgato blue) + */ + color?: string; + + /** + * Defines how the font should be rendered. **Note**, when the `key` of this layout item is set to `"title"` within the layout's JSON definition, these values will be ignored in + * favour of the user's preferred title settings, as set in property inspector. + */ + font?: { + /** + * Size of the font, in pixels, represented as a whole number. + * + * **Note**, when the `key` of this layout item is set to `"title"` within the layout's JSON definition, this value will be ignored in favour of the user's preferred title settings, as set in property inspector. + */ + size?: number; + + /** + * Weight of the font; value must be a whole `number` in the range of `100..1000`. **Note**, when the `key` of this layout item is set to `"title"` within the layout's JSON + * definition, this value will be ignored in favour of the user's preferred title settings, as set in property inspector. + * @minimum 100 + * @maximum 1000 + */ + weight?: number; + }; + + /** + * Defines how overflowing text should be rendered on the layout. + * - clip, truncates the text at the boundary of the element (default). + * - ellipsis, truncates the text prior to the boundary of the element, and adds an ellipsis (…) to the end. + * - fade, applies a fade-gradient over the end of the text. + * @default ellipsis + */ + "text-overflow"?: "clip" | "ellipsis" | "fade"; + + /** + * Text to be displayed. + */ + value?: string; +}; + +/** + * List of available types that can be applied to {@link Bar} and {@link GBar} to determine their style. + */ +export enum BarSubType { + /** + * Rectangle bar; the bar fills from left to right, determined by the {@link Bar.value}, similar to a standard progress bar. + */ + Rectangle = 0, + + /** + * Rectangle bar; the bar fills outwards from the centre of the bar, determined by the {@link Bar.value}. + * @example + * // Value is 2, range is 1-10. + * // [ ███ ] + * @example + * // Value is 10, range is 1-10. + * // [ █████] + */ + DoubleRectangle = 1, + + /** + * Trapezoid bar, represented as a right-angle triangle; the bar fills from left to right, determined by the {@link Bar.value}, similar to a volume meter. + */ + Trapezoid = 2, + + /** + * Trapezoid bar, represented by two right-angle triangles; the bar fills outwards from the centre of the bar, determined by the {@link Bar.value}. See {@link BarSubType.DoubleRectangle}. + */ + DoubleTrapezoid = 3, + + /** + * Rounded rectangle bar; the bar fills from left to right, determined by the {@link Bar.value}, similar to a standard progress bar. + */ + Groove = 4 +} + +/** + * Array defining the items coordinates and size. + */ +type Rect = [x: X, y: Y, width: Width, height: Height]; + +/** + * X coordinate of the rectangle. + * @minimum 0 + * @maximum 200 + */ +type X = number; + +/** + * Y coordinate of the rectangle. + * @minimum 0 + * @maximum 100 + */ +type Y = number; + +/** + * Width of the rectangle. + * @minimum 0 + * @maximum 200 + */ +type Width = number; + +/** + * Height of the rectangle. + * @minimum 0 + * @maximum 100 + */ +type Height = number; + +/** + * Numerical value used to specify the opacity of an item within a layout. + */ +type Opacity = 0 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1; + +/** + * Numerical value used to specify the z-order of an item, allowing for items to be layered within a layout. + * @minimum 0 + * @maximum 700 + */ +type ZOrder = number; diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/all.test.ts b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/all.test.ts new file mode 100644 index 0000000..65a5cac --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/all.test.ts @@ -0,0 +1,289 @@ +import { validateStreamDeckPluginManifest } from "@tests"; + +describe.each(["v6.4", "v6.5", "v6.6", "v6.7", "v6.8"])("%s", (version) => { + const filePath = `${version}.json`; + + /** + * Asserts the patterns of `Actions[]`. + */ + describe("Actions[]", () => { + /** + * Asserts the pattern of `Icon`. + */ + test("Icon", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.Actions[0].Icon = "test.png")); + expect(errors).toHaveError({ + instancePath: "/Actions/0/Icon", + keyword: "pattern", + params: { + pattern: patterns.IMAGE_PATH + } + }); + }); + + /** + * Asserts the pattern of `PropertyInspectorPath`. + */ + test("PropertyInspectorPath", () => { + // Arrange, act. + const errors = validateStreamDeckPluginManifest(filePath, (m) => { + // @ts-expect-error Test non-HTML file path. + m.Actions[0].PropertyInspectorPath = "file.txt"; + }); + + // Assert. + expect(errors).toHaveError({ + instancePath: "/Actions/0/PropertyInspectorPath", + keyword: "pattern", + params: { + pattern: patterns.HTML_PATH + } + }); + }); + + /** + * Asserts the pattern of `UUID`. + */ + test("UUID", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.Actions[0].UUID = "com.$.test")); + expect(errors).toHaveError({ + instancePath: "/Actions/0/UUID", + keyword: "pattern", + params: { + pattern: patterns.UUID + } + }); + }); + + /** + * Asserts the patterns of `Encoder`. + */ + describe("Encoder", () => { + /** + * Asserts the pattern of `Icon`. + */ + test("Icon", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.Actions[0].Encoder!.Icon = "test.png")); + expect(errors).toHaveError({ + instancePath: "/Actions/0/Encoder/Icon", + keyword: "pattern", + params: { + pattern: patterns.IMAGE_PATH + } + }); + }); + + /** + * Asserts the pattern of `background`. + */ + test("background", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.Actions[0].Encoder!.background = "test.png")); + expect(errors).toHaveError({ + instancePath: "/Actions/0/Encoder/background", + keyword: "pattern", + params: { + pattern: patterns.ENCODER_BACKGROUND_PATH + } + }); + }); + + /** + * Asserts the pattern of `layout`. + */ + test("layout", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.Actions[0].Encoder!.layout = "./test.json")); + expect(errors).toHaveError({ + instancePath: "/Actions/0/Encoder/layout", + keyword: "pattern", + params: { + pattern: patterns.LAYOUT + } + }); + }); + }); + + /** + * Asserts the patterns of `States[]`. + */ + describe("States[]", () => { + /** + * Asserts the pattern of `Image`. + */ + test("Image", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.Actions[0].States[0].Image = "test.png")); + expect(errors).toHaveError({ + instancePath: "/Actions/0/States/0/Image", + keyword: "pattern", + params: { + pattern: patterns.IMAGE_PATH_WITH_GIF_SUPPORT + } + }); + }); + + /** + * Asserts the pattern of `MultiActionImage`. + */ + test("MultiActionImage", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.Actions[0].States[0].MultiActionImage = "test.png")); + expect(errors).toHaveError({ + instancePath: "/Actions/0/States/0/MultiActionImage", + keyword: "pattern", + params: { + pattern: patterns.IMAGE_PATH + } + }); + }); + }); + }); + + /** + * Asserts the pattern of `CategoryIcon`. + */ + test("CategoryIcon", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.CategoryIcon = "test.png")); + expect(errors).toHaveError({ + instancePath: "/CategoryIcon", + keyword: "pattern", + params: { + pattern: patterns.IMAGE_PATH + } + }); + }); + + /** + * Asserts the pattern of `CodePath`. + */ + test("CodePath", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.CodePath = "./file.exe")); + expect(errors).toHaveError({ + instancePath: "/CodePath", + keyword: "pattern", + params: { + pattern: patterns.FILE_PATH + } + }); + }); + + /** + * Asserts the pattern of `CodePathMac`. + */ + test("CodePathMac", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.CodePathMac = "./file.exe")); + expect(errors).toHaveError({ + instancePath: "/CodePathMac", + keyword: "pattern", + params: { + pattern: patterns.FILE_PATH + } + }); + }); + + /** + * Asserts the pattern of `CodePathWin`. + */ + test("CodePathWin", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.CodePathWin = "./file.exe")); + expect(errors).toHaveError({ + instancePath: "/CodePathWin", + keyword: "pattern", + params: { + pattern: patterns.FILE_PATH + } + }); + }); + + /** + * Asserts the pattern of `Icon`. + */ + test("Icon", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.Icon = "test.png")); + expect(errors).toHaveError({ + instancePath: "/Icon", + keyword: "pattern", + params: { + pattern: patterns.ICON_PATH + } + }); + }); + + /** + * Asserts the patterns of `Profiles[]`. + */ + describe("Profiles[]", () => { + test("Name", () => { + // Arrange, act. + const errors = validateStreamDeckPluginManifest(filePath, (m) => { + m.Profiles![0].Name = "other.streamDeckProfile"; + }); + + // Assert. + expect(errors).toHaveError({ + instancePath: "/Profiles/0/Name", + keyword: "pattern", + params: { + pattern: patterns.PROFILE_PATH + } + }); + }); + }); + + /** + * Asserts the pattern of `PropertyInspectorPath`. + */ + test("PropertyInspectorPath", () => { + // Arrange, act. + const errors = validateStreamDeckPluginManifest(filePath, (m) => { + // @ts-expect-error Test non-HTML file path string. + m.PropertyInspectorPath = "test.txt"; + }); + + // Assert. + expect(errors).toHaveError({ + instancePath: "/PropertyInspectorPath", + keyword: "pattern", + params: { + pattern: patterns.HTML_PATH + } + }); + }); + + /** + * Asserts the pattern of `UUID`. + */ + test("UUID", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(filePath, (m) => (m.UUID = "com.$.test")); + expect(errors).toHaveError({ + instancePath: "/UUID", + keyword: "pattern", + params: { + pattern: patterns.UUID + } + }); + }); +}); + +const patterns = { + COLOR: "^#(?:[0-9a-fA-F]{3}){1,2}$", + ENCODER_BACKGROUND_PATH: "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Pp][Nn][Gg])|([Ss][Vv][Gg]))$).*$", + FILE_PATH: "^(?![~\\.]*[\\\\\\/]+).*$", + HTML_PATH: "^(?![~\\.]*[\\\\\\/]+).*\\.(([Hh][Tt][Mm])|([Hh][Tt][Mm][Ll]))$", + LAYOUT: "^(^(?![\\.]*[\\\\\\/]+).+\\.([Jj][Ss][Oo][Nn])$)|(\\$(X1|A0|A1|B1|B2|C1))$", + IMAGE_PATH_WITH_GIF_SUPPORT: "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Gg][Ii][Ff])|([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$", + IMAGE_PATH: "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$", + ICON_PATH: "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Pp][Nn][Gg]))$).*$", + PROFILE_PATH: "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Ss][Tt][Rr][Ee][Aa][Mm][Dd][Ee][Cc][Kk][Pp][Rr][Oo][Ff][Ii][Ll][Ee]))$).*$", + UUID: "^([a-z0-9-]+)(\\.[a-z0-9-]+)+$" +}; diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/Actions[].OS.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/Actions[].OS.json new file mode 100644 index 0000000..9b28baa --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/Actions[].OS.json @@ -0,0 +1,44 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Icon": "action-icon", + "Name": "Action One", + "OS": ["mac", "windows"], + "States": [ + { + "Image": "action-state-image" + } + ], + "UUID": "com.elgato.test.one" + } + ], + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "20" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "SDKVersion": 2, + "Software": { + "MinimumVersion": "6.6" + }, + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/Profiles[].AutoInstall.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/Profiles[].AutoInstall.json new file mode 100644 index 0000000..0fbad5f --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/Profiles[].AutoInstall.json @@ -0,0 +1,50 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Icon": "action-icon", + "Name": "Action One", + "States": [ + { + "Image": "action-state-image" + } + ], + "UUID": "com.elgato.test.one" + } + ], + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "20" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "AutoInstall": false, + "DeviceType": 7, + "Name": "Test Profile" + } + ], + "SDKVersion": 2, + "Software": { + "MinimumVersion": "6.6" + }, + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.4.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.4.json new file mode 100644 index 0000000..ff5079f --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.4.json @@ -0,0 +1,90 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Controllers": ["Encoder", "Keypad"], + "DisableAutomaticStates": true, + "DisableCaching": false, + "Encoder": { + "background": "background", + "Icon": "icon", + "layout": "$A0", + "StackColor": "#000000", + "TriggerDescription": { + "LongTouch": "Long touch", + "Push": "Push", + "Rotate": "Rotate", + "Touch": "Touch" + } + }, + "Icon": "action-icon", + "Name": "Action One", + "PropertyInspectorPath": "action.html", + "States": [ + { + "FontFamily": "Arial", + "FontSize": 12, + "FontStyle": "Bold", + "FontUnderline": true, + "Image": "action-state-image", + "MultiActionImage": "action-state-multi-action-image", + "Name": "Action State One", + "ShowTitle": true, + "Title": "State One", + "TitleAlignment": "bottom", + "TitleColor": "#000000" + } + ], + "SupportedInMultiActions": true, + "Tooltip": "This is the tooltip", + "UserTitleEnabled": true, + "UUID": "com.elgato.test.one", + "VisibleInActionsList": true + } + ], + "ApplicationsToMonitor": { + "mac": ["finder"], + "windows": ["explorer.exe"] + }, + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "CodePathMac": "main-darwin.js", + "CodePathWin": "main-windows.js", + "DefaultWindowSize": [500, 650], + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "20" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "DeviceType": 7, + "DontAutoSwitchWhenInstalled": true, + "Name": "Test Profile", + "Readonly": true + } + ], + "PropertyInspectorPath": "pi.html", + "SDKVersion": 2, + "Software": { + "MinimumVersion": "6.4" + }, + "URL": "https://www.elgato.com", + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.5.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.5.json new file mode 100644 index 0000000..730e539 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.5.json @@ -0,0 +1,90 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Controllers": ["Encoder", "Keypad"], + "DisableAutomaticStates": true, + "DisableCaching": false, + "Encoder": { + "background": "background", + "Icon": "icon", + "layout": "$A0", + "StackColor": "#000000", + "TriggerDescription": { + "LongTouch": "Long touch", + "Push": "Push", + "Rotate": "Rotate", + "Touch": "Touch" + } + }, + "Icon": "action-icon", + "Name": "Action One", + "PropertyInspectorPath": "action.html", + "States": [ + { + "FontFamily": "Arial", + "FontSize": 12, + "FontStyle": "Bold", + "FontUnderline": true, + "Image": "action-state-image", + "MultiActionImage": "action-state-multi-action-image", + "Name": "Action State One", + "ShowTitle": true, + "Title": "State One", + "TitleAlignment": "bottom", + "TitleColor": "#000000" + } + ], + "SupportedInMultiActions": true, + "Tooltip": "This is the tooltip", + "UserTitleEnabled": true, + "UUID": "com.elgato.test.one", + "VisibleInActionsList": true + } + ], + "ApplicationsToMonitor": { + "mac": ["finder"], + "windows": ["explorer.exe"] + }, + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "CodePathMac": "main-darwin.js", + "CodePathWin": "main-windows.js", + "DefaultWindowSize": [500, 650], + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "20" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "DeviceType": 7, + "DontAutoSwitchWhenInstalled": true, + "Name": "Test Profile", + "Readonly": true + } + ], + "PropertyInspectorPath": "pi.html", + "SDKVersion": 2, + "Software": { + "MinimumVersion": "6.5" + }, + "URL": "https://www.elgato.com", + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.6.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.6.json new file mode 100644 index 0000000..7187fca --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.6.json @@ -0,0 +1,91 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Controllers": ["Encoder", "Keypad"], + "DisableAutomaticStates": true, + "DisableCaching": false, + "Encoder": { + "background": "background", + "Icon": "icon", + "layout": "$A0", + "StackColor": "#000000", + "TriggerDescription": { + "LongTouch": "Long touch", + "Push": "Push", + "Rotate": "Rotate", + "Touch": "Touch" + } + }, + "Icon": "action-icon", + "Name": "Action One", + "OS": ["mac", "windows"], + "PropertyInspectorPath": "action.html", + "States": [ + { + "FontFamily": "Arial", + "FontSize": 12, + "FontStyle": "Bold", + "FontUnderline": true, + "Image": "action-state-image", + "MultiActionImage": "action-state-multi-action-image", + "Name": "Action State One", + "ShowTitle": true, + "Title": "State One", + "TitleAlignment": "bottom", + "TitleColor": "#000000" + } + ], + "SupportedInMultiActions": true, + "Tooltip": "This is the tooltip", + "UserTitleEnabled": true, + "UUID": "com.elgato.test.one", + "VisibleInActionsList": true + } + ], + "ApplicationsToMonitor": { + "mac": ["finder"], + "windows": ["explorer.exe"] + }, + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "CodePathMac": "main-darwin.js", + "CodePathWin": "main-windows.js", + "DefaultWindowSize": [500, 650], + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "20" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "DeviceType": 7, + "DontAutoSwitchWhenInstalled": true, + "Name": "Test Profile", + "Readonly": true + } + ], + "PropertyInspectorPath": "pi.html", + "SDKVersion": 2, + "Software": { + "MinimumVersion": "6.6" + }, + "URL": "https://www.elgato.com", + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.7.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.7.json new file mode 100644 index 0000000..8daa8f3 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.7.json @@ -0,0 +1,91 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Controllers": ["Encoder", "Keypad"], + "DisableAutomaticStates": true, + "DisableCaching": false, + "Encoder": { + "background": "background", + "Icon": "icon", + "layout": "$A0", + "StackColor": "#000000", + "TriggerDescription": { + "LongTouch": "Long touch", + "Push": "Push", + "Rotate": "Rotate", + "Touch": "Touch" + } + }, + "Icon": "action-icon", + "Name": "Action One", + "OS": ["mac", "windows"], + "PropertyInspectorPath": "action.html", + "States": [ + { + "FontFamily": "Arial", + "FontSize": 12, + "FontStyle": "Bold", + "FontUnderline": true, + "Image": "action-state-image", + "MultiActionImage": "action-state-multi-action-image", + "Name": "Action State One", + "ShowTitle": true, + "Title": "State One", + "TitleAlignment": "bottom", + "TitleColor": "#000000" + } + ], + "SupportedInMultiActions": true, + "Tooltip": "This is the tooltip", + "UserTitleEnabled": true, + "UUID": "com.elgato.test.one", + "VisibleInActionsList": true + } + ], + "ApplicationsToMonitor": { + "mac": ["finder"], + "windows": ["explorer.exe"] + }, + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "CodePathMac": "main-darwin.js", + "CodePathWin": "main-windows.js", + "DefaultWindowSize": [500, 650], + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "20" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "DeviceType": 7, + "DontAutoSwitchWhenInstalled": true, + "Name": "Test Profile", + "Readonly": true + } + ], + "PropertyInspectorPath": "pi.html", + "SDKVersion": 2, + "Software": { + "MinimumVersion": "6.7" + }, + "URL": "https://www.elgato.com", + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.8.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.8.json new file mode 100644 index 0000000..c4999a9 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.8.json @@ -0,0 +1,91 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Controllers": ["Encoder", "Keypad"], + "DisableAutomaticStates": true, + "DisableCaching": false, + "Encoder": { + "background": "background", + "Icon": "icon", + "layout": "$A0", + "StackColor": "#000000", + "TriggerDescription": { + "LongTouch": "Long touch", + "Push": "Push", + "Rotate": "Rotate", + "Touch": "Touch" + } + }, + "Icon": "action-icon", + "Name": "Action One", + "OS": ["mac", "windows"], + "PropertyInspectorPath": "action.html", + "States": [ + { + "FontFamily": "Arial", + "FontSize": 12, + "FontStyle": "Bold", + "FontUnderline": true, + "Image": "action-state-image", + "MultiActionImage": "action-state-multi-action-image", + "Name": "Action State One", + "ShowTitle": true, + "Title": "State One", + "TitleAlignment": "bottom", + "TitleColor": "#000000" + } + ], + "SupportedInMultiActions": true, + "Tooltip": "This is the tooltip", + "UserTitleEnabled": true, + "UUID": "com.elgato.test.one", + "VisibleInActionsList": true + } + ], + "ApplicationsToMonitor": { + "mac": ["finder"], + "windows": ["explorer.exe"] + }, + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "CodePathMac": "main-darwin.js", + "CodePathWin": "main-windows.js", + "DefaultWindowSize": [500, 650], + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "20" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "DeviceType": 7, + "DontAutoSwitchWhenInstalled": true, + "Name": "Test Profile", + "Readonly": true + } + ], + "PropertyInspectorPath": "pi.html", + "SDKVersion": 2, + "Software": { + "MinimumVersion": "6.8" + }, + "URL": "https://www.elgato.com", + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.9.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.9.json new file mode 100644 index 0000000..378bdfb --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v6.9.json @@ -0,0 +1,93 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Controllers": ["Encoder", "Keypad"], + "DisableAutomaticStates": true, + "DisableCaching": false, + "Encoder": { + "background": "background", + "Icon": "icon", + "layout": "$A0", + "StackColor": "#000000", + "TriggerDescription": { + "LongTouch": "Long touch", + "Push": "Push", + "Rotate": "Rotate", + "Touch": "Touch" + } + }, + "Icon": "action-icon", + "Name": "Action One", + "OS": ["mac", "windows"], + "PropertyInspectorPath": "action.html", + "States": [ + { + "FontFamily": "Arial", + "FontSize": 12, + "FontStyle": "Bold", + "FontUnderline": true, + "Image": "action-state-image", + "MultiActionImage": "action-state-multi-action-image", + "Name": "Action State One", + "ShowTitle": true, + "Title": "State One", + "TitleAlignment": "bottom", + "TitleColor": "#000000" + } + ], + "SupportURL": "https://help.elgato.com", + "SupportedInMultiActions": true, + "Tooltip": "This is the tooltip", + "UserTitleEnabled": true, + "UUID": "com.elgato.test.one", + "VisibleInActionsList": true + } + ], + "ApplicationsToMonitor": { + "mac": ["finder"], + "windows": ["explorer.exe"] + }, + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "CodePathMac": "main-darwin.js", + "CodePathWin": "main-windows.js", + "DefaultWindowSize": [500, 650], + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "20" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "DeviceType": 7, + "DontAutoSwitchWhenInstalled": true, + "Name": "Test Profile", + "Readonly": true + } + ], + "PropertyInspectorPath": "pi.html", + "SDKVersion": 3, + "Software": { + "MinimumVersion": "6.9" + }, + "SupportURL": "https://help.elgato.com", + "URL": "https://www.elgato.com", + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.0.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.0.json new file mode 100644 index 0000000..e67d2d3 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.0.json @@ -0,0 +1,94 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Controllers": ["Encoder", "Keypad"], + "DisableAutomaticStates": true, + "DisableCaching": false, + "Encoder": { + "background": "background", + "Icon": "icon", + "layout": "$A0", + "StackColor": "#000000", + "TriggerDescription": { + "LongTouch": "Long touch", + "Push": "Push", + "Rotate": "Rotate", + "Touch": "Touch" + } + }, + "Icon": "action-icon", + "Name": "Action One", + "OS": ["mac", "windows"], + "PropertyInspectorPath": "action.html", + "States": [ + { + "FontFamily": "Arial", + "FontSize": 12, + "FontStyle": "Bold", + "FontUnderline": true, + "Image": "action-state-image", + "MultiActionImage": "action-state-multi-action-image", + "Name": "Action State One", + "ShowTitle": true, + "Title": "State One", + "TitleAlignment": "bottom", + "TitleColor": "#000000" + } + ], + "SupportURL": "https://help.elgato.com", + "SupportedInKeyLogicActions": true, + "SupportedInMultiActions": true, + "Tooltip": "This is the tooltip", + "UserTitleEnabled": true, + "UUID": "com.elgato.test.one", + "VisibleInActionsList": true + } + ], + "ApplicationsToMonitor": { + "mac": ["finder"], + "windows": ["explorer.exe"] + }, + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "CodePathMac": "main-darwin.js", + "CodePathWin": "main-windows.js", + "DefaultWindowSize": [500, 650], + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "20" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "DeviceType": 7, + "DontAutoSwitchWhenInstalled": true, + "Name": "Test Profile", + "Readonly": true + } + ], + "PropertyInspectorPath": "pi.html", + "SDKVersion": 3, + "Software": { + "MinimumVersion": "7.0" + }, + "SupportURL": "https://help.elgato.com", + "URL": "https://www.elgato.com", + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.1.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.1.json new file mode 100644 index 0000000..0ea69a7 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.1.json @@ -0,0 +1,94 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Controllers": ["Encoder", "Keypad"], + "DisableAutomaticStates": true, + "DisableCaching": false, + "Encoder": { + "background": "background", + "Icon": "icon", + "layout": "$A0", + "StackColor": "#000000", + "TriggerDescription": { + "LongTouch": "Long touch", + "Push": "Push", + "Rotate": "Rotate", + "Touch": "Touch" + } + }, + "Icon": "action-icon", + "Name": "Action One", + "OS": ["mac", "windows"], + "PropertyInspectorPath": "action.html", + "States": [ + { + "FontFamily": "Arial", + "FontSize": 12, + "FontStyle": "Bold", + "FontUnderline": true, + "Image": "action-state-image", + "MultiActionImage": "action-state-multi-action-image", + "Name": "Action State One", + "ShowTitle": true, + "Title": "State One", + "TitleAlignment": "bottom", + "TitleColor": "#000000" + } + ], + "SupportURL": "https://help.elgato.com", + "SupportedInKeyLogicActions": true, + "SupportedInMultiActions": true, + "Tooltip": "This is the tooltip", + "UserTitleEnabled": true, + "UUID": "com.elgato.test.one", + "VisibleInActionsList": true + } + ], + "ApplicationsToMonitor": { + "mac": ["finder"], + "windows": ["explorer.exe"] + }, + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "CodePathMac": "main-darwin.js", + "CodePathWin": "main-windows.js", + "DefaultWindowSize": [500, 650], + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "24" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "DeviceType": 7, + "DontAutoSwitchWhenInstalled": true, + "Name": "Test Profile", + "Readonly": true + } + ], + "PropertyInspectorPath": "pi.html", + "SDKVersion": 3, + "Software": { + "MinimumVersion": "7.1" + }, + "SupportURL": "https://help.elgato.com", + "URL": "https://www.elgato.com", + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.2.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.2.json new file mode 100644 index 0000000..a43b437 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.2.json @@ -0,0 +1,94 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Controllers": ["Encoder", "Keypad"], + "DisableAutomaticStates": true, + "DisableCaching": false, + "Encoder": { + "background": "background", + "Icon": "icon", + "layout": "$A0", + "StackColor": "#000000", + "TriggerDescription": { + "LongTouch": "Long touch", + "Push": "Push", + "Rotate": "Rotate", + "Touch": "Touch" + } + }, + "Icon": "action-icon", + "Name": "Action One", + "OS": ["mac", "windows"], + "PropertyInspectorPath": "action.html", + "States": [ + { + "FontFamily": "Arial", + "FontSize": 12, + "FontStyle": "Bold", + "FontUnderline": true, + "Image": "action-state-image", + "MultiActionImage": "action-state-multi-action-image", + "Name": "Action State One", + "ShowTitle": true, + "Title": "State One", + "TitleAlignment": "bottom", + "TitleColor": "#000000" + } + ], + "SupportURL": "https://help.elgato.com", + "SupportedInKeyLogicActions": true, + "SupportedInMultiActions": true, + "Tooltip": "This is the tooltip", + "UserTitleEnabled": true, + "UUID": "com.elgato.test.one", + "VisibleInActionsList": true + } + ], + "ApplicationsToMonitor": { + "mac": ["finder"], + "windows": ["explorer.exe"] + }, + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "CodePathMac": "main-darwin.js", + "CodePathWin": "main-windows.js", + "DefaultWindowSize": [500, 650], + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "24" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "DeviceType": 7, + "DontAutoSwitchWhenInstalled": true, + "Name": "Test Profile", + "Readonly": true + } + ], + "PropertyInspectorPath": "pi.html", + "SDKVersion": 3, + "Software": { + "MinimumVersion": "7.2" + }, + "SupportURL": "https://help.elgato.com", + "URL": "https://www.elgato.com", + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.3.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.3.json new file mode 100644 index 0000000..9bc7cad --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.3.json @@ -0,0 +1,94 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Controllers": ["Encoder", "Keypad"], + "DisableAutomaticStates": true, + "DisableCaching": false, + "Encoder": { + "background": "background", + "Icon": "icon", + "layout": "$A0", + "StackColor": "#000000", + "TriggerDescription": { + "LongTouch": "Long touch", + "Push": "Push", + "Rotate": "Rotate", + "Touch": "Touch" + } + }, + "Icon": "action-icon", + "Name": "Action One", + "OS": ["mac", "windows"], + "PropertyInspectorPath": "action.html", + "States": [ + { + "FontFamily": "Arial", + "FontSize": 12, + "FontStyle": "Bold", + "FontUnderline": true, + "Image": "action-state-image", + "MultiActionImage": "action-state-multi-action-image", + "Name": "Action State One", + "ShowTitle": true, + "Title": "State One", + "TitleAlignment": "bottom", + "TitleColor": "#000000" + } + ], + "SupportURL": "https://help.elgato.com", + "SupportedInKeyLogicActions": true, + "SupportedInMultiActions": true, + "Tooltip": "This is the tooltip", + "UserTitleEnabled": true, + "UUID": "com.elgato.test.one", + "VisibleInActionsList": true + } + ], + "ApplicationsToMonitor": { + "mac": ["finder"], + "windows": ["explorer.exe"] + }, + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "CodePathMac": "main-darwin.js", + "CodePathWin": "main-windows.js", + "DefaultWindowSize": [500, 650], + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "24" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "DeviceType": 13, + "DontAutoSwitchWhenInstalled": true, + "Name": "Test Profile", + "Readonly": true + } + ], + "PropertyInspectorPath": "pi.html", + "SDKVersion": 3, + "Software": { + "MinimumVersion": "7.3" + }, + "SupportURL": "https://help.elgato.com", + "URL": "https://www.elgato.com", + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.4.json b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.4.json new file mode 100644 index 0000000..4434c04 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/files/v7.4.json @@ -0,0 +1,94 @@ +{ + "$schema": "../../../../../../streamdeck/plugins/manifest.json", + "Actions": [ + { + "Controllers": ["Encoder", "Keypad"], + "DisableAutomaticStates": true, + "DisableCaching": false, + "Encoder": { + "background": "background", + "Icon": "icon", + "layout": "$A0", + "StackColor": "#000000", + "TriggerDescription": { + "LongTouch": "Long touch", + "Push": "Push", + "Rotate": "Rotate", + "Touch": "Touch" + } + }, + "Icon": "action-icon", + "Name": "Action One", + "OS": ["mac", "windows"], + "PropertyInspectorPath": "action.html", + "States": [ + { + "FontFamily": "Arial", + "FontSize": 12, + "FontStyle": "Bold", + "FontUnderline": true, + "Image": "action-state-image", + "MultiActionImage": "action-state-multi-action-image", + "Name": "Action State One", + "ShowTitle": true, + "Title": "State One", + "TitleAlignment": "bottom", + "TitleColor": "#000000" + } + ], + "SupportURL": "https://help.elgato.com", + "SupportedInKeyLogicActions": true, + "SupportedInMultiActions": true, + "Tooltip": "This is the tooltip", + "UserTitleEnabled": true, + "UUID": "com.elgato.test.one", + "VisibleInActionsList": true + } + ], + "ApplicationsToMonitor": { + "mac": ["finder"], + "windows": ["explorer.exe"] + }, + "Author": "Elgato", + "Category": "Testing", + "CategoryIcon": "category-icon", + "CodePath": "main.js", + "CodePathMac": "main-darwin.js", + "CodePathWin": "main-windows.js", + "DefaultWindowSize": [500, 650], + "Description": "Manifest version 6.4", + "Icon": "icon", + "Name": "Test Manifest", + "Nodejs": { + "Debug": "break", + "GenerateProfilerOutput": false, + "Version": "24" + }, + "OS": [ + { + "MinimumVersion": "13", + "Platform": "mac" + }, + { + "MinimumVersion": "10", + "Platform": "windows" + } + ], + "Profiles": [ + { + "DeviceType": 13, + "DontAutoSwitchWhenInstalled": true, + "Name": "Test Profile", + "Readonly": true + } + ], + "PropertyInspectorPath": "pi.html", + "SDKVersion": 3, + "Software": { + "MinimumVersion": "7.4" + }, + "SupportURL": "https://help.elgato.com", + "URL": "https://www.elgato.com", + "UUID": "com.elgato.test", + "Version": "1.0.0.0" +} diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.4.test.ts b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.4.test.ts new file mode 100644 index 0000000..c5f727f --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.4.test.ts @@ -0,0 +1,46 @@ +import { validateStreamDeckPluginManifest } from "@tests"; + +const VERSION = "6.4"; + +describe("v6.4", () => { + /** + * Asserts a valid v6.4 manifest. + */ + test("full manifest", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest("v6.4.json"); + expect(errors).toHaveLength(0); + }); + + describe("v6.6 features", () => { + /** + * Asserts `Actions[].OS` is not valid for a v6.4 manifest. + */ + test("Actions[].OS is not valid in v6.4", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest("Actions[].OS.json", (m) => (m.Software.MinimumVersion = VERSION)); + expect(errors).toHaveError({ + instancePath: "/Actions/0", + keyword: "additionalProperties", + params: { + additionalProperty: "OS" + } + }); + }); + + /** + * Asserts `Profiles[].AutoInstall` is not valid for a v6.4 manifest. + */ + test("Profiles[].AutoInstall is not valid in v6.4", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest("Profiles[].AutoInstall.json", (m) => (m.Software.MinimumVersion = VERSION)); + expect(errors).toHaveError({ + instancePath: "/Profiles/0", + keyword: "additionalProperties", + params: { + additionalProperty: "AutoInstall" + } + }); + }); + }); +}); diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.5.test.ts b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.5.test.ts new file mode 100644 index 0000000..ea3ab79 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.5.test.ts @@ -0,0 +1,46 @@ +import { validateStreamDeckPluginManifest } from "@tests"; + +const VERSION = "6.5"; + +describe("v6.5", () => { + /** + * Asserts a valid v6.5 manifest. + */ + test("full manifest", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest("v6.5.json"); + expect(errors).toHaveLength(0); + }); + + describe("v6.6 features", () => { + /** + * Asserts `Actions[].OS` is not valid for a v6.5 manifest. + */ + test("Actions[].OS is not valid in v6.5", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest("Actions[].OS.json", (m) => (m.Software.MinimumVersion = VERSION)); + expect(errors).toHaveError({ + instancePath: "/Actions/0", + keyword: "additionalProperties", + params: { + additionalProperty: "OS" + } + }); + }); + + /** + * Asserts `Profiles[].AutoInstall` is not valid for a v6.5 manifest. + */ + test("Profiles[].AutoInstall is not valid in v6.5", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest("Profiles[].AutoInstall.json", (m) => (m.Software.MinimumVersion = VERSION)); + expect(errors).toHaveError({ + instancePath: "/Profiles/0", + keyword: "additionalProperties", + params: { + additionalProperty: "AutoInstall" + } + }); + }); + }); +}); diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.6.test.ts b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.6.test.ts new file mode 100644 index 0000000..507ce60 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.6.test.ts @@ -0,0 +1,101 @@ +import { validateStreamDeckPluginManifest } from "@tests"; + +describe.each(["6.6" as const, "6.7" as const, "6.8" as const])("v%s", (version) => { + /** + * Asserts the full manifest. + */ + test("full manifest", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(`v${version}.json`); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts more than 2 states are allowed. + */ + test("Actions[].States[] allow more than 2 items", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => { + m.Actions[0].States.push({ Image: "imgs/two" }); + m.Actions[0].States.push({ Image: "imgs/three" }); + m.Actions[0].States.push({ Image: "imgs/four" }); + }); + expect(errors).toHaveLength(0); + }); + + describe(`v${version} feature compatibility`, () => { + /** + * Asserts `Actions[].OS` is not valid for a v6.5 manifest. + */ + test("Actions[].OS is valid", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest("Actions[].OS.json", (m) => (m.Software.MinimumVersion = version)); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts `Profiles[].AutoInstall` is not valid for a v6.5 manifest. + */ + test("Profiles[].AutoInstall is valid", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest("Profiles[].AutoInstall.json", (m) => (m.Software.MinimumVersion = version)); + expect(errors).toHaveLength(0); + }); + }); + + describe("SDKVersion", () => { + /** + * Asserts the `SDKVersion` can be `2`. + */ + it("can be 2", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => { + m.SDKVersion = 2; + }); + + expect(errors).toHaveLength(0); + }); + + /** + * Asserts the `SDKVersion` cannot be `3`. + */ + it("cannot be 3", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => { + m.Software.MinimumVersion = version; + m.SDKVersion = 3; + }); + + expect(errors).toHaveError({ + keyword: "const", + instancePath: "/SDKVersion", + params: { + allowedValue: 2 + } + }); + }); + }); + + /** + * Asserts the SupportURL is invalid. + */ + test("SupportURL is invalid", () => { + // Arrange, act. + const errors = validateStreamDeckPluginManifest("v6.9.json", (m) => (m.Software.MinimumVersion = "6.8")); + + // Assert. + expect(errors).toHaveError({ + keyword: "additionalProperties", + instancePath: "/Actions/0", + params: { + additionalProperty: "SupportURL" + } + }); + + expect(errors).toHaveError({ + keyword: "additionalProperties", + instancePath: "", + params: { + additionalProperty: "SupportURL" + } + }); + }); +}); diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.9.test.ts b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.9.test.ts new file mode 100644 index 0000000..58ab23b --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v6.9.test.ts @@ -0,0 +1,59 @@ +import { validateStreamDeckPluginManifest } from "@tests"; + +describe.each(["6.9" as const])("v%s", (version) => { + /** + * Asserts the full manifest. + */ + test("full manifest", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(`v${version}.json`); + expect(errors).toHaveLength(0); + }); + + describe("SDKVersion", () => { + /** + * Asserts the `SDKVersion` can be `2`. + */ + test("can be 2", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => (m.SDKVersion = 2)); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts the `SDKVersion` can be `3`. + */ + test("can be 3", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => (m.SDKVersion = 3)); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts the `SDKVersion` is within scope. + */ + test("cannot be 4", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => { + // @ts-expect-error: To test invalid values + m.SDKVersion = 4; + }); + + expect(errors).toHaveError({ + keyword: "enum", + instancePath: "/SDKVersion", + params: { + allowedValues: [2, 3] + } + }); + }); + }); + + test("SupportURL is optional", () => { + // Arrange, act. + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => { + m.Actions[0].SupportURL = undefined; + m.SupportURL = undefined; + }); + + // Assert. + expect(errors).toHaveLength(0); + }); +}); diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v7.0.test.ts b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v7.0.test.ts new file mode 100644 index 0000000..75621b3 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v7.0.test.ts @@ -0,0 +1,101 @@ +import { validateStreamDeckPluginManifest } from "@tests"; + +describe.each(["7.0" as const])("v%s", (version) => { + /** + * Asserts the full manifest. + */ + test("full manifest", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(`v${version}.json`); + expect(errors).toHaveLength(0); + }); + + describe("SDKVersion", () => { + /** + * Asserts the `SDKVersion` can be `2`. + */ + test("can be 2", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => (m.SDKVersion = 2)); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts the `SDKVersion` can be `3`. + */ + test("can be 3", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => (m.SDKVersion = 3)); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts the `SDKVersion` is within scope. + */ + test("cannot be 4", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => { + // @ts-expect-error: To test invalid values + m.SDKVersion = 4; + }); + + expect(errors).toHaveError({ + keyword: "enum", + instancePath: "/SDKVersion", + params: { + allowedValues: [2, 3] + } + }); + }); + }); + + test("Node.js is optional", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => (m.Nodejs = undefined)); + expect(errors).toHaveLength(0); + }); + + describe("Nodejs.Version", () => { + /** + * Asserts Nodejs.Version can be 20. + */ + it("can be 20", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => (m.Nodejs!.Version = "20")); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts Nodejs.Version can be 24. + */ + it("cannot be 24", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => (m.Nodejs!.Version = "24")); + expect(errors).toHaveError({ + keyword: "const", + instancePath: "/Nodejs/Version", + params: { + allowedValue: "20" + } + }); + }); + }); +}); + +describe("SupportedInKeyLogicActions", () => { + /** + * Asserts Actions[].SupportedInKeyLogicActions is available in Stream Deck 7.0. + */ + it("is supported in 7.0", () => { + const errors = validateStreamDeckPluginManifest(`v7.0.json`, (m) => (m.Actions[0].SupportedInKeyLogicActions = true)); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts Actions[].SupportedInKeyLogicActions is not available in Stream Deck 6.9. + */ + it("is not supported in 6.9", () => { + const errors = validateStreamDeckPluginManifest(`v6.9.json`, (m) => (m.Actions[0].SupportedInKeyLogicActions = true)); + expect(errors).toHaveError({ + keyword: "additionalProperties", + instancePath: "/Actions/0", + params: { + additionalProperty: "SupportedInKeyLogicActions" + } + }); + }); +}); diff --git a/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v7.1.test.ts b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v7.1.test.ts new file mode 100644 index 0000000..5c3793c --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/__tests__/v7.1.test.ts @@ -0,0 +1,84 @@ +import { validateStreamDeckPluginManifest } from "@tests"; + +describe.each(["7.1" as const, "7.2" as const, "7.3" as const, "7.4" as const])("v%s", (version) => { + /** + * Asserts the full manifest. + */ + test("full manifest", () => { + // Arrange, act, assert. + const errors = validateStreamDeckPluginManifest(`v${version}.json`); + expect(errors).toHaveLength(0); + }); + + describe("SDKVersion", () => { + /** + * Asserts the `SDKVersion` can be `2`. + */ + test("can be 2", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => (m.SDKVersion = 2)); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts the `SDKVersion` can be `3`. + */ + test("can be 3", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => (m.SDKVersion = 3)); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts the `SDKVersion` is within scope. + */ + test("cannot be 4", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => { + // @ts-expect-error: To test invalid values + m.SDKVersion = 4; + }); + + expect(errors).toHaveError({ + keyword: "enum", + instancePath: "/SDKVersion", + params: { + allowedValues: [2, 3] + } + }); + }); + }); + + describe("Nodejs.Version", () => { + /** + * Asserts Nodejs.Version can be 20. + */ + it("can be 20", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => (m.Nodejs!.Version = "20")); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts Nodejs.Version can be 24. + */ + it("can be 24", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => (m.Nodejs!.Version = "24")); + expect(errors).toHaveLength(0); + }); + + /** + * Asserts Node.js version cannot be 21. + */ + it("cannot be 21", () => { + const errors = validateStreamDeckPluginManifest(`v${version}.json`, (m) => { + // @ts-expect-error Check invalid value + m.Nodejs!.Version = "21"; + }); + + expect(errors).toHaveError({ + keyword: "enum", + instancePath: "/Nodejs/Version", + params: { + allowedValues: ["20", "24"] + } + }); + }); + }); +}); diff --git a/packages/schemas/src/streamdeck/plugins/manifest/latest.ts b/packages/schemas/src/streamdeck/plugins/manifest/latest.ts new file mode 100644 index 0000000..547291b --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/latest.ts @@ -0,0 +1,752 @@ +import { DeviceType } from "../device-type"; +import type { Manifest as ManifestSchema } from "../schemas"; + +/** + * Determines the Stream Deck software requirements for this plugin. + */ +export type Software = { + /** + * Minimum version of the Stream Deck application required for this plugin to run. + */ + MinimumVersion: ManifestSchema["Software"]["MinimumVersion"]; +}; + +/** + * Defines the plugin and available actions, and all information associated with them, including the plugin's entry point, all iconography, action default behavior, etc. + */ +export type Manifest = { + /** + * Collection of actions provided by the plugin, and all of their information; this can include actions that are available to users via the actions list, and actions that are + * hidden to the user but available to pre-defined profiles distributed with the plugin (`Manifest.Actions.VisibleInActionsList`). + */ + Actions: Action[]; + + /** + * Applications to monitor on Mac and Windows; upon a monitored application being launched or terminated, Stream Deck will notify the plugin. + * + * **Also see:** + * - `streamDeck.system.onApplicationDidLaunch(...)` + * - `streamDeck.system.onApplicationDidTerminate(...)` + */ + ApplicationsToMonitor?: ApplicationMonitoring; + + /** + * Author's name that will be displayed on the plugin's product page on the Marketplace, e.g. "Elgato". + */ + Author: string; + + /** + * Defines the actions list group, providing a natural grouping of the plugin's actions with the Stream Deck application's action list. + * + * Note: `Category` should be distinctive and synonymous with your plugin, and it is therefore recommended that this be the same value as the plugin's `Name` field. When `undefined`, the + * actions will be available under the "Custom" group. + */ + Category?: string; + + /** + * Path to the image, with the **file extension omitted**, that will be displayed next to the action list group within the Stream Deck application. The icon should accurately represent + * the plugin, and enable users to quickly identify the plugin. + * + * Image must be: + * - PNG or SVG format. + * - Provided in two sizes, 28 × 28 px and 56 × 56 px (@2x). + * - Monochromatic, with foreground color of #FFFFFF and a transparent background. + * + * **Examples**: + * - assets/category-icon + * - imgs/category + * @filePath + * { extensions: [".svg", ".png"], includeExtension: false } + * @imageDimensions + * [28, 28] + */ + CategoryIcon?: string; + + /** + * Path to the plugin's main entry point; this is executed when the Stream Deck application starts the plugin. + * + * **Examples**: + * - index.js + * - Counter + * - Counter.exe + * @filePath + */ + CodePath: string; + + /** + * Path to the plugin's entry point specific to macOS; this is executed when the Stream Deck application starts the plugin on macOS. + * + * **Examples:** + * - index.js + * - Counter + * @filePath + */ + CodePathMac?: string; + + /** + * Path to the plugin's entry point specific to Windows; this is executed when the Stream Deck application starts the plugin on Windows. + * + * **Examples:** + * - index.js + * - Counter.exe + * @filePath + */ + CodePathWin?: string; + + /** + * Size of a window (`[width, height]`) opened when calling `window.open()` from the property inspector. Default value is `[500, 650]`. + * @example + * [500, 650] + */ + DefaultWindowSize?: [number, number]; + + /** + * Description of the plugin, and the functionality it provides, that will be displayed on the plugin's product page on the Marketplace. + */ + Description: string; + + /** + * Path to the image, with the **file extension omitted**, that will be displayed within Stream Deck's preferences. + * + * Image must be: + * - PNG format. + * - Provided in two sizes, 256 × 256 px and 512 × 512 px (@2x). + * + * **Examples:** + * - assets/plugin-icon + * - imgs/plugin + * @filePath + * { extensions: [".png"], includeExtension: false } + * @imageDimensions + * [256, 256] + */ + Icon: string; + + /** + * Name of the plugin, e.g. "Wave Link", "Camera Hub", "Control Center", etc. + */ + Name: string; + + /** + * Configuration options for Node.js based plugins. + * + * Note: All Node.js plugins are executed with the following command-line arguments: + * + * - [`--no-addons`](https://nodejs.org/api/cli.html#--no-addons) (Stream Deck 6.4 only) + * - [`--enable-source-maps`](https://nodejs.org/api/cli.html#--enable-source-maps) + * - [`--no-global-search-paths`](https://nodejs.org/api/cli.html#--no-global-search-paths) + */ + Nodejs?: Nodejs; + + /** + * Collection of operating systems, and their minimum required versions, that the plugin supports. + */ + OS: [OS, OS?]; + + /** + * Collection of pre-defined profiles that are distributed with this plugin. Upon the plugin switching to the profile, the user will be prompted to install the profiles. + * + * Note: Plugins may only switch to profiles distributed with the plugin, as defined within the manifest, and cannot access user-defined profiles. + * + * **Also see:** + * `streamDeck.profiles.switchToProfile(...)` + */ + Profiles?: Profile[]; + + /** + * Optional path to the HTML file that represents the property inspector for all actions; this is displayed to the user in the Stream Deck application when they add an action, + * allowing them to configure the action's settings. + * + * Note: Path should be relative to the root of the plugin's folder, with no leading slash. + * + * **Examples:** + * - mute.html + * - actions/join-voice-chat/settings.html + * + * **Also see:** + * - `streamDeck.ui.onSendToPlugin(...)` + * @filePath + * { extensions: [".htm", ".html"], includeExtension: true } + */ + PropertyInspectorPath?: FilePath<"htm" | "html">; + + /** + * Preferred SDK version (version 3 is recommended). + */ + SDKVersion: 2 | 3; + + /** + * Determines the Stream Deck software requirements for this plugin. + */ + Software: Software; + + /** + * Link to the plugin's support website. + * + * **Examples**: + * - https://help.corsair.com/ + * - https://help.elgato.com/ + * + * Available from Stream Deck 6.9. + */ + SupportURL?: string; + + /** + * Link to the plugin's website. + * + * **Examples**: + * - https://elgato.com + * - https://corsair.com + */ + URL?: string; + + /** + * Unique identifier of the plugin, represented in reverse-DNS format. + * + * **Allowed characters:** + * - Lowercase alphanumeric characters (a-z, 0-9) + * - Hyphens (-) + * - Periods (.) + * + * **Examples:** + * - com.elgato.wavelink + * - com.elgato.discord + * - tv.twitch + * @pattern + * ^([a-z0-9-]+)(\.[a-z0-9-]+)+$ + * @errorMessage + * String must be in reverse DNS format, and must only contain lowercase alphanumeric characters (a-z, 0-9), hyphens (-), and periods (.) + */ + UUID: string; + + /** + * Version of the plugin, in the format `{major}.{minor}.{patch}.{build}`. + * @example + * "1.0.0.0" + * @pattern + * ^(0|[1-9]\d*)(\.(0|[1-9]\d*)){3}$ + * @errorMessage + * String must use format {major}.{minor}.{patch}.{build} + */ + Version: string; +}; + +/** + * Defines the controller type the action is applicable to. **Keypad** refers to a standard action on a Stream Deck device, e.g. 1 of the 15 buttons on the Stream Deck MK.2, or a pedal + * on the Stream Deck Pedal, etc., whereas an **Encoder** refers to a dial / touchscreen on the Stream Deck +. + */ +export type Controller = "Encoder" | "Keypad"; + +/** + * Provides information about an action provided by the plugin. + */ +export type Action = { + /** + * Defines the controller type the action is applicable to. **Keypad** refers to a standard action on a Stream Deck device, e.g. 1 of the 15 buttons on the Stream Deck MK.2, + * or a pedal on the Stream Deck Pedal, etc., whereas an **Encoder** refers to a dial / touchscreen on the Stream Deck +. + * @uniqueItems + */ + Controllers?: [Controller, Controller?]; + + /** + * Determines whether the state of the action should automatically toggle when the user presses the action; only applies to actions that have more than one state defined. Default is + * `false`. + * @example + * false + */ + DisableAutomaticStates?: boolean; + + /** + * Determines whether Stream Deck should cache images associated with the plugin, and its actions. Default is `false`. + * @example + * false + */ + DisableCaching?: boolean; + + /** + * Provides information about how the action functions as part of an `Encoder` (dial / touchscreen). + */ + Encoder?: Encoder; + + /** + * Path to the image, with the **file extension omitted**, that will be displayed next to the action in the Stream Deck application's action list. + * + * Image must be: + * - PNG or SVG format. + * - Provided in two sizes, 20 × 20 px and 40 × 40 px (@2x). + * - Monochromatic, with foreground color of #FFFFFF and a transparent background. + * + * **Examples:** + * - assets/counter + * - imgs/actions/mute + * @filePath + * { extensions: [".svg", ".png"], includeExtension: false } + * @imageDimensions + * [20, 20] + */ + Icon: string; + + /** + * Name of the action; this is displayed to the user in the actions list, and is used throughout the Stream Deck application to visually identify the action. + */ + Name: string; + + /** + * Operating system that the action supports. + * @minItems 1 + * @maxItems 2 + * @uniqueItems + */ + OS?: OS["Platform"][]; + + /** + * Optional path to the HTML file that represents the property inspector for this action; this is displayed to the user in the Stream Deck application when they add the + * action, allowing them to configure the action's settings. When `undefined`, the manifest's top-level `PropertyInspectorPath` is used, otherwise none. + * + * Note: Path should be relative to the root of the plugin's folder, with no leading slash. + * + * **Examples:** + * - mute.html + * - actions/join-voice-chat/settings.html + * @filePath + * { extensions: [".htm", ".html"], includeExtension: true } + */ + PropertyInspectorPath?: FilePath<"htm" | "html">; + + /** + * States the action can be in. When two states are defined the action will act as a toggle, with users being able to select their preferred iconography for each state. + * + * Note: Automatic toggling of the state on action activation can be disabled by setting `DisableAutomaticStates` to `true`. + * @minItems 1 + */ + States: State[]; + + /** + * Determines whether the action is available to users when they are creating key logic actions. Default is `true`. + * + * Available from Stream Deck 7.0. + */ + SupportedInKeyLogicActions?: boolean; + + /** + * Determines whether the action is available to users when they are creating multi-actions. Default is `true`. + */ + SupportedInMultiActions?: boolean; + + /** + * Link to the actions's support website. + * + * **Examples**: + * - https://help.corsair.com/ + * - https://help.elgato.com/ + * + * Available from Stream Deck 6.9. + */ + SupportURL?: string; + + /** + * Tooltip shown to the user when they hover over the action within the actions list in the Stream Deck application. + */ + Tooltip?: string; + + /** + * Unique identifier of the action, represented in reverse-DNS format. This value is supplied by Stream Deck when events are emitted that relate to the action enabling you + * to identify the source of the event. + * + * **Allowed characters:** + * - Lowercase alphanumeric characters (a-z, 0-9) + * - Hyphens (-) + * - Periods (.) + * + * Note: `UUID` must be unique, and should be prefixed with the plugin's UUID. + * + * + * **Examples:** + * - com.elgato.wavelink.toggle-mute + * - com.elgato.discord.join-voice + * - tv.twitch.go-live + * @pattern + * ^([a-z0-9-]+)(\.[a-z0-9-]+)+$ + * @errorMessage + * String must be in reverse DNS format, and must only contain lowercase alphanumeric characters (a-z, 0-9), hyphens (-), and periods (.) + */ + UUID: string; + + /** + * Determines whether the title field is available to the user when viewing the action's property inspector. Setting this to `false` will disable the user from specifying a + * title, thus allowing the plugin to have exclusive access to the title. Default is `true`, i.e. the title field is enabled. + */ + UserTitleEnabled?: boolean; + + /** + * Determines whether the action is available to users via the actions list in the Stream Deck application. Setting this to `false` allows for the action to be used as + * part of pre-defined profiles distributed with the plugins, whilst not being available to users. Default is `true`. + */ + VisibleInActionsList?: boolean; +}; + +/** + * Applications to monitor on Mac and Windows; upon a monitored application being launched or terminated, Stream Deck will notify the plugin. + */ +export type ApplicationMonitoring = { + /** + * Collection of applications to monitor on macOS. + * + * **Examples:** + * - com.apple.mail + */ + mac?: string[]; + + /** + * Collection of applications to monitor on Windows. + * + * **Examples:** + * - Notepad.exe + */ + windows?: string[]; +}; + +/** + * Provides information about how the action functions as part of an `Encoder` (dial / touchscreen). + */ +export type Encoder = { + /** + * Path to the image, with the **file extension omitted**, that will be displayed in the Stream Deck application in the circular canvas that represents the dial of the + * action. + * + * Image must be: + * - PNG or SVG format. + * - Provided in two sizes, 72 × 72 px and 144 × 144 px (@2x). + * + * Note: Can be overridden by the user in the Stream Deck application. + * + * **Examples:** + * - assets/actions/mute/encoder-icon + * - imgs/join-voice-chat-encoder + * @filePath + * { extensions: [".svg", ".png"], includeExtension: false } + * @imageDimensions + * [72, 72] + */ + Icon?: string; + + /** + * Background color to display in the Stream Deck application when the action is part of a dial stack, and is the current action. Represented as a hexadecimal value. + * + * **Examples:** + * - #D60270 + * - #F1F1F1 + * - #0038A8 + */ + StackColor?: string; + + /** + * Descriptions that define the interaction of the action when it is associated with a dial / touchscreen on the Stream Deck +. This information is shown to the user. + * + * **Examples:** + * - "Adjust volume" + * - "Play / Pause" + */ + TriggerDescription?: TriggerDescriptions; + + /** + * Path to the image, with the **file extension omitted**, that will be displayed on the touchscreen behind the action's layout. + * + * Image must be: + * - PNG or SVG format. + * - Provided in two sizes, 200 × 100 px and 400 × 200 px (@2x). + * + * Note: Can be overridden by the user in the Stream Deck application. + * + * **Examples:** + * - assets/backgrounds/main + * - imgs/bright-blue-bg + * @imageDimensions + * [200, 100] + * @filePath + * { extensions: [".png", ".svg"], includeExtension: false } + */ + background?: string; + + /** + * Name of a pre-defined layout, or the path to a JSON file that details a custom layout and its components, to be rendered on the action's touchscreen canvas. + * + * **Pre-defined Layouts:** + * - `$X1`, layout with the title at the top and the icon beneath it in the center. + * - `$A0`, layout with the title at the top and a full-width image canvas beneath it in the center. + * - `$A1`, layout with the title at the top, the icon on the left, and text value on the right. + * - `$B1`, layout with the title at the top, the icon on the left, and a text value on the right with a progress bar beneath it. + * - `$B2`, layout with the title at the top, the icon on the left, and a text value on the right with a gradient progress bar beneath it. + * - `$C1`, layout with the title at the top, and two rows that display an icon on the left and progress bar on the right (i.e. a double progress bar layout). + * + * **Examples:** + * - $A1 + * - layouts/my-custom-layout.json + * @example + * "$X1" + * @example + * "$A0" + * @example + * "$A1" + * @example + * "$B1" + * @example + * "$B2" + * @example + * "$C1" + * @example + * "custom.json" + * @pattern + * ^(^(?![\.]*[\\\/]+).+\.([Jj][Ss][Oo][Nn])$)|(\$(X1|A0|A1|B1|B2|C1))$ + * @errorMessage + * String must reference .json file in the plugin directory, or a pre-defined layout. + */ + layout?: FilePath<"json"> | "$A0" | "$A1" | "$B1" | "$B2" | "$C1" | "$X1"; +}; + +/** + * Descriptions that define the interaction of the action when it is associated with a dial / touchscreen on the Stream Deck +. This information is shown to the user. + * + * **Examples:** + * - "Adjust volume" + * - "Play / Pause" + */ +export type TriggerDescriptions = { + /** + * Touchscreen "long-touch" interaction behavior description. + */ + LongTouch?: string; + + /** + * Dial "push" (press) interaction behavior description. + */ + Push?: string; + + /** + * Dial rotation interaction behavior description. + */ + Rotate?: string; + + /** + * Touchscreen "touch" interaction behavior description. + */ + Touch?: string; +}; + +/** + * States the action can be in. When two states are defined the action will act as a toggle, with users being able to select their preferred iconography for each state. + * + * Note: Automatic toggling of the state on action activation can be disabled by setting `DisableAutomaticStates` to `true`. + */ +export type State = { + /** + * Default font-family to be used when rendering the title of this state. + * + * Note: Can be overridden by the user in the Stream Deck application. + */ + FontFamily?: string; + + /** + * Default font-size to be used when rendering the title of this state. + * + * Note: Can be overridden by the user in the Stream Deck application. + */ + FontSize?: number; + + /** + * Default font-style to be used when rendering the title of this state. + * + * Note: Can be overridden by the user in the Stream Deck application. + */ + FontStyle?: "" | "Bold Italic" | "Bold" | "Italic" | "Regular"; + + /** + * Determines whether the title associated with this state is underlined by default. + * + * Note: Can be overridden by the user in the Stream Deck application. + */ + FontUnderline?: boolean; + + /** + * Path to the image, with the **file extension omitted**, that will be displayed on the Stream Deck when this action's state is active. + * + * Image must be: + * - GIF, PNG or SVG format. + * - Provided in two sizes, 72 × 72 px and 144 × 144 px (@2x). + * + * Note: Can be overridden by the user in the Stream Deck application. + * + * **Examples:** + * - assets/counter-key + * - assets/icons/mute + * @filePath + * { extensions: [".gif", ".svg", ".png"], includeExtension: false } + * @imageDimensions + * [72, 72] + */ + Image: string; + + /** + * Path to the image, with the **file extension omitted**, that will be displayed when the action is being viewed as part of a multi-action. + * + * Image must be: + * - PNG or SVG format. + * - Provided in two sizes, 72 × 72 px and 144 × 144 px (@2x). + * + * Note: Can be overridden by the user in the Stream Deck application. + * + * **Examples:** + * - assets/counter-key + * - assets/icons/mute + * @filePath + * { extensions: [".svg", ".png"], includeExtension: false } + * @imageDimensions + * [72, 72] + */ + MultiActionImage?: string; + + /** + * Name of the state; when multiple states are defined this value is shown to the user when the action is being added to a multi-action. The user is then able to specify which + * state they would like to activate as part of the multi-action. + */ + Name?: string; + + /** + * Determines whether the title should be shown. + * + * Note: Can be overridden by the user in the Stream Deck application. + */ + ShowTitle?: boolean; + + /** + * Default title to be shown when the action is added to the Stream Deck. + */ + Title?: string; + + /** + * Default title alignment to be used when rendering the title of this state. + * + * Note: Can be overridden by the user in the Stream Deck application. + */ + TitleAlignment?: "bottom" | "middle" | "top"; + + /** + * Default title color to be used when rendering the title of this state, represented a hexadecimal value. + * + * Note: Can be overridden by the user in the Stream Deck application. + * + * **Examples:** + * - #5BCEFA + * - #F5A9B8 + * - #FFFFFF + */ + TitleColor?: string; +}; + +/** + * Configuration options for Node.js based plugins. + */ +export type Nodejs = { + /** + * Command-line arguments supplied to the plugin when run in debug mode. Optionally, the pre-defined values `"enabled"` and `"break"` run the plugin with a debugger enabled + * with [`--inspect`](https://nodejs.org/api/cli.html#--inspecthostport) and [`--inspect-brk`](https://nodejs.org/api/cli.html#--inspect-brkhostport) respectively. + * + * Note: `"enabled"` and `"break"` will automatically be assigned an available `PORT` by Stream Deck. Alternatively, if you wish to debug on a pre-defined port, this value can be + * a set of [command-line arguments](https://nodejs.org/api/cli.html). + * + * **Examples:** + * - `"enabled"` results in `--inspect=127.0.0.1:{PORT}` + * - `"break"` results in `--inspect-brk=127.0.0.1:{PORT}` + * - `"--inspect=127.0.0.1:12345"` runs a local debugger on port `12345`. + * @example + * "enabled" + * @example + * "break" + */ + Debug?: string; + + /** + * Determines whether to generate a profiler output for the plugin; [read more](https://nodejs.org/en/docs/guides/simple-profiling). + */ + GenerateProfilerOutput?: boolean; + + /** + * Version of Node.js to use. + */ + Version: "20" | "24"; +}; + +/** + * Provides information for pre-defined profile distributed with this plugin. + */ +export type Profile = { + /** + * Determines whether the profile should be automatically installed when the plugin is installed. When `false`, the profile will be installed the first time + * the plugin attempts to switch to it. Default is `true`. + * + * Available from Stream Deck 6.6. + */ + AutoInstall?: boolean; + + /** + * Type of device the profile is intended for, for example Stream Deck +, Stream Deck Pedal, etc. + * + * **Devices** + * - Stream Deck (0) + * - Stream Deck Mini (1) + * - Stream Deck XL (2) + * - Stream Deck Mobile (3) + * - Corsair GKeys (4) + * - Stream Deck Pedal (5) + * - Corsair Voyager (6) + * - Stream Deck + (7) + * - SCUF Controller (8) + * - Stream Deck Neo (9) + * - Stream Deck Studio (10) + * - Virtual Stream Deck (11) + * - Galleon 100 SD (12) + * - Stream Deck + XL (13) + */ + DeviceType: (typeof DeviceType)[keyof typeof DeviceType]; + + /** + * Determines whether the Stream Deck application should automatically switch to the profile when it is first installed. Default value is `false`. + */ + DontAutoSwitchWhenInstalled?: boolean; + + /** + * Path to the `.streamDeckProfile`, with the **file extension omitted**, that contains the profiles layout and action settings. + * + * **Examples:** + * - assets/main-profile + * - profiles/super-cool-profile + * @filePath + * { extensions: [".streamDeckProfile"], includeExtension: false } + */ + Name: string; + + /** + * Determines whether the profile is read-only, or if the user is able to customize it within the Stream Deck application. Default value is `false`. + */ + Readonly?: boolean; +}; + +/** + * Operating system that the plugin supports, and the minimum required version needed to run the plugin. + */ +export type OS = { + /** + * Minimum version required of the operating system to run the plugin. + */ + MinimumVersion: string; + + /** + * Operating system supported by the plugin. + */ + Platform: "mac" | "windows"; +}; + +/** + * File path, relative to the manifest's location. + */ +type FilePath = `${string}.${Lowercase}`; diff --git a/packages/schemas/src/streamdeck/plugins/manifest/v6.4.ts b/packages/schemas/src/streamdeck/plugins/manifest/v6.4.ts new file mode 100644 index 0000000..32ac226 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/v6.4.ts @@ -0,0 +1,16 @@ +import type { Manifest_6_5 } from "./v6.5"; + +/** + * Defines the plugin and available actions, and all information associated with them, including the plugin's entry point, all iconography, action default behavior, etc. + */ +export type Manifest_6_4 = Omit & { + /** + * Determines the Stream Deck software requirements for this plugin. + */ + Software: { + /** + * Minimum version of the Stream Deck application required for this plugin to run. + */ + MinimumVersion: "6.4"; + }; +}; diff --git a/packages/schemas/src/streamdeck/plugins/manifest/v6.5.ts b/packages/schemas/src/streamdeck/plugins/manifest/v6.5.ts new file mode 100644 index 0000000..84365f7 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/v6.5.ts @@ -0,0 +1,33 @@ +import type { ElementOf } from "../../../utils"; +import type { Manifest_6_6 } from "./v6.6"; + +/** + * Defines the plugin and available actions, and all information associated with them, including the plugin's entry point, all iconography, action default behavior, etc. + */ +export type Manifest_6_5 = Omit & { + /** + * Collection of actions provided by the plugin, and all of their information; this can include actions that are available to user's via the actions list, and actions that are + * hidden to the user but available to pre-defined profiles distributed with the plugin (`Manifest.Actions.VisibleInActionsList`). + */ + Actions: Omit, "OS">[]; + + /** + * Collection of pre-defined profiles that are distributed with this plugin. Upon the plugin switching to the profile, the user will be prompted to install the profiles. + * + * Note: Plugins may only switch to profiles distributed with the plugin, as defined within the manifest, and cannot access user-defined profiles. + * + * **Also see:** + * `streamDeck.profiles.switchToProfile(...)` + */ + Profiles?: Omit, "AutoInstall">[]; + + /** + * Determines the Stream Deck software requirements for this plugin. + */ + Software: { + /** + * Minimum version of the Stream Deck application required for this plugin to run. + */ + MinimumVersion: "6.5"; + }; +}; diff --git a/packages/schemas/src/streamdeck/plugins/manifest/v6.6.ts b/packages/schemas/src/streamdeck/plugins/manifest/v6.6.ts new file mode 100644 index 0000000..fd0bc56 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/v6.6.ts @@ -0,0 +1,28 @@ +import type { ElementOf } from "../../../utils"; +import type { Manifest_6_9 } from "./v6.9"; + +/** + * Defines the plugin and available actions, and all information associated with them, including the plugin's entry point, all iconography, action default behavior, etc. + */ +export type Manifest_6_6 = Omit & { + /** + * Collection of actions provided by the plugin, and all of their information; this can include actions that are available to user's via the actions list, and actions that are + * hidden to the user but available to pre-defined profiles distributed with the plugin (`Manifest.Actions.VisibleInActionsList`). + */ + Actions: Omit, "SupportURL">[]; + + /** + * Determines the Stream Deck software requirements for this plugin. + */ + Software: { + /** + * Minimum version of the Stream Deck application required for this plugin to run. + */ + MinimumVersion: "6.6" | "6.7" | "6.8"; + }; + + /** + * Preferred SDK version; this should _currently_ always be 2. + */ + SDKVersion: 2; +}; diff --git a/packages/schemas/src/streamdeck/plugins/manifest/v6.9.ts b/packages/schemas/src/streamdeck/plugins/manifest/v6.9.ts new file mode 100644 index 0000000..2326ace --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/v6.9.ts @@ -0,0 +1,23 @@ +import type { ElementOf } from "../../../utils"; +import type { Manifest_7_0 } from "./v7.0"; + +/** + * Defines the plugin and available actions, and all information associated with them, including the plugin's entry point, all iconography, action default behavior, etc. + */ +export type Manifest_6_9 = Omit & { + /** + * Collection of actions provided by the plugin, and all of their information; this can include actions that are available to user's via the actions list, and actions that are + * hidden to the user but available to pre-defined profiles distributed with the plugin (`Manifest.Actions.VisibleInActionsList`). + */ + Actions: Omit, "SupportedInKeyLogicActions">[]; + + /** + * Determines the Stream Deck software requirements for this plugin. + */ + Software: { + /** + * Minimum version of the Stream Deck application required for this plugin to run. + */ + MinimumVersion: "6.9"; + }; +}; diff --git a/packages/schemas/src/streamdeck/plugins/manifest/v7.0.ts b/packages/schemas/src/streamdeck/plugins/manifest/v7.0.ts new file mode 100644 index 0000000..d957ce7 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/v7.0.ts @@ -0,0 +1,27 @@ +import type { Nodejs } from "./latest"; +import type { Manifest_7_1 } from "./v7.1"; + +/** + * Defines the plugin and available actions, and all information associated with them, including the plugin's entry point, all iconography, action default behavior, etc. + */ +export type Manifest_7_0 = Omit & { + /** + * Configuration options for Node.js based plugins. + */ + Nodejs?: Omit & { + /** + * Version of Node.js to use. + */ + Version: "20"; + }; + + /** + * Determines the Stream Deck software requirements for this plugin. + */ + Software: { + /** + * Minimum version of the Stream Deck application required for this plugin to run. + */ + MinimumVersion: "7.0"; + }; +}; diff --git a/packages/schemas/src/streamdeck/plugins/manifest/v7.1.ts b/packages/schemas/src/streamdeck/plugins/manifest/v7.1.ts new file mode 100644 index 0000000..d5a9608 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/manifest/v7.1.ts @@ -0,0 +1,16 @@ +import type { Manifest } from "./latest"; + +/** + * Defines the plugin and available actions, and all information associated with them, including the plugin's entry point, all iconography, action default behavior, etc. + */ +export type Manifest_7_1 = Omit & { + /** + * Determines the Stream Deck software requirements for this plugin. + */ + Software: { + /** + * Minimum version of the Stream Deck application required for this plugin to run. + */ + MinimumVersion: "7.1" | "7.2" | "7.3" | "7.4"; + }; +}; diff --git a/packages/schemas/src/streamdeck/plugins/schemas.ts b/packages/schemas/src/streamdeck/plugins/schemas.ts new file mode 100644 index 0000000..35637e9 --- /dev/null +++ b/packages/schemas/src/streamdeck/plugins/schemas.ts @@ -0,0 +1,29 @@ +import type { Manifest_6_4 } from "./manifest/v6.4"; +import type { Manifest_6_5 } from "./manifest/v6.5"; +import type { Manifest_6_6 } from "./manifest/v6.6"; +import type { Manifest_6_9 } from "./manifest/v6.9"; +import type { Manifest_7_0 } from "./manifest/v7.0"; +import type { Manifest_7_1 } from "./manifest/v7.1"; + +/** + * Defines the plugin and available actions, and all information associated with them, including the plugin's entry point, all iconography, action default behavior, etc. + */ +export type Manifest = + | JsonSchema + | JsonSchema + | JsonSchema + | JsonSchema + | JsonSchema + | JsonSchema; + +export type { Layout } from "./layout"; + +/** + * @inheritdoc + */ +type JsonSchema = T & { + /** + * JSON schema responsible for describing the manifest's data format and validation. + */ + $schema?: string; +}; diff --git a/packages/schemas/src/utils.ts b/packages/schemas/src/utils.ts new file mode 100644 index 0000000..b4c2c5d --- /dev/null +++ b/packages/schemas/src/utils.ts @@ -0,0 +1,4 @@ +/** + * Gets the element type of the {@template ArrayType}. + */ +export type ElementOf = ArrayType extends readonly (infer ElementType)[] ? ElementType : never; diff --git a/packages/schemas/tests/matchers/to-have-error.ts b/packages/schemas/tests/matchers/to-have-error.ts new file mode 100644 index 0000000..dfe11ae --- /dev/null +++ b/packages/schemas/tests/matchers/to-have-error.ts @@ -0,0 +1,134 @@ +import type { MatcherFunction } from "expect"; + +/** + * Matcher function that asserts the specified error exists in the collection of errors. + * @param actual Collection of JSON validation errors. + * @param error Expected error. + * @returns The matcher result. + */ +export const toHaveError: MatcherFunction<[error: AdditionalPropertyError]> = function ( + actual: unknown, + error: JsonSchemaError, +) { + if (!Array.isArray(actual)) { + return { + message: () => `expected ${this.utils.printReceived(actual)} to be an array`, + pass: false, + }; + } + + for (const item of actual) { + if (item === undefined || typeof item !== "object" || !("instancePath" in item) || !("keyword" in item)) { + return { + message: () => `expected ${this.utils.printReceived(actual)} to be a collection of JSON schema error object`, + pass: false, + }; + } + + // When the error was found, we are successful + if ( + item.keyword === error.keyword && + item.instancePath === error.instancePath && + this.equals(item.params, error.params) + ) { + return { + message: () => `success`, + pass: true, + }; + } + } + + return { + message: () => + `expected ${this.utils.printReceived(actual)} to contain a JSON schema error of ${this.utils.printExpected(error)}`, + pass: false, + }; +}; + +/** + * Represents a JSON error. + */ +type JsonSchemaError = AdditionalPropertyError | ConstError | EnumError | PatternError; + +/** + * Represents a JSON error for the keyword `additionalProperties`. + */ +type AdditionalPropertyError = JsonSchemaBaseError< + "additionalProperties", + { + /** + * Name of the property that should not be present. + */ + additionalProperty: string; + } +>; + +/** + * Represents a JSON error for the keyword `const`. + */ +type ConstError = JsonSchemaBaseError< + "const", + { + /** + * The allowed value. + */ + allowedValue: unknown; + } +>; +/** + * Represents a JSON error for the keyword `enum`. + */ +type EnumError = JsonSchemaBaseError< + "enum", + { + /** + * The allowed values. + */ + allowedValues: unknown[]; + } +>; + +/** + * Represents a JSON error for the keyword `pattern`. + */ +type PatternError = JsonSchemaBaseError< + "pattern", + { + /** + * Expected pattern. + */ + pattern: string; + } +>; + +/** + * Represents a base JSON schema error. + */ +type JsonSchemaBaseError = { + /** + * Path to the instance of the error. + */ + instancePath: string; + + /** + * Keyword of the error. + */ + keyword: TKeyword; + + /** + * Parameters that define the validation rule. + */ + params: TParams; +}; + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace jest { + interface AsymmetricMatchers { + toHaveError(error: JsonSchemaError): void; + } + interface Matchers { + toHaveError(error: JsonSchemaError): R; + } + } +} diff --git a/packages/schemas/tests/setup.ts b/packages/schemas/tests/setup.ts new file mode 100644 index 0000000..0537621 --- /dev/null +++ b/packages/schemas/tests/setup.ts @@ -0,0 +1,6 @@ +import { expect } from "@jest/globals"; +import { toHaveError } from "./matchers/to-have-error"; + +expect.extend({ + toHaveError +}); diff --git a/packages/schemas/tests/validate.ts b/packages/schemas/tests/validate.ts new file mode 100644 index 0000000..66f0b69 --- /dev/null +++ b/packages/schemas/tests/validate.ts @@ -0,0 +1,48 @@ +import Ajv, { type ErrorObject } from "ajv"; +import { existsSync, readFileSync } from "node:fs"; +import { join, resolve } from "node:path"; + +import { keywordDefinitions } from "../src/index"; +import type { Manifest } from "../src/streamdeck/plugins"; + +/** + * Validates the specified manifest file; when the version is specified the `Software.MinimumVersion` is updated. + * @param filename Name of the manifest file. + * @param modify Optional modifier to be applied to the manifest before validation. + * @returns Collection of errors as the result of validation. + */ +export function validateStreamDeckPluginManifest( + filename: string, + modify?: (manifest: Manifest) => void, +): ErrorObject, unknown>[] { + const schema = JSON.parse(getFileContents("../dist/streamdeck/plugins/manifest.json")); + const validate = new Ajv({ allErrors: true, strictTypes: false }) + .addKeyword(keywordDefinitions.errorMessage) + .addKeyword(keywordDefinitions.filePath) + .addKeyword(keywordDefinitions.imageDimensions) + .addKeyword(keywordDefinitions.markdownDescription) + .compile(schema); + + const manifest = JSON.parse(getFileContents(join(`../src/streamdeck/plugins/manifest/__tests__/files/${filename}`))); + if (modify) { + modify(manifest); + } + + validate(manifest); + return validate.errors ?? []; +} + +/** + * Gets the file contents from the specified path relative to the tests folder. + * @param relativePath Path to the file, relative to the tests folder. + * @returns The file contents. + */ +function getFileContents(relativePath: string): string { + const path = resolve(__dirname, relativePath); + if (!existsSync(path)) { + console.log(path); + throw new Error(`File not found: ${path}`); + } + + return readFileSync(path, { encoding: "utf-8" }); +} diff --git a/packages/schemas/tsconfig.json b/packages/schemas/tsconfig.json new file mode 100644 index 0000000..daa6df0 --- /dev/null +++ b/packages/schemas/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "customConditions": ["node"], + "module": "ES2022", + "moduleResolution": "Bundler", + "paths": { + "@tests": ["./tests/validate"] + }, + "types": ["jest", "node"] + }, + "include": [ + "**/*.ts", + "**/*.d.ts" + ], + "exclude": ["node_modules"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa02248..2bef020 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -67,6 +67,81 @@ importers: specifier: ^0.5.0 version: 0.5.0(vitest@3.2.4(@types/node@24.12.0)) + packages/schemas: + devDependencies: + '@elgato/eslint-config': + specifier: ^0.3.2 + version: 0.3.2(@eslint/js@9.39.4)(eslint-plugin-jsdoc@54.7.0(eslint@9.39.4))(eslint@9.39.4)(typescript-eslint@8.54.0(eslint@9.39.4)(typescript@5.9.3))(typescript@5.9.3) + '@elgato/prettier-config': + specifier: ^0.3.3 + version: 0.3.3(prettier@3.8.1) + '@jest/globals': + specifier: 29.7.0 + version: 29.7.0 + '@rollup/plugin-json': + specifier: ^6.1.0 + version: 6.1.0(rollup@4.59.0) + '@rollup/plugin-node-resolve': + specifier: ^16.0.0 + version: 16.0.3(rollup@4.59.0) + '@rollup/plugin-typescript': + specifier: ^12.1.2 + version: 12.3.0(rollup@4.59.0)(tslib@2.8.1)(typescript@5.9.3) + '@swc-node/register': + specifier: 1.10.9 + version: 1.10.9(@swc/core@1.15.24)(@swc/types@0.1.26)(typescript@5.9.3) + '@swc/core': + specifier: ^1.10.7 + version: 1.15.24 + '@swc/jest': + specifier: ^0.2.37 + version: 0.2.39(@swc/core@1.15.24) + '@tsconfig/node20': + specifier: ^20.1.4 + version: 20.1.9 + '@types/jest': + specifier: ^29.5.14 + version: 29.5.14 + '@types/json-schema': + specifier: ^7.0.15 + version: 7.0.15 + '@types/node': + specifier: ^22.10.7 + version: 22.19.17 + ajv: + specifier: ^8.17.1 + version: 8.18.0 + eslint: + specifier: ^9.39.4 + version: 9.39.4 + expect: + specifier: 29.7.0 + version: 29.7.0 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@22.19.17) + nodemon: + specifier: ^3.1.9 + version: 3.1.14 + prettier: + specifier: ^3.8.1 + version: 3.8.1 + rollup: + specifier: ^4.30.1 + version: 4.59.0 + rollup-plugin-dts: + specifier: ^6.1.1 + version: 6.4.1(rollup@4.59.0)(typescript@5.9.3) + ts-json-schema-generator: + specifier: ^2.3.0 + version: 2.9.0 + typescript: + specifier: ^5.7.3 + version: 5.9.3 + wireit: + specifier: ^0.14.12 + version: 0.14.12 + packages: '@ampproject/remapping@2.3.0': @@ -89,14 +164,40 @@ packages: resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + '@babel/generator@7.29.1': resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} + '@babel/helper-globals@7.28.0': resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -105,11 +206,110 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.2': + resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} + engines: {node: '>=6.9.0'} + '@babel/parser@7.29.0': resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} engines: {node: '>=6.0.0'} hasBin: true + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.28.6': + resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.28.6': + resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.28.6': + resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/runtime@7.28.6': resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} engines: {node: '>=6.9.0'} @@ -126,6 +326,9 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@bcoe/v8-coverage@1.0.2': resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} @@ -209,6 +412,15 @@ packages: '@elgato/utils@0.4.4': resolution: {integrity: sha512-KJbBp9JopLKR+0fO7QEK2HCurnKysVTMAD1GB8RklNHGcCzMqw0ep6mY8XRy3FX6OpDz+sIXZqz5DMws8Ec8AQ==} + '@emnapi/core@1.9.2': + resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} + + '@emnapi/runtime@1.9.2': + resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@es-joy/jsdoccomment@0.56.0': resolution: {integrity: sha512-c6EW+aA1w2rjqOMjbL93nZlwxp6c1Ln06vTYs5FjRRhmJXK8V/OrSXdT+pUr4aRYgjCgu8/OkiZr0tzeVrRSbw==} engines: {node: '>=20.11.0'} @@ -436,13 +648,102 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + '@istanbuljs/schema@0.1.3': resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} + '@jest/console@29.7.0': + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/core@29.7.0': + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/create-cache-key-function@30.3.0': + resolution: {integrity: sha512-hTupmOWylzeyqbMNeSNi7ZDprpjrcroAOOG+qCEW66st3+Z5RnYHVYkUt+zjIcLmrTUi2lPY79hJz8mB3L2oXQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect-utils@29.7.0': + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect@29.7.0': + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/globals@29.7.0': + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/pattern@30.0.1': + resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/reporters@29.7.0': + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/schemas@30.0.5': + resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/source-map@29.6.3': + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-result@29.7.0': + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-sequencer@29.7.0': + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/transform@29.7.0': + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@30.3.0': + resolution: {integrity: sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -459,6 +760,9 @@ packages: '@manypkg/get-packages@1.1.3': resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -471,10 +775,109 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@oxc-resolver/binding-darwin-arm64@1.12.0': + resolution: {integrity: sha512-wYe+dlF8npM7cwopOOxbdNjtmJp17e/xF5c0K2WooQXy5VOh74icydM33+Uh/SZDgwyum09/U1FVCX5GdeQk+A==} + cpu: [arm64] + os: [darwin] + + '@oxc-resolver/binding-darwin-x64@1.12.0': + resolution: {integrity: sha512-FZxxp99om+SlvBr1cjzF8A3TjYcS0BInCqjUlM+2f9m9bPTR2Bng9Zq5Q09ZQyrKJjfGKqlOEHs3akuVOnrx3Q==} + cpu: [x64] + os: [darwin] + + '@oxc-resolver/binding-freebsd-x64@1.12.0': + resolution: {integrity: sha512-BZi0iU6IEOnXGSkqt1OjTTkN9wfyaK6kTpQwL/axl8eCcNDc7wbv1vloHgILf7ozAY1TP75nsLYlASYI4B5kGA==} + cpu: [x64] + os: [freebsd] + + '@oxc-resolver/binding-linux-arm-gnueabihf@1.12.0': + resolution: {integrity: sha512-L2qnMEnZAqxbG9b1J3di/w/THIm+1fMVfbbTMWIQNMMXdMeqqDN6ojnOLDtuP564rAh4TBFPdLyEfGhMz6ipNA==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm64-gnu@1.12.0': + resolution: {integrity: sha512-otVbS4zeo3n71zgGLBYRTriDzc0zpruC0WI3ICwjpIk454cLwGV0yzh4jlGYWQJYJk0BRAmXFd3ooKIF+bKBHw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-arm64-musl@1.12.0': + resolution: {integrity: sha512-IStQDjIT7Lzmqg1i9wXvPL/NsYsxF24WqaQFS8b8rxra+z0VG7saBOsEnOaa4jcEY8MVpLYabFhTV+fSsA2vnA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-resolver/binding-linux-x64-gnu@1.12.0': + resolution: {integrity: sha512-SipT7EVORz8pOQSFwemOm91TpSiBAGmOjG830/o+aLEsvQ4pEy223+SAnCfITh7+AahldYsJnVoIs519jmIlKQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-x64-musl@1.12.0': + resolution: {integrity: sha512-mGh0XfUzKdn+WFaqPacziNraCWL5znkHRfQVxG9avGS9zb2KC/N1EBbPzFqutDwixGDP54r2gx4q54YCJEZ4iQ==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-resolver/binding-wasm32-wasi@1.12.0': + resolution: {integrity: sha512-SZN6v7apKmQf/Vwiqb6e/s3Y2Oacw8uW8V2i1AlxtyaEFvnFE0UBn89zq6swEwE3OCajNWs0yPvgAXUMddYc7Q==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@oxc-resolver/binding-win32-arm64-msvc@1.12.0': + resolution: {integrity: sha512-GRe4bqCfFsyghruEn5bv47s9w3EWBdO2q72xCz5kpQ0LWbw+enPHtTjw3qX5PUcFYpKykM55FaO0hFDs1yzatw==} + cpu: [arm64] + os: [win32] + + '@oxc-resolver/binding-win32-x64-msvc@1.12.0': + resolution: {integrity: sha512-Z3llHH0jfJP4mlWq3DT7bK6qV+/vYe0+xzCgfc67+Tc/U3eYndujl880bexeGdGNPh87JeYznpZAOJ44N7QVVQ==} + cpu: [x64] + os: [win32] + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@rollup/plugin-json@6.1.0': + resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@16.0.3': + resolution: {integrity: sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-typescript@12.3.0': + resolution: {integrity: sha512-7DP0/p7y3t67+NabT9f8oTBFE6gGkto4SA6Np2oudYmZE/m1dt8RB0SjL1msMxFpLo631qjRCcBlAbq1ml/Big==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.14.0||^3.0.0||^4.0.0 + tslib: '*' + typescript: '>=3.7.0' + peerDependenciesMeta: + rollup: + optional: true + tslib: + optional: true + + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/rollup-android-arm-eabi@4.59.0': resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} cpu: [arm] @@ -509,66 +912,79 @@ packages: resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.59.0': resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.59.0': resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.59.0': resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.59.0': resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.59.0': resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.59.0': resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.59.0': resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.59.0': resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.59.0': resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.59.0': resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.59.0': resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.59.0': resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.59.0': resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} @@ -600,6 +1016,133 @@ packages: cpu: [x64] os: [win32] + '@sinclair/typebox@0.27.10': + resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} + + '@sinclair/typebox@0.34.49': + resolution: {integrity: sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + + '@swc-node/core@1.14.1': + resolution: {integrity: sha512-jrt5GUaZUU6cmMS+WTJEvGvaB6j1YNKPHPzC2PUi2BjaFbtxURHj6641Az6xN7b665hNniAIdvjxWcRml5yCnw==} + engines: {node: '>= 10'} + peerDependencies: + '@swc/core': '>= 1.13.3' + '@swc/types': '>= 0.1' + + '@swc-node/register@1.10.9': + resolution: {integrity: sha512-iXy2sjP0phPEpK2yivjRC3PAgoLaT4sjSk0LDWCTdcTBJmR4waEog0E6eJbvoOkLkOtWw37SB8vCkl/bbh4+8A==} + peerDependencies: + '@swc/core': '>= 1.4.13' + typescript: '>= 4.3' + + '@swc-node/sourcemap-support@0.5.1': + resolution: {integrity: sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg==} + + '@swc/core-darwin-arm64@1.15.24': + resolution: {integrity: sha512-uM5ZGfFXjtvtJ+fe448PVBEbn/CSxS3UAyLj3O9xOqKIWy3S6hPTXSPbszxkSsGDYKi+YFhzAsR4r/eXLxEQ0g==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.15.24': + resolution: {integrity: sha512-fMIb/Zfn929pw25VMBhV7Ji2Dl+lCWtUPNdYJQYOke+00E5fcQ9ynxtP8+qhUo/HZc+mYQb1gJxwHM9vty+lXg==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.15.24': + resolution: {integrity: sha512-vOkjsyjjxnoYx3hMEWcGxQrMgnNrRm6WAegBXrN8foHtDAR+zpdhpGF5a4lj1bNPgXAvmysjui8cM1ov/Clkaw==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.15.24': + resolution: {integrity: sha512-h/oNu+upkXJ6Cicnq7YGVj9PkdfarLCdQa8l/FlHYvfv8CEiMaeeTnpLU7gSBH/rGxosM6Qkfa/J9mThGF9CLA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-arm64-musl@1.15.24': + resolution: {integrity: sha512-ZpF/pRe1guk6sKzQI9D1jAORtjTdNlyeXn9GDz8ophof/w2WhojRblvSDJaGe7rJjcPN8AaOkhwdRUh7q8oYIg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@swc/core-linux-ppc64-gnu@1.15.24': + resolution: {integrity: sha512-QZEsZfisHTSJlmyChgDFNmKPb3W6Lhbfo/O76HhIngfEdnQNmukS38/VSe1feho+xkV5A5hETyCbx3sALBZKAQ==} + engines: {node: '>=10'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-s390x-gnu@1.15.24': + resolution: {integrity: sha512-DLdJKVsJgglqQrJBuoUYNmzm3leI7kUZhLbZGHv42onfKsGf6JDS3+bzCUQfte/XOqDjh/tmmn1DR/CF/tCJFw==} + engines: {node: '>=10'} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@swc/core-linux-x64-gnu@1.15.24': + resolution: {integrity: sha512-IpLYfposPA/XLxYOKpRfeccl1p5dDa3+okZDHHTchBkXEaVCnq5MADPmIWwIYj1tudt7hORsEHccG5no6IUQRw==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-x64-musl@1.15.24': + resolution: {integrity: sha512-JHy3fMSc0t/EPWgo74+OK5TGr51aElnzqfUPaiRf2qJ/BfX5CUCfMiWVBuhI7qmVMBnk1jTRnL/xZnOSHDPLYg==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@swc/core-win32-arm64-msvc@1.15.24': + resolution: {integrity: sha512-Txj+qUH1z2bUd1P3JvwByfjKFti3cptlAxhWgmunBUUxy/IW3CXLZ6l6Gk4liANadKkU71nIU1X30Z5vpMT3BA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.15.24': + resolution: {integrity: sha512-15D/nl3XwrhFpMv+MADFOiVwv3FvH9j8c6Rf8EXBT3Q5LoMh8YnDnSgPYqw1JzPnksvsBX6QPXLiPqmcR/Z4qQ==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.15.24': + resolution: {integrity: sha512-PR0PlTlPra2JbaDphrOAzm6s0v9rA0F17YzB+XbWD95B4g2cWcZY9LAeTa4xll70VLw9Jr7xBrlohqlQmelMFQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.15.24': + resolution: {integrity: sha512-5Hj8aNasue7yusUt8LGCUe/AjM7RMAce8ZoyDyiFwx7Al+GbYKL+yE7g4sJk8vEr1dKIkTRARkNIJENc4CjkBQ==} + engines: {node: '>=10'} + peerDependencies: + '@swc/helpers': '>=0.5.17' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/jest@0.2.39': + resolution: {integrity: sha512-eyokjOwYd0Q8RnMHri+8/FS1HIrIUKK/sRrFp8c1dThUOfNeCWbLmBP1P5VsKdvmkd25JaH+OKYwEYiAYg9YAA==} + engines: {npm: '>= 7.0.0'} + peerDependencies: + '@swc/core': '*' + + '@swc/types@0.1.26': + resolution: {integrity: sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==} + '@trivago/prettier-plugin-sort-imports@5.2.2': resolution: {integrity: sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==} engines: {node: '>18.12'} @@ -619,6 +1162,21 @@ packages: '@tsconfig/node20@20.1.9': resolution: {integrity: sha512-IjlTv1RsvnPtUcjTqtVsZExKVq+KQx4g5pCP5tI7rAs6Xesl2qFwSz/tPDBC4JajkL/MlezBu3gPUwqRHl+RIg==} + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} @@ -628,6 +1186,21 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@29.5.14': + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -637,12 +1210,27 @@ packages: '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + '@types/node@22.19.17': + resolution: {integrity: sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==} + '@types/node@24.12.0': resolution: {integrity: sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==} + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + '@typescript-eslint/eslint-plugin@8.54.0': resolution: {integrity: sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -757,10 +1345,17 @@ packages: ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -773,10 +1368,18 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.3: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + are-docs-informative@0.0.2: resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} engines: {node: '>=14'} @@ -798,23 +1401,65 @@ packages: ast-v8-to-istanbul@0.3.12: resolution: {integrity: sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==} - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + babel-jest@29.7.0: + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 - balanced-match@4.0.4: - resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} - engines: {node: 18 || 20 || >=22} + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + babel-preset-current-node-syntax@1.2.0: + resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==} + peerDependencies: + '@babel/core': ^7.0.0 || ^8.0.0-0 + + babel-preset-jest@29.6.3: + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@3.0.1: + resolution: {integrity: sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==} + engines: {node: '>= 16'} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + baseline-browser-mapping@2.10.18: + resolution: {integrity: sha512-VSnGQAOLtP5mib/DPyg2/t+Tlv65NTBz83BJBJvmLVHHuKJVaDOBvJJykiT5TR++em5nfAySPccDZDa4oSrn8A==} + engines: {node: '>=6.0.0'} + hasBin: true better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + brace-expansion@4.0.1: + resolution: {integrity: sha512-YClrbvTCXGe70pU2JiEiPLYXO9gQkyxYeKpJIQHVS/gOs6EWMQP2RYBwjFLNT322Ji8TOC3IMPfsYCedNpzKfA==} + engines: {node: '>= 18'} + brace-expansion@5.0.4: resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} engines: {node: 18 || 20 || >=22} @@ -826,6 +1471,17 @@ packages: browser-or-node@3.0.0: resolution: {integrity: sha512-iczIdVJzGEYhP5DqQxYM9Hh7Ztpqqi+CXZpSmX8ALFs9ecXkQIeqRyM6TfxEfMVpwhl3dSuDvxdzzo9sUOIVBQ==} + browserslist@4.28.2: + resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -834,6 +1490,17 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001788: + resolution: {integrity: sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==} + chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} @@ -842,6 +1509,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} @@ -849,6 +1520,28 @@ packages: resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} engines: {node: '>= 16'} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + cjs-module-lexer@1.4.3: + resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + collect-v8-coverage@1.0.3: + resolution: {integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -856,6 +1549,13 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} + engines: {node: '>=20'} + comment-parser@1.4.1: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} @@ -863,6 +1563,14 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + create-jest@29.7.0: + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -876,6 +1584,14 @@ packages: supports-color: optional: true + dedent@1.7.2: + resolution: {integrity: sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} @@ -887,10 +1603,22 @@ packages: resolution: {integrity: sha512-0lopQd/gi3excE3sgBrjuR3gJv6ZElk027i30pUgdjtvSJl/OoZ8B6L42GUBm6C3G8hD1EB5ir2gTYnINzWx4g==} engines: {node: '>=22'} + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + detect-indent@6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + diff@8.0.3: resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} engines: {node: '>=0.3.1'} @@ -902,6 +1630,13 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + electron-to-chromium@1.5.336: + resolution: {integrity: sha512-AbH9q9J455r/nLmdNZes0G0ZKcRX73FicwowalLs6ijwOmCJSRRrLX63lcAlzy9ux3dWK1w1+1nsBJEWN11hcQ==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -912,6 +1647,13 @@ packages: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} @@ -920,6 +1662,14 @@ packages: engines: {node: '>=18'} hasBin: true + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -973,6 +1723,9 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -980,10 +1733,22 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + expect-type@1.3.0: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} + expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + extendable-error@0.1.7: resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} @@ -1000,9 +1765,15 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -1047,11 +1818,33 @@ packages: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1065,6 +1858,14 @@ packages: deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -1076,10 +1877,18 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -1087,10 +1896,17 @@ packages: resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} hasBin: true + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + iconv-lite@0.7.2: resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} + ignore-by-default@1.0.1: + resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1103,10 +1919,33 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -1115,14 +1954,25 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + is-subdir@1.2.0: resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} engines: {node: '>=4'} @@ -1138,10 +1988,22 @@ packages: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + istanbul-lib-report@3.0.1: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + istanbul-lib-source-maps@5.0.6: resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} engines: {node: '>=10'} @@ -1156,6 +2018,139 @@ packages: javascript-natural-sort@0.7.1: resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} + jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-cli@29.7.0: + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@29.7.0: + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + + jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-regex-util@30.0.1: + resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest@29.7.0: + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + js-tokens@10.0.0: resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} @@ -1185,9 +2180,15 @@ packages: json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -1196,16 +2197,30 @@ packages: engines: {node: '>=6'} hasBin: true + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -1229,6 +2244,13 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.3.5: + resolution: {integrity: sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + luxon@3.7.2: resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} engines: {node: '>=12'} @@ -1243,6 +2265,12 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -1251,6 +2279,10 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + minimatch@10.2.4: resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} @@ -1285,6 +2317,32 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-releases@2.0.37: + resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==} + + nodemon@3.1.14: + resolution: {integrity: sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==} + engines: {node: '>=10'} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -1292,6 +2350,9 @@ packages: outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + oxc-resolver@1.12.0: + resolution: {integrity: sha512-YlaCIArvWNKCWZFRrMjhh2l5jK80eXnpYP+bhRc1J/7cW3TiyEY0ngJo73o/5n8hA3+4yLdTmXLNTQ3Ncz50LQ==} + p-filter@2.1.0: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} engines: {node: '>=8'} @@ -1333,6 +2394,10 @@ packages: parse-imports-exports@0.2.4: resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==} + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + parse-statements@1.0.11: resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==} @@ -1340,14 +2405,25 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.11.1: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -1374,6 +2450,14 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + postcss@8.5.8: resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} engines: {node: ^10 || ^12 || >=14} @@ -1398,24 +2482,60 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + proxy-vir@2.0.2: resolution: {integrity: sha512-YgV6c/9aJ7RyNZDTPqLQ6SdqBocWHGUa5rU3hyEsHj2kg4/b0y0EMWp3dNNUEJQrw6BoywonNINEVyFvj97YXQ==} engines: {node: '>=22'} + pstree.remy@1.1.8: + resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + read-yaml-file@1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1424,10 +2544,30 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve.exports@2.0.3: + resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} + engines: {node: '>=10'} + + resolve@1.22.12: + resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} + engines: {node: '>= 0.4'} + hasBin: true + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rollup-plugin-dts@6.4.1: + resolution: {integrity: sha512-l//F3Zf7ID5GoOfLfD8kroBjQKEKpy1qfhtAdnpibFZMffPaylrg1CoDC2vGkPeTeyxUe4bVFCln2EFuL7IGGg==} + engines: {node: '>=20'} + peerDependencies: + rollup: ^3.29.4 || ^4 + typescript: ^4.5 || ^5.0 || ^6.0 + rollup@4.59.0: resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -1436,9 +2576,17 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + semver@7.7.4: resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} engines: {node: '>=10'} @@ -1455,10 +2603,20 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-update-notifier@2.0.0: + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -1467,6 +2625,16 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + spawndamnit@3.0.1: resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} @@ -1482,12 +2650,20 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -1508,6 +2684,14 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -1515,10 +2699,22 @@ packages: strip-literal@3.1.0: resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + tagged-tag@1.0.0: resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} engines: {node: '>=20'} @@ -1527,6 +2723,10 @@ packages: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + test-exclude@7.0.2: resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} engines: {node: '>=18'} @@ -1553,16 +2753,28 @@ packages: resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + touch@3.1.1: + resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} + hasBin: true + ts-api-utils@2.4.0: resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' + ts-json-schema-generator@2.9.0: + resolution: {integrity: sha512-NR5ZE108uiPtBHBJNGnhwoUaUx5vWTDJzDFG9YlRoqxPU76n+5FClRh92dcGgysbe1smRmYalM9Saj97GW1J4Q==} + engines: {node: '>=22.0.0'} + hasBin: true + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -1604,6 +2816,14 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + type-fest@5.4.4: resolution: {integrity: sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==} engines: {node: '>=20'} @@ -1624,6 +2844,12 @@ packages: engines: {node: '>=14.17'} hasBin: true + undefsafe@2.0.5: + resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -1631,9 +2857,19 @@ packages: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + vite-node@3.2.4: resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -1712,6 +2948,9 @@ packages: jsdom: optional: true + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -1722,6 +2961,11 @@ packages: engines: {node: '>=8'} hasBin: true + wireit@0.14.12: + resolution: {integrity: sha512-gNSd+nZmMo6cuICezYXRIayu6TSOeCSCDzjSF0q6g8FKDsRbdqrONrSZYzdk/uBISmRcv4vZtsno6GyGvdXwGA==} + engines: {node: '>=18.0.0'} + hasBin: true + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -1734,6 +2978,13 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + ws@8.19.0: resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} engines: {node: '>=10.0.0'} @@ -1746,6 +2997,21 @@ packages: utf-8-validate: optional: true + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -1793,6 +3059,28 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/compat-data@7.29.0': {} + + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.29.2 + '@babel/parser': 7.29.0 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@5.5.0) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/generator@7.29.1': dependencies: '@babel/parser': 7.29.0 @@ -1801,16 +3089,134 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.2 + lru-cache: 5.1.1 + semver: 6.3.1 + '@babel/helper-globals@7.28.0': {} + '@babel/helper-module-imports@7.28.6': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.28.6': {} + '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.29.2': + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + '@babel/parser@7.29.0': dependencies: '@babel/types': 7.29.0 + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/runtime@7.28.6': {} '@babel/template@7.28.6': @@ -1827,7 +3233,7 @@ snapshots: '@babel/parser': 7.29.0 '@babel/template': 7.28.6 '@babel/types': 7.29.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -1836,6 +3242,8 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@bcoe/v8-coverage@0.2.3': {} + '@bcoe/v8-coverage@1.0.2': {} '@changesets/apply-release-plan@7.1.0': @@ -2013,6 +3421,22 @@ snapshots: dependencies: zod: 3.25.76 + '@emnapi/core@1.9.2': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.9.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + '@es-joy/jsdoccomment@0.56.0': dependencies: '@types/estree': 1.0.8 @@ -2109,7 +3533,7 @@ snapshots: '@eslint/config-array@0.21.2': dependencies: '@eslint/object-schema': 2.1.7 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) minimatch: 3.1.5 transitivePeerDependencies: - supports-color @@ -2125,7 +3549,7 @@ snapshots: '@eslint/eslintrc@3.3.5': dependencies: ajv: 6.14.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 @@ -2172,13 +3596,211 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.2 + resolve-from: 5.0.0 + '@istanbuljs/schema@0.1.3': {} + '@jest/console@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@types/node': 24.12.0 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + + '@jest/core@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.19.17 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@22.19.17) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + + '@jest/create-cache-key-function@30.3.0': + dependencies: + '@jest/types': 30.3.0 + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.12.0 + jest-mock: 29.7.0 + + '@jest/expect-utils@29.7.0': + dependencies: + jest-get-type: 29.6.3 + + '@jest/expect@29.7.0': + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 24.12.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/globals@29.7.0': + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/pattern@30.0.1': + dependencies: + '@types/node': 24.12.0 + jest-regex-util: 30.0.1 + + '@jest/reporters@29.7.0': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.31 + '@types/node': 24.12.0 + chalk: 4.1.2 + collect-v8-coverage: 1.0.3 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.2.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.10 + + '@jest/schemas@30.0.5': + dependencies: + '@sinclair/typebox': 0.34.49 + + '@jest/source-map@29.6.3': + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + callsites: 3.1.0 + graceful-fs: 4.2.11 + + '@jest/test-result@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.3 + + '@jest/test-sequencer@29.7.0': + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + + '@jest/transform@29.7.0': + dependencies: + '@babel/core': 7.29.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.31 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 24.12.0 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + + '@jest/types@30.3.0': + dependencies: + '@jest/pattern': 30.0.1 + '@jest/schemas': 30.0.5 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 24.12.0 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.5.5': {} @@ -2204,6 +3826,13 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 + '@napi-rs/wasm-runtime@0.2.12': + dependencies: + '@emnapi/core': 1.9.2 + '@emnapi/runtime': 1.9.2 + '@tybys/wasm-util': 0.10.1 + optional: true + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2216,9 +3845,77 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 + '@oxc-resolver/binding-darwin-arm64@1.12.0': + optional: true + + '@oxc-resolver/binding-darwin-x64@1.12.0': + optional: true + + '@oxc-resolver/binding-freebsd-x64@1.12.0': + optional: true + + '@oxc-resolver/binding-linux-arm-gnueabihf@1.12.0': + optional: true + + '@oxc-resolver/binding-linux-arm64-gnu@1.12.0': + optional: true + + '@oxc-resolver/binding-linux-arm64-musl@1.12.0': + optional: true + + '@oxc-resolver/binding-linux-x64-gnu@1.12.0': + optional: true + + '@oxc-resolver/binding-linux-x64-musl@1.12.0': + optional: true + + '@oxc-resolver/binding-wasm32-wasi@1.12.0': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@oxc-resolver/binding-win32-arm64-msvc@1.12.0': + optional: true + + '@oxc-resolver/binding-win32-x64-msvc@1.12.0': + optional: true + '@pkgjs/parseargs@0.11.0': optional: true + '@rollup/plugin-json@6.1.0(rollup@4.59.0)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.59.0) + optionalDependencies: + rollup: 4.59.0 + + '@rollup/plugin-node-resolve@16.0.3(rollup@4.59.0)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.59.0) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.12 + optionalDependencies: + rollup: 4.59.0 + + '@rollup/plugin-typescript@12.3.0(rollup@4.59.0)(tslib@2.8.1)(typescript@5.9.3)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.59.0) + resolve: 1.22.12 + typescript: 5.9.3 + optionalDependencies: + rollup: 4.59.0 + tslib: 2.8.1 + + '@rollup/pluginutils@5.3.0(rollup@4.59.0)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.59.0 + '@rollup/rollup-android-arm-eabi@4.59.0': optional: true @@ -2294,43 +3991,206 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.59.0': optional: true - '@trivago/prettier-plugin-sort-imports@5.2.2(prettier@3.8.1)': + '@sinclair/typebox@0.27.10': {} + + '@sinclair/typebox@0.34.49': {} + + '@sinonjs/commons@3.0.1': dependencies: - '@babel/generator': 7.29.1 - '@babel/parser': 7.29.0 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - javascript-natural-sort: 0.7.1 - lodash: 4.17.23 - prettier: 3.8.1 + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@swc-node/core@1.14.1(@swc/core@1.15.24)(@swc/types@0.1.26)': + dependencies: + '@swc/core': 1.15.24 + '@swc/types': 0.1.26 + + '@swc-node/register@1.10.9(@swc/core@1.15.24)(@swc/types@0.1.26)(typescript@5.9.3)': + dependencies: + '@swc-node/core': 1.14.1(@swc/core@1.15.24)(@swc/types@0.1.26) + '@swc-node/sourcemap-support': 0.5.1 + '@swc/core': 1.15.24 + colorette: 2.0.20 + debug: 4.4.3(supports-color@5.5.0) + oxc-resolver: 1.12.0 + pirates: 4.0.7 + tslib: 2.8.1 + typescript: 5.9.3 transitivePeerDependencies: + - '@swc/types' - supports-color - '@tsconfig/node20@20.1.9': {} - - '@types/chai@5.2.3': + '@swc-node/sourcemap-support@0.5.1': dependencies: - '@types/deep-eql': 4.0.2 - assertion-error: 2.0.1 + source-map-support: 0.5.21 + tslib: 2.8.1 - '@types/deep-eql@4.0.2': {} + '@swc/core-darwin-arm64@1.15.24': + optional: true - '@types/estree@1.0.8': {} + '@swc/core-darwin-x64@1.15.24': + optional: true - '@types/json-schema@7.0.15': {} + '@swc/core-linux-arm-gnueabihf@1.15.24': + optional: true - '@types/luxon@3.7.1': {} + '@swc/core-linux-arm64-gnu@1.15.24': + optional: true - '@types/node@12.20.55': {} + '@swc/core-linux-arm64-musl@1.15.24': + optional: true - '@types/node@24.12.0': + '@swc/core-linux-ppc64-gnu@1.15.24': + optional: true + + '@swc/core-linux-s390x-gnu@1.15.24': + optional: true + + '@swc/core-linux-x64-gnu@1.15.24': + optional: true + + '@swc/core-linux-x64-musl@1.15.24': + optional: true + + '@swc/core-win32-arm64-msvc@1.15.24': + optional: true + + '@swc/core-win32-ia32-msvc@1.15.24': + optional: true + + '@swc/core-win32-x64-msvc@1.15.24': + optional: true + + '@swc/core@1.15.24': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.26 + optionalDependencies: + '@swc/core-darwin-arm64': 1.15.24 + '@swc/core-darwin-x64': 1.15.24 + '@swc/core-linux-arm-gnueabihf': 1.15.24 + '@swc/core-linux-arm64-gnu': 1.15.24 + '@swc/core-linux-arm64-musl': 1.15.24 + '@swc/core-linux-ppc64-gnu': 1.15.24 + '@swc/core-linux-s390x-gnu': 1.15.24 + '@swc/core-linux-x64-gnu': 1.15.24 + '@swc/core-linux-x64-musl': 1.15.24 + '@swc/core-win32-arm64-msvc': 1.15.24 + '@swc/core-win32-ia32-msvc': 1.15.24 + '@swc/core-win32-x64-msvc': 1.15.24 + + '@swc/counter@0.1.3': {} + + '@swc/jest@0.2.39(@swc/core@1.15.24)': + dependencies: + '@jest/create-cache-key-function': 30.3.0 + '@swc/core': 1.15.24 + '@swc/counter': 0.1.3 + jsonc-parser: 3.3.1 + + '@swc/types@0.1.26': + dependencies: + '@swc/counter': 0.1.3 + + '@trivago/prettier-plugin-sort-imports@5.2.2(prettier@3.8.1)': + dependencies: + '@babel/generator': 7.29.1 + '@babel/parser': 7.29.0 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + javascript-natural-sort: 0.7.1 + lodash: 4.17.23 + prettier: 3.8.1 + transitivePeerDependencies: + - supports-color + + '@tsconfig/node20@20.1.9': {} + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.8': {} + + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 24.12.0 + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@29.5.14': + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + + '@types/json-schema@7.0.15': {} + + '@types/luxon@3.7.1': {} + + '@types/node@12.20.55': {} + + '@types/node@22.19.17': + dependencies: + undici-types: 6.21.0 + + '@types/node@24.12.0': dependencies: undici-types: 7.16.0 + '@types/resolve@1.20.2': {} + + '@types/stack-utils@2.0.3': {} + '@types/ws@8.18.1': dependencies: '@types/node': 24.12.0 + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 + '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -2353,7 +4213,7 @@ snapshots: '@typescript-eslint/types': 8.54.0 '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.54.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) eslint: 9.39.4 typescript: 5.9.3 transitivePeerDependencies: @@ -2363,7 +4223,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) '@typescript-eslint/types': 8.56.1 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -2382,7 +4242,7 @@ snapshots: '@typescript-eslint/types': 8.54.0 '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) '@typescript-eslint/utils': 8.54.0(eslint@9.39.4)(typescript@5.9.3) - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) eslint: 9.39.4 ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 @@ -2399,7 +4259,7 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) '@typescript-eslint/types': 8.54.0 '@typescript-eslint/visitor-keys': 8.54.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) minimatch: 9.0.9 semver: 7.7.4 tinyglobby: 0.2.15 @@ -2429,7 +4289,7 @@ snapshots: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 ast-v8-to-istanbul: 0.3.12 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 @@ -2498,8 +4358,19 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-colors@4.1.3: {} + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + ansi-regex@5.0.1: {} ansi-regex@6.2.2: {} @@ -2508,8 +4379,15 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.3: {} + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + are-docs-informative@0.0.2: {} argparse@1.0.10: @@ -2528,14 +4406,75 @@ snapshots: estree-walker: 3.0.3 js-tokens: 10.0.0 + babel-jest@29.7.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.29.0) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.28.6 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@29.6.3: + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.28.0 + + babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.0) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.0) + + babel-preset-jest@29.6.3(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) + balanced-match@1.0.2: {} + balanced-match@3.0.1: {} + balanced-match@4.0.4: {} + baseline-browser-mapping@2.10.18: {} + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 + binary-extensions@2.3.0: {} + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -2545,6 +4484,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@4.0.1: + dependencies: + balanced-match: 3.0.1 + brace-expansion@5.0.4: dependencies: balanced-match: 4.0.4 @@ -2555,10 +4498,30 @@ snapshots: browser-or-node@3.0.0: {} + browserslist@4.28.2: + dependencies: + baseline-browser-mapping: 2.10.18 + caniuse-lite: 1.0.30001788 + electron-to-chromium: 1.5.336 + node-releases: 2.0.37 + update-browserslist-db: 1.2.3(browserslist@4.28.2) + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + cac@6.7.14: {} callsites@3.1.0: {} + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001788: {} + chai@5.3.3: dependencies: assertion-error: 2.0.1 @@ -2572,29 +4535,82 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + char-regex@1.0.2: {} + chardet@2.1.1: {} check-error@2.1.3: {} + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + ci-info@3.9.0: {} + + cjs-module-lexer@1.4.3: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + co@4.6.0: {} + + collect-v8-coverage@1.0.3: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 color-name@1.1.4: {} + colorette@2.0.20: {} + + commander@14.0.3: {} + comment-parser@1.4.1: {} concat-map@0.0.1: {} + convert-source-map@2.0.0: {} + + create-jest@29.7.0(@types/node@22.19.17): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@22.19.17) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - debug@4.4.3: + debug@4.4.3(supports-color@5.5.0): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 5.5.0 + + dedent@1.7.2: {} deep-eql@5.0.2: {} @@ -2602,8 +4618,14 @@ snapshots: deepcopy-esm@2.1.1: {} + deepmerge@4.3.1: {} + detect-indent@6.1.0: {} + detect-newline@3.1.0: {} + + diff-sequences@29.6.3: {} + diff@8.0.3: {} dir-glob@3.0.1: @@ -2612,6 +4634,10 @@ snapshots: eastasianwidth@0.2.0: {} + electron-to-chromium@1.5.336: {} + + emittery@0.13.1: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -2621,6 +4647,12 @@ snapshots: ansi-colors: 4.1.3 strip-ansi: 6.0.1 + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + es-errors@1.3.0: {} + es-module-lexer@1.7.0: {} esbuild@0.27.3: @@ -2652,6 +4684,10 @@ snapshots: '@esbuild/win32-ia32': 0.27.3 '@esbuild/win32-x64': 0.27.3 + escalade@3.2.0: {} + + escape-string-regexp@2.0.0: {} + escape-string-regexp@4.0.0: {} eslint-plugin-jsdoc@54.7.0(eslint@9.39.4): @@ -2659,7 +4695,7 @@ snapshots: '@es-joy/jsdoccomment': 0.56.0 are-docs-informative: 0.0.2 comment-parser: 1.4.1 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) escape-string-regexp: 4.0.0 eslint: 9.39.4 espree: 10.4.0 @@ -2696,7 +4732,7 @@ snapshots: ajv: 6.14.0 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -2736,14 +4772,38 @@ snapshots: estraverse@5.3.0: {} + estree-walker@2.0.2: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.8 esutils@2.0.3: {} + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + exit@0.1.2: {} + expect-type@1.3.0: {} + expect@29.7.0: + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + extendable-error@0.1.7: {} fast-deep-equal@3.1.3: {} @@ -2760,10 +4820,16 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-uri@3.1.0: {} + fastq@1.20.1: dependencies: reusify: 1.1.0 + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + fdir@6.5.0(picomatch@4.0.3): optionalDependencies: picomatch: 4.0.3 @@ -2810,9 +4876,21 @@ snapshots: jsonfile: 4.0.0 universalify: 0.1.2 + fs.realpath@1.0.0: {} + fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-package-type@0.1.0: {} + + get-stream@6.0.1: {} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -2830,6 +4908,21 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 + glob@13.0.6: + dependencies: + minimatch: 10.2.4 + minipass: 7.1.3 + path-scurry: 2.0.2 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + globals@14.0.0: {} globby@11.1.0: @@ -2843,16 +4936,26 @@ snapshots: graceful-fs@4.2.11: {} + has-flag@3.0.0: {} + has-flag@4.0.0: {} + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + html-escaper@2.0.2: {} human-id@4.1.3: {} + human-signals@2.1.0: {} + iconv-lite@0.7.2: dependencies: safer-buffer: 2.1.2 + ignore-by-default@1.0.1: {} + ignore@5.3.2: {} ignore@7.0.5: {} @@ -2862,18 +4965,46 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + imurmurhash@0.1.4: {} + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + is-arrayish@0.2.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + is-extglob@2.1.1: {} is-fullwidth-code-point@3.0.0: {} + is-generator-fn@2.1.0: {} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 + is-module@1.0.0: {} + is-number@7.0.0: {} + is-stream@2.0.1: {} + is-subdir@1.2.0: dependencies: better-path-resolve: 1.0.0 @@ -2884,16 +5015,44 @@ snapshots: istanbul-lib-coverage@3.2.2: {} + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.29.0 + '@babel/parser': 7.29.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@6.0.3: + dependencies: + '@babel/core': 7.29.0 + '@babel/parser': 7.29.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.7.4 + transitivePeerDependencies: + - supports-color + istanbul-lib-report@3.0.1: dependencies: istanbul-lib-coverage: 3.2.2 make-dir: 4.0.0 supports-color: 7.2.0 + istanbul-lib-source-maps@4.0.1: + dependencies: + debug: 4.4.3(supports-color@5.5.0) + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + istanbul-lib-source-maps@5.0.6: dependencies: '@jridgewell/trace-mapping': 0.3.31 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -2911,6 +5070,316 @@ snapshots: javascript-natural-sort@0.7.1: {} + jest-changed-files@29.7.0: + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + + jest-circus@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.12.0 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.7.2 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-cli@29.7.0(@types/node@22.19.17): + dependencies: + '@jest/core': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@22.19.17) + exit: 0.1.2 + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@22.19.17) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest-config@29.7.0(@types/node@22.19.17): + dependencies: + '@babel/core': 7.29.0 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.29.0) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 22.19.17 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-diff@29.7.0: + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-docblock@29.7.0: + dependencies: + detect-newline: 3.1.0 + + jest-each@29.7.0: + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + + jest-environment-node@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.12.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + jest-get-type@29.6.3: {} + + jest-haste-map@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 24.12.0 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-leak-detector@29.7.0: + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-matcher-utils@29.7.0: + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.29.0 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 24.12.0 + jest-util: 29.7.0 + + jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + optionalDependencies: + jest-resolve: 29.7.0 + + jest-regex-util@29.6.3: {} + + jest-regex-util@30.0.1: {} + + jest-resolve-dependencies@29.7.0: + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + jest-resolve@29.7.0: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.12 + resolve.exports: 2.0.3 + slash: 3.0.0 + + jest-runner@29.7.0: + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.12.0 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + + jest-runtime@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.12.0 + chalk: 4.1.2 + cjs-module-lexer: 1.4.3 + collect-v8-coverage: 1.0.3 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-snapshot@29.7.0: + dependencies: + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/types': 7.29.0 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.7.4 + transitivePeerDependencies: + - supports-color + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 24.12.0 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + + jest-watcher@29.7.0: + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.12.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + + jest-worker@29.7.0: + dependencies: + '@types/node': 24.12.0 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@29.7.0(@types/node@22.19.17): + dependencies: + '@jest/core': 29.7.0 + '@jest/types': 29.6.3 + import-local: 3.2.0 + jest-cli: 29.7.0(@types/node@22.19.17) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + js-tokens@10.0.0: {} js-tokens@4.0.0: {} @@ -2932,12 +5401,18 @@ snapshots: json-buffer@3.0.1: {} + json-parse-even-better-errors@2.3.1: {} + json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json5@2.2.3: {} + jsonc-parser@3.3.1: {} + jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 @@ -2946,11 +5421,17 @@ snapshots: dependencies: json-buffer: 3.0.1 + kleur@3.0.3: {} + + leven@3.1.0: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 + lines-and-columns@1.2.4: {} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -2969,6 +5450,12 @@ snapshots: lru-cache@10.4.3: {} + lru-cache@11.3.5: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + luxon@3.7.2: {} magic-string@0.30.21: @@ -2985,6 +5472,12 @@ snapshots: dependencies: semver: 7.7.4 + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + merge-stream@2.0.0: {} + merge2@1.4.1: {} micromatch@4.0.8: @@ -2992,6 +5485,8 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mimic-fn@2.1.0: {} + minimatch@10.2.4: dependencies: brace-expansion: 5.0.4 @@ -3016,6 +5511,37 @@ snapshots: natural-compare@1.4.0: {} + node-int64@0.4.0: {} + + node-releases@2.0.37: {} + + nodemon@3.1.14: + dependencies: + chokidar: 3.6.0 + debug: 4.4.3(supports-color@5.5.0) + ignore-by-default: 1.0.1 + minimatch: 10.2.4 + pstree.remy: 1.1.8 + semver: 7.7.4 + simple-update-notifier: 2.0.0 + supports-color: 5.5.0 + touch: 3.1.1 + undefsafe: 2.0.5 + + normalize-path@3.0.0: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -3027,6 +5553,20 @@ snapshots: outdent@0.5.0: {} + oxc-resolver@1.12.0: + optionalDependencies: + '@oxc-resolver/binding-darwin-arm64': 1.12.0 + '@oxc-resolver/binding-darwin-x64': 1.12.0 + '@oxc-resolver/binding-freebsd-x64': 1.12.0 + '@oxc-resolver/binding-linux-arm-gnueabihf': 1.12.0 + '@oxc-resolver/binding-linux-arm64-gnu': 1.12.0 + '@oxc-resolver/binding-linux-arm64-musl': 1.12.0 + '@oxc-resolver/binding-linux-x64-gnu': 1.12.0 + '@oxc-resolver/binding-linux-x64-musl': 1.12.0 + '@oxc-resolver/binding-wasm32-wasi': 1.12.0 + '@oxc-resolver/binding-win32-arm64-msvc': 1.12.0 + '@oxc-resolver/binding-win32-x64-msvc': 1.12.0 + p-filter@2.1.0: dependencies: p-map: 2.1.0 @@ -3065,17 +5605,33 @@ snapshots: dependencies: parse-statements: 1.0.11 + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.0 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + parse-statements@1.0.11: {} path-exists@4.0.0: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} + path-parse@1.0.7: {} + path-scurry@1.11.1: dependencies: lru-cache: 10.4.3 minipass: 7.1.3 + path-scurry@2.0.2: + dependencies: + lru-cache: 11.3.5 + minipass: 7.1.3 + path-type@4.0.0: {} pathe@2.0.3: {} @@ -3090,6 +5646,12 @@ snapshots: pify@4.0.1: {} + pirates@4.0.7: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + postcss@8.5.8: dependencies: nanoid: 3.3.11 @@ -3109,17 +5671,40 @@ snapshots: prettier@3.8.1: {} + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + proper-lockfile@4.1.2: + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 + proxy-vir@2.0.2: dependencies: '@augment-vir/assert': 31.68.1 '@augment-vir/common': 31.68.1 + pstree.remy@1.1.8: {} + punycode@2.3.1: {} + pure-rand@6.1.0: {} + quansync@0.2.11: {} queue-microtask@1.2.3: {} + react-is@18.3.1: {} + read-yaml-file@1.1.0: dependencies: graceful-fs: 4.2.11 @@ -3127,12 +5712,46 @@ snapshots: pify: 4.0.1 strip-bom: 3.0.0 + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + resolve-from@4.0.0: {} resolve-from@5.0.0: {} + resolve.exports@2.0.3: {} + + resolve@1.22.12: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + retry@0.12.0: {} + reusify@1.1.0: {} + rollup-plugin-dts@6.4.1(rollup@4.59.0)(typescript@5.9.3): + dependencies: + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.5.5 + convert-source-map: 2.0.0 + magic-string: 0.30.21 + rollup: 4.59.0 + typescript: 5.9.3 + optionalDependencies: + '@babel/code-frame': 7.29.0 + rollup@4.59.0: dependencies: '@types/estree': 1.0.8 @@ -3168,8 +5787,12 @@ snapshots: dependencies: queue-microtask: 1.2.3 + safe-stable-stringify@2.5.0: {} + safer-buffer@2.1.2: {} + semver@6.3.1: {} + semver@7.7.4: {} shebang-command@2.0.0: @@ -3180,12 +5803,32 @@ snapshots: siginfo@2.0.0: {} + signal-exit@3.0.7: {} + signal-exit@4.1.0: {} + simple-update-notifier@2.0.0: + dependencies: + semver: 7.7.4 + + sisteransi@1.0.5: {} + slash@3.0.0: {} source-map-js@1.2.1: {} + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + spawndamnit@3.0.1: dependencies: cross-spawn: 7.0.6 @@ -3202,10 +5845,19 @@ snapshots: sprintf-js@1.0.3: {} + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + stackback@0.0.2: {} std-env@3.10.0: {} + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -3228,20 +5880,40 @@ snapshots: strip-bom@3.0.0: {} + strip-bom@4.0.0: {} + + strip-final-newline@2.0.0: {} + strip-json-comments@3.1.1: {} strip-literal@3.1.0: dependencies: js-tokens: 9.0.1 + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + supports-color@7.2.0: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + tagged-tag@1.0.0: {} term-size@2.2.1: {} + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.5 + test-exclude@7.0.2: dependencies: '@istanbuljs/schema': 0.1.3 @@ -3263,14 +5935,29 @@ snapshots: tinyspy@4.0.4: {} + tmpl@1.0.5: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 + touch@3.1.1: {} + ts-api-utils@2.4.0(typescript@5.9.3): dependencies: typescript: 5.9.3 + ts-json-schema-generator@2.9.0: + dependencies: + '@types/json-schema': 7.0.15 + commander: 14.0.3 + glob: 13.0.6 + json5: 2.2.3 + normalize-path: 3.0.0 + safe-stable-stringify: 2.5.0 + tslib: 2.8.1 + typescript: 5.9.3 + tslib@2.8.1: {} turbo-darwin-64@2.8.14: @@ -3304,6 +5991,10 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-detect@4.0.8: {} + + type-fest@0.21.3: {} + type-fest@5.4.4: dependencies: tagged-tag: 1.0.0 @@ -3327,18 +6018,34 @@ snapshots: typescript@5.9.3: {} + undefsafe@2.0.5: {} + + undici-types@6.21.0: {} + undici-types@7.16.0: {} universalify@0.1.2: {} + update-browserslist-db@1.2.3(browserslist@4.28.2): + dependencies: + browserslist: 4.28.2 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + vite-node@3.2.4(@types/node@24.12.0): dependencies: cac: 6.7.14 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) es-module-lexer: 1.7.0 pathe: 2.0.3 vite: 7.3.1(@types/node@24.12.0) @@ -3385,7 +6092,7 @@ snapshots: '@vitest/spy': 3.2.4 '@vitest/utils': 3.2.4 chai: 5.3.3 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) expect-type: 1.3.0 magic-string: 0.30.21 pathe: 2.0.3 @@ -3415,6 +6122,10 @@ snapshots: - tsx - yaml + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + which@2.0.2: dependencies: isexe: 2.0.0 @@ -3424,6 +6135,14 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 + wireit@0.14.12: + dependencies: + brace-expansion: 4.0.1 + chokidar: 3.6.0 + fast-glob: 3.3.3 + jsonc-parser: 3.3.1 + proper-lockfile: 4.1.2 + word-wrap@1.2.5: {} wrap-ansi@7.0.0: @@ -3438,8 +6157,31 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.2.0 + wrappy@1.0.2: {} + + write-file-atomic@4.0.2: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + ws@8.19.0: {} + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yocto-queue@0.1.0: {} zod@3.25.76: {}