@hebilicious/vue-query-nuxt
Version:
A Nuxt module for Vue Query
97 lines (91 loc) • 3.5 kB
JavaScript
import { existsSync } from 'node:fs';
import { defineNuxtModule, useLogger, createResolver, addPlugin, addImports, addTemplate, addTypeTemplate, updateTemplates } from '@nuxt/kit';
import { defu } from 'defu';
import { loadFile, generateCode } from 'magicast';
import { transform } from 'esbuild';
const NAME = "vue-query-nuxt";
const configKey = "vueQuery";
const composables = [
"useQuery",
"useQueries",
"useInfiniteQuery",
"useMutation",
"useIsFetching",
"useIsMutating",
"useQueryClient"
];
const defaults = {
stateKey: NAME,
autoImports: [...composables],
queryClientOptions: {
defaultOptions: { queries: { staleTime: 5e3 } }
},
vueQueryPluginOptions: {}
};
const module = defineNuxtModule({
meta: {
name: NAME,
configKey,
compatibility: {
nuxt: "^3"
}
},
defaults,
async setup(userOptions, nuxt) {
const logger = useLogger(NAME);
const { resolve } = createResolver(import.meta.url);
logger.info(`Adding ${NAME} module...`);
nuxt.options.runtimeConfig.public[configKey] = defu(nuxt.options.runtimeConfig.public[configKey], userOptions, {});
addPlugin(resolve("./runtime/plugin"));
addImports([{ name: "defineVueQueryPluginHook", from: resolve("./runtime/composables/defineVueQueryPluginHook") }]);
const filename = "internal.vue-query-plugin-hook.mjs";
addTemplate({
filename,
write: true,
getContents: async () => {
if (existsSync(resolve(nuxt.options.rootDir, "vue-query.config.ts"))) {
const configFile = resolve(nuxt.options.rootDir, "vue-query.config.ts");
const file = await loadFile(configFile);
if (file.exports.pluginHook || file.exports.default) {
logger.success("Found vue-query.config.ts file");
if (!file.exports.pluginHook)
file.exports.pluginHook = file.exports.default;
delete file.exports.default;
const { code } = generateCode(file);
const shaked = await transform(code, { treeShaking: true, loader: "ts" });
return shaked.code;
} else {
logger.error("Found vue-query.config.ts file, but it does not export a `pluginHook`.");
}
} else {
logger.info("No vue-query.config.ts file found.");
}
return "export function pluginHook() { return { pluginReturn: null, vueQueryPluginOptions: null}}";
}
});
addTypeTemplate({
filename: "types/vue-query-nuxt-advanced.d.ts",
write: true,
getContents: () => `
type PluginHookResult = Awaited<ReturnType<typeof import(".nuxt/${filename}").pluginHook>["pluginReturn"]>
type AddDollarPrefix<T> = {
[K in keyof T['provide'] as \`$\${string & K}\`]: T['provide'][K]
}
declare module '#app' {
interface NuxtApp extends AddDollarPrefix<PluginHookResult> {}
}
export { }`
});
nuxt.hook("builder:watch", async (event, path) => {
if (path.includes("vue-query.config.ts")) {
logger.info(`[vue-query] config changed '@${event}'`, path);
updateTemplates({ filter: (t) => t.filename === filename });
logger.success("[vue-query] config reloaded.");
}
});
if (userOptions.autoImports && userOptions.autoImports.length > 0)
addImports(userOptions.autoImports.map((name) => ({ name, from: "@tanstack/vue-query" })));
logger.success(`Added ${NAME} module successfully.`);
}
});
export { module as default };