diff --git a/README.md b/README.md index 256eada..ddd2338 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ copier copy gh:quickplates/next . - package management with [`npm`](https://www.npmjs.com) - embracing [`TypeScript`](https://www.typescriptlang.org) to the fullest - server-side configuration with [`zod-config`](https://github.com/alexmarqs/zod-config) +- code generation for APIs with [`Hey API`](https://heyapi.dev) - backend for frontend pattern with [`oRPC`](https://orpc.unnoq.com) - state management with [`Valtio`](https://valtio.dev) - clean UI with [`Mantine`](https://mantine.dev) diff --git a/src/.dockerignore.jinja b/src/.dockerignore.jinja index 2f262fd..ba96c52 100644 --- a/src/.dockerignore.jinja +++ b/src/.dockerignore.jinja @@ -30,6 +30,7 @@ next-env.d.ts {%- if docs %} /docs/ {%- endif %} +/openapi/ /.copier-answers.yaml /.dockerignore /.envrc @@ -40,6 +41,7 @@ next-env.d.ts /Dockerfile /eslint.config.mjs /LICENSE +/openapi-ts.config.mts /README.md /stylelint.config.mjs /Taskfile.dist.yaml diff --git a/src/.gitignore.jinja b/src/.gitignore.jinja index ec3bcfa..5a91cf2 100644 --- a/src/.gitignore.jinja +++ b/src/.gitignore.jinja @@ -17,7 +17,7 @@ /build/ # Debug -npm-debug.log* +*.log # Typescript *.tsbuildinfo diff --git a/src/Taskfile.dist.yaml.jinja b/src/Taskfile.dist.yaml.jinja index 2ff9fb3..bfdc959 100644 --- a/src/Taskfile.dist.yaml.jinja +++ b/src/Taskfile.dist.yaml.jinja @@ -210,6 +210,33 @@ tasks: --clean --overwrite {{ '{{ .CLI_ARGS }}' }} + apis: + desc: Generate code for APIs + sources: + - openapi/**/* + - flake.lock + - "*.nix" + - openapi-ts.config.mts + - package-lock.json + - package.json + - Taskfile.dist.yaml + - "{taskfile,Taskfile}.{yaml,yml}" + - tsconfig.json + generates: + - src/common/apis/**/* + cmds: + - task: install-internal + vars: + CLI_ARGS: "" + - > + npm + exec + -- + openapi-ts + {{ '{{ .CLI_ARGS }}' }} + - task: fmt + vars: + CLI_ARGS: src/common/apis dev: desc: Run in development mode interactive: true diff --git a/src/docker-compose.yaml.jinja b/src/docker-compose.yaml.jinja index 8d4ff32..c4901a7 100644 --- a/src/docker-compose.yaml.jinja +++ b/src/docker-compose.yaml.jinja @@ -4,6 +4,10 @@ services: context: ./ network: host environment: + - "{{ envprefix }}__APIS__ICANHAZDADJOKE__HOST=${ {{- envprefix }}__APIS__ICANHAZDADJOKE__HOST:-icanhazdadjoke.com}" + - "{{ envprefix }}__APIS__ICANHAZDADJOKE__PATH=${ {{- envprefix }}__APIS__ICANHAZDADJOKE__PATH:-}" + - "{{ envprefix }}__APIS__ICANHAZDADJOKE__PORT=${ {{- envprefix }}__APIS__ICANHAZDADJOKE__PORT:-}" + - "{{ envprefix }}__APIS__ICANHAZDADJOKE__SCHEME=${ {{- envprefix }}__APIS__ICANHAZDADJOKE__SCHEME:-https}" - "{{ envprefix }}__DEBUG=${ {{- envprefix }}__DEBUG:-true}" - "{{ envprefix }}__SERVER__HOST=${ {{- envprefix }}__SERVER__HOST:-0.0.0.0}" - "{{ envprefix }}__SERVER__PORT=${ {{- envprefix }}__SERVER__PORT:-{{ port -}} }" diff --git a/src/eslint.config.mjs b/src/eslint.config.mjs index 53e1cbd..828f602 100644 --- a/src/eslint.config.mjs +++ b/src/eslint.config.mjs @@ -1,4 +1,4 @@ -import { defineConfig } from "@eslint/config-helpers"; +import { defineConfig, globalIgnores } from "@eslint/config-helpers"; import jseslint from "@eslint/js"; import nexteslint from "@next/eslint-plugin-next"; import tanstackqueryeslint from "@tanstack/eslint-plugin-query"; @@ -10,6 +10,7 @@ import globals from "globals"; import tseslint from "typescript-eslint"; const files = { + ignored: ["build/", "node_modules/", "src/common/apis/"], js: ["**/*.js", "**/*.cjs", "**/*.mjs", "**/*.jsx"], ts: ["**/*.ts", "**/*.cts", "**/*.mts", "**/*.tsx"], tsproject: [ @@ -27,6 +28,9 @@ const files = { }; export default defineConfig( + // Global ignores + globalIgnores(files.ignored), + // JavaScript support { files: files.js, diff --git a/src/openapi-ts.config.mts b/src/openapi-ts.config.mts new file mode 100644 index 0000000..6958847 --- /dev/null +++ b/src/openapi-ts.config.mts @@ -0,0 +1,122 @@ +import type { UserConfig } from "@hey-api/openapi-ts"; + +import { defineConfig } from "@hey-api/openapi-ts"; + +export default defineConfig( + [ + { + name: "icanhazdadjoke", + }, + ].map( + ({ name }) => + ({ + input: { + path: `./openapi/${name}.yaml`, + }, + + output: { + fileName: { + // Custom file name mappings + name: (name) => { + switch (name) { + case "client": + return "clnt"; + case "zod": + return "schemas"; + default: + return name; + } + }, + + // Don't add any suffix to generated files + suffix: null, + }, + + // Don't generate index file + indexFile: false, + + path: `./src/common/apis/${name}`, + }, + + parser: { + filters: { + // Exclude deprecated resources + deprecated: false, + + // Exclude orphaned resources + orphans: false, + }, + }, + + plugins: [ + // Generate types + { + definitions: { + name: "{{name}}", + }, + + errors: { + error: "{{name}}Error", + name: "{{name}}Errors", + }, + + name: "@hey-api/typescript", + + requests: { + name: "{{name}}Request", + }, + + responses: { + name: "{{name}}Responses", + response: "{{name}}Response", + }, + }, + + // Generate Zod schemas + { + // Use PascalCase for schema names + case: "PascalCase", + + definitions: { + name: "{{name}}Schema", + }, + + // Include metadata in schemas + metadata: true, + + name: "zod", + + requests: { + name: "{{name}}RequestSchema", + }, + + responses: { + name: "{{name}}ResponseSchema", + }, + }, + + // Generate Fetch API client + { + name: "@hey-api/client-fetch", + }, + + // Generate SDK + { + // Generate SDK class + asClass: true, + + // Don't use generated client by default + client: false, + + // Make SDK class instantiable + instance: true, + + name: "@hey-api/sdk", + + // Use generated schemas for validation + validator: true, + }, + ], + }) satisfies UserConfig, + ), +); diff --git a/src/openapi/icanhazdadjoke.yaml b/src/openapi/icanhazdadjoke.yaml new file mode 100644 index 0000000..68bc1ad --- /dev/null +++ b/src/openapi/icanhazdadjoke.yaml @@ -0,0 +1,41 @@ +openapi: "3.1.2" +info: + title: icanhazdadjoke + version: "1" +paths: + /: + get: + summary: Get a random joke + operationId: getRandomJoke + responses: + "200": + description: Successful response with a random joke + content: + application/json: + schema: + $ref: "#/components/schemas/GetRandomJokeSuccessResponsePayload" +components: + schemas: + GetRandomJokeSuccessResponsePayload: + description: Success response payload for getting a random joke + type: object + properties: + id: + description: Unique identifier of the joke + type: string + example: R7UfaahVfFd + joke: + description: The text of the joke + type: string + example: >- + My dog used to chase people on a bike a lot. + It got so bad I had to take his bike away. + status: + description: Status code of the response + type: integer + const: 200 + example: 200 + required: + - id + - joke + - status diff --git a/src/package-lock.json.jinja b/src/package-lock.json.jinja index 257e0fd..adc73f4 100644 --- a/src/package-lock.json.jinja +++ b/src/package-lock.json.jinja @@ -36,6 +36,7 @@ "devDependencies": { "@eslint/config-helpers": "~0.4", "@eslint/js": "~9.39", + "@hey-api/openapi-ts": "~0.88", "@lingui/cli": "~5.6", "@lingui/format-po": "~5.6", "@lingui/loader": "~5.6", @@ -121,6 +122,16 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", @@ -155,6 +166,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-globals": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", @@ -313,38 +334,28 @@ "node": ">=6.9.0" } }, - "node_modules/@cacheable/memoize": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@cacheable/memoize/-/memoize-2.0.3.tgz", - "integrity": "sha512-hl9wfQgpiydhQEIv7fkjEzTGE+tcosCXLKFDO707wYJ/78FVOlowb36djex5GdbSyeHnG62pomYLMuV/OT8Pbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cacheable/utils": "^2.0.3" - } - }, "node_modules/@cacheable/memory": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.4.tgz", - "integrity": "sha512-cCmJKCKlT1t7hNBI1+gFCwmKFd9I4pS3zqBeNGXTSODnpa0EeDmORHY8oEMTuozfdg3cgsVh8ojLaPYb6eC7Cg==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.5.tgz", + "integrity": "sha512-fkiAxCvssEyJZ5fxX4tcdZFRmW9JehSTGvvqmXn6rTzG5cH6V/3C4ad8yb01vOjp2xBydHkHrgpW0qeGtzt6VQ==", "dev": true, "license": "MIT", "dependencies": { - "@cacheable/utils": "^2.2.0", + "@cacheable/utils": "^2.3.0", "@keyv/bigmap": "^1.1.0", "hookified": "^1.12.2", - "keyv": "^5.5.3" + "keyv": "^5.5.4" } }, "node_modules/@cacheable/memory/node_modules/@keyv/bigmap": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.2.0.tgz", - "integrity": "sha512-4Lme8NejkyetZ9oJ6u8NSf0iJEFFt7I+tyDI48wZlaFmbhDEh4nZg7bEPFPwCWkpIuL50/ukWBC9AHQTmdJLUA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.0.tgz", + "integrity": "sha512-KT01GjzV6AQD5+IYrcpoYLkCu1Jod3nau1Z7EsEuViO3TZGRacSbO9MfHmbJ1WaOXFtWLxPVj169cn2WNKPkIg==", "dev": true, "license": "MIT", "dependencies": { "hashery": "^1.2.0", - "hookified": "^1.12.2" + "hookified": "^1.13.0" }, "engines": { "node": ">= 18" @@ -364,13 +375,14 @@ } }, "node_modules/@cacheable/utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.2.0.tgz", - "integrity": "sha512-7xaQayO3msdVcxXLYcLU5wDqJBNdQcPPPHr6mdTEIQI7N7TbtSVVTpWOTfjyhg0L6AQwQdq7miKdWtTDBoBldQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.3.1.tgz", + "integrity": "sha512-38NJXjIr4W1Sghun8ju+uYWD8h2c61B4dKwfnQHVDFpAJ9oS28RpfqZQJ6Dgd3RceGkILDY9YT+72HJR3LoeSQ==", "dev": true, "license": "MIT", "dependencies": { - "keyv": "^5.5.3" + "hashery": "^1.2.0", + "keyv": "^5.5.4" } }, "node_modules/@cacheable/utils/node_modules/keyv": { @@ -1181,6 +1193,70 @@ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, + "node_modules/@hey-api/codegen-core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@hey-api/codegen-core/-/codegen-core-0.3.3.tgz", + "integrity": "sha512-vArVDtrvdzFewu1hnjUm4jX1NBITlSCeO81EdWq676MxQbyxsGcDPAgohaSA+Wvr4HjPSvsg2/1s2zYxUtXebg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/hey-api" + }, + "peerDependencies": { + "typescript": ">=5.5.3" + } + }, + "node_modules/@hey-api/json-schema-ref-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@hey-api/json-schema-ref-parser/-/json-schema-ref-parser-1.2.1.tgz", + "integrity": "sha512-inPeksRLq+j3ArnuGOzQPQE//YrhezQG0+9Y9yizScBN2qatJ78fIByhEgKdNAbtguDCn4RPxmEhcrePwHxs4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/hey-api" + } + }, + "node_modules/@hey-api/openapi-ts": { + "version": "0.88.0", + "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.88.0.tgz", + "integrity": "sha512-ZrvmDfmVf+N4ry786LAhS/DoH+xkIjIJIeDnj2aL1qnMTIDsdRIXXvr80EnAZVBgunzu1wTBbHb3H9OfyDQ2EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@hey-api/codegen-core": "^0.3.3", + "@hey-api/json-schema-ref-parser": "1.2.1", + "ansi-colors": "4.1.3", + "c12": "3.3.2", + "color-support": "1.1.3", + "commander": "14.0.2", + "open": "11.0.0", + "semver": "7.7.2" + }, + "bin": { + "openapi-ts": "bin/run.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/hey-api" + }, + "peerDependencies": { + "typescript": ">=5.5.3" + } + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1857,6 +1933,13 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true, + "license": "MIT" + }, "node_modules/@keyv/serialize": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", @@ -1942,6 +2025,16 @@ "node": ">=20.0.0" } }, + "node_modules/@lingui/cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/@lingui/conf": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-5.6.0.tgz", @@ -2076,9 +2169,9 @@ } }, "node_modules/@mantine/core": { - "version": "8.3.8", - "resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.3.8.tgz", - "integrity": "sha512-UM3Za7Yl0FzbZ2zPgHwNyCpLgtSqkAi8ku13+gRS/6JB0FjwSkMwibERUqQIpwqAHdR5KNmIohjuqHu8guJowg==", + "version": "8.3.9", + "resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.3.9.tgz", + "integrity": "sha512-ivj0Crn5N521cI2eWZBsBGckg0ZYRqfOJz5vbbvYmfj65bp0EdsyqZuOxXzIcn2aUScQhskfvzyhV5XIUv81PQ==", "license": "MIT", "dependencies": { "@floating-ui/react": "^0.27.16", @@ -2089,7 +2182,7 @@ "type-fest": "^4.41.0" }, "peerDependencies": { - "@mantine/hooks": "8.3.8", + "@mantine/hooks": "8.3.9", "react": "^18.x || ^19.x", "react-dom": "^18.x || ^19.x" } @@ -2107,25 +2200,25 @@ } }, "node_modules/@mantine/dates": { - "version": "8.3.8", - "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-8.3.8.tgz", - "integrity": "sha512-N5G7ANPEZo0ObtRzCt7/4tXgChrPd9sl8xMyfdsIHJlgHGuDuQzk27zafh74yJlM49z+Yn5YZJX20DwzXFOwRQ==", + "version": "8.3.9", + "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-8.3.9.tgz", + "integrity": "sha512-XOoGrY2hydqVrn/eBmhmJnZW6fAIOTOv0TLlN/a+C/sMxAgwNLqk+hqU6Rd3WE4Hm00J1BmbJJt/g/KrvnEpNg==", "license": "MIT", "dependencies": { "clsx": "^2.1.1" }, "peerDependencies": { - "@mantine/core": "8.3.8", - "@mantine/hooks": "8.3.8", + "@mantine/core": "8.3.9", + "@mantine/hooks": "8.3.9", "dayjs": ">=1.0.0", "react": "^18.x || ^19.x", "react-dom": "^18.x || ^19.x" } }, "node_modules/@mantine/form": { - "version": "8.3.8", - "resolved": "https://registry.npmjs.org/@mantine/form/-/form-8.3.8.tgz", - "integrity": "sha512-V9/6Vk56ox9m5/gllmOjU/EEfBqxbABkZufvxrB7dgA+BLvvdSi/iS+t3FvbkRol5YcxiSRe83cN4HZTi9L04Q==", + "version": "8.3.9", + "resolved": "https://registry.npmjs.org/@mantine/form/-/form-8.3.9.tgz", + "integrity": "sha512-G7eCo5TEWGcsWHrNGwp/o1yPcCYbaMdLq6SClN+wMhAA+qaEO1ZHf9mX8fSOX78nkaoyIrZHGOhbVXcZ7hmVrQ==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -2136,34 +2229,34 @@ } }, "node_modules/@mantine/hooks": { - "version": "8.3.8", - "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.3.8.tgz", - "integrity": "sha512-2YCUk5IWz+Ebi7VpbdscUz1MwulyaVPKr236ugMfpK0PFwsun4aBaLCAc8UeMGP0LtoSkuFvnsCPR4U6rhNfeQ==", + "version": "8.3.9", + "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.3.9.tgz", + "integrity": "sha512-Dfz7W0+K1cq4Gb1WFQCZn8tsMXkLH6MV409wZR/ToqsxdNDUMJ/xxbfnwEXWEZjXNJd1wDETHgc+cZG2lTe3Xw==", "license": "MIT", "peerDependencies": { "react": "^18.x || ^19.x" } }, "node_modules/@mantine/notifications": { - "version": "8.3.8", - "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-8.3.8.tgz", - "integrity": "sha512-AS3UGnHO8UGzLpxe4cUIVpwpCoGKplWhMGm6E2hJoHnO4Wg0h3HlsR7drFEnDOZhaOMyD6MD9tAeWZ2/7rnvrw==", + "version": "8.3.9", + "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-8.3.9.tgz", + "integrity": "sha512-emUdoCyaccf/NuNmJ4fQgloJ7hEod0Pde7XIoD9xUUztVchL143oWRU2gYm6cwqzSyjpjTaqPXfz5UvEBRYjZw==", "license": "MIT", "dependencies": { - "@mantine/store": "8.3.8", + "@mantine/store": "8.3.9", "react-transition-group": "4.4.5" }, "peerDependencies": { - "@mantine/core": "8.3.8", - "@mantine/hooks": "8.3.8", + "@mantine/core": "8.3.9", + "@mantine/hooks": "8.3.9", "react": "^18.x || ^19.x", "react-dom": "^18.x || ^19.x" } }, "node_modules/@mantine/store": { - "version": "8.3.8", - "resolved": "https://registry.npmjs.org/@mantine/store/-/store-8.3.8.tgz", - "integrity": "sha512-B6LEed839OR2t9pnC7Bl3zhMyYzUvJZ46YaOpH9zCqLiFX+u4FKC+UCNzqkz2a+I+olrNlONLnrCA0NDTCjz9A==", + "version": "8.3.9", + "resolved": "https://registry.npmjs.org/@mantine/store/-/store-8.3.9.tgz", + "integrity": "sha512-Z4tYW597mD3NxHLlJ3OJ1aKucmwrD9nhqobz+142JNw01aHqzKjxVXlu3L5GGa7F3u3OjXJk/qb1QmUs4sU+Jw==", "license": "MIT", "peerDependencies": { "react": "^18.x || ^19.x" @@ -2361,51 +2454,51 @@ } }, "node_modules/@orpc/client": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/client/-/client-1.11.2.tgz", - "integrity": "sha512-Fo9rLFAPaDZkq82MZDE3+cjSwGr2u0WBPGegNNVO//vTCbABIuaEdJWvi1dCx9Es+oGIH+MW16lP5pOMmaK20Q==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/client/-/client-1.11.3.tgz", + "integrity": "sha512-USuUOvG07odUzrn3/xGE0V+JbK6DV+eYqURa98kMelSoGRLP0ceqomu49s1+paKYgT1fefRDMaCKxo04hgRNhg==", "license": "MIT", "dependencies": { - "@orpc/shared": "1.11.2", - "@orpc/standard-server": "1.11.2", - "@orpc/standard-server-fetch": "1.11.2", - "@orpc/standard-server-peer": "1.11.2" + "@orpc/shared": "1.11.3", + "@orpc/standard-server": "1.11.3", + "@orpc/standard-server-fetch": "1.11.3", + "@orpc/standard-server-peer": "1.11.3" } }, "node_modules/@orpc/contract": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/contract/-/contract-1.11.2.tgz", - "integrity": "sha512-NYSpoZ6KiZ5eqsbTAoB64SGXGk6Mdpk22Ju5taOpiPDOk2oZya6wtPBPdSIQ5iV7/JfkstuRptjhnlEpoDsZWw==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/contract/-/contract-1.11.3.tgz", + "integrity": "sha512-tEZ2jGVCtSHd6gijl/ASA9RhJOUAtaDtsDtkwARCxeA9gshxcaAHXTcG1l1Vvy4fezcj1xZ1fzS8uYWlcrVF7A==", "license": "MIT", "dependencies": { - "@orpc/client": "1.11.2", - "@orpc/shared": "1.11.2", + "@orpc/client": "1.11.3", + "@orpc/shared": "1.11.3", "@standard-schema/spec": "^1.0.0", "openapi-types": "^12.1.3" } }, "node_modules/@orpc/interop": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/interop/-/interop-1.11.2.tgz", - "integrity": "sha512-I10qsBOHcHltEek4DTYN3w8hl6Us3+aH1q3Yj+dqPhtA1dQ/uTDxcT4+XPnzrv4a4CflE6yDxnAREIZIdVz0BQ==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/interop/-/interop-1.11.3.tgz", + "integrity": "sha512-NOTXLsp1jkFyHGzZM0qST9LtCrBUr5qN7OEDpslPXm2xV6I1IFok15QoVtxg033vEBXD5AbtTVCkzmaLb5JJ1w==", "license": "MIT" }, "node_modules/@orpc/server": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/server/-/server-1.11.2.tgz", - "integrity": "sha512-3VG6K58AyxeLYLf78cCUzEoa1ntUFpNN++2E8JsYRSgCWRFg8S7pRhXyC4E+6dnzx44SZv42V8hiLR1v3OmXhg==", - "license": "MIT", - "dependencies": { - "@orpc/client": "1.11.2", - "@orpc/contract": "1.11.2", - "@orpc/interop": "1.11.2", - "@orpc/shared": "1.11.2", - "@orpc/standard-server": "1.11.2", - "@orpc/standard-server-aws-lambda": "1.11.2", - "@orpc/standard-server-fastify": "1.11.2", - "@orpc/standard-server-fetch": "1.11.2", - "@orpc/standard-server-node": "1.11.2", - "@orpc/standard-server-peer": "1.11.2", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/server/-/server-1.11.3.tgz", + "integrity": "sha512-lgwIAk8VzeoIrR/i9x2VWj/KdmCrg4lqfQeybsXABBR9xJsPAZtW3ClgjNq60+leqiGnVTpj2Xxphja22bGA0A==", + "license": "MIT", + "dependencies": { + "@orpc/client": "1.11.3", + "@orpc/contract": "1.11.3", + "@orpc/interop": "1.11.3", + "@orpc/shared": "1.11.3", + "@orpc/standard-server": "1.11.3", + "@orpc/standard-server-aws-lambda": "1.11.3", + "@orpc/standard-server-fastify": "1.11.3", + "@orpc/standard-server-fetch": "1.11.3", + "@orpc/standard-server-node": "1.11.3", + "@orpc/standard-server-peer": "1.11.3", "cookie": "^1.0.2" }, "peerDependencies": { @@ -2422,9 +2515,9 @@ } }, "node_modules/@orpc/shared": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/shared/-/shared-1.11.2.tgz", - "integrity": "sha512-XOz4cHtxNKsMnVz7THzmwOwXYsaE55Vd4BLc2Y898ZqiWhwzj3bwLtZen9X0FdquytDBz7CBWKqgU2vmOITxew==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/shared/-/shared-1.11.3.tgz", + "integrity": "sha512-hOPZhNI0oIhw91NNu4ndrmpWLdZyXTGx7tzq/bG5LwtuHuUsl4FalRsUfSIuap/V1ESOnPqSzmmSOdRv+ITcRA==", "license": "MIT", "dependencies": { "radash": "^12.1.1", @@ -2440,35 +2533,35 @@ } }, "node_modules/@orpc/standard-server": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/standard-server/-/standard-server-1.11.2.tgz", - "integrity": "sha512-AXMNHXDgUCCfO4DCFGteCmWSrnG6FbydVBEMA0/HacGwi5oxDa3psHwEl/Zp7vRgTtHBiZsxaCfWQEjM+8e+2A==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/standard-server/-/standard-server-1.11.3.tgz", + "integrity": "sha512-j61f0TqITURN+5zft3vDjuyHjwTkusx91KrTGxfZ3E6B/dP2SLtoPCvTF8aecozxb5KvyhvAvbuDQMPeyqXvDg==", "license": "MIT", "dependencies": { - "@orpc/shared": "1.11.2" + "@orpc/shared": "1.11.3" } }, "node_modules/@orpc/standard-server-aws-lambda": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/standard-server-aws-lambda/-/standard-server-aws-lambda-1.11.2.tgz", - "integrity": "sha512-6BnsGRPRwlLLRm7vigddr/VW19+pQw1iAZ9nCF6WHp2kUwKbdcF9O1ksxvvJhAW2pncyPBPjEpli8MZ1hG3oyA==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/standard-server-aws-lambda/-/standard-server-aws-lambda-1.11.3.tgz", + "integrity": "sha512-LYJkps5hRKtBpeVeXE5xxdXhgPFj8I1wPtl+PJj06LIkuwuNWEmWdlrGH5lcyh5pWtJn8yJSDOIuGqHbuMTB7Q==", "license": "MIT", "dependencies": { - "@orpc/shared": "1.11.2", - "@orpc/standard-server": "1.11.2", - "@orpc/standard-server-fetch": "1.11.2", - "@orpc/standard-server-node": "1.11.2" + "@orpc/shared": "1.11.3", + "@orpc/standard-server": "1.11.3", + "@orpc/standard-server-fetch": "1.11.3", + "@orpc/standard-server-node": "1.11.3" } }, "node_modules/@orpc/standard-server-fastify": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/standard-server-fastify/-/standard-server-fastify-1.11.2.tgz", - "integrity": "sha512-zxCcbQAhNCUKQuYB1LOchiHkbl0i3h19wbiY6KjAvu6cdZ74/8DJ6ARrkjCCHe/uHR5NW6u32CulO2/ohNXKVg==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/standard-server-fastify/-/standard-server-fastify-1.11.3.tgz", + "integrity": "sha512-Zom7Q4dDZW27KE4gco9HEH59dmBx2GLIqoRuy8LB97boktsGlbF/CVQ2W1ivcLOZ4yuJ0YXmq4egoWQ20apZww==", "license": "MIT", "dependencies": { - "@orpc/shared": "1.11.2", - "@orpc/standard-server": "1.11.2", - "@orpc/standard-server-node": "1.11.2" + "@orpc/shared": "1.11.3", + "@orpc/standard-server": "1.11.3", + "@orpc/standard-server-node": "1.11.3" }, "peerDependencies": { "fastify": ">=5.6.1" @@ -2480,46 +2573,46 @@ } }, "node_modules/@orpc/standard-server-fetch": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/standard-server-fetch/-/standard-server-fetch-1.11.2.tgz", - "integrity": "sha512-FhA9oLEejd7ebqN5vxx2l3L8g5djhgVodGykwHiDSQJo0erXIZ0n5S+YpvW6fFiRe+3k8h+U6K2ERaAL5wZXxw==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/standard-server-fetch/-/standard-server-fetch-1.11.3.tgz", + "integrity": "sha512-wiudo8W/NHaosygIpU/NJGZVBTueSHSRU4y0pIwvAhA0f9ZQ9/aCwnYxR7lnvCizzb2off8kxxKKqkS3xYRepA==", "license": "MIT", "dependencies": { - "@orpc/shared": "1.11.2", - "@orpc/standard-server": "1.11.2" + "@orpc/shared": "1.11.3", + "@orpc/standard-server": "1.11.3" } }, "node_modules/@orpc/standard-server-node": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/standard-server-node/-/standard-server-node-1.11.2.tgz", - "integrity": "sha512-Zae1WwhWfTS+1bfGx6IqHem2uuDsUMntpp+ymh+U9AlOzzCLdFtfYwScPNsuZhhuyGU9rBJpRjh1YCgeBZSanw==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/standard-server-node/-/standard-server-node-1.11.3.tgz", + "integrity": "sha512-PvGKFMs1CGZ/phiftEadUh1KwLZXgN2Q5XEw2NNE8Q8YXAClwPBSLcCRp4dVRMwo06hONznW04uUubh2OA0MWA==", "license": "MIT", "dependencies": { - "@orpc/shared": "1.11.2", - "@orpc/standard-server": "1.11.2", - "@orpc/standard-server-fetch": "1.11.2" + "@orpc/shared": "1.11.3", + "@orpc/standard-server": "1.11.3", + "@orpc/standard-server-fetch": "1.11.3" } }, "node_modules/@orpc/standard-server-peer": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/standard-server-peer/-/standard-server-peer-1.11.2.tgz", - "integrity": "sha512-TAnhNiaNN5e6UHxdT5D1ZY8fseKDXnr3UmZidX2CghJj967f9+SLl1FFtuzJ7SO06uGBdARyV6azIoKlFpt+gA==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/standard-server-peer/-/standard-server-peer-1.11.3.tgz", + "integrity": "sha512-GkINRYjWRTOKQIsPWvqCvbjNjaLnhDAVJLrQNGTaqy7yLTDG8ome7hCrmH3bdjDY4nDlt8OoUaq9oABE/1rMew==", "license": "MIT", "dependencies": { - "@orpc/shared": "1.11.2", - "@orpc/standard-server": "1.11.2" + "@orpc/shared": "1.11.3", + "@orpc/standard-server": "1.11.3" } }, "node_modules/@orpc/tanstack-query": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@orpc/tanstack-query/-/tanstack-query-1.11.2.tgz", - "integrity": "sha512-X8GCBgDuHINIE6d8sDbifbPSKzuVgg6qGItb5geqtbyV6WRs2YolYleC91XCIW64kTTPMs3H8b/qyi8mrhQbDg==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@orpc/tanstack-query/-/tanstack-query-1.11.3.tgz", + "integrity": "sha512-oGCoNqQcVs/BH8pCjMQ2UPfuLvXtIkybMlVb3oG7/LKb7KnWPRUvadsCeKNOFGp+8zyrJkUJqkKV2DlHbihW5g==", "license": "MIT", "dependencies": { - "@orpc/shared": "1.11.2" + "@orpc/shared": "1.11.3" }, "peerDependencies": { - "@orpc/client": "1.11.2", + "@orpc/client": "1.11.3", "@tanstack/query-core": ">=5.80.2" } }, @@ -2554,22 +2647,22 @@ } }, "node_modules/@rsdoctor/client": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@rsdoctor/client/-/client-1.3.9.tgz", - "integrity": "sha512-ZXpk6iJ+ytxmHPLjBBLkX5a3TIAThPgWkCYW/rGtS7AIakMlB2EnRW7HBimu7pwjdBc2O6EYQd4Amdebyw80DA==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@rsdoctor/client/-/client-1.3.11.tgz", + "integrity": "sha512-OLu71555PSvD/U+z51gChFmIGcSo97U0UiI6XqzFboc1BjJLy5wpphs/Ez0wNXCvJIZ41aExq9UycZ4PNrmEhA==", "license": "MIT" }, "node_modules/@rsdoctor/core": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@rsdoctor/core/-/core-1.3.9.tgz", - "integrity": "sha512-JsiemXVORXct+XN9AOxkEWNCJ4khVDjCd64ekinPc+V63LJ8M4nVfjgfmYck59JToY236hUTQI9MJ0OvzqmoFQ==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@rsdoctor/core/-/core-1.3.11.tgz", + "integrity": "sha512-sFXowN0oGbW2X372Wu1/JbA7eINjUTzp8qX4eY1DTjupgsGlDpQuorRTaHoAhKYRRb5xJsfnBH6ElFAqgqUUMg==", "license": "MIT", "dependencies": { "@rsbuild/plugin-check-syntax": "1.5.0", - "@rsdoctor/graph": "1.3.9", - "@rsdoctor/sdk": "1.3.9", - "@rsdoctor/types": "1.3.9", - "@rsdoctor/utils": "1.3.9", + "@rsdoctor/graph": "1.3.11", + "@rsdoctor/sdk": "1.3.11", + "@rsdoctor/types": "1.3.11", + "@rsdoctor/utils": "1.3.11", "browserslist-load-config": "^1.0.1", "enhanced-resolve": "5.12.0", "es-toolkit": "^1.41.0", @@ -2601,13 +2694,13 @@ } }, "node_modules/@rsdoctor/graph": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@rsdoctor/graph/-/graph-1.3.9.tgz", - "integrity": "sha512-wIfW6K8QEEqkP+OnXVctDDNL3A0GDh74fbAUkkv6Av7QluxRC7KuoJtF+Iky9C3crWeNP9CRZEeK/UPiez80iw==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@rsdoctor/graph/-/graph-1.3.11.tgz", + "integrity": "sha512-GlvF0JTTRImitVQC78q0/rIdFdgHb8jIr0Ff6nGIYq8iro+LsHuR40BrN+Y7ezB+YN7+anFqx2ksjcH9EY0W2w==", "license": "MIT", "dependencies": { - "@rsdoctor/types": "1.3.9", - "@rsdoctor/utils": "1.3.9", + "@rsdoctor/types": "1.3.11", + "@rsdoctor/utils": "1.3.11", "es-toolkit": "^1.41.0", "path-browserify": "1.0.1", "source-map": "^0.7.6" @@ -2623,24 +2716,24 @@ } }, "node_modules/@rsdoctor/sdk": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@rsdoctor/sdk/-/sdk-1.3.9.tgz", - "integrity": "sha512-fattCaeG1B5QOkywZwN342RuCmDs7G2u/ekpj0qBztU9l+UbkMaU88OXLjZTzniW2E6Vo2NjvogvLbwCuAJQRw==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@rsdoctor/sdk/-/sdk-1.3.11.tgz", + "integrity": "sha512-4S+KXAzRdFff56bq1KZ/x7oyepBcEfz7sGjs94V3NoKbvZKvc/5MxyVSWGf58Uubjj0fzDWR5FYagwGEEEviug==", "license": "MIT", "dependencies": { - "@rsdoctor/client": "1.3.9", - "@rsdoctor/graph": "1.3.9", - "@rsdoctor/types": "1.3.9", - "@rsdoctor/utils": "1.3.9", + "@rsdoctor/client": "1.3.11", + "@rsdoctor/graph": "1.3.11", + "@rsdoctor/types": "1.3.11", + "@rsdoctor/utils": "1.3.11", "safer-buffer": "2.1.2", "socket.io": "4.8.1", "tapable": "2.2.3" } }, "node_modules/@rsdoctor/types": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@rsdoctor/types/-/types-1.3.9.tgz", - "integrity": "sha512-SR+qCmxS/YTqemeq2JbiuoYVZ5ycJKMiDudlBykf0UrOAZc6cgFY4FAK9rvDLwH1hxu77x0IUuxkIdPD1swKvw==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@rsdoctor/types/-/types-1.3.11.tgz", + "integrity": "sha512-qQG92tmrDp/qd08Qu1zXjV0zZQabVH0qYYVR0AAPMfAoPhg2Q5pp9dtuK2197jKpzjBV8dLDAisXTqRbt6+tCg==", "license": "MIT", "dependencies": { "@types/connect": "3.4.38", @@ -2671,13 +2764,13 @@ } }, "node_modules/@rsdoctor/utils": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@rsdoctor/utils/-/utils-1.3.9.tgz", - "integrity": "sha512-uXvxjLBZ+1Xig71OpUf4z66ap4SuuiGP3EIHGwjWC6+e0A3x9b3q79PfcA8yAX0q4LRWhKpEDlKY/HVlNVqtQQ==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@rsdoctor/utils/-/utils-1.3.11.tgz", + "integrity": "sha512-PnU59Qphmtz+VDoDkoaJ8d9IkMcHPe7kClPCfVKHap0Uyv+X6pWVBOgZlSiAksSAGFWxP6zeu5SGHXoROFmOog==", "license": "MIT", "dependencies": { "@babel/code-frame": "7.26.2", - "@rsdoctor/types": "1.3.9", + "@rsdoctor/types": "1.3.11", "@types/estree": "1.0.5", "acorn": "^8.10.0", "acorn-import-attributes": "^1.9.5", @@ -2708,16 +2801,16 @@ } }, "node_modules/@rsdoctor/webpack-plugin": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@rsdoctor/webpack-plugin/-/webpack-plugin-1.3.9.tgz", - "integrity": "sha512-a0wxROhqgCo7Z7qyvFzR8b0pD/2nK7uio0sznK8sC304KzJQAXsIDbbdQgofaWLmtJQEfaCQG3Rz1F56QO67Rg==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@rsdoctor/webpack-plugin/-/webpack-plugin-1.3.11.tgz", + "integrity": "sha512-d3znK93hBhRvEGc8HCA3Jcl+TZh44LdsMQIBphWChH+U3qUMlt8o+qrAqC0pMSN+0QI7ONlF/qQflx0CNgmc1g==", "license": "MIT", "dependencies": { - "@rsdoctor/core": "1.3.9", - "@rsdoctor/graph": "1.3.9", - "@rsdoctor/sdk": "1.3.9", - "@rsdoctor/types": "1.3.9", - "@rsdoctor/utils": "1.3.9" + "@rsdoctor/core": "1.3.11", + "@rsdoctor/graph": "1.3.11", + "@rsdoctor/sdk": "1.3.11", + "@rsdoctor/types": "1.3.11", + "@rsdoctor/utils": "1.3.11" }, "peerDependencies": { "webpack": "5.x" @@ -2769,9 +2862,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.90.9", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.9.tgz", - "integrity": "sha512-UFOCQzi6pRGeVTVlPNwNdnAvT35zugcIydqjvFUzG62dvz2iVjElmNp/hJkUoM5eqbUPfSU/GJIr/wbvD8bTUw==", + "version": "5.90.10", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.10.tgz", + "integrity": "sha512-EhZVFu9rl7GfRNuJLJ3Y7wtbTnENsvzp+YpcAV7kCYiXni1v8qZh++lpw4ch4rrwC0u/EZRnBHIehzCGzwXDSQ==", "license": "MIT", "funding": { "type": "github", @@ -2790,12 +2883,12 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.90.9", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.9.tgz", - "integrity": "sha512-Zke2AaXiaSfnG8jqPZR52m8SsclKT2d9//AgE/QIzyNvbpj/Q2ln+FsZjb1j69bJZUouBvX2tg9PHirkTm8arw==", + "version": "5.90.10", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.10.tgz", + "integrity": "sha512-BKLss9Y8PQ9IUjPYQiv3/Zmlx92uxffUOX8ZZNoQlCIZBJPT5M+GOMQj7xislvVQ6l1BstBjcX0XB/aHfFYVNw==", "license": "MIT", "dependencies": { - "@tanstack/query-core": "5.90.9" + "@tanstack/query-core": "5.90.10" }, "funding": { "type": "github", @@ -2824,9 +2917,9 @@ } }, "node_modules/@tsconfig/bases": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/bases/-/bases-1.0.11.tgz", - "integrity": "sha512-8ARzf0afO+osYr/Y7cQJ4laxVCic2it8g+Hpi4HHFJYFpJFmaVa6lpH3EBzzp6EoOANNIVRsEpz1yQDFa9oY5A==", + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@tsconfig/bases/-/bases-1.0.14.tgz", + "integrity": "sha512-0UrXL0ftQWdl59XODZyX7OCgDbvLwAGbRmAqPa5Wx6w7KmL0r4wY1IvVuFRdtyJmsjf/lWStIHeqxBYB4mtrWg==", "dev": true, "license": "MIT" }, @@ -2919,13 +3012,13 @@ } }, "node_modules/@types/react": { - "version": "19.2.5", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.5.tgz", - "integrity": "sha512-keKxkZMqnDicuvFoJbzrhbtdLSPhj/rZThDlKWCDbgXmUg0rEUFtRssDXKYmtXluZlIqiC5VqkCgRwzuyLHKHw==", + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.6.tgz", + "integrity": "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==", "devOptional": true, "license": "MIT", "dependencies": { - "csstype": "^3.0.2" + "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { @@ -2994,6 +3087,178 @@ "typescript": ">=4.8.4 <6.0.0" } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/project-service": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz", + "integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.46.4", + "@typescript-eslint/types": "^8.46.4", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz", + "integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz", + "integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz", + "integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz", + "integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.46.4", + "@typescript-eslint/tsconfig-utils": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz", + "integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/typescript-estree": "8.46.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz", + "integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.4", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "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-eslint/eslint-plugin/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", @@ -3029,7 +3294,7 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/project-service": { + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/project-service": { "version": "8.46.4", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz", "integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==", @@ -3051,7 +3316,7 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/scope-manager": { + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { "version": "8.46.4", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz", "integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==", @@ -3069,7 +3334,7 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/tsconfig-utils": { "version": "8.46.4", "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz", "integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==", @@ -3086,35 +3351,355 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/type-utils": { + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.4.tgz", - "integrity": "sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz", + "integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==", "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.46.4", - "@typescript-eslint/typescript-estree": "8.46.4", - "@typescript-eslint/utils": "8.46.4", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz", + "integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.46.4", + "@typescript-eslint/tsconfig-utils": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4", "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz", + "integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.4", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "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-eslint/parser/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz", + "integrity": "sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.47.0", + "@typescript-eslint/types": "^8.47.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.47.0.tgz", + "integrity": "sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.47.0.tgz", + "integrity": "sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.4.tgz", + "integrity": "sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/typescript-estree": "8.46.4", + "@typescript-eslint/utils": "8.46.4", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/project-service": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz", + "integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.46.4", + "@typescript-eslint/types": "^8.46.4", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz", + "integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz", + "integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz", + "integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz", + "integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.46.4", + "@typescript-eslint/tsconfig-utils": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz", + "integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/typescript-estree": "8.46.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz", + "integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.4", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "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-eslint/type-utils/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz", - "integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.47.0.tgz", + "integrity": "sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==", "dev": true, "license": "MIT", "engines": { @@ -3126,16 +3711,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz", - "integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.47.0.tgz", + "integrity": "sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.46.4", - "@typescript-eslint/tsconfig-utils": "8.46.4", - "@typescript-eslint/types": "8.46.4", - "@typescript-eslint/visitor-keys": "8.46.4", + "@typescript-eslint/project-service": "8.47.0", + "@typescript-eslint/tsconfig-utils": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3171,30 +3756,17 @@ "node": ">=8.6.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/utils": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz", - "integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.47.0.tgz", + "integrity": "sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.46.4", - "@typescript-eslint/types": "8.46.4", - "@typescript-eslint/typescript-estree": "8.46.4" + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3209,13 +3781,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz", - "integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.47.0.tgz", + "integrity": "sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/types": "8.47.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -3557,6 +4129,16 @@ "license": "MIT", "peer": true }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -3825,9 +4407,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.8.28", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.28.tgz", - "integrity": "sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==", + "version": "2.8.31", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.31.tgz", + "integrity": "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.js" @@ -3961,19 +4543,93 @@ "license": "MIT", "peer": true }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/c12": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.3.2.tgz", + "integrity": "sha512-QkikB2X5voO1okL3QsES0N690Sn/K9WokXqUsDQsWy5SnYb+psYQFGA10iy1bZHj3fjISKsI67Q90gruvWWM3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^17.2.3", + "exsolve": "^1.0.8", + "giget": "^2.0.0", + "jiti": "^2.6.1", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^2.0.0", + "pkg-types": "^2.3.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "*" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/c12/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/cacheable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.1.1.tgz", - "integrity": "sha512-LmF4AXiSNdiRbI2UjH8pAp9NIXxeQsTotpEaegPiDcnN0YPygDJDV3l/Urc0mL72JWdATEorKqIHEx55nDlONg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.2.0.tgz", + "integrity": "sha512-LEJxRqfeomiiRd2t0uON6hxAtgOoWDfY3fugebbz+J3vDLO+SkdfFChQcOHTZhj9SYa9iwE9MGYNX72dKiOE4w==", "dev": true, "license": "MIT", "dependencies": { - "@cacheable/memoize": "^2.0.3", - "@cacheable/memory": "^2.0.3", - "@cacheable/utils": "^2.1.0", - "hookified": "^1.12.2", - "keyv": "^5.5.3", - "qified": "^0.5.0" + "@cacheable/memory": "^2.0.5", + "@cacheable/utils": "^2.3.0", + "hookified": "^1.13.0", + "keyv": "^5.5.4", + "qified": "^0.5.2" } }, "node_modules/cacheable/node_modules/keyv": { @@ -4070,9 +4726,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001754", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", - "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", + "version": "1.0.30001756", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", + "integrity": "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==", "funding": [ { "type": "opencollective", @@ -4138,6 +4794,16 @@ "node": ">=6.0" } }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -4221,6 +4887,16 @@ "devOptional": true, "license": "MIT" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", @@ -4239,13 +4915,13 @@ } }, "node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", + "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=14" + "node": ">=20" } }, "node_modules/concat-map": { @@ -4255,6 +4931,23 @@ "dev": true, "license": "MIT" }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -4364,9 +5057,9 @@ } }, "node_modules/csstype": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.1.tgz", - "integrity": "sha512-98XGutrXoh75MlgLihlNxAGbUuFQc7l1cqcnEZlLNKc0UrVdPndgmaDmYTDDh929VS/eqTZV0rozmhu2qqT1/g==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/data-view-buffer": { @@ -4477,6 +5170,36 @@ "dev": true, "license": "MIT" }, + "node_modules/default-browser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", + "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -4508,6 +5231,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", @@ -4526,6 +5262,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true, + "license": "MIT" + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -4535,6 +5278,13 @@ "node": ">=6" } }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "dev": true, + "license": "MIT" + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -4654,6 +5404,19 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -4677,9 +5440,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.253", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.253.tgz", - "integrity": "sha512-O0tpQ/35rrgdiGQ0/OFWhy1itmd9A6TY9uQzlqj3hKSu/aYpe7UIn5d7CU2N9myH6biZiWF3VMZVuup8pw5U9w==", + "version": "1.5.259", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.259.tgz", + "integrity": "sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -5252,6 +6015,16 @@ "node": "*" } }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-scope": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", @@ -5435,6 +6208,13 @@ "node": ">=0.8.x" } }, + "node_modules/exsolve": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", + "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -5782,16 +6562,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, "node_modules/glob": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", - "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", - "minimatch": "^10.0.3", + "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" @@ -6390,6 +7188,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -6459,6 +7273,38 @@ "node": ">=0.10.0" } }, + "node_modules/is-in-ssh": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz", + "integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -6703,6 +7549,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -7031,6 +7893,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -7363,6 +8232,13 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "dev": true, + "license": "MIT" + }, "node_modules/node-releases": { "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", @@ -7376,7 +8252,27 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.10.0" + } + }, + "node_modules/nypm": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz", + "integrity": "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==", + "dev": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.3.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" } }, "node_modules/object-assign": { @@ -7493,6 +8389,13 @@ "dev": true, "license": "MIT" }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true, + "license": "MIT" + }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -7509,6 +8412,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz", + "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.4.0", + "define-lazy-prop": "^3.0.0", + "is-in-ssh": "^1.0.0", + "is-inside-container": "^1.0.0", + "powershell-utils": "^0.1.0", + "wsl-utils": "^0.3.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/openapi-types": { "version": "12.1.3", "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", @@ -7723,6 +8647,20 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -7742,6 +8680,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, "node_modules/pofile": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/pofile/-/pofile-1.1.4.tgz", @@ -7999,6 +8949,19 @@ "dev": true, "license": "MIT" }, + "node_modules/powershell-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", + "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -8061,9 +9024,9 @@ "license": "MIT" }, "node_modules/pseudolocale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pseudolocale/-/pseudolocale-2.1.0.tgz", - "integrity": "sha512-af5fsrRvVwD+MBasBJvuDChT0KDqT0nEwD9NTgbtHJ16FKomWac9ua0z6YVNB4G9x9IOaiGWym62aby6n4tFMA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pseudolocale/-/pseudolocale-2.2.0.tgz", + "integrity": "sha512-O+D2eU7fO9wVLqrohvt9V/9fwMadnJQ4jxwiK+LeNEqhMx8JYx4xQHkArDCJFAdPPOp/pQq6z5L37eBvAoc8jw==", "dev": true, "license": "MIT", "dependencies": { @@ -8076,6 +9039,16 @@ "node": ">=16.0.0" } }, + "node_modules/pseudolocale/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -8139,6 +9112,17 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, "node_modules/react": { "version": "19.2.0", "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", @@ -8435,6 +9419,19 @@ "integrity": "sha512-93DpwwaiRrLz7fJ5z6Uwb171hHBws1VVsWjU6IruLFX63BicLA44QNu0sfn3guKHnBHZMFSKO8akfx5QhjuegQ==", "license": "MIT" }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -8604,13 +9601,16 @@ "peer": true }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "devOptional": true, + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/serialize-javascript": { @@ -9610,15 +10610,15 @@ } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.18", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.18.tgz", - "integrity": "sha512-JUPnFgHMuAVmLmoH9/zoZ6RHOt5n9NlUw/sDXsTbROJ2SFoS2DS4s+swAV6UTeTbGH/CAsZIE6M8TaG/3jVxgQ==", + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.19.tgz", + "integrity": "sha512-l/K33newPTZMTGAnnzaiqSl6NnH7Namh8jBNjrgjprWxGmZUuxx/sJNIRaijOh3n7q7ESbhNZC+pvVZMFdeU4A==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^2.1.0", + "cacheable": "^2.2.0", "flatted": "^3.3.3", - "hookified": "^1.12.0" + "hookified": "^1.13.0" } }, "node_modules/stylelint/node_modules/ignore": { @@ -9913,6 +10913,16 @@ "esm": "^3.2.25" } }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -10156,6 +11166,178 @@ "typescript": ">=4.8.4 <6.0.0" } }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/project-service": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz", + "integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.46.4", + "@typescript-eslint/types": "^8.46.4", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz", + "integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz", + "integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz", + "integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz", + "integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.46.4", + "@typescript-eslint/tsconfig-utils": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz", + "integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/typescript-estree": "8.46.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz", + "integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.4", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/typescript-eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "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-eslint/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -10414,9 +11596,9 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.102.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.1.tgz", - "integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==", + "version": "5.103.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.103.0.tgz", + "integrity": "sha512-HU1JOuV1OavsZ+mfigY0j8d1TgQgbZ6M+J75zDkpEAwYeXjWSqrGJtgnPblJjd/mAyTNQ7ygw0MiKOn6etz8yw==", "license": "MIT", "peer": true, "dependencies": { @@ -10437,7 +11619,7 @@ "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", + "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", @@ -10796,6 +11978,23 @@ } } }, + "node_modules/wsl-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.0.tgz", + "integrity": "sha512-3sFIGLiaDP7rTO4xh3g+b3AzhYDIUGGywE/WsmqzJWDxus5aJXVnPTNC/6L+r2WzrwXqVOdD262OaO+cEyPMSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0", + "powershell-utils": "^0.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/src/package.json.jinja b/src/package.json.jinja index d0475bf..8088550 100644 --- a/src/package.json.jinja +++ b/src/package.json.jinja @@ -42,6 +42,7 @@ "devDependencies": { "@eslint/config-helpers": "~0.4", "@eslint/js": "~9.39", + "@hey-api/openapi-ts": "~0.88", "@lingui/cli": "~5.6", "@lingui/format-po": "~5.6", "@lingui/loader": "~5.6", diff --git a/src/src/app/(root)/(main)/(home)/schemas.ts b/src/src/app/(root)/(main)/(home)/schemas.ts index 997401d..1d677ad 100644 --- a/src/src/app/(root)/(main)/(home)/schemas.ts +++ b/src/src/app/(root)/(main)/(home)/schemas.ts @@ -3,6 +3,6 @@ import * as z from "zod"; export const Schemas = { Path: undefined as never, Query: z.object({ - foo: z.coerce.string().optional().catch(undefined), + foo: z.string().optional().catch(undefined), }), }; diff --git a/src/src/client/test/components/test/test-widget/main.tsx b/src/src/client/test/components/test/test-widget/main.tsx index 9f0dfb8..3fbc0af 100644 --- a/src/src/client/test/components/test/test-widget/main.tsx +++ b/src/src/client/test/components/test/test-widget/main.tsx @@ -31,9 +31,11 @@ export function TestWidget({}: TestWidgetInput) { const handleSubmit = useCallback( async ({ values }: TestFormSubmitInput) => { try { - await validateMutation.mutateAsync({ value: values.value }); + const { message } = await validateMutation.mutateAsync({ + value: values.value, + }); - notifications.success({ message: msg({ message: "Submitted!" }) }); + notifications.success({ message: message }); } catch (error) { if (isOrpcDefinedError(error) && error.code === "BAD_REQUEST") { notifications.error({ message: msg({ message: "Invalid input" }) }); diff --git a/src/src/common/apis/icanhazdadjoke/client/clnt.ts b/src/src/common/apis/icanhazdadjoke/client/clnt.ts new file mode 100644 index 0000000..664cbc4 --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/client/clnt.ts @@ -0,0 +1,301 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createSseClient } from "../core/serverSentEvents"; +import type { HttpMethod } from "../core/types"; +import { getValidRequestBody } from "../core/utils"; +import type { + Client, + Config, + RequestOptions, + ResolvedRequestOptions, +} from "./types"; +import { + buildUrl, + createConfig, + createInterceptors, + getParseAs, + mergeConfigs, + mergeHeaders, + setAuthParams, +} from "./utils"; + +type ReqInit = Omit & { + body?: any; + headers: ReturnType; +}; + +export const createClient = (config: Config = {}): Client => { + let _config = mergeConfigs(createConfig(), config); + + const getConfig = (): Config => ({ ..._config }); + + const setConfig = (config: Config): Config => { + _config = mergeConfigs(_config, config); + return getConfig(); + }; + + const interceptors = createInterceptors< + Request, + Response, + unknown, + ResolvedRequestOptions + >(); + + const beforeRequest = async (options: RequestOptions) => { + const opts = { + ..._config, + ...options, + fetch: options.fetch ?? _config.fetch ?? globalThis.fetch, + headers: mergeHeaders(_config.headers, options.headers), + serializedBody: undefined, + }; + + if (opts.security) { + await setAuthParams({ + ...opts, + security: opts.security, + }); + } + + if (opts.requestValidator) { + await opts.requestValidator(opts); + } + + if (opts.body !== undefined && opts.bodySerializer) { + opts.serializedBody = opts.bodySerializer(opts.body); + } + + // remove Content-Type header if body is empty to avoid sending invalid requests + if (opts.body === undefined || opts.serializedBody === "") { + opts.headers.delete("Content-Type"); + } + + const url = buildUrl(opts); + + return { opts, url }; + }; + + const request: Client["request"] = async (options) => { + // @ts-expect-error + const { opts, url } = await beforeRequest(options); + const requestInit: ReqInit = { + redirect: "follow", + ...opts, + body: getValidRequestBody(opts), + }; + + let request = new Request(url, requestInit); + + for (const fn of interceptors.request.fns) { + if (fn) { + request = await fn(request, opts); + } + } + + // fetch must be assigned here, otherwise it would throw the error: + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation + const _fetch = opts.fetch!; + let response: Response; + + try { + response = await _fetch(request); + } catch (error) { + // Handle fetch exceptions (AbortError, network errors, etc.) + let finalError = error; + + for (const fn of interceptors.error.fns) { + if (fn) { + finalError = (await fn( + error, + undefined as any, + request, + opts, + )) as unknown; + } + } + + finalError = finalError || ({} as unknown); + + if (opts.throwOnError) { + throw finalError; + } + + // Return error response + return opts.responseStyle === "data" + ? undefined + : { + error: finalError, + request, + response: undefined as any, + }; + } + + for (const fn of interceptors.response.fns) { + if (fn) { + response = await fn(response, request, opts); + } + } + + const result = { + request, + response, + }; + + if (response.ok) { + const parseAs = + (opts.parseAs === "auto" + ? getParseAs(response.headers.get("Content-Type")) + : opts.parseAs) ?? "json"; + + if ( + response.status === 204 || + response.headers.get("Content-Length") === "0" + ) { + let emptyData: any; + switch (parseAs) { + case "arrayBuffer": + case "blob": + case "text": + emptyData = await response[parseAs](); + break; + case "formData": + emptyData = new FormData(); + break; + case "stream": + emptyData = response.body; + break; + case "json": + default: + emptyData = {}; + break; + } + return opts.responseStyle === "data" + ? emptyData + : { + data: emptyData, + ...result, + }; + } + + let data: any; + switch (parseAs) { + case "arrayBuffer": + case "blob": + case "formData": + case "json": + case "text": + data = await response[parseAs](); + break; + case "stream": + return opts.responseStyle === "data" + ? response.body + : { + data: response.body, + ...result, + }; + } + + if (parseAs === "json") { + if (opts.responseValidator) { + await opts.responseValidator(data); + } + + if (opts.responseTransformer) { + data = await opts.responseTransformer(data); + } + } + + return opts.responseStyle === "data" + ? data + : { + data, + ...result, + }; + } + + const textError = await response.text(); + let jsonError: unknown; + + try { + jsonError = JSON.parse(textError); + } catch { + // noop + } + + const error = jsonError ?? textError; + let finalError = error; + + for (const fn of interceptors.error.fns) { + if (fn) { + finalError = (await fn(error, response, request, opts)) as string; + } + } + + finalError = finalError || ({} as string); + + if (opts.throwOnError) { + throw finalError; + } + + // TODO: we probably want to return error and improve types + return opts.responseStyle === "data" + ? undefined + : { + error: finalError, + ...result, + }; + }; + + const makeMethodFn = + (method: Uppercase) => (options: RequestOptions) => + request({ ...options, method }); + + const makeSseFn = + (method: Uppercase) => async (options: RequestOptions) => { + const { opts, url } = await beforeRequest(options); + return createSseClient({ + ...opts, + body: opts.body as BodyInit | null | undefined, + headers: opts.headers as unknown as Record, + method, + onRequest: async (url, init) => { + let request = new Request(url, init); + for (const fn of interceptors.request.fns) { + if (fn) { + request = await fn(request, opts); + } + } + return request; + }, + url, + }); + }; + + return { + buildUrl, + connect: makeMethodFn("CONNECT"), + delete: makeMethodFn("DELETE"), + get: makeMethodFn("GET"), + getConfig, + head: makeMethodFn("HEAD"), + interceptors, + options: makeMethodFn("OPTIONS"), + patch: makeMethodFn("PATCH"), + post: makeMethodFn("POST"), + put: makeMethodFn("PUT"), + request, + setConfig, + sse: { + connect: makeSseFn("CONNECT"), + delete: makeSseFn("DELETE"), + get: makeSseFn("GET"), + head: makeSseFn("HEAD"), + options: makeSseFn("OPTIONS"), + patch: makeSseFn("PATCH"), + post: makeSseFn("POST"), + put: makeSseFn("PUT"), + trace: makeSseFn("TRACE"), + }, + trace: makeMethodFn("TRACE"), + } as Client; +}; diff --git a/src/src/common/apis/icanhazdadjoke/client/index.ts b/src/src/common/apis/icanhazdadjoke/client/index.ts new file mode 100644 index 0000000..064b1ff --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/client/index.ts @@ -0,0 +1,25 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type { Auth } from "../core/auth"; +export type { QuerySerializerOptions } from "../core/bodySerializer"; +export { + formDataBodySerializer, + jsonBodySerializer, + urlSearchParamsBodySerializer, +} from "../core/bodySerializer"; +export { buildClientParams } from "../core/params"; +export { serializeQueryKeyValue } from "../core/queryKeySerializer"; +export { createClient } from "./clnt"; +export type { + Client, + ClientOptions, + Config, + CreateClientConfig, + Options, + RequestOptions, + RequestResult, + ResolvedRequestOptions, + ResponseStyle, + TDataShape, +} from "./types"; +export { createConfig, mergeHeaders } from "./utils"; diff --git a/src/src/common/apis/icanhazdadjoke/client/types.ts b/src/src/common/apis/icanhazdadjoke/client/types.ts new file mode 100644 index 0000000..374902e --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/client/types.ts @@ -0,0 +1,238 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth } from "../core/auth"; +import type { + ServerSentEventsOptions, + ServerSentEventsResult, +} from "../core/serverSentEvents"; +import type { Client as CoreClient, Config as CoreConfig } from "../core/types"; +import type { Middleware } from "./utils"; + +export type ResponseStyle = "data" | "fields"; + +export interface Config + extends Omit, + CoreConfig { + /** + * Base URL for all requests made by this client. + */ + baseUrl?: T["baseUrl"]; + /** + * Fetch API implementation. You can use this option to provide a custom + * fetch instance. + * + * @default globalThis.fetch + */ + fetch?: typeof fetch; + /** + * Please don't use the Fetch client for Next.js applications. The `next` + * options won't have any effect. + * + * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead. + */ + next?: never; + /** + * Return the response data parsed in a specified format. By default, `auto` + * will infer the appropriate method from the `Content-Type` response header. + * You can override this behavior with any of the {@link Body} methods. + * Select `stream` if you don't want to parse response data at all. + * + * @default 'auto' + */ + parseAs?: + | "arrayBuffer" + | "auto" + | "blob" + | "formData" + | "json" + | "stream" + | "text"; + /** + * Should we return only data or multiple fields (data, error, response, etc.)? + * + * @default 'fields' + */ + responseStyle?: ResponseStyle; + /** + * Throw an error instead of returning it in the response? + * + * @default false + */ + throwOnError?: T["throwOnError"]; +} + +export interface RequestOptions< + TData = unknown, + TResponseStyle extends ResponseStyle = "fields", + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends Config<{ + responseStyle: TResponseStyle; + throwOnError: ThrowOnError; + }>, + Pick< + ServerSentEventsOptions, + | "onSseError" + | "onSseEvent" + | "sseDefaultRetryDelay" + | "sseMaxRetryAttempts" + | "sseMaxRetryDelay" + > { + /** + * Any body that you want to add to your request. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#body} + */ + body?: unknown; + path?: Record; + query?: Record; + /** + * Security mechanism(s) to use for the request. + */ + security?: ReadonlyArray; + url: Url; +} + +export interface ResolvedRequestOptions< + TResponseStyle extends ResponseStyle = "fields", + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends RequestOptions { + serializedBody?: string; +} + +export type RequestResult< + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = boolean, + TResponseStyle extends ResponseStyle = "fields", +> = ThrowOnError extends true + ? Promise< + TResponseStyle extends "data" + ? TData extends Record + ? TData[keyof TData] + : TData + : { + data: TData extends Record + ? TData[keyof TData] + : TData; + request: Request; + response: Response; + } + > + : Promise< + TResponseStyle extends "data" + ? + | (TData extends Record + ? TData[keyof TData] + : TData) + | undefined + : ( + | { + data: TData extends Record + ? TData[keyof TData] + : TData; + error: undefined; + } + | { + data: undefined; + error: TError extends Record + ? TError[keyof TError] + : TError; + } + ) & { + request: Request; + response: Response; + } + >; + +export interface ClientOptions { + baseUrl?: string; + responseStyle?: ResponseStyle; + throwOnError?: boolean; +} + +type MethodFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = "fields", +>( + options: Omit, "method">, +) => RequestResult; + +type SseFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = "fields", +>( + options: Omit, "method">, +) => Promise>; + +type RequestFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = "fields", +>( + options: Omit, "method"> & + Pick< + Required>, + "method" + >, +) => RequestResult; + +type BuildUrlFn = < + TData extends { + body?: unknown; + path?: Record; + query?: Record; + url: string; + }, +>( + options: TData & Options, +) => string; + +export type Client = CoreClient< + RequestFn, + Config, + MethodFn, + BuildUrlFn, + SseFn +> & { + interceptors: Middleware; +}; + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig = ( + override?: Config, +) => Config & T>; + +export interface TDataShape { + body?: unknown; + headers?: unknown; + path?: unknown; + query?: unknown; + url: string; +} + +type OmitKeys = Pick>; + +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, + TResponse = unknown, + TResponseStyle extends ResponseStyle = "fields", +> = OmitKeys< + RequestOptions, + "body" | "path" | "query" | "url" +> & + ([TData] extends [never] ? unknown : Omit); diff --git a/src/src/common/apis/icanhazdadjoke/client/utils.ts b/src/src/common/apis/icanhazdadjoke/client/utils.ts new file mode 100644 index 0000000..2bbfbde --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/client/utils.ts @@ -0,0 +1,332 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { getAuthToken } from "../core/auth"; +import type { QuerySerializerOptions } from "../core/bodySerializer"; +import { jsonBodySerializer } from "../core/bodySerializer"; +import { + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from "../core/pathSerializer"; +import { getUrl } from "../core/utils"; +import type { Client, ClientOptions, Config, RequestOptions } from "./types"; + +export const createQuerySerializer = ({ + parameters = {}, + ...args +}: QuerySerializerOptions = {}) => { + const querySerializer = (queryParams: T) => { + const search: string[] = []; + if (queryParams && typeof queryParams === "object") { + for (const name in queryParams) { + const value = queryParams[name]; + + if (value === undefined || value === null) { + continue; + } + + const options = parameters[name] || args; + + if (Array.isArray(value)) { + const serializedArray = serializeArrayParam({ + allowReserved: options.allowReserved, + explode: true, + name, + style: "form", + value, + ...options.array, + }); + if (serializedArray) search.push(serializedArray); + } else if (typeof value === "object") { + const serializedObject = serializeObjectParam({ + allowReserved: options.allowReserved, + explode: true, + name, + style: "deepObject", + value: value as Record, + ...options.object, + }); + if (serializedObject) search.push(serializedObject); + } else { + const serializedPrimitive = serializePrimitiveParam({ + allowReserved: options.allowReserved, + name, + value: value as string, + }); + if (serializedPrimitive) search.push(serializedPrimitive); + } + } + } + return search.join("&"); + }; + return querySerializer; +}; + +/** + * Infers parseAs value from provided Content-Type header. + */ +export const getParseAs = ( + contentType: string | null, +): Exclude => { + if (!contentType) { + // If no Content-Type header is provided, the best we can do is return the raw response body, + // which is effectively the same as the 'stream' option. + return "stream"; + } + + const cleanContent = contentType.split(";")[0]?.trim(); + + if (!cleanContent) { + return; + } + + if ( + cleanContent.startsWith("application/json") || + cleanContent.endsWith("+json") + ) { + return "json"; + } + + if (cleanContent === "multipart/form-data") { + return "formData"; + } + + if ( + ["application/", "audio/", "image/", "video/"].some((type) => + cleanContent.startsWith(type), + ) + ) { + return "blob"; + } + + if (cleanContent.startsWith("text/")) { + return "text"; + } + + return; +}; + +const checkForExistence = ( + options: Pick & { + headers: Headers; + }, + name?: string, +): boolean => { + if (!name) { + return false; + } + if ( + options.headers.has(name) || + options.query?.[name] || + options.headers.get("Cookie")?.includes(`${name}=`) + ) { + return true; + } + return false; +}; + +export const setAuthParams = async ({ + security, + ...options +}: Pick, "security"> & + Pick & { + headers: Headers; + }) => { + for (const auth of security) { + if (checkForExistence(options, auth.name)) { + continue; + } + + const token = await getAuthToken(auth, options.auth); + + if (!token) { + continue; + } + + const name = auth.name ?? "Authorization"; + + switch (auth.in) { + case "query": + if (!options.query) { + options.query = {}; + } + options.query[name] = token; + break; + case "cookie": + options.headers.append("Cookie", `${name}=${token}`); + break; + case "header": + default: + options.headers.set(name, token); + break; + } + } +}; + +export const buildUrl: Client["buildUrl"] = (options) => + getUrl({ + baseUrl: options.baseUrl as string, + path: options.path, + query: options.query, + querySerializer: + typeof options.querySerializer === "function" + ? options.querySerializer + : createQuerySerializer(options.querySerializer), + url: options.url, + }); + +export const mergeConfigs = (a: Config, b: Config): Config => { + const config = { ...a, ...b }; + if (config.baseUrl?.endsWith("/")) { + config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1); + } + config.headers = mergeHeaders(a.headers, b.headers); + return config; +}; + +const headersEntries = (headers: Headers): Array<[string, string]> => { + const entries: Array<[string, string]> = []; + headers.forEach((value, key) => { + entries.push([key, value]); + }); + return entries; +}; + +export const mergeHeaders = ( + ...headers: Array["headers"] | undefined> +): Headers => { + const mergedHeaders = new Headers(); + for (const header of headers) { + if (!header) { + continue; + } + + const iterator = + header instanceof Headers + ? headersEntries(header) + : Object.entries(header); + + for (const [key, value] of iterator) { + if (value === null) { + mergedHeaders.delete(key); + } else if (Array.isArray(value)) { + for (const v of value) { + mergedHeaders.append(key, v as string); + } + } else if (value !== undefined) { + // assume object headers are meant to be JSON stringified, i.e. their + // content value in OpenAPI specification is 'application/json' + mergedHeaders.set( + key, + typeof value === "object" ? JSON.stringify(value) : (value as string), + ); + } + } + } + return mergedHeaders; +}; + +type ErrInterceptor = ( + error: Err, + response: Res, + request: Req, + options: Options, +) => Err | Promise; + +type ReqInterceptor = ( + request: Req, + options: Options, +) => Req | Promise; + +type ResInterceptor = ( + response: Res, + request: Req, + options: Options, +) => Res | Promise; + +class Interceptors { + fns: Array = []; + + clear(): void { + this.fns = []; + } + + eject(id: number | Interceptor): void { + const index = this.getInterceptorIndex(id); + if (this.fns[index]) { + this.fns[index] = null; + } + } + + exists(id: number | Interceptor): boolean { + const index = this.getInterceptorIndex(id); + return Boolean(this.fns[index]); + } + + getInterceptorIndex(id: number | Interceptor): number { + if (typeof id === "number") { + return this.fns[id] ? id : -1; + } + return this.fns.indexOf(id); + } + + update( + id: number | Interceptor, + fn: Interceptor, + ): number | Interceptor | false { + const index = this.getInterceptorIndex(id); + if (this.fns[index]) { + this.fns[index] = fn; + return id; + } + return false; + } + + use(fn: Interceptor): number { + this.fns.push(fn); + return this.fns.length - 1; + } +} + +export interface Middleware { + error: Interceptors>; + request: Interceptors>; + response: Interceptors>; +} + +export const createInterceptors = (): Middleware< + Req, + Res, + Err, + Options +> => ({ + error: new Interceptors>(), + request: new Interceptors>(), + response: new Interceptors>(), +}); + +const defaultQuerySerializer = createQuerySerializer({ + allowReserved: false, + array: { + explode: true, + style: "form", + }, + object: { + explode: true, + style: "deepObject", + }, +}); + +const defaultHeaders = { + "Content-Type": "application/json", +}; + +export const createConfig = ( + override: Config & T> = {}, +): Config & T> => ({ + ...jsonBodySerializer, + headers: defaultHeaders, + parseAs: "auto", + querySerializer: defaultQuerySerializer, + ...override, +}); diff --git a/src/src/common/apis/icanhazdadjoke/clnt.ts b/src/src/common/apis/icanhazdadjoke/clnt.ts new file mode 100644 index 0000000..64ae2b1 --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/clnt.ts @@ -0,0 +1,23 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { + type ClientOptions, + type Config, + createClient, + createConfig, +} from "./client"; +import type { ClientOptions as ClientOptions2 } from "./types"; + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig = ( + override?: Config, +) => Config & T>; + +export const client = createClient(createConfig()); diff --git a/src/src/common/apis/icanhazdadjoke/core/auth.ts b/src/src/common/apis/icanhazdadjoke/core/auth.ts new file mode 100644 index 0000000..3d74115 --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/core/auth.ts @@ -0,0 +1,42 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type AuthToken = string | undefined; + +export interface Auth { + /** + * Which part of the request do we use to send the auth? + * + * @default 'header' + */ + in?: "header" | "query" | "cookie"; + /** + * Header or query parameter name. + * + * @default 'Authorization' + */ + name?: string; + scheme?: "basic" | "bearer"; + type: "apiKey" | "http"; +} + +export const getAuthToken = async ( + auth: Auth, + callback: ((auth: Auth) => Promise | AuthToken) | AuthToken, +): Promise => { + const token = + typeof callback === "function" ? await callback(auth) : callback; + + if (!token) { + return; + } + + if (auth.scheme === "bearer") { + return `Bearer ${token}`; + } + + if (auth.scheme === "basic") { + return `Basic ${btoa(token)}`; + } + + return token; +}; diff --git a/src/src/common/apis/icanhazdadjoke/core/bodySerializer.ts b/src/src/common/apis/icanhazdadjoke/core/bodySerializer.ts new file mode 100644 index 0000000..a6a3354 --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/core/bodySerializer.ts @@ -0,0 +1,100 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { + ArrayStyle, + ObjectStyle, + SerializerOptions, +} from "./pathSerializer"; + +export type QuerySerializer = (query: Record) => string; + +export type BodySerializer = (body: any) => any; + +type QuerySerializerOptionsObject = { + allowReserved?: boolean; + array?: Partial>; + object?: Partial>; +}; + +export type QuerySerializerOptions = QuerySerializerOptionsObject & { + /** + * Per-parameter serialization overrides. When provided, these settings + * override the global array/object settings for specific parameter names. + */ + parameters?: Record; +}; + +const serializeFormDataPair = ( + data: FormData, + key: string, + value: unknown, +): void => { + if (typeof value === "string" || value instanceof Blob) { + data.append(key, value); + } else if (value instanceof Date) { + data.append(key, value.toISOString()); + } else { + data.append(key, JSON.stringify(value)); + } +}; + +const serializeUrlSearchParamsPair = ( + data: URLSearchParams, + key: string, + value: unknown, +): void => { + if (typeof value === "string") { + data.append(key, value); + } else { + data.append(key, JSON.stringify(value)); + } +}; + +export const formDataBodySerializer = { + bodySerializer: | Array>>( + body: T, + ): FormData => { + const data = new FormData(); + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return; + } + if (Array.isArray(value)) { + value.forEach((v) => serializeFormDataPair(data, key, v)); + } else { + serializeFormDataPair(data, key, value); + } + }); + + return data; + }, +}; + +export const jsonBodySerializer = { + bodySerializer: (body: T): string => + JSON.stringify(body, (_key, value) => + typeof value === "bigint" ? value.toString() : value, + ), +}; + +export const urlSearchParamsBodySerializer = { + bodySerializer: | Array>>( + body: T, + ): string => { + const data = new URLSearchParams(); + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return; + } + if (Array.isArray(value)) { + value.forEach((v) => serializeUrlSearchParamsPair(data, key, v)); + } else { + serializeUrlSearchParamsPair(data, key, value); + } + }); + + return data.toString(); + }, +}; diff --git a/src/src/common/apis/icanhazdadjoke/core/params.ts b/src/src/common/apis/icanhazdadjoke/core/params.ts new file mode 100644 index 0000000..fb9f992 --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/core/params.ts @@ -0,0 +1,176 @@ +// This file is auto-generated by @hey-api/openapi-ts + +type Slot = "body" | "headers" | "path" | "query"; + +export type Field = + | { + in: Exclude; + /** + * Field name. This is the name we want the user to see and use. + */ + key: string; + /** + * Field mapped name. This is the name we want to use in the request. + * If omitted, we use the same value as `key`. + */ + map?: string; + } + | { + in: Extract; + /** + * Key isn't required for bodies. + */ + key?: string; + map?: string; + } + | { + /** + * Field name. This is the name we want the user to see and use. + */ + key: string; + /** + * Field mapped name. This is the name we want to use in the request. + * If `in` is omitted, `map` aliases `key` to the transport layer. + */ + map: Slot; + }; + +export interface Fields { + allowExtra?: Partial>; + args?: ReadonlyArray; +} + +export type FieldsConfig = ReadonlyArray; + +const extraPrefixesMap: Record = { + $body_: "body", + $headers_: "headers", + $path_: "path", + $query_: "query", +}; +const extraPrefixes = Object.entries(extraPrefixesMap); + +type KeyMap = Map< + string, + | { + in: Slot; + map?: string; + } + | { + in?: never; + map: Slot; + } +>; + +const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => { + if (!map) { + map = new Map(); + } + + for (const config of fields) { + if ("in" in config) { + if (config.key) { + map.set(config.key, { + in: config.in, + map: config.map, + }); + } + } else if ("key" in config) { + map.set(config.key, { + map: config.map, + }); + } else if (config.args) { + buildKeyMap(config.args, map); + } + } + + return map; +}; + +interface Params { + body: unknown; + headers: Record; + path: Record; + query: Record; +} + +const stripEmptySlots = (params: Params) => { + for (const [slot, value] of Object.entries(params)) { + if (value && typeof value === "object" && !Object.keys(value).length) { + delete params[slot as Slot]; + } + } +}; + +export const buildClientParams = ( + args: ReadonlyArray, + fields: FieldsConfig, +) => { + const params: Params = { + body: {}, + headers: {}, + path: {}, + query: {}, + }; + + const map = buildKeyMap(fields); + + let config: FieldsConfig[number] | undefined; + + for (const [index, arg] of args.entries()) { + if (fields[index]) { + config = fields[index]; + } + + if (!config) { + continue; + } + + if ("in" in config) { + if (config.key) { + const field = map.get(config.key)!; + const name = field.map || config.key; + if (field.in) { + (params[field.in] as Record)[name] = arg; + } + } else { + params.body = arg; + } + } else { + for (const [key, value] of Object.entries(arg ?? {})) { + const field = map.get(key); + + if (field) { + if (field.in) { + const name = field.map || key; + (params[field.in] as Record)[name] = value; + } else { + params[field.map] = value; + } + } else { + const extra = extraPrefixes.find(([prefix]) => + key.startsWith(prefix), + ); + + if (extra) { + const [prefix, slot] = extra; + (params[slot] as Record)[ + key.slice(prefix.length) + ] = value; + } else if ("allowExtra" in config && config.allowExtra) { + for (const [slot, allowed] of Object.entries(config.allowExtra)) { + if (allowed) { + (params[slot as Slot] as Record)[key] = value; + break; + } + } + } + } + } + } + } + + stripEmptySlots(params); + + return params; +}; diff --git a/src/src/common/apis/icanhazdadjoke/core/pathSerializer.ts b/src/src/common/apis/icanhazdadjoke/core/pathSerializer.ts new file mode 100644 index 0000000..034aa68 --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/core/pathSerializer.ts @@ -0,0 +1,181 @@ +// This file is auto-generated by @hey-api/openapi-ts + +interface SerializeOptions + extends SerializePrimitiveOptions, + SerializerOptions {} + +interface SerializePrimitiveOptions { + allowReserved?: boolean; + name: string; +} + +export interface SerializerOptions { + /** + * @default true + */ + explode: boolean; + style: T; +} + +export type ArrayStyle = "form" | "spaceDelimited" | "pipeDelimited"; +export type ArraySeparatorStyle = ArrayStyle | MatrixStyle; +type MatrixStyle = "label" | "matrix" | "simple"; +export type ObjectStyle = "form" | "deepObject"; +type ObjectSeparatorStyle = ObjectStyle | MatrixStyle; + +interface SerializePrimitiveParam extends SerializePrimitiveOptions { + value: string; +} + +export const separatorArrayExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case "label": + return "."; + case "matrix": + return ";"; + case "simple": + return ","; + default: + return "&"; + } +}; + +export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case "form": + return ","; + case "pipeDelimited": + return "|"; + case "spaceDelimited": + return "%20"; + default: + return ","; + } +}; + +export const separatorObjectExplode = (style: ObjectSeparatorStyle) => { + switch (style) { + case "label": + return "."; + case "matrix": + return ";"; + case "simple": + return ","; + default: + return "&"; + } +}; + +export const serializeArrayParam = ({ + allowReserved, + explode, + name, + style, + value, +}: SerializeOptions & { + value: unknown[]; +}) => { + if (!explode) { + const joinedValues = ( + allowReserved ? value : value.map((v) => encodeURIComponent(v as string)) + ).join(separatorArrayNoExplode(style)); + switch (style) { + case "label": + return `.${joinedValues}`; + case "matrix": + return `;${name}=${joinedValues}`; + case "simple": + return joinedValues; + default: + return `${name}=${joinedValues}`; + } + } + + const separator = separatorArrayExplode(style); + const joinedValues = value + .map((v) => { + if (style === "label" || style === "simple") { + return allowReserved ? v : encodeURIComponent(v as string); + } + + return serializePrimitiveParam({ + allowReserved, + name, + value: v as string, + }); + }) + .join(separator); + return style === "label" || style === "matrix" + ? separator + joinedValues + : joinedValues; +}; + +export const serializePrimitiveParam = ({ + allowReserved, + name, + value, +}: SerializePrimitiveParam) => { + if (value === undefined || value === null) { + return ""; + } + + if (typeof value === "object") { + throw new Error( + "Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.", + ); + } + + return `${name}=${allowReserved ? value : encodeURIComponent(value)}`; +}; + +export const serializeObjectParam = ({ + allowReserved, + explode, + name, + style, + value, + valueOnly, +}: SerializeOptions & { + value: Record | Date; + valueOnly?: boolean; +}) => { + if (value instanceof Date) { + return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`; + } + + if (style !== "deepObject" && !explode) { + let values: string[] = []; + Object.entries(value).forEach(([key, v]) => { + values = [ + ...values, + key, + allowReserved ? (v as string) : encodeURIComponent(v as string), + ]; + }); + const joinedValues = values.join(","); + switch (style) { + case "form": + return `${name}=${joinedValues}`; + case "label": + return `.${joinedValues}`; + case "matrix": + return `;${name}=${joinedValues}`; + default: + return joinedValues; + } + } + + const separator = separatorObjectExplode(style); + const joinedValues = Object.entries(value) + .map(([key, v]) => + serializePrimitiveParam({ + allowReserved, + name: style === "deepObject" ? `${name}[${key}]` : key, + value: v as string, + }), + ) + .join(separator); + return style === "label" || style === "matrix" + ? separator + joinedValues + : joinedValues; +}; diff --git a/src/src/common/apis/icanhazdadjoke/core/queryKeySerializer.ts b/src/src/common/apis/icanhazdadjoke/core/queryKeySerializer.ts new file mode 100644 index 0000000..0713164 --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/core/queryKeySerializer.ts @@ -0,0 +1,136 @@ +// This file is auto-generated by @hey-api/openapi-ts + +/** + * JSON-friendly union that mirrors what Pinia Colada can hash. + */ +export type JsonValue = + | null + | string + | number + | boolean + | JsonValue[] + | { [key: string]: JsonValue }; + +/** + * Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes. + */ +export const queryKeyJsonReplacer = (_key: string, value: unknown) => { + if ( + value === undefined || + typeof value === "function" || + typeof value === "symbol" + ) { + return undefined; + } + if (typeof value === "bigint") { + return value.toString(); + } + if (value instanceof Date) { + return value.toISOString(); + } + return value; +}; + +/** + * Safely stringifies a value and parses it back into a JsonValue. + */ +export const stringifyToJsonValue = (input: unknown): JsonValue | undefined => { + try { + const json = JSON.stringify(input, queryKeyJsonReplacer); + if (json === undefined) { + return undefined; + } + return JSON.parse(json) as JsonValue; + } catch { + return undefined; + } +}; + +/** + * Detects plain objects (including objects with a null prototype). + */ +const isPlainObject = (value: unknown): value is Record => { + if (value === null || typeof value !== "object") { + return false; + } + const prototype = Object.getPrototypeOf(value as object); + return prototype === Object.prototype || prototype === null; +}; + +/** + * Turns URLSearchParams into a sorted JSON object for deterministic keys. + */ +const serializeSearchParams = (params: URLSearchParams): JsonValue => { + const entries = Array.from(params.entries()).sort(([a], [b]) => + a.localeCompare(b), + ); + const result: Record = {}; + + for (const [key, value] of entries) { + const existing = result[key]; + if (existing === undefined) { + result[key] = value; + continue; + } + + if (Array.isArray(existing)) { + (existing as string[]).push(value); + } else { + result[key] = [existing, value]; + } + } + + return result; +}; + +/** + * Normalizes any accepted value into a JSON-friendly shape for query keys. + */ +export const serializeQueryKeyValue = ( + value: unknown, +): JsonValue | undefined => { + if (value === null) { + return null; + } + + if ( + typeof value === "string" || + typeof value === "number" || + typeof value === "boolean" + ) { + return value; + } + + if ( + value === undefined || + typeof value === "function" || + typeof value === "symbol" + ) { + return undefined; + } + + if (typeof value === "bigint") { + return value.toString(); + } + + if (value instanceof Date) { + return value.toISOString(); + } + + if (Array.isArray(value)) { + return stringifyToJsonValue(value); + } + + if ( + typeof URLSearchParams !== "undefined" && + value instanceof URLSearchParams + ) { + return serializeSearchParams(value); + } + + if (isPlainObject(value)) { + return stringifyToJsonValue(value); + } + + return undefined; +}; diff --git a/src/src/common/apis/icanhazdadjoke/core/serverSentEvents.ts b/src/src/common/apis/icanhazdadjoke/core/serverSentEvents.ts new file mode 100644 index 0000000..bd5293a --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/core/serverSentEvents.ts @@ -0,0 +1,264 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Config } from "./types"; + +export type ServerSentEventsOptions = Omit< + RequestInit, + "method" +> & + Pick & { + /** + * Fetch API implementation. You can use this option to provide a custom + * fetch instance. + * + * @default globalThis.fetch + */ + fetch?: typeof fetch; + /** + * Implementing clients can call request interceptors inside this hook. + */ + onRequest?: (url: string, init: RequestInit) => Promise; + /** + * Callback invoked when a network or parsing error occurs during streaming. + * + * This option applies only if the endpoint returns a stream of events. + * + * @param error The error that occurred. + */ + onSseError?: (error: unknown) => void; + /** + * Callback invoked when an event is streamed from the server. + * + * This option applies only if the endpoint returns a stream of events. + * + * @param event Event streamed from the server. + * @returns Nothing (void). + */ + onSseEvent?: (event: StreamEvent) => void; + serializedBody?: RequestInit["body"]; + /** + * Default retry delay in milliseconds. + * + * This option applies only if the endpoint returns a stream of events. + * + * @default 3000 + */ + sseDefaultRetryDelay?: number; + /** + * Maximum number of retry attempts before giving up. + */ + sseMaxRetryAttempts?: number; + /** + * Maximum retry delay in milliseconds. + * + * Applies only when exponential backoff is used. + * + * This option applies only if the endpoint returns a stream of events. + * + * @default 30000 + */ + sseMaxRetryDelay?: number; + /** + * Optional sleep function for retry backoff. + * + * Defaults to using `setTimeout`. + */ + sseSleepFn?: (ms: number) => Promise; + url: string; + }; + +export interface StreamEvent { + data: TData; + event?: string; + id?: string; + retry?: number; +} + +export type ServerSentEventsResult< + TData = unknown, + TReturn = void, + TNext = unknown, +> = { + stream: AsyncGenerator< + TData extends Record ? TData[keyof TData] : TData, + TReturn, + TNext + >; +}; + +export const createSseClient = ({ + onRequest, + onSseError, + onSseEvent, + responseTransformer, + responseValidator, + sseDefaultRetryDelay, + sseMaxRetryAttempts, + sseMaxRetryDelay, + sseSleepFn, + url, + ...options +}: ServerSentEventsOptions): ServerSentEventsResult => { + let lastEventId: string | undefined; + + const sleep = + sseSleepFn ?? + ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms))); + + const createStream = async function* () { + let retryDelay: number = sseDefaultRetryDelay ?? 3000; + let attempt = 0; + const signal = options.signal ?? new AbortController().signal; + + while (true) { + if (signal.aborted) break; + + attempt++; + + const headers = + options.headers instanceof Headers + ? options.headers + : new Headers(options.headers as Record | undefined); + + if (lastEventId !== undefined) { + headers.set("Last-Event-ID", lastEventId); + } + + try { + const requestInit: RequestInit = { + redirect: "follow", + ...options, + body: options.serializedBody, + headers, + signal, + }; + let request = new Request(url, requestInit); + if (onRequest) { + request = await onRequest(url, requestInit); + } + // fetch must be assigned here, otherwise it would throw the error: + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation + const _fetch = options.fetch ?? globalThis.fetch; + const response = await _fetch(request); + + if (!response.ok) + throw new Error( + `SSE failed: ${response.status} ${response.statusText}`, + ); + + if (!response.body) throw new Error("No body in SSE response"); + + const reader = response.body + .pipeThrough(new TextDecoderStream()) + .getReader(); + + let buffer = ""; + + const abortHandler = () => { + try { + reader.cancel(); + } catch { + // noop + } + }; + + signal.addEventListener("abort", abortHandler); + + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + buffer += value; + + const chunks = buffer.split("\n\n"); + buffer = chunks.pop() ?? ""; + + for (const chunk of chunks) { + const lines = chunk.split("\n"); + const dataLines: Array = []; + let eventName: string | undefined; + + for (const line of lines) { + if (line.startsWith("data:")) { + dataLines.push(line.replace(/^data:\s*/, "")); + } else if (line.startsWith("event:")) { + eventName = line.replace(/^event:\s*/, ""); + } else if (line.startsWith("id:")) { + lastEventId = line.replace(/^id:\s*/, ""); + } else if (line.startsWith("retry:")) { + const parsed = Number.parseInt( + line.replace(/^retry:\s*/, ""), + 10, + ); + if (!Number.isNaN(parsed)) { + retryDelay = parsed; + } + } + } + + let data: unknown; + let parsedJson = false; + + if (dataLines.length) { + const rawData = dataLines.join("\n"); + try { + data = JSON.parse(rawData); + parsedJson = true; + } catch { + data = rawData; + } + } + + if (parsedJson) { + if (responseValidator) { + await responseValidator(data); + } + + if (responseTransformer) { + data = await responseTransformer(data); + } + } + + onSseEvent?.({ + data, + event: eventName, + id: lastEventId, + retry: retryDelay, + }); + + if (dataLines.length) { + yield data as any; + } + } + } + } finally { + signal.removeEventListener("abort", abortHandler); + reader.releaseLock(); + } + + break; // exit loop on normal completion + } catch (error) { + // connection failed or aborted; retry after delay + onSseError?.(error); + + if ( + sseMaxRetryAttempts !== undefined && + attempt >= sseMaxRetryAttempts + ) { + break; // stop after firing error + } + + // exponential backoff: double retry each attempt, cap at 30s + const backoff = Math.min( + retryDelay * 2 ** (attempt - 1), + sseMaxRetryDelay ?? 30000, + ); + await sleep(backoff); + } + } + }; + + const stream = createStream(); + + return { stream }; +}; diff --git a/src/src/common/apis/icanhazdadjoke/core/types.ts b/src/src/common/apis/icanhazdadjoke/core/types.ts new file mode 100644 index 0000000..754e96b --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/core/types.ts @@ -0,0 +1,118 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth, AuthToken } from "./auth"; +import type { + BodySerializer, + QuerySerializer, + QuerySerializerOptions, +} from "./bodySerializer"; + +export type HttpMethod = + | "connect" + | "delete" + | "get" + | "head" + | "options" + | "patch" + | "post" + | "put" + | "trace"; + +export type Client< + RequestFn = never, + Config = unknown, + MethodFn = never, + BuildUrlFn = never, + SseFn = never, +> = { + /** + * Returns the final request URL. + */ + buildUrl: BuildUrlFn; + getConfig: () => Config; + request: RequestFn; + setConfig: (config: Config) => Config; +} & { + [K in HttpMethod]: MethodFn; +} & ([SseFn] extends [never] + ? { sse?: never } + : { sse: { [K in HttpMethod]: SseFn } }); + +export interface Config { + /** + * Auth token or a function returning auth token. The resolved value will be + * added to the request payload as defined by its `security` array. + */ + auth?: ((auth: Auth) => Promise | AuthToken) | AuthToken; + /** + * A function for serializing request body parameter. By default, + * {@link JSON.stringify()} will be used. + */ + bodySerializer?: BodySerializer | null; + /** + * An object containing any HTTP headers that you want to pre-populate your + * `Headers` object with. + * + * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more} + */ + headers?: + | RequestInit["headers"] + | Record< + string, + | string + | number + | boolean + | (string | number | boolean)[] + | null + | undefined + | unknown + >; + /** + * The request method. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more} + */ + method?: Uppercase; + /** + * A function for serializing request query parameters. By default, arrays + * will be exploded in form style, objects will be exploded in deepObject + * style, and reserved characters are percent-encoded. + * + * This method will have no effect if the native `paramsSerializer()` Axios + * API function is used. + * + * {@link https://swagger.io/docs/specification/serialization/#query View examples} + */ + querySerializer?: QuerySerializer | QuerySerializerOptions; + /** + * A function validating request data. This is useful if you want to ensure + * the request conforms to the desired shape, so it can be safely sent to + * the server. + */ + requestValidator?: (data: unknown) => Promise; + /** + * A function transforming response data before it's returned. This is useful + * for post-processing data, e.g. converting ISO strings into Date objects. + */ + responseTransformer?: (data: unknown) => Promise; + /** + * A function validating response data. This is useful if you want to ensure + * the response conforms to the desired shape, so it can be safely passed to + * the transformers and returned to the user. + */ + responseValidator?: (data: unknown) => Promise; +} + +type IsExactlyNeverOrNeverUndefined = [T] extends [never] + ? true + : [T] extends [never | undefined] + ? [undefined] extends [T] + ? false + : true + : false; + +export type OmitNever> = { + [K in keyof T as IsExactlyNeverOrNeverUndefined extends true + ? never + : K]: T[K]; +}; diff --git a/src/src/common/apis/icanhazdadjoke/core/utils.ts b/src/src/common/apis/icanhazdadjoke/core/utils.ts new file mode 100644 index 0000000..ad90812 --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/core/utils.ts @@ -0,0 +1,143 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { BodySerializer, QuerySerializer } from "./bodySerializer"; +import { + type ArraySeparatorStyle, + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from "./pathSerializer"; + +export interface PathSerializer { + path: Record; + url: string; +} + +export const PATH_PARAM_RE = /\{[^{}]+\}/g; + +export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => { + let url = _url; + const matches = _url.match(PATH_PARAM_RE); + if (matches) { + for (const match of matches) { + let explode = false; + let name = match.substring(1, match.length - 1); + let style: ArraySeparatorStyle = "simple"; + + if (name.endsWith("*")) { + explode = true; + name = name.substring(0, name.length - 1); + } + + if (name.startsWith(".")) { + name = name.substring(1); + style = "label"; + } else if (name.startsWith(";")) { + name = name.substring(1); + style = "matrix"; + } + + const value = path[name]; + + if (value === undefined || value === null) { + continue; + } + + if (Array.isArray(value)) { + url = url.replace( + match, + serializeArrayParam({ explode, name, style, value }), + ); + continue; + } + + if (typeof value === "object") { + url = url.replace( + match, + serializeObjectParam({ + explode, + name, + style, + value: value as Record, + valueOnly: true, + }), + ); + continue; + } + + if (style === "matrix") { + url = url.replace( + match, + `;${serializePrimitiveParam({ + name, + value: value as string, + })}`, + ); + continue; + } + + const replaceValue = encodeURIComponent( + style === "label" ? `.${value as string}` : (value as string), + ); + url = url.replace(match, replaceValue); + } + } + return url; +}; + +export const getUrl = ({ + baseUrl, + path, + query, + querySerializer, + url: _url, +}: { + baseUrl?: string; + path?: Record; + query?: Record; + querySerializer: QuerySerializer; + url: string; +}) => { + const pathUrl = _url.startsWith("/") ? _url : `/${_url}`; + let url = (baseUrl ?? "") + pathUrl; + if (path) { + url = defaultPathSerializer({ path, url }); + } + let search = query ? querySerializer(query) : ""; + if (search.startsWith("?")) { + search = search.substring(1); + } + if (search) { + url += `?${search}`; + } + return url; +}; + +export function getValidRequestBody(options: { + body?: unknown; + bodySerializer?: BodySerializer | null; + serializedBody?: unknown; +}) { + const hasBody = options.body !== undefined; + const isSerializedBody = hasBody && options.bodySerializer; + + if (isSerializedBody) { + if ("serializedBody" in options) { + const hasSerializedBody = + options.serializedBody !== undefined && options.serializedBody !== ""; + + return hasSerializedBody ? options.serializedBody : null; + } + + // not all clients implement a serializedBody property (i.e. client-axios) + return options.body !== "" ? options.body : null; + } + + // plain/text body + if (hasBody) { + return options.body; + } + + // no body was provided + return undefined; +} diff --git a/src/src/common/apis/icanhazdadjoke/schemas.ts b/src/src/common/apis/icanhazdadjoke/schemas.ts new file mode 100644 index 0000000..58458d3 --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/schemas.ts @@ -0,0 +1,34 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { z } from "zod"; + +/** + * Success response payload for getting a random joke + */ +export const GetRandomJokeSuccessResponsePayloadSchema = z + .object({ + id: z.string().register(z.globalRegistry, { + description: "Unique identifier of the joke", + }), + joke: z.string().register(z.globalRegistry, { + description: "The text of the joke", + }), + status: z.literal(200).register(z.globalRegistry, { + description: "Status code of the response", + }), + }) + .register(z.globalRegistry, { + description: "Success response payload for getting a random joke", + }); + +export const GetRandomJokeRequestSchema = z.object({ + body: z.optional(z.never()), + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful response with a random joke + */ +export const GetRandomJokeResponseSchema = + GetRandomJokeSuccessResponsePayloadSchema; diff --git a/src/src/common/apis/icanhazdadjoke/sdk.ts b/src/src/common/apis/icanhazdadjoke/sdk.ts new file mode 100644 index 0000000..a933254 --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/sdk.ts @@ -0,0 +1,82 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Client, Options as Options2, TDataShape } from "./client"; +import { + GetRandomJokeRequestSchema, + GetRandomJokeResponseSchema, +} from "./schemas"; +import type { GetRandomJokeRequest, GetRandomJokeResponses } from "./types"; + +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, +> = Options2 & { + /** + * You can provide a client instance returned by `createClient()` instead of + * individual options. This might be also useful if you want to implement a + * custom client. + */ + client?: Client; + /** + * You can pass arbitrary values through the `meta` object. This can be + * used to access values that aren't defined as part of the SDK function. + */ + meta?: Record; +}; + +class HeyApiClient { + protected client: Client; + + constructor(args: { client: Client }) { + this.client = args.client; + } +} + +class HeyApiRegistry { + private readonly defaultKey = "default"; + + private readonly instances: Map = new Map(); + + get(key?: string): T { + const instance = this.instances.get(key ?? this.defaultKey); + if (!instance) { + throw new Error( + `No SDK client found. Create one with "new Sdk()" to fix this error.`, + ); + } + return instance; + } + + set(value: T, key?: string): void { + this.instances.set(key ?? this.defaultKey, value); + } +} + +export class Sdk extends HeyApiClient { + public static readonly __registry = new HeyApiRegistry(); + + constructor(args: { client: Client; key?: string }) { + super(args); + Sdk.__registry.set(this, args.key); + } + + /** + * Get a random joke + */ + public getRandomJoke( + options?: Options, + ) { + return (options?.client ?? this.client).get< + GetRandomJokeResponses, + unknown, + ThrowOnError + >({ + requestValidator: async (data) => + await GetRandomJokeRequestSchema.parseAsync(data), + responseValidator: async (data) => + await GetRandomJokeResponseSchema.parseAsync(data), + url: "/", + ...options, + }); + } +} diff --git a/src/src/common/apis/icanhazdadjoke/types.ts b/src/src/common/apis/icanhazdadjoke/types.ts new file mode 100644 index 0000000..619331c --- /dev/null +++ b/src/src/common/apis/icanhazdadjoke/types.ts @@ -0,0 +1,40 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type ClientOptions = { + baseUrl: `${string}://${string}` | (string & {}); +}; + +/** + * Success response payload for getting a random joke + */ +export type GetRandomJokeSuccessResponsePayload = { + /** + * Unique identifier of the joke + */ + id: string; + /** + * The text of the joke + */ + joke: string; + /** + * Status code of the response + */ + status: 200; +}; + +export type GetRandomJokeRequest = { + body?: never; + path?: never; + query?: never; + url: "/"; +}; + +export type GetRandomJokeResponses = { + /** + * Successful response with a random joke + */ + 200: GetRandomJokeSuccessResponsePayload; +}; + +export type GetRandomJokeResponse = + GetRandomJokeResponses[keyof GetRandomJokeResponses]; diff --git a/src/src/common/generic/lib/create-url/index.ts b/src/src/common/generic/lib/create-url/index.ts new file mode 100644 index 0000000..dfbc6a9 --- /dev/null +++ b/src/src/common/generic/lib/create-url/index.ts @@ -0,0 +1,2 @@ +export { createUrl } from "./main"; +export type { CreateUrlInput, CreateUrlOutput } from "./types"; diff --git a/src/src/common/generic/lib/create-url/main.ts b/src/src/common/generic/lib/create-url/main.ts new file mode 100644 index 0000000..0ac903a --- /dev/null +++ b/src/src/common/generic/lib/create-url/main.ts @@ -0,0 +1,13 @@ +import { trim } from "es-toolkit/string"; + +import type { CreateUrlInput, CreateUrlOutput } from "./types"; + +export function createUrl({ + host, + path, + port, + scheme, +}: CreateUrlInput): CreateUrlOutput { + const trimmedPath = path ? trim(path, "/") : path; + return `${scheme}://${host}${port ? `:${port}` : ""}${trimmedPath ? `/${trimmedPath}` : ""}`; +} diff --git a/src/src/common/generic/lib/create-url/types.ts b/src/src/common/generic/lib/create-url/types.ts new file mode 100644 index 0000000..46b563b --- /dev/null +++ b/src/src/common/generic/lib/create-url/types.ts @@ -0,0 +1,8 @@ +export type CreateUrlInput = { + host: string; + path?: null | string; + port?: null | number; + scheme: string; +}; + +export type CreateUrlOutput = string; diff --git a/src/src/common/localization/lib/create-lingui/main.ts b/src/src/common/localization/lib/create-lingui/main.ts index 27ca875..506ccd6 100644 --- a/src/src/common/localization/lib/create-lingui/main.ts +++ b/src/src/common/localization/lib/create-lingui/main.ts @@ -1,5 +1,5 @@ import { I18n } from "@lingui/core"; -import { mapValues } from "es-toolkit"; +import { mapValues } from "es-toolkit/object"; import type { CreateLinguiInput, CreateLinguiOutput } from "./types"; diff --git a/src/src/common/localization/locales/en.po.jinja b/src/src/common/localization/locales/en.po.jinja index 070eee9..60515f6 100644 --- a/src/src/common/localization/locales/en.po.jinja +++ b/src/src/common/localization/locales/en.po.jinja @@ -13,7 +13,7 @@ msgstr "" "Language-Team: \n" "Plural-Forms: \n" -#: src/client/test/components/test/test-widget/main.tsx:49 +#: src/client/test/components/test/test-widget/main.tsx:51 msgid "An unexpected error occurred" msgstr "An unexpected error occurred" @@ -42,8 +42,8 @@ msgstr "{{ appname }} is a Next.js app" msgid "Info" msgstr "Info" -#: src/client/test/components/test/test-widget/main.tsx:39 -#: src/client/test/components/test/test-widget/main.tsx:59 +#: src/client/test/components/test/test-widget/main.tsx:41 +#: src/client/test/components/test/test-widget/main.tsx:61 msgid "Invalid input" msgstr "Invalid input" @@ -67,10 +67,6 @@ msgstr "Something went wrong" msgid "Submit" msgstr "Submit" -#: src/client/test/components/test/test-widget/main.tsx:36 -msgid "Submitted!" -msgstr "Submitted!" - #: src/isomorphic/notifications/hooks/use-notifications/main.ts:66 msgid "Success" msgstr "Success" @@ -78,3 +74,7 @@ msgstr "Success" #: src/isomorphic/notifications/hooks/use-notifications/main.ts:76 msgid "Warning" msgstr "Warning" + +#: src/server/orpc/vars/procedures/vars/test/vars/validate/main.ts:27 +msgid "Why did the chicken cross the road? To get to the other side." +msgstr "Why did the chicken cross the road? To get to the other side." diff --git a/src/src/common/localization/locales/pl.po.jinja b/src/src/common/localization/locales/pl.po.jinja index b92c0f8..8956dc3 100644 --- a/src/src/common/localization/locales/pl.po.jinja +++ b/src/src/common/localization/locales/pl.po.jinja @@ -13,7 +13,7 @@ msgstr "" "Language-Team: \n" "Plural-Forms: \n" -#: src/client/test/components/test/test-widget/main.tsx:49 +#: src/client/test/components/test/test-widget/main.tsx:51 msgid "An unexpected error occurred" msgstr "Wystąpił nieoczekiwany błąd" @@ -42,8 +42,8 @@ msgstr "{{ appname }} to aplikacja Next.js" msgid "Info" msgstr "Informacja" -#: src/client/test/components/test/test-widget/main.tsx:39 -#: src/client/test/components/test/test-widget/main.tsx:59 +#: src/client/test/components/test/test-widget/main.tsx:41 +#: src/client/test/components/test/test-widget/main.tsx:61 msgid "Invalid input" msgstr "Nieprawidłowe dane wejściowe" @@ -67,10 +67,6 @@ msgstr "Coś poszło nie tak" msgid "Submit" msgstr "Wyślij" -#: src/client/test/components/test/test-widget/main.tsx:36 -msgid "Submitted!" -msgstr "Wysłano!" - #: src/isomorphic/notifications/hooks/use-notifications/main.ts:66 msgid "Success" msgstr "Sukces" @@ -78,3 +74,7 @@ msgstr "Sukces" #: src/isomorphic/notifications/hooks/use-notifications/main.ts:76 msgid "Warning" msgstr "Ostrzeżenie" + +#: src/server/orpc/vars/procedures/vars/test/vars/validate/main.ts:27 +msgid "Why did the chicken cross the road? To get to the other side." +msgstr "Dlaczego kura przeszła przez ulicę? Żeby dostać się na drugą stronę." diff --git a/src/src/common/orpc/vars/procedures/vars/test/vars/validate/schemas.ts b/src/src/common/orpc/vars/procedures/vars/test/vars/validate/schemas.ts index f2812ce..7d3c352 100644 --- a/src/src/common/orpc/vars/procedures/vars/test/vars/validate/schemas.ts +++ b/src/src/common/orpc/vars/procedures/vars/test/vars/validate/schemas.ts @@ -1,10 +1,13 @@ import * as z from "zod"; +import { GetRandomJokeResponseSchema } from "../../../../../../../apis/icanhazdadjoke/schemas"; + export const Schemas = { Input: z.object({ value: z.string().pipe(z.literal("test")), }), Output: z.object({ + message: GetRandomJokeResponseSchema.shape.joke, value: z.literal("test"), }), }; diff --git a/src/src/instrumentation.ts b/src/src/instrumentation.ts index 54615f8..1e8b8eb 100644 --- a/src/src/instrumentation.ts +++ b/src/src/instrumentation.ts @@ -1,7 +1,27 @@ +import { createClient as createICanHazDadJokeClient } from "./common/apis/icanhazdadjoke/client"; +import { Sdk as ICanHazDadJokeSDK } from "./common/apis/icanhazdadjoke/sdk"; +import { createUrl } from "./common/generic/lib/create-url"; import { loadConfig } from "./server/config/lib/load-config"; import { state } from "./server/state/vars/state"; export async function register() { const { config } = await loadConfig(); - state.current = { config: config }; + + const apis = { + icanhazdadjoke: new ICanHazDadJokeSDK({ + client: createICanHazDadJokeClient({ + baseUrl: createUrl({ + host: config.apis.icanhazdadjoke.host, + path: config.apis.icanhazdadjoke.path, + port: config.apis.icanhazdadjoke.port, + scheme: config.apis.icanhazdadjoke.scheme, + }), + }), + }), + }; + + state.current = { + apis: apis, + config: config, + }; } diff --git a/src/src/server/config/lib/load-config/main.ts b/src/src/server/config/lib/load-config/main.ts index 3143922..9fb3080 100644 --- a/src/src/server/config/lib/load-config/main.ts +++ b/src/src/server/config/lib/load-config/main.ts @@ -14,7 +14,10 @@ export async function loadConfig({}: LoadConfigInput = {}): Promise key.toLowerCase().startsWith(constants.env.prefix.toLowerCase()) - ? { key: key.slice(constants.env.prefix.length), value } + ? { + key: key.slice(constants.env.prefix.length), + value: value === "" ? null : value, + } : false, }), ], diff --git a/src/src/server/config/schemas.ts.jinja b/src/src/server/config/schemas.ts.jinja index 7475a7e..690e66e 100644 --- a/src/src/server/config/schemas.ts.jinja +++ b/src/src/server/config/schemas.ts.jinja @@ -4,10 +4,22 @@ import * as z from "zod"; export const ConfigSchemas = { Config: z .object({ + apis: z + .object({ + icanhazdadjoke: z + .object({ + host: z.string().default("icanhazdadjoke.com"), + path: z.string().nullish(), + port: z.coerce.number().min(0).max(65535).nullish(), + scheme: z.string().default("https"), + }) + .prefault({}), + }) + .prefault({}), debug: z.stringbool().default(true), server: z .object({ - host: z.coerce.string().default("0.0.0.0"), + host: z.string().default("0.0.0.0"), port: z.coerce.number().min(0).max(65535).default({{ port }}), }) .prefault({}), diff --git a/src/src/server/metadata/lib/create-metadata/main.ts b/src/src/server/metadata/lib/create-metadata/main.ts index c689989..07d3a67 100644 --- a/src/src/server/metadata/lib/create-metadata/main.ts +++ b/src/src/server/metadata/lib/create-metadata/main.ts @@ -1,4 +1,4 @@ -import { omitBy } from "es-toolkit"; +import { omitBy } from "es-toolkit/object"; import type { CreateMetadataInput, CreateMetadataOutput } from "./types"; diff --git a/src/src/server/metadata/lib/create-viewport/main.ts b/src/src/server/metadata/lib/create-viewport/main.ts index 07fabff..ab39a83 100644 --- a/src/src/server/metadata/lib/create-viewport/main.ts +++ b/src/src/server/metadata/lib/create-viewport/main.ts @@ -1,4 +1,4 @@ -import { omitBy } from "es-toolkit"; +import { omitBy } from "es-toolkit/object"; import type { CreateViewportInput, CreateViewportOutput } from "./types"; diff --git a/src/src/server/orpc/lib/middleware/is-middleware-executed/main.ts b/src/src/server/orpc/lib/middleware/is-middleware-executed/main.ts index 0fe4f82..6e4765a 100644 --- a/src/src/server/orpc/lib/middleware/is-middleware-executed/main.ts +++ b/src/src/server/orpc/lib/middleware/is-middleware-executed/main.ts @@ -1,4 +1,4 @@ -import { isPlainObject } from "es-toolkit"; +import { isPlainObject } from "es-toolkit/predicate"; export function isMiddlewareExecuted(context: unknown, name: string): boolean { const key = `${name}Middleware`; diff --git a/src/src/server/orpc/vars/procedures/vars/test/vars/validate/main.ts b/src/src/server/orpc/vars/procedures/vars/test/vars/validate/main.ts index 7937edb..e8695d9 100644 --- a/src/src/server/orpc/vars/procedures/vars/test/vars/validate/main.ts +++ b/src/src/server/orpc/vars/procedures/vars/test/vars/validate/main.ts @@ -1,5 +1,34 @@ +import { msg } from "@lingui/core/macro"; + +import { getLocalization } from "../../../../../../../localization/lib/get-localization"; +import { state } from "../../../../../../../state/vars/state"; import { orpcServerRootBase } from "../../../../../bases/root"; +import { localeMiddleware } from "../../../../../middleware/locale"; + +export const validate = orpcServerRootBase.test.validate + .use(localeMiddleware) + .handler(async ({ context, input }) => { + const { localization } = getLocalization({ + locale: context.localeMiddleware.locale, + }); + + const response = await state.current.apis.icanhazdadjoke.getRandomJoke({ + headers: { + Accept: "application/json", + }, + throwOnError: true, + }); -export const validate = orpcServerRootBase.test.validate.handler( - async ({ input }) => ({ value: input.value }), -); + return { + message: + context.localeMiddleware.locale === "en" + ? response.data.joke + : localization.localize( + msg({ + message: + "Why did the chicken cross the road? To get to the other side.", + }), + ), + value: input.value, + }; + }); diff --git a/src/src/server/state/types.ts b/src/src/server/state/types.ts index 8dfce12..fa3d72f 100644 --- a/src/src/server/state/types.ts +++ b/src/src/server/state/types.ts @@ -1,7 +1,13 @@ import "server-only"; +import type { Sdk as ICanHazDadJokeSDK } from "../../common/apis/icanhazdadjoke/sdk"; import type { Config } from "../config/types"; +export type APIs = { + icanhazdadjoke: ICanHazDadJokeSDK; +}; + export type State = { + apis: APIs; config: Config; }; diff --git a/src/src/server/state/vars/state/utils.ts b/src/src/server/state/vars/state/utils.ts index 504fcdd..49a60b1 100644 --- a/src/src/server/state/vars/state/utils.ts +++ b/src/src/server/state/vars/state/utils.ts @@ -38,9 +38,7 @@ export class StateVariable { if (this.variable.current !== undefined) throw new StateAlreadyInitializedError(); - this.variable.current = proxy({ - config: state.config, - }); + this.variable.current = proxy(state); } private readonly variable = new GlobalVariable(constants.key); diff --git a/src/{% if docs %}docs{% endif %}/.gitignore.jinja b/src/{% if docs %}docs{% endif %}/.gitignore.jinja index 78f3f09..f699fa4 100644 --- a/src/{% if docs %}docs{% endif %}/.gitignore.jinja +++ b/src/{% if docs %}docs{% endif %}/.gitignore.jinja @@ -5,7 +5,7 @@ /build/ # Debug -npm-debug.log* +*.log # Typescript *.tsbuildinfo diff --git a/src/{% if docs %}docs{% endif %}/eslint.config.mjs b/src/{% if docs %}docs{% endif %}/eslint.config.mjs index ee56cc3..7053c38 100644 --- a/src/{% if docs %}docs{% endif %}/eslint.config.mjs +++ b/src/{% if docs %}docs{% endif %}/eslint.config.mjs @@ -1,5 +1,5 @@ import docusauruseslint from "@docusaurus/eslint-plugin"; -import { defineConfig } from "@eslint/config-helpers"; +import { defineConfig, globalIgnores } from "@eslint/config-helpers"; import jseslint from "@eslint/js"; import perfectionisteslint from "eslint-plugin-perfectionist"; import reacteslint from "eslint-plugin-react"; @@ -8,11 +8,15 @@ import globals from "globals"; import tseslint from "typescript-eslint"; const files = { + ignored: ["build/", "node_modules/"], js: ["**/*.js", "**/*.cjs", "**/*.mjs", "**/*.jsx"], ts: ["**/*.ts", "**/*.cts", "**/*.mts", "**/*.tsx"], }; export default defineConfig( + // Global ignores + globalIgnores(files.ignored), + // JavaScript support { files: files.js,