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

feat(sdk): lazily initialize sub-resources to improve performance

Lubos f481f5cb a2c88a3d

+391 -210
+5
.changeset/major-cats-divide.md
··· 1 + --- 2 + '@hey-api/openapi-ts': patch 3 + --- 4 + 5 + **@hey-api/sdk**: lazily initialize sub-resources to improve performance
+2 -1
dev/openapi-ts.config.ts
··· 48 48 // 'invalid', 49 49 // 'object-property-names.yaml', 50 50 // 'openai.yaml', 51 - 'opencode.yaml', 51 + // 'opencode.yaml', 52 52 // 'pagination-ref.yaml', 53 53 // 'schema-const.yaml', 54 54 // 'sdk-instance.yaml', 55 55 // 'sdk-method-class-conflict.yaml', 56 56 // 'sdk-nested-classes.yaml', 57 + 'sdk-nested-conflict.yaml', 57 58 // 'string-with-format.yaml', 58 59 // 'transformers.json', 59 60 // 'transformers-recursive.json',
+12 -3
packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes-instance/sdk.gen.ts
··· 57 57 } 58 58 59 59 export class Providers extends HeyApiClient { 60 - domains = new Domains({ client: this.client }); 60 + private _domains?: Domains; 61 + get domains(): Domains { 62 + return this._domains ??= new Domains({ client: this.client }); 63 + } 61 64 } 62 65 63 66 export class Business extends HeyApiClient { ··· 65 68 return (options?.client ?? this.client).get<BusinessGetResponses, unknown, ThrowOnError>({ url: '/locations/businesses', ...options }); 66 69 } 67 70 68 - providers = new Providers({ client: this.client }); 71 + private _providers?: Providers; 72 + get providers(): Providers { 73 + return this._providers ??= new Providers({ client: this.client }); 74 + } 69 75 } 70 76 71 77 export class NestedSdkWithInstance extends HeyApiClient { ··· 87 93 return (options?.client ?? this.client).get<GetResponses, unknown, ThrowOnError>({ url: '/locations', ...options }); 88 94 } 89 95 90 - business = new Business({ client: this.client }); 96 + private _business?: Business; 97 + get business(): Business { 98 + return this._business ??= new Business({ client: this.client }); 99 + } 91 100 }
+8 -2
packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/instance/sdk.gen.ts
··· 65 65 return (options?.client ?? this.client).put<FooPutResponses, unknown, ThrowOnError>({ url: '/foo', ...options }); 66 66 } 67 67 68 - bar = new Bar({ client: this.client }); 68 + private _bar?: Bar; 69 + get bar(): Bar { 70 + return this._bar ??= new Bar({ client: this.client }); 71 + } 69 72 } 70 73 71 74 export class Sdk extends HeyApiClient { ··· 87 90 return (options?.client ?? this.client).get<GetFooBarResponses, unknown, ThrowOnError>({ url: '/foo/bar', ...options }); 88 91 } 89 92 90 - foo = new Foo({ client: this.client }); 93 + private _foo?: Foo; 94 + get foo(): Foo { 95 + return this._foo ??= new Foo({ client: this.client }); 96 + } 91 97 }
+12 -3
packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes-instance/sdk.gen.ts
··· 57 57 } 58 58 59 59 export class Providers extends HeyApiClient { 60 - domains = new Domains({ client: this.client }); 60 + private _domains?: Domains; 61 + get domains(): Domains { 62 + return this._domains ??= new Domains({ client: this.client }); 63 + } 61 64 } 62 65 63 66 export class Business extends HeyApiClient { ··· 65 68 return (options?.client ?? this.client).get<BusinessGetResponses, unknown, ThrowOnError>({ url: '/locations/businesses', ...options }); 66 69 } 67 70 68 - providers = new Providers({ client: this.client }); 71 + private _providers?: Providers; 72 + get providers(): Providers { 73 + return this._providers ??= new Providers({ client: this.client }); 74 + } 69 75 } 70 76 71 77 export class NestedSdkWithInstance extends HeyApiClient { ··· 87 93 return (options?.client ?? this.client).get<GetResponses, unknown, ThrowOnError>({ url: '/locations', ...options }); 88 94 } 89 95 90 - business = new Business({ client: this.client }); 96 + private _business?: Business; 97 + get business(): Business { 98 + return this._business ??= new Business({ client: this.client }); 99 + } 91 100 }
+8 -2
packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/instance/sdk.gen.ts
··· 65 65 return (options?.client ?? this.client).put<FooPutResponses, unknown, ThrowOnError>({ url: '/foo', ...options }); 66 66 } 67 67 68 - bar = new Bar({ client: this.client }); 68 + private _bar?: Bar; 69 + get bar(): Bar { 70 + return this._bar ??= new Bar({ client: this.client }); 71 + } 69 72 } 70 73 71 74 export class Sdk extends HeyApiClient { ··· 87 90 return (options?.client ?? this.client).get<GetFooBarResponses, unknown, ThrowOnError>({ url: '/foo/bar', ...options }); 88 91 } 89 92 90 - foo = new Foo({ client: this.client }); 93 + private _foo?: Foo; 94 + get foo(): Foo { 95 + return this._foo ??= new Foo({ client: this.client }); 96 + } 91 97 }
+12 -3
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/client-fetch/sdk-nested-classes-instance/sdk.gen.ts
··· 57 57 } 58 58 59 59 export class Providers extends HeyApiClient { 60 - domains = new Domains({ client: this.client }); 60 + private _domains?: Domains; 61 + get domains(): Domains { 62 + return this._domains ??= new Domains({ client: this.client }); 63 + } 61 64 } 62 65 63 66 export class Business extends HeyApiClient { ··· 65 68 return (options?.client ?? this.client).get<BusinessGetResponses, unknown, ThrowOnError>({ url: '/locations/businesses', ...options }); 66 69 } 67 70 68 - providers = new Providers({ client: this.client }); 71 + private _providers?: Providers; 72 + get providers(): Providers { 73 + return this._providers ??= new Providers({ client: this.client }); 74 + } 69 75 } 70 76 71 77 export class NestedSdkWithInstance extends HeyApiClient { ··· 87 93 return (options?.client ?? this.client).get<GetResponses, unknown, ThrowOnError>({ url: '/locations', ...options }); 88 94 } 89 95 90 - business = new Business({ client: this.client }); 96 + private _business?: Business; 97 + get business(): Business { 98 + return this._business ??= new Business({ client: this.client }); 99 + } 91 100 }
+8 -2
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/sdk/instance/sdk.gen.ts
··· 65 65 return (options?.client ?? this.client).put<FooPutResponses, unknown, ThrowOnError>({ url: '/foo', ...options }); 66 66 } 67 67 68 - bar = new Bar({ client: this.client }); 68 + private _bar?: Bar; 69 + get bar(): Bar { 70 + return this._bar ??= new Bar({ client: this.client }); 71 + } 69 72 } 70 73 71 74 export class Sdk extends HeyApiClient { ··· 87 90 return (options?.client ?? this.client).get<GetFooBarResponses, unknown, ThrowOnError>({ url: '/foo/bar', ...options }); 88 91 } 89 92 90 - foo = new Foo({ client: this.client }); 93 + private _foo?: Foo; 94 + get foo(): Foo { 95 + return this._foo ??= new Foo({ client: this.client }); 96 + } 91 97 }
+100 -25
packages/openapi-ts-tests/sdks/__snapshots__/method-class-conflict/instance/sdk.gen.ts
··· 259 259 return (options?.client ?? this.client).get<ApiVVersionApiVersionOdataTasksKeyResponses, unknown, ThrowOnError>({ url: '/api/v1/odata/Tasks({key})', ...options }); 260 260 } 261 261 262 - accountingCompanies2 = new AccountingCompanies({ client: this.client }); 262 + private _accountingCompanies2?: AccountingCompanies; 263 + get accountingCompanies2(): AccountingCompanies { 264 + return this._accountingCompanies2 ??= new AccountingCompanies({ client: this.client }); 265 + } 263 266 264 - accountingCompanyMemberships2 = new AccountingCompanyMemberships({ client: this.client }); 267 + private _accountingCompanyMemberships2?: AccountingCompanyMemberships; 268 + get accountingCompanyMemberships2(): AccountingCompanyMemberships { 269 + return this._accountingCompanyMemberships2 ??= new AccountingCompanyMemberships({ client: this.client }); 270 + } 265 271 266 - bankAccounts2 = new BankAccounts({ client: this.client }); 272 + private _bankAccounts2?: BankAccounts; 273 + get bankAccounts2(): BankAccounts { 274 + return this._bankAccounts2 ??= new BankAccounts({ client: this.client }); 275 + } 267 276 268 - businessAccountantAssignments2 = new BusinessAccountantAssignments({ client: this.client }); 277 + private _businessAccountantAssignments2?: BusinessAccountantAssignments; 278 + get businessAccountantAssignments2(): BusinessAccountantAssignments { 279 + return this._businessAccountantAssignments2 ??= new BusinessAccountantAssignments({ client: this.client }); 280 + } 269 281 270 - businessDocumentActivities2 = new BusinessDocumentActivities({ client: this.client }); 282 + private _businessDocumentActivities2?: BusinessDocumentActivities; 283 + get businessDocumentActivities2(): BusinessDocumentActivities { 284 + return this._businessDocumentActivities2 ??= new BusinessDocumentActivities({ client: this.client }); 285 + } 271 286 272 - businessDocuments2 = new BusinessDocuments({ client: this.client }); 287 + private _businessDocuments2?: BusinessDocuments; 288 + get businessDocuments2(): BusinessDocuments { 289 + return this._businessDocuments2 ??= new BusinessDocuments({ client: this.client }); 290 + } 273 291 274 - businessDocumentsSummaries2 = new BusinessDocumentsSummaries({ client: this.client }); 292 + private _businessDocumentsSummaries2?: BusinessDocumentsSummaries; 293 + get businessDocumentsSummaries2(): BusinessDocumentsSummaries { 294 + return this._businessDocumentsSummaries2 ??= new BusinessDocumentsSummaries({ client: this.client }); 295 + } 275 296 276 - businesses2 = new Businesses({ client: this.client }); 297 + private _businesses2?: Businesses; 298 + get businesses2(): Businesses { 299 + return this._businesses2 ??= new Businesses({ client: this.client }); 300 + } 277 301 278 - businessSummaries2 = new BusinessSummaries({ client: this.client }); 302 + private _businessSummaries2?: BusinessSummaries; 303 + get businessSummaries2(): BusinessSummaries { 304 + return this._businessSummaries2 ??= new BusinessSummaries({ client: this.client }); 305 + } 279 306 280 - counterparties2 = new Counterparties({ client: this.client }); 307 + private _counterparties2?: Counterparties; 308 + get counterparties2(): Counterparties { 309 + return this._counterparties2 ??= new Counterparties({ client: this.client }); 310 + } 281 311 282 - dataBoxCredentials2 = new DataBoxCredentials({ client: this.client }); 312 + private _dataBoxCredentials2?: DataBoxCredentials; 313 + get dataBoxCredentials2(): DataBoxCredentials { 314 + return this._dataBoxCredentials2 ??= new DataBoxCredentials({ client: this.client }); 315 + } 283 316 284 - documentTypes2 = new DocumentTypes({ client: this.client }); 317 + private _documentTypes2?: DocumentTypes; 318 + get documentTypes2(): DocumentTypes { 319 + return this._documentTypes2 ??= new DocumentTypes({ client: this.client }); 320 + } 285 321 286 - invitations2 = new Invitations({ client: this.client }); 322 + private _invitations2?: Invitations; 323 + get invitations2(): Invitations { 324 + return this._invitations2 ??= new Invitations({ client: this.client }); 325 + } 287 326 288 - invoices2 = new Invoices({ client: this.client }); 327 + private _invoices2?: Invoices; 328 + get invoices2(): Invoices { 329 + return this._invoices2 ??= new Invoices({ client: this.client }); 330 + } 289 331 290 - invoiceSettings2 = new InvoiceSettings({ client: this.client }); 332 + private _invoiceSettings2?: InvoiceSettings; 333 + get invoiceSettings2(): InvoiceSettings { 334 + return this._invoiceSettings2 ??= new InvoiceSettings({ client: this.client }); 335 + } 291 336 292 - licenses2 = new Licenses({ client: this.client }); 337 + private _licenses2?: Licenses; 338 + get licenses2(): Licenses { 339 + return this._licenses2 ??= new Licenses({ client: this.client }); 340 + } 293 341 294 - personalDocuments2 = new PersonalDocuments({ client: this.client }); 342 + private _personalDocuments2?: PersonalDocuments; 343 + get personalDocuments2(): PersonalDocuments { 344 + return this._personalDocuments2 ??= new PersonalDocuments({ client: this.client }); 345 + } 295 346 296 - recurringTasks2 = new RecurringTasks({ client: this.client }); 347 + private _recurringTasks2?: RecurringTasks; 348 + get recurringTasks2(): RecurringTasks { 349 + return this._recurringTasks2 ??= new RecurringTasks({ client: this.client }); 350 + } 297 351 298 - tasks2 = new Tasks({ client: this.client }); 352 + private _tasks2?: Tasks; 353 + get tasks2(): Tasks { 354 + return this._tasks2 ??= new Tasks({ client: this.client }); 355 + } 299 356 } 300 357 301 358 export class User extends HeyApiClient { ··· 305 362 } 306 363 307 364 export class VVersionApiVersion extends HeyApiClient { 308 - odata = new Odata({ client: this.client }); 365 + private _odata?: Odata; 366 + get odata(): Odata { 367 + return this._odata ??= new Odata({ client: this.client }); 368 + } 309 369 310 - user = new User({ client: this.client }); 370 + private _user?: User; 371 + get user(): User { 372 + return this._user ??= new User({ client: this.client }); 373 + } 311 374 } 312 375 313 376 export class Api extends HeyApiClient { 314 - vVersionApiVersion = new VVersionApiVersion({ client: this.client }); 377 + private _vVersionApiVersion?: VVersionApiVersion; 378 + get vVersionApiVersion(): VVersionApiVersion { 379 + return this._vVersionApiVersion ??= new VVersionApiVersion({ client: this.client }); 380 + } 315 381 } 316 382 317 383 export class MapIdentityApi extends HeyApiClient { 318 - api = new Api({ client: this.client }); 384 + private _api?: Api; 385 + get api(): Api { 386 + return this._api ??= new Api({ client: this.client }); 387 + } 319 388 } 320 389 321 390 export class Sdk extends HeyApiClient { ··· 994 1063 }); 995 1064 } 996 1065 997 - api = new Api({ client: this.client }); 1066 + private _api?: Api; 1067 + get api(): Api { 1068 + return this._api ??= new Api({ client: this.client }); 1069 + } 998 1070 999 - mapIdentityApi = new MapIdentityApi({ client: this.client }); 1071 + private _mapIdentityApi?: MapIdentityApi; 1072 + get mapIdentityApi(): MapIdentityApi { 1073 + return this._mapIdentityApi ??= new MapIdentityApi({ client: this.client }); 1074 + } 1000 1075 }
+70 -90
packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts
··· 236 236 symbolCurrentClass.meta!.resourceId!, 237 237 )!; 238 238 239 - // avoid duplicate methods 240 - if (currentClass.methods.has(entry.methodName)) { 241 - return; 242 - } 239 + const methodName = entry.methodName; 240 + if (currentClass.methods.has(methodName)) return; 241 + currentClass.methods.add(methodName); 243 242 244 243 const opParameters = operationParameters({ 245 244 isRequiredOptions, ··· 252 251 operation, 253 252 plugin, 254 253 }); 255 - const functionNode = $.method(entry.methodName, (m) => 254 + const functionNode = $.method(methodName, (m) => 256 255 m 257 256 .$if(createOperationComment(operation), (m, v) => m.doc(v)) 258 257 .public() ··· 295 294 currentClass.nodes.push($.newline(), functionNode); 296 295 } 297 296 298 - currentClass.methods.add(entry.methodName); 299 - 300 297 sdkClasses.set(symbolCurrentClass.meta!.resourceId!, currentClass); 301 298 }); 302 299 } ··· 306 303 }, 307 304 ); 308 305 309 - const heyApiClientIndex = plugin.config.instance 310 - ? plugin.node(null) 311 - : undefined; 312 - const symbolHeyApiClient = 313 - heyApiClientIndex !== undefined 306 + const clientIndex = plugin.config.instance ? plugin.node(null) : undefined; 307 + const symbolClient = 308 + clientIndex !== undefined 314 309 ? plugin.symbol('HeyApiClient', { 315 310 meta: { 316 311 category: 'utility', ··· 320 315 }, 321 316 }) 322 317 : undefined; 323 - const heyApiRegistryIndex = plugin.config.instance 324 - ? plugin.node(null) 325 - : undefined; 318 + const registryIndex = plugin.config.instance ? plugin.node(null) : undefined; 326 319 327 320 const generateClass = (currentClass: SdkClassEntry) => { 328 - if (generatedClasses.has(currentClass.className)) { 329 - return; 330 - } 321 + const resourceId = currentClass.className; 331 322 332 - const resourceId = currentClass.className; 323 + if (generatedClasses.has(resourceId)) return; 333 324 generatedClasses.add(resourceId); 334 325 335 - if (currentClass.classes.size) { 336 - for (const childClassName of currentClass.classes) { 337 - const childClass = sdkClasses.get(childClassName)!; 338 - generateClass(childClass); 326 + if (clientIndex !== undefined && symbolClient && !symbolClient.node) { 327 + const node = createClientClass({ plugin, symbol: symbolClient }); 328 + plugin.node(node, clientIndex); 329 + } 339 330 340 - const refChildClass = plugin.referenceSymbol({ 341 - category: 'utility', 342 - resource: 'class', 343 - resourceId: childClass.className, 344 - tool: 'sdk', 345 - }); 331 + for (const childClassName of currentClass.classes) { 332 + const childClass = sdkClasses.get(childClassName)!; 333 + generateClass(childClass); 346 334 347 - const originalMemberName = stringCase({ 348 - case: 'camelCase', 349 - value: refChildClass.meta!.resourceId!, 350 - }); 351 - // avoid collisions with existing method names 352 - let memberName = originalMemberName; 353 - if (currentClass.methods.has(memberName)) { 354 - let index = 2; 355 - let attempt = `${memberName}${index}`; 356 - while (currentClass.methods.has(attempt)) { 357 - attempt = `${memberName}${index++}`; 358 - } 359 - memberName = attempt; 335 + const refChildClass = plugin.referenceSymbol({ 336 + category: 'utility', 337 + resource: 'class', 338 + resourceId: childClass.className, 339 + tool: 'sdk', 340 + }); 341 + 342 + const originalMemberName = stringCase({ 343 + case: 'camelCase', 344 + value: refChildClass.meta!.resourceId!, 345 + }); 346 + // avoid collisions with existing method names 347 + let memberName = originalMemberName; 348 + if (currentClass.methods.has(memberName)) { 349 + let index = 2; 350 + let attempt = `${memberName}${index}`; 351 + while (currentClass.methods.has(attempt)) { 352 + attempt = `${memberName}${index++}`; 360 353 } 361 - currentClass.methods.add(memberName); 354 + memberName = attempt; 355 + } 356 + currentClass.methods.add(memberName); 362 357 358 + if (currentClass.nodes.length > 0) { 359 + currentClass.nodes.push($.newline()); 360 + } 361 + 362 + if (plugin.config.instance) { 363 + const privateName = plugin.symbol(`_${memberName}`); 364 + const privateNode = $.field(privateName, (f) => 365 + f.private().optional().type(refChildClass), 366 + ); 367 + currentClass.nodes.push(privateNode); 368 + const getterNode = $.getter(memberName, (g) => 369 + g.returns(refChildClass).do( 370 + $('this') 371 + .attr(privateName) 372 + .nullishAssign( 373 + $.new(refChildClass).args( 374 + $.object().prop('client', $('this').attr('client')), 375 + ), 376 + ) 377 + .return(), 378 + ), 379 + ); 380 + currentClass.nodes.push(getterNode); 381 + } else { 363 382 const subClassReferenceNode = plugin.isSymbolRegistered( 364 383 refChildClass.id, 365 384 ) 366 - ? $.field(memberName, (f) => 367 - f 368 - .static(!plugin.config.instance) 369 - .assign( 370 - plugin.config.instance 371 - ? $.new(refChildClass).args( 372 - $.object().prop('client', $('this').attr('client')), 373 - ) 374 - : $(refChildClass), 375 - ), 376 - ) 385 + ? $.field(memberName, (f) => f.static().assign($(refChildClass))) 377 386 : $.getter(memberName, (g) => 378 - g 379 - .$if(!plugin.config.instance, (g) => g.public().static()) 380 - .do( 381 - $.return( 382 - plugin.config.instance 383 - ? $.new(refChildClass).args( 384 - $.object().prop('client', $('this').attr('client')), 385 - ) 386 - : refChildClass, 387 - ), 388 - ), 387 + g.public().static().do($.return(refChildClass)), 389 388 ); 390 - 391 - if (!currentClass.nodes.length) { 392 - currentClass.nodes.push(subClassReferenceNode); 393 - } else { 394 - currentClass.nodes.push($.newline(), subClassReferenceNode); 395 - } 389 + currentClass.nodes.push(subClassReferenceNode); 396 390 } 397 391 } 398 392 399 - if ( 400 - heyApiClientIndex !== undefined && 401 - symbolHeyApiClient && 402 - !symbolHeyApiClient.node 403 - ) { 404 - const node = createClientClass({ 405 - plugin, 406 - symbol: symbolHeyApiClient, 407 - }); 408 - plugin.node(node, heyApiClientIndex); 409 - } 410 - 411 393 const symbol = plugin.symbol(resourceId, { 412 394 meta: { 413 395 category: 'utility', ··· 417 399 }, 418 400 }); 419 401 420 - if (currentClass.root && heyApiRegistryIndex !== undefined) { 421 - const symClient = plugin.getSymbol({ 422 - category: 'client', 423 - }); 402 + if (currentClass.root && registryIndex !== undefined) { 403 + const symClient = plugin.getSymbol({ category: 'client' }); 424 404 const isClientRequired = !plugin.config.client || !symClient; 425 405 const symbolClient = plugin.referenceSymbol({ 426 406 category: 'external', ··· 466 446 sdkSymbol: symbol, 467 447 symbol: symbolRegistry, 468 448 }); 469 - plugin.node(node, heyApiRegistryIndex); 449 + plugin.node(node, registryIndex); 470 450 const registryNode = $.field(registryName, (f) => 471 451 f 472 452 .public() ··· 479 459 480 460 const node = $.class(symbol) 481 461 .export() 482 - .extends(symbolHeyApiClient) 483 - .$if(currentClass.root && isAngularClient, (c) => 462 + .extends(symbolClient) 463 + .$if(isAngularClient && currentClass.root, (c) => 484 464 c.decorator( 485 465 plugin.referenceSymbol({ 486 466 category: 'external',
+11 -5
packages/openapi-ts/src/ts-dsl/decl/field.ts
··· 15 15 ReadonlyMixin, 16 16 StaticMixin, 17 17 } from '../mixins/modifiers'; 18 + import { OptionalMixin } from '../mixins/optional'; 18 19 import { ValueMixin } from '../mixins/value'; 20 + import { TokenTsDsl } from '../token'; 19 21 import type { TypeExprName } from '../type/expr'; 20 22 import { TypeExprTsDsl } from '../type/expr'; 21 23 ··· 24 26 25 27 const Mixed = DecoratorMixin( 26 28 DocMixin( 27 - PrivateMixin( 28 - ProtectedMixin( 29 - PublicMixin( 30 - ReadonlyMixin(StaticMixin(ValueMixin(TsDsl<ts.PropertyDeclaration>))), 29 + OptionalMixin( 30 + PrivateMixin( 31 + ProtectedMixin( 32 + PublicMixin( 33 + ReadonlyMixin( 34 + StaticMixin(ValueMixin(TsDsl<ts.PropertyDeclaration>)), 35 + ), 36 + ), 31 37 ), 32 38 ), 33 39 ), ··· 61 67 const node = ts.factory.createPropertyDeclaration( 62 68 [...this.$decorators(ctx), ...this.modifiers], 63 69 this.$node(ctx, this.name) as ts.PropertyName, 64 - undefined, 70 + this._optional ? this.$node(ctx, new TokenTsDsl().optional()) : undefined, 65 71 this.$type(ctx, this._type), 66 72 this.$value(ctx), 67 73 );
+10 -14
packages/openapi-ts/src/ts-dsl/decl/func.ts
··· 7 7 import { isSymbol, ref } from '@hey-api/codegen-core'; 8 8 import ts from 'typescript'; 9 9 10 - import { TsDsl, TypeTsDsl } from '../base'; 10 + import { TsDsl } from '../base'; 11 11 import { AsMixin } from '../mixins/as'; 12 12 import { DecoratorMixin } from '../mixins/decorator'; 13 13 import { DoMixin } from '../mixins/do'; ··· 22 22 } from '../mixins/modifiers'; 23 23 import { ParamMixin } from '../mixins/param'; 24 24 import { TypeParamsMixin } from '../mixins/type-params'; 25 + import { TypeReturnsMixin } from '../mixins/type-returns'; 25 26 import { BlockTsDsl } from '../stmt/block'; 26 - import { TypeExprTsDsl } from '../type/expr'; 27 27 import { safeRuntimeName } from '../utils/name'; 28 28 29 29 export type FuncMode = 'arrow' | 'decl' | 'expr'; ··· 39 39 PrivateMixin( 40 40 ProtectedMixin( 41 41 PublicMixin( 42 - StaticMixin(TypeParamsMixin(TsDsl<ts.ArrowFunction>)), 42 + StaticMixin( 43 + TypeParamsMixin( 44 + TypeReturnsMixin(TsDsl<ts.ArrowFunction>), 45 + ), 46 + ), 43 47 ), 44 48 ), 45 49 ), ··· 56 60 57 61 protected mode?: FuncMode; 58 62 protected name?: Ref<FuncName>; 59 - protected _returns?: TypeTsDsl; 60 63 61 64 constructor(); 62 65 constructor(fn: (f: ImplFuncTsDsl<'arrow'>) => void); ··· 87 90 try { 88 91 super.analyze(ctx); 89 92 ctx.analyze(this.name); 90 - ctx.analyze(this._returns); 91 93 } finally { 92 94 ctx.popScope(); 93 95 } ··· 111 113 return this as unknown as FuncTsDsl<'expr'>; 112 114 } 113 115 114 - /** Sets the return type. */ 115 - returns(type: string | TypeTsDsl): this { 116 - this._returns = type instanceof TypeTsDsl ? type : new TypeExprTsDsl(type); 117 - return this; 118 - } 119 - 120 116 // @ts-expect-error --- need to fix types --- 121 117 override toAst( 122 118 ctx: AstContext, ··· 135 131 this.$node(ctx, this.name) as ts.Identifier, 136 132 this.$generics(ctx), 137 133 this.$params(ctx), 138 - this.$type(ctx, this._returns), 134 + this.$returns(ctx), 139 135 body, 140 136 ) as any; 141 137 return this.$docs(ctx, node); ··· 148 144 this.$node(ctx, this.name) as ts.Identifier, 149 145 this.$generics(ctx), 150 146 this.$params(ctx), 151 - this.$type(ctx, this._returns), 147 + this.$returns(ctx), 152 148 body, 153 149 ) as any; 154 150 return this.$docs(ctx, node); ··· 158 154 this.modifiers, 159 155 this.$generics(ctx), 160 156 this.$params(ctx), 161 - this.$type(ctx, this._returns), 157 + this.$returns(ctx), 162 158 undefined, 163 159 body.statements.length === 1 && 164 160 ts.isReturnStatement(body.statements[0]!) &&
+7 -2
packages/openapi-ts/src/ts-dsl/decl/getter.ts
··· 14 14 StaticMixin, 15 15 } from '../mixins/modifiers'; 16 16 import { ParamMixin } from '../mixins/param'; 17 + import { TypeReturnsMixin } from '../mixins/type-returns'; 17 18 import { BlockTsDsl } from '../stmt/block'; 18 19 19 20 export type GetterName = string | ts.PropertyName; ··· 26 27 ParamMixin( 27 28 PrivateMixin( 28 29 ProtectedMixin( 29 - PublicMixin(StaticMixin(TsDsl<ts.GetAccessorDeclaration>)), 30 + PublicMixin( 31 + StaticMixin( 32 + TypeReturnsMixin(TsDsl<ts.GetAccessorDeclaration>), 33 + ), 34 + ), 30 35 ), 31 36 ), 32 37 ), ··· 61 66 [...this.$decorators(ctx), ...this.modifiers], 62 67 this.name, 63 68 this.$params(ctx), 64 - undefined, 69 + this.$returns(ctx), 65 70 this.$node(ctx, new BlockTsDsl(...this._do).pretty()), 66 71 ); 67 72 return this.$docs(ctx, node);
+8 -12
packages/openapi-ts/src/ts-dsl/decl/method.ts
··· 1 1 import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 - import { TsDsl, TypeTsDsl } from '../base'; 4 + import { TsDsl } from '../base'; 5 5 import { DecoratorMixin } from '../mixins/decorator'; 6 6 import { DoMixin } from '../mixins/do'; 7 7 import { DocMixin } from '../mixins/doc'; ··· 16 16 import { OptionalMixin } from '../mixins/optional'; 17 17 import { ParamMixin } from '../mixins/param'; 18 18 import { TypeParamsMixin } from '../mixins/type-params'; 19 + import { TypeReturnsMixin } from '../mixins/type-returns'; 19 20 import { BlockTsDsl } from '../stmt/block'; 20 21 import { TokenTsDsl } from '../token'; 21 - import { TypeExprTsDsl } from '../type/expr'; 22 22 23 23 const Mixed = AbstractMixin( 24 24 AsyncMixin( ··· 30 30 PrivateMixin( 31 31 ProtectedMixin( 32 32 PublicMixin( 33 - StaticMixin(TypeParamsMixin(TsDsl<ts.MethodDeclaration>)), 33 + StaticMixin( 34 + TypeParamsMixin( 35 + TypeReturnsMixin(TsDsl<ts.MethodDeclaration>), 36 + ), 37 + ), 34 38 ), 35 39 ), 36 40 ), ··· 46 50 readonly '~dsl' = 'MethodTsDsl'; 47 51 48 52 protected name: string; 49 - protected _returns?: TypeTsDsl; 50 53 51 54 constructor(name: string, fn?: (m: MethodTsDsl) => void) { 52 55 super(); ··· 58 61 ctx.pushScope(); 59 62 try { 60 63 super.analyze(ctx); 61 - ctx.analyze(this._returns); 62 64 } finally { 63 65 ctx.popScope(); 64 66 } 65 67 } 66 68 67 - /** Sets the return type. */ 68 - returns(type: string | TypeTsDsl): this { 69 - this._returns = type instanceof TypeTsDsl ? type : new TypeExprTsDsl(type); 70 - return this; 71 - } 72 - 73 69 override toAst(ctx: AstContext) { 74 70 const node = ts.factory.createMethodDeclaration( 75 71 [...this.$decorators(ctx), ...this.modifiers], ··· 78 74 this._optional ? this.$node(ctx, new TokenTsDsl().optional()) : undefined, 79 75 this.$generics(ctx), 80 76 this.$params(ctx), 81 - this.$type(ctx, this._returns), 77 + this.$returns(ctx), 82 78 this.$node(ctx, new BlockTsDsl(...this._do).pretty()), 83 79 ); 84 80 return this.$docs(ctx, node);
+7
packages/openapi-ts/src/ts-dsl/expr/binary.ts
··· 30 30 | '>' 31 31 | '>=' 32 32 | '??' 33 + | '??=' 33 34 | '||'; 34 35 35 36 const Mixed = AsMixin(ExprMixin(TsDsl<ts.BinaryExpression>)); ··· 119 120 return this.opAndExpr('!==', expr); 120 121 } 121 122 123 + /** Nullish assignment — `this ??= expr` */ 124 + nullishAssign(expr: Expr): this { 125 + return this.opAndExpr('??=', expr); 126 + } 127 + 122 128 /** Logical OR — `this || expr` */ 123 129 or(expr: Expr): this { 124 130 return this.opAndExpr('||', expr); ··· 172 178 '>': ts.SyntaxKind.GreaterThanToken, 173 179 '>=': ts.SyntaxKind.GreaterThanEqualsToken, 174 180 '??': ts.SyntaxKind.QuestionQuestionToken, 181 + '??=': ts.SyntaxKind.QuestionQuestionEqualsToken, 175 182 '||': ts.SyntaxKind.BarBarToken, 176 183 }; 177 184 const token = tokenMap[op];
+6
packages/openapi-ts/src/ts-dsl/mixins/operator.ts
··· 34 34 minus(expr: Expr): BinaryTsDsl; 35 35 /** Strict inequality — `this !== expr` */ 36 36 neq(expr: Expr): BinaryTsDsl; 37 + /** Nullish assignment — `this ??= expr` */ 38 + nullishAssign(expr: Expr): BinaryTsDsl; 37 39 /** Logical OR — `this || expr` */ 38 40 or(expr: Expr): BinaryTsDsl; 39 41 /** Addition — `this + expr` */ ··· 101 103 102 104 protected neq(expr: Expr): BinaryTsDsl { 103 105 return new BinaryTsDsl(this).neq(expr); 106 + } 107 + 108 + protected nullishAssign(expr: Expr): BinaryTsDsl { 109 + return new BinaryTsDsl(this).nullishAssign(expr); 104 110 } 105 111 106 112 protected or(expr: Expr): BinaryTsDsl {
+39
packages/openapi-ts/src/ts-dsl/mixins/type-returns.ts
··· 1 + import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; 2 + import type ts from 'typescript'; 3 + 4 + import { TypeTsDsl } from '../base'; 5 + import type { TypeExprName } from '../type/expr'; 6 + import { TypeExprTsDsl } from '../type/expr'; 7 + import type { BaseCtor, MixinCtor } from './types'; 8 + 9 + export interface TypeReturnsMethods extends Node { 10 + /** Returns the return type node. */ 11 + $returns(ctx: AstContext): ts.TypeNode | undefined; 12 + /** Sets the return type. */ 13 + returns(type: TypeExprName | TypeTsDsl): this; 14 + } 15 + 16 + export function TypeReturnsMixin<T extends ts.Node, TBase extends BaseCtor<T>>( 17 + Base: TBase, 18 + ) { 19 + abstract class TypeReturns extends Base { 20 + protected _returns?: TypeTsDsl; 21 + 22 + override analyze(ctx: AnalysisContext): void { 23 + super.analyze(ctx); 24 + ctx.analyze(this._returns); 25 + } 26 + 27 + protected returns(type: TypeExprName | TypeTsDsl): this { 28 + this._returns = 29 + type instanceof TypeTsDsl ? type : new TypeExprTsDsl(type); 30 + return this; 31 + } 32 + 33 + protected $returns(ctx: AstContext): ts.TypeNode | undefined { 34 + return this.$type(ctx, this._returns); 35 + } 36 + } 37 + 38 + return TypeReturns as unknown as MixinCtor<TBase, TypeReturnsMethods>; 39 + }
+3 -2
packages/openapi-ts/src/ts-dsl/type/and.ts
··· 7 7 import { ref } from '@hey-api/codegen-core'; 8 8 import ts from 'typescript'; 9 9 10 - import { TypeTsDsl } from '../base'; 10 + import type { TypeTsDsl } from '../base'; 11 + import { TsDsl } from '../base'; 11 12 12 13 type Type = Symbol | string | ts.TypeNode | TypeTsDsl; 13 14 14 - const Mixed = TypeTsDsl<ts.IntersectionTypeNode>; 15 + const Mixed = TsDsl<ts.IntersectionTypeNode>; 15 16 16 17 export class TypeAndTsDsl extends Mixed { 17 18 readonly '~dsl' = 'TypeAndTsDsl';
+2 -2
packages/openapi-ts/src/ts-dsl/type/attr.ts
··· 8 8 import ts from 'typescript'; 9 9 10 10 import type { MaybeTsDsl } from '../base'; 11 - import { TypeTsDsl } from '../base'; 11 + import { TsDsl } from '../base'; 12 12 import { TypeExprMixin } from '../mixins/type-expr'; 13 13 14 14 type Base = Symbol | string | MaybeTsDsl<ts.EntityName>; 15 15 type Right = Symbol | string | ts.Identifier; 16 16 17 - const Mixed = TypeExprMixin(TypeTsDsl<ts.QualifiedName>); 17 + const Mixed = TypeExprMixin(TsDsl<ts.QualifiedName>); 18 18 19 19 export class TypeAttrTsDsl extends Mixed { 20 20 readonly '~dsl' = 'TypeAttrTsDsl';
+2 -2
packages/openapi-ts/src/ts-dsl/type/expr.ts
··· 7 7 import { isNode, ref } from '@hey-api/codegen-core'; 8 8 import ts from 'typescript'; 9 9 10 - import { TypeTsDsl } from '../base'; 10 + import { TsDsl } from '../base'; 11 11 import { TypeArgsMixin } from '../mixins/type-args'; 12 12 import { TypeExprMixin } from '../mixins/type-expr'; 13 13 import { f } from '../utils/factories'; ··· 21 21 fn?: TypeExprFn, 22 22 ) => TypeExprTsDsl; 23 23 24 - const Mixed = TypeArgsMixin(TypeExprMixin(TypeTsDsl<ts.TypeReferenceNode>)); 24 + const Mixed = TypeArgsMixin(TypeExprMixin(TsDsl<ts.TypeReferenceNode>)); 25 25 26 26 export class TypeExprTsDsl extends Mixed { 27 27 readonly '~dsl' = 'TypeExprTsDsl';
+6 -14
packages/openapi-ts/src/ts-dsl/type/func.ts
··· 1 1 import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 - import { TypeTsDsl } from '../base'; 4 + import { TsDsl } from '../base'; 5 5 import { DocMixin } from '../mixins/doc'; 6 6 import { ParamMixin } from '../mixins/param'; 7 7 import { TypeParamsMixin } from '../mixins/type-params'; 8 - import { TypeExprTsDsl } from './expr'; 8 + import { TypeReturnsMixin } from '../mixins/type-returns'; 9 9 10 10 const Mixed = DocMixin( 11 - ParamMixin(TypeParamsMixin(TypeTsDsl<ts.FunctionTypeNode>)), 11 + ParamMixin(TypeParamsMixin(TypeReturnsMixin(TsDsl<ts.FunctionTypeNode>))), 12 12 ); 13 13 14 14 export class TypeFuncTsDsl extends Mixed { 15 15 readonly '~dsl' = 'TypeFuncTsDsl'; 16 - 17 - protected _returns?: TypeTsDsl; 18 16 19 17 override analyze(ctx: AnalysisContext): void { 20 18 super.analyze(ctx); 21 - ctx.analyze(this._returns); 22 - } 23 - 24 - /** Sets the return type. */ 25 - returns(type: string | TypeTsDsl): this { 26 - this._returns = type instanceof TypeTsDsl ? type : new TypeExprTsDsl(type); 27 - return this; 28 19 } 29 20 30 21 override toAst(ctx: AstContext) { 31 - if (this._returns === undefined) { 22 + const returns = this.$returns(ctx); 23 + if (returns === undefined) { 32 24 throw new Error('Missing return type in function type DSL'); 33 25 } 34 26 const node = ts.factory.createFunctionTypeNode( 35 27 this.$generics(ctx), 36 28 this.$params(ctx), 37 - this.$type(ctx, this._returns), 29 + returns, 38 30 ); 39 31 return this.$docs(ctx, node); 40 32 }
+2 -2
packages/openapi-ts/src/ts-dsl/type/idx-sig.ts
··· 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 - import { TypeTsDsl } from '../base'; 5 + import { TsDsl } from '../base'; 6 6 import { DocMixin } from '../mixins/doc'; 7 7 import { ReadonlyMixin } from '../mixins/modifiers'; 8 8 9 9 export type TypeIdxSigName = string; 10 10 export type TypeIdxSigType = string | MaybeTsDsl<ts.TypeNode>; 11 11 12 - const Mixed = DocMixin(ReadonlyMixin(TypeTsDsl<ts.IndexSignatureDeclaration>)); 12 + const Mixed = DocMixin(ReadonlyMixin(TsDsl<ts.IndexSignatureDeclaration>)); 13 13 14 14 export class TypeIdxSigTsDsl extends Mixed { 15 15 readonly '~dsl' = 'TypeIdxSigTsDsl';
+2 -2
packages/openapi-ts/src/ts-dsl/type/idx.ts
··· 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 - import { TypeTsDsl } from '../base'; 5 + import { TsDsl } from '../base'; 6 6 import { TypeExprMixin } from '../mixins/type-expr'; 7 7 import { f } from '../utils/factories'; 8 8 ··· 10 10 type Index = string | number | MaybeTsDsl<ts.TypeNode>; 11 11 export type TypeIdxCtor = (base: Base, index: Index) => TypeIdxTsDsl; 12 12 13 - const Mixed = TypeExprMixin(TypeTsDsl<ts.IndexedAccessTypeNode>); 13 + const Mixed = TypeExprMixin(TsDsl<ts.IndexedAccessTypeNode>); 14 14 15 15 export class TypeIdxTsDsl extends Mixed { 16 16 readonly '~dsl' = 'TypeIdxTsDsl';
+2 -2
packages/openapi-ts/src/ts-dsl/type/literal.ts
··· 1 1 import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 - import { TypeTsDsl } from '../base'; 4 + import { TsDsl } from '../base'; 5 5 import { LiteralTsDsl } from '../expr/literal'; 6 6 7 - const Mixed = TypeTsDsl<ts.LiteralTypeNode>; 7 + const Mixed = TsDsl<ts.LiteralTypeNode>; 8 8 9 9 export class TypeLiteralTsDsl extends Mixed { 10 10 readonly '~dsl' = 'TypeLiteralTsDsl';
+2 -2
packages/openapi-ts/src/ts-dsl/type/mapped.ts
··· 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 - import { TypeTsDsl } from '../base'; 5 + import { TsDsl } from '../base'; 6 6 import { TokenTsDsl } from '../token'; 7 7 8 - const Mixed = TypeTsDsl<ts.MappedTypeNode>; 8 + const Mixed = TsDsl<ts.MappedTypeNode>; 9 9 10 10 export class TypeMappedTsDsl extends Mixed { 11 11 readonly '~dsl' = 'TypeMappedTsDsl';
+2 -2
packages/openapi-ts/src/ts-dsl/type/object.ts
··· 1 1 import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 - import { TypeTsDsl } from '../base'; 4 + import { TsDsl } from '../base'; 5 5 import { TypeIdxSigTsDsl } from './idx-sig'; 6 6 import { TypePropTsDsl } from './prop'; 7 7 8 - const Mixed = TypeTsDsl<ts.TypeNode>; 8 + const Mixed = TsDsl<ts.TypeNode>; 9 9 10 10 export class TypeObjectTsDsl extends Mixed { 11 11 readonly '~dsl' = 'TypeObjectTsDsl';
+2 -2
packages/openapi-ts/src/ts-dsl/type/operator.ts
··· 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 - import { TypeTsDsl } from '../base'; 5 + import { TsDsl } from '../base'; 6 6 import { f } from '../utils/factories'; 7 7 8 8 type Op = ··· 12 12 type Type = string | MaybeTsDsl<ts.TypeNode>; 13 13 export type TypeOperatorCtor = () => TypeOperatorTsDsl; 14 14 15 - const Mixed = TypeTsDsl<ts.TypeOperatorNode>; 15 + const Mixed = TsDsl<ts.TypeOperatorNode>; 16 16 17 17 /** 18 18 * Builds a TypeScript `TypeOperatorNode`, such as:
+3 -2
packages/openapi-ts/src/ts-dsl/type/or.ts
··· 7 7 import { ref } from '@hey-api/codegen-core'; 8 8 import ts from 'typescript'; 9 9 10 - import { TypeTsDsl } from '../base'; 10 + import type { TypeTsDsl } from '../base'; 11 + import { TsDsl } from '../base'; 11 12 12 13 type Type = Symbol | string | ts.TypeNode | TypeTsDsl; 13 14 14 - const Mixed = TypeTsDsl<ts.UnionTypeNode>; 15 + const Mixed = TsDsl<ts.UnionTypeNode>; 15 16 16 17 export class TypeOrTsDsl extends Mixed { 17 18 readonly '~dsl' = 'TypeOrTsDsl';
+3 -3
packages/openapi-ts/src/ts-dsl/type/param.ts
··· 7 7 import { ref } from '@hey-api/codegen-core'; 8 8 import ts from 'typescript'; 9 9 10 - import type { MaybeTsDsl } from '../base'; 11 - import { TypeTsDsl } from '../base'; 10 + import type { MaybeTsDsl, TypeTsDsl } from '../base'; 11 + import { TsDsl } from '../base'; 12 12 13 13 export type TypeParamName = Symbol | string; 14 14 export type TypeParamExpr = Symbol | string | boolean | MaybeTsDsl<TypeTsDsl>; 15 15 16 - const Mixed = TypeTsDsl<ts.TypeParameterDeclaration>; 16 + const Mixed = TsDsl<ts.TypeParameterDeclaration>; 17 17 18 18 export class TypeParamTsDsl extends Mixed { 19 19 readonly '~dsl' = 'TypeParamTsDsl';
+2 -2
packages/openapi-ts/src/ts-dsl/type/prop.ts
··· 8 8 import ts from 'typescript'; 9 9 10 10 import type { MaybeTsDsl } from '../base'; 11 - import { TypeTsDsl } from '../base'; 11 + import { TsDsl } from '../base'; 12 12 import { DocMixin } from '../mixins/doc'; 13 13 import { ReadonlyMixin } from '../mixins/modifiers'; 14 14 import { OptionalMixin } from '../mixins/optional'; ··· 18 18 export type TypePropName = string; 19 19 export type TypePropType = Symbol | string | MaybeTsDsl<ts.TypeNode>; 20 20 21 - const Mixed = DocMixin(OptionalMixin(ReadonlyMixin(TypeTsDsl<ts.TypeElement>))); 21 + const Mixed = DocMixin(OptionalMixin(ReadonlyMixin(TsDsl<ts.TypeElement>))); 22 22 23 23 export class TypePropTsDsl extends Mixed { 24 24 readonly '~dsl' = 'TypePropTsDsl';
+3 -3
packages/openapi-ts/src/ts-dsl/type/query.ts
··· 1 1 import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 - import type { MaybeTsDsl } from '../base'; 5 - import { TypeTsDsl } from '../base'; 4 + import type { MaybeTsDsl, TypeTsDsl } from '../base'; 5 + import { TsDsl } from '../base'; 6 6 import { TypeExprMixin } from '../mixins/type-expr'; 7 7 import { f } from '../utils/factories'; 8 8 9 9 export type TypeQueryExpr = string | MaybeTsDsl<TypeTsDsl | ts.Expression>; 10 10 export type TypeQueryCtor = (expr: TypeQueryExpr) => TypeQueryTsDsl; 11 11 12 - const Mixed = TypeExprMixin(TypeTsDsl<ts.TypeQueryNode>); 12 + const Mixed = TypeExprMixin(TsDsl<ts.TypeQueryNode>); 13 13 14 14 export class TypeQueryTsDsl extends Mixed { 15 15 readonly '~dsl' = 'TypeQueryTsDsl';
+2 -2
packages/openapi-ts/src/ts-dsl/type/template.ts
··· 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 - import { TypeTsDsl } from '../base'; 5 + import { TsDsl } from '../base'; 6 6 7 - const Mixed = TypeTsDsl<ts.TemplateLiteralTypeNode>; 7 + const Mixed = TsDsl<ts.TemplateLiteralTypeNode>; 8 8 9 9 export class TypeTemplateTsDsl extends Mixed { 10 10 readonly '~dsl' = 'TypeTemplateTsDsl';
+3 -2
packages/openapi-ts/src/ts-dsl/type/tuple.ts
··· 1 1 import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 - import { TypeTsDsl } from '../base'; 4 + import type { TypeTsDsl } from '../base'; 5 + import { TsDsl } from '../base'; 5 6 6 - const Mixed = TypeTsDsl<ts.TupleTypeNode>; 7 + const Mixed = TsDsl<ts.TupleTypeNode>; 7 8 8 9 export class TypeTupleTsDsl extends Mixed { 9 10 readonly '~dsl' = 'TypeTupleTsDsl';
+25
specs/3.1.x/sdk-nested-conflict.yaml
··· 1 + openapi: 3.1.1 2 + info: 3 + title: OpenAPI 3.1.1 sdk nested conflict example 4 + version: 1 5 + paths: 6 + /v1/providers: 7 + get: 8 + operationId: providers.list 9 + summary: List Providers 10 + tags: 11 + - providers 12 + /v1/tenants/{tenantId}/providers: 13 + get: 14 + operationId: tenants.providers.list 15 + summary: List Tenant Providers 16 + tags: 17 + - tenants 18 + - tenantProviders 19 + parameters: 20 + - name: tenantId 21 + in: path 22 + required: true 23 + schema: 24 + type: string 25 + description: Tenant ID