@@ -2,6 +2,7 @@ import type { Readable } from 'node:stream'
22import type { FetchOptions } from 'ofetch'
33import type { OpenAPI3 , OpenAPITSOptions } from 'openapi-typescript'
44import { existsSync } from 'node:fs'
5+ import { mkdir , readdir , readFile , unlink , writeFile } from 'node:fs/promises'
56import {
67 addImportsSources ,
78 addPlugin ,
@@ -12,10 +13,11 @@ import {
1213 createResolver ,
1314 defineNuxtModule ,
1415} from '@nuxt/kit'
16+ import { hash } from 'ohash'
1517import openapiTS , { astToString } from 'openapi-typescript'
1618import { join } from 'pathe'
17- import { kebabCase , pascalCase } from 'scule'
1819
20+ import { kebabCase , pascalCase } from 'scule'
1921import { name , version } from '../package.json'
2022
2123type OpenAPI3Schema = string | URL | OpenAPI3 | Readable
@@ -130,10 +132,15 @@ export default defineNuxtModule<ModuleOptions>({
130132 schemas . forEach ( ( { name, schema, openAPITS } ) => {
131133 addTemplate ( {
132134 filename : `types/${ moduleName } /schemas/${ kebabCase ( name ) } .ts` ,
133- getContents : async ( ) => {
134- const ast = await openapiTS ( schema , openAPITS )
135- return astToString ( ast )
136- } ,
135+ getContents : ( ) =>
136+ addCachedSchemaTemplate ( {
137+ name,
138+ schema,
139+ openAPITS,
140+ moduleName,
141+ nuxtBuildDir : nuxt . options . buildDir || '.nuxt' ,
142+ resolvePath : resolve ,
143+ } ) ,
137144 write : true ,
138145 } )
139146 } )
@@ -319,3 +326,59 @@ function isValidUrl(url: string) {
319326 return false
320327 }
321328}
329+
330+ interface SchemaOptions {
331+ name : string
332+ schema : string | URL | OpenAPI3 | Readable
333+ openAPITS ?: object
334+ moduleName : string
335+ nuxtBuildDir : string
336+ resolvePath : ( ...paths : string [ ] ) => string
337+ }
338+
339+ export async function addCachedSchemaTemplate ( {
340+ name,
341+ schema,
342+ openAPITS,
343+ moduleName,
344+ nuxtBuildDir,
345+ resolvePath,
346+ } : SchemaOptions ) {
347+ const shortName = kebabCase ( name )
348+ const cacheDir = resolvePath ( nuxtBuildDir || '.nuxt' , `cache/${ moduleName } ` )
349+ await mkdir ( cacheDir , { recursive : true } )
350+
351+ let fileBody = ''
352+ const filePath = schema instanceof URL ? schema . pathname : schema
353+ if ( typeof filePath === 'string' && existsSync ( filePath ) ) {
354+ fileBody = await readFile ( filePath , 'utf-8' )
355+ }
356+ else {
357+ // Currently we can only cache local files
358+ const ast = await openapiTS ( schema , openAPITS )
359+ return astToString ( ast )
360+ }
361+
362+ const key = hash ( [ schema , openAPITS , moduleName , shortName , fileBody ] )
363+ const cachedPath = resolvePath ( cacheDir , `${ shortName } -${ key } .ts` )
364+
365+ if ( existsSync ( cachedPath ) ) {
366+ return await readFile ( cachedPath , 'utf-8' )
367+ }
368+
369+ const ast = await openapiTS ( schema , openAPITS )
370+ const contents = astToString ( ast )
371+
372+ await writeFile ( cachedPath , contents , 'utf-8' )
373+
374+ for ( const file of await readdir ( cacheDir ) ) {
375+ if ( file . startsWith ( `${ shortName } -` ) && file !== `${ shortName } -${ key } .ts` ) {
376+ try {
377+ await unlink ( resolvePath ( cacheDir , file ) )
378+ }
379+ catch { }
380+ }
381+ }
382+
383+ return contents
384+ }
0 commit comments