diff --git a/.vitepress/config.ts b/.vitepress/config.ts index b4bd72d4..f9bba2ed 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -3,7 +3,7 @@ import {createRequire} from "node:module"; import process from "process"; import {fileURLToPath} from "url"; import fs from "fs-extra"; -import {createContentLoader, defineConfig, HeadConfig} from "vitepress"; +import {createContentLoader, defineConfig, HeadConfig, Plugin as VitepressPlugin} from "vitepress"; import {transformerTwoslash} from "@shikijs/vitepress-twoslash"; import ts from "typescript"; import envVar from "env-var"; @@ -308,7 +308,7 @@ export default defineConfig({ GitChangelog({ repoURL: () => "https://github.com/withcatai/node-llama-cpp", cwd: path.join(__dirname, "..", "docs") - }), + }) as VitepressPlugin, GitChangelogMarkdownSection({ exclude: (id) => ( id.includes(path.sep + "api" + path.sep) || @@ -318,7 +318,7 @@ export default defineConfig({ sections: { disableContributors: true } - }), + }) as VitepressPlugin, BlogPageInfoPlugin({ include: (id) => id.includes(path.sep + "blog" + path.sep) && !id.endsWith(path.sep + "blog" + path.sep + "index.md") }) diff --git a/docs/guide/grammar.md b/docs/guide/grammar.md index eb3bad1c..eadae8c3 100644 --- a/docs/guide/grammar.md +++ b/docs/guide/grammar.md @@ -1,3 +1,6 @@ +--- +outline: deep +--- # Using Grammar Use this to enforce a model to generate response in a specific format of text, like `JSON` for example. @@ -69,11 +72,11 @@ console.log(JSON.parse(a2)); The [`llama.createGrammarForJsonSchema(...)`](../api/classes/Llama.md#creategrammarforjsonschema) creates a [`LlamaJsonSchemaGrammar`](../api/classes/LlamaJsonSchemaGrammar) from a GBNF grammar generated a based on the [JSON schema](https://json-schema.org/learn/getting-started-step-by-step) you provide. -It only supports [a small subset of the JSON schema spec](../api/type-aliases/GbnfJsonSchema.md), +It only supports [a subset of the JSON schema spec](../api/type-aliases/GbnfJsonSchema.md), but it's enough to generate useful JSON objects using a text generation model. -Many features of [JSON schema spec](https://json-schema.org/learn/getting-started-step-by-step) are not supported here on purpose, -as those features don't align well with the way models generate text and are prone to [hallucinations](https://en.wikipedia.org/wiki/Hallucination_(artificial_intelligence)). +Some features of [JSON schema spec](https://json-schema.org/learn/getting-started-step-by-step) are not supported on purpose, +as those features don't align well with the way models generate text, and are too prone to [hallucinations](https://en.wikipedia.org/wiki/Hallucination_(artificial_intelligence)). Workarounds for the missing features that you can implement with the supported set of features often lead to improved generation quality. To see what subset of the JSON schema spec is supported, see the [`GbnfJsonSchema` type](../api/type-aliases/GbnfJsonSchema.md) and follow its sub-types. @@ -134,6 +137,41 @@ console.log( ); ``` +### Reducing Hallucinations When Using JSON Schema Grammar {#reducing-json-schema-hallucinations} +When forcing a model to follow a specific JSON schema in its response, the model isn't aware of the entire schema being enforced on it. +To avoid hallucinations, you need to inform the model in some way what are your expectations from its response. + +To do that, you can: +* Explain to the model what you expect in the prompt itself. +
+ You can do that by giving a brief explanation of what you expect, + or by dumping the entire JSON schema in the prompt (which can eat up a lot of tokens, thus is not recommended). +* Force the model to output self-explanatory keys as part of its response, so it can then generate values for those keys. +* Use a combination of both. + +The technique used in [the above example](#json-schema) forces the model to output the given keys, and then lets the model generate the values for those keys: +1. The model is forced to generate the text `{"positiveWordsInUserMessage": [`, and then we let it finish the syntax of the JSON array with only strings. +2. When it finishes the array, we force it to
generate the text `, "userMessagePositivityScoreFromOneToTen": `, and then we let it generate a number. +3. Finally, we force it to generate the text `, "nameOfUser": `, and then we let it generate either a string or `null`. + +This technique allows us to get the desired result without explaining to the model what we want in advance. +While this method works great in this example, it may not work as well in other cases that need some explanation. + +For example, let's say we force the model to generate an array with at least 2 items and at most 5 items; +if we don't provide any prior explanation for this requirement (either by using a self-explanatory key name or in the prompt), +then the model won't be able to "plan" the entire content of the array in advance, +which can lead it to generate inconsistent and unevenly spread items. +It can also make the model repeat the existing value in different forms or make up wrong values, +just so it can follow the enforced schema. + +The key takeaway is that to reduce hallucinations and achieve great results when using a JSON schema grammar, +you need to ensure you inform the model of your expectations in some way. + +::: tip NOTE +When using [function calling](./function-calling.md), the model is always aware of the entire schema being enforced on it, +so there's no need to explain the schema in the prompt. +::: + ## Creating Your Own Grammar {#custom-grammar} To create your own grammar, read the [GBNF guide](https://github.com/ggerganov/llama.cpp/blob/f5fe98d11bdf9e7797bcfb05c0c3601ffc4b9d26/grammars/README.md) to create a GBNF grammar file. diff --git a/eslint.config.js b/eslint.config.js index 35c6251d..15e7409b 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -90,7 +90,7 @@ export default tseslint.config({ after: true }], "@stylistic/comma-style": ["error", "last"], - "@stylistic/comma-dangle": ["error", "never"], + "@stylistic/comma-dangle": ["warn", "never"], "no-var": ["error"], "import/order": ["error", { groups: ["builtin", "external", "internal", "parent", "sibling", "index", "type", "object", "unknown"], @@ -142,7 +142,8 @@ export default tseslint.config({ {blankLine: "always", prev: "*", next: "method"} ] }], - "@stylistic/no-trailing-spaces": ["warn"] + "@stylistic/no-trailing-spaces": ["warn"], + "@stylistic/no-multi-spaces": ["warn"] } }, { files: ["**/**.{,c,m}ts"], diff --git a/llama/addon/AddonGrammar.cpp b/llama/addon/AddonGrammar.cpp index f6d147b8..15db61dd 100644 --- a/llama/addon/AddonGrammar.cpp +++ b/llama/addon/AddonGrammar.cpp @@ -34,6 +34,54 @@ AddonGrammar::~AddonGrammar() { } } +Napi::Value AddonGrammar::isTextCompatible(const Napi::CallbackInfo& info) { + const std::string testText = info[0].As().Utf8Value(); + + auto parsed_grammar = llama_grammar_init_impl(nullptr, grammarCode.c_str(), rootRuleName.c_str()); + + // will be empty if there are parse errors + if (parsed_grammar == nullptr) { + Napi::Error::New(info.Env(), "Failed to parse grammar").ThrowAsJavaScriptException(); + return Napi::Boolean::New(info.Env(), false); + } + + const auto cpts = unicode_cpts_from_utf8(testText); + const llama_grammar_rules & rules = llama_grammar_get_rules(parsed_grammar); + llama_grammar_stacks & stacks_cur = llama_grammar_get_stacks(parsed_grammar); + + for (const auto & cpt : cpts) { + const llama_grammar_stacks stacks_prev = llama_grammar_get_stacks(parsed_grammar); + + llama_grammar_accept(rules, stacks_prev, cpt, stacks_cur); + + if (stacks_cur.empty()) { + // no stacks means that the grammar failed to match at this point + llama_grammar_free_impl(parsed_grammar); + return Napi::Boolean::New(info.Env(), false); + } + } + + for (const auto & stack : stacks_cur) { + if (stack.empty()) { + // an empty stack means that the grammar has been completed + llama_grammar_free_impl(parsed_grammar); + return Napi::Boolean::New(info.Env(), true); + } + } + + llama_grammar_free_impl(parsed_grammar); + return Napi::Boolean::New(info.Env(), false); +} + void AddonGrammar::init(Napi::Object exports) { - exports.Set("AddonGrammar", DefineClass(exports.Env(), "AddonGrammar", {})); + exports.Set( + "AddonGrammar", + DefineClass( + exports.Env(), + "AddonGrammar", + { + InstanceMethod("isTextCompatible", &AddonGrammar::isTextCompatible), + } + ) + ); } \ No newline at end of file diff --git a/llama/addon/AddonGrammar.h b/llama/addon/AddonGrammar.h index 0df7ed71..835ab61f 100644 --- a/llama/addon/AddonGrammar.h +++ b/llama/addon/AddonGrammar.h @@ -2,6 +2,7 @@ #include "llama.h" #include "common/common.h" #include "llama-grammar.h" +#include "unicode.h" #include "napi.h" #include "addonGlobals.h" @@ -15,5 +16,7 @@ class AddonGrammar : public Napi::ObjectWrap { AddonGrammar(const Napi::CallbackInfo& info); ~AddonGrammar(); + Napi::Value isTextCompatible(const Napi::CallbackInfo& info); + static void init(Napi::Object exports); }; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 84b212d3..b59e7907 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,20 +17,20 @@ "chmodrp": "^1.0.2", "cmake-js": "^7.3.0", "cross-env": "^7.0.3", - "cross-spawn": "^7.0.3", + "cross-spawn": "^7.0.6", "env-var": "^7.5.0", "filenamify": "^6.0.0", "fs-extra": "^11.2.0", "ignore": "^5.3.2", - "ipull": "^3.9.0", + "ipull": "^3.9.2", "is-unicode-supported": "^2.1.0", "lifecycle-utils": "^1.7.0", "log-symbols": "^7.0.0", - "nanoid": "^5.0.8", - "node-addon-api": "^8.2.1", + "nanoid": "^5.0.9", + "node-addon-api": "^8.3.0", "octokit": "^4.0.2", - "ora": "^8.1.0", - "pretty-ms": "^9.1.0", + "ora": "^8.1.1", + "pretty-ms": "^9.2.0", "proper-lockfile": "^4.1.2", "semver": "^7.6.3", "simple-git": "^3.27.0", @@ -46,53 +46,53 @@ "node-llama-cpp": "dist/cli/cli.js" }, "devDependencies": { - "@commitlint/cli": "^19.5.0", - "@commitlint/config-conventional": "^19.5.0", - "@eslint/compat": "^1.2.2", + "@commitlint/cli": "^19.6.0", + "@commitlint/config-conventional": "^19.6.0", + "@eslint/compat": "^1.2.3", "@fontsource/inter": "^5.1.0", - "@nolebase/vitepress-plugin-git-changelog": "^2.6.1", - "@nolebase/vitepress-plugin-og-image": "^2.6.1", + "@nolebase/vitepress-plugin-git-changelog": "^2.11.1", + "@nolebase/vitepress-plugin-og-image": "^2.11.1", "@resvg/resvg-js": "^2.6.2", "@semantic-release/exec": "^6.0.3", - "@semantic-release/github": "11.0.0", + "@semantic-release/github": "11.0.1", "@semantic-release/npm": "12.0.1", - "@shikijs/vitepress-twoslash": "^1.22.2", - "@stylistic/eslint-plugin": "^2.9.0", + "@shikijs/vitepress-twoslash": "^1.24.0", + "@stylistic/eslint-plugin": "^2.11.0", "@types/async-retry": "^1.4.9", "@types/bytes": "^3.1.4", "@types/cross-spawn": "^6.0.2", "@types/fs-extra": "^11.0.4", - "@types/node": "^22.8.4", + "@types/node": "^22.10.1", "@types/proper-lockfile": "^4.1.4", "@types/semver": "^7.5.8", "@types/validate-npm-package-name": "^4.0.2", "@types/which": "^3.0.4", "@types/yargs": "^17.0.33", - "@vitest/coverage-v8": "^2.1.4", - "@vitest/ui": "^2.1.4", - "electron": "^33.2.0", - "eslint": "^9.13.0", + "@vitest/coverage-v8": "^2.1.6", + "@vitest/ui": "^2.1.6", + "electron": "^33.2.1", + "eslint": "^9.16.0", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsdoc": "^50.4.3", - "eslint-plugin-n": "^17.12.0", + "eslint-plugin-jsdoc": "^50.6.0", + "eslint-plugin-n": "^17.14.0", "feed": "^4.2.2", - "husky": "^9.1.6", + "husky": "^9.1.7", "rehype": "^13.0.1", "rimraf": "^6.0.1", "semantic-release": "^24.2.0", "sharp": "^0.33.5", - "tslib": "^2.8.0", - "typedoc": "^0.26.10", - "typedoc-plugin-markdown": "^4.2.9", - "typedoc-plugin-mdn-links": "^3.3.5", - "typedoc-vitepress-theme": "^1.0.2", - "typescript": "^5.6.3", - "typescript-eslint": "^8.12.2", - "vite-node": "^2.1.4", - "vitepress": "^1.4.2", - "vitest": "^2.1.4", - "zx": "^8.1.9" + "tslib": "^2.8.1", + "typedoc": "^0.27.2", + "typedoc-plugin-markdown": "^4.3.1", + "typedoc-plugin-mdn-links": "^4.0.3", + "typedoc-vitepress-theme": "^1.1.0", + "typescript": "^5.7.2", + "typescript-eslint": "^8.16.0", + "vite-node": "^2.1.6", + "vitepress": "^1.5.0", + "vitest": "^2.1.6", + "zx": "^8.2.4" }, "engines": { "node": ">=18.0.0" @@ -124,37 +124,37 @@ } }, "node_modules/@algolia/autocomplete-core": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", - "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz", + "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", - "@algolia/autocomplete-shared": "1.9.3" + "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", + "@algolia/autocomplete-shared": "1.17.7" } }, "node_modules/@algolia/autocomplete-plugin-algolia-insights": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", - "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz", + "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/autocomplete-shared": "1.9.3" + "@algolia/autocomplete-shared": "1.17.7" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "node_modules/@algolia/autocomplete-preset-algolia": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", - "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz", + "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/autocomplete-shared": "1.9.3" + "@algolia/autocomplete-shared": "1.17.7" }, "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", @@ -162,9 +162,9 @@ } }, "node_modules/@algolia/autocomplete-shared": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", - "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz", + "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -172,296 +172,199 @@ "algoliasearch": ">= 4.9.1 < 6" } }, - "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz", - "integrity": "sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/cache-common": "4.24.0" - } - }, - "node_modules/@algolia/cache-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.24.0.tgz", - "integrity": "sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@algolia/cache-in-memory": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz", - "integrity": "sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/cache-common": "4.24.0" - } - }, - "node_modules/@algolia/client-account": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.24.0.tgz", - "integrity": "sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-account/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-account/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "node_modules/@algolia/client-abtesting": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.15.0.tgz", + "integrity": "sha512-FaEM40iuiv1mAipYyiptP4EyxkJ8qHfowCpEeusdHUC4C7spATJYArD2rX3AxkVeREkDIgYEOuXcwKUbDCr7Nw==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.24.0.tgz", - "integrity": "sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.15.0.tgz", + "integrity": "sha512-lho0gTFsQDIdCwyUKTtMuf9nCLwq9jOGlLGIeQGKDxXF7HbiAysFIu5QW/iQr1LzMgDyM9NH7K98KY+BiIFriQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" } }, - "node_modules/@algolia/client-analytics/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "node_modules/@algolia/client-common": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.15.0.tgz", + "integrity": "sha512-IofrVh213VLsDkPoSKMeM9Dshrv28jhDlBDLRcVJQvlL8pzue7PEB1EZ4UoJFYS3NSn7JOcJ/V+olRQzXlJj1w==", "dev": true, "license": "MIT", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" + "engines": { + "node": ">= 14.0.0" } }, - "node_modules/@algolia/client-analytics/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "node_modules/@algolia/client-insights": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.15.0.tgz", + "integrity": "sha512-bDDEQGfFidDi0UQUCbxXOCdphbVAgbVmxvaV75cypBTQkJ+ABx/Npw7LkFGw1FsoVrttlrrQbwjvUB6mLVKs/w==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-common": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.12.0.tgz", - "integrity": "sha512-od3WmO8qxyfNhKc+K3D17tvun3IMs/xMNmxCG9MiElAkYVbPPTRUYMkRneCpmJyQI0hNx2/EA4kZgzVfQjO86Q==", - "dev": true, - "license": "MIT", - "peer": true, + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.24.0.tgz", - "integrity": "sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.15.0.tgz", + "integrity": "sha512-LfaZqLUWxdYFq44QrasCDED5bSYOswpQjSiIL7Q5fYlefAAUO95PzBPKCfUhSwhb4rKxigHfDkd81AvEicIEoA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" } }, - "node_modules/@algolia/client-personalization/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "node_modules/@algolia/client-query-suggestions": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.15.0.tgz", + "integrity": "sha512-wu8GVluiZ5+il8WIRsGKu8VxMK9dAlr225h878GGtpTL6VBvwyJvAyLdZsfFIpY0iN++jiNb31q2C1PlPL+n/A==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.12.0.tgz", - "integrity": "sha512-R3qzEytgVLHOGNri+bpta6NtTt7YtkvUe/QBcAmMDjW4Jk1P0eBYIPfvnzIPbINRsLxIq9fZs9uAYBgsrts4Zg==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.15.0.tgz", + "integrity": "sha512-Z32gEMrRRpEta5UqVQA612sLdoqY3AovvUPClDfMxYrbdDAebmGDVPtSogUba1FZ4pP5dx20D3OV3reogLKsRA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@algolia/client-common": "5.12.0", - "@algolia/requester-browser-xhr": "5.12.0", - "@algolia/requester-fetch": "5.12.0", - "@algolia/requester-node-http": "5.12.0" + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" }, "engines": { "node": ">= 14.0.0" } }, - "node_modules/@algolia/logger-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.24.0.tgz", - "integrity": "sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@algolia/logger-console": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.24.0.tgz", - "integrity": "sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/logger-common": "4.24.0" - } - }, - "node_modules/@algolia/recommend": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.24.0.tgz", - "integrity": "sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.24.0", - "@algolia/cache-common": "4.24.0", - "@algolia/cache-in-memory": "4.24.0", - "@algolia/client-common": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/logger-common": "4.24.0", - "@algolia/logger-console": "4.24.0", - "@algolia/requester-browser-xhr": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/requester-node-http": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/recommend/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "node_modules/@algolia/ingestion": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.15.0.tgz", + "integrity": "sha512-MkqkAxBQxtQ5if/EX2IPqFA7LothghVyvPoRNA/meS2AW2qkHwcxjuiBxv4H6mnAVEPfJlhu9rkdVz9LgCBgJg==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/recommend/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" } }, - "node_modules/@algolia/recommend/node_modules/@algolia/requester-browser-xhr": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", - "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", + "node_modules/@algolia/monitoring": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.15.0.tgz", + "integrity": "sha512-QPrFnnGLMMdRa8t/4bs7XilPYnoUXDY8PMQJ1sf9ZFwhUysYYhQNX34/enoO0LBjpoOY6rLpha39YQEFbzgKyQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/requester-common": "4.24.0" + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" } }, - "node_modules/@algolia/recommend/node_modules/@algolia/requester-node-http": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", - "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", + "node_modules/@algolia/recommend": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.15.0.tgz", + "integrity": "sha512-5eupMwSqMLDObgSMF0XG958zR6GJP3f7jHDQ3/WlzCM9/YIJiWIUoJFGsko9GYsA5xbLDHE/PhWtq4chcCdaGQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/requester-common": "4.24.0" + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.12.0.tgz", - "integrity": "sha512-KxwleraFuVoEGCoeW6Y1RAEbgBMS7SavqeyzWdtkJc6mXeCOJXn1iZitb8Tyn2FcpMNUKlSm0adrUTt7G47+Ow==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.15.0.tgz", + "integrity": "sha512-Po/GNib6QKruC3XE+WKP1HwVSfCDaZcXu48kD+gwmtDlqHWKc7Bq9lrS0sNZ456rfCKhXksOmMfUs4wRM/Y96w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@algolia/client-common": "5.12.0" + "@algolia/client-common": "5.15.0" }, "engines": { "node": ">= 14.0.0" } }, - "node_modules/@algolia/requester-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.24.0.tgz", - "integrity": "sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==", - "dev": true, - "license": "MIT" - }, "node_modules/@algolia/requester-fetch": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.12.0.tgz", - "integrity": "sha512-FuDZXUGU1pAg2HCnrt8+q1VGHKChV/LhvjvZlLOT7e56GJie6p+EuLu4/hMKPOVuQQ8XXtrTHKIU3Lw+7O5/bQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.15.0.tgz", + "integrity": "sha512-rOZ+c0P7ajmccAvpeeNrUmEKoliYFL8aOR5qGW5pFq3oj3Iept7Y5mEtEsOBYsRt6qLnaXn4zUKf+N8nvJpcIw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@algolia/client-common": "5.12.0" + "@algolia/client-common": "5.15.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.12.0.tgz", - "integrity": "sha512-ncDDY7CxZhMs6LIoPl+vHFQceIBhYPY5EfuGF1V7beO0U38xfsCYEyutEFB2kRzf4D9Gqppn3iWX71sNtrKcuw==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.15.0.tgz", + "integrity": "sha512-b1jTpbFf9LnQHEJP5ddDJKE2sAlhYd7EVSOWgzo/27n/SfCoHfqD0VWntnWYD83PnOKvfe8auZ2+xCb0TXotrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@algolia/client-common": "5.12.0" + "@algolia/client-common": "5.15.0" }, "engines": { "node": ">= 14.0.0" } }, - "node_modules/@algolia/transporter": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.24.0.tgz", - "integrity": "sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/cache-common": "4.24.0", - "@algolia/logger-common": "4.24.0", - "@algolia/requester-common": "4.24.0" - } - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -627,14 +530,14 @@ } }, "node_modules/@commitlint/cli": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.5.0.tgz", - "integrity": "sha512-gaGqSliGwB86MDmAAKAtV9SV1SHdmN8pnGq4EJU4+hLisQ7IFfx4jvU4s+pk6tl0+9bv6yT+CaZkufOinkSJIQ==", + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.6.0.tgz", + "integrity": "sha512-v17BgGD9w5KnthaKxXnEg6KLq6DYiAxyiN44TpiRtqyW8NSq+Kx99mkEG8Qo6uu6cI5eMzMojW2muJxjmPnF8w==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/format": "^19.5.0", - "@commitlint/lint": "^19.5.0", + "@commitlint/lint": "^19.6.0", "@commitlint/load": "^19.5.0", "@commitlint/read": "^19.5.0", "@commitlint/types": "^19.5.0", @@ -649,9 +552,9 @@ } }, "node_modules/@commitlint/config-conventional": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.5.0.tgz", - "integrity": "sha512-OBhdtJyHNPryZKg0fFpZNOBM1ZDbntMvqMuSmpfyP86XSfwzGw4CaoYRG4RutUPg0BTK07VMRIkNJT6wi2zthg==", + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.6.0.tgz", + "integrity": "sha512-DJT40iMnTYtBtUfw9ApbsLZFke1zKh6llITVJ+x9mtpHD08gsNXaIRqHTmwTZL3dNX5+WoyK7pCN/5zswvkBCQ==", "dev": true, "license": "MIT", "dependencies": { @@ -719,9 +622,9 @@ } }, "node_modules/@commitlint/is-ignored": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.5.0.tgz", - "integrity": "sha512-0XQ7Llsf9iL/ANtwyZ6G0NGp5Y3EQ8eDQSxv/SRcfJ0awlBY4tHFAvwWbw66FVUaWICH7iE5en+FD9TQsokZ5w==", + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.6.0.tgz", + "integrity": "sha512-Ov6iBgxJQFR9koOupDPHvcHU9keFupDgtB3lObdEZDroiG4jj1rzky60fbQozFKVYRTUdrBGICHG0YVmRuAJmw==", "dev": true, "license": "MIT", "dependencies": { @@ -733,15 +636,15 @@ } }, "node_modules/@commitlint/lint": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.5.0.tgz", - "integrity": "sha512-cAAQwJcRtiBxQWO0eprrAbOurtJz8U6MgYqLz+p9kLElirzSCc0vGMcyCaA1O7AqBuxo11l1XsY3FhOFowLAAg==", + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.6.0.tgz", + "integrity": "sha512-LRo7zDkXtcIrpco9RnfhOKeg8PAnE3oDDoalnrVU/EVaKHYBWYL1DlRR7+3AWn0JiBqD8yKOfetVxJGdEtZ0tg==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/is-ignored": "^19.5.0", + "@commitlint/is-ignored": "^19.6.0", "@commitlint/parse": "^19.5.0", - "@commitlint/rules": "^19.5.0", + "@commitlint/rules": "^19.6.0", "@commitlint/types": "^19.5.0" }, "engines": { @@ -831,9 +734,9 @@ } }, "node_modules/@commitlint/rules": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.5.0.tgz", - "integrity": "sha512-hDW5TPyf/h1/EufSHEKSp6Hs+YVsDMHazfJ2azIk9tHPXS6UqSz1dIRs1gpqS3eMXgtkT7JH6TW4IShdqOwhAw==", + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.6.0.tgz", + "integrity": "sha512-1f2reW7lbrI0X0ozZMesS/WZxgPa4/wi56vFuJENBmed6mWq5KsheN/nxqnl/C23ioxpPO/PL6tXpiiFy5Bhjw==", "dev": true, "license": "MIT", "dependencies": { @@ -884,34 +787,34 @@ } }, "node_modules/@docsearch/css": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.2.tgz", - "integrity": "sha512-vKNZepO2j7MrYBTZIGXvlUOIR+v9KRf70FApRgovWrj3GTs1EITz/Xb0AOlm1xsQBp16clVZj1SY/qaOJbQtZw==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.0.tgz", + "integrity": "sha512-pieeipSOW4sQ0+bE5UFC51AOZp9NGxg89wAlZ1BAQFaiRAGK1IKUaPQ0UGZeNctJXyqZ1UvBtOQh2HH+U5GtmA==", "dev": true, "license": "MIT" }, "node_modules/@docsearch/js": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.6.2.tgz", - "integrity": "sha512-pS4YZF+VzUogYrkblCucQ0Oy2m8Wggk8Kk7lECmZM60hTbaydSIhJTTiCrmoxtBqV8wxORnOqcqqOfbmkkQEcA==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.0.tgz", + "integrity": "sha512-PVuV629f5UcYRtBWqK7ID6vNL5647+2ADJypwTjfeBIrJfwPuHtzLy39hMGMfFK+0xgRyhTR0FZ83EkdEraBlg==", "dev": true, "license": "MIT", "dependencies": { - "@docsearch/react": "3.6.2", + "@docsearch/react": "3.8.0", "preact": "^10.0.0" } }, "node_modules/@docsearch/react": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.2.tgz", - "integrity": "sha512-rtZce46OOkVflCQH71IdbXSFK+S8iJZlUF56XBW5rIgx/eG5qoomC7Ag3anZson1bBac/JFQn7XOBfved/IMRA==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.0.tgz", + "integrity": "sha512-WnFK720+iwTVt94CxY3u+FgX6exb3BfN5kE9xUY6uuAH/9W/UFboBZFLlrw/zxFRHoHZCOXRtOylsXF+6LHI+Q==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/autocomplete-core": "1.9.3", - "@algolia/autocomplete-preset-algolia": "1.9.3", - "@docsearch/css": "3.6.2", - "algoliasearch": "^4.19.1" + "@algolia/autocomplete-core": "1.17.7", + "@algolia/autocomplete-preset-algolia": "1.17.7", + "@docsearch/css": "3.8.0", + "algoliasearch": "^5.12.0" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 19.0.0", @@ -1028,9 +931,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", + "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", "cpu": [ "ppc64" ], @@ -1041,13 +944,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", + "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", "cpu": [ "arm" ], @@ -1058,13 +961,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", + "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", "cpu": [ "arm64" ], @@ -1075,13 +978,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", + "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", "cpu": [ "x64" ], @@ -1092,13 +995,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", + "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", "cpu": [ "arm64" ], @@ -1109,13 +1012,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", + "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", "cpu": [ "x64" ], @@ -1126,13 +1029,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", + "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", "cpu": [ "arm64" ], @@ -1143,13 +1046,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", + "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", "cpu": [ "x64" ], @@ -1160,13 +1063,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", + "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", "cpu": [ "arm" ], @@ -1177,13 +1080,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", + "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", "cpu": [ "arm64" ], @@ -1194,13 +1097,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", + "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", "cpu": [ "ia32" ], @@ -1211,13 +1114,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", + "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", "cpu": [ "loong64" ], @@ -1228,13 +1131,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", + "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", "cpu": [ "mips64el" ], @@ -1245,13 +1148,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", + "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", "cpu": [ "ppc64" ], @@ -1262,13 +1165,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", + "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", "cpu": [ "riscv64" ], @@ -1279,13 +1182,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", + "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", "cpu": [ "s390x" ], @@ -1296,13 +1199,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", "cpu": [ "x64" ], @@ -1313,13 +1216,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", + "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", "cpu": [ "x64" ], @@ -1330,13 +1233,30 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", + "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", + "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", "cpu": [ "x64" ], @@ -1347,13 +1267,13 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", + "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", "cpu": [ "x64" ], @@ -1364,13 +1284,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", + "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", "cpu": [ "arm64" ], @@ -1381,13 +1301,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", + "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", "cpu": [ "ia32" ], @@ -1398,13 +1318,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", + "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", "cpu": [ "x64" ], @@ -1415,20 +1335,24 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } @@ -1444,9 +1368,9 @@ } }, "node_modules/@eslint/compat": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.2.tgz", - "integrity": "sha512-jhgiIrsw+tRfcBQ4BFl2C3vCrIUw2trCY0cnDvGZpwTtKCEDmZhAtMfrEUP/KpnwM6PrO0T+Ltm+ccW74olG3Q==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.3.tgz", + "integrity": "sha512-wlZhwlDFxkxIZ571aH0FoK4h4Vwx7P3HJx62Gp8hTc10bfpwT2x0nULuAHmQSJBOWPgPeVf+9YtnD4j50zVHmA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1462,9 +1386,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", + "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1501,9 +1425,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", - "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", + "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1511,9 +1435,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "license": "MIT", "dependencies": { @@ -1583,9 +1507,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", + "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", "dev": true, "license": "MIT", "engines": { @@ -1603,9 +1527,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", - "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1646,6 +1570,18 @@ "dev": true, "license": "OFL-1.1" }, + "node_modules/@gerrit0/mini-shiki": { + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-1.24.1.tgz", + "integrity": "sha512-PNP/Gjv3VqU7z7DjRgO3F9Ok5frTKqtpV+LJW1RzMcr2zpRk0ulhEWnbcNGXzPC7BZyWMIHrkfQX2GZRfxrn6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-oniguruma": "^1.24.0", + "@shikijs/types": "^1.24.0", + "@shikijs/vscode-textmate": "^9.3.0" + } + }, "node_modules/@huggingface/jinja": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.3.2.tgz", @@ -1716,6 +1652,16 @@ "@iconify/types": "*" } }, + "node_modules/@iconify-json/simple-icons": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.13.tgz", + "integrity": "sha512-rRQjMoIt/kPfaD+fnBC9YZQpso3hkn8xPeadl+YWhscJ5SVUCdB9oTeR9VIpt+/5Yi8vEkh2UOWFPq4lz3ee2A==", + "dev": true, + "license": "CC0-1.0", + "dependencies": { + "@iconify/types": "*" + } + }, "node_modules/@iconify/types": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", @@ -2282,37 +2228,37 @@ } }, "node_modules/@nolebase/ui": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@nolebase/ui/-/ui-2.6.1.tgz", - "integrity": "sha512-4jNnLalJOc1BOfuHTU6IfzP1zbXcgr2QumI2vSlZRHeIHZYYSeJTrSKfWRNTcQg2lNan7MXpYAXME478nuryvQ==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@nolebase/ui/-/ui-2.11.1.tgz", + "integrity": "sha512-J08bh8wd1AXYzgGJtnoo6ptr20W+P/JuLISm7HdOTLr5nmq/pKmygOYVx63zuDVskpd04/VwUEkzA5wVipozvg==", "dev": true, "license": "MIT", "dependencies": { "@iconify-json/octicon": "^1.2.1", - "less": "^4.2.0", - "vitepress": "^1.4.0", - "vue": "^3.5.11" + "less": "^4.2.1", + "vitepress": "^1.5.0", + "vue": "^3.5.13" } }, "node_modules/@nolebase/vitepress-plugin-git-changelog": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@nolebase/vitepress-plugin-git-changelog/-/vitepress-plugin-git-changelog-2.6.1.tgz", - "integrity": "sha512-HXZkLG5zR/ZNAddinxSAMqlCK8iTQxweM6IEo+Yz5sjNLpEcxDs41hOs/YAO33imO4yzJGnuxsbg7I1dyq3JtA==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@nolebase/vitepress-plugin-git-changelog/-/vitepress-plugin-git-changelog-2.11.1.tgz", + "integrity": "sha512-CppE+THHJimRODyoPtY7V5f2SF4fZfBUcKST0OOIb8H4Lk+56xhY7HKtq+XzOzdZGN9Q88tTfnPV26hdg+Iwgg==", "dev": true, "license": "MIT", "dependencies": { "@iconify-json/octicon": "^1.2.1", - "@nolebase/ui": "^2.6.1", + "@nolebase/ui": "^2.11.1", "colorette": "^2.0.20", "date-fns": "^4.1.0", "defu": "^6.1.4", - "es-toolkit": "^1.24.0", - "execa": "^9.4.0", + "es-toolkit": "^1.27.0", + "execa": "^9.5.1", "globby": "^14.0.2", "gray-matter": "^4.0.3", - "less": "^4.2.0", + "less": "^4.2.1", "uncrypto": "^0.1.3", - "vitepress": "^1.4.0" + "vitepress": "^1.5.0" } }, "node_modules/@nolebase/vitepress-plugin-git-changelog/node_modules/execa": { @@ -2499,9 +2445,9 @@ } }, "node_modules/@nolebase/vitepress-plugin-og-image": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@nolebase/vitepress-plugin-og-image/-/vitepress-plugin-og-image-2.6.1.tgz", - "integrity": "sha512-KABijY77XcfplAkGxvKMyNl3GBRcqbV7zKovuIh0OJt1kpF3o81otZ5GWKDalo5NtHpPpxRgMUqwwPojl5ONaw==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@nolebase/vitepress-plugin-og-image/-/vitepress-plugin-og-image-2.11.1.tgz", + "integrity": "sha512-s/4mEAcvVF/fG1tIk6OBbMiO2sgmbM6kRuk31h6E9ij67gP33UDCbhl6D4PtemA20k2fJ6Iy/O5GzqMihPG+8A==", "dev": true, "license": "MIT", "dependencies": { @@ -2510,16 +2456,16 @@ "defu": "^6.1.4", "emoji-regex": "^10.4.0", "fs-extra": "^11.2.0", - "glob": "^11.0.0", "gray-matter": "^4.0.3", - "ora": "^8.1.0", + "ora": "^8.1.1", "rehype": "^13.0.2", "rehype-meta": "^4.0.1", "rehype-parse": "^9.0.1", "rehype-stringify": "^10.0.1", + "tinyglobby": "^0.2.10", "unified": "^11.0.5", "unist-util-visit": "^5.0.0", - "vitepress": "^1.4.0" + "vitepress": "^1.5.0" } }, "node_modules/@nolebase/vitepress-plugin-og-image/node_modules/emoji-regex": { @@ -2529,99 +2475,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@nolebase/vitepress-plugin-og-image/node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@nolebase/vitepress-plugin-og-image/node_modules/jackspeak": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", - "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@nolebase/vitepress-plugin-og-image/node_modules/lru-cache": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", - "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@nolebase/vitepress-plugin-og-image/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@nolebase/vitepress-plugin-og-image/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/@nolebase/vitepress-plugin-og-image/node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@nolyfill/is-core-module": { "version": "1.0.39", "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", @@ -3457,9 +3310,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.2.tgz", - "integrity": "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.0.tgz", + "integrity": "sha512-wLJuPLT6grGZsy34g4N1yRfYeouklTgPhH1gWXCYspenKYD0s3cR99ZevOGw5BexMNywkbV3UkjADisozBmpPQ==", "cpu": [ "arm" ], @@ -3471,9 +3324,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.2.tgz", - "integrity": "sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.0.tgz", + "integrity": "sha512-eiNkznlo0dLmVG/6wf+Ifi/v78G4d4QxRhuUl+s8EWZpDewgk7PX3ZyECUXU0Zq/Ca+8nU8cQpNC4Xgn2gFNDA==", "cpu": [ "arm64" ], @@ -3485,9 +3338,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.2.tgz", - "integrity": "sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.0.tgz", + "integrity": "sha512-lmKx9yHsppblnLQZOGxdO66gT77bvdBtr/0P+TPOseowE7D9AJoBw8ZDULRasXRWf1Z86/gcOdpBrV6VDUY36Q==", "cpu": [ "arm64" ], @@ -3499,9 +3352,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.2.tgz", - "integrity": "sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.0.tgz", + "integrity": "sha512-8hxgfReVs7k9Js1uAIhS6zq3I+wKQETInnWQtgzt8JfGx51R1N6DRVy3F4o0lQwumbErRz52YqwjfvuwRxGv1w==", "cpu": [ "x64" ], @@ -3512,10 +3365,38 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.0.tgz", + "integrity": "sha512-lA1zZB3bFx5oxu9fYud4+g1mt+lYXCoch0M0V/xhqLoGatbzVse0wlSQ1UYOWKpuSu3gyN4qEc0Dxf/DII1bhQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.0.tgz", + "integrity": "sha512-aI2plavbUDjCQB/sRbeUZWX9qp12GfYkYSJOrdYTL/C5D53bsE2/nBPuoiJKoWp5SN78v2Vr8ZPnB+/VbQ2pFA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.2.tgz", - "integrity": "sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.0.tgz", + "integrity": "sha512-WXveUPKtfqtaNvpf0iOb0M6xC64GzUX/OowbqfiCSXTdi/jLlOmH0Ba94/OkiY2yTGTwteo4/dsHRfh5bDCZ+w==", "cpu": [ "arm" ], @@ -3527,9 +3408,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.2.tgz", - "integrity": "sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.0.tgz", + "integrity": "sha512-yLc3O2NtOQR67lI79zsSc7lk31xjwcaocvdD1twL64PK1yNaIqCeWI9L5B4MFPAVGEVjH5k1oWSGuYX1Wutxpg==", "cpu": [ "arm" ], @@ -3541,9 +3422,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.2.tgz", - "integrity": "sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.0.tgz", + "integrity": "sha512-+P9G9hjEpHucHRXqesY+3X9hD2wh0iNnJXX/QhS/J5vTdG6VhNYMxJ2rJkQOxRUd17u5mbMLHM7yWGZdAASfcg==", "cpu": [ "arm64" ], @@ -3555,9 +3436,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.2.tgz", - "integrity": "sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.0.tgz", + "integrity": "sha512-1xsm2rCKSTpKzi5/ypT5wfc+4bOGa/9yI/eaOLW0oMs7qpC542APWhl4A37AENGZ6St6GBMWhCCMM6tXgTIplw==", "cpu": [ "arm64" ], @@ -3569,9 +3450,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.2.tgz", - "integrity": "sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.0.tgz", + "integrity": "sha512-zgWxMq8neVQeXL+ouSf6S7DoNeo6EPgi1eeqHXVKQxqPy1B2NvTbaOUWPn/7CfMKL7xvhV0/+fq/Z/J69g1WAQ==", "cpu": [ "ppc64" ], @@ -3583,9 +3464,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.2.tgz", - "integrity": "sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.0.tgz", + "integrity": "sha512-VEdVYacLniRxbRJLNtzwGt5vwS0ycYshofI7cWAfj7Vg5asqj+pt+Q6x4n+AONSZW/kVm+5nklde0qs2EUwU2g==", "cpu": [ "riscv64" ], @@ -3597,9 +3478,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.2.tgz", - "integrity": "sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.0.tgz", + "integrity": "sha512-LQlP5t2hcDJh8HV8RELD9/xlYtEzJkm/aWGsauvdO2ulfl3QYRjqrKW+mGAIWP5kdNCBheqqqYIGElSRCaXfpw==", "cpu": [ "s390x" ], @@ -3611,9 +3492,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.2.tgz", - "integrity": "sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.0.tgz", + "integrity": "sha512-Nl4KIzteVEKE9BdAvYoTkW19pa7LR/RBrT6F1dJCV/3pbjwDcaOq+edkP0LXuJ9kflW/xOK414X78r+K84+msw==", "cpu": [ "x64" ], @@ -3625,9 +3506,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.2.tgz", - "integrity": "sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.0.tgz", + "integrity": "sha512-eKpJr4vBDOi4goT75MvW+0dXcNUqisK4jvibY9vDdlgLx+yekxSm55StsHbxUsRxSTt3JEQvlr3cGDkzcSP8bw==", "cpu": [ "x64" ], @@ -3639,9 +3520,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.2.tgz", - "integrity": "sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.0.tgz", + "integrity": "sha512-Vi+WR62xWGsE/Oj+mD0FNAPY2MEox3cfyG0zLpotZdehPFXwz6lypkGs5y38Jd/NVSbOD02aVad6q6QYF7i8Bg==", "cpu": [ "arm64" ], @@ -3653,9 +3534,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.2.tgz", - "integrity": "sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.0.tgz", + "integrity": "sha512-kN/Vpip8emMLn/eOza+4JwqDZBL6MPNpkdaEsgUtW1NYN3DZvZqSQrbKzJcTL6hd8YNmFTn7XGWMwccOcJBL0A==", "cpu": [ "ia32" ], @@ -3667,9 +3548,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.2.tgz", - "integrity": "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.0.tgz", + "integrity": "sha512-Bvno2/aZT6usSa7lRDL2+hMjVAGjuqaymF1ApZm31JXzniR/hvr14jpU+/z4X6Gt5BPlzosscyJZGUvguXIqeQ==", "cpu": [ "x64" ], @@ -3895,9 +3776,9 @@ } }, "node_modules/@semantic-release/github": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.0.tgz", - "integrity": "sha512-Uon6G6gJD8U1JNvPm7X0j46yxNRJ8Ui6SgK4Zw5Ktu8RgjEft3BGn+l/RX1TTzhhO3/uUcKuqM+/9/ETFxWS/Q==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.1.tgz", + "integrity": "sha512-Z9cr0LgU/zgucbT9cksH0/pX9zmVda9hkDPcgIE0uvjMQ8w/mElDivGjx1w1pEQ+MuQJ5CBq3VCF16S6G4VH3A==", "dev": true, "license": "MIT", "dependencies": { @@ -4302,51 +4183,51 @@ } }, "node_modules/@shikijs/core": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.2.tgz", - "integrity": "sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.24.0.tgz", + "integrity": "sha512-6pvdH0KoahMzr6689yh0QJ3rCgF4j1XsXRHNEeEN6M4xJTfQ6QPWrmHzIddotg+xPJUPEPzYzYCKzpYyhTI6Gw==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/engine-javascript": "1.22.2", - "@shikijs/engine-oniguruma": "1.22.2", - "@shikijs/types": "1.22.2", + "@shikijs/engine-javascript": "1.24.0", + "@shikijs/engine-oniguruma": "1.24.0", + "@shikijs/types": "1.24.0", "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.3" } }, "node_modules/@shikijs/engine-javascript": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz", - "integrity": "sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.24.0.tgz", + "integrity": "sha512-ZA6sCeSsF3Mnlxxr+4wGEJ9Tto4RHmfIS7ox8KIAbH0MTVUkw3roHPHZN+LlJMOHJJOVupe6tvuAzRpN8qK1vA==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "1.22.2", + "@shikijs/types": "1.24.0", "@shikijs/vscode-textmate": "^9.3.0", - "oniguruma-to-js": "0.4.3" + "oniguruma-to-es": "0.7.0" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz", - "integrity": "sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.24.0.tgz", + "integrity": "sha512-Eua0qNOL73Y82lGA4GF5P+G2+VXX9XnuUxkiUuwcxQPH4wom+tE39kZpBFXfUuwNYxHSkrSxpB1p4kyRW0moSg==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "1.22.2", + "@shikijs/types": "1.24.0", "@shikijs/vscode-textmate": "^9.3.0" } }, "node_modules/@shikijs/transformers": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.22.2.tgz", - "integrity": "sha512-8f78OiBa6pZDoZ53lYTmuvpFPlWtevn23bzG+azpPVvZg7ITax57o/K3TC91eYL3OMJOO0onPbgnQyZjRos8XQ==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.24.0.tgz", + "integrity": "sha512-Qf/hby+PRPkoHncjYnJf5svK1aCsOUtQhuLzKPnmeXJtuUZCmbH0pTpdNtXe9tgln/RHlyRJnv7q46HHS1sO0Q==", "dev": true, "license": "MIT", "dependencies": { - "shiki": "1.22.2" + "shiki": "1.24.0" } }, "node_modules/@shikijs/twoslash": { @@ -4371,9 +4252,9 @@ } }, "node_modules/@shikijs/types": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.2.tgz", - "integrity": "sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.24.0.tgz", + "integrity": "sha512-aptbEuq1Pk88DMlCe+FzXNnBZ17LCiLIGWAeCWhoFDzia5Q5Krx3DgnULLiouSdd6+LUM39XwXGppqYE0Ghtug==", "dev": true, "license": "MIT", "dependencies": { @@ -4382,9 +4263,9 @@ } }, "node_modules/@shikijs/vitepress-twoslash": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@shikijs/vitepress-twoslash/-/vitepress-twoslash-1.22.2.tgz", - "integrity": "sha512-F4cS9l6QTt/ILlz+S871bOido2CK8Xwdnl4q9gHdnTuZlN1PHAMRZbAOvYAtokvouPp9aZ2W7NtNa+CNCn3yPQ==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@shikijs/vitepress-twoslash/-/vitepress-twoslash-1.24.0.tgz", + "integrity": "sha512-uqAzAHZkg0yzOtVxA3H+xz+tNgFO2f328EfKOIeX98HgI7V1YNm/a+uUqiVuTYY03N9nBMJbdrCHcw7HIc/C3A==", "dev": true, "license": "MIT", "dependencies": { @@ -4393,10 +4274,10 @@ "mdast-util-from-markdown": "^2.0.2", "mdast-util-gfm": "^3.0.0", "mdast-util-to-hast": "^13.2.0", - "shiki": "1.22.2", + "shiki": "1.24.0", "twoslash": "^0.2.12", "twoslash-vue": "^0.2.12", - "vue": "^3.5.12" + "vue": "^3.5.13" } }, "node_modules/@shikijs/vscode-textmate": { @@ -4431,15 +4312,15 @@ } }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.9.0.tgz", - "integrity": "sha512-OrDyFAYjBT61122MIY1a3SfEgy3YCMgt2vL4eoPmvTwDBwyQhAXurxNQznlRD/jESNfYWfID8Ej+31LljvF7Xg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.11.0.tgz", + "integrity": "sha512-PNRHbydNG5EH8NK4c+izdJlxajIR6GxcUhzsYNRsn6Myep4dsZt0qFCz3rCPnkvgO5FYibDcMqgNHUT+zvjYZw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.8.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "@typescript-eslint/utils": "^8.13.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, @@ -4564,10 +4445,11 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/fs-extra": { "version": "11.0.4", @@ -4669,15 +4551,22 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.8.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", - "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", + "version": "22.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", + "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.8" + "undici-types": "~6.20.0" } }, + "node_modules/@types/node/node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", @@ -4768,17 +4657,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.2.tgz", - "integrity": "sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.16.0.tgz", + "integrity": "sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/type-utils": "8.12.2", - "@typescript-eslint/utils": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/type-utils": "8.16.0", + "@typescript-eslint/utils": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -4802,16 +4691,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.2.tgz", - "integrity": "sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.16.0.tgz", + "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/typescript-estree": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/typescript-estree": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "debug": "^4.3.4" }, "engines": { @@ -4831,14 +4720,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz", - "integrity": "sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz", + "integrity": "sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2" + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4849,14 +4738,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.12.2.tgz", - "integrity": "sha512-bwuU4TAogPI+1q/IJSKuD4shBLc/d2vGcRT588q+jzayQyjVK2X6v/fbR4InY2U2sgf8MEvVCqEWUzYzgBNcGQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.16.0.tgz", + "integrity": "sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.12.2", - "@typescript-eslint/utils": "8.12.2", + "@typescript-eslint/typescript-estree": "8.16.0", + "@typescript-eslint/utils": "8.16.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -4867,6 +4756,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -4874,9 +4766,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz", - "integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.16.0.tgz", + "integrity": "sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==", "dev": true, "license": "MIT", "engines": { @@ -4888,14 +4780,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz", - "integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz", + "integrity": "sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -4917,16 +4809,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.2.tgz", - "integrity": "sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.16.0.tgz", + "integrity": "sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/typescript-estree": "8.12.2" + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/typescript-estree": "8.16.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4937,17 +4829,22 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz", - "integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz", + "integrity": "sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.12.2", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.16.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4957,6 +4854,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@typescript/vfs": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.0.tgz", @@ -4977,23 +4887,23 @@ "dev": true }, "node_modules/@vitejs/plugin-vue": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.1.4.tgz", - "integrity": "sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz", + "integrity": "sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==", "dev": true, "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" }, "peerDependencies": { - "vite": "^5.0.0", + "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "node_modules/@vitest/coverage-v8": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.4.tgz", - "integrity": "sha512-FPKQuJfR6VTfcNMcGpqInmtJuVXFSCd9HQltYncfR01AzXhLucMEtQ5SinPdZxsT5x/5BK7I5qFJ5/ApGCmyTQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.6.tgz", + "integrity": "sha512-qItJVYDbG3MUFO68dOZUz+rWlqe9LMzotERXFXKg25s2A/kSVsyS9O0yNGrITfBd943GsnBeQZkBUu7Pc+zVeA==", "dev": true, "license": "MIT", "dependencies": { @@ -5006,7 +4916,7 @@ "istanbul-reports": "^3.1.7", "magic-string": "^0.30.12", "magicast": "^0.3.5", - "std-env": "^3.7.0", + "std-env": "^3.8.0", "test-exclude": "^7.0.1", "tinyrainbow": "^1.2.0" }, @@ -5014,8 +4924,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "2.1.4", - "vitest": "2.1.4" + "@vitest/browser": "2.1.6", + "vitest": "2.1.6" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -5024,14 +4934,14 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.4.tgz", - "integrity": "sha512-DOETT0Oh1avie/D/o2sgMHGrzYUFFo3zqESB2Hn70z6QB1HrS2IQ9z5DfyTqU8sg4Bpu13zZe9V4+UTNQlUeQA==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.6.tgz", + "integrity": "sha512-9M1UR9CAmrhJOMoSwVnPh2rELPKhYo0m/CSgqw9PyStpxtkwhmdM6XYlXGKeYyERY1N6EIuzkQ7e3Lm1WKCoUg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.4", - "@vitest/utils": "2.1.4", + "@vitest/spy": "2.1.6", + "@vitest/utils": "2.1.6", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" }, @@ -5040,13 +4950,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.4.tgz", - "integrity": "sha512-Ky/O1Lc0QBbutJdW0rqLeFNbuLEyS+mIPiNdlVlp2/yhJ0SbyYqObS5IHdhferJud8MbbwMnexg4jordE5cCoQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.6.tgz", + "integrity": "sha512-MHZp2Z+Q/A3am5oD4WSH04f9B0T7UvwEb+v5W0kCYMhtXGYbdyl2NUk1wdSMqGthmhpiThPDp/hEoVwu16+u1A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.4", + "@vitest/spy": "2.1.6", "estree-walker": "^3.0.3", "magic-string": "^0.30.12" }, @@ -5055,7 +4965,7 @@ }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^5.0.0" + "vite": "^5.0.0 || ^6.0.0" }, "peerDependenciesMeta": { "msw": { @@ -5067,9 +4977,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.4.tgz", - "integrity": "sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.6.tgz", + "integrity": "sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==", "dev": true, "license": "MIT", "dependencies": { @@ -5080,13 +4990,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.4.tgz", - "integrity": "sha512-sKRautINI9XICAMl2bjxQM8VfCMTB0EbsBc/EDFA57V6UQevEKY/TOPOF5nzcvCALltiLfXWbq4MaAwWx/YxIA==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.6.tgz", + "integrity": "sha512-SjkRGSFyrA82m5nz7To4CkRSEVWn/rwQISHoia/DB8c6IHIhaE/UNAo+7UfeaeJRE979XceGl00LNkIz09RFsA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.4", + "@vitest/utils": "2.1.6", "pathe": "^1.1.2" }, "funding": { @@ -5094,13 +5004,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.4.tgz", - "integrity": "sha512-3Kab14fn/5QZRog5BPj6Rs8dc4B+mim27XaKWFWHWA87R56AKjHTGcBFKpvZKDzC4u5Wd0w/qKsUIio3KzWW4Q==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.6.tgz", + "integrity": "sha512-5JTWHw8iS9l3v4/VSuthCndw1lN/hpPB+mlgn1BUhFbobeIUj1J1V/Bj2t2ovGEmkXLTckFjQddsxS5T6LuVWw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.4", + "@vitest/pretty-format": "2.1.6", "magic-string": "^0.30.12", "pathe": "^1.1.2" }, @@ -5109,9 +5019,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.4.tgz", - "integrity": "sha512-4JOxa+UAizJgpZfaCPKK2smq9d8mmjZVPMt2kOsg/R8QkoRzydHH1qHxIYNvr1zlEaFj4SXiaaJWxq/LPLKaLg==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.6.tgz", + "integrity": "sha512-oTFObV8bd4SDdRka5O+mSh5w9irgx5IetrD5i+OsUUsk/shsBoHifwCzy45SAORzAhtNiprUVaK3hSCCzZh1jQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5122,35 +5032,35 @@ } }, "node_modules/@vitest/ui": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-2.1.4.tgz", - "integrity": "sha512-Zd9e5oU063c+j9N9XzGJagCLNvG71x/2tOme3Js4JEZKX55zsgxhJwUgLI8hkN6NjMLpdJO8d7nVUUuPGAA58Q==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-2.1.6.tgz", + "integrity": "sha512-SrpLAM0/xpOjXBDv3mayFh5TDEYM59fmEmJXgp1AqtpUWHVw4Tonp6Z9dVBhChU/Q+BY57m74nrQZK8vxKDrMQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.4", + "@vitest/utils": "2.1.6", "fflate": "^0.8.2", "flatted": "^3.3.1", "pathe": "^1.1.2", "sirv": "^3.0.0", - "tinyglobby": "^0.2.9", + "tinyglobby": "^0.2.10", "tinyrainbow": "^1.2.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "2.1.4" + "vitest": "2.1.6" } }, "node_modules/@vitest/utils": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.4.tgz", - "integrity": "sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.6.tgz", + "integrity": "sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.4", + "@vitest/pretty-format": "2.1.6", "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" }, @@ -5176,14 +5086,14 @@ "license": "MIT" }, "node_modules/@vue/compiler-core": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.12.tgz", - "integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", + "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.25.3", - "@vue/shared": "3.5.12", + "@vue/shared": "3.5.13", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" @@ -5197,31 +5107,31 @@ "license": "MIT" }, "node_modules/@vue/compiler-dom": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz", - "integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", + "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.12", - "@vue/shared": "3.5.12" + "@vue/compiler-core": "3.5.13", + "@vue/shared": "3.5.13" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.12.tgz", - "integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", + "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.25.3", - "@vue/compiler-core": "3.5.12", - "@vue/compiler-dom": "3.5.12", - "@vue/compiler-ssr": "3.5.12", - "@vue/shared": "3.5.12", + "@vue/compiler-core": "3.5.13", + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", - "postcss": "^8.4.47", + "postcss": "^8.4.48", "source-map-js": "^1.2.0" } }, @@ -5233,14 +5143,14 @@ "license": "MIT" }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.12.tgz", - "integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", + "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.12", - "@vue/shared": "3.5.12" + "@vue/compiler-dom": "3.5.13", + "@vue/shared": "3.5.13" } }, "node_modules/@vue/compiler-vue2": { @@ -5255,23 +5165,23 @@ } }, "node_modules/@vue/devtools-api": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.6.0.tgz", - "integrity": "sha512-FGxX7jatS0ZcsglIBcdxAQciYSUpb/eXt610x0YDVBdIJaH0x6iDg0vs4MhbzSIrRCywjFmW+ZwpYus/eFIS8Q==", + "version": "7.6.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.6.7.tgz", + "integrity": "sha512-PV4I31WaV2rfA8RGauM+69uFEzWkqtP561RiLU2wK+Ce85u3zyKW3aoESlLCNzkc4y0JaJyskH6zAE3xWOP8+Q==", "dev": true, "license": "MIT", "dependencies": { - "@vue/devtools-kit": "^7.6.0" + "@vue/devtools-kit": "^7.6.7" } }, "node_modules/@vue/devtools-kit": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.6.0.tgz", - "integrity": "sha512-82Mhrk/PRiTGfLwj73mXfrrocnCbWEPLLk3r4HhIkcieTa610Snlqc0a9OBiSsldX98YI6rOcL04+Dud1tLIKg==", + "version": "7.6.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.6.7.tgz", + "integrity": "sha512-V8/jrXY/swHgnblABG9U4QCbE60c6RuPasmv2d9FvVqc5d94t1vDiESuvRmdNJBdWz4/D3q6ffgyAfRVjwHYEw==", "dev": true, "license": "MIT", "dependencies": { - "@vue/devtools-shared": "^7.6.0", + "@vue/devtools-shared": "^7.6.7", "birpc": "^0.2.19", "hookable": "^5.5.3", "mitt": "^3.0.1", @@ -5281,9 +5191,9 @@ } }, "node_modules/@vue/devtools-shared": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.6.0.tgz", - "integrity": "sha512-ANh0nvp/oQXaz5PaSXL78I9X3v767kD0Cbit8u6mOd1oZmC+sj115/1CBH8BBBdRuLg8HCjpE2444a6cbXjKTA==", + "version": "7.6.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.6.7.tgz", + "integrity": "sha512-QggO6SviAsolrePAXZ/sA1dSicSPt4TueZibCvydfhNDieL1lAuyMTgQDGst7TEvMGb4vgYv2I+1sDkO4jWNnw==", "dev": true, "license": "MIT", "dependencies": { @@ -5316,70 +5226,70 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.12.tgz", - "integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz", + "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==", "dev": true, "license": "MIT", "dependencies": { - "@vue/shared": "3.5.12" + "@vue/shared": "3.5.13" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.12.tgz", - "integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz", + "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==", "dev": true, "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.12", - "@vue/shared": "3.5.12" + "@vue/reactivity": "3.5.13", + "@vue/shared": "3.5.13" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.12.tgz", - "integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz", + "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==", "dev": true, "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.12", - "@vue/runtime-core": "3.5.12", - "@vue/shared": "3.5.12", + "@vue/reactivity": "3.5.13", + "@vue/runtime-core": "3.5.13", + "@vue/shared": "3.5.13", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.12.tgz", - "integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz", + "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.12", - "@vue/shared": "3.5.12" + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13" }, "peerDependencies": { - "vue": "3.5.12" + "vue": "3.5.13" } }, "node_modules/@vue/shared": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.12.tgz", - "integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", + "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", "dev": true, "license": "MIT" }, "node_modules/@vueuse/core": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.1.0.tgz", - "integrity": "sha512-P6dk79QYA6sKQnghrUz/1tHi0n9mrb/iO1WTMk/ElLmTyNqgDeSZ3wcDf6fRBGzRJbeG1dxzEOvLENMjr+E3fg==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.3.0.tgz", + "integrity": "sha512-7OC4Rl1f9G8IT6rUfi9JrKiXy4bfmHhZ5x2Ceojy0jnd3mHNEvV4JaRygH362ror6/NZ+Nl+n13LPzGiPN8cKA==", "dev": true, "license": "MIT", "dependencies": { "@types/web-bluetooth": "^0.0.20", - "@vueuse/metadata": "11.1.0", - "@vueuse/shared": "11.1.0", + "@vueuse/metadata": "11.3.0", + "@vueuse/shared": "11.3.0", "vue-demi": ">=0.14.10" }, "funding": { @@ -5414,14 +5324,14 @@ } }, "node_modules/@vueuse/integrations": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-11.1.0.tgz", - "integrity": "sha512-O2ZgrAGPy0qAjpoI2YR3egNgyEqwG85fxfwmA9BshRIGjV4G6yu6CfOPpMHAOoCD+UfsIl7Vb1bXJ6ifrHYDDA==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-11.3.0.tgz", + "integrity": "sha512-5fzRl0apQWrDezmobchoiGTkGw238VWESxZHazfhP3RM7pDSiyXy18QbfYkILoYNTd23HPAfQTJpkUc5QbkwTw==", "dev": true, "license": "MIT", "dependencies": { - "@vueuse/core": "11.1.0", - "@vueuse/shared": "11.1.0", + "@vueuse/core": "11.3.0", + "@vueuse/shared": "11.3.0", "vue-demi": ">=0.14.10" }, "funding": { @@ -5508,9 +5418,9 @@ } }, "node_modules/@vueuse/metadata": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.1.0.tgz", - "integrity": "sha512-l9Q502TBTaPYGanl1G+hPgd3QX5s4CGnpXriVBR5fEZ/goI6fvDaVmIl3Td8oKFurOxTmbXvBPSsgrd6eu6HYg==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.3.0.tgz", + "integrity": "sha512-pwDnDspTqtTo2HwfLw4Rp6yywuuBdYnPYDq+mO38ZYKGebCUQC/nVj/PXSiK9HX5otxLz8Fn7ECPbjiRz2CC3g==", "dev": true, "license": "MIT", "funding": { @@ -5518,9 +5428,9 @@ } }, "node_modules/@vueuse/shared": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-11.1.0.tgz", - "integrity": "sha512-YUtIpY122q7osj+zsNMFAfMTubGz0sn5QzE5gPzAIiCmtt2ha3uQUY1+JPyL4gRCTsLPX82Y9brNbo/aqlA91w==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-11.3.0.tgz", + "integrity": "sha512-P8gSSWQeucH5821ek2mn/ciCk+MS/zoRKqdQIM3bHq6p7GXDAJLmnRRKmF5F65sAVJIfzQlwR3aDzwCn10s8hA==", "dev": true, "license": "MIT", "dependencies": { @@ -5622,70 +5532,28 @@ } }, "node_modules/algoliasearch": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", - "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.24.0", - "@algolia/cache-common": "4.24.0", - "@algolia/cache-in-memory": "4.24.0", - "@algolia/client-account": "4.24.0", - "@algolia/client-analytics": "4.24.0", - "@algolia/client-common": "4.24.0", - "@algolia/client-personalization": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/logger-common": "4.24.0", - "@algolia/logger-console": "4.24.0", - "@algolia/recommend": "4.24.0", - "@algolia/requester-browser-xhr": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/requester-node-http": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/algoliasearch/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/algoliasearch/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/algoliasearch/node_modules/@algolia/requester-browser-xhr": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", - "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/requester-common": "4.24.0" - } - }, - "node_modules/algoliasearch/node_modules/@algolia/requester-node-http": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", - "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.15.0.tgz", + "integrity": "sha512-Yf3Swz1s63hjvBVZ/9f2P1Uu48GjmjCN+Esxb6MAONMGtZB1fRX8/S1AhUTtsuTlcGovbYLxpHgc7wEzstDZBw==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/requester-common": "4.24.0" + "@algolia/client-abtesting": "5.15.0", + "@algolia/client-analytics": "5.15.0", + "@algolia/client-common": "5.15.0", + "@algolia/client-insights": "5.15.0", + "@algolia/client-personalization": "5.15.0", + "@algolia/client-query-suggestions": "5.15.0", + "@algolia/client-search": "5.15.0", + "@algolia/ingestion": "1.15.0", + "@algolia/monitoring": "1.15.0", + "@algolia/recommend": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/alien-signals": { @@ -5921,9 +5789,10 @@ } }, "node_modules/axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz", + "integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -6672,6 +6541,7 @@ "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", "dev": true, + "license": "ISC", "dependencies": { "compare-func": "^2.0.0" }, @@ -6739,6 +6609,7 @@ "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", "dev": true, + "license": "MIT", "dependencies": { "is-text-path": "^2.0.0", "JSONStream": "^1.3.5", @@ -6845,9 +6716,10 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -7286,9 +7158,9 @@ "dev": true }, "node_modules/electron": { - "version": "33.2.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-33.2.0.tgz", - "integrity": "sha512-PVw1ICAQDPsnnsmpNFX/b1i/49h67pbSPxuIENd9K9WpGO1tsRaQt+K2bmXqTuoMJsbzIc75Ce8zqtuwBPqawA==", + "version": "33.2.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-33.2.1.tgz", + "integrity": "sha512-SG/nmSsK9Qg1p6wAW+ZfqU+AV8cmXMTIklUL18NnOKfZLlum4ZsDoVdmmmlL39ZmeCaq27dr7CgslRPahfoVJg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7319,6 +7191,13 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "dev": true, + "license": "MIT" + }, "node_modules/emojilib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", @@ -7555,9 +7434,9 @@ } }, "node_modules/es-toolkit": { - "version": "1.26.1", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.26.1.tgz", - "integrity": "sha512-E3H14lHWk8JpupVpIRA1gfNF4r953abHTFW+X1Rp7zl7eG37ksuthfEA4FinyVF/Y807vzzfQS1nubeZk2LTVA==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.29.0.tgz", + "integrity": "sha512-GjTll+E6APcfAQA09D89HdT8Qn2Yb+TeDSDBTMcxAo+V+w1amAtCI15LJu4YPH/UCPoSo/F47Gr1LIM0TE0lZA==", "dev": true, "license": "MIT", "workspaces": [ @@ -7574,9 +7453,9 @@ "optional": true }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", + "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7584,32 +7463,33 @@ "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" } }, "node_modules/escalade": { @@ -7633,32 +7513,32 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", + "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.7.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", - "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.16.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.5", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -7672,8 +7552,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -7902,9 +7781,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.4.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.4.3.tgz", - "integrity": "sha512-uWtwFxGRv6B8sU63HZM5dAGDhgsatb+LONwmILZJhdRALLOkCX2HFZhdL/Kw2ls8SQMAVEfK+LmnEfxInRN8HA==", + "version": "50.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.0.tgz", + "integrity": "sha512-tCNp4fR79Le3dYTPB0dKEv7yFyvGkUCa+Z3yuTrrNGGOxBlXo9Pn0PEgroOZikUQOGjxoGMVKNjrOHcYEdfszg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -7928,13 +7807,13 @@ } }, "node_modules/eslint-plugin-n": { - "version": "17.12.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.12.0.tgz", - "integrity": "sha512-zNAtz/erDn0v78bIY3MASSQlyaarV4IOTvP5ldHsqblRFrXriikB6ghkDTkHjUad+nMRrIbOy9euod2azjRfBg==", + "version": "17.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.14.0.tgz", + "integrity": "sha512-maxPLMEA0rPmRpoOlxEclKng4UpDe+N5BJS4t24I3UKnN109Qcivnfs37KMy84G0af3bxjog5lKctP5ObsvcTA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", + "@eslint-community/eslint-utils": "^4.4.1", "enhanced-resolve": "^5.17.1", "eslint-plugin-es-x": "^7.8.0", "get-tsconfig": "^4.8.1", @@ -7995,12 +7874,19 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "node_modules/eslint/node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", @@ -8627,9 +8513,9 @@ } }, "node_modules/focus-trap": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.0.tgz", - "integrity": "sha512-1td0l3pMkWJLFipobUcGaf+5DTY4PLDDrcqoSaKP8ediO/CoWCCYk/fT/Y2A4e6TNB+Sh6clRJCjOPPnKoNHnQ==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.2.tgz", + "integrity": "sha512-9FhUxK1hVju2+AiQIDJ5Dd//9R2n2RAfJ0qfhF4IHGHgcoEUTMpbTeG/zbEuwaiYXfuAH6XE0/aCyxDdRM+W5w==", "dev": true, "license": "MIT", "dependencies": { @@ -9129,7 +9015,8 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gray-matter": { "version": "4.0.3", @@ -9617,9 +9504,9 @@ } }, "node_modules/husky": { - "version": "9.1.6", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", - "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "license": "MIT", "bin": { @@ -9795,9 +9682,9 @@ } }, "node_modules/ipull": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ipull/-/ipull-3.9.0.tgz", - "integrity": "sha512-s/gZfxkfZKFJxojocTQwqWqtAxVzHKQZ0ivWvIAih3JpPN5mXkIOWzVm4/XKUmQELxan52REe3epRP69gfVQXg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/ipull/-/ipull-3.9.2.tgz", + "integrity": "sha512-YbCDsqcf0ytc3b8304ygBlvRtKJTvyygkQX2xcmPkih6vdVKbRw13pDdtSR+vEqLql3owyuPj9m6iT6IfwFaCg==", "license": "MIT", "dependencies": { "@tinyhttp/content-disposition": "^2.2.0", @@ -10026,6 +9913,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -10168,6 +10056,7 @@ "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", "dev": true, + "license": "MIT", "dependencies": { "text-extensions": "^2.0.0" }, @@ -10437,13 +10326,15 @@ "dev": true, "engines": [ "node >= 0.2.0" - ] + ], + "license": "MIT" }, "node_modules/JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, + "license": "(MIT OR Apache-2.0)", "dependencies": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" @@ -10476,9 +10367,9 @@ } }, "node_modules/less": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", - "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/less/-/less-4.2.1.tgz", + "integrity": "sha512-CasaJidTIhWmjcqv0Uj5vccMI7pJgfD9lMkKtlnTHAdJdYK/7l8pM9tumLyJ0zhbD4KJLo/YvTj+xznQd5NBhg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -11630,10 +11521,11 @@ ] }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -11743,9 +11635,9 @@ } }, "node_modules/minisearch": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.1.0.tgz", - "integrity": "sha512-tv7c/uefWdEhcu6hvrfTihflgeEi2tN6VV7HJnCjK6VxM75QQJh4t9FwJCsA2EsRS8LCnu3W87CuGPWMocOLCA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.1.1.tgz", + "integrity": "sha512-b3YZEYCEH4EdCAtYP7OlDyx7FdPwNzuNwLQ34SfJpM9dlbBZzeXndGavTrC+VCiRWomL21SWfMc6SCKO/U2ZNw==", "dev": true, "license": "MIT" }, @@ -11825,9 +11717,9 @@ } }, "node_modules/nanoid": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz", - "integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz", + "integrity": "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==", "funding": [ { "type": "github", @@ -11880,9 +11772,9 @@ "dev": true }, "node_modules/node-addon-api": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.2.1.tgz", - "integrity": "sha512-vmEOvxwiH8tlOcv4SyE8RH34rI5/nWVaigUeAUPawC6f0+HoDthwI0vkMu4tbtsZrXq6QXFfrkhjofzKEs5tpA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.0.tgz", + "integrity": "sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==", "license": "MIT", "engines": { "node": "^18 || ^20 || >= 21" @@ -14742,17 +14634,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/oniguruma-to-js": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", - "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", + "node_modules/oniguruma-to-es": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-0.7.0.tgz", + "integrity": "sha512-HRaRh09cE0gRS3+wi2zxekB+I5L8C/gN60S+vb11eADHUaB/q4u8wGGOX3GvwvitG8ixaeycZfeoyruKQzUgNg==", "dev": true, "license": "MIT", "dependencies": { - "regex": "^4.3.2" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "emoji-regex-xs": "^1.0.0", + "regex": "^5.0.2", + "regex-recursion": "^4.3.0" } }, "node_modules/optionator": { @@ -14773,9 +14664,9 @@ } }, "node_modules/ora": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.1.0.tgz", - "integrity": "sha512-GQEkNkH/GHOhPFXcqZs3IDahXEQcQxsSjEkK4KvEEST4t7eNzoMjxTzef+EZ+JluDEV+Raoi3WQ2CflnRdSVnQ==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.1.1.tgz", + "integrity": "sha512-YWielGi1XzG1UTvOaCFaNgEnuhZVMSHYkW/FQ7UX8O26PtlpdM84c0f7wLPlkvx2RfiQmnzd61d/MGxmpQeJPw==", "license": "MIT", "dependencies": { "chalk": "^5.3.0", @@ -15139,9 +15030,9 @@ "license": "MIT" }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -15247,9 +15138,9 @@ } }, "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "dev": true, "funding": [ { @@ -15268,7 +15159,7 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.1.0", + "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { @@ -15294,9 +15185,9 @@ } }, "node_modules/preact": { - "version": "10.24.3", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", - "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", + "version": "10.25.0", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.25.0.tgz", + "integrity": "sha512-6bYnzlLxXV3OSpUxLdaxBmE7PMOu0aR3pG6lryK/0jmvcDFPlcXGQAt5DpK3RITWiDrfYZRI0druyaK/S9kYLg==", "dev": true, "license": "MIT", "funding": { @@ -15325,9 +15216,9 @@ } }, "node_modules/pretty-ms": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.1.0.tgz", - "integrity": "sha512-o1piW0n3tgKIKCwk2vpM/vOV13zjJzvP37Ioze54YlTHE06m4tjEbzg9WsKkvTuyYln2DHjo5pY4qrZGI0otpw==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz", + "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==", "license": "MIT", "dependencies": { "parse-ms": "^4.0.0" @@ -15589,11 +15480,31 @@ } }, "node_modules/regex": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", - "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/regex/-/regex-5.0.2.tgz", + "integrity": "sha512-/pczGbKIQgfTMRV0XjABvc5RzLqQmwqxLHdQao2RTXPk+pmTXB2P0IaUHYdYyk412YLwUIkaeMd5T+RzVgTqnQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-4.3.0.tgz", + "integrity": "sha512-5LcLnizwjcQ2ALfOj95MjcatxyqF5RPySx9yT+PaXu3Gox2vyAtLDjHB8NTJLtMGkvyau6nI3CfpwFCjPUIs/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "dev": true, + "license": "MIT" }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", @@ -15984,13 +15895,13 @@ "optional": true }, "node_modules/rollup": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz", - "integrity": "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.0.tgz", + "integrity": "sha512-G9GOrmgWHBma4YfCcX8PjH0qhXSdH8B4HDE2o4/jaxj93S4DPCIDoLcXz99eWMji4hB29UFCEd7B2gwGJDR9cQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -16000,22 +15911,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.2", - "@rollup/rollup-android-arm64": "4.21.2", - "@rollup/rollup-darwin-arm64": "4.21.2", - "@rollup/rollup-darwin-x64": "4.21.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.2", - "@rollup/rollup-linux-arm-musleabihf": "4.21.2", - "@rollup/rollup-linux-arm64-gnu": "4.21.2", - "@rollup/rollup-linux-arm64-musl": "4.21.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.2", - "@rollup/rollup-linux-riscv64-gnu": "4.21.2", - "@rollup/rollup-linux-s390x-gnu": "4.21.2", - "@rollup/rollup-linux-x64-gnu": "4.21.2", - "@rollup/rollup-linux-x64-musl": "4.21.2", - "@rollup/rollup-win32-arm64-msvc": "4.21.2", - "@rollup/rollup-win32-ia32-msvc": "4.21.2", - "@rollup/rollup-win32-x64-msvc": "4.21.2", + "@rollup/rollup-android-arm-eabi": "4.28.0", + "@rollup/rollup-android-arm64": "4.28.0", + "@rollup/rollup-darwin-arm64": "4.28.0", + "@rollup/rollup-darwin-x64": "4.28.0", + "@rollup/rollup-freebsd-arm64": "4.28.0", + "@rollup/rollup-freebsd-x64": "4.28.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.28.0", + "@rollup/rollup-linux-arm-musleabihf": "4.28.0", + "@rollup/rollup-linux-arm64-gnu": "4.28.0", + "@rollup/rollup-linux-arm64-musl": "4.28.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.28.0", + "@rollup/rollup-linux-riscv64-gnu": "4.28.0", + "@rollup/rollup-linux-s390x-gnu": "4.28.0", + "@rollup/rollup-linux-x64-gnu": "4.28.0", + "@rollup/rollup-linux-x64-musl": "4.28.0", + "@rollup/rollup-win32-arm64-msvc": "4.28.0", + "@rollup/rollup-win32-ia32-msvc": "4.28.0", + "@rollup/rollup-win32-x64-msvc": "4.28.0", "fsevents": "~2.3.2" } }, @@ -16112,9 +16025,9 @@ "license": "ISC" }, "node_modules/search-insights": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.2.tgz", - "integrity": "sha512-zFNpOpUO+tY2D85KrxJ+aqwnIfdEGi06UH2+xEb+Bp9Mwznmauqc9djbnBibJO5mpfUPPa8st6Sx65+vbeO45g==", + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", + "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", "dev": true, "license": "MIT", "peer": true @@ -16519,16 +16432,16 @@ } }, "node_modules/shiki": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.2.tgz", - "integrity": "sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.24.0.tgz", + "integrity": "sha512-qIneep7QRwxRd5oiHb8jaRzH15V/S8F3saCXOdjwRLgozZJr5x2yeBhQtqkO3FSzQDwYEFAYuifg4oHjpDghrg==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/core": "1.22.2", - "@shikijs/engine-javascript": "1.22.2", - "@shikijs/engine-oniguruma": "1.22.2", - "@shikijs/types": "1.22.2", + "@shikijs/core": "1.24.0", + "@shikijs/engine-javascript": "1.24.0", + "@shikijs/engine-oniguruma": "1.24.0", + "@shikijs/types": "1.24.0", "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4" } @@ -16860,9 +16773,9 @@ "license": "MIT" }, "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", + "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", "dev": true, "license": "MIT" }, @@ -16870,6 +16783,7 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "license": "MIT", "engines": { "node": ">=18" }, @@ -17465,6 +17379,7 @@ "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -17472,12 +17387,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -17503,7 +17412,8 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/through2": { "version": "2.0.5", @@ -17623,9 +17533,9 @@ } }, "node_modules/tinypool": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", - "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", "dev": true, "license": "MIT", "engines": { @@ -17723,9 +17633,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", "dev": true, "license": "MIT", "engines": { @@ -17748,9 +17658,9 @@ } }, "node_modules/tslib": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", - "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD" }, @@ -17913,17 +17823,17 @@ } }, "node_modules/typedoc": { - "version": "0.26.10", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.10.tgz", - "integrity": "sha512-xLmVKJ8S21t+JeuQLNueebEuTVphx6IrP06CdV7+0WVflUSW3SPmR+h1fnWVdAR/FQePEgsSWCUHXqKKjzuUAw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.27.2.tgz", + "integrity": "sha512-C2ima5TZJHU3ecnRIz50lKd1BsYck5LhYQIy7MRPmjuSEJreUEAt+uAVcZgY7wZsSORzEI7xW8miZIdxv/cbmw==", "dev": true, "license": "Apache-2.0", "dependencies": { + "@gerrit0/mini-shiki": "^1.24.0", "lunr": "^2.3.9", "markdown-it": "^14.1.0", "minimatch": "^9.0.5", - "shiki": "^1.16.2", - "yaml": "^2.5.1" + "yaml": "^2.6.1" }, "bin": { "typedoc": "bin/typedoc" @@ -17932,46 +17842,46 @@ "node": ">= 18" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" + "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x" } }, "node_modules/typedoc-plugin-markdown": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.2.9.tgz", - "integrity": "sha512-Wqmx+7ezKFgtTklEq/iUhQ5uFeBDhAT6wiS2na9cFLidIpl9jpDHJy/COYh8jUZXgIRIZVQ/bPNjyrnPFoDwzg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.3.1.tgz", + "integrity": "sha512-cV0cjvNfr5keytkWUm5AXNFcW3/dd51BYFvbAVqo9AJbHZjt5SGkf2EZ0whSKCilqpwL7biPC/r1WNeW2NbV/w==", "dev": true, "license": "MIT", "engines": { "node": ">= 18" }, "peerDependencies": { - "typedoc": "0.26.x" + "typedoc": "0.27.x" } }, "node_modules/typedoc-plugin-mdn-links": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/typedoc-plugin-mdn-links/-/typedoc-plugin-mdn-links-3.3.5.tgz", - "integrity": "sha512-EsOmQ23eBYqFFEkjo/prud/h2O2QIPQwdVvpyocwn3SWWFCP1YfuTCs94/dDQG6Ikte7gik88ic7Md8fDvEmtw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/typedoc-plugin-mdn-links/-/typedoc-plugin-mdn-links-4.0.3.tgz", + "integrity": "sha512-q18V8nXF4MqMBGABPVodfxmU2VLK+C7RpyKgrEGP1oP3MAdavLM8Hmeh7zUJAZ4ky+zotO5ZXfhgChegmaDWug==", "dev": true, "license": "MIT", "peerDependencies": { - "typedoc": ">= 0.23.14 || 0.24.x || 0.25.x || 0.26.x" + "typedoc": "0.26.x || 0.27.x" } }, "node_modules/typedoc-vitepress-theme": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typedoc-vitepress-theme/-/typedoc-vitepress-theme-1.0.2.tgz", - "integrity": "sha512-6RUW4FBsGolOU3M92F7qz9ILKjL0oq8aHyQ5Q39tIpzapimJ2qX+ChLqzcBP7/aAtEoPYezIivjjZN9oZ4Ghvg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/typedoc-vitepress-theme/-/typedoc-vitepress-theme-1.1.0.tgz", + "integrity": "sha512-EpNpJHiXmh2AUcjSdZtK1MO9Bc2uW3iZg+EL+K7xSOS7+ruwPukaYRMpxR0FM+SkisjAA4VWNA3qdT6AKLx12A==", "dev": true, "license": "MIT", "peerDependencies": { - "typedoc-plugin-markdown": ">=4.1.0" + "typedoc-plugin-markdown": ">=4.3.0" } }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -17983,15 +17893,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.12.2.tgz", - "integrity": "sha512-UbuVUWSrHVR03q9CWx+JDHeO6B/Hr9p4U5lRH++5tq/EbFq1faYZe50ZSBePptgfIKLEti0aPQ3hFgnPVcd8ZQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.16.0.tgz", + "integrity": "sha512-wDkVmlY6O2do4V+lZd0GtRfbtXbeD0q9WygwXXSJnC1xorE8eqyC2L1tJimqpSeFrOzRlYtWnUp/uzgHQOgfBQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.12.2", - "@typescript-eslint/parser": "8.12.2", - "@typescript-eslint/utils": "8.12.2" + "@typescript-eslint/eslint-plugin": "8.16.0", + "@typescript-eslint/parser": "8.16.0", + "@typescript-eslint/utils": "8.16.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -18000,6 +17910,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -18294,21 +18207,21 @@ } }, "node_modules/vite": { - "version": "5.4.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", - "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.1.tgz", + "integrity": "sha512-Ldn6gorLGr4mCdFnmeAOLweJxZ34HjKnDm4HGo6P66IEqTxQb36VEdFJQENKxWjupNfoIjvRUnswjn1hpYEpjQ==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "esbuild": "^0.24.0", + "postcss": "^8.4.49", + "rollup": "^4.23.0" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -18317,19 +18230,25 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", - "terser": "^5.4.0" + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, + "jiti": { + "optional": true + }, "less": { "optional": true }, @@ -18350,40 +18269,48 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, "node_modules/vite-node": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.4.tgz", - "integrity": "sha512-kqa9v+oi4HwkG6g8ufRnb5AeplcRw8jUF6/7/Qz1qRQOXHImG8YnLbB+LLszENwFnoBl9xIf9nVdCFzNd7GQEg==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.6.tgz", + "integrity": "sha512-DBfJY0n9JUwnyLxPSSUmEePT21j8JZp/sR9n+/gBwQU6DcQOioPdb8/pibWfXForbirSagZCilseYIwaL3f95A==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", - "vite": "^5.0.0" + "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/vitepress": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.4.2.tgz", - "integrity": "sha512-10v92Lqx0N4r7YC3cQLBvu+gRS2rHviE7vgdKiwlupUGfSWkyiQDqYccxM5iPStDGSi1Brnec1lf+lmhaQcZXw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.5.0.tgz", + "integrity": "sha512-q4Q/G2zjvynvizdB3/bupdYkCJe2umSAMv9Ju4d92E6/NXJ59z70xB0q5p/4lpRyAwflDsbwy1mLV9Q5+nlB+g==", "dev": true, "license": "MIT", "dependencies": { "@docsearch/css": "^3.6.2", "@docsearch/js": "^3.6.2", + "@iconify-json/simple-icons": "^1.2.10", "@shikijs/core": "^1.22.2", "@shikijs/transformers": "^1.22.2", "@shikijs/types": "^1.22.2", @@ -18416,48 +18343,538 @@ } } }, + "node_modules/vitepress/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/vitepress/node_modules/vite": { + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, "node_modules/vitest": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.4.tgz", - "integrity": "sha512-eDjxbVAJw1UJJCHr5xr/xM86Zx+YxIEXGAR+bmnEID7z9qWfoxpHw0zdobz+TQAFOLT+nEXz3+gx6nUJ7RgmlQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.6.tgz", + "integrity": "sha512-isUCkvPL30J4c5O5hgONeFRsDmlw6kzFEdLQHLezmDdKQHy8Ke/B/dgdTMEgU0vm+iZ0TjW8GuK83DiahBoKWQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "2.1.4", - "@vitest/mocker": "2.1.4", - "@vitest/pretty-format": "^2.1.4", - "@vitest/runner": "2.1.4", - "@vitest/snapshot": "2.1.4", - "@vitest/spy": "2.1.4", - "@vitest/utils": "2.1.4", + "@vitest/expect": "2.1.6", + "@vitest/mocker": "2.1.6", + "@vitest/pretty-format": "^2.1.6", + "@vitest/runner": "2.1.6", + "@vitest/snapshot": "2.1.6", + "@vitest/spy": "2.1.6", + "@vitest/utils": "2.1.6", "chai": "^5.1.2", "debug": "^4.3.7", "expect-type": "^1.1.0", "magic-string": "^0.30.12", "pathe": "^1.1.2", - "std-env": "^3.7.0", + "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.1", "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.4", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "2.1.6", "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.4", - "@vitest/ui": "2.1.4", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "2.1.6", + "@vitest/ui": "2.1.6", "happy-dom": "*", "jsdom": "*" }, @@ -18483,17 +18900,17 @@ } }, "node_modules/vue": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.12.tgz", - "integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz", + "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.12", - "@vue/compiler-sfc": "3.5.12", - "@vue/runtime-dom": "3.5.12", - "@vue/server-renderer": "3.5.12", - "@vue/shared": "3.5.12" + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-sfc": "3.5.13", + "@vue/runtime-dom": "3.5.13", + "@vue/server-renderer": "3.5.13", + "@vue/shared": "3.5.13" }, "peerDependencies": { "typescript": "*" @@ -18795,9 +19212,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", "dev": true, "license": "ISC", "bin": { @@ -18879,9 +19296,9 @@ } }, "node_modules/zx": { - "version": "8.1.9", - "resolved": "https://registry.npmjs.org/zx/-/zx-8.1.9.tgz", - "integrity": "sha512-UHuLHphHmsBYKkAchkSrEN4nzDyagafqC9HUxtc1J7eopaScW6H9dsLJ1lmkAntnLtDTGoM8fa+jrJrXiIfKFA==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/zx/-/zx-8.2.4.tgz", + "integrity": "sha512-g9wVU+5+M+zVen/3IyAZfsZFmeqb6vDfjqFggakviz5uLK7OAejOirX+jeTOkyvAh/OYRlCgw+SdqzN7F61QVQ==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 372e7778..3ac48033 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,10 @@ "batching", "gpu" ], - "author": "Gilad S.", + "author": { + "name": "Gilad S.", + "url": "https://github.com/giladgd" + }, "license": "MIT", "preferUnplugged": true, "bugs": { @@ -124,53 +127,53 @@ }, "homepage": "https://node-llama-cpp.withcat.ai", "devDependencies": { - "@commitlint/cli": "^19.5.0", - "@commitlint/config-conventional": "^19.5.0", - "@eslint/compat": "^1.2.2", + "@commitlint/cli": "^19.6.0", + "@commitlint/config-conventional": "^19.6.0", + "@eslint/compat": "^1.2.3", "@fontsource/inter": "^5.1.0", - "@nolebase/vitepress-plugin-git-changelog": "^2.6.1", - "@nolebase/vitepress-plugin-og-image": "^2.6.1", + "@nolebase/vitepress-plugin-git-changelog": "^2.11.1", + "@nolebase/vitepress-plugin-og-image": "^2.11.1", "@resvg/resvg-js": "^2.6.2", "@semantic-release/exec": "^6.0.3", - "@semantic-release/github": "11.0.0", + "@semantic-release/github": "11.0.1", "@semantic-release/npm": "12.0.1", - "@shikijs/vitepress-twoslash": "^1.22.2", - "@stylistic/eslint-plugin": "^2.9.0", + "@shikijs/vitepress-twoslash": "^1.24.0", + "@stylistic/eslint-plugin": "^2.11.0", "@types/async-retry": "^1.4.9", "@types/bytes": "^3.1.4", "@types/cross-spawn": "^6.0.2", "@types/fs-extra": "^11.0.4", - "@types/node": "^22.8.4", + "@types/node": "^22.10.1", "@types/proper-lockfile": "^4.1.4", "@types/semver": "^7.5.8", "@types/validate-npm-package-name": "^4.0.2", "@types/which": "^3.0.4", "@types/yargs": "^17.0.33", - "@vitest/coverage-v8": "^2.1.4", - "@vitest/ui": "^2.1.4", - "electron": "^33.2.0", - "eslint": "^9.13.0", + "@vitest/coverage-v8": "^2.1.6", + "@vitest/ui": "^2.1.6", + "electron": "^33.2.1", + "eslint": "^9.16.0", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsdoc": "^50.4.3", - "eslint-plugin-n": "^17.12.0", + "eslint-plugin-jsdoc": "^50.6.0", + "eslint-plugin-n": "^17.14.0", "feed": "^4.2.2", - "husky": "^9.1.6", + "husky": "^9.1.7", "rehype": "^13.0.1", "rimraf": "^6.0.1", "semantic-release": "^24.2.0", "sharp": "^0.33.5", - "tslib": "^2.8.0", - "typedoc": "^0.26.10", - "typedoc-plugin-markdown": "^4.2.9", - "typedoc-plugin-mdn-links": "^3.3.5", - "typedoc-vitepress-theme": "^1.0.2", - "typescript": "^5.6.3", - "typescript-eslint": "^8.12.2", - "vite-node": "^2.1.4", - "vitepress": "^1.4.2", - "vitest": "^2.1.4", - "zx": "^8.1.9" + "tslib": "^2.8.1", + "typedoc": "^0.27.2", + "typedoc-plugin-markdown": "^4.3.1", + "typedoc-plugin-mdn-links": "^4.0.3", + "typedoc-vitepress-theme": "^1.1.0", + "typescript": "^5.7.2", + "typescript-eslint": "^8.16.0", + "vite-node": "^2.1.6", + "vitepress": "^1.5.0", + "vitest": "^2.1.6", + "zx": "^8.2.4" }, "dependencies": { "@huggingface/jinja": "^0.3.2", @@ -180,20 +183,20 @@ "chmodrp": "^1.0.2", "cmake-js": "^7.3.0", "cross-env": "^7.0.3", - "cross-spawn": "^7.0.3", + "cross-spawn": "^7.0.6", "env-var": "^7.5.0", "filenamify": "^6.0.0", "fs-extra": "^11.2.0", "ignore": "^5.3.2", - "ipull": "^3.9.0", + "ipull": "^3.9.2", "is-unicode-supported": "^2.1.0", "lifecycle-utils": "^1.7.0", "log-symbols": "^7.0.0", - "nanoid": "^5.0.8", - "node-addon-api": "^8.2.1", + "nanoid": "^5.0.9", + "node-addon-api": "^8.3.0", "octokit": "^4.0.2", - "ora": "^8.1.0", - "pretty-ms": "^9.1.0", + "ora": "^8.1.1", + "pretty-ms": "^9.2.0", "proper-lockfile": "^4.1.2", "semver": "^7.6.3", "simple-git": "^3.27.0", diff --git a/src/bindings/AddonTypes.ts b/src/bindings/AddonTypes.ts index 75b7de29..9bbf70f9 100644 --- a/src/bindings/AddonTypes.ts +++ b/src/bindings/AddonTypes.ts @@ -140,8 +140,8 @@ export type BatchLogitIndex = number & { __batchLogitIndex: never }; -export type AddonGrammar = "AddonGrammar" & { - __brand: never +export type AddonGrammar = { + isTextCompatible(testText: string): boolean }; export type AddonGrammarEvaluationState = "AddonGrammarEvaluationState" & { diff --git a/src/bindings/Llama.ts b/src/bindings/Llama.ts index bff6f34b..e48143fe 100644 --- a/src/bindings/Llama.ts +++ b/src/bindings/Llama.ts @@ -331,7 +331,7 @@ export class Llama { }); } - public async createGrammarForJsonSchema>(schema: T) { + public async createGrammarForJsonSchema(schema: Readonly) { return new LlamaJsonSchemaGrammar(this, schema); } diff --git a/src/evaluator/LlamaChatSession/LlamaChatSession.ts b/src/evaluator/LlamaChatSession/LlamaChatSession.ts index f66e9cc0..3e5842de 100644 --- a/src/evaluator/LlamaChatSession/LlamaChatSession.ts +++ b/src/evaluator/LlamaChatSession/LlamaChatSession.ts @@ -554,7 +554,7 @@ export class LlamaChatSession { `The model tried to call function "${functionCall.functionName}" which is not defined` ); - const functionCallResult = await functionDefinition.handler(functionCall.params); + const functionCallResult = await functionDefinition.handler(functionCall.params as any); return { functionCall, diff --git a/src/evaluator/LlamaChatSession/utils/defineChatSessionFunction.ts b/src/evaluator/LlamaChatSession/utils/defineChatSessionFunction.ts index 0289a503..17319b02 100644 --- a/src/evaluator/LlamaChatSession/utils/defineChatSessionFunction.ts +++ b/src/evaluator/LlamaChatSession/utils/defineChatSessionFunction.ts @@ -15,7 +15,7 @@ export function defineChatSessionFunction, handler: (params: GbnfJsonSchemaToType) => Promise | any }): ChatSessionModelFunction { return { diff --git a/src/evaluator/LlamaGrammar.ts b/src/evaluator/LlamaGrammar.ts index ab591b66..6ed7be20 100644 --- a/src/evaluator/LlamaGrammar.ts +++ b/src/evaluator/LlamaGrammar.ts @@ -71,6 +71,14 @@ export class LlamaGrammar { return this._trimWhitespaceSuffix; } + /** + * Test if the given text is compatible with the grammar. + * @internal + */ + public _testText(text: string): boolean { + return this._grammar.isTextCompatible(String(text)); + } + public static async getFor(llama: Llama, type: "json" | "json_arr" | "list" | "c" | "arithmetic" | "japanese" | "chess") { const grammarsFolder = await getGrammarsFolder(llama.buildType); diff --git a/src/evaluator/LlamaJsonSchemaGrammar.ts b/src/evaluator/LlamaJsonSchemaGrammar.ts index ac16fd4d..d34b8c63 100644 --- a/src/evaluator/LlamaJsonSchemaGrammar.ts +++ b/src/evaluator/LlamaJsonSchemaGrammar.ts @@ -5,13 +5,13 @@ import {LlamaText} from "../utils/LlamaText.js"; import {Llama} from "../bindings/Llama.js"; import {LlamaGrammar} from "./LlamaGrammar.js"; -export class LlamaJsonSchemaGrammar> extends LlamaGrammar { +export class LlamaJsonSchemaGrammar extends LlamaGrammar { private readonly _schema: T; /** * Prefer to create a new instance of this class by using `llama.createGrammarForJsonSchema(...)`. */ - public constructor(llama: Llama, schema: T) { + public constructor(llama: Llama, schema: Readonly) { const grammar = getGbnfGrammarForGbnfJsonSchema(schema); super(llama, { @@ -23,6 +23,10 @@ export class LlamaJsonSchemaGrammar> ex this._schema = schema; } + public get schema(): Readonly { + return this._schema; + } + public parse(json: string): GbnfJsonSchemaToType { const parsedJson = JSON.parse(json); diff --git a/src/index.ts b/src/index.ts index 2f0f30ec..c8277571 100644 --- a/src/index.ts +++ b/src/index.ts @@ -88,8 +88,9 @@ import { type ChatWrapperGenerateInitialHistoryOptions } from "./types.js"; import { - type GbnfJsonArraySchema, type GbnfJsonBasicSchema, type GbnfJsonConstSchema, type GbnfJsonEnumSchema, type GbnfJsonObjectSchema, - type GbnfJsonOneOfSchema, type GbnfJsonSchema, type GbnfJsonSchemaImmutableType, type GbnfJsonSchemaToType + type GbnfJsonArraySchema, type GbnfJsonBasicSchema, type GbnfJsonConstSchema, type GbnfJsonEnumSchema, type GbnfJsonStringSchema, + type GbnfJsonBasicStringSchema, type GbnfJsonFormatStringSchema, type GbnfJsonObjectSchema, type GbnfJsonOneOfSchema, + type GbnfJsonSchema, type GbnfJsonSchemaImmutableType, type GbnfJsonSchemaToType } from "./utils/gbnfJson/types.js"; import {type GgufFileInfo} from "./gguf/types/GgufFileInfoTypes.js"; import { @@ -239,6 +240,9 @@ export { type GbnfJsonBasicSchema, type GbnfJsonConstSchema, type GbnfJsonEnumSchema, + type GbnfJsonBasicStringSchema, + type GbnfJsonFormatStringSchema, + type GbnfJsonStringSchema, type GbnfJsonOneOfSchema, type GbnfJsonObjectSchema, type GbnfJsonArraySchema, diff --git a/src/types.ts b/src/types.ts index f90dc9e0..7ad51fbe 100644 --- a/src/types.ts +++ b/src/types.ts @@ -141,7 +141,7 @@ export type ChatModelFunctionCall = { export type ChatModelFunctions = { readonly [name: string]: { readonly description?: string, - readonly params?: GbnfJsonSchema | undefined | null + readonly params?: Readonly | undefined | null } }; @@ -151,7 +151,7 @@ export type ChatSessionModelFunctions = { export type ChatSessionModelFunction = { readonly description?: string, - readonly params?: Params, + readonly params?: Readonly, readonly handler: (params: GbnfJsonSchemaToType) => any }; diff --git a/src/utils/gbnfJson/GbnfGrammarGenerator.ts b/src/utils/gbnfJson/GbnfGrammarGenerator.ts index fa853ef3..272a3ed3 100644 --- a/src/utils/gbnfJson/GbnfGrammarGenerator.ts +++ b/src/utils/gbnfJson/GbnfGrammarGenerator.ts @@ -1,6 +1,9 @@ export class GbnfGrammarGenerator { public rules = new Map(); + public ruleContentToRuleName = new Map(); + public literalValueRuleNames = new Map(); private ruleId: number = 0; + private valueRuleId: number = 0; public generateRuleName() { const ruleId = this.ruleId; @@ -9,6 +12,19 @@ export class GbnfGrammarGenerator { return `rule${ruleId}`; } + public generateRuleNameForLiteralValue(value: string | number) { + const existingRuleName = this.literalValueRuleNames.get(value); + if (existingRuleName != null) + return existingRuleName; + + const ruleName = `val${this.valueRuleId}`; + this.valueRuleId++; + + this.literalValueRuleNames.set(value, ruleName); + + return ruleName; + } + public generateGbnfFile(rootGrammar: string) { const rules: {name: string, grammar: string}[] = [{ name: "root", @@ -30,4 +46,8 @@ export class GbnfGrammarGenerator { return gbnf; } + + public getProposedLiteralValueRuleNameLength() { + return `val${this.valueRuleId}`.length; + } } diff --git a/src/utils/gbnfJson/GbnfTerminal.ts b/src/utils/gbnfJson/GbnfTerminal.ts index be08e765..b8e83fe5 100644 --- a/src/utils/gbnfJson/GbnfTerminal.ts +++ b/src/utils/gbnfJson/GbnfTerminal.ts @@ -4,11 +4,16 @@ import {GbnfGrammarGenerator} from "./GbnfGrammarGenerator.js"; export abstract class GbnfTerminal { private _ruleName: string | null = null; + /** To be used only by `getRuleName` */ + protected generateRuleName(grammarGenerator: GbnfGrammarGenerator): string { + return grammarGenerator.generateRuleName(); + } + protected getRuleName(grammarGenerator: GbnfGrammarGenerator): string { if (this._ruleName != null) return this._ruleName; - const ruleName = grammarGenerator.generateRuleName(); + const ruleName = this.generateRuleName(grammarGenerator); this._ruleName = ruleName; return ruleName; @@ -16,12 +21,35 @@ export abstract class GbnfTerminal { public abstract getGrammar(grammarGenerator: GbnfGrammarGenerator): string; + protected getGrammarFromResolve(grammarGenerator: GbnfGrammarGenerator): string { + return this.getGrammar(grammarGenerator); + } + public resolve(grammarGenerator: GbnfGrammarGenerator): string { + if (this._ruleName != null) + return this._ruleName; + + const grammar = this.getGrammarFromResolve(grammarGenerator); + + const existingRuleName = grammarGenerator.ruleContentToRuleName.get(grammar); + if (existingRuleName != null) { + this._ruleName = existingRuleName; + return existingRuleName; + } + const ruleName = this.getRuleName(grammarGenerator); - if (!grammarGenerator.rules.has(ruleName)) - grammarGenerator.rules.set(ruleName, this.getGrammar(grammarGenerator)); + if (grammar === ruleName) { + this._ruleName = ruleName; + return ruleName; + } + if (!grammarGenerator.rules.has(ruleName)) { + grammarGenerator.rules.set(ruleName, grammar); + grammarGenerator.ruleContentToRuleName.set(grammar, ruleName); + } + + this._ruleName = ruleName; return ruleName; } } diff --git a/src/utils/gbnfJson/getGbnfGrammarForGbnfJsonSchema.ts b/src/utils/gbnfJson/getGbnfGrammarForGbnfJsonSchema.ts index 86b0d35f..1c8619c9 100644 --- a/src/utils/gbnfJson/getGbnfGrammarForGbnfJsonSchema.ts +++ b/src/utils/gbnfJson/getGbnfGrammarForGbnfJsonSchema.ts @@ -4,7 +4,7 @@ import {GbnfGrammarGenerator} from "./GbnfGrammarGenerator.js"; import {GbnfJsonScopeState} from "./utils/GbnfJsonScopeState.js"; -export function getGbnfGrammarForGbnfJsonSchema(schema: GbnfJsonSchema, { +export function getGbnfGrammarForGbnfJsonSchema(schema: Readonly, { allowNewLines = true, scopePadSpaces = 4 }: { diff --git a/src/utils/gbnfJson/terminals/GbnfAnyJson.ts b/src/utils/gbnfJson/terminals/GbnfAnyJson.ts new file mode 100644 index 00000000..6dcee429 --- /dev/null +++ b/src/utils/gbnfJson/terminals/GbnfAnyJson.ts @@ -0,0 +1,63 @@ +import {GbnfTerminal} from "../GbnfTerminal.js"; +import {GbnfGrammarGenerator} from "../GbnfGrammarGenerator.js"; +import {GbnfJsonScopeState} from "../utils/GbnfJsonScopeState.js"; +import {GbnfString} from "./GbnfString.js"; +import {GbnfOr} from "./GbnfOr.js"; +import {GbnfNumber} from "./GbnfNumber.js"; +import {GbnfBoolean} from "./GbnfBoolean.js"; +import {GbnfNull} from "./GbnfNull.js"; +import {GbnfArray} from "./GbnfArray.js"; +import {reservedRuleNames} from "./gbnfConsts.js"; +import {GbnfObjectMap} from "./GbnfObjectMap.js"; + + +export class GbnfAnyJson extends GbnfTerminal { + public readonly scopeState: GbnfJsonScopeState; + + public constructor(scopeState: GbnfJsonScopeState = new GbnfJsonScopeState()) { + super(); + + this.scopeState = scopeState; + } + + public getGrammar(grammarGenerator: GbnfGrammarGenerator): string { + const subAnyJsonScopeItem = this.scopeState.settings.allowNewLines + ? new GbnfAnyJson( + new GbnfJsonScopeState({ + allowNewLines: false, + scopePadSpaces: this.scopeState.settings.scopePadSpaces + }, this.scopeState.currentNestingScope) + ) + : new GbnfSubAnyJson(this.scopeState); + + return new GbnfOr([ + new GbnfString(), + new GbnfNumber({allowFractional: true}), + new GbnfBoolean(), + new GbnfNull(), + new GbnfArray({ + items: subAnyJsonScopeItem, + scopeState: this.scopeState + }), + new GbnfObjectMap({ + fields: [], + additionalProperties: subAnyJsonScopeItem, + scopeState: this.scopeState + }) + ]).getGrammar(grammarGenerator); + } + + protected override getRuleName(): string { + return reservedRuleNames.anyJson({ + allowNewLines: this.scopeState.settings.allowNewLines, + scopeSpaces: this.scopeState.settings.scopePadSpaces, + nestingScope: this.scopeState.currentNestingScope + }); + } +} + +class GbnfSubAnyJson extends GbnfAnyJson { + public override getGrammar(): string { + return this.getRuleName(); + } +} diff --git a/src/utils/gbnfJson/terminals/GbnfArray.ts b/src/utils/gbnfJson/terminals/GbnfArray.ts index be5701bc..1d36f33c 100644 --- a/src/utils/gbnfJson/terminals/GbnfArray.ts +++ b/src/utils/gbnfJson/terminals/GbnfArray.ts @@ -3,39 +3,112 @@ import {GbnfGrammarGenerator} from "../GbnfGrammarGenerator.js"; import {GbnfJsonScopeState} from "../utils/GbnfJsonScopeState.js"; import {GbnfWhitespace} from "./GbnfWhitespace.js"; import {GbnfGrammar} from "./GbnfGrammar.js"; -import {GbnfOr} from "./GbnfOr.js"; +import {GbnfRepetition} from "./GbnfRepetition.js"; +import {GbnfCommaWhitespace} from "./GbnfCommaWhitespace.js"; +import {GbnfAnyJson} from "./GbnfAnyJson.js"; export class GbnfArray extends GbnfTerminal { - public readonly items: GbnfTerminal; + public readonly items?: GbnfTerminal; + public readonly prefixItems?: GbnfTerminal[]; + public readonly minItems: number; + public readonly maxItems?: number; public readonly scopeState: GbnfJsonScopeState; - public constructor(items: GbnfTerminal, scopeState: GbnfJsonScopeState = new GbnfJsonScopeState()) { + public constructor({ + items, prefixItems, minItems = 0, maxItems, + scopeState = new GbnfJsonScopeState() + }: { + items?: GbnfTerminal, prefixItems?: GbnfTerminal[], minItems?: number, maxItems?: number, + scopeState: GbnfJsonScopeState + }) { super(); this.items = items; + this.prefixItems = prefixItems; + this.minItems = Math.floor(minItems); + this.maxItems = maxItems == null ? undefined : Math.floor(maxItems); this.scopeState = scopeState; + + if (this.prefixItems != null && this.minItems < this.prefixItems.length) + this.minItems = this.prefixItems.length; + else if (this.minItems < 0) + this.minItems = 0; + + if (this.maxItems != null && this.maxItems < this.minItems) + this.maxItems = this.minItems; + else if (this.maxItems != null && this.maxItems < 0) + this.maxItems = 0; } public getGrammar(grammarGenerator: GbnfGrammarGenerator): string { + const getWhitespaceRule = (newScope: boolean, newLine: "before" | "after" | false) => ( + newScope + ? new GbnfWhitespace(this.scopeState.getForNewScope(), {newLine}) + : new GbnfWhitespace(this.scopeState, {newLine}) + ); const getWhitespaceRuleName = (newScope: boolean, newLine: "before" | "after" | false) => ( + getWhitespaceRule(newScope, newLine).resolve(grammarGenerator) + ); + + const getCommaWhitespaceRule = (newScope: boolean, newLine: "before" | "after" | false) => ( newScope - ? new GbnfWhitespace(this.scopeState.getForNewScope(), {newLine}).resolve(grammarGenerator) - : new GbnfWhitespace(this.scopeState, {newLine}).resolve(grammarGenerator) + ? new GbnfCommaWhitespace(this.scopeState.getForNewScope(), {newLine}) + : new GbnfCommaWhitespace(this.scopeState, {newLine}) ); - const itemsGrammarRuleName = this.items.resolve(grammarGenerator); + const getCommaWhitespaceRuleName = (newScope: boolean, newLine: "before" | "after" | false) => ( + getCommaWhitespaceRule(newScope, newLine).resolve(grammarGenerator) + ); + + const arrayItemsGrammar: string[] = []; + if (this.prefixItems != null && this.prefixItems.length > 0) { + for (const item of this.prefixItems) { + if (arrayItemsGrammar.length > 0) + arrayItemsGrammar.push(getCommaWhitespaceRuleName(true, "before")); + + arrayItemsGrammar.push(item.resolve(grammarGenerator)); + } + + if (this.minItems > this.prefixItems.length || this.maxItems == null || this.maxItems > this.prefixItems.length) { + const restMinRepetitions = this.minItems - this.prefixItems.length; + const restMaxRepetitions = this.maxItems == null + ? undefined + : this.maxItems - this.prefixItems.length; + + if (arrayItemsGrammar.length > 0) + arrayItemsGrammar.push( + new GbnfRepetition({ + value: new GbnfGrammar([ + getCommaWhitespaceRuleName(true, "before"), + (this.items ?? new GbnfAnyJson()).resolve(grammarGenerator) + ], true), + minRepetitions: restMinRepetitions, + maxRepetitions: restMaxRepetitions + }).getGrammar(grammarGenerator) + ); + else + arrayItemsGrammar.push( + new GbnfRepetition({ + value: this.items ?? new GbnfAnyJson(), + separator: getCommaWhitespaceRule(true, "before"), + minRepetitions: restMinRepetitions, + maxRepetitions: restMaxRepetitions + }).getGrammar(grammarGenerator) + ); + } + } else + arrayItemsGrammar.push( + new GbnfRepetition({ + value: this.items ?? new GbnfAnyJson(), + separator: getCommaWhitespaceRule(true, "before"), + minRepetitions: this.minItems, + maxRepetitions: this.maxItems + }).getGrammar(grammarGenerator) + ); return new GbnfGrammar([ '"["', getWhitespaceRuleName(true, "before"), - new GbnfOr([ - new GbnfGrammar([ - "(", itemsGrammarRuleName, ")", - "(", '","', getWhitespaceRuleName(true, "before"), itemsGrammarRuleName, ")*" - ]), - new GbnfGrammar([ - "(", itemsGrammarRuleName, ")?" - ]) - ]).getGrammar(grammarGenerator), + new GbnfGrammar(arrayItemsGrammar).getGrammar(), getWhitespaceRuleName(false, "before"), '"]"' ]).getGrammar(); } diff --git a/src/utils/gbnfJson/terminals/GbnfBoolean.ts b/src/utils/gbnfJson/terminals/GbnfBoolean.ts index 2e506ebe..9e295b6f 100644 --- a/src/utils/gbnfJson/terminals/GbnfBoolean.ts +++ b/src/utils/gbnfJson/terminals/GbnfBoolean.ts @@ -1,16 +1,25 @@ import {GbnfTerminal} from "../GbnfTerminal.js"; -import {GbnfGrammarGenerator} from "../GbnfGrammarGenerator.js"; -import {GbnfOr} from "./GbnfOr.js"; -import {GbnfGrammar} from "./GbnfGrammar.js"; import {reservedRuleNames} from "./gbnfConsts.js"; export class GbnfBoolean extends GbnfTerminal { - public getGrammar(grammarGenerator: GbnfGrammarGenerator): string { - return new GbnfOr([ - new GbnfGrammar('"true"'), - new GbnfGrammar('"false"') - ]).getGrammar(grammarGenerator); + public getGrammar(): string { + return this._getGrammar(); + } + + protected override getGrammarFromResolve(): string { + return this._getGrammar(false); + } + + private _getGrammar(wrap: boolean = true): string { + const values: string[] = ['"true"', '"false"']; + + if (wrap) + return [ + "(", values.join(" | "), ")" + ].join(" "); + + return values.join(" | "); } protected override getRuleName(): string { diff --git a/src/utils/gbnfJson/terminals/GbnfCommaWhitespace.ts b/src/utils/gbnfJson/terminals/GbnfCommaWhitespace.ts new file mode 100644 index 00000000..e1442179 --- /dev/null +++ b/src/utils/gbnfJson/terminals/GbnfCommaWhitespace.ts @@ -0,0 +1,37 @@ +import {GbnfTerminal} from "../GbnfTerminal.js"; +import {GbnfJsonScopeState} from "../utils/GbnfJsonScopeState.js"; +import {GbnfGrammar} from "./GbnfGrammar.js"; +import {GbnfWhitespace} from "./GbnfWhitespace.js"; +import {reservedRuleNames} from "./gbnfConsts.js"; + + +export class GbnfCommaWhitespace extends GbnfTerminal { + public readonly scopeState: GbnfJsonScopeState; + public readonly newLine: "before" | "after" | false; + + public constructor(scopeState: GbnfJsonScopeState, { + newLine = "before" + }: { + newLine?: "before" | "after" | false + } = {}) { + super(); + this.scopeState = scopeState; + this.newLine = newLine; + } + + public getGrammar(): string { + return new GbnfGrammar([ + '","', new GbnfWhitespace(this.scopeState, {newLine: this.newLine}).getGrammar() + ]).getGrammar(); + } + + protected override getRuleName(): string { + return reservedRuleNames.commaWhitespace({ + newLine: this.scopeState.settings.allowNewLines + ? this.newLine + : false, + scopeSpaces: this.scopeState.settings.scopePadSpaces, + nestingScope: this.scopeState.currentNestingScope + }); + } +} diff --git a/src/utils/gbnfJson/terminals/GbnfFormatString.ts b/src/utils/gbnfJson/terminals/GbnfFormatString.ts new file mode 100644 index 00000000..86e335f6 --- /dev/null +++ b/src/utils/gbnfJson/terminals/GbnfFormatString.ts @@ -0,0 +1,100 @@ +import {GbnfTerminal} from "../GbnfTerminal.js"; +import {GbnfGrammarGenerator} from "../GbnfGrammarGenerator.js"; +import {GbnfJsonFormatStringSchema} from "../types.js"; +import {reservedRuleNames} from "./gbnfConsts.js"; +import {GbnfGrammar} from "./GbnfGrammar.js"; +import {GbnfString} from "./GbnfString.js"; + + +export class GbnfFormatString extends GbnfTerminal { + public readonly format: GbnfJsonFormatStringSchema["format"]; + + public constructor(format: GbnfJsonFormatStringSchema["format"]) { + super(); + + this.format = format; + } + + public getGrammar(grammarGenerator: GbnfGrammarGenerator): string { + const quote = '"\\""'; + if (this.format === "date") + return new GbnfGrammar([ + quote, + this._getDateGrammar(), + quote + ]).getGrammar(); + else if (this.format === "time") { + return new GbnfGrammar([ + quote, + this._getTimeGrammar(), + quote + ]).getGrammar(); + } else if (this.format === "date-time") + return new GbnfGrammar([ + quote, + this._getDateGrammar(), + '"T"', + this._getTimeGrammar(), + quote + ]).getGrammar(); + + return new GbnfString({ + minLength: 0, + maxLength: 0 + }).resolve(grammarGenerator); + } + + protected override getRuleName(): string { + return reservedRuleNames.formatString(this.format); + } + + private _getDateGrammar(): string { + return new GbnfGrammar([ + "[0-9]{4}", + '"-"', + or([ + '"0" [1-9]', + '"1" [012]' + ]), + '"-"', + or([ + '"0" [1-9]', + "[12] [0-9]", + '"3" [01]' + ]) + ]).getGrammar(); + } + + private _getTimeGrammar(): string { + return new GbnfGrammar([ + or([ + "[01] [0-9]", + '"2" [0-3]' + ]), + '":"', + "[0-5] [0-9]", + '":"', + "[0-5] [0-9]", + '( "." [0-9]{3} )?', + or([ + '"Z"', + new GbnfGrammar([ + or([ + '"+"', + '"-"' + ]), + or([ + "[01] [0-9]", + '"2" [0-3]' + ]), + '":"', + "[0-5] [0-9]" + ]).getGrammar() + ]) + ]).getGrammar(); + } +} + +function or(values: string[]) { + return "(" + values.join(" | ") + ")"; +} diff --git a/src/utils/gbnfJson/terminals/GbnfGrammar.ts b/src/utils/gbnfJson/terminals/GbnfGrammar.ts index 43440dd5..0ef1cc93 100644 --- a/src/utils/gbnfJson/terminals/GbnfGrammar.ts +++ b/src/utils/gbnfJson/terminals/GbnfGrammar.ts @@ -1,12 +1,15 @@ import {GbnfTerminal} from "../GbnfTerminal.js"; +import {GbnfGrammarGenerator} from "../GbnfGrammarGenerator.js"; export class GbnfGrammar extends GbnfTerminal { public readonly grammar: string | string[]; + public readonly resolveToRawGrammar: boolean; - public constructor(grammar: string | string[]) { + public constructor(grammar: string | string[], resolveToRawGrammar: boolean = false) { super(); this.grammar = grammar; + this.resolveToRawGrammar = resolveToRawGrammar; } public getGrammar(): string { @@ -17,4 +20,11 @@ export class GbnfGrammar extends GbnfTerminal { return this.grammar; } + + public override resolve(grammarGenerator: GbnfGrammarGenerator): string { + if (this.resolveToRawGrammar) + return this.getGrammar(); + + return super.resolve(grammarGenerator); + } } diff --git a/src/utils/gbnfJson/terminals/GbnfInsideStringChar.ts b/src/utils/gbnfJson/terminals/GbnfInsideStringChar.ts new file mode 100644 index 00000000..d91fbf3a --- /dev/null +++ b/src/utils/gbnfJson/terminals/GbnfInsideStringChar.ts @@ -0,0 +1,27 @@ +import {GbnfTerminal} from "../GbnfTerminal.js"; +import {reservedRuleNames} from "./gbnfConsts.js"; + +export class GbnfInsideStringChar extends GbnfTerminal { + public getGrammar(): string { + return [ + negatedCharacterSet([ + '"', + "\\\\", + "\\x7F", + "\\x00-\\x1F" + ]), + + // escape sequences + '"\\\\" ["\\\\/bfnrt]', + '"\\\\u" [0-9a-fA-F]{4}' + ].join(" | "); + } + + protected override getRuleName(): string { + return reservedRuleNames.stringChar; + } +} + +function negatedCharacterSet(characterDefinitions: string[]) { + return "[^" + characterDefinitions.join("") + "]"; +} diff --git a/src/utils/gbnfJson/terminals/GbnfNumber.ts b/src/utils/gbnfJson/terminals/GbnfNumber.ts index 6b8692dd..15223064 100644 --- a/src/utils/gbnfJson/terminals/GbnfNumber.ts +++ b/src/utils/gbnfJson/terminals/GbnfNumber.ts @@ -11,12 +11,13 @@ export class GbnfNumber extends GbnfTerminal { } public getGrammar(): string { - const numberGrammar = '("-"? ([0-9] | [1-9] [0-9]*))'; + const num = '"-"? ("0" | [1-9] [0-9]{0,15})'; + const exponent = ' ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))?'; if (this.allowFractional) - return numberGrammar + ' ("." [0-9]+)? ([eE] [-+]? [0-9]+)?'; + return num + ' ("." [0-9]{1,16})?' + exponent; - return numberGrammar; + return num + exponent; } protected override getRuleName(): string { diff --git a/src/utils/gbnfJson/terminals/GbnfNumberValue.ts b/src/utils/gbnfJson/terminals/GbnfNumberValue.ts index 3577123a..fc36ea05 100644 --- a/src/utils/gbnfJson/terminals/GbnfNumberValue.ts +++ b/src/utils/gbnfJson/terminals/GbnfNumberValue.ts @@ -1,4 +1,5 @@ import {GbnfTerminal} from "../GbnfTerminal.js"; +import {GbnfGrammarGenerator} from "../GbnfGrammarGenerator.js"; export class GbnfNumberValue extends GbnfTerminal { @@ -13,7 +14,15 @@ export class GbnfNumberValue extends GbnfTerminal { return '"' + JSON.stringify(this.value) + '"'; } - public override resolve(): string { - return this.getGrammar(); + public override resolve(grammarGenerator: GbnfGrammarGenerator): string { + const grammar = this.getGrammar(); + if (grammar.length <= grammarGenerator.getProposedLiteralValueRuleNameLength()) + return grammar; + + return super.resolve(grammarGenerator); + } + + protected override generateRuleName(grammarGenerator: GbnfGrammarGenerator): string { + return grammarGenerator.generateRuleNameForLiteralValue(this.value); } } diff --git a/src/utils/gbnfJson/terminals/GbnfObjectMap.ts b/src/utils/gbnfJson/terminals/GbnfObjectMap.ts index 6dd7d220..283d4f51 100644 --- a/src/utils/gbnfJson/terminals/GbnfObjectMap.ts +++ b/src/utils/gbnfJson/terminals/GbnfObjectMap.ts @@ -5,20 +5,41 @@ import {GbnfString} from "./GbnfString.js"; import {GbnfStringValue} from "./GbnfStringValue.js"; import {GbnfWhitespace} from "./GbnfWhitespace.js"; import {GbnfGrammar} from "./GbnfGrammar.js"; +import {GbnfRepetition} from "./GbnfRepetition.js"; +import {GbnfCommaWhitespace} from "./GbnfCommaWhitespace.js"; export class GbnfObjectMap extends GbnfTerminal { public readonly fields: Array>; + public readonly additionalProperties?: GbnfTerminal; + public readonly minProperties: number; + public readonly maxProperties?: number; public readonly scopeState: GbnfJsonScopeState; - public constructor( + public constructor({ + fields, additionalProperties, minProperties = 0, maxProperties, + scopeState = new GbnfJsonScopeState() + }: { fields: Array>, - scopeState: GbnfJsonScopeState = new GbnfJsonScopeState() - ) { + additionalProperties?: GbnfTerminal, + minProperties?: number, maxProperties?: number, + scopeState?: GbnfJsonScopeState + }) { super(); this.fields = fields; + this.additionalProperties = additionalProperties; + this.minProperties = Math.floor(minProperties); + this.maxProperties = maxProperties == null ? undefined : Math.floor(maxProperties); this.scopeState = scopeState; + + if (this.minProperties < this.fields.length) + this.minProperties = this.fields.length; + + if (this.maxProperties != null && this.maxProperties < this.minProperties) + this.maxProperties = this.minProperties; + else if (this.maxProperties != null && this.maxProperties < 0) + this.maxProperties = 0; } public getGrammar(grammarGenerator: GbnfGrammarGenerator): string { @@ -28,16 +49,76 @@ export class GbnfObjectMap extends GbnfTerminal { : new GbnfWhitespace(this.scopeState, {newLine}).resolve(grammarGenerator) ); + const getCommaWhitespaceRule = (newScope: boolean, newLine: "before" | "after" | false) => ( + newScope + ? new GbnfCommaWhitespace(this.scopeState.getForNewScope(), {newLine}) + : new GbnfCommaWhitespace(this.scopeState, {newLine}) + ); + const getCommaWhitespaceRuleName = (newScope: boolean, newLine: "before" | "after" | false) => ( + getCommaWhitespaceRule(newScope, newLine).resolve(grammarGenerator) + ); + + const objectItemsGrammar: string[] = []; + for (const {key, value} of this.fields) { + if (objectItemsGrammar.length > 0) + objectItemsGrammar.push(getCommaWhitespaceRuleName(true, "before")); + + objectItemsGrammar.push( + new GbnfGrammar([ + key.getGrammar(grammarGenerator), '":"', "[ ]?", value.resolve(grammarGenerator) + ]).getGrammar() + ); + } + + if (this.additionalProperties != null) { + const additionalPropertiesGrammar = new GbnfGrammar([ + new GbnfString().resolve(grammarGenerator), '":"', "[ ]?", this.additionalProperties.resolve(grammarGenerator) + ]); + + if (this.minProperties > this.fields.length) { + if (objectItemsGrammar.length > 0) + objectItemsGrammar.push(getCommaWhitespaceRuleName(true, "before")); + + objectItemsGrammar.push( + new GbnfRepetition({ + value: additionalPropertiesGrammar, + separator: getCommaWhitespaceRule(true, "before"), + minRepetitions: this.minProperties - this.fields.length, + maxRepetitions: this.maxProperties == null + ? undefined + : this.maxProperties - this.fields.length + }).getGrammar(grammarGenerator) + ); + } else if (this.maxProperties == null || this.maxProperties > this.fields.length) { + if (objectItemsGrammar.length === 0) + objectItemsGrammar.push( + new GbnfRepetition({ + value: additionalPropertiesGrammar, + separator: getCommaWhitespaceRule(true, "before"), + maxRepetitions: this.maxProperties == null + ? undefined + : this.maxProperties - this.fields.length + }).getGrammar(grammarGenerator) + ); + else + objectItemsGrammar.push( + new GbnfRepetition({ + value: new GbnfGrammar([ + getCommaWhitespaceRuleName(true, "before"), + additionalPropertiesGrammar.resolve(grammarGenerator) + ], true), + maxRepetitions: this.maxProperties == null + ? undefined + : this.maxProperties - this.fields.length + }).getGrammar(grammarGenerator) + ); + } + } + return new GbnfGrammar([ '"{"', getWhitespaceRuleName(true, "before"), - ...this.fields.map(({key, value}, index) => { - return new GbnfGrammar([ - key.getGrammar(), '":"', "[ ]?", value.resolve(grammarGenerator), - index < this.fields.length - 1 ? '","' : "", - getWhitespaceRuleName(index < this.fields.length - 1, "before") - ]).getGrammar(); - }), - '"}"' + new GbnfGrammar(objectItemsGrammar).getGrammar(), + getWhitespaceRuleName(false, "before"), '"}"' ]).getGrammar(); } } diff --git a/src/utils/gbnfJson/terminals/GbnfOr.ts b/src/utils/gbnfJson/terminals/GbnfOr.ts index 79ada978..d22b93d4 100644 --- a/src/utils/gbnfJson/terminals/GbnfOr.ts +++ b/src/utils/gbnfJson/terminals/GbnfOr.ts @@ -5,15 +5,21 @@ import {grammarNoValue} from "./gbnfConsts.js"; export class GbnfOr extends GbnfTerminal { public readonly values: readonly GbnfTerminal[]; + public readonly useRawGrammar: boolean; - public constructor(values: readonly GbnfTerminal[]) { + public constructor(values: readonly GbnfTerminal[], useRawGrammar: boolean = false) { super(); this.values = values; + this.useRawGrammar = useRawGrammar; } public getGrammar(grammarGenerator: GbnfGrammarGenerator): string { const mappedValues = this.values - .map((v) => v.resolve(grammarGenerator)) + .map((v) => ( + this.useRawGrammar + ? v.getGrammar(grammarGenerator) + : v.resolve(grammarGenerator) + )) .filter((value) => value !== "" && value !== grammarNoValue); if (mappedValues.length === 0) diff --git a/src/utils/gbnfJson/terminals/GbnfRepetition.ts b/src/utils/gbnfJson/terminals/GbnfRepetition.ts index 339e9926..fbdb0cf2 100644 --- a/src/utils/gbnfJson/terminals/GbnfRepetition.ts +++ b/src/utils/gbnfJson/terminals/GbnfRepetition.ts @@ -1,45 +1,103 @@ import {GbnfTerminal} from "../GbnfTerminal.js"; import {GbnfGrammarGenerator} from "../GbnfGrammarGenerator.js"; +import {GbnfGrammar} from "./GbnfGrammar.js"; import {grammarNoValue} from "./gbnfConsts.js"; export class GbnfRepetition extends GbnfTerminal { public readonly value: GbnfTerminal; + public readonly separator?: GbnfTerminal; public readonly minRepetitions: number; public readonly maxRepetitions: number | null; - public constructor(value: GbnfTerminal, minRepetitions: number, maxRepetitions: number | null) { + public constructor({value, separator, minRepetitions = 0, maxRepetitions}: { + value: GbnfTerminal, separator?: GbnfTerminal, minRepetitions?: number, maxRepetitions?: number | null + }) { super(); this.value = value; - this.minRepetitions = minRepetitions; - this.maxRepetitions = maxRepetitions; + this.separator = separator; + this.minRepetitions = Math.floor(minRepetitions); + this.maxRepetitions = maxRepetitions == null ? null : Math.floor(maxRepetitions); + + if (this.minRepetitions < 0) + this.minRepetitions = 0; + + if (this.maxRepetitions != null && this.maxRepetitions < 0) + this.maxRepetitions = 0; + + if (this.maxRepetitions != null && this.maxRepetitions < this.minRepetitions) + this.maxRepetitions = this.minRepetitions; } public getGrammar(grammarGenerator: GbnfGrammarGenerator): string { + if (this.maxRepetitions === 0) + return grammarNoValue; + const resolvedValue = this.value.resolve(grammarGenerator); - let grammarStart = ""; - let grammarEnd = ""; + const resolvedSeparator = this.separator?.resolve(grammarGenerator); - for (let i = 0; i < this.minRepetitions; i++) { - grammarStart += "(" + resolvedValue + " "; - grammarEnd += ")"; - } + if (this.minRepetitions === 0 && this.maxRepetitions == 1) + return new GbnfGrammar(["(", resolvedValue, ")?"]).getGrammar(); + else if (this.minRepetitions === 1 && this.maxRepetitions === 1) + return resolvedValue; + else if (this.minRepetitions === this.maxRepetitions) { + if (resolvedSeparator == null) + return new GbnfGrammar(["(", resolvedValue, "){" + String(this.minRepetitions) + "}"]).getGrammar(); + + if (this.minRepetitions === 2) + return new GbnfGrammar([resolvedValue, resolvedSeparator, resolvedValue]).getGrammar(); - if (this.maxRepetitions === Infinity || this.maxRepetitions == null) { - grammarStart += "(" + resolvedValue + " "; - grammarEnd += ")*"; - } else { - for (let i = this.minRepetitions + 1; i <= this.maxRepetitions; i++) { - grammarStart += "(" + resolvedValue + " "; - grammarEnd += ")?"; - } + return new GbnfGrammar([ + resolvedValue, "(", resolvedSeparator, resolvedValue, "){" + String(this.minRepetitions - 1) + "}" + ]).getGrammar(); + } else if (this.minRepetitions === 0 && this.maxRepetitions == null) { + if (resolvedSeparator == null) + return new GbnfGrammar(["(", resolvedValue, ")*"]).getGrammar(); + + return new GbnfGrammar([ + "(", resolvedValue, "(", resolvedSeparator, resolvedValue, ")*", ")?" + ]).getGrammar(); + } else if (this.minRepetitions === 1 && this.maxRepetitions == null) { + if (resolvedSeparator == null) + return new GbnfGrammar(["(", resolvedValue, ")+"]).getGrammar(); + + return new GbnfGrammar([ + resolvedValue, "(", resolvedSeparator, resolvedValue, ")*" + ]).getGrammar(); + } else if (this.maxRepetitions == null) { + if (resolvedSeparator == null) + return new GbnfGrammar(["(", resolvedValue, "){" + String(this.minRepetitions) + ",}"]).getGrammar(); + + return new GbnfGrammar([ + resolvedValue, "(", resolvedSeparator, resolvedValue, "){" + String(this.minRepetitions - 1) + ",}" + ]).getGrammar(); } - const res = grammarStart + grammarEnd; + if (resolvedSeparator == null) + return new GbnfGrammar(["(", resolvedValue, "){" + String(this.minRepetitions) + "," + String(this.maxRepetitions) + "}"]).getGrammar(); - if (res === "") - return grammarNoValue; + if (this.minRepetitions === 0) { + if (this.maxRepetitions === 2) + return new GbnfGrammar([ + "(", resolvedValue, "(", resolvedSeparator, resolvedValue, ")?", ")?" + ]).getGrammar(); + + return new GbnfGrammar([ + "(", resolvedValue, "(", resolvedSeparator, resolvedValue, "){0," + String(this.maxRepetitions - 1) + "}", ")?" + ]).getGrammar(); + } else if (this.minRepetitions === 1) { + if (this.maxRepetitions === 2) + return new GbnfGrammar([ + resolvedValue, "(", resolvedSeparator, resolvedValue, ")?" + ]).getGrammar(); + + return new GbnfGrammar([ + resolvedValue, "(", resolvedSeparator, resolvedValue, "){0," + String(this.maxRepetitions - 1) + "}" + ]).getGrammar(); + } - return res; + return new GbnfGrammar([ + resolvedValue, "(", resolvedSeparator, resolvedValue, "){" + String(this.minRepetitions - 1) + "," + String(this.maxRepetitions - 1) + "}" + ]).getGrammar(); } } diff --git a/src/utils/gbnfJson/terminals/GbnfString.ts b/src/utils/gbnfJson/terminals/GbnfString.ts index 2a97880a..0ad7c9c3 100644 --- a/src/utils/gbnfJson/terminals/GbnfString.ts +++ b/src/utils/gbnfJson/terminals/GbnfString.ts @@ -1,38 +1,58 @@ import {GbnfTerminal} from "../GbnfTerminal.js"; +import {GbnfGrammarGenerator} from "../GbnfGrammarGenerator.js"; import {reservedRuleNames} from "./gbnfConsts.js"; +import {GbnfRepetition} from "./GbnfRepetition.js"; +import {GbnfInsideStringChar} from "./GbnfInsideStringChar.js"; export class GbnfString extends GbnfTerminal { - public getGrammar(): string { + public readonly minLength: number; + public readonly maxLength?: number; + + public constructor({ + minLength = 0, + maxLength + }: { + minLength?: number, + maxLength?: number + } = {}) { + super(); + + this.minLength = Math.floor(minLength ?? 0); + this.maxLength = maxLength == null ? undefined : Math.floor(maxLength); + + if (this.minLength < 0) + this.minLength = 0; + + if (this.maxLength != null && this.maxLength < this.minLength) + this.maxLength = this.minLength; + } + + public getGrammar(grammarGenerator: GbnfGrammarGenerator): string { + if (this.minLength == 0 && this.maxLength == null) + return [ + '"\\""', + new GbnfInsideStringChar().resolve(grammarGenerator) + "*", + '"\\""' + ].join(" "); + else if (this.minLength == 0 && this.maxLength == 0) + return '"\\"\\""'; + return [ '"\\""', - or([ - negatedCharacterSet([ - '"', - "\\\\", - "\\x7F", - "\\x00-\\x1F" - ]), - - // escape sequences - '"\\\\" ' + or([ - '["\\\\/bfnrt]', - '"u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]' - ]) - ]) + "*", + new GbnfRepetition({ + value: new GbnfInsideStringChar(), + minRepetitions: this.minLength, + maxRepetitions: this.maxLength + }).getGrammar(grammarGenerator), '"\\""' ].join(" "); } protected override getRuleName(): string { - return reservedRuleNames.string; + return reservedRuleNames.string({ + minLength: this.minLength, + maxLength: this.maxLength + }); } } - -function negatedCharacterSet(characterDefinitions: string[]) { - return "[^" + characterDefinitions.join("") + "]"; -} - -function or(definitions: string[]) { - return "(" + definitions.join(" | ") + ")"; -} diff --git a/src/utils/gbnfJson/terminals/GbnfStringValue.ts b/src/utils/gbnfJson/terminals/GbnfStringValue.ts index a7cc24aa..0768722f 100644 --- a/src/utils/gbnfJson/terminals/GbnfStringValue.ts +++ b/src/utils/gbnfJson/terminals/GbnfStringValue.ts @@ -1,4 +1,5 @@ import {GbnfTerminal} from "../GbnfTerminal.js"; +import {GbnfGrammarGenerator} from "../GbnfGrammarGenerator.js"; export class GbnfStringValue extends GbnfTerminal { @@ -14,13 +15,17 @@ export class GbnfStringValue extends GbnfTerminal { '"', '\\"', this.value - .replaceAll("\\", "\\\\") - .replaceAll("\t", "\\t") - .replaceAll("\r", "\\r") - .replaceAll("\n", "\\n") + .replaceAll("\\", "\\\\\\\\") + .replaceAll("\t", "\\\\t") + .replaceAll("\r", "\\\\r") + .replaceAll("\n", "\\\\n") .replaceAll('"', "\\\\" + '\\"'), '\\"', '"' ].join(""); } + + protected override generateRuleName(grammarGenerator: GbnfGrammarGenerator): string { + return grammarGenerator.generateRuleNameForLiteralValue(this.value); + } } diff --git a/src/utils/gbnfJson/terminals/GbnfWhitespace.ts b/src/utils/gbnfJson/terminals/GbnfWhitespace.ts index b11b5909..2c156f82 100644 --- a/src/utils/gbnfJson/terminals/GbnfWhitespace.ts +++ b/src/utils/gbnfJson/terminals/GbnfWhitespace.ts @@ -11,8 +11,7 @@ export class GbnfWhitespace extends GbnfTerminal { public constructor(scopeState: GbnfJsonScopeState, { newLine = "before" }: { - newLine?: "before" | "after" | false, - space?: boolean + newLine?: "before" | "after" | false } = {}) { super(); this.scopeState = scopeState; @@ -20,6 +19,14 @@ export class GbnfWhitespace extends GbnfTerminal { } public getGrammar(): string { + return this._getGrammar(); + } + + protected override getGrammarFromResolve(): string { + return this._getGrammar(false); + } + + private _getGrammar(wrap: boolean = true): string { if (this.scopeState.settings.allowNewLines && this.newLine !== false) { const values = [ ...( @@ -32,12 +39,8 @@ export class GbnfWhitespace extends GbnfTerminal { ? [] : [ or([ - new GbnfVerbatimText( - " ".repeat(this.scopeState.currentNestingScope * this.scopeState.settings.scopePadSpaces) - ).getGrammar(), - new GbnfVerbatimText( - "\t".repeat(this.scopeState.currentNestingScope) - ).getGrammar() + verbatimTextRepetition(" ", this.scopeState.currentNestingScope * this.scopeState.settings.scopePadSpaces), + verbatimTextRepetition("\t", this.scopeState.currentNestingScope) ]) ] ), @@ -51,7 +54,7 @@ export class GbnfWhitespace extends GbnfTerminal { return or([ values.join(" "), "[ ]?" - ]); + ], wrap); } return "[ ]?"; @@ -59,13 +62,31 @@ export class GbnfWhitespace extends GbnfTerminal { protected override getRuleName(): string { return reservedRuleNames.whitespace({ - newLine: this.newLine, + newLine: this.scopeState.settings.allowNewLines + ? this.newLine + : false, scopeSpaces: this.scopeState.settings.scopePadSpaces, nestingScope: this.scopeState.currentNestingScope }); } } -function or(definitions: string[]) { +function or(definitions: string[], wrap: boolean = true) { + if (!wrap) + return definitions.join(" | "); + return "(" + definitions.join(" | ") + ")"; } + +function verbatimTextRepetition(text: string, count: number) { + const textRepetitionGrammar = new GbnfVerbatimText(text.repeat(count)).getGrammar(); + + if (count <= 1) + return textRepetitionGrammar; + + const textRepetitionGrammarWithRepetition = new GbnfVerbatimText(text).getGrammar() + "{" + count + "}"; + if (textRepetitionGrammarWithRepetition.length < textRepetitionGrammar.length) + return textRepetitionGrammarWithRepetition; + + return textRepetitionGrammar; +} diff --git a/src/utils/gbnfJson/terminals/gbnfConsts.ts b/src/utils/gbnfJson/terminals/gbnfConsts.ts index 589b72df..d7c74212 100644 --- a/src/utils/gbnfJson/terminals/gbnfConsts.ts +++ b/src/utils/gbnfJson/terminals/gbnfConsts.ts @@ -6,7 +6,28 @@ export const reservedRuleNames = { fractional: "fractional-number-rule", integer: "integer-number-rule" }, - string: "string-rule", + stringChar: "string-char-rule", + string({minLength, maxLength}: {minLength: number, maxLength?: number}) { + if (minLength === 0 && maxLength == null) + return "string-rule"; + else if (maxLength == null) + return [ + "string-", + minLength, + "-rule" + ].join(""); + + return [ + "string-", + minLength, + "-", + maxLength, + "-rule" + ].join(""); + }, + formatString(format: string) { + return "string-format-" + format + "-rule"; + }, whitespace({newLine, nestingScope, scopeSpaces}: { newLine?: "before" | "after" | false, nestingScope: number, scopeSpaces: number }) { @@ -24,5 +45,36 @@ export const reservedRuleNames = { "-" + scopeSpaces, "-rule" ].join(""); + }, + commaWhitespace({newLine, nestingScope, scopeSpaces}: { + newLine?: "before" | "after" | false, nestingScope: number, scopeSpaces: number + }) { + if (!newLine) + return "comma-whitespace-no-new-lines-rule"; + + return [ + "comma-whitespace-", + newLine === "before" + ? "b" + : newLine === "after" + ? "a" + : "n", + "-" + nestingScope, + "-" + scopeSpaces, + "-rule" + ].join(""); + }, + anyJson({allowNewLines, nestingScope, scopeSpaces}: { + allowNewLines: boolean, nestingScope: number, scopeSpaces: number + }) { + return [ + "any-json-", + !allowNewLines + ? "s-" + : "", + nestingScope, + "-" + scopeSpaces, + "-rule" + ].join(""); } } as const; diff --git a/src/utils/gbnfJson/types.ts b/src/utils/gbnfJson/types.ts index 8e5c11b5..0f6c798a 100644 --- a/src/utils/gbnfJson/types.ts +++ b/src/utils/gbnfJson/types.ts @@ -1,27 +1,153 @@ export type GbnfJsonSchemaImmutableType = "string" | "number" | "integer" | "boolean" | "null"; -export type GbnfJsonSchema = GbnfJsonBasicSchema | GbnfJsonConstSchema | GbnfJsonEnumSchema | GbnfJsonOneOfSchema | GbnfJsonObjectSchema | - GbnfJsonArraySchema; +export type GbnfJsonSchema = GbnfJsonBasicSchema | GbnfJsonConstSchema | GbnfJsonEnumSchema | GbnfJsonOneOfSchema | + GbnfJsonStringSchema | GbnfJsonObjectSchema | GbnfJsonArraySchema; export type GbnfJsonBasicSchema = { - type: GbnfJsonSchemaImmutableType | readonly GbnfJsonSchemaImmutableType[] + readonly type: GbnfJsonSchemaImmutableType | readonly GbnfJsonSchemaImmutableType[], + + /** + * A description of what you expect the model to set this value to. + * + * Only passed to the model when using function calling, and has no effect when using JSON Schema grammar directly. + */ + readonly description?: string }; export type GbnfJsonConstSchema = { - const: string | number | boolean | null + readonly const: string | number | boolean | null, + + /** + * A description of what you expect the model to set this value to. + * + * Only passed to the model when using function calling, and has no effect when using JSON Schema grammar directly. + */ + readonly description?: string }; export type GbnfJsonEnumSchema = { - enum: readonly (string | number | boolean | null)[] + readonly enum: readonly (string | number | boolean | null)[], + + /** + * A description of what you expect the model to set this value to. + * + * Only passed to the model when using function calling, and has no effect when using JSON Schema grammar directly. + */ + readonly description?: string }; export type GbnfJsonOneOfSchema = { - oneOf: readonly GbnfJsonSchema[] + readonly oneOf: readonly GbnfJsonSchema[], + + /** + * A description of what you expect the model to set this value to. + * + * Only passed to the model when using function calling, and has no effect when using JSON Schema grammar directly. + */ + readonly description?: string +}; +export type GbnfJsonStringSchema = GbnfJsonBasicStringSchema | GbnfJsonFormatStringSchema; +export type GbnfJsonBasicStringSchema = { + readonly type: "string", + + /** + * When using `minLength` and/or `maxLength`, + * ensure to inform the model as part of the prompt what your expectations are regarding the length of the string. + * Not doing this may lead to hallucinations. + */ + readonly minLength?: number, + + /** + * When using `minLength` and/or `maxLength`, + * ensure to inform the model as part of the prompt what your expectations are regarding the length of the string. + * Not doing this may lead to hallucinations. + */ + readonly maxLength?: number, + + /** + * A description of what you expect the model to set this value to. + * + * Only passed to the model when using function calling, and has no effect when using JSON Schema grammar directly. + */ + readonly description?: string +}; +export type GbnfJsonFormatStringSchema = { + readonly type: "string", + readonly format: "date-time" | "time" | "date", + + /** + * A description of what you expect the model to set this value to. + * + * Only passed to the model when using function calling, and has no effect when using JSON Schema grammar directly. + */ + readonly description?: string }; export type GbnfJsonObjectSchema = { - type: "object", - properties: Readonly<{[key in Keys]: GbnfJsonSchema}>, - required?: readonly Keys[] + readonly type: "object", + readonly properties?: {readonly [key in Keys]: GbnfJsonSchema}, + + /** + * Unlike the JSON Schema spec, `additionalProperties` defaults to `false` to avoid breaking existing code. + */ + readonly additionalProperties?: boolean | GbnfJsonSchema, + + /** + * Make sure you define `additionalProperties` for this to have any effect. + * + * When using `minProperties` and/or `maxProperties`, + * ensure to inform the model as part of the prompt what your expectations are regarding the number of keys in the object. + * Not doing this may lead to hallucinations. + */ + readonly minProperties?: number, + + /** + * Make sure you define `additionalProperties` for this to have any effect. + * + * When using `minProperties` and/or `maxProperties`, + * ensure to inform the model as part of the prompt what your expectations are regarding the number of keys in the object. + * Not doing this may lead to hallucinations. + */ + readonly maxProperties?: number, + + /** + * `required` is always set to all keys in `properties`, and setting it has no effect. + * + * This limitation is due to how the generation works, and may be fixed in the future. + * + * This key is part of the type to avoid breaking exiting code (though it was never actually used in the past), + * and will be removed in the future. + * @deprecated + */ + readonly required?: readonly Keys[], + + /** + * A description of what you expect the model to set this value to. + * + * Only passed to the model when using function calling, and has no effect when using JSON Schema grammar directly. + */ + readonly description?: string }; export type GbnfJsonArraySchema = { - type: "array", - items: GbnfJsonSchema + readonly type: "array", + readonly items?: GbnfJsonSchema, + readonly prefixItems?: readonly GbnfJsonSchema[], + + /** + * When using `minItems` and/or `maxItems`, + * ensure to inform the model as part of the prompt what your expectations are regarding the length of the array. + * Not doing this may lead to hallucinations. + */ + readonly minItems?: number, + + /** + * When using `minItems` and/or `maxItems`, + * ensure to inform the model as part of the prompt what your expectations are regarding the length of the array. + * Not doing this may lead to hallucinations. + */ + readonly maxItems?: number, + + /** + * A description of what you expect the model to set this value to. + * + * Only passed to the model when using function calling, and has no effect when using JSON Schema grammar directly. + */ + readonly description?: string }; @@ -31,32 +157,41 @@ export type GbnfJsonArraySchema = { export type GbnfJsonSchemaToType = GbnfJsonSchemaToTSType; export type GbnfJsonSchemaToTSType = - GbnfJsonBasicSchema extends T + Readonly extends T ? undefined : undefined extends T ? undefined - : T extends GbnfJsonBasicSchema - ? GbnfJsonBasicSchemaToType - : T extends GbnfJsonConstSchema - ? T["const"] - : T extends GbnfJsonEnumSchema - ? T["enum"][number] - : T extends GbnfJsonOneOfSchema - ? GbnfJsonSchemaToType - : T extends GbnfJsonObjectSchema - ? GbnfJsonObjectSchemaToType - : T extends GbnfJsonArraySchema - ? GbnfJsonSchemaToType[] - : undefined; - -type GbnfJsonBasicSchemaToType = + : T extends GbnfJsonBasicStringSchema + ? GbnfJsonBasicStringSchemaToType + : T extends GbnfJsonFormatStringSchema + ? string + : T extends GbnfJsonBasicSchema + ? GbnfJsonBasicSchemaToType + : T extends GbnfJsonConstSchema + ? T["const"] + : T extends GbnfJsonEnumSchema + ? T["enum"][number] + : T extends GbnfJsonOneOfSchema + ? GbnfJsonSchemaToType + : T extends GbnfJsonObjectSchema + ? GbnfJsonObjectSchemaToType + : T extends GbnfJsonArraySchema + ? ArrayTypeToType + : undefined; + +type GbnfJsonBasicStringSchemaToType = + T["maxLength"] extends 0 + ? "" + : string; + +type GbnfJsonBasicSchemaToType = T extends GbnfJsonSchemaImmutableType ? ImmutableTypeToType : T extends GbnfJsonSchemaImmutableType[] ? ImmutableTypeToType : never; -type ImmutableTypeToType = +type ImmutableTypeToType = T extends "string" ? string : T extends "number" @@ -69,10 +204,107 @@ type ImmutableTypeToType = ? null : never; -type GbnfJsonObjectSchemaToType = { - [P in keyof Props]: GbnfJsonSchemaToType -}; +type ArrayTypeToType< + T extends GbnfJsonArraySchema, + MinItems extends number = T["minItems"] extends number + ? T["prefixItems"] extends readonly GbnfJsonSchema[] + ? keyof T["prefixItems"] extends T["minItems"] + ? T["prefixItems"]["length"] + : T["minItems"] + : T["minItems"] + : T["prefixItems"] extends readonly GbnfJsonSchema[] + ? T["prefixItems"]["length"] + : 0 +> = + T["prefixItems"] extends readonly GbnfJsonSchema[] + ? ( + MinItems extends T["prefixItems"]["length"] + ? ( + T["maxItems"] extends MinItems + ? [ + ...GbnfJsonOrderedArrayTypes, + ...IndexRangeWithSkip< + MinItems, + T["prefixItems"]["length"], + T["items"] extends GbnfJsonSchema + ? GbnfJsonSchemaToType + : GbnfJsonAnyValue + > + ] + : [ + ...GbnfJsonOrderedArrayTypes, + ...( + T["items"] extends GbnfJsonSchema + ? GbnfJsonSchemaToType + : GbnfJsonAnyValue + )[] + ] + ) + : T["maxItems"] extends MinItems + ? [ + ...GbnfJsonOrderedArrayTypes, + ...( + T["items"] extends GbnfJsonSchema + ? IndexRangeWithSkip> + : IndexRangeWithSkip + ) + ] + : [ + ...GbnfJsonOrderedArrayTypes, + ...IndexRangeWithSkip< + MinItems, + T["prefixItems"]["length"], + T["items"] extends GbnfJsonSchema + ? GbnfJsonSchemaToType + : GbnfJsonAnyValue + >, + ...( + T["items"] extends GbnfJsonSchema + ? GbnfJsonSchemaToType + : GbnfJsonAnyValue + )[] + ] + ) + : T["items"] extends GbnfJsonSchema + ? ( + MinItems extends 0 + ? GbnfJsonSchemaToType[] + : T["maxItems"] extends MinItems + ? IndexRange> + : [ + ...IndexRange>, + ...GbnfJsonSchemaToType[] + ] + ) + : ( + MinItems extends 0 + ? GbnfJsonAnyValue[] + : T["maxItems"] extends MinItems + ? IndexRange + : [ + ...IndexRange, + ...GbnfJsonAnyValue[] + ] + ); + +type GbnfJsonObjectSchemaToType< + T extends GbnfJsonObjectSchema, + Props extends Readonly> | undefined = T["properties"], + AdditionalProps extends true | false | GbnfJsonSchema | undefined = T["additionalProperties"], + PropsMap = Props extends undefined + ? {} + : {-readonly [P in keyof Props]: GbnfJsonSchemaToType}, + Res = AdditionalProps extends undefined | false + ? PropsMap + : AdditionalProps extends true + ? PropsMap & {[key: string]: GbnfJsonAnyValue} + : AdditionalProps extends GbnfJsonSchema + ? PropsMap & {[key: string]: GbnfJsonSchemaToType} + : PropsMap +> = Res; + +type GbnfJsonAnyValue = string | number | boolean | null | GbnfJsonAnyValue[] | {[key: string]: GbnfJsonAnyValue}; export function isGbnfJsonConstSchema(schema: GbnfJsonSchema): schema is GbnfJsonConstSchema { return (schema as GbnfJsonConstSchema).const !== undefined; @@ -86,6 +318,14 @@ export function isGbnfJsonOneOfSchema(schema: GbnfJsonSchema): schema is GbnfJso return (schema as GbnfJsonOneOfSchema).oneOf != null; } +export function isGbnfJsonBasicStringSchema(schema: GbnfJsonSchema): schema is GbnfJsonBasicStringSchema { + return (schema as GbnfJsonBasicStringSchema).type === "string" && (schema as GbnfJsonFormatStringSchema).format == null; +} + +export function isGbnfJsonFormatStringSchema(schema: GbnfJsonSchema): schema is GbnfJsonFormatStringSchema { + return (schema as GbnfJsonFormatStringSchema).type === "string" && (schema as GbnfJsonFormatStringSchema).format != null; +} + export function isGbnfJsonObjectSchema(schema: GbnfJsonSchema): schema is GbnfJsonObjectSchema { return (schema as GbnfJsonObjectSchema).type === "object"; } @@ -102,3 +342,35 @@ export function isGbnfJsonBasicSchemaIncludesType +> = Res; +type _IndexRange< + Value extends FillType[], + MaxLength extends number, + FillType = number +> = Value["length"] extends MaxLength + ? Value + : _IndexRange<[...Value, FillType], MaxLength, FillType>; + +type IndexRangeWithSkip< + Length extends number, + SkipFirst extends number, + FillType, + Res = _IndexRangeWithSkip<[], IndexRange, Length, FillType> +> = Res; +type _IndexRangeWithSkip< + Value extends FillType[], + ConditionValue extends number[], + MaxLength extends number, + FillType +> = ConditionValue["length"] extends MaxLength + ? Value + : _IndexRangeWithSkip<[...Value, FillType], [...ConditionValue, ConditionValue["length"]], MaxLength, FillType>; + +type GbnfJsonOrderedArrayTypes = { + -readonly [P in keyof T]: GbnfJsonSchemaToType +}; diff --git a/src/utils/gbnfJson/utils/getGbnfJsonTerminalForGbnfJsonSchema.ts b/src/utils/gbnfJson/utils/getGbnfJsonTerminalForGbnfJsonSchema.ts index 45ee6a79..7777da11 100644 --- a/src/utils/gbnfJson/utils/getGbnfJsonTerminalForGbnfJsonSchema.ts +++ b/src/utils/gbnfJson/utils/getGbnfJsonTerminalForGbnfJsonSchema.ts @@ -10,8 +10,11 @@ import {GbnfNull} from "../terminals/GbnfNull.js"; import {GbnfGrammarGenerator} from "../GbnfGrammarGenerator.js"; import { GbnfJsonSchema, isGbnfJsonArraySchema, isGbnfJsonBasicSchemaIncludesType, isGbnfJsonConstSchema, isGbnfJsonEnumSchema, - isGbnfJsonObjectSchema, isGbnfJsonOneOfSchema + isGbnfJsonObjectSchema, isGbnfJsonOneOfSchema, isGbnfJsonBasicStringSchema, isGbnfJsonFormatStringSchema } from "../types.js"; +import {getConsoleLogPrefix} from "../../getConsoleLogPrefix.js"; +import {GbnfAnyJson} from "../terminals/GbnfAnyJson.js"; +import {GbnfFormatString} from "../terminals/GbnfFormatString.js"; import {getGbnfJsonTerminalForLiteral} from "./getGbnfJsonTerminalForLiteral.js"; import {GbnfJsonScopeState} from "./GbnfJsonScopeState.js"; @@ -29,19 +32,78 @@ export function getGbnfJsonTerminalForGbnfJsonSchema( } else if (isGbnfJsonEnumSchema(schema)) { return new GbnfOr(schema.enum.map((item) => getGbnfJsonTerminalForLiteral(item))); } else if (isGbnfJsonObjectSchema(schema)) { - return new GbnfObjectMap( - Object.entries(schema.properties).map(([propName, propSchema]) => { + const propertiesEntries = Object.entries(schema.properties ?? {}); + + let maxProperties = schema.maxProperties; + if (schema.properties != null && maxProperties != null && maxProperties < propertiesEntries.length) { + console.warn( + getConsoleLogPrefix(true, false), + `maxProperties (${maxProperties}) must be greater than or equal to ` + + `properties object keys number (${propertiesEntries.length}). ` + + "Using properties object keys number as maxProperties." + ); + maxProperties = propertiesEntries.length; + } + + return new GbnfObjectMap({ + fields: propertiesEntries.map(([propName, propSchema]) => { return { required: true, key: new GbnfStringValue(propName), value: getGbnfJsonTerminalForGbnfJsonSchema(propSchema, grammarGenerator, scopeState.getForNewScope()) }; }), + additionalProperties: (schema.additionalProperties == null || schema.additionalProperties === false) + ? undefined + : schema.additionalProperties === true + ? new GbnfAnyJson(scopeState.getForNewScope()) + : getGbnfJsonTerminalForGbnfJsonSchema(schema.additionalProperties, grammarGenerator, scopeState.getForNewScope()), + minProperties: schema.minProperties, + maxProperties, scopeState - ); + }); } else if (isGbnfJsonArraySchema(schema)) { - return new GbnfArray(getGbnfJsonTerminalForGbnfJsonSchema(schema.items, grammarGenerator, scopeState), scopeState); - } + let maxItems = schema.maxItems; + if (schema.prefixItems != null && maxItems != null && maxItems < schema.prefixItems.length) { + console.warn( + getConsoleLogPrefix(true, false), + `maxItems (${maxItems}) must be greater than or equal to prefixItems array length (${schema.prefixItems.length}). ` + + "Using prefixItems length as maxItems." + ); + maxItems = schema.prefixItems.length; + } + + return new GbnfArray({ + items: schema.items == null + ? undefined + : getGbnfJsonTerminalForGbnfJsonSchema(schema.items, grammarGenerator, scopeState.getForNewScope()), + prefixItems: schema.prefixItems == null + ? undefined + : schema.prefixItems.map((item) => ( + getGbnfJsonTerminalForGbnfJsonSchema(item, grammarGenerator, scopeState.getForNewScope()) + )), + minItems: schema.minItems, + maxItems, + scopeState + }); + } else if (isGbnfJsonBasicStringSchema(schema)) { + const minLength = Math.max(0, schema.minLength ?? 0); + let maxLength = schema.maxLength; + if (maxLength != null && maxLength < minLength) { + console.warn( + getConsoleLogPrefix(true, false), + `maxLength (${maxLength}) must be greater than or equal to minLength (${minLength}). ` + + "Using minLength as maxLength." + ); + maxLength = minLength; + } + + return new GbnfString({ + minLength, + maxLength + }); + } else if (isGbnfJsonFormatStringSchema(schema)) + return new GbnfFormatString(schema.format); const terminals: GbnfTerminal[] = []; diff --git a/src/utils/gbnfJson/utils/validateObjectAgainstGbnfSchema.ts b/src/utils/gbnfJson/utils/validateObjectAgainstGbnfSchema.ts index 62398ae6..69d13f0f 100644 --- a/src/utils/gbnfJson/utils/validateObjectAgainstGbnfSchema.ts +++ b/src/utils/gbnfJson/utils/validateObjectAgainstGbnfSchema.ts @@ -1,7 +1,8 @@ import { GbnfJsonArraySchema, GbnfJsonConstSchema, GbnfJsonEnumSchema, GbnfJsonObjectSchema, GbnfJsonOneOfSchema, GbnfJsonSchema, - GbnfJsonSchemaImmutableType, GbnfJsonSchemaToType, isGbnfJsonArraySchema, isGbnfJsonConstSchema, isGbnfJsonEnumSchema, - isGbnfJsonObjectSchema, isGbnfJsonOneOfSchema + GbnfJsonSchemaImmutableType, GbnfJsonSchemaToType, GbnfJsonBasicStringSchema, GbnfJsonFormatStringSchema, isGbnfJsonArraySchema, + isGbnfJsonConstSchema, isGbnfJsonEnumSchema, isGbnfJsonObjectSchema, isGbnfJsonOneOfSchema, isGbnfJsonBasicStringSchema, + isGbnfJsonFormatStringSchema } from "../types.js"; @@ -43,6 +44,10 @@ function validateObjectWithGbnfSchema(object: any, sch return validateObject(object, schema); else if (isGbnfJsonOneOfSchema(schema)) return validateOneOf(object, schema); + else if (isGbnfJsonBasicStringSchema(schema)) + return validateBasicString(object, schema); + else if (isGbnfJsonFormatStringSchema(schema)) + return validateFormatString(object, schema); else if (isGbnfJsonEnumSchema(schema)) return validateEnum(object, schema); else if (isGbnfJsonConstSchema(schema)) @@ -62,16 +67,44 @@ function validateObjectWithGbnfSchema(object: any, sch if (validateImmutableType(object, schema.type)) return true; - throw new TechnicalValidationError(`Expected "${schema.type}" but got "${object === null ? "null" : typeof object}"`); + throw new TechnicalValidationError(`Expected type "${schema.type}" but got "${object === null ? "null" : typeof object}"`); } function validateArray(object: any, schema: T): object is GbnfJsonSchemaToType { if (!(object instanceof Array)) throw new TechnicalValidationError(`Expected an array but got "${typeof object}"`); + const minItems = Math.max(schema.minItems ?? 0, schema.prefixItems?.length ?? 0); + const maxItems = schema.maxItems == null + ? undefined + : Math.max(schema.maxItems, minItems); + + if (object.length < minItems) { + if (maxItems != null && minItems === maxItems) + throw new TechnicalValidationError(`Expected exactly ${minItems} items but got ${object.length}`); + + throw new TechnicalValidationError(`Expected at least ${minItems} items but got ${object.length}`); + } else if (maxItems != null && object.length > maxItems) { + if (minItems === maxItems) + throw new TechnicalValidationError(`Expected exactly ${minItems} items but got ${object.length}`); + + throw new TechnicalValidationError(`Expected at most ${maxItems} items but got ${object.length}`); + } + let res = true; - for (const item of object) - res &&= validateObjectWithGbnfSchema(item, schema.items); + let index = 0; + + if (schema.prefixItems != null) { + for (const item of schema.prefixItems) { + res &&= validateObjectWithGbnfSchema(object[index], item); + index++; + } + } + + if (schema.items != null) { + for (; index < object.length; index++) + res &&= validateObjectWithGbnfSchema(object[index], schema.items); + } return res; } @@ -80,22 +113,48 @@ function validateObject(object: any, schema: T): if (typeof object !== "object" || object === null) throw new TechnicalValidationError(`Expected an object but got "${typeof object}"`); + let res = true; + const objectKeys = Object.keys(object); const objectKeysSet = new Set(objectKeys); - const schemaKeys = Object.keys(schema.properties); + const schemaKeys = Object.keys(schema.properties ?? {}); const schemaKeysSet = new Set(schemaKeys); + const minProperties = Math.max(schema.minProperties ?? 0, schemaKeys.length); + const maxProperties = schema.maxProperties == null + ? undefined + : Math.max(schema.maxProperties, minProperties); + const extraKeys = objectKeys.filter((key) => !schemaKeysSet.has(key)); - if (extraKeys.length > 0) - throw new TechnicalValidationError(`Unexpected keys: ${extraKeys.map((key) => JSON.stringify(key)).join(", ")}`); + if (extraKeys.length > 0) { + if (schema.additionalProperties == null || schema.additionalProperties === false) + throw new TechnicalValidationError(`Unexpected keys: ${extraKeys.map((key) => JSON.stringify(key)).join(", ")}`); + else if (schema.additionalProperties !== true) { + for (const key of extraKeys) + res &&= validateObjectWithGbnfSchema(object[key], schema.additionalProperties); + } + } const missingKeys = schemaKeys.filter((key) => !objectKeysSet.has(key)); if (missingKeys.length > 0) throw new TechnicalValidationError(`Missing keys: ${missingKeys.map((key) => JSON.stringify(key)).join(", ")}`); - let res = true; for (const key of schemaKeys) - res &&= validateObjectWithGbnfSchema(object[key], schema.properties[key]!); + res &&= validateObjectWithGbnfSchema(object[key], schema.properties![key]!); + + if (schema.additionalProperties != null && schema.additionalProperties !== false) { + if (objectKeys.length < minProperties) { + if (maxProperties != null && minProperties === maxProperties) + throw new TechnicalValidationError(`Expected exactly ${minProperties} properties but got ${objectKeys.length}`); + + throw new TechnicalValidationError(`Expected at least ${minProperties} properties but got ${objectKeys.length}`); + } else if (maxProperties != null && objectKeys.length > maxProperties) { + if (minProperties === maxProperties) + throw new TechnicalValidationError(`Expected exactly ${minProperties} properties but got ${objectKeys.length}`); + + throw new TechnicalValidationError(`Expected at most ${maxProperties} properties but got ${objectKeys.length}`); + } + } return res; } @@ -115,6 +174,59 @@ function validateOneOf(object: any, schema: T): o throw new TechnicalValidationError(`Expected one of ${schema.oneOf.length} schemas but got ${JSON.stringify(object)}`); } +function validateBasicString(object: any, schema: T): object is GbnfJsonSchemaToType { + if (typeof object !== "string") + throw new TechnicalValidationError(`Expected type "${schema.type}" but got "${object === null ? "null" : typeof object}"`); + + const minLength = Math.max(0, schema.minLength ?? 0); + const maxLength = schema.maxLength == null + ? undefined + : Math.max(schema.maxLength, minLength); + + if (object.length < minLength) { + if (minLength === maxLength) + throw new TechnicalValidationError(`Expected exactly ${minLength} characters but got ${object.length}`); + + throw new TechnicalValidationError(`Expected at least ${minLength} characters but got ${object.length}`); + } else if (maxLength != null && object.length > maxLength) { + if (minLength === maxLength) + throw new TechnicalValidationError(`Expected exactly ${minLength} characters but got ${object.length}`); + + throw new TechnicalValidationError(`Expected at most ${maxLength} characters but got ${object.length}`); + } + + return true; +} + +const dateRegex = /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])$/; +const timeRegex = /^([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d{3})?(Z|[+-]([01][0-9]|2[0-3])?:[0-5][0-9])$/; +const datetimeRegex = + /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d{3})?(Z|[+-]([01][0-9]|2[0-3])?:[0-5][0-9])$/; + +function validateFormatString(object: any, schema: T): object is GbnfJsonSchemaToType { + if (typeof object !== "string") + throw new TechnicalValidationError(`Expected type "${schema.type}" but got "${object === null ? "null" : typeof object}"`); + + if (schema.format === "date") { + if (object.match(dateRegex) != null) + return true; + + throw new TechnicalValidationError(`Expected a valid date string but got ${JSON.stringify(object)}`); + } else if (schema.format === "time") { + if (object.match(timeRegex) != null) + return true; + + throw new TechnicalValidationError(`Expected a valid time string but got ${JSON.stringify(object)}`); + } else if (schema.format === "date-time") { + if (object.match(datetimeRegex) != null) + return true; + + throw new TechnicalValidationError(`Expected a valid date-time string but got ${JSON.stringify(object)}`); + } + + throw new TechnicalValidationError(`Unknown format "${schema.format}"`); +} + function validateEnum(object: any, schema: T): object is GbnfJsonSchemaToType { for (const value of schema.enum) { if (object === value) diff --git a/src/utils/getTypeScriptTypeStringForGbnfJsonSchema.ts b/src/utils/getTypeScriptTypeStringForGbnfJsonSchema.ts index f7858b00..aac2043f 100644 --- a/src/utils/getTypeScriptTypeStringForGbnfJsonSchema.ts +++ b/src/utils/getTypeScriptTypeStringForGbnfJsonSchema.ts @@ -1,8 +1,10 @@ import { - GbnfJsonSchema, isGbnfJsonArraySchema, isGbnfJsonBasicSchemaIncludesType, isGbnfJsonConstSchema, - isGbnfJsonEnumSchema, isGbnfJsonObjectSchema, isGbnfJsonOneOfSchema + GbnfJsonSchema, isGbnfJsonArraySchema, isGbnfJsonBasicSchemaIncludesType, isGbnfJsonBasicStringSchema, isGbnfJsonConstSchema, + isGbnfJsonEnumSchema, isGbnfJsonFormatStringSchema, isGbnfJsonObjectSchema, isGbnfJsonOneOfSchema } from "./gbnfJson/types.js"; +const maxTypeRepetition = 10; + export function getTypeScriptTypeStringForGbnfJsonSchema(schema: GbnfJsonSchema): string { if (isGbnfJsonOneOfSchema(schema)) { const values = schema.oneOf @@ -17,30 +19,148 @@ export function getTypeScriptTypeStringForGbnfJsonSchema(schema: GbnfJsonSchema) .filter((item) => item !== "") .join(" | "); } else if (isGbnfJsonObjectSchema(schema)) { - return [ + let addNewline = false; + const valueTypes = Object.entries(schema.properties ?? {}) + .map(([propName, propSchema]) => { + const escapedValue = JSON.stringify(propName) ?? ""; + const keyText = escapedValue.slice(1, -1) === propName ? propName : escapedValue; + const valueType = getTypeScriptTypeStringForGbnfJsonSchema(propSchema); + + if (keyText === "" || valueType === "") + return ""; + + const mapping = keyText + ": " + valueType; + + const description: string[] = (propSchema.description != null && propSchema.description !== "") + ? [propSchema.description] + : []; + const propInfo: string[] = []; + + if (isGbnfJsonBasicStringSchema(propSchema)) { + if (propSchema.minLength != null && propSchema.minLength > 0) + propInfo.push("minimum length: " + String(Math.floor(propSchema.minLength))); + + if (propSchema.maxLength != null) + propInfo.push("maximum length: " + String(Math.floor(Math.max(propSchema.maxLength, propSchema.minLength ?? 0, 0)))); + } else if (isGbnfJsonFormatStringSchema(propSchema)) { + if (propSchema.format === "date-time") + propInfo.push("format: ISO 8601 date-time"); + else + propInfo.push("format: " + String(propSchema.format)); + } else if (isGbnfJsonArraySchema(propSchema)) { + if (propSchema.minItems != null && propSchema.minItems > maxTypeRepetition) + propInfo.push("minimum items: " + String(Math.floor(propSchema.minItems))); + + if (propSchema.maxItems != null) + propInfo.push("maximum items: " + String(Math.floor(Math.max(propSchema.maxItems, propSchema.minItems ?? 0, 0)))); + } else if (isGbnfJsonObjectSchema(propSchema)) { + if (propSchema.minProperties != null && propSchema.minProperties > 0) + propInfo.push("minimum number of properties: " + String(Math.floor(propSchema.minProperties))); + + if (propSchema.maxProperties != null) + propInfo.push( + "maximum number of properties: " + + String(Math.floor(Math.max(propSchema.maxProperties, propSchema.minProperties ?? 0, 0))) + ); + } + + if (propInfo.length > 0) + description.push(propInfo.join(", ")); + + if (description.length > 0) { + addNewline = true; + return [ + "\n", + "// ", description + .join("\n") + .split("\n") + .join("\n// "), + "\n", + mapping + ].join(""); + } + + return mapping; + }) + .filter((item) => item !== ""); + + const knownPropertiesMapSyntax = [ "{", - Object.entries(schema.properties) - .map(([propName, propSchema]) => { - const escapedValue = JSON.stringify(propName) ?? ""; - const keyText = escapedValue.slice(1, -1) === propName ? propName : escapedValue; - const valueType = getTypeScriptTypeStringForGbnfJsonSchema(propSchema); - - if (keyText === "" || valueType === "") - return ""; - - return keyText + ": " + valueType; - }) - .filter((item) => item !== "") - .join(", "), + (addNewline && valueTypes.length > 0) + ? [ + "\n ", + valueTypes + .map((value) => value.split("\n").join("\n ")) + .join(",\n ") + .trimStart(), + "\n" + ].join("") + : valueTypes.join(", "), "}" ].join(""); - } else if (isGbnfJsonArraySchema(schema)) { - const valuesType = getTypeScriptTypeStringForGbnfJsonSchema(schema.items); + const additionalPropertiesMapSyntax = (schema.additionalProperties == null || schema.additionalProperties == false) + ? undefined + : schema.additionalProperties === true + ? "{[key: string]: any}" + : schema.additionalProperties != null + ? ["{[key: string]: ", getTypeScriptTypeStringForGbnfJsonSchema(schema.additionalProperties), "}"].join("") + : undefined; - if (valuesType === "") + if (valueTypes.length === 0 && additionalPropertiesMapSyntax != null) + return additionalPropertiesMapSyntax; + else if (additionalPropertiesMapSyntax != null) + return [knownPropertiesMapSyntax, " & ", additionalPropertiesMapSyntax].join(""); + + return knownPropertiesMapSyntax; + } else if (isGbnfJsonArraySchema(schema)) { + if (schema.maxItems === 0) return "[]"; - return "(" + valuesType + ")[]"; + if (schema.prefixItems != null && schema.prefixItems.length > 0) { + const valueTypes = schema.prefixItems.map((item) => getTypeScriptTypeStringForGbnfJsonSchema(item)); + + const restType = schema.items != null + ? getTypeScriptTypeStringForGbnfJsonSchema(schema.items) + : "any"; + + if (schema.minItems != null) { + for (let i = schema.prefixItems.length; i < Math.min(schema.prefixItems.length + maxTypeRepetition, schema.minItems); i++) + valueTypes.push(restType); + } + + if (schema.maxItems == null || schema.maxItems > valueTypes.length) + valueTypes.push("..." + wrapWithParensIfNeeded(restType) + "[]"); + + return "[" + valueTypes.join(", ") + "]"; + } else if (schema.items != null) { + const valuesType = getTypeScriptTypeStringForGbnfJsonSchema(schema.items); + + if (valuesType === "") + return "[]"; + + if (schema.minItems != null) { + if (schema.minItems === schema.maxItems) { + if (schema.minItems < maxTypeRepetition) + return "[" + (valuesType + ", ").repeat(schema.minItems).slice(0, -", ".length) + "]"; + else + return [ + "[", + (valuesType + ", ").repeat(maxTypeRepetition), + "...", wrapWithParensIfNeeded(valuesType), "[]", + "]" + ].join(""); + } else if (schema.minItems <= 0) + return wrapWithParensIfNeeded(valuesType) + "[]"; + else if (schema.minItems < maxTypeRepetition) + return "[" + (valuesType + ", ").repeat(schema.minItems) + "..." + wrapWithParensIfNeeded(valuesType) + "[]]"; + else + return wrapWithParensIfNeeded(valuesType) + "[]"; + } + + return wrapWithParensIfNeeded(valuesType) + "[]"; + } + + return "any[]"; } const types: ("string" | "number" | "bigint" | "boolean" | "null")[] = []; @@ -62,3 +182,10 @@ export function getTypeScriptTypeStringForGbnfJsonSchema(schema: GbnfJsonSchema) return types.join(" | "); } + +function wrapWithParensIfNeeded(text: string): string { + if (text.includes(" ") || text.includes("|") || text.includes("&") || text.includes("\n") || text.includes("\t")) + return "(" + text + ")"; + + return text; +} diff --git a/templates/electron-typescript-react/README.md b/templates/electron-typescript-react/README.md index 11a2f5fe..1ee7da63 100644 --- a/templates/electron-typescript-react/README.md +++ b/templates/electron-typescript-react/README.md @@ -11,3 +11,5 @@ Start the project: ```bash npm start ``` + +> Generated using `npm create node-llama-cpp@latest` ([learn more](https://node-llama-cpp.withcat.ai/guide/)) diff --git a/templates/electron-typescript-react/eslint.config.js b/templates/electron-typescript-react/eslint.config.js index fb278cbf..becfe23a 100644 --- a/templates/electron-typescript-react/eslint.config.js +++ b/templates/electron-typescript-react/eslint.config.js @@ -70,7 +70,7 @@ export default tseslint.config({ after: true }], "@stylistic/comma-style": ["error", "last"], - "@stylistic/comma-dangle": ["error", "never"], + "@stylistic/comma-dangle": ["warn", "never"], "no-var": ["error"], "import/order": ["error", { groups: ["builtin", "external", "internal", "parent", "sibling", "index", "type", "object", "unknown"], @@ -119,7 +119,8 @@ export default tseslint.config({ {blankLine: "always", prev: "*", next: "method"} ] }], - "@stylistic/no-trailing-spaces": ["warn"] + "@stylistic/no-trailing-spaces": ["warn"], + "@stylistic/no-multi-spaces": ["warn"] } }, { files: ["**/**.{ts,tsx}"], diff --git a/templates/electron-typescript-react/package.json b/templates/electron-typescript-react/package.json index 113b8f63..0c7c5999 100644 --- a/templates/electron-typescript-react/package.json +++ b/templates/electron-typescript-react/package.json @@ -33,27 +33,27 @@ "semver": "^7.6.3" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.10.0", + "@stylistic/eslint-plugin": "^2.11.0", "@types/markdown-it": "^14.1.2", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@types/semver": "^7.5.8", - "@vitejs/plugin-react": "^4.3.3", - "electron": "^33.0.2", + "@vitejs/plugin-react": "^4.3.4", + "electron": "^33.2.1", "electron-builder": "^25.1.8", - "eslint": "^9.13.0", + "eslint": "^9.16.0", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsdoc": "^50.4.3", + "eslint-plugin-jsdoc": "^50.6.0", "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.14", "rimraf": "^6.0.1", - "typescript": "^5.6.3", - "typescript-eslint": "^8.12.2", - "vite": "^5.4.10", - "vite-plugin-electron": "^0.28.8", + "typescript": "^5.7.2", + "typescript-eslint": "^8.16.0", + "vite": "^6.0.1", + "vite-plugin-electron": "^0.29.0", "vite-plugin-electron-renderer": "^0.14.6", - "zx": "^8.1.9" + "zx": "^8.2.4" }, "overrides": { "electron-builder": { diff --git a/templates/node-typescript/README.md b/templates/node-typescript/README.md index 457a8292..e2aee47b 100644 --- a/templates/node-typescript/README.md +++ b/templates/node-typescript/README.md @@ -11,3 +11,5 @@ Start the project: ```bash npm start ``` + +> Generated using `npm create node-llama-cpp@latest` ([learn more](https://node-llama-cpp.withcat.ai/guide/)) diff --git a/templates/node-typescript/eslint.config.js b/templates/node-typescript/eslint.config.js index 6131d60f..180452e1 100644 --- a/templates/node-typescript/eslint.config.js +++ b/templates/node-typescript/eslint.config.js @@ -72,7 +72,7 @@ export default tseslint.config({ after: true }], "@stylistic/comma-style": ["error", "last"], - "@stylistic/comma-dangle": ["error", "never"], + "@stylistic/comma-dangle": ["warn", "never"], "no-var": ["error"], "import/order": ["error", { groups: ["builtin", "external", "internal", "parent", "sibling", "index", "type", "object", "unknown"], @@ -122,7 +122,8 @@ export default tseslint.config({ {blankLine: "always", prev: "*", next: "method"} ] }], - "@stylistic/no-trailing-spaces": ["warn"] + "@stylistic/no-trailing-spaces": ["warn"], + "@stylistic/no-multi-spaces": ["warn"] } }, { files: ["**/**.{,c,m}ts"], diff --git a/templates/node-typescript/package.json b/templates/node-typescript/package.json index c7cdf184..1e92d434 100644 --- a/templates/node-typescript/package.json +++ b/templates/node-typescript/package.json @@ -38,17 +38,17 @@ "node-llama-cpp": "file:../.." }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.10.0", - "@types/node": "^22.8.4", - "eslint": "^9.13.0", + "@stylistic/eslint-plugin": "^2.11.0", + "@types/node": "^22.10.1", + "eslint": "^9.16.0", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsdoc": "^50.4.3", - "eslint-plugin-n": "^17.12.0", + "eslint-plugin-jsdoc": "^50.6.0", + "eslint-plugin-n": "^17.14.0", "rimraf": "^6.0.1", - "tslib": "^2.8.0", - "typescript": "^5.6.3", - "typescript-eslint": "^8.12.2", - "vite-node": "^2.1.4" + "tslib": "^2.8.1", + "typescript": "^5.7.2", + "typescript-eslint": "^8.16.0", + "vite-node": "^2.1.6" } } diff --git a/test/standalone/chatWrappers/FunctionaryChatWrapper.test.ts b/test/standalone/chatWrappers/FunctionaryChatWrapper.test.ts index 8c76bf38..1980f487 100644 --- a/test/standalone/chatWrappers/FunctionaryChatWrapper.test.ts +++ b/test/standalone/chatWrappers/FunctionaryChatWrapper.test.ts @@ -38,6 +38,61 @@ describe("FunctionaryChatWrapper", () => { async handler(params) { return Math.floor(Math.random() * (params.max - params.min + 1) + params.min); } + }), + func1: defineChatSessionFunction({ + description: "Some function", + params: { + type: "object", + properties: { + message: { + type: "string", + description: "Some message", + minLength: 3, + maxLength: 10 + }, + words: { + type: "array", + description: "Some words", + items: { + type: "string" + }, + minItems: 2, + maxItems: 5 + }, + headers: { + type: "object", + description: "Some headers", + additionalProperties: { + type: "string" + }, + minProperties: 4, + maxProperties: 12 + }, + mappings: { + type: "object", + description: "Some mappings", + properties: { + a: { + type: "boolean" + }, + b: { + type: "number" + }, + c: { + type: ["string", "null"] + } + }, + additionalProperties: { + type: "string" + }, + minProperties: 4, + maxProperties: 12 + } + } + }, + handler(params) { + + } }) }; const conversationHistory2: ChatHistoryItem[] = [{ @@ -169,6 +224,25 @@ describe("FunctionaryChatWrapper", () => { // Get a random number type getRandomNumber = (_: {min: number, max: number}) => any; + // Some function + type func1 = (_: { + // Some message + // minimum length: 3, maximum length: 10 + message: string, + + // Some words + // maximum items: 5 + words: [string, string, ...string[]], + + // Some headers + // minimum number of properties: 4, maximum number of properties: 12 + headers: {[key: string]: string}, + + // Some mappings + // minimum number of properties: 4, maximum number of properties: 12 + mappings: {a: boolean, b: number, c: string | null} & {[key: string]: string} + }) => any; + } // namespace functions", { "type": "specialToken", @@ -524,6 +598,25 @@ describe("FunctionaryChatWrapper", () => { // Get a random number type getRandomNumber = (_: {min: number, max: number}) => any; + // Some function + type func1 = (_: { + // Some message + // minimum length: 3, maximum length: 10 + message: string, + + // Some words + // maximum items: 5 + words: [string, string, ...string[]], + + // Some headers + // minimum number of properties: 4, maximum number of properties: 12 + headers: {[key: string]: string}, + + // Some mappings + // minimum number of properties: 4, maximum number of properties: 12 + mappings: {a: boolean, b: number, c: string | null} & {[key: string]: string} + }) => any; + } // namespace functions", { "type": "specialTokensText", diff --git a/test/standalone/chatWrappers/generic/JinjaTemplateChatWrapper.test.ts b/test/standalone/chatWrappers/generic/JinjaTemplateChatWrapper.test.ts index 35d15d9c..ac7cab69 100644 --- a/test/standalone/chatWrappers/generic/JinjaTemplateChatWrapper.test.ts +++ b/test/standalone/chatWrappers/generic/JinjaTemplateChatWrapper.test.ts @@ -123,6 +123,76 @@ describe("JinjaTemplateChatWrapper", () => { type: "string" } } + }, + func4: { + description: "Some description here", + params: { + type: "array", + prefixItems: [ + {type: "string"}, + {type: "boolean"}, + {type: "number"}, + {type: "null"}, + {type: "object", properties: {message: {type: "string"}}}, + {type: "array", items: {type: "string"}} + ], + items: { + enum: ["1", -6] + }, + minItems: 8 + } + }, + func5: { + description: "Some description here", + params: { + type: "array", + prefixItems: [ + {type: "string"}, + {type: "boolean"}, + {type: "number"} + ], + maxItems: 3 + } + }, + func6: { + description: "Some description here", + params: { + type: "array", + items: { + type: "string" + }, + minItems: 2 + } + }, + func7: { + description: "Some description here", + params: { + type: "array", + items: { + type: "string" + }, + minItems: 2, + maxItems: 2 + } + }, + func8: { + params: { + type: "object", + properties: { + message: { + description: "The main message", + type: "string" + }, + feeling: { + description: "The feeling", + enum: ["good", "bad"] + }, + words: { + description: "The number of words.\nFor example, 6", + type: "number" + } + } + } } } as const; @@ -543,7 +613,31 @@ describe("JinjaTemplateChatWrapper", () => { function func2(params: {message: string, feeling: "good" | "bad", words: number}); // Some description here - function func3(params: (string)[]); + function func3(params: string[]); + + // Some description here + function func4(params: [string, boolean, number, null, {message: string}, string[], "1" | -6, "1" | -6, ...("1" | -6)[]]); + + // Some description here + function func5(params: [string, boolean, number]); + + // Some description here + function func6(params: [string, string, ...string[]]); + + // Some description here + function func7(params: [string, string]); + + function func8(params: { + // The main message + message: string, + + // The feeling + feeling: "good" | "bad", + + // The number of words. + // For example, 6 + words: number + }); \`\`\` Calling any of the provided functions can be done like this: @@ -622,7 +716,31 @@ describe("JinjaTemplateChatWrapper", () => { function func2(params: {message: string, feeling: "good" | "bad", words: number}); // Some description here - function func3(params: (string)[]); + function func3(params: string[]); + + // Some description here + function func4(params: [string, boolean, number, null, {message: string}, string[], "1" | -6, "1" | -6, ...("1" | -6)[]]); + + // Some description here + function func5(params: [string, boolean, number]); + + // Some description here + function func6(params: [string, string, ...string[]]); + + // Some description here + function func7(params: [string, string]); + + function func8(params: { + // The main message + message: string, + + // The feeling + feeling: "good" | "bad", + + // The number of words. + // For example, 6 + words: number + }); \`\`\` Calling any of the provided functions can be done like this: @@ -700,7 +818,31 @@ describe("JinjaTemplateChatWrapper", () => { function func2(params: {message: string, feeling: "good" | "bad", words: number}); // Some description here - function func3(params: (string)[]); + function func3(params: string[]); + + // Some description here + function func4(params: [string, boolean, number, null, {message: string}, string[], "1" | -6, "1" | -6, ...("1" | -6)[]]); + + // Some description here + function func5(params: [string, boolean, number]); + + // Some description here + function func6(params: [string, string, ...string[]]); + + // Some description here + function func7(params: [string, string]); + + function func8(params: { + // The main message + message: string, + + // The feeling + feeling: "good" | "bad", + + // The number of words. + // For example, 6 + words: number + }); \`\`\` Calling any of the provided functions can be done like this: diff --git a/test/standalone/chatWrappers/generic/TemplateChatWrapper.test.ts b/test/standalone/chatWrappers/generic/TemplateChatWrapper.test.ts index 3f642506..8aa02f9b 100644 --- a/test/standalone/chatWrappers/generic/TemplateChatWrapper.test.ts +++ b/test/standalone/chatWrappers/generic/TemplateChatWrapper.test.ts @@ -356,7 +356,7 @@ describe("TemplateChatWrapper", () => { function func2(params: {message: string, feeling: "good" | "bad", words: number}); // Some description here - function func3(params: (string)[]); + function func3(params: string[]); \`\`\` Calling any of the provided functions can be done like this: @@ -425,7 +425,7 @@ describe("TemplateChatWrapper", () => { function func2(params: {message: string, feeling: "good" | "bad", words: number}); // Some description here - function func3(params: (string)[]); + function func3(params: string[]); \`\`\` Calling any of the provided functions can be done like this: @@ -495,7 +495,7 @@ describe("TemplateChatWrapper", () => { function func2(params: {message: string, feeling: "good" | "bad", words: number}); // Some description here - function func3(params: (string)[]); + function func3(params: string[]); \`\`\` Calling any of the provided functions can be done like this: diff --git a/test/standalone/llamaEvaluator/LlamaGrammar.test.ts b/test/standalone/llamaEvaluator/LlamaGrammar.test.ts index 29fe8deb..f7e694c5 100644 --- a/test/standalone/llamaEvaluator/LlamaGrammar.test.ts +++ b/test/standalone/llamaEvaluator/LlamaGrammar.test.ts @@ -1,5 +1,5 @@ import {describe, expect, test, expectTypeOf} from "vitest"; -import {LlamaJsonSchemaGrammar} from "../../../src/index.js"; +import {jsonDumps, LlamaJsonSchemaGrammar} from "../../../src/index.js"; import {getTestLlama} from "../../utils/getTestLlama.js"; @@ -106,41 +106,47 @@ describe("grammar for JSON schema", () => { }; expect(grammar.grammar).toMatchInlineSnapshot(` - "root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? rule0 "," whitespace-b-1-4-rule "\\"numberOfWordsInMessage\\"" ":" [ ]? integer-number-rule "," whitespace-b-1-4-rule "\\"feelingGoodPercentage\\"" ":" [ ]? fractional-number-rule "," whitespace-b-1-4-rule "\\"feelingGood\\"" ":" [ ]? boolean-rule "," whitespace-b-1-4-rule "\\"feelingOverall\\"" ":" [ ]? rule5 "," whitespace-b-1-4-rule "\\"verbsInMessage\\"" ":" [ ]? rule6 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* - whitespace-b-1-4-rule ::= ([\\n] (" " | "\\t") | [ ]?) - string-rule ::= "\\"" ([^"\\\\\\x7F\\x00-\\x1F] | "\\\\" (["\\\\/bfnrt] | "u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]))* "\\"" + "root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? rule0 comma-whitespace-b-1-4-rule "\\"numberOfWordsInMessage\\"" ":" [ ]? integer-number-rule comma-whitespace-b-1-4-rule "\\"feelingGoodPercentage\\"" ":" [ ]? fractional-number-rule comma-whitespace-b-1-4-rule "\\"feelingGood\\"" ":" [ ]? boolean-rule comma-whitespace-b-1-4-rule "\\"feelingOverall\\"" ":" [ ]? rule1 comma-whitespace-b-1-4-rule "\\"verbsInMessage\\"" ":" [ ]? rule2 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" null-rule ::= "null" rule0 ::= ( string-rule | null-rule ) - integer-number-rule ::= ("-"? ([0-9] | [1-9] [0-9]*)) - fractional-number-rule ::= ("-"? ([0-9] | [1-9] [0-9]*)) ("." [0-9]+)? ([eE] [-+]? [0-9]+)? - rule1 ::= "true" - rule2 ::= "false" - boolean-rule ::= ( rule1 | rule2 ) - rule3 ::= "\\"good\\"" - rule4 ::= "\\"bad\\"" - rule5 ::= ( rule3 | rule4 ) - whitespace-b-2-4-rule ::= ([\\n] (" " | "\\t\\t") | [ ]?) - rule7 ::= ( string-rule ) ( "," whitespace-b-2-4-rule string-rule )* - rule8 ::= ( string-rule )? - rule6 ::= "[" whitespace-b-2-4-rule ( rule7 | rule8 ) whitespace-b-1-4-rule "]" - whitespace-b-0-4-rule ::= ([\\n] | [ ]?)" + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + integer-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))? + fractional-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ("." [0-9]{1,16})? ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))? + boolean-rule ::= "true" | "false" + val0 ::= "\\"good\\"" + val1 ::= "\\"bad\\"" + rule1 ::= ( val0 | val1 ) + comma-whitespace-b-2-4-rule ::= "," ([\\n] (" "{8} | "\\t\\t") | [ ]?) + whitespace-b-2-4-rule ::= [\\n] (" "{8} | "\\t\\t") | [ ]? + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + rule2 ::= "[" whitespace-b-2-4-rule ( string-rule ( comma-whitespace-b-2-4-rule string-rule )* )? whitespace-b-1-4-rule "]" + whitespace-b-0-4-rule ::= [\\n] | [ ]?" `); const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); expectTypeOf(parsedValue).toMatchTypeOf(); expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); expectTypeOf(parsedValue2).toMatchTypeOf(); expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); try { grammar.parse(JSON.stringify(exampleInvalidValue)); expect.unreachable("Parsing should have failed"); } catch (err) { - expect(err).toMatchInlineSnapshot('[Error: Expected "string" but got "number"]'); + expect(err).toMatchInlineSnapshot("[Error: Expected type \"string\" but got \"number\"]"); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); } try { @@ -148,27 +154,31 @@ describe("grammar for JSON schema", () => { expect.unreachable("Parsing should have failed"); } catch (err) { expect(err).toMatchInlineSnapshot('[Error: Expected one of ["good", "bad"] but got "average"]'); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); } try { grammar.parse(JSON.stringify(exampleInvalidValue3)); expect.unreachable("Parsing should have failed"); } catch (err) { - expect(err).toMatchInlineSnapshot('[Error: Expected "string" but got "boolean"]'); + expect(err).toMatchInlineSnapshot("[Error: Expected type \"string\" but got \"boolean\"]"); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); } try { grammar.parse(JSON.stringify(exampleInvalidValue4)); expect.unreachable("Parsing should have failed"); } catch (err) { - expect(err).toMatchInlineSnapshot('[Error: Expected "string" but got "object"]'); + expect(err).toMatchInlineSnapshot("[Error: Expected type \"string\" but got \"object\"]"); + expect(testGrammar(grammar, exampleInvalidValue4)).to.eql(false); } try { grammar.parse(JSON.stringify(exampleInvalidValue5)); expect.unreachable("Parsing should have failed"); } catch (err) { - expect(err).toMatchInlineSnapshot('[Error: Expected "string" but got "null"]'); + expect(err).toMatchInlineSnapshot("[Error: Expected type \"string\" but got \"null\"]"); + expect(testGrammar(grammar, exampleInvalidValue5)).to.eql(false); } try { @@ -176,6 +186,7 @@ describe("grammar for JSON schema", () => { expect.unreachable("Parsing should have failed"); } catch (err) { expect(err).toMatchInlineSnapshot('[Error: Expected one type of ["string", "null"] but got type "boolean"]'); + expect(testGrammar(grammar, exampleInvalidValue6)).to.eql(false); } }); @@ -212,31 +223,39 @@ describe("grammar for JSON schema", () => { }; expect(grammar.grammar).toMatchInlineSnapshot(` - "root ::= "[" whitespace-b-1-4-rule ( rule2 | rule3 ) whitespace-b-0-4-rule "]" "\\n\\n\\n\\n" [\\n]* - whitespace-b-1-4-rule ::= ([\\n] (" " | "\\t") | [ ]?) - string-rule ::= "\\"" ([^"\\\\\\x7F\\x00-\\x1F] | "\\\\" (["\\\\/bfnrt] | "u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]))* "\\"" - whitespace-b-0-4-rule ::= ([\\n] | [ ]?) - rule0 ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? string-rule whitespace-b-0-4-rule "}" + "root ::= "[" whitespace-b-1-4-rule ( rule1 ( comma-whitespace-b-1-4-rule rule1 )* )? whitespace-b-0-4-rule "]" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + whitespace-b-2-4-rule ::= [\\n] (" "{8} | "\\t\\t") | [ ]? + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + rule0 ::= "{" whitespace-b-2-4-rule "\\"message\\"" ":" [ ]? string-rule whitespace-b-1-4-rule "}" rule1 ::= ( rule0 | string-rule ) - rule2 ::= ( rule1 ) ( "," whitespace-b-1-4-rule rule1 )* - rule3 ::= ( rule1 )?" + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + whitespace-b-0-4-rule ::= [\\n] | [ ]?" `); const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); expectTypeOf(parsedValue).toMatchTypeOf(); expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); expectTypeOf(parsedValue2).toMatchTypeOf(); expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); try { grammar.parse(JSON.stringify(exampleInvalidValue)); expect.unreachable("Parsing should have failed"); } catch (err) { expect(err).toMatchInlineSnapshot("[Error: Expected one of 2 schemas but got 10]"); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); } try { @@ -244,6 +263,7 @@ describe("grammar for JSON schema", () => { expect.unreachable("Parsing should have failed"); } catch (err) { expect(err).toMatchInlineSnapshot('[Error: Expected an array but got "object"]'); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); } }); @@ -268,7 +288,7 @@ describe("grammar for JSON schema", () => { const: null }, "withNewLine": { - const: "Hooray!\nYes!\t/\\" + const: "Hooray!\nYes!\t/\\and\"and\'" }, "withQuotes": { const: 'The message is "Hi!".' @@ -281,7 +301,7 @@ describe("grammar for JSON schema", () => { "onlyVibe": "good", "onlyNumber": 10, "worstThing": null, - "withNewLine": "Hooray!\nYes!\t/\\", + "withNewLine": "Hooray!\nYes!\t/\\and\"and\'", "withQuotes": 'The message is "Hi!".' }; const exampleValidValue = { @@ -290,7 +310,7 @@ describe("grammar for JSON schema", () => { "onlyVibe": "good", "onlyNumber": 10, "worstThing": null, - "withNewLine": "Hooray!\nYes!\t/\\", + "withNewLine": "Hooray!\nYes!\t/\\and\"and\'", "withQuotes": 'The message is "Hi!".' }; const exampleInvalidValue = { @@ -299,30 +319,35 @@ describe("grammar for JSON schema", () => { "onlyVibe": "good", "onlyNumber": 10.1, "worstThing": null, - "withNewLine": "Hooray!\nYes!\t/\\", + "withNewLine": "Hooray!\nYes!\t/\\and\"and\'", "withQuotes": 'The message is "Hi!".' }; expect(grammar.grammar).toMatchInlineSnapshot(` - "root ::= "{" whitespace-b-1-4-rule "\\"onlyPositiveText\\"" ":" [ ]? "true" "," whitespace-b-1-4-rule "\\"onlyNegativeText\\"" ":" [ ]? "false" "," whitespace-b-1-4-rule "\\"onlyVibe\\"" ":" [ ]? rule0 "," whitespace-b-1-4-rule "\\"onlyNumber\\"" ":" [ ]? "10" "," whitespace-b-1-4-rule "\\"worstThing\\"" ":" [ ]? null-rule "," whitespace-b-1-4-rule "\\"withNewLine\\"" ":" [ ]? rule1 "," whitespace-b-1-4-rule "\\"withQuotes\\"" ":" [ ]? rule2 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* - whitespace-b-1-4-rule ::= ([\\n] (" " | "\\t") | [ ]?) - rule0 ::= "\\"good\\"" + "root ::= "{" whitespace-b-1-4-rule "\\"onlyPositiveText\\"" ":" [ ]? "true" comma-whitespace-b-1-4-rule "\\"onlyNegativeText\\"" ":" [ ]? "false" comma-whitespace-b-1-4-rule "\\"onlyVibe\\"" ":" [ ]? val0 comma-whitespace-b-1-4-rule "\\"onlyNumber\\"" ":" [ ]? "10" comma-whitespace-b-1-4-rule "\\"worstThing\\"" ":" [ ]? null-rule comma-whitespace-b-1-4-rule "\\"withNewLine\\"" ":" [ ]? val1 comma-whitespace-b-1-4-rule "\\"withQuotes\\"" ":" [ ]? val2 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + val0 ::= "\\"good\\"" null-rule ::= "null" - rule1 ::= "\\"Hooray!\\nYes!\\t/\\\\\\"" - rule2 ::= "\\"The message is \\\\\\"Hi!\\\\\\".\\"" - whitespace-b-0-4-rule ::= ([\\n] | [ ]?)" + val1 ::= "\\"Hooray!\\\\nYes!\\\\t/\\\\\\\\and\\\\\\"and'\\"" + val2 ::= "\\"The message is \\\\\\"Hi!\\\\\\".\\"" + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" `); const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); expectTypeOf(parsedValue).toMatchTypeOf(); expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); try { grammar.parse(JSON.stringify(exampleInvalidValue)); expect.unreachable("Parsing should have failed"); } catch (err) { expect(err).toMatchInlineSnapshot("[Error: Expected 10 but got 10.1]"); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); } }); @@ -383,25 +408,30 @@ describe("grammar for JSON schema", () => { }; expect(grammar.grammar).toMatchInlineSnapshot(` - "root ::= "{" whitespace-b-1-4-rule "\\"onlyPositiveText\\"" ":" [ ]? "true" "," whitespace-b-1-4-rule "\\"onlyNegativeText\\"" ":" [ ]? "false" "," whitespace-b-1-4-rule "\\"onlyVibe\\"" ":" [ ]? rule0 "," whitespace-b-1-4-rule "\\"onlyNumber\\"" ":" [ ]? "10" "," whitespace-b-1-4-rule "\\"worstThing\\"" ":" [ ]? null-rule "," whitespace-b-1-4-rule "\\"withNewLine\\"" ":" [ ]? rule1 "," whitespace-b-1-4-rule "\\"withQuotes\\"" ":" [ ]? rule2 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* - whitespace-b-1-4-rule ::= ([\\n] (" " | "\\t") | [ ]?) - rule0 ::= "\\"good\\"" + "root ::= "{" whitespace-b-1-4-rule "\\"onlyPositiveText\\"" ":" [ ]? "true" comma-whitespace-b-1-4-rule "\\"onlyNegativeText\\"" ":" [ ]? "false" comma-whitespace-b-1-4-rule "\\"onlyVibe\\"" ":" [ ]? val0 comma-whitespace-b-1-4-rule "\\"onlyNumber\\"" ":" [ ]? "10" comma-whitespace-b-1-4-rule "\\"worstThing\\"" ":" [ ]? null-rule comma-whitespace-b-1-4-rule "\\"withNewLine\\"" ":" [ ]? val1 comma-whitespace-b-1-4-rule "\\"withQuotes\\"" ":" [ ]? val2 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + val0 ::= "\\"good\\"" null-rule ::= "null" - rule1 ::= "\\"Hooray!\\nYes!\\t/\\\\\\"" - rule2 ::= "\\"The message is \\\\\\"Hi!\\\\\\".\\"" - whitespace-b-0-4-rule ::= ([\\n] | [ ]?)" + val1 ::= "\\"Hooray!\\\\nYes!\\\\t/\\\\\\\\\\"" + val2 ::= "\\"The message is \\\\\\"Hi!\\\\\\".\\"" + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" `); const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); expectTypeOf(parsedValue).toMatchTypeOf(); expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); try { grammar.parse(JSON.stringify(exampleInvalidValue)); expect.unreachable("Parsing should have failed"); } catch (err) { expect(err).toMatchInlineSnapshot('[Error: Missing keys: "onlyVibe"]'); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); } }); @@ -463,25 +493,1761 @@ describe("grammar for JSON schema", () => { }; expect(grammar.grammar).toMatchInlineSnapshot(` - "root ::= "{" whitespace-b-1-4-rule "\\"onlyPositiveText\\"" ":" [ ]? "true" "," whitespace-b-1-4-rule "\\"onlyNegativeText\\"" ":" [ ]? "false" "," whitespace-b-1-4-rule "\\"onlyVibe\\"" ":" [ ]? rule0 "," whitespace-b-1-4-rule "\\"onlyNumber\\"" ":" [ ]? "10" "," whitespace-b-1-4-rule "\\"worstThing\\"" ":" [ ]? null-rule "," whitespace-b-1-4-rule "\\"withNewLine\\"" ":" [ ]? rule1 "," whitespace-b-1-4-rule "\\"withQuotes\\"" ":" [ ]? rule2 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* - whitespace-b-1-4-rule ::= ([\\n] (" " | "\\t") | [ ]?) - rule0 ::= "\\"good\\"" + "root ::= "{" whitespace-b-1-4-rule "\\"onlyPositiveText\\"" ":" [ ]? "true" comma-whitespace-b-1-4-rule "\\"onlyNegativeText\\"" ":" [ ]? "false" comma-whitespace-b-1-4-rule "\\"onlyVibe\\"" ":" [ ]? val0 comma-whitespace-b-1-4-rule "\\"onlyNumber\\"" ":" [ ]? "10" comma-whitespace-b-1-4-rule "\\"worstThing\\"" ":" [ ]? null-rule comma-whitespace-b-1-4-rule "\\"withNewLine\\"" ":" [ ]? val1 comma-whitespace-b-1-4-rule "\\"withQuotes\\"" ":" [ ]? val2 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + val0 ::= "\\"good\\"" null-rule ::= "null" - rule1 ::= "\\"Hooray!\\nYes!\\t/\\\\\\"" - rule2 ::= "\\"The message is \\\\\\"Hi!\\\\\\".\\"" - whitespace-b-0-4-rule ::= ([\\n] | [ ]?)" + val1 ::= "\\"Hooray!\\\\nYes!\\\\t/\\\\\\\\\\"" + val2 ::= "\\"The message is \\\\\\"Hi!\\\\\\".\\"" + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" `); const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); expectTypeOf(parsedValue).toMatchTypeOf(); expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); try { grammar.parse(JSON.stringify(exampleInvalidValue)); expect.unreachable("Parsing should have failed"); } catch (err) { expect(err).toMatchInlineSnapshot('[Error: Unexpected keys: "onlyFeeling"]'); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); } }); + + describe("array options", () => { + test("no type", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + "simple": { + type: "array" + }, + "withMinItems": { + type: "array", + minItems: 2 + } + } + } as const); + type schemaType = { + "simple": any[], + "withMinItems": [any, any, ...any[]] + }; + + const exampleValidValue = { + "simple": [], + "withMinItems": [1, true] + }; + const exampleValidValue2 = { + "simple": [false], + "withMinItems": [1, null, "text"] + }; + + const exampleInvalidValue = { + "simple": "not an array", + "withMinItems": [1, true] + }; + const exampleInvalidValue2 = { + "simple": [], + "withMinItems": [1] + }; + const exampleInvalidValue3 = { + "simple": [], + "withMinItems": [] + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"simple\\"" ":" [ ]? rule5 comma-whitespace-b-1-4-rule "\\"withMinItems\\"" ":" [ ]? rule6 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + fractional-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ("." [0-9]{1,16})? ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))? + boolean-rule ::= "true" | "false" + null-rule ::= "null" + comma-whitespace-no-new-lines-rule ::= "," [ ]? + whitespace-no-new-lines-rule ::= [ ]? + rule0 ::= "[" whitespace-no-new-lines-rule ( any-json-s-0-4-rule ( comma-whitespace-no-new-lines-rule any-json-s-0-4-rule )* )? whitespace-no-new-lines-rule "]" + rule1 ::= string-rule ":" [ ]? any-json-s-0-4-rule + rule2 ::= "{" whitespace-no-new-lines-rule ( rule1 ( comma-whitespace-no-new-lines-rule rule1 )* )? whitespace-no-new-lines-rule "}" + any-json-s-0-4-rule ::= ( string-rule | fractional-number-rule | boolean-rule | null-rule | rule0 | rule2 ) + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]? + rule3 ::= "[" whitespace-b-1-4-rule ( any-json-s-0-4-rule ( comma-whitespace-b-1-4-rule any-json-s-0-4-rule )* )? whitespace-b-0-4-rule "]" + rule4 ::= "{" whitespace-b-1-4-rule ( rule1 ( comma-whitespace-b-1-4-rule rule1 )* )? whitespace-b-0-4-rule "}" + any-json-0-4-rule ::= ( string-rule | fractional-number-rule | boolean-rule | null-rule | rule3 | rule4 ) + comma-whitespace-b-2-4-rule ::= "," ([\\n] (" "{8} | "\\t\\t") | [ ]?) + whitespace-b-2-4-rule ::= [\\n] (" "{8} | "\\t\\t") | [ ]? + rule5 ::= "[" whitespace-b-2-4-rule ( any-json-0-4-rule ( comma-whitespace-b-2-4-rule any-json-0-4-rule )* )? whitespace-b-1-4-rule "]" + rule6 ::= "[" whitespace-b-2-4-rule any-json-0-4-rule ( comma-whitespace-b-2-4-rule any-json-0-4-rule ){1,} whitespace-b-1-4-rule "]"" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected an array but got "string"]'); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 2 items but got 1]"); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 2 items but got 0]"); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + + test("string items", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + "simple": { + type: "array", + items: { + type: "string" + } + }, + "withMinItems": { + type: "array", + items: { + type: "string" + }, + minItems: 2 + }, + "withMaxItems": { + type: "array", + items: { + type: "string" + }, + maxItems: 3 + }, + "withMinAndMaxItems": { + type: "array", + items: { + type: "string" + }, + minItems: 2, + maxItems: 3 + }, + "withEqualMinAndMaxItems": { + type: "array", + items: { + type: "string" + }, + minItems: 3, + maxItems: 3 + } + } + } as const); + type schemaType = { + "simple": string[], + "withMinItems": [string, string, ...any[]], + "withMaxItems": string[], + "withMinAndMaxItems": [string, string, ...any[]], + "withEqualMinAndMaxItems": [string, string, string] + }; + + const exampleValidValue = { + "simple": [], + "withMinItems": ["1", "2"], + "withMaxItems": ["1", "2", "3"], + "withMinAndMaxItems": ["1", "2", "3"], + "withEqualMinAndMaxItems": ["1", "2", "3"] + }; + const exampleValidValue2 = { + "simple": ["1"], + "withMinItems": ["1", "2", "3"], + "withMaxItems": ["1", "2"], + "withMinAndMaxItems": ["1", "2"], + "withEqualMinAndMaxItems": ["1", "2", "3"] + }; + + const exampleInvalidValue = { + "simple": [], + "withMinItems": ["1", 2], + "withMaxItems": ["1", "2", "3", "4"], + "withMinAndMaxItems": ["1"], + "withEqualMinAndMaxItems": ["1", "2"] + }; + const exampleInvalidValue2 = { + "simple": [], + "withMinItems": ["1"], + "withMaxItems": ["1", "2", "3", "4"], + "withMinAndMaxItems": ["1", "2", "3", "4"], + "withEqualMinAndMaxItems": ["1", "2"] + }; + const exampleInvalidValue3 = { + "simple": [], + "withMinItems": ["1", "2"], + "withMaxItems": ["1", "2", "3"], + "withMinAndMaxItems": ["1", "2"], + "withEqualMinAndMaxItems": ["1", 3] + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"simple\\"" ":" [ ]? rule0 comma-whitespace-b-1-4-rule "\\"withMinItems\\"" ":" [ ]? rule1 comma-whitespace-b-1-4-rule "\\"withMaxItems\\"" ":" [ ]? rule2 comma-whitespace-b-1-4-rule "\\"withMinAndMaxItems\\"" ":" [ ]? rule3 comma-whitespace-b-1-4-rule "\\"withEqualMinAndMaxItems\\"" ":" [ ]? rule4 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + comma-whitespace-b-2-4-rule ::= "," ([\\n] (" "{8} | "\\t\\t") | [ ]?) + whitespace-b-2-4-rule ::= [\\n] (" "{8} | "\\t\\t") | [ ]? + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + rule0 ::= "[" whitespace-b-2-4-rule ( string-rule ( comma-whitespace-b-2-4-rule string-rule )* )? whitespace-b-1-4-rule "]" + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + rule1 ::= "[" whitespace-b-2-4-rule string-rule ( comma-whitespace-b-2-4-rule string-rule ){1,} whitespace-b-1-4-rule "]" + rule2 ::= "[" whitespace-b-2-4-rule ( string-rule ( comma-whitespace-b-2-4-rule string-rule ){0,2} )? whitespace-b-1-4-rule "]" + rule3 ::= "[" whitespace-b-2-4-rule string-rule ( comma-whitespace-b-2-4-rule string-rule ){1,2} whitespace-b-1-4-rule "]" + rule4 ::= "[" whitespace-b-2-4-rule string-rule ( comma-whitespace-b-2-4-rule string-rule ){2} whitespace-b-1-4-rule "]" + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected type \"string\" but got \"number\"]"); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 2 items but got 1]"); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected exactly 3 items but got 2]"); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + }); + + test("with prefix items", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + simple: { + type: "array", + prefixItems: [ + {type: "string"}, + {type: "boolean"}, + {type: "number"}, + {type: "null"}, + {type: "object", properties: {message: {type: "string"}}}, + {type: "array", items: {type: "string"}} + ] + }, + withAdditionalItems: { + type: "array", + prefixItems: [ + {type: "string"}, + {type: "boolean"}, + {type: "number"}, + {type: "null"}, + {type: "object", properties: {message: {type: "string"}}}, + {type: "array", items: {type: "string"}} + ], + items: { + enum: ["1", -6] + } + }, + withAdditionalItemsAndMin: { + type: "array", + prefixItems: [ + {type: "string"}, + {type: "boolean"}, + {type: "number"}, + {type: "null"}, + {type: "object", properties: {message: {type: "string"}}}, + {type: "array", items: {type: "string"}} + ], + items: { + enum: ["1", -600] + }, + minItems: 8 + }, + withAdditionalItemsAndMax: { + type: "array", + prefixItems: [ + {type: "string"}, + {type: "boolean"}, + {type: "number"}, + {type: "null"}, + {type: "object", properties: {message: {type: "string"}}}, + {type: "array", items: {type: "string"}} + ], + items: { + enum: ["1", -6] + }, + maxItems: 8 + }, + withMaxSizeOfPrefixItems: { + type: "array", + prefixItems: [ + {type: "string"}, + {type: "boolean"}, + {type: "number"}, + {type: "null"}, + {type: "object", properties: {message: {type: "string"}}}, + {type: "array", items: {type: "string"}} + ], + maxItems: 6 + }, + withAdditionalItemsAndMaxSizeOfPrefixItems: { + type: "array", + prefixItems: [ + {type: "string"}, + {type: "boolean"}, + {type: "number"}, + {type: "null"}, + {type: "object", properties: {message: {type: "string"}}}, + {type: "array", items: {type: "string"}} + ], + items: { + enum: ["1", -6] + }, + maxItems: 6 + }, + withAdditionalItemsAndMinAndMax: { + type: "array", + prefixItems: [ + {type: "string"}, + {type: "boolean"}, + {type: "number"}, + {type: "null"}, + {type: "object", properties: {message: {type: "string"}}}, + {type: "array", items: {type: "string"}} + ], + items: { + enum: ["1", -6] + }, + minItems: 8, + maxItems: 10 + }, + withAdditionalItemsAndMinAndMaxEquals: { + type: "array", + prefixItems: [ + {type: "string"}, + {type: "boolean"}, + {type: "number"}, + {type: "null"}, + {type: "object", properties: {message: {type: "string"}}}, + {type: "array", items: {type: "string"}} + ], + items: { + enum: ["1", -6] + }, + minItems: 10, + maxItems: 10 + } + } + } as const); + type schemaType = { + simple: [string, boolean, number, null, {message: string}, string[], ...any[]], + withAdditionalItems: [string, boolean, number, null, {message: string}, string[], ...("1" | -6)[]], + withAdditionalItemsAndMin: [string, boolean, number, null, {message: string}, string[], "1" | -600, "1" | -600, ...("1" | -600)[]], + withAdditionalItemsAndMax: [string, boolean, number, null, {message: string}, string[], ...("1" | -6)[]], + withMaxSizeOfPrefixItems: [string, boolean, number, null, {message: string}, string[]], + withAdditionalItemsAndMaxSizeOfPrefixItems: [string, boolean, number, null, {message: string}, string[]], + withAdditionalItemsAndMinAndMax: [string, boolean, number, null, {message: string}, string[], "1" | -6, "1" | -6, ...("1" | -6)[]], + withAdditionalItemsAndMinAndMaxEquals: [string, boolean, number, null, {message: string}, string[], "1" | -6, "1" | -6, "1" | -6, "1" | -6] + }; + + const exampleValidValue = { + simple: ["text", true, 10, null, {message: "Hello"}, ["1"]], + withAdditionalItems: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6], + withAdditionalItemsAndMin: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -600, "1", -600], + withAdditionalItemsAndMax: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6], + withMaxSizeOfPrefixItems: ["text", true, 10, null, {message: "Hello"}, ["1"]], + withAdditionalItemsAndMaxSizeOfPrefixItems: ["text", true, 10, null, {message: "Hello"}, ["1"]], + withAdditionalItemsAndMinAndMax: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6], + withAdditionalItemsAndMinAndMaxEquals: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6] + }; + const exampleValidValue2 = { + simple: ["text", true, 10, null, {message: "Hello"}, ["1"], "extra"], + withAdditionalItems: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6], + withAdditionalItemsAndMin: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -600, "1", -600], + withAdditionalItemsAndMax: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6], + withMaxSizeOfPrefixItems: ["text", true, 10, null, {message: "Hello"}, ["1"]], + withAdditionalItemsAndMaxSizeOfPrefixItems: ["text", true, 10, null, {message: "Hello"}, ["1"]], + withAdditionalItemsAndMinAndMax: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6], + withAdditionalItemsAndMinAndMaxEquals: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6] + }; + + const exampleInvalidValue = { + simple: ["text", true, 10, null, {message: "Hello"}, ["1"]], + withAdditionalItems: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "extra"], + withAdditionalItemsAndMin: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -600, "1", -600], + withAdditionalItemsAndMax: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6], + withMaxSizeOfPrefixItems: ["text", true, 10, null, {message: "Hello"}, ["1"], "extra"], + withAdditionalItemsAndMaxSizeOfPrefixItems: ["text", true, 10, null, {message: "Hello"}, ["1"], "extra"], + withAdditionalItemsAndMinAndMax: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6], + withAdditionalItemsAndMinAndMaxEquals: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6] + }; + const exampleInvalidValue2 = { + simple: ["text", true, 10, null, {message: "Hello"}, ["1"], "extra"], + withAdditionalItems: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6], + withAdditionalItemsAndMin: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -600, "1", -600, "extra"], + withAdditionalItemsAndMax: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "extra"], + withMaxSizeOfPrefixItems: ["text", true, 10, null, {message: "Hello"}, ["1"]], + withAdditionalItemsAndMaxSizeOfPrefixItems: ["text", true, 10, null, {message: "Hello"}, ["1"]], + withAdditionalItemsAndMinAndMax: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6, "1", -6, "extra"], + withAdditionalItemsAndMinAndMaxEquals: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6, "1", -6] + }; + const exampleInvalidValue3 = { + simple: ["text", true, 10, null, {message: "Hello"}, ["1"]], + withAdditionalItems: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6], + withAdditionalItemsAndMin: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -600, "1", -600], + withAdditionalItemsAndMax: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6], + withMaxSizeOfPrefixItems: ["text", true, 10, null, {message: "Hello"}, ["1"], "extra"], + withAdditionalItemsAndMaxSizeOfPrefixItems: ["text", true, 10, null, {message: "Hello"}, ["1"], "extra"], + withAdditionalItemsAndMinAndMax: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6], + withAdditionalItemsAndMinAndMaxEquals: ["text", true, 10, null, {message: "Hello"}, ["1"], "1", -6, "1", -6] + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"simple\\"" ":" [ ]? rule7 comma-whitespace-b-1-4-rule "\\"withAdditionalItems\\"" ":" [ ]? rule9 comma-whitespace-b-1-4-rule "\\"withAdditionalItemsAndMin\\"" ":" [ ]? rule11 comma-whitespace-b-1-4-rule "\\"withAdditionalItemsAndMax\\"" ":" [ ]? rule12 comma-whitespace-b-1-4-rule "\\"withMaxSizeOfPrefixItems\\"" ":" [ ]? rule13 comma-whitespace-b-1-4-rule "\\"withAdditionalItemsAndMaxSizeOfPrefixItems\\"" ":" [ ]? rule13 comma-whitespace-b-1-4-rule "\\"withAdditionalItemsAndMinAndMax\\"" ":" [ ]? rule14 comma-whitespace-b-1-4-rule "\\"withAdditionalItemsAndMinAndMaxEquals\\"" ":" [ ]? rule15 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + comma-whitespace-b-2-4-rule ::= "," ([\\n] (" "{8} | "\\t\\t") | [ ]?) + boolean-rule ::= "true" | "false" + fractional-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ("." [0-9]{1,16})? ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))? + null-rule ::= "null" + whitespace-b-3-4-rule ::= [\\n] (" "{12} | "\\t"{3}) | [ ]? + whitespace-b-2-4-rule ::= [\\n] (" "{8} | "\\t\\t") | [ ]? + rule0 ::= "{" whitespace-b-3-4-rule "\\"message\\"" ":" [ ]? string-rule whitespace-b-2-4-rule "}" + comma-whitespace-b-3-4-rule ::= "," ([\\n] (" "{12} | "\\t"{3}) | [ ]?) + rule1 ::= "[" whitespace-b-3-4-rule ( string-rule ( comma-whitespace-b-3-4-rule string-rule )* )? whitespace-b-2-4-rule "]" + comma-whitespace-no-new-lines-rule ::= "," [ ]? + whitespace-no-new-lines-rule ::= [ ]? + rule2 ::= "[" whitespace-no-new-lines-rule ( any-json-s-0-4-rule ( comma-whitespace-no-new-lines-rule any-json-s-0-4-rule )* )? whitespace-no-new-lines-rule "]" + rule3 ::= string-rule ":" [ ]? any-json-s-0-4-rule + rule4 ::= "{" whitespace-no-new-lines-rule ( rule3 ( comma-whitespace-no-new-lines-rule rule3 )* )? whitespace-no-new-lines-rule "}" + any-json-s-0-4-rule ::= ( string-rule | fractional-number-rule | boolean-rule | null-rule | rule2 | rule4 ) + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]? + rule5 ::= "[" whitespace-b-1-4-rule ( any-json-s-0-4-rule ( comma-whitespace-b-1-4-rule any-json-s-0-4-rule )* )? whitespace-b-0-4-rule "]" + rule6 ::= "{" whitespace-b-1-4-rule ( rule3 ( comma-whitespace-b-1-4-rule rule3 )* )? whitespace-b-0-4-rule "}" + any-json-0-4-rule ::= ( string-rule | fractional-number-rule | boolean-rule | null-rule | rule5 | rule6 ) + rule7 ::= "[" whitespace-b-2-4-rule string-rule comma-whitespace-b-2-4-rule boolean-rule comma-whitespace-b-2-4-rule fractional-number-rule comma-whitespace-b-2-4-rule null-rule comma-whitespace-b-2-4-rule rule0 comma-whitespace-b-2-4-rule rule1 ( comma-whitespace-b-2-4-rule any-json-0-4-rule )* whitespace-b-1-4-rule "]" + val0 ::= "\\"1\\"" + rule8 ::= ( val0 | "-6" ) + rule9 ::= "[" whitespace-b-2-4-rule string-rule comma-whitespace-b-2-4-rule boolean-rule comma-whitespace-b-2-4-rule fractional-number-rule comma-whitespace-b-2-4-rule null-rule comma-whitespace-b-2-4-rule rule0 comma-whitespace-b-2-4-rule rule1 ( comma-whitespace-b-2-4-rule rule8 )* whitespace-b-1-4-rule "]" + val1 ::= "-600" + rule10 ::= ( val0 | val1 ) + rule11 ::= "[" whitespace-b-2-4-rule string-rule comma-whitespace-b-2-4-rule boolean-rule comma-whitespace-b-2-4-rule fractional-number-rule comma-whitespace-b-2-4-rule null-rule comma-whitespace-b-2-4-rule rule0 comma-whitespace-b-2-4-rule rule1 ( comma-whitespace-b-2-4-rule rule10 ){2,} whitespace-b-1-4-rule "]" + rule12 ::= "[" whitespace-b-2-4-rule string-rule comma-whitespace-b-2-4-rule boolean-rule comma-whitespace-b-2-4-rule fractional-number-rule comma-whitespace-b-2-4-rule null-rule comma-whitespace-b-2-4-rule rule0 comma-whitespace-b-2-4-rule rule1 ( comma-whitespace-b-2-4-rule rule8 ){0,2} whitespace-b-1-4-rule "]" + rule13 ::= "[" whitespace-b-2-4-rule string-rule comma-whitespace-b-2-4-rule boolean-rule comma-whitespace-b-2-4-rule fractional-number-rule comma-whitespace-b-2-4-rule null-rule comma-whitespace-b-2-4-rule rule0 comma-whitespace-b-2-4-rule rule1 whitespace-b-1-4-rule "]" + rule14 ::= "[" whitespace-b-2-4-rule string-rule comma-whitespace-b-2-4-rule boolean-rule comma-whitespace-b-2-4-rule fractional-number-rule comma-whitespace-b-2-4-rule null-rule comma-whitespace-b-2-4-rule rule0 comma-whitespace-b-2-4-rule rule1 ( comma-whitespace-b-2-4-rule rule8 ){2,4} whitespace-b-1-4-rule "]" + rule15 ::= "[" whitespace-b-2-4-rule string-rule comma-whitespace-b-2-4-rule boolean-rule comma-whitespace-b-2-4-rule fractional-number-rule comma-whitespace-b-2-4-rule null-rule comma-whitespace-b-2-4-rule rule0 comma-whitespace-b-2-4-rule rule1 ( comma-whitespace-b-2-4-rule rule8 ){4} whitespace-b-1-4-rule "]"" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected one of ["1", -6] but got "extra"]'); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected one of ["1", -600] but got "extra"]'); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at most 8 items but got 10]"); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + }); + + describe("object options", () => { + test("additionalProperties", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + message: { + type: "string" + }, + percentage: { + type: "number" + } + }, + additionalProperties: { + type: "boolean" + } + } as const); + type schemaType = { + message: string, + percentage: number + } & { + [key: string]: boolean + }; + + const exampleValidValue = { + message: "Hello", + percentage: 10 + }; + const exampleValidValue2 = { + message: "Hi", + percentage: 11, + extra1: true, + extra2: false + }; + + const exampleInvalidValue = { + message: "Hello", + percentage: false + }; + const exampleInvalidValue2 = { + message: "Hi", + percentage: 11, + extra1: 10 + }; + const exampleInvalidValue3 = { + message: "Hi", + percentage: 11, + extra1: true, + extra2: 10 + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? string-rule comma-whitespace-b-1-4-rule "\\"percentage\\"" ":" [ ]? fractional-number-rule ( comma-whitespace-b-1-4-rule rule0 )* whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + fractional-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ("." [0-9]{1,16})? ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))? + boolean-rule ::= "true" | "false" + rule0 ::= string-rule ":" [ ]? boolean-rule + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected type "number" but got "boolean"]'); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected type "boolean" but got "number"]'); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected type "boolean" but got "number"]'); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + + test("minProperties", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + message: { + type: "string" + }, + percentage: { + type: "number" + } + }, + minProperties: 4, + additionalProperties: { + type: "boolean" + } + } as const); + type schemaType = { + message: string, + percentage: number + } & { + [key: string]: boolean + }; + + const exampleValidValue = { + message: "Hello", + percentage: 10, + extra1: true, + extra2: true + }; + const exampleValidValue2 = { + message: "Hi", + percentage: 11, + extra1: true, + extra2: false, + extra3: false + }; + + const exampleInvalidValue = { + message: "Hello", + percentage: 10 + }; + const exampleInvalidValue2 = { + message: "Hi", + percentage: 11, + extra1: true + }; + const exampleInvalidValue3 = { + message: "Hi", + percentage: 11, + extra1: 10 + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? string-rule comma-whitespace-b-1-4-rule "\\"percentage\\"" ":" [ ]? fractional-number-rule comma-whitespace-b-1-4-rule rule0 ( comma-whitespace-b-1-4-rule rule0 ){1,} whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + fractional-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ("." [0-9]{1,16})? ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))? + boolean-rule ::= "true" | "false" + rule0 ::= string-rule ":" [ ]? boolean-rule + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 4 properties but got 2]"); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 4 properties but got 3]"); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected type "boolean" but got "number"]'); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + + test("maxProperties", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + message: { + type: "string" + }, + percentage: { + type: "number" + } + }, + maxProperties: 4, + additionalProperties: { + type: "boolean" + } + } as const); + type schemaType = { + message: string, + percentage: number + } & { + [key: string]: boolean + }; + + const exampleValidValue = { + message: "Hello", + percentage: 10, + extra1: true + }; + const exampleValidValue2 = { + message: "Hi", + percentage: 11, + extra1: true, + extra2: false + }; + + const exampleInvalidValue = { + message: "Hello", + percentage: 10, + extra1: true, + extra2: false, + extra3: false + }; + const exampleInvalidValue2 = { + message: "Hi", + percentage: 11, + extra1: true, + extra2: false, + extra3: false, + extra4: false + }; + const exampleInvalidValue3 = { + message: "Hi", + percentage: 11, + extra1: true, + extra2: false, + extra3: false, + extra4: 10 + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? string-rule comma-whitespace-b-1-4-rule "\\"percentage\\"" ":" [ ]? fractional-number-rule ( comma-whitespace-b-1-4-rule rule0 ){0,2} whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + fractional-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ("." [0-9]{1,16})? ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))? + boolean-rule ::= "true" | "false" + rule0 ::= string-rule ":" [ ]? boolean-rule + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at most 4 properties but got 5]"); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at most 4 properties but got 6]"); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected type "boolean" but got "number"]'); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + + test("minProperties and maxProperties", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + message: { + type: "string" + }, + percentage: { + type: "number" + } + }, + minProperties: 3, + maxProperties: 4, + additionalProperties: { + type: "boolean" + } + } as const); + type schemaType = { + message: string, + percentage: number + } & { + [key: string]: boolean + }; + + const exampleValidValue = { + message: "Hello", + percentage: 10, + extra1: true + }; + const exampleValidValue2 = { + message: "Hi", + percentage: 11, + extra1: true, + extra2: false + }; + + const exampleInvalidValue = { + message: "Hello", + percentage: 10 + }; + const exampleInvalidValue2 = { + message: "Hi", + percentage: 11, + extra1: true, + extra2: false, + extra3: false + }; + const exampleInvalidValue3 = { + message: "Hi", + percentage: 11, + extra1: true, + extra2: false, + extra3: 10 + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? string-rule comma-whitespace-b-1-4-rule "\\"percentage\\"" ":" [ ]? fractional-number-rule comma-whitespace-b-1-4-rule rule0 ( comma-whitespace-b-1-4-rule rule0 )? whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + fractional-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ("." [0-9]{1,16})? ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))? + boolean-rule ::= "true" | "false" + rule0 ::= string-rule ":" [ ]? boolean-rule + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 3 properties but got 2]"); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at most 4 properties but got 5]"); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected type "boolean" but got "number"]'); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + + test("minProperties without type", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + message: { + type: "string" + }, + percentage: { + type: "number" + } + }, + minProperties: 4, + additionalProperties: true + } as const); + type schemaType = { + message: string, + percentage: number + } & { + [key: string]: any + }; + + const exampleValidValue = { + message: "Hello", + percentage: 10, + extra1: true, + extra2: null + }; + const exampleValidValue2 = { + message: "Hi", + percentage: 11, + extra1: true, + extra2: "hi", + extra3: 6 + }; + + const exampleInvalidValue = { + message: "Hello", + percentage: 10 + }; + const exampleInvalidValue2 = { + message: "Hi", + percentage: 11, + extra1: true + }; + const exampleInvalidValue3 = { + message: "Hi", + percentage: 11, + extra1: 10 + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? string-rule comma-whitespace-b-1-4-rule "\\"percentage\\"" ":" [ ]? fractional-number-rule comma-whitespace-b-1-4-rule rule5 ( comma-whitespace-b-1-4-rule rule5 ){1,} whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + fractional-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ("." [0-9]{1,16})? ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))? + boolean-rule ::= "true" | "false" + null-rule ::= "null" + comma-whitespace-no-new-lines-rule ::= "," [ ]? + whitespace-no-new-lines-rule ::= [ ]? + rule0 ::= "[" whitespace-no-new-lines-rule ( any-json-s-1-4-rule ( comma-whitespace-no-new-lines-rule any-json-s-1-4-rule )* )? whitespace-no-new-lines-rule "]" + rule1 ::= string-rule ":" [ ]? any-json-s-1-4-rule + rule2 ::= "{" whitespace-no-new-lines-rule ( rule1 ( comma-whitespace-no-new-lines-rule rule1 )* )? whitespace-no-new-lines-rule "}" + any-json-s-1-4-rule ::= ( string-rule | fractional-number-rule | boolean-rule | null-rule | rule0 | rule2 ) + comma-whitespace-b-2-4-rule ::= "," ([\\n] (" "{8} | "\\t\\t") | [ ]?) + whitespace-b-2-4-rule ::= [\\n] (" "{8} | "\\t\\t") | [ ]? + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + rule3 ::= "[" whitespace-b-2-4-rule ( any-json-s-1-4-rule ( comma-whitespace-b-2-4-rule any-json-s-1-4-rule )* )? whitespace-b-1-4-rule "]" + rule4 ::= "{" whitespace-b-2-4-rule ( rule1 ( comma-whitespace-b-2-4-rule rule1 )* )? whitespace-b-1-4-rule "}" + any-json-1-4-rule ::= ( string-rule | fractional-number-rule | boolean-rule | null-rule | rule3 | rule4 ) + rule5 ::= string-rule ":" [ ]? any-json-1-4-rule + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 4 properties but got 2]"); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 4 properties but got 3]"); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 4 properties but got 3]"); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + + test("minProperties without setting additionalProperties", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + message: { + type: "string" + }, + percentage: { + type: "number" + } + }, + minProperties: 4 + } as const); + type schemaType = { + message: string, + percentage: number + }; + + const exampleValidValue = { + message: "Hello", + percentage: 10 + }; + const exampleValidValue2 = { + message: "Hi", + percentage: 11 + }; + + const exampleInvalidValue = { + message: "Hello", + percentage: 10, + extra1: true, + extra2: true + }; + const exampleInvalidValue2 = { + message: "Hi", + percentage: 11, + extra1: true + }; + const exampleInvalidValue3 = { + message: "Hi", + percentage: 11, + extra1: 10 + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? string-rule comma-whitespace-b-1-4-rule "\\"percentage\\"" ":" [ ]? fractional-number-rule whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + fractional-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ("." [0-9]{1,16})? ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))? + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Unexpected keys: "extra1", "extra2"]'); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Unexpected keys: "extra1"]'); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Unexpected keys: "extra1"]'); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + }); + + describe("string options", () => { + test("minLength", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + text: { + type: "string", + minLength: 2 + } + } + } as const); + type schemaType = { + text: string + }; + + const exampleValidValue = { + text: "12" + }; + const exampleValidValue2 = { + text: "1\n" + }; + const exampleValidValue3 = { + text: "1234" + }; + + const exampleInvalidValue = { + text: "1" + }; + const exampleInvalidValue2 = { + text: "" + }; + const exampleInvalidValue3 = { + text: "\n" + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"text\\"" ":" [ ]? string-2-rule whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-2-rule ::= "\\"" ( string-char-rule ){2,} "\\"" + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + const parsedValue3 = grammar.parse(JSON.stringify(exampleValidValue3)); + expectTypeOf(parsedValue3).toMatchTypeOf(); + expect(parsedValue3).toEqual(exampleValidValue3); + expect(testGrammar(grammar, exampleValidValue3)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 2 characters but got 1]"); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 2 characters but got 0]"); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 2 characters but got 1]"); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + + test("maxLength", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + text: { + type: "string", + maxLength: 4 + } + } + } as const); + type schemaType = { + text: string + }; + + const exampleValidValue = { + text: "12" + }; + const exampleValidValue2 = { + text: "1\n" + }; + const exampleValidValue3 = { + text: "1234" + }; + + const exampleInvalidValue = { + text: "12345" + }; + const exampleInvalidValue2 = { + text: "1234\n" + }; + const exampleInvalidValue3 = { + text: "12 45" + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"text\\"" ":" [ ]? string-0-4-rule whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-0-4-rule ::= "\\"" ( string-char-rule ){0,4} "\\"" + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + const parsedValue3 = grammar.parse(JSON.stringify(exampleValidValue3)); + expectTypeOf(parsedValue3).toMatchTypeOf(); + expect(parsedValue3).toEqual(exampleValidValue3); + expect(testGrammar(grammar, exampleValidValue3)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at most 4 characters but got 5]"); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at most 4 characters but got 5]"); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at most 4 characters but got 5]"); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + + test("minLength and maxLength", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + text: { + type: "string", + minLength: 2, + maxLength: 4 + } + } + } as const); + type schemaType = { + text: string + }; + + const exampleValidValue = { + text: "12" + }; + const exampleValidValue2 = { + text: "123" + }; + const exampleValidValue3 = { + text: "1234" + }; + + const exampleInvalidValue = { + text: "1" + }; + const exampleInvalidValue2 = { + text: "12345" + }; + const exampleInvalidValue3 = { + text: "123456" + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"text\\"" ":" [ ]? string-2-4-rule whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-2-4-rule ::= "\\"" ( string-char-rule ){2,4} "\\"" + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + const parsedValue3 = grammar.parse(JSON.stringify(exampleValidValue3)); + expectTypeOf(parsedValue3).toMatchTypeOf(); + expect(parsedValue3).toEqual(exampleValidValue3); + expect(testGrammar(grammar, exampleValidValue3)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at least 2 characters but got 1]"); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at most 4 characters but got 5]"); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Expected at most 4 characters but got 6]"); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + + describe("formats", () => { + test("date", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + text: { + type: "string", + format: "date" + } + } + } as const); + type schemaType = { + text: string + }; + + const exampleValidValue = { + text: "2024-12-01" + }; + const exampleValidValue2 = { + text: "2000-01-01" + }; + const exampleValidValue3 = { + text: "2020-10-20" + }; + + const exampleInvalidValue = { + text: "2024-12-32" + }; + const exampleInvalidValue2 = { + text: "2024-13-20" + }; + const exampleInvalidValue3 = { + text: "2024-00-20" + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"text\\"" ":" [ ]? string-format-date-rule whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-format-date-rule ::= "\\"" [0-9]{4} "-" ("0" [1-9] | "1" [012]) "-" ("0" [1-9] | [12] [0-9] | "3" [01]) "\\"" + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + const parsedValue3 = grammar.parse(JSON.stringify(exampleValidValue3)); + expectTypeOf(parsedValue3).toMatchTypeOf(); + expect(parsedValue3).toEqual(exampleValidValue3); + expect(testGrammar(grammar, exampleValidValue3)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected a valid date string but got "2024-12-32"]'); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected a valid date string but got "2024-13-20"]'); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected a valid date string but got "2024-00-20"]'); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + }); + + test("time", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + text: { + type: "string", + format: "time" + } + } + } as const); + type schemaType = { + text: string + }; + + const exampleValidValue = { + text: "02:00:00.010Z" + }; + const exampleValidValue2 = { + text: "12:00:00Z" + }; + const exampleValidValue3 = { + text: "22:00:00+01:00" + }; + const exampleValidValue4 = { + text: "12:00:00.001+01:00" + }; + + const exampleInvalidValue = { + text: "12:00:00.000" + }; + const exampleInvalidValue2 = { + text: "12:00:00" + }; + const exampleInvalidValue3 = { + text: "24:00:00Z" + }; + const exampleInvalidValue4 = { + text: "22:60:00Z" + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"text\\"" ":" [ ]? string-format-time-rule whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-format-time-rule ::= "\\"" ([01] [0-9] | "2" [0-3]) ":" [0-5] [0-9] ":" [0-5] [0-9] ( "." [0-9]{3} )? ("Z" | ("+" | "-") ([01] [0-9] | "2" [0-3]) ":" [0-5] [0-9]) "\\"" + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + const parsedValue3 = grammar.parse(JSON.stringify(exampleValidValue3)); + expectTypeOf(parsedValue3).toMatchTypeOf(); + expect(parsedValue3).toEqual(exampleValidValue3); + expect(testGrammar(grammar, exampleValidValue3)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "dumps")).to.eql(true); + + const parsedValue4 = grammar.parse(JSON.stringify(exampleValidValue4)); + expectTypeOf(parsedValue4).toMatchTypeOf(); + expect(parsedValue4).toEqual(exampleValidValue4); + expect(testGrammar(grammar, exampleValidValue4)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue4, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue4, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected a valid time string but got "12:00:00.000"]'); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected a valid time string but got "12:00:00"]'); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected a valid time string but got "24:00:00Z"]'); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue4)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected a valid time string but got "22:60:00Z"]'); + expect(testGrammar(grammar, exampleInvalidValue4)).to.eql(false); + } + }); + + test("date-time", async () => { + const llama = await getTestLlama(); + const grammar = new LlamaJsonSchemaGrammar(llama, { + type: "object", + properties: { + text: { + type: "string", + format: "date-time" + } + } + } as const); + type schemaType = { + text: string + }; + + const exampleValidValue = { + text: "2024-12-01T02:00:00.010Z" + }; + const exampleValidValue2 = { + text: "2000-01-01T12:00:00Z" + }; + const exampleValidValue3 = { + text: "2020-10-20T22:00:00+01:00" + }; + const exampleValidValue4 = { + text: "2020-10-20T12:00:00.001+01:00" + }; + + const exampleInvalidValue = { + text: "2024-12-01T12:00:00.000" + }; + const exampleInvalidValue2 = { + text: "2024-12-32T02:00:00.010Z" + }; + const exampleInvalidValue3 = { + text: "2000-01-01T24:00:00Z" + }; + const exampleInvalidValue4 = { + text: "2024-00-20T22:00:00+01:00" + }; + + expect(grammar.grammar).toMatchInlineSnapshot(` + "root ::= "{" whitespace-b-1-4-rule "\\"text\\"" ":" [ ]? string-format-date-time-rule whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]* + string-format-date-time-rule ::= "\\"" [0-9]{4} "-" ("0" [1-9] | "1" [012]) "-" ("0" [1-9] | [12] [0-9] | "3" [01]) "T" ([01] [0-9] | "2" [0-3]) ":" [0-5] [0-9] ":" [0-5] [0-9] ( "." [0-9]{3} )? ("Z" | ("+" | "-") ([01] [0-9] | "2" [0-3]) ":" [0-5] [0-9]) "\\"" + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" + `); + + const parsedValue = grammar.parse(JSON.stringify(exampleValidValue)); + expectTypeOf(parsedValue).toMatchTypeOf(); + expect(parsedValue).toEqual(exampleValidValue); + expect(testGrammar(grammar, exampleValidValue)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue, "dumps")).to.eql(true); + + const parsedValue2 = grammar.parse(JSON.stringify(exampleValidValue2)); + expectTypeOf(parsedValue2).toMatchTypeOf(); + expect(parsedValue2).toEqual(exampleValidValue2); + expect(testGrammar(grammar, exampleValidValue2)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue2, "dumps")).to.eql(true); + + const parsedValue3 = grammar.parse(JSON.stringify(exampleValidValue3)); + expectTypeOf(parsedValue3).toMatchTypeOf(); + expect(parsedValue3).toEqual(exampleValidValue3); + expect(testGrammar(grammar, exampleValidValue3)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue3, "dumps")).to.eql(true); + + const parsedValue4 = grammar.parse(JSON.stringify(exampleValidValue4)); + expectTypeOf(parsedValue4).toMatchTypeOf(); + expect(parsedValue4).toEqual(exampleValidValue4); + expect(testGrammar(grammar, exampleValidValue4)).to.eql(true); + expect(testGrammar(grammar, exampleValidValue4, "pretty")).to.eql(true); + expect(testGrammar(grammar, exampleValidValue4, "dumps")).to.eql(true); + + try { + grammar.parse(JSON.stringify(exampleInvalidValue)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected a valid date-time string but got "2024-12-01T12:00:00.000"]'); + expect(testGrammar(grammar, exampleInvalidValue)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue2)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected a valid date-time string but got "2024-12-32T02:00:00.010Z"]'); + expect(testGrammar(grammar, exampleInvalidValue2)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue3)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected a valid date-time string but got "2000-01-01T24:00:00Z"]'); + expect(testGrammar(grammar, exampleInvalidValue3)).to.eql(false); + } + + try { + grammar.parse(JSON.stringify(exampleInvalidValue4)); + expect.unreachable("Parsing should have failed"); + } catch (err) { + expect(err).toMatchInlineSnapshot('[Error: Expected a valid date-time string but got "2024-00-20T22:00:00+01:00"]'); + expect(testGrammar(grammar, exampleInvalidValue4)).to.eql(false); + } + }); + }); + }); }); + +function testGrammar(grammar: LlamaJsonSchemaGrammar, object: any, formattingType: false | "dumps" | "pretty" = false) { + if (formattingType === "pretty") + return grammar._testText(JSON.stringify(object, undefined, 4) + "\n".repeat(4)); + else if (formattingType === "dumps") + return grammar._testText(jsonDumps(object) + "\n".repeat(4)); + + return grammar._testText(JSON.stringify(object) + "\n".repeat(4)); +} diff --git a/test/standalone/llamaEvaluator/functionCallGrammar.test.ts b/test/standalone/llamaEvaluator/functionCallGrammar.test.ts index 736b6625..b4867a9a 100644 --- a/test/standalone/llamaEvaluator/functionCallGrammar.test.ts +++ b/test/standalone/llamaEvaluator/functionCallGrammar.test.ts @@ -60,14 +60,16 @@ describe("grammar for functions", () => { expect(grammar1.grammar).toMatchInlineSnapshot( ` - "root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? string-rule "," whitespace-b-1-4-rule "\\"feeling\\"" ":" [ ]? rule2 "," whitespace-b-1-4-rule "\\"words\\"" ":" [ ]? integer-number-rule whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" - whitespace-b-1-4-rule ::= ([\\n] (" " | "\\t") | [ ]?) - string-rule ::= "\\"" ([^"\\\\\\x7F\\x00-\\x1F] | "\\\\" (["\\\\/bfnrt] | "u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]))* "\\"" - rule0 ::= "\\"good\\"" - rule1 ::= "\\"bad\\"" - rule2 ::= ( rule0 | rule1 ) - integer-number-rule ::= ("-"? ([0-9] | [1-9] [0-9]*)) - whitespace-b-0-4-rule ::= ([\\n] | [ ]?)" + "root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? string-rule comma-whitespace-b-1-4-rule "\\"feeling\\"" ":" [ ]? rule0 comma-whitespace-b-1-4-rule "\\"words\\"" ":" [ ]? integer-number-rule whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + val0 ::= "\\"good\\"" + val1 ::= "\\"bad\\"" + rule0 ::= ( val0 | val1 ) + integer-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))? + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" ` ); @@ -75,12 +77,12 @@ describe("grammar for functions", () => { expect(grammar2.grammar).toMatchInlineSnapshot( ` - "root ::= "[" whitespace-b-1-4-rule ( rule0 | rule1 ) whitespace-b-0-4-rule "]" "\\n\\n\\n\\n" - string-rule ::= "\\"" ([^"\\\\\\x7F\\x00-\\x1F] | "\\\\" (["\\\\/bfnrt] | "u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]))* "\\"" - whitespace-b-1-4-rule ::= ([\\n] (" " | "\\t") | [ ]?) - rule0 ::= ( string-rule ) ( "," whitespace-b-1-4-rule string-rule )* - rule1 ::= ( string-rule )? - whitespace-b-0-4-rule ::= ([\\n] | [ ]?)" + "root ::= "[" whitespace-b-1-4-rule ( string-rule ( comma-whitespace-b-1-4-rule string-rule )* )? whitespace-b-0-4-rule "]" "\\n\\n\\n\\n" + string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4} + string-rule ::= "\\"" string-char-rule* "\\"" + comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?) + whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]? + whitespace-b-0-4-rule ::= [\\n] | [ ]?" ` ); });