fork of hey-api/openapi-ts because I need some additional things
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #571 from hey-api/feat/multiple-configs

chore: update types for multiple configs

authored by

Lubos and committed by
GitHub
0277e291 cd0f77fe

+127 -83
-2
README.md
··· 13 13 - works with CLI, Node.js, or npx 14 14 - supports OpenAPI 2.0, 3.0, and 3.1 specifications 15 15 - supports both JSON and YAML input files 16 - - supports external references using [json-schema-ref-parser](https://github.com/APIDevTools/json-schema-ref-parser/) 17 16 - generates TypeScript interfaces, REST clients, and JSON Schemas 18 17 - Fetch API, Axios, Angular, Node.js, and XHR clients available 19 - - abortable requests through cancellable promise pattern 20 18 21 19 ## Documentation 22 20
+25
docs/openapi-ts/configuration.md
··· 101 101 You might not need a `node` client. Fetch API is [experimental](https://nodejs.org/docs/latest-v18.x/api/globals.html#fetch) in Node.js v18 and [stable](https://nodejs.org/docs/latest-v21.x/api/globals.html#fetch) in Node.js v21. We recommend upgrading to the latest Node.js version. 102 102 ::: 103 103 104 + <!-- 105 + TODO: uncomment after c12 supports multiple configs 106 + see https://github.com/unjs/c12/issues/92 107 + --> 108 + <!-- ### Multiple Clients 109 + 110 + If you want to generate multiple clients with a single `openapi-ts` command, you can provide an array of configuration objects. 111 + 112 + ```js 113 + import { defineConfig } from '@hey-api/openapi-ts'; 114 + 115 + export default defineConfig([ 116 + { 117 + client: 'fetch', 118 + input: 'path/to/openapi_one.json', 119 + output: 'src/client_one', 120 + }, 121 + { 122 + client: 'axios', 123 + input: 'path/to/openapi_two.json', 124 + output: 'src/client_two', 125 + }, 126 + ]) 127 + ``` --> 128 + 104 129 ## Formatting 105 130 106 131 By default, `openapi-ts` will not automatically format your client. To enable this feature, set `output.format` to a valid formatter.
+92 -74
packages/openapi-ts/src/index.ts
··· 5 5 6 6 import { parse } from './openApi'; 7 7 import type { Client } from './types/client'; 8 - import type { Config, UserConfig } from './types/config'; 8 + import type { ClientConfig, Config, UserConfig } from './types/config'; 9 9 import { getConfig, setConfig } from './utils/config'; 10 10 import { getOpenApiSpec } from './utils/getOpenApiSpec'; 11 11 import { registerHandlebarTemplates } from './utils/handlebars'; ··· 96 96 } 97 97 }; 98 98 99 - const getOutput = (userConfig: UserConfig): Config['output'] => { 99 + const getOutput = (userConfig: ClientConfig): Config['output'] => { 100 100 let output: Config['output'] = { 101 101 format: false, 102 102 lint: false, ··· 113 113 return output; 114 114 }; 115 115 116 - const getSchemas = (userConfig: UserConfig): Config['schemas'] => { 116 + const getSchemas = (userConfig: ClientConfig): Config['schemas'] => { 117 117 let schemas: Config['schemas'] = { 118 118 export: true, 119 119 type: 'json', ··· 129 129 return schemas; 130 130 }; 131 131 132 - const getServices = (userConfig: UserConfig): Config['services'] => { 132 + const getServices = (userConfig: ClientConfig): Config['services'] => { 133 133 let services: Config['services'] = { 134 134 export: true, 135 135 name: '{{name}}Service', ··· 149 149 return services; 150 150 }; 151 151 152 - const getTypes = (userConfig: UserConfig): Config['types'] => { 152 + const getTypes = (userConfig: ClientConfig): Config['types'] => { 153 153 let types: Config['types'] = { 154 154 dates: false, 155 155 enums: false, ··· 169 169 return types; 170 170 }; 171 171 172 - const initConfig = async (userConfig: UserConfig) => { 173 - const { config: userConfigFromFile } = await loadConfig<UserConfig>({ 172 + const initConfigs = async (userConfig: UserConfig): Promise<Config[]> => { 173 + const { config: configFromFile } = await loadConfig<UserConfig>({ 174 174 jitiOptions: { 175 175 esmResolve: true, 176 176 }, 177 177 name: 'openapi-ts', 178 - overrides: userConfig, 179 178 }); 180 179 181 - if (userConfigFromFile) { 182 - userConfig = { ...userConfigFromFile, ...userConfig }; 183 - } 180 + const userConfigs: ClientConfig[] = Array.isArray(userConfig) 181 + ? userConfig 182 + : Array.isArray(configFromFile) 183 + ? configFromFile.map((config) => ({ 184 + ...config, 185 + ...userConfig, 186 + })) 187 + : [{ ...(configFromFile ?? {}), ...userConfig }]; 184 188 185 - const { 186 - base, 187 - client = 'fetch', 188 - debug = false, 189 - dryRun = false, 190 - exportCore = true, 191 - input, 192 - name, 193 - request, 194 - useOptions = true, 195 - } = userConfig; 189 + return userConfigs.map((userConfig) => { 190 + const { 191 + base, 192 + client = 'fetch', 193 + debug = false, 194 + dryRun = false, 195 + exportCore = true, 196 + input, 197 + name, 198 + request, 199 + useOptions = true, 200 + } = userConfig; 196 201 197 - if (debug) { 198 - console.warn('userConfig:', userConfig); 199 - } 202 + if (debug) { 203 + console.warn('userConfig:', userConfig); 204 + } 200 205 201 - const output = getOutput(userConfig); 206 + const output = getOutput(userConfig); 202 207 203 - if (!input) { 204 - throw new Error( 205 - '🚫 input not provided - provide path to OpenAPI specification', 206 - ); 207 - } 208 + if (!input) { 209 + throw new Error( 210 + '🚫 input not provided - provide path to OpenAPI specification', 211 + ); 212 + } 208 213 209 - if (!output.path) { 210 - throw new Error( 211 - '🚫 output not provided - provide path where we should generate your client', 212 - ); 213 - } 214 + if (!output.path) { 215 + throw new Error( 216 + '🚫 output not provided - provide path where we should generate your client', 217 + ); 218 + } 214 219 215 - if (!useOptions) { 216 - console.warn( 217 - '⚠️ Deprecation warning: useOptions set to false. This setting will be removed in future versions. Please migrate useOptions to true https://heyapi.vercel.app/openapi-ts/migrating.html#v0-27-38', 218 - ); 219 - } 220 + if (!useOptions) { 221 + console.warn( 222 + '⚠️ Deprecation warning: useOptions set to false. This setting will be removed in future versions. Please migrate useOptions to true https://heyapi.vercel.app/openapi-ts/migrating.html#v0-27-38', 223 + ); 224 + } 220 225 221 - const schemas = getSchemas(userConfig); 222 - const services = getServices(userConfig); 223 - const types = getTypes(userConfig); 226 + const schemas = getSchemas(userConfig); 227 + const services = getServices(userConfig); 228 + const types = getTypes(userConfig); 224 229 225 - output.path = path.resolve(process.cwd(), output.path); 230 + output.path = path.resolve(process.cwd(), output.path); 226 231 227 - return setConfig({ 228 - base, 229 - client, 230 - debug, 231 - dryRun, 232 - exportCore: client.startsWith('@hey-api') ? false : exportCore, 233 - input, 234 - name, 235 - output, 236 - request, 237 - schemas, 238 - services, 239 - types, 240 - useOptions, 232 + return setConfig({ 233 + base, 234 + client, 235 + debug, 236 + dryRun, 237 + exportCore: client.startsWith('@hey-api') ? false : exportCore, 238 + input, 239 + name, 240 + output, 241 + request, 242 + schemas, 243 + services, 244 + types, 245 + useOptions, 246 + }); 241 247 }); 242 248 }; 243 249 ··· 247 253 * service layer, etc. 248 254 * @param userConfig {@link UserConfig} passed to the `createClient()` method 249 255 */ 250 - export async function createClient(userConfig: UserConfig): Promise<Client> { 251 - const config = await initConfig(userConfig); 256 + export async function createClient(userConfig: UserConfig): Promise<Client[]> { 257 + const configs = await initConfigs(userConfig); 258 + 259 + const createClientPromise = (config: Config) => async () => { 260 + const openApi = 261 + typeof config.input === 'string' 262 + ? await getOpenApiSpec(config.input) 263 + : (config.input as unknown as Awaited< 264 + ReturnType<typeof getOpenApiSpec> 265 + >); 252 266 253 - const openApi = 254 - typeof config.input === 'string' 255 - ? await getOpenApiSpec(config.input) 256 - : (config.input as unknown as Awaited<ReturnType<typeof getOpenApiSpec>>); 267 + const client = postProcessClient(parse(openApi)); 268 + const templates = registerHandlebarTemplates(); 257 269 258 - const client = postProcessClient(parse(openApi)); 259 - const templates = registerHandlebarTemplates(); 270 + if (!config.dryRun) { 271 + logClientMessage(); 272 + await writeClient(openApi, client, templates); 273 + processOutput(); 274 + } 260 275 261 - if (!config.dryRun) { 262 - logClientMessage(); 263 - await writeClient(openApi, client, templates); 264 - processOutput(); 265 - } 276 + console.log('✨ Done! Your client is located in:', config.output.path); 266 277 267 - console.log('✨ Done! Your client is located in:', config.output.path); 278 + return client; 279 + }; 268 280 269 - return client; 281 + let clients: Client[] = []; 282 + const clientPromises = configs.map((config) => createClientPromise(config)); 283 + for (const clientPromise of clientPromises) { 284 + const client = await clientPromise(); 285 + clients = [...clients, client]; 286 + } 287 + return clients; 270 288 } 271 289 272 290 /**
+10 -7
packages/openapi-ts/src/types/config.ts
··· 1 - export interface UserConfig { 1 + export interface ClientConfig { 2 2 /** 3 3 * Manually set base in OpenAPI config instead of inferring from server value 4 4 * @deprecated ··· 160 160 useOptions?: boolean; 161 161 } 162 162 163 + // export type UserConfig = ClientConfig | Array<ClientConfig> 164 + export type UserConfig = ClientConfig; 165 + 163 166 export type Config = Omit< 164 - Required<UserConfig>, 167 + Required<ClientConfig>, 165 168 'base' | 'name' | 'output' | 'request' | 'schemas' | 'services' | 'types' 166 169 > & 167 - Pick<UserConfig, 'base' | 'name' | 'request'> & { 168 - output: Extract<Required<UserConfig>['output'], object>; 169 - schemas: Extract<Required<UserConfig>['schemas'], object>; 170 - services: Extract<Required<UserConfig>['services'], object>; 171 - types: Extract<Required<UserConfig>['types'], object>; 170 + Pick<ClientConfig, 'base' | 'name' | 'request'> & { 171 + output: Extract<Required<ClientConfig>['output'], object>; 172 + schemas: Extract<Required<ClientConfig>['schemas'], object>; 173 + services: Extract<Required<ClientConfig>['services'], object>; 174 + types: Extract<Required<ClientConfig>['types'], object>; 172 175 };