Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/vue-query-nuxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@
"@nuxt/kit": "^3.11.2",
"defu": "^6.1.4",
"esbuild": "^0.20.2",
"magicast": "^0.3.4"
"magicast": "^0.3.4",
"serialize-error": "^12.0.0"
},
"devDependencies": {
"@nuxt/module-builder": "^0.5.5"
Expand Down
2 changes: 1 addition & 1 deletion packages/vue-query-nuxt/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default defineNuxtModule<ModuleOptions>({
else {
logger.info("No vue-query.config.ts file found.")
}
return "export function pluginHook() { return { pluginReturn: null, vueQueryPluginOptions: null}}"
return "export function pluginHook() { return {} }"
}
})

Expand Down
49 changes: 45 additions & 4 deletions packages/vue-query-nuxt/src/runtime/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { DehydratedState } from "@tanstack/vue-query"
import { QueryClient, VueQueryPlugin, dehydrate, hydrate } from "@tanstack/vue-query"
import { isErrorLike, deserializeError, serializeError } from 'serialize-error';
import { getVueQueryOptions } from "./utils"
import { pluginHook } from "#build/internal.vue-query-plugin-hook"
import { defineNuxtPlugin, useRuntimeConfig, useState } from "#imports"
Expand All @@ -10,17 +11,57 @@ export default defineNuxtPlugin((nuxt) => {
const queryClient = new QueryClient(queryClientOptions)

// The plugin hook is replaced by the user provided vue-query.config.ts and allow advanced modifications
const { pluginReturn, vueQueryPluginOptions: hookOptions } = pluginHook({ queryClient, nuxt })
const {
pluginReturn,
vueQueryPluginOptions: hookOptions,
hydrateOptions,
dehydrateOptions,
serializeErrorOptions,
deserializeErrorOptions
} = pluginHook({ queryClient, nuxt })

nuxt.vueApp.use(VueQueryPlugin, { queryClient, ...vueQueryPluginOptions, ...hookOptions })

type Dehydrated = ReturnType<typeof dehydrate>
type QueryOrMutations = Dehydrated['queries'] | Dehydrated['mutations']
if (import.meta.server) {
nuxt.hooks.hook("app:rendered", () => {
vueQueryState.value = dehydrate(queryClient)
const serializeErrors = <T extends QueryOrMutations>(queryOrMutations: T): T => queryOrMutations
.filter(queryOrMutation => queryOrMutation.state.error instanceof Error)
.map(queryOrMutation => {
const state = queryOrMutation.state
state.error = serializeError(state.error, serializeErrorOptions) as Error | null
if ('fetchFailureReason' in state)
state.fetchFailureReason = serializeError(state.fetchFailureReason, serializeErrorOptions) as Error | null
if ('failureReason' in state)
state.failureReason = serializeError(state.failureReason, serializeErrorOptions) as Error | null
return queryOrMutation
}) as T
const dehydrated = dehydrate(queryClient, dehydrateOptions)
dehydrated.queries = serializeErrors(dehydrated.queries)
dehydrated.mutations = serializeErrors(dehydrated.mutations)
vueQueryState.value = dehydrated
})
}

if (import.meta.client) hydrate(queryClient, vueQueryState.value)
if (import.meta.client) {
const deserializeErrors = <T extends QueryOrMutations>(queryOrMutations: T): T => queryOrMutations
.filter(queryOrMutation => isErrorLike(queryOrMutation.state.error))
.map(queryOrMutation => {
const state = queryOrMutation.state
state.error = deserializeError(state.error, deserializeErrorOptions)
if ('fetchFailureReason' in state)
state.fetchFailureReason = deserializeError(state.fetchFailureReason, deserializeErrorOptions)
if ('failureReason' in state)
state.failureReason = deserializeError(state.failureReason, deserializeErrorOptions)
return queryOrMutation
}) as T
const dehydrated = vueQueryState.value
dehydrated.queries = deserializeErrors(dehydrated.queries)
dehydrated.mutations = deserializeErrors(dehydrated.mutations)
hydrate(queryClient, dehydrated, hydrateOptions)
}

return pluginReturn
if (pluginReturn !== undefined) return pluginReturn
return;
})
20 changes: 12 additions & 8 deletions packages/vue-query-nuxt/src/runtime/types.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import type { NuxtApp } from "nuxt/app"
import type { QueryClient, VueQueryPluginOptions } from "@tanstack/vue-query"
import type { NuxtApp, Plugin } from "nuxt/app"
import type { DehydrateOptions, HydrateOptions, QueryClient, VueQueryPluginOptions } from "@tanstack/vue-query"
import type { Options } from "serialize-error"

export type NuxtPluginReturn =
| void
| Promise<void>
| Promise<{ provide?: Record<string, unknown> | undefined }>
| { provide?: Record<string, unknown> | undefined }
export type NuxtPluginReturn = ReturnType<Plugin>

// NuxtApp & _NuxtApp are different so we use any
export interface PluginHookParameters {
nuxt: NuxtApp & any
queryClient: QueryClient
}

export interface PluginHookReturn { pluginReturn: NuxtPluginReturn; vueQueryPluginOptions?: VueQueryPluginOptions }
export interface PluginHookReturn {
pluginReturn?: NuxtPluginReturn,
vueQueryPluginOptions?: VueQueryPluginOptions,
hydrateOptions?: HydrateOptions,
dehydrateOptions?: DehydrateOptions,
serializeErrorOptions?: Options,
deserializeErrorOptions?: Options
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import type { PluginHookParameters, PluginHookReturn } from "./types"

// eslint-disable-next-line unused-imports/no-unused-vars
export function pluginHook(pluginHookParameters: PluginHookParameters): PluginHookReturn {
return { pluginReturn: {}, vueQueryPluginOptions: {} }
return {}
}