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

Merge pull request #3047 from hey-api/fix/sdk-flat-map

fix(@hey-api/sdk): correctly map flat parameters

authored by

Lubos and committed by
GitHub
2b11229a 7f52c346

+113 -86
+5
.changeset/deep-lies-wish.md
··· 1 + --- 2 + '@hey-api/openapi-ts': patch 3 + --- 4 + 5 + **@hey-api/sdk**: correctly map flat parameters
+19 -19
dev/openapi-ts.config.ts
··· 40 40 // 'circular.yaml', 41 41 // 'dutchie.json', 42 42 // 'invalid', 43 - 'full.yaml', 43 + // 'full.yaml', 44 44 // 'object-property-names.yaml', 45 45 // 'openai.yaml', 46 - // 'opencode.yaml', 46 + 'opencode.yaml', 47 47 // 'pagination-ref.yaml', 48 48 // 'sdk-instance.yaml', 49 49 // 'string-with-format.yaml', ··· 96 96 // suffix: '.meh', 97 97 // }, 98 98 // format: 'prettier', 99 - // importFileExtension: '.ts', 99 + importFileExtension: '.ts', 100 100 // indexFile: false, 101 101 // lint: 'eslint', 102 102 path: path.resolve(__dirname, '.gen'), 103 - tsConfigPath: path.resolve( 104 - __dirname, 105 - 'tsconfig', 106 - 'tsconfig.nodenext.json', 107 - ), 103 + // tsConfigPath: path.resolve( 104 + // __dirname, 105 + // 'tsconfig', 106 + // 'tsconfig.nodenext.json', 107 + // ), 108 108 }, 109 109 // '.gen', 110 110 ], ··· 217 217 { 218 218 // baseUrl: false, 219 219 // exportFromIndex: true, 220 - name: '@hey-api/client-angular', 220 + // name: '@hey-api/client-angular', 221 221 // runtimeConfigPath: path.resolve(__dirname, 'hey-api.ts'), 222 222 // runtimeConfigPath: './src/hey-api.ts', 223 223 // strictBaseUrl: true, ··· 264 264 // instance: true, 265 265 name: '@hey-api/sdk', 266 266 // operationId: false, 267 - // paramsStructure: 'flat', 268 - responseStyle: 'data', 267 + paramsStructure: 'flat', 268 + // responseStyle: 'data', 269 269 // signature: 'auto', 270 270 // signature: 'client', 271 271 // signature: 'object', 272 272 // transformer: '@hey-api/transformers', 273 273 // transformer: true, 274 - validator: 'valibot', 274 + // validator: 'valibot', 275 275 // validator: { 276 276 // request: 'zod', 277 277 // response: 'zod', ··· 293 293 { 294 294 // bigInt: true, 295 295 dates: true, 296 - name: '@hey-api/transformers', 296 + // name: '@hey-api/transformers', 297 297 }, 298 298 { 299 - name: 'fastify', 299 + // name: 'fastify', 300 300 }, 301 301 { 302 - name: 'swr', 302 + // name: 'swr', 303 303 }, 304 304 { 305 305 // case: 'SCREAMING_SNAKE_CASE', ··· 357 357 }, 358 358 }, 359 359 { 360 - name: 'arktype', 360 + // name: 'arktype', 361 361 types: { 362 362 infer: true, 363 363 }, ··· 368 368 // definitions: 'z{{name}}Definition', 369 369 exportFromIndex: true, 370 370 // metadata: true, 371 - name: 'valibot', 371 + // name: 'valibot', 372 372 // requests: { 373 373 // case: 'PascalCase', 374 374 // name: '{{name}}Data', ··· 445 445 }, 446 446 // exportFromIndex: true, 447 447 metadata: true, 448 - name: 'zod', 448 + // name: 'zod', 449 449 // requests: { 450 450 // // case: 'SCREAMING_SNAKE_CASE', 451 451 // // name: 'z{{name}}TestData', ··· 522 522 httpResources: { 523 523 asClass: true, 524 524 }, 525 - name: '@angular/common', 525 + // name: '@angular/common', 526 526 }, 527 527 { 528 528 exportFromIndex: true,
+3
dev/package.json
··· 6 6 "engines": { 7 7 "node": ">=20.19.0" 8 8 }, 9 + "scripts": { 10 + "dev": "ts-node ./playground.ts" 11 + }, 9 12 "devDependencies": { 10 13 "@hey-api/codegen-core": "workspace:*", 11 14 "@hey-api/openapi-ts": "workspace:*",
+15 -1
dev/playground.ts
··· 1 1 import type { DefinePlugin, IR } from '@hey-api/openapi-ts'; 2 2 3 + import { authSet } from './.gen/index.ts'; 4 + 3 5 type MyPluginConfig = { readonly name: 'myplugin' }; 4 6 type MyPlugin = DefinePlugin<MyPluginConfig>; 5 7 6 8 export function f(schema: IR.SchemaObject, plugin: MyPlugin['Instance']) { 7 - plugin.context.resolveIrRef(schema.$ref); 9 + plugin.context.resolveIrRef(schema.$ref!); 8 10 } 9 11 10 12 export const handler: MyPlugin['Handler'] = ({ plugin }) => { ··· 12 14 console.log(event); 13 15 }); 14 16 }; 17 + 18 + console.log( 19 + authSet({ 20 + auth: { 21 + access: '', 22 + expires: 1, 23 + refresh: '', 24 + type: 'oauth', 25 + }, 26 + id: '123', 27 + }), 28 + );
+65 -65
packages/openapi-ts-tests/sdks/__snapshots__/opencode/flat/sdk.gen.ts
··· 50 50 parentID?: string; 51 51 title?: string; 52 52 }, options?: Options<never, ThrowOnError>) => { 53 - const params = buildClientParams([parameters], [{ in: 'body', key: 'parentID' }, { in: 'body', key: 'title' }]); 53 + const params = buildClientParams([parameters], [{ args: [{ in: 'body', key: 'parentID' }, { in: 'body', key: 'title' }] }]); 54 54 return (options?.client ?? client).post<SessionCreateResponses, SessionCreateErrors, ThrowOnError>({ 55 55 url: '/session', 56 56 ...options, ··· 69 69 export const sessionDelete = <ThrowOnError extends boolean = false>(parameters: { 70 70 id: string; 71 71 }, options?: Options<never, ThrowOnError>) => { 72 - const params = buildClientParams([parameters], [{ in: 'path', key: 'id' }]); 72 + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'id' }] }]); 73 73 return (options?.client ?? client).delete<SessionDeleteResponses, unknown, ThrowOnError>({ 74 74 url: '/session/{id}', 75 75 ...options, ··· 83 83 export const sessionGet = <ThrowOnError extends boolean = false>(parameters: { 84 84 id: string; 85 85 }, options?: Options<never, ThrowOnError>) => { 86 - const params = buildClientParams([parameters], [{ in: 'path', key: 'id' }]); 86 + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'id' }] }]); 87 87 return (options?.client ?? client).get<SessionGetResponses, unknown, ThrowOnError>({ 88 88 url: '/session/{id}', 89 89 ...options, ··· 98 98 id: string; 99 99 title?: string; 100 100 }, options?: Options<never, ThrowOnError>) => { 101 - const params = buildClientParams([parameters], [{ in: 'path', key: 'id' }, { in: 'body', key: 'title' }]); 101 + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'id' }, { in: 'body', key: 'title' }] }]); 102 102 return (options?.client ?? client).patch<SessionUpdateResponses, unknown, ThrowOnError>({ 103 103 url: '/session/{id}', 104 104 ...options, ··· 117 117 export const sessionChildren = <ThrowOnError extends boolean = false>(parameters: { 118 118 id: string; 119 119 }, options?: Options<never, ThrowOnError>) => { 120 - const params = buildClientParams([parameters], [{ in: 'path', key: 'id' }]); 120 + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'id' }] }]); 121 121 return (options?.client ?? client).get<SessionChildrenResponses, unknown, ThrowOnError>({ 122 122 url: '/session/{id}/children', 123 123 ...options, ··· 134 134 providerID?: string; 135 135 modelID?: string; 136 136 }, options?: Options<never, ThrowOnError>) => { 137 - const params = buildClientParams([parameters], [ 138 - { in: 'path', key: 'id' }, 139 - { in: 'body', key: 'messageID' }, 140 - { in: 'body', key: 'providerID' }, 141 - { in: 'body', key: 'modelID' } 142 - ]); 137 + const params = buildClientParams([parameters], [{ args: [ 138 + { in: 'path', key: 'id' }, 139 + { in: 'body', key: 'messageID' }, 140 + { in: 'body', key: 'providerID' }, 141 + { in: 'body', key: 'modelID' } 142 + ] }]); 143 143 return (options?.client ?? client).post<SessionInitResponses, unknown, ThrowOnError>({ 144 144 url: '/session/{id}/init', 145 145 ...options, ··· 158 158 export const sessionAbort = <ThrowOnError extends boolean = false>(parameters: { 159 159 id: string; 160 160 }, options?: Options<never, ThrowOnError>) => { 161 - const params = buildClientParams([parameters], [{ in: 'path', key: 'id' }]); 161 + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'id' }] }]); 162 162 return (options?.client ?? client).post<SessionAbortResponses, unknown, ThrowOnError>({ 163 163 url: '/session/{id}/abort', 164 164 ...options, ··· 172 172 export const sessionUnshare = <ThrowOnError extends boolean = false>(parameters: { 173 173 id: string; 174 174 }, options?: Options<never, ThrowOnError>) => { 175 - const params = buildClientParams([parameters], [{ in: 'path', key: 'id' }]); 175 + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'id' }] }]); 176 176 return (options?.client ?? client).delete<SessionUnshareResponses, unknown, ThrowOnError>({ 177 177 url: '/session/{id}/share', 178 178 ...options, ··· 186 186 export const sessionShare = <ThrowOnError extends boolean = false>(parameters: { 187 187 id: string; 188 188 }, options?: Options<never, ThrowOnError>) => { 189 - const params = buildClientParams([parameters], [{ in: 'path', key: 'id' }]); 189 + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'id' }] }]); 190 190 return (options?.client ?? client).post<SessionShareResponses, unknown, ThrowOnError>({ 191 191 url: '/session/{id}/share', 192 192 ...options, ··· 202 202 providerID?: string; 203 203 modelID?: string; 204 204 }, options?: Options<never, ThrowOnError>) => { 205 - const params = buildClientParams([parameters], [ 206 - { in: 'path', key: 'id' }, 207 - { in: 'body', key: 'providerID' }, 208 - { in: 'body', key: 'modelID' } 209 - ]); 205 + const params = buildClientParams([parameters], [{ args: [ 206 + { in: 'path', key: 'id' }, 207 + { in: 'body', key: 'providerID' }, 208 + { in: 'body', key: 'modelID' } 209 + ] }]); 210 210 return (options?.client ?? client).post<SessionSummarizeResponses, unknown, ThrowOnError>({ 211 211 url: '/session/{id}/summarize', 212 212 ...options, ··· 225 225 export const sessionMessages = <ThrowOnError extends boolean = false>(parameters: { 226 226 id: string; 227 227 }, options?: Options<never, ThrowOnError>) => { 228 - const params = buildClientParams([parameters], [{ in: 'path', key: 'id' }]); 228 + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'id' }] }]); 229 229 return (options?.client ?? client).get<SessionMessagesResponses, unknown, ThrowOnError>({ 230 230 url: '/session/{id}/message', 231 231 ...options, ··· 254 254 type: 'agent'; 255 255 } & AgentPartInput)>; 256 256 }, options?: Options<never, ThrowOnError>) => { 257 - const params = buildClientParams([parameters], [ 258 - { in: 'path', key: 'id' }, 259 - { in: 'body', key: 'messageID' }, 260 - { in: 'body', key: 'providerID' }, 261 - { in: 'body', key: 'modelID' }, 262 - { in: 'body', key: 'agent' }, 263 - { in: 'body', key: 'system' }, 264 - { in: 'body', key: 'tools' }, 265 - { in: 'body', key: 'parts' } 266 - ]); 257 + const params = buildClientParams([parameters], [{ args: [ 258 + { in: 'path', key: 'id' }, 259 + { in: 'body', key: 'messageID' }, 260 + { in: 'body', key: 'providerID' }, 261 + { in: 'body', key: 'modelID' }, 262 + { in: 'body', key: 'agent' }, 263 + { in: 'body', key: 'system' }, 264 + { in: 'body', key: 'tools' }, 265 + { in: 'body', key: 'parts' } 266 + ] }]); 267 267 return (options?.client ?? client).post<SessionChatResponses, unknown, ThrowOnError>({ 268 268 url: '/session/{id}/message', 269 269 ...options, ··· 283 283 id: string; 284 284 messageID: string; 285 285 }, options?: Options<never, ThrowOnError>) => { 286 - const params = buildClientParams([parameters], [{ in: 'path', key: 'id' }, { in: 'path', key: 'messageID' }]); 286 + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'id' }, { in: 'path', key: 'messageID' }] }]); 287 287 return (options?.client ?? client).get<SessionMessageResponses, unknown, ThrowOnError>({ 288 288 url: '/session/{id}/message/{messageID}', 289 289 ...options, ··· 299 299 agent?: string; 300 300 command?: string; 301 301 }, options?: Options<never, ThrowOnError>) => { 302 - const params = buildClientParams([parameters], [ 303 - { in: 'path', key: 'id' }, 304 - { in: 'body', key: 'agent' }, 305 - { in: 'body', key: 'command' } 306 - ]); 302 + const params = buildClientParams([parameters], [{ args: [ 303 + { in: 'path', key: 'id' }, 304 + { in: 'body', key: 'agent' }, 305 + { in: 'body', key: 'command' } 306 + ] }]); 307 307 return (options?.client ?? client).post<SessionShellResponses, unknown, ThrowOnError>({ 308 308 url: '/session/{id}/shell', 309 309 ...options, ··· 324 324 messageID?: string; 325 325 partID?: string; 326 326 }, options?: Options<never, ThrowOnError>) => { 327 - const params = buildClientParams([parameters], [ 328 - { in: 'path', key: 'id' }, 329 - { in: 'body', key: 'messageID' }, 330 - { in: 'body', key: 'partID' } 331 - ]); 327 + const params = buildClientParams([parameters], [{ args: [ 328 + { in: 'path', key: 'id' }, 329 + { in: 'body', key: 'messageID' }, 330 + { in: 'body', key: 'partID' } 331 + ] }]); 332 332 return (options?.client ?? client).post<SessionRevertResponses, unknown, ThrowOnError>({ 333 333 url: '/session/{id}/revert', 334 334 ...options, ··· 347 347 export const sessionUnrevert = <ThrowOnError extends boolean = false>(parameters: { 348 348 id: string; 349 349 }, options?: Options<never, ThrowOnError>) => { 350 - const params = buildClientParams([parameters], [{ in: 'path', key: 'id' }]); 350 + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'id' }] }]); 351 351 return (options?.client ?? client).post<SessionUnrevertResponses, unknown, ThrowOnError>({ 352 352 url: '/session/{id}/unrevert', 353 353 ...options, ··· 363 363 permissionID: string; 364 364 response?: 'once' | 'always' | 'reject'; 365 365 }, options?: Options<never, ThrowOnError>) => { 366 - const params = buildClientParams([parameters], [ 367 - { in: 'path', key: 'id' }, 368 - { in: 'path', key: 'permissionID' }, 369 - { in: 'body', key: 'response' } 370 - ]); 366 + const params = buildClientParams([parameters], [{ args: [ 367 + { in: 'path', key: 'id' }, 368 + { in: 'path', key: 'permissionID' }, 369 + { in: 'body', key: 'response' } 370 + ] }]); 371 371 return (options?.client ?? client).post<PostSessionByIdPermissionsByPermissionIdResponses, unknown, ThrowOnError>({ 372 372 url: '/session/{id}/permissions/{permissionID}', 373 373 ...options, ··· 391 391 export const findText = <ThrowOnError extends boolean = false>(parameters: { 392 392 pattern: string; 393 393 }, options?: Options<never, ThrowOnError>) => { 394 - const params = buildClientParams([parameters], [{ in: 'query', key: 'pattern' }]); 394 + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'pattern' }] }]); 395 395 return (options?.client ?? client).get<FindTextResponses, unknown, ThrowOnError>({ 396 396 url: '/find', 397 397 ...options, ··· 405 405 export const findFiles = <ThrowOnError extends boolean = false>(parameters: { 406 406 query: string; 407 407 }, options?: Options<never, ThrowOnError>) => { 408 - const params = buildClientParams([parameters], [{ in: 'query', key: 'query' }]); 408 + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'query' }] }]); 409 409 return (options?.client ?? client).get<FindFilesResponses, unknown, ThrowOnError>({ 410 410 url: '/find/file', 411 411 ...options, ··· 419 419 export const findSymbols = <ThrowOnError extends boolean = false>(parameters: { 420 420 query: string; 421 421 }, options?: Options<never, ThrowOnError>) => { 422 - const params = buildClientParams([parameters], [{ in: 'query', key: 'query' }]); 422 + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'query' }] }]); 423 423 return (options?.client ?? client).get<FindSymbolsResponses, unknown, ThrowOnError>({ 424 424 url: '/find/symbol', 425 425 ...options, ··· 433 433 export const fileRead = <ThrowOnError extends boolean = false>(parameters: { 434 434 path: string; 435 435 }, options?: Options<never, ThrowOnError>) => { 436 - const params = buildClientParams([parameters], [{ in: 'query', key: 'path' }]); 436 + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'path' }] }]); 437 437 return (options?.client ?? client).get<FileReadResponses, unknown, ThrowOnError>({ 438 438 url: '/file', 439 439 ...options, ··· 457 457 [key: string]: unknown; 458 458 }; 459 459 }, options?: Options<never, ThrowOnError>) => { 460 - const params = buildClientParams([parameters], [ 461 - { in: 'body', key: 'service' }, 462 - { in: 'body', key: 'level' }, 463 - { in: 'body', key: 'message' }, 464 - { in: 'body', key: 'extra' } 465 - ]); 460 + const params = buildClientParams([parameters], [{ args: [ 461 + { in: 'body', key: 'service' }, 462 + { in: 'body', key: 'level' }, 463 + { in: 'body', key: 'message' }, 464 + { in: 'body', key: 'extra' } 465 + ] }]); 466 466 return (options?.client ?? client).post<AppLogResponses, unknown, ThrowOnError>({ 467 467 url: '/log', 468 468 ...options, ··· 486 486 export const tuiAppendPrompt = <ThrowOnError extends boolean = false>(parameters?: { 487 487 text?: string; 488 488 }, options?: Options<never, ThrowOnError>) => { 489 - const params = buildClientParams([parameters], [{ in: 'body', key: 'text' }]); 489 + const params = buildClientParams([parameters], [{ args: [{ in: 'body', key: 'text' }] }]); 490 490 return (options?.client ?? client).post<TuiAppendPromptResponses, unknown, ThrowOnError>({ 491 491 url: '/tui/append-prompt', 492 492 ...options, ··· 535 535 export const tuiExecuteCommand = <ThrowOnError extends boolean = false>(parameters?: { 536 536 command?: string; 537 537 }, options?: Options<never, ThrowOnError>) => { 538 - const params = buildClientParams([parameters], [{ in: 'body', key: 'command' }]); 538 + const params = buildClientParams([parameters], [{ args: [{ in: 'body', key: 'command' }] }]); 539 539 return (options?.client ?? client).post<TuiExecuteCommandResponses, unknown, ThrowOnError>({ 540 540 url: '/tui/execute-command', 541 541 ...options, ··· 556 556 message?: string; 557 557 variant?: 'info' | 'success' | 'warning' | 'error'; 558 558 }, options?: Options<never, ThrowOnError>) => { 559 - const params = buildClientParams([parameters], [ 560 - { in: 'body', key: 'title' }, 561 - { in: 'body', key: 'message' }, 562 - { in: 'body', key: 'variant' } 563 - ]); 559 + const params = buildClientParams([parameters], [{ args: [ 560 + { in: 'body', key: 'title' }, 561 + { in: 'body', key: 'message' }, 562 + { in: 'body', key: 'variant' } 563 + ] }]); 564 564 return (options?.client ?? client).post<TuiShowToastResponses, unknown, ThrowOnError>({ 565 565 url: '/tui/show-toast', 566 566 ...options, ··· 580 580 id: string; 581 581 auth?: Auth; 582 582 }, options?: Options<never, ThrowOnError>) => { 583 - const params = buildClientParams([parameters], [{ in: 'path', key: 'id' }, {}]); 583 + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'id' }, { key: 'auth', map: 'body' }] }]); 584 584 return (options?.client ?? client).put<AuthSetResponses, AuthSetErrors, ThrowOnError>({ 585 585 url: '/auth/{id}', 586 586 ...options,
+6 -1
packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts
··· 548 548 const shape = $.object(); 549 549 if ('in' in field) { 550 550 shape.prop('in', $.literal(field.in)); 551 + } 552 + if ('key' in field) { 551 553 if (field.key) { 552 554 shape.prop('key', $.literal(field.key)); 553 555 } ··· 563 565 }); 564 566 statements.push( 565 567 $.const('params').assign( 566 - $(symbol.placeholder).call($.array(...args), $.array(...config)), 568 + $(symbol.placeholder).call( 569 + $.array(...args), 570 + $.array($.object().prop('args', $.array(...config))), 571 + ), 567 572 ), 568 573 ); 569 574 reqOptions.spread('params');