mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 07:05:11 +00:00
feat(kit): addTypeTemplate
helper with auto-registration (#21331)
This commit is contained in:
parent
31a1b98f3f
commit
ee6869b1ba
@ -443,22 +443,40 @@ export default defineNuxtModule({
|
||||
|
||||
::
|
||||
|
||||
#### Augmenting Types
|
||||
#### Adding Templates/Virtual Files
|
||||
|
||||
If your module should augment types handled by Nuxt, you can use the `prepare:types` hook to perform this operation.
|
||||
If you need to add a virtual file that can be imported into the user's app, you can use the `addTemplate` utility.
|
||||
|
||||
```js
|
||||
import { defineNuxtModule, addTemplate, createResolver } from '@nuxt/kit'
|
||||
```ts
|
||||
import { defineNuxtModule, addTemplate } from '@nuxt/kit'
|
||||
|
||||
export default defineNuxtModule({
|
||||
setup (options, nuxt) {
|
||||
const { resolve } = createResolver(import.meta.url)
|
||||
|
||||
// Generating types to be injected
|
||||
// The file is added to Nuxt's internal virtual file system and can be imported from '#build/my-module-feature.mjs'
|
||||
addTemplate({
|
||||
filename: 'my-module.d.ts',
|
||||
getContents: () => {
|
||||
return `// Generated by my-module
|
||||
filename: 'my-module-feature.mjs',
|
||||
getContents: () => 'export const myModuleFeature = () => "hello world !"'
|
||||
})
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Adding Type Declarations
|
||||
|
||||
You might also want to add a type declaration to the user's project (for example, to augment an Nuxt interface
|
||||
or provide a global type of your own). For this, Nuxt provides the `addTypeTemplate` utility that both
|
||||
writes a template to disk and adds a reference to it in the generated `nuxt.d.ts` file that.
|
||||
|
||||
If your module should augment types handled by Nuxt, you can use `addTypeTemplate` to perform this operation:
|
||||
|
||||
```js
|
||||
import { defineNuxtModule, addTemplate, addTypeTemplate } from '@nuxt/kit'
|
||||
|
||||
export default defineNuxtModule({
|
||||
setup (options, nuxt) {
|
||||
addTypeTemplate({
|
||||
filename: 'types/my-module.d.ts',
|
||||
getContents: () => `// Generated by my-module
|
||||
interface MyModuleNitroRules {
|
||||
myModule?: { foo: 'bar' }
|
||||
}
|
||||
@ -467,13 +485,29 @@ export default defineNuxtModule({
|
||||
interface NitroRouteConfig extends MyModuleNitroRules {}
|
||||
}
|
||||
export {}`
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
// Injecting previously generated types
|
||||
nuxt.hooks.hook('prepare:types', ({ references }) => {
|
||||
references.push({ path: resolve(nuxt.options.buildDir, 'my-module.d.ts') })
|
||||
})
|
||||
If you need more granular control, you can use the `prepare:types` hook to register a callback that will inject your types.
|
||||
|
||||
```ts
|
||||
const template = addTemplate({ /* template options */ })
|
||||
nuxt.hook('prepare:types', ({ references }) => {
|
||||
references.push({ path: template.dst })
|
||||
})
|
||||
```
|
||||
|
||||
##### Updating Templates
|
||||
|
||||
If you need to update your templates/virtual files, you can leverage the `updateTemplates` utility like this :
|
||||
|
||||
```ts
|
||||
nuxt.hook('builder:watch', async (event, path) => {
|
||||
if (path.includes('my-module-feature.config')) {
|
||||
// This will reload the template that you registered
|
||||
updateTemplates({ filter: t => t.filename === 'my-module-feature.mjs' })
|
||||
}
|
||||
})
|
||||
```
|
||||
|
@ -76,6 +76,7 @@ description: Nuxt Kit provides composable utilities to help interacting with Nux
|
||||
[source code](https://github.com/nuxt/nuxt/blob/main/packages/kit/src/template.ts)
|
||||
|
||||
- `addTemplate(templateOptions)`
|
||||
- `addTypeTemplate(templateOptions)`
|
||||
- `updateTemplates({ filter?: ResolvedNuxtTemplate => boolean })`
|
||||
|
||||
### Nitro
|
||||
|
@ -23,6 +23,27 @@ export function addTemplate (_template: NuxtTemplate<any> | string) {
|
||||
return template
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders given types using lodash template during build into the project buildDir
|
||||
* and register them as types.
|
||||
*/
|
||||
export function addTypeTemplate (_template: NuxtTemplate<any>) {
|
||||
const nuxt = useNuxt()
|
||||
|
||||
const template = addTemplate(_template)
|
||||
|
||||
if (!template.filename.endsWith('.d.ts')) {
|
||||
throw new Error(`Invalid type template. Filename must end with .d.ts : "${template.filename}"`)
|
||||
}
|
||||
|
||||
// Add template to types reference
|
||||
nuxt.hook('prepare:types', ({ references }) => {
|
||||
references.push({ path: template.dst })
|
||||
})
|
||||
|
||||
return template
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a nuxt template object
|
||||
*/
|
||||
|
8
test/fixtures/basic-types/nuxt.config.ts
vendored
8
test/fixtures/basic-types/nuxt.config.ts
vendored
@ -1,3 +1,5 @@
|
||||
import { addTypeTemplate } from 'nuxt/kit'
|
||||
|
||||
export default defineNuxtConfig({
|
||||
experimental: {
|
||||
typedPages: true
|
||||
@ -33,6 +35,12 @@ export default defineNuxtConfig({
|
||||
}
|
||||
},
|
||||
modules: [
|
||||
function () {
|
||||
addTypeTemplate({
|
||||
filename: 'test.d.ts',
|
||||
getContents: () => 'declare type Fromage = "cheese"'
|
||||
})
|
||||
},
|
||||
'./modules/test',
|
||||
[
|
||||
'~/modules/example',
|
||||
|
9
test/fixtures/basic-types/types.ts
vendored
9
test/fixtures/basic-types/types.ts
vendored
@ -401,3 +401,12 @@ describe('composables inference', () => {
|
||||
expectTypeOf<typeof bob>().toEqualTypeOf<boolean | Promise<boolean>>()
|
||||
})
|
||||
})
|
||||
|
||||
describe('kit utilities', () => {
|
||||
it('addTypeTemplate', () => {
|
||||
// @ts-expect-error Fromage is 'cheese'
|
||||
const _fake: Fromage = 'babybel'
|
||||
|
||||
const _fromage: Fromage = 'cheese'
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user