From e7cb060ea4f473930a137224f00a907c30bfe599 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sat, 4 May 2024 08:46:12 -0400 Subject: [PATCH 01/33] WIP: basic functionality --- apps/web/next-env.d.ts | 6 + packages/redwoodjs/package.json | 16 +- packages/redwoodjs/src/index.ts | 14 +- packages/redwoodjs/src/ratelimit/README.md | 87 + packages/redwoodjs/src/ratelimit/index.ts | 79 + packages/redwoodjs/src/ratelimit/util.ts | 37 + pnpm-lock.yaml | 7784 +++++++++++++++----- 7 files changed, 6246 insertions(+), 1777 deletions(-) create mode 100644 apps/web/next-env.d.ts create mode 100644 packages/redwoodjs/src/ratelimit/README.md create mode 100644 packages/redwoodjs/src/ratelimit/index.ts create mode 100644 packages/redwoodjs/src/ratelimit/util.ts diff --git a/apps/web/next-env.d.ts b/apps/web/next-env.d.ts new file mode 100644 index 0000000000..fd36f9494e --- /dev/null +++ b/apps/web/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/packages/redwoodjs/package.json b/packages/redwoodjs/package.json index e86a184e84..497b2b08c5 100644 --- a/packages/redwoodjs/package.json +++ b/packages/redwoodjs/package.json @@ -8,22 +8,32 @@ "publishConfig": { "access": "public" }, - "keywords": ["unkey", "redwoodjs", "sdk"], + "keywords": [ + "unkey", + "redwoodjs", + "sdk" + ], "bugs": { "url": "https://github.com/unkeyed/unkey/issues" }, "homepage": "https://github.com/unkeyed/unkey#readme", - "files": ["./dist/**"], + "files": [ + "./dist/**" + ], "author": "David Thyresson", "scripts": { "build": "tsup" }, "devDependencies": { + "@redwoodjs/vite": "^7.4.3", "@types/node": "^20.12.7", "tsup": "^8.0.2", "typescript": "^5.3.3" }, "dependencies": { - "@unkey/api": "workspace:^" + "@unkey/api": "workspace:^", + "@unkey/ratelimit": "workspace:^", + "@redwoodjs/vite": "8.0.0-canary.542", + "path-to-regexp": "^6.2.2" } } diff --git a/packages/redwoodjs/src/index.ts b/packages/redwoodjs/src/index.ts index fc6dd5a8f1..c42f9bc8e6 100644 --- a/packages/redwoodjs/src/index.ts +++ b/packages/redwoodjs/src/index.ts @@ -1,13 +1 @@ -import { Unkey } from "@unkey/api"; - -import { version } from "../package.json"; - -export async function doTheMagicHere() { - const _unkey = new Unkey({ - rootKey: "GET_THIS_FROM_ENV_SOMEHOW", - wrapperSdkVersion: `@unkey/redwoodjs@${version}`, - disableTelemetry: false, // TODO: andreas - }); - - // do stuff :) -} +export * from "./ratelimit"; diff --git a/packages/redwoodjs/src/ratelimit/README.md b/packages/redwoodjs/src/ratelimit/README.md new file mode 100644 index 0000000000..4c05d1f2e2 --- /dev/null +++ b/packages/redwoodjs/src/ratelimit/README.md @@ -0,0 +1,87 @@ +# withUnkey + +RedwoodJS Middleware to rate limit requests + +## Setup + +See [Rate limiting Onboarding](https://www.unkey.com/docs/onboarding/onboarding-ratelimiting) to get started with standalone [rate limiting](https://www.unkey.com/docs/apis/features/ratelimiting) from [Unkey](https://www.unkey.com). + +Note: Be sure to set your `UNKEY_ROOT_KEY` or key to be used for rate limiting in an `.env` file. + +## Examples + +### With Third Party Authentication like Supabase + +Here, we use a custom identifier function `supabaseRatelimitIdentifier` that: + +- checks is the request is authenticated +- constructs the identifier `sub` from the current user, since here the currentUser will be a JWT where the user id is the `sub` claim +- registers `supabaseAuthMiddleware` before `unkeyMiddleware` so the request can be authenticated before determining limits + +```file="web/entry.server.ts" +import createSupabaseAuthMiddleware from '@redwoodjs/auth-supabase-middleware' +import type { MiddlewareRequest } from '@redwoodjs/vite/middleware' +import type { TagDescriptor } from '@redwoodjs/web' + +import App from './App' +import { Document } from './Document' +import withUnkey from '@unkey/redwoodjs' +import type { withUnkeyOptions } from '@unkey/redwoodjs' + +// eslint-disable-next-line no-restricted-imports +import { getCurrentUser } from '$api/src/lib/auth' + +interface Props { + css: string[] + meta?: TagDescriptor[] +} + +export const supabaseRatelimitIdentifier = (req: MiddlewareRequest) => { + const authContext = req?.serverAuthContext?.get() + console.log('>>>> in supabaseRatelimitIdentifier', authContext) + const identifier = authContext?.isAuthenticated + ? (authContext.currentUser?.sub as string) || 'anonymous-user' + : '192.168.1.1' + return identifier +} + +export const registerMiddleware = () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: 'my-app', + limit: 1, + duration: '30s', + async: true, + }, + matcher: ['/blog-post/:slug(\\d{1,})'], + ratelimitIdentifierFn: supabaseRatelimitIdentifier, + } + const unkeyMiddleware = withUnkey(options) + const supabaseAuthMiddleware = createSupabaseAuthMiddleware({ + getCurrentUser, + }) + return [supabaseAuthMiddleware, unkeyMiddleware] +} + +interface Props { + css: string[] + meta?: TagDescriptor[] +} + +export const ServerEntry: React.FC = ({ css, meta }) => { + return ( + + + + ) +} +``` + +## Custom Rate Limit Exceeded Response + +TODO + +## Custom Rate Limit Error Response + +TODO diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts new file mode 100644 index 0000000000..b154028f7c --- /dev/null +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -0,0 +1,79 @@ +//import { Unkey } from "@unkey/api"; +//import { version } from "../../package.json"; + +import { Ratelimit } from "@unkey/ratelimit"; +import type { RatelimitConfig } from "@unkey/ratelimit"; + +import type { MiddlewareRequest } from "@redwoodjs/vite/dist/middleware"; +import type { MiddlewareResponse } from "@redwoodjs/vite/dist/middleware"; + +import { + defaultRatelimitErrorResponse, + defaultRatelimitExceededResponse, + defaultRatelimitIdentifier, + matchesPath, +} from "./util"; +import type { MiddlewarePathMatcher } from "./util"; + +export type withUnkeyOptions = { + ratelimitConfig: RatelimitConfig; + matcher: MiddlewarePathMatcher; + ratelimitIdentifierFn?: (req: MiddlewareRequest) => string; + ratelimitExceededResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; + ratelimitErrorResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; +}; + +const withUnkey = (options: withUnkeyOptions) => { + console.debug(">>>> in withUnkey createMiddleware", options); + const unkey = new Ratelimit(options.ratelimitConfig); + + return async (req: MiddlewareRequest, res: MiddlewareResponse) => { + const ratelimitIdentifier = options.ratelimitIdentifierFn || defaultRatelimitIdentifier; + + const rateLimitExceededResponse = + options.ratelimitExceededResponseFn || defaultRatelimitExceededResponse; + + const rateLimitErrorResponse = + options.ratelimitErrorResponseFn || defaultRatelimitErrorResponse; + + try { + const url = new URL(req.url); + const path = url.pathname; + + if (!matchesPath(path, options.matcher)) { + console.debug(">>>> in withUnkey skip middleware for", req.url); + return res; + } + + const identifier = ratelimitIdentifier(req); + + console.debug(">>>> in withUnkey identifier", identifier); + const ratelimit = await unkey.limit(identifier); + + if (!ratelimit.success) { + console.error("Rate limit exceeded", ratelimit); + const response = rateLimitExceededResponse(req); + if (response.status !== 429) { + console.warn("Rate limit exceeded response is not 429. Overriding status.", response); + response.status = 429; + } + return response; + } + } catch (e) { + console.error("Error in withUnkey", e); + const response = rateLimitErrorResponse(req); + if (response.status === 500) { + console.warn( + "Rate limit error response is 200 OK. Consider changing status to 500.", + response, + ); + } + } + + console.debug(">>>> in withUnkey return response for", req.url); + + return res; + }; +}; + +export default withUnkey; diff --git a/packages/redwoodjs/src/ratelimit/util.ts b/packages/redwoodjs/src/ratelimit/util.ts new file mode 100644 index 0000000000..0c2b3dc24d --- /dev/null +++ b/packages/redwoodjs/src/ratelimit/util.ts @@ -0,0 +1,37 @@ +import { type MatchFunction, match } from "path-to-regexp"; + +import type { MiddlewareRequest } from "@redwoodjs/vite/dist/middleware"; +import { MiddlewareResponse } from "@redwoodjs/vite/dist/middleware"; + +export type MiddlewarePathMatcher = string | string[]; + +export const defaultRatelimitIdentifier = (req: MiddlewareRequest) => { + const authContext = req?.serverAuthContext?.get(); + const identifier = authContext?.isAuthenticated + ? Buffer.from(JSON.stringify(authContext.currentUser)).toString("base64") + : "192.168.1.1"; + return identifier; +}; + +export const matchesPath = (path: string, matcher: MiddlewarePathMatcher): boolean => { + // Convert matcher to an array if it's not already one + const matchers = Array.isArray(matcher) ? matcher : [matcher]; + + console.debug(">>>> in matchesPath", matchers, path); + + // Create a list of matching functions from the matchers + const matchingFunctions: MatchFunction[] = matchers.map((pattern) => + match(pattern, { decode: decodeURIComponent }), + ); + + // Check if the path matches any of the patterns + return matchingFunctions.some((matchFunc) => matchFunc(path) !== false); +}; + +export const defaultRatelimitExceededResponse = (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Rate limit exceeded", { status: 429 }); +}; + +export const defaultRatelimitErrorResponse = (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Internal server error", { status: 500 }); +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1cfbad3479..a744833e79 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1347,9 +1347,18 @@ importers: packages/redwoodjs: dependencies: + '@redwoodjs/vite': + specifier: 8.0.0-canary.542 + version: 8.0.0-canary.542(@types/node@20.12.7)(csstype@3.1.3)(graphql-tag@2.12.6)(react-dom@18.3.1)(webpack@5.91.0) '@unkey/api': specifier: workspace:^ version: link:../api + '@unkey/ratelimit': + specifier: workspace:^ + version: link:../ratelimit + path-to-regexp: + specifier: ^6.2.2 + version: 6.2.2 devDependencies: '@types/node': specifier: ^20.12.7 @@ -1936,6 +1945,83 @@ packages: openapi-types: 12.1.3 dev: true + /@apollo/client@3.9.9(graphql@16.8.1)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): + resolution: {integrity: sha512-/sMecU/M0WK9knrguts1lSLV8xFKzIgOMVb4mi6MOxgJXjliDB8PvOtmXhTqh2cVMMR4TzXgOnb+af/690zlQw==} + peerDependencies: + graphql: ^15.0.0 || ^16.0.0 + graphql-ws: ^5.5.5 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + subscriptions-transport-ws: ^0.9.0 || ^0.11.0 + peerDependenciesMeta: + graphql-ws: + optional: true + react: + optional: true + react-dom: + optional: true + subscriptions-transport-ws: + optional: true + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + '@wry/caches': 1.0.1 + '@wry/equality': 0.5.7 + '@wry/trie': 0.5.0 + graphql: 16.8.1 + graphql-tag: 2.12.6(graphql@16.8.1) + hoist-non-react-statics: 3.3.2 + optimism: 0.18.0 + prop-types: 15.8.1 + react: 19.0.0-canary-cb151849e1-20240424 + react-dom: 18.3.1(react@18.3.1) + rehackt: 0.0.6(react@19.0.0-canary-cb151849e1-20240424) + response-iterator: 0.2.6 + symbol-observable: 4.0.0 + ts-invariant: 0.10.3 + tslib: 2.6.2 + zen-observable-ts: 1.2.5 + transitivePeerDependencies: + - '@types/react' + dev: false + + /@ardatan/relay-compiler@12.0.0(graphql@16.8.1): + resolution: {integrity: sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q==} + hasBin: true + peerDependencies: + graphql: '*' + dependencies: + '@babel/core': 7.24.5 + '@babel/generator': 7.24.5 + '@babel/parser': 7.24.5 + '@babel/runtime': 7.24.5 + '@babel/traverse': 7.24.5 + '@babel/types': 7.24.5 + babel-preset-fbjs: 3.4.0(@babel/core@7.24.5) + chalk: 4.1.2 + fb-watchman: 2.0.2 + fbjs: 3.0.5 + glob: 7.2.3 + graphql: 16.8.1 + immutable: 3.7.6 + invariant: 2.2.4 + nullthrows: 1.1.1 + relay-runtime: 12.0.0 + signedsource: 1.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@ardatan/sync-fetch@0.0.1: + resolution: {integrity: sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA==} + engines: {node: '>=14'} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + /@asteasolutions/zod-to-openapi@7.0.0(zod@3.23.5): resolution: {integrity: sha512-rJRKHD2m6nUb/9ZheeN8nqOURX24WTzY8Sex1ZKT0Kpx+xfpRcD0fTD6vEeXNHGaDGxzu65Jj/jb2x6nLTjcMw==} peerDependencies: @@ -1986,6 +2072,16 @@ packages: transitivePeerDependencies: - supports-color + /@babel/generator@7.24.1: + resolution: {integrity: sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.5 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 2.5.2 + dev: false + /@babel/generator@7.24.5: resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==} engines: {node: '>=6.9.0'} @@ -2000,7 +2096,13 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.24.5 - dev: true + + /@babel/helper-builder-binary-assignment-operator-visitor@7.22.15: + resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.5 + dev: false /@babel/helper-compilation-targets@7.23.6: resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} @@ -2028,7 +2130,33 @@ packages: '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 '@babel/helper-split-export-declaration': 7.24.5 semver: 6.3.1 - dev: true + + /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.24.5): + resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-annotate-as-pure': 7.22.5 + regexpu-core: 5.3.2 + semver: 6.3.1 + dev: false + + /@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.24.5): + resolution: {integrity: sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-plugin-utils': 7.24.5 + debug: 4.3.4 + lodash.debounce: 4.0.8 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: false /@babel/helper-environment-visitor@7.22.20: resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} @@ -2052,7 +2180,6 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.24.5 - dev: true /@babel/helper-module-imports@7.22.15: resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} @@ -2085,12 +2212,22 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.24.5 - dev: true /@babel/helper-plugin-utils@7.24.5: resolution: {integrity: sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==} engines: {node: '>=6.9.0'} - dev: true + + /@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.24.5): + resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-wrap-function': 7.24.5 + dev: false /@babel/helper-replace-supers@7.24.1(@babel/core@7.24.5): resolution: {integrity: sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==} @@ -2102,7 +2239,6 @@ packages: '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-member-expression-to-functions': 7.24.5 '@babel/helper-optimise-call-expression': 7.22.5 - dev: true /@babel/helper-simple-access@7.24.5: resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==} @@ -2115,7 +2251,6 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.24.5 - dev: true /@babel/helper-split-export-declaration@7.24.5: resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==} @@ -2135,6 +2270,15 @@ packages: resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} engines: {node: '>=6.9.0'} + /@babel/helper-wrap-function@7.24.5: + resolution: {integrity: sha512-/xxzuNvgRl4/HLNKvnFwdhdgN3cpLxgLROeLDl83Yx0AJ1SGvq1ak0OszTOjDfiB8Vx03eJbeDWh9r+jCCWttw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-function-name': 7.23.0 + '@babel/template': 7.24.0 + '@babel/types': 7.24.5 + dev: false + /@babel/helpers@7.24.5: resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==} engines: {node: '>=6.9.0'} @@ -2169,6 +2313,62 @@ packages: dependencies: '@babel/types': 7.24.5 + /@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-LdXRi1wEMTrHVR4Zc9F8OewC3vdm5h4QB6L71zy6StmYeqGi1b3ttIO8UC+BfZKcH9jdr4aI249rBkm+3+YvHw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-plugin-utils': 7.24.5 + dev: false + + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false + + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.24.5) + dev: false + + /@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-plugin-utils': 7.24.5 + dev: false + + /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.24.5): + resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + dev: false + /@babel/plugin-proposal-decorators@7.24.1(@babel/core@7.24.5): resolution: {integrity: sha512-zPEvzFijn+hRvJuX2Vu3KbEBN39LN3f7tW3MQO2LsIs57B26KU+kUc82BdAktS1VCM6libzh45eKGI65lg0cpA==} engines: {node: '>=6.9.0'} @@ -2181,47 +2381,60 @@ packages: '@babel/plugin-syntax-decorators': 7.24.1(@babel/core@7.24.5) dev: true - /@babel/plugin-syntax-decorators@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-05RJdO/cCrtVWuAaSn1tS3bH8jbsJa/Y1uD186u6J4C/1mnHFxseeuWpsqr9anvo7TUulev7tm7GDwRV+VuhDw==} + /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.24.5): + resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead. peerDependencies: '@babel/core': ^7.0.0-0 dependencies: + '@babel/compat-data': 7.24.4 '@babel/core': 7.24.5 + '@babel/helper-compilation-targets': 7.23.6 '@babel/helper-plugin-utils': 7.24.5 - dev: true + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.24.5) + dev: false - /@babel/plugin-syntax-import-attributes@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==} + /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.5): + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + dev: false + + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.5): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.24.5 '@babel/helper-plugin-utils': 7.24.5 - dev: true + dev: false - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.5): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.5): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.24.5 '@babel/helper-plugin-utils': 7.24.5 - dev: true + dev: false - /@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.5): + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.24.5 '@babel/helper-plugin-utils': 7.24.5 - dev: true + dev: false - /@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} + /@babel/plugin-syntax-decorators@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-05RJdO/cCrtVWuAaSn1tS3bH8jbsJa/Y1uD186u6J4C/1mnHFxseeuWpsqr9anvo7TUulev7tm7GDwRV+VuhDw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2230,2079 +2443,4045 @@ packages: '@babel/helper-plugin-utils': 7.24.5 dev: true - /@babel/plugin-transform-modules-commonjs@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==} - engines: {node: '>=6.9.0'} + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.24.5 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-simple-access': 7.24.5 - dev: true + dev: false - /@babel/plugin-transform-typescript@7.24.5(@babel/core@7.24.5): - resolution: {integrity: sha512-E0VWu/hk83BIFUWnsKZ4D81KXjN5L3MobvevOHErASk9IPwKHOkTgvqzvNo1yP/ePJWqqK2SpUR5z+KQbl6NVw==} - engines: {node: '>=6.9.0'} + /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5) - dev: true + dev: false - /@babel/preset-typescript@7.24.1(@babel/core@7.24.5): - resolution: {integrity: sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==} + /@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.24.5 '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-typescript': 7.24.5(@babel/core@7.24.5) - dev: true + dev: false - /@babel/runtime@7.24.5: - resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==} + /@babel/plugin-syntax-import-assertions@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - regenerator-runtime: 0.14.1 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@babel/standalone@7.24.5: - resolution: {integrity: sha512-Sl8oN9bGfRlNUA2jzfzoHEZxFBDliBlwi5mPVCAWKSlBNkXXJOHpu7SDOqjF6mRoTa6GNX/1kAWG3Tr+YQ3N7A==} + /@babel/plugin-syntax-import-attributes@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - /@babel/template@7.24.0: - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} - engines: {node: '>=6.9.0'} + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.5): + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/code-frame': 7.24.2 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - /@babel/traverse@7.24.5: - resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==} - engines: {node: '>=6.9.0'} + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@babel/types@7.24.5: - resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} + /@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.24.5 - to-fast-properties: 2.0.0 - - /@biomejs/biome@1.6.3: - resolution: {integrity: sha512-Xnp/TIpIcTnRA4LwerJuoGYQJEqwXtn5AL0U0OPXll/QGbAKmcUAfizU880xTwZRD4f53iceqODLDaD3wxYlIw==} - engines: {node: '>=14.*'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@biomejs/cli-darwin-arm64': 1.6.3 - '@biomejs/cli-darwin-x64': 1.6.3 - '@biomejs/cli-linux-arm64': 1.6.3 - '@biomejs/cli-linux-arm64-musl': 1.6.3 - '@biomejs/cli-linux-x64': 1.6.3 - '@biomejs/cli-linux-x64-musl': 1.6.3 - '@biomejs/cli-win32-arm64': 1.6.3 - '@biomejs/cli-win32-x64': 1.6.3 - dev: true - - /@biomejs/cli-darwin-arm64@1.6.3: - resolution: {integrity: sha512-0E8PGu3/8HSkBJdtjno+niJE1ANS/12D7sPK65vw5lTBYmmaYwJdfclDp6XO0IAX7uVd3/YtXlsEua0SVrNt3Q==} - engines: {node: '>=14.*'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@biomejs/cli-darwin-x64@1.6.3: - resolution: {integrity: sha512-UWu0We/aIRtWXgJKe6ygWt2xR0yXs64BwWqtZbfxBojRn3jgW8UdFAkV5yiUOX3TQlsV6BZH1EQaUAVsccUeeA==} - engines: {node: '>=14.*'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@biomejs/cli-linux-arm64-musl@1.6.3: - resolution: {integrity: sha512-AntGCSfLN1nPcQj4VOk3X2JgnDw07DaPC8BuBmRcsRmn+7GPSWLllVN5awIKlRPZEbGJtSnLkTiDc5Bxw8OiuA==} - engines: {node: '>=14.*'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - /@biomejs/cli-linux-arm64@1.6.3: - resolution: {integrity: sha512-wFVkQw38kOssfnkbpSh6ums5TaElw3RAt5i/VZwHmgR2nQgE0fHXLO7HwIE9VBkOEdbiIFq+2PxvFIHuJF3z3Q==} - engines: {node: '>=14.*'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.5): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@biomejs/cli-linux-x64-musl@1.6.3: - resolution: {integrity: sha512-GelAvGsUwbxfFpKLG+7+dvDmbrfkGqn08sL8CMQrGnhjE1krAqHWiXQsjfmi0UMFdMsk7hbc4oSAP+1+mrXcHQ==} - engines: {node: '>=14.*'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@biomejs/cli-linux-x64@1.6.3: - resolution: {integrity: sha512-vyn8TQaTZg617hjqFitwGmb1St5XXvq6I3vmxU/QFalM74BryMSvYCrYWb2Yw/TkykdEwZTMGYp+SWHRb04fTg==} - engines: {node: '>=14.*'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.5): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@biomejs/cli-win32-arm64@1.6.3: - resolution: {integrity: sha512-Gx8N2Tixke6pAI1BniteCVZgUUmaFEDYosdWxoaCus15BZI/7RcBxhsRM0ZL/lC66StSQ8vHl8JBrrld1k570Q==} - engines: {node: '>=14.*'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@biomejs/cli-win32-x64@1.6.3: - resolution: {integrity: sha512-meungPJw64SqoR7LXY1wG7GC4+4wgpyThdFUMGXa6PCe0BLFOIOcZ9VMj9PstuczMPdgmt/BUMPsj25dK1VO8A==} - engines: {node: '>=14.*'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@bundled-es-modules/cookie@2.0.0: - resolution: {integrity: sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==} + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - cookie: 0.5.0 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@bundled-es-modules/statuses@1.0.1: - resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.5): + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - statuses: 2.0.1 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@changesets/apply-release-plan@7.0.0: - resolution: {integrity: sha512-vfi69JR416qC9hWmFGSxj7N6wA5J222XNBmezSVATPWDVPIF7gkd4d8CpbEbXmRWbVrkoli3oerGS6dcL/BGsQ==} + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.5): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/runtime': 7.24.5 - '@changesets/config': 3.0.0 - '@changesets/get-version-range-type': 0.4.0 - '@changesets/git': 3.0.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - detect-indent: 6.1.0 - fs-extra: 7.0.1 - lodash.startcase: 4.4.0 - outdent: 0.5.0 - prettier: 2.8.8 - resolve-from: 5.0.0 - semver: 7.6.0 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@changesets/assemble-release-plan@6.0.0: - resolution: {integrity: sha512-4QG7NuisAjisbW4hkLCmGW2lRYdPrKzro+fCtZaILX+3zdUELSvYjpL4GTv0E4aM9Mef3PuIQp89VmHJ4y2bfw==} + /@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/runtime': 7.24.5 - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - semver: 7.6.0 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 - /@changesets/changelog-git@0.2.0: - resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} + /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.5): + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 dependencies: - '@changesets/types': 6.0.0 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@changesets/cli@2.27.1: - resolution: {integrity: sha512-iJ91xlvRnnrJnELTp4eJJEOPjgpF3NOh4qeQehM6Ugiz9gJPRZ2t+TsXun6E3AMN4hScZKjqVXl0TX+C7AB3ZQ==} - hasBin: true + /@babel/plugin-transform-arrow-functions@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/runtime': 7.24.5 - '@changesets/apply-release-plan': 7.0.0 - '@changesets/assemble-release-plan': 6.0.0 - '@changesets/changelog-git': 0.2.0 - '@changesets/config': 3.0.0 - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/get-release-plan': 4.0.0 - '@changesets/git': 3.0.0 - '@changesets/logger': 0.1.0 - '@changesets/pre': 2.0.0 - '@changesets/read': 0.6.0 - '@changesets/types': 6.0.0 - '@changesets/write': 0.3.0 - '@manypkg/get-packages': 1.1.3 - '@types/semver': 7.5.8 - ansi-colors: 4.1.3 - chalk: 2.4.2 - ci-info: 3.9.0 - enquirer: 2.4.1 - external-editor: 3.1.0 - fs-extra: 7.0.1 - human-id: 1.0.2 - meow: 6.1.1 - outdent: 0.5.0 - p-limit: 2.3.0 - preferred-pm: 3.1.3 - resolve-from: 5.0.0 - semver: 7.6.0 - spawndamnit: 2.0.0 - term-size: 2.2.1 - tty-table: 4.2.3 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@changesets/config@3.0.0: - resolution: {integrity: sha512-o/rwLNnAo/+j9Yvw9mkBQOZySDYyOr/q+wptRLcAVGlU6djOeP9v1nlalbL9MFsobuBVQbZCTp+dIzdq+CLQUA==} + /@babel/plugin-transform-async-generator-functions@7.24.3(@babel/core@7.24.5): + resolution: {integrity: sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/logger': 0.1.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - fs-extra: 7.0.1 - micromatch: 4.0.5 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.5) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5) + dev: false - /@changesets/errors@0.2.0: - resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + /@babel/plugin-transform-async-to-generator@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - extendable-error: 0.1.7 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-module-imports': 7.24.3 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.5) + dev: false - /@changesets/get-dependents-graph@2.0.0: - resolution: {integrity: sha512-cafUXponivK4vBgZ3yLu944mTvam06XEn2IZGjjKc0antpenkYANXiiE6GExV/yKdsCnE8dXVZ25yGqLYZmScA==} + /@babel/plugin-transform-block-scoped-functions@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - chalk: 2.4.2 - fs-extra: 7.0.1 - semver: 7.6.0 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@changesets/get-release-plan@4.0.0: - resolution: {integrity: sha512-9L9xCUeD/Tb6L/oKmpm8nyzsOzhdNBBbt/ZNcjynbHC07WW4E1eX8NMGC5g5SbM5z/V+MOrYsJ4lRW41GCbg3w==} + /@babel/plugin-transform-block-scoping@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/runtime': 7.24.5 - '@changesets/assemble-release-plan': 6.0.0 - '@changesets/config': 3.0.0 - '@changesets/pre': 2.0.0 - '@changesets/read': 0.6.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - dev: true - - /@changesets/get-version-range-type@0.4.0: - resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@changesets/git@3.0.0: - resolution: {integrity: sha512-vvhnZDHe2eiBNRFHEgMiGd2CT+164dfYyrJDhwwxTVD/OW0FUD6G7+4DIx1dNwkwjHyzisxGAU96q0sVNBns0w==} + /@babel/plugin-transform-class-properties@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/runtime': 7.24.5 - '@changesets/errors': 0.2.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - is-subdir: 1.2.0 - micromatch: 4.0.5 - spawndamnit: 2.0.0 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@changesets/logger@0.1.0: - resolution: {integrity: sha512-pBrJm4CQm9VqFVwWnSqKEfsS2ESnwqwH+xR7jETxIErZcfd1u2zBSqrHbRHR7xjhSgep9x2PSKFKY//FAshA3g==} + /@babel/plugin-transform-class-static-block@7.24.4(@babel/core@7.24.5): + resolution: {integrity: sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 dependencies: - chalk: 2.4.2 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.5) + dev: false - /@changesets/parse@0.4.0: - resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} + /@babel/plugin-transform-classes@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@changesets/types': 6.0.0 - js-yaml: 3.14.1 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.5) + '@babel/helper-split-export-declaration': 7.24.5 + globals: 11.12.0 + dev: false - /@changesets/pre@2.0.0: - resolution: {integrity: sha512-HLTNYX/A4jZxc+Sq8D1AMBsv+1qD6rmmJtjsCJa/9MSRybdxh0mjbTvE6JYZQ/ZiQ0mMlDOlGPXTm9KLTU3jyw==} + /@babel/plugin-transform-computed-properties@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/runtime': 7.24.5 - '@changesets/errors': 0.2.0 - '@changesets/types': 6.0.0 - '@manypkg/get-packages': 1.1.3 - fs-extra: 7.0.1 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/template': 7.24.0 + dev: false - /@changesets/read@0.6.0: - resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==} + /@babel/plugin-transform-destructuring@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/runtime': 7.24.5 - '@changesets/git': 3.0.0 - '@changesets/logger': 0.1.0 - '@changesets/parse': 0.4.0 - '@changesets/types': 6.0.0 - chalk: 2.4.2 - fs-extra: 7.0.1 - p-filter: 2.1.0 - dev: true - - /@changesets/types@4.1.0: - resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} - dev: true - - /@changesets/types@6.0.0: - resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@changesets/write@0.3.0: - resolution: {integrity: sha512-slGLb21fxZVUYbyea+94uFiD6ntQW0M2hIKNznFizDhZPDgn2c/fv1UzzlW43RVzh1BEDuIqW6hzlJ1OflNmcw==} + /@babel/plugin-transform-dotall-regex@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/runtime': 7.24.5 - '@changesets/types': 6.0.0 - fs-extra: 7.0.1 - human-id: 1.0.2 - prettier: 2.8.8 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@chronark/zod-bird@0.3.7: - resolution: {integrity: sha512-6IbCXqaaWtjxsYMbPHOUBZYCRRct4JufZ55LW9zHgyQNM0fP1KO7SQG2sIGD2ZHjd9P9OIESNmeYaxBxXTqWgA==} + /@babel/plugin-transform-duplicate-keys@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - zod: 3.23.5 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@clack/core@0.3.4: - resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==} + /@babel/plugin-transform-dynamic-import@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - picocolors: 1.0.0 - sisteransi: 1.0.5 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.5) + dev: false - /@clack/prompts@0.7.0: - resolution: {integrity: sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==} + /@babel/plugin-transform-exponentiation-operator@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@clack/core': 0.3.4 - picocolors: 1.0.0 - sisteransi: 1.0.5 - dev: true - bundledDependencies: - - is-unicode-supported + '@babel/core': 7.24.5 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@clerk/backend@0.38.4(react@18.2.0): - resolution: {integrity: sha512-Cp/vcuFqo3VsoBXWEWONhlzK5gXB3RDBImc5XgA4hvTSDAq7vvn+WYh/ya1eeVZ8g1LMaRx2Wl2OFml3zjGWJA==} - engines: {node: '>=14'} + /@babel/plugin-transform-export-namespace-from@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@clerk/shared': 1.4.0(react@18.2.0) - '@clerk/types': 3.63.0 - '@peculiar/webcrypto': 1.4.1 - '@types/node': 16.18.6 - cookie: 0.5.0 - deepmerge: 4.2.2 - node-fetch-native: 1.0.1 - snakecase-keys: 5.4.4 - tslib: 2.4.1 - transitivePeerDependencies: - - react + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.5) dev: false - /@clerk/backend@0.38.4(react@18.3.1): - resolution: {integrity: sha512-Cp/vcuFqo3VsoBXWEWONhlzK5gXB3RDBImc5XgA4hvTSDAq7vvn+WYh/ya1eeVZ8g1LMaRx2Wl2OFml3zjGWJA==} - engines: {node: '>=14'} + /@babel/plugin-transform-flow-strip-types@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@clerk/shared': 1.4.0(react@18.3.1) - '@clerk/types': 3.63.0 - '@peculiar/webcrypto': 1.4.1 - '@types/node': 16.18.6 - cookie: 0.5.0 - deepmerge: 4.2.2 - node-fetch-native: 1.0.1 - snakecase-keys: 5.4.4 - tslib: 2.4.1 - transitivePeerDependencies: - - react + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-flow': 7.24.1(@babel/core@7.24.5) dev: false - /@clerk/clerk-react@4.30.8(react@18.2.0): - resolution: {integrity: sha512-MehccfniWs2v7WSx4qGjJYxL+jtnsK6sETrzBuWctb7rLbvv4jDqjalhXbCm8YTV4qG19jHZl/WNsHOXSzBc7Q==} - engines: {node: '>=14'} + /@babel/plugin-transform-for-of@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==} + engines: {node: '>=6.9.0'} peerDependencies: - react: '>=16' + '@babel/core': ^7.0.0-0 dependencies: - '@clerk/shared': 1.4.0(react@18.2.0) - '@clerk/types': 3.63.0 - react: 18.2.0 - tslib: 2.4.1 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 dev: false - /@clerk/clerk-react@4.30.8(react@18.3.1): - resolution: {integrity: sha512-MehccfniWs2v7WSx4qGjJYxL+jtnsK6sETrzBuWctb7rLbvv4jDqjalhXbCm8YTV4qG19jHZl/WNsHOXSzBc7Q==} - engines: {node: '>=14'} + /@babel/plugin-transform-function-name@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==} + engines: {node: '>=6.9.0'} peerDependencies: - react: '>=16' + '@babel/core': ^7.0.0-0 dependencies: - '@clerk/shared': 1.4.0(react@18.3.1) - '@clerk/types': 3.63.0 - react: 18.3.1 - tslib: 2.4.1 + '@babel/core': 7.24.5 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@clerk/clerk-sdk-node@4.13.12(react@18.2.0): - resolution: {integrity: sha512-6OluVdh13OwOVk5m+Zgfwph1B/1Zz3AzBepuZubdPmI2r0c1YVOuo/09WJiBRZdglkoIcS0868ZRBsZMrPJDLQ==} - engines: {node: '>=14'} + /@babel/plugin-transform-json-strings@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@clerk/backend': 0.38.4(react@18.2.0) - '@clerk/shared': 1.4.0(react@18.2.0) - '@clerk/types': 3.63.0 - '@types/cookies': 0.7.7 - '@types/express': 4.17.14 - '@types/node-fetch': 2.6.2 - camelcase-keys: 6.2.2 - snakecase-keys: 3.2.1 - tslib: 2.4.1 - transitivePeerDependencies: - - react + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5) dev: false - /@clerk/clerk-sdk-node@4.13.12(react@18.3.1): - resolution: {integrity: sha512-6OluVdh13OwOVk5m+Zgfwph1B/1Zz3AzBepuZubdPmI2r0c1YVOuo/09WJiBRZdglkoIcS0868ZRBsZMrPJDLQ==} - engines: {node: '>=14'} + /@babel/plugin-transform-literals@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@clerk/backend': 0.38.4(react@18.3.1) - '@clerk/shared': 1.4.0(react@18.3.1) - '@clerk/types': 3.63.0 - '@types/cookies': 0.7.7 - '@types/express': 4.17.14 - '@types/node-fetch': 2.6.2 - camelcase-keys: 6.2.2 - snakecase-keys: 3.2.1 - tslib: 2.4.1 - transitivePeerDependencies: - - react + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@clerk/nextjs@4.29.10(next@14.1.3)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-nu8tIzZxxwqFYupBp66BSYSp+qAEUvGUFJ1eAqvgQjOUWh+rElQTfOMI0sm3hOX85sZv04WKA9hiAT93qLILsg==} - engines: {node: '>=14'} + /@babel/plugin-transform-logical-assignment-operators@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==} + engines: {node: '>=6.9.0'} peerDependencies: - next: '>=10' - react: ^17.0.2 || ^18.0.0-0 - react-dom: ^17.0.2 || ^18.0.0-0 + '@babel/core': ^7.0.0-0 dependencies: - '@clerk/backend': 0.38.4(react@18.2.0) - '@clerk/clerk-react': 4.30.8(react@18.2.0) - '@clerk/clerk-sdk-node': 4.13.12(react@18.2.0) - '@clerk/shared': 1.4.0(react@18.2.0) - '@clerk/types': 3.63.0 - next: 14.1.3(@babel/core@7.24.5)(react-dom@18.2.0)(react@18.2.0) - path-to-regexp: 6.2.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - tslib: 2.4.1 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5) dev: false - /@clerk/nextjs@4.29.10(next@14.2.2)(react-dom@18.2.0)(react@18.3.1): - resolution: {integrity: sha512-nu8tIzZxxwqFYupBp66BSYSp+qAEUvGUFJ1eAqvgQjOUWh+rElQTfOMI0sm3hOX85sZv04WKA9hiAT93qLILsg==} - engines: {node: '>=14'} + /@babel/plugin-transform-member-expression-literals@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==} + engines: {node: '>=6.9.0'} peerDependencies: - next: '>=10' - react: ^17.0.2 || ^18.0.0-0 - react-dom: ^17.0.2 || ^18.0.0-0 + '@babel/core': ^7.0.0-0 dependencies: - '@clerk/backend': 0.38.4(react@18.3.1) - '@clerk/clerk-react': 4.30.8(react@18.3.1) - '@clerk/clerk-sdk-node': 4.13.12(react@18.3.1) - '@clerk/shared': 1.4.0(react@18.3.1) - '@clerk/types': 3.63.0 - next: 14.2.2(@babel/core@7.24.5)(@opentelemetry/api@1.4.1)(react-dom@18.2.0)(react@18.3.1) - path-to-regexp: 6.2.1 - react: 18.3.1 - react-dom: 18.2.0(react@18.3.1) - tslib: 2.4.1 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@clerk/shared@1.4.0(react@18.2.0): - resolution: {integrity: sha512-LANWfdw3n7lCN90oY+myuCN74CfGgBQE/T11ry/bTSNVqUxXiYaUlfu5Fkp0GsR4icYiA6NRyROFmYdYZfBMAA==} + /@babel/plugin-transform-modules-amd@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==} + engines: {node: '>=6.9.0'} peerDependencies: - react: '>=16' - peerDependenciesMeta: - react: - optional: true + '@babel/core': ^7.0.0-0 dependencies: - glob-to-regexp: 0.4.1 - js-cookie: 3.0.1 - react: 18.2.0 - swr: 2.2.0(react@18.2.0) + '@babel/core': 7.24.5 + '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@clerk/shared@1.4.0(react@18.3.1): - resolution: {integrity: sha512-LANWfdw3n7lCN90oY+myuCN74CfGgBQE/T11ry/bTSNVqUxXiYaUlfu5Fkp0GsR4icYiA6NRyROFmYdYZfBMAA==} + /@babel/plugin-transform-modules-commonjs@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==} + engines: {node: '>=6.9.0'} peerDependencies: - react: '>=16' - peerDependenciesMeta: - react: - optional: true + '@babel/core': ^7.0.0-0 dependencies: - glob-to-regexp: 0.4.1 - js-cookie: 3.0.1 - react: 18.3.1 - swr: 2.2.0(react@18.3.1) - dev: false + '@babel/core': 7.24.5 + '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-simple-access': 7.24.5 - /@clerk/types@3.63.0: - resolution: {integrity: sha512-+32fWK+lUG2u0hVaoQ3aZ+j2T/LhF3yNNylBrkD1Kca/goLb+NB/nmw6Svs0Q810FK/uYgqWlXvABPhgILeQFA==} - engines: {node: '>=14'} + /@babel/plugin-transform-modules-systemjs@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - csstype: 3.1.1 + '@babel/core': 7.24.5 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-validator-identifier': 7.24.5 dev: false - /@clerk/types@3.63.1: - resolution: {integrity: sha512-PeZrRzWApJl1BYsT/wQPtEzhDmwfqeMKWuSRcHe3Kh0Itc5Gp7w9HrrKkyMnRuzebVj4z5gX4rwJOmTD/P1DhQ==} - engines: {node: '>=14'} + /@babel/plugin-transform-modules-umd@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - csstype: 3.1.1 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@cloudflare/kv-asset-handler@0.3.1: - resolution: {integrity: sha512-lKN2XCfKCmpKb86a1tl4GIwsJYDy9TGuwjhDELLmpKygQhw8X2xR4dusgpC5Tg7q1pB96Eb0rBo81kxSILQMwA==} + /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.24.5): + resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 dependencies: - mime: 3.0.0 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@cloudflare/kv-asset-handler@0.3.2: - resolution: {integrity: sha512-EeEjMobfuJrwoctj7FA1y1KEbM0+Q1xSjobIEyie9k4haVEBB7vkDvsasw1pM3rO39mL2akxIAzLMUAtrMHZhA==} - engines: {node: '>=16.13'} + /@babel/plugin-transform-new-target@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - mime: 3.0.0 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@cloudflare/vitest-pool-workers@0.2.2(@cloudflare/workers-types@4.20240419.0)(@vitest/runner@1.3.0)(@vitest/snapshot@1.3.0)(vitest@1.3.0): - resolution: {integrity: sha512-LQfSLMCreWX9idVNB1qBRhZHi347nAN90PU0mxMyYZ9ElGnvJjKj/49aefW6X9+ixwLG3pH5eV1i06T8017fZg==} + /@babel/plugin-transform-nullish-coalescing-operator@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==} + engines: {node: '>=6.9.0'} peerDependencies: - '@vitest/runner': 1.3.0 - '@vitest/snapshot': 1.3.0 - vitest: 1.3.0 + '@babel/core': ^7.0.0-0 dependencies: - '@vitest/runner': 1.3.0 - '@vitest/snapshot': 1.3.0 - birpc: 0.2.14 - cjs-module-lexer: 1.3.1 - devalue: 4.3.3 - esbuild: 0.17.19 - miniflare: 3.20240405.2 - vitest: 1.3.0(@types/node@20.12.7)(@vitest/ui@1.3.0) - wrangler: 3.51.2(@cloudflare/workers-types@4.20240419.0) - zod: 3.23.5 - transitivePeerDependencies: - - '@cloudflare/workers-types' - - bufferutil - - supports-color - - utf-8-validate - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5) + dev: false - /@cloudflare/workerd-darwin-64@1.20240405.0: - resolution: {integrity: sha512-ut8kwpHmlz9dNSjoov6v1b6jS50J46Mj9QcMA0t1Hne36InaQk/qqPSd12fN5p2GesZ9OOBJvBdDsTblVdyJ1w==} - engines: {node: '>=16'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true + /@babel/plugin-transform-numeric-separator@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5) + dev: false - /@cloudflare/workerd-darwin-arm64@1.20240405.0: - resolution: {integrity: sha512-x3A3Ym+J2DH1uYnw0aedeKOTnUebEo312+Aladv7bFri97pjRJcqVbYhMtOHLkHjwYn7bpKSY2eL5iM+0XT29A==} - engines: {node: '>=16'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true + /@babel/plugin-transform-object-rest-spread@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.24.5) + dev: false - /@cloudflare/workerd-linux-64@1.20240405.0: - resolution: {integrity: sha512-3tYpfjtxEQ0R30Pna7OF3Bz0CTx30hc0QNtH61KnkvXtaeYMkWutSKQKXIuVlPa/7v1MHp+8ViBXMflmS7HquA==} - engines: {node: '>=16'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true + /@babel/plugin-transform-object-super@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.5) + dev: false - /@cloudflare/workerd-linux-arm64@1.20240405.0: - resolution: {integrity: sha512-NpKZlvmdgcX/m4tP5zM91AfJpZrue2/GRA+Sl3szxAivu2uE5jDVf5SS9dzqzCVfPrdhylqH7yeL4U/cafFNOg==} - engines: {node: '>=16'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true + /@babel/plugin-transform-optional-catch-binding@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5) + dev: false - /@cloudflare/workerd-windows-64@1.20240405.0: - resolution: {integrity: sha512-REBeJMxvUCjwuEVzSSIBtzAyM69QjToab8qBst0S9vdih+9DObym4dw8CevdBQhDbFrHiyL9E6pAZpLPNHVgCw==} - engines: {node: '>=16'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true + /@babel/plugin-transform-optional-chaining@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5) + dev: false - /@cloudflare/workers-types@4.20240419.0: - resolution: {integrity: sha512-UM16sr4HEe0mDj6C5OFcodzdj/CnEp0bfncAq3g7OpDsoZ1sBrfsMrb7Yc4f8J81EemvmQZyE6sSanpURtVkcQ==} + /@babel/plugin-transform-parameters@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@commitlint/config-validator@19.0.3: - resolution: {integrity: sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==} - engines: {node: '>=v18'} + /@babel/plugin-transform-private-methods@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@commitlint/types': 19.0.3 - ajv: 8.13.0 - dev: true - optional: true + '@babel/core': 7.24.5 + '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@commitlint/execute-rule@19.0.0: - resolution: {integrity: sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==} - engines: {node: '>=v18'} - dev: true - optional: true - - /@commitlint/load@19.2.0(@types/node@20.12.7)(typescript@5.3.3): - resolution: {integrity: sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ==} - engines: {node: '>=v18'} - requiresBuild: true - dependencies: - '@commitlint/config-validator': 19.0.3 - '@commitlint/execute-rule': 19.0.0 - '@commitlint/resolve-extends': 19.1.0 - '@commitlint/types': 19.0.3 - chalk: 5.3.0 - cosmiconfig: 9.0.0(typescript@5.3.3) - cosmiconfig-typescript-loader: 5.0.0(@types/node@20.12.7)(cosmiconfig@9.0.0)(typescript@5.3.3) - lodash.isplainobject: 4.0.6 - lodash.merge: 4.6.2 - lodash.uniq: 4.5.0 - transitivePeerDependencies: - - '@types/node' - - typescript - dev: true - optional: true - - /@commitlint/resolve-extends@19.1.0: - resolution: {integrity: sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==} - engines: {node: '>=v18'} + /@babel/plugin-transform-private-property-in-object@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@commitlint/config-validator': 19.0.3 - '@commitlint/types': 19.0.3 - global-directory: 4.0.1 - import-meta-resolve: 4.1.0 - lodash.mergewith: 4.6.2 - resolve-from: 5.0.0 - dev: true - optional: true + '@babel/core': 7.24.5 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.5) + dev: false - /@commitlint/types@19.0.3: - resolution: {integrity: sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==} - engines: {node: '>=v18'} + /@babel/plugin-transform-property-literals@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@types/conventional-commits-parser': 5.0.0 - chalk: 5.3.0 - dev: true - optional: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@contentlayer/cli@0.3.4(esbuild@0.20.2): - resolution: {integrity: sha512-vNDwgLuhYNu+m70NZ3XK9kexKNguuxPXg7Yvzj3B34cEilQjjzSrcTY/i+AIQm9V7uT5GGshx9ukzPf+SmoszQ==} + /@babel/plugin-transform-react-display-name@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@contentlayer/core': 0.3.4(esbuild@0.20.2) - '@contentlayer/utils': 0.3.4 - clipanion: 3.2.1(typanion@3.14.0) - typanion: 3.14.0 - transitivePeerDependencies: - - '@effect-ts/otel-node' - - esbuild - - markdown-wasm - - supports-color + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@contentlayer/client@0.3.4(esbuild@0.20.2): - resolution: {integrity: sha512-QSlLyc3y4PtdC5lFw0L4wTZUH8BQnv2nk37hNCsPAqGf+dRO7TLAzdc+2/mVIRgK+vSH+pSOzjLsQpFxxXRTZA==} + /@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.24.5): + resolution: {integrity: sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@contentlayer/core': 0.3.4(esbuild@0.20.2) - transitivePeerDependencies: - - '@effect-ts/otel-node' - - esbuild - - markdown-wasm - - supports-color + '@babel/core': 7.24.5 + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.5) dev: false - /@contentlayer/core@0.3.4(esbuild@0.20.2): - resolution: {integrity: sha512-o68oBLwfYZ+2vtgfk1lgHxOl3LoxvRNiUfeQ8IWFWy/L4wnIkKIqLZX01zlRE5IzYM+ZMMN5V0cKQlO7DsyR9g==} + /@babel/plugin-transform-react-jsx-self@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-RtCJoUO2oYrYwFPtR1/jkoBEcFuI1ae9a9IMxeyAVa3a1Ap4AnxmyIKG2b2FaJKqkidw/0cxRbWN+HOs6ZWd1w==} + engines: {node: '>=6.9.0'} peerDependencies: - esbuild: 0.17.x || 0.18.x - markdown-wasm: 1.x - peerDependenciesMeta: - esbuild: - optional: true - markdown-wasm: - optional: true + '@babel/core': ^7.0.0-0 dependencies: - '@contentlayer/utils': 0.3.4 - camel-case: 4.1.2 - comment-json: 4.2.3 - esbuild: 0.20.2 - gray-matter: 4.0.3 - mdx-bundler: 9.2.1(esbuild@0.20.2) - rehype-stringify: 9.0.4 - remark-frontmatter: 4.0.1 - remark-parse: 10.0.2 - remark-rehype: 10.1.0 - source-map-support: 0.5.21 - type-fest: 3.13.1 - unified: 10.1.2 - transitivePeerDependencies: - - '@effect-ts/otel-node' - - supports-color + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@contentlayer/source-files@0.3.4(esbuild@0.20.2): - resolution: {integrity: sha512-4njyn0OFPu7WY4tAjMxiJgWOKeiHuBOGdQ36EYE03iij/pPPRbiWbL+cmLccYXUFEW58mDwpqROZZm6pnxjRDQ==} + /@babel/plugin-transform-react-jsx-source@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@contentlayer/core': 0.3.4(esbuild@0.20.2) - '@contentlayer/utils': 0.3.4 - chokidar: 3.6.0 - fast-glob: 3.3.2 - gray-matter: 4.0.3 - imagescript: 1.3.0 - micromatch: 4.0.5 - ts-pattern: 4.3.0 - unified: 10.1.2 - yaml: 2.4.2 - zod: 3.23.5 - transitivePeerDependencies: - - '@effect-ts/otel-node' - - esbuild - - markdown-wasm - - supports-color + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@contentlayer/source-remote-files@0.3.4(esbuild@0.20.2): - resolution: {integrity: sha512-cyiv4sNUySZvR0uAKlM+kSAELzNd2h2QT1R2e41dRKbwOUVxeLfmGiLugr0aVac6Q3xYcD99dbHyR1xWPV+w9w==} + /@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.5): + resolution: {integrity: sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@contentlayer/core': 0.3.4(esbuild@0.20.2) - '@contentlayer/source-files': 0.3.4(esbuild@0.20.2) - '@contentlayer/utils': 0.3.4 - transitivePeerDependencies: - - '@effect-ts/otel-node' - - esbuild - - markdown-wasm - - supports-color + '@babel/core': 7.24.5 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-module-imports': 7.24.3 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) + '@babel/types': 7.24.5 dev: false - /@contentlayer/utils@0.3.4: - resolution: {integrity: sha512-ZWWOhbUWYQ2QHoLIlcUnEo7X4ZbwcyFPuzVQWWMkK43BxCveyQtZwBIzfyx54sqVzi0GUmKP8bHzsLQT0QxaLQ==} + /@babel/plugin-transform-react-pure-annotations@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA==} + engines: {node: '>=6.9.0'} peerDependencies: - '@effect-ts/otel-node': '*' - peerDependenciesMeta: - '@effect-ts/core': - optional: true - '@effect-ts/otel': - optional: true - '@effect-ts/otel-node': - optional: true + '@babel/core': ^7.0.0-0 dependencies: - '@effect-ts/core': 0.60.5 - '@effect-ts/otel': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0) - '@effect-ts/otel-exporter-trace-otlp-grpc': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/exporter-trace-otlp-grpc@0.39.1)(@opentelemetry/sdk-trace-base@1.13.0) - '@effect-ts/otel-sdk-trace-node': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0)(@opentelemetry/sdk-trace-node@1.13.0) - '@js-temporal/polyfill': 0.4.4 - '@opentelemetry/api': 1.4.1 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.4.1) - '@opentelemetry/exporter-trace-otlp-grpc': 0.39.1(@opentelemetry/api@1.4.1) - '@opentelemetry/resources': 1.13.0(@opentelemetry/api@1.4.1) - '@opentelemetry/sdk-trace-base': 1.13.0(@opentelemetry/api@1.4.1) - '@opentelemetry/sdk-trace-node': 1.13.0(@opentelemetry/api@1.4.1) - '@opentelemetry/semantic-conventions': 1.13.0 - chokidar: 3.6.0 - hash-wasm: 4.11.0 - inflection: 2.0.1 - memfs: 3.5.3 - oo-ascii-tree: 1.97.0 - ts-pattern: 4.3.0 - type-fest: 3.13.1 + '@babel/core': 7.24.5 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} + /@babel/plugin-transform-regenerator@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + regenerator-transform: 0.15.2 + dev: false - /@dagrejs/graphlib@2.1.4: - resolution: {integrity: sha512-QCg9sL4uhjn468FDEsb/S9hS2xUZSrv/+dApb1Ze5VKO96pTXKNJZ6MGhIpgWkc1TVhbVGH9/7rq/Mf8/jWicw==} + /@babel/plugin-transform-reserved-words@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - lodash: 4.17.21 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@effect-ts/core@0.60.5: - resolution: {integrity: sha512-qi1WrtJA90XLMnj2hnUszW9Sx4dXP03ZJtCc5DiUBIOhF4Vw7plfb65/bdBySPoC9s7zy995TdUX1XBSxUkl5w==} + /@babel/plugin-transform-runtime@7.24.3(@babel/core@7.24.5): + resolution: {integrity: sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@effect-ts/system': 0.57.5 + '@babel/core': 7.24.5 + '@babel/helper-module-imports': 7.24.3 + '@babel/helper-plugin-utils': 7.24.5 + babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.24.5) + babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.24.5) + babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.24.5) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color dev: false - /@effect-ts/otel-exporter-trace-otlp-grpc@0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/exporter-trace-otlp-grpc@0.39.1)(@opentelemetry/sdk-trace-base@1.13.0): - resolution: {integrity: sha512-47gAg0O2pW5Jlo86jfzjdkwL5a7Bzb+Kj5WTmdu4CxYRfWn9ytKjuuYIfsNDW8neuhdKzn+P5wCddgEh0glYyQ==} + /@babel/plugin-transform-shorthand-properties@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==} + engines: {node: '>=6.9.0'} peerDependencies: - '@effect-ts/core': ^0.60.2 - '@opentelemetry/api': ^1.4.0 - '@opentelemetry/core': ^1.13.0 - '@opentelemetry/exporter-trace-otlp-grpc': ^0.39.0 - '@opentelemetry/sdk-trace-base': ^1.13.0 + '@babel/core': ^7.0.0-0 dependencies: - '@effect-ts/core': 0.60.5 - '@effect-ts/otel': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0) - '@opentelemetry/api': 1.4.1 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.4.1) - '@opentelemetry/exporter-trace-otlp-grpc': 0.39.1(@opentelemetry/api@1.4.1) - '@opentelemetry/sdk-trace-base': 1.13.0(@opentelemetry/api@1.4.1) + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@effect-ts/otel-sdk-trace-node@0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0)(@opentelemetry/sdk-trace-node@1.13.0): - resolution: {integrity: sha512-a2sF0ylmn8xOJs8fNeT/spJ1gUcsksAJCALxo9WOfuTCMtTwMVtVhCKEPEeQoL7wFqU+JgPkVdP91+FJ/Rkeow==} + /@babel/plugin-transform-spread@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==} + engines: {node: '>=6.9.0'} peerDependencies: - '@effect-ts/core': ^0.60.2 - '@opentelemetry/api': ^1.4.0 - '@opentelemetry/core': ^1.13.0 - '@opentelemetry/sdk-trace-base': ^1.13.0 - '@opentelemetry/sdk-trace-node': ^1.13.0 + '@babel/core': ^7.0.0-0 dependencies: - '@effect-ts/core': 0.60.5 - '@effect-ts/otel': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0) - '@opentelemetry/api': 1.4.1 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.4.1) - '@opentelemetry/sdk-trace-base': 1.13.0(@opentelemetry/api@1.4.1) - '@opentelemetry/sdk-trace-node': 1.13.0(@opentelemetry/api@1.4.1) + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 dev: false - /@effect-ts/otel@0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0): - resolution: {integrity: sha512-AmZJHl7t0+Peh7Yb2+hqn6r9+rd9/UfeA4AMV9h0YGTdOyouyFfD3wzWlxnAUzAQ4Lrod4kC7Noruret4EpqpA==} + /@babel/plugin-transform-sticky-regex@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==} + engines: {node: '>=6.9.0'} peerDependencies: - '@effect-ts/core': ^0.60.2 - '@opentelemetry/api': ^1.4.0 - '@opentelemetry/core': ^1.13.0 - '@opentelemetry/sdk-trace-base': ^1.13.0 + '@babel/core': ^7.0.0-0 dependencies: - '@effect-ts/core': 0.60.5 - '@opentelemetry/api': 1.4.1 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.4.1) - '@opentelemetry/sdk-trace-base': 1.13.0(@opentelemetry/api@1.4.1) - dev: false - - /@effect-ts/system@0.57.5: - resolution: {integrity: sha512-/crHGujo0xnuHIYNc1VgP0HGJGFSoSqq88JFXe6FmFyXPpWt8Xu39LyLg7rchsxfXFeEdA9CrIZvLV5eswXV5g==} + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - /@emnapi/runtime@1.1.1: - resolution: {integrity: sha512-3bfqkzuR1KLx57nZfjr2NLnFOobvyS0aTszaEGCGqmYMVDRaGvgIZbjGSV/MHSSmLgQ/b9JFHQ5xm5WRZYd+XQ==} - requiresBuild: true - dependencies: - tslib: 2.6.2 - dev: true - optional: true - - /@emotion/is-prop-valid@0.8.8: - resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} - requiresBuild: true + /@babel/plugin-transform-template-literals@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@emotion/memoize': 0.7.4 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - optional: true - /@emotion/memoize@0.7.4: - resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + /@babel/plugin-transform-typeof-symbol@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: false - optional: true - /@ericcornelissen/bash-parser@0.5.2: - resolution: {integrity: sha512-4pIMTa1nEFfMXitv7oaNEWOdM+zpOZavesa5GaiWTgda6Zk32CFGxjUp/iIaN0PwgUW1yTq/fztSjbpE8SLGZQ==} - engines: {node: '>=4'} + /@babel/plugin-transform-typescript@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-E0VWu/hk83BIFUWnsKZ4D81KXjN5L3MobvevOHErASk9IPwKHOkTgvqzvNo1yP/ePJWqqK2SpUR5z+KQbl6NVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - array-last: 1.3.0 - babylon: 6.18.0 - compose-function: 3.0.3 - deep-freeze: 0.0.1 - filter-iterator: 0.0.1 - filter-obj: 1.1.0 - has-own-property: 0.1.0 - identity-function: 1.0.0 - is-iterable: 1.1.1 - iterable-lookahead: 1.0.0 - lodash.curry: 4.1.1 - magic-string: 0.16.0 - map-obj: 2.0.0 - object-pairs: 0.1.0 - object-values: 1.0.0 - reverse-arguments: 1.0.0 - shell-quote-word: 1.0.1 - to-pascal-case: 1.0.0 - unescape-js: 1.1.4 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5) - /@esbuild-kit/core-utils@3.3.2: - resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} + /@babel/plugin-transform-unicode-escapes@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - esbuild: 0.18.20 - source-map-support: 0.5.21 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@esbuild-kit/esm-loader@2.6.5: - resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} + /@babel/plugin-transform-unicode-property-regex@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@esbuild-kit/core-utils': 3.3.2 - get-tsconfig: 4.7.3 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19): - resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==} + /@babel/plugin-transform-unicode-regex@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==} + engines: {node: '>=6.9.0'} peerDependencies: - esbuild: '*' + '@babel/core': ^7.0.0-0 dependencies: - esbuild: 0.17.19 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19): - resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==} + /@babel/plugin-transform-unicode-sets-regex@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==} + engines: {node: '>=6.9.0'} peerDependencies: - esbuild: '*' + '@babel/core': ^7.0.0 dependencies: - esbuild: 0.17.19 - escape-string-regexp: 4.0.0 - rollup-plugin-node-polyfills: 0.2.1 - dev: true + '@babel/core': 7.24.5 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) + '@babel/helper-plugin-utils': 7.24.5 + dev: false - /@esbuild-plugins/node-resolve@0.1.4(esbuild@0.20.2): - resolution: {integrity: sha512-haFQ0qhxEpqtWWY0kx1Y5oE3sMyO1PcoSiWEPrAw6tm/ZOOLXjSs6Q+v1v9eyuVF0nNt50YEvrcrvENmyoMv5g==} + /@babel/preset-env@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==} + engines: {node: '>=6.9.0'} peerDependencies: - esbuild: '*' + '@babel/core': ^7.0.0-0 dependencies: - '@types/resolve': 1.20.6 - debug: 4.3.4 - esbuild: 0.20.2 - escape-string-regexp: 4.0.0 - resolve: 1.22.8 + '@babel/compat-data': 7.24.4 + '@babel/core': 7.24.5 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-validator-option': 7.23.5 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.5) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.5) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.5) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-import-assertions': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-syntax-import-attributes': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.5) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.5) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.5) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.24.5) + '@babel/plugin-transform-arrow-functions': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-async-generator-functions': 7.24.3(@babel/core@7.24.5) + '@babel/plugin-transform-async-to-generator': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-block-scoped-functions': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-block-scoping': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-class-properties': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-class-static-block': 7.24.4(@babel/core@7.24.5) + '@babel/plugin-transform-classes': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-computed-properties': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-destructuring': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-dotall-regex': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-duplicate-keys': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-dynamic-import': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-exponentiation-operator': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-export-namespace-from': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-for-of': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-function-name': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-json-strings': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-literals': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-logical-assignment-operators': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-member-expression-literals': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-modules-amd': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-modules-systemjs': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-modules-umd': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.24.5) + '@babel/plugin-transform-new-target': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-nullish-coalescing-operator': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-numeric-separator': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-object-rest-spread': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-object-super': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-optional-catch-binding': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-private-methods': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-private-property-in-object': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-property-literals': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-regenerator': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-reserved-words': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-shorthand-properties': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-spread': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-sticky-regex': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-template-literals': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-typeof-symbol': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-unicode-escapes': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-unicode-property-regex': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-unicode-regex': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-unicode-sets-regex': 7.24.1(@babel/core@7.24.5) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.24.5) + babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.24.5) + babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.24.5) + babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.24.5) + core-js-compat: 3.37.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color dev: false - /@esbuild/aix-ppc64@0.19.11: - resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true + /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.5): + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/types': 7.24.5 + esutils: 2.0.3 dev: false - optional: true - - /@esbuild/aix-ppc64@0.19.12: - resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: true - optional: true - /@esbuild/aix-ppc64@0.20.2: - resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - optional: true + /@babel/preset-react@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-validator-option': 7.23.5 + '@babel/plugin-transform-react-display-name': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.5) + '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.24.5) + '@babel/plugin-transform-react-pure-annotations': 7.24.1(@babel/core@7.24.5) + dev: false - /@esbuild/android-arm64@0.17.19: - resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true + /@babel/preset-typescript@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-validator-option': 7.23.5 + '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-typescript': 7.24.5(@babel/core@7.24.5) - /@esbuild/android-arm64@0.18.20: - resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true + /@babel/register@7.23.7(@babel/core@7.24.5): + resolution: {integrity: sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + clone-deep: 4.0.1 + find-cache-dir: 2.1.0 + make-dir: 2.1.0 + pirates: 4.0.6 + source-map-support: 0.5.21 + dev: false - /@esbuild/android-arm64@0.19.11: - resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true + /@babel/regjsgen@0.8.0: + resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} dev: false - optional: true - /@esbuild/android-arm64@0.19.12: - resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true + /@babel/runtime-corejs3@7.24.1: + resolution: {integrity: sha512-T9ko/35G+Bkl+win48GduaPlhSlOjjE5s1TeiEcD+QpxlLQnoEfb/nO/T+TQqkm+ipFwORn+rB8w14iJ/uD0bg==} + engines: {node: '>=6.9.0'} + dependencies: + core-js-pure: 3.37.0 + regenerator-runtime: 0.14.1 + dev: false - /@esbuild/android-arm64@0.20.2: - resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true + /@babel/runtime@7.24.5: + resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 - /@esbuild/android-arm@0.17.19: - resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true + /@babel/standalone@7.24.5: + resolution: {integrity: sha512-Sl8oN9bGfRlNUA2jzfzoHEZxFBDliBlwi5mPVCAWKSlBNkXXJOHpu7SDOqjF6mRoTa6GNX/1kAWG3Tr+YQ3N7A==} + engines: {node: '>=6.9.0'} - /@esbuild/android-arm@0.18.20: - resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true - - /@esbuild/android-arm@0.19.11: - resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@esbuild/android-arm@0.19.12: - resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.20.2: - resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true - - /@esbuild/android-x64@0.17.19: - resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true + /@babel/template@7.24.0: + resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.24.2 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 - /@esbuild/android-x64@0.18.20: - resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - optional: true + /@babel/traverse@7.24.5: + resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.24.2 + '@babel/generator': 7.24.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.24.5 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color - /@esbuild/android-x64@0.19.11: - resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: false - optional: true + /@babel/types@7.24.5: + resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.24.1 + '@babel/helper-validator-identifier': 7.24.5 + to-fast-properties: 2.0.0 - /@esbuild/android-x64@0.19.12: - resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] + /@biomejs/biome@1.6.3: + resolution: {integrity: sha512-Xnp/TIpIcTnRA4LwerJuoGYQJEqwXtn5AL0U0OPXll/QGbAKmcUAfizU880xTwZRD4f53iceqODLDaD3wxYlIw==} + engines: {node: '>=14.*'} + hasBin: true requiresBuild: true + optionalDependencies: + '@biomejs/cli-darwin-arm64': 1.6.3 + '@biomejs/cli-darwin-x64': 1.6.3 + '@biomejs/cli-linux-arm64': 1.6.3 + '@biomejs/cli-linux-arm64-musl': 1.6.3 + '@biomejs/cli-linux-x64': 1.6.3 + '@biomejs/cli-linux-x64-musl': 1.6.3 + '@biomejs/cli-win32-arm64': 1.6.3 + '@biomejs/cli-win32-x64': 1.6.3 dev: true - optional: true - - /@esbuild/android-x64@0.20.2: - resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - optional: true - /@esbuild/darwin-arm64@0.17.19: - resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} - engines: {node: '>=12'} + /@biomejs/cli-darwin-arm64@1.6.3: + resolution: {integrity: sha512-0E8PGu3/8HSkBJdtjno+niJE1ANS/12D7sPK65vw5lTBYmmaYwJdfclDp6XO0IAX7uVd3/YtXlsEua0SVrNt3Q==} + engines: {node: '>=14.*'} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true - /@esbuild/darwin-arm64@0.18.20: - resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@esbuild/darwin-arm64@0.19.11: - resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==} - engines: {node: '>=12'} - cpu: [arm64] + /@biomejs/cli-darwin-x64@1.6.3: + resolution: {integrity: sha512-UWu0We/aIRtWXgJKe6ygWt2xR0yXs64BwWqtZbfxBojRn3jgW8UdFAkV5yiUOX3TQlsV6BZH1EQaUAVsccUeeA==} + engines: {node: '>=14.*'} + cpu: [x64] os: [darwin] requiresBuild: true - dev: false + dev: true optional: true - /@esbuild/darwin-arm64@0.19.12: - resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} - engines: {node: '>=12'} + /@biomejs/cli-linux-arm64-musl@1.6.3: + resolution: {integrity: sha512-AntGCSfLN1nPcQj4VOk3X2JgnDw07DaPC8BuBmRcsRmn+7GPSWLllVN5awIKlRPZEbGJtSnLkTiDc5Bxw8OiuA==} + engines: {node: '>=14.*'} cpu: [arm64] - os: [darwin] + os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/darwin-arm64@0.20.2: - resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} - engines: {node: '>=12'} + /@biomejs/cli-linux-arm64@1.6.3: + resolution: {integrity: sha512-wFVkQw38kOssfnkbpSh6ums5TaElw3RAt5i/VZwHmgR2nQgE0fHXLO7HwIE9VBkOEdbiIFq+2PxvFIHuJF3z3Q==} + engines: {node: '>=14.*'} cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@esbuild/darwin-x64@0.17.19: - resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] + os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/darwin-x64@0.18.20: - resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@esbuild/darwin-x64@0.19.11: - resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@esbuild/darwin-x64@0.19.12: - resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} - engines: {node: '>=12'} + /@biomejs/cli-linux-x64-musl@1.6.3: + resolution: {integrity: sha512-GelAvGsUwbxfFpKLG+7+dvDmbrfkGqn08sL8CMQrGnhjE1krAqHWiXQsjfmi0UMFdMsk7hbc4oSAP+1+mrXcHQ==} + engines: {node: '>=14.*'} cpu: [x64] - os: [darwin] + os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/darwin-x64@0.20.2: - resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} - engines: {node: '>=12'} + /@biomejs/cli-linux-x64@1.6.3: + resolution: {integrity: sha512-vyn8TQaTZg617hjqFitwGmb1St5XXvq6I3vmxU/QFalM74BryMSvYCrYWb2Yw/TkykdEwZTMGYp+SWHRb04fTg==} + engines: {node: '>=14.*'} cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@esbuild/freebsd-arm64@0.17.19: - resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] + os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/freebsd-arm64@0.18.20: - resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - optional: true - - /@esbuild/freebsd-arm64@0.19.11: - resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: false - optional: true - - /@esbuild/freebsd-arm64@0.19.12: - resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} - engines: {node: '>=12'} + /@biomejs/cli-win32-arm64@1.6.3: + resolution: {integrity: sha512-Gx8N2Tixke6pAI1BniteCVZgUUmaFEDYosdWxoaCus15BZI/7RcBxhsRM0ZL/lC66StSQ8vHl8JBrrld1k570Q==} + engines: {node: '>=14.*'} cpu: [arm64] - os: [freebsd] + os: [win32] requiresBuild: true dev: true optional: true - /@esbuild/freebsd-arm64@0.20.2: - resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - optional: true - - /@esbuild/freebsd-x64@0.17.19: - resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} - engines: {node: '>=12'} + /@biomejs/cli-win32-x64@1.6.3: + resolution: {integrity: sha512-meungPJw64SqoR7LXY1wG7GC4+4wgpyThdFUMGXa6PCe0BLFOIOcZ9VMj9PstuczMPdgmt/BUMPsj25dK1VO8A==} + engines: {node: '>=14.*'} cpu: [x64] - os: [freebsd] + os: [win32] requiresBuild: true dev: true optional: true - /@esbuild/freebsd-x64@0.18.20: - resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true + /@bundled-es-modules/cookie@2.0.0: + resolution: {integrity: sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==} + dependencies: + cookie: 0.5.0 - /@esbuild/freebsd-x64@0.19.11: - resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==} + /@bundled-es-modules/statuses@1.0.1: + resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} + dependencies: + statuses: 2.0.1 + + /@changesets/apply-release-plan@7.0.0: + resolution: {integrity: sha512-vfi69JR416qC9hWmFGSxj7N6wA5J222XNBmezSVATPWDVPIF7gkd4d8CpbEbXmRWbVrkoli3oerGS6dcL/BGsQ==} + dependencies: + '@babel/runtime': 7.24.5 + '@changesets/config': 3.0.0 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.6.0 + dev: true + + /@changesets/assemble-release-plan@6.0.0: + resolution: {integrity: sha512-4QG7NuisAjisbW4hkLCmGW2lRYdPrKzro+fCtZaILX+3zdUELSvYjpL4GTv0E4aM9Mef3PuIQp89VmHJ4y2bfw==} + dependencies: + '@babel/runtime': 7.24.5 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.0.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.6.0 + dev: true + + /@changesets/changelog-git@0.2.0: + resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} + dependencies: + '@changesets/types': 6.0.0 + dev: true + + /@changesets/cli@2.27.1: + resolution: {integrity: sha512-iJ91xlvRnnrJnELTp4eJJEOPjgpF3NOh4qeQehM6Ugiz9gJPRZ2t+TsXun6E3AMN4hScZKjqVXl0TX+C7AB3ZQ==} + hasBin: true + dependencies: + '@babel/runtime': 7.24.5 + '@changesets/apply-release-plan': 7.0.0 + '@changesets/assemble-release-plan': 6.0.0 + '@changesets/changelog-git': 0.2.0 + '@changesets/config': 3.0.0 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.0.0 + '@changesets/get-release-plan': 4.0.0 + '@changesets/git': 3.0.0 + '@changesets/logger': 0.1.0 + '@changesets/pre': 2.0.0 + '@changesets/read': 0.6.0 + '@changesets/types': 6.0.0 + '@changesets/write': 0.3.0 + '@manypkg/get-packages': 1.1.3 + '@types/semver': 7.5.8 + ansi-colors: 4.1.3 + chalk: 2.4.2 + ci-info: 3.9.0 + enquirer: 2.4.1 + external-editor: 3.1.0 + fs-extra: 7.0.1 + human-id: 1.0.2 + meow: 6.1.1 + outdent: 0.5.0 + p-limit: 2.3.0 + preferred-pm: 3.1.3 + resolve-from: 5.0.0 + semver: 7.6.0 + spawndamnit: 2.0.0 + term-size: 2.2.1 + tty-table: 4.2.3 + dev: true + + /@changesets/config@3.0.0: + resolution: {integrity: sha512-o/rwLNnAo/+j9Yvw9mkBQOZySDYyOr/q+wptRLcAVGlU6djOeP9v1nlalbL9MFsobuBVQbZCTp+dIzdq+CLQUA==} + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.0.0 + '@changesets/logger': 0.1.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.5 + dev: true + + /@changesets/errors@0.2.0: + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + dependencies: + extendable-error: 0.1.7 + dev: true + + /@changesets/get-dependents-graph@2.0.0: + resolution: {integrity: sha512-cafUXponivK4vBgZ3yLu944mTvam06XEn2IZGjjKc0antpenkYANXiiE6GExV/yKdsCnE8dXVZ25yGqLYZmScA==} + dependencies: + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + chalk: 2.4.2 + fs-extra: 7.0.1 + semver: 7.6.0 + dev: true + + /@changesets/get-release-plan@4.0.0: + resolution: {integrity: sha512-9L9xCUeD/Tb6L/oKmpm8nyzsOzhdNBBbt/ZNcjynbHC07WW4E1eX8NMGC5g5SbM5z/V+MOrYsJ4lRW41GCbg3w==} + dependencies: + '@babel/runtime': 7.24.5 + '@changesets/assemble-release-plan': 6.0.0 + '@changesets/config': 3.0.0 + '@changesets/pre': 2.0.0 + '@changesets/read': 0.6.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + dev: true + + /@changesets/get-version-range-type@0.4.0: + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} + dev: true + + /@changesets/git@3.0.0: + resolution: {integrity: sha512-vvhnZDHe2eiBNRFHEgMiGd2CT+164dfYyrJDhwwxTVD/OW0FUD6G7+4DIx1dNwkwjHyzisxGAU96q0sVNBns0w==} + dependencies: + '@babel/runtime': 7.24.5 + '@changesets/errors': 0.2.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.5 + spawndamnit: 2.0.0 + dev: true + + /@changesets/logger@0.1.0: + resolution: {integrity: sha512-pBrJm4CQm9VqFVwWnSqKEfsS2ESnwqwH+xR7jETxIErZcfd1u2zBSqrHbRHR7xjhSgep9x2PSKFKY//FAshA3g==} + dependencies: + chalk: 2.4.2 + dev: true + + /@changesets/parse@0.4.0: + resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} + dependencies: + '@changesets/types': 6.0.0 + js-yaml: 3.14.1 + dev: true + + /@changesets/pre@2.0.0: + resolution: {integrity: sha512-HLTNYX/A4jZxc+Sq8D1AMBsv+1qD6rmmJtjsCJa/9MSRybdxh0mjbTvE6JYZQ/ZiQ0mMlDOlGPXTm9KLTU3jyw==} + dependencies: + '@babel/runtime': 7.24.5 + '@changesets/errors': 0.2.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + dev: true + + /@changesets/read@0.6.0: + resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==} + dependencies: + '@babel/runtime': 7.24.5 + '@changesets/git': 3.0.0 + '@changesets/logger': 0.1.0 + '@changesets/parse': 0.4.0 + '@changesets/types': 6.0.0 + chalk: 2.4.2 + fs-extra: 7.0.1 + p-filter: 2.1.0 + dev: true + + /@changesets/types@4.1.0: + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + dev: true + + /@changesets/types@6.0.0: + resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} + dev: true + + /@changesets/write@0.3.0: + resolution: {integrity: sha512-slGLb21fxZVUYbyea+94uFiD6ntQW0M2hIKNznFizDhZPDgn2c/fv1UzzlW43RVzh1BEDuIqW6hzlJ1OflNmcw==} + dependencies: + '@babel/runtime': 7.24.5 + '@changesets/types': 6.0.0 + fs-extra: 7.0.1 + human-id: 1.0.2 + prettier: 2.8.8 + dev: true + + /@chevrotain/cst-dts-gen@10.5.0: + resolution: {integrity: sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==} + dependencies: + '@chevrotain/gast': 10.5.0 + '@chevrotain/types': 10.5.0 + lodash: 4.17.21 + dev: false + + /@chevrotain/gast@10.5.0: + resolution: {integrity: sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==} + dependencies: + '@chevrotain/types': 10.5.0 + lodash: 4.17.21 + dev: false + + /@chevrotain/types@10.5.0: + resolution: {integrity: sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==} + dev: false + + /@chevrotain/utils@10.5.0: + resolution: {integrity: sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==} + dev: false + + /@chronark/zod-bird@0.3.7: + resolution: {integrity: sha512-6IbCXqaaWtjxsYMbPHOUBZYCRRct4JufZ55LW9zHgyQNM0fP1KO7SQG2sIGD2ZHjd9P9OIESNmeYaxBxXTqWgA==} + dependencies: + zod: 3.23.5 + dev: false + + /@clack/core@0.3.4: + resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==} + dependencies: + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: true + + /@clack/prompts@0.7.0: + resolution: {integrity: sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==} + dependencies: + '@clack/core': 0.3.4 + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: true + bundledDependencies: + - is-unicode-supported + + /@clerk/backend@0.38.4(react@18.2.0): + resolution: {integrity: sha512-Cp/vcuFqo3VsoBXWEWONhlzK5gXB3RDBImc5XgA4hvTSDAq7vvn+WYh/ya1eeVZ8g1LMaRx2Wl2OFml3zjGWJA==} + engines: {node: '>=14'} + dependencies: + '@clerk/shared': 1.4.0(react@18.2.0) + '@clerk/types': 3.63.0 + '@peculiar/webcrypto': 1.4.1 + '@types/node': 16.18.6 + cookie: 0.5.0 + deepmerge: 4.2.2 + node-fetch-native: 1.0.1 + snakecase-keys: 5.4.4 + tslib: 2.4.1 + transitivePeerDependencies: + - react + dev: false + + /@clerk/backend@0.38.4(react@18.3.1): + resolution: {integrity: sha512-Cp/vcuFqo3VsoBXWEWONhlzK5gXB3RDBImc5XgA4hvTSDAq7vvn+WYh/ya1eeVZ8g1LMaRx2Wl2OFml3zjGWJA==} + engines: {node: '>=14'} + dependencies: + '@clerk/shared': 1.4.0(react@18.3.1) + '@clerk/types': 3.63.0 + '@peculiar/webcrypto': 1.4.1 + '@types/node': 16.18.6 + cookie: 0.5.0 + deepmerge: 4.2.2 + node-fetch-native: 1.0.1 + snakecase-keys: 5.4.4 + tslib: 2.4.1 + transitivePeerDependencies: + - react + dev: false + + /@clerk/clerk-react@4.30.8(react@18.2.0): + resolution: {integrity: sha512-MehccfniWs2v7WSx4qGjJYxL+jtnsK6sETrzBuWctb7rLbvv4jDqjalhXbCm8YTV4qG19jHZl/WNsHOXSzBc7Q==} + engines: {node: '>=14'} + peerDependencies: + react: '>=16' + dependencies: + '@clerk/shared': 1.4.0(react@18.2.0) + '@clerk/types': 3.63.0 + react: 18.2.0 + tslib: 2.4.1 + dev: false + + /@clerk/clerk-react@4.30.8(react@18.3.1): + resolution: {integrity: sha512-MehccfniWs2v7WSx4qGjJYxL+jtnsK6sETrzBuWctb7rLbvv4jDqjalhXbCm8YTV4qG19jHZl/WNsHOXSzBc7Q==} + engines: {node: '>=14'} + peerDependencies: + react: '>=16' + dependencies: + '@clerk/shared': 1.4.0(react@18.3.1) + '@clerk/types': 3.63.0 + react: 18.3.1 + tslib: 2.4.1 + dev: false + + /@clerk/clerk-sdk-node@4.13.12(react@18.2.0): + resolution: {integrity: sha512-6OluVdh13OwOVk5m+Zgfwph1B/1Zz3AzBepuZubdPmI2r0c1YVOuo/09WJiBRZdglkoIcS0868ZRBsZMrPJDLQ==} + engines: {node: '>=14'} + dependencies: + '@clerk/backend': 0.38.4(react@18.2.0) + '@clerk/shared': 1.4.0(react@18.2.0) + '@clerk/types': 3.63.0 + '@types/cookies': 0.7.7 + '@types/express': 4.17.14 + '@types/node-fetch': 2.6.2 + camelcase-keys: 6.2.2 + snakecase-keys: 3.2.1 + tslib: 2.4.1 + transitivePeerDependencies: + - react + dev: false + + /@clerk/clerk-sdk-node@4.13.12(react@18.3.1): + resolution: {integrity: sha512-6OluVdh13OwOVk5m+Zgfwph1B/1Zz3AzBepuZubdPmI2r0c1YVOuo/09WJiBRZdglkoIcS0868ZRBsZMrPJDLQ==} + engines: {node: '>=14'} + dependencies: + '@clerk/backend': 0.38.4(react@18.3.1) + '@clerk/shared': 1.4.0(react@18.3.1) + '@clerk/types': 3.63.0 + '@types/cookies': 0.7.7 + '@types/express': 4.17.14 + '@types/node-fetch': 2.6.2 + camelcase-keys: 6.2.2 + snakecase-keys: 3.2.1 + tslib: 2.4.1 + transitivePeerDependencies: + - react + dev: false + + /@clerk/nextjs@4.29.10(next@14.1.3)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-nu8tIzZxxwqFYupBp66BSYSp+qAEUvGUFJ1eAqvgQjOUWh+rElQTfOMI0sm3hOX85sZv04WKA9hiAT93qLILsg==} + engines: {node: '>=14'} + peerDependencies: + next: '>=10' + react: ^17.0.2 || ^18.0.0-0 + react-dom: ^17.0.2 || ^18.0.0-0 + dependencies: + '@clerk/backend': 0.38.4(react@18.2.0) + '@clerk/clerk-react': 4.30.8(react@18.2.0) + '@clerk/clerk-sdk-node': 4.13.12(react@18.2.0) + '@clerk/shared': 1.4.0(react@18.2.0) + '@clerk/types': 3.63.0 + next: 14.1.3(@babel/core@7.24.5)(react-dom@18.2.0)(react@18.2.0) + path-to-regexp: 6.2.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tslib: 2.4.1 + dev: false + + /@clerk/nextjs@4.29.10(next@14.2.2)(react-dom@18.2.0)(react@18.3.1): + resolution: {integrity: sha512-nu8tIzZxxwqFYupBp66BSYSp+qAEUvGUFJ1eAqvgQjOUWh+rElQTfOMI0sm3hOX85sZv04WKA9hiAT93qLILsg==} + engines: {node: '>=14'} + peerDependencies: + next: '>=10' + react: ^17.0.2 || ^18.0.0-0 + react-dom: ^17.0.2 || ^18.0.0-0 + dependencies: + '@clerk/backend': 0.38.4(react@18.3.1) + '@clerk/clerk-react': 4.30.8(react@18.3.1) + '@clerk/clerk-sdk-node': 4.13.12(react@18.3.1) + '@clerk/shared': 1.4.0(react@18.3.1) + '@clerk/types': 3.63.0 + next: 14.2.2(@babel/core@7.24.5)(@opentelemetry/api@1.4.1)(react-dom@18.2.0)(react@18.3.1) + path-to-regexp: 6.2.1 + react: 18.3.1 + react-dom: 18.2.0(react@18.3.1) + tslib: 2.4.1 + dev: false + + /@clerk/shared@1.4.0(react@18.2.0): + resolution: {integrity: sha512-LANWfdw3n7lCN90oY+myuCN74CfGgBQE/T11ry/bTSNVqUxXiYaUlfu5Fkp0GsR4icYiA6NRyROFmYdYZfBMAA==} + peerDependencies: + react: '>=16' + peerDependenciesMeta: + react: + optional: true + dependencies: + glob-to-regexp: 0.4.1 + js-cookie: 3.0.1 + react: 18.2.0 + swr: 2.2.0(react@18.2.0) + dev: false + + /@clerk/shared@1.4.0(react@18.3.1): + resolution: {integrity: sha512-LANWfdw3n7lCN90oY+myuCN74CfGgBQE/T11ry/bTSNVqUxXiYaUlfu5Fkp0GsR4icYiA6NRyROFmYdYZfBMAA==} + peerDependencies: + react: '>=16' + peerDependenciesMeta: + react: + optional: true + dependencies: + glob-to-regexp: 0.4.1 + js-cookie: 3.0.1 + react: 18.3.1 + swr: 2.2.0(react@18.3.1) + dev: false + + /@clerk/types@3.63.0: + resolution: {integrity: sha512-+32fWK+lUG2u0hVaoQ3aZ+j2T/LhF3yNNylBrkD1Kca/goLb+NB/nmw6Svs0Q810FK/uYgqWlXvABPhgILeQFA==} + engines: {node: '>=14'} + dependencies: + csstype: 3.1.1 + dev: false + + /@clerk/types@3.63.1: + resolution: {integrity: sha512-PeZrRzWApJl1BYsT/wQPtEzhDmwfqeMKWuSRcHe3Kh0Itc5Gp7w9HrrKkyMnRuzebVj4z5gX4rwJOmTD/P1DhQ==} + engines: {node: '>=14'} + dependencies: + csstype: 3.1.1 + dev: true + + /@cloudflare/kv-asset-handler@0.3.1: + resolution: {integrity: sha512-lKN2XCfKCmpKb86a1tl4GIwsJYDy9TGuwjhDELLmpKygQhw8X2xR4dusgpC5Tg7q1pB96Eb0rBo81kxSILQMwA==} + dependencies: + mime: 3.0.0 + dev: true + + /@cloudflare/kv-asset-handler@0.3.2: + resolution: {integrity: sha512-EeEjMobfuJrwoctj7FA1y1KEbM0+Q1xSjobIEyie9k4haVEBB7vkDvsasw1pM3rO39mL2akxIAzLMUAtrMHZhA==} + engines: {node: '>=16.13'} + dependencies: + mime: 3.0.0 + dev: true + + /@cloudflare/vitest-pool-workers@0.2.2(@cloudflare/workers-types@4.20240419.0)(@vitest/runner@1.3.0)(@vitest/snapshot@1.3.0)(vitest@1.3.0): + resolution: {integrity: sha512-LQfSLMCreWX9idVNB1qBRhZHi347nAN90PU0mxMyYZ9ElGnvJjKj/49aefW6X9+ixwLG3pH5eV1i06T8017fZg==} + peerDependencies: + '@vitest/runner': 1.3.0 + '@vitest/snapshot': 1.3.0 + vitest: 1.3.0 + dependencies: + '@vitest/runner': 1.3.0 + '@vitest/snapshot': 1.3.0 + birpc: 0.2.14 + cjs-module-lexer: 1.3.1 + devalue: 4.3.3 + esbuild: 0.17.19 + miniflare: 3.20240405.2 + vitest: 1.3.0(@types/node@20.12.7)(@vitest/ui@1.3.0) + wrangler: 3.51.2(@cloudflare/workers-types@4.20240419.0) + zod: 3.23.5 + transitivePeerDependencies: + - '@cloudflare/workers-types' + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /@cloudflare/workerd-darwin-64@1.20240405.0: + resolution: {integrity: sha512-ut8kwpHmlz9dNSjoov6v1b6jS50J46Mj9QcMA0t1Hne36InaQk/qqPSd12fN5p2GesZ9OOBJvBdDsTblVdyJ1w==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-darwin-arm64@1.20240405.0: + resolution: {integrity: sha512-x3A3Ym+J2DH1uYnw0aedeKOTnUebEo312+Aladv7bFri97pjRJcqVbYhMtOHLkHjwYn7bpKSY2eL5iM+0XT29A==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-linux-64@1.20240405.0: + resolution: {integrity: sha512-3tYpfjtxEQ0R30Pna7OF3Bz0CTx30hc0QNtH61KnkvXtaeYMkWutSKQKXIuVlPa/7v1MHp+8ViBXMflmS7HquA==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-linux-arm64@1.20240405.0: + resolution: {integrity: sha512-NpKZlvmdgcX/m4tP5zM91AfJpZrue2/GRA+Sl3szxAivu2uE5jDVf5SS9dzqzCVfPrdhylqH7yeL4U/cafFNOg==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-windows-64@1.20240405.0: + resolution: {integrity: sha512-REBeJMxvUCjwuEVzSSIBtzAyM69QjToab8qBst0S9vdih+9DObym4dw8CevdBQhDbFrHiyL9E6pAZpLPNHVgCw==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workers-types@4.20240419.0: + resolution: {integrity: sha512-UM16sr4HEe0mDj6C5OFcodzdj/CnEp0bfncAq3g7OpDsoZ1sBrfsMrb7Yc4f8J81EemvmQZyE6sSanpURtVkcQ==} + + /@commitlint/config-validator@19.0.3: + resolution: {integrity: sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 19.0.3 + ajv: 8.13.0 + dev: true + optional: true + + /@commitlint/execute-rule@19.0.0: + resolution: {integrity: sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==} + engines: {node: '>=v18'} + dev: true + optional: true + + /@commitlint/load@19.2.0(@types/node@20.12.7)(typescript@5.3.3): + resolution: {integrity: sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ==} + engines: {node: '>=v18'} + requiresBuild: true + dependencies: + '@commitlint/config-validator': 19.0.3 + '@commitlint/execute-rule': 19.0.0 + '@commitlint/resolve-extends': 19.1.0 + '@commitlint/types': 19.0.3 + chalk: 5.3.0 + cosmiconfig: 9.0.0(typescript@5.3.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.12.7)(cosmiconfig@9.0.0)(typescript@5.3.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + dev: true + optional: true + + /@commitlint/resolve-extends@19.1.0: + resolution: {integrity: sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/config-validator': 19.0.3 + '@commitlint/types': 19.0.3 + global-directory: 4.0.1 + import-meta-resolve: 4.1.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + dev: true + optional: true + + /@commitlint/types@19.0.3: + resolution: {integrity: sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==} + engines: {node: '>=v18'} + dependencies: + '@types/conventional-commits-parser': 5.0.0 + chalk: 5.3.0 + dev: true + optional: true + + /@contentlayer/cli@0.3.4(esbuild@0.20.2): + resolution: {integrity: sha512-vNDwgLuhYNu+m70NZ3XK9kexKNguuxPXg7Yvzj3B34cEilQjjzSrcTY/i+AIQm9V7uT5GGshx9ukzPf+SmoszQ==} + dependencies: + '@contentlayer/core': 0.3.4(esbuild@0.20.2) + '@contentlayer/utils': 0.3.4 + clipanion: 3.2.1(typanion@3.14.0) + typanion: 3.14.0 + transitivePeerDependencies: + - '@effect-ts/otel-node' + - esbuild + - markdown-wasm + - supports-color + dev: false + + /@contentlayer/client@0.3.4(esbuild@0.20.2): + resolution: {integrity: sha512-QSlLyc3y4PtdC5lFw0L4wTZUH8BQnv2nk37hNCsPAqGf+dRO7TLAzdc+2/mVIRgK+vSH+pSOzjLsQpFxxXRTZA==} + dependencies: + '@contentlayer/core': 0.3.4(esbuild@0.20.2) + transitivePeerDependencies: + - '@effect-ts/otel-node' + - esbuild + - markdown-wasm + - supports-color + dev: false + + /@contentlayer/core@0.3.4(esbuild@0.20.2): + resolution: {integrity: sha512-o68oBLwfYZ+2vtgfk1lgHxOl3LoxvRNiUfeQ8IWFWy/L4wnIkKIqLZX01zlRE5IzYM+ZMMN5V0cKQlO7DsyR9g==} + peerDependencies: + esbuild: 0.17.x || 0.18.x + markdown-wasm: 1.x + peerDependenciesMeta: + esbuild: + optional: true + markdown-wasm: + optional: true + dependencies: + '@contentlayer/utils': 0.3.4 + camel-case: 4.1.2 + comment-json: 4.2.3 + esbuild: 0.20.2 + gray-matter: 4.0.3 + mdx-bundler: 9.2.1(esbuild@0.20.2) + rehype-stringify: 9.0.4 + remark-frontmatter: 4.0.1 + remark-parse: 10.0.2 + remark-rehype: 10.1.0 + source-map-support: 0.5.21 + type-fest: 3.13.1 + unified: 10.1.2 + transitivePeerDependencies: + - '@effect-ts/otel-node' + - supports-color + dev: false + + /@contentlayer/source-files@0.3.4(esbuild@0.20.2): + resolution: {integrity: sha512-4njyn0OFPu7WY4tAjMxiJgWOKeiHuBOGdQ36EYE03iij/pPPRbiWbL+cmLccYXUFEW58mDwpqROZZm6pnxjRDQ==} + dependencies: + '@contentlayer/core': 0.3.4(esbuild@0.20.2) + '@contentlayer/utils': 0.3.4 + chokidar: 3.6.0 + fast-glob: 3.3.2 + gray-matter: 4.0.3 + imagescript: 1.3.0 + micromatch: 4.0.5 + ts-pattern: 4.3.0 + unified: 10.1.2 + yaml: 2.4.2 + zod: 3.23.5 + transitivePeerDependencies: + - '@effect-ts/otel-node' + - esbuild + - markdown-wasm + - supports-color + dev: false + + /@contentlayer/source-remote-files@0.3.4(esbuild@0.20.2): + resolution: {integrity: sha512-cyiv4sNUySZvR0uAKlM+kSAELzNd2h2QT1R2e41dRKbwOUVxeLfmGiLugr0aVac6Q3xYcD99dbHyR1xWPV+w9w==} + dependencies: + '@contentlayer/core': 0.3.4(esbuild@0.20.2) + '@contentlayer/source-files': 0.3.4(esbuild@0.20.2) + '@contentlayer/utils': 0.3.4 + transitivePeerDependencies: + - '@effect-ts/otel-node' + - esbuild + - markdown-wasm + - supports-color + dev: false + + /@contentlayer/utils@0.3.4: + resolution: {integrity: sha512-ZWWOhbUWYQ2QHoLIlcUnEo7X4ZbwcyFPuzVQWWMkK43BxCveyQtZwBIzfyx54sqVzi0GUmKP8bHzsLQT0QxaLQ==} + peerDependencies: + '@effect-ts/otel-node': '*' + peerDependenciesMeta: + '@effect-ts/core': + optional: true + '@effect-ts/otel': + optional: true + '@effect-ts/otel-node': + optional: true + dependencies: + '@effect-ts/core': 0.60.5 + '@effect-ts/otel': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0) + '@effect-ts/otel-exporter-trace-otlp-grpc': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/exporter-trace-otlp-grpc@0.39.1)(@opentelemetry/sdk-trace-base@1.13.0) + '@effect-ts/otel-sdk-trace-node': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0)(@opentelemetry/sdk-trace-node@1.13.0) + '@js-temporal/polyfill': 0.4.4 + '@opentelemetry/api': 1.4.1 + '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.4.1) + '@opentelemetry/exporter-trace-otlp-grpc': 0.39.1(@opentelemetry/api@1.4.1) + '@opentelemetry/resources': 1.13.0(@opentelemetry/api@1.4.1) + '@opentelemetry/sdk-trace-base': 1.13.0(@opentelemetry/api@1.4.1) + '@opentelemetry/sdk-trace-node': 1.13.0(@opentelemetry/api@1.4.1) + '@opentelemetry/semantic-conventions': 1.13.0 + chokidar: 3.6.0 + hash-wasm: 4.11.0 + inflection: 2.0.1 + memfs: 3.5.3 + oo-ascii-tree: 1.97.0 + ts-pattern: 4.3.0 + type-fest: 3.13.1 + dev: false + + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + /@dagrejs/graphlib@2.1.4: + resolution: {integrity: sha512-QCg9sL4uhjn468FDEsb/S9hS2xUZSrv/+dApb1Ze5VKO96pTXKNJZ6MGhIpgWkc1TVhbVGH9/7rq/Mf8/jWicw==} + dependencies: + lodash: 4.17.21 + dev: false + + /@effect-ts/core@0.60.5: + resolution: {integrity: sha512-qi1WrtJA90XLMnj2hnUszW9Sx4dXP03ZJtCc5DiUBIOhF4Vw7plfb65/bdBySPoC9s7zy995TdUX1XBSxUkl5w==} + dependencies: + '@effect-ts/system': 0.57.5 + dev: false + + /@effect-ts/otel-exporter-trace-otlp-grpc@0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/exporter-trace-otlp-grpc@0.39.1)(@opentelemetry/sdk-trace-base@1.13.0): + resolution: {integrity: sha512-47gAg0O2pW5Jlo86jfzjdkwL5a7Bzb+Kj5WTmdu4CxYRfWn9ytKjuuYIfsNDW8neuhdKzn+P5wCddgEh0glYyQ==} + peerDependencies: + '@effect-ts/core': ^0.60.2 + '@opentelemetry/api': ^1.4.0 + '@opentelemetry/core': ^1.13.0 + '@opentelemetry/exporter-trace-otlp-grpc': ^0.39.0 + '@opentelemetry/sdk-trace-base': ^1.13.0 + dependencies: + '@effect-ts/core': 0.60.5 + '@effect-ts/otel': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0) + '@opentelemetry/api': 1.4.1 + '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.4.1) + '@opentelemetry/exporter-trace-otlp-grpc': 0.39.1(@opentelemetry/api@1.4.1) + '@opentelemetry/sdk-trace-base': 1.13.0(@opentelemetry/api@1.4.1) + dev: false + + /@effect-ts/otel-sdk-trace-node@0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0)(@opentelemetry/sdk-trace-node@1.13.0): + resolution: {integrity: sha512-a2sF0ylmn8xOJs8fNeT/spJ1gUcsksAJCALxo9WOfuTCMtTwMVtVhCKEPEeQoL7wFqU+JgPkVdP91+FJ/Rkeow==} + peerDependencies: + '@effect-ts/core': ^0.60.2 + '@opentelemetry/api': ^1.4.0 + '@opentelemetry/core': ^1.13.0 + '@opentelemetry/sdk-trace-base': ^1.13.0 + '@opentelemetry/sdk-trace-node': ^1.13.0 + dependencies: + '@effect-ts/core': 0.60.5 + '@effect-ts/otel': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0) + '@opentelemetry/api': 1.4.1 + '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.4.1) + '@opentelemetry/sdk-trace-base': 1.13.0(@opentelemetry/api@1.4.1) + '@opentelemetry/sdk-trace-node': 1.13.0(@opentelemetry/api@1.4.1) + dev: false + + /@effect-ts/otel@0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.4.1)(@opentelemetry/core@1.13.0)(@opentelemetry/sdk-trace-base@1.13.0): + resolution: {integrity: sha512-AmZJHl7t0+Peh7Yb2+hqn6r9+rd9/UfeA4AMV9h0YGTdOyouyFfD3wzWlxnAUzAQ4Lrod4kC7Noruret4EpqpA==} + peerDependencies: + '@effect-ts/core': ^0.60.2 + '@opentelemetry/api': ^1.4.0 + '@opentelemetry/core': ^1.13.0 + '@opentelemetry/sdk-trace-base': ^1.13.0 + dependencies: + '@effect-ts/core': 0.60.5 + '@opentelemetry/api': 1.4.1 + '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.4.1) + '@opentelemetry/sdk-trace-base': 1.13.0(@opentelemetry/api@1.4.1) + dev: false + + /@effect-ts/system@0.57.5: + resolution: {integrity: sha512-/crHGujo0xnuHIYNc1VgP0HGJGFSoSqq88JFXe6FmFyXPpWt8Xu39LyLg7rchsxfXFeEdA9CrIZvLV5eswXV5g==} + dev: false + + /@emnapi/runtime@1.1.1: + resolution: {integrity: sha512-3bfqkzuR1KLx57nZfjr2NLnFOobvyS0aTszaEGCGqmYMVDRaGvgIZbjGSV/MHSSmLgQ/b9JFHQ5xm5WRZYd+XQ==} + requiresBuild: true + dependencies: + tslib: 2.6.2 + dev: true + optional: true + + /@emotion/is-prop-valid@0.8.8: + resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} + requiresBuild: true + dependencies: + '@emotion/memoize': 0.7.4 + dev: false + optional: true + + /@emotion/memoize@0.7.4: + resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + dev: false + optional: true + + /@envelop/core@4.0.3: + resolution: {integrity: sha512-O0Vz8E0TObT6ijAob8jYFVJavcGywKThM3UAsxUIBBVPYZTMiqI9lo2gmAnbMUnrDcAYkUTZEW9FDYPRdF5l6g==} + engines: {node: '>=16.0.0'} + requiresBuild: true + dependencies: + '@envelop/types': 4.0.1 + tslib: 2.6.2 + dev: false + optional: true + + /@envelop/core@5.0.0: + resolution: {integrity: sha512-aJdnH/ptv+cvwfvciCBe7TSvccBwo9g0S5f6u35TBVzRVqIGkK03lFlIL+x1cnfZgN9EfR2b1PH2galrT1CdCQ==} + engines: {node: '>=18.0.0'} + dependencies: + '@envelop/types': 5.0.0 + tslib: 2.6.2 + dev: false + + /@envelop/depth-limit@4.0.0(@envelop/core@5.0.0)(graphql@16.8.1): + resolution: {integrity: sha512-5lr6x3sx4+CqtrLjnK0UxWrtq0EkAyNHCR25du2hrlvszcq4IA/GjyQEpAy/3J6JYKgRJ4cZ+w5V6ppo2q6LLA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@envelop/core': ^5.0.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@envelop/core': 5.0.0 + graphql: 16.8.1 + graphql-depth-limit: 1.1.0(graphql@16.8.1) + tslib: 2.6.2 + dev: false + + /@envelop/disable-introspection@6.0.0(@envelop/core@5.0.0)(graphql@16.8.1): + resolution: {integrity: sha512-+DxCvKdzsHat/aWr6dqDsebbGk6ZGiM7VZlnpwKS8g4+PDHg7AfMBnDP8CtUODgifU+kgZME4TFzU288MNpNDg==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@envelop/core': ^5.0.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@envelop/core': 5.0.0 + graphql: 16.8.1 + tslib: 2.6.2 + dev: false + + /@envelop/filter-operation-type@6.0.0(@envelop/core@5.0.0)(graphql@16.8.1): + resolution: {integrity: sha512-eL4FWCNkQ/XUJX2pyHd3xfu9erqj08fVUWDpid8giuYHu5fx+CrVLUjwekkFOAYIIXdxYLdePrfLCrouX2XeWQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@envelop/core': ^5.0.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@envelop/core': 5.0.0 + graphql: 16.8.1 + tslib: 2.6.2 + dev: false + + /@envelop/on-resolve@4.1.0(@envelop/core@5.0.0)(graphql@16.8.1): + resolution: {integrity: sha512-2AXxf8jbBIepBUiY0KQtyCO6gnT7LKBEYdaARZBJ7ujy1+iQHQPORKvAwl51kIdD6v5x38eldZnm7A19jFimOg==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@envelop/core': ^5.0.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@envelop/core': 5.0.0 + graphql: 16.8.1 + dev: false + + /@envelop/types@4.0.1: + resolution: {integrity: sha512-ULo27/doEsP7uUhm2iTnElx13qTO6I5FKvmLoX41cpfuw8x6e0NUFknoqhEsLzAbgz8xVS5mjwcxGCXh4lDYzg==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + optional: true + + /@envelop/types@5.0.0: + resolution: {integrity: sha512-IPjmgSc4KpQRlO4qbEDnBEixvtb06WDmjKfi/7fkZaryh5HuOmTtixe1EupQI5XfXO8joc3d27uUZ0QdC++euA==} + engines: {node: '>=18.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + + /@ericcornelissen/bash-parser@0.5.2: + resolution: {integrity: sha512-4pIMTa1nEFfMXitv7oaNEWOdM+zpOZavesa5GaiWTgda6Zk32CFGxjUp/iIaN0PwgUW1yTq/fztSjbpE8SLGZQ==} + engines: {node: '>=4'} + dependencies: + array-last: 1.3.0 + babylon: 6.18.0 + compose-function: 3.0.3 + deep-freeze: 0.0.1 + filter-iterator: 0.0.1 + filter-obj: 1.1.0 + has-own-property: 0.1.0 + identity-function: 1.0.0 + is-iterable: 1.1.1 + iterable-lookahead: 1.0.0 + lodash.curry: 4.1.1 + magic-string: 0.16.0 + map-obj: 2.0.0 + object-pairs: 0.1.0 + object-values: 1.0.0 + reverse-arguments: 1.0.0 + shell-quote-word: 1.0.1 + to-pascal-case: 1.0.0 + unescape-js: 1.1.4 + dev: true + + /@esbuild-kit/core-utils@3.3.2: + resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} + dependencies: + esbuild: 0.18.20 + source-map-support: 0.5.21 + dev: true + + /@esbuild-kit/esm-loader@2.6.5: + resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} + dependencies: + '@esbuild-kit/core-utils': 3.3.2 + get-tsconfig: 4.7.3 + dev: true + + /@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19): + resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==} + peerDependencies: + esbuild: '*' + dependencies: + esbuild: 0.17.19 + dev: true + + /@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19): + resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==} + peerDependencies: + esbuild: '*' + dependencies: + esbuild: 0.17.19 + escape-string-regexp: 4.0.0 + rollup-plugin-node-polyfills: 0.2.1 + dev: true + + /@esbuild-plugins/node-resolve@0.1.4(esbuild@0.20.2): + resolution: {integrity: sha512-haFQ0qhxEpqtWWY0kx1Y5oE3sMyO1PcoSiWEPrAw6tm/ZOOLXjSs6Q+v1v9eyuVF0nNt50YEvrcrvENmyoMv5g==} + peerDependencies: + esbuild: '*' + dependencies: + '@types/resolve': 1.20.6 + debug: 4.3.4 + esbuild: 0.20.2 + escape-string-regexp: 4.0.0 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: false + + /@esbuild/aix-ppc64@0.19.11: + resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: false + optional: true + + /@esbuild/aix-ppc64@0.19.12: + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + optional: true + + /@esbuild/aix-ppc64@0.20.2: + resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + optional: true + + /@esbuild/android-arm64@0.17.19: + resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.18.20: + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-arm64@0.19.11: + resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm64@0.19.12: + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-arm64@0.20.2: + resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-arm@0.17.19: + resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.18.20: + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-arm@0.19.11: + resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm@0.19.12: + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-arm@0.20.2: + resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-x64@0.17.19: + resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.18.20: + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-x64@0.19.11: + resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-x64@0.19.12: + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-x64@0.20.2: + resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/darwin-arm64@0.17.19: + resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.18.20: + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/darwin-arm64@0.19.11: + resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-arm64@0.19.12: + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/darwin-arm64@0.20.2: + resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/darwin-x64@0.17.19: + resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.18.20: + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/darwin-x64@0.19.11: + resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-x64@0.19.12: + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/darwin-x64@0.20.2: + resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/freebsd-arm64@0.17.19: + resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.18.20: + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/freebsd-arm64@0.19.11: + resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-arm64@0.19.12: + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/freebsd-arm64@0.20.2: + resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/freebsd-x64@0.17.19: + resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.18.20: + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/freebsd-x64@0.19.11: + resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-x64@0.19.12: + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/freebsd-x64@0.20.2: + resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/linux-arm64@0.17.19: + resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.18.20: + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-arm64@0.19.11: + resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm64@0.19.12: + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-arm64@0.20.2: + resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-arm@0.17.19: + resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.18.20: + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-arm@0.19.11: + resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm@0.19.12: + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-arm@0.20.2: + resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ia32@0.17.19: + resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.18.20: + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ia32@0.19.11: + resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ia32@0.19.12: + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ia32@0.20.2: + resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-loong64@0.17.19: + resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.18.20: + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-loong64@0.19.11: + resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-loong64@0.19.12: + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-loong64@0.20.2: + resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-mips64el@0.17.19: + resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.18.20: + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-mips64el@0.19.11: + resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-mips64el@0.19.12: + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-mips64el@0.20.2: + resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ppc64@0.17.19: + resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.18.20: + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] + cpu: [ppc64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ppc64@0.19.11: + resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] requiresBuild: true dev: false optional: true - /@esbuild/freebsd-x64@0.19.12: - resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + /@esbuild/linux-ppc64@0.19.12: + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] + cpu: [ppc64] + os: [linux] requiresBuild: true - dev: true optional: true - /@esbuild/freebsd-x64@0.20.2: - resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + /@esbuild/linux-ppc64@0.20.2: + resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] + cpu: [ppc64] + os: [linux] requiresBuild: true optional: true - /@esbuild/linux-arm64@0.17.19: - resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} + /@esbuild/linux-riscv64@0.17.19: + resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} engines: {node: '>=12'} - cpu: [arm64] + cpu: [riscv64] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-arm64@0.18.20: - resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + /@esbuild/linux-riscv64@0.18.20: + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} engines: {node: '>=12'} - cpu: [arm64] + cpu: [riscv64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-arm64@0.19.11: - resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==} + /@esbuild/linux-riscv64@0.19.11: + resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==} engines: {node: '>=12'} - cpu: [arm64] + cpu: [riscv64] os: [linux] requiresBuild: true dev: false optional: true - /@esbuild/linux-arm64@0.19.12: - resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + /@esbuild/linux-riscv64@0.19.12: + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} engines: {node: '>=12'} - cpu: [arm64] + cpu: [riscv64] os: [linux] requiresBuild: true - dev: true optional: true - /@esbuild/linux-arm64@0.20.2: - resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + /@esbuild/linux-riscv64@0.20.2: + resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} engines: {node: '>=12'} - cpu: [arm64] + cpu: [riscv64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-arm@0.17.19: - resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} + /@esbuild/linux-s390x@0.17.19: + resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} engines: {node: '>=12'} - cpu: [arm] + cpu: [s390x] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-arm@0.18.20: - resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + /@esbuild/linux-s390x@0.18.20: + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} engines: {node: '>=12'} - cpu: [arm] + cpu: [s390x] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-arm@0.19.11: - resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==} + /@esbuild/linux-s390x@0.19.11: + resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==} engines: {node: '>=12'} - cpu: [arm] + cpu: [s390x] os: [linux] requiresBuild: true dev: false optional: true - /@esbuild/linux-arm@0.19.12: - resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + /@esbuild/linux-s390x@0.19.12: + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} engines: {node: '>=12'} - cpu: [arm] + cpu: [s390x] os: [linux] requiresBuild: true - dev: true optional: true - /@esbuild/linux-arm@0.20.2: - resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + /@esbuild/linux-s390x@0.20.2: + resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} engines: {node: '>=12'} - cpu: [arm] + cpu: [s390x] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-ia32@0.17.19: - resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} + /@esbuild/linux-x64@0.17.19: + resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} engines: {node: '>=12'} - cpu: [ia32] + cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-ia32@0.18.20: - resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + /@esbuild/linux-x64@0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} engines: {node: '>=12'} - cpu: [ia32] + cpu: [x64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-ia32@0.19.11: - resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==} + /@esbuild/linux-x64@0.19.11: + resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==} engines: {node: '>=12'} - cpu: [ia32] + cpu: [x64] os: [linux] requiresBuild: true dev: false optional: true - /@esbuild/linux-ia32@0.19.12: - resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + /@esbuild/linux-x64@0.19.12: + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} engines: {node: '>=12'} - cpu: [ia32] + cpu: [x64] os: [linux] requiresBuild: true - dev: true optional: true - /@esbuild/linux-ia32@0.20.2: - resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + /@esbuild/linux-x64@0.20.2: + resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} engines: {node: '>=12'} - cpu: [ia32] + cpu: [x64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-loong64@0.17.19: - resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} + /@esbuild/netbsd-x64@0.17.19: + resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.18.20: + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + optional: true + + /@esbuild/netbsd-x64@0.19.11: + resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/netbsd-x64@0.19.12: + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + optional: true + + /@esbuild/netbsd-x64@0.20.2: + resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + optional: true + + /@esbuild/openbsd-x64@0.17.19: + resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.18.20: + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + optional: true + + /@esbuild/openbsd-x64@0.19.11: + resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/openbsd-x64@0.19.12: + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + optional: true + + /@esbuild/openbsd-x64@0.20.2: + resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + optional: true + + /@esbuild/sunos-x64@0.17.19: + resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.18.20: + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + optional: true + + /@esbuild/sunos-x64@0.19.11: + resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: false + optional: true + + /@esbuild/sunos-x64@0.19.12: + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + optional: true + + /@esbuild/sunos-x64@0.20.2: + resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + optional: true + + /@esbuild/win32-arm64@0.17.19: + resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} engines: {node: '>=12'} - cpu: [loong64] - os: [linux] + cpu: [arm64] + os: [win32] requiresBuild: true dev: true optional: true - /@esbuild/linux-loong64@0.18.20: - resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + /@esbuild/win32-arm64@0.18.20: + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} engines: {node: '>=12'} - cpu: [loong64] - os: [linux] + cpu: [arm64] + os: [win32] requiresBuild: true optional: true - /@esbuild/linux-loong64@0.19.11: - resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==} + /@esbuild/win32-arm64@0.19.11: + resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==} engines: {node: '>=12'} - cpu: [loong64] - os: [linux] + cpu: [arm64] + os: [win32] requiresBuild: true dev: false optional: true - /@esbuild/linux-loong64@0.19.12: - resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + /@esbuild/win32-arm64@0.19.12: + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} engines: {node: '>=12'} - cpu: [loong64] - os: [linux] + cpu: [arm64] + os: [win32] requiresBuild: true - dev: true optional: true - /@esbuild/linux-loong64@0.20.2: - resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + /@esbuild/win32-arm64@0.20.2: + resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} engines: {node: '>=12'} - cpu: [loong64] - os: [linux] + cpu: [arm64] + os: [win32] requiresBuild: true optional: true - /@esbuild/linux-mips64el@0.17.19: - resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} + /@esbuild/win32-ia32@0.17.19: + resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] + cpu: [ia32] + os: [win32] requiresBuild: true dev: true optional: true - /@esbuild/linux-mips64el@0.18.20: - resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + /@esbuild/win32-ia32@0.18.20: + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] + cpu: [ia32] + os: [win32] requiresBuild: true optional: true - /@esbuild/linux-mips64el@0.19.11: - resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==} + /@esbuild/win32-ia32@0.19.11: + resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==} engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] + cpu: [ia32] + os: [win32] requiresBuild: true dev: false optional: true - /@esbuild/linux-mips64el@0.19.12: - resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + /@esbuild/win32-ia32@0.19.12: + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] + cpu: [ia32] + os: [win32] requiresBuild: true - dev: true optional: true - /@esbuild/linux-mips64el@0.20.2: - resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + /@esbuild/win32-ia32@0.20.2: + resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] + cpu: [ia32] + os: [win32] requiresBuild: true optional: true - /@esbuild/linux-ppc64@0.17.19: - resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} + /@esbuild/win32-x64@0.17.19: + resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] + cpu: [x64] + os: [win32] requiresBuild: true dev: true optional: true - /@esbuild/linux-ppc64@0.18.20: - resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + /@esbuild/win32-x64@0.18.20: + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] + cpu: [x64] + os: [win32] requiresBuild: true optional: true - /@esbuild/linux-ppc64@0.19.11: - resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==} + /@esbuild/win32-x64@0.19.11: + resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==} engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] + cpu: [x64] + os: [win32] requiresBuild: true dev: false optional: true - /@esbuild/linux-ppc64@0.19.12: - resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} + /@esbuild/win32-x64@0.19.12: + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] + cpu: [x64] + os: [win32] requiresBuild: true - dev: true optional: true - /@esbuild/linux-ppc64@0.20.2: - resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} + /@esbuild/win32-x64@0.20.2: + resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + /@escape.tech/graphql-armor-block-field-suggestions@2.1.0: + resolution: {integrity: sha512-Sna+jK02oUDJMWSfA7ica69HdtBroP3VakeMUK0+QgWlAEBEphT+SzKGDX5vn6sS7sAsEoY50gUAIgtTG+2qVw==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + dev: false + + /@escape.tech/graphql-armor-cost-limit@2.1.0: + resolution: {integrity: sha512-zejjLm3vn4MQDpXRaPGXclo1Tq1lc93Ltoh3UoqUDiFV29ZUAnSnuuEw/AdbkK+YFrSIfZYMAGDV8AZ2Xz76RQ==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + '@escape.tech/graphql-armor-types': 0.5.0 + dev: false + + /@escape.tech/graphql-armor-max-aliases@2.1.0: + resolution: {integrity: sha512-jaqB8YWIpfDSNrbiGEt301MQqSH7cLu+ZYZjEQ/irL5rqbSN1c9zE+nqEP1cXxB8jB6D+vp8jU30rrZWS9goAQ==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + '@escape.tech/graphql-armor-types': 0.5.0 + dev: false + + /@escape.tech/graphql-armor-max-depth@2.2.0: + resolution: {integrity: sha512-v0z2yelQL614mYFpYL/iRkieq/7H2XKbvJ6RvbGMFFSqo3eSIz8fyX0f6pyswR7myQxki4ur0MFxSn8S5jjfqw==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + '@escape.tech/graphql-armor-types': 0.5.0 + dev: false + + /@escape.tech/graphql-armor-max-directives@2.1.0: + resolution: {integrity: sha512-0OuvWBbOVdphyLPafqTknM4EIrFsGHjv9DcSw8mM7Ol0kKLwYG7tGuBmEzwopRntkqW3utID5tMtf/B6px/Eyw==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + '@escape.tech/graphql-armor-types': 0.5.0 + dev: false + + /@escape.tech/graphql-armor-max-tokens@2.2.0: + resolution: {integrity: sha512-s6IBS8R4fxQ9cVX1USf4dUOWEDbVVrlcGmVOuTCyW1LnpFJQ5vWCs0n93Lsw2ge/MlRIkZEtGuiXdr0YmLU4Pg==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + '@escape.tech/graphql-armor-types': 0.5.0 + dev: false + + /@escape.tech/graphql-armor-types@0.5.0: + resolution: {integrity: sha512-a7KMhb1qVHFFWw4bvGYQI637YaIZRozbfc+Fj1Vv/pwnTCJOzOgnvKO8+WBXJsFFGJ2Kj+fRORmSpz7J+lJF1w==} requiresBuild: true + dependencies: + graphql: 16.8.1 + dev: false optional: true - /@esbuild/linux-riscv64@0.17.19: - resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true + /@escape.tech/graphql-armor@2.3.1(@envelop/core@5.0.0): + resolution: {integrity: sha512-2HV6ApCeb52eVTeXjgpo00VLDZkiQfxeMi9KTPHsK8/1f3X60gx51szHwTRYhPUeimUquRcxqlO36Iq3rbhywQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@apollo/server': ^4.0.0 + '@envelop/core': ^4.0.0 + '@escape.tech/graphql-armor-types': 0.5.0 + peerDependenciesMeta: + '@apollo/server': + optional: true + '@envelop/core': + optional: true + '@escape.tech/graphql-armor-types': + optional: true + dependencies: + '@envelop/core': 5.0.0 + '@escape.tech/graphql-armor-block-field-suggestions': 2.1.0 + '@escape.tech/graphql-armor-cost-limit': 2.1.0 + '@escape.tech/graphql-armor-max-aliases': 2.1.0 + '@escape.tech/graphql-armor-max-depth': 2.2.0 + '@escape.tech/graphql-armor-max-directives': 2.1.0 + '@escape.tech/graphql-armor-max-tokens': 2.2.0 + graphql: 16.8.1 + dev: false + + /@eslint-community/eslint-utils@4.4.0(eslint@9.1.1): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 9.1.1 + eslint-visitor-keys: 3.4.3 + dev: false + + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: false + + /@eslint/eslintrc@3.0.2: + resolution: {integrity: sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 10.0.1 + globals: 14.0.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@eslint/js@9.1.1: + resolution: {integrity: sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dev: false + + /@faker-js/faker@8.4.1: + resolution: {integrity: sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0, npm: '>=6.14.13'} + dev: false + + /@fal-works/esbuild-plugin-global-externals@2.1.2: + resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==} + dev: false + + /@fastify/busboy@2.1.1: + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + /@floating-ui/core@1.6.1: + resolution: {integrity: sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A==} + dependencies: + '@floating-ui/utils': 0.2.2 + + /@floating-ui/dom@1.1.1: + resolution: {integrity: sha512-TpIO93+DIujg3g7SykEAGZMDtbJRrmnYRCNYSjJlvIbGhBjRSNTLVbNeDQBrzy9qDgUbiWdc7KA0uZHZ2tJmiw==} + dependencies: + '@floating-ui/core': 1.6.1 + dev: true + + /@floating-ui/dom@1.6.4: + resolution: {integrity: sha512-0G8R+zOvQsAG1pg2Q99P21jiqxqGBW1iRe/iXHsBRBxnpXKFI8QwbB4x5KmYLggNO5m34IQgOIu9SCRfR/WWiQ==} + dependencies: + '@floating-ui/core': 1.6.1 + '@floating-ui/utils': 0.2.2 + + /@floating-ui/react-dom@2.0.9(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 1.6.4 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@floating-ui/react-dom@2.0.9(react-dom@18.3.1)(react@18.2.0): + resolution: {integrity: sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 1.6.4 + react: 18.2.0 + react-dom: 18.3.1(react@18.2.0) + dev: false + + /@floating-ui/react-dom@2.0.9(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 1.6.4 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) dev: true - optional: true - /@esbuild/linux-riscv64@0.18.20: - resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - optional: true + /@floating-ui/utils@0.2.2: + resolution: {integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==} - /@esbuild/linux-riscv64@0.19.11: - resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true + /@google-cloud/precise-date@4.0.0: + resolution: {integrity: sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA==} + engines: {node: '>=14.0.0'} dev: false - optional: true - /@esbuild/linux-riscv64@0.19.12: - resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true + /@graphql-codegen/add@4.0.1(graphql@16.8.1): + resolution: {integrity: sha512-A7k+9eRfrKyyNfhWEN/0eKz09R5cp4XXxUuNLQAVm/aohmVI2xdMV4lM02rTlM6Pyou3cU/v0iZnhgo6IRpqeg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.5.3 + dev: false - /@esbuild/linux-riscv64@0.20.2: - resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - optional: true + /@graphql-codegen/add@5.0.2(graphql@16.8.1): + resolution: {integrity: sha512-ouBkSvMFUhda5VoKumo/ZvsZM9P5ZTyDsI8LW18VxSNWOjrTeLXBWHG8Gfaai0HwhflPtCYVABbriEcOmrRShQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.3(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + dev: false - /@esbuild/linux-s390x@0.17.19: - resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true + /@graphql-codegen/cli@3.3.1(@babel/core@7.24.5)(@types/node@20.12.7)(graphql@16.8.1): + resolution: {integrity: sha512-4Es8Y9zFeT0Zx2qRL7L3qXDbbqvXK6aID+8v8lP6gaYD+uWx3Jd4Hsq5vxwVBR+6flm0BW/C85Qm0cvmT7O6LA==} + hasBin: true + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@babel/generator': 7.24.5 + '@babel/template': 7.24.0 + '@babel/types': 7.24.5 + '@graphql-codegen/core': 3.1.0(graphql@16.8.1) + '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) + '@graphql-tools/apollo-engine-loader': 7.3.26(graphql@16.8.1) + '@graphql-tools/code-file-loader': 7.3.23(@babel/core@7.24.5)(graphql@16.8.1) + '@graphql-tools/git-loader': 7.3.0(@babel/core@7.24.5)(graphql@16.8.1) + '@graphql-tools/github-loader': 7.3.28(@babel/core@7.24.5)(@types/node@20.12.7)(graphql@16.8.1) + '@graphql-tools/graphql-file-loader': 7.5.17(graphql@16.8.1) + '@graphql-tools/json-file-loader': 7.4.18(graphql@16.8.1) + '@graphql-tools/load': 7.8.14(graphql@16.8.1) + '@graphql-tools/prisma-loader': 7.2.72(@types/node@20.12.7)(graphql@16.8.1) + '@graphql-tools/url-loader': 7.17.18(@types/node@20.12.7)(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@parcel/watcher': 2.4.1 + '@whatwg-node/fetch': 0.8.8 + chalk: 4.1.2 + cosmiconfig: 7.1.0 + debounce: 1.2.1 + detect-indent: 6.1.0 + graphql: 16.8.1 + graphql-config: 4.5.0(@types/node@20.12.7)(graphql@16.8.1) + inquirer: 8.2.5 + is-glob: 4.0.3 + jiti: 1.21.0 + json-to-pretty-yaml: 1.2.2 + listr2: 4.0.5 + log-symbols: 4.1.0 + micromatch: 4.0.5 + shell-quote: 1.8.1 + string-env-interpolation: 1.0.1 + ts-log: 2.2.5 + tslib: 2.6.2 + yaml: 1.10.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@babel/core' + - '@types/node' + - bufferutil + - cosmiconfig-toml-loader + - encoding + - enquirer + - supports-color + - utf-8-validate + dev: false - /@esbuild/linux-s390x@0.18.20: - resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - optional: true + /@graphql-codegen/client-preset@4.2.5(graphql@16.8.1): + resolution: {integrity: sha512-hAdB6HN8EDmkoBtr0bPUN/7NH6svzqbcTDMWBCRXPESXkl7y80po+IXrXUjsSrvhKG8xkNXgJNz/2mjwHzywcA==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@babel/helper-plugin-utils': 7.24.5 + '@babel/template': 7.24.0 + '@graphql-codegen/add': 5.0.2(graphql@16.8.1) + '@graphql-codegen/gql-tag-operations': 4.0.6(graphql@16.8.1) + '@graphql-codegen/plugin-helpers': 5.0.3(graphql@16.8.1) + '@graphql-codegen/typed-document-node': 5.0.6(graphql@16.8.1) + '@graphql-codegen/typescript': 4.0.6(graphql@16.8.1) + '@graphql-codegen/typescript-operations': 4.2.0(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 5.1.0(graphql@16.8.1) + '@graphql-tools/documents': 1.0.0(graphql@16.8.1) + '@graphql-tools/utils': 10.2.0(graphql@16.8.1) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: false - /@esbuild/linux-s390x@0.19.11: - resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true + /@graphql-codegen/core@3.1.0(graphql@16.8.1): + resolution: {integrity: sha512-DH1/yaR7oJE6/B+c6ZF2Tbdh7LixF1K8L+8BoSubjNyQ8pNwR4a70mvc1sv6H7qgp6y1bPQ9tKE+aazRRshysw==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) + '@graphql-tools/schema': 9.0.19(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.5.3 dev: false - optional: true - /@esbuild/linux-s390x@0.19.12: - resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true + /@graphql-codegen/fragment-matcher@5.0.2(graphql@16.8.1): + resolution: {integrity: sha512-AeazT6Arv7LvpkvPYTajfUO6g1FeGLqyt6VaxDhMIRCuJN21PAvSWsh3wayc+K5L5VtYFZXYczC7Lw1bMb8C2Q==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.3(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + dev: false - /@esbuild/linux-s390x@0.20.2: - resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - optional: true + /@graphql-codegen/gql-tag-operations@4.0.6(graphql@16.8.1): + resolution: {integrity: sha512-y6iXEDpDNjwNxJw3WZqX1/Znj0QHW7+y8O+t2V8qvbTT+3kb2lr9ntc8By7vCr6ctw9tXI4XKaJgpTstJDOwFA==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.3(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 5.1.0(graphql@16.8.1) + '@graphql-tools/utils': 10.2.0(graphql@16.8.1) + auto-bind: 4.0.0 + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: false - /@esbuild/linux-x64@0.17.19: - resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true + /@graphql-codegen/plugin-helpers@2.7.2(graphql@16.8.1): + resolution: {integrity: sha512-kln2AZ12uii6U59OQXdjLk5nOlh1pHis1R98cDZGFnfaiAbX9V3fxcZ1MMJkB7qFUymTALzyjZoXXdyVmPMfRg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-tools/utils': 8.13.1(graphql@16.8.1) + change-case-all: 1.0.14 + common-tags: 1.8.2 + graphql: 16.8.1 + import-from: 4.0.0 + lodash: 4.17.21 + tslib: 2.4.1 + dev: false - /@esbuild/linux-x64@0.18.20: - resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true + /@graphql-codegen/plugin-helpers@4.2.0(graphql@16.8.1): + resolution: {integrity: sha512-THFTCfg+46PXlXobYJ/OoCX6pzjI+9woQqCjdyKtgoI0tn3Xq2HUUCiidndxUpEYVrXb5pRiRXb7b/ZbMQqD0A==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + change-case-all: 1.0.15 + common-tags: 1.8.2 + graphql: 16.8.1 + import-from: 4.0.0 + lodash: 4.17.21 + tslib: 2.5.3 + dev: false - /@esbuild/linux-x64@0.19.11: - resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true + /@graphql-codegen/plugin-helpers@5.0.3(graphql@16.8.1): + resolution: {integrity: sha512-yZ1rpULIWKBZqCDlvGIJRSyj1B2utkEdGmXZTBT/GVayP4hyRYlkd36AJV/LfEsVD8dnsKL5rLz2VTYmRNlJ5Q==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-tools/utils': 10.2.0(graphql@16.8.1) + change-case-all: 1.0.15 + common-tags: 1.8.2 + graphql: 16.8.1 + import-from: 4.0.0 + lodash: 4.17.21 + tslib: 2.6.2 dev: false - optional: true - /@esbuild/linux-x64@0.19.12: - resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true + /@graphql-codegen/schema-ast@3.0.1(graphql@16.8.1): + resolution: {integrity: sha512-rTKTi4XiW4QFZnrEqetpiYEWVsOFNoiR/v3rY9mFSttXFbIwNXPme32EspTiGWmEEdHY8UuTDtZN3vEcs/31zw==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.5.3 + dev: false - /@esbuild/linux-x64@0.20.2: - resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true + /@graphql-codegen/schema-ast@4.0.2(graphql@16.8.1): + resolution: {integrity: sha512-5mVAOQQK3Oz7EtMl/l3vOQdc2aYClUzVDHHkMvZlunc+KlGgl81j8TLa+X7ANIllqU4fUEsQU3lJmk4hXP6K7Q==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.3(graphql@16.8.1) + '@graphql-tools/utils': 10.2.0(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + dev: false - /@esbuild/netbsd-x64@0.17.19: - resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true + /@graphql-codegen/typed-document-node@5.0.6(graphql@16.8.1): + resolution: {integrity: sha512-US0J95hOE2/W/h42w4oiY+DFKG7IetEN1mQMgXXeat1w6FAR5PlIz4JrRrEkiVfVetZ1g7K78SOwBD8/IJnDiA==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.3(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 5.1.0(graphql@16.8.1) + auto-bind: 4.0.0 + change-case-all: 1.0.15 + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: false - /@esbuild/netbsd-x64@0.18.20: - resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - optional: true + /@graphql-codegen/typescript-operations@3.0.4(graphql@16.8.1): + resolution: {integrity: sha512-6yE2OL2+WJ1vd5MwFEGXpaxsFGzjAGUytPVHDML3Bi3TwP1F3lnQlIko4untwvHW0JhZEGQ7Ck30H9HjcxpdKA==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) + '@graphql-codegen/typescript': 3.0.4(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 3.1.1(graphql@16.8.1) + auto-bind: 4.0.0 + graphql: 16.8.1 + tslib: 2.5.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: false - /@esbuild/netbsd-x64@0.19.11: - resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true + /@graphql-codegen/typescript-operations@4.2.0(graphql@16.8.1): + resolution: {integrity: sha512-lmuwYb03XC7LNRS8oo9M4/vlOrq/wOKmTLBHlltK2YJ1BO/4K/Q9Jdv/jDmJpNydHVR1fmeF4wAfsIp1f9JibA==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.3(graphql@16.8.1) + '@graphql-codegen/typescript': 4.0.6(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 5.1.0(graphql@16.8.1) + auto-bind: 4.0.0 + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color dev: false - optional: true - - /@esbuild/netbsd-x64@0.19.12: - resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/netbsd-x64@0.20.2: - resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - optional: true + /@graphql-codegen/typescript-react-apollo@3.3.7(graphql-tag@2.12.6)(graphql@16.8.1): + resolution: {integrity: sha512-9DUiGE8rcwwEkf/S1kpBT/Py/UUs9Qak14bOnTT1JHWs1MWhiDA7vml+A8opU7YFI1EVbSSaE5jjRv11WHoikQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + graphql-tag: ^2.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 2.7.2(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 2.13.1(graphql@16.8.1) + auto-bind: 4.0.0 + change-case-all: 1.0.14 + graphql: 16.8.1 + graphql-tag: 2.12.6(graphql@16.8.1) + tslib: 2.4.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: false - /@esbuild/openbsd-x64@0.17.19: - resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true + /@graphql-codegen/typescript-resolvers@3.2.1(graphql@16.8.1): + resolution: {integrity: sha512-2ZIHk5J6HTuylse5ZIxw+aega54prHxvj7vM8hiKJ6vejZ94kvVPAq4aWmSFOkZ5lqU3YnM/ZyWfnhT5CUDj1g==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) + '@graphql-codegen/typescript': 3.0.4(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 3.1.1(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + auto-bind: 4.0.0 + graphql: 16.8.1 + tslib: 2.5.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: false - /@esbuild/openbsd-x64@0.18.20: - resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - optional: true + /@graphql-codegen/typescript@3.0.4(graphql@16.8.1): + resolution: {integrity: sha512-x4O47447DZrWNtE/l5CU9QzzW4m1RbmCEdijlA3s2flG/y1Ckqdemob4CWfilSm5/tZ3w1junVDY616RDTSvZw==} + peerDependencies: + graphql: ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) + '@graphql-codegen/schema-ast': 3.0.1(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 3.1.1(graphql@16.8.1) + auto-bind: 4.0.0 + graphql: 16.8.1 + tslib: 2.5.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: false - /@esbuild/openbsd-x64@0.19.11: - resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true + /@graphql-codegen/typescript@4.0.6(graphql@16.8.1): + resolution: {integrity: sha512-IBG4N+Blv7KAL27bseruIoLTjORFCT3r+QYyMC3g11uY3/9TPpaUyjSdF70yBe5GIQ6dAgDU+ENUC1v7EPi0rw==} + peerDependencies: + graphql: ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.3(graphql@16.8.1) + '@graphql-codegen/schema-ast': 4.0.2(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 5.1.0(graphql@16.8.1) + auto-bind: 4.0.0 + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color dev: false - optional: true - /@esbuild/openbsd-x64@0.19.12: - resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true + /@graphql-codegen/visitor-plugin-common@2.13.1(graphql@16.8.1): + resolution: {integrity: sha512-mD9ufZhDGhyrSaWQGrU1Q1c5f01TeWtSWy/cDwXYjJcHIj1Y/DG2x0tOflEfCvh5WcnmHNIw4lzDsg1W7iFJEg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 2.7.2(graphql@16.8.1) + '@graphql-tools/optimize': 1.4.0(graphql@16.8.1) + '@graphql-tools/relay-operation-optimizer': 6.5.18(graphql@16.8.1) + '@graphql-tools/utils': 8.13.1(graphql@16.8.1) + auto-bind: 4.0.0 + change-case-all: 1.0.14 + dependency-graph: 0.11.0 + graphql: 16.8.1 + graphql-tag: 2.12.6(graphql@16.8.1) + parse-filepath: 1.0.2 + tslib: 2.4.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: false - /@esbuild/openbsd-x64@0.20.2: - resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - optional: true + /@graphql-codegen/visitor-plugin-common@3.1.1(graphql@16.8.1): + resolution: {integrity: sha512-uAfp+zu/009R3HUAuTK2AamR1bxIltM6rrYYI6EXSmkM3rFtFsLTuJhjUDj98HcUCszJZrADppz8KKLGRUVlNg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) + '@graphql-tools/optimize': 1.4.0(graphql@16.8.1) + '@graphql-tools/relay-operation-optimizer': 6.5.18(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + auto-bind: 4.0.0 + change-case-all: 1.0.15 + dependency-graph: 0.11.0 + graphql: 16.8.1 + graphql-tag: 2.12.6(graphql@16.8.1) + parse-filepath: 1.0.2 + tslib: 2.5.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: false - /@esbuild/sunos-x64@0.17.19: - resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true + /@graphql-codegen/visitor-plugin-common@5.1.0(graphql@16.8.1): + resolution: {integrity: sha512-eamQxtA9bjJqI2lU5eYoA1GbdMIRT2X8m8vhWYsVQVWD3qM7sx/IqJU0kx0J3Vd4/CSd36BzL6RKwksibytDIg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.3(graphql@16.8.1) + '@graphql-tools/optimize': 2.0.0(graphql@16.8.1) + '@graphql-tools/relay-operation-optimizer': 7.0.1(graphql@16.8.1) + '@graphql-tools/utils': 10.2.0(graphql@16.8.1) + auto-bind: 4.0.0 + change-case-all: 1.0.15 + dependency-graph: 0.11.0 + graphql: 16.8.1 + graphql-tag: 2.12.6(graphql@16.8.1) + parse-filepath: 1.0.2 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: false - /@esbuild/sunos-x64@0.18.20: - resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - optional: true + /@graphql-tools/apollo-engine-loader@7.3.26(graphql@16.8.1): + resolution: {integrity: sha512-h1vfhdJFjnCYn9b5EY1Z91JTF0KB3hHVJNQIsiUV2mpQXZdeOXQoaWeYEKaiI5R6kwBw5PP9B0fv3jfUIG8LyQ==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/sync-fetch': 0.0.1 + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@whatwg-node/fetch': 0.8.8 + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + dev: false - /@esbuild/sunos-x64@0.19.11: - resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true + /@graphql-tools/batch-execute@8.5.22(graphql@16.8.1): + resolution: {integrity: sha512-hcV1JaY6NJQFQEwCKrYhpfLK8frSXDbtNMoTur98u10Cmecy1zrqNKSqhEyGetpgHxaJRqszGzKeI3RuroDN6A==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + dataloader: 2.2.2 + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 dev: false - optional: true - /@esbuild/sunos-x64@0.19.12: - resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true + /@graphql-tools/code-file-loader@7.3.23(@babel/core@7.24.5)(graphql@16.8.1): + resolution: {integrity: sha512-8Wt1rTtyTEs0p47uzsPJ1vAtfAx0jmxPifiNdmo9EOCuUPyQGEbMaik/YkqZ7QUFIEYEQu+Vgfo8tElwOPtx5Q==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/graphql-tag-pluck': 7.5.2(@babel/core@7.24.5)(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + globby: 11.1.0 + graphql: 16.8.1 + tslib: 2.6.2 + unixify: 1.0.0 + transitivePeerDependencies: + - '@babel/core' + - supports-color + dev: false - /@esbuild/sunos-x64@0.20.2: - resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - optional: true + /@graphql-tools/delegate@9.0.35(graphql@16.8.1): + resolution: {integrity: sha512-jwPu8NJbzRRMqi4Vp/5QX1vIUeUPpWmlQpOkXQD2r1X45YsVceyUUBnktCrlJlDB4jPRVy7JQGwmYo3KFiOBMA==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/batch-execute': 8.5.22(graphql@16.8.1) + '@graphql-tools/executor': 0.0.20(graphql@16.8.1) + '@graphql-tools/schema': 9.0.19(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + dataloader: 2.2.2 + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 + dev: false - /@esbuild/win32-arm64@0.17.19: - resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true + /@graphql-tools/documents@1.0.0(graphql@16.8.1): + resolution: {integrity: sha512-rHGjX1vg/nZ2DKqRGfDPNC55CWZBMldEVcH+91BThRa6JeT80NqXknffLLEZLRUxyikCfkwMsk6xR3UNMqG0Rg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.8.1 + lodash.sortby: 4.7.0 + tslib: 2.6.2 + dev: false - /@esbuild/win32-arm64@0.18.20: - resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true + /@graphql-tools/executor-graphql-ws@0.0.14(graphql@16.8.1): + resolution: {integrity: sha512-P2nlkAsPZKLIXImFhj0YTtny5NQVGSsKnhi7PzXiaHSXc6KkzqbWZHKvikD4PObanqg+7IO58rKFpGXP7eeO+w==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@repeaterjs/repeater': 3.0.4 + '@types/ws': 8.5.10 + graphql: 16.8.1 + graphql-ws: 5.12.1(graphql@16.8.1) + isomorphic-ws: 5.0.0(ws@8.13.0) + tslib: 2.6.2 + ws: 8.13.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false - /@esbuild/win32-arm64@0.19.11: - resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true + /@graphql-tools/executor-http@0.1.10(@types/node@20.12.7)(graphql@16.8.1): + resolution: {integrity: sha512-hnAfbKv0/lb9s31LhWzawQ5hghBfHS+gYWtqxME6Rl0Aufq9GltiiLBcl7OVVOnkLF0KhwgbYP1mB5VKmgTGpg==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@repeaterjs/repeater': 3.0.5 + '@whatwg-node/fetch': 0.8.8 + dset: 3.1.3 + extract-files: 11.0.0 + graphql: 16.8.1 + meros: 1.3.0(@types/node@20.12.7) + tslib: 2.6.2 + value-or-promise: 1.0.12 + transitivePeerDependencies: + - '@types/node' dev: false - optional: true - /@esbuild/win32-arm64@0.19.12: - resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true + /@graphql-tools/executor-legacy-ws@0.0.11(graphql@16.8.1): + resolution: {integrity: sha512-4ai+NnxlNfvIQ4c70hWFvOZlSUN8lt7yc+ZsrwtNFbFPH/EroIzFMapAxM9zwyv9bH38AdO3TQxZ5zNxgBdvUw==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@types/ws': 8.5.10 + graphql: 16.8.1 + isomorphic-ws: 5.0.0(ws@8.13.0) + tslib: 2.6.2 + ws: 8.13.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false - /@esbuild/win32-arm64@0.20.2: - resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true + /@graphql-tools/executor@0.0.20(graphql@16.8.1): + resolution: {integrity: sha512-GdvNc4vszmfeGvUqlcaH1FjBoguvMYzxAfT6tDd4/LgwymepHhinqLNA5otqwVLW+JETcDaK7xGENzFomuE6TA==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + '@repeaterjs/repeater': 3.0.5 + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 + dev: false - /@esbuild/win32-ia32@0.17.19: - resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true + /@graphql-tools/executor@1.2.6(graphql@16.8.1): + resolution: {integrity: sha512-+1kjfqzM5T2R+dCw7F4vdJ3CqG+fY/LYJyhNiWEFtq0ToLwYzR/KKyD8YuzTirEjSxWTVlcBh7endkx5n5F6ew==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.2.0(graphql@16.8.1) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + '@repeaterjs/repeater': 3.0.5 + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 + dev: false - /@esbuild/win32-ia32@0.18.20: - resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true + /@graphql-tools/git-loader@7.3.0(@babel/core@7.24.5)(graphql@16.8.1): + resolution: {integrity: sha512-gcGAK+u16eHkwsMYqqghZbmDquh8QaO24Scsxq+cVR+vx1ekRlsEiXvu+yXVDbZdcJ6PBIbeLcQbEu+xhDLmvQ==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/graphql-tag-pluck': 7.5.2(@babel/core@7.24.5)(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + is-glob: 4.0.3 + micromatch: 4.0.5 + tslib: 2.6.2 + unixify: 1.0.0 + transitivePeerDependencies: + - '@babel/core' + - supports-color + dev: false - /@esbuild/win32-ia32@0.19.11: - resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true + /@graphql-tools/github-loader@7.3.28(@babel/core@7.24.5)(@types/node@20.12.7)(graphql@16.8.1): + resolution: {integrity: sha512-OK92Lf9pmxPQvjUNv05b3tnVhw0JRfPqOf15jZjyQ8BfdEUrJoP32b4dRQQem/wyRL24KY4wOfArJNqzpsbwCA==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/sync-fetch': 0.0.1 + '@graphql-tools/executor-http': 0.1.10(@types/node@20.12.7)(graphql@16.8.1) + '@graphql-tools/graphql-tag-pluck': 7.5.2(@babel/core@7.24.5)(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@whatwg-node/fetch': 0.8.8 + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 + transitivePeerDependencies: + - '@babel/core' + - '@types/node' + - encoding + - supports-color dev: false - optional: true - /@esbuild/win32-ia32@0.19.12: - resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true + /@graphql-tools/graphql-file-loader@7.5.17(graphql@16.8.1): + resolution: {integrity: sha512-hVwwxPf41zOYgm4gdaZILCYnKB9Zap7Ys9OhY1hbwuAuC4MMNY9GpUjoTU3CQc3zUiPoYStyRtUGkHSJZ3HxBw==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/import': 6.7.18(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + globby: 11.1.0 + graphql: 16.8.1 + tslib: 2.6.2 + unixify: 1.0.0 + dev: false - /@esbuild/win32-ia32@0.20.2: - resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true + /@graphql-tools/graphql-tag-pluck@7.5.2(@babel/core@7.24.5)(graphql@16.8.1): + resolution: {integrity: sha512-RW+H8FqOOLQw0BPXaahYepVSRjuOHw+7IL8Opaa5G5uYGOBxoXR7DceyQ7BcpMgktAOOmpDNQ2WtcboChOJSRA==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@babel/parser': 7.24.5 + '@babel/plugin-syntax-import-assertions': 7.24.1(@babel/core@7.24.5) + '@babel/traverse': 7.24.5 + '@babel/types': 7.24.5 + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - '@babel/core' + - supports-color + dev: false - /@esbuild/win32-x64@0.17.19: - resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true + /@graphql-tools/import@6.7.18(graphql@16.8.1): + resolution: {integrity: sha512-XQDdyZTp+FYmT7as3xRWH/x8dx0QZA2WZqfMF5EWb36a0PiH7WwlRQYIdyYXj8YCLpiWkeBXgBRHmMnwEYR8iQ==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + resolve-from: 5.0.0 + tslib: 2.6.2 + dev: false - /@esbuild/win32-x64@0.18.20: - resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true + /@graphql-tools/json-file-loader@7.4.18(graphql@16.8.1): + resolution: {integrity: sha512-AJ1b6Y1wiVgkwsxT5dELXhIVUPs/u3VZ8/0/oOtpcoyO/vAeM5rOvvWegzicOOnQw8G45fgBRMkkRfeuwVt6+w==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + globby: 11.1.0 + graphql: 16.8.1 + tslib: 2.6.2 + unixify: 1.0.0 + dev: false - /@esbuild/win32-x64@0.19.11: - resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true + /@graphql-tools/load@7.8.14(graphql@16.8.1): + resolution: {integrity: sha512-ASQvP+snHMYm+FhIaLxxFgVdRaM0vrN9wW2BKInQpktwWTXVyk+yP5nQUCEGmn0RTdlPKrffBaigxepkEAJPrg==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/schema': 9.0.19(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + p-limit: 3.1.0 + tslib: 2.6.2 dev: false - optional: true - /@esbuild/win32-x64@0.19.12: - resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true + /@graphql-tools/merge@8.4.2(graphql@16.8.1): + resolution: {integrity: sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + dev: false - /@esbuild/win32-x64@0.20.2: - resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true + /@graphql-tools/merge@9.0.3(graphql@16.8.1): + resolution: {integrity: sha512-FeKv9lKLMwqDu0pQjPpF59GY3HReUkWXKsMIuMuJQOKh9BETu7zPEFUELvcw8w+lwZkl4ileJsHXC9+AnsT2Lw==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.2.0(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + dev: false - /@eslint-community/eslint-utils@4.4.0(eslint@9.1.1): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@graphql-tools/optimize@1.4.0(graphql@16.8.1): + resolution: {integrity: sha512-dJs/2XvZp+wgHH8T5J2TqptT9/6uVzIYvA6uFACha+ufvdMBedkfR4b4GbT8jAKLRARiqRTxy3dctnwkTM2tdw==} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: - eslint: 9.1.1 - eslint-visitor-keys: 3.4.3 + graphql: 16.8.1 + tslib: 2.6.2 dev: false - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + /@graphql-tools/optimize@2.0.0(graphql@16.8.1): + resolution: {integrity: sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.8.1 + tslib: 2.6.2 dev: false - /@eslint/eslintrc@3.0.2: - resolution: {integrity: sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + /@graphql-tools/prisma-loader@7.2.72(@types/node@20.12.7)(graphql@16.8.1): + resolution: {integrity: sha512-0a7uV7Fky6yDqd0tI9+XMuvgIo6GAqiVzzzFV4OSLry4AwiQlI3igYseBV7ZVOGhedOTqj/URxjpiv07hRcwag==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: - ajv: 6.12.6 + '@graphql-tools/url-loader': 7.17.18(@types/node@20.12.7)(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@types/js-yaml': 4.0.9 + '@types/json-stable-stringify': 1.0.36 + '@whatwg-node/fetch': 0.8.8 + chalk: 4.1.2 debug: 4.3.4 - espree: 10.0.1 - globals: 14.0.0 - ignore: 5.3.1 - import-fresh: 3.3.0 + dotenv: 16.4.5 + graphql: 16.8.1 + graphql-request: 6.1.0(graphql@16.8.1) + http-proxy-agent: 6.1.1 + https-proxy-agent: 6.2.1 + jose: 4.15.5 js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 + json-stable-stringify: 1.1.1 + lodash: 4.17.21 + scuid: 1.1.0 + tslib: 2.6.2 + yaml-ast-parser: 0.0.43 transitivePeerDependencies: + - '@types/node' + - bufferutil + - encoding - supports-color + - utf-8-validate dev: false - /@eslint/js@9.1.1: - resolution: {integrity: sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + /@graphql-tools/relay-operation-optimizer@6.5.18(graphql@16.8.1): + resolution: {integrity: sha512-mc5VPyTeV+LwiM+DNvoDQfPqwQYhPV/cl5jOBjTgSniyaq8/86aODfMkrE2OduhQ5E00hqrkuL2Fdrgk0w1QJg==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/relay-compiler': 12.0.0(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color dev: false - /@faker-js/faker@8.4.1: - resolution: {integrity: sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0, npm: '>=6.14.13'} + /@graphql-tools/relay-operation-optimizer@7.0.1(graphql@16.8.1): + resolution: {integrity: sha512-y0ZrQ/iyqWZlsS/xrJfSir3TbVYJTYmMOu4TaSz6F4FRDTQ3ie43BlKkhf04rC28pnUOS4BO9pDcAo1D30l5+A==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/relay-compiler': 12.0.0(graphql@16.8.1) + '@graphql-tools/utils': 10.2.0(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color dev: false - /@fal-works/esbuild-plugin-global-externals@2.1.2: - resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==} + /@graphql-tools/schema@10.0.3(graphql@16.8.1): + resolution: {integrity: sha512-p28Oh9EcOna6i0yLaCFOnkcBDQECVf3SCexT6ktb86QNj9idnkhI+tCxnwZDh58Qvjd2nURdkbevvoZkvxzCog==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/merge': 9.0.3(graphql@16.8.1) + '@graphql-tools/utils': 10.2.0(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 dev: false - /@fastify/busboy@2.1.1: - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} + /@graphql-tools/schema@9.0.19(graphql@16.8.1): + resolution: {integrity: sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/merge': 8.4.2(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 + dev: false - /@floating-ui/core@1.6.1: - resolution: {integrity: sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A==} + /@graphql-tools/url-loader@7.17.18(@types/node@20.12.7)(graphql@16.8.1): + resolution: {integrity: sha512-ear0CiyTj04jCVAxi7TvgbnGDIN2HgqzXzwsfcqiVg9cvjT40NcMlZ2P1lZDgqMkZ9oyLTV8Bw6j+SyG6A+xPw==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: - '@floating-ui/utils': 0.2.2 + '@ardatan/sync-fetch': 0.0.1 + '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) + '@graphql-tools/executor-graphql-ws': 0.0.14(graphql@16.8.1) + '@graphql-tools/executor-http': 0.1.10(@types/node@20.12.7)(graphql@16.8.1) + '@graphql-tools/executor-legacy-ws': 0.0.11(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) + '@types/ws': 8.5.10 + '@whatwg-node/fetch': 0.8.8 + graphql: 16.8.1 + isomorphic-ws: 5.0.0(ws@8.17.0) + tslib: 2.6.2 + value-or-promise: 1.0.12 + ws: 8.17.0 + transitivePeerDependencies: + - '@types/node' + - bufferutil + - encoding + - utf-8-validate + dev: false - /@floating-ui/dom@1.1.1: - resolution: {integrity: sha512-TpIO93+DIujg3g7SykEAGZMDtbJRrmnYRCNYSjJlvIbGhBjRSNTLVbNeDQBrzy9qDgUbiWdc7KA0uZHZ2tJmiw==} + /@graphql-tools/utils@10.1.2(graphql@16.8.1): + resolution: {integrity: sha512-fX13CYsDnX4yifIyNdiN0cVygz/muvkreWWem6BBw130+ODbRRgfiVveL0NizCEnKXkpvdeTy9Bxvo9LIKlhrw==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: - '@floating-ui/core': 1.6.1 - dev: true + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + cross-inspect: 1.0.0 + dset: 3.1.3 + graphql: 16.8.1 + tslib: 2.6.2 + dev: false - /@floating-ui/dom@1.6.4: - resolution: {integrity: sha512-0G8R+zOvQsAG1pg2Q99P21jiqxqGBW1iRe/iXHsBRBxnpXKFI8QwbB4x5KmYLggNO5m34IQgOIu9SCRfR/WWiQ==} + /@graphql-tools/utils@10.2.0(graphql@16.8.1): + resolution: {integrity: sha512-HYV7dO6pNA2nGKawygaBpk8y+vXOUjjzzO43W/Kb7EPRmXUEQKjHxPYRvQbiF72u1N3XxwGK5jnnFk9WVhUwYw==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: - '@floating-ui/core': 1.6.1 - '@floating-ui/utils': 0.2.2 + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + cross-inspect: 1.0.0 + dset: 3.1.3 + graphql: 16.8.1 + tslib: 2.6.2 + dev: false - /@floating-ui/react-dom@2.0.9(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==} + /@graphql-tools/utils@8.13.1(graphql@16.8.1): + resolution: {integrity: sha512-qIh9yYpdUFmctVqovwMdheVNJqFh+DQNWIhX87FJStfXYnmweBUDATok9fWPleKeFwxnW8IapKmY8m8toJEkAw==} peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: - '@floating-ui/dom': 1.6.4 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + graphql: 16.8.1 + tslib: 2.6.2 + dev: false + + /@graphql-tools/utils@9.2.1(graphql@16.8.1): + resolution: {integrity: sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 dev: false - /@floating-ui/react-dom@2.0.9(react-dom@18.3.1)(react@18.2.0): - resolution: {integrity: sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==} + /@graphql-tools/wrap@9.4.2(graphql@16.8.1): + resolution: {integrity: sha512-DFcd9r51lmcEKn0JW43CWkkI2D6T9XI1juW/Yo86i04v43O9w2/k4/nx2XTJv4Yv+iXwUw7Ok81PGltwGJSDSA==} peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: - '@floating-ui/dom': 1.6.4 - react: 18.2.0 - react-dom: 18.3.1(react@18.2.0) + '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) + '@graphql-tools/schema': 9.0.19(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 dev: false - /@floating-ui/react-dom@2.0.9(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==} + /@graphql-typed-document-node/core@3.2.0(graphql@16.8.1): + resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: - '@floating-ui/dom': 1.6.4 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: true - - /@floating-ui/utils@0.2.2: - resolution: {integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==} + graphql: 16.8.1 + dev: false - /@google-cloud/precise-date@4.0.0: - resolution: {integrity: sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA==} - engines: {node: '>=14.0.0'} + /@graphql-yoga/logger@2.0.0: + resolution: {integrity: sha512-Mg8psdkAp+YTG1OGmvU+xa6xpsAmSir0hhr3yFYPyLNwzUj95DdIwsMpKadDj9xDpYgJcH3Hp/4JMal9DhQimA==} + engines: {node: '>=18.0.0'} + dependencies: + tslib: 2.6.2 dev: false - /@graphql-typed-document-node/core@3.2.0(graphql@16.8.1): - resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} + /@graphql-yoga/plugin-persisted-operations@3.2.0(@graphql-tools/utils@10.1.2)(graphql-yoga@5.2.0)(graphql@16.8.1): + resolution: {integrity: sha512-Lyb0qttANsWOhaQw6hpc4bC+2N9ZF1DfJOQmxbgvxcYHJlcbrTi0NC8ykJxODcTrZyl2HmCvPoTMr7PuVF4nxA==} + engines: {node: '>=18.0.0'} peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/utils': ^10.0.0 + graphql: ^15.2.0 || ^16.0.0 + graphql-yoga: ^5.2.0 dependencies: + '@graphql-tools/utils': 10.1.2(graphql@16.8.1) graphql: 16.8.1 + graphql-yoga: 5.2.0(graphql@16.8.1) + dev: false + + /@graphql-yoga/subscription@5.0.0: + resolution: {integrity: sha512-Ri7sK8hmxd/kwaEa0YT8uqQUb2wOLsmBMxI90QDyf96lzOMJRgBuNYoEkU1pSgsgmW2glceZ96sRYfaXqwVxUw==} + engines: {node: '>=18.0.0'} + dependencies: + '@graphql-yoga/typed-event-target': 3.0.0 + '@repeaterjs/repeater': 3.0.5 + '@whatwg-node/events': 0.1.1 + tslib: 2.6.2 + dev: false + + /@graphql-yoga/typed-event-target@3.0.0: + resolution: {integrity: sha512-w+liuBySifrstuHbFrHoHAEyVnDFVib+073q8AeAJ/qqJfvFvAwUPLLtNohR/WDVRgSasfXtl3dcNuVJWN+rjg==} + engines: {node: '>=18.0.0'} + dependencies: + '@repeaterjs/repeater': 3.0.5 + tslib: 2.6.2 dev: false /@grpc/grpc-js@1.10.6: @@ -4395,6 +6574,10 @@ packages: engines: {node: '>=18.18'} dev: false + /@iarna/toml@2.2.5: + resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} + dev: false + /@iconify/types@2.0.0: resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} dev: true @@ -4692,7 +6875,6 @@ packages: dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - dev: true /@js-sdsl/ordered-map@4.4.2: resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} @@ -4710,6 +6892,10 @@ packages: resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} dev: true + /@kamilkisiela/fast-url-parser@1.1.4: + resolution: {integrity: sha512-gbkePEBupNydxCelHCESvFSFM8XPh1Zs/OAVRW/rKpEqPAl5PbOM90Si8mv9bvnR53uPD2s/FiRxdvSejpRJew==} + dev: false + /@kwsites/file-exists@1.1.1: resolution: {integrity: sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==} dependencies: @@ -5071,6 +7257,13 @@ packages: - debug dev: true + /@mrleebo/prisma-ast@0.5.2: + resolution: {integrity: sha512-v2jwtrLt/x5/MaF7Sucsz/do8tDUmiq3KA+UYdyZfr3OQ2IGXUtpNSXmdlvyRM+vQ7Abn/FxpLW/qqhZGB9vhQ==} + engines: {node: '>=12'} + dependencies: + chevrotain: 10.5.0 + dev: false + /@mswjs/cookies@1.1.0: resolution: {integrity: sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==} engines: {node: '>=18'} @@ -6622,7 +8815,6 @@ packages: cpu: [arm64] os: [android] requiresBuild: true - dev: true optional: true /@parcel/watcher-darwin-arm64@2.4.1: @@ -6631,7 +8823,6 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true - dev: true optional: true /@parcel/watcher-darwin-x64@2.4.1: @@ -6640,7 +8831,6 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true - dev: true optional: true /@parcel/watcher-freebsd-x64@2.4.1: @@ -6649,7 +8839,6 @@ packages: cpu: [x64] os: [freebsd] requiresBuild: true - dev: true optional: true /@parcel/watcher-linux-arm-glibc@2.4.1: @@ -6658,7 +8847,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: true optional: true /@parcel/watcher-linux-arm64-glibc@2.4.1: @@ -6667,7 +8855,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: true optional: true /@parcel/watcher-linux-arm64-musl@2.4.1: @@ -6676,7 +8863,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: true optional: true /@parcel/watcher-linux-x64-glibc@2.4.1: @@ -6685,7 +8871,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: true optional: true /@parcel/watcher-linux-x64-musl@2.4.1: @@ -6694,7 +8879,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: true optional: true /@parcel/watcher-wasm@2.4.1: @@ -6703,6 +8887,7 @@ packages: dependencies: is-glob: 4.0.3 micromatch: 4.0.5 + napi-wasm: 1.1.0 dev: true bundledDependencies: - napi-wasm @@ -6713,7 +8898,6 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true - dev: true optional: true /@parcel/watcher-win32-ia32@2.4.1: @@ -6722,7 +8906,6 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true - dev: true optional: true /@parcel/watcher-win32-x64@2.4.1: @@ -6731,7 +8914,6 @@ packages: cpu: [x64] os: [win32] requiresBuild: true - dev: true optional: true /@parcel/watcher@2.4.1: @@ -6755,7 +8937,6 @@ packages: '@parcel/watcher-win32-arm64': 2.4.1 '@parcel/watcher-win32-ia32': 2.4.1 '@parcel/watcher-win32-x64': 2.4.1 - dev: true /@peculiar/asn1-schema@2.3.8: resolution: {integrity: sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==} @@ -6797,6 +8978,17 @@ packages: resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} dev: true + /@prisma/client@5.11.0: + resolution: {integrity: sha512-SWshvS5FDXvgJKM/a0y9nDC1rqd7KG0Q6ZVzd+U7ZXK5soe73DJxJJgbNBt2GNXOa+ysWB4suTpdK5zfFPhwiw==} + engines: {node: '>=16.13'} + requiresBuild: true + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + dev: false + /@probe.gl/env@3.6.0: resolution: {integrity: sha512-4tTZYUg/8BICC3Yyb9rOeoKeijKbZHRXBEKObrfPmX4sQmYB15ZOUpoVBhAyJkOYVAM8EkPci6Uw5dLCwx2BEQ==} dependencies: @@ -9170,6 +11362,285 @@ packages: - immer dev: false + /@redwoodjs/api@8.0.0-canary.542: + resolution: {integrity: sha512-6wo2h9QZ0zxwbYFJOWUDX8ehxPkbFx1ofpNanVPCMbnM7exjGDZmNY2rl1GDMY3I5ALLADJ04QsJB5fnKMiVsQ==} + hasBin: true + peerDependencies: + memjs: 1.3.2 + redis: 4.6.7 + peerDependenciesMeta: + memjs: + optional: true + redis: + optional: true + dependencies: + '@babel/runtime-corejs3': 7.24.1 + '@prisma/client': 5.11.0 + '@whatwg-node/fetch': 0.9.17 + core-js: 3.36.1 + humanize-string: 2.1.0 + jsonwebtoken: 9.0.2 + pascalcase: 1.0.0 + pino: 8.19.0 + title-case: 3.0.3 + transitivePeerDependencies: + - prisma + dev: false + + /@redwoodjs/auth@8.0.0-canary.542: + resolution: {integrity: sha512-Rx5vPPfCw6Xha6dMYHd6hEYG67RdcozkS5bSmYKw9DomFg1kvrS/a3NEsRmVYOPRV8wnCqG9bTZ7FjSrzOmUAA==} + dependencies: + core-js: 3.36.1 + react: 19.0.0-canary-cb151849e1-20240424 + dev: false + + /@redwoodjs/babel-config@8.0.0-canary.542(graphql-tag@2.12.6): + resolution: {integrity: sha512-OqVcKoGS1bBg01xH5QkSYcVu8lfjOaibosECLp1AP9EMPXPxz5m+mbVM4cToY4fKFJFU49dna0wfajWr8gAYGA==} + dependencies: + '@babel/core': 7.24.5 + '@babel/parser': 7.24.5 + '@babel/plugin-transform-class-properties': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-private-methods': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-private-property-in-object': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.5) + '@babel/plugin-transform-runtime': 7.24.3(@babel/core@7.24.5) + '@babel/preset-env': 7.24.5(@babel/core@7.24.5) + '@babel/preset-react': 7.24.1(@babel/core@7.24.5) + '@babel/preset-typescript': 7.24.1(@babel/core@7.24.5) + '@babel/register': 7.23.7(@babel/core@7.24.5) + '@babel/runtime-corejs3': 7.24.1 + '@babel/traverse': 7.24.5 + '@redwoodjs/project-config': 8.0.0-canary.542 + babel-plugin-auto-import: 1.1.0 + babel-plugin-graphql-tag: 3.3.0(@babel/core@7.24.5)(graphql-tag@2.12.6) + babel-plugin-module-resolver: 5.0.0 + core-js: 3.36.1 + fast-glob: 3.3.2 + graphql: 16.8.1 + typescript: 5.4.5 + transitivePeerDependencies: + - graphql-tag + - supports-color + dev: false + + /@redwoodjs/context@8.0.0-canary.542: + resolution: {integrity: sha512-kNx2gPOZ0xfgAI6vt0+fUKuY2XS6L+PzhdC53BjxVxOkweH7dgCw+XUKsHZzRinh77rHkfnnDkB8dLUlCuzWsg==} + dev: false + + /@redwoodjs/graphql-server@8.0.0-canary.542: + resolution: {integrity: sha512-d0E6g7IC5zcSAwmj3VN8hOCzn52G3IX2V01+0Rdw0wHMmSZaLXCUC3ARGmbYwPtXGFO7uBNv0Uh1ssRFyjPBPg==} + dependencies: + '@babel/runtime-corejs3': 7.24.1 + '@envelop/core': 5.0.0 + '@envelop/depth-limit': 4.0.0(@envelop/core@5.0.0)(graphql@16.8.1) + '@envelop/disable-introspection': 6.0.0(@envelop/core@5.0.0)(graphql@16.8.1) + '@envelop/filter-operation-type': 6.0.0(@envelop/core@5.0.0)(graphql@16.8.1) + '@envelop/on-resolve': 4.1.0(@envelop/core@5.0.0)(graphql@16.8.1) + '@escape.tech/graphql-armor': 2.3.1(@envelop/core@5.0.0) + '@graphql-tools/merge': 9.0.3(graphql@16.8.1) + '@graphql-tools/schema': 10.0.3(graphql@16.8.1) + '@graphql-tools/utils': 10.1.2(graphql@16.8.1) + '@graphql-yoga/plugin-persisted-operations': 3.2.0(@graphql-tools/utils@10.1.2)(graphql-yoga@5.2.0)(graphql@16.8.1) + '@opentelemetry/api': 1.4.1 + '@redwoodjs/api': 8.0.0-canary.542 + '@redwoodjs/context': 8.0.0-canary.542 + core-js: 3.36.1 + graphql: 16.8.1 + graphql-scalars: 1.23.0(graphql@16.8.1) + graphql-tag: 2.12.6(graphql@16.8.1) + graphql-yoga: 5.2.0(graphql@16.8.1) + lodash: 4.17.21 + uuid: 9.0.1 + transitivePeerDependencies: + - '@apollo/server' + - '@escape.tech/graphql-armor-types' + - memjs + - prisma + - redis + dev: false + + /@redwoodjs/internal@8.0.0-canary.542(@swc/core@1.4.11)(@types/node@20.12.7)(graphql-tag@2.12.6)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): + resolution: {integrity: sha512-wBHkWTf5mf1wt44FkZQLd+nLlT4Oo5dZat8IxePCwuW913+ac5kEgby+5CWpS7ye98LzuOk4l7FEvqp8uI6Cgg==} + hasBin: true + dependencies: + '@babel/core': 7.24.5 + '@babel/parser': 7.24.5 + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.5) + '@babel/plugin-transform-typescript': 7.24.5(@babel/core@7.24.5) + '@babel/runtime-corejs3': 7.24.1 + '@babel/traverse': 7.24.5 + '@graphql-codegen/add': 4.0.1(graphql@16.8.1) + '@graphql-codegen/cli': 3.3.1(@babel/core@7.24.5)(@types/node@20.12.7)(graphql@16.8.1) + '@graphql-codegen/client-preset': 4.2.5(graphql@16.8.1) + '@graphql-codegen/core': 3.1.0(graphql@16.8.1) + '@graphql-codegen/fragment-matcher': 5.0.2(graphql@16.8.1) + '@graphql-codegen/schema-ast': 3.0.1(graphql@16.8.1) + '@graphql-codegen/typed-document-node': 5.0.6(graphql@16.8.1) + '@graphql-codegen/typescript': 3.0.4(graphql@16.8.1) + '@graphql-codegen/typescript-operations': 3.0.4(graphql@16.8.1) + '@graphql-codegen/typescript-react-apollo': 3.3.7(graphql-tag@2.12.6)(graphql@16.8.1) + '@graphql-codegen/typescript-resolvers': 3.2.1(graphql@16.8.1) + '@graphql-tools/documents': 1.0.0(graphql@16.8.1) + '@redwoodjs/babel-config': 8.0.0-canary.542(graphql-tag@2.12.6) + '@redwoodjs/graphql-server': 8.0.0-canary.542 + '@redwoodjs/project-config': 8.0.0-canary.542 + '@redwoodjs/router': 8.0.0-canary.542(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) + '@sdl-codegen/node': 0.0.13(graphql@16.8.1)(prettier@3.2.5)(typescript@5.4.5) + chalk: 4.1.2 + core-js: 3.36.1 + deepmerge: 4.3.1 + esbuild: 0.20.2 + fast-glob: 3.3.2 + fs-extra: 11.2.0 + graphql: 16.8.1 + kill-port: 1.6.1 + prettier: 3.2.5 + rimraf: 5.0.5 + source-map: 0.7.4 + string-env-interpolation: 1.0.1 + systeminformation: 5.22.6 + terminal-link: 2.1.1 + ts-node: 10.9.2(@swc/core@1.4.11)(@types/node@20.12.7)(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - '@apollo/server' + - '@escape.tech/graphql-armor-types' + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - bufferutil + - cosmiconfig-toml-loader + - encoding + - enquirer + - graphql-tag + - memjs + - prisma + - react + - react-dom + - redis + - supports-color + - utf-8-validate + dev: false + + /@redwoodjs/project-config@8.0.0-canary.542: + resolution: {integrity: sha512-veuppVknJvxwnySlIP6fnCJ9vMoU6FVuI3t6E9a+aV7NaSb/C1UHNDRQVH6X2LIecOIlxqsoD+31nUCXTdosHQ==} + dependencies: + '@iarna/toml': 2.2.5 + deepmerge: 4.3.1 + fast-glob: 3.3.2 + string-env-interpolation: 1.0.1 + dev: false + + /@redwoodjs/router@8.0.0-canary.542(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): + resolution: {integrity: sha512-3/9mlFB9uyB1tx70ey1bMvLTrp/VwFI9EF9SbNSK01zqJlGUstRM9KmBSMDFbPQZyoBrSNkQQuMpY2CXVXK/TQ==} + peerDependencies: + react: 19.0.0-canary-cb151849e1-20240424 + react-dom: 19.0.0-canary-cb151849e1-20240424 + dependencies: + '@babel/runtime-corejs3': 7.24.1 + '@redwoodjs/auth': 8.0.0-canary.542 + core-js: 3.36.1 + react: 19.0.0-canary-cb151849e1-20240424 + react-dom: 18.3.1(react@18.3.1) + dev: false + + /@redwoodjs/vite@8.0.0-canary.542(@types/node@20.12.7)(csstype@3.1.3)(graphql-tag@2.12.6)(react-dom@18.3.1)(webpack@5.91.0): + resolution: {integrity: sha512-oOp71H8eXcWuWGaWIDY7k8XsRix3JSv0cFwsY3T2l2A7MDmp/mFYgLtsLrFXugvMCZiQnYC9XxP0l3dSBUhDWQ==} + hasBin: true + dependencies: + '@babel/generator': 7.24.1 + '@babel/parser': 7.24.5 + '@babel/traverse': 7.24.5 + '@redwoodjs/babel-config': 8.0.0-canary.542(graphql-tag@2.12.6) + '@redwoodjs/internal': 8.0.0-canary.542(@swc/core@1.4.11)(@types/node@20.12.7)(graphql-tag@2.12.6)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) + '@redwoodjs/project-config': 8.0.0-canary.542 + '@redwoodjs/web': 8.0.0-canary.542(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) + '@swc/core': 1.4.11 + '@vitejs/plugin-react': 4.2.1(vite@5.2.8) + '@whatwg-node/fetch': 0.9.17 + '@whatwg-node/server': 0.9.32 + acorn-loose: 8.4.0 + buffer: 6.0.3 + busboy: 1.6.0 + cookie: 0.6.0 + core-js: 3.36.1 + dotenv-defaults: 5.0.2 + express: 4.19.2 + find-my-way: 8.1.0 + http-proxy-middleware: 2.0.6 + isbot: 3.8.0 + react: 19.0.0-canary-cb151849e1-20240424 + react-server-dom-webpack: 19.0.0-canary-cb151849e1-20240424(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424)(webpack@5.91.0) + vite: 5.2.8(@types/node@20.12.7) + vite-plugin-cjs-interop: 2.1.0 + yargs-parser: 21.1.1 + transitivePeerDependencies: + - '@apollo/server' + - '@escape.tech/graphql-armor-types' + - '@swc/helpers' + - '@swc/wasm' + - '@types/express' + - '@types/node' + - '@types/react' + - bufferutil + - cosmiconfig-toml-loader + - csstype + - debug + - encoding + - enquirer + - graphql-tag + - graphql-ws + - less + - lightningcss + - memjs + - prisma + - react-dom + - redis + - sass + - stylus + - subscriptions-transport-ws + - sugarss + - supports-color + - terser + - utf-8-validate + - webpack + dev: false + + /@redwoodjs/web@8.0.0-canary.542(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): + resolution: {integrity: sha512-0IjImjt0TQgzL9rsOiLwprW3EuX18qFFI/bTlbsGjwVavfWEt3mSt3yKtkmZkDEyXAbWaEJ4iH6yRHYx/qxU2A==} + hasBin: true + peerDependencies: + react: 19.0.0-canary-cb151849e1-20240424 + react-dom: 19.0.0-canary-cb151849e1-20240424 + dependencies: + '@apollo/client': 3.9.9(graphql@16.8.1)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) + '@babel/runtime-corejs3': 7.24.1 + '@redwoodjs/auth': 8.0.0-canary.542 + core-js: 3.36.1 + graphql: 16.8.1 + graphql-sse: 2.5.2(graphql@16.8.1) + graphql-tag: 2.12.6(graphql@16.8.1) + react: 19.0.0-canary-cb151849e1-20240424 + react-dom: 18.3.1(react@18.3.1) + react-helmet-async: 2.0.4(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) + react-hot-toast: 2.4.1(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) + stacktracey: 2.1.8 + ts-toolbelt: 9.6.0 + transitivePeerDependencies: + - '@types/react' + - csstype + - graphql-ws + - subscriptions-transport-ws + dev: false + + /@repeaterjs/repeater@3.0.4: + resolution: {integrity: sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA==} + dev: false + + /@repeaterjs/repeater@3.0.5: + resolution: {integrity: sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA==} + dev: false + /@resvg/resvg-wasm@2.4.0: resolution: {integrity: sha512-C7c51Nn4yTxXFKvgh2txJFNweaVcfUPQxwEUFw4aWsCmfiBDJsTSwviIF8EcwjQ6k8bPyMWCl1vw4BdxE569Cg==} engines: {node: '>= 10'} @@ -9399,7 +11870,6 @@ packages: cpu: [arm] os: [android] requiresBuild: true - dev: true optional: true /@rollup/rollup-android-arm64@4.17.2: @@ -9407,7 +11877,6 @@ packages: cpu: [arm64] os: [android] requiresBuild: true - dev: true optional: true /@rollup/rollup-darwin-arm64@4.17.2: @@ -9415,7 +11884,6 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true - dev: true optional: true /@rollup/rollup-darwin-x64@4.17.2: @@ -9423,7 +11891,6 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true - dev: true optional: true /@rollup/rollup-linux-arm-gnueabihf@4.17.2: @@ -9431,7 +11898,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: true optional: true /@rollup/rollup-linux-arm-musleabihf@4.17.2: @@ -9439,7 +11905,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: true optional: true /@rollup/rollup-linux-arm64-gnu@4.17.2: @@ -9447,7 +11912,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: true optional: true /@rollup/rollup-linux-arm64-musl@4.17.2: @@ -9455,7 +11919,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: true optional: true /@rollup/rollup-linux-powerpc64le-gnu@4.17.2: @@ -9463,7 +11926,6 @@ packages: cpu: [ppc64] os: [linux] requiresBuild: true - dev: true optional: true /@rollup/rollup-linux-riscv64-gnu@4.17.2: @@ -9471,7 +11933,6 @@ packages: cpu: [riscv64] os: [linux] requiresBuild: true - dev: true optional: true /@rollup/rollup-linux-s390x-gnu@4.17.2: @@ -9479,7 +11940,6 @@ packages: cpu: [s390x] os: [linux] requiresBuild: true - dev: true optional: true /@rollup/rollup-linux-x64-gnu@4.17.2: @@ -9487,7 +11947,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: true optional: true /@rollup/rollup-linux-x64-musl@4.17.2: @@ -9495,7 +11954,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: true optional: true /@rollup/rollup-win32-arm64-msvc@4.17.2: @@ -9503,7 +11961,6 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true - dev: true optional: true /@rollup/rollup-win32-ia32-msvc@4.17.2: @@ -9511,7 +11968,6 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true - dev: true optional: true /@rollup/rollup-win32-x64-msvc@4.17.2: @@ -9519,9 +11975,26 @@ packages: cpu: [x64] os: [win32] requiresBuild: true - dev: true optional: true + /@sdl-codegen/node@0.0.13(graphql@16.8.1)(prettier@3.2.5)(typescript@5.4.5): + resolution: {integrity: sha512-QBNzDFzsAb1xvJgEoT2Qc/KIE/H0LlwspiOTnlXd7oyWNgqGlPtAwBIlZdDUjGCwuqLJOAE0U/9/bsgbfy+wUg==} + engines: {node: '>=16'} + peerDependencies: + graphql: '*' + prettier: ^2 + typescript: '*' + peerDependenciesMeta: + prettier: + optional: true + dependencies: + '@mrleebo/prisma-ast': 0.5.2 + graphql: 16.8.1 + prettier: 3.2.5 + ts-morph: 18.0.0 + typescript: 5.4.5 + dev: false + /@selderee/plugin-htmlparser2@0.11.0: resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} dependencies: @@ -9676,6 +12149,15 @@ packages: dev: false optional: true + /@swc/core-darwin-arm64@1.4.11: + resolution: {integrity: sha512-C1j1Qp/IHSelVWdEnT7f0iONWxQz6FAqzjCF2iaL+0vFg4V5f2nlgrueY8vj5pNNzSGhrAlxsMxEIp4dj1MXkg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + /@swc/core-darwin-x64@1.3.101: resolution: {integrity: sha512-B085j8XOx73Fg15KsHvzYWG262bRweGr3JooO1aW5ec5pYbz5Ew9VS5JKYS03w2UBSxf2maWdbPz2UFAxg0whw==} engines: {node: '>=10'} @@ -9685,17 +12167,62 @@ packages: dev: false optional: true + /@swc/core-darwin-x64@1.4.11: + resolution: {integrity: sha512-0TTy3Ni8ncgaMCchSQ7FK8ZXQLlamy0FXmGWbR58c+pVZWYZltYPTmheJUvVcR0H2+gPAymRKyfC0iLszDALjg==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + /@swc/core-linux-arm-gnueabihf@1.3.101: resolution: {integrity: sha512-9xLKRb6zSzRGPqdz52Hy5GuB1lSjmLqa0lST6MTFads3apmx4Vgs8Y5NuGhx/h2I8QM4jXdLbpqQlifpzTlSSw==} engines: {node: '>=10'} - cpu: [arm] + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@swc/core-linux-arm-gnueabihf@1.4.11: + resolution: {integrity: sha512-XJLB71uw0rog4DjYAPxFGAuGCBQpgJDlPZZK6MTmZOvI/1t0+DelJ24IjHIxk500YYM26Yv47xPabqFPD7I2zQ==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@swc/core-linux-arm64-gnu@1.3.101: + resolution: {integrity: sha512-oE+r1lo7g/vs96Weh2R5l971dt+ZLuhaUX+n3BfDdPxNHfObXgKMjO7E+QS5RbGjv/AwiPCxQmbdCp/xN5ICJA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@swc/core-linux-arm64-gnu@1.4.11: + resolution: {integrity: sha512-vYQwzJvm/iu052d5Iw27UFALIN5xSrGkPZXxLNMHPySVko2QMNNBv35HLatkEQHbQ3X+VKSW9J9SkdtAvAVRAQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@swc/core-linux-arm64-musl@1.3.101: + resolution: {integrity: sha512-OGjYG3H4BMOTnJWJyBIovCez6KiHF30zMIu4+lGJTCrxRI2fAjGLml3PEXj8tC3FMcud7U2WUn6TdG0/te2k6g==} + engines: {node: '>=10'} + cpu: [arm64] os: [linux] requiresBuild: true dev: false optional: true - /@swc/core-linux-arm64-gnu@1.3.101: - resolution: {integrity: sha512-oE+r1lo7g/vs96Weh2R5l971dt+ZLuhaUX+n3BfDdPxNHfObXgKMjO7E+QS5RbGjv/AwiPCxQmbdCp/xN5ICJA==} + /@swc/core-linux-arm64-musl@1.4.11: + resolution: {integrity: sha512-eV+KduiRYUFjPsvbZuJ9aknQH9Tj0U2/G9oIZSzLx/18WsYi+upzHbgxmIIHJ2VJgfd7nN40RI/hMtxNsUzR/g==} engines: {node: '>=10'} cpu: [arm64] os: [linux] @@ -9703,17 +12230,17 @@ packages: dev: false optional: true - /@swc/core-linux-arm64-musl@1.3.101: - resolution: {integrity: sha512-OGjYG3H4BMOTnJWJyBIovCez6KiHF30zMIu4+lGJTCrxRI2fAjGLml3PEXj8tC3FMcud7U2WUn6TdG0/te2k6g==} + /@swc/core-linux-x64-gnu@1.3.101: + resolution: {integrity: sha512-/kBMcoF12PRO/lwa8Z7w4YyiKDcXQEiLvM+S3G9EvkoKYGgkkz4Q6PSNhF5rwg/E3+Hq5/9D2R+6nrkF287ihg==} engines: {node: '>=10'} - cpu: [arm64] + cpu: [x64] os: [linux] requiresBuild: true dev: false optional: true - /@swc/core-linux-x64-gnu@1.3.101: - resolution: {integrity: sha512-/kBMcoF12PRO/lwa8Z7w4YyiKDcXQEiLvM+S3G9EvkoKYGgkkz4Q6PSNhF5rwg/E3+Hq5/9D2R+6nrkF287ihg==} + /@swc/core-linux-x64-gnu@1.4.11: + resolution: {integrity: sha512-WA1iGXZ2HpqM1OR9VCQZJ8sQ1KP2or9O4bO8vWZo6HZJIeoQSo7aa9waaCLRpkZvkng1ct/TF/l6ymqSNFXIzQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] @@ -9730,6 +12257,15 @@ packages: dev: false optional: true + /@swc/core-linux-x64-musl@1.4.11: + resolution: {integrity: sha512-UkVJToKf0owwQYRnGvjHAeYVDfeimCEcx0VQSbJoN7Iy0ckRZi7YPlmWJU31xtKvikE2bQWCOVe0qbSDqqcWXA==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@swc/core-win32-arm64-msvc@1.3.101: resolution: {integrity: sha512-9Wn8TTLWwJKw63K/S+jjrZb9yoJfJwCE2RV5vPCCWmlMf3U1AXj5XuWOLUX+Rp2sGKau7wZKsvywhheWm+qndQ==} engines: {node: '>=10'} @@ -9739,6 +12275,15 @@ packages: dev: false optional: true + /@swc/core-win32-arm64-msvc@1.4.11: + resolution: {integrity: sha512-35khwkyly7lF5NDSyvIrukBMzxPorgc5iTSDfVO/LvnmN5+fm4lTlrDr4tUfTdOhv3Emy7CsKlsNAeFRJ+Pm+w==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@swc/core-win32-ia32-msvc@1.3.101: resolution: {integrity: sha512-onO5KvICRVlu2xmr4//V2je9O2XgS1SGKpbX206KmmjcJhXN5EYLSxW9qgg+kgV5mip+sKTHTAu7IkzkAtElYA==} engines: {node: '>=10'} @@ -9748,6 +12293,15 @@ packages: dev: false optional: true + /@swc/core-win32-ia32-msvc@1.4.11: + resolution: {integrity: sha512-Wx8/6f0ufgQF2pbVPsJ2dAmFLwIOW+xBE5fxnb7VnEbGkTgP1qMDWiiAtD9rtvDSuODG3i1AEmAak/2HAc6i6A==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@swc/core-win32-x64-msvc@1.3.101: resolution: {integrity: sha512-T3GeJtNQV00YmiVw/88/nxJ/H43CJvFnpvBHCVn17xbahiVUOPOduh3rc9LgAkKiNt/aV8vU3OJR+6PhfMR7UQ==} engines: {node: '>=10'} @@ -9757,6 +12311,15 @@ packages: dev: false optional: true + /@swc/core-win32-x64-msvc@1.4.11: + resolution: {integrity: sha512-0xRFW6K9UZQH2NVC/0pVB0GJXS45lY24f+6XaPBF1YnMHd8A8GoHl7ugyM5yNUTe2AKhSgk5fJV00EJt/XBtdQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@swc/core@1.3.101: resolution: {integrity: sha512-w5aQ9qYsd/IYmXADAnkXPGDMTqkQalIi+kfFf/MHRKTpaOL7DHjMXwPp/n8hJ0qNjRvchzmPtOqtPBiER50d8A==} engines: {node: '>=10'} @@ -9782,6 +12345,31 @@ packages: '@swc/core-win32-x64-msvc': 1.3.101 dev: false + /@swc/core@1.4.11: + resolution: {integrity: sha512-WKEakMZxkVwRdgMN4AMJ9K5nysY8g8npgQPczmjBeNK5In7QEAZAJwnyccrWwJZU0XjVeHn2uj+XbOKdDW17rg==} + engines: {node: '>=10'} + requiresBuild: true + peerDependencies: + '@swc/helpers': ^0.5.0 + peerDependenciesMeta: + '@swc/helpers': + optional: true + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.6 + optionalDependencies: + '@swc/core-darwin-arm64': 1.4.11 + '@swc/core-darwin-x64': 1.4.11 + '@swc/core-linux-arm-gnueabihf': 1.4.11 + '@swc/core-linux-arm64-gnu': 1.4.11 + '@swc/core-linux-arm64-musl': 1.4.11 + '@swc/core-linux-x64-gnu': 1.4.11 + '@swc/core-linux-x64-musl': 1.4.11 + '@swc/core-win32-arm64-msvc': 1.4.11 + '@swc/core-win32-ia32-msvc': 1.4.11 + '@swc/core-win32-x64-msvc': 1.4.11 + dev: false + /@swc/counter@0.1.3: resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} dev: false @@ -10072,6 +12660,31 @@ packages: engines: {node: '>=10.13.0'} dev: true + /@ts-morph/common@0.19.0: + resolution: {integrity: sha512-Unz/WHmd4pGax91rdIKWi51wnVUW11QttMEPpBiBgIewnc9UQIX7UDLxr5vRlqeByXCwhkF6VabSsI0raWcyAQ==} + dependencies: + fast-glob: 3.3.2 + minimatch: 7.4.6 + mkdirp: 2.1.6 + path-browserify: 1.0.1 + dev: false + + /@tsconfig/node10@1.0.11: + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + dev: false + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: false + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: false + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + dev: false + /@tufjs/canonical-json@2.0.0: resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==} engines: {node: ^16.14.0 || >=18.0.0} @@ -10090,6 +12703,35 @@ packages: dependencies: '@types/estree': 1.0.5 + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.5 + dev: false + + /@types/babel__generator@7.6.8: + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + dependencies: + '@babel/types': 7.24.5 + dev: false + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 + dev: false + + /@types/babel__traverse@7.20.5: + resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} + dependencies: + '@babel/types': 7.24.5 + dev: false + /@types/body-parser@1.19.5: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: @@ -10439,7 +13081,6 @@ packages: resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} dependencies: '@types/node': 20.12.7 - dev: true /@types/is-stream@1.1.0: resolution: {integrity: sha512-jkZatu4QVbR60mpIzjINmtS1ZF4a/FqdTUTBeQDVOQ2PYyidtwFKr0B5G6ERukKwliq+7mIXvxyppwzG5EgRYg==} @@ -10453,6 +13094,10 @@ packages: /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + /@types/json-stable-stringify@1.0.36: + resolution: {integrity: sha512-b7bq23s4fgBB76n34m2b3RBf6M369B0Z9uRR8aHTMd8kZISRkmDEpPD8hhpYvDFzr3bJCPES96cm3Q6qRNDbQw==} + dev: false + /@types/katex@0.14.0: resolution: {integrity: sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA==} dev: true @@ -10535,6 +13180,10 @@ packages: resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} dev: true + /@types/parse-json@4.0.2: + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + dev: false + /@types/parse5@6.0.3: resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} @@ -10627,6 +13276,12 @@ packages: /@types/wrap-ansi@3.0.0: resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + /@types/ws@8.5.10: + resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + dependencies: + '@types/node': 20.12.7 + dev: false + /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: false @@ -11093,6 +13748,22 @@ packages: internmap: 2.0.3 dev: false + /@vitejs/plugin-react@4.2.1(vite@5.2.8): + resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/plugin-transform-react-jsx-self': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.5) + '@types/babel__core': 7.20.5 + react-refresh: 0.14.2 + vite: 5.2.8(@types/node@20.12.7) + transitivePeerDependencies: + - supports-color + dev: false + /@vitejs/plugin-vue-jsx@3.1.0(vite@5.2.10)(vue@3.4.23): resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==} engines: {node: ^14.18.0 || >=16.0.0} @@ -11654,6 +14325,105 @@ packages: resolution: {integrity: sha512-cvvCMSZBT4VsRNtt0lI6XQqvOIIWw6+NRUtnPUMDVDgsI4pCZColz3qzF5QcP9wIYOHEc3jssIBse8UWONKhlQ==} dev: false + /@whatwg-node/events@0.0.3: + resolution: {integrity: sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA==} + dev: false + + /@whatwg-node/events@0.1.1: + resolution: {integrity: sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==} + engines: {node: '>=16.0.0'} + dev: false + + /@whatwg-node/fetch@0.8.8: + resolution: {integrity: sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg==} + dependencies: + '@peculiar/webcrypto': 1.4.1 + '@whatwg-node/node-fetch': 0.3.6 + busboy: 1.6.0 + urlpattern-polyfill: 8.0.2 + web-streams-polyfill: 3.3.3 + dev: false + + /@whatwg-node/fetch@0.9.17: + resolution: {integrity: sha512-TDYP3CpCrxwxpiNY0UMNf096H5Ihf67BK1iKGegQl5u9SlpEDYrvnV71gWBGJm+Xm31qOy8ATgma9rm8Pe7/5Q==} + engines: {node: '>=16.0.0'} + dependencies: + '@whatwg-node/node-fetch': 0.5.11 + urlpattern-polyfill: 10.0.0 + dev: false + + /@whatwg-node/node-fetch@0.3.6: + resolution: {integrity: sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA==} + dependencies: + '@whatwg-node/events': 0.0.3 + busboy: 1.6.0 + fast-querystring: 1.1.2 + fast-url-parser: 1.1.3 + tslib: 2.6.2 + dev: false + + /@whatwg-node/node-fetch@0.5.11: + resolution: {integrity: sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==} + engines: {node: '>=16.0.0'} + dependencies: + '@kamilkisiela/fast-url-parser': 1.1.4 + '@whatwg-node/events': 0.1.1 + busboy: 1.6.0 + fast-querystring: 1.1.2 + tslib: 2.6.2 + dev: false + + /@whatwg-node/server@0.9.32: + resolution: {integrity: sha512-PRTRE8ZhObwYx9yRoUdxYkrhCoDk2vyDA5BtaG+NAqEmU1wwbwlXUpaeRRrPuGaM7ScbIkueU25A0GJIRQzccw==} + engines: {node: '>=16.0.0'} + dependencies: + '@whatwg-node/fetch': 0.9.17 + tslib: 2.6.2 + dev: false + + /@whatwg-node/server@0.9.34: + resolution: {integrity: sha512-1sHRjqUtZIyTR2m2dS/dJpzS5OcNDpPuUSVDa2PoEgzYVKr4GsqJaYtRaEXXFohvvyh6PkouYCc1rE7jMDWVCA==} + engines: {node: '>=16.0.0'} + dependencies: + '@whatwg-node/fetch': 0.9.17 + tslib: 2.6.2 + dev: false + + /@wry/caches@1.0.1: + resolution: {integrity: sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==} + engines: {node: '>=8'} + dependencies: + tslib: 2.6.2 + dev: false + + /@wry/context@0.7.4: + resolution: {integrity: sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==} + engines: {node: '>=8'} + dependencies: + tslib: 2.6.2 + dev: false + + /@wry/equality@0.5.7: + resolution: {integrity: sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==} + engines: {node: '>=8'} + dependencies: + tslib: 2.6.2 + dev: false + + /@wry/trie@0.4.3: + resolution: {integrity: sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==} + engines: {node: '>=8'} + dependencies: + tslib: 2.6.2 + dev: false + + /@wry/trie@0.5.0: + resolution: {integrity: sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==} + engines: {node: '>=8'} + dependencies: + tslib: 2.6.2 + dev: false + /@xtuc/ieee754@1.2.0: resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} dev: false @@ -11675,7 +14445,6 @@ packages: engines: {node: '>=6.5'} dependencies: event-target-shim: 5.0.1 - dev: true /accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} @@ -11707,10 +14476,16 @@ packages: dependencies: acorn: 8.11.3 + /acorn-loose@8.4.0: + resolution: {integrity: sha512-M0EUka6rb+QC4l9Z3T0nJEzNOO7JcoJlYMrBlyBCiFSXRyxjLKayd4TbQs2FDRWQU1h9FR7QVNHt+PEaoNL5rQ==} + engines: {node: '>=0.4.0'} + dependencies: + acorn: 8.11.3 + dev: false + /acorn-walk@8.3.2: resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} engines: {node: '>=0.4.0'} - dev: true /acorn@8.11.3: resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} @@ -11738,7 +14513,6 @@ packages: debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true /aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} @@ -11746,7 +14520,6 @@ packages: dependencies: clean-stack: 2.2.0 indent-string: 4.0.0 - dev: true /aggregate-error@4.0.1: resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} @@ -11921,6 +14694,10 @@ packages: readable-stream: 3.6.2 dev: true + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: false + /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -11951,7 +14728,6 @@ packages: /array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: true /array-iterate@2.0.1: resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} @@ -11971,7 +14747,6 @@ packages: /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - dev: true /array.prototype.flat@1.3.2: resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} @@ -11999,13 +14774,15 @@ packages: /arrify@1.0.1: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} engines: {node: '>=0.10.0'} - dev: true /as-table@1.0.55: resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} dependencies: printable-characters: 1.0.42 - dev: true + + /asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + dev: false /asn1js@3.0.5: resolution: {integrity: sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==} @@ -12049,6 +14826,11 @@ packages: - rollup dev: true + /astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: false + /astring@1.8.6: resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==} hasBin: true @@ -12069,6 +14851,16 @@ packages: engines: {node: '>= 4.0.0'} dev: true + /atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + dev: false + + /auto-bind@4.0.0: + resolution: {integrity: sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==} + engines: {node: '>=8'} + dev: false + /autoprefixer@10.4.14(postcss@8.4.35): resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==} engines: {node: ^10 || ^12 || >=14} @@ -12119,6 +14911,130 @@ packages: resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} dev: true + /babel-literal-to-ast@2.1.0(@babel/core@7.24.5): + resolution: {integrity: sha512-CxfpQ0ysQ0bZOhlaPgcWjl79Em16Rhqc6++UAFn0A3duiXmuyhhj8yyl9PYbj0I0CyjrHovdDbp2QEKT7uIMxw==} + peerDependencies: + '@babel/core': ^7.1.2 + dependencies: + '@babel/core': 7.24.5 + '@babel/parser': 7.24.5 + '@babel/traverse': 7.24.5 + '@babel/types': 7.24.5 + transitivePeerDependencies: + - supports-color + dev: false + + /babel-plugin-auto-import@1.1.0: + resolution: {integrity: sha512-mHtA3i1BYyWLHKc4v+NLS07VSlXGLcKIGcUmV2Xrasbox0bRV/xhe5W36Ki21GJfOZHG/eeAiwxe4tbBNbDXlA==} + dependencies: + '@babel/core': 7.24.5 + logical-not: 1.0.9 + transitivePeerDependencies: + - supports-color + dev: false + + /babel-plugin-graphql-tag@3.3.0(@babel/core@7.24.5)(graphql-tag@2.12.6): + resolution: {integrity: sha512-27qfJhFJ2jQg+ktcC3cdppE2RrXZ5uiDz+39YC5lhkmftWPuJW8ET9Ehskwv7ujScZ1jSKhs5/JZKlESCkwIBg==} + peerDependencies: + '@babel/core': ^7.0.0 + graphql-tag: ^2.10.1 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + '@babel/parser': 7.24.5 + babel-literal-to-ast: 2.1.0(@babel/core@7.24.5) + debug: 4.3.4 + graphql-tag: 2.12.6(graphql@16.8.1) + transitivePeerDependencies: + - supports-color + dev: false + + /babel-plugin-module-resolver@5.0.0: + resolution: {integrity: sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q==} + engines: {node: '>= 16'} + dependencies: + find-babel-config: 2.1.1 + glob: 8.1.0 + pkg-up: 3.1.0 + reselect: 4.1.8 + resolve: 1.22.8 + dev: false + + /babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.24.5): + resolution: {integrity: sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/compat-data': 7.24.4 + '@babel/core': 7.24.5 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.5) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /babel-plugin-polyfill-corejs3@0.10.4(@babel/core@7.24.5): + resolution: {integrity: sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.5) + core-js-compat: 3.37.0 + transitivePeerDependencies: + - supports-color + dev: false + + /babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.24.5): + resolution: {integrity: sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.5) + transitivePeerDependencies: + - supports-color + dev: false + + /babel-plugin-syntax-trailing-function-commas@7.0.0-beta.0: + resolution: {integrity: sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==} + dev: false + + /babel-preset-fbjs@3.4.0(@babel/core@7.24.5): + resolution: {integrity: sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.24.5) + '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.24.5) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.5) + '@babel/plugin-syntax-flow': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-transform-arrow-functions': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-block-scoped-functions': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-block-scoping': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-classes': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-computed-properties': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-destructuring': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-flow-strip-types': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-for-of': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-function-name': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-literals': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-member-expression-literals': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-object-super': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.24.5) + '@babel/plugin-transform-property-literals': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-react-display-name': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.5) + '@babel/plugin-transform-shorthand-properties': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-spread': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-transform-template-literals': 7.24.1(@babel/core@7.24.5) + babel-plugin-syntax-trailing-function-commas: 7.0.0-beta.0 + dev: false + /babel-walk@3.0.0: resolution: {integrity: sha512-fdRxJkQ9MUSEi4jH2DcV3FAPFktk0wefilxrwNyUuWpoWawQGN7G7cB+fOYTtFfI6XNkFgwqJ/D3G18BoJJ/jg==} engines: {node: '>= 10.0.0'} @@ -12228,7 +15144,6 @@ packages: unpipe: 1.0.0 transitivePeerDependencies: - supports-color - dev: true /boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -12267,11 +15182,21 @@ packages: node-releases: 2.0.14 update-browserslist-db: 1.0.13(browserslist@4.23.0) + /bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: false + /buffer-crc32@1.0.0: resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} engines: {node: '>=8.0.0'} dev: true + /buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + dev: false + /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -12286,7 +15211,6 @@ packages: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - dev: true /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} @@ -12335,7 +15259,6 @@ packages: /bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} - dev: true /c12@1.10.0: resolution: {integrity: sha512-0SsG7UDhoRWcuSvKWHaXmu5uNjDCDN3nkQLRL4Q42IlFy+ze58FcCoI3uPwINXinkz7ZinbhEgyzYFw9u9ZV8g==} @@ -12471,6 +15394,14 @@ packages: /caniuse-lite@1.0.30001614: resolution: {integrity: sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog==} + /capital-case@1.0.4: + resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.2 + upper-case-first: 2.0.2 + dev: false + /capnp-ts@0.7.0: resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==} dependencies: @@ -12534,6 +15465,53 @@ packages: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + /change-case-all@1.0.14: + resolution: {integrity: sha512-CWVm2uT7dmSHdO/z1CXT/n47mWonyypzBbuCy5tN7uMg22BsfkhwT6oHmFCAk+gL1LOOxhdbB9SZz3J1KTY3gA==} + dependencies: + change-case: 4.1.2 + is-lower-case: 2.0.2 + is-upper-case: 2.0.2 + lower-case: 2.0.2 + lower-case-first: 2.0.2 + sponge-case: 1.0.1 + swap-case: 2.0.2 + title-case: 3.0.3 + upper-case: 2.0.2 + upper-case-first: 2.0.2 + dev: false + + /change-case-all@1.0.15: + resolution: {integrity: sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==} + dependencies: + change-case: 4.1.2 + is-lower-case: 2.0.2 + is-upper-case: 2.0.2 + lower-case: 2.0.2 + lower-case-first: 2.0.2 + sponge-case: 1.0.1 + swap-case: 2.0.2 + title-case: 3.0.3 + upper-case: 2.0.2 + upper-case-first: 2.0.2 + dev: false + + /change-case@4.1.2: + resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==} + dependencies: + camel-case: 4.1.2 + capital-case: 1.0.4 + constant-case: 3.0.4 + dot-case: 3.0.4 + header-case: 2.0.4 + no-case: 3.0.4 + param-case: 3.0.4 + pascal-case: 3.1.2 + path-case: 3.0.4 + sentence-case: 3.0.4 + snake-case: 3.0.4 + tslib: 2.6.2 + dev: false + /character-entities-html4@2.1.0: resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} @@ -12548,7 +15526,6 @@ packages: /chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: true /check-error@1.0.3: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} @@ -12556,6 +15533,17 @@ packages: get-func-name: 2.0.2 dev: true + /chevrotain@10.5.0: + resolution: {integrity: sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==} + dependencies: + '@chevrotain/cst-dts-gen': 10.5.0 + '@chevrotain/gast': 10.5.0 + '@chevrotain/types': 10.5.0 + '@chevrotain/utils': 10.5.0 + lodash: 4.17.21 + regexp-to-ast: 0.5.0 + dev: false + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -12629,7 +15617,6 @@ packages: /clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} - dev: true /clean-stack@4.2.0: resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==} @@ -12670,6 +15657,14 @@ packages: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} + /cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + dev: false + /cli-truncate@3.1.0: resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -12689,7 +15684,6 @@ packages: /cli-width@3.0.0: resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} engines: {node: '>= 10'} - dev: true /cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} @@ -12729,7 +15723,6 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 6.2.0 - dev: true /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} @@ -12739,6 +15732,15 @@ packages: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + /clone-deep@4.0.1: + resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} + engines: {node: '>=6'} + dependencies: + is-plain-object: 2.0.4 + kind-of: 6.0.3 + shallow-clone: 3.0.1 + dev: false + /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} @@ -12795,6 +15797,10 @@ packages: - '@types/react-dom' dev: false + /code-block-writer@12.0.0: + resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==} + dev: false + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -12844,7 +15850,6 @@ packages: /colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - dev: true /combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} @@ -12926,9 +15931,13 @@ packages: - typescript dev: true + /common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + dev: false + /commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - dev: true /compose-function@3.0.3: resolution: {integrity: sha512-xzhzTJ5eC+gmIzvZq+C3kCJHsp9os6tJkrigDRZclyGtOKINbZtE8n1Tzmeh32jW+BUDPbvZpibwvJHBLGMVwg==} @@ -12968,17 +15977,23 @@ packages: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} dev: true + /constant-case@3.0.4: + resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.2 + upper-case: 2.0.2 + dev: false + /content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} dependencies: safe-buffer: 5.2.1 - dev: true /content-type@1.0.5: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - dev: true /contentlayer@0.3.4(esbuild@0.20.2): resolution: {integrity: sha512-FYDdTUFaN4yqep0waswrhcXjmMJnPD5iXDTtxcUCGdklfuIrXM2xLx51xl748cHmGA6IsC+27YZFxU6Ym13QIA==} @@ -13016,7 +16031,6 @@ packages: /cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: true /cookie@0.4.2: resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} @@ -13029,7 +16043,6 @@ packages: /cookie@0.6.0: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} - dev: true /copy-anything@3.0.5: resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} @@ -13037,6 +16050,22 @@ packages: dependencies: is-what: 4.1.16 + /core-js-compat@3.37.0: + resolution: {integrity: sha512-vYq4L+T8aS5UuFg4UwDhc7YNRWVeVZwltad9C/jV3R2LgVOpS9BDr7l/WL6BN0dbV3k1XejPTHqqEzJgsa0frA==} + dependencies: + browserslist: 4.23.0 + dev: false + + /core-js-pure@3.37.0: + resolution: {integrity: sha512-d3BrpyFr5eD4KcbRvQ3FTUx/KWmaDesr7+a3+1+P46IUnNoEt+oiLijPINZMEon7w9oGkIINWxrBAU9DEciwFQ==} + requiresBuild: true + dev: false + + /core-js@3.36.1: + resolution: {integrity: sha512-BTvUrwxVBezj5SZ3f10ImnX2oRByMxql3EimVqMysepbC9EeMUOpLwdy6Eoili2x6E4kf+ZUB5k/+Jv55alPfA==} + requiresBuild: true + dev: false + /core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -13062,6 +16091,27 @@ packages: dev: true optional: true + /cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: false + + /cosmiconfig@8.0.0: + resolution: {integrity: sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ==} + engines: {node: '>=14'} + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + dev: false + /cosmiconfig@9.0.0(typescript@5.3.3): resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} engines: {node: '>=14'} @@ -13095,7 +16145,6 @@ packages: /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true /croner@8.0.2: resolution: {integrity: sha512-HgSdlSUX8mIgDTTiQpWUP4qY4IFRMsduPCYdca34Pelt8MVdxdaDOzreFtCscA6R+cRZd7UbD1CD3uyx6J3X1A==} @@ -13106,6 +16155,21 @@ packages: resolution: {integrity: sha512-FWZBqdStQaPR8ZTBQGALh1EK9Hl1HcG70dyGvD1rKLPafFO3H73o38dz/e8YkIlbLn3JxmBI/f6Doe3Nh+DcEQ==} hasBin: true + /cross-fetch@3.1.8: + resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + + /cross-inspect@1.0.0: + resolution: {integrity: sha512-4PFfn4b5ZN6FMNGSZlyb7wUhuN8wvj8t/VQHZdM4JsDcruGJ8L2kf9zao98QIrBPFCpdk27qst/AGTl7pL3ypQ==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + /cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} dependencies: @@ -13566,7 +16630,6 @@ packages: /data-uri-to-buffer@2.0.2: resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} - dev: true /data-uri-to-buffer@4.0.1: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} @@ -13597,6 +16660,10 @@ packages: es-errors: 1.3.0 is-data-view: 1.0.1 + /dataloader@2.2.2: + resolution: {integrity: sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==} + dev: false + /date-fns@3.6.0: resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==} dev: false @@ -13634,7 +16701,6 @@ packages: optional: true dependencies: ms: 2.0.0 - dev: true /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} @@ -13659,6 +16725,13 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + /decamelize@2.0.0: + resolution: {integrity: sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==} + engines: {node: '>=4'} + dependencies: + xregexp: 4.0.0 + dev: false + /decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} dependencies: @@ -13787,7 +16860,11 @@ packages: /depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} - dev: true + + /dependency-graph@0.11.0: + resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} + engines: {node: '>= 0.6.0'} + dev: false /deprecation@2.3.1: resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} @@ -13802,7 +16879,6 @@ packages: /destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: true /detect-browser@5.3.0: resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} @@ -13816,13 +16892,11 @@ packages: /detect-indent@6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} - dev: true /detect-libc@1.0.3: resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} engines: {node: '>=0.10'} hasBin: true - dev: true /detect-libc@2.0.3: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} @@ -13859,6 +16933,11 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dev: true + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: false + /diff@5.2.0: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} @@ -13939,11 +17018,22 @@ packages: minimist: 1.2.8 dev: true + /dotenv-defaults@5.0.2: + resolution: {integrity: sha512-y5z4NhblzwNk8XBIYVzjLcFkANK0rxbRDO6kGOfH9QrVYIGVEX52IqwSprKVsaLHM9pnNkCSxazZF/JPydDPvA==} + dependencies: + dotenv: 14.3.2 + dev: false + /dotenv-expand@10.0.0: resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} engines: {node: '>=12'} dev: true + /dotenv@14.3.2: + resolution: {integrity: sha512-vwEppIphpFdvaMCaHfCEv9IgwcxMljMw2TnAQBB4VWPvzXQLTb82jwmdOKzlEVUL3gNFT4l4TPKO+Bn+sqcrVQ==} + engines: {node: '>=12'} + dev: false + /dotenv@16.0.3: resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} engines: {node: '>=12'} @@ -14334,6 +17424,11 @@ packages: mysql2: 3.9.7 react: 18.3.1 + /dset@3.1.3: + resolution: {integrity: sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==} + engines: {node: '>=4'} + dev: false + /duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} dev: true @@ -14349,6 +17444,12 @@ packages: wcwidth: 1.0.1 dev: true + /ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /editorconfig@1.0.4: resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==} engines: {node: '>=14'} @@ -14362,7 +17463,6 @@ packages: /ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: true /electron-to-chromium@1.4.751: resolution: {integrity: sha512-2DEPi++qa89SMGRhufWTiLmzqyuGmNF3SK4+PQetW1JKiZdEpF4XQonJXJCzyuYSA6mauiMhbyVhqYAP45Hvfw==} @@ -14379,7 +17479,6 @@ packages: /encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} - dev: true /encoding@0.1.13: resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} @@ -14477,7 +17576,6 @@ packages: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: is-arrayish: 0.2.1 - dev: true /error-stack-parser-es@0.1.1: resolution: {integrity: sha512-g/9rfnvnagiNf+DRMHEVGuGuIBlCIMDFoTA616HaP2l9PlCjGjVhD98PNbVSJvmK4TttqT5mV5tInMhoFgi+aA==} @@ -14764,7 +17862,6 @@ packages: '@esbuild/win32-arm64': 0.19.12 '@esbuild/win32-ia32': 0.19.12 '@esbuild/win32-x64': 0.19.12 - dev: true /esbuild@0.20.2: resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} @@ -15033,7 +18130,6 @@ packages: /etag@1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} - dev: true /event-emitter@0.3.5: resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} @@ -15045,7 +18141,6 @@ packages: /event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} - dev: true /eventemitter3@3.1.2: resolution: {integrity: sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==} @@ -15168,7 +18263,6 @@ packages: vary: 1.1.2 transitivePeerDependencies: - supports-color - dev: true /ext@1.7.0: resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} @@ -15196,7 +18290,6 @@ packages: chardet: 0.7.0 iconv-lite: 0.4.24 tmp: 0.0.33 - dev: true /externality@1.0.2: resolution: {integrity: sha512-LyExtJWKxtgVzmgtEHyQtLFpw1KFhQphF9nTG8TpAIVkiI/xQ3FJh75tRFLYl4hkn7BNIIdLJInuDAavX35pMw==} @@ -15207,11 +18300,20 @@ packages: ufo: 1.5.3 dev: true + /extract-files@11.0.0: + resolution: {integrity: sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==} + engines: {node: ^12.20 || >= 14.13} + dev: false + /fake-indexeddb@5.0.2: resolution: {integrity: sha512-cB507r5T3D55DfclY01GLkninZLfU7HXV/mhVRTnTRm5k2u+fY7Fof2dBkr80p5t7G7dlA/G5dI87QiMdPpMCQ==} engines: {node: '>=18'} dev: true + /fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + dev: false + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -15237,10 +18339,27 @@ packages: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: false + /fast-querystring@1.1.2: + resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + dependencies: + fast-decode-uri-component: 1.0.1 + dev: false + + /fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + dev: false + /fast-sha256@1.3.0: resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==} dev: false + /fast-url-parser@1.1.3: + resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==} + dependencies: + punycode: 1.4.1 + dev: false + /fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} dependencies: @@ -15260,6 +18379,30 @@ packages: xml2js: 0.6.2 dev: true + /fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + dependencies: + bser: 2.1.1 + dev: false + + /fbjs-css-vars@1.0.2: + resolution: {integrity: sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==} + dev: false + + /fbjs@3.0.5: + resolution: {integrity: sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==} + dependencies: + cross-fetch: 3.1.8 + fbjs-css-vars: 1.0.2 + loose-envify: 1.4.0 + object-assign: 4.1.1 + promise: 7.3.1 + setimmediate: 1.0.5 + ua-parser-js: 1.0.37 + transitivePeerDependencies: + - encoding + dev: false + /fecha@4.2.3: resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} dev: false @@ -15292,7 +18435,6 @@ packages: engines: {node: '>=8'} dependencies: escape-string-regexp: 1.0.5 - dev: true /file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} @@ -15332,7 +18474,31 @@ packages: unpipe: 1.0.0 transitivePeerDependencies: - supports-color - dev: true + + /find-babel-config@2.1.1: + resolution: {integrity: sha512-5Ji+EAysHGe1OipH7GN4qDjok5Z1uw5KAwDCbicU/4wyTZY7CqOCzcWbG7J5ad9mazq67k89fXlbc1MuIfl9uA==} + dependencies: + json5: 2.2.3 + path-exists: 4.0.0 + dev: false + + /find-cache-dir@2.1.0: + resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==} + engines: {node: '>=6'} + dependencies: + commondir: 1.0.1 + make-dir: 2.1.0 + pkg-dir: 3.0.0 + dev: false + + /find-my-way@8.1.0: + resolution: {integrity: sha512-41QwjCGcVTODUmLLqTMeoHeiozbMXYMAE1CKFiDyi9zVZ2Vjh0yz3MF0WQZoIb+cmzP/XlbFjlF2NtJmvZHznA==} + engines: {node: '>=14'} + dependencies: + fast-deep-equal: 3.1.3 + fast-querystring: 1.1.2 + safe-regex2: 2.0.0 + dev: false /find-node-modules@2.1.3: resolution: {integrity: sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==} @@ -15345,13 +18511,19 @@ packages: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} dev: true + /find-up@3.0.0: + resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} + engines: {node: '>=6'} + dependencies: + locate-path: 3.0.0 + dev: false + /find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} dependencies: locate-path: 5.0.0 path-exists: 4.0.0 - dev: true /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} @@ -15484,7 +18656,6 @@ packages: /forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} - dev: true /fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} @@ -15537,7 +18708,6 @@ packages: /fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} - dev: true /fs-extra@11.2.0: resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} @@ -15546,7 +18716,6 @@ packages: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 - dev: true /fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} @@ -15702,7 +18871,6 @@ packages: dependencies: data-uri-to-buffer: 2.0.2 source-map: 0.6.1 - dev: true /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} @@ -15721,6 +18889,10 @@ packages: es-errors: 1.3.0 get-intrinsic: 1.2.4 + /get-them-args@1.3.2: + resolution: {integrity: sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw==} + dev: false + /get-tsconfig@4.7.3: resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} dependencies: @@ -15845,7 +19017,6 @@ packages: inherits: 2.0.4 minimatch: 5.1.6 once: 1.4.0 - dev: true /global-directory@4.0.1: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} @@ -15900,7 +19071,6 @@ packages: ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 - dev: true /globby@13.2.2: resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} @@ -15924,6 +19094,14 @@ packages: unicorn-magic: 0.1.0 dev: true + /goober@2.1.14(csstype@3.1.3): + resolution: {integrity: sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==} + peerDependencies: + csstype: ^3.0.10 + dependencies: + csstype: 3.1.3 + dev: false + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -15946,34 +19124,143 @@ packages: responselike: 3.0.0 dev: true - /got@13.0.0: - resolution: {integrity: sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==} - engines: {node: '>=16'} + /got@13.0.0: + resolution: {integrity: sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==} + engines: {node: '>=16'} + dependencies: + '@sindresorhus/is': 5.6.0 + '@szmarczak/http-timer': 5.0.1 + cacheable-lookup: 7.0.0 + cacheable-request: 10.2.14 + decompress-response: 6.0.0 + form-data-encoder: 2.1.4 + get-stream: 6.0.1 + http2-wrapper: 2.2.1 + lowercase-keys: 3.0.0 + p-cancelable: 3.0.0 + responselike: 3.0.0 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + /grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + dev: true + + /graphlib@2.1.8: + resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==} + dependencies: + lodash: 4.17.21 + dev: false + + /graphql-config@4.5.0(@types/node@20.12.7)(graphql@16.8.1): + resolution: {integrity: sha512-x6D0/cftpLUJ0Ch1e5sj1TZn6Wcxx4oMfmhaG9shM0DKajA9iR+j1z86GSTQ19fShbGvrSSvbIQsHku6aQ6BBw==} + engines: {node: '>= 10.0.0'} + peerDependencies: + cosmiconfig-toml-loader: ^1.0.0 + graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + peerDependenciesMeta: + cosmiconfig-toml-loader: + optional: true + dependencies: + '@graphql-tools/graphql-file-loader': 7.5.17(graphql@16.8.1) + '@graphql-tools/json-file-loader': 7.4.18(graphql@16.8.1) + '@graphql-tools/load': 7.8.14(graphql@16.8.1) + '@graphql-tools/merge': 8.4.2(graphql@16.8.1) + '@graphql-tools/url-loader': 7.17.18(@types/node@20.12.7)(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + cosmiconfig: 8.0.0 + graphql: 16.8.1 + jiti: 1.17.1 + minimatch: 4.2.3 + string-env-interpolation: 1.0.1 + tslib: 2.6.2 + transitivePeerDependencies: + - '@types/node' + - bufferutil + - encoding + - utf-8-validate + dev: false + + /graphql-depth-limit@1.1.0(graphql@16.8.1): + resolution: {integrity: sha512-+3B2BaG8qQ8E18kzk9yiSdAa75i/hnnOwgSeAxVJctGQPvmeiLtqKOYF6HETCyRjiF7Xfsyal0HbLlxCQkgkrw==} + engines: {node: '>=6.0.0'} + peerDependencies: + graphql: '*' + dependencies: + arrify: 1.0.1 + graphql: 16.8.1 + dev: false + + /graphql-request@6.1.0(graphql@16.8.1): + resolution: {integrity: sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==} + peerDependencies: + graphql: 14 - 16 + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + cross-fetch: 3.1.8 + graphql: 16.8.1 + transitivePeerDependencies: + - encoding + dev: false + + /graphql-scalars@1.23.0(graphql@16.8.1): + resolution: {integrity: sha512-YTRNcwitkn8CqYcleKOx9IvedA8JIERn8BRq21nlKgOr4NEcTaWEG0sT+H92eF3ALTFbPgsqfft4cw+MGgv0Gg==} + engines: {node: '>=10'} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: - '@sindresorhus/is': 5.6.0 - '@szmarczak/http-timer': 5.0.1 - cacheable-lookup: 7.0.0 - cacheable-request: 10.2.14 - decompress-response: 6.0.0 - form-data-encoder: 2.1.4 - get-stream: 6.0.1 - http2-wrapper: 2.2.1 - lowercase-keys: 3.0.0 - p-cancelable: 3.0.0 - responselike: 3.0.0 - dev: true + graphql: 16.8.1 + tslib: 2.6.2 + dev: false - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + /graphql-sse@2.5.2(graphql@16.8.1): + resolution: {integrity: sha512-KCTl7HpD12xQrbXGdLrc1BL0ybfB6M83lxRO1mqT31pvOY01ZuWgiJKTY8+NAX8sgEMPVrnXXOXh9LqYDgNI+g==} + engines: {node: '>=12'} + peerDependencies: + graphql: '>=0.11 <=16' + dependencies: + graphql: 16.8.1 + dev: false - /grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - dev: true + /graphql-tag@2.12.6(graphql@16.8.1): + resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==} + engines: {node: '>=10'} + peerDependencies: + graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + graphql: 16.8.1 + tslib: 2.6.2 + dev: false - /graphlib@2.1.8: - resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==} + /graphql-ws@5.12.1(graphql@16.8.1): + resolution: {integrity: sha512-umt4f5NnMK46ChM2coO36PTFhHouBrK9stWWBczERguwYrGnPNxJ9dimU6IyOBfOkC6Izhkg4H8+F51W/8CYDg==} + engines: {node: '>=10'} + peerDependencies: + graphql: '>=0.11 <=16' dependencies: - lodash: 4.17.21 + graphql: 16.8.1 + dev: false + + /graphql-yoga@5.2.0(graphql@16.8.1): + resolution: {integrity: sha512-wazpTEK0B6fSgcGge1EDpP69Oet5Gdp4VmzhqKJD7Uu9S1tP9vUR7AoeuWcrURoCWP2WTv/3dWTQWVt9RxmB1Q==} + engines: {node: '>=18.0.0'} + peerDependencies: + graphql: ^15.2.0 || ^16.0.0 + dependencies: + '@envelop/core': 5.0.0 + '@graphql-tools/executor': 1.2.6(graphql@16.8.1) + '@graphql-tools/schema': 10.0.3(graphql@16.8.1) + '@graphql-tools/utils': 10.2.0(graphql@16.8.1) + '@graphql-yoga/logger': 2.0.0 + '@graphql-yoga/subscription': 5.0.0 + '@whatwg-node/fetch': 0.9.17 + '@whatwg-node/server': 0.9.34 + dset: 3.1.3 + graphql: 16.8.1 + lru-cache: 10.2.2 + tslib: 2.6.2 dev: false /graphql@16.8.1: @@ -16366,6 +19653,13 @@ packages: property-information: 6.5.0 space-separated-tokens: 2.0.2 + /header-case@2.0.4: + resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==} + dependencies: + capital-case: 1.0.4 + tslib: 2.6.2 + dev: false + /headers-polyfill@4.0.3: resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} @@ -16378,6 +19672,12 @@ packages: engines: {node: '>=6'} dev: false + /hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + dependencies: + react-is: 16.13.1 + dev: false + /homedir-polyfill@1.0.3: resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} engines: {node: '>=0.10.0'} @@ -16453,7 +19753,16 @@ packages: setprototypeof: 1.2.0 statuses: 2.0.1 toidentifier: 1.0.1 - dev: true + + /http-proxy-agent@6.1.1: + resolution: {integrity: sha512-JRCz+4Whs6yrrIoIlrH+ZTmhrRwtMnmOHsHn8GFEn9O2sVfSE+DAZ3oyyGIKF8tjJEeSJmP89j7aTjVsSqsU0g==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.1 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false /http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} @@ -16465,6 +19774,35 @@ packages: - supports-color dev: true + /http-proxy-middleware@2.0.6: + resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + dependencies: + '@types/http-proxy': 1.17.14 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.5 + transitivePeerDependencies: + - debug + dev: false + + /http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.6 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + dev: false + /http-shutdown@1.2.2: resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -16488,6 +19826,16 @@ packages: - supports-color dev: true + /https-proxy-agent@6.2.1: + resolution: {integrity: sha512-ONsE3+yfZF2caH5+bJlcddtWqNI3Gvs5A38+ngvljxaBiRXRswym2c7yf8UAeFpRFKjFNHIFEHqR/OLAWJzyiA==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.1 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /https-proxy-agent@7.0.4: resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} engines: {node: '>= 14'} @@ -16524,6 +19872,13 @@ packages: resolution: {integrity: sha512-6WsXYTHJr7hXKqoqf5zoWza/lANRAqGlbnZnm0cjDykbXuez1JVXOQGmq0EPB45pXYAJyueRA3S3hfhmMbrMEQ==} dev: false + /humanize-string@2.1.0: + resolution: {integrity: sha512-sQ+hqmxyXW8Cj7iqxcQxD7oSy3+AXnIZXdUF9lQMkzaG8dtbKAB8U7lCtViMnwQ+MpdCKsO2Kiij3G6UUXq/Xg==} + engines: {node: '>=6'} + dependencies: + decamelize: 2.0.0 + dev: false + /husky@9.0.11: resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} engines: {node: '>=18'} @@ -16535,7 +19890,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 - dev: true /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} @@ -16570,6 +19924,11 @@ packages: engines: {node: '>=14.0.0'} dev: false + /immutable@3.7.6: + resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} + engines: {node: '>=0.8.0'} + dev: false + /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -16577,6 +19936,11 @@ packages: parent-module: 1.0.1 resolve-from: 4.0.0 + /import-from@4.0.0: + resolution: {integrity: sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==} + engines: {node: '>=12.2'} + dev: false + /import-in-the-middle@1.7.1: resolution: {integrity: sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==} dependencies: @@ -16598,7 +19962,6 @@ packages: /indent-string@4.0.0: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} - dev: true /indent-string@5.0.0: resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} @@ -16659,7 +20022,6 @@ packages: strip-ansi: 6.0.1 through: 2.3.8 wrap-ansi: 7.0.0 - dev: true /insert-css@2.0.0: resolution: {integrity: sha512-xGq5ISgcUP5cvGkS2MMFLtPDBtrtQPSFfC6gA6U8wHKqfjTIMZLZNxOItQnoSjdOzlXOLU/yD32RKC4SvjNbtA==} @@ -16729,7 +20091,6 @@ packages: /ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - dev: true /iron-webcrypto@1.1.1: resolution: {integrity: sha512-5xGwQUWHQSy039rFr+5q/zOmj7GP0Ypzvo34Ep+61bPIhaLduEDp/PvLGlU3awD2mzWUR0weN2vJ1mILydFPEg==} @@ -16740,6 +20101,14 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true + /is-absolute@1.0.0: + resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==} + engines: {node: '>=0.10.0'} + dependencies: + is-relative: 1.0.0 + is-windows: 1.0.2 + dev: false + /is-alphabetical@2.0.1: resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} @@ -16770,7 +20139,6 @@ packages: /is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true /is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} @@ -16928,6 +20296,12 @@ packages: resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} dev: true + /is-lower-case@2.0.2: + resolution: {integrity: sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==} + dependencies: + tslib: 2.6.2 + dev: false + /is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} dev: true @@ -16993,6 +20367,13 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + /is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: false + /is-plain-object@5.0.0: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} engines: {node: '>=0.10.0'} @@ -17027,6 +20408,13 @@ packages: call-bind: 1.0.7 has-tostringtag: 1.0.2 + /is-relative@1.0.0: + resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==} + engines: {node: '>=0.10.0'} + dependencies: + is-unc-path: 1.0.0 + dev: false + /is-shared-array-buffer@1.0.3: resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} engines: {node: '>= 0.4'} @@ -17078,6 +20466,13 @@ packages: dependencies: which-typed-array: 1.1.15 + /is-unc-path@1.0.0: + resolution: {integrity: sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==} + engines: {node: '>=0.10.0'} + dependencies: + unc-path-regex: 0.1.2 + dev: false + /is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} @@ -17087,6 +20482,12 @@ packages: engines: {node: '>=12'} dev: true + /is-upper-case@2.0.2: + resolution: {integrity: sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==} + dependencies: + tslib: 2.6.2 + dev: false + /is-utf8@0.2.1: resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==} dev: true @@ -17103,7 +20504,6 @@ packages: /is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} - dev: true /is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} @@ -17132,6 +20532,11 @@ packages: /isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + /isbot@3.8.0: + resolution: {integrity: sha512-vne1mzQUTR+qsMLeCBL9+/tgnDXRyc2pygLGl/WsgA+EZKIiB5Ehu0CiVTHIIk30zhJ24uGz4M5Ppse37aR0Hg==} + engines: {node: '>=12'} + dev: false + /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -17140,6 +20545,11 @@ packages: engines: {node: '>=16'} dev: true + /isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: false + /isomorphic-fetch@3.0.0: resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} dependencies: @@ -17149,6 +20559,22 @@ packages: - encoding dev: true + /isomorphic-ws@5.0.0(ws@8.13.0): + resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} + peerDependencies: + ws: '*' + dependencies: + ws: 8.13.0 + dev: false + + /isomorphic-ws@5.0.0(ws@8.17.0): + resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} + peerDependencies: + ws: '*' + dependencies: + ws: 8.17.0 + dev: false + /iterable-lookahead@1.0.0: resolution: {integrity: sha512-hJnEP2Xk4+44DDwJqUQGdXal5VbyeWLaPyDl2AQc242Zr7iqz4DgpQOrEzglWVMGHMDCkguLHEKxd1+rOsmgSQ==} engines: {node: '>=4'} @@ -17171,10 +20597,19 @@ packages: supports-color: 8.1.1 dev: false + /jiti@1.17.1: + resolution: {integrity: sha512-NZIITw8uZQFuzQimqjUxIrIcEdxYDFIe/0xYfIlVXTkiBjjyBEvgasj5bb0/cHtPRD/NziPbT312sFrkI5ALpw==} + hasBin: true + dev: false + /jiti@1.21.0: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true + /jose@4.15.5: + resolution: {integrity: sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==} + dev: false + /joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -17230,6 +20665,11 @@ packages: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} dev: true + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: false + /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} @@ -17267,6 +20707,24 @@ packages: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: false + /json-stable-stringify@1.1.1: + resolution: {integrity: sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + isarray: 2.0.5 + jsonify: 0.0.1 + object-keys: 1.1.1 + dev: false + + /json-to-pretty-yaml@1.2.2: + resolution: {integrity: sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==} + engines: {node: '>= 0.2.0'} + dependencies: + remedial: 1.0.8 + remove-trailing-spaces: 1.0.8 + dev: false + /json2module@0.0.3: resolution: {integrity: sha512-qYGxqrRrt4GbB8IEOy1jJGypkNsjWoIMlZt4bAsmUScCA507Hbc2p1JOhBzqn45u3PWafUgH2OnzyNU7udO/GA==} hasBin: true @@ -17295,13 +20753,47 @@ packages: universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 - dev: true + + /jsonify@0.0.1: + resolution: {integrity: sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==} + dev: false /jsonparse@1.3.1: resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} engines: {'0': node >= 0.2.0} dev: true + /jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + engines: {node: '>=12', npm: '>=6'} + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.6.0 + dev: false + + /jwa@1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + dev: false + + /jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + dev: false + /k6@0.0.0: resolution: {integrity: sha512-GAQSWayS2+LjbH5bkRi+pMPYyP1JSp7o+4j58ANZ762N/RH/SdlAT3CHHztnn8s/xgg8kYNM24Gd2IPo9b5W+g==} dev: true @@ -17318,6 +20810,14 @@ packages: dependencies: json-buffer: 3.0.1 + /kill-port@1.6.1: + resolution: {integrity: sha512-un0Y55cOM7JKGaLnGja28T38tDDop0AQ8N0KlAdyh+B1nmMoX8AnNmqPNZbS3mUMgiST51DCVqmbFT1gNJpVNw==} + hasBin: true + dependencies: + get-them-args: 1.3.2 + shell-exec: 1.0.2 + dev: false + /kind-of@3.2.2: resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} engines: {node: '>=0.10.0'} @@ -17489,6 +20989,25 @@ packages: - uWebSockets.js dev: true + /listr2@4.0.5: + resolution: {integrity: sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==} + engines: {node: '>=12'} + peerDependencies: + enquirer: '>= 2.3.0 < 3' + peerDependenciesMeta: + enquirer: + optional: true + dependencies: + cli-truncate: 2.1.0 + colorette: 2.0.20 + log-update: 4.0.0 + p-map: 4.0.0 + rfdc: 1.3.1 + rxjs: 7.8.1 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: false + /listr2@8.0.1: resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} engines: {node: '>=18.0.0'} @@ -17532,12 +21051,19 @@ packages: mlly: 1.6.1 pkg-types: 1.1.0 + /locate-path@3.0.0: + resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} + engines: {node: '>=6'} + dependencies: + p-locate: 3.0.0 + path-exists: 3.0.0 + dev: false + /locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} dependencies: p-locate: 4.1.0 - dev: true /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -17567,13 +21093,33 @@ packages: resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} dev: true + /lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + dev: false + /lodash.isarguments@3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} dev: true + /lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + dev: false + + /lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + dev: false + + /lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + dev: false + /lodash.isplainobject@4.0.6: resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + /lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + dev: false + /lodash.map@4.6.0: resolution: {integrity: sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==} dev: true @@ -17590,9 +21136,12 @@ packages: dev: true optional: true + /lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + dev: false + /lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - dev: true /lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} @@ -17624,6 +21173,16 @@ packages: is-unicode-supported: 1.3.0 dev: true + /log-update@4.0.0: + resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} + engines: {node: '>=10'} + dependencies: + ansi-escapes: 4.3.2 + cli-cursor: 3.1.0 + slice-ansi: 4.0.0 + wrap-ansi: 6.2.0 + dev: false + /log-update@6.0.0: resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} engines: {node: '>=18'} @@ -17635,6 +21194,10 @@ packages: wrap-ansi: 9.0.0 dev: true + /logical-not@1.0.9: + resolution: {integrity: sha512-RMNo9GZNS+1UXgwwwfPzuN5e5vlwbw+U0nti0qn5CrwnpcgBjl/4leZAbHjvThe31WF/aOb+fV6dLR6VjQfAvw==} + dev: false + /long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} @@ -17663,10 +21226,16 @@ packages: get-func-name: 2.0.2 dev: true + /lower-case-first@2.0.2: + resolution: {integrity: sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==} + dependencies: + tslib: 2.6.2 + dev: false + /lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} dependencies: - tslib: 2.4.1 + tslib: 2.6.2 dev: false /lowercase-keys@3.0.0: @@ -17750,6 +21319,14 @@ packages: source-map-js: 1.2.0 dev: true + /make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + dependencies: + pify: 4.0.1 + semver: 5.7.2 + dev: false + /make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -17757,6 +21334,10 @@ packages: semver: 6.3.1 dev: true + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: false + /make-fetch-happen@13.0.1: resolution: {integrity: sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==} engines: {node: ^16.14.0 || >=18.0.0} @@ -17777,6 +21358,11 @@ packages: - supports-color dev: true + /map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + dev: false + /map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} engines: {node: '>=0.10.0'} @@ -18051,7 +21637,6 @@ packages: /media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - dev: true /memfs@3.5.3: resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} @@ -18099,7 +21684,6 @@ packages: /merge-descriptors@1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: true /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -18112,10 +21696,21 @@ packages: resolution: {integrity: sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==} dev: true + /meros@1.3.0(@types/node@20.12.7): + resolution: {integrity: sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==} + engines: {node: '>=13'} + peerDependencies: + '@types/node': '>=13' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 20.12.7 + dev: false + /methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - dev: true /micromark-core-commonmark@1.1.0: resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==} @@ -18484,7 +22079,6 @@ packages: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} hasBin: true - dev: true /mime@3.0.0: resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} @@ -18552,19 +22146,24 @@ packages: dependencies: brace-expansion: 1.1.11 + /minimatch@4.2.3: + resolution: {integrity: sha512-lIUdtK5hdofgCTu3aT0sOaHsYR37viUuIc0rwnnDXImbwFRcumyLMeZaM0t0I/fgxS6s6JMfu0rLD1Wz9pv1ng==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 1.1.11 + dev: false + /minimatch@5.1.6: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} dependencies: brace-expansion: 2.0.1 - dev: true /minimatch@7.4.6: resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} engines: {node: '>=10'} dependencies: brace-expansion: 2.0.1 - dev: true /minimatch@9.0.1: resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} @@ -18696,6 +22295,12 @@ packages: engines: {node: '>=10'} hasBin: true + /mkdirp@2.1.6: + resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==} + engines: {node: '>=10'} + hasBin: true + dev: false + /mkdist@1.5.1(typescript@5.3.3): resolution: {integrity: sha512-lCu1spNiA52o7IaKgZnOjg28nNHwYqUDjBfXePXyUtzD7Xhe6rRTkGTalQ/ALfrZC/SrPw2+A/0qkeJ+fPDZtQ==} hasBin: true @@ -18797,7 +22402,6 @@ packages: /ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: true /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -18874,7 +22478,6 @@ packages: /mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} - dev: true /mute-stream@1.0.0: resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} @@ -18916,6 +22519,10 @@ packages: engines: {node: ^18 || >=20} hasBin: true + /napi-wasm@1.1.0: + resolution: {integrity: sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg==} + dev: true + /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: false @@ -19315,7 +22922,6 @@ packages: /node-addon-api@7.1.0: resolution: {integrity: sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==} engines: {node: ^16 || ^18 || >= 20} - dev: true /node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} @@ -19378,6 +22984,10 @@ packages: - supports-color dev: true + /node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: false + /node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} @@ -19415,6 +23025,13 @@ packages: validate-npm-package-license: 3.0.4 dev: true + /normalize-path@2.1.1: + resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} + engines: {node: '>=0.10.0'} + dependencies: + remove-trailing-separator: 1.1.0 + dev: false + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -19518,6 +23135,10 @@ packages: boolbase: 1.0.0 dev: true + /nullthrows@1.1.1: + resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + dev: false + /nuqs@1.17.1(next@14.1.3): resolution: {integrity: sha512-zJPisj8L+SzKzt57c5s3fJW0ikksPr+PyeLyNwvx0i5ggTr5XR5uFhCoX/T+Mkmb6X5UxHB/0nnuZyFiQsh0cA==} peerDependencies: @@ -19728,12 +23349,16 @@ packages: /ohash@1.1.3: resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} + /on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + dev: false + /on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} dependencies: ee-first: 1.1.1 - dev: true /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -19798,6 +23423,15 @@ packages: yaml: 2.4.2 dev: false + /optimism@0.18.0: + resolution: {integrity: sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ==} + dependencies: + '@wry/caches': 1.0.1 + '@wry/context': 0.7.4 + '@wry/trie': 0.4.3 + tslib: 2.6.2 + dev: false + /optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -19842,7 +23476,6 @@ packages: /os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} - dev: true /outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} @@ -19881,7 +23514,6 @@ packages: engines: {node: '>=6'} dependencies: p-try: 2.2.0 - dev: true /p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} @@ -19896,12 +23528,18 @@ packages: yocto-queue: 1.0.0 dev: true + /p-locate@3.0.0: + resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} + engines: {node: '>=6'} + dependencies: + p-limit: 2.3.0 + dev: false + /p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} dependencies: p-limit: 2.3.0 - dev: true /p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} @@ -19919,7 +23557,6 @@ packages: engines: {node: '>=10'} dependencies: aggregate-error: 3.1.0 - dev: true /p-queue@6.6.2: resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} @@ -19960,7 +23597,6 @@ packages: /p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} - dev: true /pacote@18.0.2: resolution: {integrity: sha512-oMxnZQCOZqFZyEh5oJtpMepoub4hoI6EfMUCdbwkBqkFuJ1Dwfz5IMQD344dKbwPPBNZWKwGL/kNvmDubZyvug==} @@ -19993,6 +23629,13 @@ packages: resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} dev: false + /param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + dependencies: + dot-case: 3.0.4 + tslib: 2.6.2 + dev: false + /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -20018,6 +23661,15 @@ packages: is-decimal: 2.0.1 is-hexadecimal: 2.0.1 + /parse-filepath@1.0.2: + resolution: {integrity: sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==} + engines: {node: '>=0.8'} + dependencies: + is-absolute: 1.0.0 + map-cache: 0.2.2 + path-root: 0.1.1 + dev: false + /parse-git-config@3.0.0: resolution: {integrity: sha512-wXoQGL1D+2COYWCD35/xbiKma1Z15xvZL8cI25wvxzled58V51SJM04Urt/uznS900iQor7QO04SgdfT/XlbuA==} engines: {node: '>=8'} @@ -20034,7 +23686,6 @@ packages: error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - dev: true /parse-latin@5.0.1: resolution: {integrity: sha512-b/K8ExXaWC9t34kKeDV8kGXBkXZ1HCSAZRYE7HR14eA1GlXX5L8iWhs8USJNhQU9q5ci413jCKF0gOyovvyRBg==} @@ -20088,7 +23739,6 @@ packages: /parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} - dev: true /pascal-case@3.1.2: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} @@ -20097,6 +23747,27 @@ packages: tslib: 2.6.2 dev: false + /pascalcase@1.0.0: + resolution: {integrity: sha512-BSExi0rRnCHReJys6NocaK+cfTXNinAegfWBvr0JD3hiaEG7Nuc7r0CIdOJunXrs8gU/sbHQ9dxVAtiVQisjmg==} + engines: {node: '>=8'} + dev: false + + /path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + dev: false + + /path-case@3.0.4: + resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} + dependencies: + dot-case: 3.0.4 + tslib: 2.6.2 + dev: false + + /path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + dev: false + /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -20116,6 +23787,18 @@ packages: /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + /path-root-regex@0.1.2: + resolution: {integrity: sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==} + engines: {node: '>=0.10.0'} + dev: false + + /path-root@0.1.1: + resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==} + engines: {node: '>=0.10.0'} + dependencies: + path-root-regex: 0.1.2 + dev: false + /path-scurry@1.10.2: resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} engines: {node: '>=16 || 14 >=14.17'} @@ -20125,7 +23808,6 @@ packages: /path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: true /path-to-regexp@6.2.1: resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} @@ -20193,12 +23875,46 @@ packages: /pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} - dev: true + + /pino-abstract-transport@1.1.0: + resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==} + dependencies: + readable-stream: 4.5.2 + split2: 4.2.0 + dev: false + + /pino-std-serializers@6.2.2: + resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} + dev: false + + /pino@8.19.0: + resolution: {integrity: sha512-oswmokxkav9bADfJ2ifrvfHUwad6MLp73Uat0IkQWY3iAw5xTRoznXbXksZs8oaOUMpmhVWD+PZogNzllWpJaA==} + hasBin: true + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 1.1.0 + pino-std-serializers: 6.2.2 + process-warning: 3.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.4.3 + sonic-boom: 3.8.1 + thread-stream: 2.7.0 + dev: false /pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} + /pkg-dir@3.0.0: + resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==} + engines: {node: '>=6'} + dependencies: + find-up: 3.0.0 + dev: false + /pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -20213,6 +23929,13 @@ packages: mlly: 1.6.1 pathe: 1.1.2 + /pkg-up@3.1.0: + resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} + engines: {node: '>=8'} + dependencies: + find-up: 3.0.0 + dev: false + /polyline-miter-util@1.0.1: resolution: {integrity: sha512-/3u91zz6mBerBZo6qnOJOTjv7EfPhKtsV028jMyj86YpzLRNmCCFfrX7IO9tCEQ2W4x45yc+vKOezjf7u2Nd6Q==} dependencies: @@ -20937,6 +24660,12 @@ packages: hasBin: true dev: true + /prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + engines: {node: '>=14'} + hasBin: true + dev: false + /pretty-bytes@6.1.1: resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} engines: {node: ^14.13.1 || >=16.0.0} @@ -20960,7 +24689,6 @@ packages: /printable-characters@1.0.42: resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} - dev: true /prism-react-renderer@2.1.0(react@18.2.0): resolution: {integrity: sha512-I5cvXHjA1PVGbGm1MsWCpvBCRrYyxEri0MC7/JbfIfYfcXAxHyO5PaUjs3A8H5GW6kJcLhTHxxMaOZZpRZD2iQ==} @@ -21009,10 +24737,13 @@ packages: /process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + /process-warning@3.0.0: + resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} + dev: false + /process@0.11.10: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} - dev: true /promise-inflight@1.0.1: resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} @@ -21031,6 +24762,12 @@ packages: retry: 0.12.0 dev: true + /promise@7.3.1: + resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} + dependencies: + asap: 2.0.6 + dev: false + /prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -21082,7 +24819,6 @@ packages: dependencies: forwarded: 0.2.0 ipaddr.js: 1.9.1 - dev: true /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -21103,6 +24839,10 @@ packages: is-ip: 3.1.0 dev: true + /punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + dev: false + /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -21123,7 +24863,6 @@ packages: engines: {node: '>=0.6'} dependencies: side-channel: 1.0.6 - dev: true /qs@6.12.1: resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==} @@ -21143,6 +24882,10 @@ packages: resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} dev: true + /quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + dev: false + /quick-lru@4.0.1: resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} engines: {node: '>=8'} @@ -21164,7 +24907,6 @@ packages: /range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} - dev: true /raw-body@2.5.2: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} @@ -21174,7 +24916,6 @@ packages: http-errors: 2.0.0 iconv-lite: 0.4.24 unpipe: 1.0.0 - dev: true /rc9@2.1.2: resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} @@ -21229,7 +24970,6 @@ packages: loose-envify: 1.4.0 react: 18.3.1 scheduler: 0.23.2 - dev: true /react-draggable@4.4.6(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==} @@ -21306,6 +25046,23 @@ packages: - webpack-cli dev: false + /react-fast-compare@3.2.2: + resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} + dev: false + + /react-helmet-async@2.0.4(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): + resolution: {integrity: sha512-yxjQMWposw+akRfvpl5+8xejl4JtUlHnEBcji6u8/e6oc7ozT+P9PNTWMhCbz2y9tc5zPegw2BvKjQA+NwdEjQ==} + peerDependencies: + react: ^16.6.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 + dependencies: + invariant: 2.2.4 + react: 19.0.0-canary-cb151849e1-20240424 + react-dom: 18.3.1(react@18.3.1) + react-fast-compare: 3.2.2 + shallowequal: 1.1.0 + dev: false + /react-hook-form@7.51.3(react@18.2.0): resolution: {integrity: sha512-cvJ/wbHdhYx8aviSWh28w9ImjmVsb5Y05n1+FW786vEZQJV5STNM0pW6ujS+oiBecb0ARBxJFyAnXj9+GHXACQ==} engines: {node: '>=12.22.0'} @@ -21315,6 +25072,20 @@ packages: react: 18.2.0 dev: false + /react-hot-toast@2.4.1(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): + resolution: {integrity: sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==} + engines: {node: '>=10'} + peerDependencies: + react: '>=16' + react-dom: '>=16' + dependencies: + goober: 2.1.14(csstype@3.1.3) + react: 19.0.0-canary-cb151849e1-20240424 + react-dom: 18.3.1(react@18.3.1) + transitivePeerDependencies: + - csstype + dev: false + /react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -21359,6 +25130,11 @@ packages: scheduler: 0.23.2 dev: true + /react-refresh@0.14.2: + resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + engines: {node: '>=0.10.0'} + dev: false + /react-remove-scroll-bar@2.3.6(@types/react@18.2.79)(react@18.2.0): resolution: {integrity: sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==} engines: {node: '>=10'} @@ -21445,6 +25221,21 @@ packages: use-sidecar: 1.1.2(react@18.3.1) dev: true + /react-server-dom-webpack@19.0.0-canary-cb151849e1-20240424(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424)(webpack@5.91.0): + resolution: {integrity: sha512-JEvR9/PnN28iZVnJjNAeSyUGIO0GAjsSPjJm6Dni8OgPg4aCXbQphrwI59Hs7vDb8YJ/QLjytxMZNRYaGbYfbQ==} + engines: {node: '>=0.10.0'} + peerDependencies: + react: 19.0.0-canary-cb151849e1-20240424 + react-dom: 19.0.0-canary-cb151849e1-20240424 + webpack: ^5.59.0 + dependencies: + acorn-loose: 8.4.0 + neo-async: 2.6.2 + react: 19.0.0-canary-cb151849e1-20240424 + react-dom: 18.3.1(react@18.3.1) + webpack: 5.91.0(esbuild@0.19.12) + dev: false + /react-style-singleton@2.2.1(@types/react@18.2.79)(react@18.2.0): resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} engines: {node: '>=10'} @@ -21502,6 +25293,11 @@ packages: dependencies: loose-envify: 1.4.0 + /react@19.0.0-canary-cb151849e1-20240424: + resolution: {integrity: sha512-sX0ec4kqR1z2PAMdCo0cztaYaoGbpy2EoS5hAzUsBekB9FFnGWP4jbYK7GFURTIh5EK9ny1Mmgkb1hiyVYkj4Q==} + engines: {node: '>=0.10.0'} + dev: false + /reactflow@11.11.1(@types/react@18.2.79)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-2GEh0bTkYR7rzAV3qdeN6C1o4qumtETZl7yQv1GVrfgr3c77nCUAOKsv5hetRejOGNnJudRwn6axeWFAY+IjNg==} peerDependencies: @@ -21583,7 +25379,6 @@ packages: events: 3.3.0 process: 0.11.10 string_decoder: 1.3.0 - dev: true /readdir-glob@1.1.3: resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} @@ -21597,6 +25392,11 @@ packages: dependencies: picomatch: 2.3.1 + /real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + dev: false + /rechoir@0.6.2: resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} engines: {node: '>= 0.10'} @@ -21651,9 +25451,30 @@ packages: parse-entities: 4.0.1 dev: true + /regenerate-unicode-properties@10.1.1: + resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} + engines: {node: '>=4'} + dependencies: + regenerate: 1.4.2 + dev: false + + /regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + dev: false + /regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + /regenerator-transform@0.15.2: + resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} + dependencies: + '@babel/runtime': 7.24.5 + dev: false + + /regexp-to-ast@0.5.0: + resolution: {integrity: sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==} + dev: false + /regexp.prototype.flags@1.5.2: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} @@ -21663,10 +25484,43 @@ packages: es-errors: 1.3.0 set-function-name: 2.0.2 + /regexpu-core@5.3.2: + resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} + engines: {node: '>=4'} + dependencies: + '@babel/regjsgen': 0.8.0 + regenerate: 1.4.2 + regenerate-unicode-properties: 10.1.1 + regjsparser: 0.9.1 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.1.0 + dev: false + + /regjsparser@0.9.1: + resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: false + /regl@1.7.0: resolution: {integrity: sha512-bEAtp/qrtKucxXSJkD4ebopFZYP0q1+3Vb2WECWv/T8yQEgKxDxJ7ztO285tAMaYZVR6mM1GgI6CCn8FROtL1w==} dev: false + /rehackt@0.0.6(react@19.0.0-canary-cb151849e1-20240424): + resolution: {integrity: sha512-l3WEzkt4ntlEc/IB3/mF6SRgNHA6zfQR7BlGOgBTOmx7IJJXojDASav+NsgXHFjHn+6RmwqsGPFgZpabWpeOdw==} + peerDependencies: + '@types/react': '*' + react: '*' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + dependencies: + react: 19.0.0-canary-cb151849e1-20240424 + dev: false + /rehype-autolink-headings@7.1.0: resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==} dependencies: @@ -21736,6 +25590,16 @@ packages: unified: 10.1.2 dev: false + /relay-runtime@12.0.0: + resolution: {integrity: sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug==} + dependencies: + '@babel/runtime': 7.24.5 + fbjs: 3.0.5 + invariant: 2.2.4 + transitivePeerDependencies: + - encoding + dev: false + /remark-frontmatter@4.0.1: resolution: {integrity: sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==} dependencies: @@ -21826,6 +25690,18 @@ packages: - supports-color dev: true + /remedial@1.0.8: + resolution: {integrity: sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==} + dev: false + + /remove-trailing-separator@1.1.0: + resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} + dev: false + + /remove-trailing-spaces@1.0.8: + resolution: {integrity: sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==} + dev: false + /repeat-string@1.6.1: resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} engines: {node: '>=0.10'} @@ -21853,12 +25729,15 @@ packages: /require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - dev: true /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} dev: false + /reselect@4.1.8: + resolution: {integrity: sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==} + dev: false + /resend@3.2.0: resolution: {integrity: sha512-lDHhexiFYPoLXy7zRlJ8D5eKxoXy6Tr9/elN3+Vv7PkUoYuSSD1fpiIfa/JYXEWyiyN2UczkCTLpkT8dDPJ4Pg==} engines: {node: '>=18'} @@ -21885,7 +25764,6 @@ packages: /resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} - dev: true /resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} @@ -21904,6 +25782,11 @@ packages: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + /response-iterator@0.2.6: + resolution: {integrity: sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==} + engines: {node: '>=0.8'} + dev: false + /responselike@3.0.0: resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} engines: {node: '>=14.16'} @@ -21926,6 +25809,11 @@ packages: signal-exit: 3.0.7 dev: true + /ret@0.2.2: + resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} + engines: {node: '>=4'} + dev: false + /retext-latin@3.1.0: resolution: {integrity: sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ==} dependencies: @@ -21981,7 +25869,6 @@ packages: /rfdc@1.3.1: resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} - dev: true /right-align@0.1.3: resolution: {integrity: sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==} @@ -21997,6 +25884,14 @@ packages: glob: 7.2.3 dev: true + /rimraf@5.0.5: + resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} + engines: {node: '>=14'} + hasBin: true + dependencies: + glob: 10.3.12 + dev: false + /robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} dev: false @@ -22110,7 +26005,6 @@ packages: '@rollup/rollup-win32-ia32-msvc': 4.17.2 '@rollup/rollup-win32-x64-msvc': 4.17.2 fsevents: 2.3.3 - dev: true /run-applescript@7.0.0: resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} @@ -22120,7 +26014,6 @@ packages: /run-async@2.4.1: resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} engines: {node: '>=0.12.0'} - dev: true /run-exclusive@2.2.19: resolution: {integrity: sha512-K3mdoAi7tjJ/qT7Flj90L7QyPozwUaAG+CVhkdDje4HLKXUYC3N/Jzkau3flHVDLQVhiHBtcimVodMjN9egYbA==} @@ -22145,7 +26038,6 @@ packages: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} dependencies: tslib: 2.6.2 - dev: true /sade@1.8.1: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} @@ -22176,10 +26068,15 @@ packages: es-errors: 1.3.0 is-regex: 1.1.4 + /safe-regex2@2.0.0: + resolution: {integrity: sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==} + dependencies: + ret: 0.2.2 + dev: false + /safe-stable-stringify@2.4.3: resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} engines: {node: '>=10'} - dev: true /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -22218,6 +26115,10 @@ packages: ajv-keywords: 3.5.2(ajv@6.12.6) dev: false + /scuid@1.1.0: + resolution: {integrity: sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==} + dev: false + /scule@1.3.0: resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} @@ -22245,7 +26146,6 @@ packages: /semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true - dev: true /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} @@ -22277,7 +26177,14 @@ packages: statuses: 2.0.1 transitivePeerDependencies: - supports-color - dev: true + + /sentence-case@3.0.4: + resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.2 + upper-case-first: 2.0.2 + dev: false /seq-queue@0.0.5: resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==} @@ -22303,11 +26210,9 @@ packages: send: 0.18.0 transitivePeerDependencies: - supports-color - dev: true /set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true /set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} @@ -22329,9 +26234,23 @@ packages: functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 + /setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + dev: false + /setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: true + + /shallow-clone@3.0.1: + resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} + engines: {node: '>=8'} + dependencies: + kind-of: 6.0.3 + dev: false + + /shallowequal@1.1.0: + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + dev: false /sharp@0.33.3: resolution: {integrity: sha512-vHUeXJU1UvlO/BNwTpT0x/r53WkLUVxrmb5JTgW92fdFCFk0ispLMAeu/jPO2vjkXM1fYUi3K7/qcLF47pwM1A==} @@ -22385,13 +26304,16 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + /shell-exec@1.0.2: + resolution: {integrity: sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==} + dev: false + /shell-quote-word@1.0.1: resolution: {integrity: sha512-lT297f1WLAdq0A4O+AknIFRP6kkiI3s8C913eJ0XqBxJbZPGWUNkRQk2u8zk4bEAjUJ5i+fSLwB6z1HzeT+DEg==} dev: true /shell-quote@1.8.1: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - dev: true /shelljs@0.8.5: resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} @@ -22442,6 +26364,10 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + /signedsource@1.0.0: + resolution: {integrity: sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww==} + dev: false + /sigstore@2.3.0: resolution: {integrity: sha512-q+o8L2ebiWD1AxD17eglf1pFrl9jtW7FHa0ygqY6EKvibK8JHyq9Z26v9MZXeDiw+RbfOJ9j2v70M10Hd6E06A==} engines: {node: ^16.14.0 || >=18.0.0} @@ -22503,16 +26429,33 @@ packages: /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - dev: true /slash@4.0.0: resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} engines: {node: '>=12'} - /slash@5.1.0: - resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} - engines: {node: '>=14.16'} - dev: true + /slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + dev: true + + /slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: false + + /slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: false /slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} @@ -22684,6 +26627,12 @@ packages: smart-buffer: 4.2.0 dev: true + /sonic-boom@3.8.1: + resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} + dependencies: + atomic-sleep: 1.0.0 + dev: false + /sonner@1.3.1(react-dom@18.3.1)(react@18.2.0): resolution: {integrity: sha512-+rOAO56b2eI3q5BtgljERSn2umRk63KFIvgb2ohbZ5X+Eb5u+a/7/0ZgswYqgBMg8dyl7n6OXd9KasA8QF9ToA==} peerDependencies: @@ -22801,10 +26750,21 @@ packages: engines: {node: '>=0.10.0'} dev: true + /split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + dev: false + /splitpanes@3.1.5: resolution: {integrity: sha512-r3Mq2ITFQ5a2VXLOy4/Sb2Ptp7OfEO8YIbhVJqJXoFc9hc5nTXXkCvtVDjIGbvC0vdE7tse+xTM9BMjsszP6bw==} dev: true + /sponge-case@1.0.1: + resolution: {integrity: sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==} + dependencies: + tslib: 2.6.2 + dev: false + /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -22839,7 +26799,6 @@ packages: dependencies: as-table: 1.0.55 get-source: 2.0.12 - dev: true /standard-as-callback@2.1.0: resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} @@ -22891,6 +26850,10 @@ packages: engines: {node: '>=0.6.19'} dev: true + /string-env-interpolation@1.0.1: + resolution: {integrity: sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==} + dev: false + /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -23206,6 +27169,12 @@ packages: - encoding dev: false + /swap-case@2.0.2: + resolution: {integrity: sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==} + dependencies: + tslib: 2.6.2 + dev: false + /swr@2.2.0(react@18.2.0): resolution: {integrity: sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==} peerDependencies: @@ -23224,11 +27193,23 @@ packages: use-sync-external-store: 1.2.2(react@18.3.1) dev: false + /symbol-observable@4.0.0: + resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} + engines: {node: '>=0.10'} + dev: false + /system-architecture@0.1.0: resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} engines: {node: '>=18'} dev: true + /systeminformation@5.22.6: + resolution: {integrity: sha512-hUTQX+bRgIFbv1T/z251NtwGwNIeSyWURnT2BGnsYu6dQNbkiBl4oAwk50acVfITFq1Zvb8KDNgibQK9uGlUGg==} + engines: {node: '>=8.0.0'} + os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android] + hasBin: true + dev: false + /tabbable@6.2.0: resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} dev: true @@ -23368,6 +27349,14 @@ packages: engines: {node: '>=8'} dev: true + /terminal-link@2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.3.0 + dev: false + /terminal-link@3.0.0: resolution: {integrity: sha512-flFL3m4wuixmf6IfhFJd1YPiLiMuxEc8uHRM1buzIeZPm22Au2pDqBJQgdo7n1WfPU1ONFGv7YDwpFBmHGF6lg==} engines: {node: '>=12'} @@ -23402,6 +27391,31 @@ packages: webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11) dev: false + /terser-webpack-plugin@5.3.10(esbuild@0.19.12)(webpack@5.91.0): + resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + esbuild: 0.19.12 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.2 + terser: 5.31.0 + webpack: 5.91.0(esbuild@0.19.12) + dev: false + /terser@5.31.0: resolution: {integrity: sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==} engines: {node: '>=10'} @@ -23427,9 +27441,14 @@ packages: dependencies: any-promise: 1.3.0 + /thread-stream@2.7.0: + resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==} + dependencies: + real-require: 0.2.0 + dev: false + /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true /timers-ext@0.1.7: resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} @@ -23464,12 +27483,17 @@ packages: engines: {node: '>=14.0.0'} dev: true + /title-case@3.0.3: + resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} + dependencies: + tslib: 2.6.2 + dev: false + /tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} dependencies: os-tmpdir: 1.0.2 - dev: true /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} @@ -23504,7 +27528,6 @@ packages: /toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - dev: true /toml@3.0.0: resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} @@ -23579,6 +27602,13 @@ packages: /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + /ts-invariant@0.10.3: + resolution: {integrity: sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==} + engines: {node: '>=8'} + dependencies: + tslib: 2.6.2 + dev: false + /ts-json-schema-generator@1.5.1: resolution: {integrity: sha512-apX5qG2+NA66j7b4AJm8q/DpdTeOsjfh7A3LpKsUiil0FepkNwtN28zYgjrsiiya2/OPhsr/PSjX5FUYg79rCg==} engines: {node: '>=10.0.0'} @@ -23593,10 +27623,57 @@ packages: typescript: 5.4.5 dev: true + /ts-log@2.2.5: + resolution: {integrity: sha512-PGcnJoTBnVGy6yYNFxWVNkdcAuAMstvutN9MgDJIV6L0oG8fB+ZNNy1T+wJzah8RPGor1mZuPQkVfXNDpy9eHA==} + dev: false + + /ts-morph@18.0.0: + resolution: {integrity: sha512-Kg5u0mk19PIIe4islUI/HWRvm9bC1lHejK4S0oh1zaZ77TMZAEmQC0sHQYiu2RgCQFZKXz1fMVi/7nOOeirznA==} + dependencies: + '@ts-morph/common': 0.19.0 + code-block-writer: 12.0.0 + dev: false + + /ts-node@10.9.2(@swc/core@1.4.11)(@types/node@20.12.7)(typescript@5.4.5): + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@swc/core': 1.4.11 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.12.7 + acorn: 8.11.3 + acorn-walk: 8.3.2 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.4.5 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: false + /ts-pattern@4.3.0: resolution: {integrity: sha512-pefrkcd4lmIVR0LA49Imjf9DYLK8vtWhqBPA3Ya1ir8xCW0O2yjL9dsCVvI7pCodLC5q7smNpEtDR2yVulQxOg==} dev: false + /ts-toolbelt@9.6.0: + resolution: {integrity: sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==} + dev: false + /tsafe@1.6.6: resolution: {integrity: sha512-gzkapsdbMNwBnTIjgO758GujLCj031IgHK/PKr2mrmkCSJMhSOR5FeOuSxKLMUoYc0vAA4RGEYYbjt/v6afD3g==} dev: false @@ -23609,6 +27686,10 @@ packages: resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} dev: false + /tslib@2.5.3: + resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} + dev: false + /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -23816,7 +27897,6 @@ packages: dependencies: media-typer: 0.3.0 mime-types: 2.1.35 - dev: true /type@2.7.2: resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} @@ -23877,7 +27957,10 @@ packages: resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} hasBin: true - dev: true + + /ua-parser-js@1.0.37: + resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==} + dev: false /ufo@1.5.3: resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} @@ -23963,6 +28046,11 @@ packages: - vue-tsc dev: true + /unc-path-regex@0.1.2: + resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} + engines: {node: '>=0.10.0'} + dev: false + /unconfig@0.3.13: resolution: {integrity: sha512-N9Ph5NC4+sqtcOjPfHrRcHekBCadCXWTBzp2VYYbySOHW0PfD9XLCeXshTXjkPYwLrBr9AtSeU0CZmkYECJhng==} dependencies: @@ -24021,6 +28109,29 @@ packages: resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==} dev: true + /unicode-canonical-property-names-ecmascript@2.0.0: + resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} + engines: {node: '>=4'} + dev: false + + /unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.0 + unicode-property-aliases-ecmascript: 2.1.0 + dev: false + + /unicode-match-property-value-ecmascript@2.1.0: + resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} + engines: {node: '>=4'} + dev: false + + /unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + dev: false + /unicode-trie@2.0.0: resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==} dependencies: @@ -24251,7 +28362,13 @@ packages: /universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} - dev: true + + /unixify@1.0.0: + resolution: {integrity: sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==} + engines: {node: '>=0.10.0'} + dependencies: + normalize-path: 2.1.1 + dev: false /unocss@0.59.4(postcss@8.4.38)(rollup@3.29.4)(vite@5.2.10): resolution: {integrity: sha512-QmCVjRObvVu/gsGrJGVt0NnrdhFFn314BUZn2WQyXV9rIvHLRmG5bIu0j5vibJkj7ZhFchTrnTM1pTFXP1xt5g==} @@ -24295,7 +28412,6 @@ packages: /unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - dev: true /unplugin-vue-router@0.7.0(rollup@3.29.4)(vue-router@4.3.2)(vue@3.4.23): resolution: {integrity: sha512-ddRreGq0t5vlSB7OMy4e4cfU1w2AwBQCwmvW3oP/0IHQiokzbx4hd3TpwBu3eIAFVuhX2cwNQwp1U32UybTVCw==} @@ -24436,6 +28552,18 @@ packages: escalade: 3.1.2 picocolors: 1.0.0 + /upper-case-first@2.0.2: + resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==} + dependencies: + tslib: 2.6.2 + dev: false + + /upper-case@2.0.2: + resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==} + dependencies: + tslib: 2.6.2 + dev: false + /uqr@0.1.2: resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} dev: true @@ -24452,9 +28580,12 @@ packages: requires-port: 1.0.0 dev: false + /urlpattern-polyfill@10.0.0: + resolution: {integrity: sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==} + dev: false + /urlpattern-polyfill@8.0.2: resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==} - dev: true /use-callback-ref@1.3.2(@types/react@18.2.79)(react@18.2.0): resolution: {integrity: sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==} @@ -24564,7 +28695,6 @@ packages: /utils-merge@1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} - dev: true /uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} @@ -24586,6 +28716,10 @@ packages: kleur: 4.1.5 sade: 1.8.1 + /v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + dev: false + /validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} dependencies: @@ -24600,6 +28734,11 @@ packages: builtins: 5.1.0 dev: true + /value-or-promise@1.0.12: + resolution: {integrity: sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==} + engines: {node: '>=12'} + dev: false + /vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -24764,6 +28903,16 @@ packages: vscode-uri: 3.0.8 dev: true + /vite-plugin-cjs-interop@2.1.0: + resolution: {integrity: sha512-qp+54VPRKiiuqKZ4tToiEZz5d5uiZf33PrXOfyH5SInlVsYz4b6YoZMNxCrx+vKdAQVsZu03vDJK71Ri5oKMqg==} + dependencies: + acorn: 8.11.3 + acorn-import-assertions: 1.9.0(acorn@8.11.3) + estree-walker: 3.0.3 + magic-string: 0.30.10 + minimatch: 9.0.4 + dev: false + /vite-plugin-inspect@0.8.4(@nuxt/kit@3.11.2)(rollup@3.29.4)(vite@5.2.10): resolution: {integrity: sha512-G0N3rjfw+AiiwnGw50KlObIHYWfulVwaCBUBLh2xTW9G1eM9ocE5olXkEYUbwyTmX+azM8duubi+9w5awdCz+g==} engines: {node: '>=14'} @@ -24845,6 +28994,42 @@ packages: fsevents: 2.3.3 dev: true + /vite@5.2.8(@types/node@20.12.7): + resolution: {integrity: sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.12.7 + esbuild: 0.20.2 + postcss: 8.4.38 + rollup: 4.17.2 + optionalDependencies: + fsevents: 2.3.3 + dev: false + /vitest-environment-nuxt@1.0.0(@vitest/ui@1.3.0)(h3@1.11.1)(rollup@3.29.4)(vite@5.2.10)(vitest@1.3.0)(vue-router@4.3.2)(vue@3.4.23): resolution: {integrity: sha512-AWMO9h4HdbaFdPWZw34gALFI8gbBiOpvfbyeZwHIPfh4kWg/TwElYHvYMQ61WPUlCGaS5LebfHkaI0WPyb//Iw==} dependencies: @@ -25139,6 +29324,46 @@ packages: - uglify-js dev: false + /webpack@5.91.0(esbuild@0.19.12): + resolution: {integrity: sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.5 + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/wasm-edit': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + acorn: 8.11.3 + acorn-import-assertions: 1.9.0(acorn@8.11.3) + browserslist: 4.23.0 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.16.0 + es-module-lexer: 1.5.2 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.10(esbuild@0.19.12)(webpack@5.91.0) + watchpack: 2.4.1 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: false + /whatwg-fetch@3.6.20: resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} @@ -25167,7 +29392,6 @@ packages: /which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - dev: true /which-pm@2.0.0: resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} @@ -25345,6 +29569,19 @@ packages: utf-8-validate: optional: true + /ws@8.13.0: + resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /ws@8.17.0: resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} engines: {node: '>=10.0.0'} @@ -25375,13 +29612,16 @@ packages: engines: {node: '>=0.4.0'} dev: false + /xregexp@4.0.0: + resolution: {integrity: sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==} + dev: false + /xxhash-wasm@1.0.2: resolution: {integrity: sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==} dev: true /y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - dev: true /y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} @@ -25397,6 +29637,15 @@ packages: /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + /yaml-ast-parser@0.0.43: + resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==} + dev: false + + /yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: false + /yaml@2.3.4: resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} engines: {node: '>= 14'} @@ -25413,7 +29662,6 @@ packages: dependencies: camelcase: 5.3.1 decamelize: 1.2.0 - dev: true /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} @@ -25434,7 +29682,6 @@ packages: which-module: 2.0.1 y18n: 4.0.3 yargs-parser: 18.1.3 - dev: true /yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} @@ -25457,6 +29704,11 @@ packages: window-size: 0.1.0 dev: false + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: false + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -25478,6 +29730,16 @@ packages: stacktracey: 2.1.8 dev: true + /zen-observable-ts@1.2.5: + resolution: {integrity: sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==} + dependencies: + zen-observable: 0.8.15 + dev: false + + /zen-observable@0.8.15: + resolution: {integrity: sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==} + dev: false + /zhead@2.2.4: resolution: {integrity: sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==} dev: true From 42e3169edfa8c8548c00f87cb20eb7607b836cb0 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sat, 4 May 2024 13:13:22 -0400 Subject: [PATCH 02/33] Setup vitest --- packages/redwoodjs/package.json | 19 +-- .../src/ratelimit/__tests__/util.test.ts | 27 ++++ packages/redwoodjs/tsconfig.json | 8 +- packages/redwoodjs/vitest.config.ts | 14 ++ pnpm-lock.yaml | 128 +++++++++++++++++- 5 files changed, 178 insertions(+), 18 deletions(-) create mode 100644 packages/redwoodjs/src/ratelimit/__tests__/util.test.ts create mode 100644 packages/redwoodjs/vitest.config.ts diff --git a/packages/redwoodjs/package.json b/packages/redwoodjs/package.json index 497b2b08c5..962adb3879 100644 --- a/packages/redwoodjs/package.json +++ b/packages/redwoodjs/package.json @@ -22,18 +22,19 @@ ], "author": "David Thyresson", "scripts": { - "build": "tsup" - }, - "devDependencies": { - "@redwoodjs/vite": "^7.4.3", - "@types/node": "^20.12.7", - "tsup": "^8.0.2", - "typescript": "^5.3.3" + "build": "tsup", + "test": "vitest" }, "dependencies": { - "@unkey/api": "workspace:^", - "@unkey/ratelimit": "workspace:^", "@redwoodjs/vite": "8.0.0-canary.542", + "@unkey/ratelimit": "workspace:^", "path-to-regexp": "^6.2.2" + }, + "devDependencies": { + "@types/node": "^20.12.7", + "@unkey/tsconfig": "workspace:^", + "tsup": "^8.0.2", + "typescript": "^5.3.3", + "vitest": "^1.6.0" } } diff --git a/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts new file mode 100644 index 0000000000..17da8743b3 --- /dev/null +++ b/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts @@ -0,0 +1,27 @@ +import type { MiddlewareRequest } from "@redwoodjs/vite/dist/middleware"; +import { assert, describe, expect, it } from "vitest"; +import { defaultRatelimitIdentifier, matchesPath } from "../util"; + +describe("defaultRatelimitIdentifier", () => { + it("should return correct identifier", () => { + // Your test logic here + const req = {} as MiddlewareRequest; + assert.equal(defaultRatelimitIdentifier(req), "default"); + }); +}); + +describe("matchesPath", () => { + it("should return true if path matches the pattern", () => { + const path = "/api/user"; + const pattern = "/api/*"; + const result = matchesPath(path, pattern); + expect(result).toBe(true); + }); + + it("should return false if path does not match the pattern", () => { + const path = "/api/user"; + const pattern = "/admin/*"; + const result = matchesPath(path, pattern); + expect(result).toBe(false); + }); +}); diff --git a/packages/redwoodjs/tsconfig.json b/packages/redwoodjs/tsconfig.json index da9b626fec..5c14d7e03f 100644 --- a/packages/redwoodjs/tsconfig.json +++ b/packages/redwoodjs/tsconfig.json @@ -1,4 +1,5 @@ { + "extends": "@unkey/tsconfig/base.json", "compilerOptions": { /* Visit https://aka.ms/tsconfig to read more about this file */ /* Projects */ @@ -10,11 +11,8 @@ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ "target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, - "lib": [ - "ESNext", - "DOM" - ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, - // "jsx": "preserve", /* Specify what JSX code is generated. */ + "lib": ["ESNext", "DOM"], + /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ diff --git a/packages/redwoodjs/vitest.config.ts b/packages/redwoodjs/vitest.config.ts new file mode 100644 index 0000000000..71447bc163 --- /dev/null +++ b/packages/redwoodjs/vitest.config.ts @@ -0,0 +1,14 @@ +import path from "node:path"; +import { configDefaults, defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: [...configDefaults.include, "**/__tests__/**/*.{ts,tsx}"], + deps: { + moduleDirectories: [ + "node_modules", + path.resolve("../node_modules/@redwoodjs/vite/dist/middleware"), + ], + }, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a744833e79..61fa97405d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1350,9 +1350,6 @@ importers: '@redwoodjs/vite': specifier: 8.0.0-canary.542 version: 8.0.0-canary.542(@types/node@20.12.7)(csstype@3.1.3)(graphql-tag@2.12.6)(react-dom@18.3.1)(webpack@5.91.0) - '@unkey/api': - specifier: workspace:^ - version: link:../api '@unkey/ratelimit': specifier: workspace:^ version: link:../ratelimit @@ -1363,12 +1360,18 @@ importers: '@types/node': specifier: ^20.12.7 version: 20.12.7 + '@unkey/tsconfig': + specifier: workspace:^ + version: link:../../internal/tsconfig tsup: specifier: ^8.0.2 version: 8.0.2(typescript@5.3.3) typescript: specifier: ^5.3.3 version: 5.3.3 + vitest: + specifier: ^1.6.0 + version: 1.6.0(@types/node@20.12.7)(@vitest/ui@1.3.0) tools/k6: devDependencies: @@ -13799,6 +13802,14 @@ packages: chai: 4.4.1 dev: true + /@vitest/expect@1.6.0: + resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} + dependencies: + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 + chai: 4.4.1 + dev: true + /@vitest/runner@1.3.0: resolution: {integrity: sha512-1Jb15Vo/Oy7mwZ5bXi7zbgszsdIBNjc4IqP8Jpr/8RdBC4nF1CTzIAn2dxYvpF1nGSseeL39lfLQ2uvs5u1Y9A==} dependencies: @@ -13807,6 +13818,14 @@ packages: pathe: 1.1.2 dev: true + /@vitest/runner@1.6.0: + resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} + dependencies: + '@vitest/utils': 1.6.0 + p-limit: 5.0.0 + pathe: 1.1.2 + dev: true + /@vitest/snapshot@1.3.0: resolution: {integrity: sha512-swmktcviVVPYx9U4SEQXLV6AEY51Y6bZ14jA2yo6TgMxQ3h+ZYiO0YhAHGJNp0ohCFbPAis1R9kK0cvN6lDPQA==} dependencies: @@ -13815,12 +13834,26 @@ packages: pretty-format: 29.7.0 dev: true + /@vitest/snapshot@1.6.0: + resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} + dependencies: + magic-string: 0.30.10 + pathe: 1.1.2 + pretty-format: 29.7.0 + dev: true + /@vitest/spy@1.3.0: resolution: {integrity: sha512-AkCU0ThZunMvblDpPKgjIi025UxR8V7MZ/g/EwmAGpjIujLVV2X6rGYGmxE2D4FJbAy0/ijdROHMWa2M/6JVMw==} dependencies: tinyspy: 2.2.1 dev: true + /@vitest/spy@1.6.0: + resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} + dependencies: + tinyspy: 2.2.1 + dev: true + /@vitest/ui@1.3.0(vitest@1.3.0): resolution: {integrity: sha512-gDGEBUddrPOJvF4e0nIeKBz1whiDthBxBB0OUAbUqnY0HxJwqlKg9R257Sxoeh1Q7ZDSzc7qY96n4hrEPy1NaQ==} peerDependencies: @@ -13845,6 +13878,15 @@ packages: pretty-format: 29.7.0 dev: true + /@vitest/utils@1.6.0: + resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + dev: true + /@vue-macros/common@1.10.2(rollup@3.29.4)(vue@3.4.23): resolution: {integrity: sha512-WC66NPVh2mJWqm4L0l/u/cOqm4pNOIwVdMGnDYAH2rHcOWy5x68GkhpkYTBu1+xwCSeHWOQn1TCGGbD+98fFpA==} engines: {node: '>=16.14.0'} @@ -24607,7 +24649,7 @@ packages: dependencies: nanoid: 3.3.7 picocolors: 1.0.0 - source-map-js: 1.0.2 + source-map-js: 1.2.0 dev: false /postcss@8.4.38: @@ -28853,6 +28895,27 @@ packages: - terser dev: true + /vite-node@1.6.0(@types/node@20.12.7): + resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + pathe: 1.1.2 + picocolors: 1.0.0 + vite: 5.2.10(@types/node@20.12.7) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vite-plugin-checker@0.6.4(typescript@5.3.3)(vite@5.2.10): resolution: {integrity: sha512-2zKHH5oxr+ye43nReRbC2fny1nyARwhxdm0uNYp/ERy4YvU9iZpNOsueoi/luXw5gnpqRSvjcEPxXbS153O2wA==} engines: {node: '>=14.16'} @@ -29110,6 +29173,63 @@ packages: - terser dev: true + /vitest@1.6.0(@types/node@20.12.7)(@vitest/ui@1.3.0): + resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 1.6.0 + '@vitest/ui': 1.6.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/node': 20.12.7 + '@vitest/expect': 1.6.0 + '@vitest/runner': 1.6.0 + '@vitest/snapshot': 1.6.0 + '@vitest/spy': 1.6.0 + '@vitest/ui': 1.3.0(vitest@1.3.0) + '@vitest/utils': 1.6.0 + acorn-walk: 8.3.2 + chai: 4.4.1 + debug: 4.3.4 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.10 + pathe: 1.1.2 + picocolors: 1.0.0 + std-env: 3.7.0 + strip-literal: 2.1.0 + tinybench: 2.8.0 + tinypool: 0.8.4 + vite: 5.2.10(@types/node@20.12.7) + vite-node: 1.6.0(@types/node@20.12.7) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vlq@0.2.3: resolution: {integrity: sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==} dev: true From b3d68f9ab76e9d2d5a44dae80c9b93185824b3f2 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sat, 4 May 2024 13:18:49 -0400 Subject: [PATCH 03/33] Delete apps/web/next-env.d.ts Accidentally added --- apps/web/next-env.d.ts | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 apps/web/next-env.d.ts diff --git a/apps/web/next-env.d.ts b/apps/web/next-env.d.ts deleted file mode 100644 index fd36f9494e..0000000000 --- a/apps/web/next-env.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -/// -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. From da515f5461bd2616336cdcad9186b148c7fd9fca Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Mon, 6 May 2024 09:23:59 -0400 Subject: [PATCH 04/33] Fix configs and tsconfig to properly import rw middleware --- packages/redwoodjs/package.json | 2 +- .../src/ratelimit/__tests__/util.test.ts | 32 +++++++++---------- packages/redwoodjs/src/ratelimit/index.ts | 4 +-- packages/redwoodjs/src/ratelimit/util.ts | 4 +-- packages/redwoodjs/tsconfig.json | 4 +-- packages/redwoodjs/vitest.config.mts | 4 +++ packages/redwoodjs/vitest.config.ts | 14 -------- pnpm-lock.yaml | 23 +------------ 8 files changed, 28 insertions(+), 59 deletions(-) create mode 100644 packages/redwoodjs/vitest.config.mts delete mode 100644 packages/redwoodjs/vitest.config.ts diff --git a/packages/redwoodjs/package.json b/packages/redwoodjs/package.json index 962adb3879..7902ec29f3 100644 --- a/packages/redwoodjs/package.json +++ b/packages/redwoodjs/package.json @@ -23,7 +23,7 @@ "author": "David Thyresson", "scripts": { "build": "tsup", - "test": "vitest" + "test": "vitest run" }, "dependencies": { "@redwoodjs/vite": "8.0.0-canary.542", diff --git a/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts index 17da8743b3..738d1052ca 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts @@ -1,4 +1,4 @@ -import type { MiddlewareRequest } from "@redwoodjs/vite/dist/middleware"; +import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import { assert, describe, expect, it } from "vitest"; import { defaultRatelimitIdentifier, matchesPath } from "../util"; @@ -6,22 +6,22 @@ describe("defaultRatelimitIdentifier", () => { it("should return correct identifier", () => { // Your test logic here const req = {} as MiddlewareRequest; - assert.equal(defaultRatelimitIdentifier(req), "default"); + assert.equal(defaultRatelimitIdentifier(req), "192.168.1.1"); }); }); -describe("matchesPath", () => { - it("should return true if path matches the pattern", () => { - const path = "/api/user"; - const pattern = "/api/*"; - const result = matchesPath(path, pattern); - expect(result).toBe(true); - }); +// describe("matchesPath", () => { +// it("should return true if path matches the pattern", () => { +// const path = "/api/user"; +// const pattern = "/api/*"; +// const result = matchesPath(path, pattern); +// expect(result).toBe(true); +// }); - it("should return false if path does not match the pattern", () => { - const path = "/api/user"; - const pattern = "/admin/*"; - const result = matchesPath(path, pattern); - expect(result).toBe(false); - }); -}); +// it("should return false if path does not match the pattern", () => { +// const path = "/api/user"; +// const pattern = "/admin/*"; +// const result = matchesPath(path, pattern); +// expect(result).toBe(false); +// }); +// }); diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index b154028f7c..ba6843a69c 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -4,8 +4,8 @@ import { Ratelimit } from "@unkey/ratelimit"; import type { RatelimitConfig } from "@unkey/ratelimit"; -import type { MiddlewareRequest } from "@redwoodjs/vite/dist/middleware"; -import type { MiddlewareResponse } from "@redwoodjs/vite/dist/middleware"; +import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; +import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; import { defaultRatelimitErrorResponse, diff --git a/packages/redwoodjs/src/ratelimit/util.ts b/packages/redwoodjs/src/ratelimit/util.ts index 0c2b3dc24d..abd019386f 100644 --- a/packages/redwoodjs/src/ratelimit/util.ts +++ b/packages/redwoodjs/src/ratelimit/util.ts @@ -1,7 +1,7 @@ import { type MatchFunction, match } from "path-to-regexp"; -import type { MiddlewareRequest } from "@redwoodjs/vite/dist/middleware"; -import { MiddlewareResponse } from "@redwoodjs/vite/dist/middleware"; +import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; +import { MiddlewareResponse } from "@redwoodjs/vite/middleware"; export type MiddlewarePathMatcher = string | string[]; diff --git a/packages/redwoodjs/tsconfig.json b/packages/redwoodjs/tsconfig.json index 5c14d7e03f..9e8524ce08 100644 --- a/packages/redwoodjs/tsconfig.json +++ b/packages/redwoodjs/tsconfig.json @@ -23,9 +23,9 @@ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ /* Modules */ - // "module": "CommonJS", /* Specify what module code is generated. */ + "module": "NodeNext" /* Specify what module code is generated. */, // "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, + "moduleResolution": "NodeNext" /* Specify how TypeScript looks up a file from a given module specifier. */, // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ diff --git a/packages/redwoodjs/vitest.config.mts b/packages/redwoodjs/vitest.config.mts new file mode 100644 index 0000000000..34eae339ae --- /dev/null +++ b/packages/redwoodjs/vitest.config.mts @@ -0,0 +1,4 @@ +import path from "node:path"; +import { defineConfig } from "vitest/config"; + +export default defineConfig({}); diff --git a/packages/redwoodjs/vitest.config.ts b/packages/redwoodjs/vitest.config.ts deleted file mode 100644 index 71447bc163..0000000000 --- a/packages/redwoodjs/vitest.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import path from "node:path"; -import { configDefaults, defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - include: [...configDefaults.include, "**/__tests__/**/*.{ts,tsx}"], - deps: { - moduleDirectories: [ - "node_modules", - path.resolve("../node_modules/@redwoodjs/vite/dist/middleware"), - ], - }, - }, -}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 61fa97405d..a534f6122d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8040,7 +8040,7 @@ packages: unenv: 1.9.0 unplugin: 1.10.1 vite: 5.2.10(@types/node@20.12.7) - vite-node: 1.5.3(@types/node@20.12.7) + vite-node: 1.6.0(@types/node@20.12.7) vite-plugin-checker: 0.6.4(typescript@5.3.3)(vite@5.2.10) vue: 3.4.23(typescript@5.3.3) vue-bundle-renderer: 2.0.0 @@ -28874,27 +28874,6 @@ packages: - terser dev: true - /vite-node@1.5.3(@types/node@20.12.7): - resolution: {integrity: sha512-axFo00qiCpU/JLd8N1gu9iEYL3xTbMbMrbe5nDp9GL0nb6gurIdZLkkFogZXWnE8Oyy5kfSLwNVIcVsnhE7lgQ==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - dependencies: - cac: 6.7.14 - debug: 4.3.4 - pathe: 1.1.2 - picocolors: 1.0.0 - vite: 5.2.10(@types/node@20.12.7) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - /vite-node@1.6.0(@types/node@20.12.7): resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} engines: {node: ^18.0.0 || >=20.0.0} From 1b6e655a2b29e96d4d4e1991c7c57cd3e47480de Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Mon, 6 May 2024 14:09:22 -0400 Subject: [PATCH 05/33] get to green --- .../src/ratelimit/__tests__/util.test.ts | 27 ---------- .../util/defaultRatelimitIdentifier.test.ts | 31 +++++++++++ .../__tests__/util/matchesPath.test.ts | 32 ++++++++++++ packages/redwoodjs/src/ratelimit/util.ts | 51 ++++++++++++------- 4 files changed, 97 insertions(+), 44 deletions(-) delete mode 100644 packages/redwoodjs/src/ratelimit/__tests__/util.test.ts create mode 100644 packages/redwoodjs/src/ratelimit/__tests__/util/defaultRatelimitIdentifier.test.ts create mode 100644 packages/redwoodjs/src/ratelimit/__tests__/util/matchesPath.test.ts diff --git a/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts deleted file mode 100644 index 738d1052ca..0000000000 --- a/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; -import { assert, describe, expect, it } from "vitest"; -import { defaultRatelimitIdentifier, matchesPath } from "../util"; - -describe("defaultRatelimitIdentifier", () => { - it("should return correct identifier", () => { - // Your test logic here - const req = {} as MiddlewareRequest; - assert.equal(defaultRatelimitIdentifier(req), "192.168.1.1"); - }); -}); - -// describe("matchesPath", () => { -// it("should return true if path matches the pattern", () => { -// const path = "/api/user"; -// const pattern = "/api/*"; -// const result = matchesPath(path, pattern); -// expect(result).toBe(true); -// }); - -// it("should return false if path does not match the pattern", () => { -// const path = "/api/user"; -// const pattern = "/admin/*"; -// const result = matchesPath(path, pattern); -// expect(result).toBe(false); -// }); -// }); diff --git a/packages/redwoodjs/src/ratelimit/__tests__/util/defaultRatelimitIdentifier.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/util/defaultRatelimitIdentifier.test.ts new file mode 100644 index 0000000000..6091598cd4 --- /dev/null +++ b/packages/redwoodjs/src/ratelimit/__tests__/util/defaultRatelimitIdentifier.test.ts @@ -0,0 +1,31 @@ +import { MiddlewareRequest } from "@redwoodjs/vite/middleware"; +import { assert, describe, expect, it } from "vitest"; +import { defaultRatelimitIdentifier } from "../../util"; + +describe("defaultRatelimitIdentifier", () => { + it("should return correct identifier", () => { + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + assert.equal(defaultRatelimitIdentifier(req), "192.168.1.1"); + }); + + it("when authenticated, should return correct identifier", () => { + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + req.serverAuthContext.set({ + isAuthenticated: true, + currentUser: { id: 1 }, + }); + assert.equal(defaultRatelimitIdentifier(req), "eyJpZCI6MX0="); + }); + + it("when not authenticated, should return correct identifier", () => { + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + req.serverAuthContext.set({ + isAuthenticated: false, + currentUser: { id: 1 }, + }); + assert.equal(defaultRatelimitIdentifier(req), "192.168.1.1"); + }); +}); diff --git a/packages/redwoodjs/src/ratelimit/__tests__/util/matchesPath.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/util/matchesPath.test.ts new file mode 100644 index 0000000000..86c1e64203 --- /dev/null +++ b/packages/redwoodjs/src/ratelimit/__tests__/util/matchesPath.test.ts @@ -0,0 +1,32 @@ +import { assert, describe, expect, it } from "vitest"; +import { matchesPath } from "../../util"; + +describe("matchesPath", () => { + it("should return true if path matches the exact pattern", () => { + const path = "/api/user"; + const pattern = "/api/user"; + const result = matchesPath(path, pattern); + expect(result).toBe(true); + }); + + it("should return true if path matches the pattern with any", () => { + const path = "/api/user"; + const pattern = "/api/(.*)"; + const result = matchesPath(path, pattern); + expect(result).toBe(true); + }); + + it("should return true if path matches the patter with a slug", () => { + const path = "/api/user/123"; + const pattern = "/api/user/:id"; + const result = matchesPath(path, pattern); + expect(result).toBe(true); + }); + + it("should return false if path does not match the pattern", () => { + const path = "/api/user"; + const pattern = "/admin"; + const result = matchesPath(path, pattern); + expect(result).toBe(false); + }); +}); diff --git a/packages/redwoodjs/src/ratelimit/util.ts b/packages/redwoodjs/src/ratelimit/util.ts index abd019386f..803ee6562a 100644 --- a/packages/redwoodjs/src/ratelimit/util.ts +++ b/packages/redwoodjs/src/ratelimit/util.ts @@ -1,10 +1,13 @@ -import { type MatchFunction, match } from "path-to-regexp"; - import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import { MiddlewareResponse } from "@redwoodjs/vite/middleware"; +import { match } from "path-to-regexp"; +import type { MatchFunction } from "path-to-regexp"; export type MiddlewarePathMatcher = string | string[]; +/** + * defaultRatelimitIdentifier is the default function to generate a ratelimit identifier + */ export const defaultRatelimitIdentifier = (req: MiddlewareRequest) => { const authContext = req?.serverAuthContext?.get(); const identifier = authContext?.isAuthenticated @@ -13,25 +16,39 @@ export const defaultRatelimitIdentifier = (req: MiddlewareRequest) => { return identifier; }; -export const matchesPath = (path: string, matcher: MiddlewarePathMatcher): boolean => { - // Convert matcher to an array if it's not already one - const matchers = Array.isArray(matcher) ? matcher : [matcher]; - - console.debug(">>>> in matchesPath", matchers, path); - - // Create a list of matching functions from the matchers - const matchingFunctions: MatchFunction[] = matchers.map((pattern) => - match(pattern, { decode: decodeURIComponent }), - ); - - // Check if the path matches any of the patterns - return matchingFunctions.some((matchFunc) => matchFunc(path) !== false); -}; - +/* + * defaultRatelimitExceededResponse is the default response when the rate limit is exceeded + */ export const defaultRatelimitExceededResponse = (_req: MiddlewareRequest) => { return new MiddlewareResponse("Rate limit exceeded", { status: 429 }); }; +/** + * defaultRatelimitErrorResponse is the default response when there is an error with the rate limit + */ export const defaultRatelimitErrorResponse = (_req: MiddlewareRequest) => { return new MiddlewareResponse("Internal server error", { status: 500 }); }; + +/** + * matchesPath checks if a path matches a pattern + */ +export const matchesPath = (path: string, matcher: MiddlewarePathMatcher): boolean => { + try { + // Convert matcher to an array if it's not already one + const matchers = Array.isArray(matcher) ? matcher : [matcher]; + + console.debug(">>>> in matchesPath", matchers, path); + + // Create a list of matching functions from the matchers + const matchingFunctions: MatchFunction[] = matchers.map((pattern) => { + return match(pattern, { decode: decodeURIComponent }); + }); + + // Check if the path matches any of the patterns + return matchingFunctions.some((matchFunc) => matchFunc(path) !== false); + } catch (e) { + console.error("Error in matchesPath", e); + throw e; + } +}; From 6e35a371e8fc68303619abd3df6979296a2412e2 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Mon, 6 May 2024 14:35:36 -0400 Subject: [PATCH 06/33] added some ratelimit mocking --- .../src/ratelimit/__tests__/withUnkey.test.ts | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts diff --git a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts new file mode 100644 index 0000000000..546200aed8 --- /dev/null +++ b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts @@ -0,0 +1,78 @@ +import { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; +import { Ratelimit } from "@unkey/ratelimit"; +import type { RatelimitConfig, RatelimitResponse } from "@unkey/ratelimit"; +import { assert, describe, expect, it, vi } from "vitest"; +import withUnkey from "../index"; +import type { withUnkeyOptions } from "../index"; + +/** + * Mock the Ratelimit class + * + * Use namespace to store the ratelimit identifier that determines if the rate limit is exceeded + * + * If namespace matches the identifier generated by withUnkey middlewate, the rate limit is exceeded + * and the response status is 429 because success is false + */ +vi.mock("@unkey/ratelimit", () => { + let rateLimitIdentifier = ""; + + return { + Ratelimit: class { + constructor(config: RatelimitConfig) { + console.debug(">>>> in Ratelimit constructor", config); + rateLimitIdentifier = config.namespace; + } + limit(identifier: string): Promise { + console.debug(">>>> in limit", identifier); + return Promise.resolve({ + success: identifier === rateLimitIdentifier, + limit: 0, + remaining: 0, + reset: 0, + }); + } + }, + }; +}); + +describe("withUnkey", () => { + it("should work", async () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: "foo", + namespace: "192.168.1.1", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/api/user"], + }; + const unkeyMiddleware = withUnkey(options); + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = await unkeyMiddleware(req, res); + expect(result.status).toBe(200); + }); + + it("should be limited", async () => { + // here the namespace will cause the rate limit to be exceeded because it does not match the identifier + // generated by the withUnkey middleware + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: "foo", + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/api/user"], + }; + const unkeyMiddleware = withUnkey(options); + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = await unkeyMiddleware(req, res); + expect(result.status).toBe(429); + }); +}); From e71d942b0a15fce64fbc3d736df48e4f349e2bed Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Mon, 6 May 2024 15:07:50 -0400 Subject: [PATCH 07/33] Fixes custom error logic --- .../src/ratelimit/__tests__/withUnkey.test.ts | 128 ++++++++++++++++++ packages/redwoodjs/src/ratelimit/index.ts | 10 +- 2 files changed, 134 insertions(+), 4 deletions(-) diff --git a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts index 546200aed8..a89128eb42 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts @@ -36,6 +36,26 @@ vi.mock("@unkey/ratelimit", () => { }); describe("withUnkey", () => { + it("should pass response through as path does not match", async () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: "foo", + namespace: "192.168.1.1", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/api/user"], + }; + const unkeyMiddleware = withUnkey(options); + const request = new Request("http://localhost:8910/api/no/match"); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse("PASS THROUGH OK", { status: 200 }); + const result = await unkeyMiddleware(req, res); + expect(result.status).toBe(200); + expect(result.body).toBe("PASS THROUGH OK"); + }); + it("should work", async () => { const options: withUnkeyOptions = { ratelimitConfig: { @@ -75,4 +95,112 @@ describe("withUnkey", () => { const result = await unkeyMiddleware(req, res); expect(result.status).toBe(429); }); + + it("should be not limited with a custom default identifier function", async () => { + // here the namespace will cause the rate limit to be exceeded because it does not match the identifier + // generated by the withUnkey middleware + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: "foo", + namespace: "abcdefg", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/api/user"], + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + return "abcdefg"; + }, + }; + const unkeyMiddleware = withUnkey(options); + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = await unkeyMiddleware(req, res); + expect(result.status).toBe(200); + }); + + it("should be limited with a custom default identifier function", async () => { + // here the namespace will cause the rate limit to be exceeded because it does not match the identifier + // generated by the withUnkey middleware + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: "foo", + namespace: "12345", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/api/user"], + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + return "abcdefg"; + }, + }; + const unkeyMiddleware = withUnkey(options); + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = await unkeyMiddleware(req, res); + expect(result.status).toBe(429); + }); + + it("should be limited with a custom rate limit exceeded message function", async () => { + // here the namespace will cause the rate limit to be exceeded because it does not match the identifier + // generated by the withUnkey middleware + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: "foo", + namespace: "exceeded", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/api/user"], + ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Rate limit exceeded message", { + status: 429, + }); + }, + }; + const unkeyMiddleware = withUnkey(options); + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = await unkeyMiddleware(req, res); + expect(result.status).toBe(429); + expect(result.body).toBe("Custom Rate limit exceeded message"); + }); + + it("should error", async () => { + // here the namespace will cause the rate limit to be exceeded because it does not match the identifier + // generated by the withUnkey middleware + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: "foo", + namespace: "exceeded", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/api/user"], + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + console.debug(">>>> in ratelimitIdentifierFn"); + throw new Error("Error simulated by test"); + }, + ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + console.debug(">>>> in ratelimitErrorResponseFn"); + return new MiddlewareResponse("Custom Error message when rate limiting", { + status: 500, + }); + }, + }; + const unkeyMiddleware = withUnkey(options); + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = await unkeyMiddleware(req, res); + + expect(result.body).toBe("Custom Error message when rate limiting"); + expect(result.status).toBe(500); + }); }); diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index ba6843a69c..20c76b6f11 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -61,13 +61,15 @@ const withUnkey = (options: withUnkeyOptions) => { } } catch (e) { console.error("Error in withUnkey", e); - const response = rateLimitErrorResponse(req); - if (response.status === 500) { + const errorResponse = rateLimitErrorResponse(req); + if (errorResponse.status !== 500) { console.warn( - "Rate limit error response is 200 OK. Consider changing status to 500.", - response, + `Rate limit error response is ${errorResponse.status}. Consider changing status to 500.`, + errorResponse, ); } + + return errorResponse; } console.debug(">>>> in withUnkey return response for", req.url); From 07d96a33ee3fea7b6bec27516384491a1c466e52 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Mon, 6 May 2024 16:12:58 -0400 Subject: [PATCH 08/33] Support redwoodjs logger --- packages/redwoodjs/console | 2 + packages/redwoodjs/package.json | 2 + .../src/ratelimit/__tests__/withUnkey.test.ts | 120 +++++++++++++++++- packages/redwoodjs/src/ratelimit/index.ts | 30 +++-- packages/redwoodjs/src/ratelimit/util.ts | 2 - pnpm-lock.yaml | 20 ++- 6 files changed, 151 insertions(+), 25 deletions(-) create mode 100644 packages/redwoodjs/console diff --git a/packages/redwoodjs/console b/packages/redwoodjs/console new file mode 100644 index 0000000000..64c0ddf128 --- /dev/null +++ b/packages/redwoodjs/console @@ -0,0 +1,2 @@ +{"level":60,"time":1715026201796,"pid":94751,"hostname":"depthcharge-air-3303.local","msg":">>> Unkey bopom"} +{"level":50,"time":1715026201796,"pid":94751,"hostname":"depthcharge-air-3303.local","msg":"Error in withUnkey"} diff --git a/packages/redwoodjs/package.json b/packages/redwoodjs/package.json index 7902ec29f3..4f4148bc7f 100644 --- a/packages/redwoodjs/package.json +++ b/packages/redwoodjs/package.json @@ -26,8 +26,10 @@ "test": "vitest run" }, "dependencies": { + "@redwoodjs/api": "8.0.0-canary.542", "@redwoodjs/vite": "8.0.0-canary.542", "@unkey/ratelimit": "workspace:^", + "abstract-logging": "^2.0.1", "path-to-regexp": "^6.2.2" }, "devDependencies": { diff --git a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts index a89128eb42..0797c06b50 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts @@ -1,3 +1,4 @@ +import { createLogger } from "@redwoodjs/api/logger"; import { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; import { Ratelimit } from "@unkey/ratelimit"; import type { RatelimitConfig, RatelimitResponse } from "@unkey/ratelimit"; @@ -10,7 +11,7 @@ import type { withUnkeyOptions } from "../index"; * * Use namespace to store the ratelimit identifier that determines if the rate limit is exceeded * - * If namespace matches the identifier generated by withUnkey middlewate, the rate limit is exceeded + * If namespace matches the identifier generated by withUnkey middleware, the rate limit is exceeded * and the response status is 429 because success is false */ vi.mock("@unkey/ratelimit", () => { @@ -19,11 +20,9 @@ vi.mock("@unkey/ratelimit", () => { return { Ratelimit: class { constructor(config: RatelimitConfig) { - console.debug(">>>> in Ratelimit constructor", config); rateLimitIdentifier = config.namespace; } limit(identifier: string): Promise { - console.debug(">>>> in limit", identifier); return Promise.resolve({ success: identifier === rateLimitIdentifier, limit: 0, @@ -96,6 +95,27 @@ describe("withUnkey", () => { expect(result.status).toBe(429); }); + it("should be limited when matches one of provided matcher patterns", async () => { + // here the namespace will cause the rate limit to be exceeded because it does not match the identifier + // generated by the withUnkey middleware + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: "foo", + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/api/no-match", "/api/it-matches"], + }; + const unkeyMiddleware = withUnkey(options); + const request = new Request("http://localhost:8910/api/it-matches"); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = await unkeyMiddleware(req, res); + expect(result.status).toBe(429); + }); + it("should be not limited with a custom default identifier function", async () => { // here the namespace will cause the rate limit to be exceeded because it does not match the identifier // generated by the withUnkey middleware @@ -184,11 +204,35 @@ describe("withUnkey", () => { }, matcher: ["/api/user"], ratelimitIdentifierFn: (_req: MiddlewareRequest) => { - console.debug(">>>> in ratelimitIdentifierFn"); + throw new Error("Error simulated by test"); + }, + }; + const unkeyMiddleware = withUnkey(options); + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = await unkeyMiddleware(req, res); + + expect(result.body).toBe("Internal server error"); + expect(result.status).toBe(500); + }); + + it("should error with custom message", async () => { + // here the namespace will cause the rate limit to be exceeded because it does not match the identifier + // generated by the withUnkey middleware + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: "foo", + namespace: "exceeded", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/api/user"], + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { throw new Error("Error simulated by test"); }, ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { - console.debug(">>>> in ratelimitErrorResponseFn"); return new MiddlewareResponse("Custom Error message when rate limiting", { status: 500, }); @@ -203,4 +247,70 @@ describe("withUnkey", () => { expect(result.body).toBe("Custom Error message when rate limiting"); expect(result.status).toBe(500); }); + + it("should error with custom message and status", async () => { + // here the namespace will cause the rate limit to be exceeded because it does not match the identifier + // generated by the withUnkey middleware + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: "foo", + namespace: "exceeded", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/api/user"], + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + throw new Error("Error simulated by test"); + }, + ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Not implemented", { + status: 501, + }); + }, + }; + const unkeyMiddleware = withUnkey(options); + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = await unkeyMiddleware(req, res); + + expect(result.body).toBe("Not implemented"); + expect(result.status).toBe(501); + }); + + it("should use a RedwoodJS-compatible logger", async () => { + // here the namespace will cause the rate limit to be exceeded because it does not match the identifier + // generated by the withUnkey middleware + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: "foo", + namespace: "exceeded", + limit: 1, + duration: "30s", + async: true, + }, + logger: createLogger({ + options: { level: "error", enabled: true }, + }), + + matcher: ["/api/user"], + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + throw new Error("Error simulated by test"); + }, + ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Not implemented", { + status: 501, + }); + }, + }; + const unkeyMiddleware = withUnkey(options); + const request = new Request("http://localhost:8910/api/user"); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = await unkeyMiddleware(req, res); + + expect(result.body).toBe("Not implemented"); + expect(result.status).toBe(501); + }); }); diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index 20c76b6f11..b16173e27e 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -1,12 +1,11 @@ //import { Unkey } from "@unkey/api"; //import { version } from "../../package.json"; -import { Ratelimit } from "@unkey/ratelimit"; -import type { RatelimitConfig } from "@unkey/ratelimit"; - +import type { Logger } from "@redwoodjs/api/logger"; import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; - +import { Ratelimit } from "@unkey/ratelimit"; +import type { RatelimitConfig } from "@unkey/ratelimit"; import { defaultRatelimitErrorResponse, defaultRatelimitExceededResponse, @@ -15,19 +14,23 @@ import { } from "./util"; import type { MiddlewarePathMatcher } from "./util"; +const defaultLogger = require("abstract-logging") as Logger; + export type withUnkeyOptions = { ratelimitConfig: RatelimitConfig; matcher: MiddlewarePathMatcher; + logger?: Logger; ratelimitIdentifierFn?: (req: MiddlewareRequest) => string; ratelimitExceededResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; ratelimitErrorResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; }; const withUnkey = (options: withUnkeyOptions) => { - console.debug(">>>> in withUnkey createMiddleware", options); const unkey = new Ratelimit(options.ratelimitConfig); return async (req: MiddlewareRequest, res: MiddlewareResponse) => { + const logger = options.logger || defaultLogger; + logger.fatal(">>> Unkey bopom"); const ratelimitIdentifier = options.ratelimitIdentifierFn || defaultRatelimitIdentifier; const rateLimitExceededResponse = @@ -41,29 +44,32 @@ const withUnkey = (options: withUnkeyOptions) => { const path = url.pathname; if (!matchesPath(path, options.matcher)) { - console.debug(">>>> in withUnkey skip middleware for", req.url); return res; } const identifier = ratelimitIdentifier(req); - console.debug(">>>> in withUnkey identifier", identifier); const ratelimit = await unkey.limit(identifier); if (!ratelimit.success) { - console.error("Rate limit exceeded", ratelimit); + logger.debug("Rate limit exceeded", { + ratelimit, + url, + path, + identifier, + }); const response = rateLimitExceededResponse(req); if (response.status !== 429) { - console.warn("Rate limit exceeded response is not 429. Overriding status.", response); + logger.warn("Rate limit exceeded response is not 429. Overriding status.", response); response.status = 429; } return response; } } catch (e) { - console.error("Error in withUnkey", e); + logger.error("Error in withUnkey", e); const errorResponse = rateLimitErrorResponse(req); if (errorResponse.status !== 500) { - console.warn( + logger.warn( `Rate limit error response is ${errorResponse.status}. Consider changing status to 500.`, errorResponse, ); @@ -72,8 +78,6 @@ const withUnkey = (options: withUnkeyOptions) => { return errorResponse; } - console.debug(">>>> in withUnkey return response for", req.url); - return res; }; }; diff --git a/packages/redwoodjs/src/ratelimit/util.ts b/packages/redwoodjs/src/ratelimit/util.ts index 803ee6562a..d47414e43c 100644 --- a/packages/redwoodjs/src/ratelimit/util.ts +++ b/packages/redwoodjs/src/ratelimit/util.ts @@ -38,8 +38,6 @@ export const matchesPath = (path: string, matcher: MiddlewarePathMatcher): boole // Convert matcher to an array if it's not already one const matchers = Array.isArray(matcher) ? matcher : [matcher]; - console.debug(">>>> in matchesPath", matchers, path); - // Create a list of matching functions from the matchers const matchingFunctions: MatchFunction[] = matchers.map((pattern) => { return match(pattern, { decode: decodeURIComponent }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a534f6122d..51c5251e4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1347,12 +1347,18 @@ importers: packages/redwoodjs: dependencies: + '@redwoodjs/api': + specifier: 8.0.0-canary.542 + version: 8.0.0-canary.542 '@redwoodjs/vite': specifier: 8.0.0-canary.542 version: 8.0.0-canary.542(@types/node@20.12.7)(csstype@3.1.3)(graphql-tag@2.12.6)(react-dom@18.3.1)(webpack@5.91.0) '@unkey/ratelimit': specifier: workspace:^ version: link:../ratelimit + abstract-logging: + specifier: ^2.0.1 + version: 2.0.1 path-to-regexp: specifier: ^6.2.2 version: 6.2.2 @@ -8953,7 +8959,7 @@ packages: resolution: {integrity: sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==} engines: {node: '>=8.0.0'} dependencies: - tslib: 2.4.1 + tslib: 2.6.2 dev: false /@peculiar/webcrypto@1.4.1: @@ -8963,7 +8969,7 @@ packages: '@peculiar/asn1-schema': 2.3.8 '@peculiar/json-schema': 1.1.12 pvtsutils: 1.3.5 - tslib: 2.4.1 + tslib: 2.6.2 webcrypto-core: 1.7.9 dev: false @@ -14488,6 +14494,10 @@ packages: dependencies: event-target-shim: 5.0.1 + /abstract-logging@2.0.1: + resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + dev: false + /accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -17040,7 +17050,7 @@ packages: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} dependencies: no-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.6.2 dev: false /dot-prop@8.0.2: @@ -22958,7 +22968,7 @@ packages: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} dependencies: lower-case: 2.0.2 - tslib: 2.4.1 + tslib: 2.6.2 dev: false /node-addon-api@7.1.0: @@ -26549,7 +26559,7 @@ packages: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} dependencies: dot-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.6.2 dev: false /snakecase-keys@3.2.1: From 495e268015b4fabd36d481b22990e7edca9a43ba Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Tue, 7 May 2024 10:05:17 -0400 Subject: [PATCH 09/33] Added docs --- packages/redwoodjs/src/ratelimit/README.md | 145 +++++++++++++----- .../src/ratelimit/__tests__/withUnkey.test.ts | 64 +++----- packages/redwoodjs/src/ratelimit/index.ts | 46 +++++- packages/redwoodjs/src/ratelimit/util.ts | 4 + 4 files changed, 173 insertions(+), 86 deletions(-) diff --git a/packages/redwoodjs/src/ratelimit/README.md b/packages/redwoodjs/src/ratelimit/README.md index 4c05d1f2e2..be378be445 100644 --- a/packages/redwoodjs/src/ratelimit/README.md +++ b/packages/redwoodjs/src/ratelimit/README.md @@ -1,6 +1,6 @@ # withUnkey -RedwoodJS Middleware to rate limit requests +RedwoodJS Middleware to rate limit requests using Unkey Ratelimiting ## Setup @@ -10,7 +10,40 @@ Note: Be sure to set your `UNKEY_ROOT_KEY` or key to be used for rate limiting i ## Examples -### With Third Party Authentication like Supabase +`withUnkey` provides several ways to customize rate limiting for a variety of use cases. + +The following examples sow how to set: + +- pattern `matcher`s to match paths on which to enforce rate limits +- custom identifier generator function +- custom rate limit exceeded responses +- custom error responses + +### Basic Matching + +```ts file="web/src/entry.server.tsx" +import withUnkey from "@unkey/redwoodjs"; +import type { withUnkeyOptions } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/blog-post/:slug(\\d{1,})"], + }; + + const unkeyMiddleware = withUnkey(options); + + return [unkeyMiddleware]; +}; +``` + +### With Custom Identifier Function and Third Party Authentication Here, we use a custom identifier function `supabaseRatelimitIdentifier` that: @@ -18,70 +51,100 @@ Here, we use a custom identifier function `supabaseRatelimitIdentifier` that: - constructs the identifier `sub` from the current user, since here the currentUser will be a JWT where the user id is the `sub` claim - registers `supabaseAuthMiddleware` before `unkeyMiddleware` so the request can be authenticated before determining limits -```file="web/entry.server.ts" -import createSupabaseAuthMiddleware from '@redwoodjs/auth-supabase-middleware' -import type { MiddlewareRequest } from '@redwoodjs/vite/middleware' -import type { TagDescriptor } from '@redwoodjs/web' +```ts file="web/src/entry.server.ts" +import createSupabaseAuthMiddleware from "@redwoodjs/auth-supabase-middleware"; +import withUnkey from "@unkey/redwoodjs"; +import type { withUnkeyOptions } from "@unkey/redwoodjs"; +import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; +import type { TagDescriptor } from "@redwoodjs/web"; -import App from './App' -import { Document } from './Document' -import withUnkey from '@unkey/redwoodjs' -import type { withUnkeyOptions } from '@unkey/redwoodjs' +import App from "./App"; +import { Document } from "./Document"; // eslint-disable-next-line no-restricted-imports -import { getCurrentUser } from '$api/src/lib/auth' +import { getCurrentUser } from "$api/src/lib/auth"; interface Props { - css: string[] - meta?: TagDescriptor[] + css: string[]; + meta?: TagDescriptor[]; } export const supabaseRatelimitIdentifier = (req: MiddlewareRequest) => { - const authContext = req?.serverAuthContext?.get() - console.log('>>>> in supabaseRatelimitIdentifier', authContext) + const authContext = req?.serverAuthContext?.get(); + console.log(">>>> in supabaseRatelimitIdentifier", authContext); const identifier = authContext?.isAuthenticated - ? (authContext.currentUser?.sub as string) || 'anonymous-user' - : '192.168.1.1' - return identifier -} + ? (authContext.currentUser?.sub as string) || "anonymous-user" + : "192.168.1.1"; + return identifier; +}; export const registerMiddleware = () => { const options: withUnkeyOptions = { ratelimitConfig: { rootKey: process.env.UNKEY_ROOT_KEY, - namespace: 'my-app', + namespace: "my-app", limit: 1, - duration: '30s', + duration: "30s", async: true, }, - matcher: ['/blog-post/:slug(\\d{1,})'], + matcher: ["/blog-post/:slug(\\d{1,})"], ratelimitIdentifierFn: supabaseRatelimitIdentifier, - } - const unkeyMiddleware = withUnkey(options) + }; + const unkeyMiddleware = withUnkey(options); const supabaseAuthMiddleware = createSupabaseAuthMiddleware({ getCurrentUser, - }) - return [supabaseAuthMiddleware, unkeyMiddleware] -} - -interface Props { - css: string[] - meta?: TagDescriptor[] -} + }); -export const ServerEntry: React.FC = ({ css, meta }) => { - return ( - - - - ) -} + return [supabaseAuthMiddleware, unkeyMiddleware]; +}; ``` ## Custom Rate Limit Exceeded Response -TODO +```ts +export const registerMiddleware = () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/blog-post/:slug(\\d{1,})"], + ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Rate limit exceeded message", { + status: 429, + }); + }, + }; + const unkeyMiddleware = withUnkey(options); + + return [unkeyMiddleware]; +}; +``` ## Custom Rate Limit Error Response -TODO +```ts +export const registerMiddleware = () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/blog-post/:slug(\\d{1,})"], + ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Error message when rate limiting", { + status: 500, + }); + }, + }; + const unkeyMiddleware = withUnkey(options); + + return [unkeyMiddleware]; +}; +``` diff --git a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts index 0797c06b50..5a8f66bbdd 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts @@ -34,15 +34,21 @@ vi.mock("@unkey/ratelimit", () => { }; }); +const MOCK_ROOT_KEY = "unkey_mocked_root_key"; + +const defaultRateLimitConfig: Pick = { + rootKey: MOCK_ROOT_KEY, + limit: 1, + duration: "30s", + async: true, +}; + describe("withUnkey", () => { it("should pass response through as path does not match", async () => { const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: "foo", namespace: "192.168.1.1", - limit: 1, - duration: "30s", - async: true, + ...defaultRateLimitConfig, }, matcher: ["/api/user"], }; @@ -58,11 +64,8 @@ describe("withUnkey", () => { it("should work", async () => { const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: "foo", namespace: "192.168.1.1", - limit: 1, - duration: "30s", - async: true, + ...defaultRateLimitConfig, }, matcher: ["/api/user"], }; @@ -79,11 +82,8 @@ describe("withUnkey", () => { // generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: "foo", namespace: "my-app", - limit: 1, - duration: "30s", - async: true, + ...defaultRateLimitConfig, }, matcher: ["/api/user"], }; @@ -100,11 +100,8 @@ describe("withUnkey", () => { // generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: "foo", namespace: "my-app", - limit: 1, - duration: "30s", - async: true, + ...defaultRateLimitConfig, }, matcher: ["/api/no-match", "/api/it-matches"], }; @@ -121,11 +118,8 @@ describe("withUnkey", () => { // generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: "foo", namespace: "abcdefg", - limit: 1, - duration: "30s", - async: true, + ...defaultRateLimitConfig, }, matcher: ["/api/user"], ratelimitIdentifierFn: (_req: MiddlewareRequest) => { @@ -145,11 +139,8 @@ describe("withUnkey", () => { // generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: "foo", namespace: "12345", - limit: 1, - duration: "30s", - async: true, + ...defaultRateLimitConfig, }, matcher: ["/api/user"], ratelimitIdentifierFn: (_req: MiddlewareRequest) => { @@ -169,11 +160,8 @@ describe("withUnkey", () => { // generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: "foo", namespace: "exceeded", - limit: 1, - duration: "30s", - async: true, + ...defaultRateLimitConfig, }, matcher: ["/api/user"], ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { @@ -196,11 +184,8 @@ describe("withUnkey", () => { // generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: "foo", namespace: "exceeded", - limit: 1, - duration: "30s", - async: true, + ...defaultRateLimitConfig, }, matcher: ["/api/user"], ratelimitIdentifierFn: (_req: MiddlewareRequest) => { @@ -222,11 +207,8 @@ describe("withUnkey", () => { // generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: "foo", namespace: "exceeded", - limit: 1, - duration: "30s", - async: true, + ...defaultRateLimitConfig, }, matcher: ["/api/user"], ratelimitIdentifierFn: (_req: MiddlewareRequest) => { @@ -253,11 +235,8 @@ describe("withUnkey", () => { // generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: "foo", namespace: "exceeded", - limit: 1, - duration: "30s", - async: true, + ...defaultRateLimitConfig, }, matcher: ["/api/user"], ratelimitIdentifierFn: (_req: MiddlewareRequest) => { @@ -284,11 +263,8 @@ describe("withUnkey", () => { // generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: "foo", namespace: "exceeded", - limit: 1, - duration: "30s", - async: true, + ...defaultRateLimitConfig, }, logger: createLogger({ options: { level: "error", enabled: true }, diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index b16173e27e..9f82789915 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -25,12 +25,56 @@ export type withUnkeyOptions = { ratelimitErrorResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; }; +/** + * withUnkey is RedwoodJS middleware that adds Unkey rate limiting to a route + * + * @see https://redwoodjs.com/docs/middleware#withUnkey + * @see https://www.unkey.com/docs/apis/features/ratelimiting + * + * Provide the Unkey rate limit configuration and the path matcher to apply the rate limit to. + * + * @param options ratelimitConfig: RatelimitConfig; + * @param options matcher: MiddlewarePathMatcher; + * + * You can provide optional custom functions to construct rate limit identifier, + * rate limit exceeded response, and rate limit error response. + * + * @param options ratelimitIdentifierFn?: (req: MiddlewareRequest) => string; + * @param options ratelimitExceededResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; + * @param options ratelimitErrorResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; + * + * @param options logger?: Logger; + * + * @example + * ```ts file="web/src/entry.server.tsx" + * + * import withUnkey from '@unkey/redwoodjs' + * import type { withUnkeyOptions } from '@unkey/redwoodjs' + * + * export const registerMiddleware = () => { + * const options: withUnkeyOptions = { + * ratelimitConfig: { + * rootKey: process.env.UNKEY_ROOT_KEY, + * namespace: 'my-app', + * limit: 1, + * duration: '30s', + * async: true, + * }, + * matcher: ['/blog-post/:slug(\\d{1,})'], + * } + * + * const unkeyMiddleware = withUnkey(options) + * + * return [unkeyMiddleware] + * } + * ``` + */ const withUnkey = (options: withUnkeyOptions) => { const unkey = new Ratelimit(options.ratelimitConfig); return async (req: MiddlewareRequest, res: MiddlewareResponse) => { const logger = options.logger || defaultLogger; - logger.fatal(">>> Unkey bopom"); + const ratelimitIdentifier = options.ratelimitIdentifierFn || defaultRatelimitIdentifier; const rateLimitExceededResponse = diff --git a/packages/redwoodjs/src/ratelimit/util.ts b/packages/redwoodjs/src/ratelimit/util.ts index d47414e43c..c944cbc303 100644 --- a/packages/redwoodjs/src/ratelimit/util.ts +++ b/packages/redwoodjs/src/ratelimit/util.ts @@ -7,6 +7,10 @@ export type MiddlewarePathMatcher = string | string[]; /** * defaultRatelimitIdentifier is the default function to generate a ratelimit identifier + * + * Use the req serverAuthContext to access authentication information, if available + * in order to access a current user identifier + * */ export const defaultRatelimitIdentifier = (req: MiddlewareRequest) => { const authContext = req?.serverAuthContext?.get(); From 580db94b3efac7da72f2764842350b8f7e19e73a Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Tue, 7 May 2024 12:32:04 -0400 Subject: [PATCH 10/33] can rely on baked in middleware pattern route matching --- packages/redwoodjs/package.json | 3 +- packages/redwoodjs/src/ratelimit/README.md | 54 +++++++++-- .../__tests__/util/matchesPath.test.ts | 32 ------- .../src/ratelimit/__tests__/withUnkey.test.ts | 93 ++++++------------- packages/redwoodjs/src/ratelimit/index.ts | 14 --- packages/redwoodjs/src/ratelimit/util.ts | 25 ----- 6 files changed, 78 insertions(+), 143 deletions(-) delete mode 100644 packages/redwoodjs/src/ratelimit/__tests__/util/matchesPath.test.ts diff --git a/packages/redwoodjs/package.json b/packages/redwoodjs/package.json index 4f4148bc7f..b21b34571b 100644 --- a/packages/redwoodjs/package.json +++ b/packages/redwoodjs/package.json @@ -29,8 +29,7 @@ "@redwoodjs/api": "8.0.0-canary.542", "@redwoodjs/vite": "8.0.0-canary.542", "@unkey/ratelimit": "workspace:^", - "abstract-logging": "^2.0.1", - "path-to-regexp": "^6.2.2" + "abstract-logging": "^2.0.1" }, "devDependencies": { "@types/node": "^20.12.7", diff --git a/packages/redwoodjs/src/ratelimit/README.md b/packages/redwoodjs/src/ratelimit/README.md index be378be445..b81f1071e0 100644 --- a/packages/redwoodjs/src/ratelimit/README.md +++ b/packages/redwoodjs/src/ratelimit/README.md @@ -14,12 +14,14 @@ Note: Be sure to set your `UNKEY_ROOT_KEY` or key to be used for rate limiting i The following examples sow how to set: -- pattern `matcher`s to match paths on which to enforce rate limits +- pattern matches when registering the middleware to match paths on which to enforce rate limits - custom identifier generator function - custom rate limit exceeded responses - custom error responses -### Basic Matching +### Rate Limit All Requests + +To rate limit all requests, register the unkeyMiddleware without route matching. ```ts file="web/src/entry.server.tsx" import withUnkey from "@unkey/redwoodjs"; @@ -34,7 +36,6 @@ export const registerMiddleware = () => { duration: "30s", async: true, }, - matcher: ["/blog-post/:slug(\\d{1,})"], }; const unkeyMiddleware = withUnkey(options); @@ -43,6 +44,46 @@ export const registerMiddleware = () => { }; ``` +### Basic Matching + +To rate limit a matching rout, register the unkeyMiddleware with the matching pattern. + +```ts file="web/src/entry.server.tsx" +import withUnkey from "@unkey/redwoodjs"; +import type { withUnkeyOptions } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + }; + + const unkeyMiddleware = withUnkey(options); + + return [[unkeyMiddleware, "/blog-post/:slug(\\d{1,})"]]; +}; +``` + +Note: If you need to match multiple patterns you can compose a complex expression + +```ts +return [[unkeyMiddleware, "/rss.(xml|atom|json)"]]; +``` + +or register multiple with different patterns: + +```ts +return [ + [unkeyMiddleware, "/blog-post/:slug(\\d{1,})"], + [unkeyMiddleware, "/admin"], +]; +``` + ### With Custom Identifier Function and Third Party Authentication Here, we use a custom identifier function `supabaseRatelimitIdentifier` that: @@ -87,7 +128,6 @@ export const registerMiddleware = () => { duration: "30s", async: true, }, - matcher: ["/blog-post/:slug(\\d{1,})"], ratelimitIdentifierFn: supabaseRatelimitIdentifier, }; const unkeyMiddleware = withUnkey(options); @@ -95,7 +135,10 @@ export const registerMiddleware = () => { getCurrentUser, }); - return [supabaseAuthMiddleware, unkeyMiddleware]; + return [ + supabaseAuthMiddleware, + [unkeyMiddleware, "/blog-post/:slug(\\d{1,})"], + ]; }; ``` @@ -111,7 +154,6 @@ export const registerMiddleware = () => { duration: "30s", async: true, }, - matcher: ["/blog-post/:slug(\\d{1,})"], ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { return new MiddlewareResponse("Custom Rate limit exceeded message", { status: 429, diff --git a/packages/redwoodjs/src/ratelimit/__tests__/util/matchesPath.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/util/matchesPath.test.ts deleted file mode 100644 index 86c1e64203..0000000000 --- a/packages/redwoodjs/src/ratelimit/__tests__/util/matchesPath.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { assert, describe, expect, it } from "vitest"; -import { matchesPath } from "../../util"; - -describe("matchesPath", () => { - it("should return true if path matches the exact pattern", () => { - const path = "/api/user"; - const pattern = "/api/user"; - const result = matchesPath(path, pattern); - expect(result).toBe(true); - }); - - it("should return true if path matches the pattern with any", () => { - const path = "/api/user"; - const pattern = "/api/(.*)"; - const result = matchesPath(path, pattern); - expect(result).toBe(true); - }); - - it("should return true if path matches the patter with a slug", () => { - const path = "/api/user/123"; - const pattern = "/api/user/:id"; - const result = matchesPath(path, pattern); - expect(result).toBe(true); - }); - - it("should return false if path does not match the pattern", () => { - const path = "/api/user"; - const pattern = "/admin"; - const result = matchesPath(path, pattern); - expect(result).toBe(false); - }); -}); diff --git a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts index 5a8f66bbdd..abb93cffb7 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts @@ -13,6 +13,8 @@ import type { withUnkeyOptions } from "../index"; * * If namespace matches the identifier generated by withUnkey middleware, the rate limit is exceeded * and the response status is 429 because success is false + * + * Important: This behavior is for *this test mock only*. The actual Ratelimit class will *not* behave this way. */ vi.mock("@unkey/ratelimit", () => { let rateLimitIdentifier = ""; @@ -44,30 +46,12 @@ const defaultRateLimitConfig: Pick { - it("should pass response through as path does not match", async () => { + it("should not rate limit", async () => { const options: withUnkeyOptions = { ratelimitConfig: { namespace: "192.168.1.1", ...defaultRateLimitConfig, }, - matcher: ["/api/user"], - }; - const unkeyMiddleware = withUnkey(options); - const request = new Request("http://localhost:8910/api/no/match"); - const req = new MiddlewareRequest(request); - const res = new MiddlewareResponse("PASS THROUGH OK", { status: 200 }); - const result = await unkeyMiddleware(req, res); - expect(result.status).toBe(200); - expect(result.body).toBe("PASS THROUGH OK"); - }); - - it("should work", async () => { - const options: withUnkeyOptions = { - ratelimitConfig: { - namespace: "192.168.1.1", - ...defaultRateLimitConfig, - }, - matcher: ["/api/user"], }; const unkeyMiddleware = withUnkey(options); const request = new Request("http://localhost:8910/api/user"); @@ -77,15 +61,16 @@ describe("withUnkey", () => { expect(result.status).toBe(200); }); - it("should be limited", async () => { - // here the namespace will cause the rate limit to be exceeded because it does not match the identifier - // generated by the withUnkey middleware + it("should rate limit", async () => { + // here the namespace will cause the rate limit + // to be exceeded (status 429) because + // it does not match the identifier generated by the withUnkey middleware + // which is a defaulted value const options: withUnkeyOptions = { ratelimitConfig: { namespace: "my-app", ...defaultRateLimitConfig, }, - matcher: ["/api/user"], }; const unkeyMiddleware = withUnkey(options); const request = new Request("http://localhost:8910/api/user"); @@ -95,35 +80,18 @@ describe("withUnkey", () => { expect(result.status).toBe(429); }); - it("should be limited when matches one of provided matcher patterns", async () => { - // here the namespace will cause the rate limit to be exceeded because it does not match the identifier - // generated by the withUnkey middleware - const options: withUnkeyOptions = { - ratelimitConfig: { - namespace: "my-app", - ...defaultRateLimitConfig, - }, - matcher: ["/api/no-match", "/api/it-matches"], - }; - const unkeyMiddleware = withUnkey(options); - const request = new Request("http://localhost:8910/api/it-matches"); - const req = new MiddlewareRequest(request); - const res = new MiddlewareResponse(); - const result = await unkeyMiddleware(req, res); - expect(result.status).toBe(429); - }); - - it("should be not limited with a custom default identifier function", async () => { - // here the namespace will cause the rate limit to be exceeded because it does not match the identifier - // generated by the withUnkey middleware + it("should be not rate limited with a custom default identifier function", async () => { + // here the namespace will cause the rate limit + // not to be exceeded (status 200) because it + // matches the identifies generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { namespace: "abcdefg", ...defaultRateLimitConfig, }, - matcher: ["/api/user"], + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { - return "abcdefg"; + return "abcdefg"; // matches namespace so no rate limit for this test }, }; const unkeyMiddleware = withUnkey(options); @@ -135,14 +103,14 @@ describe("withUnkey", () => { }); it("should be limited with a custom default identifier function", async () => { - // here the namespace will cause the rate limit to be exceeded because it does not match the identifier - // generated by the withUnkey middleware + // here the namespace will cause the rate limit to be exceeded (status 429) + // because it does not match the identifier generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { namespace: "12345", ...defaultRateLimitConfig, }, - matcher: ["/api/user"], + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { return "abcdefg"; }, @@ -156,14 +124,14 @@ describe("withUnkey", () => { }); it("should be limited with a custom rate limit exceeded message function", async () => { - // here the namespace will cause the rate limit to be exceeded because it does not match the identifier - // generated by the withUnkey middleware + // here the namespace will cause the rate limit to be exceeded (status 429) + // because it does not match the identifier generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { namespace: "exceeded", ...defaultRateLimitConfig, }, - matcher: ["/api/user"], + ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { return new MiddlewareResponse("Custom Rate limit exceeded message", { status: 429, @@ -180,14 +148,14 @@ describe("withUnkey", () => { }); it("should error", async () => { - // here the namespace will cause the rate limit to be exceeded because it does not match the identifier - // generated by the withUnkey middleware + // here the the identifier function will throw an error + // which will cause a teh default error response to be returned const options: withUnkeyOptions = { ratelimitConfig: { namespace: "exceeded", ...defaultRateLimitConfig, }, - matcher: ["/api/user"], + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { throw new Error("Error simulated by test"); }, @@ -203,14 +171,14 @@ describe("withUnkey", () => { }); it("should error with custom message", async () => { - // here the namespace will cause the rate limit to be exceeded because it does not match the identifier - // generated by the withUnkey middleware + // here the the identifier function will throw an error + // which will cause the default error response to be returned const options: withUnkeyOptions = { ratelimitConfig: { namespace: "exceeded", ...defaultRateLimitConfig, }, - matcher: ["/api/user"], + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { throw new Error("Error simulated by test"); }, @@ -231,14 +199,14 @@ describe("withUnkey", () => { }); it("should error with custom message and status", async () => { - // here the namespace will cause the rate limit to be exceeded because it does not match the identifier - // generated by the withUnkey middleware + // here the the identifier function will throw an error + // which will cause a custom error response to be returned const options: withUnkeyOptions = { ratelimitConfig: { namespace: "exceeded", ...defaultRateLimitConfig, }, - matcher: ["/api/user"], + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { throw new Error("Error simulated by test"); }, @@ -259,8 +227,6 @@ describe("withUnkey", () => { }); it("should use a RedwoodJS-compatible logger", async () => { - // here the namespace will cause the rate limit to be exceeded because it does not match the identifier - // generated by the withUnkey middleware const options: withUnkeyOptions = { ratelimitConfig: { namespace: "exceeded", @@ -270,7 +236,6 @@ describe("withUnkey", () => { options: { level: "error", enabled: true }, }), - matcher: ["/api/user"], ratelimitIdentifierFn: (_req: MiddlewareRequest) => { throw new Error("Error simulated by test"); }, diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index 9f82789915..4537af7b75 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -10,15 +10,12 @@ import { defaultRatelimitErrorResponse, defaultRatelimitExceededResponse, defaultRatelimitIdentifier, - matchesPath, } from "./util"; -import type { MiddlewarePathMatcher } from "./util"; const defaultLogger = require("abstract-logging") as Logger; export type withUnkeyOptions = { ratelimitConfig: RatelimitConfig; - matcher: MiddlewarePathMatcher; logger?: Logger; ratelimitIdentifierFn?: (req: MiddlewareRequest) => string; ratelimitExceededResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; @@ -34,7 +31,6 @@ export type withUnkeyOptions = { * Provide the Unkey rate limit configuration and the path matcher to apply the rate limit to. * * @param options ratelimitConfig: RatelimitConfig; - * @param options matcher: MiddlewarePathMatcher; * * You can provide optional custom functions to construct rate limit identifier, * rate limit exceeded response, and rate limit error response. @@ -60,7 +56,6 @@ export type withUnkeyOptions = { * duration: '30s', * async: true, * }, - * matcher: ['/blog-post/:slug(\\d{1,})'], * } * * const unkeyMiddleware = withUnkey(options) @@ -84,13 +79,6 @@ const withUnkey = (options: withUnkeyOptions) => { options.ratelimitErrorResponseFn || defaultRatelimitErrorResponse; try { - const url = new URL(req.url); - const path = url.pathname; - - if (!matchesPath(path, options.matcher)) { - return res; - } - const identifier = ratelimitIdentifier(req); const ratelimit = await unkey.limit(identifier); @@ -98,8 +86,6 @@ const withUnkey = (options: withUnkeyOptions) => { if (!ratelimit.success) { logger.debug("Rate limit exceeded", { ratelimit, - url, - path, identifier, }); const response = rateLimitExceededResponse(req); diff --git a/packages/redwoodjs/src/ratelimit/util.ts b/packages/redwoodjs/src/ratelimit/util.ts index c944cbc303..a2e1c1388d 100644 --- a/packages/redwoodjs/src/ratelimit/util.ts +++ b/packages/redwoodjs/src/ratelimit/util.ts @@ -1,9 +1,5 @@ import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import { MiddlewareResponse } from "@redwoodjs/vite/middleware"; -import { match } from "path-to-regexp"; -import type { MatchFunction } from "path-to-regexp"; - -export type MiddlewarePathMatcher = string | string[]; /** * defaultRatelimitIdentifier is the default function to generate a ratelimit identifier @@ -33,24 +29,3 @@ export const defaultRatelimitExceededResponse = (_req: MiddlewareRequest) => { export const defaultRatelimitErrorResponse = (_req: MiddlewareRequest) => { return new MiddlewareResponse("Internal server error", { status: 500 }); }; - -/** - * matchesPath checks if a path matches a pattern - */ -export const matchesPath = (path: string, matcher: MiddlewarePathMatcher): boolean => { - try { - // Convert matcher to an array if it's not already one - const matchers = Array.isArray(matcher) ? matcher : [matcher]; - - // Create a list of matching functions from the matchers - const matchingFunctions: MatchFunction[] = matchers.map((pattern) => { - return match(pattern, { decode: decodeURIComponent }); - }); - - // Check if the path matches any of the patterns - return matchingFunctions.some((matchFunc) => matchFunc(path) !== false); - } catch (e) { - console.error("Error in matchesPath", e); - throw e; - } -}; From 3be79951930966ae2d207798fd9102b555536cdd Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Tue, 7 May 2024 13:46:30 -0400 Subject: [PATCH 11/33] ran fmt --- packages/redwoodjs/package.json | 10 ++-------- packages/redwoodjs/src/ratelimit/index.ts | 3 --- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/redwoodjs/package.json b/packages/redwoodjs/package.json index b21b34571b..72816cf433 100644 --- a/packages/redwoodjs/package.json +++ b/packages/redwoodjs/package.json @@ -8,18 +8,12 @@ "publishConfig": { "access": "public" }, - "keywords": [ - "unkey", - "redwoodjs", - "sdk" - ], + "keywords": ["unkey", "redwoodjs", "sdk"], "bugs": { "url": "https://github.com/unkeyed/unkey/issues" }, "homepage": "https://github.com/unkeyed/unkey#readme", - "files": [ - "./dist/**" - ], + "files": ["./dist/**"], "author": "David Thyresson", "scripts": { "build": "tsup", diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index 4537af7b75..b435746e36 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -1,6 +1,3 @@ -//import { Unkey } from "@unkey/api"; -//import { version } from "../../package.json"; - import type { Logger } from "@redwoodjs/api/logger"; import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; From 88af99cba6eaa2362dce8b1135e3bd6159ce7443 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Tue, 7 May 2024 14:43:04 -0400 Subject: [PATCH 12/33] remove path to exp --- pnpm-lock.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 51c5251e4f..f207eeff3c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1359,9 +1359,6 @@ importers: abstract-logging: specifier: ^2.0.1 version: 2.0.1 - path-to-regexp: - specifier: ^6.2.2 - version: 6.2.2 devDependencies: '@types/node': specifier: ^20.12.7 From 59aa8b57e85949b12c6706a199ce5b1f369194f2 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Wed, 8 May 2024 12:14:05 -0400 Subject: [PATCH 13/33] Adds redwoodjs library docs --- .../ts/redwoodjs/middleware/ratelimiting.mdx | 199 ++++++++++++++++++ apps/docs/libraries/ts/redwoodjs/overview.mdx | 18 ++ apps/docs/libraries/ts/sdk/overview.mdx | 52 ++--- apps/docs/mint.json | 30 ++- packages/redwoodjs/src/ratelimit/README.md | 2 +- 5 files changed, 262 insertions(+), 39 deletions(-) create mode 100644 apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx create mode 100644 apps/docs/libraries/ts/redwoodjs/overview.mdx diff --git a/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx b/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx new file mode 100644 index 0000000000..17e2b605f0 --- /dev/null +++ b/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx @@ -0,0 +1,199 @@ +--- +title: "Rate limiting" +description: "Unkey Rate limiting with RedwoodJS Middleware" +--- + +# Usage + +Rate limit requests using `withUnkey` middleware. + +Middleware is only available when SSR is enabled in RedwoodJS. + +## Unkey Setup + +See [Rate limiting Onboarding](https://www.unkey.com/docs/onboarding/onboarding-ratelimiting) to get started with standalone [rate limiting](https://www.unkey.com/docs/apis/features/ratelimiting) from [Unkey](https://www.unkey.com). + +Note: Be sure to set your `UNKEY_ROOT_KEY` or key to be used for rate limiting in an `.env` file. + +## Examples + +`withUnkey` provides several ways to customize rate limiting for a variety of use cases. + +The following examples sow how to set: + +- pattern matches when registering the middleware to match paths on which to enforce rate limits +- custom identifier generator function +- custom rate limit exceeded responses +- custom error responses + +### Rate Limit All Requests + +To rate limit all requests, register the unkeyMiddleware without route matching. + +```ts file="web/src/entry.server.tsx" +import withUnkey from "@unkey/redwoodjs"; +import type { withUnkeyOptions } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + }; + + const unkeyMiddleware = withUnkey(options); + + return [unkeyMiddleware]; +}; +``` + +### Basic Matching + +To rate limit a matching rout, register the unkeyMiddleware with the matching pattern. + +```ts file="web/src/entry.server.tsx" +import withUnkey from "@unkey/redwoodjs"; +import type { withUnkeyOptions } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + }; + + const unkeyMiddleware = withUnkey(options); + + return [[unkeyMiddleware, "/blog-post/:slug(\\d{1,})"]]; +}; +``` + +Note: If you need to match multiple patterns you can compose a complex expression + +```ts +return [[unkeyMiddleware, "/rss.(xml|atom|json)"]]; +``` + +or register multiple with different patterns: + +```ts +return [ + [unkeyMiddleware, "/blog-post/:slug(\\d{1,})"], + [unkeyMiddleware, "/admin"], +]; +``` + +### With Custom Identifier Function and Third Party Authentication + +Here, we use a custom identifier function `supabaseRatelimitIdentifier` that: + +- checks is the request is authenticated +- constructs the identifier `sub` from the current user, since here the currentUser will be a JWT where the user id is the `sub` claim +- registers `supabaseAuthMiddleware` before `unkeyMiddleware` so the request can be authenticated before determining limits + +```ts file="web/src/entry.server.ts" +import createSupabaseAuthMiddleware from "@redwoodjs/auth-supabase-middleware"; +import withUnkey from "@unkey/redwoodjs"; +import type { withUnkeyOptions } from "@unkey/redwoodjs"; +import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; +import type { TagDescriptor } from "@redwoodjs/web"; + +import App from "./App"; +import { Document } from "./Document"; + +// eslint-disable-next-line no-restricted-imports +import { getCurrentUser } from "$api/src/lib/auth"; + +interface Props { + css: string[]; + meta?: TagDescriptor[]; +} + +export const supabaseRatelimitIdentifier = (req: MiddlewareRequest) => { + const authContext = req?.serverAuthContext?.get(); + console.log(">>>> in supabaseRatelimitIdentifier", authContext); + const identifier = authContext?.isAuthenticated + ? (authContext.currentUser?.sub as string) || "anonymous-user" + : "192.168.1.1"; + return identifier; +}; + +export const registerMiddleware = () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + ratelimitIdentifierFn: supabaseRatelimitIdentifier, + }; + const unkeyMiddleware = withUnkey(options); + const supabaseAuthMiddleware = createSupabaseAuthMiddleware({ + getCurrentUser, + }); + + return [ + supabaseAuthMiddleware, + [unkeyMiddleware, "/blog-post/:slug(\\d{1,})"], + ]; +}; +``` + +## Custom Rate Limit Exceeded Response + +```ts +export const registerMiddleware = () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Rate limit exceeded message", { + status: 429, + }); + }, + }; + const unkeyMiddleware = withUnkey(options); + + return [unkeyMiddleware]; +}; +``` + +## Custom Rate Limit Error Response + +```ts +export const registerMiddleware = () => { + const options: withUnkeyOptions = { + ratelimitConfig: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/blog-post/:slug(\\d{1,})"], + ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Error message when rate limiting", { + status: 500, + }); + }, + }; + const unkeyMiddleware = withUnkey(options); + + return [unkeyMiddleware]; +}; +``` diff --git a/apps/docs/libraries/ts/redwoodjs/overview.mdx b/apps/docs/libraries/ts/redwoodjs/overview.mdx new file mode 100644 index 0000000000..54ce262a1f --- /dev/null +++ b/apps/docs/libraries/ts/redwoodjs/overview.mdx @@ -0,0 +1,18 @@ +--- +title: "Overview" +description: "RedwoodJS SDK for Unkey" +--- + +The official RedwoodJS SDK for Unkey. + +- Rate limit requests using `withUnkey` middleware + +## Install + + + + ```bash + yarn rw workspace web add @unkey/redwoodjs + ``` + + diff --git a/apps/docs/libraries/ts/sdk/overview.mdx b/apps/docs/libraries/ts/sdk/overview.mdx index 309ce82dab..0254a84e62 100644 --- a/apps/docs/libraries/ts/sdk/overview.mdx +++ b/apps/docs/libraries/ts/sdk/overview.mdx @@ -8,26 +8,10 @@ If you prefer a typed experience over calling http endpoints directly, you can u ## Install - - ```bash - npm install @unkey/api - ``` - - - ```bash - pnpm add @unkey/api - ``` - - - ```bash - yarn add @unkey/api - ``` - - - ```bash - bun install @unkey/api - ``` - + ```bash npm install @unkey/api ``` + ```bash pnpm add @unkey/api ``` + ```bash yarn add @unkey/api ``` + ```bash bun install @unkey/api ``` ## Unkey Root Key @@ -101,12 +85,10 @@ if (!result.valid) { console.log(result); ``` - ## Options The constructor accepts some options to customize the behavior: - ### Base Url Run all requests agaisnt your own instance of unkey hosted on your own infrastructure. @@ -125,14 +107,14 @@ const unkey = new Unkey({ By default the client will retry on network errors, you can customize this behavior: - How often to retry - A function that returns how many milliseconds to wait until the next attempt is made. + A function that returns how many milliseconds to wait until the next + attempt is made. @@ -142,9 +124,9 @@ const unkey = new Unkey({ // ... retry: { attempts: 3, - backoff: (retryCount) => retryCount * 1000 - } -}) + backoff: (retryCount) => retryCount * 1000, + }, +}); ``` ### Cache @@ -152,18 +134,20 @@ const unkey = new Unkey({ Configure the `fetch` cache behavior. -As of October 2023, the `cache` option is not yet implemented in cloudflare workers and will throw an error if used. + As of October 2023, the `cache` option is not yet implemented in cloudflare + workers and will throw an error if used. - Available options are: `default`, `force-cache`, `no-cache`, `no-store`, `only-if-cached` or `reload`. - + Available options are: `default`, `force-cache`, `no-cache`, `no-store`, + `only-if-cached` or `reload`. + ```ts const unkey = new Unkey({ // ... - cache: "no-cache" -}) + cache: "no-cache", +}); ``` ### Disable telemetry @@ -174,6 +158,6 @@ If you wish to disable this, you can do so by passing a boolean flag to the cons ```ts const unkey = new Unkey({ - disableTelemetry: true -}) + disableTelemetry: true, +}); ``` diff --git a/apps/docs/mint.json b/apps/docs/mint.json index 276b356e96..e557624359 100644 --- a/apps/docs/mint.json +++ b/apps/docs/mint.json @@ -63,7 +63,10 @@ "introduction", { "group": "Onboarding", - "pages": ["onboarding/onboarding-api", "onboarding/onboarding-ratelimiting"] + "pages": [ + "onboarding/onboarding-api", + "onboarding/onboarding-ratelimiting" + ] }, { "group": "Security", @@ -77,7 +80,11 @@ "apis/introduction", { "group": "Quickstart", - "pages": ["apis/quickstart/nextjs", "apis/quickstart/express", "apis/quickstart/bun"] + "pages": [ + "apis/quickstart/nextjs", + "apis/quickstart/express", + "apis/quickstart/bun" + ] }, { "group": "Features", @@ -106,7 +113,11 @@ }, { "group": "Ratelimiting", - "pages": ["ratelimiting/introduction", "ratelimiting/modes", "ratelimiting/overrides"] + "pages": [ + "ratelimiting/introduction", + "ratelimiting/modes", + "ratelimiting/overrides" + ] }, { "group": "Audit logs", @@ -192,9 +203,20 @@ } ] }, + "libraries/ts/ratelimit", "libraries/ts/nextjs", - "libraries/ts/hono" + "libraries/ts/hono", + { + "group": "@unkey/redwoodjs", + "pages": [ + "libraries/ts/redwoodjs/overview", + { + "group": "withUnkey", + "pages": ["libraries/ts/redwoodjs/middleware/ratelimiting"] + } + ] + } ] }, { diff --git a/packages/redwoodjs/src/ratelimit/README.md b/packages/redwoodjs/src/ratelimit/README.md index b81f1071e0..4b9a246c61 100644 --- a/packages/redwoodjs/src/ratelimit/README.md +++ b/packages/redwoodjs/src/ratelimit/README.md @@ -1,6 +1,6 @@ # withUnkey -RedwoodJS Middleware to rate limit requests using Unkey Ratelimiting +RedwoodJS Middleware to rate limit requests using Unkey ## Setup From a1276ba4d4a115aa8264042d32e667a55b958759 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Wed, 8 May 2024 12:16:23 -0400 Subject: [PATCH 14/33] update readme --- packages/redwoodjs/src/ratelimit/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/redwoodjs/src/ratelimit/README.md b/packages/redwoodjs/src/ratelimit/README.md index 4b9a246c61..b8d2e88c59 100644 --- a/packages/redwoodjs/src/ratelimit/README.md +++ b/packages/redwoodjs/src/ratelimit/README.md @@ -1,6 +1,6 @@ # withUnkey -RedwoodJS Middleware to rate limit requests using Unkey +[RedwoodJS Middleware](https://www.unkey.com/docs/libraries/ts/redwoodjs/middleware/ratelimiting) to rate limit requests using Unkey ## Setup From 0f5448af9e0af4ba90fb6ff80893178c85db37e9 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Fri, 10 May 2024 07:21:44 -0400 Subject: [PATCH 15/33] rework so in future one middleware can be used for both ratelimiting and auth --- .../ts/redwoodjs/middleware/ratelimiting.mdx | 74 +++++---- packages/redwoodjs/src/ratelimit/README.md | 95 ++++++----- .../src/ratelimit/__tests__/withUnkey.test.ts | 152 ++++++++++-------- packages/redwoodjs/src/ratelimit/index.ts | 23 ++- packages/redwoodjs/src/ratelimit/types.ts | 15 ++ 5 files changed, 205 insertions(+), 154 deletions(-) create mode 100644 packages/redwoodjs/src/ratelimit/types.ts diff --git a/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx b/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx index 17e2b605f0..1ed62a11b3 100644 --- a/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx +++ b/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx @@ -36,12 +36,14 @@ import type { withUnkeyOptions } from "@unkey/redwoodjs"; export const registerMiddleware = () => { const options: withUnkeyOptions = { - ratelimitConfig: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, + ratelimit: { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, }, }; @@ -61,12 +63,14 @@ import type { withUnkeyOptions } from "@unkey/redwoodjs"; export const registerMiddleware = () => { const options: withUnkeyOptions = { - ratelimitConfig: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, + ratelimit: { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, }, }; @@ -128,14 +132,16 @@ export const supabaseRatelimitIdentifier = (req: MiddlewareRequest) => { export const registerMiddleware = () => { const options: withUnkeyOptions = { - ratelimitConfig: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, + ratelimit: { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + ratelimitIdentifierFn: supabaseRatelimitIdentifier, }, - ratelimitIdentifierFn: supabaseRatelimitIdentifier, }; const unkeyMiddleware = withUnkey(options); const supabaseAuthMiddleware = createSupabaseAuthMiddleware({ @@ -154,17 +160,19 @@ export const registerMiddleware = () => { ```ts export const registerMiddleware = () => { const options: withUnkeyOptions = { - ratelimitConfig: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Custom Rate limit exceeded message", { - status: 429, - }); + ratelimit: { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Rate limit exceeded message", { + status: 429, + }); + }, }, }; const unkeyMiddleware = withUnkey(options); @@ -178,14 +186,14 @@ export const registerMiddleware = () => { ```ts export const registerMiddleware = () => { const options: withUnkeyOptions = { - ratelimitConfig: { + ratelimit: {config: { rootKey: process.env.UNKEY_ROOT_KEY, namespace: "my-app", limit: 1, duration: "30s", async: true, }, - matcher: ["/blog-post/:slug(\\d{1,})"], + matcher: , ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { return new MiddlewareResponse("Custom Error message when rate limiting", { status: 500, @@ -194,6 +202,6 @@ export const registerMiddleware = () => { }; const unkeyMiddleware = withUnkey(options); - return [unkeyMiddleware]; + return [[unkeyMiddleware, "/blog-post/:slug(\\d{1,})"]]; }; ``` diff --git a/packages/redwoodjs/src/ratelimit/README.md b/packages/redwoodjs/src/ratelimit/README.md index b8d2e88c59..f2375cdc43 100644 --- a/packages/redwoodjs/src/ratelimit/README.md +++ b/packages/redwoodjs/src/ratelimit/README.md @@ -29,12 +29,14 @@ import type { withUnkeyOptions } from "@unkey/redwoodjs"; export const registerMiddleware = () => { const options: withUnkeyOptions = { - ratelimitConfig: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, + ratelimit: { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, }, }; @@ -54,12 +56,14 @@ import type { withUnkeyOptions } from "@unkey/redwoodjs"; export const registerMiddleware = () => { const options: withUnkeyOptions = { - ratelimitConfig: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, + ratelimit: { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, }, }; @@ -121,14 +125,16 @@ export const supabaseRatelimitIdentifier = (req: MiddlewareRequest) => { export const registerMiddleware = () => { const options: withUnkeyOptions = { - ratelimitConfig: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, + ratelimit: { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + ratelimitIdentifierFn: supabaseRatelimitIdentifier, }, - ratelimitIdentifierFn: supabaseRatelimitIdentifier, }; const unkeyMiddleware = withUnkey(options); const supabaseAuthMiddleware = createSupabaseAuthMiddleware({ @@ -148,16 +154,18 @@ export const registerMiddleware = () => { export const registerMiddleware = () => { const options: withUnkeyOptions = { ratelimitConfig: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Custom Rate limit exceeded message", { - status: 429, - }); + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Rate limit exceeded message", { + status: 429, + }); + }, }, }; const unkeyMiddleware = withUnkey(options); @@ -171,18 +179,23 @@ export const registerMiddleware = () => { ```ts export const registerMiddleware = () => { const options: withUnkeyOptions = { - ratelimitConfig: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - matcher: ["/blog-post/:slug(\\d{1,})"], - ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Custom Error message when rate limiting", { - status: 500, - }); + ratelimit: { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + matcher: ["/blog-post/:slug(\\d{1,})"], + ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse( + "Custom Error message when rate limiting", + { + status: 500, + } + ); + }, }, }; const unkeyMiddleware = withUnkey(options); diff --git a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts index abb93cffb7..65a914828d 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts @@ -4,7 +4,7 @@ import { Ratelimit } from "@unkey/ratelimit"; import type { RatelimitConfig, RatelimitResponse } from "@unkey/ratelimit"; import { assert, describe, expect, it, vi } from "vitest"; import withUnkey from "../index"; -import type { withUnkeyOptions } from "../index"; +import type { withUnkeyOptions } from "../types"; /** * Mock the Ratelimit class @@ -48,9 +48,11 @@ const defaultRateLimitConfig: Pick { it("should not rate limit", async () => { const options: withUnkeyOptions = { - ratelimitConfig: { - namespace: "192.168.1.1", - ...defaultRateLimitConfig, + ratelimit: { + config: { + namespace: "192.168.1.1", + ...defaultRateLimitConfig, + }, }, }; const unkeyMiddleware = withUnkey(options); @@ -67,9 +69,11 @@ describe("withUnkey", () => { // it does not match the identifier generated by the withUnkey middleware // which is a defaulted value const options: withUnkeyOptions = { - ratelimitConfig: { - namespace: "my-app", - ...defaultRateLimitConfig, + ratelimit: { + config: { + namespace: "my-app", + ...defaultRateLimitConfig, + }, }, }; const unkeyMiddleware = withUnkey(options); @@ -85,13 +89,15 @@ describe("withUnkey", () => { // not to be exceeded (status 200) because it // matches the identifies generated by the withUnkey middleware const options: withUnkeyOptions = { - ratelimitConfig: { - namespace: "abcdefg", - ...defaultRateLimitConfig, - }, + ratelimit: { + config: { + namespace: "abcdefg", + ...defaultRateLimitConfig, + }, - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { - return "abcdefg"; // matches namespace so no rate limit for this test + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + return "abcdefg"; // matches namespace so no rate limit for this test + }, }, }; const unkeyMiddleware = withUnkey(options); @@ -106,13 +112,15 @@ describe("withUnkey", () => { // here the namespace will cause the rate limit to be exceeded (status 429) // because it does not match the identifier generated by the withUnkey middleware const options: withUnkeyOptions = { - ratelimitConfig: { - namespace: "12345", - ...defaultRateLimitConfig, - }, + ratelimit: { + config: { + namespace: "12345", + ...defaultRateLimitConfig, + }, - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { - return "abcdefg"; + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + return "abcdefg"; + }, }, }; const unkeyMiddleware = withUnkey(options); @@ -127,15 +135,17 @@ describe("withUnkey", () => { // here the namespace will cause the rate limit to be exceeded (status 429) // because it does not match the identifier generated by the withUnkey middleware const options: withUnkeyOptions = { - ratelimitConfig: { - namespace: "exceeded", - ...defaultRateLimitConfig, - }, + ratelimit: { + config: { + namespace: "exceeded", + ...defaultRateLimitConfig, + }, - ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Custom Rate limit exceeded message", { - status: 429, - }); + ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Rate limit exceeded message", { + status: 429, + }); + }, }, }; const unkeyMiddleware = withUnkey(options); @@ -151,13 +161,15 @@ describe("withUnkey", () => { // here the the identifier function will throw an error // which will cause a teh default error response to be returned const options: withUnkeyOptions = { - ratelimitConfig: { - namespace: "exceeded", - ...defaultRateLimitConfig, - }, + ratelimit: { + config: { + namespace: "exceeded", + ...defaultRateLimitConfig, + }, - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { - throw new Error("Error simulated by test"); + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + throw new Error("Error simulated by test"); + }, }, }; const unkeyMiddleware = withUnkey(options); @@ -174,18 +186,20 @@ describe("withUnkey", () => { // here the the identifier function will throw an error // which will cause the default error response to be returned const options: withUnkeyOptions = { - ratelimitConfig: { - namespace: "exceeded", - ...defaultRateLimitConfig, - }, + ratelimit: { + config: { + namespace: "exceeded", + ...defaultRateLimitConfig, + }, - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { - throw new Error("Error simulated by test"); - }, - ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Custom Error message when rate limiting", { - status: 500, - }); + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + throw new Error("Error simulated by test"); + }, + ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Error message when rate limiting", { + status: 500, + }); + }, }, }; const unkeyMiddleware = withUnkey(options); @@ -202,18 +216,20 @@ describe("withUnkey", () => { // here the the identifier function will throw an error // which will cause a custom error response to be returned const options: withUnkeyOptions = { - ratelimitConfig: { - namespace: "exceeded", - ...defaultRateLimitConfig, - }, + ratelimit: { + config: { + namespace: "exceeded", + ...defaultRateLimitConfig, + }, - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { - throw new Error("Error simulated by test"); - }, - ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Not implemented", { - status: 501, - }); + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + throw new Error("Error simulated by test"); + }, + ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Not implemented", { + status: 501, + }); + }, }, }; const unkeyMiddleware = withUnkey(options); @@ -228,22 +244,24 @@ describe("withUnkey", () => { it("should use a RedwoodJS-compatible logger", async () => { const options: withUnkeyOptions = { - ratelimitConfig: { - namespace: "exceeded", - ...defaultRateLimitConfig, + ratelimit: { + config: { + namespace: "exceeded", + ...defaultRateLimitConfig, + }, + + ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + throw new Error("Error simulated by test"); + }, + ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Not implemented", { + status: 501, + }); + }, }, logger: createLogger({ options: { level: "error", enabled: true }, }), - - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { - throw new Error("Error simulated by test"); - }, - ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Not implemented", { - status: 501, - }); - }, }; const unkeyMiddleware = withUnkey(options); const request = new Request("http://localhost:8910/api/user"); diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index b435746e36..bf8a2625bf 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -2,7 +2,7 @@ import type { Logger } from "@redwoodjs/api/logger"; import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; import { Ratelimit } from "@unkey/ratelimit"; -import type { RatelimitConfig } from "@unkey/ratelimit"; +import type { withUnkeyOptions } from "./types"; import { defaultRatelimitErrorResponse, defaultRatelimitExceededResponse, @@ -11,14 +11,6 @@ import { const defaultLogger = require("abstract-logging") as Logger; -export type withUnkeyOptions = { - ratelimitConfig: RatelimitConfig; - logger?: Logger; - ratelimitIdentifierFn?: (req: MiddlewareRequest) => string; - ratelimitExceededResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; - ratelimitErrorResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; -}; - /** * withUnkey is RedwoodJS middleware that adds Unkey rate limiting to a route * @@ -62,18 +54,23 @@ export type withUnkeyOptions = { * ``` */ const withUnkey = (options: withUnkeyOptions) => { - const unkey = new Ratelimit(options.ratelimitConfig); + if (!options.ratelimit) { + throw new Error("ratelimitConfig is required"); + } + + const unkey = new Ratelimit(options.ratelimit.config); return async (req: MiddlewareRequest, res: MiddlewareResponse) => { const logger = options.logger || defaultLogger; - const ratelimitIdentifier = options.ratelimitIdentifierFn || defaultRatelimitIdentifier; + const ratelimitIdentifier = + options.ratelimit?.ratelimitIdentifierFn || defaultRatelimitIdentifier; const rateLimitExceededResponse = - options.ratelimitExceededResponseFn || defaultRatelimitExceededResponse; + options.ratelimit?.ratelimitExceededResponseFn || defaultRatelimitExceededResponse; const rateLimitErrorResponse = - options.ratelimitErrorResponseFn || defaultRatelimitErrorResponse; + options.ratelimit?.ratelimitErrorResponseFn || defaultRatelimitErrorResponse; try { const identifier = ratelimitIdentifier(req); diff --git a/packages/redwoodjs/src/ratelimit/types.ts b/packages/redwoodjs/src/ratelimit/types.ts new file mode 100644 index 0000000000..937cccf290 --- /dev/null +++ b/packages/redwoodjs/src/ratelimit/types.ts @@ -0,0 +1,15 @@ +import type { Logger } from "@redwoodjs/api/logger"; +import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; +import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; +import type { RatelimitConfig } from "@unkey/ratelimit"; + +export type withUnkeyRatelimitConfig = { + config: RatelimitConfig; + ratelimitIdentifierFn?: (req: MiddlewareRequest) => string; + ratelimitExceededResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; + ratelimitErrorResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; +}; +export type withUnkeyOptions = { + ratelimit?: withUnkeyRatelimitConfig; + logger?: Logger; +}; From 58a25cfdd5faa45069bf75383d2d38de5f3724b8 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Fri, 10 May 2024 07:26:30 -0400 Subject: [PATCH 16/33] fix jsdoc example code --- packages/redwoodjs/src/ratelimit/index.ts | 27 +++++++++++++---------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index bf8a2625bf..bc5eda4047 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -19,14 +19,15 @@ const defaultLogger = require("abstract-logging") as Logger; * * Provide the Unkey rate limit configuration and the path matcher to apply the rate limit to. * - * @param options ratelimitConfig: RatelimitConfig; - * + * @param options withUnkeyOptions: withUnkeyOptions; + * @param options ratelimit: withUnkeyRatelimitConfig; + * * @param options ratelimit config: RatelimitConfig; * You can provide optional custom functions to construct rate limit identifier, * rate limit exceeded response, and rate limit error response. * - * @param options ratelimitIdentifierFn?: (req: MiddlewareRequest) => string; - * @param options ratelimitExceededResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; - * @param options ratelimitErrorResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; + * @param options ratelimit ratelimitIdentifierFn?: (req: MiddlewareRequest) => string; + * @param optionsz ratelimit ratelimitExceededResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; + * @param options ratelimit ratelimitErrorResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; * * @param options logger?: Logger; * @@ -38,13 +39,15 @@ const defaultLogger = require("abstract-logging") as Logger; * * export const registerMiddleware = () => { * const options: withUnkeyOptions = { - * ratelimitConfig: { - * rootKey: process.env.UNKEY_ROOT_KEY, - * namespace: 'my-app', - * limit: 1, - * duration: '30s', - * async: true, - * }, + * ratelimit: { + * config: { + * rootKey: process.env.UNKEY_ROOT_KEY, + * namespace: 'my-app', + * limit: 1, + * duration: '30s', + * async: true, + * }, + * } * } * * const unkeyMiddleware = withUnkey(options) From b7a7a967a51aea5dee4757a13a13074b8b876151 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Fri, 10 May 2024 07:36:57 -0400 Subject: [PATCH 17/33] rename custom functions for simplicity --- .../ts/redwoodjs/middleware/ratelimiting.mdx | 6 ++--- packages/redwoodjs/src/ratelimit/README.md | 11 ++++----- .../src/ratelimit/__tests__/withUnkey.test.ts | 20 ++++++++-------- packages/redwoodjs/src/ratelimit/index.ts | 24 +++++++++---------- packages/redwoodjs/src/ratelimit/types.ts | 6 ++--- 5 files changed, 32 insertions(+), 35 deletions(-) diff --git a/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx b/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx index 1ed62a11b3..56993a0b37 100644 --- a/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx +++ b/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx @@ -140,7 +140,7 @@ export const registerMiddleware = () => { duration: "30s", async: true, }, - ratelimitIdentifierFn: supabaseRatelimitIdentifier, + getIdentifier: supabaseRatelimitIdentifier, }, }; const unkeyMiddleware = withUnkey(options); @@ -168,7 +168,7 @@ export const registerMiddleware = () => { duration: "30s", async: true, }, - ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { + onExceeded: (_req: MiddlewareRequest) => { return new MiddlewareResponse("Custom Rate limit exceeded message", { status: 429, }); @@ -194,7 +194,7 @@ export const registerMiddleware = () => { async: true, }, matcher: , - ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + onError: (_req: MiddlewareRequest) => { return new MiddlewareResponse("Custom Error message when rate limiting", { status: 500, }); diff --git a/packages/redwoodjs/src/ratelimit/README.md b/packages/redwoodjs/src/ratelimit/README.md index f2375cdc43..804e970407 100644 --- a/packages/redwoodjs/src/ratelimit/README.md +++ b/packages/redwoodjs/src/ratelimit/README.md @@ -133,7 +133,7 @@ export const registerMiddleware = () => { duration: "30s", async: true, }, - ratelimitIdentifierFn: supabaseRatelimitIdentifier, + getIdentifier: supabaseRatelimitIdentifier, }, }; const unkeyMiddleware = withUnkey(options); @@ -153,7 +153,7 @@ export const registerMiddleware = () => { ```ts export const registerMiddleware = () => { const options: withUnkeyOptions = { - ratelimitConfig: { + ratelimit: { config: { rootKey: process.env.UNKEY_ROOT_KEY, namespace: "my-app", @@ -161,7 +161,7 @@ export const registerMiddleware = () => { duration: "30s", async: true, }, - ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { + onExceeded: (_req: MiddlewareRequest) => { return new MiddlewareResponse("Custom Rate limit exceeded message", { status: 429, }); @@ -187,8 +187,7 @@ export const registerMiddleware = () => { duration: "30s", async: true, }, - matcher: ["/blog-post/:slug(\\d{1,})"], - ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + onError: (_req: MiddlewareRequest) => { return new MiddlewareResponse( "Custom Error message when rate limiting", { @@ -200,6 +199,6 @@ export const registerMiddleware = () => { }; const unkeyMiddleware = withUnkey(options); - return [unkeyMiddleware]; + return [unkeyMiddleware, ["/blog-post/:slug(\\d{1,})"]]; }; ``` diff --git a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts index 65a914828d..759ea16927 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts @@ -95,7 +95,7 @@ describe("withUnkey", () => { ...defaultRateLimitConfig, }, - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + getIdentifier: (_req: MiddlewareRequest) => { return "abcdefg"; // matches namespace so no rate limit for this test }, }, @@ -118,7 +118,7 @@ describe("withUnkey", () => { ...defaultRateLimitConfig, }, - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + getIdentifier: (_req: MiddlewareRequest) => { return "abcdefg"; }, }, @@ -141,7 +141,7 @@ describe("withUnkey", () => { ...defaultRateLimitConfig, }, - ratelimitExceededResponseFn: (_req: MiddlewareRequest) => { + onExceeded: (_req: MiddlewareRequest) => { return new MiddlewareResponse("Custom Rate limit exceeded message", { status: 429, }); @@ -167,7 +167,7 @@ describe("withUnkey", () => { ...defaultRateLimitConfig, }, - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + getIdentifier: (_req: MiddlewareRequest) => { throw new Error("Error simulated by test"); }, }, @@ -192,10 +192,10 @@ describe("withUnkey", () => { ...defaultRateLimitConfig, }, - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + getIdentifier: (_req: MiddlewareRequest) => { throw new Error("Error simulated by test"); }, - ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + onError: (_req: MiddlewareRequest) => { return new MiddlewareResponse("Custom Error message when rate limiting", { status: 500, }); @@ -222,10 +222,10 @@ describe("withUnkey", () => { ...defaultRateLimitConfig, }, - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + getIdentifier: (_req: MiddlewareRequest) => { throw new Error("Error simulated by test"); }, - ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + onError: (_req: MiddlewareRequest) => { return new MiddlewareResponse("Not implemented", { status: 501, }); @@ -250,10 +250,10 @@ describe("withUnkey", () => { ...defaultRateLimitConfig, }, - ratelimitIdentifierFn: (_req: MiddlewareRequest) => { + getIdentifier: (_req: MiddlewareRequest) => { throw new Error("Error simulated by test"); }, - ratelimitErrorResponseFn: (_req: MiddlewareRequest) => { + onError: (_req: MiddlewareRequest) => { return new MiddlewareResponse("Not implemented", { status: 501, }); diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index bc5eda4047..f7a46c1c42 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -21,13 +21,14 @@ const defaultLogger = require("abstract-logging") as Logger; * * @param options withUnkeyOptions: withUnkeyOptions; * @param options ratelimit: withUnkeyRatelimitConfig; - * * @param options ratelimit config: RatelimitConfig; + * @param options ratelimit config: RatelimitConfig; + * * You can provide optional custom functions to construct rate limit identifier, * rate limit exceeded response, and rate limit error response. * - * @param options ratelimit ratelimitIdentifierFn?: (req: MiddlewareRequest) => string; - * @param optionsz ratelimit ratelimitExceededResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; - * @param options ratelimit ratelimitErrorResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; + * @param options ratelimit getIdentifier?: (req: MiddlewareRequest) => string; + * @param options ratelimit onExceeded?: (req: MiddlewareRequest) => MiddlewareResponse; + * @param options ratelimit onError?: (req: MiddlewareRequest) => MiddlewareResponse; * * @param options logger?: Logger; * @@ -66,17 +67,14 @@ const withUnkey = (options: withUnkeyOptions) => { return async (req: MiddlewareRequest, res: MiddlewareResponse) => { const logger = options.logger || defaultLogger; - const ratelimitIdentifier = - options.ratelimit?.ratelimitIdentifierFn || defaultRatelimitIdentifier; + const getIdentifier = options.ratelimit?.getIdentifier || defaultRatelimitIdentifier; - const rateLimitExceededResponse = - options.ratelimit?.ratelimitExceededResponseFn || defaultRatelimitExceededResponse; + const onExceeded = options.ratelimit?.onExceeded || defaultRatelimitExceededResponse; - const rateLimitErrorResponse = - options.ratelimit?.ratelimitErrorResponseFn || defaultRatelimitErrorResponse; + const onError = options.ratelimit?.onError || defaultRatelimitErrorResponse; try { - const identifier = ratelimitIdentifier(req); + const identifier = getIdentifier(req); const ratelimit = await unkey.limit(identifier); @@ -85,7 +83,7 @@ const withUnkey = (options: withUnkeyOptions) => { ratelimit, identifier, }); - const response = rateLimitExceededResponse(req); + const response = onExceeded(req); if (response.status !== 429) { logger.warn("Rate limit exceeded response is not 429. Overriding status.", response); response.status = 429; @@ -94,7 +92,7 @@ const withUnkey = (options: withUnkeyOptions) => { } } catch (e) { logger.error("Error in withUnkey", e); - const errorResponse = rateLimitErrorResponse(req); + const errorResponse = onError(req); if (errorResponse.status !== 500) { logger.warn( `Rate limit error response is ${errorResponse.status}. Consider changing status to 500.`, diff --git a/packages/redwoodjs/src/ratelimit/types.ts b/packages/redwoodjs/src/ratelimit/types.ts index 937cccf290..a2b16958ac 100644 --- a/packages/redwoodjs/src/ratelimit/types.ts +++ b/packages/redwoodjs/src/ratelimit/types.ts @@ -5,9 +5,9 @@ import type { RatelimitConfig } from "@unkey/ratelimit"; export type withUnkeyRatelimitConfig = { config: RatelimitConfig; - ratelimitIdentifierFn?: (req: MiddlewareRequest) => string; - ratelimitExceededResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; - ratelimitErrorResponseFn?: (req: MiddlewareRequest) => MiddlewareResponse; + getIdentifier?: (req: MiddlewareRequest) => string; + onExceeded?: (req: MiddlewareRequest) => MiddlewareResponse; + onError?: (req: MiddlewareRequest) => MiddlewareResponse; }; export type withUnkeyOptions = { ratelimit?: withUnkeyRatelimitConfig; From 5e4914122b9b1f1b92a68b160ed2a582268df67e Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Fri, 10 May 2024 07:46:20 -0400 Subject: [PATCH 18/33] rename to withUnkeyConfig --- .../ts/redwoodjs/middleware/ratelimiting.mdx | 26 +++++------ packages/redwoodjs/src/ratelimit/README.md | 26 +++++------ .../src/ratelimit/__tests__/withUnkey.test.ts | 20 ++++----- packages/redwoodjs/src/ratelimit/index.ts | 45 ++++++++++--------- packages/redwoodjs/src/ratelimit/types.ts | 2 +- 5 files changed, 62 insertions(+), 57 deletions(-) diff --git a/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx b/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx index 56993a0b37..49d1f8861a 100644 --- a/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx +++ b/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx @@ -32,10 +32,10 @@ To rate limit all requests, register the unkeyMiddleware without route matching. ```ts file="web/src/entry.server.tsx" import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyOptions } from "@unkey/redwoodjs"; +import type { withUnkeyConfig } from "@unkey/redwoodjs"; export const registerMiddleware = () => { - const options: withUnkeyOptions = { + const config: withUnkeyConfig = { ratelimit: { config: { rootKey: process.env.UNKEY_ROOT_KEY, @@ -47,7 +47,7 @@ export const registerMiddleware = () => { }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = withUnkey(config); return [unkeyMiddleware]; }; @@ -59,10 +59,10 @@ To rate limit a matching rout, register the unkeyMiddleware with the matching pa ```ts file="web/src/entry.server.tsx" import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyOptions } from "@unkey/redwoodjs"; +import type { withUnkeyConfig } from "@unkey/redwoodjs"; export const registerMiddleware = () => { - const options: withUnkeyOptions = { + const config: withUnkeyConfig = { ratelimit: { config: { rootKey: process.env.UNKEY_ROOT_KEY, @@ -74,7 +74,7 @@ export const registerMiddleware = () => { }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = withUnkey(config); return [[unkeyMiddleware, "/blog-post/:slug(\\d{1,})"]]; }; @@ -106,7 +106,7 @@ Here, we use a custom identifier function `supabaseRatelimitIdentifier` that: ```ts file="web/src/entry.server.ts" import createSupabaseAuthMiddleware from "@redwoodjs/auth-supabase-middleware"; import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyOptions } from "@unkey/redwoodjs"; +import type { withUnkeyConfig } from "@unkey/redwoodjs"; import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import type { TagDescriptor } from "@redwoodjs/web"; @@ -131,7 +131,7 @@ export const supabaseRatelimitIdentifier = (req: MiddlewareRequest) => { }; export const registerMiddleware = () => { - const options: withUnkeyOptions = { + const config: withUnkeyConfig = { ratelimit: { config: { rootKey: process.env.UNKEY_ROOT_KEY, @@ -143,7 +143,7 @@ export const registerMiddleware = () => { getIdentifier: supabaseRatelimitIdentifier, }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = withUnkey(config); const supabaseAuthMiddleware = createSupabaseAuthMiddleware({ getCurrentUser, }); @@ -159,7 +159,7 @@ export const registerMiddleware = () => { ```ts export const registerMiddleware = () => { - const options: withUnkeyOptions = { + const config: withUnkeyConfig = { ratelimit: { config: { rootKey: process.env.UNKEY_ROOT_KEY, @@ -175,7 +175,7 @@ export const registerMiddleware = () => { }, }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = withUnkey(config); return [unkeyMiddleware]; }; @@ -185,7 +185,7 @@ export const registerMiddleware = () => { ```ts export const registerMiddleware = () => { - const options: withUnkeyOptions = { + const config: withUnkeyConfig = { ratelimit: {config: { rootKey: process.env.UNKEY_ROOT_KEY, namespace: "my-app", @@ -200,7 +200,7 @@ export const registerMiddleware = () => { }); }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = withUnkey(config); return [[unkeyMiddleware, "/blog-post/:slug(\\d{1,})"]]; }; diff --git a/packages/redwoodjs/src/ratelimit/README.md b/packages/redwoodjs/src/ratelimit/README.md index 804e970407..dbf1861e22 100644 --- a/packages/redwoodjs/src/ratelimit/README.md +++ b/packages/redwoodjs/src/ratelimit/README.md @@ -25,10 +25,10 @@ To rate limit all requests, register the unkeyMiddleware without route matching. ```ts file="web/src/entry.server.tsx" import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyOptions } from "@unkey/redwoodjs"; +import type { withUnkeyConfig } from "@unkey/redwoodjs"; export const registerMiddleware = () => { - const options: withUnkeyOptions = { + const config: withUnkeyConfig = { ratelimit: { config: { rootKey: process.env.UNKEY_ROOT_KEY, @@ -40,7 +40,7 @@ export const registerMiddleware = () => { }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = withUnkey(config); return [unkeyMiddleware]; }; @@ -52,10 +52,10 @@ To rate limit a matching rout, register the unkeyMiddleware with the matching pa ```ts file="web/src/entry.server.tsx" import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyOptions } from "@unkey/redwoodjs"; +import type { withUnkeyConfig } from "@unkey/redwoodjs"; export const registerMiddleware = () => { - const options: withUnkeyOptions = { + const config: withUnkeyConfig = { ratelimit: { config: { rootKey: process.env.UNKEY_ROOT_KEY, @@ -67,7 +67,7 @@ export const registerMiddleware = () => { }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = withUnkey(config); return [[unkeyMiddleware, "/blog-post/:slug(\\d{1,})"]]; }; @@ -99,7 +99,7 @@ Here, we use a custom identifier function `supabaseRatelimitIdentifier` that: ```ts file="web/src/entry.server.ts" import createSupabaseAuthMiddleware from "@redwoodjs/auth-supabase-middleware"; import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyOptions } from "@unkey/redwoodjs"; +import type { withUnkeyConfig } from "@unkey/redwoodjs"; import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import type { TagDescriptor } from "@redwoodjs/web"; @@ -124,7 +124,7 @@ export const supabaseRatelimitIdentifier = (req: MiddlewareRequest) => { }; export const registerMiddleware = () => { - const options: withUnkeyOptions = { + const config: withUnkeyConfig = { ratelimit: { config: { rootKey: process.env.UNKEY_ROOT_KEY, @@ -136,7 +136,7 @@ export const registerMiddleware = () => { getIdentifier: supabaseRatelimitIdentifier, }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = withUnkey(config); const supabaseAuthMiddleware = createSupabaseAuthMiddleware({ getCurrentUser, }); @@ -152,7 +152,7 @@ export const registerMiddleware = () => { ```ts export const registerMiddleware = () => { - const options: withUnkeyOptions = { + const config: withUnkeyConfig = { ratelimit: { config: { rootKey: process.env.UNKEY_ROOT_KEY, @@ -168,7 +168,7 @@ export const registerMiddleware = () => { }, }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = withUnkey(config); return [unkeyMiddleware]; }; @@ -178,7 +178,7 @@ export const registerMiddleware = () => { ```ts export const registerMiddleware = () => { - const options: withUnkeyOptions = { + const config: withUnkeyConfig = { ratelimit: { config: { rootKey: process.env.UNKEY_ROOT_KEY, @@ -197,7 +197,7 @@ export const registerMiddleware = () => { }, }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = withUnkey(config); return [unkeyMiddleware, ["/blog-post/:slug(\\d{1,})"]]; }; diff --git a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts index 759ea16927..bd508b419b 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts @@ -4,7 +4,7 @@ import { Ratelimit } from "@unkey/ratelimit"; import type { RatelimitConfig, RatelimitResponse } from "@unkey/ratelimit"; import { assert, describe, expect, it, vi } from "vitest"; import withUnkey from "../index"; -import type { withUnkeyOptions } from "../types"; +import type { withUnkeyConfig } from "../types"; /** * Mock the Ratelimit class @@ -47,7 +47,7 @@ const defaultRateLimitConfig: Pick { it("should not rate limit", async () => { - const options: withUnkeyOptions = { + const options: withUnkeyConfig = { ratelimit: { config: { namespace: "192.168.1.1", @@ -68,7 +68,7 @@ describe("withUnkey", () => { // to be exceeded (status 429) because // it does not match the identifier generated by the withUnkey middleware // which is a defaulted value - const options: withUnkeyOptions = { + const options: withUnkeyConfig = { ratelimit: { config: { namespace: "my-app", @@ -88,7 +88,7 @@ describe("withUnkey", () => { // here the namespace will cause the rate limit // not to be exceeded (status 200) because it // matches the identifies generated by the withUnkey middleware - const options: withUnkeyOptions = { + const options: withUnkeyConfig = { ratelimit: { config: { namespace: "abcdefg", @@ -111,7 +111,7 @@ describe("withUnkey", () => { it("should be limited with a custom default identifier function", async () => { // here the namespace will cause the rate limit to be exceeded (status 429) // because it does not match the identifier generated by the withUnkey middleware - const options: withUnkeyOptions = { + const options: withUnkeyConfig = { ratelimit: { config: { namespace: "12345", @@ -134,7 +134,7 @@ describe("withUnkey", () => { it("should be limited with a custom rate limit exceeded message function", async () => { // here the namespace will cause the rate limit to be exceeded (status 429) // because it does not match the identifier generated by the withUnkey middleware - const options: withUnkeyOptions = { + const options: withUnkeyConfig = { ratelimit: { config: { namespace: "exceeded", @@ -160,7 +160,7 @@ describe("withUnkey", () => { it("should error", async () => { // here the the identifier function will throw an error // which will cause a teh default error response to be returned - const options: withUnkeyOptions = { + const options: withUnkeyConfig = { ratelimit: { config: { namespace: "exceeded", @@ -185,7 +185,7 @@ describe("withUnkey", () => { it("should error with custom message", async () => { // here the the identifier function will throw an error // which will cause the default error response to be returned - const options: withUnkeyOptions = { + const options: withUnkeyConfig = { ratelimit: { config: { namespace: "exceeded", @@ -215,7 +215,7 @@ describe("withUnkey", () => { it("should error with custom message and status", async () => { // here the the identifier function will throw an error // which will cause a custom error response to be returned - const options: withUnkeyOptions = { + const options: withUnkeyConfig = { ratelimit: { config: { namespace: "exceeded", @@ -243,7 +243,7 @@ describe("withUnkey", () => { }); it("should use a RedwoodJS-compatible logger", async () => { - const options: withUnkeyOptions = { + const options: withUnkeyConfig = { ratelimit: { config: { namespace: "exceeded", diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index f7a46c1c42..c73167f989 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -1,8 +1,12 @@ import type { Logger } from "@redwoodjs/api/logger"; -import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; -import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; +import type { + // Middleware, + MiddlewareRequest, + MiddlewareResponse, +} from "@redwoodjs/vite/middleware"; + import { Ratelimit } from "@unkey/ratelimit"; -import type { withUnkeyOptions } from "./types"; +import type { withUnkeyConfig } from "./types"; import { defaultRatelimitErrorResponse, defaultRatelimitExceededResponse, @@ -19,27 +23,27 @@ const defaultLogger = require("abstract-logging") as Logger; * * Provide the Unkey rate limit configuration and the path matcher to apply the rate limit to. * - * @param options withUnkeyOptions: withUnkeyOptions; - * @param options ratelimit: withUnkeyRatelimitConfig; - * @param options ratelimit config: RatelimitConfig; + * @param config withUnkeyOptions: withUnkeyOptions; + * @param config ratelimit: withUnkeyRatelimitConfig; + * @param config ratelimit config: RatelimitConfig; * * You can provide optional custom functions to construct rate limit identifier, * rate limit exceeded response, and rate limit error response. * - * @param options ratelimit getIdentifier?: (req: MiddlewareRequest) => string; - * @param options ratelimit onExceeded?: (req: MiddlewareRequest) => MiddlewareResponse; - * @param options ratelimit onError?: (req: MiddlewareRequest) => MiddlewareResponse; + * @param config ratelimit getIdentifier?: (req: MiddlewareRequest) => string; + * @param config ratelimit onExceeded?: (req: MiddlewareRequest) => MiddlewareResponse; + * @param config ratelimit onError?: (req: MiddlewareRequest) => MiddlewareResponse; * - * @param options logger?: Logger; + * @param config logger?: Logger; * * @example * ```ts file="web/src/entry.server.tsx" * * import withUnkey from '@unkey/redwoodjs' - * import type { withUnkeyOptions } from '@unkey/redwoodjs' + * import type { withUnkeyConfig } from '@unkey/redwoodjs' * * export const registerMiddleware = () => { - * const options: withUnkeyOptions = { + * const options: withUnkeyConfig = { * ratelimit: { * config: { * rootKey: process.env.UNKEY_ROOT_KEY, @@ -56,22 +60,23 @@ const defaultLogger = require("abstract-logging") as Logger; * return [unkeyMiddleware] * } * ``` + * */ -const withUnkey = (options: withUnkeyOptions) => { - if (!options.ratelimit) { - throw new Error("ratelimitConfig is required"); +const withUnkey = (config: withUnkeyConfig) => { + if (!config.ratelimit) { + throw new Error("ratelimit configuration is required"); } - const unkey = new Ratelimit(options.ratelimit.config); + const unkey = new Ratelimit(config.ratelimit.config); return async (req: MiddlewareRequest, res: MiddlewareResponse) => { - const logger = options.logger || defaultLogger; + const logger = config.logger || defaultLogger; - const getIdentifier = options.ratelimit?.getIdentifier || defaultRatelimitIdentifier; + const getIdentifier = config.ratelimit?.getIdentifier || defaultRatelimitIdentifier; - const onExceeded = options.ratelimit?.onExceeded || defaultRatelimitExceededResponse; + const onExceeded = config.ratelimit?.onExceeded || defaultRatelimitExceededResponse; - const onError = options.ratelimit?.onError || defaultRatelimitErrorResponse; + const onError = config.ratelimit?.onError || defaultRatelimitErrorResponse; try { const identifier = getIdentifier(req); diff --git a/packages/redwoodjs/src/ratelimit/types.ts b/packages/redwoodjs/src/ratelimit/types.ts index a2b16958ac..4c0381f83a 100644 --- a/packages/redwoodjs/src/ratelimit/types.ts +++ b/packages/redwoodjs/src/ratelimit/types.ts @@ -9,7 +9,7 @@ export type withUnkeyRatelimitConfig = { onExceeded?: (req: MiddlewareRequest) => MiddlewareResponse; onError?: (req: MiddlewareRequest) => MiddlewareResponse; }; -export type withUnkeyOptions = { +export type withUnkeyConfig = { ratelimit?: withUnkeyRatelimitConfig; logger?: Logger; }; From 15f40407c40e927da78302b16bacbae8e7818f35 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Fri, 10 May 2024 08:27:33 -0400 Subject: [PATCH 19/33] WIP key auth middleware --- packages/redwoodjs/package.json | 11 +- packages/redwoodjs/src/ratelimit/index.ts | 153 ++++++++++++++++------ packages/redwoodjs/src/ratelimit/types.ts | 57 ++++++++ pnpm-lock.yaml | 3 + 4 files changed, 182 insertions(+), 42 deletions(-) diff --git a/packages/redwoodjs/package.json b/packages/redwoodjs/package.json index 72816cf433..62eabe21de 100644 --- a/packages/redwoodjs/package.json +++ b/packages/redwoodjs/package.json @@ -8,12 +8,18 @@ "publishConfig": { "access": "public" }, - "keywords": ["unkey", "redwoodjs", "sdk"], + "keywords": [ + "unkey", + "redwoodjs", + "sdk" + ], "bugs": { "url": "https://github.com/unkeyed/unkey/issues" }, "homepage": "https://github.com/unkeyed/unkey#readme", - "files": ["./dist/**"], + "files": [ + "./dist/**" + ], "author": "David Thyresson", "scripts": { "build": "tsup", @@ -22,6 +28,7 @@ "dependencies": { "@redwoodjs/api": "8.0.0-canary.542", "@redwoodjs/vite": "8.0.0-canary.542", + "@unkey/api": "workspace:^", "@unkey/ratelimit": "workspace:^", "abstract-logging": "^2.0.1" }, diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index c73167f989..4c849fd101 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -1,18 +1,19 @@ -import type { Logger } from "@redwoodjs/api/logger"; -import type { - // Middleware, - MiddlewareRequest, - MiddlewareResponse, -} from "@redwoodjs/vite/middleware"; - +import { Unkey } from "@unkey/api"; import { Ratelimit } from "@unkey/ratelimit"; -import type { withUnkeyConfig } from "./types"; + +import { version } from "../../package.json"; + import { defaultRatelimitErrorResponse, defaultRatelimitExceededResponse, defaultRatelimitIdentifier, } from "./util"; +import type { Logger } from "@redwoodjs/api/logger"; + +import type { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; +import type { withUnkeyConfig } from "./types"; + const defaultLogger = require("abstract-logging") as Logger; /** @@ -43,7 +44,7 @@ const defaultLogger = require("abstract-logging") as Logger; * import type { withUnkeyConfig } from '@unkey/redwoodjs' * * export const registerMiddleware = () => { - * const options: withUnkeyConfig = { + * const config: withUnkeyConfig = { * ratelimit: { * config: { * rootKey: process.env.UNKEY_ROOT_KEY, @@ -63,51 +64,123 @@ const defaultLogger = require("abstract-logging") as Logger; * */ const withUnkey = (config: withUnkeyConfig) => { - if (!config.ratelimit) { - throw new Error("ratelimit configuration is required"); + if (!config) { + throw new Error("withUnkey requires a configuration object"); } - const unkey = new Ratelimit(config.ratelimit.config); + if (!config.ratelimit && !config.auth) { + throw new Error("withUnkey requires a ratelimit or auth configuration object"); + } - return async (req: MiddlewareRequest, res: MiddlewareResponse) => { - const logger = config.logger || defaultLogger; + const logger = config.logger || defaultLogger; - const getIdentifier = config.ratelimit?.getIdentifier || defaultRatelimitIdentifier; + if (config.auth) { + return async (req: MiddlewareRequest, res: MiddlewareResponse) => { + /** + * Get key from request and return a response early if not found + */ + const key = config.auth?.getKey + ? config.auth.getKey(req) + : req.headers.get("authorization")?.replace("Bearer ", "") ?? null; - const onExceeded = config.ratelimit?.onExceeded || defaultRatelimitExceededResponse; + if (key === null) { + res.body = "Unauthorized"; + res.status = 401; + return res; + } - const onError = config.ratelimit?.onError || defaultRatelimitErrorResponse; + if (typeof key !== "string") { + return key; + } - try { - const identifier = getIdentifier(req); + const unkey = new Unkey({ + rootKey: "public", + wrapperSdkVersion: `@unkey/redwoodjs@${version}`, + disableTelemetry: config.auth?.disableTelemetry, + }); - const ratelimit = await unkey.limit(identifier); + const unkeyVerificationResult = await unkey.keys.verify( + config.auth?.apiId ? { key, apiId: config.auth?.apiId } : { key }, + ); - if (!ratelimit.success) { - logger.debug("Rate limit exceeded", { - ratelimit, - identifier, - }); - const response = onExceeded(req); - if (response.status !== 429) { - logger.warn("Rate limit exceeded response is not 429. Overriding status.", response); - response.status = 429; + if (unkeyVerificationResult.error) { + if (config.auth?.onError) { + return config.auth.onError( + req, + //unkeyVerificationResult.error + ); } - return response; - } - } catch (e) { - logger.error("Error in withUnkey", e); - const errorResponse = onError(req); - if (errorResponse.status !== 500) { - logger.warn( - `Rate limit error response is ${errorResponse.status}. Consider changing status to 500.`, - errorResponse, + console.error( + `unkey error: [CODE: ${unkeyVerificationResult.error.code}] - [TRACE: ${unkeyVerificationResult.error.requestId}] - ${unkeyVerificationResult.error.message} - read more at ${unkeyVerificationResult.error.docs}`, ); + + res.body = "Internal Server Error"; + res.status = 500; } - return errorResponse; - } + if (!unkeyVerificationResult.result?.valid) { + if (config.auth?.onInvalidKey) { + return config.auth.onInvalidKey( + req, //res.result + ); + } + + res.body = "Unauthorized"; + res.status = 401; + // return new NextResponse("Unauthorized", { status: 500 }); + } + + return res; + }; + } + + if (config.ratelimit) { + const unkeyRateLimiter = new Ratelimit(config.ratelimit.config); + + return async (req: MiddlewareRequest, res: MiddlewareResponse) => { + const getIdentifier = config.ratelimit?.getIdentifier || defaultRatelimitIdentifier; + + const onExceeded = config.ratelimit?.onExceeded || defaultRatelimitExceededResponse; + + const onError = config.ratelimit?.onError || defaultRatelimitErrorResponse; + + try { + const identifier = getIdentifier(req); + + const ratelimit = await unkeyRateLimiter.limit(identifier); + + if (!ratelimit.success) { + logger.debug("Rate limit exceeded", { + ratelimit, + identifier, + }); + const response = onExceeded(req); + if (response.status !== 429) { + logger.warn("Rate limit exceeded response is not 429. Overriding status.", response); + response.status = 429; + } + return response; + } + } catch (e) { + logger.error("Error in withUnkey", e); + const errorResponse = onError(req); + if (errorResponse.status !== 500) { + logger.warn( + `Rate limit error response is ${errorResponse.status}. Consider changing status to 500.`, + errorResponse, + ); + } + + return errorResponse; + } + + return res; + }; + } + + return async (req: MiddlewareRequest, res: MiddlewareResponse) => { + logger.error(req, "No configuration provided. Skipping middleware."); return res; }; }; diff --git a/packages/redwoodjs/src/ratelimit/types.ts b/packages/redwoodjs/src/ratelimit/types.ts index 4c0381f83a..afc4a621d2 100644 --- a/packages/redwoodjs/src/ratelimit/types.ts +++ b/packages/redwoodjs/src/ratelimit/types.ts @@ -3,13 +3,70 @@ import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; import type { RatelimitConfig } from "@unkey/ratelimit"; +export type withUnkeyApiKeyConfig = { + /** + * The apiId to verify against. + * + * This will be required soon. + */ + apiId?: string; + + /** + * + * By default telemetry data is enabled, and sends: + * runtime (Node.js / Edge) + * platform (Node.js / Vercel / AWS) + * SDK version + */ + disableTelemetry?: boolean; + + /** + * How to get the key from the request + * Usually the key is provided in an `Authorization` header, but you can do what you want. + * + * Return the key as string, or null if it doesn't exist. + * + * You can also override the response given to the caller by returning a `NextResponse` + * + * @default `req.headers.get("authorization")?.replace("Bearer ", "") ?? null` + */ + getKey?: (req: MiddlewareRequest) => string; + + /** + * Automatically return a custom response when a key is invalid + */ + onInvalidKey?: (req: MiddlewareRequest) => MiddlewareResponse; + + /** + * What to do if things go wrong + */ + onError?: (req: MiddlewareRequest) => MiddlewareResponse; +}; + export type withUnkeyRatelimitConfig = { + /** + * The Unkey configuration for the rate limiter + */ config: RatelimitConfig; + + /** + * Custom function to get the identifier for the rate limiter + */ getIdentifier?: (req: MiddlewareRequest) => string; + + /** + * Custom function to handle when the rate limit is exceeded + */ onExceeded?: (req: MiddlewareRequest) => MiddlewareResponse; + + /** + * Custom function to handle when an error occurs + */ onError?: (req: MiddlewareRequest) => MiddlewareResponse; }; + export type withUnkeyConfig = { + auth?: withUnkeyApiKeyConfig; ratelimit?: withUnkeyRatelimitConfig; logger?: Logger; }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f207eeff3c..039e769b5e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1353,6 +1353,9 @@ importers: '@redwoodjs/vite': specifier: 8.0.0-canary.542 version: 8.0.0-canary.542(@types/node@20.12.7)(csstype@3.1.3)(graphql-tag@2.12.6)(react-dom@18.3.1)(webpack@5.91.0) + '@unkey/api': + specifier: workspace:^ + version: link:../api '@unkey/ratelimit': specifier: workspace:^ version: link:../ratelimit From 5e6d6966f7e0d6ed9eaa63417510d381835a440e Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Fri, 10 May 2024 08:49:08 -0400 Subject: [PATCH 20/33] WIP auth key middleware --- packages/redwoodjs/console | 2 - packages/redwoodjs/src/auth/index.ts | 1 + .../redwoodjs/src/auth/middleware/README.ts | 0 .../redwoodjs/src/auth/middleware/index.ts | 71 +++++++++ .../redwoodjs/src/auth/middleware/types.ts | 53 +++++++ packages/redwoodjs/src/ratelimit/index.ts | 135 ++++-------------- packages/redwoodjs/src/ratelimit/types.ts | 43 +----- 7 files changed, 155 insertions(+), 150 deletions(-) delete mode 100644 packages/redwoodjs/console create mode 100644 packages/redwoodjs/src/auth/index.ts create mode 100644 packages/redwoodjs/src/auth/middleware/README.ts create mode 100644 packages/redwoodjs/src/auth/middleware/index.ts create mode 100644 packages/redwoodjs/src/auth/middleware/types.ts diff --git a/packages/redwoodjs/console b/packages/redwoodjs/console deleted file mode 100644 index 64c0ddf128..0000000000 --- a/packages/redwoodjs/console +++ /dev/null @@ -1,2 +0,0 @@ -{"level":60,"time":1715026201796,"pid":94751,"hostname":"depthcharge-air-3303.local","msg":">>> Unkey bopom"} -{"level":50,"time":1715026201796,"pid":94751,"hostname":"depthcharge-air-3303.local","msg":"Error in withUnkey"} diff --git a/packages/redwoodjs/src/auth/index.ts b/packages/redwoodjs/src/auth/index.ts new file mode 100644 index 0000000000..758c3c6824 --- /dev/null +++ b/packages/redwoodjs/src/auth/index.ts @@ -0,0 +1 @@ +export * from "./middleware"; diff --git a/packages/redwoodjs/src/auth/middleware/README.ts b/packages/redwoodjs/src/auth/middleware/README.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/redwoodjs/src/auth/middleware/index.ts b/packages/redwoodjs/src/auth/middleware/index.ts new file mode 100644 index 0000000000..dfd6436610 --- /dev/null +++ b/packages/redwoodjs/src/auth/middleware/index.ts @@ -0,0 +1,71 @@ +import { Unkey } from "@unkey/api"; +import { version } from "../../../package.json"; + +import type { Logger } from "@redwoodjs/api/logger"; + +import type { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; +import type { withUnkeyConfig } from "./types"; + +const defaultLogger = require("abstract-logging") as Logger; + +const withUnkey = (config: withUnkeyConfig) => { + const logger = config.logger || defaultLogger; + logger.debug("withUnkey middleware"); + + if (config.auth) { + return async (req: MiddlewareRequest, res: MiddlewareResponse) => { + /** + * Get key from request and return a response early if not found + */ + const key = config.auth?.getKey + ? config.auth.getKey(req) + : req.headers.get("authorization")?.replace("Bearer ", "") ?? null; + + if (key === null) { + res.body = "Unauthorized"; + res.status = 401; + return res; + } + + if (typeof key !== "string") { + // why not error? + return key; + } + + const unkey = new Unkey({ + rootKey: "public", + wrapperSdkVersion: `@unkey/redwoodjs@${version}`, + disableTelemetry: config.auth?.disableTelemetry, + }); + + const unkeyVerificationResult = await unkey.keys.verify( + config.auth?.apiId ? { key, apiId: config.auth?.apiId } : { key }, + ); + + if (unkeyVerificationResult.error) { + if (config.auth?.onError) { + return config.auth.onError(req, unkeyVerificationResult.error); + } + console.error( + `unkey error: [CODE: ${unkeyVerificationResult.error.code}] - [TRACE: ${unkeyVerificationResult.error.requestId}] - ${unkeyVerificationResult.error.message} - read more at ${unkeyVerificationResult.error.docs}`, + ); + + res.body = "Internal Server Error"; + res.status = 500; + } + + if (!unkeyVerificationResult.result?.valid) { + if (config.auth?.onInvalidKey) { + return config.auth.onInvalidKey(req, unkeyVerificationResult.result); + } + + res.body = "Unauthorized"; + res.status = 401; + } + + return res; + }; + } +}; + +export default withUnkey; diff --git a/packages/redwoodjs/src/auth/middleware/types.ts b/packages/redwoodjs/src/auth/middleware/types.ts new file mode 100644 index 0000000000..4b8798bf62 --- /dev/null +++ b/packages/redwoodjs/src/auth/middleware/types.ts @@ -0,0 +1,53 @@ +import type { ErrorResponse, Unkey } from "@unkey/api"; + +import type { Logger } from "@redwoodjs/api/logger"; +import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; +import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; + +type VerifyResponse = Awaited["keys"]["verify"]>>; +export type UnkeyContext = VerifyResponse["result"]; + +export type withUnkeyApiKeyConfig = { + /** + * The apiId to verify against. + * + * This will be required soon. + */ + apiId?: string; + + /** + * + * By default telemetry data is enabled, and sends: + * runtime (Node.js / Edge) + * platform (Node.js / Vercel / AWS) + * SDK version + */ + disableTelemetry?: boolean; + + /** + * How to get the key from the request + * Usually the key is provided in an `Authorization` header, but you can do what you want. + * + * Return the key as string, or null if it doesn't exist. + * + * You can also override the response given to the caller by returning a `NextResponse` + * + * @default `req.headers.get("authorization")?.replace("Bearer ", "") ?? null` + */ + getKey?: (req: MiddlewareRequest) => string; + + /** + * Automatically return a custom response when a key is invalid + */ + onInvalidKey?: (req: MiddlewareRequest, result: UnkeyContext) => MiddlewareResponse; + + /** + * What to do if things go wrong + */ + onError?: (req: MiddlewareRequest, err: ErrorResponse["error"]) => MiddlewareResponse; +}; + +export type withUnkeyConfig = { + auth?: withUnkeyApiKeyConfig; + logger?: Logger; +}; diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index 4c849fd101..8115e594c5 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -1,4 +1,3 @@ -import { Unkey } from "@unkey/api"; import { Ratelimit } from "@unkey/ratelimit"; import { version } from "../../package.json"; @@ -64,123 +63,47 @@ const defaultLogger = require("abstract-logging") as Logger; * */ const withUnkey = (config: withUnkeyConfig) => { - if (!config) { - throw new Error("withUnkey requires a configuration object"); - } - - if (!config.ratelimit && !config.auth) { - throw new Error("withUnkey requires a ratelimit or auth configuration object"); - } - const logger = config.logger || defaultLogger; - if (config.auth) { - return async (req: MiddlewareRequest, res: MiddlewareResponse) => { - /** - * Get key from request and return a response early if not found - */ - const key = config.auth?.getKey - ? config.auth.getKey(req) - : req.headers.get("authorization")?.replace("Bearer ", "") ?? null; - - if (key === null) { - res.body = "Unauthorized"; - res.status = 401; - return res; - } - - if (typeof key !== "string") { - return key; - } - - const unkey = new Unkey({ - rootKey: "public", - wrapperSdkVersion: `@unkey/redwoodjs@${version}`, - disableTelemetry: config.auth?.disableTelemetry, - }); - - const unkeyVerificationResult = await unkey.keys.verify( - config.auth?.apiId ? { key, apiId: config.auth?.apiId } : { key }, - ); - - if (unkeyVerificationResult.error) { - if (config.auth?.onError) { - return config.auth.onError( - req, - //unkeyVerificationResult.error - ); - } - console.error( - `unkey error: [CODE: ${unkeyVerificationResult.error.code}] - [TRACE: ${unkeyVerificationResult.error.requestId}] - ${unkeyVerificationResult.error.message} - read more at ${unkeyVerificationResult.error.docs}`, - ); - - res.body = "Internal Server Error"; - res.status = 500; - } - - if (!unkeyVerificationResult.result?.valid) { - if (config.auth?.onInvalidKey) { - return config.auth.onInvalidKey( - req, //res.result - ); - } + const unkeyRateLimiter = new Ratelimit(config.ratelimit.config); - res.body = "Unauthorized"; - res.status = 401; - - // return new NextResponse("Unauthorized", { status: 500 }); - } - - return res; - }; - } - - if (config.ratelimit) { - const unkeyRateLimiter = new Ratelimit(config.ratelimit.config); - - return async (req: MiddlewareRequest, res: MiddlewareResponse) => { - const getIdentifier = config.ratelimit?.getIdentifier || defaultRatelimitIdentifier; + return async (req: MiddlewareRequest, res: MiddlewareResponse) => { + const getIdentifier = config.ratelimit?.getIdentifier || defaultRatelimitIdentifier; - const onExceeded = config.ratelimit?.onExceeded || defaultRatelimitExceededResponse; + const onExceeded = config.ratelimit?.onExceeded || defaultRatelimitExceededResponse; - const onError = config.ratelimit?.onError || defaultRatelimitErrorResponse; + const onError = config.ratelimit?.onError || defaultRatelimitErrorResponse; - try { - const identifier = getIdentifier(req); + try { + const identifier = getIdentifier(req); - const ratelimit = await unkeyRateLimiter.limit(identifier); + const ratelimit = await unkeyRateLimiter.limit(identifier); - if (!ratelimit.success) { - logger.debug("Rate limit exceeded", { - ratelimit, - identifier, - }); - const response = onExceeded(req); - if (response.status !== 429) { - logger.warn("Rate limit exceeded response is not 429. Overriding status.", response); - response.status = 429; - } - return response; + if (!ratelimit.success) { + logger.debug("Rate limit exceeded", { + ratelimit, + identifier, + }); + const response = onExceeded(req); + if (response.status !== 429) { + logger.warn("Rate limit exceeded response is not 429. Overriding status.", response); + response.status = 429; } - } catch (e) { - logger.error("Error in withUnkey", e); - const errorResponse = onError(req); - if (errorResponse.status !== 500) { - logger.warn( - `Rate limit error response is ${errorResponse.status}. Consider changing status to 500.`, - errorResponse, - ); - } - - return errorResponse; + return response; + } + } catch (e) { + logger.error("Error in withUnkey", e); + const errorResponse = onError(req); + if (errorResponse.status !== 500) { + logger.warn( + `Rate limit error response is ${errorResponse.status}. Consider changing status to 500.`, + errorResponse, + ); } - return res; - }; - } + return errorResponse; + } - return async (req: MiddlewareRequest, res: MiddlewareResponse) => { - logger.error(req, "No configuration provided. Skipping middleware."); return res; }; }; diff --git a/packages/redwoodjs/src/ratelimit/types.ts b/packages/redwoodjs/src/ratelimit/types.ts index afc4a621d2..7a73600143 100644 --- a/packages/redwoodjs/src/ratelimit/types.ts +++ b/packages/redwoodjs/src/ratelimit/types.ts @@ -3,46 +3,6 @@ import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; import type { RatelimitConfig } from "@unkey/ratelimit"; -export type withUnkeyApiKeyConfig = { - /** - * The apiId to verify against. - * - * This will be required soon. - */ - apiId?: string; - - /** - * - * By default telemetry data is enabled, and sends: - * runtime (Node.js / Edge) - * platform (Node.js / Vercel / AWS) - * SDK version - */ - disableTelemetry?: boolean; - - /** - * How to get the key from the request - * Usually the key is provided in an `Authorization` header, but you can do what you want. - * - * Return the key as string, or null if it doesn't exist. - * - * You can also override the response given to the caller by returning a `NextResponse` - * - * @default `req.headers.get("authorization")?.replace("Bearer ", "") ?? null` - */ - getKey?: (req: MiddlewareRequest) => string; - - /** - * Automatically return a custom response when a key is invalid - */ - onInvalidKey?: (req: MiddlewareRequest) => MiddlewareResponse; - - /** - * What to do if things go wrong - */ - onError?: (req: MiddlewareRequest) => MiddlewareResponse; -}; - export type withUnkeyRatelimitConfig = { /** * The Unkey configuration for the rate limiter @@ -66,7 +26,6 @@ export type withUnkeyRatelimitConfig = { }; export type withUnkeyConfig = { - auth?: withUnkeyApiKeyConfig; - ratelimit?: withUnkeyRatelimitConfig; + ratelimit: withUnkeyRatelimitConfig; logger?: Logger; }; From 4b9cf393fb2b392ac4ce2f67d915b5572ffa19e1 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sat, 11 May 2024 12:03:26 -0400 Subject: [PATCH 21/33] Refactor and rename --- .../ts/redwoodjs/middleware/ratelimiting.mdx | 207 ----------------- apps/docs/libraries/ts/redwoodjs/overview.mdx | 8 +- .../libraries/ts/redwoodjs/ratelimiting.mdx | 184 +++++++++++++++ apps/docs/mint.json | 5 +- packages/redwoodjs/src/auth/index.ts | 1 - .../redwoodjs/src/auth/middleware/index.ts | 71 ------ .../src/{auth/middleware => keys}/README.ts | 0 packages/redwoodjs/src/keys/index.ts | 68 ++++++ .../src/{auth/middleware => keys}/types.ts | 8 +- packages/redwoodjs/src/ratelimit/README.md | 195 +++++++--------- ...t.ts => createRatelimitMiddleware.test.ts} | 218 ++++++++---------- ...telimitIdentifier.test.ts => util.test.ts} | 2 +- packages/redwoodjs/src/ratelimit/index.ts | 69 ++---- packages/redwoodjs/src/ratelimit/types.ts | 8 +- 14 files changed, 467 insertions(+), 577 deletions(-) delete mode 100644 apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx create mode 100644 apps/docs/libraries/ts/redwoodjs/ratelimiting.mdx delete mode 100644 packages/redwoodjs/src/auth/index.ts delete mode 100644 packages/redwoodjs/src/auth/middleware/index.ts rename packages/redwoodjs/src/{auth/middleware => keys}/README.ts (100%) create mode 100644 packages/redwoodjs/src/keys/index.ts rename packages/redwoodjs/src/{auth/middleware => keys}/types.ts (93%) rename packages/redwoodjs/src/ratelimit/__tests__/{withUnkey.test.ts => createRatelimitMiddleware.test.ts} (56%) rename packages/redwoodjs/src/ratelimit/__tests__/{util/defaultRatelimitIdentifier.test.ts => util.test.ts} (95%) diff --git a/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx b/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx deleted file mode 100644 index 49d1f8861a..0000000000 --- a/apps/docs/libraries/ts/redwoodjs/middleware/ratelimiting.mdx +++ /dev/null @@ -1,207 +0,0 @@ ---- -title: "Rate limiting" -description: "Unkey Rate limiting with RedwoodJS Middleware" ---- - -# Usage - -Rate limit requests using `withUnkey` middleware. - -Middleware is only available when SSR is enabled in RedwoodJS. - -## Unkey Setup - -See [Rate limiting Onboarding](https://www.unkey.com/docs/onboarding/onboarding-ratelimiting) to get started with standalone [rate limiting](https://www.unkey.com/docs/apis/features/ratelimiting) from [Unkey](https://www.unkey.com). - -Note: Be sure to set your `UNKEY_ROOT_KEY` or key to be used for rate limiting in an `.env` file. - -## Examples - -`withUnkey` provides several ways to customize rate limiting for a variety of use cases. - -The following examples sow how to set: - -- pattern matches when registering the middleware to match paths on which to enforce rate limits -- custom identifier generator function -- custom rate limit exceeded responses -- custom error responses - -### Rate Limit All Requests - -To rate limit all requests, register the unkeyMiddleware without route matching. - -```ts file="web/src/entry.server.tsx" -import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyConfig } from "@unkey/redwoodjs"; - -export const registerMiddleware = () => { - const config: withUnkeyConfig = { - ratelimit: { - config: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - }, - }; - - const unkeyMiddleware = withUnkey(config); - - return [unkeyMiddleware]; -}; -``` - -### Basic Matching - -To rate limit a matching rout, register the unkeyMiddleware with the matching pattern. - -```ts file="web/src/entry.server.tsx" -import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyConfig } from "@unkey/redwoodjs"; - -export const registerMiddleware = () => { - const config: withUnkeyConfig = { - ratelimit: { - config: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - }, - }; - - const unkeyMiddleware = withUnkey(config); - - return [[unkeyMiddleware, "/blog-post/:slug(\\d{1,})"]]; -}; -``` - -Note: If you need to match multiple patterns you can compose a complex expression - -```ts -return [[unkeyMiddleware, "/rss.(xml|atom|json)"]]; -``` - -or register multiple with different patterns: - -```ts -return [ - [unkeyMiddleware, "/blog-post/:slug(\\d{1,})"], - [unkeyMiddleware, "/admin"], -]; -``` - -### With Custom Identifier Function and Third Party Authentication - -Here, we use a custom identifier function `supabaseRatelimitIdentifier` that: - -- checks is the request is authenticated -- constructs the identifier `sub` from the current user, since here the currentUser will be a JWT where the user id is the `sub` claim -- registers `supabaseAuthMiddleware` before `unkeyMiddleware` so the request can be authenticated before determining limits - -```ts file="web/src/entry.server.ts" -import createSupabaseAuthMiddleware from "@redwoodjs/auth-supabase-middleware"; -import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyConfig } from "@unkey/redwoodjs"; -import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; -import type { TagDescriptor } from "@redwoodjs/web"; - -import App from "./App"; -import { Document } from "./Document"; - -// eslint-disable-next-line no-restricted-imports -import { getCurrentUser } from "$api/src/lib/auth"; - -interface Props { - css: string[]; - meta?: TagDescriptor[]; -} - -export const supabaseRatelimitIdentifier = (req: MiddlewareRequest) => { - const authContext = req?.serverAuthContext?.get(); - console.log(">>>> in supabaseRatelimitIdentifier", authContext); - const identifier = authContext?.isAuthenticated - ? (authContext.currentUser?.sub as string) || "anonymous-user" - : "192.168.1.1"; - return identifier; -}; - -export const registerMiddleware = () => { - const config: withUnkeyConfig = { - ratelimit: { - config: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - getIdentifier: supabaseRatelimitIdentifier, - }, - }; - const unkeyMiddleware = withUnkey(config); - const supabaseAuthMiddleware = createSupabaseAuthMiddleware({ - getCurrentUser, - }); - - return [ - supabaseAuthMiddleware, - [unkeyMiddleware, "/blog-post/:slug(\\d{1,})"], - ]; -}; -``` - -## Custom Rate Limit Exceeded Response - -```ts -export const registerMiddleware = () => { - const config: withUnkeyConfig = { - ratelimit: { - config: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - onExceeded: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Custom Rate limit exceeded message", { - status: 429, - }); - }, - }, - }; - const unkeyMiddleware = withUnkey(config); - - return [unkeyMiddleware]; -}; -``` - -## Custom Rate Limit Error Response - -```ts -export const registerMiddleware = () => { - const config: withUnkeyConfig = { - ratelimit: {config: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - matcher: , - onError: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Custom Error message when rate limiting", { - status: 500, - }); - }, - }; - const unkeyMiddleware = withUnkey(config); - - return [[unkeyMiddleware, "/blog-post/:slug(\\d{1,})"]]; -}; -``` diff --git a/apps/docs/libraries/ts/redwoodjs/overview.mdx b/apps/docs/libraries/ts/redwoodjs/overview.mdx index 54ce262a1f..75e68732a9 100644 --- a/apps/docs/libraries/ts/redwoodjs/overview.mdx +++ b/apps/docs/libraries/ts/redwoodjs/overview.mdx @@ -5,14 +5,14 @@ description: "RedwoodJS SDK for Unkey" The official RedwoodJS SDK for Unkey. -- Rate limit requests using `withUnkey` middleware +- Rate limit requests using `createRatelimitMiddleware` middleware ## Install - ```bash - yarn rw workspace web add @unkey/redwoodjs - ``` + ``` + bash yarn rw workspace web add @unkey/redwoodjs + ``` diff --git a/apps/docs/libraries/ts/redwoodjs/ratelimiting.mdx b/apps/docs/libraries/ts/redwoodjs/ratelimiting.mdx new file mode 100644 index 0000000000..6bd635e2bc --- /dev/null +++ b/apps/docs/libraries/ts/redwoodjs/ratelimiting.mdx @@ -0,0 +1,184 @@ +--- +title: "Rate Limiting" +description: "Implement rate limiting with RedwoodJS Middleware and Unkey" +--- + +# Usage + +Implement request rate limiting in your RedwoodJS application using the `createRatelimitMiddleware` from Unkey. + + + This middleware is only available when Server-Side Rendering (SSR) is enabled + in RedwoodJS. + + +To learn more about this middleware, visit the [RedwoodJS Middleware documentation](https://www.unkey.com/docs/libraries/ts/redwoodjs/middleware/ratelimiting). + +## Setup + +To get started with standalone rate limiting using Unkey, see the [Rate Limiting Onboarding Guide](https://www.unkey.com/docs/onboarding/onboarding-ratelimiting). + +**Important**: Ensure that your `UNKEY_ROOT_KEY` is set in your `.env` file for rate limiting. + +## Examples + +The `createRatelimitMiddleware` function allows for extensive customization to suit various use cases. Below are examples demonstrating how to: + +- Implement pattern matches to enforce rate limits on specific paths. +- Utilize a custom identifier generator function. +- Customize responses when rate limits are exceeded. +- Provide custom error responses. + +### Rate Limit All Requests + +To apply a rate limit to all requests, register the middleware globally without route matching: + +```ts file="web/src/entry.server.tsx" +import createRatelimitMiddleware from "@unkey/redwoodjs"; +import type { RatelimitMiddlewareConfig } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const config: RatelimitMiddlewareConfig = { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }; + + const middleware = createRatelimitMiddleware(config); + + return [middleware]; +}; +``` + +### Basic Route Matching + +To rate limit requests on specific routes, register the middleware with a pattern match: + +```ts file="web/src/entry.server.tsx" +import createRatelimitMiddleware from "@unkey/redwoodjs"; +import type { RatelimitMiddlewareConfig } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const config: RatelimitMiddlewareConfig = { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + }; + + const middleware = createRatelimitMiddleware(config); + + return [[middleware, "/blog-post/:slug(\\d{1,})"]]; +}; +``` + +To handle multiple patterns, either compose a complex expression + +```ts +return [[middleware, "/rss.(xml|atom|json)"]]; +``` + +or register multiple patterns: + +```ts +return [ + [middleware, "/blog-post/:slug(\\d{1,})"], + [middleware, "/admin"], +]; +``` + +### With Custom Identifier Function and Third Party Authentication + +Customize the identifier function to utilize user authentication status, such as with Supabase. + +Here, we use a custom identifier function `supabaseRatelimitIdentifier` that: + +- checks is the request is authenticated +- constructs the identifier `sub` from the current user, since here the currentUser will be a JWT where the user id is the `sub` claim +- registers `supabaseAuthMiddleware` before `middleware` so the request can be authenticated before determining limits + +```ts file="web/src/entry.server.ts" +import createSupabaseAuthMiddleware from "@redwoodjs/auth-supabase-middleware"; +import createRatelimitMiddleware from "@unkey/redwoodjs"; +import type { RatelimitMiddlewareConfig } from "@unkey/redwoodjs"; +import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; +import type { TagDescriptor } from "@redwoodjs/web"; + +import App from "./App"; +import { Document } from "./Document"; + +// eslint-disable-next-line no-restricted-imports +import { getCurrentUser } from "$api/src/lib/auth"; + +interface Props { + css: string[]; + meta?: TagDescriptor[]; +} + +export const supabaseRatelimitIdentifier = (req: MiddlewareRequest) => { + const authContext = req?.serverAuthContext?.get(); + console.log(">>>> in supabaseRatelimitIdentifier", authContext); + const identifier = authContext?.isAuthenticated + ? (authContext.currentUser?.sub as string) || "anonymous-user" + : "192.168.1.1"; + return identifier; +}; + +export const registerMiddleware = () => { + const config: RatelimitMiddlewareConfig = { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + getIdentifier: supabaseRatelimitIdentifier, + }; + const middleware = createRatelimitMiddleware(config); + const supabaseAuthMiddleware = createSupabaseAuthMiddleware({ + getCurrentUser, + }); + + return [supabaseAuthMiddleware, [middleware, "/blog-post/:slug(\\d{1,})"]]; +}; +``` + +### Custom Rate Limit Exceeded and Error Responses + +Define custom responses for exceeded limits and errors: + +```ts +export const registerMiddleware = () => { + const config: RatelimitMiddlewareConfig = { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + onExceeded: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Rate limit exceeded message", { + status: 429, + }); + }, + onError: (_req: MiddlewareRequest) => { + return new MiddlewareResponse( + "Custom Error message when rate limiting fails", + { + status: 500, + } + ); + }, + }; + const middleware = createRatelimitMiddleware(config); + + return [middleware]; +}; +``` diff --git a/apps/docs/mint.json b/apps/docs/mint.json index e557624359..8d5ea38db2 100644 --- a/apps/docs/mint.json +++ b/apps/docs/mint.json @@ -211,10 +211,7 @@ "group": "@unkey/redwoodjs", "pages": [ "libraries/ts/redwoodjs/overview", - { - "group": "withUnkey", - "pages": ["libraries/ts/redwoodjs/middleware/ratelimiting"] - } + "libraries/ts/redwoodjs/ratelimiting" ] } ] diff --git a/packages/redwoodjs/src/auth/index.ts b/packages/redwoodjs/src/auth/index.ts deleted file mode 100644 index 758c3c6824..0000000000 --- a/packages/redwoodjs/src/auth/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./middleware"; diff --git a/packages/redwoodjs/src/auth/middleware/index.ts b/packages/redwoodjs/src/auth/middleware/index.ts deleted file mode 100644 index dfd6436610..0000000000 --- a/packages/redwoodjs/src/auth/middleware/index.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Unkey } from "@unkey/api"; -import { version } from "../../../package.json"; - -import type { Logger } from "@redwoodjs/api/logger"; - -import type { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; -import type { withUnkeyConfig } from "./types"; - -const defaultLogger = require("abstract-logging") as Logger; - -const withUnkey = (config: withUnkeyConfig) => { - const logger = config.logger || defaultLogger; - logger.debug("withUnkey middleware"); - - if (config.auth) { - return async (req: MiddlewareRequest, res: MiddlewareResponse) => { - /** - * Get key from request and return a response early if not found - */ - const key = config.auth?.getKey - ? config.auth.getKey(req) - : req.headers.get("authorization")?.replace("Bearer ", "") ?? null; - - if (key === null) { - res.body = "Unauthorized"; - res.status = 401; - return res; - } - - if (typeof key !== "string") { - // why not error? - return key; - } - - const unkey = new Unkey({ - rootKey: "public", - wrapperSdkVersion: `@unkey/redwoodjs@${version}`, - disableTelemetry: config.auth?.disableTelemetry, - }); - - const unkeyVerificationResult = await unkey.keys.verify( - config.auth?.apiId ? { key, apiId: config.auth?.apiId } : { key }, - ); - - if (unkeyVerificationResult.error) { - if (config.auth?.onError) { - return config.auth.onError(req, unkeyVerificationResult.error); - } - console.error( - `unkey error: [CODE: ${unkeyVerificationResult.error.code}] - [TRACE: ${unkeyVerificationResult.error.requestId}] - ${unkeyVerificationResult.error.message} - read more at ${unkeyVerificationResult.error.docs}`, - ); - - res.body = "Internal Server Error"; - res.status = 500; - } - - if (!unkeyVerificationResult.result?.valid) { - if (config.auth?.onInvalidKey) { - return config.auth.onInvalidKey(req, unkeyVerificationResult.result); - } - - res.body = "Unauthorized"; - res.status = 401; - } - - return res; - }; - } -}; - -export default withUnkey; diff --git a/packages/redwoodjs/src/auth/middleware/README.ts b/packages/redwoodjs/src/keys/README.ts similarity index 100% rename from packages/redwoodjs/src/auth/middleware/README.ts rename to packages/redwoodjs/src/keys/README.ts diff --git a/packages/redwoodjs/src/keys/index.ts b/packages/redwoodjs/src/keys/index.ts new file mode 100644 index 0000000000..196f87395d --- /dev/null +++ b/packages/redwoodjs/src/keys/index.ts @@ -0,0 +1,68 @@ +import { Unkey } from "@unkey/api"; +import { version } from "../../package.json"; + +import type { Logger } from "@redwoodjs/api/logger"; + +import type { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; +import type { ApiKeyMiddlewareConfig } from "./types"; + +const defaultLogger = require("abstract-logging") as Logger; + +const ApiKeyMiddleware = (config: ApiKeyMiddlewareConfig) => { + const logger = config.logger || defaultLogger; + + return async (req: MiddlewareRequest, res: MiddlewareResponse) => { + /** + * Get key from request and return a response early if not found + */ + const key = config.getKey + ? config.getKey(req) + : req.headers.get("authorization")?.replace("Bearer ", "") ?? null; + + if (key === null) { + res.body = "Unauthorized"; + res.status = 401; + return res; + } + + if (typeof key !== "string") { + // why not error? + return key; + } + + const unkey = new Unkey({ + rootKey: "public", + wrapperSdkVersion: `@unkey/redwoodjs@${version}`, + disableTelemetry: config.disableTelemetry, + }); + + const unkeyVerificationResult = await unkey.keys.verify( + config.apiId ? { key, apiId: config.apiId } : { key }, + ); + + if (unkeyVerificationResult.error) { + if (config.onError) { + return config.onError(req, unkeyVerificationResult.error); + } + logger.error( + `unkey error: [CODE: ${unkeyVerificationResult.error.code}] - [TRACE: ${unkeyVerificationResult.error.requestId}] - ${unkeyVerificationResult.error.message} - read more at ${unkeyVerificationResult.error.docs}`, + ); + + res.body = "Internal Server Error"; + res.status = 500; + } + + if (!unkeyVerificationResult.result?.valid) { + if (config.onInvalidKey) { + return config.onInvalidKey(req, unkeyVerificationResult.result); + } + + res.body = "Unauthorized"; + res.status = 401; + } + + return res; + }; +}; + +export default ApiKeyMiddleware; diff --git a/packages/redwoodjs/src/auth/middleware/types.ts b/packages/redwoodjs/src/keys/types.ts similarity index 93% rename from packages/redwoodjs/src/auth/middleware/types.ts rename to packages/redwoodjs/src/keys/types.ts index 4b8798bf62..bc9d0e7ebc 100644 --- a/packages/redwoodjs/src/auth/middleware/types.ts +++ b/packages/redwoodjs/src/keys/types.ts @@ -7,7 +7,7 @@ import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; type VerifyResponse = Awaited["keys"]["verify"]>>; export type UnkeyContext = VerifyResponse["result"]; -export type withUnkeyApiKeyConfig = { +export type ApiKeyMiddlewareConfig = { /** * The apiId to verify against. * @@ -45,9 +45,9 @@ export type withUnkeyApiKeyConfig = { * What to do if things go wrong */ onError?: (req: MiddlewareRequest, err: ErrorResponse["error"]) => MiddlewareResponse; -}; -export type withUnkeyConfig = { - auth?: withUnkeyApiKeyConfig; + /* + * RedwoodJS-compatible Logger to use for logging + */ logger?: Logger; }; diff --git a/packages/redwoodjs/src/ratelimit/README.md b/packages/redwoodjs/src/ratelimit/README.md index dbf1861e22..b9abb012e8 100644 --- a/packages/redwoodjs/src/ratelimit/README.md +++ b/packages/redwoodjs/src/ratelimit/README.md @@ -1,105 +1,108 @@ -# withUnkey +# RedwoodJS Rate Limiting -[RedwoodJS Middleware](https://www.unkey.com/docs/libraries/ts/redwoodjs/middleware/ratelimiting) to rate limit requests using Unkey +# Usage + +Implement request rate limiting in your RedwoodJS application using the `createRatelimitMiddleware` from Unkey. + + + This middleware is only available when Server-Side Rendering (SSR) is enabled + in RedwoodJS. + + +To learn more about this middleware, visit the [RedwoodJS Middleware documentation](https://www.unkey.com/docs/libraries/ts/redwoodjs/middleware/ratelimiting). ## Setup -See [Rate limiting Onboarding](https://www.unkey.com/docs/onboarding/onboarding-ratelimiting) to get started with standalone [rate limiting](https://www.unkey.com/docs/apis/features/ratelimiting) from [Unkey](https://www.unkey.com). +To get started with standalone rate limiting using Unkey, see the [Rate Limiting Onboarding Guide](https://www.unkey.com/docs/onboarding/onboarding-ratelimiting). -Note: Be sure to set your `UNKEY_ROOT_KEY` or key to be used for rate limiting in an `.env` file. +**Important**: Ensure that your `UNKEY_ROOT_KEY` is set in your `.env` file for rate limiting. ## Examples -`withUnkey` provides several ways to customize rate limiting for a variety of use cases. - -The following examples sow how to set: +The `createRatelimitMiddleware` function allows for extensive customization to suit various use cases. Below are examples demonstrating how to: -- pattern matches when registering the middleware to match paths on which to enforce rate limits -- custom identifier generator function -- custom rate limit exceeded responses -- custom error responses +- Implement pattern matches to enforce rate limits on specific paths. +- Utilize a custom identifier generator function. +- Customize responses when rate limits are exceeded. +- Provide custom error responses. ### Rate Limit All Requests -To rate limit all requests, register the unkeyMiddleware without route matching. +To apply a rate limit to all requests, register the middleware globally without route matching: ```ts file="web/src/entry.server.tsx" -import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyConfig } from "@unkey/redwoodjs"; +import createRatelimitMiddleware from "@unkey/redwoodjs"; +import type { RatelimitMiddlewareConfig } from "@unkey/redwoodjs"; export const registerMiddleware = () => { - const config: withUnkeyConfig = { - ratelimit: { - config: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - }, + const config: RatelimitMiddlewareConfig = { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, }; - const unkeyMiddleware = withUnkey(config); + const middleware = createRatelimitMiddleware(config); - return [unkeyMiddleware]; + return [middleware]; }; ``` -### Basic Matching +### Basic Route Matching -To rate limit a matching rout, register the unkeyMiddleware with the matching pattern. +To rate limit requests on specific routes, register the middleware with a pattern match: ```ts file="web/src/entry.server.tsx" -import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyConfig } from "@unkey/redwoodjs"; +import createRatelimitMiddleware from "@unkey/redwoodjs"; +import type { RatelimitMiddlewareConfig } from "@unkey/redwoodjs"; export const registerMiddleware = () => { - const config: withUnkeyConfig = { - ratelimit: { - config: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, + const config: RatelimitMiddlewareConfig = { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, }, }; - const unkeyMiddleware = withUnkey(config); + const middleware = createRatelimitMiddleware(config); - return [[unkeyMiddleware, "/blog-post/:slug(\\d{1,})"]]; + return [[middleware, "/blog-post/:slug(\\d{1,})"]]; }; ``` -Note: If you need to match multiple patterns you can compose a complex expression +To handle multiple patterns, either compose a complex expression ```ts -return [[unkeyMiddleware, "/rss.(xml|atom|json)"]]; +return [[middleware, "/rss.(xml|atom|json)"]]; ``` -or register multiple with different patterns: +or register multiple patterns: ```ts return [ - [unkeyMiddleware, "/blog-post/:slug(\\d{1,})"], - [unkeyMiddleware, "/admin"], + [middleware, "/blog-post/:slug(\\d{1,})"], + [middleware, "/admin"], ]; ``` ### With Custom Identifier Function and Third Party Authentication +Customize the identifier function to utilize user authentication status, such as with Supabase. + Here, we use a custom identifier function `supabaseRatelimitIdentifier` that: - checks is the request is authenticated - constructs the identifier `sub` from the current user, since here the currentUser will be a JWT where the user id is the `sub` claim -- registers `supabaseAuthMiddleware` before `unkeyMiddleware` so the request can be authenticated before determining limits +- registers `supabaseAuthMiddleware` before `middleware` so the request can be authenticated before determining limits ```ts file="web/src/entry.server.ts" import createSupabaseAuthMiddleware from "@redwoodjs/auth-supabase-middleware"; -import withUnkey from "@unkey/redwoodjs"; -import type { withUnkeyConfig } from "@unkey/redwoodjs"; +import createRatelimitMiddleware from "@unkey/redwoodjs"; +import type { RatelimitMiddlewareConfig } from "@unkey/redwoodjs"; import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import type { TagDescriptor } from "@redwoodjs/web"; @@ -124,81 +127,55 @@ export const supabaseRatelimitIdentifier = (req: MiddlewareRequest) => { }; export const registerMiddleware = () => { - const config: withUnkeyConfig = { - ratelimit: { - config: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - getIdentifier: supabaseRatelimitIdentifier, + const config: RatelimitMiddlewareConfig = { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, }, + getIdentifier: supabaseRatelimitIdentifier, }; - const unkeyMiddleware = withUnkey(config); + const middleware = createRatelimitMiddleware(config); const supabaseAuthMiddleware = createSupabaseAuthMiddleware({ getCurrentUser, }); - return [ - supabaseAuthMiddleware, - [unkeyMiddleware, "/blog-post/:slug(\\d{1,})"], - ]; + return [supabaseAuthMiddleware, [middleware, "/blog-post/:slug(\\d{1,})"]]; }; ``` -## Custom Rate Limit Exceeded Response - -```ts -export const registerMiddleware = () => { - const config: withUnkeyConfig = { - ratelimit: { - config: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - onExceeded: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Custom Rate limit exceeded message", { - status: 429, - }); - }, - }, - }; - const unkeyMiddleware = withUnkey(config); - - return [unkeyMiddleware]; -}; -``` +### Custom Rate Limit Exceeded and Error Responses -## Custom Rate Limit Error Response +Define custom responses for exceeded limits and errors: ```ts export const registerMiddleware = () => { - const config: withUnkeyConfig = { - ratelimit: { - config: { - rootKey: process.env.UNKEY_ROOT_KEY, - namespace: "my-app", - limit: 1, - duration: "30s", - async: true, - }, - onError: (_req: MiddlewareRequest) => { - return new MiddlewareResponse( - "Custom Error message when rate limiting", - { - status: 500, - } - ); - }, + const config: RatelimitMiddlewareConfig = { + config: { + rootKey: process.env.UNKEY_ROOT_KEY, + namespace: "my-app", + limit: 1, + duration: "30s", + async: true, + }, + onExceeded: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Rate limit exceeded message", { + status: 429, + }); + }, + onError: (_req: MiddlewareRequest) => { + return new MiddlewareResponse( + "Custom Error message when rate limiting fails", + { + status: 500, + } + ); }, }; - const unkeyMiddleware = withUnkey(config); + const middleware = createRatelimitMiddleware(config); - return [unkeyMiddleware, ["/blog-post/:slug(\\d{1,})"]]; + return [middleware]; }; ``` diff --git a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/createRatelimitMiddleware.test.ts similarity index 56% rename from packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts rename to packages/redwoodjs/src/ratelimit/__tests__/createRatelimitMiddleware.test.ts index bd508b419b..bfdd34541a 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/withUnkey.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/createRatelimitMiddleware.test.ts @@ -3,8 +3,8 @@ import { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middlewar import { Ratelimit } from "@unkey/ratelimit"; import type { RatelimitConfig, RatelimitResponse } from "@unkey/ratelimit"; import { assert, describe, expect, it, vi } from "vitest"; -import withUnkey from "../index"; -import type { withUnkeyConfig } from "../types"; +import createRatelimitMiddleware from "../index"; +import type { RatelimitMiddlewareConfig } from "../types"; /** * Mock the Ratelimit class @@ -47,20 +47,18 @@ const defaultRateLimitConfig: Pick { it("should not rate limit", async () => { - const options: withUnkeyConfig = { - ratelimit: { - config: { - namespace: "192.168.1.1", - ...defaultRateLimitConfig, - }, + const config: RatelimitMiddlewareConfig = { + config: { + namespace: "192.168.1.1", + ...defaultRateLimitConfig, }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = createRatelimitMiddleware(config); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); - const result = await unkeyMiddleware(req, res); - expect(result.status).toBe(200); + const result = (await unkeyMiddleware(req, res)) as MiddlewareResponse; + expect(result?.status).toBe(200); }); it("should rate limit", async () => { @@ -68,208 +66,192 @@ describe("withUnkey", () => { // to be exceeded (status 429) because // it does not match the identifier generated by the withUnkey middleware // which is a defaulted value - const options: withUnkeyConfig = { - ratelimit: { - config: { - namespace: "my-app", - ...defaultRateLimitConfig, - }, + const config: RatelimitMiddlewareConfig = { + config: { + namespace: "my-app", + ...defaultRateLimitConfig, }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = createRatelimitMiddleware(config); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); const result = await unkeyMiddleware(req, res); - expect(result.status).toBe(429); + expect(result?.status).toBe(429); }); it("should be not rate limited with a custom default identifier function", async () => { // here the namespace will cause the rate limit // not to be exceeded (status 200) because it // matches the identifies generated by the withUnkey middleware - const options: withUnkeyConfig = { - ratelimit: { - config: { - namespace: "abcdefg", - ...defaultRateLimitConfig, - }, + const config: RatelimitMiddlewareConfig = { + config: { + namespace: "abcdefg", + ...defaultRateLimitConfig, + }, - getIdentifier: (_req: MiddlewareRequest) => { - return "abcdefg"; // matches namespace so no rate limit for this test - }, + getIdentifier: (_req: MiddlewareRequest) => { + return "abcdefg"; // matches namespace so no rate limit for this test }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = createRatelimitMiddleware(config); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); const result = await unkeyMiddleware(req, res); - expect(result.status).toBe(200); + expect(result?.status).toBe(200); }); it("should be limited with a custom default identifier function", async () => { // here the namespace will cause the rate limit to be exceeded (status 429) // because it does not match the identifier generated by the withUnkey middleware - const options: withUnkeyConfig = { - ratelimit: { - config: { - namespace: "12345", - ...defaultRateLimitConfig, - }, + const config: RatelimitMiddlewareConfig = { + config: { + namespace: "12345", + ...defaultRateLimitConfig, + }, - getIdentifier: (_req: MiddlewareRequest) => { - return "abcdefg"; - }, + getIdentifier: (_req: MiddlewareRequest) => { + return "abcdefg"; }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = createRatelimitMiddleware(config); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); const result = await unkeyMiddleware(req, res); - expect(result.status).toBe(429); + expect(result?.status).toBe(429); }); it("should be limited with a custom rate limit exceeded message function", async () => { // here the namespace will cause the rate limit to be exceeded (status 429) // because it does not match the identifier generated by the withUnkey middleware - const options: withUnkeyConfig = { - ratelimit: { - config: { - namespace: "exceeded", - ...defaultRateLimitConfig, - }, + const options: RatelimitMiddlewareConfig = { + config: { + namespace: "exceeded", + ...defaultRateLimitConfig, + }, - onExceeded: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Custom Rate limit exceeded message", { - status: 429, - }); - }, + onExceeded: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Rate limit exceeded message", { + status: 429, + }); }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = createRatelimitMiddleware(options); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); const result = await unkeyMiddleware(req, res); - expect(result.status).toBe(429); - expect(result.body).toBe("Custom Rate limit exceeded message"); + expect(result?.status).toBe(429); + expect(result?.body).toBe("Custom Rate limit exceeded message"); }); it("should error", async () => { // here the the identifier function will throw an error // which will cause a teh default error response to be returned - const options: withUnkeyConfig = { - ratelimit: { - config: { - namespace: "exceeded", - ...defaultRateLimitConfig, - }, + const options: RatelimitMiddlewareConfig = { + config: { + namespace: "exceeded", + ...defaultRateLimitConfig, + }, - getIdentifier: (_req: MiddlewareRequest) => { - throw new Error("Error simulated by test"); - }, + getIdentifier: (_req: MiddlewareRequest) => { + throw new Error("Error simulated by test"); }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = createRatelimitMiddleware(options); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); const result = await unkeyMiddleware(req, res); - expect(result.body).toBe("Internal server error"); - expect(result.status).toBe(500); + expect(result?.body).toBe("Internal server error"); + expect(result?.status).toBe(500); }); it("should error with custom message", async () => { // here the the identifier function will throw an error // which will cause the default error response to be returned - const options: withUnkeyConfig = { - ratelimit: { - config: { - namespace: "exceeded", - ...defaultRateLimitConfig, - }, + const options: RatelimitMiddlewareConfig = { + config: { + namespace: "exceeded", + ...defaultRateLimitConfig, + }, - getIdentifier: (_req: MiddlewareRequest) => { - throw new Error("Error simulated by test"); - }, - onError: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Custom Error message when rate limiting", { - status: 500, - }); - }, + getIdentifier: (_req: MiddlewareRequest) => { + throw new Error("Error simulated by test"); + }, + onError: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Custom Error message when rate limiting", { + status: 500, + }); }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = createRatelimitMiddleware(options); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); const result = await unkeyMiddleware(req, res); - expect(result.body).toBe("Custom Error message when rate limiting"); - expect(result.status).toBe(500); + expect(result?.body).toBe("Custom Error message when rate limiting"); + expect(result?.status).toBe(500); }); it("should error with custom message and status", async () => { // here the the identifier function will throw an error // which will cause a custom error response to be returned - const options: withUnkeyConfig = { - ratelimit: { - config: { - namespace: "exceeded", - ...defaultRateLimitConfig, - }, + const options: RatelimitMiddlewareConfig = { + config: { + namespace: "exceeded", + ...defaultRateLimitConfig, + }, - getIdentifier: (_req: MiddlewareRequest) => { - throw new Error("Error simulated by test"); - }, - onError: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Not implemented", { - status: 501, - }); - }, + getIdentifier: (_req: MiddlewareRequest) => { + throw new Error("Error simulated by test"); + }, + onError: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Not implemented", { + status: 501, + }); }, }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = createRatelimitMiddleware(options); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); const result = await unkeyMiddleware(req, res); - expect(result.body).toBe("Not implemented"); - expect(result.status).toBe(501); + expect(result?.body).toBe("Not implemented"); + expect(result?.status).toBe(501); }); it("should use a RedwoodJS-compatible logger", async () => { - const options: withUnkeyConfig = { - ratelimit: { - config: { - namespace: "exceeded", - ...defaultRateLimitConfig, - }, + const options: RatelimitMiddlewareConfig = { + config: { + namespace: "exceeded", + ...defaultRateLimitConfig, + }, - getIdentifier: (_req: MiddlewareRequest) => { - throw new Error("Error simulated by test"); - }, - onError: (_req: MiddlewareRequest) => { - return new MiddlewareResponse("Not implemented", { - status: 501, - }); - }, + getIdentifier: (_req: MiddlewareRequest) => { + throw new Error("Error simulated by test"); + }, + onError: (_req: MiddlewareRequest) => { + return new MiddlewareResponse("Not implemented", { + status: 501, + }); }, logger: createLogger({ options: { level: "error", enabled: true }, }), }; - const unkeyMiddleware = withUnkey(options); + const unkeyMiddleware = createRatelimitMiddleware(options); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); const result = await unkeyMiddleware(req, res); - expect(result.body).toBe("Not implemented"); - expect(result.status).toBe(501); + expect(result?.body).toBe("Not implemented"); + expect(result?.status).toBe(501); }); }); diff --git a/packages/redwoodjs/src/ratelimit/__tests__/util/defaultRatelimitIdentifier.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts similarity index 95% rename from packages/redwoodjs/src/ratelimit/__tests__/util/defaultRatelimitIdentifier.test.ts rename to packages/redwoodjs/src/ratelimit/__tests__/util.test.ts index 6091598cd4..e86f29d2fb 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/util/defaultRatelimitIdentifier.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts @@ -1,6 +1,6 @@ import { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import { assert, describe, expect, it } from "vitest"; -import { defaultRatelimitIdentifier } from "../../util"; +import { defaultRatelimitIdentifier } from "../util"; describe("defaultRatelimitIdentifier", () => { it("should return correct identifier", () => { diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index 8115e594c5..db42c0f411 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -10,70 +10,31 @@ import { import type { Logger } from "@redwoodjs/api/logger"; -import type { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; -import type { withUnkeyConfig } from "./types"; +import type { Middleware, MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; +import type { RatelimitMiddlewareConfig } from "./types"; const defaultLogger = require("abstract-logging") as Logger; /** - * withUnkey is RedwoodJS middleware that adds Unkey rate limiting to a route - * - * @see https://redwoodjs.com/docs/middleware#withUnkey - * @see https://www.unkey.com/docs/apis/features/ratelimiting - * - * Provide the Unkey rate limit configuration and the path matcher to apply the rate limit to. - * - * @param config withUnkeyOptions: withUnkeyOptions; - * @param config ratelimit: withUnkeyRatelimitConfig; - * @param config ratelimit config: RatelimitConfig; + * createRatelimitMiddleware creates RedwoodJS middleware + * that rate limits requests using Unkey's rate limiter. * * You can provide optional custom functions to construct rate limit identifier, * rate limit exceeded response, and rate limit error response. * - * @param config ratelimit getIdentifier?: (req: MiddlewareRequest) => string; - * @param config ratelimit onExceeded?: (req: MiddlewareRequest) => MiddlewareResponse; - * @param config ratelimit onError?: (req: MiddlewareRequest) => MiddlewareResponse; - * - * @param config logger?: Logger; - * - * @example - * ```ts file="web/src/entry.server.tsx" - * - * import withUnkey from '@unkey/redwoodjs' - * import type { withUnkeyConfig } from '@unkey/redwoodjs' - * - * export const registerMiddleware = () => { - * const config: withUnkeyConfig = { - * ratelimit: { - * config: { - * rootKey: process.env.UNKEY_ROOT_KEY, - * namespace: 'my-app', - * limit: 1, - * duration: '30s', - * async: true, - * }, - * } - * } - * - * const unkeyMiddleware = withUnkey(options) - * - * return [unkeyMiddleware] - * } - * ``` + * @see https://www.unkey.com/docs/apis/features/ratelimiting * */ -const withUnkey = (config: withUnkeyConfig) => { - const logger = config.logger || defaultLogger; - - const unkeyRateLimiter = new Ratelimit(config.ratelimit.config); +const createRatelimitMiddleware = ({ + config, + getIdentifier = defaultRatelimitIdentifier, + onExceeded = defaultRatelimitExceededResponse, + onError = defaultRatelimitErrorResponse, + logger = defaultLogger, +}: RatelimitMiddlewareConfig): Middleware => { + const unkeyRateLimiter = new Ratelimit(config); return async (req: MiddlewareRequest, res: MiddlewareResponse) => { - const getIdentifier = config.ratelimit?.getIdentifier || defaultRatelimitIdentifier; - - const onExceeded = config.ratelimit?.onExceeded || defaultRatelimitExceededResponse; - - const onError = config.ratelimit?.onError || defaultRatelimitErrorResponse; - try { const identifier = getIdentifier(req); @@ -92,7 +53,7 @@ const withUnkey = (config: withUnkeyConfig) => { return response; } } catch (e) { - logger.error("Error in withUnkey", e); + logger.error("Error in unkeyRateLimitMiddleware", e); const errorResponse = onError(req); if (errorResponse.status !== 500) { logger.warn( @@ -108,4 +69,4 @@ const withUnkey = (config: withUnkeyConfig) => { }; }; -export default withUnkey; +export default createRatelimitMiddleware; diff --git a/packages/redwoodjs/src/ratelimit/types.ts b/packages/redwoodjs/src/ratelimit/types.ts index 7a73600143..b4edc9ca23 100644 --- a/packages/redwoodjs/src/ratelimit/types.ts +++ b/packages/redwoodjs/src/ratelimit/types.ts @@ -3,7 +3,7 @@ import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; import type { RatelimitConfig } from "@unkey/ratelimit"; -export type withUnkeyRatelimitConfig = { +export type RatelimitMiddlewareConfig = { /** * The Unkey configuration for the rate limiter */ @@ -23,9 +23,9 @@ export type withUnkeyRatelimitConfig = { * Custom function to handle when an error occurs */ onError?: (req: MiddlewareRequest) => MiddlewareResponse; -}; -export type withUnkeyConfig = { - ratelimit: withUnkeyRatelimitConfig; + /* + * RedwoodJS-compatible Logger to use for logging + */ logger?: Logger; }; From 2a0afd55337736d65f73457afde8472d0d539ea8 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sat, 11 May 2024 12:07:57 -0400 Subject: [PATCH 22/33] move logger and rename apikey using create --- packages/redwoodjs/src/index.ts | 4 ++++ packages/redwoodjs/src/keys/index.ts | 10 ++++------ packages/redwoodjs/src/ratelimit/index.ts | 4 +--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/redwoodjs/src/index.ts b/packages/redwoodjs/src/index.ts index c42f9bc8e6..03a5a96bb7 100644 --- a/packages/redwoodjs/src/index.ts +++ b/packages/redwoodjs/src/index.ts @@ -1 +1,5 @@ +import type { Logger } from "@redwoodjs/api/logger"; + export * from "./ratelimit"; + +export const defaultLogger = require("abstract-logging") as Logger; diff --git a/packages/redwoodjs/src/keys/index.ts b/packages/redwoodjs/src/keys/index.ts index 196f87395d..ecdbc4a113 100644 --- a/packages/redwoodjs/src/keys/index.ts +++ b/packages/redwoodjs/src/keys/index.ts @@ -1,14 +1,12 @@ import { Unkey } from "@unkey/api"; import { version } from "../../package.json"; -import type { Logger } from "@redwoodjs/api/logger"; +import { defaultLogger } from "../index"; -import type { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; +import type { Middleware, MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; import type { ApiKeyMiddlewareConfig } from "./types"; -const defaultLogger = require("abstract-logging") as Logger; - -const ApiKeyMiddleware = (config: ApiKeyMiddlewareConfig) => { +const createApiKeyMiddleware = (config: ApiKeyMiddlewareConfig): Middleware => { const logger = config.logger || defaultLogger; return async (req: MiddlewareRequest, res: MiddlewareResponse) => { @@ -65,4 +63,4 @@ const ApiKeyMiddleware = (config: ApiKeyMiddlewareConfig) => { }; }; -export default ApiKeyMiddleware; +export default createApiKeyMiddleware; diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/index.ts index db42c0f411..a82a1460b1 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/index.ts @@ -8,13 +8,11 @@ import { defaultRatelimitIdentifier, } from "./util"; -import type { Logger } from "@redwoodjs/api/logger"; +import { defaultLogger } from "../index"; import type { Middleware, MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; import type { RatelimitMiddlewareConfig } from "./types"; -const defaultLogger = require("abstract-logging") as Logger; - /** * createRatelimitMiddleware creates RedwoodJS middleware * that rate limits requests using Unkey's rate limiter. From 2b5b31668730c1badbd19c1d4a5301788812f1fa Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sat, 11 May 2024 12:11:47 -0400 Subject: [PATCH 23/33] add readme for key middleware --- packages/redwoodjs/src/keys/README.md | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 packages/redwoodjs/src/keys/README.md diff --git a/packages/redwoodjs/src/keys/README.md b/packages/redwoodjs/src/keys/README.md new file mode 100644 index 0000000000..4d5f7c99ec --- /dev/null +++ b/packages/redwoodjs/src/keys/README.md @@ -0,0 +1,31 @@ +# RedwoodJS Api Key Verification + +`createApiKeyMiddleware` is middleware function for RedwoodJS used to validate API keys sent in the request headers with Unkey. + +## Usage + +Here's a basic example of how to use `createApiKeyMiddleware`: + +```javascript + +``` + +In this example, `createApiKeyMiddleware` is used as a global middleware. It will validate the API key for all incoming requests. + +## Configuration + +`createApiKeyMiddleware` can be configured by passing an options object to the function. Here's an example: + +```javascript + +``` + +In this example, `createApiKeyMiddleware` will look for the API key in the 'X-API-KEY' header and validate it by comparing it to 'expected-key'. + +## Error Handling + +If the API key is missing or invalid, `createApiKeyMiddleware` will send a 401 Unauthorized response and stop the request from being processed further. You can customize this behavior by providing your own error handling function in the options object: + +```javascript + +``` From ad04dd79fd5f7431546d8690a1a1046e87af3de8 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sat, 11 May 2024 19:25:34 -0400 Subject: [PATCH 24/33] Reorganize file directory structure --- apps/docs/libraries/ts/redwoodjs/keys.mdx | 8 ++++++++ apps/docs/libraries/ts/redwoodjs/overview.mdx | 16 +++++++++++++--- apps/docs/mint.json | 1 + packages/redwoodjs/src/index.ts | 8 +++++++- packages/redwoodjs/src/keys/README.md | 2 ++ packages/redwoodjs/src/keys/README.ts | 0 .../createApiKeyMiddleware.ts} | 4 ++-- .../redwoodjs/src/keys/{ => middleware}/types.ts | 0 packages/redwoodjs/src/ratelimit/README.md | 8 +++++++- .../createRatelimitMiddleware.test.ts | 4 ++-- .../__tests__/{ => middleware}/util.test.ts | 2 +- .../createRatelimitMiddleware.ts} | 4 ++-- .../src/ratelimit/{ => middleware}/types.ts | 0 .../src/ratelimit/{ => middleware}/util.ts | 0 14 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 apps/docs/libraries/ts/redwoodjs/keys.mdx delete mode 100644 packages/redwoodjs/src/keys/README.ts rename packages/redwoodjs/src/keys/{index.ts => middleware/createApiKeyMiddleware.ts} (95%) rename packages/redwoodjs/src/keys/{ => middleware}/types.ts (100%) rename packages/redwoodjs/src/ratelimit/__tests__/{ => middleware}/createRatelimitMiddleware.test.ts (98%) rename packages/redwoodjs/src/ratelimit/__tests__/{ => middleware}/util.test.ts (94%) rename packages/redwoodjs/src/ratelimit/{index.ts => middleware/createRatelimitMiddleware.ts} (95%) rename packages/redwoodjs/src/ratelimit/{ => middleware}/types.ts (100%) rename packages/redwoodjs/src/ratelimit/{ => middleware}/util.ts (100%) diff --git a/apps/docs/libraries/ts/redwoodjs/keys.mdx b/apps/docs/libraries/ts/redwoodjs/keys.mdx new file mode 100644 index 0000000000..01fc880838 --- /dev/null +++ b/apps/docs/libraries/ts/redwoodjs/keys.mdx @@ -0,0 +1,8 @@ +--- +title: "API Key Verification" +description: "Implement API Key Verification with RedwoodJS Middleware and Unkey" +--- + +# Usage + +Coming soon. diff --git a/apps/docs/libraries/ts/redwoodjs/overview.mdx b/apps/docs/libraries/ts/redwoodjs/overview.mdx index 75e68732a9..42a53f7276 100644 --- a/apps/docs/libraries/ts/redwoodjs/overview.mdx +++ b/apps/docs/libraries/ts/redwoodjs/overview.mdx @@ -7,12 +7,22 @@ The official RedwoodJS SDK for Unkey. - Rate limit requests using `createRatelimitMiddleware` middleware +## Rate Limiting + +RedwoodJS supports Unkey rate limiting via: + +- middleware with Server-Side Rendering (SSR) enabled + +In the future, support for rate limiting GraphQL operations and other RedwoodJS functions will be added. + +## API Key Verification + +RedwoodJS support for Unkey API key verification is coming soon. + ## Install - ``` - bash yarn rw workspace web add @unkey/redwoodjs - ``` + ``` bash yarn rw workspace web add @unkey/redwoodjs ``` diff --git a/apps/docs/mint.json b/apps/docs/mint.json index 8d5ea38db2..7b3b7f78fe 100644 --- a/apps/docs/mint.json +++ b/apps/docs/mint.json @@ -211,6 +211,7 @@ "group": "@unkey/redwoodjs", "pages": [ "libraries/ts/redwoodjs/overview", + "libraries/ts/redwoodjs/keys", "libraries/ts/redwoodjs/ratelimiting" ] } diff --git a/packages/redwoodjs/src/index.ts b/packages/redwoodjs/src/index.ts index 03a5a96bb7..11d3bb6865 100644 --- a/packages/redwoodjs/src/index.ts +++ b/packages/redwoodjs/src/index.ts @@ -1,5 +1,11 @@ import type { Logger } from "@redwoodjs/api/logger"; -export * from "./ratelimit"; +export * from "./keys/middleware/createApiKeyMiddleware"; + +export * from "./ratelimit/middleware/createRatelimitMiddleware"; +export * from "./ratelimit/middleware/util"; + +export type * from "./keys/middleware/types"; +export type * from "./ratelimit/middleware/types"; export const defaultLogger = require("abstract-logging") as Logger; diff --git a/packages/redwoodjs/src/keys/README.md b/packages/redwoodjs/src/keys/README.md index 4d5f7c99ec..585e7c241b 100644 --- a/packages/redwoodjs/src/keys/README.md +++ b/packages/redwoodjs/src/keys/README.md @@ -2,6 +2,8 @@ `createApiKeyMiddleware` is middleware function for RedwoodJS used to validate API keys sent in the request headers with Unkey. +In the future, support for key verification in GraphQL operations and other RedwoodJS functions will be added. + ## Usage Here's a basic example of how to use `createApiKeyMiddleware`: diff --git a/packages/redwoodjs/src/keys/README.ts b/packages/redwoodjs/src/keys/README.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/redwoodjs/src/keys/index.ts b/packages/redwoodjs/src/keys/middleware/createApiKeyMiddleware.ts similarity index 95% rename from packages/redwoodjs/src/keys/index.ts rename to packages/redwoodjs/src/keys/middleware/createApiKeyMiddleware.ts index ecdbc4a113..e3c3070c89 100644 --- a/packages/redwoodjs/src/keys/index.ts +++ b/packages/redwoodjs/src/keys/middleware/createApiKeyMiddleware.ts @@ -1,7 +1,7 @@ import { Unkey } from "@unkey/api"; -import { version } from "../../package.json"; +import { version } from "../../../package.json"; -import { defaultLogger } from "../index"; +import { defaultLogger } from "../../index"; import type { Middleware, MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; import type { ApiKeyMiddlewareConfig } from "./types"; diff --git a/packages/redwoodjs/src/keys/types.ts b/packages/redwoodjs/src/keys/middleware/types.ts similarity index 100% rename from packages/redwoodjs/src/keys/types.ts rename to packages/redwoodjs/src/keys/middleware/types.ts diff --git a/packages/redwoodjs/src/ratelimit/README.md b/packages/redwoodjs/src/ratelimit/README.md index b9abb012e8..99ff27e37b 100644 --- a/packages/redwoodjs/src/ratelimit/README.md +++ b/packages/redwoodjs/src/ratelimit/README.md @@ -1,6 +1,12 @@ # RedwoodJS Rate Limiting -# Usage +RedwoodJS supports Unkey rate limiting via: + +- middleware with Server-Side Rendering (SSR) enabled + +In the future, support for rate limiting GraphQL operations and other RedwoodJS functions will be added. + +# Middleware Implement request rate limiting in your RedwoodJS application using the `createRatelimitMiddleware` from Unkey. diff --git a/packages/redwoodjs/src/ratelimit/__tests__/createRatelimitMiddleware.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/middleware/createRatelimitMiddleware.test.ts similarity index 98% rename from packages/redwoodjs/src/ratelimit/__tests__/createRatelimitMiddleware.test.ts rename to packages/redwoodjs/src/ratelimit/__tests__/middleware/createRatelimitMiddleware.test.ts index bfdd34541a..c6c6cb5c36 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/createRatelimitMiddleware.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/middleware/createRatelimitMiddleware.test.ts @@ -3,8 +3,8 @@ import { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middlewar import { Ratelimit } from "@unkey/ratelimit"; import type { RatelimitConfig, RatelimitResponse } from "@unkey/ratelimit"; import { assert, describe, expect, it, vi } from "vitest"; -import createRatelimitMiddleware from "../index"; -import type { RatelimitMiddlewareConfig } from "../types"; +import createRatelimitMiddleware from "../../middleware/createRatelimitMiddleware"; +import type { RatelimitMiddlewareConfig } from "../../middleware/types"; /** * Mock the Ratelimit class diff --git a/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts b/packages/redwoodjs/src/ratelimit/__tests__/middleware/util.test.ts similarity index 94% rename from packages/redwoodjs/src/ratelimit/__tests__/util.test.ts rename to packages/redwoodjs/src/ratelimit/__tests__/middleware/util.test.ts index e86f29d2fb..a9efb3a70c 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/util.test.ts +++ b/packages/redwoodjs/src/ratelimit/__tests__/middleware/util.test.ts @@ -1,6 +1,6 @@ import { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import { assert, describe, expect, it } from "vitest"; -import { defaultRatelimitIdentifier } from "../util"; +import { defaultRatelimitIdentifier } from "../../middleware/util"; describe("defaultRatelimitIdentifier", () => { it("should return correct identifier", () => { diff --git a/packages/redwoodjs/src/ratelimit/index.ts b/packages/redwoodjs/src/ratelimit/middleware/createRatelimitMiddleware.ts similarity index 95% rename from packages/redwoodjs/src/ratelimit/index.ts rename to packages/redwoodjs/src/ratelimit/middleware/createRatelimitMiddleware.ts index a82a1460b1..63277fe466 100644 --- a/packages/redwoodjs/src/ratelimit/index.ts +++ b/packages/redwoodjs/src/ratelimit/middleware/createRatelimitMiddleware.ts @@ -1,6 +1,6 @@ import { Ratelimit } from "@unkey/ratelimit"; -import { version } from "../../package.json"; +import { version } from "../../../package.json"; import { defaultRatelimitErrorResponse, @@ -8,7 +8,7 @@ import { defaultRatelimitIdentifier, } from "./util"; -import { defaultLogger } from "../index"; +import { defaultLogger } from "../../index"; import type { Middleware, MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; import type { RatelimitMiddlewareConfig } from "./types"; diff --git a/packages/redwoodjs/src/ratelimit/types.ts b/packages/redwoodjs/src/ratelimit/middleware/types.ts similarity index 100% rename from packages/redwoodjs/src/ratelimit/types.ts rename to packages/redwoodjs/src/ratelimit/middleware/types.ts diff --git a/packages/redwoodjs/src/ratelimit/util.ts b/packages/redwoodjs/src/ratelimit/middleware/util.ts similarity index 100% rename from packages/redwoodjs/src/ratelimit/util.ts rename to packages/redwoodjs/src/ratelimit/middleware/util.ts From 884db75c3a329162a943c8255f801f146818effd Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sat, 11 May 2024 19:27:32 -0400 Subject: [PATCH 25/33] move tests --- .../__tests__}/createRatelimitMiddleware.test.ts | 4 ++-- .../middleware => middleware/__tests__}/util.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename packages/redwoodjs/src/ratelimit/{__tests__/middleware => middleware/__tests__}/createRatelimitMiddleware.test.ts (98%) rename packages/redwoodjs/src/ratelimit/{__tests__/middleware => middleware/__tests__}/util.test.ts (94%) diff --git a/packages/redwoodjs/src/ratelimit/__tests__/middleware/createRatelimitMiddleware.test.ts b/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts similarity index 98% rename from packages/redwoodjs/src/ratelimit/__tests__/middleware/createRatelimitMiddleware.test.ts rename to packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts index c6c6cb5c36..4313c71be8 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/middleware/createRatelimitMiddleware.test.ts +++ b/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts @@ -3,8 +3,8 @@ import { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middlewar import { Ratelimit } from "@unkey/ratelimit"; import type { RatelimitConfig, RatelimitResponse } from "@unkey/ratelimit"; import { assert, describe, expect, it, vi } from "vitest"; -import createRatelimitMiddleware from "../../middleware/createRatelimitMiddleware"; -import type { RatelimitMiddlewareConfig } from "../../middleware/types"; +import createRatelimitMiddleware from "../createRatelimitMiddleware"; +import type { RatelimitMiddlewareConfig } from "../types"; /** * Mock the Ratelimit class diff --git a/packages/redwoodjs/src/ratelimit/__tests__/middleware/util.test.ts b/packages/redwoodjs/src/ratelimit/middleware/__tests__/util.test.ts similarity index 94% rename from packages/redwoodjs/src/ratelimit/__tests__/middleware/util.test.ts rename to packages/redwoodjs/src/ratelimit/middleware/__tests__/util.test.ts index a9efb3a70c..e86f29d2fb 100644 --- a/packages/redwoodjs/src/ratelimit/__tests__/middleware/util.test.ts +++ b/packages/redwoodjs/src/ratelimit/middleware/__tests__/util.test.ts @@ -1,6 +1,6 @@ import { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import { assert, describe, expect, it } from "vitest"; -import { defaultRatelimitIdentifier } from "../../middleware/util"; +import { defaultRatelimitIdentifier } from "../util"; describe("defaultRatelimitIdentifier", () => { it("should return correct identifier", () => { From d70379c5918e46d5b3cc1df9bd60eea966dc4b9b Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sat, 11 May 2024 19:29:08 -0400 Subject: [PATCH 26/33] rename test blocks --- .../createRatelimitMiddleware.test.ts | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts b/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts index 4313c71be8..05c4877642 100644 --- a/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts +++ b/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts @@ -45,7 +45,7 @@ const defaultRateLimitConfig: Pick { +describe("createRatelimitMiddleware", () => { it("should not rate limit", async () => { const config: RatelimitMiddlewareConfig = { config: { @@ -53,11 +53,11 @@ describe("withUnkey", () => { ...defaultRateLimitConfig, }, }; - const unkeyMiddleware = createRatelimitMiddleware(config); + const middleware = createRatelimitMiddleware(config); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); - const result = (await unkeyMiddleware(req, res)) as MiddlewareResponse; + const result = (await middleware(req, res)) as MiddlewareResponse; expect(result?.status).toBe(200); }); @@ -72,11 +72,11 @@ describe("withUnkey", () => { ...defaultRateLimitConfig, }, }; - const unkeyMiddleware = createRatelimitMiddleware(config); + const middleware = createRatelimitMiddleware(config); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); - const result = await unkeyMiddleware(req, res); + const result = await middleware(req, res); expect(result?.status).toBe(429); }); @@ -94,11 +94,11 @@ describe("withUnkey", () => { return "abcdefg"; // matches namespace so no rate limit for this test }, }; - const unkeyMiddleware = createRatelimitMiddleware(config); + const middleware = createRatelimitMiddleware(config); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); - const result = await unkeyMiddleware(req, res); + const result = await middleware(req, res); expect(result?.status).toBe(200); }); @@ -115,11 +115,11 @@ describe("withUnkey", () => { return "abcdefg"; }, }; - const unkeyMiddleware = createRatelimitMiddleware(config); + const middleware = createRatelimitMiddleware(config); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); - const result = await unkeyMiddleware(req, res); + const result = await middleware(req, res); expect(result?.status).toBe(429); }); @@ -138,11 +138,11 @@ describe("withUnkey", () => { }); }, }; - const unkeyMiddleware = createRatelimitMiddleware(options); + const middleware = createRatelimitMiddleware(options); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); - const result = await unkeyMiddleware(req, res); + const result = await middleware(req, res); expect(result?.status).toBe(429); expect(result?.body).toBe("Custom Rate limit exceeded message"); }); @@ -160,11 +160,11 @@ describe("withUnkey", () => { throw new Error("Error simulated by test"); }, }; - const unkeyMiddleware = createRatelimitMiddleware(options); + const middleware = createRatelimitMiddleware(options); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); - const result = await unkeyMiddleware(req, res); + const result = await middleware(req, res); expect(result?.body).toBe("Internal server error"); expect(result?.status).toBe(500); @@ -188,11 +188,11 @@ describe("withUnkey", () => { }); }, }; - const unkeyMiddleware = createRatelimitMiddleware(options); + const middleware = createRatelimitMiddleware(options); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); - const result = await unkeyMiddleware(req, res); + const result = await middleware(req, res); expect(result?.body).toBe("Custom Error message when rate limiting"); expect(result?.status).toBe(500); @@ -216,11 +216,11 @@ describe("withUnkey", () => { }); }, }; - const unkeyMiddleware = createRatelimitMiddleware(options); + const middleware = createRatelimitMiddleware(options); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); - const result = await unkeyMiddleware(req, res); + const result = await middleware(req, res); expect(result?.body).toBe("Not implemented"); expect(result?.status).toBe(501); @@ -245,11 +245,11 @@ describe("withUnkey", () => { options: { level: "error", enabled: true }, }), }; - const unkeyMiddleware = createRatelimitMiddleware(options); + const middleware = createRatelimitMiddleware(options); const request = new Request("http://localhost:8910/api/user"); const req = new MiddlewareRequest(request); const res = new MiddlewareResponse(); - const result = await unkeyMiddleware(req, res); + const result = await middleware(req, res); expect(result?.body).toBe("Not implemented"); expect(result?.status).toBe(501); From 7ca2759a48a1c5e7b83438ac2f3f3352c5aaf70d Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sat, 11 May 2024 19:34:45 -0400 Subject: [PATCH 27/33] stub some tests --- .../__tests__/createApiKeyMiddleware.test.ts | 13 +++++++++++++ .../__tests__/createRatelimitMiddleware.test.ts | 12 +++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts diff --git a/packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts b/packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts new file mode 100644 index 0000000000..bc5e1bdd7f --- /dev/null +++ b/packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts @@ -0,0 +1,13 @@ +import { createLogger } from "@redwoodjs/api/logger"; +import { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; +import { assert, describe, expect, it, vi } from "vitest"; +import createApiKeyMiddleware from "../createApiKeyMiddleware"; +import type { ApiKeyMiddlewareConfig } from "../types"; + +describe("createApiKeyMiddleware", () => { + it("should create middleware", async () => { + const config: ApiKeyMiddlewareConfig = {}; + const middleware = createApiKeyMiddleware(config); + expect(middleware).toBeDefined(); + }); +}); diff --git a/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts b/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts index 05c4877642..725d750806 100644 --- a/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts +++ b/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts @@ -1,6 +1,5 @@ import { createLogger } from "@redwoodjs/api/logger"; import { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; -import { Ratelimit } from "@unkey/ratelimit"; import type { RatelimitConfig, RatelimitResponse } from "@unkey/ratelimit"; import { assert, describe, expect, it, vi } from "vitest"; import createRatelimitMiddleware from "../createRatelimitMiddleware"; @@ -46,6 +45,17 @@ const defaultRateLimitConfig: Pick { + it("should create middleware", async () => { + const config: RatelimitMiddlewareConfig = { + config: { + namespace: "app", + ...defaultRateLimitConfig, + }, + }; + const middleware = createRatelimitMiddleware(config); + expect(middleware).toBeDefined(); + }); + it("should not rate limit", async () => { const config: RatelimitMiddlewareConfig = { config: { From 4781fe4500fbfa1782d0ab74aa713837a2649f8a Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sat, 11 May 2024 19:45:56 -0400 Subject: [PATCH 28/33] commented --- .../keys/middleware/createApiKeyMiddleware.ts | 28 +++++++++++++++---- .../middleware/createRatelimitMiddleware.ts | 11 ++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/packages/redwoodjs/src/keys/middleware/createApiKeyMiddleware.ts b/packages/redwoodjs/src/keys/middleware/createApiKeyMiddleware.ts index e3c3070c89..c48c7b6aba 100644 --- a/packages/redwoodjs/src/keys/middleware/createApiKeyMiddleware.ts +++ b/packages/redwoodjs/src/keys/middleware/createApiKeyMiddleware.ts @@ -6,17 +6,27 @@ import { defaultLogger } from "../../index"; import type { Middleware, MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; import type { ApiKeyMiddlewareConfig } from "./types"; +/** + * Get key tp verify from request using the custom getKey function + * or the default authorization header + */ +export const getKey = (config: ApiKeyMiddlewareConfig, req: MiddlewareRequest): string | null => { + return config.getKey + ? config.getKey(req) + : req.headers.get("authorization")?.replace("Bearer ", "") ?? null; +}; + +/** + * Create RedwoodJS middleware to verify an API key using Unkey + */ const createApiKeyMiddleware = (config: ApiKeyMiddlewareConfig): Middleware => { const logger = config.logger || defaultLogger; return async (req: MiddlewareRequest, res: MiddlewareResponse) => { - /** - * Get key from request and return a response early if not found - */ - const key = config.getKey - ? config.getKey(req) - : req.headers.get("authorization")?.replace("Bearer ", "") ?? null; + // Get key from request and return + const key = getKey(config, req); + // return an unauthorized response if no key is found if (key === null) { res.body = "Unauthorized"; res.status = 401; @@ -25,19 +35,23 @@ const createApiKeyMiddleware = (config: ApiKeyMiddlewareConfig): Middleware => { if (typeof key !== "string") { // why not error? + logger.error(key, "Key is not a string"); return key; } + // Create an instance of Unkey const unkey = new Unkey({ rootKey: "public", wrapperSdkVersion: `@unkey/redwoodjs@${version}`, disableTelemetry: config.disableTelemetry, }); + // if apiId is provided, verify against it otherwise just verify the key const unkeyVerificationResult = await unkey.keys.verify( config.apiId ? { key, apiId: config.apiId } : { key }, ); + // if there is an error, log it and return an error response if (unkeyVerificationResult.error) { if (config.onError) { return config.onError(req, unkeyVerificationResult.error); @@ -50,6 +64,7 @@ const createApiKeyMiddleware = (config: ApiKeyMiddlewareConfig): Middleware => { res.status = 500; } + // if the key is invalid, return an unauthorized response if (!unkeyVerificationResult.result?.valid) { if (config.onInvalidKey) { return config.onInvalidKey(req, unkeyVerificationResult.result); @@ -59,6 +74,7 @@ const createApiKeyMiddleware = (config: ApiKeyMiddlewareConfig): Middleware => { res.status = 401; } + // if the key is valid, continue return res; }; }; diff --git a/packages/redwoodjs/src/ratelimit/middleware/createRatelimitMiddleware.ts b/packages/redwoodjs/src/ratelimit/middleware/createRatelimitMiddleware.ts index 63277fe466..fdef2457de 100644 --- a/packages/redwoodjs/src/ratelimit/middleware/createRatelimitMiddleware.ts +++ b/packages/redwoodjs/src/ratelimit/middleware/createRatelimitMiddleware.ts @@ -34,16 +34,22 @@ const createRatelimitMiddleware = ({ return async (req: MiddlewareRequest, res: MiddlewareResponse) => { try { + // Get identifier from request const identifier = getIdentifier(req); + // Check rate limit for the identifier and namespace in the config const ratelimit = await unkeyRateLimiter.limit(identifier); + // if rate limit is exceeded, return the exceeded response if (!ratelimit.success) { logger.debug("Rate limit exceeded", { ratelimit, identifier, }); + const response = onExceeded(req); + + // if the response status is not 429, log a warning and override the status if (response.status !== 429) { logger.warn("Rate limit exceeded response is not 429. Overriding status.", response); response.status = 429; @@ -51,8 +57,12 @@ const createRatelimitMiddleware = ({ return response; } } catch (e) { + // if we have an error, log it and return an error response logger.error("Error in unkeyRateLimitMiddleware", e); + const errorResponse = onError(req); + + // if the response status is not 500, log a warning and override the status if (errorResponse.status !== 500) { logger.warn( `Rate limit error response is ${errorResponse.status}. Consider changing status to 500.`, @@ -63,6 +73,7 @@ const createRatelimitMiddleware = ({ return errorResponse; } + // if no rate limit exceeded, return the response return res; }; }; From 3e23eaf1aa1dbfdff488412fa41a28d63628b164 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Sun, 12 May 2024 10:28:18 -0400 Subject: [PATCH 29/33] start testing createApiKeyMiddleware --- .../__tests__/createApiKeyMiddleware.test.ts | 135 +++++++++++++++++- .../keys/middleware/createApiKeyMiddleware.ts | 9 +- .../redwoodjs/src/keys/middleware/types.ts | 2 +- .../createRatelimitMiddleware.test.ts | 2 +- 4 files changed, 141 insertions(+), 7 deletions(-) diff --git a/packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts b/packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts index bc5e1bdd7f..1dd8bb3f10 100644 --- a/packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts +++ b/packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts @@ -1,8 +1,79 @@ import { createLogger } from "@redwoodjs/api/logger"; import { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; -import { assert, describe, expect, it, vi } from "vitest"; +import { describe, expect, it, vi } from "vitest"; import createApiKeyMiddleware from "../createApiKeyMiddleware"; -import type { ApiKeyMiddlewareConfig } from "../types"; +import type { ApiKeyMiddlewareConfig, VerifyResponse } from "../types"; + +const VALID_KEY = "valid-key"; +const INVALID_KEY = "invalid-key"; +const DEFAULT_API_ID = "defaultApiId"; + +/** + * Mock Unkey key verification + * + * If the key is valid and the apiId is the defaultApiId, return a valid response + * + * Uses a known valid key to return a valid response + * + * Important: This behavior is for *this test mock only*. The actual verifyKey will *not* behave this way. + */ +vi.mock("@unkey/api", () => { + return { + Unkey: class { + public get keys() { + return { + verify: ({ + key, + apiId, + }: { + key: string; + apiId?: string; + }): VerifyResponse => { + if (apiId !== DEFAULT_API_ID) { + return { + error: { + code: "INTERNAL_SERVER_ERROR", + docs: "", + message: `Internal server error ${key} ${apiId}`, + requestId: "123", + }, + }; + } + + if (key === VALID_KEY && apiId === DEFAULT_API_ID) { + return { + error: undefined, + result: { + valid: true, + code: "VALID", + }, + }; + } + + if (key !== VALID_KEY && apiId === DEFAULT_API_ID) { + return { + error: undefined, + result: { + valid: false, + code: "FORBIDDEN", + }, + }; + } + + return { + error: { + code: "INTERNAL_SERVER_ERROR", + docs: "", + message: `Internal server error ${key} ${apiId}`, + requestId: "123", + }, + }; + }, + }; + } + }, + }; +}); describe("createApiKeyMiddleware", () => { it("should create middleware", async () => { @@ -10,4 +81,64 @@ describe("createApiKeyMiddleware", () => { const middleware = createApiKeyMiddleware(config); expect(middleware).toBeDefined(); }); + + it("key is valid is a 200", async () => { + const config: ApiKeyMiddlewareConfig = { apiId: "defaultApiId" }; + const middleware = createApiKeyMiddleware(config); + const request = new Request("http://localhost:8910/api/protected", { + headers: { authorization: `Bearer ${VALID_KEY}` }, + }); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = (await middleware(req, res)) as MiddlewareResponse; + expect(result?.status).toBe(200); + }); + + it("key is invalid is a 401", async () => { + const config: ApiKeyMiddlewareConfig = { apiId: "defaultApiId" }; + const middleware = createApiKeyMiddleware(config); + const request = new Request("http://localhost:8910/api/protected", { + headers: { authorization: `Bearer ${INVALID_KEY}` }, + }); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = (await middleware(req, res)) as MiddlewareResponse; + expect(result?.status).toBe(401); + }); + + it("no headers is a 401", async () => { + const config: ApiKeyMiddlewareConfig = { apiId: "defaultApiId" }; + const middleware = createApiKeyMiddleware(config); + const request = new Request("http://localhost:8910/api/protected", { + headers: {}, + }); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = (await middleware(req, res)) as MiddlewareResponse; + expect(result?.status).toBe(401); + }); + + it("no authorization header is a 401", async () => { + const config: ApiKeyMiddlewareConfig = { apiId: "defaultApiId" }; + const middleware = createApiKeyMiddleware(config); + const request = new Request("http://localhost:8910/api/protected", { + headers: { agent: "test" }, + }); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = (await middleware(req, res)) as MiddlewareResponse; + expect(result?.status).toBe(401); + }); + + it("unsupported appId is a 500", async () => { + const config: ApiKeyMiddlewareConfig = { apiId: "badid" }; + const middleware = createApiKeyMiddleware(config); + const request = new Request("http://localhost:8910/api/protected", { + headers: { authorization: `Bearer ${VALID_KEY}` }, + }); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = (await middleware(req, res)) as MiddlewareResponse; + expect(result?.status).toBe(500); + }); }); diff --git a/packages/redwoodjs/src/keys/middleware/createApiKeyMiddleware.ts b/packages/redwoodjs/src/keys/middleware/createApiKeyMiddleware.ts index c48c7b6aba..0d9bf32b75 100644 --- a/packages/redwoodjs/src/keys/middleware/createApiKeyMiddleware.ts +++ b/packages/redwoodjs/src/keys/middleware/createApiKeyMiddleware.ts @@ -53,15 +53,16 @@ const createApiKeyMiddleware = (config: ApiKeyMiddlewareConfig): Middleware => { // if there is an error, log it and return an error response if (unkeyVerificationResult.error) { + console.error(unkeyVerificationResult.error, "Error when verifying key"); + if (config.onError) { return config.onError(req, unkeyVerificationResult.error); } - logger.error( - `unkey error: [CODE: ${unkeyVerificationResult.error.code}] - [TRACE: ${unkeyVerificationResult.error.requestId}] - ${unkeyVerificationResult.error.message} - read more at ${unkeyVerificationResult.error.docs}`, - ); res.body = "Internal Server Error"; res.status = 500; + + return res; } // if the key is invalid, return an unauthorized response @@ -72,6 +73,8 @@ const createApiKeyMiddleware = (config: ApiKeyMiddlewareConfig): Middleware => { res.body = "Unauthorized"; res.status = 401; + + return res; } // if the key is valid, continue diff --git a/packages/redwoodjs/src/keys/middleware/types.ts b/packages/redwoodjs/src/keys/middleware/types.ts index bc9d0e7ebc..8b768b4563 100644 --- a/packages/redwoodjs/src/keys/middleware/types.ts +++ b/packages/redwoodjs/src/keys/middleware/types.ts @@ -4,7 +4,7 @@ import type { Logger } from "@redwoodjs/api/logger"; import type { MiddlewareRequest } from "@redwoodjs/vite/middleware"; import type { MiddlewareResponse } from "@redwoodjs/vite/middleware"; -type VerifyResponse = Awaited["keys"]["verify"]>>; +export type VerifyResponse = Awaited["keys"]["verify"]>>; export type UnkeyContext = VerifyResponse["result"]; export type ApiKeyMiddlewareConfig = { diff --git a/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts b/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts index 725d750806..09bf04898a 100644 --- a/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts +++ b/packages/redwoodjs/src/ratelimit/middleware/__tests__/createRatelimitMiddleware.test.ts @@ -1,7 +1,7 @@ import { createLogger } from "@redwoodjs/api/logger"; import { MiddlewareRequest, MiddlewareResponse } from "@redwoodjs/vite/middleware"; import type { RatelimitConfig, RatelimitResponse } from "@unkey/ratelimit"; -import { assert, describe, expect, it, vi } from "vitest"; +import { describe, expect, it, vi } from "vitest"; import createRatelimitMiddleware from "../createRatelimitMiddleware"; import type { RatelimitMiddlewareConfig } from "../types"; From 670ce90e0ffe4a4c62e9e02a4627fc00ceb005e1 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Mon, 13 May 2024 10:54:21 -0400 Subject: [PATCH 30/33] add apikey middleware tests --- .../__tests__/createApiKeyMiddleware.test.ts | 79 ++++++++++++++++++- 1 file changed, 75 insertions(+), 4 deletions(-) diff --git a/packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts b/packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts index 1dd8bb3f10..275086e536 100644 --- a/packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts +++ b/packages/redwoodjs/src/keys/middleware/__tests__/createApiKeyMiddleware.test.ts @@ -94,7 +94,7 @@ describe("createApiKeyMiddleware", () => { expect(result?.status).toBe(200); }); - it("key is invalid is a 401", async () => { + it("should 401 if key is invalid", async () => { const config: ApiKeyMiddlewareConfig = { apiId: "defaultApiId" }; const middleware = createApiKeyMiddleware(config); const request = new Request("http://localhost:8910/api/protected", { @@ -106,7 +106,7 @@ describe("createApiKeyMiddleware", () => { expect(result?.status).toBe(401); }); - it("no headers is a 401", async () => { + it("should 401 if no headers", async () => { const config: ApiKeyMiddlewareConfig = { apiId: "defaultApiId" }; const middleware = createApiKeyMiddleware(config); const request = new Request("http://localhost:8910/api/protected", { @@ -118,7 +118,7 @@ describe("createApiKeyMiddleware", () => { expect(result?.status).toBe(401); }); - it("no authorization header is a 401", async () => { + it("should 401 if no authorization header", async () => { const config: ApiKeyMiddlewareConfig = { apiId: "defaultApiId" }; const middleware = createApiKeyMiddleware(config); const request = new Request("http://localhost:8910/api/protected", { @@ -130,7 +130,7 @@ describe("createApiKeyMiddleware", () => { expect(result?.status).toBe(401); }); - it("unsupported appId is a 500", async () => { + it("should 500 if unsupported appId", async () => { const config: ApiKeyMiddlewareConfig = { apiId: "badid" }; const middleware = createApiKeyMiddleware(config); const request = new Request("http://localhost:8910/api/protected", { @@ -141,4 +141,75 @@ describe("createApiKeyMiddleware", () => { const result = (await middleware(req, res)) as MiddlewareResponse; expect(result?.status).toBe(500); }); + + it("should be valid when using a custom key function", async () => { + const config: ApiKeyMiddlewareConfig = { + apiId: "defaultApiId", + getKey: (req) => { + return req.headers.get("x-api-key") ?? ""; + }, + }; + const middleware = createApiKeyMiddleware(config); + const request = new Request("http://localhost:8910/api/protected", { + headers: { "x-api-key": VALID_KEY }, + }); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = (await middleware(req, res)) as MiddlewareResponse; + expect(result?.status).toBe(200); + }); + + it("should be invalid when using a custom key function with invalid token", async () => { + const config: ApiKeyMiddlewareConfig = { + apiId: "defaultApiId", + getKey: (req) => { + return req.headers.get("x-api-key") ?? ""; + }, + }; + const middleware = createApiKeyMiddleware(config); + const request = new Request("http://localhost:8910/api/protected", { + headers: { "x-api-key": INVALID_KEY }, + }); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = (await middleware(req, res)) as MiddlewareResponse; + expect(result?.status).toBe(401); + }); + + it("should be a custom invalid response when using a custom key function with invalid token", async () => { + const config: ApiKeyMiddlewareConfig = { + apiId: "defaultApiId", + getKey: (req) => { + return req.headers.get("x-api-key") ?? ""; + }, + onInvalidKey: (_req, _result) => { + return new MiddlewareResponse("Custom forbidden", { status: 403 }); + }, + }; + const middleware = createApiKeyMiddleware(config); + const request = new Request("http://localhost:8910/api/protected", { + headers: { "x-api-key": INVALID_KEY }, + }); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = (await middleware(req, res)) as MiddlewareResponse; + expect(result?.body).toBe("Custom forbidden"); + expect(result?.status).toBe(403); + }); + + it("should have a custom error response if unsupported appId", async () => { + const config: ApiKeyMiddlewareConfig = { + apiId: "badid", + onError: (_req, _err) => new MiddlewareResponse("Custom unavailable", { status: 503 }), + }; + const middleware = createApiKeyMiddleware(config); + const request = new Request("http://localhost:8910/api/protected", { + headers: { authorization: `Bearer ${INVALID_KEY}` }, + }); + const req = new MiddlewareRequest(request); + const res = new MiddlewareResponse(); + const result = (await middleware(req, res)) as MiddlewareResponse; + expect(result?.body).toBe("Custom unavailable"); + expect(result?.status).toBe(503); + }); }); From 01d2e6f9a14e9abe3031a7079bb7cd89e6605b9e Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Tue, 14 May 2024 08:06:49 -0400 Subject: [PATCH 31/33] adds docs for verify keys --- apps/docs/libraries/ts/redwoodjs/keys.mdx | 96 ++++++++++++++++++- apps/docs/libraries/ts/redwoodjs/overview.mdx | 16 ++-- packages/redwoodjs/src/keys/README.md | 82 ++++++++++++++-- 3 files changed, 175 insertions(+), 19 deletions(-) diff --git a/apps/docs/libraries/ts/redwoodjs/keys.mdx b/apps/docs/libraries/ts/redwoodjs/keys.mdx index 01fc880838..8bcb7f3063 100644 --- a/apps/docs/libraries/ts/redwoodjs/keys.mdx +++ b/apps/docs/libraries/ts/redwoodjs/keys.mdx @@ -3,6 +3,98 @@ title: "API Key Verification" description: "Implement API Key Verification with RedwoodJS Middleware and Unkey" --- -# Usage +## Usage -Coming soon. +`createApiKeyMiddleware` is middleware function for RedwoodJS used to validate API keys sent in the request headers with [Unkey](https://www.unkey.com/docs). + +By default, Unkey verifies a key provided in the request's authorization header: `"Authorization: Bearer unkey_xxx"`. How Unkey extracts the key to verify can be customized using the `getKey` function option. + +Here's a basic example of how to use `createApiKeyMiddleware`: + +```ts file="web/src/entry.server.tsx" +import createApiKeyMiddleware from "@unkey/redwoodjs"; +import type { ApiKeyMiddlewareConfig } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const config: ApiKeyMiddlewareConfig = { + apiId: "my-app-id", + }; + + const middleware = createApiKeyMiddleware(config); + + return [middleware]; +}; +``` + +In this example, `createApiKeyMiddleware` is used as a global middleware. It will validate the API key for all incoming requests. + +## Configuration + +`createApiKeyMiddleware` can be configured by providing `ApiKeyMiddlewareConfig` configuration options when creating the middleware. + +### Custom getKey + +In this example, `createApiKeyMiddleware` will look for the API key in the 'X-API-KEY' header and validate it via a custom `getKey` function. + +```ts file="web/src/entry.server.tsx" +import createApiKeyMiddleware from "@unkey/redwoodjs"; +import type { ApiKeyMiddlewareConfig } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const config: ApiKeyMiddlewareConfig = { + apiId: 'my-app-id' + getKey: (req) => { + return req.headers.get("x-api-key") ?? ""; + }, + }; + + const middleware = createApiKeyMiddleware(config); + + return [middleware]; +}; +``` + +### Custom onInvalidKey + +In this example, `createApiKeyMiddleware` respond with a custom message and status if the key is invalid. + +```ts file="web/src/entry.server.tsx" +import createApiKeyMiddleware from "@unkey/redwoodjs"; +import type { ApiKeyMiddlewareConfig } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const config: ApiKeyMiddlewareConfig = { + apiId: 'my-app-id' + onInvalidKey: (_req, _result) => { + return new MiddlewareResponse("Custom forbidden", { status: 403 }); + }, + }; + + const middleware = createApiKeyMiddleware(config); + + return [middleware]; +}; +``` + +### Error Handling + +If the API key is missing or invalid, `createApiKeyMiddleware` will send a 401 Unauthorized response and stop the request from being processed further. + +You can customize this behavior by providing your own error handling function in the options object: + +```ts file="web/src/entry.server.tsx" +import createApiKeyMiddleware from "@unkey/redwoodjs"; +import type { ApiKeyMiddlewareConfig } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const config: ApiKeyMiddlewareConfig = { + apiId: "my-app-id", + onError: (_req, _err) => + new MiddlewareResponse("Custom unavailable", { status: 503 }), + }; + + const middleware = createApiKeyMiddleware(config); + + return [middleware]; +}; +``` diff --git a/apps/docs/libraries/ts/redwoodjs/overview.mdx b/apps/docs/libraries/ts/redwoodjs/overview.mdx index 42a53f7276..4370f336d7 100644 --- a/apps/docs/libraries/ts/redwoodjs/overview.mdx +++ b/apps/docs/libraries/ts/redwoodjs/overview.mdx @@ -3,21 +3,19 @@ title: "Overview" description: "RedwoodJS SDK for Unkey" --- -The official RedwoodJS SDK for Unkey. +The official RedwoodJS SDK for Unkey. Use this to verify and rate limit request using Unkey. -- Rate limit requests using `createRatelimitMiddleware` middleware - -## Rate Limiting - -RedwoodJS supports Unkey rate limiting via: - -- middleware with Server-Side Rendering (SSR) enabled +To use, a RedwoodJS app must be setup with Server-Side Rendering (SSR) and middleware enabled. In the future, support for rate limiting GraphQL operations and other RedwoodJS functions will be added. ## API Key Verification -RedwoodJS support for Unkey API key verification is coming soon. +RedwoodJS supports Unkey API key verification with its`createApiKeyMiddleware` middleware. + +## Rate Limiting + +RedwoodJS supports Unkey Rate limiting verification with its `createRatelimitMiddleware` middleware. ## Install diff --git a/packages/redwoodjs/src/keys/README.md b/packages/redwoodjs/src/keys/README.md index 585e7c241b..02cd35f98d 100644 --- a/packages/redwoodjs/src/keys/README.md +++ b/packages/redwoodjs/src/keys/README.md @@ -1,6 +1,8 @@ # RedwoodJS Api Key Verification -`createApiKeyMiddleware` is middleware function for RedwoodJS used to validate API keys sent in the request headers with Unkey. +`createApiKeyMiddleware` is middleware function for RedwoodJS used to validate API keys sent in the request headers with [Unkey](https://www.unkey.com/docs). + +By default, Unkey verifies a key provided in the request's authorization header: `"Authorization: Bearer unkey_xxx"`. How Unkey extracts the key to verify can be customized using the `getKey` function option. In the future, support for key verification in GraphQL operations and other RedwoodJS functions will be added. @@ -8,26 +10,90 @@ In the future, support for key verification in GraphQL operations and other Redw Here's a basic example of how to use `createApiKeyMiddleware`: -```javascript +```ts file="web/src/entry.server.tsx" +import createApiKeyMiddleware from "@unkey/redwoodjs"; +import type { ApiKeyMiddlewareConfig } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const config: ApiKeyMiddlewareConfig = { + apiId: "my-app-id", + }; + const middleware = createApiKeyMiddleware(config); + + return [middleware]; +}; ``` In this example, `createApiKeyMiddleware` is used as a global middleware. It will validate the API key for all incoming requests. ## Configuration -`createApiKeyMiddleware` can be configured by passing an options object to the function. Here's an example: +`createApiKeyMiddleware` can be configured by providing `ApiKeyMiddlewareConfig` configuration options when creating the middleware. + +### Custom getKey + +In this example, `createApiKeyMiddleware` will look for the API key in the 'X-API-KEY' header and validate it via a custom `getKey` function. + +```ts file="web/src/entry.server.tsx" +import createApiKeyMiddleware from "@unkey/redwoodjs"; +import type { ApiKeyMiddlewareConfig } from "@unkey/redwoodjs"; + +export const registerMiddleware = () => { + const config: ApiKeyMiddlewareConfig = { + apiId: 'my-app-id' + getKey: (req) => { + return req.headers.get("x-api-key") ?? ""; + }, + }; + + const middleware = createApiKeyMiddleware(config); -```javascript + return [middleware]; +}; +``` + +### Custom onInvalidKey + +In this example, `createApiKeyMiddleware` respond with a custom message and status if the key is invalid. + +```ts file="web/src/entry.server.tsx" +import createApiKeyMiddleware from "@unkey/redwoodjs"; +import type { ApiKeyMiddlewareConfig } from "@unkey/redwoodjs"; +export const registerMiddleware = () => { + const config: ApiKeyMiddlewareConfig = { + apiId: 'my-app-id' + onInvalidKey: (_req, _result) => { + return new MiddlewareResponse("Custom forbidden", { status: 403 }); + }, + }; + + const middleware = createApiKeyMiddleware(config); + + return [middleware]; +}; ``` -In this example, `createApiKeyMiddleware` will look for the API key in the 'X-API-KEY' header and validate it by comparing it to 'expected-key'. +### Error Handling + +If the API key is missing or invalid, `createApiKeyMiddleware` will send a 401 Unauthorized response and stop the request from being processed further. + +You can customize this behavior by providing your own error handling function in the options object: -## Error Handling +```ts file="web/src/entry.server.tsx" +import createApiKeyMiddleware from "@unkey/redwoodjs"; +import type { ApiKeyMiddlewareConfig } from "@unkey/redwoodjs"; -If the API key is missing or invalid, `createApiKeyMiddleware` will send a 401 Unauthorized response and stop the request from being processed further. You can customize this behavior by providing your own error handling function in the options object: +export const registerMiddleware = () => { + const config: ApiKeyMiddlewareConfig = { + apiId: "my-app-id", + onError: (_req, _err) => + new MiddlewareResponse("Custom unavailable", { status: 503 }), + }; -```javascript + const middleware = createApiKeyMiddleware(config); + return [middleware]; +}; ``` From 0689f0cd0608c96769d09dc219c8e257d09f5138 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Tue, 14 May 2024 08:41:21 -0400 Subject: [PATCH 32/33] Upgrade redwood canary --- packages/redwoodjs/package.json | 4 +- pnpm-lock.yaml | 130 ++++++++++++++++---------------- 2 files changed, 67 insertions(+), 67 deletions(-) diff --git a/packages/redwoodjs/package.json b/packages/redwoodjs/package.json index 62eabe21de..c0db8017c5 100644 --- a/packages/redwoodjs/package.json +++ b/packages/redwoodjs/package.json @@ -26,8 +26,8 @@ "test": "vitest run" }, "dependencies": { - "@redwoodjs/api": "8.0.0-canary.542", - "@redwoodjs/vite": "8.0.0-canary.542", + "@redwoodjs/api": "8.0.0-canary.571", + "@redwoodjs/vite": "8.0.0-canary.571", "@unkey/api": "workspace:^", "@unkey/ratelimit": "workspace:^", "abstract-logging": "^2.0.1" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 039e769b5e..25caf0ee39 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1348,11 +1348,11 @@ importers: packages/redwoodjs: dependencies: '@redwoodjs/api': - specifier: 8.0.0-canary.542 - version: 8.0.0-canary.542 + specifier: 8.0.0-canary.571 + version: 8.0.0-canary.571 '@redwoodjs/vite': - specifier: 8.0.0-canary.542 - version: 8.0.0-canary.542(@types/node@20.12.7)(csstype@3.1.3)(graphql-tag@2.12.6)(react-dom@18.3.1)(webpack@5.91.0) + specifier: 8.0.0-canary.571 + version: 8.0.0-canary.571(@types/node@20.12.7)(csstype@3.1.3)(graphql-tag@2.12.6)(react-dom@18.3.1)(webpack@5.91.0) '@unkey/api': specifier: workspace:^ version: link:../api @@ -1954,7 +1954,7 @@ packages: openapi-types: 12.1.3 dev: true - /@apollo/client@3.9.9(graphql@16.8.1)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): + /@apollo/client@3.9.9(graphql@16.8.1)(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508): resolution: {integrity: sha512-/sMecU/M0WK9knrguts1lSLV8xFKzIgOMVb4mi6MOxgJXjliDB8PvOtmXhTqh2cVMMR4TzXgOnb+af/690zlQw==} peerDependencies: graphql: ^15.0.0 || ^16.0.0 @@ -1981,9 +1981,9 @@ packages: hoist-non-react-statics: 3.3.2 optimism: 0.18.0 prop-types: 15.8.1 - react: 19.0.0-canary-cb151849e1-20240424 + react: 19.0.0-beta-04b058868c-20240508 react-dom: 18.3.1(react@18.3.1) - rehackt: 0.0.6(react@19.0.0-canary-cb151849e1-20240424) + rehackt: 0.0.6(react@19.0.0-beta-04b058868c-20240508) response-iterator: 0.2.6 symbol-observable: 4.0.0 ts-invariant: 0.10.3 @@ -11371,8 +11371,8 @@ packages: - immer dev: false - /@redwoodjs/api@8.0.0-canary.542: - resolution: {integrity: sha512-6wo2h9QZ0zxwbYFJOWUDX8ehxPkbFx1ofpNanVPCMbnM7exjGDZmNY2rl1GDMY3I5ALLADJ04QsJB5fnKMiVsQ==} + /@redwoodjs/api@8.0.0-canary.571: + resolution: {integrity: sha512-nzmn6lOn+BwXgsvbXpjwaJKCcj/K671BRWIuVsyGeivphvK/FU5IZAFiLZQUKYmPd6OYrwzWfJKGfXoP7xY47g==} hasBin: true peerDependencies: memjs: 1.3.2 @@ -11396,15 +11396,15 @@ packages: - prisma dev: false - /@redwoodjs/auth@8.0.0-canary.542: - resolution: {integrity: sha512-Rx5vPPfCw6Xha6dMYHd6hEYG67RdcozkS5bSmYKw9DomFg1kvrS/a3NEsRmVYOPRV8wnCqG9bTZ7FjSrzOmUAA==} + /@redwoodjs/auth@8.0.0-canary.571: + resolution: {integrity: sha512-42dp6JUzBitSzl8swFnzl3H+J2L4XWjIePmV19X2TyNDa+xE4hIEm4+JuQoKopGBuM+okSN3BKKC/XOb4/dd7Q==} dependencies: core-js: 3.36.1 - react: 19.0.0-canary-cb151849e1-20240424 + react: 19.0.0-beta-04b058868c-20240508 dev: false - /@redwoodjs/babel-config@8.0.0-canary.542(graphql-tag@2.12.6): - resolution: {integrity: sha512-OqVcKoGS1bBg01xH5QkSYcVu8lfjOaibosECLp1AP9EMPXPxz5m+mbVM4cToY4fKFJFU49dna0wfajWr8gAYGA==} + /@redwoodjs/babel-config@8.0.0-canary.571(graphql-tag@2.12.6): + resolution: {integrity: sha512-lmxRCyXuOMnpbAv8Q/QF3e7lh0VS+P90qySFuFS4KWodcX5LCIIOzVSpIiGCoPO9u/fnHjgldqxQZTgzYD0IFw==} dependencies: '@babel/core': 7.24.5 '@babel/parser': 7.24.5 @@ -11419,7 +11419,7 @@ packages: '@babel/register': 7.23.7(@babel/core@7.24.5) '@babel/runtime-corejs3': 7.24.1 '@babel/traverse': 7.24.5 - '@redwoodjs/project-config': 8.0.0-canary.542 + '@redwoodjs/project-config': 8.0.0-canary.571 babel-plugin-auto-import: 1.1.0 babel-plugin-graphql-tag: 3.3.0(@babel/core@7.24.5)(graphql-tag@2.12.6) babel-plugin-module-resolver: 5.0.0 @@ -11432,12 +11432,12 @@ packages: - supports-color dev: false - /@redwoodjs/context@8.0.0-canary.542: - resolution: {integrity: sha512-kNx2gPOZ0xfgAI6vt0+fUKuY2XS6L+PzhdC53BjxVxOkweH7dgCw+XUKsHZzRinh77rHkfnnDkB8dLUlCuzWsg==} + /@redwoodjs/context@8.0.0-canary.571: + resolution: {integrity: sha512-uPNcW1RWWZi8xhDL0+mlim0Ov+GJP5BQCa8Xwx7wm3zt9lxsfCkBNVqaPsVOakf0daulyoob4EJZ2BNe/OEVWw==} dev: false - /@redwoodjs/graphql-server@8.0.0-canary.542: - resolution: {integrity: sha512-d0E6g7IC5zcSAwmj3VN8hOCzn52G3IX2V01+0Rdw0wHMmSZaLXCUC3ARGmbYwPtXGFO7uBNv0Uh1ssRFyjPBPg==} + /@redwoodjs/graphql-server@8.0.0-canary.571: + resolution: {integrity: sha512-SwOs8nQVyCf68EPVjLlzL8sIwRqiSYp223DKX8sMrwoKLBAZbDkkX1vzyul7tJTgJTLw73OSjyC174U1Pxppfw==} dependencies: '@babel/runtime-corejs3': 7.24.1 '@envelop/core': 5.0.0 @@ -11451,8 +11451,8 @@ packages: '@graphql-tools/utils': 10.1.2(graphql@16.8.1) '@graphql-yoga/plugin-persisted-operations': 3.2.0(@graphql-tools/utils@10.1.2)(graphql-yoga@5.2.0)(graphql@16.8.1) '@opentelemetry/api': 1.4.1 - '@redwoodjs/api': 8.0.0-canary.542 - '@redwoodjs/context': 8.0.0-canary.542 + '@redwoodjs/api': 8.0.0-canary.571 + '@redwoodjs/context': 8.0.0-canary.571 core-js: 3.36.1 graphql: 16.8.1 graphql-scalars: 1.23.0(graphql@16.8.1) @@ -11468,8 +11468,8 @@ packages: - redis dev: false - /@redwoodjs/internal@8.0.0-canary.542(@swc/core@1.4.11)(@types/node@20.12.7)(graphql-tag@2.12.6)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): - resolution: {integrity: sha512-wBHkWTf5mf1wt44FkZQLd+nLlT4Oo5dZat8IxePCwuW913+ac5kEgby+5CWpS7ye98LzuOk4l7FEvqp8uI6Cgg==} + /@redwoodjs/internal@8.0.0-canary.571(@swc/core@1.4.11)(@types/node@20.12.7)(graphql-tag@2.12.6)(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508): + resolution: {integrity: sha512-sTTJsoWGDLMhjfICnyai3bM3XTzMsAVeRFoZ7dqaNrmr435zk0F8xQhx/deZt+q6D/aU1gxLgHYBmiVg7dY5SA==} hasBin: true dependencies: '@babel/core': 7.24.5 @@ -11490,10 +11490,10 @@ packages: '@graphql-codegen/typescript-react-apollo': 3.3.7(graphql-tag@2.12.6)(graphql@16.8.1) '@graphql-codegen/typescript-resolvers': 3.2.1(graphql@16.8.1) '@graphql-tools/documents': 1.0.0(graphql@16.8.1) - '@redwoodjs/babel-config': 8.0.0-canary.542(graphql-tag@2.12.6) - '@redwoodjs/graphql-server': 8.0.0-canary.542 - '@redwoodjs/project-config': 8.0.0-canary.542 - '@redwoodjs/router': 8.0.0-canary.542(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) + '@redwoodjs/babel-config': 8.0.0-canary.571(graphql-tag@2.12.6) + '@redwoodjs/graphql-server': 8.0.0-canary.571 + '@redwoodjs/project-config': 8.0.0-canary.571 + '@redwoodjs/router': 8.0.0-canary.571(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508) '@sdl-codegen/node': 0.0.13(graphql@16.8.1)(prettier@3.2.5)(typescript@5.4.5) chalk: 4.1.2 core-js: 3.36.1 @@ -11531,8 +11531,8 @@ packages: - utf-8-validate dev: false - /@redwoodjs/project-config@8.0.0-canary.542: - resolution: {integrity: sha512-veuppVknJvxwnySlIP6fnCJ9vMoU6FVuI3t6E9a+aV7NaSb/C1UHNDRQVH6X2LIecOIlxqsoD+31nUCXTdosHQ==} + /@redwoodjs/project-config@8.0.0-canary.571: + resolution: {integrity: sha512-7kVNSoAfmrtTf9fqfqyHYsHA5RXvkJqTQ7oPEsPkCSo88o8bok1V0UT7dVomNILdsnno1t8+OIgG7rUG9DaiDg==} dependencies: '@iarna/toml': 2.2.5 deepmerge: 4.3.1 @@ -11540,30 +11540,30 @@ packages: string-env-interpolation: 1.0.1 dev: false - /@redwoodjs/router@8.0.0-canary.542(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): - resolution: {integrity: sha512-3/9mlFB9uyB1tx70ey1bMvLTrp/VwFI9EF9SbNSK01zqJlGUstRM9KmBSMDFbPQZyoBrSNkQQuMpY2CXVXK/TQ==} + /@redwoodjs/router@8.0.0-canary.571(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508): + resolution: {integrity: sha512-pfDj67uMUmtULvY9tRMs2dANK3wKXr6tos5nxksU3khDGGf33WOzRK4wdm0gW3SNS9IljgTg5v8Ubu6mSAzRZg==} peerDependencies: - react: 19.0.0-canary-cb151849e1-20240424 - react-dom: 19.0.0-canary-cb151849e1-20240424 + react: 19.0.0-beta-04b058868c-20240508 + react-dom: 19.0.0-beta-04b058868c-20240508 dependencies: '@babel/runtime-corejs3': 7.24.1 - '@redwoodjs/auth': 8.0.0-canary.542 + '@redwoodjs/auth': 8.0.0-canary.571 core-js: 3.36.1 - react: 19.0.0-canary-cb151849e1-20240424 + react: 19.0.0-beta-04b058868c-20240508 react-dom: 18.3.1(react@18.3.1) dev: false - /@redwoodjs/vite@8.0.0-canary.542(@types/node@20.12.7)(csstype@3.1.3)(graphql-tag@2.12.6)(react-dom@18.3.1)(webpack@5.91.0): - resolution: {integrity: sha512-oOp71H8eXcWuWGaWIDY7k8XsRix3JSv0cFwsY3T2l2A7MDmp/mFYgLtsLrFXugvMCZiQnYC9XxP0l3dSBUhDWQ==} + /@redwoodjs/vite@8.0.0-canary.571(@types/node@20.12.7)(csstype@3.1.3)(graphql-tag@2.12.6)(react-dom@18.3.1)(webpack@5.91.0): + resolution: {integrity: sha512-JfM85fcnq0JEJAMZM6Pl7frNYxvgFHn1aVDnxtl6kpBO1sn/Gtj+QyTiC3D3Vrqg4gIkN0KH/xDCCVOReRfjhQ==} hasBin: true dependencies: '@babel/generator': 7.24.1 '@babel/parser': 7.24.5 '@babel/traverse': 7.24.5 - '@redwoodjs/babel-config': 8.0.0-canary.542(graphql-tag@2.12.6) - '@redwoodjs/internal': 8.0.0-canary.542(@swc/core@1.4.11)(@types/node@20.12.7)(graphql-tag@2.12.6)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) - '@redwoodjs/project-config': 8.0.0-canary.542 - '@redwoodjs/web': 8.0.0-canary.542(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) + '@redwoodjs/babel-config': 8.0.0-canary.571(graphql-tag@2.12.6) + '@redwoodjs/internal': 8.0.0-canary.571(@swc/core@1.4.11)(@types/node@20.12.7)(graphql-tag@2.12.6)(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508) + '@redwoodjs/project-config': 8.0.0-canary.571 + '@redwoodjs/web': 8.0.0-canary.571(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508) '@swc/core': 1.4.11 '@vitejs/plugin-react': 4.2.1(vite@5.2.8) '@whatwg-node/fetch': 0.9.17 @@ -11578,8 +11578,8 @@ packages: find-my-way: 8.1.0 http-proxy-middleware: 2.0.6 isbot: 3.8.0 - react: 19.0.0-canary-cb151849e1-20240424 - react-server-dom-webpack: 19.0.0-canary-cb151849e1-20240424(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424)(webpack@5.91.0) + react: 19.0.0-beta-04b058868c-20240508 + react-server-dom-webpack: 19.0.0-beta-04b058868c-20240508(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508)(webpack@5.91.0) vite: 5.2.8(@types/node@20.12.7) vite-plugin-cjs-interop: 2.1.0 yargs-parser: 21.1.1 @@ -11615,24 +11615,24 @@ packages: - webpack dev: false - /@redwoodjs/web@8.0.0-canary.542(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): - resolution: {integrity: sha512-0IjImjt0TQgzL9rsOiLwprW3EuX18qFFI/bTlbsGjwVavfWEt3mSt3yKtkmZkDEyXAbWaEJ4iH6yRHYx/qxU2A==} + /@redwoodjs/web@8.0.0-canary.571(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508): + resolution: {integrity: sha512-9yNAci8sRriG1bv6eUShfqSmykmGADs1sLouu+0Y5zG5qUD9y1b2v+YrfRUvzcYfhdMkNRpOCdoESTdjEHB9WA==} hasBin: true peerDependencies: - react: 19.0.0-canary-cb151849e1-20240424 - react-dom: 19.0.0-canary-cb151849e1-20240424 + react: 19.0.0-beta-04b058868c-20240508 + react-dom: 19.0.0-beta-04b058868c-20240508 dependencies: - '@apollo/client': 3.9.9(graphql@16.8.1)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) + '@apollo/client': 3.9.9(graphql@16.8.1)(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508) '@babel/runtime-corejs3': 7.24.1 - '@redwoodjs/auth': 8.0.0-canary.542 + '@redwoodjs/auth': 8.0.0-canary.571 core-js: 3.36.1 graphql: 16.8.1 graphql-sse: 2.5.2(graphql@16.8.1) graphql-tag: 2.12.6(graphql@16.8.1) - react: 19.0.0-canary-cb151849e1-20240424 + react: 19.0.0-beta-04b058868c-20240508 react-dom: 18.3.1(react@18.3.1) - react-helmet-async: 2.0.4(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) - react-hot-toast: 2.4.1(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424) + react-helmet-async: 2.0.4(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508) + react-hot-toast: 2.4.1(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508) stacktracey: 2.1.8 ts-toolbelt: 9.6.0 transitivePeerDependencies: @@ -25102,14 +25102,14 @@ packages: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} dev: false - /react-helmet-async@2.0.4(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): + /react-helmet-async@2.0.4(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508): resolution: {integrity: sha512-yxjQMWposw+akRfvpl5+8xejl4JtUlHnEBcji6u8/e6oc7ozT+P9PNTWMhCbz2y9tc5zPegw2BvKjQA+NwdEjQ==} peerDependencies: react: ^16.6.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 dependencies: invariant: 2.2.4 - react: 19.0.0-canary-cb151849e1-20240424 + react: 19.0.0-beta-04b058868c-20240508 react-dom: 18.3.1(react@18.3.1) react-fast-compare: 3.2.2 shallowequal: 1.1.0 @@ -25124,7 +25124,7 @@ packages: react: 18.2.0 dev: false - /react-hot-toast@2.4.1(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424): + /react-hot-toast@2.4.1(csstype@3.1.3)(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508): resolution: {integrity: sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==} engines: {node: '>=10'} peerDependencies: @@ -25132,7 +25132,7 @@ packages: react-dom: '>=16' dependencies: goober: 2.1.14(csstype@3.1.3) - react: 19.0.0-canary-cb151849e1-20240424 + react: 19.0.0-beta-04b058868c-20240508 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: - csstype @@ -25273,17 +25273,17 @@ packages: use-sidecar: 1.1.2(react@18.3.1) dev: true - /react-server-dom-webpack@19.0.0-canary-cb151849e1-20240424(react-dom@18.3.1)(react@19.0.0-canary-cb151849e1-20240424)(webpack@5.91.0): - resolution: {integrity: sha512-JEvR9/PnN28iZVnJjNAeSyUGIO0GAjsSPjJm6Dni8OgPg4aCXbQphrwI59Hs7vDb8YJ/QLjytxMZNRYaGbYfbQ==} + /react-server-dom-webpack@19.0.0-beta-04b058868c-20240508(react-dom@18.3.1)(react@19.0.0-beta-04b058868c-20240508)(webpack@5.91.0): + resolution: {integrity: sha512-xamieQ8brN2RDSSIRDXi7trDvzC0z3u62WmIuftzQ613VX/PxsDw/xj0WBfLFi/NYdypIY8BuCsiw2NbhiOEKQ==} engines: {node: '>=0.10.0'} peerDependencies: - react: 19.0.0-canary-cb151849e1-20240424 - react-dom: 19.0.0-canary-cb151849e1-20240424 + react: 19.0.0-beta-04b058868c-20240508 + react-dom: 19.0.0-beta-04b058868c-20240508 webpack: ^5.59.0 dependencies: acorn-loose: 8.4.0 neo-async: 2.6.2 - react: 19.0.0-canary-cb151849e1-20240424 + react: 19.0.0-beta-04b058868c-20240508 react-dom: 18.3.1(react@18.3.1) webpack: 5.91.0(esbuild@0.19.12) dev: false @@ -25345,8 +25345,8 @@ packages: dependencies: loose-envify: 1.4.0 - /react@19.0.0-canary-cb151849e1-20240424: - resolution: {integrity: sha512-sX0ec4kqR1z2PAMdCo0cztaYaoGbpy2EoS5hAzUsBekB9FFnGWP4jbYK7GFURTIh5EK9ny1Mmgkb1hiyVYkj4Q==} + /react@19.0.0-beta-04b058868c-20240508: + resolution: {integrity: sha512-Mch4EeDejk1ZgH/O3TIH6KtELBUzcJdTZujQGWFA6tz9Y9J+X7ZgY9WS2VhUCS/alOlEcIdCXAz0Cb/JET1QVg==} engines: {node: '>=0.10.0'} dev: false @@ -25559,7 +25559,7 @@ packages: resolution: {integrity: sha512-bEAtp/qrtKucxXSJkD4ebopFZYP0q1+3Vb2WECWv/T8yQEgKxDxJ7ztO285tAMaYZVR6mM1GgI6CCn8FROtL1w==} dev: false - /rehackt@0.0.6(react@19.0.0-canary-cb151849e1-20240424): + /rehackt@0.0.6(react@19.0.0-beta-04b058868c-20240508): resolution: {integrity: sha512-l3WEzkt4ntlEc/IB3/mF6SRgNHA6zfQR7BlGOgBTOmx7IJJXojDASav+NsgXHFjHn+6RmwqsGPFgZpabWpeOdw==} peerDependencies: '@types/react': '*' @@ -25570,7 +25570,7 @@ packages: react: optional: true dependencies: - react: 19.0.0-canary-cb151849e1-20240424 + react: 19.0.0-beta-04b058868c-20240508 dev: false /rehype-autolink-headings@7.1.0: From 550c2715573dbee1d16098f5c61ee96d041c2104 Mon Sep 17 00:00:00 2001 From: David Thyresson Date: Tue, 14 May 2024 09:17:33 -0400 Subject: [PATCH 33/33] make both docs table of contents same --- apps/docs/libraries/ts/redwoodjs/keys.mdx | 6 +++++- packages/redwoodjs/src/keys/README.md | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/docs/libraries/ts/redwoodjs/keys.mdx b/apps/docs/libraries/ts/redwoodjs/keys.mdx index 8bcb7f3063..e2b8038eba 100644 --- a/apps/docs/libraries/ts/redwoodjs/keys.mdx +++ b/apps/docs/libraries/ts/redwoodjs/keys.mdx @@ -28,7 +28,11 @@ export const registerMiddleware = () => { In this example, `createApiKeyMiddleware` is used as a global middleware. It will validate the API key for all incoming requests. -## Configuration +## Setup + +To get started with standalone API Key Verification using Unkey, see the [Public API Protection Onboarding Guide](https://www.unkey.com/docs/onboarding/onboarding-api). + +## Examples `createApiKeyMiddleware` can be configured by providing `ApiKeyMiddlewareConfig` configuration options when creating the middleware. diff --git a/packages/redwoodjs/src/keys/README.md b/packages/redwoodjs/src/keys/README.md index 02cd35f98d..62505d085b 100644 --- a/packages/redwoodjs/src/keys/README.md +++ b/packages/redwoodjs/src/keys/README.md @@ -27,7 +27,11 @@ export const registerMiddleware = () => { In this example, `createApiKeyMiddleware` is used as a global middleware. It will validate the API key for all incoming requests. -## Configuration +## Setup + +To get started with standalone API Key Verification using Unkey, see the [Public API Protection Onboarding Guide](https://www.unkey.com/docs/onboarding/onboarding-api). + +## Examples `createApiKeyMiddleware` can be configured by providing `ApiKeyMiddlewareConfig` configuration options when creating the middleware.