diff --git a/README.md b/README.md index beec8471..64e0e3c8 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,8 @@ Even without using advanced features, ZenStack offers the following benefits as # Quick start -> You can also check the [blog sample](./samples/blog) for a complete example. +- [ORM](./samples/orm): A simple example demonstrating ZenStack ORM usage. +- [Next.js + TanStack Query](./samples/next.js): A full-stack sample demonstrating using TanStack Query to consume ZenStack's automatic CRUD services in a Next.js app. ## Installation diff --git a/package.json b/package.json index bef5363a..69a1c859 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,8 @@ "typescript": "catalog:", "typescript-eslint": "^8.34.1", "vitest": "^3.2.4", - "yaml": "^2.8.0" + "yaml": "^2.8.0", + "prisma": "catalog:" }, "pnpm": { "onlyBuiltDependencies": [ diff --git a/packages/cli/package.json b/packages/cli/package.json index 39bf3b43..aa669c54 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -45,7 +45,7 @@ "prisma": "catalog:" }, "devDependencies": { - "@types/better-sqlite3": "^7.6.13", + "@types/better-sqlite3": "catalog:", "@types/semver": "^7.7.0", "@types/tmp": "catalog:", "@zenstackhq/eslint-config": "workspace:*", diff --git a/packages/tanstack-query/eslint.config.js b/packages/clients/tanstack-query/eslint.config.js similarity index 100% rename from packages/tanstack-query/eslint.config.js rename to packages/clients/tanstack-query/eslint.config.js diff --git a/packages/clients/tanstack-query/package.json b/packages/clients/tanstack-query/package.json new file mode 100644 index 00000000..269a024c --- /dev/null +++ b/packages/clients/tanstack-query/package.json @@ -0,0 +1,70 @@ +{ + "name": "@zenstackhq/tanstack-query", + "version": "3.0.0-beta.15", + "description": "TanStack Query Client for consuming ZenStack v3's CRUD service", + "main": "index.js", + "type": "module", + "private": true, + "scripts": { + "build": "tsc --noEmit && tsup-node", + "watch": "tsup-node --watch", + "lint": "eslint src --ext ts", + "test": "vitest run", + "pack": "pnpm pack", + "test:generate": "tsx scripts/generate.ts" + }, + "keywords": [ + "tanstack-query", + "react-query", + "zenstack", + "orm", + "fullstack" + ], + "author": "ZenStack Team", + "license": "MIT", + "exports": { + "./react": { + "import": { + "types": "./dist/react.d.ts", + "default": "./dist/react.js" + }, + "require": { + "types": "./dist/react.d.cts", + "default": "./dist/react.cjs" + } + } + }, + "dependencies": { + "@zenstackhq/common-helpers": "workspace:*", + "@zenstackhq/orm": "workspace:*", + "@zenstackhq/schema": "workspace:*", + "decimal.js": "catalog:", + "superjson": "^2.2.3" + }, + "devDependencies": { + "@tanstack/react-query": "catalog:", + "@testing-library/dom": "^10.4.1", + "@testing-library/react": "^16.3.0", + "@types/react": "catalog:", + "@zenstackhq/eslint-config": "workspace:*", + "@zenstackhq/language": "workspace:*", + "@zenstackhq/sdk": "workspace:*", + "@zenstackhq/typescript-config": "workspace:*", + "@zenstackhq/vitest-config": "workspace:*", + "happy-dom": "^20.0.10", + "nock": "^14.0.10", + "react": "catalog:" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.0.0", + "react": "^18 || ^19" + }, + "peerDependenciesMeta": { + "@tanstack/react-query": { + "optional": true + }, + "react": { + "optional": true + } + } +} diff --git a/packages/clients/tanstack-query/scripts/generate.ts b/packages/clients/tanstack-query/scripts/generate.ts new file mode 100644 index 00000000..f4f0c03b --- /dev/null +++ b/packages/clients/tanstack-query/scripts/generate.ts @@ -0,0 +1,27 @@ +import { loadDocument } from '@zenstackhq/language'; +import { TsSchemaGenerator } from '@zenstackhq/sdk'; +import { glob } from 'glob'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const dir = path.dirname(fileURLToPath(import.meta.url)); + +async function main() { + const zmodelFiles = glob.sync(path.resolve(dir, '../test/**/*.zmodel')); + for (const file of zmodelFiles) { + console.log(`Generating TS schema for: ${file}`); + await generate(file); + } +} + +async function generate(schemaPath: string) { + const generator = new TsSchemaGenerator(); + const outputDir = path.dirname(schemaPath); + const result = await loadDocument(schemaPath); + if (!result.success) { + throw new Error(`Failed to load schema from ${schemaPath}: ${result.errors}`); + } + await generator.generate(result.model, outputDir); +} + +main(); diff --git a/packages/clients/tanstack-query/src/react.ts b/packages/clients/tanstack-query/src/react.ts new file mode 100644 index 00000000..a1145273 --- /dev/null +++ b/packages/clients/tanstack-query/src/react.ts @@ -0,0 +1,529 @@ +import { + useInfiniteQuery, + useMutation, + useQuery, + useQueryClient, + useSuspenseInfiniteQuery, + useSuspenseQuery, + type DefaultError, + type InfiniteData, + type QueryKey, + type UseInfiniteQueryOptions, + type UseInfiniteQueryResult, + type UseMutationOptions, + type UseMutationResult, + type UseQueryOptions, + type UseQueryResult, + type UseSuspenseInfiniteQueryOptions, + type UseSuspenseInfiniteQueryResult, + type UseSuspenseQueryOptions, + type UseSuspenseQueryResult, +} from '@tanstack/react-query'; +import { lowerCaseFirst } from '@zenstackhq/common-helpers'; +import type { + AggregateArgs, + AggregateResult, + BatchResult, + CountArgs, + CountResult, + CreateArgs, + CreateManyAndReturnArgs, + CreateManyArgs, + DeleteArgs, + DeleteManyArgs, + FindArgs, + FindUniqueArgs, + GroupByArgs, + GroupByResult, + ModelResult, + SelectSubset, + UpdateArgs, + UpdateManyAndReturnArgs, + UpdateManyArgs, + UpsertArgs, +} from '@zenstackhq/orm'; +import type { GetModels, SchemaDef } from '@zenstackhq/schema'; +import { createContext, useContext } from 'react'; +import { + fetcher, + getQueryKey, + makeUrl, + marshal, + setupInvalidation, + setupOptimisticUpdate, + type APIContext, + type ExtraMutationOptions, + type ExtraQueryOptions, +} from './utils/common'; + +/** + * The default query endpoint. + */ +export const DEFAULT_QUERY_ENDPOINT = '/api/model'; + +/** + * React context for query settings. + */ +export const QuerySettingsContext = createContext({ + endpoint: DEFAULT_QUERY_ENDPOINT, + fetch: undefined, +}); + +/** + * React context provider for configuring query settings. + */ +export const QuerySettingsProvider = QuerySettingsContext.Provider; + +/** + * React context provider for configuring query settings. + * + * @deprecated Use `QuerySettingsProvider` instead. + */ +export const Provider = QuerySettingsProvider; + +function useHooksContext() { + const { endpoint, ...rest } = useContext(QuerySettingsContext); + return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest }; +} + +export type ModelQueryOptions = Omit, 'queryKey'> & ExtraQueryOptions; + +export type ModelQueryResult = UseQueryResult & { queryKey: QueryKey }; + +export type ModelSuspenseQueryOptions = Omit, 'queryKey'> & + ExtraQueryOptions; + +export type ModelSuspenseQueryResult = UseSuspenseQueryResult & { queryKey: QueryKey }; + +export type ModelInfiniteQueryOptions = Omit< + UseInfiniteQueryOptions>, + 'queryKey' | 'initialPageParam' +>; + +export type ModelInfiniteQueryResult = UseInfiniteQueryResult & { queryKey: QueryKey }; + +export type ModelSuspenseInfiniteQueryOptions = Omit< + UseSuspenseInfiniteQueryOptions>, + 'queryKey' | 'initialPageParam' +>; + +export type ModelSuspenseInfiniteQueryResult = UseSuspenseInfiniteQueryResult & { + queryKey: QueryKey; +}; + +export type ModelMutationOptions = Omit, 'mutationFn'> & + ExtraMutationOptions; + +export type ModelMutationResult = UseMutationResult; + +export type SchemaHooks = { + [Model in GetModels as `${Uncapitalize}`]: ModelQueryHooks; +}; + +export type ModelQueryHooks> = { + useFindUnique>( + args: SelectSubset>, + options?: ModelQueryOptions | null>, + ): ModelQueryResult | null>; + + useSuspenseFindUnique>( + args: SelectSubset>, + options?: ModelSuspenseQueryOptions | null>, + ): ModelSuspenseQueryResult | null>; + + useFindFirst>( + args?: SelectSubset>, + options?: ModelQueryOptions | null>, + ): ModelQueryResult | null>; + + useSuspenseFindFirst>( + args?: SelectSubset>, + options?: ModelSuspenseQueryOptions | null>, + ): ModelSuspenseQueryResult | null>; + + useFindMany>( + args?: SelectSubset>, + options?: ModelQueryOptions[]>, + ): ModelQueryResult[]>; + + useSuspenseFindMany>( + args?: SelectSubset>, + options?: ModelSuspenseQueryOptions[]>, + ): ModelSuspenseQueryResult[]>; + + useInfiniteFindMany>( + args?: SelectSubset>, + options?: ModelInfiniteQueryOptions[]>, + ): ModelInfiniteQueryResult[]>>; + + useSuspenseInfiniteFindMany>( + args?: SelectSubset>, + options?: ModelSuspenseInfiniteQueryOptions[]>, + ): ModelSuspenseInfiniteQueryResult[]>>; + + useCreate>( + options?: ModelMutationOptions, T>, + ): ModelMutationResult, T>; + + useCreateMany>( + options?: ModelMutationOptions, + ): ModelMutationResult; + + useCreateManyAndReturn>( + options?: ModelMutationOptions[], T>, + ): ModelMutationResult[], T>; + + useUpdate>( + options?: ModelMutationOptions, T>, + ): ModelMutationResult, T>; + + useUpdateMany[]>( + options?: ModelMutationOptions, + ): ModelMutationResult; + + useUpdateManyAndReturn>( + options?: ModelMutationOptions[], T>, + ): ModelMutationResult[], T>; + + useUpsert>( + options?: ModelMutationOptions, T>, + ): ModelMutationResult, T>; + + useDelete>( + options?: ModelMutationOptions, T>, + ): ModelMutationResult, T>; + + useDeleteMany[]>( + options?: ModelMutationOptions, + ): ModelMutationResult; + + useCount>( + options?: ModelQueryOptions>, + ): ModelQueryResult>; + + useSuspenseCount>( + options?: ModelSuspenseQueryOptions>, + ): ModelSuspenseQueryResult>; + + useAggregate>( + options?: ModelQueryOptions>, + ): ModelQueryResult>; + + useSuspenseAggregate>( + options?: ModelSuspenseQueryOptions>, + ): ModelSuspenseQueryResult>; + + useGroupBy>( + options?: ModelQueryOptions>, + ): ModelQueryResult>; + + useSuspenseGroupBy>( + options?: ModelSuspenseQueryOptions>, + ): ModelSuspenseQueryResult>; +}; + +/** + * Gets data query hooks for all models in the schema. + */ +export function useClientQueries(schema: Schema): SchemaHooks { + return Object.keys(schema.models).reduce((acc, model) => { + (acc as any)[lowerCaseFirst(model)] = useModelQueries(schema, model as GetModels); + return acc; + }, {} as SchemaHooks); +} + +/** + * Gets data query hooks for a specific model in the schema. + */ +export function useModelQueries>( + schema: Schema, + model: Model, +): ModelQueryHooks { + const modelDef = Object.values(schema.models).find((m) => m.name.toLowerCase() === model.toLowerCase()); + if (!modelDef) { + throw new Error(`Model "${model}" not found in schema`); + } + + const modelName = modelDef.name; + + return { + useFindUnique: (args: any, options?: any) => { + return useInternalQuery(schema, modelName, 'findUnique', args, options); + }, + + useSuspenseFindUnique: (args: any, options?: any) => { + return useInternalSuspenseQuery(schema, modelName, 'findUnique', args, options); + }, + + useFindFirst: (args: any, options?: any) => { + return useInternalQuery(schema, modelName, 'findFirst', args, options); + }, + + useSuspenseFindFirst: (args: any, options?: any) => { + return useInternalSuspenseQuery(schema, modelName, 'findFirst', args, options); + }, + + useFindMany: (args: any, options?: any) => { + return useInternalQuery(schema, modelName, 'findMany', args, options); + }, + + useSuspenseFindMany: (args: any, options?: any) => { + return useInternalSuspenseQuery(schema, modelName, 'findMany', args, options); + }, + + useInfiniteFindMany: (args: any, options?: any) => { + return useInternalInfiniteQuery(schema, modelName, 'findMany', args, options); + }, + + useSuspenseInfiniteFindMany: (args: any, options?: any) => { + return useInternalSuspenseInfiniteQuery(schema, modelName, 'findMany', args, options); + }, + + useCreate: (options?: any) => { + return useInternalMutation(schema, modelName, 'POST', 'create', options, true); + }, + + useCreateMany: (options?: any) => { + return useInternalMutation(schema, modelName, 'POST', 'createMany', options, false); + }, + + useCreateManyAndReturn: (options?: any) => { + return useInternalMutation(schema, modelName, 'POST', 'createManyAndReturn', options, true); + }, + + useUpdate: (options?: any) => { + return useInternalMutation(schema, modelName, 'PUT', 'update', options, true); + }, + + useUpdateMany: (options?: any) => { + return useInternalMutation(schema, modelName, 'PUT', 'updateMany', options, false); + }, + + useUpdateManyAndReturn: (options?: any) => { + return useInternalMutation(schema, modelName, 'PUT', 'updateManyAndReturn', options, true); + }, + + useUpsert: (options?: any) => { + return useInternalMutation(schema, modelName, 'POST', 'upsert', options, true); + }, + + useDelete: (options?: any) => { + return useInternalMutation(schema, modelName, 'DELETE', 'delete', options, true); + }, + + useDeleteMany: (options?: any) => { + return useInternalMutation(schema, modelName, 'DELETE', 'deleteMany', options, false); + }, + + useCount: (options?: any) => { + return useInternalQuery(schema, modelName, 'count', undefined, options); + }, + + useSuspenseCount: (options?: any) => { + return useInternalSuspenseQuery(schema, modelName, 'count', undefined, options); + }, + + useAggregate: (options?: any) => { + return useInternalQuery(schema, modelName, 'aggregate', undefined, options); + }, + + useSuspenseAggregate: (options?: any) => { + return useInternalSuspenseQuery(schema, modelName, 'aggregate', undefined, options); + }, + + useGroupBy: (options?: any) => { + return useInternalQuery(schema, modelName, 'groupBy', undefined, options); + }, + + useSuspenseGroupBy: (options?: any) => { + return useInternalSuspenseQuery(schema, modelName, 'groupBy', undefined, options); + }, + } as ModelQueryHooks; +} + +export function useInternalQuery( + _schema: SchemaDef, + model: string, + operation: string, + args?: unknown, + options?: Omit, 'queryKey'> & ExtraQueryOptions, +) { + const { endpoint, fetch } = useHooksContext(); + const reqUrl = makeUrl(endpoint, model, operation, args); + const queryKey = getQueryKey(model, operation, args, { + infinite: false, + optimisticUpdate: options?.optimisticUpdate !== false, + }); + return { + queryKey, + ...useQuery({ + queryKey, + queryFn: ({ signal }) => fetcher(reqUrl, { signal }, fetch, false), + ...options, + }), + }; +} + +export function useInternalSuspenseQuery( + _schema: SchemaDef, + model: string, + operation: string, + args?: unknown, + options?: Omit, 'queryKey'> & ExtraQueryOptions, +) { + const { endpoint, fetch } = useHooksContext(); + const reqUrl = makeUrl(endpoint, model, operation, args); + const queryKey = getQueryKey(model, operation, args, { + infinite: false, + optimisticUpdate: options?.optimisticUpdate !== false, + }); + return { + queryKey, + ...useSuspenseQuery({ + queryKey, + queryFn: ({ signal }) => fetcher(reqUrl, { signal }, fetch, false), + ...options, + }), + }; +} + +export function useInternalInfiniteQuery( + _schema: SchemaDef, + model: string, + operation: string, + args: unknown, + options: Omit< + UseInfiniteQueryOptions>, + 'queryKey' | 'initialPageParam' + >, +) { + const { endpoint, fetch } = useHooksContext(); + const queryKey = getQueryKey(model, operation, args, { infinite: true, optimisticUpdate: false }); + return { + queryKey, + ...useInfiniteQuery({ + queryKey, + queryFn: ({ pageParam, signal }) => { + return fetcher( + makeUrl(endpoint, model, operation, pageParam ?? args), + { signal }, + fetch, + false, + ); + }, + initialPageParam: args, + ...options, + }), + }; +} + +export function useInternalSuspenseInfiniteQuery( + _schema: SchemaDef, + model: string, + operation: string, + args: unknown, + options: Omit< + UseSuspenseInfiniteQueryOptions>, + 'queryKey' | 'initialPageParam' + >, +) { + const { endpoint, fetch } = useHooksContext(); + const queryKey = getQueryKey(model, operation, args, { infinite: true, optimisticUpdate: false }); + return { + queryKey, + ...useSuspenseInfiniteQuery({ + queryKey, + queryFn: ({ pageParam, signal }) => { + return fetcher( + makeUrl(endpoint, model, operation, pageParam ?? args), + { signal }, + fetch, + false, + ); + }, + initialPageParam: args, + ...options, + }), + }; +} + +/** + * Creates a react-query mutation + * + * @private + * + * @param model The name of the model under mutation. + * @param method The HTTP method. + * @param operation The mutation operation (e.g. `create`). + * @param options The react-query options. + * @param checkReadBack Whether to check for read back errors and return undefined if found. + */ +export function useInternalMutation< + TArgs, + R = any, + C extends boolean = boolean, + Result = C extends true ? R | undefined : R, +>( + schema: SchemaDef, + model: string, + method: 'POST' | 'PUT' | 'DELETE', + operation: string, + options?: Omit, 'mutationFn'> & ExtraMutationOptions, + checkReadBack?: C, +) { + const { endpoint, fetch } = useHooksContext(); + const queryClient = useQueryClient(); + const mutationFn = (data: any) => { + const reqUrl = + method === 'DELETE' ? makeUrl(endpoint, model, operation, data) : makeUrl(endpoint, model, operation); + const fetchInit: RequestInit = { + method, + ...(method !== 'DELETE' && { + headers: { + 'content-type': 'application/json', + }, + body: marshal(data), + }), + }; + return fetcher(reqUrl, fetchInit, fetch, checkReadBack) as Promise; + }; + + const finalOptions = { ...options, mutationFn }; + const invalidateQueries = options?.invalidateQueries !== false; + const optimisticUpdate = !!options?.optimisticUpdate; + const { logging } = useContext(QuerySettingsContext); + + if (operation) { + if (invalidateQueries) { + setupInvalidation( + model, + operation, + schema, + finalOptions, + (predicate) => queryClient.invalidateQueries({ predicate }), + logging, + ); + } + + if (optimisticUpdate) { + setupOptimisticUpdate( + model, + operation, + schema, + finalOptions, + queryClient.getQueryCache().getAll(), + (queryKey, data) => { + // update query cache + queryClient.setQueryData(queryKey, data); + // cancel on-flight queries to avoid redundant cache updates, + // the settlement of the current mutation will trigger a new revalidation + queryClient.cancelQueries({ queryKey }, { revert: false, silent: true }); + }, + invalidateQueries ? (predicate) => queryClient.invalidateQueries({ predicate }) : undefined, + logging, + ); + } + } + + return useMutation(finalOptions); +} diff --git a/packages/clients/tanstack-query/src/utils/common.ts b/packages/clients/tanstack-query/src/utils/common.ts new file mode 100644 index 00000000..b26720ee --- /dev/null +++ b/packages/clients/tanstack-query/src/utils/common.ts @@ -0,0 +1,457 @@ +import { lowerCaseFirst } from '@zenstackhq/common-helpers'; +import type { SchemaDef } from '@zenstackhq/schema'; +import { applyMutation } from './mutator'; +import { getMutatedModels, getReadModels } from './query-analysis'; +import { deserialize, serialize } from './serialization'; +import type { ORMWriteActionType } from './types'; + +/** + * The default query endpoint. + */ +export const DEFAULT_QUERY_ENDPOINT = '/api/model'; + +/** + * Prefix for react-query keys. + */ +export const QUERY_KEY_PREFIX = 'zenstack'; + +/** + * Function signature for `fetch`. + */ +export type FetchFn = (url: string, options?: RequestInit) => Promise; + +/** + * Type for query and mutation errors. + */ +export type QueryError = Error & { + /** + * Additional error information. + */ + info?: unknown; + + /** + * HTTP status code. + */ + status?: number; +}; + +/** + * Result of optimistic data provider. + */ +export type OptimisticDataProviderResult = { + /** + * Kind of the result. + * - Update: use the `data` field to update the query cache. + * - Skip: skip the optimistic update for this query. + * - ProceedDefault: proceed with the default optimistic update. + */ + kind: 'Update' | 'Skip' | 'ProceedDefault'; + + /** + * Data to update the query cache. Only applicable if `kind` is 'Update'. + * + * If the data is an object with fields updated, it should have a `$optimistic` + * field set to `true`. If it's an array and an element object is created or updated, + * the element should have a `$optimistic` field set to `true`. + */ + data?: any; +}; + +/** + * Optimistic data provider. + * + * @param args Arguments. + * @param args.queryModel The model of the query. + * @param args.queryOperation The operation of the query, `findMany`, `count`, etc. + * @param args.queryArgs The arguments of the query. + * @param args.currentData The current cache data for the query. + * @param args.mutationArgs The arguments of the mutation. + */ +export type OptimisticDataProvider = (args: { + queryModel: string; + queryOperation: string; + queryArgs: any; + currentData: any; + mutationArgs: any; +}) => OptimisticDataProviderResult | Promise; + +/** + * Extra mutation options. + */ +export type ExtraMutationOptions = { + /** + * Whether to automatically invalidate queries potentially affected by the mutation. Defaults to `true`. + */ + invalidateQueries?: boolean; + + /** + * Whether to optimistically update queries potentially affected by the mutation. Defaults to `false`. + */ + optimisticUpdate?: boolean; + + /** + * A callback for computing optimistic update data for each query cache entry. + */ + optimisticDataProvider?: OptimisticDataProvider; +}; + +/** + * Extra query options. + */ +export type ExtraQueryOptions = { + /** + * Whether to opt-in to optimistic updates for this query. Defaults to `true`. + */ + optimisticUpdate?: boolean; +}; + +/** + * Context type for configuring the hooks. + */ +export type APIContext = { + /** + * The endpoint to use for the queries. + */ + endpoint?: string; + + /** + * A custom fetch function for sending the HTTP requests. + */ + fetch?: FetchFn; + + /** + * If logging is enabled. + */ + logging?: boolean; +}; + +export async function fetcher( + url: string, + options?: RequestInit, + customFetch?: FetchFn, + checkReadBack?: C, +): Promise { + const _fetch = customFetch ?? fetch; + const res = await _fetch(url, options); + if (!res.ok) { + const errData = unmarshal(await res.text()); + if ( + checkReadBack !== false && + errData.error?.rejectedByPolicy && + errData.error?.rejectReason === 'cannot-read-back' + ) { + // policy doesn't allow mutation result to be read back, just return undefined + return undefined as any; + } + const error: QueryError = new Error('An error occurred while fetching the data.'); + error.info = errData.error; + error.status = res.status; + throw error; + } + + const textResult = await res.text(); + try { + return unmarshal(textResult).data as R; + } catch (err) { + console.error(`Unable to deserialize data:`, textResult); + throw err; + } +} + +type QueryKey = [ + string /* prefix */, + string /* model */, + string /* operation */, + unknown /* args */, + { + infinite: boolean; + optimisticUpdate: boolean; + } /* flags */, +]; + +/** + * Computes query key for the given model, operation and query args. + * @param model Model name. + * @param operation Query operation (e.g, `findMany`) or request URL. If it's a URL, the last path segment will be used as the operation name. + * @param args Query arguments. + * @param options Query options, including `infinite` indicating if it's an infinite query (defaults to false), and `optimisticUpdate` indicating if optimistic updates are enabled (defaults to true). + * @returns Query key + */ +export function getQueryKey( + model: string, + operation: string, + args: unknown, + options: { infinite: boolean; optimisticUpdate: boolean } = { infinite: false, optimisticUpdate: true }, +): QueryKey { + const infinite = options.infinite; + // infinite query doesn't support optimistic updates + const optimisticUpdate = options.infinite ? false : options.optimisticUpdate; + return [QUERY_KEY_PREFIX, model, operation!, args, { infinite, optimisticUpdate }]; +} + +export function marshal(value: unknown) { + const { data, meta } = serialize(value); + if (meta) { + return JSON.stringify({ ...(data as any), meta: { serialization: meta } }); + } else { + return JSON.stringify(data); + } +} + +export function unmarshal(value: string) { + const parsed = JSON.parse(value); + if (typeof parsed === 'object' && parsed?.data && parsed?.meta?.serialization) { + const deserializedData = deserialize(parsed.data, parsed.meta.serialization); + return { ...parsed, data: deserializedData }; + } else { + return parsed; + } +} + +export function makeUrl(url: string, model: string, operation: string, args?: unknown) { + const baseUrl = `${url}/${lowerCaseFirst(model)}/${operation}`; + if (!args) { + return baseUrl; + } + + const { data, meta } = serialize(args); + let result = `${baseUrl}?q=${encodeURIComponent(JSON.stringify(data))}`; + if (meta) { + result += `&meta=${encodeURIComponent(JSON.stringify({ serialization: meta }))}`; + } + return result; +} + +type InvalidationPredicate = ({ queryKey }: { queryKey: readonly unknown[] }) => boolean; +type InvalidateFunc = (predicate: InvalidationPredicate) => Promise; +type MutationOptions = { + onMutate?: (...args: any[]) => any; + onSuccess?: (...args: any[]) => any; + onSettled?: (...args: any[]) => any; +}; + +// sets up invalidation hook for a mutation +export function setupInvalidation( + model: string, + operation: string, + schema: SchemaDef, + options: MutationOptions, + invalidate: InvalidateFunc, + logging = false, +) { + const origOnSuccess = options?.onSuccess; + options.onSuccess = async (...args: unknown[]) => { + const [_, variables] = args; + const predicate = await getInvalidationPredicate( + model, + operation as ORMWriteActionType, + variables, + schema, + logging, + ); + await invalidate(predicate); + return origOnSuccess?.(...args); + }; +} + +// gets a predicate for evaluating whether a query should be invalidated +async function getInvalidationPredicate( + model: string, + operation: ORMWriteActionType, + mutationArgs: any, + schema: SchemaDef, + logging = false, +) { + const mutatedModels = await getMutatedModels(model, operation, mutationArgs, schema); + + return ({ queryKey }: { queryKey: readonly unknown[] }) => { + const [_, queryModel, , args] = queryKey as QueryKey; + + if (mutatedModels.includes(queryModel)) { + // direct match + if (logging) { + console.log(`Invalidating query ${JSON.stringify(queryKey)} due to mutation "${model}.${operation}"`); + } + return true; + } + + if (args) { + // traverse query args to find nested reads that match the model under mutation + if (findNestedRead(queryModel, mutatedModels, schema, args)) { + if (logging) { + console.log( + `Invalidating query ${JSON.stringify(queryKey)} due to mutation "${model}.${operation}"`, + ); + } + return true; + } + } + + return false; + }; +} + +// find nested reads that match the given models +function findNestedRead(visitingModel: string, targetModels: string[], schema: SchemaDef, args: any) { + const modelsRead = getReadModels(visitingModel, schema, args); + return targetModels.some((m) => modelsRead.includes(m)); +} + +type QueryCache = { + queryKey: readonly unknown[]; + state: { + data: unknown; + error: unknown; + }; +}[]; + +type SetCacheFunc = (queryKey: readonly unknown[], data: unknown) => void; + +/** + * Sets up optimistic update and invalidation (after settled) for a mutation. + */ +export function setupOptimisticUpdate( + model: string, + operation: string, + schema: SchemaDef, + options: MutationOptions & ExtraMutationOptions, + queryCache: QueryCache, + setCache: SetCacheFunc, + invalidate?: InvalidateFunc, + logging = false, +) { + const origOnMutate = options?.onMutate; + const origOnSettled = options?.onSettled; + + // optimistic update on mutate + options.onMutate = async (...args: unknown[]) => { + const [variables] = args; + await optimisticUpdate( + model, + operation as ORMWriteActionType, + variables, + options, + schema, + queryCache, + setCache, + logging, + ); + return origOnMutate?.(...args); + }; + + // invalidate on settled + options.onSettled = async (...args: unknown[]) => { + if (invalidate) { + const [, , variables] = args; + const predicate = await getInvalidationPredicate( + model, + operation as ORMWriteActionType, + variables, + schema, + logging, + ); + await invalidate(predicate); + } + return origOnSettled?.(...args); + }; +} + +// optimistically updates query cache +async function optimisticUpdate( + mutationModel: string, + mutationOp: string, + mutationArgs: any, + options: MutationOptions & ExtraMutationOptions, + schema: SchemaDef, + queryCache: QueryCache, + setCache: SetCacheFunc, + logging = false, +) { + for (const cacheItem of queryCache) { + const { + queryKey, + state: { data, error }, + } = cacheItem; + + if (!isZenStackQueryKey(queryKey)) { + // skip non-zenstack queries + continue; + } + + if (error) { + if (logging) { + console.warn(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to error:`, error); + } + continue; + } + + const [_, queryModel, queryOperation, queryArgs, queryOptions] = queryKey; + if (!queryOptions?.optimisticUpdate) { + if (logging) { + console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to opt-out`); + } + continue; + } + + if (options.optimisticDataProvider) { + const providerResult = await options.optimisticDataProvider({ + queryModel, + queryOperation, + queryArgs, + currentData: data, + mutationArgs, + }); + + if (providerResult?.kind === 'Skip') { + // skip + if (logging) { + console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to provider`); + } + continue; + } else if (providerResult?.kind === 'Update') { + // update cache + if (logging) { + console.log(`Optimistically updating query ${JSON.stringify(queryKey)} due to provider`); + } + setCache(queryKey, providerResult.data); + continue; + } + } + + // proceed with default optimistic update + const mutatedData = await applyMutation( + queryModel, + queryOperation, + data, + mutationModel, + mutationOp as ORMWriteActionType, + mutationArgs, + schema, + logging, + ); + + if (mutatedData !== undefined) { + // mutation applicable to this query, update cache + if (logging) { + console.log( + `Optimistically updating query ${JSON.stringify( + queryKey, + )} due to mutation "${mutationModel}.${mutationOp}"`, + ); + } + setCache(queryKey, mutatedData); + } + } +} + +function isZenStackQueryKey(queryKey: readonly unknown[]): queryKey is QueryKey { + if (queryKey.length < 5) { + return false; + } + + if (queryKey[0] !== QUERY_KEY_PREFIX) { + return false; + } + + return true; +} diff --git a/packages/clients/tanstack-query/src/utils/mutator.ts b/packages/clients/tanstack-query/src/utils/mutator.ts new file mode 100644 index 00000000..5d131dd9 --- /dev/null +++ b/packages/clients/tanstack-query/src/utils/mutator.ts @@ -0,0 +1,441 @@ +import { clone, enumerate, invariant, zip } from '@zenstackhq/common-helpers'; +import type { FieldDef, SchemaDef } from '@zenstackhq/schema'; +import { NestedWriteVisitor } from './nested-write-visitor'; +import type { ORMWriteActionType } from './types'; + +/** + * Tries to apply a mutation to a query result. + * + * @param queryModel the model of the query + * @param queryOp the operation of the query + * @param queryData the result data of the query + * @param mutationModel the model of the mutation + * @param mutationOp the operation of the mutation + * @param mutationArgs the arguments of the mutation + * @param schema the model metadata + * @param logging whether to log the mutation application + * @returns the updated query data if the mutation is applicable, otherwise undefined + */ +export async function applyMutation( + queryModel: string, + queryOp: string, + queryData: any, + mutationModel: string, + mutationOp: ORMWriteActionType, + mutationArgs: any, + schema: SchemaDef, + logging: boolean, +) { + if (!queryData || (typeof queryData !== 'object' && !Array.isArray(queryData))) { + return undefined; + } + + if (!queryOp.startsWith('find')) { + // only findXXX results are applicable + return undefined; + } + + return await doApplyMutation(queryModel, queryData, mutationModel, mutationOp, mutationArgs, schema, logging); +} + +async function doApplyMutation( + queryModel: string, + queryData: any, + mutationModel: string, + mutationOp: ORMWriteActionType, + mutationArgs: any, + schema: SchemaDef, + logging: boolean, +) { + let resultData = queryData; + let updated = false; + + const visitor = new NestedWriteVisitor(schema, { + create: (model, args) => { + if ( + model === queryModel && + Array.isArray(resultData) // "create" mutation is only relevant for arrays + ) { + const r = createMutate(queryModel, resultData, args, schema, logging); + if (r) { + resultData = r; + updated = true; + } + } + }, + + createMany: (model, args) => { + if ( + model === queryModel && + args?.data && + Array.isArray(resultData) // "createMany" mutation is only relevant for arrays + ) { + for (const oneArg of enumerate(args.data)) { + const r = createMutate(queryModel, resultData, oneArg, schema, logging); + if (r) { + resultData = r; + updated = true; + } + } + } + }, + + update: (model, args) => { + if ( + model === queryModel && + !Array.isArray(resultData) // array elements will be handled with recursion + ) { + const r = updateMutate(queryModel, resultData, model, args, schema, logging); + if (r) { + resultData = r; + updated = true; + } + } + }, + + upsert: (model, args) => { + if (model === queryModel && args?.where && args?.create && args?.update) { + const r = upsertMutate(queryModel, resultData, model, args, schema, logging); + if (r) { + resultData = r; + updated = true; + } + } + }, + + delete: (model, args) => { + if (model === queryModel) { + const r = deleteMutate(queryModel, resultData, model, args, schema, logging); + if (r) { + resultData = r; + updated = true; + } + } + }, + }); + + await visitor.visit(mutationModel, mutationOp, mutationArgs); + + const modelFields = schema.models[queryModel]?.fields; + invariant(modelFields, `Model ${queryModel} not found in schema`); + + if (Array.isArray(resultData)) { + // try to apply mutation to each item in the array, replicate the entire + // array if any item is updated + + let arrayCloned = false; + for (let i = 0; i < resultData.length; i++) { + const item = resultData[i]; + if ( + !item || + typeof item !== 'object' || + item.$optimistic // skip items already optimistically updated + ) { + continue; + } + + const r = await doApplyMutation(queryModel, item, mutationModel, mutationOp, mutationArgs, schema, logging); + + if (r && typeof r === 'object') { + if (!arrayCloned) { + resultData = [...resultData]; + arrayCloned = true; + } + resultData[i] = r; + updated = true; + } + } + } else if (resultData !== null && typeof resultData === 'object') { + // Clone resultData to prevent mutations affecting the loop + const currentData = { ...resultData }; + + // iterate over each field and apply mutation to nested data models + for (const [key, value] of Object.entries(currentData)) { + const fieldDef = modelFields[key]; + if (!fieldDef?.relation) { + continue; + } + + const r = await doApplyMutation( + fieldDef.type, + value, + mutationModel, + mutationOp, + mutationArgs, + schema, + logging, + ); + + if (r && typeof r === 'object') { + resultData = { ...resultData, [key]: r }; + updated = true; + } + } + } + + return updated ? resultData : undefined; +} + +function createMutate(queryModel: string, currentData: any, newData: any, schema: SchemaDef, logging: boolean) { + if (!newData) { + return undefined; + } + + const modelFields = schema.models[queryModel]?.fields; + if (!modelFields) { + return undefined; + } + + const insert: any = {}; + const newDataFields = Object.keys(newData); + + Object.entries(modelFields).forEach(([name, field]) => { + if (field.relation && newData[name]) { + // deal with "connect" + assignForeignKeyFields(field, insert, newData[name]); + return; + } + + if (newDataFields.includes(name)) { + insert[name] = clone(newData[name]); + } else { + const defaultAttr = field.attributes?.find((attr) => attr.name === '@default'); + if (field.type === 'DateTime') { + // default value for DateTime field + if (defaultAttr || field.attributes?.some((attr) => attr.name === '@updatedAt')) { + insert[name] = new Date(); + return; + } + } + + const defaultArg = defaultAttr?.args?.[0]?.value; + if (defaultArg?.kind === 'literal') { + // other default value + insert[name] = defaultArg.value; + } + } + }); + + // add temp id value + const idFields = getIdFields(schema, queryModel); + idFields.forEach((f) => { + if (insert[f.name] === undefined) { + if (f.type === 'Int' || f.type === 'BigInt') { + const currMax = Array.isArray(currentData) + ? Math.max( + ...[...currentData].map((item) => { + const idv = parseInt(item[f.name]); + return isNaN(idv) ? 0 : idv; + }), + ) + : 0; + insert[f.name] = currMax + 1; + } else { + insert[f.name] = crypto.randomUUID(); + } + } + }); + + insert.$optimistic = true; + + if (logging) { + console.log(`Optimistic create for ${queryModel}:`, insert); + } + return [insert, ...(Array.isArray(currentData) ? currentData : [])]; +} + +function updateMutate( + queryModel: string, + currentData: any, + mutateModel: string, + mutateArgs: any, + schema: SchemaDef, + logging: boolean, +) { + if (!currentData || typeof currentData !== 'object') { + return undefined; + } + + if (!mutateArgs?.where || typeof mutateArgs.where !== 'object') { + return undefined; + } + + if (!mutateArgs?.data || typeof mutateArgs.data !== 'object') { + return undefined; + } + + if (!idFieldsMatch(mutateModel, currentData, mutateArgs.where, schema)) { + return undefined; + } + + const modelFields = schema.models[queryModel]?.fields; + if (!modelFields) { + return undefined; + } + + let updated = false; + let resultData = currentData; + + for (const [key, value] of Object.entries(mutateArgs.data)) { + const fieldInfo = modelFields[key]; + if (!fieldInfo) { + continue; + } + + if (fieldInfo.relation && !value?.connect) { + // relation field but without "connect" + continue; + } + + if (!updated) { + // clone + resultData = { ...currentData }; + } + + if (fieldInfo.relation) { + // deal with "connect" + assignForeignKeyFields(fieldInfo, resultData, value); + } else { + resultData[key] = clone(value); + } + resultData.$optimistic = true; + updated = true; + + if (logging) { + console.log(`Optimistic update for ${queryModel}:`, resultData); + } + } + + return updated ? resultData : undefined; +} + +function upsertMutate( + queryModel: string, + currentData: any, + model: string, + args: { where: object; create: any; update: any }, + schema: SchemaDef, + logging: boolean, +) { + let updated = false; + let resultData = currentData; + + if (Array.isArray(resultData)) { + // check if we should create or update + const foundIndex = resultData.findIndex((x) => idFieldsMatch(model, x, args.where, schema)); + if (foundIndex >= 0) { + const updateResult = updateMutate( + queryModel, + resultData[foundIndex], + model, + { where: args.where, data: args.update }, + schema, + logging, + ); + if (updateResult) { + // replace the found item with updated item + resultData = [...resultData.slice(0, foundIndex), updateResult, ...resultData.slice(foundIndex + 1)]; + updated = true; + } + } else { + const createResult = createMutate(queryModel, resultData, args.create, schema, logging); + if (createResult) { + resultData = createResult; + updated = true; + } + } + } else { + // try update only + const updateResult = updateMutate( + queryModel, + resultData, + model, + { where: args.where, data: args.update }, + schema, + logging, + ); + if (updateResult) { + resultData = updateResult; + updated = true; + } + } + + return updated ? resultData : undefined; +} + +function deleteMutate( + queryModel: string, + currentData: any, + mutateModel: string, + mutateArgs: any, + schema: SchemaDef, + logging: boolean, +) { + // TODO: handle mutation of nested reads? + + if (!currentData || !mutateArgs) { + return undefined; + } + + if (queryModel !== mutateModel) { + return undefined; + } + + let updated = false; + let result = currentData; + + if (Array.isArray(currentData)) { + for (const item of currentData) { + if (idFieldsMatch(mutateModel, item, mutateArgs, schema)) { + result = (result as unknown[]).filter((x) => x !== item); + updated = true; + if (logging) { + console.log(`Optimistic delete for ${queryModel}:`, item); + } + } + } + } else { + if (idFieldsMatch(mutateModel, currentData, mutateArgs, schema)) { + result = null; + updated = true; + if (logging) { + console.log(`Optimistic delete for ${queryModel}:`, currentData); + } + } + } + + return updated ? result : undefined; +} + +function idFieldsMatch(model: string, x: any, y: any, schema: SchemaDef) { + if (!x || !y || typeof x !== 'object' || typeof y !== 'object') { + return false; + } + const idFields = getIdFields(schema, model); + if (idFields.length === 0) { + return false; + } + return idFields.every((f) => x[f.name] === y[f.name]); +} + +function assignForeignKeyFields(field: FieldDef, resultData: any, mutationData: any) { + // convert "connect" like `{ connect: { id: '...' } }` to foreign key fields + // assignment: `{ userId: '...' }` + if (!mutationData?.connect) { + return; + } + + if (!field.relation?.fields || !field.relation.references) { + return; + } + + for (const [idField, fkField] of zip(field.relation.references, field.relation.fields)) { + if (idField in mutationData.connect) { + resultData[fkField] = mutationData.connect[idField]; + } + } +} + +function getIdFields(schema: SchemaDef, model: string) { + return (schema.models[model]?.idFields ?? []).map((f) => schema.models[model]!.fields[f]!); +} diff --git a/packages/clients/tanstack-query/src/utils/nested-read-visitor.ts b/packages/clients/tanstack-query/src/utils/nested-read-visitor.ts new file mode 100644 index 00000000..1a4323ea --- /dev/null +++ b/packages/clients/tanstack-query/src/utils/nested-read-visitor.ts @@ -0,0 +1,61 @@ +import type { FieldDef, SchemaDef } from '@zenstackhq/schema'; + +export type NestedReadVisitorCallback = { + field?: ( + model: string, + field: FieldDef | undefined, + kind: 'include' | 'select' | undefined, + args: unknown, + ) => void | boolean; +}; + +/** + * Visitor for nested read payload. + */ +export class NestedReadVisitor { + constructor( + private readonly schema: SchemaDef, + private readonly callback: NestedReadVisitorCallback, + ) {} + + doVisit(model: string, field: FieldDef | undefined, kind: 'include' | 'select' | undefined, args: unknown) { + if (this.callback.field) { + const r = this.callback.field(model, field, kind, args); + if (r === false) { + return; + } + } + + if (!args || typeof args !== 'object') { + return; + } + + let selectInclude: any; + let nextKind: 'select' | 'include' | undefined; + if ((args as any).select) { + selectInclude = (args as any).select; + nextKind = 'select'; + } else if ((args as any).include) { + selectInclude = (args as any).include; + nextKind = 'include'; + } + + if (selectInclude && typeof selectInclude === 'object') { + for (const [k, v] of Object.entries(selectInclude)) { + if (k === '_count' && typeof v === 'object' && v) { + // recurse into { _count: { ... } } + this.doVisit(model, field, kind, v); + } else { + const field = this.schema.models[model]?.fields[k]; + if (field) { + this.doVisit(field.type, field, nextKind, v); + } + } + } + } + } + + visit(model: string, args: unknown) { + this.doVisit(model, undefined, undefined, args); + } +} diff --git a/packages/clients/tanstack-query/src/utils/nested-write-visitor.ts b/packages/clients/tanstack-query/src/utils/nested-write-visitor.ts new file mode 100644 index 00000000..06e89b7e --- /dev/null +++ b/packages/clients/tanstack-query/src/utils/nested-write-visitor.ts @@ -0,0 +1,359 @@ +import { enumerate } from '@zenstackhq/common-helpers'; +import type { FieldDef, SchemaDef } from '@zenstackhq/schema'; +import { ORMWriteActions, type MaybePromise, type ORMWriteActionType } from './types'; + +type NestingPathItem = { field?: FieldDef; model: string; where: any; unique: boolean }; + +/** + * Context for visiting + */ +export type NestedWriteVisitorContext = { + /** + * Parent data, can be used to replace fields + */ + parent: any; + + /** + * Current field, undefined if toplevel + */ + field?: FieldDef; + + /** + * A top-down path of all nested update conditions and corresponding field till now + */ + nestingPath: NestingPathItem[]; +}; + +/** + * NestedWriteVisitor's callback actions. A call back function should return true or void to indicate + * that the visitor should continue traversing its children, or false to stop. It can also return an object + * to let the visitor traverse it instead of its original children. + */ +export type NestedWriterVisitorCallback = { + create?: (model: string, data: any, context: NestedWriteVisitorContext) => MaybePromise; + + createMany?: ( + model: string, + args: { data: any; skipDuplicates?: boolean }, + context: NestedWriteVisitorContext, + ) => MaybePromise; + + connectOrCreate?: ( + model: string, + args: { where: object; create: any }, + context: NestedWriteVisitorContext, + ) => MaybePromise; + + connect?: ( + model: string, + args: object, + context: NestedWriteVisitorContext, + ) => MaybePromise; + + disconnect?: ( + model: string, + args: object, + context: NestedWriteVisitorContext, + ) => MaybePromise; + + set?: (model: string, args: object, context: NestedWriteVisitorContext) => MaybePromise; + + update?: (model: string, args: object, context: NestedWriteVisitorContext) => MaybePromise; + + updateMany?: ( + model: string, + args: { where?: object; data: any }, + context: NestedWriteVisitorContext, + ) => MaybePromise; + + upsert?: ( + model: string, + args: { where: object; create: any; update: any }, + context: NestedWriteVisitorContext, + ) => MaybePromise; + + delete?: ( + model: string, + args: object | boolean, + context: NestedWriteVisitorContext, + ) => MaybePromise; + + deleteMany?: ( + model: string, + args: any | object, + context: NestedWriteVisitorContext, + ) => MaybePromise; + + field?: ( + field: FieldDef, + action: ORMWriteActionType, + data: any, + context: NestedWriteVisitorContext, + ) => MaybePromise; +}; + +/** + * Recursive visitor for nested write (create/update) payload. + */ +export class NestedWriteVisitor { + constructor( + private readonly schema: SchemaDef, + private readonly callback: NestedWriterVisitorCallback, + ) {} + + private isWriteAction(value: string): value is ORMWriteActionType { + return ORMWriteActions.includes(value as ORMWriteActionType); + } + + /** + * Start visiting + * + * @see NestedWriterVisitorCallback + */ + async visit(model: string, action: ORMWriteActionType, args: any): Promise { + if (!args) { + return; + } + + let topData = args; + + switch (action) { + // create has its data wrapped in 'data' field + case 'create': + topData = topData.data; + break; + + case 'delete': + case 'deleteMany': + topData = topData.where; + break; + } + + await this.doVisit(model, action, topData, undefined, undefined, []); + } + + private async doVisit( + model: string, + action: ORMWriteActionType, + data: any, + parent: any, + field: FieldDef | undefined, + nestingPath: NestingPathItem[], + ): Promise { + if (!data) { + return; + } + + const toplevel = field == undefined; + + const context = { parent, field, nestingPath: [...nestingPath] }; + const pushNewContext = (field: FieldDef | undefined, model: string, where: any, unique = false) => { + return { ...context, nestingPath: [...context.nestingPath, { field, model, where, unique }] }; + }; + + // visit payload + switch (action) { + case 'create': + for (const item of this.enumerateReverse(data)) { + const newContext = pushNewContext(field, model, {}); + let callbackResult: any; + if (this.callback.create) { + callbackResult = await this.callback.create(model, item, newContext); + } + if (callbackResult !== false) { + const subPayload = typeof callbackResult === 'object' ? callbackResult : item; + await this.visitSubPayload(model, action, subPayload, newContext.nestingPath); + } + } + break; + + case 'createMany': + case 'createManyAndReturn': + { + const newContext = pushNewContext(field, model, {}); + let callbackResult: any; + if (this.callback.createMany) { + callbackResult = await this.callback.createMany(model, data, newContext); + } + if (callbackResult !== false) { + const subPayload = typeof callbackResult === 'object' ? callbackResult : data.data; + await this.visitSubPayload(model, action, subPayload, newContext.nestingPath); + } + } + break; + + case 'connectOrCreate': + for (const item of this.enumerateReverse(data)) { + const newContext = pushNewContext(field, model, item.where); + let callbackResult: any; + if (this.callback.connectOrCreate) { + callbackResult = await this.callback.connectOrCreate(model, item, newContext); + } + if (callbackResult !== false) { + const subPayload = typeof callbackResult === 'object' ? callbackResult : item.create; + await this.visitSubPayload(model, action, subPayload, newContext.nestingPath); + } + } + break; + + case 'connect': + if (this.callback.connect) { + for (const item of this.enumerateReverse(data)) { + const newContext = pushNewContext(field, model, item, true); + await this.callback.connect(model, item, newContext); + } + } + break; + + case 'disconnect': + // disconnect has two forms: + // if relation is to-many, the payload is a unique filter object + // if relation is to-one, the payload can only be boolean `true` + if (this.callback.disconnect) { + for (const item of this.enumerateReverse(data)) { + const newContext = pushNewContext(field, model, item, typeof item === 'object'); + await this.callback.disconnect(model, item, newContext); + } + } + break; + + case 'set': + if (this.callback.set) { + for (const item of this.enumerateReverse(data)) { + const newContext = pushNewContext(field, model, item, true); + await this.callback.set(model, item, newContext); + } + } + break; + + case 'update': + for (const item of this.enumerateReverse(data)) { + const newContext = pushNewContext(field, model, item.where); + let callbackResult: any; + if (this.callback.update) { + callbackResult = await this.callback.update(model, item, newContext); + } + if (callbackResult !== false) { + const subPayload = + typeof callbackResult === 'object' + ? callbackResult + : typeof item.data === 'object' + ? item.data + : item; + await this.visitSubPayload(model, action, subPayload, newContext.nestingPath); + } + } + break; + + case 'updateMany': + case 'updateManyAndReturn': + for (const item of this.enumerateReverse(data)) { + const newContext = pushNewContext(field, model, item.where); + let callbackResult: any; + if (this.callback.updateMany) { + callbackResult = await this.callback.updateMany(model, item, newContext); + } + if (callbackResult !== false) { + const subPayload = typeof callbackResult === 'object' ? callbackResult : item; + await this.visitSubPayload(model, action, subPayload, newContext.nestingPath); + } + } + break; + + case 'upsert': { + for (const item of this.enumerateReverse(data)) { + const newContext = pushNewContext(field, model, item.where); + let callbackResult: any; + if (this.callback.upsert) { + callbackResult = await this.callback.upsert(model, item, newContext); + } + if (callbackResult !== false) { + if (typeof callbackResult === 'object') { + await this.visitSubPayload(model, action, callbackResult, newContext.nestingPath); + } else { + await this.visitSubPayload(model, action, item.create, newContext.nestingPath); + await this.visitSubPayload(model, action, item.update, newContext.nestingPath); + } + } + } + break; + } + + case 'delete': { + if (this.callback.delete) { + for (const item of this.enumerateReverse(data)) { + const newContext = pushNewContext(field, model, toplevel ? item.where : item); + await this.callback.delete(model, item, newContext); + } + } + break; + } + + case 'deleteMany': + if (this.callback.deleteMany) { + for (const item of this.enumerateReverse(data)) { + const newContext = pushNewContext(field, model, toplevel ? item.where : item); + await this.callback.deleteMany(model, item, newContext); + } + } + break; + + default: { + throw new Error(`unhandled action type ${action}`); + } + } + } + + private async visitSubPayload( + model: string, + action: ORMWriteActionType, + payload: any, + nestingPath: NestingPathItem[], + ) { + for (const item of enumerate(payload)) { + if (!item || typeof item !== 'object') { + continue; + } + for (const field of Object.keys(item)) { + const fieldDef = this.schema.models[model]?.fields[field]; + if (!fieldDef) { + continue; + } + + if (fieldDef.relation) { + if (item[field]) { + // recurse into nested payloads + for (const [subAction, subData] of Object.entries(item[field])) { + if (this.isWriteAction(subAction) && subData) { + await this.doVisit(fieldDef.type, subAction, subData, item[field], fieldDef, [ + ...nestingPath, + ]); + } + } + } + } else { + // visit plain field + if (this.callback.field) { + await this.callback.field(fieldDef, action, item[field], { + parent: item, + nestingPath, + field: fieldDef, + }); + } + } + } + } + } + + // enumerate a (possible) array in reverse order, so that the enumeration + // callback can safely delete the current item + private *enumerateReverse(data: any) { + if (Array.isArray(data)) { + for (let i = data.length - 1; i >= 0; i--) { + yield data[i]; + } + } else { + yield data; + } + } +} diff --git a/packages/clients/tanstack-query/src/utils/query-analysis.ts b/packages/clients/tanstack-query/src/utils/query-analysis.ts new file mode 100644 index 00000000..ccc2af90 --- /dev/null +++ b/packages/clients/tanstack-query/src/utils/query-analysis.ts @@ -0,0 +1,116 @@ +import type { SchemaDef } from '@zenstackhq/schema'; +import { NestedReadVisitor } from './nested-read-visitor'; +import { NestedWriteVisitor } from './nested-write-visitor'; +import type { ORMWriteActionType } from './types'; + +/** + * Gets models read (including nested ones) given a query args. + * @param model + * @param targetModels + * @param schema + * @param args + * @returns + */ +export function getReadModels(model: string, schema: SchemaDef, args: any) { + const result = new Set(); + result.add(model); + const visitor = new NestedReadVisitor(schema, { + field: (model) => { + result.add(model); + return true; + }, + }); + visitor.visit(model, args); + return [...result]; +} + +/** + * Gets mutated models (including nested ones) given a mutation args. + */ +export async function getMutatedModels( + model: string, + operation: ORMWriteActionType, + mutationArgs: any, + schema: SchemaDef, +) { + const result = new Set(); + result.add(model); + + if (mutationArgs) { + const addModel = (model: string) => void result.add(model); + + // add models that are cascaded deleted recursively + const addCascades = (model: string) => { + const cascades = new Set(); + const visited = new Set(); + collectDeleteCascades(model, schema, cascades, visited); + cascades.forEach((m) => addModel(m)); + }; + + const visitor = new NestedWriteVisitor(schema, { + create: addModel, + createMany: addModel, + connectOrCreate: addModel, + connect: addModel, + disconnect: addModel, + set: addModel, + update: addModel, + updateMany: addModel, + upsert: addModel, + delete: (model) => { + addModel(model); + addCascades(model); + }, + deleteMany: (model) => { + addModel(model); + addCascades(model); + }, + }); + await visitor.visit(model, operation, mutationArgs); + } + + // include delegate base models recursively + result.forEach((m) => { + getBaseRecursively(m, schema, result); + }); + + return [...result]; +} + +function collectDeleteCascades(model: string, schema: SchemaDef, result: Set, visited: Set) { + if (visited.has(model)) { + // break circle + return; + } + visited.add(model); + + const modelDef = schema.models[model]; + if (!modelDef) { + return; + } + + for (const [modelName, modelDef] of Object.entries(schema.models)) { + if (!modelDef) { + continue; + } + for (const fieldDef of Object.values(modelDef.fields)) { + if (fieldDef.relation?.onDelete === 'Cascade' && fieldDef.type === model) { + if (!result.has(modelName)) { + result.add(modelName); + } + collectDeleteCascades(modelName, schema, result, visited); + } + } + } +} + +function getBaseRecursively(model: string, schema: SchemaDef, result: Set) { + const modelDef = schema.models[model]; + if (!modelDef) { + return; + } + if (modelDef.baseModel) { + result.add(modelDef.baseModel); + getBaseRecursively(modelDef.baseModel, schema, result); + } +} diff --git a/packages/clients/tanstack-query/src/utils/serialization.ts b/packages/clients/tanstack-query/src/utils/serialization.ts new file mode 100644 index 00000000..4df15555 --- /dev/null +++ b/packages/clients/tanstack-query/src/utils/serialization.ts @@ -0,0 +1,39 @@ +import { Buffer } from 'buffer'; +import Decimal from 'decimal.js'; +import SuperJSON from 'superjson'; + +SuperJSON.registerCustom( + { + isApplicable: (v): v is Decimal => + v instanceof Decimal || + // interop with decimal.js + v?.toStringTag === '[object Decimal]', + serialize: (v) => v.toJSON(), + deserialize: (v) => new Decimal(v), + }, + 'Decimal' +); + +SuperJSON.registerCustom( + { + isApplicable: (v): v is Buffer => Buffer.isBuffer(v), + serialize: (v) => v.toString('base64'), + deserialize: (v) => Buffer.from(v, 'base64'), + }, + 'Bytes' +); + +/** + * Serialize the given value with superjson + */ +export function serialize(value: unknown): { data: unknown; meta: unknown } { + const { json, meta } = SuperJSON.serialize(value); + return { data: json, meta }; +} + +/** + * Deserialize the given value with superjson using the given metadata + */ +export function deserialize(value: unknown, meta: any): unknown { + return SuperJSON.deserialize({ json: value as any, meta }); +} diff --git a/packages/clients/tanstack-query/src/utils/types.ts b/packages/clients/tanstack-query/src/utils/types.ts new file mode 100644 index 00000000..1ebd2d25 --- /dev/null +++ b/packages/clients/tanstack-query/src/utils/types.ts @@ -0,0 +1,19 @@ +export type MaybePromise = T | Promise | PromiseLike; + +export const ORMWriteActions = [ + 'create', + 'createMany', + 'createManyAndReturn', + 'connectOrCreate', + 'update', + 'updateMany', + 'updateManyAndReturn', + 'upsert', + 'connect', + 'disconnect', + 'set', + 'delete', + 'deleteMany', +] as const; + +export type ORMWriteActionType = (typeof ORMWriteActions)[number]; diff --git a/packages/clients/tanstack-query/test/react-query.test.tsx b/packages/clients/tanstack-query/test/react-query.test.tsx new file mode 100644 index 00000000..fef6a62a --- /dev/null +++ b/packages/clients/tanstack-query/test/react-query.test.tsx @@ -0,0 +1,1715 @@ +/** + * @vitest-environment happy-dom + */ + +import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query'; +import { act, cleanup, renderHook, waitFor } from '@testing-library/react'; +import nock from 'nock'; +import React from 'react'; +import { afterEach, describe, expect, it } from 'vitest'; +import { QuerySettingsProvider, useClientQueries } from '../src/react'; +import { getQueryKey } from '../src/utils/common'; +import { schema } from './schemas/basic/schema'; + +const BASE_URL = 'http://localhost'; + +describe('React Query Test', () => { + function createWrapper() { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + experimental_prefetchInRender: true, + }, + }, + }); + const Provider = QuerySettingsProvider; + const wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ); + return { queryClient, wrapper }; + } + + function makeUrl(model: string, operation: string, args?: unknown) { + let r = `${BASE_URL}/api/model/${model}/${operation}`; + if (args) { + r += `?q=${encodeURIComponent(JSON.stringify(args))}`; + } + return r; + } + + afterEach(() => { + nock.cleanAll(); + cleanup(); + }); + + it('works with simple query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const queryArgs = { where: { id: '1' } }; + const data = { id: '1', name: 'foo' }; + + nock(makeUrl('User', 'findUnique', queryArgs)) + .get(/.*/) + .reply(200, { + data, + }); + + const { result } = renderHook(() => useClientQueries(schema).user.useFindUnique(queryArgs), { + wrapper, + }); + + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + expect(result.current.data).toMatchObject(data); + const cacheData = queryClient.getQueryData(getQueryKey('User', 'findUnique', queryArgs)); + expect(cacheData).toMatchObject(data); + }); + }); + + it('infinite query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const queryArgs = { where: { id: '1' } }; + const data = [{ id: '1', name: 'foo' }]; + + nock(makeUrl('User', 'findMany', queryArgs)) + .get(/.*/) + .reply(200, () => ({ + data, + })); + + const { result } = renderHook( + () => + useClientQueries(schema).user.useInfiniteFindMany(queryArgs, { + getNextPageParam: () => null, + }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + const resultData = result.current.data!; + expect(resultData.pages).toHaveLength(1); + expect(resultData.pages[0]).toMatchObject(data); + expect(resultData?.pageParams).toHaveLength(1); + expect(resultData?.pageParams[0]).toMatchObject(queryArgs); + expect(result.current.hasNextPage).toBe(false); + const cacheData: any = queryClient.getQueryData( + getQueryKey('User', 'findMany', queryArgs, { infinite: true, optimisticUpdate: false }), + ); + expect(cacheData.pages[0]).toMatchObject(data); + }); + }); + + it('independent mutation and query', async () => { + const { wrapper } = createWrapper(); + + const queryArgs = { where: { id: '1' } }; + const data = { id: '1', name: 'foo' }; + + let queryCount = 0; + nock(makeUrl('User', 'findUnique', queryArgs)) + .get(/.*/) + .reply(200, () => { + queryCount++; + return { data }; + }) + .persist(); + + const { result } = renderHook(() => useClientQueries(schema).user.useFindUnique(queryArgs), { + wrapper, + }); + await waitFor(() => { + expect(result.current.data).toMatchObject({ name: 'foo' }); + }); + + nock(makeUrl('Post', 'create')) + .post(/.*/) + .reply(200, () => ({ + data: { id: '1', title: 'post1' }, + })); + + const { result: mutationResult } = renderHook(() => useClientQueries(schema).post.useCreate(), { + wrapper, + }); + + act(() => mutationResult.current.mutate({ data: { title: 'post1' } })); + + await waitFor(() => { + // no refetch caused by invalidation + expect(queryCount).toBe(1); + }); + }); + + it('create and invalidation', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any[] = []; + + nock(makeUrl('User', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook(() => useClientQueries(schema).user.useFindMany(), { + wrapper, + }); + await waitFor(() => { + expect(result.current.data).toHaveLength(0); + }); + + nock(makeUrl('User', 'create')) + .post(/.*/) + .reply(200, () => { + data.push({ id: '1', email: 'foo' }); + return { data: data[0] }; + }); + + const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useCreate(), { + wrapper, + }); + + act(() => mutationResult.current.mutate({ data: { email: 'foo' } })); + + await waitFor(() => { + const cacheData = queryClient.getQueryData(getQueryKey('User', 'findMany', undefined)); + expect(cacheData).toHaveLength(1); + }); + }); + + it('create and no invalidation', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any[] = []; + + nock(makeUrl('User', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook(() => useClientQueries(schema).user.useFindMany(), { + wrapper, + }); + await waitFor(() => { + expect(result.current.data).toHaveLength(0); + }); + + nock(makeUrl('User', 'create')) + .post(/.*/) + .reply(200, () => { + data.push({ id: '1', email: 'foo' }); + return { data: data[0] }; + }); + + const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useCreate(), { + wrapper, + }); + + act(() => mutationResult.current.mutate({ data: { email: 'foo' } })); + + await waitFor(() => { + const cacheData = queryClient.getQueryData(getQueryKey('User', 'findMany', undefined)); + expect(cacheData).toHaveLength(0); + }); + }); + + it('optimistic create single', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any[] = []; + + nock(makeUrl('User', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toHaveLength(0); + }); + + nock(makeUrl('User', 'create')) + .post(/.*/) + .reply(200, () => ({ + data: null, + })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useCreate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ data: { email: 'foo' } })); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toHaveLength(1); + expect(cacheData[0].$optimistic).toBe(true); + expect(cacheData[0].id).toBeTruthy(); + expect(cacheData[0].email).toBe('foo'); + }); + }); + + it('optimistic create updating nested query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any[] = [{ id: '1', name: 'user1', posts: [] }]; + + nock(makeUrl('User', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => + useClientQueries(schema).user.useFindMany( + { + include: { posts: true }, + }, + { optimisticUpdate: true }, + ), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toHaveLength(1); + }); + + nock(makeUrl('Post', 'create')) + .post(/.*/) + .reply(200, () => ({ + data: null, + })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).post.useCreate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ data: { title: 'post1', owner: { connect: { id: '1' } } } })); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey( + 'User', + 'findMany', + { include: { posts: true } }, + { infinite: false, optimisticUpdate: true }, + ), + ); + const posts = cacheData[0].posts; + expect(posts).toHaveLength(1); + expect(posts[0]).toMatchObject({ $optimistic: true, id: expect.any(String), title: 'post1', ownerId: '1' }); + }); + }); + + it('optimistic create updating deeply nested query', async () => { + const { queryClient, wrapper } = createWrapper(); + + // populate the cache with a user + + const userData: any[] = [{ id: '1', email: 'user1', posts: [] }]; + + nock(BASE_URL) + .get('/api/model/user/findMany') + .query(true) + .reply(200, () => ({ data: userData })) + .persist(); + + const { result: userResult } = renderHook( + () => + useClientQueries(schema).user.useFindMany( + { + include: { + posts: { + include: { + category: true, + }, + }, + }, + }, + { optimisticUpdate: true }, + ), + { + wrapper, + }, + ); + await waitFor(() => { + expect(userResult.current.data).toHaveLength(1); + }); + + // populate the cache with a category + const categoryData: any[] = [{ id: '1', name: 'category1', posts: [] }]; + + nock(BASE_URL) + .get('/api/model/category/findMany') + .query(true) + .reply(200, () => ({ data: categoryData })) + .persist(); + + const { result: categoryResult } = renderHook( + () => + useClientQueries(schema).category.useFindMany( + { + include: { + posts: true, + }, + }, + { optimisticUpdate: true }, + ), + { + wrapper, + }, + ); + await waitFor(() => { + expect(categoryResult.current.data).toHaveLength(1); + }); + + // create a post and connect it to the category + nock(BASE_URL) + .post('/api/model/post/create') + .reply(200, () => ({ + data: null, + })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).post.useCreate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => + mutationResult.current.mutate({ + data: { title: 'post1', owner: { connect: { id: '1' } }, category: { connect: { id: '1' } } }, + }), + ); + + // assert that the post was created and connected to the category + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey( + 'Category', + 'findMany', + { + include: { + posts: true, + }, + }, + { infinite: false, optimisticUpdate: true }, + ), + ); + const posts = cacheData[0].posts; + expect(posts).toHaveLength(1); + expect(posts[0]).toMatchObject({ + $optimistic: true, + id: expect.any(String), + title: 'post1', + ownerId: '1', + }); + }); + + // assert that the post was created and connected to the user, and included the category + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey( + 'User', + 'findMany', + { + include: { + posts: { + include: { + category: true, + }, + }, + }, + }, + { infinite: false, optimisticUpdate: true }, + ), + ); + const posts = cacheData[0].posts; + expect(posts).toHaveLength(1); + expect(posts[0]).toMatchObject({ + $optimistic: true, + id: expect.any(String), + title: 'post1', + ownerId: '1', + categoryId: '1', + // TODO: should this include the category object and not just the foreign key? + // category: { $optimistic: true, id: '1', name: 'category1' }, + }); + }); + }); + + it('optimistic update with optional one-to-many relationship', async () => { + const { queryClient, wrapper } = createWrapper(); + + // populate the cache with a post, with an optional category relationship + const postData: any = { + id: '1', + title: 'post1', + ownerId: '1', + categoryId: null, + category: null, + }; + + const data: any[] = [postData]; + + nock(makeUrl('Post', 'findMany')) + .get(/.*/) + .query(true) + .reply(200, () => ({ + data, + })) + .persist(); + + const { result: postResult } = renderHook( + () => + useClientQueries(schema).post.useFindMany( + { + include: { + category: true, + }, + }, + { optimisticUpdate: true }, + ), + { + wrapper, + }, + ); + await waitFor(() => { + expect(postResult.current.data).toHaveLength(1); + }); + + // mock a put request to update the post title + nock(makeUrl('Post', 'update')) + .put(/.*/) + .reply(200, () => { + postData.title = 'postA'; + return { data: postData }; + }); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).post.useUpdate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ where: { id: '1' }, data: { title: 'postA' } })); + + // assert that the post was updated despite the optional (null) category relationship + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey( + 'Post', + 'findMany', + { + include: { + category: true, + }, + }, + { infinite: false, optimisticUpdate: true }, + ), + ); + const posts = cacheData; + expect(posts).toHaveLength(1); + expect(posts[0]).toMatchObject({ + $optimistic: true, + id: expect.any(String), + title: 'postA', + ownerId: '1', + categoryId: null, + category: null, + }); + }); + }); + + it('optimistic update with nested optional one-to-many relationship', async () => { + const { queryClient, wrapper } = createWrapper(); + + // populate the cache with a user and a post, with an optional category + const postData: any = { + id: '1', + title: 'post1', + ownerId: '1', + categoryId: null, + category: null, + }; + + const userData: any[] = [{ id: '1', name: 'user1', posts: [postData] }]; + + nock(BASE_URL) + .get('/api/model/user/findMany') + .query(true) + .reply(200, () => { + return { data: userData }; + }) + .persist(); + + const { result: userResult } = renderHook( + () => + useClientQueries(schema).user.useFindMany( + { + include: { + posts: { + include: { + category: true, + }, + }, + }, + }, + { optimisticUpdate: true }, + ), + { + wrapper, + }, + ); + await waitFor(() => { + expect(userResult.current.data).toHaveLength(1); + }); + + // mock a put request to update the post title + nock(BASE_URL) + .put('/api/model/post/update') + .reply(200, () => { + postData.title = 'postA'; + return { data: postData }; + }); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).post.useUpdate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ where: { id: '1' }, data: { title: 'postA' } })); + + // assert that the post was updated + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey( + 'User', + 'findMany', + { + include: { + posts: { + include: { + category: true, + }, + }, + }, + }, + { infinite: false, optimisticUpdate: true }, + ), + ); + const posts = cacheData[0].posts; + expect(posts).toHaveLength(1); + expect(posts[0]).toMatchObject({ + $optimistic: true, + id: expect.any(String), + title: 'postA', + ownerId: '1', + categoryId: null, + category: null, + }); + }); + }); + + it('optimistic nested create updating query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any[] = []; + + nock(makeUrl('Post', 'findMany')) + .get(/.*/) + .reply(200, () => ({ + data, + })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).post.useFindMany(undefined, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toHaveLength(0); + }); + + nock(makeUrl('User', 'create')) + .post(/.*/) + .reply(200, () => ({ + data: null, + })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useCreate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ data: { email: 'user1', posts: { create: { title: 'post1' } } } })); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('Post', 'findMany', undefined, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toHaveLength(1); + expect(cacheData[0].$optimistic).toBe(true); + expect(cacheData[0].id).toBeTruthy(); + expect(cacheData[0].title).toBe('post1'); + }); + }); + + it('optimistic create many', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any[] = []; + + nock(makeUrl('User', 'findMany')) + .get(/.*/) + .reply(200, () => ({ + data, + })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toHaveLength(0); + }); + + nock(makeUrl('User', 'createMany')) + .post(/.*/) + .reply(200, () => ({ + data: null, + })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useCreateMany({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ data: [{ email: 'foo' }, { email: 'bar' }] })); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toHaveLength(2); + }); + }); + + it('update and invalidation', async () => { + const { queryClient, wrapper } = createWrapper(); + + const queryArgs = { where: { id: '1' } }; + const data = { id: '1', name: 'foo' }; + + nock(makeUrl('User', 'findUnique', queryArgs)) + .get(/.*/) + .reply(200, () => ({ + data, + })) + .persist(); + + const { result } = renderHook(() => useClientQueries(schema).user.useFindUnique(queryArgs), { + wrapper, + }); + await waitFor(() => { + expect(result.current.data).toMatchObject({ name: 'foo' }); + }); + + nock(makeUrl('User', 'update')) + .put(/.*/) + .reply(200, () => { + data.name = 'bar'; + return data; + }); + + const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useUpdate(), { + wrapper, + }); + + act(() => mutationResult.current.mutate({ ...queryArgs, data: { name: 'bar' } })); + + await waitFor(() => { + const cacheData = queryClient.getQueryData(getQueryKey('User', 'findUnique', queryArgs)); + expect(cacheData).toMatchObject({ name: 'bar' }); + }); + }); + + it('update and no invalidation', async () => { + const { queryClient, wrapper } = createWrapper(); + + const queryArgs = { where: { id: '1' } }; + const data = { id: '1', name: 'foo' }; + + nock(makeUrl('User', 'findUnique', queryArgs)) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook(() => useClientQueries(schema).user.useFindUnique(queryArgs), { + wrapper, + }); + await waitFor(() => { + expect(result.current.data).toMatchObject({ name: 'foo' }); + }); + + nock(makeUrl('User', 'update')) + .put(/.*/) + .reply(200, () => { + data.name = 'bar'; + return data; + }); + + const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useUpdate(), { + wrapper, + }); + + act(() => mutationResult.current.mutate({ ...queryArgs, data: { name: 'bar' } })); + + await waitFor(() => { + const cacheData = queryClient.getQueryData(getQueryKey('User', 'findUnique', queryArgs)); + expect(cacheData).toMatchObject({ name: 'foo' }); + }); + }); + + it('optimistic update simple', async () => { + const { queryClient, wrapper } = createWrapper(); + + const queryArgs = { where: { id: '1' } }; + const data = { id: '1', name: 'foo' }; + + nock(makeUrl('User', 'findUnique', queryArgs)) + .get(/.*/) + .reply(200, () => ({ + data, + })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).user.useFindUnique(queryArgs, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toMatchObject({ name: 'foo' }); + }); + + nock(makeUrl('User', 'update')) + .put(/.*/) + .reply(200, () => data); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useUpdate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ ...queryArgs, data: { name: 'bar' } })); + + await waitFor(() => { + const cacheData = queryClient.getQueryData( + getQueryKey('User', 'findUnique', queryArgs, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toMatchObject({ name: 'bar', $optimistic: true }); + }); + }); + + it('optimistic update updating nested query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const queryArgs = { where: { id: '1' }, include: { posts: true } }; + const data = { id: '1', name: 'foo', posts: [{ id: 'p1', title: 'post1' }] }; + + nock(makeUrl('User', 'findUnique', queryArgs)) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).user.useFindUnique(queryArgs, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toMatchObject({ name: 'foo' }); + }); + + nock(makeUrl('Post', 'update')) + .put(/.*/) + .reply(200, () => data); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).post.useUpdate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => + mutationResult.current.mutate({ + where: { id: 'p1' }, + data: { title: 'post2', owner: { connect: { id: '2' } } }, + }), + ); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('User', 'findUnique', queryArgs, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData.posts[0]).toMatchObject({ title: 'post2', $optimistic: true, ownerId: '2' }); + }); + }); + + it('optimistic nested update updating query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const queryArgs = { where: { id: 'p1' } }; + const data = { id: 'p1', title: 'post1' }; + + nock(makeUrl('Post', 'findUnique', queryArgs)) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).post.useFindUnique(queryArgs, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toMatchObject({ title: 'post1' }); + }); + + nock(makeUrl('User', 'update')) + .put(/.*/) + .reply(200, () => data); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useUpdate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => + mutationResult.current.mutate({ + where: { id: '1' }, + data: { posts: { update: { where: { id: 'p1' }, data: { title: 'post2' } } } }, + }), + ); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('Post', 'findUnique', queryArgs, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toMatchObject({ title: 'post2', $optimistic: true }); + }); + }); + + it('optimistic upsert - create simple', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any[] = []; + + nock(makeUrl('User', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toHaveLength(0); + }); + + nock(makeUrl('User', 'upsert')) + .post(/.*/) + .reply(200, () => ({ data: null })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useUpsert({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => + mutationResult.current.mutate({ + where: { id: '1' }, + create: { id: '1', email: 'foo' }, + update: { email: 'bar' }, + }), + ); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toHaveLength(1); + expect(cacheData[0]).toMatchObject({ id: '1', email: 'foo', $optimistic: true }); + }); + }); + + it('optimistic upsert - create updating nested query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any = { id: '1', name: 'user1', posts: [{ id: 'p1', title: 'post1' }] }; + + nock(makeUrl('User', 'findUnique')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).user.useFindUnique({ where: { id: '1' } }, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toMatchObject({ id: '1' }); + }); + + nock(makeUrl('Post', 'upsert')) + .post(/.*/) + .reply(200, () => ({ data: null })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).post.useUpsert({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => + mutationResult.current.mutate({ + where: { id: 'p2' }, + create: { id: 'p2', title: 'post2', owner: { connect: { id: '1' } } }, + update: { title: 'post3' }, + }), + ); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('User', 'findUnique', { where: { id: '1' } }, { infinite: false, optimisticUpdate: true }), + ); + const posts = cacheData.posts; + expect(posts).toHaveLength(2); + expect(posts[0]).toMatchObject({ id: 'p2', title: 'post2', ownerId: '1', $optimistic: true }); + }); + }); + + it('optimistic upsert - nested create updating query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any = [{ id: 'p1', title: 'post1' }]; + + nock(makeUrl('Post', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).post.useFindMany(undefined, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toHaveLength(1); + }); + + nock(makeUrl('User', 'update')) + .post(/.*/) + .reply(200, () => ({ data: null })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useUpdate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => + mutationResult.current.mutate({ + where: { id: '1' }, + data: { + posts: { + upsert: { + where: { id: 'p2' }, + create: { id: 'p2', title: 'post2' }, + update: { title: 'post3' }, + }, + }, + }, + }), + ); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('Post', 'findMany', undefined, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toHaveLength(2); + expect(cacheData[0]).toMatchObject({ id: 'p2', title: 'post2', $optimistic: true }); + }); + }); + + it('optimistic upsert - update simple', async () => { + const { queryClient, wrapper } = createWrapper(); + + const queryArgs = { where: { id: '1' } }; + const data = { id: '1', name: 'foo' }; + + nock(makeUrl('User', 'findUnique', queryArgs)) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).user.useFindUnique(queryArgs, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toMatchObject({ name: 'foo' }); + }); + + nock(makeUrl('User', 'upsert')) + .post(/.*/) + .reply(200, () => data); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useUpsert({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ ...queryArgs, update: { email: 'bar' }, create: { email: 'zee' } })); + + await waitFor(() => { + const cacheData = queryClient.getQueryData( + getQueryKey('User', 'findUnique', queryArgs, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toMatchObject({ email: 'bar', $optimistic: true }); + }); + }); + + it('optimistic upsert - update updating nested query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any = { id: '1', name: 'user1', posts: [{ id: 'p1', title: 'post1' }] }; + + nock(makeUrl('User', 'findUnique')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).user.useFindUnique({ where: { id: '1' } }, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toMatchObject({ id: '1' }); + }); + + nock(makeUrl('Post', 'upsert')) + .post(/.*/) + .reply(200, () => ({ data: null })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).post.useUpsert({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => + mutationResult.current.mutate({ + where: { id: 'p1' }, + create: { id: 'p1', title: 'post1' }, + update: { title: 'post2' }, + }), + ); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('User', 'findUnique', { where: { id: '1' } }, { infinite: false, optimisticUpdate: true }), + ); + const posts = cacheData.posts; + expect(posts).toHaveLength(1); + expect(posts[0]).toMatchObject({ id: 'p1', title: 'post2', $optimistic: true }); + }); + }); + + it('optimistic upsert - nested update updating query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any = [{ id: 'p1', title: 'post1' }]; + + nock(makeUrl('Post', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).post.useFindMany(undefined, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toHaveLength(1); + }); + + nock(makeUrl('User', 'update')) + .post(/.*/) + .reply(200, () => ({ data: null })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useUpdate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => + mutationResult.current.mutate({ + where: { id: '1' }, + data: { + posts: { + upsert: { + where: { id: 'p1' }, + create: { id: 'p1', title: 'post1' }, + update: { title: 'post2' }, + }, + }, + }, + }), + ); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('Post', 'findMany', undefined, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toHaveLength(1); + expect(cacheData[0]).toMatchObject({ id: 'p1', title: 'post2', $optimistic: true }); + }); + }); + + it('delete and invalidation', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any[] = [{ id: '1', name: 'foo' }]; + + nock(makeUrl('User', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook(() => useClientQueries(schema).user.useFindMany(), { + wrapper, + }); + await waitFor(() => { + expect(result.current.data).toHaveLength(1); + }); + + nock(makeUrl('User', 'delete')) + .delete(/.*/) + .reply(200, () => { + data.splice(0, 1); + return { data: [] }; + }); + + const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useDelete(), { + wrapper, + }); + + act(() => mutationResult.current.mutate({ where: { id: '1' } })); + + await waitFor(() => { + const cacheData = queryClient.getQueryData(getQueryKey('User', 'findMany', undefined)); + expect(cacheData).toHaveLength(0); + }); + }); + + it('optimistic delete simple', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any[] = [{ id: '1', name: 'foo' }]; + + nock(makeUrl('User', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toHaveLength(1); + }); + + nock(makeUrl('User', 'delete')) + .delete(/.*/) + .reply(200, () => ({ data })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useDelete({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ where: { id: '1' } })); + + await waitFor(() => { + const cacheData = queryClient.getQueryData( + getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toHaveLength(0); + }); + }); + + it('optimistic delete nested query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any = { id: '1', name: 'foo', posts: [{ id: 'p1', title: 'post1' }] }; + + nock(makeUrl('User', 'findFirst')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => + useClientQueries(schema).user.useFindFirst( + { + include: { posts: true }, + }, + { optimisticUpdate: true }, + ), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toMatchObject({ id: '1' }); + }); + + nock(makeUrl('Post', 'delete')) + .delete(/.*/) + .reply(200, () => ({ data })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).post.useDelete({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ where: { id: 'p1' } })); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey( + 'User', + 'findFirst', + { include: { posts: true } }, + { infinite: false, optimisticUpdate: true }, + ), + ); + expect(cacheData.posts).toHaveLength(0); + }); + }); + + it('optimistic nested delete update query', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any = [ + { id: 'p1', title: 'post1' }, + { id: 'p2', title: 'post2' }, + ]; + + nock(makeUrl('Post', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).post.useFindMany(undefined, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toHaveLength(2); + }); + + nock(makeUrl('User', 'update')) + .delete(/.*/) + .reply(200, () => ({ data })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useUpdate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ where: { id: '1' }, data: { posts: { delete: { id: 'p1' } } } })); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('Post', 'findMany', undefined, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toHaveLength(1); + }); + }); + + it('top-level mutation and nested-read invalidation', async () => { + const { queryClient, wrapper } = createWrapper(); + + const queryArgs = { where: { id: '1' }, include: { posts: true } }; + const data = { posts: [{ id: '1', title: 'post1' }] }; + + nock(makeUrl('User', 'findUnique', queryArgs)) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook(() => useClientQueries(schema).user.useFindUnique(queryArgs), { + wrapper, + }); + await waitFor(() => { + expect(result.current.data).toMatchObject(data); + }); + + nock(makeUrl('Post', 'update')) + .put(/.*/) + .reply(200, () => { + data.posts[0].title = 'post2'; + return data; + }); + + const { result: mutationResult } = renderHook(() => useClientQueries(schema).post.useUpdate(), { + wrapper, + }); + + act(() => mutationResult.current.mutate({ where: { id: '1' }, data: { title: 'post2' } })); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData(getQueryKey('User', 'findUnique', queryArgs)); + expect(cacheData.posts[0].title).toBe('post2'); + }); + }); + + it('nested mutation and top-level-read invalidation', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data = [{ id: '1', title: 'post1', ownerId: '1' }]; + + nock(makeUrl('Post', 'findMany')) + .get(/.*/) + .reply(200, () => ({ + data, + })) + .persist(); + + const { result } = renderHook(() => useClientQueries(schema).post.useFindMany(), { + wrapper, + }); + await waitFor(() => { + expect(result.current.data).toMatchObject(data); + }); + + nock(makeUrl('User', 'update')) + .put(/.*/) + .reply(200, () => { + data.push({ id: '2', title: 'post2', ownerId: '1' }); + return data; + }); + + const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useUpdate(), { + wrapper, + }); + + act(() => + mutationResult.current.mutate({ where: { id: '1' }, data: { posts: { create: { title: 'post2' } } } }), + ); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData(getQueryKey('Post', 'findMany', undefined)); + expect(cacheData).toHaveLength(2); + }); + }); + + it('optimistic create with custom provider', async () => { + const { queryClient, wrapper } = createWrapper(); + + const data: any[] = []; + + nock(makeUrl('User', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toHaveLength(0); + }); + + nock(makeUrl('User', 'create')) + .post(/.*/) + .reply(200, () => ({ data: null })) + .persist(); + + const { result: mutationResult1 } = renderHook( + () => + useClientQueries(schema).user.useCreate({ + optimisticUpdate: true, + invalidateQueries: false, + optimisticDataProvider: ({ queryModel, queryOperation }) => { + if (queryModel === 'User' && queryOperation === 'findMany') { + return { kind: 'Skip' }; + } else { + return { kind: 'ProceedDefault' }; + } + }, + }), + { + wrapper, + }, + ); + + act(() => mutationResult1.current.mutate({ data: { email: 'foo' } })); + + // cache should not update + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toHaveLength(0); + }); + + const { result: mutationResult2 } = renderHook( + () => + useClientQueries(schema).user.useCreate({ + optimisticUpdate: true, + invalidateQueries: false, + optimisticDataProvider: ({ queryModel, queryOperation, currentData, mutationArgs }) => { + if (queryModel === 'User' && queryOperation === 'findMany') { + return { + kind: 'Update', + data: [ + ...currentData, + { id: 100, email: mutationArgs.data.email + 'hooray', $optimistic: true }, + ], + }; + } else { + return { kind: 'ProceedDefault' }; + } + }, + }), + { + wrapper, + }, + ); + + act(() => mutationResult2.current.mutate({ data: { email: 'foo' } })); + + // cache should update + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toHaveLength(1); + expect(cacheData[0].$optimistic).toBe(true); + expect(cacheData[0].id).toBeTruthy(); + expect(cacheData[0].email).toBe('foohooray'); + }); + }); + + it('optimistic update mixed with non-zenstack queries', async () => { + const { queryClient, wrapper } = createWrapper(); + + // non-zenstack query + const { result: myQueryResult } = renderHook( + () => useQuery({ queryKey: ['myQuery'], queryFn: () => ({ data: 'myData' }) }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(myQueryResult.current.data).toEqual({ data: 'myData' }); + }); + + const data: any[] = []; + + nock(makeUrl('User', 'findMany')) + .get(/.*/) + .reply(200, () => ({ data })) + .persist(); + + const { result } = renderHook( + () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }), + { + wrapper, + }, + ); + await waitFor(() => { + expect(result.current.data).toHaveLength(0); + }); + + nock(makeUrl('User', 'create')) + .post(/.*/) + .reply(200, () => ({ data: null })); + + const { result: mutationResult } = renderHook( + () => + useClientQueries(schema).user.useCreate({ + optimisticUpdate: true, + invalidateQueries: false, + }), + { + wrapper, + }, + ); + + act(() => mutationResult.current.mutate({ data: { email: 'foo' } })); + + await waitFor(() => { + const cacheData: any = queryClient.getQueryData( + getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }), + ); + expect(cacheData).toHaveLength(1); + expect(cacheData[0].$optimistic).toBe(true); + expect(cacheData[0].id).toBeTruthy(); + expect(cacheData[0].email).toBe('foo'); + }); + }); +}); diff --git a/packages/clients/tanstack-query/test/schemas/basic/input.ts b/packages/clients/tanstack-query/test/schemas/basic/input.ts new file mode 100644 index 00000000..ad01c7b9 --- /dev/null +++ b/packages/clients/tanstack-query/test/schemas/basic/input.ts @@ -0,0 +1,70 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT MODIFY THIS FILE // +// This file is automatically generated by ZenStack CLI and should not be manually updated. // +////////////////////////////////////////////////////////////////////////////////////////////// + +/* eslint-disable */ + +import { type SchemaType as $Schema } from "./schema"; +import type { FindManyArgs as $FindManyArgs, FindUniqueArgs as $FindUniqueArgs, FindFirstArgs as $FindFirstArgs, CreateArgs as $CreateArgs, CreateManyArgs as $CreateManyArgs, CreateManyAndReturnArgs as $CreateManyAndReturnArgs, UpdateArgs as $UpdateArgs, UpdateManyArgs as $UpdateManyArgs, UpdateManyAndReturnArgs as $UpdateManyAndReturnArgs, UpsertArgs as $UpsertArgs, DeleteArgs as $DeleteArgs, DeleteManyArgs as $DeleteManyArgs, CountArgs as $CountArgs, AggregateArgs as $AggregateArgs, GroupByArgs as $GroupByArgs, WhereInput as $WhereInput, SelectInput as $SelectInput, IncludeInput as $IncludeInput, OmitInput as $OmitInput } from "@zenstackhq/orm"; +import type { SimplifiedModelResult as $SimplifiedModelResult, SelectIncludeOmit as $SelectIncludeOmit } from "@zenstackhq/orm"; +export type UserFindManyArgs = $FindManyArgs<$Schema, "User">; +export type UserFindUniqueArgs = $FindUniqueArgs<$Schema, "User">; +export type UserFindFirstArgs = $FindFirstArgs<$Schema, "User">; +export type UserCreateArgs = $CreateArgs<$Schema, "User">; +export type UserCreateManyArgs = $CreateManyArgs<$Schema, "User">; +export type UserCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "User">; +export type UserUpdateArgs = $UpdateArgs<$Schema, "User">; +export type UserUpdateManyArgs = $UpdateManyArgs<$Schema, "User">; +export type UserUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "User">; +export type UserUpsertArgs = $UpsertArgs<$Schema, "User">; +export type UserDeleteArgs = $DeleteArgs<$Schema, "User">; +export type UserDeleteManyArgs = $DeleteManyArgs<$Schema, "User">; +export type UserCountArgs = $CountArgs<$Schema, "User">; +export type UserAggregateArgs = $AggregateArgs<$Schema, "User">; +export type UserGroupByArgs = $GroupByArgs<$Schema, "User">; +export type UserWhereInput = $WhereInput<$Schema, "User">; +export type UserSelect = $SelectInput<$Schema, "User">; +export type UserInclude = $IncludeInput<$Schema, "User">; +export type UserOmit = $OmitInput<$Schema, "User">; +export type UserGetPayload> = $SimplifiedModelResult<$Schema, "User", Args>; +export type PostFindManyArgs = $FindManyArgs<$Schema, "Post">; +export type PostFindUniqueArgs = $FindUniqueArgs<$Schema, "Post">; +export type PostFindFirstArgs = $FindFirstArgs<$Schema, "Post">; +export type PostCreateArgs = $CreateArgs<$Schema, "Post">; +export type PostCreateManyArgs = $CreateManyArgs<$Schema, "Post">; +export type PostCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "Post">; +export type PostUpdateArgs = $UpdateArgs<$Schema, "Post">; +export type PostUpdateManyArgs = $UpdateManyArgs<$Schema, "Post">; +export type PostUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "Post">; +export type PostUpsertArgs = $UpsertArgs<$Schema, "Post">; +export type PostDeleteArgs = $DeleteArgs<$Schema, "Post">; +export type PostDeleteManyArgs = $DeleteManyArgs<$Schema, "Post">; +export type PostCountArgs = $CountArgs<$Schema, "Post">; +export type PostAggregateArgs = $AggregateArgs<$Schema, "Post">; +export type PostGroupByArgs = $GroupByArgs<$Schema, "Post">; +export type PostWhereInput = $WhereInput<$Schema, "Post">; +export type PostSelect = $SelectInput<$Schema, "Post">; +export type PostInclude = $IncludeInput<$Schema, "Post">; +export type PostOmit = $OmitInput<$Schema, "Post">; +export type PostGetPayload> = $SimplifiedModelResult<$Schema, "Post", Args>; +export type CategoryFindManyArgs = $FindManyArgs<$Schema, "Category">; +export type CategoryFindUniqueArgs = $FindUniqueArgs<$Schema, "Category">; +export type CategoryFindFirstArgs = $FindFirstArgs<$Schema, "Category">; +export type CategoryCreateArgs = $CreateArgs<$Schema, "Category">; +export type CategoryCreateManyArgs = $CreateManyArgs<$Schema, "Category">; +export type CategoryCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "Category">; +export type CategoryUpdateArgs = $UpdateArgs<$Schema, "Category">; +export type CategoryUpdateManyArgs = $UpdateManyArgs<$Schema, "Category">; +export type CategoryUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "Category">; +export type CategoryUpsertArgs = $UpsertArgs<$Schema, "Category">; +export type CategoryDeleteArgs = $DeleteArgs<$Schema, "Category">; +export type CategoryDeleteManyArgs = $DeleteManyArgs<$Schema, "Category">; +export type CategoryCountArgs = $CountArgs<$Schema, "Category">; +export type CategoryAggregateArgs = $AggregateArgs<$Schema, "Category">; +export type CategoryGroupByArgs = $GroupByArgs<$Schema, "Category">; +export type CategoryWhereInput = $WhereInput<$Schema, "Category">; +export type CategorySelect = $SelectInput<$Schema, "Category">; +export type CategoryInclude = $IncludeInput<$Schema, "Category">; +export type CategoryOmit = $OmitInput<$Schema, "Category">; +export type CategoryGetPayload> = $SimplifiedModelResult<$Schema, "Category", Args>; diff --git a/packages/clients/tanstack-query/test/schemas/basic/models.ts b/packages/clients/tanstack-query/test/schemas/basic/models.ts new file mode 100644 index 00000000..7a4b7eb4 --- /dev/null +++ b/packages/clients/tanstack-query/test/schemas/basic/models.ts @@ -0,0 +1,12 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT MODIFY THIS FILE // +// This file is automatically generated by ZenStack CLI and should not be manually updated. // +////////////////////////////////////////////////////////////////////////////////////////////// + +/* eslint-disable */ + +import { type SchemaType as $Schema } from "./schema"; +import { type ModelResult as $ModelResult } from "@zenstackhq/orm"; +export type User = $ModelResult<$Schema, "User">; +export type Post = $ModelResult<$Schema, "Post">; +export type Category = $ModelResult<$Schema, "Category">; diff --git a/packages/clients/tanstack-query/test/schemas/basic/schema.ts b/packages/clients/tanstack-query/test/schemas/basic/schema.ts new file mode 100644 index 00000000..b56d0b5e --- /dev/null +++ b/packages/clients/tanstack-query/test/schemas/basic/schema.ts @@ -0,0 +1,131 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT MODIFY THIS FILE // +// This file is automatically generated by ZenStack CLI and should not be manually updated. // +////////////////////////////////////////////////////////////////////////////////////////////// + +/* eslint-disable */ + +import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; +export const schema = { + provider: { + type: "sqlite" + }, + models: { + User: { + name: "User", + fields: { + id: { + name: "id", + type: "String", + id: true, + attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }], + default: ExpressionUtils.call("cuid") + }, + email: { + name: "email", + type: "String", + unique: true, + attributes: [{ name: "@unique" }] + }, + name: { + name: "name", + type: "String", + optional: true + }, + posts: { + name: "posts", + type: "Post", + array: true, + relation: { opposite: "owner" } + } + }, + idFields: ["id"], + uniqueFields: { + id: { type: "String" }, + email: { type: "String" } + } + }, + Post: { + name: "Post", + fields: { + id: { + name: "id", + type: "String", + id: true, + attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }], + default: ExpressionUtils.call("cuid") + }, + title: { + name: "title", + type: "String" + }, + owner: { + name: "owner", + type: "User", + optional: true, + attributes: [{ name: "@relation", args: [{ name: "fields", value: ExpressionUtils.array([ExpressionUtils.field("ownerId")]) }, { name: "references", value: ExpressionUtils.array([ExpressionUtils.field("id")]) }] }], + relation: { opposite: "posts", fields: ["ownerId"], references: ["id"] } + }, + ownerId: { + name: "ownerId", + type: "String", + optional: true, + foreignKeyFor: [ + "owner" + ] + }, + category: { + name: "category", + type: "Category", + optional: true, + attributes: [{ name: "@relation", args: [{ name: "fields", value: ExpressionUtils.array([ExpressionUtils.field("categoryId")]) }, { name: "references", value: ExpressionUtils.array([ExpressionUtils.field("id")]) }] }], + relation: { opposite: "posts", fields: ["categoryId"], references: ["id"] } + }, + categoryId: { + name: "categoryId", + type: "String", + optional: true, + foreignKeyFor: [ + "category" + ] + } + }, + idFields: ["id"], + uniqueFields: { + id: { type: "String" } + } + }, + Category: { + name: "Category", + fields: { + id: { + name: "id", + type: "String", + id: true, + attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }], + default: ExpressionUtils.call("cuid") + }, + name: { + name: "name", + type: "String", + unique: true, + attributes: [{ name: "@unique" }] + }, + posts: { + name: "posts", + type: "Post", + array: true, + relation: { opposite: "category" } + } + }, + idFields: ["id"], + uniqueFields: { + id: { type: "String" }, + name: { type: "String" } + } + } + }, + authType: "User", + plugins: {} +} as const satisfies SchemaDef; +export type SchemaType = typeof schema; diff --git a/packages/clients/tanstack-query/test/schemas/basic/schema.zmodel b/packages/clients/tanstack-query/test/schemas/basic/schema.zmodel new file mode 100644 index 00000000..039051df --- /dev/null +++ b/packages/clients/tanstack-query/test/schemas/basic/schema.zmodel @@ -0,0 +1,25 @@ +datasource db { + provider = 'sqlite' +} + +model User { + id String @id @default(cuid()) + email String @unique + name String? + posts Post[] +} + +model Post { + id String @id @default(cuid()) + title String + owner User? @relation(fields: [ownerId], references: [id]) + ownerId String? + category Category? @relation(fields: [categoryId], references: [id]) + categoryId String? +} + +model Category { + id String @id @default(cuid()) + name String @unique + posts Post[] +} \ No newline at end of file diff --git a/packages/clients/tanstack-query/tsconfig.json b/packages/clients/tanstack-query/tsconfig.json new file mode 100644 index 00000000..53cf6cf5 --- /dev/null +++ b/packages/clients/tanstack-query/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@zenstackhq/typescript-config/base.json", + "include": ["src/**/*.ts", "test/**/*.ts"], + "compilerOptions": { + "lib": ["ESNext"] + } +} diff --git a/packages/tanstack-query/tsup.config.ts b/packages/clients/tanstack-query/tsup.config.ts similarity index 100% rename from packages/tanstack-query/tsup.config.ts rename to packages/clients/tanstack-query/tsup.config.ts diff --git a/packages/clients/tanstack-query/vitest.config.ts b/packages/clients/tanstack-query/vitest.config.ts new file mode 100644 index 00000000..221fe580 --- /dev/null +++ b/packages/clients/tanstack-query/vitest.config.ts @@ -0,0 +1,11 @@ +import base from '@zenstackhq/vitest-config/base'; +import { defineConfig, mergeConfig } from 'vitest/config'; + +export default mergeConfig( + base, + defineConfig({ + test: { + include: ['test/**/*.test.ts', 'test/**/*.test.tsx'], + }, + }), +); diff --git a/packages/orm/package.json b/packages/orm/package.json index 50892908..4ec117f0 100644 --- a/packages/orm/package.json +++ b/packages/orm/package.json @@ -89,7 +89,7 @@ } }, "devDependencies": { - "@types/better-sqlite3": "^7.6.13", + "@types/better-sqlite3": "catalog:", "@types/pg": "^8.0.0", "@types/toposort": "^2.0.7", "@zenstackhq/eslint-config": "workspace:*", diff --git a/packages/plugins/policy/package.json b/packages/plugins/policy/package.json index efc13147..d64edb13 100644 --- a/packages/plugins/policy/package.json +++ b/packages/plugins/policy/package.json @@ -45,7 +45,7 @@ "kysely": "catalog:" }, "devDependencies": { - "@types/better-sqlite3": "^7.6.13", + "@types/better-sqlite3": "catalog:", "@types/pg": "^8.0.0", "@zenstackhq/eslint-config": "workspace:*", "@zenstackhq/typescript-config": "workspace:*", diff --git a/packages/sdk/src/model-utils.ts b/packages/sdk/src/model-utils.ts index 198e59ac..c9102c22 100644 --- a/packages/sdk/src/model-utils.ts +++ b/packages/sdk/src/model-utils.ts @@ -27,7 +27,7 @@ export function isIdField(field: DataField, contextModel: DataModel) { } // NOTE: we have to use name to match fields because the fields - // may be inherited from an abstract base and have cloned identities + // may be inherited from a base and have different identities // model-level @@id attribute with a list of fields const modelLevelIds = getModelIdFields(contextModel); @@ -37,7 +37,7 @@ export function isIdField(field: DataField, contextModel: DataModel) { const allFields = getAllFields(contextModel); if (allFields.some((f) => hasAttribute(f, '@id')) || modelLevelIds.length > 0) { - // the model already has id field, don't check @unique and @@unique + // the model already has `@id` or `@@id` field, don't further check unique fields return false; } diff --git a/packages/server/package.json b/packages/server/package.json index 81b708d2..2cc18ed1 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -146,7 +146,7 @@ "fastify-plugin": "^5.1.0", "h3": "^1.15.4", "hono": "^4.6.3", - "next": "^15.0.0", + "next": "catalog:", "nuxt": "^4.2.0", "supertest": "^7.1.4", "zod": "^4.1.0" @@ -158,7 +158,7 @@ "fastify": "^5.0.0", "fastify-plugin": "^5.0.0", "hono": "^4.6.0", - "next": "^15.0.0", + "next": "^15.0.0 || ^16.0.0", "nuxt": "^4.0.0", "zod": "catalog:" }, diff --git a/packages/tanstack-query/package.json b/packages/tanstack-query/package.json deleted file mode 100644 index d87affb3..00000000 --- a/packages/tanstack-query/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "@zenstackhq/tanstack-query", - "version": "3.0.0-beta.15", - "description": "", - "main": "index.js", - "type": "module", - "private": true, - "scripts": { - "build": "tsc --noEmit && tsup-node", - "lint": "eslint src --ext ts" - }, - "keywords": [], - "author": "", - "license": "MIT", - "exports": { - "./react": { - "import": { - "types": "./dist/react.d.ts", - "default": "./dist/react.js" - }, - "require": { - "types": "./dist/react.d.cts", - "default": "./dist/react.cjs" - } - } - }, - "dependencies": { - "@zenstackhq/orm": "workspace:*" - }, - "devDependencies": { - "@zenstackhq/eslint-config": "workspace:*", - "@zenstackhq/typescript-config": "workspace:*" - }, - "peerDependencies": { - "@tanstack/react-query": "^5.0.0" - }, - "peerDependenciesMeta": { - "@tanstack/react-query": { - "optional": true - } - } -} diff --git a/packages/tanstack-query/src/react.ts b/packages/tanstack-query/src/react.ts deleted file mode 100644 index 9c36163c..00000000 --- a/packages/tanstack-query/src/react.ts +++ /dev/null @@ -1,78 +0,0 @@ -import type { - DefaultError, - UseMutationOptions, - UseMutationResult, - UseQueryOptions, - UseQueryResult, -} from '@tanstack/react-query'; -import type { CreateArgs, FindArgs, ModelResult, SelectSubset } from '@zenstackhq/orm'; -import type { GetModels, SchemaDef } from '@zenstackhq/orm/schema'; - -export type toHooks = { - [Model in GetModels as Uncapitalize]: ToModelHooks; -}; - -type ToModelHooks> = { - findMany>( - args?: SelectSubset>, - options?: Omit[]>, 'queryKey'>, - ): UseQueryResult[]>; - - findFirst>( - args?: SelectSubset>, - options?: Omit[]>, 'queryKey'>, - ): UseQueryResult | null>; - - create>( - options?: UseMutationOptions, DefaultError, T>, - ): UseMutationResult, DefaultError, T>; -}; - -function uncapitalize(s: string) { - return s.charAt(0).toLowerCase() + s.slice(1); -} - -export function toHooks(schema: Schema): toHooks { - return Object.entries(schema.models).reduce( - (acc, [model, _]) => - Object.assign(acc, { - [uncapitalize(model)]: toModelHooks(schema, model as GetModels), - }), - {} as toHooks, - ); -} - -function toModelHooks>(schema: Schema, model: Model): any { - const modelDef = schema.models[model]; - if (!modelDef) { - throw new Error(`Model ${model} not found in schema`); - } - - return { - findMany: () => { - return { - data: [], - isLoading: false, - isError: false, - }; - }, - - findFirst: () => { - return { - data: null, - isLoading: false, - isError: false, - }; - }, - - create: () => { - return { - mutate: async () => { - return null; - }, - isLoading: false, - isError: false, - }; - }, - }; -} diff --git a/packages/tanstack-query/tsconfig.json b/packages/tanstack-query/tsconfig.json deleted file mode 100644 index e7ce31be..00000000 --- a/packages/tanstack-query/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "@zenstackhq/typescript-config/base.json", - "include": ["src/**/*.ts", "test/**/*.ts"] -} diff --git a/packages/testtools/package.json b/packages/testtools/package.json index 02f1f6b5..1b9ffcd1 100644 --- a/packages/testtools/package.json +++ b/packages/testtools/package.json @@ -48,7 +48,7 @@ "pg": "catalog:" }, "devDependencies": { - "@types/better-sqlite3": "^7.6.13", + "@types/better-sqlite3": "catalog:", "@types/node": "catalog:", "@types/tmp": "catalog:", "@types/pg": "^8.11.11", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1267adc4..fb54f39b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,45 +6,18 @@ settings: catalogs: default: - '@types/node': - specifier: ^20.17.24 - version: 20.17.24 - '@types/tmp': - specifier: ^0.2.6 - version: 0.2.6 - better-sqlite3: - specifier: ^12.2.0 - version: 12.2.0 + '@tanstack/react-query': + specifier: 5.90.6 + version: 5.90.6 + '@types/react': + specifier: 19.2.0 + version: 19.2.0 decimal.js: specifier: ^10.4.3 version: 10.4.3 - kysely: - specifier: ^0.27.6 - version: 0.27.6 - langium: - specifier: 3.5.0 - version: 3.5.0 - langium-cli: - specifier: 3.5.0 - version: 3.5.0 - pg: - specifier: ^8.13.1 - version: 8.16.3 - prisma: - specifier: ^6.10.0 - version: 6.14.0 - tmp: - specifier: ^0.2.3 - version: 0.2.3 - ts-pattern: - specifier: ^5.7.1 - version: 5.7.1 - typescript: - specifier: ^5.8.0 - version: 5.8.3 - zod-validation-error: - specifier: ^4.0.1 - version: 4.0.1 + react: + specifier: 19.2.0 + version: 19.2.0 importers: @@ -65,6 +38,9 @@ importers: prettier: specifier: ^3.5.3 version: 3.5.3 + prisma: + specifier: 'catalog:' + version: 6.14.0(magicast@0.3.5)(typescript@5.8.3) tsup: specifier: ^8.5.0 version: 8.5.0(@swc/core@1.12.5)(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0) @@ -82,7 +58,7 @@ importers: version: 8.34.1(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) + version: 3.2.4(@types/node@20.17.24)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) yaml: specifier: ^2.8.0 version: 2.8.0 @@ -127,7 +103,7 @@ importers: version: 5.7.1 devDependencies: '@types/better-sqlite3': - specifier: ^7.6.13 + specifier: 'catalog:' version: 7.6.13 '@types/semver': specifier: ^7.7.0 @@ -157,6 +133,61 @@ importers: specifier: 'catalog:' version: 0.2.3 + packages/clients/tanstack-query: + dependencies: + '@zenstackhq/common-helpers': + specifier: workspace:* + version: link:../../common-helpers + '@zenstackhq/orm': + specifier: workspace:* + version: link:../../orm + '@zenstackhq/schema': + specifier: workspace:* + version: link:../../schema + decimal.js: + specifier: 'catalog:' + version: 10.4.3 + superjson: + specifier: ^2.2.3 + version: 2.2.3 + devDependencies: + '@tanstack/react-query': + specifier: 'catalog:' + version: 5.90.6(react@19.2.0) + '@testing-library/dom': + specifier: ^10.4.1 + version: 10.4.1 + '@testing-library/react': + specifier: ^16.3.0 + version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.0(@types/react@19.2.0))(@types/react@19.2.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@types/react': + specifier: 'catalog:' + version: 19.2.0 + '@zenstackhq/eslint-config': + specifier: workspace:* + version: link:../../config/eslint-config + '@zenstackhq/language': + specifier: workspace:* + version: link:../../language + '@zenstackhq/sdk': + specifier: workspace:* + version: link:../../sdk + '@zenstackhq/typescript-config': + specifier: workspace:* + version: link:../../config/typescript-config + '@zenstackhq/vitest-config': + specifier: workspace:* + version: link:../../config/vitest-config + happy-dom: + specifier: ^20.0.10 + version: 20.0.10 + nock: + specifier: ^14.0.10 + version: 14.0.10 + react: + specifier: 'catalog:' + version: 19.2.0 + packages/common-helpers: devDependencies: '@zenstackhq/eslint-config': @@ -323,7 +354,7 @@ importers: version: 4.0.1(zod@4.1.12) devDependencies: '@types/better-sqlite3': - specifier: ^7.6.13 + specifier: 'catalog:' version: 7.6.13 '@types/pg': specifier: ^8.0.0 @@ -363,7 +394,7 @@ importers: version: 5.7.1 devDependencies: '@types/better-sqlite3': - specifier: ^7.6.13 + specifier: 'catalog:' version: 7.6.13 '@types/pg': specifier: ^8.0.0 @@ -451,7 +482,7 @@ importers: devDependencies: '@sveltejs/kit': specifier: ^2.48.3 - version: 2.48.3(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + version: 2.48.3(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) '@types/body-parser': specifier: ^1.19.6 version: 1.19.6 @@ -495,11 +526,11 @@ importers: specifier: ^4.6.3 version: 4.10.3 next: - specifier: ^15.0.0 - version: 15.5.6(@babel/core@7.28.5)(react-dom@19.2.0(react@19.1.0))(react@19.1.0) + specifier: 'catalog:' + version: 16.0.1(@babel/core@7.28.5)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) nuxt: specifier: ^4.2.0 - version: 4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1) + version: 4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1) supertest: specifier: ^7.1.4 version: 7.1.4 @@ -507,22 +538,6 @@ importers: specifier: ^4.1.0 version: 4.1.12 - packages/tanstack-query: - dependencies: - '@tanstack/react-query': - specifier: ^5.0.0 - version: 5.81.0(react@19.1.0) - '@zenstackhq/orm': - specifier: workspace:* - version: link:../orm - devDependencies: - '@zenstackhq/eslint-config': - specifier: workspace:* - version: link:../config/eslint-config - '@zenstackhq/typescript-config': - specifier: workspace:* - version: link:../config/typescript-config - packages/testtools: dependencies: '@zenstackhq/common-helpers': @@ -566,7 +581,7 @@ importers: version: 5.7.1 devDependencies: '@types/better-sqlite3': - specifier: ^7.6.13 + specifier: 'catalog:' version: 7.6.13 '@types/node': specifier: 'catalog:' @@ -606,7 +621,71 @@ importers: specifier: ^4.1.0 version: 4.1.12 - samples/blog: + samples/next.js: + dependencies: + '@tanstack/react-query': + specifier: 'catalog:' + version: 5.90.6(react@19.2.0) + '@zenstackhq/orm': + specifier: workspace:* + version: link:../../packages/orm + '@zenstackhq/server': + specifier: workspace:* + version: link:../../packages/server + '@zenstackhq/tanstack-query': + specifier: workspace:* + version: link:../../packages/clients/tanstack-query + better-sqlite3: + specifier: 'catalog:' + version: 12.2.0 + kysely: + specifier: 'catalog:' + version: 0.27.6 + lorem-ipsum: + specifier: ^2.0.8 + version: 2.0.8 + next: + specifier: 16.0.1 + version: 16.0.1(@babel/core@7.28.5)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + react: + specifier: 'catalog:' + version: 19.2.0 + react-dom: + specifier: 'catalog:' + version: 19.2.0(react@19.2.0) + devDependencies: + '@tailwindcss/postcss': + specifier: ^4 + version: 4.1.16 + '@types/better-sqlite3': + specifier: 'catalog:' + version: 7.6.13 + '@types/node': + specifier: ^20 + version: 20.17.24 + '@types/react': + specifier: 'catalog:' + version: 19.2.0 + '@types/react-dom': + specifier: 'catalog:' + version: 19.2.0(@types/react@19.2.0) + '@zenstackhq/cli': + specifier: workspace:* + version: link:../../packages/cli + eslint: + specifier: ^9 + version: 9.29.0(jiti@2.6.1) + eslint-config-next: + specifier: 16.0.1 + version: 16.0.1(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) + tailwindcss: + specifier: ^4 + version: 4.1.16 + typescript: + specifier: ^5 + version: 5.8.3 + + samples/orm: dependencies: '@zenstackhq/orm': specifier: workspace:* @@ -615,14 +694,14 @@ importers: specifier: workspace:* version: link:../../packages/plugins/policy better-sqlite3: - specifier: ^12.2.0 + specifier: 'catalog:' version: 12.2.0 kysely: specifier: 'catalog:' version: 0.27.6 devDependencies: '@types/better-sqlite3': - specifier: ^7.6.13 + specifier: 'catalog:' version: 7.6.13 '@zenstackhq/cli': specifier: workspace:* @@ -716,6 +795,22 @@ importers: packages: + '@acemir/cssom@0.9.19': + resolution: {integrity: sha512-Pp2gAQXPZ2o7lt4j0IMwNRXqQ3pagxtDj5wctL5U2Lz4oV0ocDNlkgx4DpxfyKav4S/bePuI+SMqcBSUHLy9kg==} + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@asamuzakjp/css-color@4.0.5': + resolution: {integrity: sha512-lMrXidNhPGsDjytDy11Vwlb6OIGrT3CmLg3VWNFyWkLWtijKl7xjvForlh8vuj0SHGjgl4qZEQzUmYTeQA2JFQ==} + + '@asamuzakjp/dom-selector@6.7.4': + resolution: {integrity: sha512-buQDjkm+wDPXd6c13534URWZqbz0RP5PAhXZ+LIoa5LgwInT9HVJvGIJivg75vi8I13CxDGdTnz+aY5YUJlIAA==} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -821,6 +916,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/runtime@7.28.4': + resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} + engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} @@ -855,6 +954,38 @@ packages: resolution: {integrity: sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==} engines: {node: '>=18.0.0'} + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-syntax-patches-for-csstree@1.0.15': + resolution: {integrity: sha512-q0p6zkVq2lJnmzZVPR33doA51G7YOja+FBvRdp5ISIthL0MtFCgYHHhR563z9WFGxcOn0WfjSkPDJ5Qig3H3Sw==} + engines: {node: '>=18'} + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + '@dxup/nuxt@0.2.0': resolution: {integrity: sha512-tUS2040HEiGwjwZ8hTczfuRoiXSOuA+ATPXO9Bllf03nHHj1lSlmaAyVJHFsSXL5Os5NZqimNAZ1iDed7VElzA==} @@ -1437,56 +1568,66 @@ packages: engines: {node: '>=18'} hasBin: true + '@mswjs/interceptors@0.39.8': + resolution: {integrity: sha512-2+BzZbjRO7Ct61k8fMNHEtoKjeWI9pIlHFTqBwZ5icHpqszIgEZbjb1MW5Z0+bITTCTl3gk4PDBxs9tA/csXvA==} + engines: {node: '>=18'} + + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + '@napi-rs/wasm-runtime@1.0.7': resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} - '@next/env@15.5.6': - resolution: {integrity: sha512-3qBGRW+sCGzgbpc5TS1a0p7eNxnOarGVQhZxfvTdnV0gFI61lX7QNtQ4V1TSREctXzYn5NetbUsLvyqwLFJM6Q==} + '@next/env@16.0.1': + resolution: {integrity: sha512-LFvlK0TG2L3fEOX77OC35KowL8D7DlFF45C0OvKMC4hy8c/md1RC4UMNDlUGJqfCoCS2VWrZ4dSE6OjaX5+8mw==} + + '@next/eslint-plugin-next@16.0.1': + resolution: {integrity: sha512-g4Cqmv/gyFEXNeVB2HkqDlYKfy+YrlM2k8AVIO/YQVEPfhVruH1VA99uT1zELLnPLIeOnx8IZ6Ddso0asfTIdw==} - '@next/swc-darwin-arm64@15.5.6': - resolution: {integrity: sha512-ES3nRz7N+L5Umz4KoGfZ4XX6gwHplwPhioVRc25+QNsDa7RtUF/z8wJcbuQ2Tffm5RZwuN2A063eapoJ1u4nPg==} + '@next/swc-darwin-arm64@16.0.1': + resolution: {integrity: sha512-R0YxRp6/4W7yG1nKbfu41bp3d96a0EalonQXiMe+1H9GTHfKxGNCGFNWUho18avRBPsO8T3RmdWuzmfurlQPbg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.5.6': - resolution: {integrity: sha512-JIGcytAyk9LQp2/nuVZPAtj8uaJ/zZhsKOASTjxDug0SPU9LAM3wy6nPU735M1OqacR4U20LHVF5v5Wnl9ptTA==} + '@next/swc-darwin-x64@16.0.1': + resolution: {integrity: sha512-kETZBocRux3xITiZtOtVoVvXyQLB7VBxN7L6EPqgI5paZiUlnsgYv4q8diTNYeHmF9EiehydOBo20lTttCbHAg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.5.6': - resolution: {integrity: sha512-qvz4SVKQ0P3/Im9zcS2RmfFL/UCQnsJKJwQSkissbngnB/12c6bZTCB0gHTexz1s6d/mD0+egPKXAIRFVS7hQg==} + '@next/swc-linux-arm64-gnu@16.0.1': + resolution: {integrity: sha512-hWg3BtsxQuSKhfe0LunJoqxjO4NEpBmKkE+P2Sroos7yB//OOX3jD5ISP2wv8QdUwtRehMdwYz6VB50mY6hqAg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.5.6': - resolution: {integrity: sha512-FsbGVw3SJz1hZlvnWD+T6GFgV9/NYDeLTNQB2MXoPN5u9VA9OEDy6fJEfePfsUKAhJufFbZLgp0cPxMuV6SV0w==} + '@next/swc-linux-arm64-musl@16.0.1': + resolution: {integrity: sha512-UPnOvYg+fjAhP3b1iQStcYPWeBFRLrugEyK/lDKGk7kLNua8t5/DvDbAEFotfV1YfcOY6bru76qN9qnjLoyHCQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.5.6': - resolution: {integrity: sha512-3QnHGFWlnvAgyxFxt2Ny8PTpXtQD7kVEeaFat5oPAHHI192WKYB+VIKZijtHLGdBBvc16tiAkPTDmQNOQ0dyrA==} + '@next/swc-linux-x64-gnu@16.0.1': + resolution: {integrity: sha512-Et81SdWkcRqAJziIgFtsFyJizHoWne4fzJkvjd6V4wEkWTB4MX6J0uByUb0peiJQ4WeAt6GGmMszE5KrXK6WKg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.5.6': - resolution: {integrity: sha512-OsGX148sL+TqMK9YFaPFPoIaJKbFJJxFzkXZljIgA9hjMjdruKht6xDCEv1HLtlLNfkx3c5w2GLKhj7veBQizQ==} + '@next/swc-linux-x64-musl@16.0.1': + resolution: {integrity: sha512-qBbgYEBRrC1egcG03FZaVfVxrJm8wBl7vr8UFKplnxNRprctdP26xEv9nJ07Ggq4y1adwa0nz2mz83CELY7N6Q==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.5.6': - resolution: {integrity: sha512-ONOMrqWxdzXDJNh2n60H6gGyKed42Ieu6UTVPZteXpuKbLZTH4G4eBMsr5qWgOBA+s7F+uB4OJbZnrkEDnZ5Fg==} + '@next/swc-win32-arm64-msvc@16.0.1': + resolution: {integrity: sha512-cPuBjYP6I699/RdbHJonb3BiRNEDm5CKEBuJ6SD8k3oLam2fDRMKAvmrli4QMDgT2ixyRJ0+DTkiODbIQhRkeQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.5.6': - resolution: {integrity: sha512-pxK4VIjFRx1MY92UycLOOw7dTdvccWsNETQ0kDHkBlcFH1GrTLUjSiHU1ohrznnux6TqRHgv5oflhfIWZwVROQ==} + '@next/swc-win32-x64-msvc@16.0.1': + resolution: {integrity: sha512-XeEUJsE4JYtfrXe/LaJn3z1pD19fK0Q6Er8Qoufi+HqvdO4LEPyCxLUt4rxA+4RfYo6S9gMlmzCMU2F+AatFqQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1507,6 +1648,10 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@nolyfill/is-core-module@1.0.39': + resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} + engines: {node: '>=12.4.0'} + '@nuxt/cli@3.29.3': resolution: {integrity: sha512-48GYmH4SyzR5pqd02UXVzBfrvEGaurPKMjSWxlHgqnpI5buwOYCvH+OqvHOmvnLrDP2bxR9hbDod/UIphOjMhg==} engines: {node: ^16.10.0 || >=18.0.0} @@ -1564,6 +1709,15 @@ packages: rolldown: optional: true + '@open-draft/deferred-promise@2.2.0': + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + + '@open-draft/logger@0.3.0': + resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} + + '@open-draft/until@2.1.0': + resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + '@oxc-minify/binding-android-arm64@0.95.0': resolution: {integrity: sha512-ck0NakTt3oBWTMQjxKf5ZW1GzCs0y1kETzJdh8h8NAWTutlMfeWiuUxCgG4FMF4XiTnCdLq/dFAKFcdbiwcoqg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2250,6 +2404,9 @@ packages: cpu: [x64] os: [win32] + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} @@ -2381,14 +2538,121 @@ packages: '@swc/types@0.1.23': resolution: {integrity: sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==} - '@tanstack/query-core@5.81.0': - resolution: {integrity: sha512-lFsd8NBhkh26vzaq8uOOM2o3r4NtJros7kASI+TTMBmKT8C43HVN/2mOI9PFX9kzmxLThBzOLa4NI8ORhX8N9g==} + '@tailwindcss/node@4.1.16': + resolution: {integrity: sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==} + + '@tailwindcss/oxide-android-arm64@4.1.16': + resolution: {integrity: sha512-8+ctzkjHgwDJ5caq9IqRSgsP70xhdhJvm+oueS/yhD5ixLhqTw9fSL1OurzMUhBwE5zK26FXLCz2f/RtkISqHA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.1.16': + resolution: {integrity: sha512-C3oZy5042v2FOALBZtY0JTDnGNdS6w7DxL/odvSny17ORUnaRKhyTse8xYi3yKGyfnTUOdavRCdmc8QqJYwFKA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.1.16': + resolution: {integrity: sha512-vjrl/1Ub9+JwU6BP0emgipGjowzYZMjbWCDqwA2Z4vCa+HBSpP4v6U2ddejcHsolsYxwL5r4bPNoamlV0xDdLg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.1.16': + resolution: {integrity: sha512-TSMpPYpQLm+aR1wW5rKuUuEruc/oOX3C7H0BTnPDn7W/eMw8W+MRMpiypKMkXZfwH8wqPIRKppuZoedTtNj2tg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16': + resolution: {integrity: sha512-p0GGfRg/w0sdsFKBjMYvvKIiKy/LNWLWgV/plR4lUgrsxFAoQBFrXkZ4C0w8IOXfslB9vHK/JGASWD2IefIpvw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.16': + resolution: {integrity: sha512-DoixyMmTNO19rwRPdqviTrG1rYzpxgyYJl8RgQvdAQUzxC1ToLRqtNJpU/ATURSKgIg6uerPw2feW0aS8SNr/w==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.1.16': + resolution: {integrity: sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.1.16': + resolution: {integrity: sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.1.16': + resolution: {integrity: sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.1.16': + resolution: {integrity: sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.16': + resolution: {integrity: sha512-zX+Q8sSkGj6HKRTMJXuPvOcP8XfYON24zJBRPlszcH1Np7xuHXhWn8qfFjIujVzvH3BHU+16jBXwgpl20i+v9A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.1.16': + resolution: {integrity: sha512-m5dDFJUEejbFqP+UXVstd4W/wnxA4F61q8SoL+mqTypId2T2ZpuxosNSgowiCnLp2+Z+rivdU0AqpfgiD7yCBg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.1.16': + resolution: {integrity: sha512-2OSv52FRuhdlgyOQqgtQHuCgXnS8nFSYRp2tJ+4WZXKgTxqPy7SMSls8c3mPT5pkZ17SBToGM5LHEJBO7miEdg==} + engines: {node: '>= 10'} + + '@tailwindcss/postcss@4.1.16': + resolution: {integrity: sha512-Qn3SFGPXYQMKR/UtqS+dqvPrzEeBZHrFA92maT4zijCVggdsXnDBMsPFJo1eArX3J+O+Gi+8pV4PkqjLCNBk3A==} + + '@tanstack/query-core@5.90.6': + resolution: {integrity: sha512-AnZSLF26R8uX+tqb/ivdrwbVdGemdEDm1Q19qM6pry6eOZ6bEYiY7mWhzXT1YDIPTNEVcZ5kYP9nWjoxDLiIVw==} - '@tanstack/react-query@5.81.0': - resolution: {integrity: sha512-nutU/X1xrgMJXui61oi5j0gXKs2ZlHnI9f/C128CNha/MRi9i/E5tN3pcUIjvQZzNQnOxp1Uv90SZs3kmcecgw==} + '@tanstack/react-query@5.90.6': + resolution: {integrity: sha512-gB1sljYjcobZKxjPbKSa31FUTyr+ROaBdoH+wSSs9Dk+yDCmMs+TkTV3PybRRVLC7ax7q0erJ9LvRWnMktnRAw==} peerDependencies: react: ^18 || ^19 + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} + + '@testing-library/react@16.3.0': + resolution: {integrity: sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@tokenizer/inflate@0.2.7': resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==} engines: {node: '>=18'} @@ -2399,6 +2663,9 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + '@types/better-sqlite3@7.6.13': resolution: {integrity: sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==} @@ -2438,6 +2705,9 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + '@types/methods@1.1.4': resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} @@ -2463,6 +2733,14 @@ packages: '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/react-dom@19.2.0': + resolution: {integrity: sha512-brtBs0MnE9SMx7px208g39lRmC5uHZs96caOJfTjFcYSLHNamvaSMfJNagChVNkup2SdtOxKX1FDBkRSJe1ZAg==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.0': + resolution: {integrity: sha512-1LOH8xovvsKsCBq1wnT4ntDUdCJKmnEakhsuoUSy6ExlHCkGP2hqnatagYTgFk6oeL0VU31u7SNjunPN+GchtA==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -2500,6 +2778,9 @@ packages: '@types/vscode@1.101.0': resolution: {integrity: sha512-ZWf0IWa+NGegdW3iU42AcDTFHWW7fApLdkdnBqwYEtHVIBGbTu0ZNQKP/kX3Ds/uMJXIMQNAojHR4vexCEEz5Q==} + '@types/whatwg-mimetype@3.0.2': + resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} + '@typescript-eslint/eslint-plugin@8.34.1': resolution: {integrity: sha512-STXcN6ebF6li4PxwNeFnqF8/2BNDvBupf2OPx2yWNzr6mKNGF7q49VM00Pz5FaomJyqvbXpY6PhO+T9w139YEQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2508,6 +2789,14 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/eslint-plugin@8.46.2': + resolution: {integrity: sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.46.2 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/parser@8.34.1': resolution: {integrity: sha512-4O3idHxhyzjClSMJ0a29AcoK0+YwnEqzI6oz3vlRf3xw0zbzt15MzXwItOlnr5nIth6zlY2RENLsOPvhyrKAQA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2515,22 +2804,45 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/parser@8.46.2': + resolution: {integrity: sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/project-service@8.34.1': resolution: {integrity: sha512-nuHlOmFZfuRwLJKDGQOVc0xnQrAmuq1Mj/ISou5044y1ajGNp2BNliIqp7F2LPQ5sForz8lempMFCovfeS1XoA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/project-service@8.46.2': + resolution: {integrity: sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/scope-manager@8.34.1': resolution: {integrity: sha512-beu6o6QY4hJAgL1E8RaXNC071G4Kso2MGmJskCFQhRhg8VOH/FDbC8soP8NHN7e/Hdphwp8G8cE6OBzC8o41ZA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.46.2': + resolution: {integrity: sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.34.1': resolution: {integrity: sha512-K4Sjdo4/xF9NEeA2khOb7Y5nY6NSXBnod87uniVYW9kHP+hNlDV8trUSFeynA2uxWam4gIWgWoygPrv9VMWrYg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/tsconfig-utils@8.46.2': + resolution: {integrity: sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/type-utils@8.34.1': resolution: {integrity: sha512-Tv7tCCr6e5m8hP4+xFugcrwTOucB8lshffJ6zf1mF1TbU67R+ntCc6DzLNKM+s/uzDyv8gLq7tufaAhIBYeV8g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2538,16 +2850,33 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/type-utils@8.46.2': + resolution: {integrity: sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/types@8.34.1': resolution: {integrity: sha512-rjLVbmE7HR18kDsjNIZQHxmv9RZwlgzavryL5Lnj2ujIRTeXlKtILHgRNmQ3j4daw7zd+mQgy+uyt6Zo6I0IGA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.46.2': + resolution: {integrity: sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.34.1': resolution: {integrity: sha512-rjCNqqYPuMUF5ODD+hWBNmOitjBWghkGKJg6hiCHzUvXRy6rK22Jd3rwbP2Xi+R7oYVvIKhokHVhH41BxPV5mA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/typescript-estree@8.46.2': + resolution: {integrity: sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/utils@8.34.1': resolution: {integrity: sha512-mqOwUdZ3KjtGk7xJJnLbHxTuWVn3GO2WZZuM+Slhkun4+qthLdXx32C8xIXbO1kfCECb3jIs3eoxK3eryk7aoQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2555,46 +2884,152 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/utils@8.46.2': + resolution: {integrity: sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/visitor-keys@8.34.1': resolution: {integrity: sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.46.2': + resolution: {integrity: sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@unhead/vue@2.0.19': resolution: {integrity: sha512-7BYjHfOaoZ9+ARJkT10Q2TjnTUqDXmMpfakIAsD/hXiuff1oqWg1xeXT5+MomhNcC15HbiABpbbBmITLSHxdKg==} peerDependencies: vue: '>=3.5.18' - '@vercel/nft@0.30.3': - resolution: {integrity: sha512-UEq+eF0ocEf9WQCV1gktxKhha36KDs7jln5qii6UpPf5clMqDc0p3E7d9l2Smx0i9Pm1qpq4S4lLfNl97bbv6w==} - engines: {node: '>=18'} - hasBin: true + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + cpu: [arm] + os: [android] - '@vitejs/plugin-vue-jsx@5.1.1': - resolution: {integrity: sha512-uQkfxzlF8SGHJJVH966lFTdjM/lGcwJGzwAHpVqAPDD/QcsqoUGa+q31ox1BrUfi+FLP2ChVp7uLXE3DkHyDdQ==} - engines: {node: ^20.19.0 || >=22.12.0} - peerDependencies: - vite: ^5.0.0 || ^6.0.0 || ^7.0.0 - vue: ^3.0.0 + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + cpu: [arm64] + os: [android] - '@vitejs/plugin-vue@6.0.1': - resolution: {integrity: sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==} - engines: {node: ^20.19.0 || >=22.12.0} - peerDependencies: - vite: ^5.0.0 || ^6.0.0 || ^7.0.0 - vue: ^3.2.25 + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + cpu: [arm64] + os: [darwin] - '@vitest/expect@3.2.4': - resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + cpu: [x64] + os: [darwin] - '@vitest/mocker@3.2.4': - resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} - peerDependencies: - msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 - peerDependenciesMeta: - msw: - optional: true - vite: + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + cpu: [ppc64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + cpu: [s390x] + os: [linux] + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + cpu: [x64] + os: [win32] + + '@vercel/nft@0.30.3': + resolution: {integrity: sha512-UEq+eF0ocEf9WQCV1gktxKhha36KDs7jln5qii6UpPf5clMqDc0p3E7d9l2Smx0i9Pm1qpq4S4lLfNl97bbv6w==} + engines: {node: '>=18'} + hasBin: true + + '@vitejs/plugin-vue-jsx@5.1.1': + resolution: {integrity: sha512-uQkfxzlF8SGHJJVH966lFTdjM/lGcwJGzwAHpVqAPDD/QcsqoUGa+q31ox1BrUfi+FLP2ChVp7uLXE3DkHyDdQ==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 + vue: ^3.0.0 + + '@vitejs/plugin-vue@6.0.1': + resolution: {integrity: sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 + vue: ^3.2.25 + + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: optional: true '@vitest/pretty-format@3.2.4': @@ -2761,6 +3196,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} @@ -2787,10 +3226,45 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlastindex@1.2.6: + resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} @@ -2802,10 +3276,17 @@ packages: resolution: {integrity: sha512-TH+b3Lv6pUjy/Nu0m6A2JULtdzLpmqF9x1Dhj00ZoEiML8qvVA9j1flkzTKNYgdEhWrjDwtWNpyyCUbfQe514g==} engines: {node: '>=20.19.0'} + ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + ast-walker-scope@0.8.3: resolution: {integrity: sha512-cbdCP0PGOBq0ASG+sjnKIoYkWMKhhz+F/h9pRexUdX2Hd38+WOlBkRKlqkGOSm0YQpcFMQBJeK4WspUAkwsEdg==} engines: {node: '>=20.19.0'} + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + async-sema@3.1.1: resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} @@ -2826,9 +3307,17 @@ packages: peerDependencies: postcss: ^8.1.0 + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + avvio@9.1.0: resolution: {integrity: sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==} + axe-core@4.11.0: + resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==} + engines: {node: '>=4'} + axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -2863,6 +3352,9 @@ packages: resolution: {integrity: sha512-eGbYq2CT+tos1fBwLQ/tkBt9J5M3JEHjku4hbvQUePCckkvVf14xWj+1m7dGoK81M/fOjFT7yM9UMeKT/+vFLQ==} engines: {node: 20.x || 22.x || 23.x || 24.x} + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} @@ -3076,6 +3568,10 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} @@ -3213,9 +3709,32 @@ packages: resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + cssstyle@5.3.2: + resolution: {integrity: sha512-zDMqXh8Vs1CdRYZQ2M633m/SFgcjlu8RB8b/1h82i+6vpArF507NSYIWJHGlJaTWoS+imcnctmEz43txhbVkOw==} + engines: {node: '>=20'} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + + data-urls@6.0.0: + resolution: {integrity: sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==} + engines: {node: '>=20'} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + db0@0.3.4: resolution: {integrity: sha512-RiXXi4WaNzPTHEOu8UPQKMooIbqOEyqA1t7Z6MsdxSCeb8iUC9ko3LcmsLmeUt2SM5bctfArZKkRQggKZz7JNw==} peerDependencies: @@ -3239,6 +3758,14 @@ packages: sqlite3: optional: true + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.4.1: resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} @@ -3251,6 +3778,9 @@ packages: decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} @@ -3297,6 +3827,10 @@ packages: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} engines: {node: '>=12'} + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} @@ -3324,10 +3858,6 @@ packages: engines: {node: '>=0.10'} hasBin: true - detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} - engines: {node: '>=8'} - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -3342,6 +3872,13 @@ packages: resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} engines: {node: '>=0.3.1'} + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -3418,16 +3955,28 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + enhanced-resolve@5.18.3: + resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} + engines: {node: '>=10.13.0'} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + error-stack-parser-es@1.0.5: resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==} errx@0.1.0: resolution: {integrity: sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==} + es-abstract@1.24.0: + resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} + engines: {node: '>= 0.4'} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -3436,6 +3985,10 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-iterator-helpers@1.2.1: + resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} + engines: {node: '>= 0.4'} + es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} @@ -3447,6 +4000,14 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + esbuild@0.25.11: resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} engines: {node: '>=18'} @@ -3472,6 +4033,80 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} + eslint-config-next@16.0.1: + resolution: {integrity: sha512-wNuHw5gNOxwLUvpg0cu6IL0crrVC9hAwdS/7UwleNkwyaMiWIOAwf8yzXVqBBzL3c9A7jVRngJxjoSpPP1aEhg==} + peerDependencies: + eslint: '>=9.0.0' + typescript: '>=3.3.1' + peerDependenciesMeta: + typescript: + optional: true + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-import-resolver-typescript@3.10.1: + resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + eslint-plugin-import-x: '*' + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + + eslint-module-utils@2.12.1: + resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-import@2.32.0: + resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-jsx-a11y@6.10.2: + resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + + eslint-plugin-react-hooks@7.0.1: + resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3585,6 +4220,10 @@ packages: fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} @@ -3680,6 +4319,10 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} @@ -3718,10 +4361,21 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + fuse.js@7.1.0: resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==} engines: {node: '>=10'} + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -3749,6 +4403,10 @@ packages: resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} engines: {node: '>=18'} + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + get-tsconfig@4.10.1: resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} @@ -3790,6 +4448,14 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} + globals@16.4.0: + resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + globby@15.0.0: resolution: {integrity: sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw==} engines: {node: '>=20'} @@ -3811,6 +4477,14 @@ packages: h3@1.15.4: resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==} + happy-dom@20.0.10: + resolution: {integrity: sha512-6umCCHcjQrhP5oXhrHQQvLB0bwb1UzHAHdsXy+FjtKoYjUhmNZsQL8NivwM1vDvNEChJabVrUYxUnp/ZdYmy2g==} + engines: {node: '>=20.0.0'} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -3818,6 +4492,10 @@ packages: has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + has-symbols@1.1.0: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} @@ -3830,6 +4508,12 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + hono@4.10.3: resolution: {integrity: sha512-2LOYWUbnhdxdL8MNbNg9XZig6k+cZXm5IjHn2Aviv7honhBMOHb+jxrKIeJRZJRmn+htUCKhaicxwXuUDlchRA==} engines: {node: '>=16.9.0'} @@ -3837,10 +4521,18 @@ packages: hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + http-shutdown@1.2.2: resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -3907,6 +4599,10 @@ packages: resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + ioredis@5.8.2: resolution: {integrity: sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q==} engines: {node: '>=12.22.0'} @@ -3922,10 +4618,41 @@ packages: iron-webcrypto@1.2.1: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-bun-module@2.0.0: + resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + is-core-module@2.16.1: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} @@ -3940,10 +4667,18 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -3961,9 +4696,24 @@ packages: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-node-process@1.2.0: + resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -3976,6 +4726,9 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} @@ -3985,6 +4738,18 @@ packages: is-reference@3.0.3: resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + is-ssh@1.4.1: resolution: {integrity: sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==} @@ -4000,6 +4765,18 @@ packages: resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} engines: {node: '>=18'} + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} @@ -4012,6 +4789,18 @@ packages: resolution: {integrity: sha512-QkbMsWkIfkrzOPxenwye0h56iAXirZYHG9eHVPb22fO9y+wPbaX/CHacOWBa/I++4ohTcByimhM1/nyCsH8KNA==} engines: {node: '>=20'} + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + is-what@5.5.0: resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} engines: {node: '>=18'} @@ -4041,6 +4830,10 @@ packages: resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} engines: {node: '>=16'} + iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} + jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -4070,6 +4863,15 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + jsdom@27.1.0: + resolution: {integrity: sha512-Pcfm3eZ+eO4JdZCXthW9tCDT3nF4K+9dmeZ+5X39n+Kqz0DDIABRP5CAEOHRFZk8RGuC2efksTJxrjp8EXCunQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -4094,7 +4896,14 @@ packages: resolution: {integrity: sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==} engines: {node: '>= 0.4'} - json5@2.2.3: + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true @@ -4108,6 +4917,10 @@ packages: jsonschema@1.4.1: resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -4142,6 +4955,13 @@ packages: resolution: {integrity: sha512-tnqVzWOkUcoiY0bWlyE8diFrZjmGBCF7MesC1bjUaZM+YGQSfdPC+KkhmHM0DWFG+uLcPxidKaPP1SYGtg3J0Q==} engines: {node: '>=18.0.0'} + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + + language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + launch-editor@2.12.0: resolution: {integrity: sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==} @@ -4156,6 +4976,76 @@ packages: light-my-request@6.6.0: resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==} + lightningcss-android-arm64@1.30.2: + resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.30.2: + resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.30.2: + resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.30.2: + resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.30.2: + resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.30.2: + resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.30.2: + resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.30.2: + resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.30.2: + resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.30.2: + resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.30.2: + resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.30.2: + resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} + engines: {node: '>= 12.0.0'} + lilconfig@3.1.3: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} @@ -4210,6 +5100,15 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lorem-ipsum@2.0.8: + resolution: {integrity: sha512-5RIwHuCb979RASgCJH0VKERn9cQo/+NcAi2BMe9ddj+gp7hujl6BI+qdOG4nVsLDpwWEJwTVYXNKP6BGgbcoGA==} + engines: {node: '>= 8.x', npm: '>= 5.x'} + hasBin: true + loupe@3.1.4: resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==} @@ -4220,9 +5119,17 @@ packages: resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} engines: {node: 20 || >=22} + lru-cache@11.2.2: + resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-regexp@0.10.0: resolution: {integrity: sha512-Uly1Bu4lO1hwHUW0CQeSWuRtzCMNO00CmXtS8N6fyvB3B979GOEEeAkiTUDsmbYLAbvpUS/Kt5c4ibosAzVyVg==} @@ -4404,6 +5311,11 @@ packages: napi-build-utils@2.0.0: resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -4411,9 +5323,9 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} - next@15.5.6: - resolution: {integrity: sha512-zTxsnI3LQo3c9HSdSf91O1jMNsEzIXDShXd4wVdg9y5shwLqBXi4ZtUUJyB86KGVSJLZx0PFONvO54aheGX8QQ==} - engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} + next@16.0.1: + resolution: {integrity: sha512-e9RLSssZwd35p7/vOa+hoDFggUZIUbZhIUSLZuETCwrCVvxOs87NamoUzT+vbcNAL8Ld9GobBnWOA6SbV/arOw==} + engines: {node: '>=20.9.0'} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 @@ -4442,6 +5354,10 @@ packages: xml2js: optional: true + nock@14.0.10: + resolution: {integrity: sha512-Q7HjkpyPeLa0ZVZC5qpxBt5EyLczFJ91MEewQiIi9taWuA0KB/MDJlUWtON+7dGouVdADTQsf9RA7TZk6D8VMw==} + engines: {node: '>=18.20.0 <20 || >=20.12.1'} + node-abi@3.73.0: resolution: {integrity: sha512-z8iYzQGBu35ZkTQ9mtR8RqugJZ9RCLn8fv3d7LsgDBzOijGQP3RdKTX4LA7LXw03ZhU5z0l4xfhIMgSES31+cg==} engines: {node: '>=10'} @@ -4534,6 +5450,26 @@ packages: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + obuf@1.1.2: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} @@ -4585,6 +5521,13 @@ packages: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} + outvariant@1.4.3: + resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + oxc-minify@0.95.0: resolution: {integrity: sha512-3k//447vscNk5JZXVnr2qv0QONjUU7F8Y6ewAPFVQNgdvYh3gCLYCRjQ/DR5kVkqxFgVa8R/FFBV3X5jlztSzw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4631,6 +5574,9 @@ packages: resolution: {integrity: sha512-bCgsFI+GeGWPAvAiUv63ZorMeif3/U0zaXABGJbOWt5OH2KCaPHF6S+0ok4aqM9RuIPGyZdx9tR9l13PsW4AYQ==} engines: {node: '>=14.13.0'} + parse5@8.0.0: + resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -4768,6 +5714,10 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + postcss-calc@10.1.1: resolution: {integrity: sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw==} engines: {node: ^18.12 || ^20.9 || >=22.0} @@ -5016,6 +5966,10 @@ packages: resolution: {integrity: sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw==} engines: {node: '>=20'} + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pretty-ms@9.3.0: resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} engines: {node: '>=18'} @@ -5047,6 +6001,13 @@ packages: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + propagate@2.0.1: + resolution: {integrity: sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==} + engines: {node: '>= 8'} + protocols@2.0.2: resolution: {integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==} @@ -5110,8 +6071,14 @@ packages: peerDependencies: react: ^19.2.0 - react@19.1.0: - resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + react@19.2.0: + resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} engines: {node: '>=0.10.0'} readable-stream@2.3.8: @@ -5144,10 +6111,18 @@ packages: resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} engines: {node: '>=4'} + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + regexp-tree@0.1.27: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -5172,6 +6147,10 @@ packages: engines: {node: '>= 0.4'} hasBin: true + resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} @@ -5225,12 +6204,24 @@ packages: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + safe-regex2@5.0.0: resolution: {integrity: sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==} @@ -5244,6 +6235,10 @@ packages: sax@1.4.1: resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -5292,6 +6287,14 @@ packages: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -5399,6 +6402,9 @@ packages: engines: {node: '>=20.16.0'} hasBin: true + stable-hash@0.0.5: + resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -5415,9 +6421,16 @@ packages: std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + streamx@2.23.0: resolution: {integrity: sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==} + strict-event-emitter@0.5.1: + resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -5426,6 +6439,29 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string.prototype.includes@2.0.1: + resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} + engines: {node: '>= 0.4'} + + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} + + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -5440,6 +6476,10 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} @@ -5526,6 +6566,9 @@ packages: engines: {node: '>=16'} hasBin: true + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + system-architecture@0.1.0: resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} engines: {node: '>=18'} @@ -5534,6 +6577,13 @@ packages: resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} engines: {node: '>=20'} + tailwindcss@4.1.16: + resolution: {integrity: sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==} + + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} + engines: {node: '>=6'} + tar-fs@2.1.2: resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} @@ -5598,6 +6648,13 @@ packages: resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} engines: {node: '>=14.0.0'} + tldts-core@7.0.17: + resolution: {integrity: sha512-DieYoGrP78PWKsrXr8MZwtQ7GLCUeLxihtjC1jZsW1DnvSMdKPitJSe8OSYDM2u5H6g3kWJZpePqkp43TfLh0g==} + + tldts@7.0.17: + resolution: {integrity: sha512-Y1KQBgDd/NUc+LfOtKS6mNsC9CCaH+m2P1RoIZy7RAPo3C3/t8X45+zgut31cRZtZ3xKPjfn3TkGTrctC2TQIQ==} + hasBin: true + tmp@0.2.3: resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} engines: {node: '>=14.14'} @@ -5625,12 +6682,20 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tough-cookie@6.0.0: + resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} + engines: {node: '>=16'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -5651,6 +6716,9 @@ packages: ts-pattern@5.7.1: resolution: {integrity: sha512-EGs8PguQqAAUIcQfK4E9xdXxB6s2GK4sJfT/vcc9V1ELIvC4LH/zXu2t/5fajtv6oiRCxdv7BgtVK3vWgROxag==} + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -5730,6 +6798,22 @@ packages: type-level-regexp@0.1.17: resolution: {integrity: sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg==} + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + typescript-eslint@8.34.1: resolution: {integrity: sha512-XjS+b6Vg9oT1BaIUfkW3M3LvqZE++rbzAMEHuccCfO/YkP43ha6w3jTEMilQxMF92nVOYCcdjv1ZUhAa1D/0ow==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5737,6 +6821,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + typescript-eslint@8.46.2: + resolution: {integrity: sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + typescript@5.8.3: resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} engines: {node: '>=14.17'} @@ -5756,6 +6847,10 @@ packages: ultrahtml@1.6.0: resolution: {integrity: sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==} + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + uncrypto@0.1.3: resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} @@ -5812,6 +6907,9 @@ packages: resolution: {integrity: sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==} engines: {node: '>=18.12.0'} + unrs-resolver@1.11.1: + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + unstorage@1.17.1: resolution: {integrity: sha512-KKGwRTT0iVBCErKemkJCLs7JdxNVfqTPc/85ae1XES0+bsHbc/sFBfVi5kJp156cc51BHinIH2l3k0EZ24vOBQ==} peerDependencies: @@ -6142,6 +7240,10 @@ packages: typescript: optional: true + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} @@ -6151,15 +7253,51 @@ packages: webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + webidl-conversions@8.0.0: + resolution: {integrity: sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==} + engines: {node: '>=20'} + webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@15.1.0: + resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} + engines: {node: '>=20'} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -6206,6 +7344,13 @@ packages: resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} engines: {node: '>=18'} + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -6271,6 +7416,32 @@ packages: snapshots: + '@acemir/cssom@0.9.19': + optional: true + + '@alloc/quick-lru@5.2.0': {} + + '@asamuzakjp/css-color@4.0.5': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 11.2.2 + optional: true + + '@asamuzakjp/dom-selector@6.7.4': + dependencies: + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.1.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.2.2 + optional: true + + '@asamuzakjp/nwsapi@2.3.9': + optional: true + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -6415,6 +7586,8 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/runtime@7.28.4': {} + '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 @@ -6461,6 +7634,34 @@ snapshots: dependencies: mime: 3.0.0 + '@csstools/color-helpers@5.1.0': + optional: true + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + optional: true + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + optional: true + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + optional: true + + '@csstools/css-syntax-patches-for-csstree@1.0.15': + optional: true + + '@csstools/css-tokenizer@3.0.4': + optional: true + '@dxup/nuxt@0.2.0(magicast@0.5.0)': dependencies: '@dxup/unimport': 0.1.0 @@ -6890,6 +8091,22 @@ snapshots: - encoding - supports-color + '@mswjs/interceptors@0.39.8': + dependencies: + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/logger': 0.3.0 + '@open-draft/until': 2.1.0 + is-node-process: 1.2.0 + outvariant: 1.4.3 + strict-event-emitter: 0.5.1 + + '@napi-rs/wasm-runtime@0.2.12': + dependencies: + '@emnapi/core': 1.6.0 + '@emnapi/runtime': 1.6.0 + '@tybys/wasm-util': 0.10.1 + optional: true + '@napi-rs/wasm-runtime@1.0.7': dependencies: '@emnapi/core': 1.6.0 @@ -6897,30 +8114,34 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@next/env@15.5.6': {} + '@next/env@16.0.1': {} - '@next/swc-darwin-arm64@15.5.6': + '@next/eslint-plugin-next@16.0.1': + dependencies: + fast-glob: 3.3.1 + + '@next/swc-darwin-arm64@16.0.1': optional: true - '@next/swc-darwin-x64@15.5.6': + '@next/swc-darwin-x64@16.0.1': optional: true - '@next/swc-linux-arm64-gnu@15.5.6': + '@next/swc-linux-arm64-gnu@16.0.1': optional: true - '@next/swc-linux-arm64-musl@15.5.6': + '@next/swc-linux-arm64-musl@16.0.1': optional: true - '@next/swc-linux-x64-gnu@15.5.6': + '@next/swc-linux-x64-gnu@16.0.1': optional: true - '@next/swc-linux-x64-musl@15.5.6': + '@next/swc-linux-x64-musl@16.0.1': optional: true - '@next/swc-win32-arm64-msvc@15.5.6': + '@next/swc-win32-arm64-msvc@16.0.1': optional: true - '@next/swc-win32-x64-msvc@15.5.6': + '@next/swc-win32-x64-msvc@16.0.1': optional: true '@noble/hashes@1.7.1': {} @@ -6937,6 +8158,8 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 + '@nolyfill/is-core-module@1.0.39': {} + '@nuxt/cli@3.29.3(magicast@0.5.0)': dependencies: c12: 3.3.1(magicast@0.5.0) @@ -6971,11 +8194,11 @@ snapshots: '@nuxt/devalue@2.0.2': {} - '@nuxt/devtools-kit@2.7.0(magicast@0.3.5)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))': + '@nuxt/devtools-kit@2.7.0(magicast@0.3.5)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))': dependencies: '@nuxt/kit': 3.20.0(magicast@0.3.5) execa: 8.0.1 - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) transitivePeerDependencies: - magicast @@ -6990,12 +8213,12 @@ snapshots: prompts: 2.4.2 semver: 7.7.3 - '@nuxt/devtools@2.7.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3))': + '@nuxt/devtools@2.7.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3))': dependencies: - '@nuxt/devtools-kit': 2.7.0(magicast@0.3.5)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + '@nuxt/devtools-kit': 2.7.0(magicast@0.3.5)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) '@nuxt/devtools-wizard': 2.7.0 '@nuxt/kit': 3.20.0(magicast@0.3.5) - '@vue/devtools-core': 7.7.7(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)) + '@vue/devtools-core': 7.7.7(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)) '@vue/devtools-kit': 7.7.7 birpc: 2.6.1 consola: 3.4.2 @@ -7020,9 +8243,9 @@ snapshots: sirv: 3.0.2 structured-clone-es: 1.0.0 tinyglobby: 0.2.15 - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) - vite-plugin-inspect: 11.3.3(@nuxt/kit@3.20.0(magicast@0.3.5))(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) - vite-plugin-vue-tracer: 1.0.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite-plugin-inspect: 11.3.3(@nuxt/kit@3.20.0(magicast@0.3.5))(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + vite-plugin-vue-tracer: 1.0.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)) which: 5.0.0 ws: 8.18.3 transitivePeerDependencies: @@ -7108,7 +8331,7 @@ snapshots: transitivePeerDependencies: - magicast - '@nuxt/nitro-server@4.2.0(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(ioredis@5.8.2)(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1))(typescript@5.8.3)': + '@nuxt/nitro-server@4.2.0(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(ioredis@5.8.2)(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1))(typescript@5.8.3)': dependencies: '@nuxt/devalue': 2.0.2 '@nuxt/kit': 4.2.0(magicast@0.5.0) @@ -7126,7 +8349,7 @@ snapshots: klona: 2.0.6 mocked-exports: 0.1.1 nitropack: 2.12.9(better-sqlite3@12.2.0) - nuxt: 4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1) + nuxt: 4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1) pathe: 2.0.3 pkg-types: 2.3.0 radix3: 1.1.2 @@ -7197,12 +8420,12 @@ snapshots: transitivePeerDependencies: - magicast - '@nuxt/vite-builder@4.2.0(@types/node@20.17.24)(eslint@9.29.0(jiti@2.6.1))(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vue@3.5.22(typescript@5.8.3))(yaml@2.8.1)': + '@nuxt/vite-builder@4.2.0(@types/node@20.17.24)(eslint@9.29.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vue@3.5.22(typescript@5.8.3))(yaml@2.8.1)': dependencies: '@nuxt/kit': 4.2.0(magicast@0.5.0) '@rollup/plugin-replace': 6.0.3(rollup@4.52.5) - '@vitejs/plugin-vue': 6.0.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)) - '@vitejs/plugin-vue-jsx': 5.1.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)) + '@vitejs/plugin-vue': 6.0.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)) + '@vitejs/plugin-vue-jsx': 5.1.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)) autoprefixer: 10.4.21(postcss@8.5.6) consola: 3.4.2 cssnano: 7.1.2(postcss@8.5.6) @@ -7217,7 +8440,7 @@ snapshots: magic-string: 0.30.21 mlly: 1.8.0 mocked-exports: 0.1.1 - nuxt: 4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1) + nuxt: 4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1) pathe: 2.0.3 pkg-types: 2.3.0 postcss: 8.5.6 @@ -7226,9 +8449,9 @@ snapshots: std-env: 3.10.0 ufo: 1.6.1 unenv: 2.0.0-rc.24 - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) - vite-plugin-checker: 0.11.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite-plugin-checker: 0.11.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) vue: 3.5.22(typescript@5.8.3) vue-bundle-renderer: 2.2.0 transitivePeerDependencies: @@ -7256,6 +8479,15 @@ snapshots: - vue-tsc - yaml + '@open-draft/deferred-promise@2.2.0': {} + + '@open-draft/logger@0.3.0': + dependencies: + is-node-process: 1.2.0 + outvariant: 1.4.3 + + '@open-draft/until@2.1.0': {} + '@oxc-minify/binding-android-arm64@0.95.0': optional: true @@ -7710,6 +8942,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.52.5': optional: true + '@rtsao/scc@1.1.0': {} + '@sec-ant/readable-stream@0.4.1': {} '@sinclair/typebox@0.34.41': {} @@ -7726,11 +8960,11 @@ snapshots: dependencies: acorn: 8.15.0 - '@sveltejs/kit@2.48.3(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))': + '@sveltejs/kit@2.48.3(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))': dependencies: '@standard-schema/spec': 1.0.0 '@sveltejs/acorn-typescript': 1.0.6(acorn@8.15.0) - '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) '@types/cookie': 0.6.0 acorn: 8.15.0 cookie: 0.6.0 @@ -7743,26 +8977,26 @@ snapshots: set-cookie-parser: 2.7.2 sirv: 3.0.2 svelte: 5.43.0 - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) - '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))': + '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) debug: 4.4.1 svelte: 5.43.0 - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))': + '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) debug: 4.4.1 deepmerge: 4.3.1 magic-string: 0.30.21 svelte: 5.43.0 - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) - vitefu: 1.1.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vitefu: 1.1.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) transitivePeerDependencies: - supports-color @@ -7825,12 +9059,102 @@ snapshots: '@swc/counter': 0.1.3 optional: true - '@tanstack/query-core@5.81.0': {} + '@tailwindcss/node@4.1.16': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.18.3 + jiti: 2.6.1 + lightningcss: 1.30.2 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.1.16 + + '@tailwindcss/oxide-android-arm64@4.1.16': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.1.16': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.1.16': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.1.16': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.16': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.1.16': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.1.16': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.1.16': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.1.16': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.16': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.1.16': + optional: true + + '@tailwindcss/oxide@4.1.16': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.1.16 + '@tailwindcss/oxide-darwin-arm64': 4.1.16 + '@tailwindcss/oxide-darwin-x64': 4.1.16 + '@tailwindcss/oxide-freebsd-x64': 4.1.16 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.16 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.16 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.16 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.16 + '@tailwindcss/oxide-linux-x64-musl': 4.1.16 + '@tailwindcss/oxide-wasm32-wasi': 4.1.16 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.16 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.16 + + '@tailwindcss/postcss@4.1.16': + dependencies: + '@alloc/quick-lru': 5.2.0 + '@tailwindcss/node': 4.1.16 + '@tailwindcss/oxide': 4.1.16 + postcss: 8.5.6 + tailwindcss: 4.1.16 - '@tanstack/react-query@5.81.0(react@19.1.0)': + '@tanstack/query-core@5.90.6': {} + + '@tanstack/react-query@5.90.6(react@19.2.0)': + dependencies: + '@tanstack/query-core': 5.90.6 + react: 19.2.0 + + '@testing-library/dom@10.4.1': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/runtime': 7.28.4 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + '@testing-library/react@16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.0(@types/react@19.2.0))(@types/react@19.2.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@tanstack/query-core': 5.81.0 - react: 19.1.0 + '@babel/runtime': 7.28.4 + '@testing-library/dom': 10.4.1 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + optionalDependencies: + '@types/react': 19.2.0 + '@types/react-dom': 19.2.0(@types/react@19.2.0) '@tokenizer/inflate@0.2.7': dependencies: @@ -7847,6 +9171,8 @@ snapshots: tslib: 2.8.1 optional: true + '@types/aria-query@5.0.4': {} + '@types/better-sqlite3@7.6.13': dependencies: '@types/node': 20.17.24 @@ -7891,6 +9217,8 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/json5@0.0.29': {} + '@types/methods@1.1.4': {} '@types/mime@1.3.5': {} @@ -7915,6 +9243,14 @@ snapshots: '@types/range-parser@1.2.7': {} + '@types/react-dom@19.2.0(@types/react@19.2.0)': + dependencies: + '@types/react': 19.2.0 + + '@types/react@19.2.0': + dependencies: + csstype: 3.1.3 + '@types/resolve@1.20.2': {} '@types/semver@7.7.0': {} @@ -7961,6 +9297,8 @@ snapshots: '@types/vscode@1.101.0': {} + '@types/whatwg-mimetype@3.0.2': {} + '@typescript-eslint/eslint-plugin@8.34.1(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -7978,6 +9316,23 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.46.2 + '@typescript-eslint/type-utils': 8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/utils': 8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.46.2 + eslint: 9.29.0(jiti@2.6.1) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3)': dependencies: '@typescript-eslint/scope-manager': 8.34.1 @@ -7990,6 +9345,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.46.2 + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.46.2 + debug: 4.4.1 + eslint: 9.29.0(jiti@2.6.1) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/project-service@8.34.1(typescript@5.8.3)': dependencies: '@typescript-eslint/tsconfig-utils': 8.34.1(typescript@5.8.3) @@ -7999,15 +9366,33 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.46.2(typescript@5.8.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.46.2(typescript@5.8.3) + '@typescript-eslint/types': 8.46.2 + debug: 4.4.1 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@8.34.1': dependencies: '@typescript-eslint/types': 8.34.1 '@typescript-eslint/visitor-keys': 8.34.1 + '@typescript-eslint/scope-manager@8.46.2': + dependencies: + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/visitor-keys': 8.46.2 + '@typescript-eslint/tsconfig-utils@8.34.1(typescript@5.8.3)': dependencies: typescript: 5.8.3 + '@typescript-eslint/tsconfig-utils@8.46.2(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@typescript-eslint/type-utils@8.34.1(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3)': dependencies: '@typescript-eslint/typescript-estree': 8.34.1(typescript@5.8.3) @@ -8019,8 +9404,22 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.8.3) + '@typescript-eslint/utils': 8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) + debug: 4.4.1 + eslint: 9.29.0(jiti@2.6.1) + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/types@8.34.1': {} + '@typescript-eslint/types@8.46.2': {} + '@typescript-eslint/typescript-estree@8.34.1(typescript@5.8.3)': dependencies: '@typescript-eslint/project-service': 8.34.1(typescript@5.8.3) @@ -8037,6 +9436,22 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.46.2(typescript@5.8.3)': + dependencies: + '@typescript-eslint/project-service': 8.46.2(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.46.2(typescript@5.8.3) + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/visitor-keys': 8.46.2 + debug: 4.4.1 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.3 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.34.1(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3)': dependencies: '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@2.6.1)) @@ -8048,17 +9463,92 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.46.2 + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.8.3) + eslint: 9.29.0(jiti@2.6.1) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@8.34.1': dependencies: '@typescript-eslint/types': 8.34.1 eslint-visitor-keys: 4.2.1 + '@typescript-eslint/visitor-keys@8.46.2': + dependencies: + '@typescript-eslint/types': 8.46.2 + eslint-visitor-keys: 4.2.1 + '@unhead/vue@2.0.19(vue@3.5.22(typescript@5.8.3))': dependencies: hookable: 5.5.3 unhead: 2.0.19 vue: 3.5.22(typescript@5.8.3) + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + optional: true + + '@unrs/resolver-binding-android-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + optional: true + '@vercel/nft@0.30.3(rollup@4.52.5)': dependencies: '@mapbox/node-pre-gyp': 2.0.0 @@ -8078,22 +9568,22 @@ snapshots: - rollup - supports-color - '@vitejs/plugin-vue-jsx@5.1.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3))': + '@vitejs/plugin-vue-jsx@5.1.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) '@babel/plugin-transform-typescript': 7.28.5(@babel/core@7.28.5) '@rolldown/pluginutils': 1.0.0-beta.45 '@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.28.5) - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) vue: 3.5.22(typescript@5.8.3) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@6.0.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3))': + '@vitejs/plugin-vue@6.0.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.29 - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) vue: 3.5.22(typescript@5.8.3) '@vitest/expect@3.2.4': @@ -8104,13 +9594,13 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0))': + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.5(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) + vite: 6.3.5(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) '@vitest/pretty-format@3.2.4': dependencies: @@ -8215,14 +9705,14 @@ snapshots: '@vue/devtools-api@6.6.4': {} - '@vue/devtools-core@7.7.7(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3))': + '@vue/devtools-core@7.7.7(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3))': dependencies: '@vue/devtools-kit': 7.7.7 '@vue/devtools-shared': 7.7.7 mitt: 3.0.1 nanoid: 5.1.6 pathe: 2.0.3 - vite-hot-client: 2.1.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + vite-hot-client: 2.1.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) vue: 3.5.22(typescript@5.8.3) transitivePeerDependencies: - vite @@ -8336,6 +9826,8 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.1: {} ansis@4.2.0: {} @@ -8372,8 +9864,79 @@ snapshots: argparse@2.0.1: {} + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + aria-query@5.3.2: {} + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-includes@3.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.findlastindex@1.2.6: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-shim-unscopables: 1.1.0 + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + asap@2.0.6: {} assertion-error@2.0.1: {} @@ -8383,11 +9946,15 @@ snapshots: '@babel/parser': 7.28.5 pathe: 2.0.3 + ast-types-flow@0.0.8: {} + ast-walker-scope@0.8.3: dependencies: '@babel/parser': 7.28.5 ast-kit: 2.1.3 + async-function@1.0.0: {} + async-sema@3.1.1: {} async@3.2.6: {} @@ -8406,11 +9973,17 @@ snapshots: postcss: 8.5.6 postcss-value-parser: 4.2.0 + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + avvio@9.1.0: dependencies: '@fastify/error': 4.2.0 fastq: 1.19.1 + axe-core@4.11.0: {} + axobject-query@4.1.0: {} b4a@1.7.3: {} @@ -8428,6 +10001,11 @@ snapshots: bindings: 1.5.0 prebuild-install: 7.1.3 + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + optional: true + bindings@1.5.0: dependencies: file-uri-to-path: 1.0.0 @@ -8687,6 +10265,8 @@ snapshots: commander@8.3.0: {} + commander@9.5.0: {} + commondir@1.0.1: {} compatx@0.2.0: {} @@ -8830,18 +10410,58 @@ snapshots: dependencies: css-tree: 2.2.1 + cssstyle@5.3.2: + dependencies: + '@asamuzakjp/css-color': 4.0.5 + '@csstools/css-syntax-patches-for-csstree': 1.0.15 + css-tree: 3.1.0 + optional: true + csstype@3.1.3: {} + damerau-levenshtein@1.0.8: {} + + data-urls@6.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + optional: true + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + db0@0.3.4(better-sqlite3@12.2.0): optionalDependencies: better-sqlite3: 12.2.0 + debug@3.2.7: + dependencies: + ms: 2.1.3 + debug@4.4.1: dependencies: ms: 2.1.3 decimal.js@10.4.3: {} + decimal.js@10.6.0: + optional: true + decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 @@ -8877,6 +10497,12 @@ snapshots: define-lazy-prop@3.0.0: {} + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + defu@6.1.4: {} delayed-stream@1.0.0: {} @@ -8891,8 +10517,6 @@ snapshots: detect-libc@1.0.3: {} - detect-libc@2.0.3: {} - detect-libc@2.1.2: {} devalue@5.4.2: {} @@ -8904,6 +10528,12 @@ snapshots: diff@8.0.2: {} + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + dom-accessibility-api@0.5.16: {} + dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -8973,16 +10603,100 @@ snapshots: dependencies: once: 1.4.0 + enhanced-resolve@5.18.3: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.0 + entities@4.5.0: {} + entities@6.0.1: + optional: true + error-stack-parser-es@1.0.5: {} errx@0.1.0: {} + es-abstract@1.24.0: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.19 + es-define-property@1.0.1: {} es-errors@1.3.0: {} + es-iterator-helpers@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-set-tostringtag: 2.1.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + safe-array-concat: 1.1.3 + es-module-lexer@1.7.0: {} es-object-atoms@1.1.1: @@ -8996,6 +10710,16 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + esbuild@0.25.11: optionalDependencies: '@esbuild/aix-ppc64': 0.25.11 @@ -9061,6 +10785,141 @@ snapshots: escape-string-regexp@5.0.0: {} + eslint-config-next@16.0.1(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3): + dependencies: + '@next/eslint-plugin-next': 16.0.1 + eslint: 9.29.0(jiti@2.6.1) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.29.0(jiti@2.6.1)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.29.0(jiti@2.6.1)) + eslint-plugin-react: 7.37.5(eslint@9.29.0(jiti@2.6.1)) + eslint-plugin-react-hooks: 7.0.1(eslint@9.29.0(jiti@2.6.1)) + globals: 16.4.0 + typescript-eslint: 8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-webpack + - eslint-plugin-import-x + - supports-color + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 1.22.11 + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.4.1 + eslint: 9.29.0(jiti@2.6.1) + get-tsconfig: 4.10.1 + is-bun-module: 2.0.0 + stable-hash: 0.0.5 + tinyglobby: 0.2.15 + unrs-resolver: 1.11.1 + optionalDependencies: + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.29.0(jiti@2.6.1)) + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) + eslint: 9.29.0(jiti@2.6.1) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)) + transitivePeerDependencies: + - supports-color + + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.29.0(jiti@2.6.1)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.29.0(jiti@2.6.1) + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jsx-a11y@6.10.2(eslint@9.29.0(jiti@2.6.1)): + dependencies: + aria-query: 5.3.2 + array-includes: 3.1.9 + array.prototype.flatmap: 1.3.3 + ast-types-flow: 0.0.8 + axe-core: 4.11.0 + axobject-query: 4.1.0 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + eslint: 9.29.0(jiti@2.6.1) + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + safe-regex-test: 1.1.0 + string.prototype.includes: 2.0.1 + + eslint-plugin-react-hooks@7.0.1(eslint@9.29.0(jiti@2.6.1)): + dependencies: + '@babel/core': 7.28.5 + '@babel/parser': 7.28.5 + eslint: 9.29.0(jiti@2.6.1) + hermes-parser: 0.25.1 + zod: 4.1.12 + zod-validation-error: 4.0.1(zod@4.1.12) + transitivePeerDependencies: + - supports-color + + eslint-plugin-react@7.37.5(eslint@9.29.0(jiti@2.6.1)): + dependencies: + array-includes: 3.1.9 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.1 + eslint: 9.29.0(jiti@2.6.1) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 @@ -9233,6 +11092,14 @@ snapshots: fast-fifo@1.3.2: {} + fast-glob@3.3.1: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -9356,6 +11223,10 @@ snapshots: flatted@3.3.3: {} + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 @@ -9394,8 +11265,21 @@ snapshots: function-bind@1.1.2: {} + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + fuse.js@7.1.0: {} + generator-function@2.0.1: {} + gensync@1.0.0-beta.2: {} get-caller-file@2.0.5: {} @@ -9427,6 +11311,12 @@ snapshots: '@sec-ant/readable-stream': 0.4.1 is-stream: 4.0.1 + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + get-tsconfig@4.10.1: dependencies: resolve-pkg-maps: 1.0.0 @@ -9483,6 +11373,13 @@ snapshots: globals@14.0.0: {} + globals@16.4.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + globby@15.0.0: dependencies: '@sindresorhus/merge-streams': 4.0.0 @@ -9514,12 +11411,24 @@ snapshots: ufo: 1.6.1 uncrypto: 0.1.3 + happy-dom@20.0.10: + dependencies: + '@types/node': 20.17.24 + '@types/whatwg-mimetype': 3.0.2 + whatwg-mimetype: 3.0.0 + + has-bigints@1.1.0: {} + has-flag@4.0.0: {} has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.1 + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + has-symbols@1.1.0: {} has-tostringtag@1.0.2: @@ -9530,10 +11439,21 @@ snapshots: dependencies: function-bind: 1.1.2 + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + hono@4.10.3: {} hookable@5.5.3: {} + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + optional: true + http-errors@2.0.0: dependencies: depd: 2.0.0 @@ -9542,6 +11462,14 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + optional: true + http-shutdown@1.2.2: {} https-proxy-agent@5.0.0: @@ -9601,6 +11529,12 @@ snapshots: ini@4.1.1: {} + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + ioredis@5.8.2: dependencies: '@ioredis/commands': 1.4.0 @@ -9621,18 +11555,70 @@ snapshots: iron-webcrypto@1.2.1: {} + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-bun-module@2.0.0: + dependencies: + semver: 7.7.3 + + is-callable@1.2.7: {} + is-core-module@2.16.1: dependencies: hasown: 2.0.2 + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-docker@2.2.1: {} is-docker@3.0.0: {} is-extglob@2.1.1: {} + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + is-fullwidth-code-point@3.0.0: {} + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -9648,14 +11634,28 @@ snapshots: is-interactive@1.0.0: {} + is-map@2.0.3: {} + is-module@1.0.0: {} + is-negative-zero@2.0.3: {} + + is-node-process@1.2.0: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-number@7.0.0: {} is-path-inside@4.0.0: {} is-plain-obj@4.1.0: {} + is-potential-custom-element-name@1.0.1: + optional: true + is-promise@4.0.0: {} is-reference@1.2.1: @@ -9666,6 +11666,19 @@ snapshots: dependencies: '@types/estree': 1.0.8 + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + is-ssh@1.4.1: dependencies: protocols: 2.0.2 @@ -9676,12 +11689,38 @@ snapshots: is-stream@4.0.1: {} + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.19 + is-unicode-supported@0.1.0: {} is-unicode-supported@2.1.0: {} is-wayland@0.1.0: {} + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-what@5.5.0: {} is-wsl@2.2.0: @@ -9704,6 +11743,15 @@ snapshots: isexe@3.1.1: {} + iterator.prototype@1.1.5: + dependencies: + define-data-property: 1.1.4 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -9728,6 +11776,34 @@ snapshots: dependencies: argparse: 2.0.1 + jsdom@27.1.0: + dependencies: + '@acemir/cssom': 0.9.19 + '@asamuzakjp/dom-selector': 6.7.4 + cssstyle: 5.3.2 + data-urls: 6.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + parse5: 8.0.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + ws: 8.18.3 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + optional: true + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -9750,6 +11826,12 @@ snapshots: jsonify: 0.0.1 object-keys: 1.1.1 + json-stringify-safe@5.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + json5@2.2.3: {} jsonfile@6.1.0: @@ -9762,6 +11844,13 @@ snapshots: jsonschema@1.4.1: {} + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.9 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -9799,6 +11888,12 @@ snapshots: vscode-languageserver-textdocument: 1.0.12 vscode-uri: 3.0.8 + language-subtag-registry@0.3.23: {} + + language-tags@1.0.9: + dependencies: + language-subtag-registry: 0.3.23 + launch-editor@2.12.0: dependencies: picocolors: 1.1.1 @@ -9819,6 +11914,55 @@ snapshots: process-warning: 4.0.1 set-cookie-parser: 2.7.2 + lightningcss-android-arm64@1.30.2: + optional: true + + lightningcss-darwin-arm64@1.30.2: + optional: true + + lightningcss-darwin-x64@1.30.2: + optional: true + + lightningcss-freebsd-x64@1.30.2: + optional: true + + lightningcss-linux-arm-gnueabihf@1.30.2: + optional: true + + lightningcss-linux-arm64-gnu@1.30.2: + optional: true + + lightningcss-linux-arm64-musl@1.30.2: + optional: true + + lightningcss-linux-x64-gnu@1.30.2: + optional: true + + lightningcss-linux-x64-musl@1.30.2: + optional: true + + lightningcss-win32-arm64-msvc@1.30.2: + optional: true + + lightningcss-win32-x64-msvc@1.30.2: + optional: true + + lightningcss@1.30.2: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.30.2 + lightningcss-darwin-arm64: 1.30.2 + lightningcss-darwin-x64: 1.30.2 + lightningcss-freebsd-x64: 1.30.2 + lightningcss-linux-arm-gnueabihf: 1.30.2 + lightningcss-linux-arm64-gnu: 1.30.2 + lightningcss-linux-arm64-musl: 1.30.2 + lightningcss-linux-x64-gnu: 1.30.2 + lightningcss-linux-x64-musl: 1.30.2 + lightningcss-win32-arm64-msvc: 1.30.2 + lightningcss-win32-x64-msvc: 1.30.2 + lilconfig@3.1.3: {} lines-and-columns@1.2.4: {} @@ -9879,16 +12023,29 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lorem-ipsum@2.0.8: + dependencies: + commander: 9.5.0 + loupe@3.1.4: {} lru-cache@10.4.3: {} lru-cache@11.1.0: {} + lru-cache@11.2.2: + optional: true + lru-cache@5.1.1: dependencies: yallist: 3.1.1 + lz-string@1.5.0: {} + magic-regexp@0.10.0: dependencies: estree-walker: 3.0.3 @@ -10044,28 +12201,30 @@ snapshots: napi-build-utils@2.0.0: {} + napi-postinstall@0.3.4: {} + natural-compare@1.4.0: {} negotiator@1.0.0: {} - next@15.5.6(@babel/core@7.28.5)(react-dom@19.2.0(react@19.1.0))(react@19.1.0): + next@16.0.1(@babel/core@7.28.5)(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - '@next/env': 15.5.6 + '@next/env': 16.0.1 '@swc/helpers': 0.5.15 caniuse-lite: 1.0.30001751 postcss: 8.4.31 - react: 19.1.0 - react-dom: 19.2.0(react@19.1.0) - styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.1.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.2.0) optionalDependencies: - '@next/swc-darwin-arm64': 15.5.6 - '@next/swc-darwin-x64': 15.5.6 - '@next/swc-linux-arm64-gnu': 15.5.6 - '@next/swc-linux-arm64-musl': 15.5.6 - '@next/swc-linux-x64-gnu': 15.5.6 - '@next/swc-linux-x64-musl': 15.5.6 - '@next/swc-win32-arm64-msvc': 15.5.6 - '@next/swc-win32-x64-msvc': 15.5.6 + '@next/swc-darwin-arm64': 16.0.1 + '@next/swc-darwin-x64': 16.0.1 + '@next/swc-linux-arm64-gnu': 16.0.1 + '@next/swc-linux-arm64-musl': 16.0.1 + '@next/swc-linux-x64-gnu': 16.0.1 + '@next/swc-linux-x64-musl': 16.0.1 + '@next/swc-win32-arm64-msvc': 16.0.1 + '@next/swc-win32-x64-msvc': 16.0.1 sharp: 0.34.4 transitivePeerDependencies: - '@babel/core' @@ -10173,9 +12332,15 @@ snapshots: - supports-color - uploadthing + nock@14.0.10: + dependencies: + '@mswjs/interceptors': 0.39.8 + json-stringify-safe: 5.0.1 + propagate: 2.0.1 + node-abi@3.73.0: dependencies: - semver: 7.7.2 + semver: 7.7.3 node-addon-api@7.1.1: {} @@ -10214,16 +12379,16 @@ snapshots: dependencies: boolbase: 1.0.0 - nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1): + nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1): dependencies: '@dxup/nuxt': 0.2.0(magicast@0.5.0) '@nuxt/cli': 3.29.3(magicast@0.5.0) - '@nuxt/devtools': 2.7.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)) + '@nuxt/devtools': 2.7.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)) '@nuxt/kit': 4.2.0(magicast@0.5.0) - '@nuxt/nitro-server': 4.2.0(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(ioredis@5.8.2)(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1))(typescript@5.8.3) + '@nuxt/nitro-server': 4.2.0(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(ioredis@5.8.2)(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1))(typescript@5.8.3) '@nuxt/schema': 4.2.0 '@nuxt/telemetry': 2.6.6(magicast@0.5.0) - '@nuxt/vite-builder': 4.2.0(@types/node@20.17.24)(eslint@9.29.0(jiti@2.6.1))(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vue@3.5.22(typescript@5.8.3))(yaml@2.8.1) + '@nuxt/vite-builder': 4.2.0(@types/node@20.17.24)(eslint@9.29.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@20.17.24)(@vue/compiler-sfc@3.5.22)(better-sqlite3@12.2.0)(db0@0.3.4(better-sqlite3@12.2.0))(eslint@9.29.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(tsx@4.20.3)(typescript@5.8.3)(vue@3.5.22(typescript@5.8.3))(yaml@2.8.1) '@unhead/vue': 2.0.19(vue@3.5.22(typescript@5.8.3)) '@vue/shared': 3.5.22 c12: 3.3.1(magicast@0.5.0) @@ -10356,6 +12521,42 @@ snapshots: object-keys@1.1.1: {} + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + obuf@1.1.2: {} ofetch@1.5.0: @@ -10422,6 +12623,14 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 + outvariant@1.4.3: {} + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + oxc-minify@0.95.0: optionalDependencies: '@oxc-minify/binding-android-arm64': 0.95.0 @@ -10510,6 +12719,11 @@ snapshots: '@types/parse-path': 7.1.0 parse-path: 7.1.0 + parse5@8.0.0: + dependencies: + entities: 6.0.1 + optional: true + parseurl@1.3.3: {} path-browserify@1.0.1: {} @@ -10643,6 +12857,8 @@ snapshots: pluralize@8.0.0: {} + possible-typed-array-names@1.1.0: {} + postcss-calc@10.1.1(postcss@8.5.6): dependencies: postcss: 8.5.6 @@ -10844,7 +13060,7 @@ snapshots: prebuild-install@7.1.3: dependencies: - detect-libc: 2.0.3 + detect-libc: 2.1.2 expand-template: 2.0.3 github-from-package: 0.0.0 minimist: 1.2.8 @@ -10863,6 +13079,12 @@ snapshots: pretty-bytes@7.1.0: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + pretty-ms@9.3.0: dependencies: parse-ms: 4.0.0 @@ -10889,6 +13111,14 @@ snapshots: kleur: 3.0.3 sisteransi: 1.0.5 + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + propagate@2.0.1: {} + protocols@2.0.2: {} proxy-addr@2.0.7: @@ -10948,12 +13178,16 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - react-dom@19.2.0(react@19.1.0): + react-dom@19.2.0(react@19.2.0): dependencies: - react: 19.1.0 + react: 19.2.0 scheduler: 0.27.0 - react@19.1.0: {} + react-is@16.13.1: {} + + react-is@17.0.2: {} + + react@19.2.0: {} readable-stream@2.3.8: dependencies: @@ -10993,8 +13227,28 @@ snapshots: dependencies: redis-errors: 1.2.0 + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + regexp-tree@0.1.27: {} + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -11011,6 +13265,12 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + resolve@2.0.0-next.5: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + restore-cursor@3.1.0: dependencies: onetime: 5.1.2 @@ -11105,10 +13365,29 @@ snapshots: dependencies: mri: 1.2.0 + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + safe-buffer@5.1.2: {} safe-buffer@5.2.1: {} + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + safe-regex2@5.0.0: dependencies: ret: 0.5.0 @@ -11119,6 +13398,11 @@ snapshots: sax@1.4.1: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + optional: true + scheduler@0.27.0: {} scule@1.3.0: {} @@ -11177,13 +13461,26 @@ snapshots: gopd: 1.2.0 has-property-descriptors: 1.0.2 + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + setprototypeof@1.2.0: {} sharp@0.34.4: dependencies: '@img/colour': 1.0.0 detect-libc: 2.1.2 - semver: 7.7.2 + semver: 7.7.3 optionalDependencies: '@img/sharp-darwin-arm64': 0.34.4 '@img/sharp-darwin-x64': 0.34.4 @@ -11306,6 +13603,8 @@ snapshots: srvx@0.8.16: {} + stable-hash@0.0.5: {} + stackback@0.0.2: {} standard-as-callback@2.1.0: {} @@ -11316,6 +13615,11 @@ snapshots: std-env@3.9.0: {} + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + streamx@2.23.0: dependencies: events-universal: 1.0.1 @@ -11325,6 +13629,8 @@ snapshots: - bare-abort-controller - react-native-b4a + strict-event-emitter@0.5.1: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -11337,6 +13643,56 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 + string.prototype.includes@2.0.1: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.24.0 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 @@ -11353,6 +13709,8 @@ snapshots: dependencies: ansi-regex: 6.1.0 + strip-bom@3.0.0: {} + strip-final-newline@3.0.0: {} strip-final-newline@4.0.0: {} @@ -11375,10 +13733,10 @@ snapshots: structured-clone-es@1.0.0: {} - styled-jsx@5.1.6(@babel/core@7.28.5)(react@19.1.0): + styled-jsx@5.1.6(@babel/core@7.28.5)(react@19.2.0): dependencies: client-only: 0.0.1 - react: 19.1.0 + react: 19.2.0 optionalDependencies: '@babel/core': 7.28.5 @@ -11458,10 +13816,17 @@ snapshots: picocolors: 1.1.1 sax: 1.4.1 + symbol-tree@3.2.4: + optional: true + system-architecture@0.1.0: {} tagged-tag@1.0.0: {} + tailwindcss@4.1.16: {} + + tapable@2.3.0: {} + tar-fs@2.1.2: dependencies: chownr: 1.1.4 @@ -11543,6 +13908,14 @@ snapshots: tinyspy@4.0.3: {} + tldts-core@7.0.17: + optional: true + + tldts@7.0.17: + dependencies: + tldts-core: 7.0.17 + optional: true + tmp@0.2.3: {} to-regex-range@5.0.1: @@ -11563,12 +13936,22 @@ snapshots: totalist@3.0.1: {} + tough-cookie@6.0.0: + dependencies: + tldts: 7.0.17 + optional: true + tr46@0.0.3: {} tr46@1.0.1: dependencies: punycode: 2.3.1 + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + optional: true + tree-kill@1.2.2: {} ts-api-utils@2.1.0(typescript@5.8.3): @@ -11581,6 +13964,13 @@ snapshots: ts-pattern@5.7.1: {} + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + tslib@2.8.1: {} tsup@8.5.0(@swc/core@1.12.5)(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0): @@ -11666,6 +14056,39 @@ snapshots: type-level-regexp@0.1.17: {} + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + typescript-eslint@8.34.1(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3): dependencies: '@typescript-eslint/eslint-plugin': 8.34.1(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) @@ -11676,6 +14099,17 @@ snapshots: transitivePeerDependencies: - supports-color + typescript-eslint@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/parser': 8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.8.3) + '@typescript-eslint/utils': 8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3) + eslint: 9.29.0(jiti@2.6.1) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + typescript@5.8.3: {} ufo@1.6.1: {} @@ -11686,6 +14120,13 @@ snapshots: ultrahtml@1.6.0: {} + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + uncrypto@0.1.3: {} unctx@2.4.1: @@ -11773,6 +14214,30 @@ snapshots: picomatch: 4.0.3 webpack-virtual-modules: 0.6.2 + unrs-resolver@1.11.1: + dependencies: + napi-postinstall: 0.3.4 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + unstorage@1.17.1(db0@0.3.4(better-sqlite3@12.2.0))(ioredis@5.8.2): dependencies: anymatch: 3.1.3 @@ -11830,23 +14295,23 @@ snapshots: vary@1.1.2: {} - vite-dev-rpc@1.1.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)): + vite-dev-rpc@1.1.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)): dependencies: birpc: 2.6.1 - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) - vite-hot-client: 2.1.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite-hot-client: 2.1.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) - vite-hot-client@2.1.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)): + vite-hot-client@2.1.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)): dependencies: - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) - vite-node@3.2.4(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0): + vite-node@3.2.4(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0): dependencies: cac: 6.7.14 debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) + vite: 6.3.5(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - jiti @@ -11861,13 +14326,13 @@ snapshots: - tsx - yaml - vite-node@3.2.4(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1): + vite-node@3.2.4(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1): dependencies: cac: 6.7.14 debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite: 6.3.5(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -11882,7 +14347,7 @@ snapshots: - tsx - yaml - vite-plugin-checker@0.11.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)): + vite-plugin-checker@0.11.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@5.8.3)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)): dependencies: '@babel/code-frame': 7.27.1 chokidar: 4.0.3 @@ -11891,14 +14356,14 @@ snapshots: picomatch: 4.0.3 tiny-invariant: 1.3.3 tinyglobby: 0.2.15 - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) vscode-uri: 3.1.0 optionalDependencies: eslint: 9.29.0(jiti@2.6.1) optionator: 0.9.4 typescript: 5.8.3 - vite-plugin-inspect@11.3.3(@nuxt/kit@3.20.0(magicast@0.3.5))(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)): + vite-plugin-inspect@11.3.3(@nuxt/kit@3.20.0(magicast@0.3.5))(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)): dependencies: ansis: 4.2.0 debug: 4.4.1 @@ -11908,24 +14373,24 @@ snapshots: perfect-debounce: 2.0.0 sirv: 3.0.2 unplugin-utils: 0.3.1 - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) - vite-dev-rpc: 1.1.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite-dev-rpc: 1.1.0(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) optionalDependencies: '@nuxt/kit': 3.20.0(magicast@0.3.5) transitivePeerDependencies: - supports-color - vite-plugin-vue-tracer@1.0.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)): + vite-plugin-vue-tracer@1.0.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.3)): dependencies: estree-walker: 3.0.3 exsolve: 1.0.7 magic-string: 0.30.21 pathe: 2.0.3 source-map-js: 1.2.1 - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) vue: 3.5.22(typescript@5.8.3) - vite@6.3.5(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0): + vite@6.3.5(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0): dependencies: esbuild: 0.25.5 fdir: 6.4.6(picomatch@4.0.2) @@ -11937,11 +14402,12 @@ snapshots: '@types/node': 20.17.24 fsevents: 2.3.3 jiti: 2.6.1 + lightningcss: 1.30.2 terser: 5.44.0 tsx: 4.20.3 yaml: 2.8.0 - vite@6.3.5(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1): + vite@6.3.5(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1): dependencies: esbuild: 0.25.5 fdir: 6.4.6(picomatch@4.0.2) @@ -11953,11 +14419,12 @@ snapshots: '@types/node': 20.17.24 fsevents: 2.3.3 jiti: 2.6.1 + lightningcss: 1.30.2 terser: 5.44.0 tsx: 4.20.3 yaml: 2.8.1 - vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1): + vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1): dependencies: esbuild: 0.25.11 fdir: 6.5.0(picomatch@4.0.3) @@ -11969,19 +14436,20 @@ snapshots: '@types/node': 20.17.24 fsevents: 2.3.3 jiti: 2.6.1 + lightningcss: 1.30.2 terser: 5.44.0 tsx: 4.20.3 yaml: 2.8.1 - vitefu@1.1.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)): + vitefu@1.1.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)): optionalDependencies: - vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) - vitest@3.2.4(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0): + vitest@3.2.4(@types/node@20.17.24)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0)) + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -11999,11 +14467,13 @@ snapshots: tinyglobby: 0.2.14 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.5(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) - vite-node: 3.2.4(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) + vite: 6.3.5(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) + vite-node: 3.2.4(@types/node@20.17.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.17.24 + happy-dom: 20.0.10 + jsdom: 27.1.0 transitivePeerDependencies: - jiti - less @@ -12064,6 +14534,11 @@ snapshots: optionalDependencies: typescript: 5.8.3 + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + optional: true + wcwidth@1.0.1: dependencies: defaults: 1.0.4 @@ -12072,8 +14547,27 @@ snapshots: webidl-conversions@4.0.2: {} + webidl-conversions@8.0.0: + optional: true + webpack-virtual-modules@0.6.2: {} + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + optional: true + + whatwg-mimetype@3.0.0: {} + + whatwg-mimetype@4.0.0: + optional: true + + whatwg-url@15.1.0: + dependencies: + tr46: 6.0.0 + webidl-conversions: 8.0.0 + optional: true + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -12085,6 +14579,47 @@ snapshots: tr46: 1.0.1 webidl-conversions: 4.0.2 + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.19: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + which@2.0.2: dependencies: isexe: 2.0.0 @@ -12120,6 +14655,12 @@ snapshots: dependencies: is-wsl: 3.1.0 + xml-name-validator@5.0.0: + optional: true + + xmlchars@2.2.0: + optional: true + xtend@4.0.2: {} y18n@5.0.8: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a702ade3..2fbbf861 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -15,5 +15,12 @@ catalog: '@types/tmp': ^0.2.6 'zod-validation-error': ^4.0.1 'better-sqlite3': ^12.2.0 + '@types/better-sqlite3': ^7.6.13 'pg': ^8.13.1 'decimal.js': '^10.4.3' + react: 19.2.0 + '@types/react': 19.2.0 + react-dom: 19.2.0 + '@types/react-dom': 19.2.0 + '@tanstack/react-query': 5.90.6 + 'next': 16.0.1 diff --git a/samples/next.js/.gitignore b/samples/next.js/.gitignore new file mode 100644 index 00000000..5ef6a520 --- /dev/null +++ b/samples/next.js/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/samples/next.js/README.md b/samples/next.js/README.md new file mode 100644 index 00000000..a88892ae --- /dev/null +++ b/samples/next.js/README.md @@ -0,0 +1,7 @@ +This is a sample project demonstrating using [Next.js](https://nextjs.org) and [TanStack Query](https://tanstack.com/query) with [ZenStack v3](https://zenstack.dev/v3). + +## Getting Started + +- pnpm install +- pnpm db:init +- pnpm dev diff --git a/samples/next.js/app/api/model/[...path]/route.ts b/samples/next.js/app/api/model/[...path]/route.ts new file mode 100644 index 00000000..49ba5ff5 --- /dev/null +++ b/samples/next.js/app/api/model/[...path]/route.ts @@ -0,0 +1,14 @@ +import { db } from '@/lib/db'; +import { schema } from '@/zenstack/schema'; +import { RPCApiHandler } from '@zenstackhq/server/api'; +import { NextRequestHandler } from '@zenstackhq/server/next'; + +const handler = NextRequestHandler({ + apiHandler: new RPCApiHandler({ schema }), + // fully open ZenStackClient is used here for demo purposes only, in a real application, + // you should use one with access policies enabled + getClient: () => db, + useAppDir: true, +}); + +export { handler as DELETE, handler as GET, handler as PATCH, handler as POST, handler as PUT }; diff --git a/samples/next.js/app/favicon.ico b/samples/next.js/app/favicon.ico new file mode 100644 index 00000000..718d6fea Binary files /dev/null and b/samples/next.js/app/favicon.ico differ diff --git a/samples/next.js/app/globals.css b/samples/next.js/app/globals.css new file mode 100644 index 00000000..a2dc41ec --- /dev/null +++ b/samples/next.js/app/globals.css @@ -0,0 +1,26 @@ +@import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + background: var(--background); + color: var(--foreground); + font-family: Arial, Helvetica, sans-serif; +} diff --git a/samples/next.js/app/layout.tsx b/samples/next.js/app/layout.tsx new file mode 100644 index 00000000..7a6da3a5 --- /dev/null +++ b/samples/next.js/app/layout.tsx @@ -0,0 +1,27 @@ +import { Geist, Geist_Mono } from 'next/font/google'; +import './globals.css'; +import Providers from './providers'; + +const geistSans = Geist({ + variable: '--font-geist-sans', + subsets: ['latin'], +}); + +const geistMono = Geist_Mono({ + variable: '--font-geist-mono', + subsets: ['latin'], +}); + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + {children} + + + ); +} diff --git a/samples/next.js/app/page.tsx b/samples/next.js/app/page.tsx new file mode 100644 index 00000000..b411313c --- /dev/null +++ b/samples/next.js/app/page.tsx @@ -0,0 +1,97 @@ +'use client'; + +import { schema } from '@/zenstack/schema'; +import { useClientQueries } from '@zenstackhq/tanstack-query/react'; +import { LoremIpsum } from 'lorem-ipsum'; +import Image from 'next/image'; + +const lorem = new LoremIpsum({ wordsPerSentence: { max: 6, min: 4 } }); + +export default function Home() { + const clientQueries = useClientQueries(schema); + const { data: users, isFetched: isUsersFetched } = clientQueries.user.useFindMany(); + const { data: posts } = clientQueries.post.useFindMany({ + orderBy: { createdAt: 'desc' }, + include: { author: true }, + }); + const createPost = clientQueries.post.useCreate(); + const deletePost = clientQueries.post.useDelete(); + + const onCreatePost = () => { + if (!users) { + return; + } + + // random title + const title = lorem.generateWords(); + + // random user as author + const forUser = users[Math.floor(Math.random() * users.length)]; + + console.log('Creating post for user:', forUser.id, 'with title:', title); + createPost.mutate({ + data: { + title, + authorId: forUser.id, + }, + }); + }; + + const onDeletePost = (postId: string) => { + deletePost.mutate({ + where: { id: postId }, + }); + }; + + if (isUsersFetched && (!users || users.length === 0)) { + return
No users found. Please run "pnpm db:init" to seed the database.
; + } + + return ( +
+
+ Next.js logo +
+

+ My Awesome Blog +

+ + + +
+
Current users
+
+ {users?.map((user) => ( +
+ {user.email} +
+ ))} +
+
+ +
+ {posts?.map((post) => ( +
+
+

{post.title}

+ +
+

by {post.author.name}

+
+ ))} +
+
+
+
+ ); +} diff --git a/samples/next.js/app/providers.tsx b/samples/next.js/app/providers.tsx new file mode 100644 index 00000000..065bd039 --- /dev/null +++ b/samples/next.js/app/providers.tsx @@ -0,0 +1,15 @@ +'use client'; + +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { QuerySettingsProvider } from '@zenstackhq/tanstack-query/react'; +import type { ReactNode } from 'react'; + +const queryClient = new QueryClient(); + +export default function Providers({ children }: { children: ReactNode }) { + return ( + + {children} + + ); +} diff --git a/samples/next.js/eslint.config.mjs b/samples/next.js/eslint.config.mjs new file mode 100644 index 00000000..05e726d1 --- /dev/null +++ b/samples/next.js/eslint.config.mjs @@ -0,0 +1,18 @@ +import { defineConfig, globalIgnores } from "eslint/config"; +import nextVitals from "eslint-config-next/core-web-vitals"; +import nextTs from "eslint-config-next/typescript"; + +const eslintConfig = defineConfig([ + ...nextVitals, + ...nextTs, + // Override default ignores of eslint-config-next. + globalIgnores([ + // Default ignores of eslint-config-next: + ".next/**", + "out/**", + "build/**", + "next-env.d.ts", + ]), +]); + +export default eslintConfig; diff --git a/samples/next.js/lib/db.ts b/samples/next.js/lib/db.ts new file mode 100644 index 00000000..688e7886 --- /dev/null +++ b/samples/next.js/lib/db.ts @@ -0,0 +1,10 @@ +import { schema } from '@/zenstack/schema'; +import { ZenStackClient } from '@zenstackhq/orm'; +import SQLite from 'better-sqlite3'; +import { SqliteDialect } from 'kysely'; + +export const db = new ZenStackClient(schema, { + dialect: new SqliteDialect({ + database: new SQLite('./zenstack/dev.db'), + }), +}); diff --git a/samples/next.js/next.config.ts b/samples/next.js/next.config.ts new file mode 100644 index 00000000..e9ffa308 --- /dev/null +++ b/samples/next.js/next.config.ts @@ -0,0 +1,7 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + /* config options here */ +}; + +export default nextConfig; diff --git a/samples/next.js/package.json b/samples/next.js/package.json new file mode 100644 index 00000000..5dcd3e4f --- /dev/null +++ b/samples/next.js/package.json @@ -0,0 +1,37 @@ +{ + "name": "next.js", + "version": "0.1.0", + "private": true, + "scripts": { + "generate": "zen generate", + "db:init": "pnpm generate && zen db push && npx tsx zenstack/seed.ts", + "dev": "next dev", + "build": "pnpm generate && next build", + "start": "next start", + "lint": "eslint" + }, + "dependencies": { + "@tanstack/react-query": "catalog:", + "@zenstackhq/orm": "workspace:*", + "@zenstackhq/server": "workspace:*", + "@zenstackhq/tanstack-query": "workspace:*", + "better-sqlite3": "catalog:", + "kysely": "catalog:", + "lorem-ipsum": "^2.0.8", + "next": "16.0.1", + "react": "catalog:", + "react-dom": "catalog:" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/better-sqlite3": "catalog:", + "@types/node": "^20", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@zenstackhq/cli": "workspace:*", + "eslint": "^9", + "eslint-config-next": "16.0.1", + "tailwindcss": "^4", + "typescript": "^5" + } +} diff --git a/samples/next.js/postcss.config.mjs b/samples/next.js/postcss.config.mjs new file mode 100644 index 00000000..61e36849 --- /dev/null +++ b/samples/next.js/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/samples/next.js/public/file.svg b/samples/next.js/public/file.svg new file mode 100644 index 00000000..004145cd --- /dev/null +++ b/samples/next.js/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/next.js/public/globe.svg b/samples/next.js/public/globe.svg new file mode 100644 index 00000000..567f17b0 --- /dev/null +++ b/samples/next.js/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/next.js/public/next.svg b/samples/next.js/public/next.svg new file mode 100644 index 00000000..5174b28c --- /dev/null +++ b/samples/next.js/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/next.js/public/vercel.svg b/samples/next.js/public/vercel.svg new file mode 100644 index 00000000..77053960 --- /dev/null +++ b/samples/next.js/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/next.js/public/window.svg b/samples/next.js/public/window.svg new file mode 100644 index 00000000..b2b2a44f --- /dev/null +++ b/samples/next.js/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/next.js/tsconfig.json b/samples/next.js/tsconfig.json new file mode 100644 index 00000000..3a13f90a --- /dev/null +++ b/samples/next.js/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts", + "**/*.mts" + ], + "exclude": ["node_modules"] +} diff --git a/samples/next.js/zenstack/input.ts b/samples/next.js/zenstack/input.ts new file mode 100644 index 00000000..6c876632 --- /dev/null +++ b/samples/next.js/zenstack/input.ts @@ -0,0 +1,50 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT MODIFY THIS FILE // +// This file is automatically generated by ZenStack CLI and should not be manually updated. // +////////////////////////////////////////////////////////////////////////////////////////////// + +/* eslint-disable */ + +import { type SchemaType as $Schema } from "./schema"; +import type { FindManyArgs as $FindManyArgs, FindUniqueArgs as $FindUniqueArgs, FindFirstArgs as $FindFirstArgs, CreateArgs as $CreateArgs, CreateManyArgs as $CreateManyArgs, CreateManyAndReturnArgs as $CreateManyAndReturnArgs, UpdateArgs as $UpdateArgs, UpdateManyArgs as $UpdateManyArgs, UpdateManyAndReturnArgs as $UpdateManyAndReturnArgs, UpsertArgs as $UpsertArgs, DeleteArgs as $DeleteArgs, DeleteManyArgs as $DeleteManyArgs, CountArgs as $CountArgs, AggregateArgs as $AggregateArgs, GroupByArgs as $GroupByArgs, WhereInput as $WhereInput, SelectInput as $SelectInput, IncludeInput as $IncludeInput, OmitInput as $OmitInput } from "@zenstackhq/orm"; +import type { SimplifiedModelResult as $SimplifiedModelResult, SelectIncludeOmit as $SelectIncludeOmit } from "@zenstackhq/orm"; +export type UserFindManyArgs = $FindManyArgs<$Schema, "User">; +export type UserFindUniqueArgs = $FindUniqueArgs<$Schema, "User">; +export type UserFindFirstArgs = $FindFirstArgs<$Schema, "User">; +export type UserCreateArgs = $CreateArgs<$Schema, "User">; +export type UserCreateManyArgs = $CreateManyArgs<$Schema, "User">; +export type UserCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "User">; +export type UserUpdateArgs = $UpdateArgs<$Schema, "User">; +export type UserUpdateManyArgs = $UpdateManyArgs<$Schema, "User">; +export type UserUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "User">; +export type UserUpsertArgs = $UpsertArgs<$Schema, "User">; +export type UserDeleteArgs = $DeleteArgs<$Schema, "User">; +export type UserDeleteManyArgs = $DeleteManyArgs<$Schema, "User">; +export type UserCountArgs = $CountArgs<$Schema, "User">; +export type UserAggregateArgs = $AggregateArgs<$Schema, "User">; +export type UserGroupByArgs = $GroupByArgs<$Schema, "User">; +export type UserWhereInput = $WhereInput<$Schema, "User">; +export type UserSelect = $SelectInput<$Schema, "User">; +export type UserInclude = $IncludeInput<$Schema, "User">; +export type UserOmit = $OmitInput<$Schema, "User">; +export type UserGetPayload> = $SimplifiedModelResult<$Schema, "User", Args>; +export type PostFindManyArgs = $FindManyArgs<$Schema, "Post">; +export type PostFindUniqueArgs = $FindUniqueArgs<$Schema, "Post">; +export type PostFindFirstArgs = $FindFirstArgs<$Schema, "Post">; +export type PostCreateArgs = $CreateArgs<$Schema, "Post">; +export type PostCreateManyArgs = $CreateManyArgs<$Schema, "Post">; +export type PostCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "Post">; +export type PostUpdateArgs = $UpdateArgs<$Schema, "Post">; +export type PostUpdateManyArgs = $UpdateManyArgs<$Schema, "Post">; +export type PostUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "Post">; +export type PostUpsertArgs = $UpsertArgs<$Schema, "Post">; +export type PostDeleteArgs = $DeleteArgs<$Schema, "Post">; +export type PostDeleteManyArgs = $DeleteManyArgs<$Schema, "Post">; +export type PostCountArgs = $CountArgs<$Schema, "Post">; +export type PostAggregateArgs = $AggregateArgs<$Schema, "Post">; +export type PostGroupByArgs = $GroupByArgs<$Schema, "Post">; +export type PostWhereInput = $WhereInput<$Schema, "Post">; +export type PostSelect = $SelectInput<$Schema, "Post">; +export type PostInclude = $IncludeInput<$Schema, "Post">; +export type PostOmit = $OmitInput<$Schema, "Post">; +export type PostGetPayload> = $SimplifiedModelResult<$Schema, "Post", Args>; diff --git a/samples/next.js/zenstack/models.ts b/samples/next.js/zenstack/models.ts new file mode 100644 index 00000000..80be7341 --- /dev/null +++ b/samples/next.js/zenstack/models.ts @@ -0,0 +1,17 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT MODIFY THIS FILE // +// This file is automatically generated by ZenStack CLI and should not be manually updated. // +////////////////////////////////////////////////////////////////////////////////////////////// + +/* eslint-disable */ + +import { type SchemaType as $Schema } from "./schema"; +import { type ModelResult as $ModelResult } from "@zenstackhq/orm"; +/** + * User model + */ +export type User = $ModelResult<$Schema, "User">; +/** + * Post model + */ +export type Post = $ModelResult<$Schema, "Post">; diff --git a/samples/next.js/zenstack/schema.ts b/samples/next.js/zenstack/schema.ts new file mode 100644 index 00000000..8a6632b0 --- /dev/null +++ b/samples/next.js/zenstack/schema.ts @@ -0,0 +1,115 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT MODIFY THIS FILE // +// This file is automatically generated by ZenStack CLI and should not be manually updated. // +////////////////////////////////////////////////////////////////////////////////////////////// + +/* eslint-disable */ + +import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; +export const schema = { + provider: { + type: "sqlite" + }, + models: { + User: { + name: "User", + fields: { + id: { + name: "id", + type: "String", + id: true, + attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }], + default: ExpressionUtils.call("cuid") + }, + createdAt: { + name: "createdAt", + type: "DateTime", + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("now") }] }], + default: ExpressionUtils.call("now") + }, + updatedAt: { + name: "updatedAt", + type: "DateTime", + updatedAt: true, + attributes: [{ name: "@updatedAt" }] + }, + email: { + name: "email", + type: "String", + unique: true, + attributes: [{ name: "@unique" }] + }, + name: { + name: "name", + type: "String", + optional: true + }, + posts: { + name: "posts", + type: "Post", + array: true, + relation: { opposite: "author" } + } + }, + idFields: ["id"], + uniqueFields: { + id: { type: "String" }, + email: { type: "String" } + } + }, + Post: { + name: "Post", + fields: { + id: { + name: "id", + type: "String", + id: true, + attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }], + default: ExpressionUtils.call("cuid") + }, + createdAt: { + name: "createdAt", + type: "DateTime", + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("now") }] }], + default: ExpressionUtils.call("now") + }, + updatedAt: { + name: "updatedAt", + type: "DateTime", + updatedAt: true, + attributes: [{ name: "@updatedAt" }] + }, + title: { + name: "title", + type: "String" + }, + published: { + name: "published", + type: "Boolean", + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.literal(false) }] }], + default: false + }, + author: { + name: "author", + type: "User", + attributes: [{ name: "@relation", args: [{ name: "fields", value: ExpressionUtils.array([ExpressionUtils.field("authorId")]) }, { name: "references", value: ExpressionUtils.array([ExpressionUtils.field("id")]) }, { name: "onUpdate", value: ExpressionUtils.literal("Cascade") }, { name: "onDelete", value: ExpressionUtils.literal("Cascade") }] }], + relation: { opposite: "posts", fields: ["authorId"], references: ["id"], onUpdate: "Cascade", onDelete: "Cascade" } + }, + authorId: { + name: "authorId", + type: "String", + foreignKeyFor: [ + "author" + ] + } + }, + idFields: ["id"], + uniqueFields: { + id: { type: "String" } + } + } + }, + authType: "User", + plugins: {} +} as const satisfies SchemaDef; +export type SchemaType = typeof schema; diff --git a/samples/next.js/zenstack/schema.zmodel b/samples/next.js/zenstack/schema.zmodel new file mode 100644 index 00000000..e1775e12 --- /dev/null +++ b/samples/next.js/zenstack/schema.zmodel @@ -0,0 +1,25 @@ +datasource db { + provider = 'sqlite' + url = 'file:./dev.db' +} + +/// User model +model User { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + email String @unique + name String? + posts Post[] +} + +/// Post model +model Post { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + title String + published Boolean @default(false) + author User @relation(fields: [authorId], references: [id], onUpdate: Cascade, onDelete: Cascade) + authorId String +} diff --git a/samples/next.js/zenstack/seed.ts b/samples/next.js/zenstack/seed.ts new file mode 100644 index 00000000..6e02d80d --- /dev/null +++ b/samples/next.js/zenstack/seed.ts @@ -0,0 +1,23 @@ +import { ZenStackClient } from '@zenstackhq/orm'; +import SQLite from 'better-sqlite3'; +import { SqliteDialect } from 'kysely'; +import { schema } from './schema'; + +async function main() { + const db = new ZenStackClient(schema, { + dialect: new SqliteDialect({ + database: new SQLite('./zenstack/dev.db'), + }), + }); + + await db.user.deleteMany(); + + await db.user.createMany({ + data: [ + { id: '1', name: 'Alice', email: 'alice@example.com' }, + { id: '2', name: 'Bob', email: 'bob@example.com' }, + ], + }); +} + +main(); diff --git a/samples/blog/.gitignore b/samples/orm/.gitignore similarity index 100% rename from samples/blog/.gitignore rename to samples/orm/.gitignore diff --git a/samples/blog/README.md b/samples/orm/README.md similarity index 100% rename from samples/blog/README.md rename to samples/orm/README.md diff --git a/samples/blog/main.ts b/samples/orm/main.ts similarity index 100% rename from samples/blog/main.ts rename to samples/orm/main.ts diff --git a/samples/blog/package.json b/samples/orm/package.json similarity index 86% rename from samples/blog/package.json rename to samples/orm/package.json index aac2a675..f0137a6a 100644 --- a/samples/blog/package.json +++ b/samples/orm/package.json @@ -3,6 +3,7 @@ "version": "3.0.0-beta.15", "description": "", "main": "index.js", + "private": true, "scripts": { "generate": "zen generate", "db:push": "zen db push", @@ -16,11 +17,11 @@ "dependencies": { "@zenstackhq/orm": "workspace:*", "@zenstackhq/plugin-policy": "workspace:*", - "better-sqlite3": "^12.2.0", + "better-sqlite3": "catalog:", "kysely": "catalog:" }, "devDependencies": { - "@types/better-sqlite3": "^7.6.13", + "@types/better-sqlite3": "catalog:", "prisma": "catalog:", "@zenstackhq/cli": "workspace:*", "@zenstackhq/typescript-config": "workspace:*" diff --git a/samples/blog/tsconfig.json b/samples/orm/tsconfig.json similarity index 100% rename from samples/blog/tsconfig.json rename to samples/orm/tsconfig.json diff --git a/samples/blog/zenstack/input.ts b/samples/orm/zenstack/input.ts similarity index 100% rename from samples/blog/zenstack/input.ts rename to samples/orm/zenstack/input.ts diff --git a/samples/blog/zenstack/models.ts b/samples/orm/zenstack/models.ts similarity index 100% rename from samples/blog/zenstack/models.ts rename to samples/orm/zenstack/models.ts diff --git a/samples/blog/zenstack/schema.ts b/samples/orm/zenstack/schema.ts similarity index 100% rename from samples/blog/zenstack/schema.ts rename to samples/orm/zenstack/schema.ts diff --git a/samples/blog/zenstack/schema.zmodel b/samples/orm/zenstack/schema.zmodel similarity index 100% rename from samples/blog/zenstack/schema.zmodel rename to samples/orm/zenstack/schema.zmodel diff --git a/tests/regression/generate.ts b/tests/regression/generate.ts index 22959cda..07cbab0d 100644 --- a/tests/regression/generate.ts +++ b/tests/regression/generate.ts @@ -1,7 +1,6 @@ import { loadDocument } from '@zenstackhq/language'; import { TsSchemaGenerator } from '@zenstackhq/sdk'; import { glob } from 'glob'; -import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url';