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 #2840 from hey-api/refactor/sdk-plugin

refactor: clean up sdk plugin

authored by

Lubos and committed by
GitHub
eab646b9 73288fb8

+639 -621
+11 -5
packages/openapi-ts-tests/main/test/openapi-ts.config.ts
··· 141 141 if (!symbol.external && !symbol.meta?.path) { 142 142 console.log(`[${plugin.name}]:`, symbol.name, symbol.meta); 143 143 } 144 - // if (symbol.meta?.path) { 145 - // console.log(`[${plugin.name}]:`, symbol.name, symbol.meta.path); 146 - // } 144 + if (symbol.meta?.path) { 145 + if (plugin.name === '@hey-api/sdk') { 146 + console.log( 147 + `[${plugin.name}]:`, 148 + symbol.name, 149 + symbol.meta.path, 150 + ); 151 + } 152 + } 147 153 }, 148 154 // 'symbol:setValue:after': ({ plugin, symbol }) => { 149 155 // console.log(`(${plugin.name}) set value:`, symbol.id); ··· 229 235 // error: '他們_error_{{name}}', 230 236 // name: '你們_errors_{{name}}', 231 237 // }, 232 - name: '@hey-api/typescript', 238 + // name: '@hey-api/typescript', 233 239 // requests: '我們_data_{{name}}', 234 240 // responses: { 235 241 // name: '我_responses_{{name}}', ··· 255 261 // }, 256 262 // include... 257 263 // instance: true, 258 - // name: '@hey-api/sdk', 264 + name: '@hey-api/sdk', 259 265 // operationId: false, 260 266 // params_EXPERIMENTAL: 'experiment', 261 267 // responseStyle: 'data',
-1
packages/openapi-ts/src/generate/__tests__/class.test.ts
··· 97 97 }, 98 98 '@hey-api/sdk': { 99 99 api: { 100 - createOperationComment: () => undefined, 101 100 selector: () => [], 102 101 }, 103 102 config: {
-3
packages/openapi-ts/src/generate/__tests__/core.test.ts
··· 112 112 }, 113 113 '@hey-api/sdk': { 114 114 api: { 115 - createOperationComment: () => undefined, 116 115 selector: () => [], 117 116 }, 118 117 config: { ··· 270 269 }, 271 270 '@hey-api/sdk': { 272 271 api: { 273 - createOperationComment: () => undefined, 274 272 selector: () => [], 275 273 }, 276 274 config: { ··· 411 409 }, 412 410 '@hey-api/sdk': { 413 411 api: { 414 - createOperationComment: () => undefined, 415 412 selector: () => [], 416 413 }, 417 414 config: {
-1
packages/openapi-ts/src/generate/legacy/__tests__/index.test.ts
··· 96 96 }, 97 97 '@hey-api/sdk': { 98 98 api: { 99 - createOperationComment: () => undefined, 100 99 selector: () => [], 101 100 }, 102 101 config: {
-1
packages/openapi-ts/src/generate/legacy/__tests__/output.test.ts
··· 109 109 }, 110 110 '@hey-api/sdk': { 111 111 api: { 112 - createOperationComment: () => undefined, 113 112 selector: () => [], 114 113 }, 115 114 config: {
+7 -4
packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts
··· 4 4 import type { IR } from '~/ir/types'; 5 5 import { buildName } from '~/openApi/shared/utils/name'; 6 6 import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; 7 - import { operationClasses } from '~/plugins/@hey-api/sdk/operation'; 8 - import { isOperationOptionsRequired } from '~/plugins/shared/utils/operation'; 7 + import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; 8 + import { 9 + createOperationComment, 10 + isOperationOptionsRequired, 11 + } from '~/plugins/shared/utils/operation'; 9 12 import { tsc } from '~/tsc'; 10 13 import { stringCase } from '~/utils/stringCase'; 11 14 ··· 293 296 294 297 return tsc.methodDeclaration({ 295 298 accessLevel: 'public', 296 - comment: sdkPlugin.api.createOperationComment({ operation }), 299 + comment: createOperationComment({ operation }), 297 300 name: methodName, 298 301 parameters: [ 299 302 { ··· 349 352 const dataType = symbolDataType?.placeholder || 'unknown'; 350 353 351 354 return tsc.constVariable({ 352 - comment: sdkPlugin.api.createOperationComment({ operation }), 355 + comment: createOperationComment({ operation }), 353 356 exportConst: symbol.exported, 354 357 expression: tsc.arrowFunction({ 355 358 parameters: [
+7 -4
packages/openapi-ts/src/plugins/@angular/common/httpResources.ts
··· 3 3 4 4 import type { IR } from '~/ir/types'; 5 5 import { buildName } from '~/openApi/shared/utils/name'; 6 - import { operationClasses } from '~/plugins/@hey-api/sdk/operation'; 7 - import { isOperationOptionsRequired } from '~/plugins/shared/utils/operation'; 6 + import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; 7 + import { 8 + createOperationComment, 9 + isOperationOptionsRequired, 10 + } from '~/plugins/shared/utils/operation'; 8 11 import { tsc } from '~/tsc'; 9 12 import { stringCase } from '~/utils/stringCase'; 10 13 ··· 374 377 375 378 return tsc.methodDeclaration({ 376 379 accessLevel: 'public', 377 - comment: sdkPlugin.api.createOperationComment({ operation }), 380 + comment: createOperationComment({ operation }), 378 381 name: methodName, 379 382 parameters: [ 380 383 { ··· 426 429 const dataType = symbolDataType?.placeholder || 'unknown'; 427 430 428 431 return tsc.constVariable({ 429 - comment: sdkPlugin.api.createOperationComment({ operation }), 432 + comment: createOperationComment({ operation }), 430 433 exportConst: symbol.exported, 431 434 expression: tsc.arrowFunction({ 432 435 parameters: [
+3
packages/openapi-ts/src/plugins/@hey-api/client-core/client.ts
··· 93 93 ]; 94 94 95 95 const symbolClient = plugin.registerSymbol({ 96 + meta: { 97 + path: [], 98 + }, 96 99 name: 'client', 97 100 selector: plugin.api.selector('client'), 98 101 });
+1
packages/openapi-ts/src/plugins/@hey-api/client-core/createClientConfig.ts
··· 29 29 exported: true, 30 30 meta: { 31 31 kind: 'type', 32 + path: [], 32 33 }, 33 34 name: 'CreateClientConfig', 34 35 });
-2
packages/openapi-ts/src/plugins/@hey-api/schemas/__tests__/schemas.test.ts
··· 100 100 }, 101 101 '@hey-api/sdk': { 102 102 api: { 103 - createOperationComment: () => undefined, 104 103 selector: () => [], 105 104 }, 106 105 config: { ··· 271 270 }, 272 271 '@hey-api/sdk': { 273 272 api: { 274 - createOperationComment: () => undefined, 275 273 selector: () => [], 276 274 }, 277 275 config: {
-4
packages/openapi-ts/src/plugins/@hey-api/sdk/__tests__/plugin.test.ts
··· 102 102 }, 103 103 '@hey-api/sdk': { 104 104 api: { 105 - createOperationComment: () => undefined, 106 105 selector: () => [], 107 106 }, 108 107 config: { ··· 345 344 }, 346 345 '@hey-api/sdk': { 347 346 api: { 348 - createOperationComment: () => undefined, 349 347 selector: () => [], 350 348 }, 351 349 config: { ··· 510 508 }, 511 509 '@hey-api/sdk': { 512 510 api: { 513 - createOperationComment: () => undefined, 514 511 selector: () => [], 515 512 }, 516 513 config: { ··· 678 675 }, 679 676 '@hey-api/sdk': { 680 677 api: { 681 - createOperationComment: () => undefined, 682 678 selector: () => [], 683 679 }, 684 680 config: {
-9
packages/openapi-ts/src/plugins/@hey-api/sdk/api.ts
··· 2 2 3 3 import type { Plugin } from '~/plugins'; 4 4 5 - import { createOperationComment } from './comment'; 6 - 7 5 type SelectorType = 8 6 | 'buildClientParams' 9 7 | 'class' ··· 16 14 | 'urlSearchParamsBodySerializer'; 17 15 18 16 export type IApi = { 19 - createOperationComment: typeof createOperationComment; 20 17 /** 21 18 * @param type Selector type. 22 19 * @param value Depends on `type`: ··· 36 33 37 34 export class Api implements IApi { 38 35 constructor(public meta: Plugin.Name<'@hey-api/sdk'>) {} 39 - 40 - createOperationComment( 41 - ...args: Parameters<typeof createOperationComment> 42 - ): ReturnType<typeof createOperationComment> { 43 - return createOperationComment(...args); 44 - } 45 36 46 37 selector(...args: ReadonlyArray<string | undefined>): Selector { 47 38 return [this.meta.name, ...(args as Selector)];
+2 -2
packages/openapi-ts/src/plugins/@hey-api/sdk/auth.ts packages/openapi-ts/src/plugins/@hey-api/sdk/shared/auth.ts
··· 1 1 import type { IR } from '~/ir/types'; 2 2 3 - import type { Auth } from '../client-core/bundle/auth'; 4 - import type { HeyApiSdkPlugin } from './types'; 3 + import type { Auth } from '../../client-core/bundle/auth'; 4 + import type { HeyApiSdkPlugin } from '../types'; 5 5 6 6 // TODO: parser - handle more security types 7 7 const securitySchemeObjectToAuthObject = ({
-37
packages/openapi-ts/src/plugins/@hey-api/sdk/comment.ts
··· 1 - import type { IR } from '~/ir/types'; 2 - import type { Comments } from '~/tsc'; 3 - import { escapeComment } from '~/utils/escape'; 4 - 5 - export const createOperationComment = ({ 6 - operation, 7 - }: { 8 - operation: IR.OperationObject; 9 - }): Comments | undefined => { 10 - const comments: Array<string> = []; 11 - 12 - if (operation.summary) { 13 - comments.push(escapeComment(operation.summary)); 14 - } 15 - 16 - if (operation.description) { 17 - if (comments.length) { 18 - comments.push(''); // Add an empty line between summary and description 19 - } 20 - 21 - comments.push(escapeComment(operation.description)); 22 - } 23 - 24 - if (operation.deprecated) { 25 - if (comments.length) { 26 - comments.push(''); // Add an empty line before deprecated 27 - } 28 - 29 - comments.push('@deprecated'); 30 - } 31 - 32 - if (!comments.length) { 33 - return; 34 - } 35 - 36 - return comments; 37 - };
packages/openapi-ts/src/plugins/@hey-api/sdk/constants.ts packages/openapi-ts/src/plugins/@hey-api/sdk/shared/constants.ts
+3 -3
packages/openapi-ts/src/plugins/@hey-api/sdk/operation.ts packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts
··· 11 11 import { stringCase } from '~/utils/stringCase'; 12 12 import { transformClassName } from '~/utils/transform'; 13 13 14 - import type { Field, Fields } from '../client-core/bundle/params'; 14 + import type { Field, Fields } from '../../client-core/bundle/params'; 15 + // import { getSignatureParameters } from './signature'; 16 + import type { HeyApiSdkPlugin } from '../types'; 15 17 import { operationAuth } from './auth'; 16 18 import { nuxtTypeComposable, nuxtTypeDefault } from './constants'; 17 - // import { getSignatureParameters } from './signature'; 18 - import type { HeyApiSdkPlugin } from './types'; 19 19 import { createRequestValidator, createResponseValidator } from './validator'; 20 20 21 21 interface ClassNameEntry {
+2 -512
packages/openapi-ts/src/plugins/@hey-api/sdk/plugin.ts
··· 1 - import type ts from 'typescript'; 2 - 3 - import { clientFolderAbsolutePath } from '~/generate/client'; 4 - import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; 5 - import { isOperationOptionsRequired } from '~/plugins/shared/utils/operation'; 6 - import { tsc } from '~/tsc'; 7 - import { stringCase } from '~/utils/stringCase'; 8 - 9 - import { nuxtTypeComposable, nuxtTypeDefault } from './constants'; 10 - import { 11 - operationClasses, 12 - operationParameters, 13 - operationStatements, 14 - } from './operation'; 15 - import { serviceFunctionIdentifier } from './plugin-legacy'; 16 - import { createTypeOptions } from './typeOptions'; 17 1 import type { HeyApiSdkPlugin } from './types'; 18 - 19 - const createClientClassNodes = ({ 20 - plugin, 21 - }: { 22 - plugin: HeyApiSdkPlugin['Instance']; 23 - }): ReadonlyArray<ts.ClassElement> => { 24 - const clientAssignmentStatement = tsc.expressionToStatement({ 25 - expression: tsc.binaryExpression({ 26 - left: tsc.propertyAccessExpression({ 27 - expression: tsc.this(), 28 - name: '_client', 29 - }), 30 - operator: '=', 31 - right: tsc.propertyAccessExpression({ 32 - expression: tsc.identifier({ text: 'args' }), 33 - name: 'client', 34 - }), 35 - }), 36 - }); 37 - 38 - const symbolClient = plugin.referenceSymbol(plugin.api.selector('Client')); 39 - const client = getClientPlugin(plugin.context.config); 40 - const symClient = 41 - client.api && 'selector' in client.api 42 - ? plugin.getSymbol( 43 - // @ts-expect-error 44 - client.api.selector('client'), 45 - ) 46 - : undefined; 47 - 48 - return [ 49 - tsc.propertyDeclaration({ 50 - initializer: symClient 51 - ? tsc.identifier({ text: symClient.placeholder }) 52 - : undefined, 53 - modifier: 'protected', 54 - name: '_client', 55 - type: tsc.typeReferenceNode({ typeName: symbolClient.placeholder }), 56 - }), 57 - // @ts-expect-error 58 - tsc.identifier({ text: '\n' }), 59 - tsc.constructorDeclaration({ 60 - multiLine: true, 61 - parameters: [ 62 - { 63 - isRequired: !plugin.config.client, 64 - name: 'args', 65 - type: tsc.typeInterfaceNode({ 66 - properties: [ 67 - { 68 - isRequired: !plugin.config.client, 69 - name: 'client', 70 - type: symbolClient.placeholder, 71 - }, 72 - ], 73 - useLegacyResolution: false, 74 - }), 75 - }, 76 - ], 77 - statements: [ 78 - !plugin.config.client 79 - ? clientAssignmentStatement 80 - : tsc.ifStatement({ 81 - expression: tsc.propertyAccessExpression({ 82 - expression: tsc.identifier({ text: 'args' }), 83 - isOptional: true, 84 - name: 'client', 85 - }), 86 - thenStatement: tsc.block({ 87 - statements: [clientAssignmentStatement], 88 - }), 89 - }), 90 - ], 91 - }), 92 - ]; 93 - }; 94 - 95 - interface SdkClassEntry { 96 - /** 97 - * Name of the class. 98 - */ 99 - className: string; 100 - /** 101 - * Symbol IDs for child classes located inside this class. 102 - */ 103 - classes: Set<number>; 104 - /** 105 - * Symbol ID for the class. 106 - */ 107 - id: number; 108 - /** 109 - * Track unique added method nodes. 110 - */ 111 - methods: Set<string>; 112 - /** 113 - * List of class nodes containing methods. 114 - */ 115 - nodes: Array<ts.ClassElement>; 116 - /** 117 - * Is this a root class? 118 - */ 119 - root: boolean; 120 - } 121 - 122 - const generateClassSdk = ({ 123 - plugin, 124 - }: { 125 - plugin: HeyApiSdkPlugin['Instance']; 126 - }) => { 127 - const client = getClientPlugin(plugin.context.config); 128 - const isAngularClient = client.name === '@hey-api/client-angular'; 129 - const isNuxtClient = client.name === '@hey-api/client-nuxt'; 130 - const sdkClasses = new Map<number, SdkClassEntry>(); 131 - /** 132 - * Track unique added classes. 133 - */ 134 - const generatedClasses = new Set<number>(); 135 - 136 - const clientClassNodes = plugin.config.instance 137 - ? createClientClassNodes({ plugin }) 138 - : []; 139 - 140 - plugin.forEach( 141 - 'operation', 142 - ({ operation }) => { 143 - const isRequiredOptions = isOperationOptionsRequired({ 144 - context: plugin.context, 145 - operation, 146 - }); 147 - const pluginTypeScript = plugin.getPluginOrThrow('@hey-api/typescript'); 148 - const symbolResponse = isNuxtClient 149 - ? plugin.getSymbol( 150 - pluginTypeScript.api.selector('response', operation.id), 151 - ) 152 - : undefined; 153 - 154 - const classes = operationClasses({ 155 - context: plugin.context, 156 - operation, 157 - plugin, 158 - }); 159 - 160 - for (const entry of classes.values()) { 161 - entry.path.forEach((currentClassName, index) => { 162 - const symbolCurrentClass = plugin.referenceSymbol( 163 - plugin.api.selector('class', currentClassName), 164 - ); 165 - if (!sdkClasses.has(symbolCurrentClass.id)) { 166 - sdkClasses.set(symbolCurrentClass.id, { 167 - className: currentClassName, 168 - classes: new Set(), 169 - id: symbolCurrentClass.id, 170 - methods: new Set(), 171 - nodes: [], 172 - root: !index, 173 - }); 174 - } 175 - 176 - const parentClassName = entry.path[index - 1]; 177 - if (parentClassName) { 178 - const symbolParentClass = plugin.referenceSymbol( 179 - plugin.api.selector('class', parentClassName), 180 - ); 181 - if ( 182 - symbolParentClass.placeholder !== symbolCurrentClass.placeholder 183 - ) { 184 - const parentClass = sdkClasses.get(symbolParentClass.id)!; 185 - parentClass.classes.add(symbolCurrentClass.id); 186 - sdkClasses.set(symbolParentClass.id, parentClass); 187 - } 188 - } 189 - 190 - const isLast = entry.path.length === index + 1; 191 - // add methods only to the last class 192 - if (!isLast) { 193 - return; 194 - } 195 - 196 - const currentClass = sdkClasses.get(symbolCurrentClass.id)!; 197 - 198 - // avoid duplicate methods 199 - if (currentClass.methods.has(entry.methodName)) { 200 - return; 201 - } 202 - 203 - const opParameters = operationParameters({ 204 - isRequiredOptions, 205 - operation, 206 - plugin, 207 - }); 208 - const statements = operationStatements({ 209 - isRequiredOptions, 210 - opParameters, 211 - operation, 212 - plugin, 213 - }); 214 - const functionNode = tsc.methodDeclaration({ 215 - accessLevel: 'public', 216 - comment: plugin.api.createOperationComment({ operation }), 217 - isStatic: isAngularClient ? false : !plugin.config.instance, 218 - name: entry.methodName, 219 - parameters: opParameters.parameters, 220 - returnType: undefined, 221 - statements, 222 - types: isNuxtClient 223 - ? [ 224 - { 225 - default: tsc.ots.string('$fetch'), 226 - extends: tsc.typeNode( 227 - plugin.referenceSymbol(plugin.api.selector('Composable')) 228 - .placeholder, 229 - ), 230 - name: nuxtTypeComposable, 231 - }, 232 - { 233 - default: symbolResponse 234 - ? tsc.typeReferenceNode({ 235 - typeName: symbolResponse.placeholder, 236 - }) 237 - : tsc.typeNode('undefined'), 238 - extends: symbolResponse 239 - ? tsc.typeReferenceNode({ 240 - typeName: symbolResponse.placeholder, 241 - }) 242 - : undefined, 243 - name: nuxtTypeDefault, 244 - }, 245 - ] 246 - : [ 247 - { 248 - default: 249 - ('throwOnError' in client.config 250 - ? client.config.throwOnError 251 - : false) ?? false, 252 - extends: 'boolean', 253 - name: 'ThrowOnError', 254 - }, 255 - ], 256 - }); 257 - 258 - if (!currentClass.nodes.length) { 259 - currentClass.nodes.push(functionNode); 260 - } else { 261 - currentClass.nodes.push( 262 - // @ts-expect-error 263 - tsc.identifier({ text: '\n' }), 264 - functionNode, 265 - ); 266 - } 2 + import { handlerV1 } from './v1/plugin'; 267 3 268 - currentClass.methods.add(entry.methodName); 269 - 270 - sdkClasses.set(symbolCurrentClass.id, currentClass); 271 - }); 272 - } 273 - }, 274 - { 275 - order: 'declarations', 276 - }, 277 - ); 278 - 279 - const symbolHeyApiClient = plugin.registerSymbol({ 280 - exported: false, 281 - name: '_HeyApiClient', 282 - }); 283 - 284 - const generateClass = (currentClass: SdkClassEntry) => { 285 - if (generatedClasses.has(currentClass.id)) { 286 - return; 287 - } 288 - 289 - if (currentClass.classes.size) { 290 - for (const childClassName of currentClass.classes) { 291 - const childClass = sdkClasses.get(childClassName)!; 292 - generateClass(childClass); 293 - 294 - currentClass.nodes.push( 295 - tsc.propertyDeclaration({ 296 - initializer: plugin.config.instance 297 - ? tsc.newExpression({ 298 - argumentsArray: plugin.config.instance 299 - ? [ 300 - tsc.objectExpression({ 301 - multiLine: false, 302 - obj: [ 303 - { 304 - key: 'client', 305 - value: tsc.propertyAccessExpression({ 306 - expression: tsc.this(), 307 - name: '_client', 308 - }), 309 - }, 310 - ], 311 - }), 312 - ] 313 - : [], 314 - expression: tsc.identifier({ 315 - text: plugin.referenceSymbol(childClass.id).placeholder, 316 - }), 317 - }) 318 - : tsc.identifier({ 319 - text: plugin.referenceSymbol(childClass.id).placeholder, 320 - }), 321 - modifier: plugin.config.instance ? undefined : 'static', 322 - name: stringCase({ 323 - case: 'camelCase', 324 - value: childClass.className, 325 - }), 326 - }), 327 - ); 328 - } 329 - } 330 - 331 - const symbol = plugin.registerSymbol({ 332 - exported: true, 333 - name: currentClass.className, 334 - selector: plugin.api.selector('class', currentClass.className), 335 - }); 336 - const node = tsc.classDeclaration({ 337 - decorator: 338 - currentClass.root && isAngularClient 339 - ? { 340 - args: [ 341 - { 342 - providedIn: 'root', 343 - }, 344 - ], 345 - name: plugin.referenceSymbol(plugin.api.selector('Injectable')) 346 - .placeholder, 347 - } 348 - : undefined, 349 - exportClass: symbol.exported, 350 - extendedClasses: plugin.config.instance 351 - ? [symbolHeyApiClient.placeholder] 352 - : undefined, 353 - name: symbol.placeholder, 354 - nodes: currentClass.nodes, 355 - }); 356 - plugin.setSymbolValue(symbol, node); 357 - generatedClasses.add(symbol.id); 358 - }; 359 - 360 - if (clientClassNodes.length) { 361 - const node = tsc.classDeclaration({ 362 - exportClass: symbolHeyApiClient.exported, 363 - name: symbolHeyApiClient.placeholder, 364 - nodes: clientClassNodes, 365 - }); 366 - plugin.setSymbolValue(symbolHeyApiClient, node); 367 - } 368 - 369 - for (const sdkClass of sdkClasses.values()) { 370 - generateClass(sdkClass); 371 - } 372 - }; 373 - 374 - const generateFlatSdk = ({ 375 - plugin, 376 - }: { 377 - plugin: HeyApiSdkPlugin['Instance']; 378 - }) => { 379 - const client = getClientPlugin(plugin.context.config); 380 - const isNuxtClient = client.name === '@hey-api/client-nuxt'; 381 - 382 - plugin.forEach( 383 - 'operation', 384 - ({ operation }) => { 385 - const isRequiredOptions = isOperationOptionsRequired({ 386 - context: plugin.context, 387 - operation, 388 - }); 389 - const pluginTypeScript = plugin.getPluginOrThrow('@hey-api/typescript'); 390 - const symbolResponse = isNuxtClient 391 - ? plugin.getSymbol( 392 - pluginTypeScript.api.selector('response', operation.id), 393 - ) 394 - : undefined; 395 - const opParameters = operationParameters({ 396 - isRequiredOptions, 397 - operation, 398 - plugin, 399 - }); 400 - const statements = operationStatements({ 401 - isRequiredOptions, 402 - opParameters, 403 - operation, 404 - plugin, 405 - }); 406 - const symbol = plugin.registerSymbol({ 407 - name: serviceFunctionIdentifier({ 408 - config: plugin.context.config, 409 - handleIllegal: true, 410 - id: operation.id, 411 - operation, 412 - }), 413 - selector: plugin.api.selector('function', operation.id), 414 - }); 415 - const node = tsc.constVariable({ 416 - comment: plugin.api.createOperationComment({ operation }), 417 - exportConst: true, 418 - expression: tsc.arrowFunction({ 419 - parameters: opParameters.parameters, 420 - returnType: undefined, 421 - statements, 422 - types: isNuxtClient 423 - ? [ 424 - { 425 - default: tsc.ots.string('$fetch'), 426 - extends: tsc.typeNode( 427 - plugin.referenceSymbol(plugin.api.selector('Composable')) 428 - .placeholder, 429 - ), 430 - name: nuxtTypeComposable, 431 - }, 432 - { 433 - default: symbolResponse 434 - ? tsc.typeReferenceNode({ 435 - typeName: symbolResponse.placeholder, 436 - }) 437 - : tsc.typeNode('undefined'), 438 - extends: symbolResponse 439 - ? tsc.typeReferenceNode({ 440 - typeName: symbolResponse.placeholder, 441 - }) 442 - : undefined, 443 - name: nuxtTypeDefault, 444 - }, 445 - ] 446 - : [ 447 - { 448 - default: 449 - ('throwOnError' in client.config 450 - ? client.config.throwOnError 451 - : false) ?? false, 452 - extends: 'boolean', 453 - name: 'ThrowOnError', 454 - }, 455 - ], 456 - }), 457 - name: symbol.placeholder, 458 - }); 459 - plugin.setSymbolValue(symbol, node); 460 - }, 461 - { 462 - order: 'declarations', 463 - }, 464 - ); 465 - }; 466 - 467 - export const handler: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { 468 - const clientModule = clientFolderAbsolutePath(plugin.context.config); 469 - plugin.registerSymbol({ 470 - external: clientModule, 471 - name: 'formDataBodySerializer', 472 - selector: plugin.api.selector('formDataBodySerializer'), 473 - }); 474 - plugin.registerSymbol({ 475 - external: clientModule, 476 - name: 'urlSearchParamsBodySerializer', 477 - selector: plugin.api.selector('urlSearchParamsBodySerializer'), 478 - }); 479 - plugin.registerSymbol({ 480 - external: clientModule, 481 - name: 'buildClientParams', 482 - selector: plugin.api.selector('buildClientParams'), 483 - }); 484 - 485 - const client = getClientPlugin(plugin.context.config); 486 - const isAngularClient = client.name === '@hey-api/client-angular'; 487 - const isNuxtClient = client.name === '@hey-api/client-nuxt'; 488 - if (isNuxtClient) { 489 - plugin.registerSymbol({ 490 - external: clientModule, 491 - meta: { 492 - kind: 'type', 493 - }, 494 - name: 'Composable', 495 - selector: plugin.api.selector('Composable'), 496 - }); 497 - } 498 - 499 - if (isAngularClient && plugin.config.asClass) { 500 - plugin.registerSymbol({ 501 - external: '@angular/core', 502 - name: 'Injectable', 503 - selector: plugin.api.selector('Injectable'), 504 - }); 505 - } 506 - 507 - createTypeOptions({ plugin }); 508 - 509 - if (plugin.config.asClass) { 510 - generateClassSdk({ plugin }); 511 - } else { 512 - generateFlatSdk({ plugin }); 513 - } 514 - }; 4 + export const handler: HeyApiSdkPlugin['Handler'] = (args) => handlerV1(args);
+378
packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts
··· 1 + import type ts from 'typescript'; 2 + 3 + import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; 4 + import { 5 + createOperationComment, 6 + isOperationOptionsRequired, 7 + } from '~/plugins/shared/utils/operation'; 8 + import { tsc } from '~/tsc'; 9 + import { stringCase } from '~/utils/stringCase'; 10 + 11 + import type { HeyApiSdkPlugin } from '../types'; 12 + import { nuxtTypeComposable, nuxtTypeDefault } from './constants'; 13 + import { 14 + operationClasses, 15 + operationParameters, 16 + operationStatements, 17 + } from './operation'; 18 + 19 + type SdkClassEntry = { 20 + /** 21 + * Name of the class. 22 + */ 23 + className: string; 24 + /** 25 + * Symbol IDs for child classes located inside this class. 26 + */ 27 + classes: Set<number>; 28 + /** 29 + * Symbol ID for the class. 30 + */ 31 + id: number; 32 + /** 33 + * Track unique added method nodes. 34 + */ 35 + methods: Set<string>; 36 + /** 37 + * List of class nodes containing methods. 38 + */ 39 + nodes: Array<ts.ClassElement>; 40 + /** 41 + * Is this a root class? 42 + */ 43 + root: boolean; 44 + }; 45 + 46 + const createClientClassNodes = ({ 47 + plugin, 48 + }: { 49 + plugin: HeyApiSdkPlugin['Instance']; 50 + }): ReadonlyArray<ts.ClassElement> => { 51 + const clientAssignmentStatement = tsc.expressionToStatement({ 52 + expression: tsc.binaryExpression({ 53 + left: tsc.propertyAccessExpression({ 54 + expression: tsc.this(), 55 + name: '_client', 56 + }), 57 + operator: '=', 58 + right: tsc.propertyAccessExpression({ 59 + expression: tsc.identifier({ text: 'args' }), 60 + name: 'client', 61 + }), 62 + }), 63 + }); 64 + 65 + const symbolClient = plugin.referenceSymbol(plugin.api.selector('Client')); 66 + const client = getClientPlugin(plugin.context.config); 67 + const symClient = 68 + client.api && 'selector' in client.api 69 + ? plugin.getSymbol( 70 + // @ts-expect-error 71 + client.api.selector('client'), 72 + ) 73 + : undefined; 74 + 75 + return [ 76 + tsc.propertyDeclaration({ 77 + initializer: symClient 78 + ? tsc.identifier({ text: symClient.placeholder }) 79 + : undefined, 80 + modifier: 'protected', 81 + name: '_client', 82 + type: tsc.typeReferenceNode({ typeName: symbolClient.placeholder }), 83 + }), 84 + // @ts-expect-error 85 + tsc.identifier({ text: '\n' }), 86 + tsc.constructorDeclaration({ 87 + multiLine: true, 88 + parameters: [ 89 + { 90 + isRequired: !plugin.config.client, 91 + name: 'args', 92 + type: tsc.typeInterfaceNode({ 93 + properties: [ 94 + { 95 + isRequired: !plugin.config.client, 96 + name: 'client', 97 + type: symbolClient.placeholder, 98 + }, 99 + ], 100 + useLegacyResolution: false, 101 + }), 102 + }, 103 + ], 104 + statements: [ 105 + !plugin.config.client 106 + ? clientAssignmentStatement 107 + : tsc.ifStatement({ 108 + expression: tsc.propertyAccessExpression({ 109 + expression: tsc.identifier({ text: 'args' }), 110 + isOptional: true, 111 + name: 'client', 112 + }), 113 + thenStatement: tsc.block({ 114 + statements: [clientAssignmentStatement], 115 + }), 116 + }), 117 + ], 118 + }), 119 + ]; 120 + }; 121 + 122 + export const generateClassSdk = ({ 123 + plugin, 124 + }: { 125 + plugin: HeyApiSdkPlugin['Instance']; 126 + }): void => { 127 + const client = getClientPlugin(plugin.context.config); 128 + const isAngularClient = client.name === '@hey-api/client-angular'; 129 + const isNuxtClient = client.name === '@hey-api/client-nuxt'; 130 + const sdkClasses = new Map<number, SdkClassEntry>(); 131 + /** 132 + * Track unique added classes. 133 + */ 134 + const generatedClasses = new Set<number>(); 135 + 136 + const clientClassNodes = plugin.config.instance 137 + ? createClientClassNodes({ plugin }) 138 + : []; 139 + 140 + plugin.forEach( 141 + 'operation', 142 + ({ operation }) => { 143 + const isRequiredOptions = isOperationOptionsRequired({ 144 + context: plugin.context, 145 + operation, 146 + }); 147 + const pluginTypeScript = plugin.getPluginOrThrow('@hey-api/typescript'); 148 + const symbolResponse = isNuxtClient 149 + ? plugin.getSymbol( 150 + pluginTypeScript.api.selector('response', operation.id), 151 + ) 152 + : undefined; 153 + 154 + const classes = operationClasses({ 155 + context: plugin.context, 156 + operation, 157 + plugin, 158 + }); 159 + 160 + for (const entry of classes.values()) { 161 + entry.path.forEach((currentClassName, index) => { 162 + const symbolCurrentClass = plugin.referenceSymbol( 163 + plugin.api.selector('class', currentClassName), 164 + ); 165 + if (!sdkClasses.has(symbolCurrentClass.id)) { 166 + sdkClasses.set(symbolCurrentClass.id, { 167 + className: currentClassName, 168 + classes: new Set(), 169 + id: symbolCurrentClass.id, 170 + methods: new Set(), 171 + nodes: [], 172 + root: !index, 173 + }); 174 + } 175 + 176 + const parentClassName = entry.path[index - 1]; 177 + if (parentClassName) { 178 + const symbolParentClass = plugin.referenceSymbol( 179 + plugin.api.selector('class', parentClassName), 180 + ); 181 + if ( 182 + symbolParentClass.placeholder !== symbolCurrentClass.placeholder 183 + ) { 184 + const parentClass = sdkClasses.get(symbolParentClass.id)!; 185 + parentClass.classes.add(symbolCurrentClass.id); 186 + sdkClasses.set(symbolParentClass.id, parentClass); 187 + } 188 + } 189 + 190 + const isLast = entry.path.length === index + 1; 191 + // add methods only to the last class 192 + if (!isLast) { 193 + return; 194 + } 195 + 196 + const currentClass = sdkClasses.get(symbolCurrentClass.id)!; 197 + 198 + // avoid duplicate methods 199 + if (currentClass.methods.has(entry.methodName)) { 200 + return; 201 + } 202 + 203 + const opParameters = operationParameters({ 204 + isRequiredOptions, 205 + operation, 206 + plugin, 207 + }); 208 + const statements = operationStatements({ 209 + isRequiredOptions, 210 + opParameters, 211 + operation, 212 + plugin, 213 + }); 214 + const functionNode = tsc.methodDeclaration({ 215 + accessLevel: 'public', 216 + comment: createOperationComment({ operation }), 217 + isStatic: isAngularClient ? false : !plugin.config.instance, 218 + name: entry.methodName, 219 + parameters: opParameters.parameters, 220 + returnType: undefined, 221 + statements, 222 + types: isNuxtClient 223 + ? [ 224 + { 225 + default: tsc.ots.string('$fetch'), 226 + extends: tsc.typeNode( 227 + plugin.referenceSymbol(plugin.api.selector('Composable')) 228 + .placeholder, 229 + ), 230 + name: nuxtTypeComposable, 231 + }, 232 + { 233 + default: symbolResponse 234 + ? tsc.typeReferenceNode({ 235 + typeName: symbolResponse.placeholder, 236 + }) 237 + : tsc.typeNode('undefined'), 238 + extends: symbolResponse 239 + ? tsc.typeReferenceNode({ 240 + typeName: symbolResponse.placeholder, 241 + }) 242 + : undefined, 243 + name: nuxtTypeDefault, 244 + }, 245 + ] 246 + : [ 247 + { 248 + default: 249 + ('throwOnError' in client.config 250 + ? client.config.throwOnError 251 + : false) ?? false, 252 + extends: 'boolean', 253 + name: 'ThrowOnError', 254 + }, 255 + ], 256 + }); 257 + 258 + if (!currentClass.nodes.length) { 259 + currentClass.nodes.push(functionNode); 260 + } else { 261 + currentClass.nodes.push( 262 + // @ts-expect-error 263 + tsc.identifier({ text: '\n' }), 264 + functionNode, 265 + ); 266 + } 267 + 268 + currentClass.methods.add(entry.methodName); 269 + 270 + sdkClasses.set(symbolCurrentClass.id, currentClass); 271 + }); 272 + } 273 + }, 274 + { 275 + order: 'declarations', 276 + }, 277 + ); 278 + 279 + const symbolHeyApiClient = plugin.registerSymbol({ 280 + exported: false, 281 + meta: { 282 + path: [], 283 + }, 284 + name: '_HeyApiClient', 285 + }); 286 + 287 + const generateClass = (currentClass: SdkClassEntry) => { 288 + if (generatedClasses.has(currentClass.id)) { 289 + return; 290 + } 291 + 292 + if (currentClass.classes.size) { 293 + for (const childClassName of currentClass.classes) { 294 + const childClass = sdkClasses.get(childClassName)!; 295 + generateClass(childClass); 296 + 297 + currentClass.nodes.push( 298 + tsc.propertyDeclaration({ 299 + initializer: plugin.config.instance 300 + ? tsc.newExpression({ 301 + argumentsArray: plugin.config.instance 302 + ? [ 303 + tsc.objectExpression({ 304 + multiLine: false, 305 + obj: [ 306 + { 307 + key: 'client', 308 + value: tsc.propertyAccessExpression({ 309 + expression: tsc.this(), 310 + name: '_client', 311 + }), 312 + }, 313 + ], 314 + }), 315 + ] 316 + : [], 317 + expression: tsc.identifier({ 318 + text: plugin.referenceSymbol(childClass.id).placeholder, 319 + }), 320 + }) 321 + : tsc.identifier({ 322 + text: plugin.referenceSymbol(childClass.id).placeholder, 323 + }), 324 + modifier: plugin.config.instance ? undefined : 'static', 325 + name: stringCase({ 326 + case: 'camelCase', 327 + value: childClass.className, 328 + }), 329 + }), 330 + ); 331 + } 332 + } 333 + 334 + const symbol = plugin.registerSymbol({ 335 + exported: true, 336 + meta: { 337 + path: [], 338 + }, 339 + name: currentClass.className, 340 + selector: plugin.api.selector('class', currentClass.className), 341 + }); 342 + const node = tsc.classDeclaration({ 343 + decorator: 344 + currentClass.root && isAngularClient 345 + ? { 346 + args: [ 347 + { 348 + providedIn: 'root', 349 + }, 350 + ], 351 + name: plugin.referenceSymbol(plugin.api.selector('Injectable')) 352 + .placeholder, 353 + } 354 + : undefined, 355 + exportClass: symbol.exported, 356 + extendedClasses: plugin.config.instance 357 + ? [symbolHeyApiClient.placeholder] 358 + : undefined, 359 + name: symbol.placeholder, 360 + nodes: currentClass.nodes, 361 + }); 362 + plugin.setSymbolValue(symbol, node); 363 + generatedClasses.add(symbol.id); 364 + }; 365 + 366 + if (clientClassNodes.length) { 367 + const node = tsc.classDeclaration({ 368 + exportClass: symbolHeyApiClient.exported, 369 + name: symbolHeyApiClient.placeholder, 370 + nodes: clientClassNodes, 371 + }); 372 + plugin.setSymbolValue(symbolHeyApiClient, node); 373 + } 374 + 375 + for (const sdkClass of sdkClasses.values()) { 376 + generateClass(sdkClass); 377 + } 378 + };
+108
packages/openapi-ts/src/plugins/@hey-api/sdk/shared/functions.ts
··· 1 + import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; 2 + import { 3 + createOperationComment, 4 + isOperationOptionsRequired, 5 + } from '~/plugins/shared/utils/operation'; 6 + import { tsc } from '~/tsc'; 7 + 8 + import { serviceFunctionIdentifier } from '../plugin-legacy'; 9 + import type { HeyApiSdkPlugin } from '../types'; 10 + import { nuxtTypeComposable, nuxtTypeDefault } from './constants'; 11 + import { operationParameters, operationStatements } from './operation'; 12 + 13 + export const generateFlatSdk = ({ 14 + plugin, 15 + }: { 16 + plugin: HeyApiSdkPlugin['Instance']; 17 + }): void => { 18 + const client = getClientPlugin(plugin.context.config); 19 + const isNuxtClient = client.name === '@hey-api/client-nuxt'; 20 + 21 + plugin.forEach( 22 + 'operation', 23 + (event) => { 24 + const { operation } = event; 25 + const isRequiredOptions = isOperationOptionsRequired({ 26 + context: plugin.context, 27 + operation, 28 + }); 29 + const pluginTypeScript = plugin.getPluginOrThrow('@hey-api/typescript'); 30 + const symbolResponse = isNuxtClient 31 + ? plugin.getSymbol( 32 + pluginTypeScript.api.selector('response', operation.id), 33 + ) 34 + : undefined; 35 + const opParameters = operationParameters({ 36 + isRequiredOptions, 37 + operation, 38 + plugin, 39 + }); 40 + const statements = operationStatements({ 41 + isRequiredOptions, 42 + opParameters, 43 + operation, 44 + plugin, 45 + }); 46 + const symbol = plugin.registerSymbol({ 47 + meta: { 48 + path: event._path, 49 + }, 50 + name: serviceFunctionIdentifier({ 51 + config: plugin.context.config, 52 + handleIllegal: true, 53 + id: operation.id, 54 + operation, 55 + }), 56 + selector: plugin.api.selector('function', operation.id), 57 + }); 58 + const node = tsc.constVariable({ 59 + comment: createOperationComment({ operation }), 60 + exportConst: true, 61 + expression: tsc.arrowFunction({ 62 + parameters: opParameters.parameters, 63 + returnType: undefined, 64 + statements, 65 + types: isNuxtClient 66 + ? [ 67 + { 68 + default: tsc.ots.string('$fetch'), 69 + extends: tsc.typeNode( 70 + plugin.referenceSymbol(plugin.api.selector('Composable')) 71 + .placeholder, 72 + ), 73 + name: nuxtTypeComposable, 74 + }, 75 + { 76 + default: symbolResponse 77 + ? tsc.typeReferenceNode({ 78 + typeName: symbolResponse.placeholder, 79 + }) 80 + : tsc.typeNode('undefined'), 81 + extends: symbolResponse 82 + ? tsc.typeReferenceNode({ 83 + typeName: symbolResponse.placeholder, 84 + }) 85 + : undefined, 86 + name: nuxtTypeDefault, 87 + }, 88 + ] 89 + : [ 90 + { 91 + default: 92 + ('throwOnError' in client.config 93 + ? client.config.throwOnError 94 + : false) ?? false, 95 + extends: 'boolean', 96 + name: 'ThrowOnError', 97 + }, 98 + ], 99 + }), 100 + name: symbol.placeholder, 101 + }); 102 + plugin.setSymbolValue(symbol, node); 103 + }, 104 + { 105 + order: 'declarations', 106 + }, 107 + ); 108 + };
packages/openapi-ts/src/plugins/@hey-api/sdk/signature.ts packages/openapi-ts/src/plugins/@hey-api/sdk/shared/signature.ts
+5 -1
packages/openapi-ts/src/plugins/@hey-api/sdk/typeOptions.ts packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts
··· 2 2 import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; 3 3 import { tsc } from '~/tsc'; 4 4 5 + import type { HeyApiSdkPlugin } from '../types'; 5 6 import { nuxtTypeDefault, nuxtTypeResponse } from './constants'; 6 - import type { HeyApiSdkPlugin } from './types'; 7 7 8 8 export const createTypeOptions = ({ 9 9 plugin, ··· 18 18 external: clientModule, 19 19 meta: { 20 20 kind: 'type', 21 + path: [], 21 22 }, 22 23 name: 'TDataShape', 23 24 }); ··· 25 26 external: clientModule, 26 27 meta: { 27 28 kind: 'type', 29 + path: [], 28 30 }, 29 31 name: 'Client', 30 32 selector: plugin.api.selector('Client'), ··· 33 35 external: clientModule, 34 36 meta: { 35 37 kind: 'type', 38 + path: [], 36 39 }, 37 40 name: 'Options', 38 41 }); ··· 40 43 exported: true, 41 44 meta: { 42 45 kind: 'type', 46 + path: [], 43 47 }, 44 48 name: 'Options', 45 49 selector: plugin.api.selector('Options'),
+56
packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts
··· 1 + import { clientFolderAbsolutePath } from '~/generate/client'; 2 + import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; 3 + 4 + import { generateClassSdk } from '../shared/class'; 5 + import { generateFlatSdk } from '../shared/functions'; 6 + import { createTypeOptions } from '../shared/typeOptions'; 7 + import type { HeyApiSdkPlugin } from '../types'; 8 + 9 + export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { 10 + const clientModule = clientFolderAbsolutePath(plugin.context.config); 11 + plugin.registerSymbol({ 12 + external: clientModule, 13 + name: 'formDataBodySerializer', 14 + selector: plugin.api.selector('formDataBodySerializer'), 15 + }); 16 + plugin.registerSymbol({ 17 + external: clientModule, 18 + name: 'urlSearchParamsBodySerializer', 19 + selector: plugin.api.selector('urlSearchParamsBodySerializer'), 20 + }); 21 + plugin.registerSymbol({ 22 + external: clientModule, 23 + name: 'buildClientParams', 24 + selector: plugin.api.selector('buildClientParams'), 25 + }); 26 + 27 + const client = getClientPlugin(plugin.context.config); 28 + const isAngularClient = client.name === '@hey-api/client-angular'; 29 + const isNuxtClient = client.name === '@hey-api/client-nuxt'; 30 + if (isNuxtClient) { 31 + plugin.registerSymbol({ 32 + external: clientModule, 33 + meta: { 34 + kind: 'type', 35 + }, 36 + name: 'Composable', 37 + selector: plugin.api.selector('Composable'), 38 + }); 39 + } 40 + 41 + if (isAngularClient && plugin.config.asClass) { 42 + plugin.registerSymbol({ 43 + external: '@angular/core', 44 + name: 'Injectable', 45 + selector: plugin.api.selector('Injectable'), 46 + }); 47 + } 48 + 49 + createTypeOptions({ plugin }); 50 + 51 + if (plugin.config.asClass) { 52 + generateClassSdk({ plugin }); 53 + } else { 54 + generateFlatSdk({ plugin }); 55 + } 56 + };
+1 -1
packages/openapi-ts/src/plugins/@hey-api/sdk/validator.ts packages/openapi-ts/src/plugins/@hey-api/sdk/shared/validator.ts
··· 2 2 3 3 import type { IR } from '~/ir/types'; 4 4 5 - import type { HeyApiSdkPlugin } from './types'; 5 + import type { HeyApiSdkPlugin } from '../types'; 6 6 7 7 interface ValidatorProps { 8 8 operation: IR.OperationObject;
-1
packages/openapi-ts/src/plugins/@hey-api/typescript/__tests__/plugin.test.ts
··· 100 100 }, 101 101 '@hey-api/sdk': { 102 102 api: { 103 - createOperationComment: () => undefined, 104 103 selector: () => [], 105 104 }, 106 105 config: {
+2 -3
packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts
··· 2 2 3 3 import type { IR } from '~/ir/types'; 4 4 import { buildName } from '~/openApi/shared/utils/name'; 5 + import { createOperationComment } from '~/plugins/shared/utils/operation'; 5 6 import { tsc } from '~/tsc'; 6 7 7 8 import { handleMeta } from './meta'; ··· 108 109 }); 109 110 } 110 111 111 - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); 112 - 113 112 const symbolMutationOptions = plugin.registerSymbol({ 114 113 exported: true, 115 114 name: buildName({ ··· 119 118 }); 120 119 const statement = tsc.constVariable({ 121 120 comment: plugin.config.comments 122 - ? sdkPlugin.api.createOperationComment({ operation }) 121 + ? createOperationComment({ operation }) 123 122 : undefined, 124 123 exportConst: symbolMutationOptions.exported, 125 124 expression: tsc.arrowFunction({
+1 -1
packages/openapi-ts/src/plugins/@pinia/colada/plugin.ts
··· 1 - import { operationClasses } from '~/plugins/@hey-api/sdk/operation'; 1 + import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; 2 2 import { stringCase } from '~/utils/stringCase'; 3 3 4 4 import { createMutationOptions } from './mutationOptions';
+2 -3
packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts
··· 3 3 import type { IR } from '~/ir/types'; 4 4 import { buildName } from '~/openApi/shared/utils/name'; 5 5 import { 6 + createOperationComment, 6 7 hasOperationSse, 7 8 isOperationOptionsRequired, 8 9 } from '~/plugins/shared/utils/operation'; ··· 148 149 }); 149 150 } 150 151 151 - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); 152 - 153 152 const symbolQueryOptionsFn = plugin.registerSymbol({ 154 153 exported: true, 155 154 name: buildName({ ··· 165 164 }); 166 165 const statement = tsc.constVariable({ 167 166 comment: plugin.config.comments 168 - ? sdkPlugin.api.createOperationComment({ operation }) 167 + ? createOperationComment({ operation }) 169 168 : undefined, 170 169 exportConst: symbolQueryOptionsFn.exported, 171 170 expression: tsc.callExpression({
+1 -1
packages/openapi-ts/src/plugins/@pinia/colada/useType.ts
··· 1 1 import type { IR } from '~/ir/types'; 2 2 import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; 3 - import { operationOptionsType } from '~/plugins/@hey-api/sdk/operation'; 3 + import { operationOptionsType } from '~/plugins/@hey-api/sdk/shared/operation'; 4 4 5 5 import type { PiniaColadaPlugin } from './types'; 6 6
+5 -4
packages/openapi-ts/src/plugins/@tanstack/query-core/infiniteQueryOptions.ts
··· 3 3 import { operationPagination } from '~/ir/operation'; 4 4 import type { IR } from '~/ir/types'; 5 5 import { buildName } from '~/openApi/shared/utils/name'; 6 - import { isOperationOptionsRequired } from '~/plugins/shared/utils/operation'; 6 + import { 7 + createOperationComment, 8 + isOperationOptionsRequired, 9 + } from '~/plugins/shared/utils/operation'; 7 10 import { tsc } from '~/tsc'; 8 11 import { tsNodeToString } from '~/tsc/utils'; 9 12 ··· 444 447 }); 445 448 } 446 449 447 - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); 448 - 449 450 const symbolInfiniteQueryOptionsFn = plugin.registerSymbol({ 450 451 exported: true, 451 452 name: buildName({ ··· 455 456 }); 456 457 const statement = tsc.constVariable({ 457 458 comment: plugin.config.comments 458 - ? sdkPlugin.api.createOperationComment({ operation }) 459 + ? createOperationComment({ operation }) 459 460 : undefined, 460 461 exportConst: symbolInfiniteQueryOptionsFn.exported, 461 462 expression: tsc.arrowFunction({
+2 -3
packages/openapi-ts/src/plugins/@tanstack/query-core/mutationOptions.ts
··· 2 2 3 3 import type { IR } from '~/ir/types'; 4 4 import { buildName } from '~/openApi/shared/utils/name'; 5 + import { createOperationComment } from '~/plugins/shared/utils/operation'; 5 6 import { tsc } from '~/tsc'; 6 7 7 8 import { handleMeta } from './meta'; ··· 98 99 }); 99 100 } 100 101 101 - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); 102 - 103 102 const mutationOptionsFn = 'mutationOptions'; 104 103 const expression = tsc.arrowFunction({ 105 104 parameters: [ ··· 132 131 }); 133 132 const statement = tsc.constVariable({ 134 133 comment: plugin.config.comments 135 - ? sdkPlugin.api.createOperationComment({ operation }) 134 + ? createOperationComment({ operation }) 136 135 : undefined, 137 136 exportConst: symbolMutationOptions.exported, 138 137 expression,
+1 -1
packages/openapi-ts/src/plugins/@tanstack/query-core/plugin.ts
··· 1 - import { operationClasses } from '~/plugins/@hey-api/sdk/operation'; 1 + import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; 2 2 import { stringCase } from '~/utils/stringCase'; 3 3 4 4 import { createInfiniteQueryOptions } from './infiniteQueryOptions';
+2 -3
packages/openapi-ts/src/plugins/@tanstack/query-core/queryOptions.ts
··· 3 3 import type { IR } from '~/ir/types'; 4 4 import { buildName } from '~/openApi/shared/utils/name'; 5 5 import { 6 + createOperationComment, 6 7 hasOperationSse, 7 8 isOperationOptionsRequired, 8 9 } from '~/plugins/shared/utils/operation'; ··· 153 154 }); 154 155 } 155 156 156 - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); 157 - 158 157 const symbolQueryOptionsFn = plugin.registerSymbol({ 159 158 exported: plugin.config.queryOptions.exported, 160 159 name: buildName({ ··· 165 164 }); 166 165 const statement = tsc.constVariable({ 167 166 comment: plugin.config.comments 168 - ? sdkPlugin.api.createOperationComment({ operation }) 167 + ? createOperationComment({ operation }) 169 168 : undefined, 170 169 exportConst: symbolQueryOptionsFn.exported, 171 170 expression: tsc.arrowFunction({
+2 -3
packages/openapi-ts/src/plugins/@tanstack/query-core/useQuery.ts
··· 1 1 import type { IR } from '~/ir/types'; 2 2 import { buildName } from '~/openApi/shared/utils/name'; 3 3 import { 4 + createOperationComment, 4 5 hasOperationSse, 5 6 isOperationOptionsRequired, 6 7 } from '~/plugins/shared/utils/operation'; ··· 25 26 if (!('useQuery' in plugin.config)) { 26 27 return; 27 28 } 28 - 29 - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); 30 29 31 30 const symbolUseQueryFn = plugin.registerSymbol({ 32 31 exported: true, ··· 51 50 ); 52 51 const statement = tsc.constVariable({ 53 52 comment: plugin.config.comments 54 - ? sdkPlugin.api.createOperationComment({ operation }) 53 + ? createOperationComment({ operation }) 55 54 : undefined, 56 55 exportConst: symbolUseQueryFn.exported, 57 56 expression: tsc.arrowFunction({
+1 -1
packages/openapi-ts/src/plugins/@tanstack/query-core/useType.ts
··· 1 1 import type { IR } from '~/ir/types'; 2 2 import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; 3 - import { operationOptionsType } from '~/plugins/@hey-api/sdk/operation'; 3 + import { operationOptionsType } from '~/plugins/@hey-api/sdk/shared/operation'; 4 4 5 5 import type { PluginInstance } from './types'; 6 6
+36
packages/openapi-ts/src/plugins/shared/utils/operation.ts
··· 1 1 import { hasOperationDataRequired } from '~/ir/operation'; 2 2 import type { IR } from '~/ir/types'; 3 3 import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; 4 + import type { Comments } from '~/tsc'; 5 + import { escapeComment } from '~/utils/escape'; 6 + 7 + export const createOperationComment = ({ 8 + operation, 9 + }: { 10 + operation: IR.OperationObject; 11 + }): Comments | undefined => { 12 + const comments: Array<string> = []; 13 + 14 + if (operation.summary) { 15 + comments.push(escapeComment(operation.summary)); 16 + } 17 + 18 + if (operation.description) { 19 + if (comments.length) { 20 + comments.push(''); // Add an empty line between summary and description 21 + } 22 + 23 + comments.push(escapeComment(operation.description)); 24 + } 25 + 26 + if (operation.deprecated) { 27 + if (comments.length) { 28 + comments.push(''); // Add an empty line before deprecated 29 + } 30 + 31 + comments.push('@deprecated'); 32 + } 33 + 34 + if (!comments.length) { 35 + return; 36 + } 37 + 38 + return comments; 39 + }; 4 40 5 41 export const isOperationOptionsRequired = ({ 6 42 context,
-2
packages/openapi-ts/src/utils/__tests__/handlebars.test.ts
··· 93 93 }, 94 94 '@hey-api/sdk': { 95 95 api: { 96 - createOperationComment: () => undefined, 97 96 selector: () => [], 98 97 }, 99 98 config: { ··· 224 223 }, 225 224 '@hey-api/sdk': { 226 225 api: { 227 - createOperationComment: () => undefined, 228 226 selector: () => [], 229 227 }, 230 228 config: {
-5
packages/openapi-ts/src/utils/__tests__/parse.test.ts
··· 72 72 plugins: { 73 73 '@hey-api/sdk': { 74 74 api: { 75 - createOperationComment: () => undefined, 76 75 selector: () => [], 77 76 }, 78 77 config: { ··· 103 102 ...optionsCommon.plugins, 104 103 '@hey-api/sdk': { 105 104 api: { 106 - createOperationComment: () => undefined, 107 105 selector: () => [], 108 106 }, 109 107 config: { ··· 124 122 ...optionsCommon.plugins, 125 123 '@hey-api/sdk': { 126 124 api: { 127 - createOperationComment: () => undefined, 128 125 selector: () => [], 129 126 }, 130 127 config: { ··· 157 154 }, 158 155 '@hey-api/sdk': { 159 156 api: { 160 - createOperationComment: () => undefined, 161 157 selector: () => [], 162 158 }, 163 159 config: { ··· 190 186 }, 191 187 '@hey-api/sdk': { 192 188 api: { 193 - createOperationComment: () => undefined, 194 189 selector: () => [], 195 190 }, 196 191 config: {