fork of hey-api/openapi-ts because I need some additional things
at feat/skip-token 174 lines 5.0 kB view raw
1import type { AnyPluginName, PluginContext, PluginNames } from '@hey-api/shared'; 2import { dependencyFactory, valueToObject } from '@hey-api/shared'; 3 4import { defaultPluginConfigs } from '../plugins/config'; 5import type { Config, UserConfig } from './types'; 6 7/** 8 * Default plugins used to generate artifacts if plugins aren't specified. 9 */ 10export const defaultPlugins = ['@hey-api/python-sdk'] as const satisfies ReadonlyArray<PluginNames>; 11 12function getPluginsConfig({ 13 dependencies, 14 userPlugins, 15 userPluginsConfig, 16}: { 17 dependencies: Record<string, string>; 18 userPlugins: ReadonlyArray<AnyPluginName>; 19 userPluginsConfig: Config['plugins']; 20}): Pick<Config, 'plugins' | 'pluginOrder'> { 21 const circularReferenceTracker = new Set<AnyPluginName>(); 22 const pluginOrder = new Set<AnyPluginName>(); 23 const plugins: Config['plugins'] = {}; 24 25 const dfs = (name: AnyPluginName) => { 26 if (circularReferenceTracker.has(name)) { 27 throw new Error(`Circular reference detected at '${name}'`); 28 } 29 30 if (pluginOrder.has(name)) { 31 return; 32 } 33 34 circularReferenceTracker.add(name); 35 36 const defaultPlugin = defaultPluginConfigs[name as PluginNames]; 37 const userPlugin = userPluginsConfig[name as PluginNames]; 38 39 if (!defaultPlugin && !userPlugin) { 40 throw new Error( 41 `unknown plugin dependency "${name}" - do you need to register a custom plugin with this name?`, 42 ); 43 } 44 45 const plugin = { 46 ...defaultPlugin, 47 ...userPlugin, 48 config: { 49 ...defaultPlugin?.config, 50 ...userPlugin?.config, 51 }, 52 dependencies: new Set([ 53 ...(defaultPlugin?.dependencies || []), 54 ...(userPlugin?.dependencies || []), 55 ]), 56 }; 57 58 if (plugin.resolveConfig) { 59 const context: PluginContext = { 60 package: dependencyFactory(dependencies), 61 pluginByTag: (tag, props = {}) => { 62 const { defaultPlugin, errorMessage } = props; 63 64 for (const userPlugin of userPlugins) { 65 const defaultConfig = 66 defaultPluginConfigs[userPlugin as PluginNames] || 67 userPluginsConfig[userPlugin as PluginNames]; 68 if (defaultConfig && defaultConfig.tags?.includes(tag) && userPlugin !== name) { 69 return userPlugin as any; 70 } 71 } 72 73 if (defaultPlugin) { 74 const defaultConfig = 75 defaultPluginConfigs[defaultPlugin as PluginNames] || 76 userPluginsConfig[defaultPlugin as PluginNames]; 77 if (defaultConfig && defaultConfig.tags?.includes(tag) && defaultPlugin !== name) { 78 return defaultPlugin; 79 } 80 } 81 82 throw new Error(errorMessage || `missing plugin - no plugin with tag "${tag}" found`); 83 }, 84 valueToObject, 85 }; 86 // @ts-expect-error 87 plugin.resolveConfig(plugin, context); 88 } 89 90 for (const dependency of plugin.dependencies) { 91 dfs(dependency); 92 } 93 94 circularReferenceTracker.delete(name); 95 pluginOrder.add(name); 96 97 // @ts-expect-error 98 plugins[name] = plugin; 99 }; 100 101 for (const name of userPlugins) { 102 dfs(name); 103 } 104 105 return { 106 pluginOrder: Array.from(pluginOrder) as ReadonlyArray<PluginNames>, 107 plugins, 108 }; 109} 110 111function isPluginClient(plugin: Required<UserConfig>['plugins'][number]): boolean { 112 if (typeof plugin === 'string') { 113 return plugin.startsWith('@hey-api/client'); 114 } 115 116 return ( 117 plugin.name.startsWith('@hey-api/client') || 118 // @ts-expect-error 119 (plugin.tags && plugin.tags.includes('client')) 120 ); 121} 122 123export function getPlugins({ 124 dependencies, 125 userConfig, 126}: { 127 dependencies: Record<string, string>; 128 userConfig: UserConfig; 129}): Pick<Config, 'plugins' | 'pluginOrder'> { 130 const userPluginsConfig: Config['plugins'] = {}; 131 132 let definedPlugins: UserConfig['plugins'] = defaultPlugins; 133 134 if (userConfig.plugins) { 135 userConfig.plugins = userConfig.plugins.filter( 136 (plugin) => 137 (typeof plugin === 'string' && plugin) || (typeof plugin !== 'string' && plugin.name), 138 ); 139 if (userConfig.plugins.length === 1 && isPluginClient(userConfig.plugins[0]!)) { 140 definedPlugins = [...defaultPlugins, ...userConfig.plugins]; 141 } else { 142 definedPlugins = userConfig.plugins; 143 } 144 } 145 146 const userPlugins = definedPlugins 147 .map((plugin) => { 148 if (typeof plugin === 'string') { 149 return plugin; 150 } 151 152 const pluginName = plugin.name; 153 154 if (pluginName) { 155 // @ts-expect-error 156 if (plugin.handler) { 157 // @ts-expect-error 158 userPluginsConfig[pluginName] = plugin; 159 } else { 160 // @ts-expect-error 161 userPluginsConfig[pluginName] = { 162 config: { ...plugin }, 163 }; 164 // @ts-expect-error 165 delete userPluginsConfig[pluginName]!.config.name; 166 } 167 } 168 169 return pluginName; 170 }) 171 .filter(Boolean); 172 173 return getPluginsConfig({ dependencies, userPlugins, userPluginsConfig }); 174}