UNPKG

nuxt-kql

Version:

Kirby's Query Language API for Nuxt

188 lines (181 loc) 5.94 kB
import process from 'node:process'; import { useLogger, defineNuxtModule, createResolver, addServerHandler, addImports, addTemplate } from '@nuxt/kit'; import { defu } from 'defu'; import { join } from 'pathe'; import { pascalCase } from 'scule'; import { withLeadingSlash } from 'ufo'; import { ofetch } from 'ofetch'; import { createAuthHeader } from '../dist/runtime/utils.js'; const name = "nuxt-kql"; const logger = useLogger("nuxt-kql"); async function prefetchQueries(options) { const results = /* @__PURE__ */ new Map(); if (!options.prefetch || Object.keys(options.prefetch).length === 0) return results; if (!options.url) { logger.error("Skipping KQL prefetch, since no Kirby base URL is provided"); return results; } const start = Date.now(); for (const [key, query] of Object.entries(options.prefetch)) { const language = "language" in query ? query.language : void 0; if (language && !query.query) { logger.error(`Prefetch KQL query "${key}" requires the "query" property in multi-language mode`); continue; } try { results.set( key, await ofetch(options.prefix, { baseURL: options.url, method: "POST", body: language ? query.query : query, headers: { ...createAuthHeader(options), ...language && { "X-Language": language } } }) ); } catch (error) { const _error = error; logger.error( `Prefetch KQL query "${key}" failed${_error.status ? ` with status code ${_error.status}: ${JSON.stringify(_error.data, void 0, 2)}` : `: ${_error}`}` ); } } if (results.size > 0) { const firstKey = results.keys().next().value; logger.info( `Prefetched ${results.size === 1 ? "" : `${results.size} `}KQL ${results.size === 1 ? `query "${firstKey}"` : "queries"} in ${Date.now() - start}ms` ); } return results; } const KIRBY_TYPES_PKG_EXPORT_NAMES = [ "KirbyApiResponse", "KirbyBlock", "KirbyDefaultBlockType", "KirbyDefaultBlocks", "KirbyLayout", "KirbyLayoutColumn", "KirbyQuery", "KirbyQueryChain", "KirbyQueryModel", "KirbyQueryRequest", "KirbyQueryResponse", "KirbyQuerySchema" ]; const module = defineNuxtModule({ meta: { name, configKey: "kql", compatibility: { nuxt: ">=3.17" } }, defaults: { url: process.env.KIRBY_BASE_URL || "", prefix: "", auth: "basic", token: process.env.KIRBY_API_TOKEN || "", credentials: { username: process.env.KIRBY_API_USERNAME || "", password: process.env.KIRBY_API_PASSWORD || "" }, client: false, prefetch: {}, server: { cache: false, storage: "cache", swr: false, maxAge: 1, verboseErrors: false } }, async setup(options, nuxt) { const moduleName = name; if (!options.url) logger.error("Missing `KIRBY_BASE_URL` environment variable"); if (options.auth === "basic" && (!options.credentials || !options.credentials.username || !options.credentials.password)) logger.error("Missing `KIRBY_API_USERNAME` and `KIRBY_API_PASSWORD` environment variable for basic authentication"); if (options.auth === "bearer" && !options.token) logger.error("Missing `KIRBY_API_TOKEN` environment variable for bearer authentication"); if (!options.prefix) { if (options.auth === "basic") options.prefix = "api/query"; else if (options.auth === "bearer") options.prefix = "api/kql"; } if (!nuxt.options.ssr) { logger.info("KQL requests are client-only because SSR is disabled"); options.client = true; } if (options.server) { options.server.storage ||= "cache"; options.server.storage = withLeadingSlash(options.server.storage); } nuxt.options.runtimeConfig.kql = defu( nuxt.options.runtimeConfig.kql, options ); nuxt.options.runtimeConfig.public.kql = defu( nuxt.options.runtimeConfig.public.kql, options.client ? options : { client: false } ); const { resolve } = createResolver(import.meta.url); nuxt.options.build.transpile.push(resolve("runtime")); addServerHandler({ route: "/api/__kirby__/:key", handler: resolve("runtime/server/handler"), method: "post" }); addImports( ["$kirby", "$kql", "useKirbyData", "useKql"].map((name2) => ({ name: name2, as: name2, from: resolve(`runtime/composables/${name2}`) })) ); nuxt.hooks.hook("nitro:config", (config) => { config.externals ||= {}; config.externals.inline ||= []; config.externals.inline.push(resolve("runtime/utils")); config.imports = defu(config.imports, { presets: [{ from: resolve("runtime/server/imports"), imports: ["$kirby", "$kql"] }] }); }); nuxt.options.alias[`#${moduleName}`] = join(nuxt.options.buildDir, `module/${moduleName}`); const prefetchedQueries = await prefetchQueries(options); addTemplate({ filename: `module/${moduleName}.mjs`, write: true, getContents() { return ` // Generated by ${moduleName} ${[...prefetchedQueries.entries()].map(([key, response]) => ` export const ${key} = ${JSON.stringify(response?.result || null, void 0, 2)} `.trimStart()).join("") || `export {} `}`.trimStart(); } }); addTemplate({ filename: `module/${moduleName}.d.ts`, write: true, getContents() { return ` // Generated by ${moduleName} export type { ${KIRBY_TYPES_PKG_EXPORT_NAMES.join(", ")} } from 'kirby-types' ${[...prefetchedQueries.entries()].map(([key, response]) => ` export declare const ${key}: ${JSON.stringify(response?.result || null, void 0, 2)} export type ${pascalCase(key)} = typeof ${key} `.trimStart()).join("") || `export {} `}`.trimStart(); } }); } }); export { module as default };