Skip to content

Commit

Permalink
feat: properly type plugin callback
Browse files Browse the repository at this point in the history
  • Loading branch information
Hebilicious committed Jun 2, 2023
1 parent 3bea7d7 commit 8e72f91
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 24 deletions.
37 changes: 25 additions & 12 deletions packages/vue-query-nuxt/src/module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { existsSync, promises as fsp } from "node:fs"
import { addImports, addPlugin, createResolver, defineNuxtModule, useLogger } from "@nuxt/kit"
import { addImports, addPlugin, addTemplate, createResolver, defineNuxtModule, useLogger } from "@nuxt/kit"
import { defu } from "defu"
import { generateCode, loadFile } from "magicast"
import { transform } from "esbuild"
Expand Down Expand Up @@ -33,7 +33,7 @@ export default defineNuxtModule<VueQueryOptions>({
const filename = "internal.vue-query-plugin-callback.mjs"

// 4. Write pluginCallback() to .nuxt
const writeFile = async ({ update = false } = {}) => {
const writeFile = async () => {
let getContents = async () => "export function pluginCallback() {}"
if (existsSync(resolve(nuxt.options.rootDir, "vue-query.config.ts"))) {
const configFile = resolve(nuxt.options.rootDir, "vue-query.config.ts")
Expand All @@ -53,29 +53,42 @@ export default defineNuxtModule<VueQueryOptions>({
else {
logger.info("No vue-query.config.ts file found.")
}
// Create file in .nuxt
// if (update) await updateTemplates()
// else addTemplate({ filename, write: true, getContents })

// @todo Make @nuxt/kit support this
// addTemplate({ filename, write: true, getContents, replace: true })

// Create file in .nuxt
const filePath = resolve(nuxt.options.buildDir, filename)
if (existsSync(filePath)) await fsp.rm(filePath)
await fsp.writeFile(filePath, await getContents())
}
writeFile()

// 4. Add types at the end of plugins.d.ts
nuxt.hook("build:before", async () => {
await fsp.appendFile(resolve(nuxt.options.buildDir, "types/plugins.d.ts"),
`declare module '#app' {
interface NuxtApp extends InjectionType<typeof import(".nuxt/${filename}").pluginCallback> { }
}`)
// 4. Add types for the plugin callback.
const advancedTypes = "types/vue-query-nuxt-advanced.d.ts"
addTemplate({
filename: advancedTypes,
getContents: () => `
type PluginCallbackResult = Awaited<ReturnType<typeof import(".nuxt/${filename}").pluginCallback>>
type AddPrefix<T> = {
[K in keyof T['provide'] as \`$\${string & K}\`]: T['provide'][K]
}
declare module '#app' {
interface NuxtApp extends AddPrefix<PluginCallbackResult> {}
}
export { }`
})
nuxt.hook("prepare:types", ({ references }) => {
references.push({ path: advancedTypes })
})

// 5. Auto - reload the config
nuxt.hook("builder:watch", async (event, path) => {
if (path.includes("vue-query.config.ts")) {
logger.info(`[vue-query] config changed '@${event}'`, path)
writeFile({ update: true })
writeFile()
logger.success("[vue-query] config reloaded.")
}
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import type { PluginCallbackParameters, ReturnedByPlugin } from "#build/internal.vue-query-plugin-callback"
import type { PluginCallbackParameters, ReturnedByPlugin } from "../types"

export const defineVueQueryPluginCallback = (callback: (pluginCallbackParameters: PluginCallbackParameters) => ReturnedByPlugin): typeof callback => callback
export function defineVueQueryPluginCallback<T extends ReturnedByPlugin>(
callback: (callbackParameters: PluginCallbackParameters) => T
): (callbackParameters: PluginCallbackParameters) => T {
return callback
}
12 changes: 2 additions & 10 deletions packages/vue-query-nuxt/src/runtime/internal.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import { type QueryClient } from "@tanstack/vue-query"
import type { PluginCallbackParameters, ReturnedByPlugin } from "./types"

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

export interface PluginCallbackParameters {
queryClient: QueryClient
}
// "#build/internal.vue-query-plugin-callback will resolve to this file when building the library.
// The actual function will be defined by the user and injected in the .nuxt directory.
// Typescript will resolve this type regardless

// eslint-disable-next-line unused-imports/no-unused-vars
export const pluginCallback = (pluginCallbackParameters: PluginCallbackParameters): ReturnedByPlugin => ({})
11 changes: 11 additions & 0 deletions packages/vue-query-nuxt/src/runtime/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { type QueryClient } from "@tanstack/vue-query"

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

export interface PluginCallbackParameters {
queryClient: QueryClient
}

0 comments on commit 8e72f91

Please sign in to comment.