fork of hey-api/openapi-ts because I need some additional things
at feat/skip-token 112 lines 3.2 kB view raw
1import fs from 'node:fs'; 2import path from 'node:path'; 3 4import type { UserConfig } from '@hey-api/openapi-ts'; 5import { createClient } from '@hey-api/openapi-ts'; 6import { addImportsSources, defineNuxtModule, useNuxt } from '@nuxt/kit'; 7import type {} from '@nuxt/schema'; 8import { defu } from 'defu'; 9import { findExports, findTypeExports } from 'mlly'; 10import { findPath } from 'nuxt/kit'; 11 12interface ModuleOptions { 13 /** 14 * Module alias. 15 * 16 * @default '#hey-api' 17 */ 18 alias?: string; 19 /** 20 * Automatically import all re-exported identifiers from the index file? 21 * You may want to disable this option if the imported identifier names 22 * clash with identifier names from other modules. 23 * 24 * @default true 25 */ 26 autoImport?: boolean; 27 /** 28 * `@hey-api/openapi-ts` configuration options. 29 */ 30 config: Omit<UserConfig, 'output'> & Partial<Pick<UserConfig, 'output'>>; 31} 32 33export default defineNuxtModule<ModuleOptions>({ 34 defaults: { 35 alias: '#hey-api', 36 autoImport: true, 37 }, 38 meta: { 39 configKey: 'heyApi', 40 name: '@hey-api/nuxt', 41 }, 42 async setup(options) { 43 const nuxt = useNuxt(); 44 45 const config = defu(options.config, { 46 output: { 47 path: path.join(nuxt.options.buildDir, 'client'), 48 }, 49 plugins: (options.config.plugins || []).some( 50 (plugin: Required<UserConfig>['plugins'][number]) => { 51 const pluginName = typeof plugin === 'string' ? plugin : plugin.name; 52 return pluginName === '@hey-api/client-nuxt'; 53 }, 54 ) 55 ? [] 56 : ['@hey-api/client-nuxt'], 57 } satisfies Partial<UserConfig>) as UserConfig; 58 59 if (nuxt.options._prepare) { 60 config.watch = false; 61 } 62 63 const output = config.output instanceof Array ? config.output[0] : config.output; 64 const folder = path.resolve( 65 nuxt.options.rootDir, 66 typeof output === 'string' ? output : (output?.path ?? ''), 67 ); 68 69 nuxt.options.alias[options.alias!] = folder; 70 71 nuxt.hooks.hookOnce('app:templates', async () => { 72 await createClient(config); 73 }); 74 75 // auto-import enabled 76 if (options.autoImport) { 77 await createClient(config); 78 const typeImports = new Set<string>(); 79 const valueImports = new Set<string>(); 80 const files = findExports(fs.readFileSync(path.join(folder, 'index.ts'), 'utf-8')); 81 for (const file of files) { 82 if (!file.specifier || !/^\.{1,2}\//.test(file.specifier)) { 83 continue; 84 } 85 const filePath = await findPath(path.resolve(folder, file.specifier)); 86 if (!filePath) { 87 continue; 88 } 89 const blob = fs.readFileSync(filePath, 'utf-8'); 90 for (const { names } of findTypeExports(blob)) { 91 for (const name of names) { 92 typeImports.add(name); 93 } 94 } 95 for (const { names } of findExports(blob)) { 96 for (const name of names) { 97 valueImports.add(name); 98 } 99 } 100 } 101 102 const imports = [...[...typeImports].map((name) => ({ name, type: true })), ...valueImports]; 103 104 if (imports.length && options.alias) { 105 addImportsSources({ 106 from: options.alias, 107 imports, 108 }); 109 } 110 } 111 }, 112}) as any;