mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 23:22:02 +00:00
feat(nuxt3,bridge): add automatic schema augmentation declaration (#3096)
Co-authored-by: Pooya Parsa <pyapar@gmail.com>
This commit is contained in:
parent
ba522b2034
commit
7825e2aa12
@ -34,6 +34,7 @@
|
|||||||
"defu": "^5.0.1",
|
"defu": "^5.0.1",
|
||||||
"destr": "^1.1.0",
|
"destr": "^1.1.0",
|
||||||
"enhanced-resolve": "^5.9.0",
|
"enhanced-resolve": "^5.9.0",
|
||||||
|
"escape-string-regexp": "^5.0.0",
|
||||||
"estree-walker": "^3.0.1",
|
"estree-walker": "^3.0.1",
|
||||||
"externality": "^0.1.6",
|
"externality": "^0.1.6",
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^10.0.0",
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { useNuxt, resolveModule, addTemplate } from '@nuxt/kit'
|
import { useNuxt, resolveModule, addTemplate, resolveAlias } from '@nuxt/kit'
|
||||||
|
import { NuxtModule } from '@nuxt/schema'
|
||||||
import { resolve } from 'pathe'
|
import { resolve } from 'pathe'
|
||||||
import { componentsTypeTemplate } from '../../nuxt3/src/components/templates'
|
import { componentsTypeTemplate } from '../../nuxt3/src/components/templates'
|
||||||
|
import { schemaTemplate } from '../../nuxt3/src/core/templates'
|
||||||
import { distDir } from './dirs'
|
import { distDir } from './dirs'
|
||||||
|
|
||||||
export function setupAppBridge (_options: any) {
|
export function setupAppBridge (_options: any) {
|
||||||
@ -38,6 +40,15 @@ export function setupAppBridge (_options: any) {
|
|||||||
references.push({ path: resolve(nuxt.options.buildDir, 'types/components.d.ts') })
|
references.push({ path: resolve(nuxt.options.buildDir, 'types/components.d.ts') })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Augment schema with module types
|
||||||
|
nuxt.hook('modules:done', async (container: any) => {
|
||||||
|
nuxt.options._installedModules = await Promise.all(Object.values(container.requiredModules).map(async (m: { src: string, handler: NuxtModule }) => ({
|
||||||
|
meta: await m.handler.getMeta?.(),
|
||||||
|
entryPath: resolveAlias(m.src, nuxt.options.alias)
|
||||||
|
})))
|
||||||
|
addTemplate(schemaTemplate)
|
||||||
|
})
|
||||||
|
|
||||||
// Alias vue to have identical vue3 exports
|
// Alias vue to have identical vue3 exports
|
||||||
nuxt.options.alias['vue2-bridge'] = resolve(distDir, 'runtime/vue2-bridge.mjs')
|
nuxt.options.alias['vue2-bridge'] = resolve(distDir, 'runtime/vue2-bridge.mjs')
|
||||||
for (const alias of [
|
for (const alias of [
|
||||||
|
@ -32,7 +32,7 @@ export function useModuleContainer (nuxt: Nuxt = useNuxt()): ModuleContainer {
|
|||||||
} else {
|
} else {
|
||||||
src = moduleOpts
|
src = moduleOpts
|
||||||
}
|
}
|
||||||
await installModule(src, inlineOptions, nuxt)
|
await installModule(src, inlineOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
nuxt[MODULE_CONTAINER_KEY] = <ModuleContainer>{
|
nuxt[MODULE_CONTAINER_KEY] = <ModuleContainer>{
|
||||||
|
@ -1,18 +1,34 @@
|
|||||||
import type { NuxtModule, Nuxt } from '@nuxt/schema'
|
import type { Nuxt, NuxtModule } from '@nuxt/schema'
|
||||||
import { useNuxt } from '../context'
|
import { useNuxt } from '../context'
|
||||||
import { resolveModule, requireModule, importModule } from '../internal/cjs'
|
import { resolveModule, requireModule, importModule } from '../internal/cjs'
|
||||||
import { resolveAlias } from '../resolve'
|
import { resolveAlias } from '../resolve'
|
||||||
import { useModuleContainer } from './container'
|
import { useModuleContainer } from './container'
|
||||||
|
|
||||||
/** Installs a module on a Nuxt instance. */
|
/** Installs a module on a Nuxt instance. */
|
||||||
export async function installModule (nuxtModule: string | NuxtModule, inlineOptions?: any, nuxt: Nuxt = useNuxt()) {
|
export async function installModule (moduleToInstall: string | NuxtModule, _inlineOptions?: any, _nuxt?: Nuxt) {
|
||||||
|
const nuxt = useNuxt()
|
||||||
|
const { nuxtModule, inlineOptions } = await normalizeModule(moduleToInstall, _inlineOptions)
|
||||||
|
|
||||||
|
// Call module
|
||||||
|
await nuxtModule.call(useModuleContainer(), inlineOptions, nuxt)
|
||||||
|
|
||||||
|
nuxt.options._installedModules = nuxt.options._installedModules || []
|
||||||
|
nuxt.options._installedModules.push({
|
||||||
|
meta: await nuxtModule.getMeta?.(),
|
||||||
|
entryPath: typeof moduleToInstall === 'string' ? resolveAlias(moduleToInstall) : undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Internal ---
|
||||||
|
|
||||||
|
async function normalizeModule (nuxtModule: string | NuxtModule, inlineOptions?: any) {
|
||||||
|
const nuxt = useNuxt()
|
||||||
|
|
||||||
// Detect if `installModule` used with older signuture (nuxt, nuxtModule)
|
// Detect if `installModule` used with older signuture (nuxt, nuxtModule)
|
||||||
// TODO: Remove in RC
|
// TODO: Remove in RC
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (nuxtModule?._version || nuxtModule?.version || nuxtModule?.constructor?.version || '') {
|
if (nuxtModule?._version || nuxtModule?.version || nuxtModule?.constructor?.version || '') {
|
||||||
// @ts-ignore
|
[nuxtModule, inlineOptions] = [inlineOptions, {}]
|
||||||
[nuxt, nuxtModule] = [nuxtModule, inlineOptions]
|
|
||||||
inlineOptions = {}
|
|
||||||
console.warn(new Error('`installModule` is being called with old signature!'))
|
console.warn(new Error('`installModule` is being called with old signature!'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,6 +45,5 @@ export async function installModule (nuxtModule: string | NuxtModule, inlineOpti
|
|||||||
throw new TypeError('Nuxt module should be a function: ' + nuxtModule)
|
throw new TypeError('Nuxt module should be a function: ' + nuxtModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call module
|
return { nuxtModule, inlineOptions } as { nuxtModule: NuxtModule<any>, inlineOptions: undefined | Record<string, any> }
|
||||||
await nuxtModule.call(useModuleContainer(), inlineOptions, nuxt)
|
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,8 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
if (nuxt.options.typescript.shim) {
|
if (nuxt.options.typescript.shim) {
|
||||||
opts.references.push({ path: resolve(nuxt.options.buildDir, 'types/vue-shim.d.ts') })
|
opts.references.push({ path: resolve(nuxt.options.buildDir, 'types/vue-shim.d.ts') })
|
||||||
}
|
}
|
||||||
|
// Add module augmentations directly to NuxtConfig
|
||||||
|
opts.references.push({ path: resolve(nuxt.options.buildDir, 'types/schema.d.ts') })
|
||||||
})
|
})
|
||||||
|
|
||||||
// Add import protection
|
// Add import protection
|
||||||
@ -82,9 +84,9 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
|
|
||||||
for (const m of modulesToInstall) {
|
for (const m of modulesToInstall) {
|
||||||
if (Array.isArray(m)) {
|
if (Array.isArray(m)) {
|
||||||
await installModule(m[0], m[1], nuxt)
|
await installModule(m[0], m[1])
|
||||||
} else {
|
} else {
|
||||||
await installModule(m, {}, nuxt)
|
await installModule(m, {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { templateUtils } from '@nuxt/kit'
|
import { templateUtils } from '@nuxt/kit'
|
||||||
import type { Nuxt, NuxtApp } from '@nuxt/schema'
|
import type { Nuxt, NuxtApp } from '@nuxt/schema'
|
||||||
import { genArrayFromRaw, genDynamicImport, genExport, genImport } from 'knitwork'
|
import { genArrayFromRaw, genDynamicImport, genExport, genImport, genString } from 'knitwork'
|
||||||
|
|
||||||
import { isAbsolute, join, relative } from 'pathe'
|
import { isAbsolute, join, relative } from 'pathe'
|
||||||
import escapeRE from 'escape-string-regexp'
|
import escapeRE from 'escape-string-regexp'
|
||||||
|
|
||||||
type TemplateContext = {
|
export interface TemplateContext {
|
||||||
nuxt: Nuxt;
|
nuxt: Nuxt
|
||||||
app: NuxtApp;
|
app: NuxtApp
|
||||||
}
|
}
|
||||||
|
|
||||||
export const vueShim = {
|
export const vueShim = {
|
||||||
@ -110,3 +110,25 @@ export { }
|
|||||||
`
|
`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>`
|
||||||
|
),
|
||||||
|
' }',
|
||||||
|
'}'
|
||||||
|
].join('\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -288,6 +288,14 @@ export default {
|
|||||||
*/
|
*/
|
||||||
_modules: [],
|
_modules: [],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installed module metadata
|
||||||
|
*
|
||||||
|
* @version 3
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_installedModules: [],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows customizing the global ID used in the main HTML template as well as the main
|
* Allows customizing the global ID used in the main HTML template as well as the main
|
||||||
* Vue instance name and other options.
|
* Vue instance name and other options.
|
||||||
@ -678,13 +686,13 @@ export default {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Runtime config allows passing dynamic config and environment variables to the Nuxt app context.
|
* Runtime config allows passing dynamic config and environment variables to the Nuxt app context.
|
||||||
*
|
*
|
||||||
* The value of this object is accessible from server only using `$config` or `useRuntimeConfig`.
|
* The value of this object is accessible from server only using `$config` or `useRuntimeConfig`.
|
||||||
* It will override `publicRuntimeConfig` on the server-side.
|
* It will override `publicRuntimeConfig` on the server-side.
|
||||||
*
|
*
|
||||||
* It should hold _private_ environment variables (that should not be exposed on the frontend).
|
* It should hold _private_ environment variables (that should not be exposed on the frontend).
|
||||||
* This could include a reference to your API secret tokens.
|
* This could include a reference to your API secret tokens.
|
||||||
*
|
*
|
||||||
* Values are automatically replaced by matching env variables at runtime, e.g. setting an environment
|
* Values are automatically replaced by matching env variables at runtime, e.g. setting an environment
|
||||||
* variable `API_SECRET=my-api-key` would overwrite the value in the example below.
|
* variable `API_SECRET=my-api-key` would overwrite the value in the example below.
|
||||||
* Note that the env variable has to be named exactly the same as the config key.
|
* Note that the env variable has to be named exactly the same as the config key.
|
||||||
@ -705,9 +713,9 @@ export default {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Runtime config allows passing dynamic config and environment variables to the Nuxt app context.
|
* Runtime config allows passing dynamic config and environment variables to the Nuxt app context.
|
||||||
*
|
*
|
||||||
* The value of this object is accessible from both client and server using `$config` or `useRuntimeConfig`.
|
* The value of this object is accessible from both client and server using `$config` or `useRuntimeConfig`.
|
||||||
*
|
*
|
||||||
* It should hold env variables that are _public_ as they will be accessible on the frontend. This could include a
|
* It should hold env variables that are _public_ as they will be accessible on the frontend. This could include a
|
||||||
* reference to your public URL.
|
* reference to your public URL.
|
||||||
*
|
*
|
||||||
|
@ -2576,6 +2576,7 @@ __metadata:
|
|||||||
defu: ^5.0.1
|
defu: ^5.0.1
|
||||||
destr: ^1.1.0
|
destr: ^1.1.0
|
||||||
enhanced-resolve: ^5.9.0
|
enhanced-resolve: ^5.9.0
|
||||||
|
escape-string-regexp: ^5.0.0
|
||||||
estree-walker: ^3.0.1
|
estree-walker: ^3.0.1
|
||||||
externality: ^0.1.6
|
externality: ^0.1.6
|
||||||
fs-extra: ^10.0.0
|
fs-extra: ^10.0.0
|
||||||
|
Loading…
Reference in New Issue
Block a user