diff --git a/packages/clients/tanstack-query/package.json b/packages/clients/tanstack-query/package.json index caba300f..6e0f775e 100644 --- a/packages/clients/tanstack-query/package.json +++ b/packages/clients/tanstack-query/package.json @@ -32,6 +32,20 @@ "types": "./dist/react.d.cts", "default": "./dist/react.cjs" } + }, + "./vue": { + "import": { + "types": "./dist/vue.d.ts", + "default": "./dist/vue.js" + }, + "require": { + "types": "./dist/vue.d.cts", + "default": "./dist/vue.cjs" + } + }, + "./package.json": { + "import": "./package.json", + "require": "./package.json" } }, "dependencies": { @@ -43,6 +57,7 @@ }, "devDependencies": { "@tanstack/react-query": "catalog:", + "@tanstack/vue-query": "5.90.6", "@testing-library/dom": "^10.4.1", "@testing-library/react": "^16.3.0", "@types/react": "catalog:", @@ -53,17 +68,18 @@ "@zenstackhq/vitest-config": "workspace:*", "happy-dom": "^20.0.10", "nock": "^14.0.10", - "react": "catalog:" + "react": "catalog:", + "vue": "catalog:" }, "peerDependencies": { "@tanstack/react-query": "^5.0.0", - "react": "^18 || ^19" + "@tanstack/vue-query": "^5.0.0" }, "peerDependenciesMeta": { "@tanstack/react-query": { "optional": true }, - "react": { + "@tanstack/vue-query": { "optional": true } } diff --git a/packages/clients/tanstack-query/src/react.ts b/packages/clients/tanstack-query/src/react.ts index d860f5b5..6e5de2fd 100644 --- a/packages/clients/tanstack-query/src/react.ts +++ b/packages/clients/tanstack-query/src/react.ts @@ -79,7 +79,7 @@ export const QuerySettingsProvider = QuerySettingsContext.Provider; /** * React context provider for configuring query settings. * - * @deprecated Use `QuerySettingsProvider` instead. + * @deprecated Use {@link QuerySettingsProvider} instead. */ export const Provider = QuerySettingsProvider; @@ -473,7 +473,7 @@ export function useInternalMutation< options?: Omit, 'mutationFn'> & ExtraMutationOptions, checkReadBack?: C, ) { - const { endpoint, fetch } = useHooksContext(); + const { endpoint, fetch, logging } = useHooksContext(); const queryClient = useQueryClient(); const mutationFn = (data: any) => { const reqUrl = @@ -493,7 +493,6 @@ export function useInternalMutation< const finalOptions = { ...options, mutationFn }; const invalidateQueries = options?.invalidateQueries !== false; const optimisticUpdate = !!options?.optimisticUpdate; - const { logging } = useContext(QuerySettingsContext); if (operation) { if (invalidateQueries) { diff --git a/packages/clients/tanstack-query/src/utils/common.ts b/packages/clients/tanstack-query/src/utils/common.ts index b26720ee..87fc8fe6 100644 --- a/packages/clients/tanstack-query/src/utils/common.ts +++ b/packages/clients/tanstack-query/src/utils/common.ts @@ -208,8 +208,8 @@ export function unmarshal(value: string) { } } -export function makeUrl(url: string, model: string, operation: string, args?: unknown) { - const baseUrl = `${url}/${lowerCaseFirst(model)}/${operation}`; +export function makeUrl(endpoint: string, model: string, operation: string, args?: unknown) { + const baseUrl = `${endpoint}/${lowerCaseFirst(model)}/${operation}`; if (!args) { return baseUrl; } diff --git a/packages/clients/tanstack-query/src/vue.ts b/packages/clients/tanstack-query/src/vue.ts new file mode 100644 index 00000000..742c58de --- /dev/null +++ b/packages/clients/tanstack-query/src/vue.ts @@ -0,0 +1,406 @@ +import { + useInfiniteQuery, + useMutation, + useQuery, + useQueryClient, + type DefaultError, + type InfiniteData, + type QueryKey, + type UseInfiniteQueryOptions, + type UseInfiniteQueryReturnType, + type UseMutationOptions, + type UseMutationReturnType, + type UseQueryOptions, + type UseQueryReturnType, +} from '@tanstack/vue-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 { inject, provide, toValue, type MaybeRefOrGetter, type UnwrapRef } from 'vue'; +import { + DEFAULT_QUERY_ENDPOINT, + fetcher, + getQueryKey, + makeUrl, + marshal, + setupInvalidation, + setupOptimisticUpdate, + type APIContext, + type ExtraMutationOptions, + type ExtraQueryOptions, +} from './utils/common'; + +export type { FetchFn } from './utils/common'; +export const VueQueryContextKey = 'zenstack-vue-query-context'; + +/** + * Provide context for query settings. + * + * @deprecated Use {@link provideQuerySettingsContext} instead. + */ +export function provideHooksContext(context: APIContext) { + provide(VueQueryContextKey, context); +} + +/** + * Provide context for query settings. + */ +export function provideQuerySettingsContext(context: APIContext) { + provide(VueQueryContextKey, context); +} + +function getQuerySettings() { + const { endpoint, ...rest } = inject(VueQueryContextKey, { + endpoint: DEFAULT_QUERY_ENDPOINT, + fetch: undefined, + logging: false, + }); + return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest }; +} + +export type ModelQueryOptions = Omit, 'queryKey'> & ExtraQueryOptions; + +export type ModelQueryResult = UseQueryReturnType & { queryKey: QueryKey }; + +export type ModelInfiniteQueryOptions = Omit< + UseInfiniteQueryOptions>, + 'queryKey' | 'initialPageParam' +>; + +export type ModelInfiniteQueryResult = UseInfiniteQueryReturnType & { queryKey: QueryKey }; + +export type ModelMutationOptions = Omit, 'mutationFn'> & + ExtraMutationOptions; + +export type ModelMutationResult = UseMutationReturnType; + +export type SchemaHooks = { + [Model in GetModels as `${Uncapitalize}`]: ModelQueryHooks; +}; + +export type ModelQueryHooks> = { + useFindUnique>( + args: SelectSubset>, + options?: ModelQueryOptions | null>, + ): ModelQueryResult | null>; + + useFindFirst>( + args?: SelectSubset>, + options?: ModelQueryOptions | null>, + ): ModelQueryResult | null>; + + useFindMany>( + args?: SelectSubset>, + options?: ModelQueryOptions[]>, + ): ModelQueryResult[]>; + + useInfiniteFindMany>( + args?: SelectSubset>, + options?: ModelInfiniteQueryOptions[]>, + ): ModelInfiniteQueryResult[]>>; + + 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>; + + useAggregate>( + options?: ModelQueryOptions>, + ): ModelQueryResult>; + + useGroupBy>( + options?: ModelQueryOptions>, + ): ModelQueryResult>; +}; + +/** + * 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); + }, + + useFindFirst: (args: any, options?: any) => { + return useInternalQuery(schema, modelName, 'findFirst', args, options); + }, + + useFindMany: (args: any, options?: any) => { + return useInternalQuery(schema, modelName, 'findMany', args, options); + }, + + useInfiniteFindMany: (args: any, options?: any) => { + return useInternalInfiniteQuery(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); + }, + + useAggregate: (options?: any) => { + return useInternalQuery(schema, modelName, 'aggregate', undefined, options); + }, + + useGroupBy: (options?: any) => { + return useInternalQuery(schema, modelName, 'groupBy', undefined, options); + }, + } as ModelQueryHooks; +} + +export function useInternalQuery( + _schema: SchemaDef, + model: string, + operation: string, + args?: MaybeRefOrGetter, + options?: MaybeRefOrGetter< + Omit>, 'queryKey'> & ExtraQueryOptions + >, +) { + const argsValue = toValue(args); + const { optimisticUpdate, ...restOptions } = toValue(options) ?? {}; + const queryKey = getQueryKey(model, operation, argsValue, { + infinite: false, + optimisticUpdate: optimisticUpdate !== false, + }); + const { endpoint, fetch } = getQuerySettings(); + + const finalOptions: any = { + queryKey, + queryFn: ({ queryKey, signal }: any) => { + const [_prefix, _model, _op, args] = queryKey; + const reqUrl = makeUrl(endpoint, model, operation, args); + return fetcher(reqUrl, { signal }, fetch, false); + }, + ...restOptions, + }; + return { queryKey, ...useQuery(finalOptions) }; +} + +export function useInternalInfiniteQuery( + _schema: SchemaDef, + model: string, + operation: string, + args: MaybeRefOrGetter, + options: MaybeRefOrGetter< + Omit< + UnwrapRef>>, + 'queryKey' | 'initialPageParam' + > + >, +) { + const { endpoint, fetch } = getQuerySettings(); + const argsValue = toValue(args); + const optionsValue = toValue(options); + const queryKey = getQueryKey(model, operation, argsValue, { infinite: true, optimisticUpdate: false }); + + const finalOptions: any = { + queryKey, + queryFn: ({ queryKey, signal }: any) => { + const [_prefix, _model, _op, args] = queryKey; + const reqUrl = makeUrl(endpoint, model, operation, args); + return fetcher(reqUrl, { signal }, fetch, false); + }, + initialPageParam: argsValue, + ...optionsValue, + }; + return { + queryKey, + ...useInfiniteQuery(finalOptions), + }; +} + +/** + * Creates a vue-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 vue-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?: MaybeRefOrGetter< + Omit>, 'mutationFn'> & ExtraMutationOptions + >, + checkReadBack?: C, +) { + const { endpoint, fetch, logging } = getQuerySettings(); + 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 optionsValue = toValue(options); + const finalOptions: any = { ...optionsValue, mutationFn }; + const invalidateQueries = optionsValue?.invalidateQueries !== false; + const optimisticUpdate = !!optionsValue?.optimisticUpdate; + + 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/tsup.config.ts b/packages/clients/tanstack-query/tsup.config.ts index 41c31736..00bcc071 100644 --- a/packages/clients/tanstack-query/tsup.config.ts +++ b/packages/clients/tanstack-query/tsup.config.ts @@ -3,6 +3,7 @@ import { defineConfig } from 'tsup'; export default defineConfig({ entry: { react: 'src/react.ts', + vue: 'src/vue.ts', }, outDir: 'dist', splitting: false, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb54f39b..dcd772f0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,15 +9,66 @@ catalogs: '@tanstack/react-query': specifier: 5.90.6 version: 5.90.6 + '@types/better-sqlite3': + specifier: ^7.6.13 + version: 7.6.13 + '@types/node': + specifier: ^20.17.24 + version: 20.17.24 '@types/react': specifier: 19.2.0 version: 19.2.0 + '@types/react-dom': + specifier: 19.2.0 + version: 19.2.0 + '@types/tmp': + specifier: ^0.2.6 + version: 0.2.6 + better-sqlite3: + specifier: ^12.2.0 + version: 12.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 + next: + specifier: 16.0.1 + version: 16.0.1 + pg: + specifier: ^8.13.1 + version: 8.16.3 + prisma: + specifier: ^6.10.0 + version: 6.14.0 react: specifier: 19.2.0 version: 19.2.0 + react-dom: + specifier: 19.2.0 + version: 19.2.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 + vue: + specifier: 3.5.22 + version: 3.5.22 + zod-validation-error: + specifier: ^4.0.1 + version: 4.0.1 importers: @@ -154,6 +205,9 @@ importers: '@tanstack/react-query': specifier: 'catalog:' version: 5.90.6(react@19.2.0) + '@tanstack/vue-query': + specifier: 5.90.6 + version: 5.90.6(vue@3.5.22(typescript@5.8.3)) '@testing-library/dom': specifier: ^10.4.1 version: 10.4.1 @@ -187,6 +241,9 @@ importers: react: specifier: 'catalog:' version: 19.2.0 + vue: + specifier: 'catalog:' + version: 3.5.22(typescript@5.8.3) packages/common-helpers: devDependencies: @@ -2626,6 +2683,10 @@ packages: '@tailwindcss/postcss@4.1.16': resolution: {integrity: sha512-Qn3SFGPXYQMKR/UtqS+dqvPrzEeBZHrFA92maT4zijCVggdsXnDBMsPFJo1eArX3J+O+Gi+8pV4PkqjLCNBk3A==} + '@tanstack/match-sorter-utils@8.19.4': + resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} + engines: {node: '>=12'} + '@tanstack/query-core@5.90.6': resolution: {integrity: sha512-AnZSLF26R8uX+tqb/ivdrwbVdGemdEDm1Q19qM6pry6eOZ6bEYiY7mWhzXT1YDIPTNEVcZ5kYP9nWjoxDLiIVw==} @@ -2634,6 +2695,15 @@ packages: peerDependencies: react: ^18 || ^19 + '@tanstack/vue-query@5.90.6': + resolution: {integrity: sha512-7lKXKuTkX8XPjNd3g71B39JDE5B83Gtrr+yDPs5DiHm5wsM80OcwolLYkXumOM8+7VSm6ZYCrI9HSWszTIx5Gw==} + peerDependencies: + '@vue/composition-api': ^1.1.2 + vue: ^2.6.0 || ^3.3.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -4841,10 +4911,6 @@ packages: resolution: {integrity: sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==} engines: {node: 20 || >=22} - jiti@2.4.2: - resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} - hasBin: true - jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true @@ -6123,6 +6189,9 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} + remove-accents@0.5.0: + resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -7224,6 +7293,17 @@ packages: vue-bundle-renderer@2.2.0: resolution: {integrity: sha512-sz/0WEdYH1KfaOm0XaBmRZOWgYTEvUDt6yPYaUzl4E52qzgWLlknaPPTTZmp6benaPTlQAI/hN1x3tAzZygycg==} + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + vue-devtools-stub@0.1.0: resolution: {integrity: sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==} @@ -9128,6 +9208,10 @@ snapshots: postcss: 8.5.6 tailwindcss: 4.1.16 + '@tanstack/match-sorter-utils@8.19.4': + dependencies: + remove-accents: 0.5.0 + '@tanstack/query-core@5.90.6': {} '@tanstack/react-query@5.90.6(react@19.2.0)': @@ -9135,6 +9219,14 @@ snapshots: '@tanstack/query-core': 5.90.6 react: 19.2.0 + '@tanstack/vue-query@5.90.6(vue@3.5.22(typescript@5.8.3))': + dependencies: + '@tanstack/match-sorter-utils': 8.19.4 + '@tanstack/query-core': 5.90.6 + '@vue/devtools-api': 6.6.4 + vue: 3.5.22(typescript@5.8.3) + vue-demi: 0.14.10(vue@3.5.22(typescript@5.8.3)) + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.27.1 @@ -10092,11 +10184,11 @@ snapshots: dotenv: 16.6.1 exsolve: 1.0.7 giget: 2.0.0 - jiti: 2.4.2 + jiti: 2.6.1 ohash: 2.0.11 pathe: 2.0.3 perfect-debounce: 1.0.0 - pkg-types: 2.2.0 + pkg-types: 2.3.0 rc9: 2.1.2 optionalDependencies: magicast: 0.3.5 @@ -10791,7 +10883,7 @@ snapshots: 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-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-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)) 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)) @@ -10824,7 +10916,7 @@ snapshots: 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)) + 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-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)) transitivePeerDependencies: - supports-color @@ -10839,7 +10931,7 @@ snapshots: 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)): + 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-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: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -11762,8 +11854,6 @@ snapshots: dependencies: '@isaacs/cliui': 8.0.2 - jiti@2.4.2: {} - jiti@2.6.1: {} joycon@3.1.1: {} @@ -13249,6 +13339,8 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 + remove-accents@0.5.0: {} + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -14517,6 +14609,10 @@ snapshots: dependencies: ufo: 1.6.1 + vue-demi@0.14.10(vue@3.5.22(typescript@5.8.3)): + dependencies: + vue: 3.5.22(typescript@5.8.3) + vue-devtools-stub@0.1.0: {} vue-router@4.6.3(vue@3.5.22(typescript@5.8.3)): diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2fbbf861..351849ee 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -24,3 +24,4 @@ catalog: '@types/react-dom': 19.2.0 '@tanstack/react-query': 5.90.6 'next': 16.0.1 + 'vue': 3.5.22