2022-03-14 10:47:24 +00:00
|
|
|
import type { Nuxt, NuxtApp, NuxtTemplate } from '@nuxt/schema'
|
2022-06-10 13:12:21 +00:00
|
|
|
import { genArrayFromRaw, genDynamicImport, genExport, genImport, genObjectFromRawEntries, genString, genSafeVariableName } from 'knitwork'
|
2021-09-21 14:55:07 +00:00
|
|
|
|
2022-02-07 10:20:01 +00:00
|
|
|
import { isAbsolute, join, relative } from 'pathe'
|
2022-03-09 13:41:24 +00:00
|
|
|
import { resolveSchema, generateTypes } from 'untyped'
|
2022-01-27 11:13:32 +00:00
|
|
|
import escapeRE from 'escape-string-regexp'
|
2022-08-08 11:03:44 +00:00
|
|
|
import { hash } from 'ohash'
|
2021-11-18 13:11:34 +00:00
|
|
|
|
2022-02-08 19:09:44 +00:00
|
|
|
export interface TemplateContext {
|
|
|
|
nuxt: Nuxt
|
|
|
|
app: NuxtApp
|
2021-09-21 14:55:07 +00:00
|
|
|
}
|
|
|
|
|
2022-01-19 18:10:38 +00:00
|
|
|
export const vueShim = {
|
2022-02-07 10:20:01 +00:00
|
|
|
filename: 'types/vue-shim.d.ts',
|
2022-01-19 18:10:38 +00:00
|
|
|
getContents: () =>
|
|
|
|
[
|
|
|
|
'declare module \'*.vue\' {',
|
|
|
|
' import { DefineComponent } from \'@vue/runtime-core\'',
|
|
|
|
' const component: DefineComponent<{}, {}, any>',
|
|
|
|
' export default component',
|
|
|
|
'}'
|
|
|
|
].join('\n')
|
|
|
|
}
|
|
|
|
|
2021-10-12 12:51:41 +00:00
|
|
|
// TODO: Use an alias
|
|
|
|
export const appComponentTemplate = {
|
|
|
|
filename: 'app-component.mjs',
|
2022-02-07 13:45:47 +00:00
|
|
|
getContents: (ctx: TemplateContext) => genExport(ctx.app.mainComponent, ['default'])
|
2021-10-12 12:51:41 +00:00
|
|
|
}
|
|
|
|
// TODO: Use an alias
|
|
|
|
export const rootComponentTemplate = {
|
|
|
|
filename: 'root-component.mjs',
|
2022-02-07 13:45:47 +00:00
|
|
|
getContents: (ctx: TemplateContext) => genExport(ctx.app.rootComponent, ['default'])
|
2021-09-21 14:55:07 +00:00
|
|
|
}
|
2022-03-11 08:22:16 +00:00
|
|
|
// TODO: Use an alias
|
|
|
|
export const errorComponentTemplate = {
|
|
|
|
filename: 'error-component.mjs',
|
|
|
|
getContents: (ctx: TemplateContext) => genExport(ctx.app.errorComponent, ['default'])
|
|
|
|
}
|
2021-09-21 14:55:07 +00:00
|
|
|
|
|
|
|
export const cssTemplate = {
|
|
|
|
filename: 'css.mjs',
|
2022-02-15 09:50:11 +00:00
|
|
|
getContents: (ctx: TemplateContext) => ctx.nuxt.options.css.map(i => genImport(i)).join('\n')
|
2021-09-21 14:55:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export const clientPluginTemplate = {
|
|
|
|
filename: 'plugins/client.mjs',
|
|
|
|
getContents (ctx: TemplateContext) {
|
2021-11-04 08:16:54 +00:00
|
|
|
const clientPlugins = ctx.app.plugins.filter(p => !p.mode || p.mode !== 'server')
|
2022-08-08 11:03:44 +00:00
|
|
|
const exports: string[] = []
|
|
|
|
const imports: string[] = []
|
|
|
|
for (const plugin of clientPlugins) {
|
|
|
|
const path = relative(ctx.nuxt.options.rootDir, plugin.src)
|
|
|
|
const variable = genSafeVariableName(path).replace(/_(45|46|47)/g, '_') + '_' + hash(path)
|
|
|
|
exports.push(variable)
|
|
|
|
imports.push(genImport(plugin.src, variable))
|
|
|
|
}
|
2021-09-21 14:55:07 +00:00
|
|
|
return [
|
2022-07-21 18:09:27 +00:00
|
|
|
...imports,
|
|
|
|
`export default ${genArrayFromRaw(exports)}`
|
2021-09-21 14:55:07 +00:00
|
|
|
].join('\n')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export const serverPluginTemplate = {
|
|
|
|
filename: 'plugins/server.mjs',
|
|
|
|
getContents (ctx: TemplateContext) {
|
2021-11-04 08:16:54 +00:00
|
|
|
const serverPlugins = ctx.app.plugins.filter(p => !p.mode || p.mode !== 'client')
|
2022-08-08 11:03:44 +00:00
|
|
|
const exports: string[] = ['preload']
|
|
|
|
const imports: string[] = ["import preload from '#app/plugins/preload.server'"]
|
|
|
|
for (const plugin of serverPlugins) {
|
|
|
|
const path = relative(ctx.nuxt.options.rootDir, plugin.src)
|
|
|
|
const variable = genSafeVariableName(path).replace(/_(45|46|47)/g, '_') + '_' + hash(path)
|
|
|
|
exports.push(variable)
|
|
|
|
imports.push(genImport(plugin.src, variable))
|
|
|
|
}
|
2021-09-21 14:55:07 +00:00
|
|
|
return [
|
2022-07-21 18:09:27 +00:00
|
|
|
...imports,
|
2022-08-08 11:03:44 +00:00
|
|
|
`export default ${genArrayFromRaw(exports)}`
|
2021-09-21 14:55:07 +00:00
|
|
|
].join('\n')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-18 13:11:34 +00:00
|
|
|
export const pluginsDeclaration = {
|
2022-02-07 10:20:01 +00:00
|
|
|
filename: 'types/plugins.d.ts',
|
2021-11-18 13:11:34 +00:00
|
|
|
getContents: (ctx: TemplateContext) => {
|
2022-01-27 16:02:25 +00:00
|
|
|
const EXTENSION_RE = new RegExp(`(?<=\\w)(${ctx.nuxt.options.extensions.map(e => escapeRE(e)).join('|')})$`, 'g')
|
2022-02-07 10:20:01 +00:00
|
|
|
const tsImports = ctx.app.plugins.map(p => (isAbsolute(p.src) ? relative(join(ctx.nuxt.options.buildDir, 'types'), p.src) : p.src).replace(EXTENSION_RE, ''))
|
2021-11-18 13:11:34 +00:00
|
|
|
|
2022-04-20 08:52:39 +00:00
|
|
|
return `// Generated by Nuxt'
|
2021-11-18 13:11:34 +00:00
|
|
|
import type { Plugin } from '#app'
|
|
|
|
|
|
|
|
type Decorate<T extends Record<string, any>> = { [K in keyof T as K extends string ? \`$\${K}\` : never]: T[K] }
|
|
|
|
|
|
|
|
type InjectionType<A extends Plugin> = A extends Plugin<infer T> ? Decorate<T> : unknown
|
|
|
|
|
2022-02-07 13:45:47 +00:00
|
|
|
type NuxtAppInjections = \n ${tsImports.map(p => `InjectionType<typeof ${genDynamicImport(p, { wrapper: false })}.default>`).join(' &\n ')}
|
2021-11-18 13:11:34 +00:00
|
|
|
|
|
|
|
declare module '#app' {
|
|
|
|
interface NuxtApp extends NuxtAppInjections { }
|
|
|
|
}
|
|
|
|
|
|
|
|
declare module '@vue/runtime-core' {
|
|
|
|
interface ComponentCustomProperties extends NuxtAppInjections { }
|
|
|
|
}
|
|
|
|
|
|
|
|
export { }
|
|
|
|
`
|
|
|
|
}
|
|
|
|
}
|
2022-02-08 19:09:44 +00:00
|
|
|
|
|
|
|
const adHocModules = ['router', 'pages', 'auto-imports', 'meta', 'components']
|
|
|
|
export const schemaTemplate = {
|
|
|
|
filename: 'types/schema.d.ts',
|
|
|
|
getContents: ({ nuxt }: TemplateContext) => {
|
|
|
|
const moduleInfo = nuxt.options._installedModules.map(m => ({
|
|
|
|
...m.meta || {},
|
|
|
|
importName: m.entryPath || m.meta?.name
|
|
|
|
})).filter(m => m.configKey && m.name && !adHocModules.includes(m.name))
|
|
|
|
|
|
|
|
return [
|
|
|
|
"import { NuxtModule } from '@nuxt/schema'",
|
|
|
|
"declare module '@nuxt/schema' {",
|
|
|
|
' interface NuxtConfig {',
|
|
|
|
...moduleInfo.filter(Boolean).map(meta =>
|
|
|
|
` [${genString(meta.configKey)}]?: typeof ${genDynamicImport(meta.importName, { wrapper: false })}.default extends NuxtModule<infer O> ? Partial<O> : Record<string, any>`
|
|
|
|
),
|
|
|
|
' }',
|
2022-05-06 13:27:42 +00:00
|
|
|
generateTypes(resolveSchema(Object.fromEntries(Object.entries(nuxt.options.runtimeConfig).filter(([key]) => key !== 'public'))),
|
2022-03-09 13:41:24 +00:00
|
|
|
{
|
2022-04-11 14:34:23 +00:00
|
|
|
interfaceName: 'RuntimeConfig',
|
2022-03-09 13:41:24 +00:00
|
|
|
addExport: false,
|
|
|
|
addDefaults: false,
|
|
|
|
allowExtraKeys: false,
|
|
|
|
indentation: 2
|
|
|
|
}),
|
2022-05-06 13:27:42 +00:00
|
|
|
generateTypes(resolveSchema(nuxt.options.runtimeConfig.public),
|
|
|
|
{
|
|
|
|
interfaceName: 'PublicRuntimeConfig',
|
|
|
|
addExport: false,
|
|
|
|
addDefaults: false,
|
|
|
|
allowExtraKeys: false,
|
|
|
|
indentation: 2
|
|
|
|
}),
|
2022-02-08 19:09:44 +00:00
|
|
|
'}'
|
|
|
|
].join('\n')
|
|
|
|
}
|
|
|
|
}
|
2022-03-14 10:47:24 +00:00
|
|
|
|
|
|
|
// Add layouts template
|
|
|
|
export const layoutTemplate: NuxtTemplate = {
|
|
|
|
filename: 'layouts.mjs',
|
2022-06-27 12:10:29 +00:00
|
|
|
getContents ({ app }: TemplateContext) {
|
2022-03-14 10:47:24 +00:00
|
|
|
const layoutsObject = genObjectFromRawEntries(Object.values(app.layouts).map(({ name, file }) => {
|
2022-03-15 11:22:25 +00:00
|
|
|
return [name, `defineAsyncComponent(${genDynamicImport(file)})`]
|
2022-03-14 10:47:24 +00:00
|
|
|
}))
|
|
|
|
return [
|
|
|
|
'import { defineAsyncComponent } from \'vue\'',
|
|
|
|
`export default ${layoutsObject}`
|
|
|
|
].join('\n')
|
|
|
|
}
|
|
|
|
}
|
2022-03-22 15:51:26 +00:00
|
|
|
|
2022-06-27 12:10:29 +00:00
|
|
|
// Add middleware template
|
|
|
|
export const middlewareTemplate: NuxtTemplate = {
|
|
|
|
filename: 'middleware.mjs',
|
|
|
|
getContents ({ app }: TemplateContext) {
|
|
|
|
const globalMiddleware = app.middleware.filter(mw => mw.global)
|
|
|
|
const namedMiddleware = app.middleware.filter(mw => !mw.global)
|
|
|
|
const namedMiddlewareObject = genObjectFromRawEntries(namedMiddleware.map(mw => [mw.name, genDynamicImport(mw.path)]))
|
|
|
|
return [
|
|
|
|
...globalMiddleware.map(mw => genImport(mw.path, genSafeVariableName(mw.name))),
|
|
|
|
`export const globalMiddleware = ${genArrayFromRaw(globalMiddleware.map(mw => genSafeVariableName(mw.name)))}`,
|
|
|
|
`export const namedMiddleware = ${namedMiddlewareObject}`
|
|
|
|
].join('\n')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-22 15:51:26 +00:00
|
|
|
export const clientConfigTemplate: NuxtTemplate = {
|
2022-04-07 11:28:04 +00:00
|
|
|
filename: 'nitro.client.mjs',
|
|
|
|
getContents: () => `
|
|
|
|
export const useRuntimeConfig = () => window?.__NUXT__?.config || {}
|
|
|
|
`
|
2022-03-22 15:51:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export const publicPathTemplate: NuxtTemplate = {
|
|
|
|
filename: 'paths.mjs',
|
|
|
|
getContents ({ nuxt }) {
|
|
|
|
return [
|
|
|
|
'import { joinURL } from \'ufo\'',
|
2022-04-19 19:10:32 +00:00
|
|
|
!nuxt.options.dev && 'import { useRuntimeConfig } from \'#internal/nitro\'',
|
2022-03-22 15:51:26 +00:00
|
|
|
|
|
|
|
nuxt.options.dev
|
|
|
|
? `const appConfig = ${JSON.stringify(nuxt.options.app)}`
|
2022-04-07 11:28:04 +00:00
|
|
|
: 'const appConfig = useRuntimeConfig().app',
|
2022-03-22 15:51:26 +00:00
|
|
|
|
|
|
|
'export const baseURL = () => appConfig.baseURL',
|
|
|
|
'export const buildAssetsDir = () => appConfig.buildAssetsDir',
|
|
|
|
|
|
|
|
'export const buildAssetsURL = (...path) => joinURL(publicAssetsURL(), buildAssetsDir(), ...path)',
|
|
|
|
|
|
|
|
'export const publicAssetsURL = (...path) => {',
|
|
|
|
' const publicBase = appConfig.cdnURL || appConfig.baseURL',
|
|
|
|
' return path.length ? joinURL(publicBase, ...path) : publicBase',
|
2022-07-21 10:44:33 +00:00
|
|
|
'}',
|
|
|
|
|
|
|
|
'globalThis.__buildAssetsURL = buildAssetsURL',
|
|
|
|
'globalThis.__publicAssetsURL = publicAssetsURL'
|
2022-03-25 11:38:36 +00:00
|
|
|
].filter(Boolean).join('\n')
|
2022-03-22 15:51:26 +00:00
|
|
|
}
|
|
|
|
}
|