import { isAbsolute, join, relative } from 'pathe' import type { Component } from '@nuxt/schema' import { genDynamicImport, genObjectFromRawEntries } from 'knitwork' export type ComponentsTemplateOptions = { buildDir?: string components: Component[] } export type ImportMagicCommentsOptions = { chunkName:string prefetch?: boolean | number preload?: boolean | number } const createImportMagicComments = (options: ImportMagicCommentsOptions) => { const { chunkName, prefetch, preload } = options return [ `webpackChunkName: "${chunkName}"`, prefetch === true || typeof prefetch === 'number' ? `webpackPrefetch: ${prefetch}` : false, preload === true || typeof preload === 'number' ? `webpackPreload: ${preload}` : false ].filter(Boolean).join(', ') } export const componentsTemplate = { filename: 'components.mjs', getContents ({ options }: { options: ComponentsTemplateOptions }) { return `import { defineAsyncComponent } from 'vue' const components = ${genObjectFromRawEntries(options.components.filter(c => c.global === true).map((c) => { const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']` const comment = createImportMagicComments(c) return [c.pascalName, `defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))`] }))} export default function (nuxtApp) { for (const name in components) { nuxtApp.vueApp.component(name, components[name]) nuxtApp.vueApp.component('Lazy' + name, components[name]) } } ` } } export const componentsTypeTemplate = { filename: 'types/components.d.ts', getContents: ({ options }: { options: ComponentsTemplateOptions }) => `// Generated by components discovery declare module 'vue' { export interface GlobalComponents { ${options.components.map(c => ` '${c.pascalName}': typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(join(options.buildDir, 'types'), c.filePath) : c.filePath, { wrapper: false })}['${c.export}']`).join(',\n')} ${options.components.map(c => ` 'Lazy${c.pascalName}': typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(join(options.buildDir, 'types'), c.filePath) : c.filePath, { wrapper: false })}['${c.export}']`).join(',\n')} } } export {} ` }