From 5613ac0ca436e0d11a1d5af90ee1d73419ab241e Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 16 Dec 2025 05:54:39 +0800 Subject: [PATCH 01/15] fix(@hey-api/sdk): dedup classes --- dev/openapi-ts.config.ts | 19 +- packages/codegen-core/src/files/file.ts | 2 +- packages/codegen-core/src/planner/analyzer.ts | 16 +- packages/codegen-core/src/planner/planner.ts | 85 ++- packages/codegen-core/src/planner/scope.ts | 35 ++ packages/codegen-core/src/planner/types.d.ts | 22 +- packages/codegen-core/src/symbols/symbol.ts | 6 +- .../src/openApi/shared/utils/name.ts | 7 +- .../src/openApi/shared/utils/operation.ts | 12 +- .../plugins/@angular/common/httpRequests.ts | 6 +- .../plugins/@angular/common/httpResources.ts | 16 +- .../src/plugins/@hey-api/sdk/config.ts | 1 + .../src/plugins/@hey-api/sdk/model/class.ts | 312 ++++++++++ .../src/plugins/@hey-api/sdk/shared/class.ts | 571 ++++++++++-------- .../plugins/@hey-api/sdk/shared/operation.ts | 27 +- .../plugins/@hey-api/sdk/shared/signature.ts | 6 +- .../src/plugins/@hey-api/sdk/types.d.ts | 12 +- .../@hey-api/typescript/shared/export.ts | 6 +- .../@hey-api/typescript/v1/toAst/string.ts | 7 +- .../src/plugins/@pinia/colada/v0/plugin.ts | 7 +- .../plugins/@tanstack/query-core/v5/plugin.ts | 7 +- .../openapi-ts/src/plugins/swr/v2/plugin.ts | 7 +- packages/openapi-ts/src/ts-dsl/base.ts | 8 +- packages/openapi-ts/src/ts-dsl/decl/class.ts | 13 +- packages/openapi-ts/src/ts-dsl/decl/field.ts | 7 +- packages/openapi-ts/src/ts-dsl/decl/getter.ts | 18 +- packages/openapi-ts/src/ts-dsl/decl/method.ts | 20 +- packages/openapi-ts/src/ts-dsl/decl/setter.ts | 18 +- .../{stringCase.test.ts => to-case.test.ts} | 32 +- packages/openapi-ts/src/utils/exports.ts | 31 +- .../src/utils/{stringCase.ts => to-case.ts} | 79 ++- 31 files changed, 919 insertions(+), 496 deletions(-) create mode 100644 packages/codegen-core/src/planner/scope.ts create mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts rename packages/openapi-ts/src/utils/__tests__/{stringCase.test.ts => to-case.test.ts} (89%) rename packages/openapi-ts/src/utils/{stringCase.ts => to-case.ts} (72%) diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index b5b117b67..3ead7e0ca 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -277,7 +277,7 @@ export default defineConfig(() => { // asClass: true, // auth: false, // classNameBuilder: '{{name}}', - // classNameBuilder: '{{name}}Service', + classNameBuilder: '{{name}}Service', // classStructure: 'off', // client: false, // getSignature: ({ fields, signature, operation }) => { @@ -285,7 +285,8 @@ export default defineConfig(() => { // fields.unwrap('path') // }, // include... - instance: true, + instance: 'Root', + methodNameBuilder: '{{name}}Methods', name: '@hey-api/sdk', // operationId: false, // paramsStructure: 'flat', @@ -304,10 +305,7 @@ export default defineConfig(() => { symbols: { // getFilePath: (symbol) => { // if (symbol.name) { - // return utils.stringCase({ - // case: 'camelCase', - // value: symbol.name, - // }); + // return utils.toCase(symbol.name, 'camelCase'); // } // return; // }, @@ -351,7 +349,7 @@ export default defineConfig(() => { // name: '{{name}}MO', // name: 'options', }, - name: '@tanstack/react-query', + // name: '@tanstack/react-query', queryKeys: { // name: '{{name}}QK', // name: 'options', @@ -421,10 +419,7 @@ export default defineConfig(() => { symbols: { // getFilePath: (symbol) => { // if (symbol.name) { - // return utils.stringCase({ - // case: 'camelCase', - // value: symbol.name, - // }); + // return utils.toCase(symbol.name, 'camelCase'); // } // return; // }, @@ -615,7 +610,7 @@ export default defineConfig(() => { { exportFromIndex: true, // mutationOptions: '{{name}}Mutationssss', - name: '@pinia/colada', + // name: '@pinia/colada', // queryOptions: { // name: '{{name}}Queryyyyy', // }, diff --git a/packages/codegen-core/src/files/file.ts b/packages/codegen-core/src/files/file.ts index 3e5aad135..adb37dcc9 100644 --- a/packages/codegen-core/src/files/file.ts +++ b/packages/codegen-core/src/files/file.ts @@ -5,7 +5,7 @@ import { fileBrand } from '../brands'; import { debug } from '../debug'; import type { Language } from '../languages/types'; import type { INode } from '../nodes/node'; -import type { NameScopes } from '../planner/types'; +import type { NameScopes } from '../planner/scope'; import type { IProject } from '../project/types'; import type { Renderer } from '../renderer'; import type { IFileIn } from './types'; diff --git a/packages/codegen-core/src/planner/analyzer.ts b/packages/codegen-core/src/planner/analyzer.ts index 1af9bfab9..7a9900165 100644 --- a/packages/codegen-core/src/planner/analyzer.ts +++ b/packages/codegen-core/src/planner/analyzer.ts @@ -3,21 +3,17 @@ import type { INode } from '../nodes/node'; import { fromRef, isRef, ref } from '../refs/refs'; import type { Ref } from '../refs/types'; import type { Symbol } from '../symbols/symbol'; -import type { IAnalysisContext, Input, NameScopes, Scope } from './types'; - -const createScope = (parent?: Scope): Scope => ({ - children: [], - localNames: new Map(), - parent, - symbols: [], -}); +import type { NameScopes, Scope } from './scope'; +import { createScope } from './scope'; +import type { IAnalysisContext, Input } from './types'; export class AnalysisContext implements IAnalysisContext { + scope: Scope; scopes: Scope = createScope(); symbol?: Symbol; - scope: Scope = this.scopes; constructor(symbol?: Symbol) { + this.scope = this.scopes; this.symbol = symbol; } @@ -62,7 +58,7 @@ export class AnalysisContext implements IAnalysisContext { } pushScope(): void { - const scope = createScope(this.scope); + const scope = createScope({ parent: this.scope }); this.scope.children.push(scope); this.scope = scope; } diff --git a/packages/codegen-core/src/planner/planner.ts b/packages/codegen-core/src/planner/planner.ts index 932e57b95..4938a23b5 100644 --- a/packages/codegen-core/src/planner/planner.ts +++ b/packages/codegen-core/src/planner/planner.ts @@ -12,7 +12,8 @@ import type { Symbol } from '../symbols/symbol'; import type { SymbolKind } from '../symbols/types'; import type { AnalysisContext } from './analyzer'; import { Analyzer } from './analyzer'; -import type { AssignOptions, NameScopes } from './types'; +import type { AssignOptions, Scope } from './scope'; +import { createScope } from './scope'; const isTypeOnlyKind = (kind: SymbolKind) => kind === 'type' || kind === 'interface'; @@ -76,7 +77,7 @@ export class Planner { this.analyzer.analyze(this.project.nodes.all(), (ctx, node) => { const symbol = node.symbol; if (!symbol) return; - this.assignTopLevelName(symbol, ctx); + this.assignTopLevelName({ ctx, symbol }); }); this.analyzer.analyze(this.project.nodes.all(), (ctx, node) => { @@ -86,8 +87,11 @@ export class Planner { const dep = fromRef(dependency); // top-level or external symbol if (dep.file) return; - this.assignLocalName(dep, ctx, { - scopesToUpdate: [file.allNames], + this.assignLocalName({ + ctx, + file, + scopesToUpdate: [createScope({ localNames: file.allNames })], + symbol: dep, }); }); }); @@ -166,7 +170,7 @@ export class Planner { }); exp.setFile(target); sourceFile.set(exp.id, file); - this.assignTopLevelName(exp, ctx); + this.assignTopLevelName({ ctx, symbol: exp }); let entry = fileMap.get(exp.finalName); if (!entry) { @@ -253,7 +257,7 @@ export class Planner { if (!dep.file || dep.file.id === file.id) return; if (dep.external) { - this.assignTopLevelName(dep, ctx); + this.assignTopLevelName({ ctx, symbol: dep }); } const fromFileId = dep.file.id; @@ -272,8 +276,10 @@ export class Planner { name: dep.finalName, }); imp.setFile(file); - this.assignTopLevelName(imp, ctx, { - scope: imp.file!.allNames, + this.assignTopLevelName({ + ctx, + scope: createScope({ localNames: imp.file!.allNames }), + symbol: imp, }); entry = { dep, @@ -334,17 +340,22 @@ export class Planner { * Supports optional overrides for the naming scope and scopes to update. */ private assignTopLevelName( - symbol: Symbol, - ctx: AnalysisContext, - options?: Partial, + args: Partial & { + ctx: AnalysisContext; + symbol: Symbol; + }, ): void { - if (!symbol.file) return; - this.assignSymbolName(symbol, { - scope: options?.scope ?? symbol.file.topLevelNames, + if (!args.symbol.file) return; + this.assignSymbolName({ + ...args, + file: args.symbol.file, + scope: + args?.scope ?? + createScope({ localNames: args.symbol.file.topLevelNames }), scopesToUpdate: [ - symbol.file.allNames, - ctx.scopes.localNames, - ...(options?.scopesToUpdate ?? []), + createScope({ localNames: args.symbol.file.allNames }), + args.ctx.scopes, + ...(args?.scopesToUpdate ?? []), ], }); } @@ -357,14 +368,17 @@ export class Planner { * Updates all provided name scopes accordingly. */ private assignLocalName( - symbol: Symbol, - ctx: AnalysisContext, - options: Pick, 'scope'> & - Pick, + args: Pick, 'scope'> & + Pick & { + ctx: AnalysisContext; + /** The file the symbol belongs to. */ + file: File; + symbol: Symbol; + }, ): void { - this.assignSymbolName(symbol, { - scope: options.scope ?? ctx.localNames(ctx.scope), - scopesToUpdate: options.scopesToUpdate, + this.assignSymbolName({ + ...args, + scope: args.scope ?? args.ctx.scope, }); } @@ -375,20 +389,29 @@ export class Planner { * * Updates all specified name scopes with the assigned final name. */ - private assignSymbolName(symbol: Symbol, options: AssignOptions): void { + private assignSymbolName( + args: AssignOptions & { + ctx: AnalysisContext; + /** The file the symbol belongs to. */ + file: File; + symbol: Symbol; + }, + ): void { + const { ctx, file, scope, scopesToUpdate, symbol } = args; if (this.cacheResolvedNames.has(symbol.id)) return; const baseName = symbol.name; let finalName = symbol.nameSanitizer?.(baseName) ?? baseName; let attempt = 1; + const localNames = ctx.localNames(scope); while (true) { - const kinds = [...(options.scope.get(finalName) ?? [])]; + const kinds = [...(localNames.get(finalName) ?? [])]; const ok = kinds.every((kind) => canShareName(symbol.kind, kind)); if (ok) break; - const language = symbol.node?.language || symbol.file?.language; + const language = symbol.node?.language || file.language; const resolver = (language ? this.project.nameConflictResolvers[language] : undefined) ?? this.project.defaultNameConflictResolver; @@ -403,7 +426,7 @@ export class Planner { symbol.setFinalName(finalName); this.cacheResolvedNames.add(symbol.id); - const updateScopes = [options.scope, ...options.scopesToUpdate]; + const updateScopes = [scope, ...scopesToUpdate]; for (const scope of updateScopes) { this.updateScope(symbol, scope); } @@ -414,11 +437,11 @@ export class Planner { * * Ensures the name scope tracks all kinds associated with a given name. */ - private updateScope(symbol: Symbol, scope: NameScopes): void { + private updateScope(symbol: Symbol, scope: Scope): void { const name = symbol.finalName; - const cache = scope.get(name) ?? new Set(); + const cache = scope.localNames.get(name) ?? new Set(); cache.add(symbol.kind); - scope.set(name, cache); + scope.localNames.set(name, cache); } private symbolToFileIn(symbol: Symbol): IFileIn { diff --git a/packages/codegen-core/src/planner/scope.ts b/packages/codegen-core/src/planner/scope.ts new file mode 100644 index 000000000..d48821d12 --- /dev/null +++ b/packages/codegen-core/src/planner/scope.ts @@ -0,0 +1,35 @@ +import type { Ref } from '../refs/types'; +import type { Symbol } from '../symbols/symbol'; +import type { SymbolKind } from '../symbols/types'; + +export type NameScopes = Map>; + +export type Scope = { + /** Child scopes. */ + children: Array; + /** Resolved names in this scope. */ + localNames: NameScopes; + /** Parent scope, if any. */ + parent?: Scope; + /** Symbols registered in this scope. */ + symbols: Array>; +}; + +export type AssignOptions = { + /** The primary scope in which to assign a symbol's final name. */ + scope: Scope; + /** Additional scopes to update as side effects when assigning a symbol's final name. */ + scopesToUpdate: ReadonlyArray; +}; + +export const createScope = ( + args: { + localNames?: NameScopes; + parent?: Scope; + } = {}, +): Scope => ({ + children: [], + localNames: args.localNames || new Map(), + parent: args.parent, + symbols: [], +}); diff --git a/packages/codegen-core/src/planner/types.d.ts b/packages/codegen-core/src/planner/types.d.ts index aa98ed3d7..a62a01380 100644 --- a/packages/codegen-core/src/planner/types.d.ts +++ b/packages/codegen-core/src/planner/types.d.ts @@ -1,34 +1,14 @@ import type { Ref } from '../refs/types'; import type { Symbol } from '../symbols/symbol'; -import type { SymbolKind } from '../symbols/types'; - -export type AssignOptions = { - /** The primary scope in which to assign a symbol's final name. */ - scope: NameScopes; - /** Additional scopes to update as side effects when assigning a symbol's final name. */ - scopesToUpdate: ReadonlyArray; -}; +import type { NameScopes, Scope } from './scope'; export type Input = Ref | object | string | number | undefined; -export type NameScopes = Map>; - export type NameConflictResolver = (args: { attempt: number; baseName: string; }) => string | null; -export type Scope = { - /** Child scopes. */ - children: Array; - /** Resolved names in this scope. */ - localNames: NameScopes; - /** Parent scope, if any. */ - parent?: Scope; - /** Symbols registered in this scope. */ - symbols: Array>; -}; - export interface IAnalysisContext { /** Register a dependency on another symbol. */ addDependency(symbol: Ref): void; diff --git a/packages/codegen-core/src/symbols/symbol.ts b/packages/codegen-core/src/symbols/symbol.ts index ed285d87c..726f4dc59 100644 --- a/packages/codegen-core/src/symbols/symbol.ts +++ b/packages/codegen-core/src/symbols/symbol.ts @@ -337,7 +337,11 @@ export class Symbol { * Returns a debug‑friendly string representation identifying the symbol. */ toString(): string { - return `[Symbol ${this.name}#${this.id}]`; + const canonical = this.canonical; + if (canonical._finalName && canonical._finalName !== canonical._name) { + return `[Symbol ${canonical._name} → ${canonical._finalName}#${canonical.id}]`; + } + return `[Symbol ${canonical._name}#${canonical.id}]`; } /** diff --git a/packages/openapi-ts/src/openApi/shared/utils/name.ts b/packages/openapi-ts/src/openApi/shared/utils/name.ts index fff76b867..74424495e 100644 --- a/packages/openapi-ts/src/openApi/shared/utils/name.ts +++ b/packages/openapi-ts/src/openApi/shared/utils/name.ts @@ -1,6 +1,5 @@ -import { stringCase } from '~/utils/stringCase'; - -import type { StringCase, StringName } from '../../../types/case'; +import type { StringCase, StringName } from '~/types/case'; +import { toCase } from '~/utils/to-case'; export const buildName = ({ config, @@ -19,5 +18,5 @@ export const buildName = ({ name = config.name.replace('{{name}}', `${separator}${name}${separator}`); } - return stringCase({ case: config.case, value: name }); + return toCase(name, config.case); }; diff --git a/packages/openapi-ts/src/openApi/shared/utils/operation.ts b/packages/openapi-ts/src/openApi/shared/utils/operation.ts index ec11085f9..7d75734ea 100644 --- a/packages/openapi-ts/src/openApi/shared/utils/operation.ts +++ b/packages/openapi-ts/src/openApi/shared/utils/operation.ts @@ -1,7 +1,7 @@ import type { Context } from '~/ir/context'; import { createOperationKey } from '~/ir/operation'; import { sanitizeNamespaceIdentifier } from '~/openApi/common/parser/sanitize'; -import { stringCase } from '~/utils/stringCase'; +import { toCase } from '~/utils/to-case'; import type { State } from '../types/state'; @@ -49,20 +49,14 @@ export const operationToId = ({ (!context.config.plugins['@hey-api/sdk'] || context.config.plugins['@hey-api/sdk'].config.operationId) ) { - result = stringCase({ - case: targetCase, - value: sanitizeNamespaceIdentifier(id), - }); + result = toCase(sanitizeNamespaceIdentifier(id), targetCase); } else { const pathWithoutPlaceholders = path .replace(/{(.*?)}/g, 'by-$1') // replace slashes with hyphens for camelcase method at the end .replace(/[/:+]/g, '-'); - result = stringCase({ - case: targetCase, - value: `${method}-${pathWithoutPlaceholders}`, - }); + result = toCase(`${method}-${pathWithoutPlaceholders}`, targetCase); } if (count > 1) { diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts b/packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts index 3d37e0734..c5fd134ac 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts @@ -8,7 +8,7 @@ import { isOperationOptionsRequired, } from '~/plugins/shared/utils/operation'; import { $ } from '~/ts-dsl'; -import { stringCase } from '~/utils/stringCase'; +import { toCase } from '~/utils/to-case'; import type { AngularCommonPlugin } from './types'; @@ -107,9 +107,7 @@ const generateAngularClassRequests = ({ generateClass(childClass); currentClass.nodes.push( - $.field( - stringCase({ case: 'camelCase', value: childClass.className }), - ).assign( + $.field(toCase(childClass.className, 'camelCase')).assign( $.new( buildName({ config: { diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpResources.ts b/packages/openapi-ts/src/plugins/@angular/common/httpResources.ts index ae433738f..fee0c24b0 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/httpResources.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/httpResources.ts @@ -8,7 +8,7 @@ import { isOperationOptionsRequired, } from '~/plugins/shared/utils/operation'; import { $ } from '~/ts-dsl'; -import { stringCase } from '~/utils/stringCase'; +import { toCase } from '~/utils/to-case'; import type { AngularCommonPlugin } from './types'; @@ -107,12 +107,7 @@ const generateAngularClassServices = ({ generateClass(childClass); currentClass.nodes.push( - $.field( - stringCase({ - case: 'camelCase', - value: childClass.className, - }), - ).assign( + $.field(toCase(childClass.className, 'camelCase')).assign( $.new( buildName({ config: { @@ -237,12 +232,7 @@ const generateResourceCallExpression = ({ for (let i = 1; i < firstEntry.path.length; i++) { const className = firstEntry.path[i]; if (className) { - methodAccess = methodAccess.attr( - stringCase({ - case: 'camelCase', - value: className, - }), - ); + methodAccess = methodAccess.attr(toCase(className, 'camelCase')); } } diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts index 4cd1c7aee..aa5dc94ab 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts @@ -12,6 +12,7 @@ export const defaultConfig: HeyApiSdkPlugin['Config'] = { client: true, exportFromIndex: true, instance: '', + methodNameBuilder: '{{name}}', operationId: true, paramsStructure: 'grouped', response: 'body', diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts new file mode 100644 index 000000000..3ccf4d237 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts @@ -0,0 +1,312 @@ +import type { IR } from '~/ir/types'; +import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; +import { + createOperationComment, + isOperationOptionsRequired, +} from '~/plugins/shared/utils/operation'; +import { $ } from '~/ts-dsl'; +import { toCase } from '~/utils/to-case'; + +import { createClientClass, createRegistryClass } from '../shared/class'; +import { nuxtTypeComposable, nuxtTypeDefault } from '../shared/constants'; +import { + operationClassName, + operationMethodName, + operationParameters, + operationStatements, +} from '../shared/operation'; +import type { HeyApiSdkPlugin } from '../types'; + +/** + * Represents a class in the SDK hierarchy. + * + * Classes can be nested (via children) and contain operations (methods). + */ +export class SdkClassModel { + /** Nested classes within this class. */ + children: Map = new Map(); + /** The name of this class (e.g., "Users", "Accounts"). */ + name: string; + /** Operations that will become methods in this class. */ + operations: Array = []; + /** Parent class in the hierarchy. Undefined if this is the root class. */ + parent?: SdkClassModel; + + constructor(name: string, parent?: SdkClassModel) { + this.name = name; + this.parent = parent; + } + + get isRoot(): boolean { + return !this.parent; + } + + /** + * Adds an operation to this class. + * + * The operation will be converted to a method during code generation. + */ + addOperation(operation: IR.OperationObject): void { + this.operations.push(operation); + } + + /** + * Gets or creates a child class. + * + * If the child doesn't exist, it's created automatically. + * + * @param name - The name of the child class + * @returns The child class instance + */ + child(name: string): SdkClassModel { + if (!this.children.has(name)) { + this.children.set(name, new SdkClassModel(name, this)); + } + return this.children.get(name)!; + } + + /** + * Inserts an operation into the class tree. + * + * Parses the operation ID and creates the class hierarchy. + */ + insert( + operation: IR.OperationObject, + plugin: HeyApiSdkPlugin['Instance'], + ): void { + const classSegments = + plugin.config.classStructure === 'auto' && operation.operationId + ? operation.operationId.split(/[./]/).slice(0, -1) + : []; + + // eslint-disable-next-line @typescript-eslint/no-this-alias + let cursor: SdkClassModel = this; + for (const segment of classSegments) { + cursor = cursor.child(segment); + } + + cursor.addOperation(operation); + } + + /** + * Converts this class group to a class node. + */ + toNode(plugin: HeyApiSdkPlugin['Instance']): { + dependencies: Array>; + node: ReturnType; + } { + const dependencies: Array> = []; + + const client = getClientPlugin(plugin.context.config); + const isAngularClient = client.name === '@hey-api/client-angular'; + const isNuxtClient = client.name === '@hey-api/client-nuxt'; + + const symbolClass = plugin.symbol( + operationClassName({ plugin, value: this.name }), + { + meta: { + category: 'utility', + resource: 'class', + resourceId: this.name, + tool: 'sdk', + }, + }, + ); + const node = $.class(symbolClass) + .export() + .extends( + plugin.referenceSymbol({ + category: 'utility', + resource: 'class', + resourceId: 'HeyApiClient', + tool: 'sdk', + }), + ) + .$if(isAngularClient && this.isRoot, (c) => + c.decorator( + plugin.referenceSymbol({ + category: 'external', + resource: '@angular/core.Injectable', + }), + $.object().prop('providedIn', $.literal('root')), + ), + ); + + if (this.isRoot) { + const symbolClient = plugin.symbol('HeyApiClient', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiClient', + tool: 'sdk', + }, + }); + const clientNode = createClientClass({ plugin, symbol: symbolClient }); + dependencies.push(clientNode); + const symbolRegistry = plugin.symbol('HeyApiRegistry', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiRegistry', + tool: 'sdk', + }, + }); + const registryNode = createRegistryClass({ + plugin, + sdkSymbol: symbolClass, + symbol: symbolRegistry, + }); + dependencies.push(registryNode); + node.field('__registry', (f) => + f + .public() + .static() + .readonly() + .assign($.new(symbolRegistry).generic(symbolClass)), + ); + node.newline(); + + const symClient = plugin.getSymbol({ category: 'client' }); + const isClientRequired = !plugin.config.client || !symClient; + const symbolClientType = plugin.referenceSymbol({ + category: 'external', + resource: 'client.Client', + }); + node.init((i) => + i + .param('args', (p) => + p.required(isClientRequired).type( + $.type + .object() + .prop('client', (p) => + p.required(isClientRequired).type(symbolClientType), + ) + .prop('key', (p) => p.optional().type('string')), + ), + ) + .do( + $('super').call('args'), + $(symbolClass) + .attr('__registry') + .attr('set') + .call('this', $('args').attr('key').required(isClientRequired)), + ), + ); + } + + this.operations.forEach((operation, index) => { + if (index > 0 || node.hasBody) node.newline(); + const symbolMethod = plugin.symbol( + operationMethodName({ + operation, + plugin, + value: + plugin.config.classStructure === 'auto' && operation.operationId + ? toCase(operation.operationId.split(/[./]/).pop()!, 'camelCase') + : operation.id, + }), + ); + const isRequiredOptions = isOperationOptionsRequired({ + context: plugin.context, + operation, + }); + const opParameters = operationParameters({ + isRequiredOptions, + operation, + plugin, + }); + const statements = operationStatements({ + isRequiredOptions, + opParameters, + operation, + plugin, + }); + node.method(symbolMethod, (m) => + m + .$if(createOperationComment(operation), (m, v) => m.doc(v)) + .public() + .static(!isAngularClient && !plugin.config.instance) + .$if( + isNuxtClient, + (m) => + m + .generic(nuxtTypeComposable, (t) => + t + .extends( + plugin.referenceSymbol({ + category: 'external', + resource: 'client.Composable', + }), + ) + .default($.type.literal('$fetch')), + ) + .generic(nuxtTypeDefault, (t) => + t.$if( + plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'response', + }), + (t, s) => t.extends(s).default(s), + ), + ), + (m) => + m.generic('ThrowOnError', (t) => + t + .extends('boolean') + .default( + ('throwOnError' in client.config + ? client.config.throwOnError + : false) ?? false, + ), + ), + ) + .params(...opParameters.parameters) + .do(...statements), + ); + }); + + for (const child of this.children.values()) { + if (node.hasBody) node.newline(); + const refChild = plugin.referenceSymbol({ + category: 'utility', + resource: 'class', + resourceId: child.name, + tool: 'sdk', + }); + const memberName = toCase(refChild.name, 'camelCase'); + const privateName = plugin.symbol(`_${memberName}`); + const getterName = plugin.symbol(memberName); + node.field(privateName, (f) => f.private().optional().type(refChild)); + node.do( + $.getter(getterName, (g) => + g.returns(refChild).do( + $('this') + .attr(privateName) + .nullishAssign( + $.new(refChild).args( + $.object().prop('client', $('this').attr('client')), + ), + ) + .return(), + ), + ), + ); + } + + return { dependencies, node }; + } + + /** + * Recursively walks the tree depth-first. + * + * Yields this node, then all descendants. + */ + *walk(): Generator { + for (const child of this.children.values()) { + yield* child.walk(); + } + yield this; + } +} diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts index a575fa769..967d8dbfa 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts @@ -7,8 +7,9 @@ import { } from '~/plugins/shared/utils/operation'; import type { TsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; -import { stringCase } from '~/utils/stringCase'; +import { toCase } from '~/utils/to-case'; +import { SdkClassModel } from '../model/class'; import type { HeyApiSdkPlugin } from '../types'; import { nuxtTypeComposable, nuxtTypeDefault } from './constants'; import { @@ -46,7 +47,7 @@ type SdkClassEntry = { export const registryName = '__registry'; -const createRegistryClass = ({ +export const createRegistryClass = ({ plugin, sdkSymbol, symbol, @@ -54,7 +55,7 @@ const createRegistryClass = ({ plugin: HeyApiSdkPlugin['Instance']; sdkSymbol: Symbol; symbol: Symbol; -}): TsDsl => { +}): ReturnType => { const symbolDefaultKey = plugin.symbol('defaultKey'); const symbolInstances = plugin.symbol('instances'); return $.class(symbol) @@ -107,16 +108,14 @@ const createRegistryClass = ({ ); }; -const createClientClass = ({ +export const createClientClass = ({ plugin, symbol, }: { plugin: HeyApiSdkPlugin['Instance']; symbol: Symbol; -}): TsDsl => { - const symClient = plugin.getSymbol({ - category: 'client', - }); +}): ReturnType => { + const symClient = plugin.getSymbol({ category: 'client' }); const optionalClient = Boolean(plugin.config.client && symClient); const symbolClient = plugin.referenceSymbol({ category: 'external', @@ -165,133 +164,146 @@ export const generateClassSdk = ({ */ const generatedClasses = new Set(); + const sdkModel = plugin.config.instance + ? new SdkClassModel(plugin.config.instance) + : undefined; + plugin.forEach( 'operation', ({ operation }) => { - const isRequiredOptions = isOperationOptionsRequired({ - context: plugin.context, - operation, - }); - const symbolResponse = isNuxtClient - ? plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'response', - }) - : undefined; - - const classes = operationClasses({ operation, plugin }); - - for (const entry of classes.values()) { - entry.path.forEach((currentClassName, index) => { - const symbolCurrentClass = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: currentClassName, - tool: 'sdk', - }); - if (!sdkClasses.has(symbolCurrentClass.meta!.resourceId!)) { - sdkClasses.set(symbolCurrentClass.meta!.resourceId!, { - className: symbolCurrentClass.meta!.resourceId!, - classes: new Set(), - id: symbolCurrentClass.id, - methods: new Set(), - nodes: [], - root: !index, - }); - } - - const parentClassName = entry.path[index - 1]; - if (parentClassName) { - const symbolParentClass = plugin.referenceSymbol({ + if (sdkModel) { + sdkModel.insert(operation, plugin); + } else { + const isRequiredOptions = isOperationOptionsRequired({ + context: plugin.context, + operation, + }); + const symbolResponse = isNuxtClient + ? plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'response', + }) + : undefined; + + const classes = operationClasses({ operation, plugin }); + + for (const entry of classes.values()) { + entry.path.forEach((currentClassName, index) => { + const symbolCurrentClass = plugin.referenceSymbol({ category: 'utility', resource: 'class', - resourceId: parentClassName, + resourceId: currentClassName, tool: 'sdk', }); - if ( - symbolParentClass.meta?.resourceId !== - symbolCurrentClass.meta?.resourceId - ) { - const parentClass = sdkClasses.get( - symbolParentClass.meta!.resourceId!, - )!; - parentClass.classes.add(symbolCurrentClass.meta!.resourceId!); - sdkClasses.set(symbolParentClass.meta!.resourceId!, parentClass); + if (!sdkClasses.has(symbolCurrentClass.meta!.resourceId!)) { + sdkClasses.set(symbolCurrentClass.meta!.resourceId!, { + className: symbolCurrentClass.meta!.resourceId!, + classes: new Set(), + id: symbolCurrentClass.id, + methods: new Set(), + nodes: [], + root: !index, + }); } - } - const isLast = entry.path.length === index + 1; - // add methods only to the last class - if (!isLast) { - return; - } + const parentClassName = entry.path[index - 1]; + if (parentClassName) { + const symbolParentClass = plugin.referenceSymbol({ + category: 'utility', + resource: 'class', + resourceId: parentClassName, + tool: 'sdk', + }); + if ( + symbolParentClass.meta?.resourceId !== + symbolCurrentClass.meta?.resourceId + ) { + const parentClass = sdkClasses.get( + symbolParentClass.meta!.resourceId!, + )!; + parentClass.classes.add(symbolCurrentClass.meta!.resourceId!); + sdkClasses.set( + symbolParentClass.meta!.resourceId!, + parentClass, + ); + } + } - const currentClass = sdkClasses.get( - symbolCurrentClass.meta!.resourceId!, - )!; + const isLast = entry.path.length === index + 1; + // add methods only to the last class + if (!isLast) { + return; + } - const methodName = entry.methodName; - if (currentClass.methods.has(methodName)) return; - currentClass.methods.add(methodName); + const currentClass = sdkClasses.get( + symbolCurrentClass.meta!.resourceId!, + )!; - const opParameters = operationParameters({ - isRequiredOptions, - operation, - plugin, - }); - const statements = operationStatements({ - isRequiredOptions, - opParameters, - operation, - plugin, - }); - const functionNode = $.method(methodName, (m) => - m - .$if(createOperationComment(operation), (m, v) => m.doc(v)) - .public() - .static(!isAngularClient && !plugin.config.instance) - .$if( - isNuxtClient, - (m) => - m - .generic(nuxtTypeComposable, (t) => + const methodName = entry.methodName; + if (currentClass.methods.has(methodName)) return; + currentClass.methods.add(methodName); + + const opParameters = operationParameters({ + isRequiredOptions, + operation, + plugin, + }); + const statements = operationStatements({ + isRequiredOptions, + opParameters, + operation, + plugin, + }); + const functionNode = $.method(methodName, (m) => + m + .$if(createOperationComment(operation), (m, v) => m.doc(v)) + .public() + .static(!isAngularClient && !plugin.config.instance) + .$if( + isNuxtClient, + (m) => + m + .generic(nuxtTypeComposable, (t) => + t + .extends( + plugin.referenceSymbol({ + category: 'external', + resource: 'client.Composable', + }), + ) + .default($.type.literal('$fetch')), + ) + .generic(nuxtTypeDefault, (t) => + t.$if(symbolResponse, (t, s) => + t.extends(s).default(s), + ), + ), + (m) => + m.generic('ThrowOnError', (t) => t - .extends( - plugin.referenceSymbol({ - category: 'external', - resource: 'client.Composable', - }), - ) - .default($.type.literal('$fetch')), - ) - .generic(nuxtTypeDefault, (t) => - t.$if(symbolResponse, (t, s) => t.extends(s).default(s)), + .extends('boolean') + .default( + ('throwOnError' in client.config + ? client.config.throwOnError + : false) ?? false, + ), ), - (m) => - m.generic('ThrowOnError', (t) => - t - .extends('boolean') - .default( - ('throwOnError' in client.config - ? client.config.throwOnError - : false) ?? false, - ), - ), - ) - .params(...opParameters.parameters) - .do(...statements), - ); + ) + .params(...opParameters.parameters) + .do(...statements), + ); - if (!currentClass.nodes.length) { - currentClass.nodes.push(functionNode); - } else { - currentClass.nodes.push($.newline(), functionNode); - } + if (!currentClass.nodes.length) { + currentClass.nodes.push(functionNode); + } else { + currentClass.nodes.push($.newline(), functionNode); + } - sdkClasses.set(symbolCurrentClass.meta!.resourceId!, currentClass); - }); + sdkClasses.set(symbolCurrentClass.meta!.resourceId!, currentClass); + }); + } } }, { @@ -299,177 +311,202 @@ export const generateClassSdk = ({ }, ); - const clientIndex = plugin.config.instance ? plugin.node(null) : undefined; - const symbolClient = - clientIndex !== undefined - ? plugin.symbol('HeyApiClient', { - meta: { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiClient', - tool: 'sdk', - }, - }) + if (!sdkModel) { + const clientIndex = plugin.config.instance ? plugin.node(null) : undefined; + const symbolClient = + clientIndex !== undefined + ? plugin.symbol('HeyApiClient', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiClient', + tool: 'sdk', + }, + }) + : undefined; + const registryIndex = plugin.config.instance + ? plugin.node(null) : undefined; - const registryIndex = plugin.config.instance ? plugin.node(null) : undefined; - const generateClass = (currentClass: SdkClassEntry) => { - const resourceId = currentClass.className; + const generateClass = (currentClass: SdkClassEntry) => { + const resourceId = currentClass.className; - if (generatedClasses.has(resourceId)) return; - generatedClasses.add(resourceId); + if (generatedClasses.has(resourceId)) return; + generatedClasses.add(resourceId); - if (clientIndex !== undefined && symbolClient && !symbolClient.node) { - const node = createClientClass({ plugin, symbol: symbolClient }); - plugin.node(node, clientIndex); - } + if (clientIndex !== undefined && symbolClient && !symbolClient.node) { + const node = createClientClass({ plugin, symbol: symbolClient }); + plugin.node(node, clientIndex); + } - for (const childClassName of currentClass.classes) { - const childClass = sdkClasses.get(childClassName)!; - generateClass(childClass); + for (const childClassName of currentClass.classes) { + const childClass = sdkClasses.get(childClassName)!; + generateClass(childClass); - const refChildClass = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: childClass.className, - tool: 'sdk', - }); + const refChildClass = plugin.referenceSymbol({ + category: 'utility', + resource: 'class', + resourceId: childClass.className, + tool: 'sdk', + }); - const originalMemberName = stringCase({ - case: 'camelCase', - value: refChildClass.meta!.resourceId!, - }); - // avoid collisions with existing method names - let memberName = originalMemberName; - if (currentClass.methods.has(memberName)) { - let index = 2; - let attempt = `${memberName}${index}`; - while (currentClass.methods.has(attempt)) { - attempt = `${memberName}${index++}`; + const originalMemberName = toCase( + refChildClass.meta!.resourceId!, + 'camelCase', + ); + // avoid collisions with existing method names + let memberName = originalMemberName; + if (currentClass.methods.has(memberName)) { + let index = 2; + let attempt = `${memberName}${index}`; + while (currentClass.methods.has(attempt)) { + attempt = `${memberName}${index++}`; + } + memberName = attempt; } - memberName = attempt; - } - currentClass.methods.add(memberName); + currentClass.methods.add(memberName); - if (currentClass.nodes.length > 0) { - currentClass.nodes.push($.newline()); - } - - if (plugin.config.instance) { - const privateName = plugin.symbol(`_${memberName}`); - const privateNode = $.field(privateName, (f) => - f.private().optional().type(refChildClass), - ); - currentClass.nodes.push(privateNode); - const getterNode = $.getter(memberName, (g) => - g.returns(refChildClass).do( - $('this') - .attr(privateName) - .nullishAssign( - $.new(refChildClass).args( - $.object().prop('client', $('this').attr('client')), - ), - ) - .return(), - ), - ); - currentClass.nodes.push(getterNode); - } else { - const subClassReferenceNode = plugin.isSymbolRegistered( - refChildClass.id, - ) - ? $.field(memberName, (f) => f.static().assign($(refChildClass))) - : $.getter(memberName, (g) => - g.public().static().do($.return(refChildClass)), - ); - currentClass.nodes.push(subClassReferenceNode); - } - } + if (currentClass.nodes.length > 0) { + currentClass.nodes.push($.newline()); + } - const symbol = plugin.symbol(resourceId, { - meta: { - category: 'utility', - resource: 'class', - resourceId, - tool: 'sdk', - }, - }); - - if (currentClass.root && registryIndex !== undefined) { - const symClient = plugin.getSymbol({ category: 'client' }); - const isClientRequired = !plugin.config.client || !symClient; - const symbolClient = plugin.referenceSymbol({ - category: 'external', - resource: 'client.Client', - }); - const ctor = $.init((i) => - i - .param('args', (p) => - p.required(isClientRequired).type( - $.type - .object() - .prop('client', (p) => - p.required(isClientRequired).type(symbolClient), + if (plugin.config.instance) { + const privateName = plugin.symbol(`_${memberName}`); + const privateNode = $.field(privateName, (f) => + f.private().optional().type(refChildClass), + ); + currentClass.nodes.push(privateNode); + const getterNode = $.getter(memberName, (g) => + g.returns(refChildClass).do( + $('this') + .attr(privateName) + .nullishAssign( + $.new(refChildClass).args( + $.object().prop('client', $('this').attr('client')), + ), ) - .prop('key', (p) => p.optional().type('string')), + .return(), ), + ); + currentClass.nodes.push(getterNode); + } else { + const subClassReferenceNode = plugin.isSymbolRegistered( + refChildClass.id, ) - .do( - $('super').call('args'), - $(symbol) - .attr(registryName) - .attr('set') - .call('this', $('args').attr('key').required(isClientRequired)), - ), - ); - - if (!currentClass.nodes.length) { - currentClass.nodes.unshift(ctor); - } else { - currentClass.nodes.unshift(ctor, $.newline()); + ? $.field(memberName, (f) => f.static().assign($(refChildClass))) + : $.getter(memberName, (g) => + g.public().static().do($.return(refChildClass)), + ); + currentClass.nodes.push(subClassReferenceNode); + } } - const symbolRegistry = plugin.symbol('HeyApiRegistry', { + const symbol = plugin.symbol(resourceId, { meta: { category: 'utility', resource: 'class', - resourceId: 'HeyApiRegistry', + resourceId, tool: 'sdk', }, }); - const node = createRegistryClass({ - plugin, - sdkSymbol: symbol, - symbol: symbolRegistry, - }); - plugin.node(node, registryIndex); - const registryNode = $.field(registryName, (f) => - f - .public() - .static() - .readonly() - .assign($.new(symbolRegistry).generic(symbol)), - ); - currentClass.nodes.unshift(registryNode, $.newline()); + + if (currentClass.root && registryIndex !== undefined) { + const symClient = plugin.getSymbol({ category: 'client' }); + const isClientRequired = !plugin.config.client || !symClient; + const symbolClient = plugin.referenceSymbol({ + category: 'external', + resource: 'client.Client', + }); + const ctor = $.init((i) => + i + .param('args', (p) => + p.required(isClientRequired).type( + $.type + .object() + .prop('client', (p) => + p.required(isClientRequired).type(symbolClient), + ) + .prop('key', (p) => p.optional().type('string')), + ), + ) + .do( + $('super').call('args'), + $(symbol) + .attr(registryName) + .attr('set') + .call('this', $('args').attr('key').required(isClientRequired)), + ), + ); + + if (!currentClass.nodes.length) { + currentClass.nodes.unshift(ctor); + } else { + currentClass.nodes.unshift(ctor, $.newline()); + } + + const symbolRegistry = plugin.symbol('HeyApiRegistry', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiRegistry', + tool: 'sdk', + }, + }); + const node = createRegistryClass({ + plugin, + sdkSymbol: symbol, + symbol: symbolRegistry, + }); + plugin.node(node, registryIndex); + const registryNode = $.field(registryName, (f) => + f + .public() + .static() + .readonly() + .assign($.new(symbolRegistry).generic(symbol)), + ); + currentClass.nodes.unshift(registryNode, $.newline()); + } + + const node = $.class(symbol) + .export() + .extends(symbolClient) + .$if(isAngularClient && currentClass.root, (c) => + c.decorator( + plugin.referenceSymbol({ + category: 'external', + resource: '@angular/core.Injectable', + }), + $.object().prop('providedIn', $.literal('root')), + ), + ) + .do(...currentClass.nodes); + plugin.node(node); + }; + + for (const sdkClass of sdkClasses.values()) { + generateClass(sdkClass); + } + } else { + const allDependencies: Array> = []; + const allNodes: Array> = []; + + for (const model of sdkModel.walk()) { + const { dependencies, node } = model.toNode(plugin); + allDependencies.push(...dependencies); + allNodes.push(node); } - const node = $.class(symbol) - .export() - .extends(symbolClient) - .$if(isAngularClient && currentClass.root, (c) => - c.decorator( - plugin.referenceSymbol({ - category: 'external', - resource: '@angular/core.Injectable', - }), - $.object().prop('providedIn', $.literal('root')), - ), - ) - .do(...currentClass.nodes); - plugin.node(node); - }; + const uniqueDeps = new Map>(); + for (const dep of allDependencies) { + if (dep.symbol) uniqueDeps.set(dep.symbol.id, dep); + } + for (const dep of uniqueDeps.values()) { + plugin.node(dep); + } - for (const sdkClass of sdkClasses.values()) { - generateClass(sdkClass); + for (const node of allNodes) { + plugin.node(node); + } } }; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts index c3fc799b9..1d35d73bc 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts @@ -6,7 +6,7 @@ import type { IR } from '~/ir/types'; import { sanitizeNamespaceIdentifier } from '~/openApi/common/parser/sanitize'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; import { $ } from '~/ts-dsl'; -import { stringCase } from '~/utils/stringCase'; +import { toCase } from '~/utils/to-case'; import type { Field, Fields } from '../../client-core/bundle/params'; import type { HeyApiSdkPlugin } from '../types'; @@ -30,14 +30,15 @@ interface ClassNameEntry { path: ReadonlyArray; } -const operationClassName = ({ +export const operationClassName = ({ plugin, value, }: { plugin: HeyApiSdkPlugin['Instance']; value: string; }) => { - const name = stringCase({ case: 'PascalCase', value }); + // TODO: expose casing option + const name = toCase(value, 'PascalCase'); return ( (typeof plugin.config.classNameBuilder === 'string' ? plugin.config.classNameBuilder.replace('{{name}}', name) @@ -48,10 +49,20 @@ const operationClassName = ({ export const operationMethodName = ({ operation, plugin, + value, }: { operation: IR.OperationObject; plugin: HeyApiSdkPlugin['Instance']; -}) => plugin.config.methodNameBuilder?.(operation) || operation.id; + value?: string; +}) => { + // TODO: expose casing option + const name = toCase(value || operation.id, 'camelCase'); + return ( + (typeof plugin.config.methodNameBuilder === 'string' + ? plugin.config.methodNameBuilder.replace('{{name}}', name) + : plugin.config.methodNameBuilder?.(name, operation)) || name + ); +}; /** * Returns a list of classes where this operation appears in the generated SDK. @@ -73,10 +84,10 @@ export const operationClasses = ({ classCandidates = operation.operationId.split(/[./]/).filter(Boolean); if (classCandidates.length >= 2) { const methodCandidate = classCandidates.pop()!; - methodName = stringCase({ - case: 'camelCase', - value: sanitizeNamespaceIdentifier(methodCandidate), - }); + methodName = toCase( + sanitizeNamespaceIdentifier(methodCandidate), + 'camelCase', + ); className = classCandidates.pop()!; } } diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/signature.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/signature.ts index cbd7f7a68..bf11fc7b7 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/signature.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/signature.ts @@ -1,7 +1,7 @@ import type { IR } from '~/ir/types'; import type { PluginInstance } from '~/plugins/shared/utils/instance'; import { refToName } from '~/utils/ref'; -import { stringCase } from '~/utils/stringCase'; +import { toCase } from '~/utils/to-case'; import type { Field } from '../../client-core/bundle/params'; @@ -83,7 +83,7 @@ export const getSignatureParameters = ({ } else if (operation.body.schema.$ref) { // alias body for more ergonomic naming, e.g. user if the type is User const name = refToName(operation.body.schema.$ref); - const key = stringCase({ case: 'camelCase', value: name }); + const key = toCase(name, 'camelCase'); addParameter(key, 'body'); } else { addParameter('body', 'body'); @@ -157,7 +157,7 @@ export const getSignatureParameters = ({ } } else if (operation.body.schema.$ref) { const value = refToName(operation.body.schema.$ref); - const originalName = stringCase({ case: 'camelCase', value }); + const originalName = toCase(value, 'camelCase'); const name = conflicts.has(originalName) ? `${location}_${originalName}` : originalName; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts index c0b39fa84..b947f5b72 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts @@ -75,9 +75,11 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & instance?: string | boolean; /** * Customise the name of methods within the service. By default, - * {@link IR.OperationObject.id} is used. + * `operation.id` is used. */ - methodNameBuilder?: (operation: IR.OperationObject) => string; + methodNameBuilder?: + | string + | ((name: string, operation: IR.OperationObject) => string); // TODO: parser - rename operationId option to something like inferId?: boolean /** * Use operation ID to generate operation names? @@ -252,9 +254,11 @@ export type Config = Plugin.Name<'@hey-api/sdk'> & instance: string; /** * Customise the name of methods within the service. By default, - * {@link IR.OperationObject.id} is used. + * `operation.id` is used. */ - methodNameBuilder?: (operation: IR.OperationObject) => string; + methodNameBuilder: + | string + | ((name: string, operation: IR.OperationObject) => string); // TODO: parser - rename operationId option to something like inferId?: boolean /** * Use operation ID to generate operation names? diff --git a/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/export.ts b/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/export.ts index d43096065..986488b99 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/export.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/export.ts @@ -6,7 +6,7 @@ import { createSchemaComment } from '~/plugins/shared/utils/schema'; import type { MaybeTsDsl, TypeTsDsl } from '~/ts-dsl'; import { $, regexp } from '~/ts-dsl'; import { pathToJsonPointer, refToName } from '~/utils/ref'; -import { stringCase } from '~/utils/stringCase'; +import { toCase } from '~/utils/to-case'; import type { HeyApiTypeScriptPlugin } from '../types'; import type { IrSchemaToAstOptions } from './types'; @@ -52,10 +52,8 @@ const schemaToEnumObject = ({ } if (key) { - key = stringCase({ - case: plugin.config.enums.case, + key = toCase(key, plugin.config.enums.case, { stripLeadingSeparators: false, - value: key, }); regexp.number.lastIndex = 0; diff --git a/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/toAst/string.ts b/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/toAst/string.ts index acaad7db4..132bd6193 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/toAst/string.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/toAst/string.ts @@ -3,7 +3,7 @@ import type { SymbolMeta } from '@hey-api/codegen-core'; import type { SchemaWithType } from '~/plugins'; import type { TypeTsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; -import { stringCase } from '~/utils/stringCase'; +import { toCase } from '~/utils/to-case'; import type { IrSchemaToAstOptions } from '../../shared/types'; @@ -66,10 +66,7 @@ export const stringToAst = ({ const symbolTypeId = plugin.referenceSymbol(queryTypeId); const symbolTypeName = plugin.registerSymbol({ meta: query, - name: stringCase({ - case: plugin.config.case, - value: `${type}_id`, - }), + name: toCase(`${type}_id`, plugin.config.case), }); const node = $.type .alias(symbolTypeName) diff --git a/packages/openapi-ts/src/plugins/@pinia/colada/v0/plugin.ts b/packages/openapi-ts/src/plugins/@pinia/colada/v0/plugin.ts index 34e44d61d..adb41fbb4 100644 --- a/packages/openapi-ts/src/plugins/@pinia/colada/v0/plugin.ts +++ b/packages/openapi-ts/src/plugins/@pinia/colada/v0/plugin.ts @@ -1,7 +1,7 @@ import { registryName } from '~/plugins/@hey-api/sdk/shared/class'; import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; import { $ } from '~/ts-dsl'; -import { stringCase } from '~/utils/stringCase'; +import { toCase } from '~/utils/to-case'; import { createMutationOptions } from '../mutationOptions'; import { createQueryOptions } from '../queryOptions'; @@ -76,10 +76,7 @@ export const handlerV0: PiniaColadaPlugin['Handler'] = ({ plugin }) => { e.attr(registryName).attr('get').call(), ); for (const className of entry.path.slice(1)) { - const cls = stringCase({ - case: 'camelCase', - value: className, - }); + const cls = toCase(className, 'camelCase'); queryFn = queryFn.attr(cls); } queryFn = queryFn.attr(entry.methodName); diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/plugin.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/plugin.ts index 7619e0243..601eefdb3 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/plugin.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/plugin.ts @@ -1,7 +1,7 @@ import { registryName } from '~/plugins/@hey-api/sdk/shared/class'; import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; import { $ } from '~/ts-dsl'; -import { stringCase } from '~/utils/stringCase'; +import { toCase } from '~/utils/to-case'; import type { PluginHandler } from '../types'; import { createInfiniteQueryOptions } from './infiniteQueryOptions'; @@ -100,10 +100,7 @@ export const handlerV5: PluginHandler = ({ plugin }) => { e.attr(registryName).attr('get').call(), ); for (const className of entry.path.slice(1)) { - const cls = stringCase({ - case: 'camelCase', - value: className, - }); + const cls = toCase(className, 'camelCase'); queryFn = queryFn.attr(cls); } queryFn = queryFn.attr(entry.methodName); diff --git a/packages/openapi-ts/src/plugins/swr/v2/plugin.ts b/packages/openapi-ts/src/plugins/swr/v2/plugin.ts index f949256cf..65754a523 100644 --- a/packages/openapi-ts/src/plugins/swr/v2/plugin.ts +++ b/packages/openapi-ts/src/plugins/swr/v2/plugin.ts @@ -1,7 +1,7 @@ import { registryName } from '~/plugins/@hey-api/sdk/shared/class'; import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; import { $ } from '~/ts-dsl'; -import { stringCase } from '~/utils/stringCase'; +import { toCase } from '~/utils/to-case'; import type { SwrPlugin } from '../types'; import { createUseSwr } from './useSwr'; @@ -41,10 +41,7 @@ export const handlerV2: SwrPlugin['Handler'] = ({ plugin }) => { e.attr(registryName).attr('get').call(), ); for (const className of entry.path.slice(1)) { - const cls = stringCase({ - case: 'camelCase', - value: className, - }); + const cls = toCase(className, 'camelCase'); queryFn = queryFn.attr(cls); } queryFn = queryFn.attr(entry.methodName); diff --git a/packages/openapi-ts/src/ts-dsl/base.ts b/packages/openapi-ts/src/ts-dsl/base.ts index c6f1aab6e..ebe29d37a 100644 --- a/packages/openapi-ts/src/ts-dsl/base.ts +++ b/packages/openapi-ts/src/ts-dsl/base.ts @@ -135,10 +135,10 @@ export abstract class TsDsl implements Node { if (value instanceof Array) { return value.map((item) => { if (isRef(item)) item = fromRef(item); - return this.unwrap(item, ctx); + return this.unwrap(ctx, item); }) as NodeOfMaybe; } - return this.unwrap(value as any, ctx) as NodeOfMaybe; + return this.unwrap(ctx, value as any) as NodeOfMaybe; } protected $type( @@ -174,13 +174,13 @@ export abstract class TsDsl implements Node { if (value instanceof Array) { return value.map((item) => this.$type(ctx, item, args)) as TypeOfMaybe; } - return this.unwrap(value as any, ctx) as TypeOfMaybe; + return this.unwrap(ctx, value as any) as TypeOfMaybe; } /** Unwraps nested nodes into raw TypeScript AST. */ private unwrap( - value: I, ctx: AstContext, + value: I, ): I extends TsDsl ? N : I { return (isNode(value) ? value.toAst(ctx) : value) as I extends TsDsl< infer N diff --git a/packages/openapi-ts/src/ts-dsl/decl/class.ts b/packages/openapi-ts/src/ts-dsl/decl/class.ts index 2100cfe09..5975bdce2 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/class.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/class.ts @@ -18,6 +18,7 @@ import { safeRuntimeName } from '../utils/name'; import type { FieldName } from './field'; import { FieldTsDsl } from './field'; import { InitTsDsl } from './init'; +import type { MethodName } from './method'; import { MethodTsDsl } from './method'; type Base = Symbol | string; @@ -63,6 +64,11 @@ export class ClassTsDsl extends Mixed { } } + /** Returns true if the class has any members. */ + get hasBody(): boolean { + return this.body.length > 0; + } + /** Adds one or more class members (fields, methods, etc.). */ do(...items: Body): this { this.body.push(...items); @@ -83,14 +89,15 @@ export class ClassTsDsl extends Mixed { } /** Adds a class constructor. */ - init(fn?: (i: InitTsDsl) => void): this { - const i = new InitTsDsl(fn); + init(fn?: InitTsDsl | ((i: InitTsDsl) => void)): this { + const i = + typeof fn === 'function' ? new InitTsDsl(fn) : fn || new InitTsDsl(); this.body.push(i); return this; } /** Adds a class method. */ - method(name: string, fn?: (m: MethodTsDsl) => void): this { + method(name: MethodName, fn?: (m: MethodTsDsl) => void): this { const m = new MethodTsDsl(name, fn); this.body.push(m); return this; diff --git a/packages/openapi-ts/src/ts-dsl/decl/field.ts b/packages/openapi-ts/src/ts-dsl/decl/field.ts index 73f8d00d6..550df0ec3 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/field.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/field.ts @@ -1,8 +1,10 @@ import type { AnalysisContext, AstContext, + Ref, Symbol, } from '@hey-api/codegen-core'; +import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl, TypeTsDsl } from '../base'; @@ -43,17 +45,18 @@ const Mixed = DecoratorMixin( export class FieldTsDsl extends Mixed { readonly '~dsl' = 'FieldTsDsl'; - protected name: FieldName; + protected name: Ref; protected _type?: TypeTsDsl; constructor(name: FieldName, fn?: (f: FieldTsDsl) => void) { super(); - this.name = name; + this.name = ref(name); fn?.(this); } override analyze(ctx: AnalysisContext): void { super.analyze(ctx); + ctx.analyze(this.name); ctx.analyze(this._type); } diff --git a/packages/openapi-ts/src/ts-dsl/decl/getter.ts b/packages/openapi-ts/src/ts-dsl/decl/getter.ts index 6ec55d14b..6905c0d3f 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/getter.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/getter.ts @@ -1,4 +1,10 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + Ref, + Symbol, +} from '@hey-api/codegen-core'; +import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -17,7 +23,7 @@ import { ParamMixin } from '../mixins/param'; import { TypeReturnsMixin } from '../mixins/type-returns'; import { BlockTsDsl } from '../stmt/block'; -export type GetterName = string | ts.PropertyName; +export type GetterName = Symbol | string | ts.PropertyName; const Mixed = AbstractMixin( AsyncMixin( @@ -44,15 +50,17 @@ const Mixed = AbstractMixin( export class GetterTsDsl extends Mixed { readonly '~dsl' = 'GetterTsDsl'; - protected name: GetterName; + protected name: Ref; constructor(name: GetterName, fn?: (g: GetterTsDsl) => void) { super(); - this.name = name; + this.name = ref(name); fn?.(this); } override analyze(ctx: AnalysisContext): void { + ctx.analyze(this.name); + ctx.pushScope(); try { super.analyze(ctx); @@ -64,7 +72,7 @@ export class GetterTsDsl extends Mixed { override toAst(ctx: AstContext) { const node = ts.factory.createGetAccessorDeclaration( [...this.$decorators(ctx), ...this.modifiers], - this.name, + this.$node(ctx, this.name) as ts.PropertyName, this.$params(ctx), this.$returns(ctx), this.$node(ctx, new BlockTsDsl(...this._do).pretty()), diff --git a/packages/openapi-ts/src/ts-dsl/decl/method.ts b/packages/openapi-ts/src/ts-dsl/decl/method.ts index e21d1ca97..e3d811f00 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/method.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/method.ts @@ -1,4 +1,10 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + Ref, + Symbol, +} from '@hey-api/codegen-core'; +import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -20,6 +26,8 @@ import { TypeReturnsMixin } from '../mixins/type-returns'; import { BlockTsDsl } from '../stmt/block'; import { TokenTsDsl } from '../token'; +export type MethodName = Symbol | string; + const Mixed = AbstractMixin( AsyncMixin( DecoratorMixin( @@ -49,15 +57,17 @@ const Mixed = AbstractMixin( export class MethodTsDsl extends Mixed { readonly '~dsl' = 'MethodTsDsl'; - protected name: string; + protected name: Ref; - constructor(name: string, fn?: (m: MethodTsDsl) => void) { + constructor(name: MethodName, fn?: (m: MethodTsDsl) => void) { super(); - this.name = name; + this.name = ref(name); fn?.(this); } override analyze(ctx: AnalysisContext): void { + ctx.analyze(this.name); + ctx.pushScope(); try { super.analyze(ctx); @@ -70,7 +80,7 @@ export class MethodTsDsl extends Mixed { const node = ts.factory.createMethodDeclaration( [...this.$decorators(ctx), ...this.modifiers], undefined, - this.name, + this.$node(ctx, this.name) as ts.PropertyName, this._optional ? this.$node(ctx, new TokenTsDsl().optional()) : undefined, this.$generics(ctx), this.$params(ctx), diff --git a/packages/openapi-ts/src/ts-dsl/decl/setter.ts b/packages/openapi-ts/src/ts-dsl/decl/setter.ts index 6b7f82feb..0f87c3918 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/setter.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/setter.ts @@ -1,4 +1,10 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + Ref, + Symbol, +} from '@hey-api/codegen-core'; +import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -16,7 +22,7 @@ import { import { ParamMixin } from '../mixins/param'; import { BlockTsDsl } from '../stmt/block'; -export type SetterName = string | ts.PropertyName; +export type SetterName = Symbol | string | ts.PropertyName; const Mixed = AbstractMixin( AsyncMixin( @@ -39,15 +45,17 @@ const Mixed = AbstractMixin( export class SetterTsDsl extends Mixed { readonly '~dsl' = 'SetterTsDsl'; - protected name: SetterName; + protected name: Ref; constructor(name: SetterName, fn?: (s: SetterTsDsl) => void) { super(); - this.name = name; + this.name = ref(name); fn?.(this); } override analyze(ctx: AnalysisContext): void { + ctx.analyze(this.name); + ctx.pushScope(); try { super.analyze(ctx); @@ -59,7 +67,7 @@ export class SetterTsDsl extends Mixed { override toAst(ctx: AstContext) { const node = ts.factory.createSetAccessorDeclaration( [...this.$decorators(ctx), ...this.modifiers], - this.name, + this.$node(ctx, this.name) as ts.PropertyName, this.$params(ctx), this.$node(ctx, new BlockTsDsl(...this._do).pretty()), ); diff --git a/packages/openapi-ts/src/utils/__tests__/stringCase.test.ts b/packages/openapi-ts/src/utils/__tests__/to-case.test.ts similarity index 89% rename from packages/openapi-ts/src/utils/__tests__/stringCase.test.ts rename to packages/openapi-ts/src/utils/__tests__/to-case.test.ts index 806c044ca..ffaca396f 100644 --- a/packages/openapi-ts/src/utils/__tests__/stringCase.test.ts +++ b/packages/openapi-ts/src/utils/__tests__/to-case.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest'; import type { StringCase } from '~/types/case'; -import { stringCase } from '../stringCase'; +import { toCase } from '../to-case'; const cases: ReadonlyArray = [ 'camelCase', @@ -178,16 +178,16 @@ const scenarios: ReadonlyArray<{ }, ]; -describe('stringCase', () => { - describe.each(cases)('%s', (style) => { - switch (style) { +describe('toCase', () => { + describe.each(cases)('%s', (casing) => { + switch (casing) { case 'PascalCase': it.each(scenarios)( '$value -> $PascalCase', ({ PascalCase, stripLeadingSeparators, value }) => { - expect( - stringCase({ case: style, stripLeadingSeparators, value }), - ).toBe(PascalCase); + expect(toCase(value, casing, { stripLeadingSeparators })).toBe( + PascalCase, + ); }, ); break; @@ -195,9 +195,9 @@ describe('stringCase', () => { it.each(scenarios)( '$value -> $camelCase', ({ camelCase, stripLeadingSeparators, value }) => { - expect( - stringCase({ case: style, stripLeadingSeparators, value }), - ).toBe(camelCase); + expect(toCase(value, casing, { stripLeadingSeparators })).toBe( + camelCase, + ); }, ); break; @@ -205,9 +205,9 @@ describe('stringCase', () => { it.each(scenarios)( '$value -> $SCREAMING_SNAKE_CASE', ({ SCREAMING_SNAKE_CASE, stripLeadingSeparators, value }) => { - expect( - stringCase({ case: style, stripLeadingSeparators, value }), - ).toBe(SCREAMING_SNAKE_CASE); + expect(toCase(value, casing, { stripLeadingSeparators })).toBe( + SCREAMING_SNAKE_CASE, + ); }, ); break; @@ -215,9 +215,9 @@ describe('stringCase', () => { it.each(scenarios)( '$value -> $snake_case', ({ snake_case, stripLeadingSeparators, value }) => { - expect( - stringCase({ case: style, stripLeadingSeparators, value }), - ).toBe(snake_case); + expect(toCase(value, casing, { stripLeadingSeparators })).toBe( + snake_case, + ); }, ); break; diff --git a/packages/openapi-ts/src/utils/exports.ts b/packages/openapi-ts/src/utils/exports.ts index e529c9363..4082989a5 100644 --- a/packages/openapi-ts/src/utils/exports.ts +++ b/packages/openapi-ts/src/utils/exports.ts @@ -1,6 +1,31 @@ -import { stringCase } from './stringCase'; +import type { StringCase } from '~/types/case'; -// publicly exposed utils +import { toCase } from './to-case'; + +/** + * Utilities shared across the package. + */ export const utils = { - stringCase, + /** + * @deprecated use `toCase` instead + */ + stringCase({ + case: casing, + stripLeadingSeparators, + value, + }: { + readonly case: StringCase | undefined; + /** + * If leading separators have a semantic meaning, we might not want to + * remove them. + */ + stripLeadingSeparators?: boolean; + value: string; + }) { + return toCase(value, casing, { stripLeadingSeparators }); + }, + /** + * Converts the given string to the specified casing. + */ + toCase, }; diff --git a/packages/openapi-ts/src/utils/stringCase.ts b/packages/openapi-ts/src/utils/to-case.ts similarity index 72% rename from packages/openapi-ts/src/utils/stringCase.ts rename to packages/openapi-ts/src/utils/to-case.ts index 41f869e50..255fbc6e1 100644 --- a/packages/openapi-ts/src/utils/stringCase.ts +++ b/packages/openapi-ts/src/utils/to-case.ts @@ -3,7 +3,7 @@ import type { StringCase } from '~/types/case'; const uppercaseRegExp = /[\p{Lu}]/u; const lowercaseRegExp = /[\p{Ll}]/u; const identifierRegExp = /([\p{Alpha}\p{N}_]|$)/u; -const separatorsRegExp = /[_.:\- `\\[\]{}\\/]+/; +const separatorsRegExp = /[_.:\- `\\[\](){}\\/]+/; const leadingSeparatorsRegExp = new RegExp(`^${separatorsRegExp.source}`); const separatorsAndIdentifierRegExp = new RegExp( @@ -15,32 +15,25 @@ const numbersAndIdentifierRegExp = new RegExp( 'gu', ); -const preserveCase = ({ - case: _case, - string, -}: { - readonly case: StringCase; - string: string; -}) => { +const preserveCase = (value: string, casing: StringCase) => { let isLastCharLower = false; let isLastCharUpper = false; let isLastLastCharUpper = false; let isLastLastCharPreserved = false; const separator = - _case === 'snake_case' || _case === 'SCREAMING_SNAKE_CASE' ? '_' : '-'; + casing === 'snake_case' || casing === 'SCREAMING_SNAKE_CASE' ? '_' : '-'; - for (let index = 0; index < string.length; index++) { - const character = string[index]!; - isLastLastCharPreserved = - index > 2 ? string[index - 3] === separator : true; + for (let index = 0; index < value.length; index++) { + const character = value[index]!; + isLastLastCharPreserved = index > 2 ? value[index - 3] === separator : true; let nextIndex = index + 1; - let nextCharacter = string[nextIndex]; + let nextCharacter = value[nextIndex]; separatorsRegExp.lastIndex = 0; while (nextCharacter && separatorsRegExp.test(nextCharacter)) { nextIndex += 1; - nextCharacter = string[nextIndex]; + nextCharacter = value[nextIndex]; } const isSeparatorBeforeNextCharacter = nextIndex !== index + 1; @@ -55,7 +48,7 @@ const preserveCase = ({ lowercaseRegExp.test(nextCharacter))) ) { // insert separator behind character - string = `${string.slice(0, index)}${separator}${string.slice(index)}`; + value = `${value.slice(0, index)}${separator}${value.slice(index)}`; index++; isLastLastCharUpper = isLastCharUpper; isLastCharLower = false; @@ -72,7 +65,7 @@ const preserveCase = ({ ) ) { // insert separator 2 characters behind - string = `${string.slice(0, index - 1)}${separator}${string.slice(index - 1)}`; + value = `${value.slice(0, index - 1)}${separator}${value.slice(index - 1)}`; isLastLastCharUpper = isLastCharUpper; isLastCharLower = true; isLastCharUpper = false; @@ -87,29 +80,33 @@ const preserveCase = ({ } } - return string; + return value; }; -export const stringCase = ({ - case: _case, - stripLeadingSeparators = true, - value, -}: { - readonly case: StringCase | undefined; - /** - * If leading separators have a semantic meaning, we might not want to - * remove them. - */ - stripLeadingSeparators?: boolean; - value: string; -}): string => { - let result = value.trim(); +/** + * Converts the given string to the specified casing. + * + * @param value - The string to convert + * @param casing - The target casing + * @param options - Additional options + * @returns The converted string + */ +export const toCase = ( + value: string, + casing: StringCase | undefined, + options: { + /** + * If leading separators have a semantic meaning, we might not want to + * remove them. + */ + stripLeadingSeparators?: boolean; + } = {}, +) => { + const stripLeadingSeparators = options.stripLeadingSeparators ?? true; - if (!result.length) { - return ''; - } + let result = value.trim(); - if (!_case || _case === 'preserve') { + if (!result.length || !casing || casing === 'preserve') { return result; } @@ -119,7 +116,7 @@ export const stringCase = ({ return ''; } - return _case === 'PascalCase' || _case === 'SCREAMING_SNAKE_CASE' + return casing === 'PascalCase' || casing === 'SCREAMING_SNAKE_CASE' ? result.toLocaleUpperCase() : result.toLocaleLowerCase(); } @@ -127,7 +124,7 @@ export const stringCase = ({ const hasUpperCase = result !== result.toLocaleLowerCase(); if (hasUpperCase) { - result = preserveCase({ case: _case, string: result }); + result = preserveCase(result, casing); } if (stripLeadingSeparators || result[0] !== value[0]) { @@ -135,15 +132,15 @@ export const stringCase = ({ } result = - _case === 'SCREAMING_SNAKE_CASE' + casing === 'SCREAMING_SNAKE_CASE' ? result.toLocaleUpperCase() : result.toLocaleLowerCase(); - if (_case === 'PascalCase') { + if (casing === 'PascalCase') { result = `${result.charAt(0).toLocaleUpperCase()}${result.slice(1)}`; } - if (_case === 'snake_case' || _case === 'SCREAMING_SNAKE_CASE') { + if (casing === 'snake_case' || casing === 'SCREAMING_SNAKE_CASE') { result = result.replaceAll( separatorsAndIdentifierRegExp, (match, identifier, offset) => { -- 2.51.2 From 24db8ca787ddb8f73d31692724741d4a2283633d Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 16 Dec 2025 20:09:15 +0800 Subject: [PATCH 02/15] chore: port asClass functionality --- dev/openapi-ts.config.ts | 4 +- .../src/plugins/@hey-api/sdk/model/class.ts | 90 ++-- .../plugins/@hey-api/sdk/model/structure.ts | 59 +++ .../src/plugins/@hey-api/sdk/shared/class.ts | 404 +----------------- .../plugins/@hey-api/sdk/shared/operation.ts | 2 + 5 files changed, 139 insertions(+), 420 deletions(-) create mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index 3ead7e0ca..5694a7080 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -54,7 +54,7 @@ export default defineConfig(() => { // 'sdk-instance.yaml', // 'sdk-method-class-conflict.yaml', // 'sdk-nested-classes.yaml', - // 'sdk-nested-conflict.yaml', + 'sdk-nested-conflict.yaml', // 'string-with-format.yaml', // 'transformers.json', // 'transformers-recursive.json', @@ -274,7 +274,7 @@ export default defineConfig(() => { // }, }, { - // asClass: true, + asClass: true, // auth: false, // classNameBuilder: '{{name}}', classNameBuilder: '{{name}}Service', diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts index 3ccf4d237..998c8bb29 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts @@ -1,3 +1,5 @@ +import type { SymbolMeta } from '@hey-api/codegen-core'; + import type { IR } from '~/ir/types'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; import { @@ -65,6 +67,22 @@ export class SdkClassModel { return this.children.get(name)!; } + /** + * Gets the full path of this class in the hierarchy. + * + * @returns An array of class names from the root to this class + */ + getPath(): ReadonlyArray { + const path: Array = []; + // eslint-disable-next-line @typescript-eslint/no-this-alias + let cursor: SdkClassModel | undefined = this; + while (cursor) { + path.unshift(cursor.name); + cursor = cursor.parent; + } + return path; + } + /** * Inserts an operation into the class tree. * @@ -107,20 +125,21 @@ export class SdkClassModel { meta: { category: 'utility', resource: 'class', - resourceId: this.name, + resourceId: this.getPath().join('.'), tool: 'sdk', }, }, ); + const metaClient: SymbolMeta = { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiClient', + tool: 'sdk', + }; const node = $.class(symbolClass) .export() - .extends( - plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: 'HeyApiClient', - tool: 'sdk', - }), + .$if(plugin.config.instance, (c) => + c.extends(plugin.referenceSymbol(metaClient)), ) .$if(isAngularClient && this.isRoot, (c) => c.decorator( @@ -132,15 +151,8 @@ export class SdkClassModel { ), ); - if (this.isRoot) { - const symbolClient = plugin.symbol('HeyApiClient', { - meta: { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiClient', - tool: 'sdk', - }, - }); + if (this.isRoot && plugin.config.instance) { + const symbolClient = plugin.symbol('HeyApiClient', { meta: metaClient }); const clientNode = createClientClass({ plugin, symbol: symbolClient }); dependencies.push(clientNode); const symbolRegistry = plugin.symbol('HeyApiRegistry', { @@ -272,27 +284,37 @@ export class SdkClassModel { const refChild = plugin.referenceSymbol({ category: 'utility', resource: 'class', - resourceId: child.name, + resourceId: child.getPath().join('.'), tool: 'sdk', }); const memberName = toCase(refChild.name, 'camelCase'); - const privateName = plugin.symbol(`_${memberName}`); - const getterName = plugin.symbol(memberName); - node.field(privateName, (f) => f.private().optional().type(refChild)); - node.do( - $.getter(getterName, (g) => - g.returns(refChild).do( - $('this') - .attr(privateName) - .nullishAssign( - $.new(refChild).args( - $.object().prop('client', $('this').attr('client')), - ), - ) - .return(), + if (plugin.config.instance) { + const privateName = plugin.symbol(`_${memberName}`); + const getterName = plugin.symbol(memberName); + node.field(privateName, (f) => f.private().optional().type(refChild)); + node.do( + $.getter(getterName, (g) => + g.returns(refChild).do( + $('this') + .attr(privateName) + .nullishAssign( + $.new(refChild).args( + $.object().prop('client', $('this').attr('client')), + ), + ) + .return(), + ), ), - ), - ); + ); + } else { + node.do( + plugin.isSymbolRegistered(refChild.id) + ? $.field(memberName, (f) => f.static().assign($(refChild))) + : $.getter(memberName, (g) => + g.public().static().do($.return(refChild)), + ), + ); + } } return { dependencies, node }; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts new file mode 100644 index 000000000..76514cb7e --- /dev/null +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts @@ -0,0 +1,59 @@ +import type { IR } from '~/ir/types'; + +import type { HeyApiSdkPlugin } from '../types'; +import { SdkClassModel } from './class'; + +export class SdkStructureModel { + /** Name of the SDK. If empty, we fallback to operation tags. */ + private _name: string; + + /** Root classes mapped by their names. */ + roots: Map = new Map(); + + constructor(name: string) { + this._name = name; + } + + /** + * Inserts an operation into the structure. + * + * Parses the operation ID and organizes it into classes based on tags. + */ + insert( + operation: IR.OperationObject, + plugin: HeyApiSdkPlugin['Instance'], + ): void { + const roots = this._name ? [this._name] : (operation.tags ?? ['default']); + + for (const name of roots) { + const model = this.root(name); + model.insert(operation, plugin); + } + } + + /** + * Gets or creates a root class by name. + * + * If the root doesn't exist, it's created automatically. + * + * @param name - The name of the root class + * @returns The root class instance + */ + root(name: string): SdkClassModel { + if (!this.roots.has(name)) { + this.roots.set(name, new SdkClassModel(name)); + } + return this.roots.get(name)!; + } + + /** + * Recursively walks the structure. + * + * Yields all classes in the structure. + */ + *walk(): Generator { + for (const model of this.roots.values()) { + yield* model.walk(); + } + } +} diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts index 967d8dbfa..682e86720 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts @@ -1,49 +1,9 @@ import type { Symbol } from '@hey-api/codegen-core'; -import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; -import { - createOperationComment, - isOperationOptionsRequired, -} from '~/plugins/shared/utils/operation'; -import type { TsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/to-case'; -import { SdkClassModel } from '../model/class'; +import { SdkStructureModel } from '../model/structure'; import type { HeyApiSdkPlugin } from '../types'; -import { nuxtTypeComposable, nuxtTypeDefault } from './constants'; -import { - operationClasses, - operationParameters, - operationStatements, -} from './operation'; - -type SdkClassEntry = { - /** - * Name of the class. - */ - className: string; - /** - * Class names for child classes located inside this class. - */ - classes: Set; - /** - * Symbol ID for the class. - */ - id: number; - /** - * Track unique added method nodes. - */ - methods: Set; - /** - * List of class nodes containing methods. - */ - nodes: Array; - /** - * Is this a root class? - */ - root: boolean; -}; export const registryName = '__registry'; @@ -155,358 +115,34 @@ export const generateClassSdk = ({ }: { plugin: HeyApiSdkPlugin['Instance']; }): void => { - const client = getClientPlugin(plugin.context.config); - const isAngularClient = client.name === '@hey-api/client-angular'; - const isNuxtClient = client.name === '@hey-api/client-nuxt'; - const sdkClasses = new Map(); - /** - * Track unique added classes. - */ - const generatedClasses = new Set(); - - const sdkModel = plugin.config.instance - ? new SdkClassModel(plugin.config.instance) - : undefined; + const structure = new SdkStructureModel(plugin.config.instance); plugin.forEach( 'operation', ({ operation }) => { - if (sdkModel) { - sdkModel.insert(operation, plugin); - } else { - const isRequiredOptions = isOperationOptionsRequired({ - context: plugin.context, - operation, - }); - const symbolResponse = isNuxtClient - ? plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'response', - }) - : undefined; - - const classes = operationClasses({ operation, plugin }); - - for (const entry of classes.values()) { - entry.path.forEach((currentClassName, index) => { - const symbolCurrentClass = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: currentClassName, - tool: 'sdk', - }); - if (!sdkClasses.has(symbolCurrentClass.meta!.resourceId!)) { - sdkClasses.set(symbolCurrentClass.meta!.resourceId!, { - className: symbolCurrentClass.meta!.resourceId!, - classes: new Set(), - id: symbolCurrentClass.id, - methods: new Set(), - nodes: [], - root: !index, - }); - } - - const parentClassName = entry.path[index - 1]; - if (parentClassName) { - const symbolParentClass = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: parentClassName, - tool: 'sdk', - }); - if ( - symbolParentClass.meta?.resourceId !== - symbolCurrentClass.meta?.resourceId - ) { - const parentClass = sdkClasses.get( - symbolParentClass.meta!.resourceId!, - )!; - parentClass.classes.add(symbolCurrentClass.meta!.resourceId!); - sdkClasses.set( - symbolParentClass.meta!.resourceId!, - parentClass, - ); - } - } - - const isLast = entry.path.length === index + 1; - // add methods only to the last class - if (!isLast) { - return; - } - - const currentClass = sdkClasses.get( - symbolCurrentClass.meta!.resourceId!, - )!; - - const methodName = entry.methodName; - if (currentClass.methods.has(methodName)) return; - currentClass.methods.add(methodName); - - const opParameters = operationParameters({ - isRequiredOptions, - operation, - plugin, - }); - const statements = operationStatements({ - isRequiredOptions, - opParameters, - operation, - plugin, - }); - const functionNode = $.method(methodName, (m) => - m - .$if(createOperationComment(operation), (m, v) => m.doc(v)) - .public() - .static(!isAngularClient && !plugin.config.instance) - .$if( - isNuxtClient, - (m) => - m - .generic(nuxtTypeComposable, (t) => - t - .extends( - plugin.referenceSymbol({ - category: 'external', - resource: 'client.Composable', - }), - ) - .default($.type.literal('$fetch')), - ) - .generic(nuxtTypeDefault, (t) => - t.$if(symbolResponse, (t, s) => - t.extends(s).default(s), - ), - ), - (m) => - m.generic('ThrowOnError', (t) => - t - .extends('boolean') - .default( - ('throwOnError' in client.config - ? client.config.throwOnError - : false) ?? false, - ), - ), - ) - .params(...opParameters.parameters) - .do(...statements), - ); - - if (!currentClass.nodes.length) { - currentClass.nodes.push(functionNode); - } else { - currentClass.nodes.push($.newline(), functionNode); - } - - sdkClasses.set(symbolCurrentClass.meta!.resourceId!, currentClass); - }); - } - } - }, - { - order: 'declarations', + structure.insert(operation, plugin); }, + { order: 'declarations' }, ); - if (!sdkModel) { - const clientIndex = plugin.config.instance ? plugin.node(null) : undefined; - const symbolClient = - clientIndex !== undefined - ? plugin.symbol('HeyApiClient', { - meta: { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiClient', - tool: 'sdk', - }, - }) - : undefined; - const registryIndex = plugin.config.instance - ? plugin.node(null) - : undefined; - - const generateClass = (currentClass: SdkClassEntry) => { - const resourceId = currentClass.className; - - if (generatedClasses.has(resourceId)) return; - generatedClasses.add(resourceId); - - if (clientIndex !== undefined && symbolClient && !symbolClient.node) { - const node = createClientClass({ plugin, symbol: symbolClient }); - plugin.node(node, clientIndex); - } - - for (const childClassName of currentClass.classes) { - const childClass = sdkClasses.get(childClassName)!; - generateClass(childClass); + const allDependencies: Array> = []; + const allNodes: Array> = []; - const refChildClass = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: childClass.className, - tool: 'sdk', - }); - - const originalMemberName = toCase( - refChildClass.meta!.resourceId!, - 'camelCase', - ); - // avoid collisions with existing method names - let memberName = originalMemberName; - if (currentClass.methods.has(memberName)) { - let index = 2; - let attempt = `${memberName}${index}`; - while (currentClass.methods.has(attempt)) { - attempt = `${memberName}${index++}`; - } - memberName = attempt; - } - currentClass.methods.add(memberName); - - if (currentClass.nodes.length > 0) { - currentClass.nodes.push($.newline()); - } - - if (plugin.config.instance) { - const privateName = plugin.symbol(`_${memberName}`); - const privateNode = $.field(privateName, (f) => - f.private().optional().type(refChildClass), - ); - currentClass.nodes.push(privateNode); - const getterNode = $.getter(memberName, (g) => - g.returns(refChildClass).do( - $('this') - .attr(privateName) - .nullishAssign( - $.new(refChildClass).args( - $.object().prop('client', $('this').attr('client')), - ), - ) - .return(), - ), - ); - currentClass.nodes.push(getterNode); - } else { - const subClassReferenceNode = plugin.isSymbolRegistered( - refChildClass.id, - ) - ? $.field(memberName, (f) => f.static().assign($(refChildClass))) - : $.getter(memberName, (g) => - g.public().static().do($.return(refChildClass)), - ); - currentClass.nodes.push(subClassReferenceNode); - } - } - - const symbol = plugin.symbol(resourceId, { - meta: { - category: 'utility', - resource: 'class', - resourceId, - tool: 'sdk', - }, - }); - - if (currentClass.root && registryIndex !== undefined) { - const symClient = plugin.getSymbol({ category: 'client' }); - const isClientRequired = !plugin.config.client || !symClient; - const symbolClient = plugin.referenceSymbol({ - category: 'external', - resource: 'client.Client', - }); - const ctor = $.init((i) => - i - .param('args', (p) => - p.required(isClientRequired).type( - $.type - .object() - .prop('client', (p) => - p.required(isClientRequired).type(symbolClient), - ) - .prop('key', (p) => p.optional().type('string')), - ), - ) - .do( - $('super').call('args'), - $(symbol) - .attr(registryName) - .attr('set') - .call('this', $('args').attr('key').required(isClientRequired)), - ), - ); - - if (!currentClass.nodes.length) { - currentClass.nodes.unshift(ctor); - } else { - currentClass.nodes.unshift(ctor, $.newline()); - } - - const symbolRegistry = plugin.symbol('HeyApiRegistry', { - meta: { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiRegistry', - tool: 'sdk', - }, - }); - const node = createRegistryClass({ - plugin, - sdkSymbol: symbol, - symbol: symbolRegistry, - }); - plugin.node(node, registryIndex); - const registryNode = $.field(registryName, (f) => - f - .public() - .static() - .readonly() - .assign($.new(symbolRegistry).generic(symbol)), - ); - currentClass.nodes.unshift(registryNode, $.newline()); - } - - const node = $.class(symbol) - .export() - .extends(symbolClient) - .$if(isAngularClient && currentClass.root, (c) => - c.decorator( - plugin.referenceSymbol({ - category: 'external', - resource: '@angular/core.Injectable', - }), - $.object().prop('providedIn', $.literal('root')), - ), - ) - .do(...currentClass.nodes); - plugin.node(node); - }; - - for (const sdkClass of sdkClasses.values()) { - generateClass(sdkClass); - } - } else { - const allDependencies: Array> = []; - const allNodes: Array> = []; - - for (const model of sdkModel.walk()) { - const { dependencies, node } = model.toNode(plugin); - allDependencies.push(...dependencies); - allNodes.push(node); - } + for (const model of structure.walk()) { + const { dependencies, node } = model.toNode(plugin); + allDependencies.push(...dependencies); + allNodes.push(node); + } - const uniqueDeps = new Map>(); - for (const dep of allDependencies) { - if (dep.symbol) uniqueDeps.set(dep.symbol.id, dep); - } - for (const dep of uniqueDeps.values()) { - plugin.node(dep); - } + const uniqueDependencies = new Map>(); + for (const dep of allDependencies) { + if (dep.symbol) uniqueDependencies.set(dep.symbol.id, dep); + } + for (const dep of uniqueDependencies.values()) { + plugin.node(dep); + } - for (const node of allNodes) { - plugin.node(node); - } + for (const node of allNodes) { + plugin.node(node); } }; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts index 1d35d73bc..b8c80e4aa 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts @@ -66,6 +66,8 @@ export const operationMethodName = ({ /** * Returns a list of classes where this operation appears in the generated SDK. + * + * @deprecated */ export const operationClasses = ({ operation, -- 2.51.2 From 71025a37a1984c443f8a3b7de3a5a78b4a570d2d Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 16 Dec 2025 23:51:11 +0800 Subject: [PATCH 03/15] chore: port function functionality --- dev/openapi-ts.config.ts | 6 +- dev/package.json | 2 + .../src/plugins/@hey-api/sdk/model/class.ts | 334 -------------- .../plugins/@hey-api/sdk/model/resource.ts | 425 ++++++++++++++++++ .../plugins/@hey-api/sdk/model/structure.ts | 58 ++- .../src/plugins/@hey-api/sdk/shared/class.ts | 38 -- .../plugins/@hey-api/sdk/shared/functions.ts | 107 ----- .../src/plugins/@hey-api/sdk/v1/plugin.ts | 61 ++- pnpm-lock.yaml | 322 +++++++++---- 9 files changed, 747 insertions(+), 606 deletions(-) delete mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts create mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts delete mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/shared/functions.ts diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index 5694a7080..43c6111f9 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -240,7 +240,7 @@ export default defineConfig(() => { { // baseUrl: false, // exportFromIndex: true, - // name: '@hey-api/client-angular', + name: '@hey-api/client-nuxt', // runtimeConfigPath: path.resolve(__dirname, 'hey-api.ts'), // runtimeConfigPath: './src/hey-api.ts', // strictBaseUrl: true, @@ -274,7 +274,7 @@ export default defineConfig(() => { // }, }, { - asClass: true, + // asClass: true, // auth: false, // classNameBuilder: '{{name}}', classNameBuilder: '{{name}}Service', @@ -285,7 +285,7 @@ export default defineConfig(() => { // fields.unwrap('path') // }, // include... - instance: 'Root', + // instance: 'Root', methodNameBuilder: '{{name}}Methods', name: '@hey-api/sdk', // operationId: false, diff --git a/dev/package.json b/dev/package.json index c74cfa168..2e2a453fc 100644 --- a/dev/package.json +++ b/dev/package.json @@ -19,9 +19,11 @@ "@tanstack/svelte-query": "5.73.3", "@tanstack/vue-query": "5.73.3", "arktype": "2.1.29", + "nuxt": "3.14.1592", "swr": "2.3.8", "typescript": "5.9.3", "valibot": "1.2.0", + "vue": "3.5.25", "zod": "4.1.12" } } diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts deleted file mode 100644 index 998c8bb29..000000000 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/class.ts +++ /dev/null @@ -1,334 +0,0 @@ -import type { SymbolMeta } from '@hey-api/codegen-core'; - -import type { IR } from '~/ir/types'; -import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; -import { - createOperationComment, - isOperationOptionsRequired, -} from '~/plugins/shared/utils/operation'; -import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/to-case'; - -import { createClientClass, createRegistryClass } from '../shared/class'; -import { nuxtTypeComposable, nuxtTypeDefault } from '../shared/constants'; -import { - operationClassName, - operationMethodName, - operationParameters, - operationStatements, -} from '../shared/operation'; -import type { HeyApiSdkPlugin } from '../types'; - -/** - * Represents a class in the SDK hierarchy. - * - * Classes can be nested (via children) and contain operations (methods). - */ -export class SdkClassModel { - /** Nested classes within this class. */ - children: Map = new Map(); - /** The name of this class (e.g., "Users", "Accounts"). */ - name: string; - /** Operations that will become methods in this class. */ - operations: Array = []; - /** Parent class in the hierarchy. Undefined if this is the root class. */ - parent?: SdkClassModel; - - constructor(name: string, parent?: SdkClassModel) { - this.name = name; - this.parent = parent; - } - - get isRoot(): boolean { - return !this.parent; - } - - /** - * Adds an operation to this class. - * - * The operation will be converted to a method during code generation. - */ - addOperation(operation: IR.OperationObject): void { - this.operations.push(operation); - } - - /** - * Gets or creates a child class. - * - * If the child doesn't exist, it's created automatically. - * - * @param name - The name of the child class - * @returns The child class instance - */ - child(name: string): SdkClassModel { - if (!this.children.has(name)) { - this.children.set(name, new SdkClassModel(name, this)); - } - return this.children.get(name)!; - } - - /** - * Gets the full path of this class in the hierarchy. - * - * @returns An array of class names from the root to this class - */ - getPath(): ReadonlyArray { - const path: Array = []; - // eslint-disable-next-line @typescript-eslint/no-this-alias - let cursor: SdkClassModel | undefined = this; - while (cursor) { - path.unshift(cursor.name); - cursor = cursor.parent; - } - return path; - } - - /** - * Inserts an operation into the class tree. - * - * Parses the operation ID and creates the class hierarchy. - */ - insert( - operation: IR.OperationObject, - plugin: HeyApiSdkPlugin['Instance'], - ): void { - const classSegments = - plugin.config.classStructure === 'auto' && operation.operationId - ? operation.operationId.split(/[./]/).slice(0, -1) - : []; - - // eslint-disable-next-line @typescript-eslint/no-this-alias - let cursor: SdkClassModel = this; - for (const segment of classSegments) { - cursor = cursor.child(segment); - } - - cursor.addOperation(operation); - } - - /** - * Converts this class group to a class node. - */ - toNode(plugin: HeyApiSdkPlugin['Instance']): { - dependencies: Array>; - node: ReturnType; - } { - const dependencies: Array> = []; - - const client = getClientPlugin(plugin.context.config); - const isAngularClient = client.name === '@hey-api/client-angular'; - const isNuxtClient = client.name === '@hey-api/client-nuxt'; - - const symbolClass = plugin.symbol( - operationClassName({ plugin, value: this.name }), - { - meta: { - category: 'utility', - resource: 'class', - resourceId: this.getPath().join('.'), - tool: 'sdk', - }, - }, - ); - const metaClient: SymbolMeta = { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiClient', - tool: 'sdk', - }; - const node = $.class(symbolClass) - .export() - .$if(plugin.config.instance, (c) => - c.extends(plugin.referenceSymbol(metaClient)), - ) - .$if(isAngularClient && this.isRoot, (c) => - c.decorator( - plugin.referenceSymbol({ - category: 'external', - resource: '@angular/core.Injectable', - }), - $.object().prop('providedIn', $.literal('root')), - ), - ); - - if (this.isRoot && plugin.config.instance) { - const symbolClient = plugin.symbol('HeyApiClient', { meta: metaClient }); - const clientNode = createClientClass({ plugin, symbol: symbolClient }); - dependencies.push(clientNode); - const symbolRegistry = plugin.symbol('HeyApiRegistry', { - meta: { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiRegistry', - tool: 'sdk', - }, - }); - const registryNode = createRegistryClass({ - plugin, - sdkSymbol: symbolClass, - symbol: symbolRegistry, - }); - dependencies.push(registryNode); - node.field('__registry', (f) => - f - .public() - .static() - .readonly() - .assign($.new(symbolRegistry).generic(symbolClass)), - ); - node.newline(); - - const symClient = plugin.getSymbol({ category: 'client' }); - const isClientRequired = !plugin.config.client || !symClient; - const symbolClientType = plugin.referenceSymbol({ - category: 'external', - resource: 'client.Client', - }); - node.init((i) => - i - .param('args', (p) => - p.required(isClientRequired).type( - $.type - .object() - .prop('client', (p) => - p.required(isClientRequired).type(symbolClientType), - ) - .prop('key', (p) => p.optional().type('string')), - ), - ) - .do( - $('super').call('args'), - $(symbolClass) - .attr('__registry') - .attr('set') - .call('this', $('args').attr('key').required(isClientRequired)), - ), - ); - } - - this.operations.forEach((operation, index) => { - if (index > 0 || node.hasBody) node.newline(); - const symbolMethod = plugin.symbol( - operationMethodName({ - operation, - plugin, - value: - plugin.config.classStructure === 'auto' && operation.operationId - ? toCase(operation.operationId.split(/[./]/).pop()!, 'camelCase') - : operation.id, - }), - ); - const isRequiredOptions = isOperationOptionsRequired({ - context: plugin.context, - operation, - }); - const opParameters = operationParameters({ - isRequiredOptions, - operation, - plugin, - }); - const statements = operationStatements({ - isRequiredOptions, - opParameters, - operation, - plugin, - }); - node.method(symbolMethod, (m) => - m - .$if(createOperationComment(operation), (m, v) => m.doc(v)) - .public() - .static(!isAngularClient && !plugin.config.instance) - .$if( - isNuxtClient, - (m) => - m - .generic(nuxtTypeComposable, (t) => - t - .extends( - plugin.referenceSymbol({ - category: 'external', - resource: 'client.Composable', - }), - ) - .default($.type.literal('$fetch')), - ) - .generic(nuxtTypeDefault, (t) => - t.$if( - plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'response', - }), - (t, s) => t.extends(s).default(s), - ), - ), - (m) => - m.generic('ThrowOnError', (t) => - t - .extends('boolean') - .default( - ('throwOnError' in client.config - ? client.config.throwOnError - : false) ?? false, - ), - ), - ) - .params(...opParameters.parameters) - .do(...statements), - ); - }); - - for (const child of this.children.values()) { - if (node.hasBody) node.newline(); - const refChild = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: child.getPath().join('.'), - tool: 'sdk', - }); - const memberName = toCase(refChild.name, 'camelCase'); - if (plugin.config.instance) { - const privateName = plugin.symbol(`_${memberName}`); - const getterName = plugin.symbol(memberName); - node.field(privateName, (f) => f.private().optional().type(refChild)); - node.do( - $.getter(getterName, (g) => - g.returns(refChild).do( - $('this') - .attr(privateName) - .nullishAssign( - $.new(refChild).args( - $.object().prop('client', $('this').attr('client')), - ), - ) - .return(), - ), - ), - ); - } else { - node.do( - plugin.isSymbolRegistered(refChild.id) - ? $.field(memberName, (f) => f.static().assign($(refChild))) - : $.getter(memberName, (g) => - g.public().static().do($.return(refChild)), - ), - ); - } - } - - return { dependencies, node }; - } - - /** - * Recursively walks the tree depth-first. - * - * Yields this node, then all descendants. - */ - *walk(): Generator { - for (const child of this.children.values()) { - yield* child.walk(); - } - yield this; - } -} diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts new file mode 100644 index 000000000..61e016b32 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts @@ -0,0 +1,425 @@ +import type { Symbol } from '@hey-api/codegen-core'; + +import type { IR } from '~/ir/types'; +import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; +import { + createOperationComment, + isOperationOptionsRequired, +} from '~/plugins/shared/utils/operation'; +import { $ } from '~/ts-dsl'; +import { toCase } from '~/utils/to-case'; + +import { createClientClass, createRegistryClass } from '../shared/class'; +import { nuxtTypeComposable, nuxtTypeDefault } from '../shared/constants'; +import { + operationClassName, + operationMethodName, + operationParameters, + operationStatements, +} from '../shared/operation'; +import type { HeyApiSdkPlugin } from '../types'; + +export type Event = { + operation: IR.OperationObject; + path: ReadonlyArray; + tags: ReadonlyArray | undefined; +}; + +/** + * Represents a resource layer in the SDK hierarchy. + * + * Resources can be nested (via children) and contain operations (methods). + */ +export class SdkResourceModel { + /** Nested resources within this resource. */ + children: Map = new Map(); + /** The name of this resource (e.g., "Users", "Accounts"). */ + name: string; + /** Operations that will become methods in this resource. */ + operations: Array = []; + /** Parent resource in the hierarchy. Undefined if this is the root resource. */ + parent?: SdkResourceModel; + + constructor(name: string, parent?: SdkResourceModel) { + this.name = name; + this.parent = parent; + } + + get isRoot(): boolean { + return !this.parent; + } + + /** + * Gets or creates a child resource. + * + * If the child doesn't exist, it's created automatically. + * + * @param name - The name of the child resource + * @returns The child resource instance + */ + child(name: string): SdkResourceModel { + if (!this.children.has(name)) { + this.children.set(name, new SdkResourceModel(name, this)); + } + return this.children.get(name)!; + } + + /** + * Gets the full path of this resource in the hierarchy. + * + * @returns An array of resource names from the root to this resource + */ + getPath(): ReadonlyArray { + const path: Array = []; + // eslint-disable-next-line @typescript-eslint/no-this-alias + let cursor: SdkResourceModel | undefined = this; + while (cursor) { + path.unshift(cursor.name); + cursor = cursor.parent; + } + return path; + } + + /** + * Inserts an operation event into the resource tree. + * + * Parses the operation ID and creates the resource hierarchy. + */ + insert(event: Event, plugin: HeyApiSdkPlugin['Instance']): void { + const { operation } = event; + const classSegments = + this.name && + plugin.config.classStructure === 'auto' && + operation.operationId + ? operation.operationId.split(/[./]/).slice(0, -1) + : []; + + // eslint-disable-next-line @typescript-eslint/no-this-alias + let cursor: SdkResourceModel = this; + for (const segment of classSegments) { + cursor = cursor.child(segment); + } + + cursor.operations.push(event); + } + + /** + * Converts this class group to a class node. + */ + toNode(plugin: HeyApiSdkPlugin['Instance']): { + dependencies: Array>; + nodes: ReadonlyArray>; + } { + const dependencies: Array> = []; + const nodes: Array> = []; + + const client = getClientPlugin(plugin.context.config); + const isAngularClient = client.name === '@hey-api/client-angular'; + + if (this.name) { + const { node, symbol: symbolClass } = this.classToNode(plugin); + + if (this.isRoot && plugin.config.instance) { + node.do(...this.rootClassToNode(symbolClass, dependencies, plugin)); + } + + this.operations.forEach((event, index) => { + const { operation } = event; + if (index > 0 || node.hasBody) node.newline(); + node.do( + this.implementFn({ + node: $.method(this.createFnSymbol(plugin, event), (m) => + m + .public() + .static(!isAngularClient && !plugin.config.instance) + .$if(createOperationComment(operation), (m, v) => m.doc(v)), + ), + operation, + plugin, + }), + ); + }); + + for (const child of this.children.values()) { + if (node.hasBody) node.newline(); + node.do(...this.childToNode(child, plugin)); + } + + nodes.push(node); + } else { + this.operations.forEach((event) => { + const { operation } = event; + const node = $.const(this.createFnSymbol(plugin, event)) + .export() + .$if(createOperationComment(operation), (c, v) => c.doc(v)) + .assign( + this.implementFn({ + node: $.func(), + operation, + plugin, + }), + ); + nodes.push(node); + }); + } + + return { dependencies, nodes }; + } + + /** + * Recursively walks the tree depth-first. + * + * Yields this node, then all descendants. + */ + *walk(): Generator { + for (const child of this.children.values()) { + yield* child.walk(); + } + yield this; + } + + private createFnSymbol( + plugin: HeyApiSdkPlugin['Instance'], + event: Event, + ): Symbol { + const { operation, path, tags } = event; + const extractFromOperationId = + this.name && plugin.config.classStructure === 'auto'; + return plugin.symbol( + operationMethodName({ + operation, + plugin, + value: + extractFromOperationId && operation.operationId + ? toCase(operation.operationId.split(/[./]/).pop()!, 'camelCase') + : operation.id, + }), + { + meta: { + category: 'sdk', + path, + resource: 'operation', + resourceId: operation.id, + tags, + tool: 'sdk', + }, + }, + ); + } + + private childToNode( + resource: SdkResourceModel, + plugin: HeyApiSdkPlugin['Instance'], + ): ReadonlyArray> { + const refChild = plugin.referenceSymbol({ + category: 'utility', + resource: 'class', + resourceId: resource.getPath().join('.'), + tool: 'sdk', + }); + const memberName = toCase(refChild.name, 'camelCase'); + if (plugin.config.instance) { + const privateName = plugin.symbol(`_${memberName}`); + const getterName = plugin.symbol(memberName); + return [ + $.field(privateName, (f) => f.private().optional().type(refChild)), + $.getter(getterName, (g) => + g.returns(refChild).do( + $('this') + .attr(privateName) + .nullishAssign( + $.new(refChild).args( + $.object().prop('client', $('this').attr('client')), + ), + ) + .return(), + ), + ), + ]; + } + if (plugin.isSymbolRegistered(refChild.id)) { + return [$.field(memberName, (f) => f.static().assign($(refChild)))]; + } + return [ + $.getter(memberName, (g) => g.public().static().do($.return(refChild))), + ]; + } + + private classToNode(plugin: HeyApiSdkPlugin['Instance']): { + node: ReturnType; + symbol: Symbol; + } { + const client = getClientPlugin(plugin.context.config); + const isAngularClient = client.name === '@hey-api/client-angular'; + const symbol = plugin.symbol( + operationClassName({ plugin, value: this.name }), + { + meta: { + category: 'utility', + resource: 'class', + resourceId: this.getPath().join('.'), + tool: 'sdk', + }, + }, + ); + const node = $.class(symbol) + .export() + .$if(plugin.config.instance, (c) => + c.extends( + plugin.referenceSymbol({ + category: 'utility', + resource: 'class', + resourceId: 'HeyApiClient', + tool: 'sdk', + }), + ), + ) + .$if(isAngularClient && this.isRoot, (c) => + c.decorator( + plugin.referenceSymbol({ + category: 'external', + resource: '@angular/core.Injectable', + }), + $.object().prop('providedIn', $.literal('root')), + ), + ); + return { node, symbol }; + } + + private implementFn< + T extends ReturnType, + >(args: { + node: T; + operation: IR.OperationObject; + plugin: HeyApiSdkPlugin['Instance']; + }): T { + const { node, operation, plugin } = args; + const client = getClientPlugin(plugin.context.config); + const isNuxtClient = client.name === '@hey-api/client-nuxt'; + const isRequiredOptions = isOperationOptionsRequired({ + context: plugin.context, + operation, + }); + const opParameters = operationParameters({ + isRequiredOptions, + operation, + plugin, + }); + const statements = operationStatements({ + isRequiredOptions, + opParameters, + operation, + plugin, + }); + return node + .$if( + isNuxtClient, + (m) => + m + .generic(nuxtTypeComposable, (t) => + t + .extends( + plugin.referenceSymbol({ + category: 'external', + resource: 'client.Composable', + }), + ) + .default($.type.literal('$fetch')), + ) + .generic(nuxtTypeDefault, (t) => + t.$if( + plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'response', + }), + (t, s) => t.extends(s).default(s), + (t) => t.default('undefined'), + ), + ), + (m) => + m.generic('ThrowOnError', (t) => + t + .extends('boolean') + .default( + ('throwOnError' in client.config + ? client.config.throwOnError + : false) ?? false, + ), + ), + ) + .params(...opParameters.parameters) + .do(...statements) as T; + } + + private rootClassToNode( + symbol: Symbol, + dependencies: Array>, + plugin: HeyApiSdkPlugin['Instance'], + ): ReadonlyArray< + ReturnType + > { + const symbolClient = plugin.symbol('HeyApiClient', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiClient', + tool: 'sdk', + }, + }); + dependencies.push(createClientClass({ plugin, symbol: symbolClient })); + const symbolRegistry = plugin.symbol('HeyApiRegistry', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiRegistry', + tool: 'sdk', + }, + }); + dependencies.push( + createRegistryClass({ + plugin, + sdkSymbol: symbol, + symbol: symbolRegistry, + }), + ); + const isClientRequired = + !plugin.config.client || !plugin.getSymbol({ category: 'client' }); + return [ + $.field('__registry', (f) => + f + .public() + .static() + .readonly() + .assign($.new(symbolRegistry).generic(symbol)), + ), + $.newline(), + $.init((i) => + i + .param('args', (p) => + p.required(isClientRequired).type( + $.type + .object() + .prop('client', (p) => + p.required(isClientRequired).type( + plugin.referenceSymbol({ + category: 'external', + resource: 'client.Client', + }), + ), + ) + .prop('key', (p) => p.optional().type('string')), + ), + ) + .do( + $('super').call('args'), + $(symbol) + .attr('__registry') + .attr('set') + .call('this', $('args').attr('key').required(isClientRequired)), + ), + ), + ]; + } +} diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts index 76514cb7e..f99ca35f8 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts @@ -1,47 +1,59 @@ -import type { IR } from '~/ir/types'; - import type { HeyApiSdkPlugin } from '../types'; -import { SdkClassModel } from './class'; +import type { Event } from './resource'; +import { SdkResourceModel } from './resource'; export class SdkStructureModel { + /** If true, generates a flat SDK without resource hierarchy. */ + private _flat: boolean; /** Name of the SDK. If empty, we fallback to operation tags. */ private _name: string; - /** Root classes mapped by their names. */ - roots: Map = new Map(); + /** Root resources mapped by their names. */ + roots: Map = new Map(); - constructor(name: string) { + constructor( + name: string, + options?: { + /** If true, generates a flat SDK without resource hierarchy. */ + flat?: boolean; + }, + ) { + this._flat = options?.flat ?? false; this._name = name; } /** - * Inserts an operation into the structure. + * Inserts an operation event into the structure. * * Parses the operation ID and organizes it into classes based on tags. */ - insert( - operation: IR.OperationObject, - plugin: HeyApiSdkPlugin['Instance'], - ): void { - const roots = this._name ? [this._name] : (operation.tags ?? ['default']); + insert(event: Event, plugin: HeyApiSdkPlugin['Instance']): void { + const { operation } = event; + const roots = this._name + ? [this._name] + : this._flat + ? [''] + : operation.tags && operation.tags.length > 0 + ? operation.tags + : ['default']; for (const name of roots) { - const model = this.root(name); - model.insert(operation, plugin); + const resource = this.root(name); + resource.insert(event, plugin); } } /** - * Gets or creates a root class by name. + * Gets or creates a root resource by name. * * If the root doesn't exist, it's created automatically. * - * @param name - The name of the root class - * @returns The root class instance + * @param name - The name of the root resource + * @returns The root resource instance */ - root(name: string): SdkClassModel { + root(name: string): SdkResourceModel { if (!this.roots.has(name)) { - this.roots.set(name, new SdkClassModel(name)); + this.roots.set(name, new SdkResourceModel(name)); } return this.roots.get(name)!; } @@ -49,11 +61,11 @@ export class SdkStructureModel { /** * Recursively walks the structure. * - * Yields all classes in the structure. + * Yields all resources in the structure. */ - *walk(): Generator { - for (const model of this.roots.values()) { - yield* model.walk(); + *walk(): Generator { + for (const resource of this.roots.values()) { + yield* resource.walk(); } } } diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts index 682e86720..666c03018 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts @@ -2,7 +2,6 @@ import type { Symbol } from '@hey-api/codegen-core'; import { $ } from '~/ts-dsl'; -import { SdkStructureModel } from '../model/structure'; import type { HeyApiSdkPlugin } from '../types'; export const registryName = '__registry'; @@ -109,40 +108,3 @@ export const createClientClass = ({ ), ); }; - -export const generateClassSdk = ({ - plugin, -}: { - plugin: HeyApiSdkPlugin['Instance']; -}): void => { - const structure = new SdkStructureModel(plugin.config.instance); - - plugin.forEach( - 'operation', - ({ operation }) => { - structure.insert(operation, plugin); - }, - { order: 'declarations' }, - ); - - const allDependencies: Array> = []; - const allNodes: Array> = []; - - for (const model of structure.walk()) { - const { dependencies, node } = model.toNode(plugin); - allDependencies.push(...dependencies); - allNodes.push(node); - } - - const uniqueDependencies = new Map>(); - for (const dep of allDependencies) { - if (dep.symbol) uniqueDependencies.set(dep.symbol.id, dep); - } - for (const dep of uniqueDependencies.values()) { - plugin.node(dep); - } - - for (const node of allNodes) { - plugin.node(node); - } -}; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/functions.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/functions.ts deleted file mode 100644 index efb451253..000000000 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/functions.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; -import { - createOperationComment, - isOperationOptionsRequired, -} from '~/plugins/shared/utils/operation'; -import { $ } from '~/ts-dsl'; - -import type { HeyApiSdkPlugin } from '../types'; -import { nuxtTypeComposable, nuxtTypeDefault } from './constants'; -import { - operationMethodName, - operationParameters, - operationStatements, -} from './operation'; - -export const generateFlatSdk = ({ - plugin, -}: { - plugin: HeyApiSdkPlugin['Instance']; -}): void => { - const client = getClientPlugin(plugin.context.config); - const isNuxtClient = client.name === '@hey-api/client-nuxt'; - - plugin.forEach( - 'operation', - (event) => { - const { operation } = event; - const isRequiredOptions = isOperationOptionsRequired({ - context: plugin.context, - operation, - }); - const symbolResponse = isNuxtClient - ? plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'response', - }) - : undefined; - const opParameters = operationParameters({ - isRequiredOptions, - operation, - plugin, - }); - const statements = operationStatements({ - isRequiredOptions, - opParameters, - operation, - plugin, - }); - const symbol = plugin.symbol(operationMethodName({ operation, plugin }), { - meta: { - category: 'sdk', - path: event._path, - resource: 'operation', - resourceId: operation.id, - tags: event.tags, - tool: 'sdk', - }, - }); - const node = $.const(symbol) - .export() - .$if(createOperationComment(operation), (c, v) => c.doc(v)) - .assign( - $.func() - .params(...opParameters.parameters) - .$if( - isNuxtClient, - (f) => - f - .generic(nuxtTypeComposable, (g) => - g - .extends( - plugin.referenceSymbol({ - category: 'external', - resource: 'client.Composable', - }), - ) - .default($.type.literal('$fetch')), - ) - .generic(nuxtTypeDefault, (g) => - g.$if( - symbolResponse, - (t, s) => t.extends(s).default(s), - (t) => t.default('undefined'), - ), - ), - (f) => - f.generic('ThrowOnError', (g) => - g - .extends('boolean') - .default( - ('throwOnError' in client.config - ? client.config.throwOnError - : false) ?? false, - ), - ), - ) - .do(...statements), - ); - plugin.node(node); - }, - { - order: 'declarations', - }, - ); -}; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts index 631b9c927..f5d199461 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts @@ -1,8 +1,8 @@ import { clientFolderAbsolutePath } from '~/generate/client'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; +import type { $ } from '~/ts-dsl'; -import { generateClassSdk } from '../shared/class'; -import { generateFlatSdk } from '../shared/functions'; +import { SdkStructureModel } from '../model/structure'; import { createTypeOptions } from '../shared/typeOptions'; import type { HeyApiSdkPlugin } from '../types'; @@ -12,35 +12,32 @@ export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { const isAngularClient = client.name === '@hey-api/client-angular'; const isNuxtClient = client.name === '@hey-api/client-nuxt'; - plugin.registerSymbol({ + plugin.symbol('formDataBodySerializer', { external: clientModule, meta: { category: 'external', resource: 'client.formDataBodySerializer', tool: client.name, }, - name: 'formDataBodySerializer', }); - plugin.registerSymbol({ + plugin.symbol('urlSearchParamsBodySerializer', { external: clientModule, meta: { category: 'external', resource: 'client.urlSearchParamsBodySerializer', tool: client.name, }, - name: 'urlSearchParamsBodySerializer', }); - plugin.registerSymbol({ + plugin.symbol('buildClientParams', { external: clientModule, meta: { category: 'external', resource: 'client.buildClientParams', tool: client.name, }, - name: 'buildClientParams', }); if (isNuxtClient) { - plugin.registerSymbol({ + plugin.symbol('Composable', { external: clientModule, kind: 'type', meta: { @@ -48,25 +45,57 @@ export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { resource: 'client.Composable', tool: client.name, }, - name: 'Composable', }); } if (isAngularClient && plugin.config.asClass) { - plugin.registerSymbol({ + plugin.symbol('Injectable', { external: '@angular/core', meta: { category: 'external', resource: '@angular/core.Injectable', }, - name: 'Injectable', }); } createTypeOptions({ plugin }); - if (plugin.config.asClass) { - generateClassSdk({ plugin }); - } else { - generateFlatSdk({ plugin }); + const structure = plugin.config.asClass + ? new SdkStructureModel(plugin.config.instance) + : new SdkStructureModel('', { flat: true }); + + plugin.forEach( + 'operation', + (event) => { + structure.insert( + { + operation: event.operation, + path: event._path, + tags: event.tags, + }, + plugin, + ); + }, + { order: 'declarations' }, + ); + + const allDependencies: Array> = []; + const allNodes: Array> = []; + + for (const model of structure.walk()) { + const { dependencies, nodes } = model.toNode(plugin); + allDependencies.push(...dependencies); + allNodes.push(...nodes); + } + + const uniqueDependencies = new Map>(); + for (const dep of allDependencies) { + if (dep.symbol) uniqueDependencies.set(dep.symbol.id, dep); + } + for (const dep of uniqueDependencies.values()) { + plugin.node(dep); + } + + for (const node of allNodes) { + plugin.node(node); } }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 46059784b..f09388b1a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -139,6 +139,9 @@ importers: arktype: specifier: 2.1.29 version: 2.1.29 + nuxt: + specifier: 3.14.1592 + version: 3.14.1592(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@22.10.5)(db0@0.3.2)(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.2.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.57)(rollup@4.54.0)(sass@1.85.0)(terser@5.43.1)(typescript@5.9.3)(vite@5.4.19(@types/node@22.10.5)(less@4.2.2)(sass@1.85.0)(terser@5.43.1)) swr: specifier: 2.3.8 version: 2.3.8(react@19.0.0) @@ -148,6 +151,9 @@ importers: valibot: specifier: 1.2.0 version: 1.2.0(typescript@5.9.3) + vue: + specifier: 3.5.25 + version: 3.5.25(typescript@5.9.3) zod: specifier: 4.1.12 version: 4.1.12 @@ -1385,7 +1391,7 @@ importers: version: 1.14.2 nuxt: specifier: 3.14.1592 - version: 3.14.1592(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@22.10.5)(db0@0.3.2)(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.2.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.57)(rollup@4.54.0)(sass@1.85.0)(terser@5.43.1)(typescript@5.9.3)(vite@5.4.19(@types/node@22.10.5)(less@4.2.2)(sass@1.85.0)(terser@5.43.1)) + version: 3.14.1592(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@22.10.5)(db0@0.3.2)(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.2.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.57)(rollup@4.54.0)(sass@1.85.0)(terser@5.43.1)(typescript@5.9.3) ofetch: specifier: 1.5.1 version: 1.5.1 @@ -2800,10 +2806,6 @@ packages: resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.4': - resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} - engines: {node: '>=6.9.0'} - '@babel/types@7.28.5': resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} @@ -7212,9 +7214,6 @@ packages: '@vue/shared@3.5.13': resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} - '@vue/shared@3.5.21': - resolution: {integrity: sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==} - '@vue/shared@3.5.24': resolution: {integrity: sha512-9cwHL2EsJBdi8NY22pngYYWzkTDhld6fAD6jlaeloNGciNSJL6bLpbxVgXl96X00Jtc6YWQv96YA/0sxex/k1A==} @@ -10556,9 +10555,6 @@ packages: magic-string@0.30.18: resolution: {integrity: sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==} - magic-string@0.30.19: - resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} - magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -14313,7 +14309,6 @@ packages: whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} - deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} @@ -14584,7 +14579,7 @@ snapshots: dependencies: '@ampproject/remapping': 2.3.0 '@angular-devkit/architect': 0.1902.0(chokidar@4.0.3) - '@angular-devkit/build-webpack': 0.1902.0(chokidar@4.0.3)(webpack-dev-server@5.2.0(webpack@5.98.0))(webpack@5.98.0(esbuild@0.25.0)) + '@angular-devkit/build-webpack': 0.1902.0(chokidar@4.0.3)(webpack-dev-server@5.2.0(webpack@5.98.0(esbuild@0.25.0)))(webpack@5.98.0(esbuild@0.25.0)) '@angular-devkit/core': 19.2.0(chokidar@4.0.3) '@angular/build': 19.2.0(@angular/compiler-cli@19.2.0(@angular/compiler@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1)))(typescript@5.8.3))(@angular/compiler@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/platform-server@19.2.0(@angular/common@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.0(@angular/animations@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1))))(@angular/ssr@19.2.15(5c03da8199d2fcdf9ff93b70f9349edd))(@types/node@22.10.5)(chokidar@4.0.3)(jiti@2.6.1)(karma@6.4.4)(less@4.2.2)(postcss@8.5.2)(tailwindcss@3.4.14(ts-node@10.9.2(@types/node@22.10.5)(typescript@5.8.3)))(terser@5.39.0)(typescript@5.8.3)(yaml@2.8.2) '@angular/compiler-cli': 19.2.0(@angular/compiler@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1)))(typescript@5.8.3) @@ -14635,8 +14630,8 @@ snapshots: tslib: 2.8.1 typescript: 5.8.3 webpack: 5.98.0(esbuild@0.25.0) - webpack-dev-middleware: 7.4.2(webpack@5.98.0) - webpack-dev-server: 5.2.0(webpack@5.98.0) + webpack-dev-middleware: 7.4.2(webpack@5.98.0(esbuild@0.25.0)) + webpack-dev-server: 5.2.0(webpack@5.98.0(esbuild@0.25.0)) webpack-merge: 6.0.1 webpack-subresource-integrity: 5.1.0(webpack@5.98.0) optionalDependencies: @@ -14672,7 +14667,7 @@ snapshots: dependencies: '@ampproject/remapping': 2.3.0 '@angular-devkit/architect': 0.1902.0(chokidar@4.0.3) - '@angular-devkit/build-webpack': 0.1902.0(chokidar@4.0.3)(webpack-dev-server@5.2.0(webpack@5.98.0))(webpack@5.98.0(esbuild@0.25.0)) + '@angular-devkit/build-webpack': 0.1902.0(chokidar@4.0.3)(webpack-dev-server@5.2.0(webpack@5.98.0(esbuild@0.25.0)))(webpack@5.98.0(esbuild@0.25.0)) '@angular-devkit/core': 19.2.0(chokidar@4.0.3) '@angular/build': 19.2.0(@angular/compiler-cli@19.2.0(@angular/compiler@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1)))(typescript@5.8.3))(@angular/compiler@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/platform-server@19.2.0(@angular/common@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.0(@angular/animations@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1))))(@angular/ssr@19.2.15(5c03da8199d2fcdf9ff93b70f9349edd))(@types/node@22.10.5)(chokidar@4.0.3)(jiti@2.6.1)(karma@6.4.4)(less@4.2.2)(postcss@8.5.2)(tailwindcss@3.4.14(ts-node@10.9.2(@types/node@22.10.5)(typescript@5.8.3)))(terser@5.39.0)(typescript@5.8.3)(yaml@2.8.2) '@angular/compiler-cli': 19.2.0(@angular/compiler@19.2.0(@angular/core@19.2.0(rxjs@7.8.2)(zone.js@0.15.1)))(typescript@5.8.3) @@ -14723,8 +14718,8 @@ snapshots: tslib: 2.8.1 typescript: 5.8.3 webpack: 5.98.0(esbuild@0.25.0) - webpack-dev-middleware: 7.4.2(webpack@5.98.0) - webpack-dev-server: 5.2.0(webpack@5.98.0) + webpack-dev-middleware: 7.4.2(webpack@5.98.0(esbuild@0.25.0)) + webpack-dev-server: 5.2.0(webpack@5.98.0(esbuild@0.25.0)) webpack-merge: 6.0.1 webpack-subresource-integrity: 5.1.0(webpack@5.98.0) optionalDependencies: @@ -14811,7 +14806,7 @@ snapshots: tslib: 2.8.1 typescript: 5.8.3 webpack: 5.98.0(esbuild@0.25.4) - webpack-dev-middleware: 7.4.2(webpack@5.98.0) + webpack-dev-middleware: 7.4.2(webpack@5.98.0(esbuild@0.25.0)) webpack-dev-server: 5.2.2(webpack@5.98.0) webpack-merge: 6.0.1 webpack-subresource-integrity: 5.1.0(webpack@5.98.0) @@ -14899,7 +14894,7 @@ snapshots: tslib: 2.8.1 typescript: 5.9.3 webpack: 5.98.0(esbuild@0.25.4) - webpack-dev-middleware: 7.4.2(webpack@5.98.0) + webpack-dev-middleware: 7.4.2(webpack@5.98.0(esbuild@0.25.0)) webpack-dev-server: 5.2.2(webpack@5.98.0) webpack-merge: 6.0.1 webpack-subresource-integrity: 5.1.0(webpack@5.98.0) @@ -14931,12 +14926,12 @@ snapshots: - webpack-cli - yaml - '@angular-devkit/build-webpack@0.1902.0(chokidar@4.0.3)(webpack-dev-server@5.2.0(webpack@5.98.0))(webpack@5.98.0(esbuild@0.25.0))': + '@angular-devkit/build-webpack@0.1902.0(chokidar@4.0.3)(webpack-dev-server@5.2.0(webpack@5.98.0(esbuild@0.25.0)))(webpack@5.98.0(esbuild@0.25.0))': dependencies: '@angular-devkit/architect': 0.1902.0(chokidar@4.0.3) rxjs: 7.8.1 webpack: 5.98.0(esbuild@0.25.0) - webpack-dev-server: 5.2.0(webpack@5.98.0) + webpack-dev-server: 5.2.0(webpack@5.98.0(esbuild@0.25.0)) transitivePeerDependencies: - chokidar @@ -16922,11 +16917,6 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/types@7.28.4': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/types@7.28.5': dependencies: '@babel/helper-string-parser': 7.27.1 @@ -18283,7 +18273,7 @@ snapshots: '@mapbox/node-pre-gyp@2.0.0(encoding@0.1.13)': dependencies: consola: 3.4.2 - detect-libc: 2.0.4 + detect-libc: 2.1.2 https-proxy-agent: 7.0.6 node-fetch: 2.7.0(encoding@0.1.13) nopt: 8.1.0 @@ -18841,6 +18831,52 @@ snapshots: - utf-8-validate - vue + '@nuxt/devtools@1.7.0(rollup@4.54.0)(vue@3.5.25(typescript@5.9.3))': + dependencies: + '@antfu/utils': 0.7.10 + '@nuxt/devtools-kit': 1.7.0(magicast@0.3.5)(vite@7.2.2(@types/node@22.10.5)(jiti@2.6.1)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.8.2)) + '@nuxt/devtools-wizard': 1.7.0 + '@nuxt/kit': 3.15.4(magicast@0.3.5) + '@vue/devtools-core': 7.6.8(vite@7.2.2(@types/node@22.10.5)(jiti@2.6.1)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) + '@vue/devtools-kit': 7.6.8 + birpc: 0.2.19 + consola: 3.4.2 + cronstrue: 2.59.0 + destr: 2.0.5 + error-stack-parser-es: 0.1.5 + execa: 7.2.0 + fast-npm-meta: 0.2.2 + flatted: 3.3.3 + get-port-please: 3.2.0 + hookable: 5.5.3 + image-meta: 0.2.1 + is-installed-globally: 1.0.0 + launch-editor: 2.11.1 + local-pkg: 0.5.1 + magicast: 0.3.5 + nypm: 0.4.1 + ohash: 1.1.6 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + pkg-types: 1.3.1 + rc9: 2.1.2 + scule: 1.3.0 + semver: 7.7.3 + simple-git: 3.28.0 + sirv: 3.0.2 + tinyglobby: 0.2.15 + unimport: 3.14.6(rollup@4.54.0) + vite-plugin-inspect: 0.8.9(@nuxt/kit@3.15.4(magicast@0.3.5))(rollup@4.54.0)(vite@7.1.2(@types/node@22.10.5)(jiti@2.6.1)(less@4.2.2)(sass@1.85.0)(terser@5.43.1)(yaml@2.8.2)) + vite-plugin-vue-inspector: 5.3.2(vite@7.2.2(@types/node@22.10.5)(jiti@2.6.1)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.8.2)) + which: 3.0.1 + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - rollup + - supports-color + - utf-8-validate + - vue + '@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@3.29.5)': dependencies: '@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@3.29.5) @@ -18853,7 +18889,7 @@ snapshots: ignore: 6.0.2 jiti: 2.6.1 klona: 2.0.6 - knitwork: 1.2.0 + knitwork: 1.3.0 mlly: 1.8.0 pathe: 1.1.2 pkg-types: 1.3.1 @@ -18880,7 +18916,7 @@ snapshots: ignore: 6.0.2 jiti: 2.6.1 klona: 2.0.6 - knitwork: 1.2.0 + knitwork: 1.3.0 mlly: 1.8.0 pathe: 1.1.2 pkg-types: 1.3.1 @@ -18976,7 +19012,7 @@ snapshots: pathe: 1.1.2 pkg-types: 1.3.1 scule: 1.3.0 - std-env: 3.9.0 + std-env: 3.10.0 ufo: 1.6.1 uncrypto: 0.1.3 unimport: 3.14.6(rollup@3.29.5) @@ -18996,7 +19032,7 @@ snapshots: pathe: 1.1.2 pkg-types: 1.3.1 scule: 1.3.0 - std-env: 3.9.0 + std-env: 3.10.0 ufo: 1.6.1 uncrypto: 0.1.3 unimport: 3.14.6(rollup@4.54.0) @@ -19026,7 +19062,7 @@ snapshots: package-manager-detector: 1.3.0 pathe: 2.0.3 rc9: 2.1.2 - std-env: 3.9.0 + std-env: 3.10.0 transitivePeerDependencies: - magicast - supports-color @@ -19084,7 +19120,7 @@ snapshots: get-port-please: 3.2.0 h3: 1.15.4 jiti: 2.6.1 - knitwork: 1.2.0 + knitwork: 1.3.0 magic-string: 0.30.21 mlly: 1.8.0 ohash: 1.1.6 @@ -19093,7 +19129,7 @@ snapshots: pkg-types: 1.3.1 postcss: 8.5.6 rollup-plugin-visualizer: 5.14.0(rolldown@1.0.0-beta.57)(rollup@3.29.5) - std-env: 3.9.0 + std-env: 3.10.0 strip-literal: 2.1.1 ufo: 1.6.1 unenv: 1.10.0 @@ -19144,7 +19180,7 @@ snapshots: get-port-please: 3.2.0 h3: 1.15.4 jiti: 2.6.1 - knitwork: 1.2.0 + knitwork: 1.3.0 magic-string: 0.30.21 mlly: 1.8.0 ohash: 1.1.6 @@ -19153,7 +19189,7 @@ snapshots: pkg-types: 1.3.1 postcss: 8.5.6 rollup-plugin-visualizer: 5.14.0(rolldown@1.0.0-beta.57)(rollup@4.54.0) - std-env: 3.9.0 + std-env: 3.10.0 strip-literal: 2.1.1 ufo: 1.6.1 unenv: 1.10.0 @@ -19204,7 +19240,7 @@ snapshots: get-port-please: 3.2.0 h3: 1.15.4 jiti: 2.6.1 - knitwork: 1.2.0 + knitwork: 1.3.0 magic-string: 0.30.21 mlly: 1.8.0 ohash: 1.1.6 @@ -19213,7 +19249,7 @@ snapshots: pkg-types: 1.3.1 postcss: 8.5.6 rollup-plugin-visualizer: 5.14.0(rolldown@1.0.0-beta.57)(rollup@4.54.0) - std-env: 3.9.0 + std-env: 3.10.0 strip-literal: 2.1.1 ufo: 1.6.1 unenv: 1.10.0 @@ -21743,8 +21779,6 @@ snapshots: '@vue/shared@3.5.13': {} - '@vue/shared@3.5.21': {} - '@vue/shared@3.5.24': {} '@vue/shared@3.5.25': {} @@ -23112,7 +23146,8 @@ snapshots: detect-libc@1.0.3: {} - detect-libc@2.0.4: {} + detect-libc@2.0.4: + optional: true detect-libc@2.1.2: {} @@ -23678,8 +23713,8 @@ snapshots: '@typescript-eslint/parser': 8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3) eslint: 9.17.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.17.0(jiti@2.6.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.17.0(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.17.0(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@9.17.0(jiti@2.6.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.17.0(jiti@2.6.1)) @@ -23706,7 +23741,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.17.0(jiti@2.6.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 @@ -23717,22 +23752,22 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.17.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.17.0(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3) eslint: 9.17.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.17.0(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.17.0(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -23743,7 +23778,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.17.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.17.0(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.29.1(eslint@9.17.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)))(eslint@9.17.0(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -24928,7 +24963,7 @@ snapshots: mlly: 1.8.0 mocked-exports: 0.1.1 pathe: 2.0.3 - unplugin: 2.3.10 + unplugin: 2.3.11 transitivePeerDependencies: - rollup @@ -24938,7 +24973,7 @@ snapshots: mlly: 1.8.0 mocked-exports: 0.1.1 pathe: 2.0.3 - unplugin: 2.3.10 + unplugin: 2.3.11 transitivePeerDependencies: - rollup @@ -25763,10 +25798,6 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magic-string@0.30.19: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -26361,14 +26392,14 @@ snapshots: ioredis: 5.7.0 jiti: 2.6.1 klona: 2.0.6 - knitwork: 1.2.0 + knitwork: 1.3.0 listhen: 1.9.0 magic-string: 0.30.21 magicast: 0.3.5 mime: 4.0.7 mlly: 1.8.0 node-fetch-native: 1.6.7 - node-mock-http: 1.0.2 + node-mock-http: 1.0.4 ofetch: 1.5.1 ohash: 2.0.11 pathe: 2.0.3 @@ -26383,7 +26414,7 @@ snapshots: serve-placeholder: 2.0.2 serve-static: 2.2.0 source-map: 0.7.6 - std-env: 3.9.0 + std-env: 3.10.0 ufo: 1.6.1 ultrahtml: 1.6.0 uncrypto: 0.1.3 @@ -26592,7 +26623,7 @@ snapshots: '@unhead/shared': 1.11.20 '@unhead/ssr': 1.11.20 '@unhead/vue': 1.11.20(vue@3.5.25(typescript@5.9.3)) - '@vue/shared': 3.5.21 + '@vue/shared': 3.5.25 acorn: 8.14.0 c12: 2.0.1(magicast@0.3.5) chokidar: 4.0.3 @@ -26613,8 +26644,8 @@ snapshots: impound: 0.2.2(rollup@3.29.5) jiti: 2.6.1 klona: 2.0.6 - knitwork: 1.2.0 - magic-string: 0.30.19 + knitwork: 1.3.0 + magic-string: 0.30.21 mlly: 1.8.0 nanotar: 0.1.1 nitropack: 2.12.4(@netlify/blobs@9.1.2)(encoding@0.1.13)(rolldown@1.0.0-beta.57) @@ -26628,7 +26659,7 @@ snapshots: radix3: 1.1.2 scule: 1.3.0 semver: 7.7.3 - std-env: 3.9.0 + std-env: 3.10.0 strip-literal: 2.1.1 tinyglobby: 0.2.10 ufo: 1.6.1 @@ -26713,7 +26744,7 @@ snapshots: '@unhead/shared': 1.11.20 '@unhead/ssr': 1.11.20 '@unhead/vue': 1.11.20(vue@3.5.25(typescript@5.9.3)) - '@vue/shared': 3.5.21 + '@vue/shared': 3.5.25 acorn: 8.14.0 c12: 2.0.1(magicast@0.3.5) chokidar: 4.0.3 @@ -26734,8 +26765,8 @@ snapshots: impound: 0.2.2(rollup@4.54.0) jiti: 2.6.1 klona: 2.0.6 - knitwork: 1.2.0 - magic-string: 0.30.19 + knitwork: 1.3.0 + magic-string: 0.30.21 mlly: 1.8.0 nanotar: 0.1.1 nitropack: 2.12.4(@netlify/blobs@9.1.2)(encoding@0.1.13)(rolldown@1.0.0-beta.57) @@ -26749,7 +26780,128 @@ snapshots: radix3: 1.1.2 scule: 1.3.0 semver: 7.7.3 - std-env: 3.9.0 + std-env: 3.10.0 + strip-literal: 2.1.1 + tinyglobby: 0.2.10 + ufo: 1.6.1 + ultrahtml: 1.6.0 + uncrypto: 0.1.3 + unctx: 2.4.1 + unenv: 1.10.0 + unhead: 1.11.20 + unimport: 3.14.6(rollup@4.54.0) + unplugin: 1.16.1 + unplugin-vue-router: 0.10.9(rollup@4.54.0)(vue-router@4.5.0(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) + unstorage: 1.17.0(@netlify/blobs@9.1.2)(db0@0.3.2)(ioredis@5.7.0) + untyped: 1.5.2 + vue: 3.5.25(typescript@5.9.3) + vue-bundle-renderer: 2.1.2 + vue-devtools-stub: 0.1.0 + vue-router: 4.5.0(vue@3.5.25(typescript@5.9.3)) + optionalDependencies: + '@parcel/watcher': 2.5.1 + '@types/node': 22.10.5 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@biomejs/biome' + - '@capacitor/preferences' + - '@deno/kv' + - '@electric-sql/pglite' + - '@libsql/client' + - '@netlify/blobs' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - better-sqlite3 + - bufferutil + - db0 + - drizzle-orm + - encoding + - eslint + - idb-keyval + - ioredis + - less + - lightningcss + - magicast + - meow + - mysql2 + - optionator + - rolldown + - rollup + - sass + - sass-embedded + - sqlite3 + - stylelint + - stylus + - sugarss + - supports-color + - terser + - typescript + - uploadthing + - utf-8-validate + - vite + - vls + - vti + - vue-tsc + - xml2js + + nuxt@3.14.1592(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@22.10.5)(db0@0.3.2)(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.2.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.57)(rollup@4.54.0)(sass@1.85.0)(terser@5.43.1)(typescript@5.9.3): + dependencies: + '@nuxt/devalue': 2.0.2 + '@nuxt/devtools': 1.7.0(rollup@4.54.0)(vue@3.5.25(typescript@5.9.3)) + '@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.54.0) + '@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@4.54.0) + '@nuxt/telemetry': 2.6.6(magicast@0.3.5) + '@nuxt/vite-builder': 3.14.1592(@types/node@22.10.5)(eslint@9.39.1(jiti@2.6.1))(less@4.2.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.57)(rollup@4.54.0)(sass@1.85.0)(terser@5.43.1)(typescript@5.9.3)(vue@3.5.25(typescript@5.9.3)) + '@unhead/dom': 1.11.20 + '@unhead/shared': 1.11.20 + '@unhead/ssr': 1.11.20 + '@unhead/vue': 1.11.20(vue@3.5.25(typescript@5.9.3)) + '@vue/shared': 3.5.25 + acorn: 8.14.0 + c12: 2.0.1(magicast@0.3.5) + chokidar: 4.0.3 + compatx: 0.1.8 + consola: 3.4.2 + cookie-es: 1.2.2 + defu: 6.1.4 + destr: 2.0.5 + devalue: 5.3.2 + errx: 0.1.0 + esbuild: 0.24.2 + escape-string-regexp: 5.0.0 + estree-walker: 3.0.3 + globby: 14.1.0 + h3: 1.15.4 + hookable: 5.5.3 + ignore: 6.0.2 + impound: 0.2.2(rollup@4.54.0) + jiti: 2.6.1 + klona: 2.0.6 + knitwork: 1.3.0 + magic-string: 0.30.21 + mlly: 1.8.0 + nanotar: 0.1.1 + nitropack: 2.12.4(@netlify/blobs@9.1.2)(encoding@0.1.13)(rolldown@1.0.0-beta.57) + nuxi: 3.28.0 + nypm: 0.3.12 + ofetch: 1.5.1 + ohash: 1.1.6 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + pkg-types: 1.3.1 + radix3: 1.1.2 + scule: 1.3.0 + semver: 7.7.3 + std-env: 3.10.0 strip-literal: 2.1.1 tinyglobby: 0.2.10 ufo: 1.6.1 @@ -26834,7 +26986,7 @@ snapshots: '@unhead/shared': 1.11.20 '@unhead/ssr': 1.11.20 '@unhead/vue': 1.11.20(vue@3.5.25(typescript@5.9.3)) - '@vue/shared': 3.5.21 + '@vue/shared': 3.5.25 acorn: 8.14.0 c12: 2.0.1(magicast@0.3.5) chokidar: 4.0.3 @@ -26855,8 +27007,8 @@ snapshots: impound: 0.2.2(rollup@4.54.0) jiti: 2.6.1 klona: 2.0.6 - knitwork: 1.2.0 - magic-string: 0.30.19 + knitwork: 1.3.0 + magic-string: 0.30.21 mlly: 1.8.0 nanotar: 0.1.1 nitropack: 2.12.4(@netlify/blobs@9.1.2)(encoding@0.1.13)(rolldown@1.0.0-beta.57) @@ -26870,7 +27022,7 @@ snapshots: radix3: 1.1.2 scule: 1.3.0 semver: 7.7.3 - std-env: 3.9.0 + std-env: 3.10.0 strip-literal: 2.1.1 tinyglobby: 0.2.10 ufo: 1.6.1 @@ -26955,7 +27107,7 @@ snapshots: '@unhead/shared': 1.11.20 '@unhead/ssr': 1.11.20 '@unhead/vue': 1.11.20(vue@3.5.25(typescript@5.9.3)) - '@vue/shared': 3.5.21 + '@vue/shared': 3.5.25 acorn: 8.14.0 c12: 2.0.1(magicast@0.3.5) chokidar: 4.0.3 @@ -26976,8 +27128,8 @@ snapshots: impound: 0.2.2(rollup@4.54.0) jiti: 2.6.1 klona: 2.0.6 - knitwork: 1.2.0 - magic-string: 0.30.19 + knitwork: 1.3.0 + magic-string: 0.30.21 mlly: 1.8.0 nanotar: 0.1.1 nitropack: 2.12.4(@netlify/blobs@9.1.2)(encoding@0.1.13)(rolldown@1.0.0-beta.57) @@ -26991,7 +27143,7 @@ snapshots: radix3: 1.1.2 scule: 1.3.0 semver: 7.7.3 - std-env: 3.9.0 + std-env: 3.10.0 strip-literal: 2.1.1 tinyglobby: 0.2.10 ufo: 1.6.1 @@ -29831,7 +29983,7 @@ snapshots: scule: 1.3.0 strip-literal: 3.0.0 tinyglobby: 0.2.15 - unplugin: 2.3.10 + unplugin: 2.3.11 unplugin-utils: 0.2.5 unique-filename@4.0.0: @@ -29895,7 +30047,7 @@ snapshots: unplugin-vue-router@0.10.9(rollup@3.29.5)(vue-router@4.5.0(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)): dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@rollup/pluginutils': 5.2.0(rollup@3.29.5) '@vue-macros/common': 1.16.1(vue@3.5.25(typescript@5.9.3)) ast-walker-scope: 0.6.2 @@ -29917,7 +30069,7 @@ snapshots: unplugin-vue-router@0.10.9(rollup@4.54.0)(vue-router@4.5.0(vue@3.5.13(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)): dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@rollup/pluginutils': 5.2.0(rollup@4.54.0) '@vue-macros/common': 1.16.1(vue@3.5.25(typescript@5.9.3)) ast-walker-scope: 0.6.2 @@ -29939,7 +30091,7 @@ snapshots: unplugin-vue-router@0.10.9(rollup@4.54.0)(vue-router@4.5.0(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)): dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@rollup/pluginutils': 5.2.0(rollup@4.54.0) '@vue-macros/common': 1.16.1(vue@3.5.25(typescript@5.9.3)) ast-walker-scope: 0.6.2 @@ -30057,12 +30209,12 @@ snapshots: unwasm@0.3.11: dependencies: - knitwork: 1.2.0 + knitwork: 1.3.0 magic-string: 0.30.21 mlly: 1.8.0 pathe: 2.0.3 pkg-types: 2.3.0 - unplugin: 2.3.10 + unplugin: 2.3.11 update-browserslist-db@1.1.3(browserslist@4.25.4): dependencies: @@ -30899,7 +31051,7 @@ snapshots: webidl-conversions@7.0.0: {} - webpack-dev-middleware@7.4.2(webpack@5.98.0): + webpack-dev-middleware@7.4.2(webpack@5.98.0(esbuild@0.25.0)): dependencies: colorette: 2.0.20 memfs: 4.38.2 @@ -30910,7 +31062,7 @@ snapshots: optionalDependencies: webpack: 5.98.0(esbuild@0.25.0) - webpack-dev-server@5.2.0(webpack@5.98.0): + webpack-dev-server@5.2.0(webpack@5.98.0(esbuild@0.25.0)): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -30937,7 +31089,7 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.2(webpack@5.98.0) + webpack-dev-middleware: 7.4.2(webpack@5.98.0(esbuild@0.25.0)) ws: 8.18.3 optionalDependencies: webpack: 5.98.0(esbuild@0.25.0) @@ -30975,7 +31127,7 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.2(webpack@5.98.0) + webpack-dev-middleware: 7.4.2(webpack@5.98.0(esbuild@0.25.0)) ws: 8.18.3 optionalDependencies: webpack: 5.98.0(esbuild@0.25.0) -- 2.51.2 From b73309716fed69302140df4f41a8b0a8d27592d8 Mon Sep 17 00:00:00 2001 From: Lubos Date: Thu, 18 Dec 2025 02:21:06 +0800 Subject: [PATCH 04/15] chore: port operation classes function --- dev/openapi-ts.config.ts | 14 +- packages/codegen-core/src/files/file.ts | 8 +- packages/codegen-core/src/index.ts | 11 +- packages/codegen-core/src/nodes/context.d.ts | 12 +- packages/codegen-core/src/nodes/node.d.ts | 65 +++++++- packages/codegen-core/src/planner/analyzer.ts | 79 +++++++-- packages/codegen-core/src/planner/planner.ts | 10 +- packages/codegen-core/src/project/project.ts | 13 +- packages/codegen-core/src/refs/refs.ts | 16 +- packages/codegen-core/src/refs/types.d.ts | 6 +- packages/codegen-core/src/renderer.d.ts | 12 +- packages/codegen-core/src/symbols/symbol.ts | 40 +---- packages/codegen-core/src/symbols/types.d.ts | 2 - .../plugins/@hey-api/sdk/model/resource.ts | 150 +++++++++--------- .../plugins/@hey-api/sdk/model/structure.ts | 11 +- .../src/plugins/@hey-api/sdk/shared/class.ts | 2 - .../plugins/@pinia/colada/mutationOptions.ts | 13 +- .../src/plugins/@pinia/colada/queryOptions.ts | 13 +- .../src/plugins/@pinia/colada/v0/plugin.ts | 57 +------ .../query-core/v5/infiniteQueryOptions.ts | 13 +- .../query-core/v5/mutationOptions.ts | 13 +- .../plugins/@tanstack/query-core/v5/plugin.ts | 65 ++------ .../@tanstack/query-core/v5/queryOptions.ts | 13 +- .../src/plugins/shared/utils/instance.ts | 20 ++- .../openapi-ts/src/plugins/swr/v2/plugin.ts | 44 +---- .../openapi-ts/src/plugins/swr/v2/useSwr.ts | 13 +- packages/openapi-ts/src/ts-dsl/base.ts | 46 +++++- packages/openapi-ts/src/ts-dsl/decl/class.ts | 23 ++- .../openapi-ts/src/ts-dsl/decl/decorator.ts | 16 +- packages/openapi-ts/src/ts-dsl/decl/enum.ts | 17 +- packages/openapi-ts/src/ts-dsl/decl/field.ts | 15 +- packages/openapi-ts/src/ts-dsl/decl/func.ts | 24 ++- packages/openapi-ts/src/ts-dsl/decl/getter.ts | 16 +- packages/openapi-ts/src/ts-dsl/decl/member.ts | 13 +- packages/openapi-ts/src/ts-dsl/decl/method.ts | 20 +-- packages/openapi-ts/src/ts-dsl/decl/param.ts | 22 +-- packages/openapi-ts/src/ts-dsl/decl/setter.ts | 14 +- packages/openapi-ts/src/ts-dsl/expr/as.ts | 6 +- packages/openapi-ts/src/ts-dsl/expr/attr.ts | 40 ++--- packages/openapi-ts/src/ts-dsl/expr/await.ts | 4 +- packages/openapi-ts/src/ts-dsl/expr/binary.ts | 4 +- packages/openapi-ts/src/ts-dsl/expr/call.ts | 4 +- packages/openapi-ts/src/ts-dsl/expr/expr.ts | 4 +- packages/openapi-ts/src/ts-dsl/expr/id.ts | 6 +- .../openapi-ts/src/ts-dsl/expr/literal.ts | 11 +- packages/openapi-ts/src/ts-dsl/expr/new.ts | 4 +- packages/openapi-ts/src/ts-dsl/expr/object.ts | 6 +- packages/openapi-ts/src/ts-dsl/expr/prop.ts | 14 +- .../openapi-ts/src/ts-dsl/expr/template.ts | 8 +- packages/openapi-ts/src/ts-dsl/index.ts | 1 + packages/openapi-ts/src/ts-dsl/mixins/args.ts | 4 +- .../openapi-ts/src/ts-dsl/mixins/decorator.ts | 6 +- .../openapi-ts/src/ts-dsl/mixins/operator.ts | 4 +- .../openapi-ts/src/ts-dsl/mixins/param.ts | 11 +- .../openapi-ts/src/ts-dsl/mixins/type-args.ts | 4 +- .../src/ts-dsl/mixins/type-params.ts | 17 +- .../src/ts-dsl/mixins/type-returns.ts | 12 +- .../render/__tests__/typescript.test.ts | 15 +- .../src/ts-dsl/render/typescript.ts | 26 +-- packages/openapi-ts/src/ts-dsl/stmt/return.ts | 4 +- packages/openapi-ts/src/ts-dsl/stmt/try.ts | 8 +- packages/openapi-ts/src/ts-dsl/stmt/var.ts | 14 +- packages/openapi-ts/src/ts-dsl/type/alias.ts | 17 +- packages/openapi-ts/src/ts-dsl/type/and.ts | 6 +- packages/openapi-ts/src/ts-dsl/type/attr.ts | 8 +- packages/openapi-ts/src/ts-dsl/type/expr.ts | 15 +- packages/openapi-ts/src/ts-dsl/type/func.ts | 7 +- .../openapi-ts/src/ts-dsl/type/idx-sig.ts | 21 +-- packages/openapi-ts/src/ts-dsl/type/idx.ts | 7 +- .../openapi-ts/src/ts-dsl/type/literal.ts | 7 +- packages/openapi-ts/src/ts-dsl/type/mapped.ts | 26 ++- packages/openapi-ts/src/ts-dsl/type/object.ts | 7 +- .../openapi-ts/src/ts-dsl/type/operator.ts | 7 +- packages/openapi-ts/src/ts-dsl/type/or.ts | 6 +- packages/openapi-ts/src/ts-dsl/type/param.ts | 15 +- packages/openapi-ts/src/ts-dsl/type/prop.ts | 19 +-- packages/openapi-ts/src/ts-dsl/type/query.ts | 7 +- .../openapi-ts/src/ts-dsl/type/template.ts | 7 +- packages/openapi-ts/src/ts-dsl/type/tuple.ts | 7 +- .../openapi-ts/src/ts-dsl/utils/context.ts | 113 +++++++++++++ packages/openapi-ts/src/ts-dsl/utils/lazy.ts | 8 +- packages/openapi-ts/src/ts-dsl/utils/name.ts | 34 +++- 82 files changed, 866 insertions(+), 656 deletions(-) create mode 100644 packages/openapi-ts/src/ts-dsl/utils/context.ts diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index 43c6111f9..3a07fd1ba 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -43,8 +43,8 @@ export default defineConfig(() => { // 'circular.yaml', // 'dutchie.json', // 'enum-names-values.yaml', - // 'full.yaml', - 'integer-formats.yaml', + 'full.yaml', + // 'integer-formats.yaml', // 'invalid', // 'object-property-names.yaml', // 'openai.yaml', @@ -54,7 +54,7 @@ export default defineConfig(() => { // 'sdk-instance.yaml', // 'sdk-method-class-conflict.yaml', // 'sdk-nested-classes.yaml', - 'sdk-nested-conflict.yaml', + // 'sdk-nested-conflict.yaml', // 'string-with-format.yaml', // 'transformers.json', // 'transformers-recursive.json', @@ -240,7 +240,7 @@ export default defineConfig(() => { { // baseUrl: false, // exportFromIndex: true, - name: '@hey-api/client-nuxt', + // name: '@hey-api/client-nuxt', // runtimeConfigPath: path.resolve(__dirname, 'hey-api.ts'), // runtimeConfigPath: './src/hey-api.ts', // strictBaseUrl: true, @@ -285,8 +285,8 @@ export default defineConfig(() => { // fields.unwrap('path') // }, // include... - // instance: 'Root', - methodNameBuilder: '{{name}}Methods', + instance: 'Root', + methodNameBuilder: '{{name}}', name: '@hey-api/sdk', // operationId: false, // paramsStructure: 'flat', @@ -349,7 +349,7 @@ export default defineConfig(() => { // name: '{{name}}MO', // name: 'options', }, - // name: '@tanstack/react-query', + name: '@tanstack/react-query', queryKeys: { // name: '{{name}}QK', // name: 'options', diff --git a/packages/codegen-core/src/files/file.ts b/packages/codegen-core/src/files/file.ts index adb37dcc9..14c040ff2 100644 --- a/packages/codegen-core/src/files/file.ts +++ b/packages/codegen-core/src/files/file.ts @@ -10,7 +10,7 @@ import type { IProject } from '../project/types'; import type { Renderer } from '../renderer'; import type { IFileIn } from './types'; -export class File { +export class File { /** * Exports from this file. */ @@ -42,7 +42,7 @@ export class File { /** * Syntax nodes contained in this file. */ - private _nodes: Array = []; + private _nodes: Array = []; /** * Renderer assigned to this file. */ @@ -142,7 +142,7 @@ export class File { /** * Syntax nodes contained in this file. */ - get nodes(): ReadonlyArray { + get nodes(): ReadonlyArray { return [...this._nodes]; } @@ -170,7 +170,7 @@ export class File { /** * Add a syntax node to the file. */ - addNode(node: INode): void { + addNode(node: Node): void { this._nodes.push(node); node.file = this; } diff --git a/packages/codegen-core/src/index.ts b/packages/codegen-core/src/index.ts index d0e46d8d2..b5659b96c 100644 --- a/packages/codegen-core/src/index.ts +++ b/packages/codegen-core/src/index.ts @@ -21,7 +21,16 @@ export type { NameConflictResolvers, } from './languages/types'; export type { AstContext } from './nodes/context'; -export type { INode as Node } from './nodes/node'; +export type { + AccessPatternContext, + AccessPatternOptions, + INode as Node, + NodeName, + NodeNameSanitizer, + NodeRole, + NodeScope, + StructuralRelationship, +} from './nodes/node'; export type { IOutput as Output } from './output'; export { simpleNameConflictResolver, diff --git a/packages/codegen-core/src/nodes/context.d.ts b/packages/codegen-core/src/nodes/context.d.ts index 08b33d21d..733c7d871 100644 --- a/packages/codegen-core/src/nodes/context.d.ts +++ b/packages/codegen-core/src/nodes/context.d.ts @@ -1,11 +1,15 @@ -import type { INode } from './node'; +import type { Symbol } from '../symbols/symbol'; +import type { AccessPatternOptions, INode } from './node'; /** * Context passed to `.toAst()` methods. */ -export type AstContext = { +export interface AstContext { /** * Returns the canonical node for accessing the provided node. */ - getAccess(node: T): T; -}; + getAccess( + node: INode | Symbol, + options?: AccessPatternOptions, + ): T; +} diff --git a/packages/codegen-core/src/nodes/node.d.ts b/packages/codegen-core/src/nodes/node.d.ts index d120e498b..137c9b8f5 100644 --- a/packages/codegen-core/src/nodes/node.d.ts +++ b/packages/codegen-core/src/nodes/node.d.ts @@ -1,10 +1,54 @@ import type { File } from '../files/file'; import type { Language } from '../languages/types'; import type { IAnalysisContext } from '../planner/types'; +import type { Ref } from '../refs/types'; import type { Symbol } from '../symbols/symbol'; import type { AstContext } from './context'; +export type AccessContext = 'docs' | 'runtime'; + +export interface AccessPatternContext { + /** The full chain. */ + chain: ReadonlyArray; + /** Position in the chain (0 = root). */ + index: number; + /** Is this the leaf node? */ + isLeaf: boolean; + /** Is this the root node? */ + isRoot: boolean; + /** Total length of the chain. */ + length: number; +} + +export interface AccessPatternOptions { + /** The access context. */ + context: AccessContext; +} + +export type MaybeRef = T | Ref; + +export type NodeName = MaybeRef; + +export type NodeNameSanitizer = (name: string) => string; + +export type NodeRole = + | 'accessor' + | 'container' + | 'control-flow' + | 'expression' + | 'literal'; + +export type NodeScope = 'type' | 'value'; + +export type StructuralRelationship = 'container' | 'reference'; + export interface INode { + /** Custom access pattern for this node. */ + accessPattern?( + node: this, + options: AccessPatternOptions, + ctx: AccessPatternContext, + ): unknown | undefined; /** Perform semantic analysis. */ analyze(ctx: IAnalysisContext): void; /** Whether this node is exported from its file. */ @@ -13,10 +57,23 @@ export interface INode { file?: File; /** The programming language associated with this node */ language: Language; - /** Parent node in the syntax tree. */ - parent?: INode; - /** Root node of the syntax tree. */ - root?: INode; + /** The display name of this node. */ + readonly name: Ref & { + set(value: NodeName): void; + toString(): string; + }; + /** Optional function to sanitize the node name. */ + readonly nameSanitizer?: NodeNameSanitizer; + /** The role of this node within the structure. */ + role?: NodeRole; + /** Whether this node is a root node in the file. */ + root?: boolean; + /** The scope of this node. */ + scope?: NodeScope; + /** Semantic children in the structure hierarchy. */ + structuralChildren?: Map; + /** Semantic parents in the structure hierarchy. */ + structuralParents?: Map; /** The symbol associated with this node. */ symbol?: Symbol; /** Convert this node into AST representation. */ diff --git a/packages/codegen-core/src/planner/analyzer.ts b/packages/codegen-core/src/planner/analyzer.ts index 7a9900165..8231ecc0f 100644 --- a/packages/codegen-core/src/planner/analyzer.ts +++ b/packages/codegen-core/src/planner/analyzer.ts @@ -1,5 +1,5 @@ import { isNodeRef, isSymbolRef } from '../guards'; -import type { INode } from '../nodes/node'; +import type { INode, StructuralRelationship } from '../nodes/node'; import { fromRef, isRef, ref } from '../refs/refs'; import type { Ref } from '../refs/types'; import type { Symbol } from '../symbols/symbol'; @@ -8,13 +8,49 @@ import { createScope } from './scope'; import type { IAnalysisContext, Input } from './types'; export class AnalysisContext implements IAnalysisContext { + /** + * Stack of parent nodes during analysis. + * + * The top of the stack is the current semantic container. + */ + private _parentStack: Array = []; + scope: Scope; scopes: Scope = createScope(); symbol?: Symbol; - constructor(symbol?: Symbol) { + constructor(node: INode) { + this._parentStack.push(node); this.scope = this.scopes; - this.symbol = symbol; + this.symbol = node.symbol; + } + + /** + * Get the current semantic parent (top of stack). + */ + get currentParent(): INode | undefined { + return this._parentStack[this._parentStack.length - 1]; + } + + /** + * Register a child node under the current parent. + */ + addChild( + child: INode, + relationship: StructuralRelationship = 'container', + ): void { + const parent = this.currentParent; + if (!parent) return; + + if (!parent.structuralChildren) { + parent.structuralChildren = new Map(); + } + parent.structuralChildren.set(child, relationship); + + if (!child.structuralParents) { + child.structuralParents = new Map(); + } + child.structuralParents.set(parent, relationship); } addDependency(symbol: Ref): void { @@ -24,11 +60,20 @@ export class AnalysisContext implements IAnalysisContext { } analyze(input: Input): void { - const v = isRef(input) ? input : ref(input); - if (isSymbolRef(v)) { - this.addDependency(v); - } else if (isNodeRef(v)) { - fromRef(v).analyze(this); + const value = isRef(input) ? input : ref(input); + if (isSymbolRef(value)) { + const symbol = fromRef(value); + // avoid adding self as child + if (symbol.node && this.currentParent !== symbol.node) { + this.addChild(symbol.node, 'reference'); + } + this.addDependency(value); + } else if (isNodeRef(value)) { + const node = fromRef(value); + this.addChild(node, 'container'); + this.pushParent(node); + node.analyze(this); + this.popParent(); } } @@ -53,10 +98,25 @@ export class AnalysisContext implements IAnalysisContext { return names; } + /** + * Pop the current semantic parent. + * Call this when exiting a container node. + */ + popParent(): void { + this._parentStack.pop(); + } + popScope(): void { this.scope = this.scope.parent ?? this.scope; } + /** + * Push a node as the current semantic parent. + */ + pushParent(node: INode): void { + this._parentStack.push(node); + } + pushScope(): void { const scope = createScope({ parent: this.scope }); this.scope.children.push(scope); @@ -86,7 +146,8 @@ export class Analyzer { const cached = this.nodeCache.get(node); if (cached) return cached; - const ctx = new AnalysisContext(node.symbol); + node.root = true; + const ctx = new AnalysisContext(node); node.analyze(ctx); this.nodeCache.set(node, ctx); diff --git a/packages/codegen-core/src/planner/planner.ts b/packages/codegen-core/src/planner/planner.ts index 4938a23b5..8e50ef4d8 100644 --- a/packages/codegen-core/src/planner/planner.ts +++ b/packages/codegen-core/src/planner/planner.ts @@ -113,11 +113,7 @@ export class Planner { if (finalPath) { file.setFinalPath(path.resolve(this.project.root, finalPath)); } - const ctx: Omit = { - file, - meta, - project: this.project, - }; + const ctx: RenderContext = { file, meta, project: this.project }; const renderer = this.project.renderers.find((r) => r.supports(ctx)); if (renderer) file.setRenderer(renderer); } @@ -401,7 +397,7 @@ export class Planner { if (this.cacheResolvedNames.has(symbol.id)) return; const baseName = symbol.name; - let finalName = symbol.nameSanitizer?.(baseName) ?? baseName; + let finalName = symbol.node?.nameSanitizer?.(baseName) ?? baseName; let attempt = 1; const localNames = ctx.localNames(scope); @@ -420,7 +416,7 @@ export class Planner { throw new Error(`Unresolvable name conflict: ${symbol.toString()}`); } - finalName = symbol.nameSanitizer?.(resolvedName) ?? resolvedName; + finalName = symbol.node?.nameSanitizer?.(resolvedName) ?? resolvedName; attempt = attempt + 1; } diff --git a/packages/codegen-core/src/project/project.ts b/packages/codegen-core/src/project/project.ts index 187316825..d31f5bb60 100644 --- a/packages/codegen-core/src/project/project.ts +++ b/packages/codegen-core/src/project/project.ts @@ -5,7 +5,6 @@ import { FileRegistry } from '../files/registry'; import { defaultExtensions } from '../languages/extensions'; import { defaultNameConflictResolvers } from '../languages/resolvers'; import type { Extensions, NameConflictResolvers } from '../languages/types'; -import type { AstContext } from '../nodes/context'; import { NodeRegistry } from '../nodes/registry'; import type { IOutput } from '../output'; import { Planner } from '../planner/planner'; @@ -61,19 +60,9 @@ export class Project implements IProject { render(meta?: IProjectRenderMeta): ReadonlyArray { new Planner(this).plan(meta); const files: Array = []; - const astContext: AstContext = { - getAccess(node) { - return node; - }, - }; for (const file of this.files.registered()) { if (file.finalPath && file.renderer) { - const content = file.renderer.render({ - astContext, - file, - meta, - project: this, - }); + const content = file.renderer.render({ file, meta, project: this }); files.push({ content, path: file.finalPath }); } } diff --git a/packages/codegen-core/src/refs/refs.ts b/packages/codegen-core/src/refs/refs.ts index c5797bc92..f34c4cfc3 100644 --- a/packages/codegen-core/src/refs/refs.ts +++ b/packages/codegen-core/src/refs/refs.ts @@ -1,15 +1,24 @@ -import type { FromRefs, Ref, Refs } from './types'; +import type { FromRef, FromRefs, Ref, Refs } from './types'; /** * Wraps a single value in a Ref object. * + * If the value is already a Ref, returns it as-is (idempotent). + * * @example * ```ts * const r = ref(123); // { '~ref': 123 } * console.log(r['~ref']); // 123 + * + * const r2 = ref(r); // { '~ref': 123 } (not double-wrapped) * ``` */ -export const ref = (value: T): Ref => ({ '~ref': value }); +export const ref = (value: T): Ref => { + if (isRef(value)) { + return value as Ref; + } + return { '~ref': value } as Ref; +}; /** * Converts a plain object to an object of Refs (deep, per property). @@ -42,8 +51,7 @@ export const refs = >(obj: T): Refs => { */ export const fromRef = | undefined>( ref: T, -): T extends Ref ? U : undefined => - ref?.['~ref'] as T extends Ref ? U : undefined; +): FromRef => ref?.['~ref'] as FromRef; /** * Converts an object of Refs back to a plain object (unwraps all refs). diff --git a/packages/codegen-core/src/refs/types.d.ts b/packages/codegen-core/src/refs/types.d.ts index f5b76fbeb..c52830329 100644 --- a/packages/codegen-core/src/refs/types.d.ts +++ b/packages/codegen-core/src/refs/types.d.ts @@ -8,7 +8,7 @@ * console.log(num['~ref']); // 42 * ``` */ -export type Ref = { '~ref': T }; +export type Ref = T extends { ['~ref']: unknown } ? T : { '~ref': T }; /** * Maps every property of `T` to a `Ref` of that property. @@ -33,7 +33,7 @@ export type Refs = { * type N = FromRef<{ '~ref': number }>; // number * ``` */ -export type FromRef = T extends Ref ? V : T; +export type FromRef = T extends { '~ref': infer U } ? U : T; /** * Maps every property of a Ref-wrapped object back to its plain value. @@ -46,5 +46,5 @@ export type FromRef = T extends Ref ? V : T; * ``` */ export type FromRefs = { - [K in keyof T]: T[K] extends Ref ? V : T[K]; + [K in keyof T]: T[K] extends Ref ? U : T[K]; }; diff --git a/packages/codegen-core/src/renderer.d.ts b/packages/codegen-core/src/renderer.d.ts index 758626c56..ceee414c0 100644 --- a/packages/codegen-core/src/renderer.d.ts +++ b/packages/codegen-core/src/renderer.d.ts @@ -1,17 +1,13 @@ import type { IProjectRenderMeta } from './extensions'; import type { File } from './files/file'; -import type { AstContext } from './nodes/context'; +import type { INode } from './nodes/node'; import type { IProject } from './project/types'; -export interface RenderContext { - /** - * The context passed to `.toAst()` methods. - */ - astContext: AstContext; +export interface RenderContext { /** * The current file. */ - file: File; + file: File; /** * Arbitrary metadata. */ @@ -26,5 +22,5 @@ export interface Renderer { /** Renders the given file. */ render(ctx: RenderContext): string; /** Returns whether this renderer can render the given file. */ - supports(ctx: Omit): boolean; + supports(ctx: RenderContext): boolean; } diff --git a/packages/codegen-core/src/symbols/symbol.ts b/packages/codegen-core/src/symbols/symbol.ts index 726f4dc59..0517ca3e7 100644 --- a/packages/codegen-core/src/symbols/symbol.ts +++ b/packages/codegen-core/src/symbols/symbol.ts @@ -3,14 +3,9 @@ import { debug } from '../debug'; import type { ISymbolMeta } from '../extensions'; import type { File } from '../files/file'; import type { INode } from '../nodes/node'; -import type { - BindingKind, - ISymbolIn, - SymbolKind, - SymbolNameSanitizer, -} from './types'; +import type { BindingKind, ISymbolIn, SymbolKind } from './types'; -export class Symbol { +export class Symbol { /** * Canonical symbol this stub resolves to, if any. * @@ -78,16 +73,10 @@ export class Symbol { * @example "UserModel" */ private _name: string; - /** - * Optional function to sanitize the symbol name. - * - * @default undefined - */ - private _nameSanitizer?: SymbolNameSanitizer; /** * Node that defines this symbol. */ - private _node?: INode; + private _node?: Node; /** Brand used for identifying symbols. */ readonly '~brand' = symbolBrand; @@ -201,18 +190,11 @@ export class Symbol { return this.canonical._name; } - /** - * Optional function to sanitize the symbol name. - */ - get nameSanitizer(): SymbolNameSanitizer | undefined { - return this.canonical._nameSanitizer; - } - /** * Read‑only accessor for the defining node. */ - get node(): INode | undefined { - return this.canonical._node; + get node(): Node | undefined { + return this.canonical._node as Node | undefined; } /** @@ -307,22 +289,12 @@ export class Symbol { this._name = name; } - /** - * Sets a custom function to sanitize the symbol's name. - * - * @param fn — The name sanitizer function to apply. - */ - setNameSanitizer(fn: SymbolNameSanitizer): void { - this.assertCanonical(); - this._nameSanitizer = fn; - } - /** * Binds the node that defines this symbol. * * This may only be set once. */ - setNode(node: INode): void { + setNode(node: Node): void { this.assertCanonical(); if (this._node && this._node !== node) { const message = `Symbol ${this.canonical.toString()} is already bound to a different node.`; diff --git a/packages/codegen-core/src/symbols/types.d.ts b/packages/codegen-core/src/symbols/types.d.ts index 2249cf29b..9992320fd 100644 --- a/packages/codegen-core/src/symbols/types.d.ts +++ b/packages/codegen-core/src/symbols/types.d.ts @@ -14,8 +14,6 @@ export type SymbolKind = | 'type' | 'var'; -export type SymbolNameSanitizer = (name: string) => string; - export type ISymbolIn = { /** * Array of file names (without extensions) from which this symbol is re-exported. diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts index 61e016b32..4b1fd8436 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts @@ -120,7 +120,12 @@ export class SdkResourceModel { const { node, symbol: symbolClass } = this.classToNode(plugin); if (this.isRoot && plugin.config.instance) { - node.do(...this.rootClassToNode(symbolClass, dependencies, plugin)); + this.enrichRootClass({ + dependencies, + node, + plugin, + symbol: symbolClass, + }); } this.operations.forEach((event, index) => { @@ -286,6 +291,79 @@ export class SdkResourceModel { return { node, symbol }; } + private enrichRootClass(args: { + dependencies: Array>; + node: ReturnType; + plugin: HeyApiSdkPlugin['Instance']; + symbol: Symbol; + }): void { + const { dependencies, node, plugin, symbol } = args; + const symbolClient = plugin.symbol('HeyApiClient', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiClient', + tool: 'sdk', + }, + }); + dependencies.push(createClientClass({ plugin, symbol: symbolClient })); + const symbolRegistry = plugin.symbol('HeyApiRegistry', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiRegistry', + tool: 'sdk', + }, + }); + dependencies.push( + createRegistryClass({ + plugin, + sdkSymbol: symbol, + symbol: symbolRegistry, + }), + ); + const isClientRequired = + !plugin.config.client || !plugin.getSymbol({ category: 'client' }); + const registry = plugin.symbol('__registry'); + node.accessPattern = (node) => + $(node.name).attr(registry).attr('get').call(); + node.do( + $.field(registry, (f) => + f + .public() + .static() + .readonly() + .assign($.new(symbolRegistry).generic(symbol)), + ), + $.newline(), + $.init((i) => + i + .param('args', (p) => + p.required(isClientRequired).type( + $.type + .object() + .prop('client', (p) => + p.required(isClientRequired).type( + plugin.referenceSymbol({ + category: 'external', + resource: 'client.Client', + }), + ), + ) + .prop('key', (p) => p.optional().type('string')), + ), + ) + .do( + $('super').call('args'), + $(symbol) + .attr(registry) + .attr('set') + .call('this', $('args').attr('key').required(isClientRequired)), + ), + ), + ); + } + private implementFn< T extends ReturnType, >(args: { @@ -352,74 +430,4 @@ export class SdkResourceModel { .params(...opParameters.parameters) .do(...statements) as T; } - - private rootClassToNode( - symbol: Symbol, - dependencies: Array>, - plugin: HeyApiSdkPlugin['Instance'], - ): ReadonlyArray< - ReturnType - > { - const symbolClient = plugin.symbol('HeyApiClient', { - meta: { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiClient', - tool: 'sdk', - }, - }); - dependencies.push(createClientClass({ plugin, symbol: symbolClient })); - const symbolRegistry = plugin.symbol('HeyApiRegistry', { - meta: { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiRegistry', - tool: 'sdk', - }, - }); - dependencies.push( - createRegistryClass({ - plugin, - sdkSymbol: symbol, - symbol: symbolRegistry, - }), - ); - const isClientRequired = - !plugin.config.client || !plugin.getSymbol({ category: 'client' }); - return [ - $.field('__registry', (f) => - f - .public() - .static() - .readonly() - .assign($.new(symbolRegistry).generic(symbol)), - ), - $.newline(), - $.init((i) => - i - .param('args', (p) => - p.required(isClientRequired).type( - $.type - .object() - .prop('client', (p) => - p.required(isClientRequired).type( - plugin.referenceSymbol({ - category: 'external', - resource: 'client.Client', - }), - ), - ) - .prop('key', (p) => p.optional().type('string')), - ), - ) - .do( - $('super').call('args'), - $(symbol) - .attr('__registry') - .attr('set') - .call('this', $('args').attr('key').required(isClientRequired)), - ), - ), - ]; - } } diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts index f99ca35f8..91b7553b8 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts @@ -7,9 +7,8 @@ export class SdkStructureModel { private _flat: boolean; /** Name of the SDK. If empty, we fallback to operation tags. */ private _name: string; - /** Root resources mapped by their names. */ - roots: Map = new Map(); + private _roots: Map = new Map(); constructor( name: string, @@ -52,10 +51,10 @@ export class SdkStructureModel { * @returns The root resource instance */ root(name: string): SdkResourceModel { - if (!this.roots.has(name)) { - this.roots.set(name, new SdkResourceModel(name)); + if (!this._roots.has(name)) { + this._roots.set(name, new SdkResourceModel(name)); } - return this.roots.get(name)!; + return this._roots.get(name)!; } /** @@ -64,7 +63,7 @@ export class SdkStructureModel { * Yields all resources in the structure. */ *walk(): Generator { - for (const resource of this.roots.values()) { + for (const resource of this._roots.values()) { yield* resource.walk(); } } diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts index 666c03018..3906b8904 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts @@ -4,8 +4,6 @@ import { $ } from '~/ts-dsl'; import type { HeyApiSdkPlugin } from '../types'; -export const registryName = '__registry'; - export const createRegistryClass = ({ plugin, sdkSymbol, diff --git a/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts b/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts index c586ed9f3..1b262bc77 100644 --- a/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts +++ b/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts @@ -12,11 +12,9 @@ import { getPublicTypeData } from './utils'; export const createMutationOptions = ({ operation, plugin, - queryFn, }: { operation: IR.OperationObject; plugin: PiniaColadaPlugin['Instance']; - queryFn: ReturnType; }): void => { const symbolMutationOptionsType = plugin.referenceSymbol({ category: 'external', @@ -31,8 +29,15 @@ export const createMutationOptions = ({ const options = plugin.symbol('options'); const fnOptions = plugin.symbol('vars'); - const awaitSdkFn = $.lazy(() => - $(queryFn) + const awaitSdkFn = $.lazy((ctx) => + ctx + .getAccess>( + plugin.referenceSymbol({ + category: 'sdk', + resource: 'operation', + resourceId: operation.id, + }), + ) .call( $.object() .pretty() diff --git a/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts b/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts index 314fdba5a..fa618a150 100644 --- a/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts +++ b/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts @@ -23,11 +23,9 @@ const fnOptions = 'context'; export const createQueryOptions = ({ operation, plugin, - queryFn, }: { operation: IR.OperationObject; plugin: PiniaColadaPlugin['Instance']; - queryFn: ReturnType; }): void => { if (hasOperationSse({ operation })) { return; @@ -88,8 +86,15 @@ export const createQueryOptions = ({ const client = getClientPlugin(plugin.context.config); const isNuxtClient = client.name === '@hey-api/client-nuxt'; const typeData = getPublicTypeData({ isNuxtClient, operation, plugin }); - const awaitSdkFn = $.lazy(() => - $(queryFn) + const awaitSdkFn = $.lazy((ctx) => + ctx + .getAccess>( + plugin.referenceSymbol({ + category: 'sdk', + resource: 'operation', + resourceId: operation.id, + }), + ) .call( $.object() .spread(optionsParamName) diff --git a/packages/openapi-ts/src/plugins/@pinia/colada/v0/plugin.ts b/packages/openapi-ts/src/plugins/@pinia/colada/v0/plugin.ts index adb41fbb4..637ec54e1 100644 --- a/packages/openapi-ts/src/plugins/@pinia/colada/v0/plugin.ts +++ b/packages/openapi-ts/src/plugins/@pinia/colada/v0/plugin.ts @@ -1,103 +1,60 @@ -import { registryName } from '~/plugins/@hey-api/sdk/shared/class'; -import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; -import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/to-case'; - import { createMutationOptions } from '../mutationOptions'; import { createQueryOptions } from '../queryOptions'; import type { PiniaColadaPlugin } from '../types'; export const handlerV0: PiniaColadaPlugin['Handler'] = ({ plugin }) => { - plugin.registerSymbol({ + plugin.symbol('defineQueryOptions', { external: plugin.name, meta: { category: 'external', resource: `${plugin.name}.defineQueryOptions`, }, - name: 'defineQueryOptions', }); - plugin.registerSymbol({ + plugin.symbol('UseMutationOptions', { external: plugin.name, kind: 'type', meta: { category: 'external', resource: `${plugin.name}.UseMutationOptions`, }, - name: 'UseMutationOptions', }); - plugin.registerSymbol({ + plugin.symbol('UseQueryOptions', { external: plugin.name, kind: 'type', meta: { category: 'external', resource: `${plugin.name}.UseQueryOptions`, }, - name: 'UseQueryOptions', }); - plugin.registerSymbol({ + plugin.symbol('_JSONValue', { external: plugin.name, kind: 'type', meta: { category: 'external', resource: `${plugin.name}._JSONValue`, }, - name: '_JSONValue', }); - plugin.registerSymbol({ + plugin.symbol('AxiosError', { external: 'axios', kind: 'type', meta: { category: 'external', resource: 'axios.AxiosError', }, - name: 'AxiosError', }); - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); - plugin.forEach( 'operation', ({ operation }) => { - const classes = sdkPlugin.config.asClass - ? operationClasses({ operation, plugin: sdkPlugin }) - : undefined; - const entry = classes ? classes.values().next().value : undefined; - // TODO: this should use class graph to determine correct path string - // as it's really easy to break once we change the class casing - let queryFn: ReturnType; - if (entry) { - const symbolClass = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: entry.path[0], - tool: 'sdk', - }); - queryFn = $(symbolClass).$if(sdkPlugin.config.instance, (e) => - e.attr(registryName).attr('get').call(), - ); - for (const className of entry.path.slice(1)) { - const cls = toCase(className, 'camelCase'); - queryFn = queryFn.attr(cls); - } - queryFn = queryFn.attr(entry.methodName); - } else { - const symbol = plugin.referenceSymbol({ - category: 'sdk', - resource: 'operation', - resourceId: operation.id, - }); - queryFn = $(symbol); - } - if (plugin.hooks.operation.isQuery(operation)) { if (plugin.config.queryOptions.enabled) { - createQueryOptions({ operation, plugin, queryFn }); + createQueryOptions({ operation, plugin }); } } if (plugin.hooks.operation.isMutation(operation)) { if (plugin.config.mutationOptions.enabled) { - createMutationOptions({ operation, plugin, queryFn }); + createMutationOptions({ operation, plugin }); } } }, diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts index 570e3599f..625ff5f38 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts @@ -106,11 +106,9 @@ const createInfiniteParamsFunction = ({ export const createInfiniteQueryOptions = ({ operation, plugin, - queryFn, }: { operation: IR.OperationObject; plugin: PluginInstance; - queryFn: ReturnType; }): void => { const pagination = operationPagination({ context: plugin.context, @@ -198,8 +196,15 @@ export const createInfiniteQueryOptions = ({ }); plugin.node(node); - const awaitSdkFn = $.lazy(() => - $(queryFn) + const awaitSdkFn = $.lazy((ctx) => + ctx + .getAccess>( + plugin.referenceSymbol({ + category: 'sdk', + resource: 'operation', + resourceId: operation.id, + }), + ) .call( $.object() .spread('options') diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts index 406e43202..22b822847 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts @@ -11,11 +11,9 @@ import type { PluginInstance } from '../types'; export const createMutationOptions = ({ operation, plugin, - queryFn, }: { operation: IR.OperationObject; plugin: PluginInstance; - queryFn: ReturnType; }): void => { const symbolMutationOptionsType = plugin.referenceSymbol({ category: 'external', @@ -30,8 +28,15 @@ export const createMutationOptions = ({ const fnOptions = 'fnOptions'; - const awaitSdkFn = $.lazy(() => - $(queryFn) + const awaitSdkFn = $.lazy((ctx) => + ctx + .getAccess>( + plugin.referenceSymbol({ + category: 'sdk', + resource: 'operation', + resourceId: operation.id, + }), + ) .call( $.object() .spread('options') diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/plugin.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/plugin.ts index 601eefdb3..722bb821a 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/plugin.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/plugin.ts @@ -1,8 +1,3 @@ -import { registryName } from '~/plugins/@hey-api/sdk/shared/class'; -import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; -import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/to-case'; - import type { PluginHandler } from '../types'; import { createInfiniteQueryOptions } from './infiniteQueryOptions'; import { createMutationOptions } from './mutationOptions'; @@ -10,23 +5,21 @@ import { createQueryOptions } from './queryOptions'; import { createUseQuery } from './useQuery'; export const handlerV5: PluginHandler = ({ plugin }) => { - plugin.registerSymbol({ + plugin.symbol('DefaultError', { external: plugin.name, kind: 'type', meta: { category: 'external', resource: `${plugin.name}.DefaultError`, }, - name: 'DefaultError', }); - plugin.registerSymbol({ + plugin.symbol('InfiniteData', { external: plugin.name, kind: 'type', meta: { category: 'external', resource: `${plugin.name}.InfiniteData`, }, - name: 'InfiniteData', }); const mutationsType = plugin.name === '@tanstack/angular-query-experimental' || @@ -34,92 +27,54 @@ export const handlerV5: PluginHandler = ({ plugin }) => { plugin.name === '@tanstack/solid-query' ? 'MutationOptions' : 'UseMutationOptions'; - plugin.registerSymbol({ + plugin.symbol(mutationsType, { external: plugin.name, kind: 'type', meta: { category: 'external', resource: `${plugin.name}.MutationOptions`, }, - name: mutationsType, }); - plugin.registerSymbol({ + plugin.symbol('infiniteQueryOptions', { external: plugin.name, meta: { category: 'external', resource: `${plugin.name}.infiniteQueryOptions`, }, - name: 'infiniteQueryOptions', }); - plugin.registerSymbol({ + plugin.symbol('queryOptions', { external: plugin.name, meta: { category: 'external', resource: `${plugin.name}.queryOptions`, }, - name: 'queryOptions', }); - plugin.registerSymbol({ + plugin.symbol('useQuery', { external: plugin.name, meta: { category: 'external', resource: `${plugin.name}.useQuery`, }, - name: 'useQuery', }); - plugin.registerSymbol({ + plugin.symbol('AxiosError', { external: 'axios', kind: 'type', meta: { category: 'external', resource: 'axios.AxiosError', }, - name: 'AxiosError', }); - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); - plugin.forEach( 'operation', ({ operation }) => { - const classes = sdkPlugin.config.asClass - ? operationClasses({ operation, plugin: sdkPlugin }) - : undefined; - const entry = classes ? classes.values().next().value : undefined; - // TODO: this should use class graph to determine correct path string - // as it's really easy to break once we change the class casing - let queryFn: ReturnType; - if (entry) { - const symbolClass = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: entry.path[0], - tool: 'sdk', - }); - queryFn = $(symbolClass).$if(sdkPlugin.config.instance, (e) => - e.attr(registryName).attr('get').call(), - ); - for (const className of entry.path.slice(1)) { - const cls = toCase(className, 'camelCase'); - queryFn = queryFn.attr(cls); - } - queryFn = queryFn.attr(entry.methodName); - } else { - const symbol = plugin.referenceSymbol({ - category: 'sdk', - resource: 'operation', - resourceId: operation.id, - }); - queryFn = $(symbol); - } - if (plugin.hooks.operation.isQuery(operation)) { if (plugin.config.queryOptions.enabled) { - createQueryOptions({ operation, plugin, queryFn }); + createQueryOptions({ operation, plugin }); } if (plugin.config.infiniteQueryOptions.enabled) { - createInfiniteQueryOptions({ operation, plugin, queryFn }); + createInfiniteQueryOptions({ operation, plugin }); } if ('useQuery' in plugin.config && plugin.config.useQuery.enabled) { @@ -129,7 +84,7 @@ export const handlerV5: PluginHandler = ({ plugin }) => { if (plugin.hooks.operation.isMutation(operation)) { if (plugin.config.mutationOptions.enabled) { - createMutationOptions({ operation, plugin, queryFn }); + createMutationOptions({ operation, plugin }); } } }, diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts index ea417baf7..373821c69 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts @@ -22,11 +22,9 @@ const optionsParamName = 'options'; export const createQueryOptions = ({ operation, plugin, - queryFn, }: { operation: IR.OperationObject; plugin: PluginInstance; - queryFn: ReturnType; }): void => { if (hasOperationSse({ operation })) { return; @@ -69,8 +67,15 @@ export const createQueryOptions = ({ const typeResponse = useTypeResponse({ operation, plugin }); - const awaitSdkFn = $.lazy(() => - $(queryFn) + const awaitSdkFn = $.lazy((ctx) => + ctx + .getAccess>( + plugin.referenceSymbol({ + category: 'sdk', + resource: 'operation', + resourceId: operation.id, + }), + ) .call( $.object() .spread(optionsParamName) diff --git a/packages/openapi-ts/src/plugins/shared/utils/instance.ts b/packages/openapi-ts/src/plugins/shared/utils/instance.ts index 35419155b..b5b9d9149 100644 --- a/packages/openapi-ts/src/plugins/shared/utils/instance.ts +++ b/packages/openapi-ts/src/plugins/shared/utils/instance.ts @@ -25,6 +25,7 @@ import type { OpenApi } from '~/openApi/types'; import type { Hooks } from '~/parser/types/hooks'; import type { Plugin } from '~/plugins'; import type { PluginConfigMap } from '~/plugins/config'; +import type { TsDsl } from '~/ts-dsl'; import { jsonPointerToPath } from '~/utils/ref'; import type { BaseEvent, WalkEvent } from '../types/instance'; @@ -334,19 +335,19 @@ export class PluginInstance { return result as T extends number ? void : number; } - querySymbol(filter: SymbolMeta): Symbol | undefined { - return this.gen.symbols.query(filter)[0]; + querySymbol(filter: SymbolMeta): Symbol | undefined { + return this.gen.symbols.query(filter)[0] as Symbol | undefined; } - referenceSymbol(meta: SymbolMeta): Symbol { - return this.gen.symbols.reference(meta); + referenceSymbol(meta: SymbolMeta): Symbol { + return this.gen.symbols.reference(meta) as Symbol; } /** * @deprecated use `plugin.symbol()` instead */ - registerSymbol(symbol: SymbolIn): Symbol { - return this.symbol(symbol.name, symbol); + registerSymbol(symbol: SymbolIn): Symbol { + return this.symbol(symbol.name, symbol) as Symbol; } /** @@ -362,7 +363,10 @@ export class PluginInstance { } } - symbol(name: SymbolIn['name'], symbol?: Omit): Symbol { + symbol( + name: SymbolIn['name'], + symbol?: Omit, + ): Symbol { const symbolIn: SymbolIn = { ...symbol, exportFrom: @@ -386,7 +390,7 @@ export class PluginInstance { for (const hook of this.eventHooks['symbol:register:after']) { hook({ plugin: this, symbol: symbolOut }); } - return symbolOut; + return symbolOut as Symbol; } /** diff --git a/packages/openapi-ts/src/plugins/swr/v2/plugin.ts b/packages/openapi-ts/src/plugins/swr/v2/plugin.ts index 65754a523..8554dc7f8 100644 --- a/packages/openapi-ts/src/plugins/swr/v2/plugin.ts +++ b/packages/openapi-ts/src/plugins/swr/v2/plugin.ts @@ -1,8 +1,3 @@ -import { registryName } from '~/plugins/@hey-api/sdk/shared/class'; -import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; -import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/to-case'; - import type { SwrPlugin } from '../types'; import { createUseSwr } from './useSwr'; @@ -18,53 +13,20 @@ export const handlerV2: SwrPlugin['Handler'] = ({ plugin }) => { name: 'useSWR', }); - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); - plugin.forEach( 'operation', ({ operation }) => { - const classes = sdkPlugin.config.asClass - ? operationClasses({ operation, plugin: sdkPlugin }) - : undefined; - const entry = classes ? classes.values().next().value : undefined; - // TODO: this should use class graph to determine correct path string - // as it's really easy to break once we change the class casing - let queryFn: ReturnType; - if (entry) { - const symbolClass = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: entry.path[0], - tool: 'sdk', - }); - queryFn = $(symbolClass).$if(sdkPlugin.config.instance, (e) => - e.attr(registryName).attr('get').call(), - ); - for (const className of entry.path.slice(1)) { - const cls = toCase(className, 'camelCase'); - queryFn = queryFn.attr(cls); - } - queryFn = queryFn.attr(entry.methodName); - } else { - const symbol = plugin.referenceSymbol({ - category: 'sdk', - resource: 'operation', - resourceId: operation.id, - }); - queryFn = $(symbol); - } - if (plugin.hooks.operation.isQuery(operation)) { // if (plugin.config.queryOptions.enabled) { - // createQueryOptions({ operation, plugin, queryFn }); + // createQueryOptions({ operation, plugin }); // } // if (plugin.config.infiniteQueryOptions.enabled) { - // createInfiniteQueryOptions({ operation, plugin, queryFn }); + // createInfiniteQueryOptions({ operation, plugin }); // } if (plugin.config.useSwr.enabled) { - createUseSwr({ operation, plugin, queryFn }); + createUseSwr({ operation, plugin }); } } }, diff --git a/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts b/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts index b5e0e8682..d8419cf06 100644 --- a/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts +++ b/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts @@ -12,11 +12,9 @@ import type { SwrPlugin } from '../types'; export const createUseSwr = ({ operation, plugin, - queryFn, }: { operation: IR.OperationObject; plugin: SwrPlugin['Instance']; - queryFn: ReturnType; }): void => { if (hasOperationSse({ operation })) { return; @@ -33,8 +31,15 @@ export const createUseSwr = ({ }), }); - const awaitSdkFn = $.lazy(() => - $(queryFn) + const awaitSdkFn = $.lazy((ctx) => + ctx + .getAccess>( + plugin.referenceSymbol({ + category: 'sdk', + resource: 'operation', + resourceId: operation.id, + }), + ) .call($.object().prop('throwOnError', $.literal(true))) .await(), ); diff --git a/packages/openapi-ts/src/ts-dsl/base.ts b/packages/openapi-ts/src/ts-dsl/base.ts index ebe29d37a..a52fba10f 100644 --- a/packages/openapi-ts/src/ts-dsl/base.ts +++ b/packages/openapi-ts/src/ts-dsl/base.ts @@ -1,11 +1,19 @@ // TODO: symbol should be protected, but needs to be public to satisfy types import type { + AccessPatternContext, + AccessPatternOptions, AnalysisContext, AstContext, File, FromRef, Language, Node, + NodeName, + NodeNameSanitizer, + NodeRole, + NodeScope, + Ref, + StructuralRelationship, Symbol, } from '@hey-api/codegen-core'; import { @@ -14,19 +22,39 @@ import { isRef, isSymbol, nodeBrand, + ref, } from '@hey-api/codegen-core'; import ts from 'typescript'; export type MaybeArray = T | ReadonlyArray; export abstract class TsDsl implements Node { + accessPattern?( + node: this, + options: AccessPatternOptions, + ctx: AccessPatternContext, + ): unknown | undefined; // eslint-disable-next-line @typescript-eslint/no-unused-vars analyze(_: AnalysisContext): void {} exported?: boolean; file?: File; + get name(): Node['name'] { + return { + ...this._name, + set: (value) => { + this._name = ref(value); + }, + toString: () => (this._name ? this.$name(this._name) : ''), + } as Node['name']; + } + readonly nameSanitizer?: NodeNameSanitizer; language: Language = 'typescript'; parent?: Node; - root?: Node; + role?: NodeRole; + root: boolean = false; + scope?: NodeScope = 'value'; + structuralChildren?: Map; + structuralParents?: Map; symbol?: Symbol; // eslint-disable-next-line @typescript-eslint/no-unused-vars toAst(_: AstContext): T { @@ -35,7 +63,7 @@ export abstract class TsDsl implements Node { readonly '~brand' = nodeBrand; /** Branding property to identify the DSL class at runtime. */ - abstract readonly '~dsl': string; + abstract readonly '~dsl': string & {}; /** Conditionally applies a callback to this builder. */ $if( @@ -120,6 +148,18 @@ export abstract class TsDsl implements Node { ) as T extends string ? ts.Identifier : T; } + protected $name(name: Ref): string { + const value = fromRef(name); + if (isSymbol(value)) { + try { + return value.finalName; + } catch { + return value.name; + } + } + return String(value); + } + protected $node(ctx: AstContext, value: I): NodeOfMaybe { if (value === undefined) { return undefined as NodeOfMaybe; @@ -177,6 +217,8 @@ export abstract class TsDsl implements Node { return this.unwrap(ctx, value as any) as TypeOfMaybe; } + private _name?: Ref; + /** Unwraps nested nodes into raw TypeScript AST. */ private unwrap( ctx: AstContext, diff --git a/packages/openapi-ts/src/ts-dsl/decl/class.ts b/packages/openapi-ts/src/ts-dsl/decl/class.ts index 5975bdce2..16b5c7070 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/class.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/class.ts @@ -1,8 +1,9 @@ import type { AnalysisContext, AstContext, + NodeName, + NodeRole, Ref, - Symbol, } from '@hey-api/codegen-core'; import { isSymbol, ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -15,14 +16,10 @@ import { DocMixin } from '../mixins/doc'; import { AbstractMixin, DefaultMixin, ExportMixin } from '../mixins/modifiers'; import { TypeParamsMixin } from '../mixins/type-params'; import { safeRuntimeName } from '../utils/name'; -import type { FieldName } from './field'; import { FieldTsDsl } from './field'; import { InitTsDsl } from './init'; -import type { MethodName } from './method'; import { MethodTsDsl } from './method'; -type Base = Symbol | string; -type Name = Symbol | string; type Body = Array>; const Mixed = AbstractMixin( @@ -35,17 +32,17 @@ const Mixed = AbstractMixin( export class ClassTsDsl extends Mixed { readonly '~dsl' = 'ClassTsDsl'; + override readonly nameSanitizer = safeRuntimeName; + override role?: NodeRole = 'container'; - protected baseClass?: Ref; + protected baseClass?: Ref; protected body: Body = []; - protected name: Ref; - constructor(name: Name) { + constructor(name: NodeName) { super(); - this.name = ref(name); + this.name.set(name); if (isSymbol(name)) { name.setKind('class'); - name.setNameSanitizer(safeRuntimeName); name.setNode(this); } } @@ -76,13 +73,13 @@ export class ClassTsDsl extends Mixed { } /** Records a base class to extend from. */ - extends(base?: Base): this { + extends(base?: NodeName): this { this.baseClass = base ? ref(base) : undefined; return this; } /** Adds a class field. */ - field(name: FieldName, fn?: (f: FieldTsDsl) => void): this { + field(name: NodeName, fn?: (f: FieldTsDsl) => void): this { const f = new FieldTsDsl(name, fn); this.body.push(f); return this; @@ -97,7 +94,7 @@ export class ClassTsDsl extends Mixed { } /** Adds a class method. */ - method(name: MethodName, fn?: (m: MethodTsDsl) => void): this { + method(name: NodeName, fn?: (m: MethodTsDsl) => void): this { const m = new MethodTsDsl(name, fn); this.body.push(m); return this; diff --git a/packages/openapi-ts/src/ts-dsl/decl/decorator.ts b/packages/openapi-ts/src/ts-dsl/decl/decorator.ts index 0fe61c7ac..7506a7062 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/decorator.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/decorator.ts @@ -1,10 +1,8 @@ import type { AnalysisContext, AstContext, - Ref, - Symbol, + NodeName, } from '@hey-api/codegen-core'; -import { isSymbol, ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -12,24 +10,18 @@ import { TsDsl } from '../base'; import { ArgsMixin } from '../mixins/args'; import { safeRuntimeName } from '../utils/name'; -export type DecoratorName = Symbol | string | MaybeTsDsl; - const Mixed = ArgsMixin(TsDsl); export class DecoratorTsDsl extends Mixed { readonly '~dsl' = 'DecoratorTsDsl'; - - protected name: Ref; + override readonly nameSanitizer = safeRuntimeName; constructor( - name: DecoratorName, + name: NodeName, ...args: ReadonlyArray> ) { super(); - this.name = ref(name); - if (isSymbol(name)) { - name.setNameSanitizer(safeRuntimeName); - } + this.name.set(name); this.args(...args); } diff --git a/packages/openapi-ts/src/ts-dsl/decl/enum.ts b/packages/openapi-ts/src/ts-dsl/decl/enum.ts index 54f91068e..f35f0bd6d 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/enum.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/enum.ts @@ -1,10 +1,9 @@ import type { AnalysisContext, AstContext, - Ref, - Symbol, + NodeName, } from '@hey-api/codegen-core'; -import { isSymbol, ref } from '@hey-api/codegen-core'; +import { isSymbol } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -14,7 +13,6 @@ import { ConstMixin, ExportMixin } from '../mixins/modifiers'; import { safeRuntimeName } from '../utils/name'; import { EnumMemberTsDsl } from './member'; -export type EnumName = Symbol | string; type Value = string | number | MaybeTsDsl; type ValueFn = Value | ((m: EnumMemberTsDsl) => void); @@ -22,16 +20,15 @@ const Mixed = ConstMixin(DocMixin(ExportMixin(TsDsl))); export class EnumTsDsl extends Mixed { readonly '~dsl' = 'EnumTsDsl'; + override readonly nameSanitizer = safeRuntimeName; private _members: Array = []; - private _name: Ref; - constructor(name: EnumName, fn?: (e: EnumTsDsl) => void) { + constructor(name: NodeName, fn?: (e: EnumTsDsl) => void) { super(); - this._name = ref(name); + this.name.set(name); if (isSymbol(name)) { name.setKind('enum'); - name.setNameSanitizer(safeRuntimeName); name.setNode(this); } fn?.(this); @@ -39,7 +36,7 @@ export class EnumTsDsl extends Mixed { override analyze(ctx: AnalysisContext): void { super.analyze(ctx); - ctx.analyze(this._name); + ctx.analyze(this.name); ctx.pushScope(); try { for (const member of this._members) { @@ -66,7 +63,7 @@ export class EnumTsDsl extends Mixed { override toAst(ctx: AstContext) { const node = ts.factory.createEnumDeclaration( this.modifiers, - this.$node(ctx, this._name) as ts.Identifier, + this.$node(ctx, this.name) as ts.Identifier, this.$node(ctx, this._members) as ReadonlyArray, ); return this.$docs(ctx, node); diff --git a/packages/openapi-ts/src/ts-dsl/decl/field.ts b/packages/openapi-ts/src/ts-dsl/decl/field.ts index 550df0ec3..3ecfff9b4 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/field.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/field.ts @@ -1,10 +1,9 @@ import type { AnalysisContext, AstContext, - Ref, - Symbol, + NodeName, + NodeRole, } from '@hey-api/codegen-core'; -import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl, TypeTsDsl } from '../base'; @@ -20,11 +19,9 @@ import { import { OptionalMixin } from '../mixins/optional'; import { ValueMixin } from '../mixins/value'; import { TokenTsDsl } from '../token'; -import type { TypeExprName } from '../type/expr'; import { TypeExprTsDsl } from '../type/expr'; -export type FieldName = Symbol | string; -export type FieldType = TypeExprName | TypeTsDsl; +export type FieldType = NodeName | TypeTsDsl; const Mixed = DecoratorMixin( DocMixin( @@ -44,13 +41,13 @@ const Mixed = DecoratorMixin( export class FieldTsDsl extends Mixed { readonly '~dsl' = 'FieldTsDsl'; + override role?: NodeRole = 'accessor'; - protected name: Ref; protected _type?: TypeTsDsl; - constructor(name: FieldName, fn?: (f: FieldTsDsl) => void) { + constructor(name: NodeName, fn?: (f: FieldTsDsl) => void) { super(); - this.name = ref(name); + this.name.set(name); fn?.(this); } diff --git a/packages/openapi-ts/src/ts-dsl/decl/func.ts b/packages/openapi-ts/src/ts-dsl/decl/func.ts index c8eac07b2..ce7f80594 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/func.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/func.ts @@ -1,10 +1,9 @@ import type { AnalysisContext, AstContext, - Ref, - Symbol, + NodeName, } from '@hey-api/codegen-core'; -import { isSymbol, ref } from '@hey-api/codegen-core'; +import { isSymbol } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -27,7 +26,6 @@ import { BlockTsDsl } from '../stmt/block'; import { safeRuntimeName } from '../utils/name'; export type FuncMode = 'arrow' | 'decl' | 'expr'; -export type FuncName = Symbol | string; const Mixed = AbstractMixin( AsMixin( @@ -57,16 +55,16 @@ const Mixed = AbstractMixin( class ImplFuncTsDsl extends Mixed { readonly '~dsl' = 'FuncTsDsl'; + override readonly nameSanitizer = safeRuntimeName; protected mode?: FuncMode; - protected name?: Ref; constructor(); constructor(fn: (f: ImplFuncTsDsl<'arrow'>) => void); - constructor(name: FuncName); - constructor(name: FuncName, fn: (f: ImplFuncTsDsl<'decl'>) => void); + constructor(name: NodeName); + constructor(name: NodeName, fn: (f: ImplFuncTsDsl<'decl'>) => void); constructor( - name?: FuncName | ((f: ImplFuncTsDsl<'arrow'>) => void), + name?: NodeName | ((f: ImplFuncTsDsl<'arrow'>) => void), fn?: (f: ImplFuncTsDsl<'decl'>) => void, ) { super(); @@ -75,10 +73,9 @@ class ImplFuncTsDsl extends Mixed { name(this as unknown as FuncTsDsl<'arrow'>); } else if (name) { this.mode = 'decl'; - this.name = ref(name); + this.name.set(name); if (isSymbol(name)) { name.setKind('function'); - name.setNameSanitizer(safeRuntimeName); name.setNode(this); } fn?.(this as unknown as FuncTsDsl<'decl'>); @@ -124,7 +121,8 @@ class ImplFuncTsDsl extends Mixed { const body = this.$node(ctx, new BlockTsDsl(...this._do).pretty()); if (this.mode === 'decl') { - if (!this.name) throw new Error('Function declaration requires a name'); + const name = this.name.toString(); + if (!name) throw new Error('Function declaration requires a name'); const node = ts.factory.createFunctionDeclaration( [...this.$decorators(ctx), ...this.modifiers], undefined, @@ -169,7 +167,7 @@ class ImplFuncTsDsl extends Mixed { export const FuncTsDsl = ImplFuncTsDsl as { new (): FuncTsDsl<'arrow'>; new (fn: (f: FuncTsDsl<'arrow'>) => void): FuncTsDsl<'arrow'>; - new (name: string): FuncTsDsl<'decl'>; - new (name: string, fn: (f: FuncTsDsl<'decl'>) => void): FuncTsDsl<'decl'>; + new (name: NodeName): FuncTsDsl<'decl'>; + new (name: NodeName, fn: (f: FuncTsDsl<'decl'>) => void): FuncTsDsl<'decl'>; } & typeof ImplFuncTsDsl; export type FuncTsDsl = ImplFuncTsDsl; diff --git a/packages/openapi-ts/src/ts-dsl/decl/getter.ts b/packages/openapi-ts/src/ts-dsl/decl/getter.ts index 6905c0d3f..c8276fa38 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/getter.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/getter.ts @@ -1,10 +1,9 @@ import type { AnalysisContext, AstContext, - Ref, - Symbol, + NodeName, + NodeRole, } from '@hey-api/codegen-core'; -import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -22,8 +21,7 @@ import { import { ParamMixin } from '../mixins/param'; import { TypeReturnsMixin } from '../mixins/type-returns'; import { BlockTsDsl } from '../stmt/block'; - -export type GetterName = Symbol | string | ts.PropertyName; +import { safeAccessorName } from '../utils/name'; const Mixed = AbstractMixin( AsyncMixin( @@ -49,12 +47,12 @@ const Mixed = AbstractMixin( export class GetterTsDsl extends Mixed { readonly '~dsl' = 'GetterTsDsl'; + override readonly nameSanitizer = safeAccessorName; + override role?: NodeRole = 'accessor'; - protected name: Ref; - - constructor(name: GetterName, fn?: (g: GetterTsDsl) => void) { + constructor(name: NodeName, fn?: (g: GetterTsDsl) => void) { super(); - this.name = ref(name); + this.name.set(name); fn?.(this); } diff --git a/packages/openapi-ts/src/ts-dsl/decl/member.ts b/packages/openapi-ts/src/ts-dsl/decl/member.ts index 718b8ac3b..e3cc17d5b 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/member.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/member.ts @@ -1,4 +1,8 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + NodeName, +} from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -14,12 +18,11 @@ const Mixed = DocMixin(TsDsl); export class EnumMemberTsDsl extends Mixed { readonly '~dsl' = 'EnumMemberTsDsl'; - private _name: string; private _value?: Value; - constructor(name: string, value?: ValueFn) { + constructor(name: NodeName, value?: ValueFn) { super(); - this._name = name; + this.name.set(name); if (typeof value === 'function') { value(this); } else { @@ -40,7 +43,7 @@ export class EnumMemberTsDsl extends Mixed { override toAst(ctx: AstContext) { const node = ts.factory.createEnumMember( - this.$node(ctx, safeMemberName(this._name)), + this.$node(ctx, safeMemberName(this.name.toString())), this.$node(ctx, this._value), ); return this.$docs(ctx, node); diff --git a/packages/openapi-ts/src/ts-dsl/decl/method.ts b/packages/openapi-ts/src/ts-dsl/decl/method.ts index e3d811f00..9c4b2653d 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/method.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/method.ts @@ -1,10 +1,10 @@ import type { AnalysisContext, AstContext, - Ref, - Symbol, + NodeName, + NodeRole, } from '@hey-api/codegen-core'; -import { ref } from '@hey-api/codegen-core'; +import { isSymbol } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -25,8 +25,7 @@ import { TypeParamsMixin } from '../mixins/type-params'; import { TypeReturnsMixin } from '../mixins/type-returns'; import { BlockTsDsl } from '../stmt/block'; import { TokenTsDsl } from '../token'; - -export type MethodName = Symbol | string; +import { safeAccessorName } from '../utils/name'; const Mixed = AbstractMixin( AsyncMixin( @@ -56,12 +55,15 @@ const Mixed = AbstractMixin( export class MethodTsDsl extends Mixed { readonly '~dsl' = 'MethodTsDsl'; + override readonly nameSanitizer = safeAccessorName; + override role?: NodeRole = 'accessor'; - protected name: Ref; - - constructor(name: MethodName, fn?: (m: MethodTsDsl) => void) { + constructor(name: NodeName, fn?: (m: MethodTsDsl) => void) { super(); - this.name = ref(name); + this.name.set(name); + if (isSymbol(name)) { + name.setNode(this); + } fn?.(this); } diff --git a/packages/openapi-ts/src/ts-dsl/decl/param.ts b/packages/openapi-ts/src/ts-dsl/decl/param.ts index 4ec1746cb..9652a4c18 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/param.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/param.ts @@ -1,10 +1,8 @@ import type { AnalysisContext, AstContext, - Ref, - Symbol, + NodeName, } from '@hey-api/codegen-core'; -import { fromRef, isSymbolRef, ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl, TypeTsDsl } from '../base'; @@ -15,9 +13,8 @@ import { ValueMixin } from '../mixins/value'; import { TokenTsDsl } from '../token'; import { TypeExprTsDsl } from '../type/expr'; -export type ParamName = Symbol | string; export type ParamCtor = ( - name: ParamName | ((p: ParamTsDsl) => void), + name: NodeName | ((p: ParamTsDsl) => void), fn?: (p: ParamTsDsl) => void, ) => ParamTsDsl; @@ -28,18 +25,17 @@ const Mixed = DecoratorMixin( export class ParamTsDsl extends Mixed { readonly '~dsl' = 'ParamTsDsl'; - protected name?: Ref; protected _type?: TypeTsDsl; constructor( - name: ParamName | ((p: ParamTsDsl) => void), + name: NodeName | ((p: ParamTsDsl) => void), fn?: (p: ParamTsDsl) => void, ) { super(); if (typeof name === 'function') { name(this); } else { - this.name = ref(name); + this.name.set(name); fn?.(this); } } @@ -57,16 +53,12 @@ export class ParamTsDsl extends Mixed { } override toAst(ctx: AstContext) { - let name: string | ReturnType = this.$pattern(ctx); - if (!name && this.name) { - name = isSymbolRef(this.name) - ? fromRef(this.name).finalName - : (fromRef(this.name) as string); - } - if (!name) + const name = this.$pattern(ctx) || this.name.toString(); + if (!name) { throw new Error( 'Param must have either a name or a destructuring pattern', ); + } return ts.factory.createParameterDeclaration( this.$decorators(ctx), undefined, diff --git a/packages/openapi-ts/src/ts-dsl/decl/setter.ts b/packages/openapi-ts/src/ts-dsl/decl/setter.ts index 0f87c3918..352cab4ca 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/setter.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/setter.ts @@ -1,10 +1,8 @@ import type { AnalysisContext, AstContext, - Ref, - Symbol, + NodeName, } from '@hey-api/codegen-core'; -import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -21,8 +19,7 @@ import { } from '../mixins/modifiers'; import { ParamMixin } from '../mixins/param'; import { BlockTsDsl } from '../stmt/block'; - -export type SetterName = Symbol | string | ts.PropertyName; +import { safeAccessorName } from '../utils/name'; const Mixed = AbstractMixin( AsyncMixin( @@ -44,12 +41,11 @@ const Mixed = AbstractMixin( export class SetterTsDsl extends Mixed { readonly '~dsl' = 'SetterTsDsl'; + override readonly nameSanitizer = safeAccessorName; - protected name: Ref; - - constructor(name: SetterName, fn?: (s: SetterTsDsl) => void) { + constructor(name: NodeName, fn?: (s: SetterTsDsl) => void) { super(); - this.name = ref(name); + this.name.set(name); fn?.(this); } diff --git a/packages/openapi-ts/src/ts-dsl/expr/as.ts b/packages/openapi-ts/src/ts-dsl/expr/as.ts index 8cbceb965..684a9b4fb 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/as.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/as.ts @@ -1,8 +1,8 @@ import type { AnalysisContext, AstContext, + NodeName, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -13,8 +13,8 @@ import { AsMixin } from '../mixins/as'; import { ExprMixin } from '../mixins/expr'; import { f } from '../utils/factories'; -export type AsExpr = Symbol | string | MaybeTsDsl; -export type AsType = Symbol | string | TypeTsDsl; +export type AsExpr = NodeName | MaybeTsDsl; +export type AsType = NodeName | TypeTsDsl; export type AsCtor = (expr: AsExpr, type: AsType) => AsTsDsl; const Mixed = AsMixin(ExprMixin(TsDsl)); diff --git a/packages/openapi-ts/src/ts-dsl/expr/attr.ts b/packages/openapi-ts/src/ts-dsl/expr/attr.ts index 07b3a2c6e..5c2da3625 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/attr.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/attr.ts @@ -1,10 +1,10 @@ import type { AnalysisContext, AstContext, + NodeName, Ref, - Symbol, } from '@hey-api/codegen-core'; -import { fromRef, ref } from '@hey-api/codegen-core'; +import { fromRef, isSymbol, ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -18,9 +18,8 @@ import { f } from '../utils/factories'; import { regexp } from '../utils/regexp'; import { LiteralTsDsl } from './literal'; -export type AttrLeft = Symbol | string | MaybeTsDsl; -export type AttrRight = Symbol | string | ts.MemberName | number; -export type AttrCtor = (left: AttrLeft, right: AttrRight) => AttrTsDsl; +export type AttrLeft = NodeName | MaybeTsDsl; +export type AttrCtor = (left: AttrLeft, right: NodeName) => AttrTsDsl; const Mixed = AsMixin( ExprMixin( @@ -36,50 +35,55 @@ export class AttrTsDsl extends Mixed { readonly '~dsl' = 'AttrTsDsl'; protected left: Ref; - protected right: Ref; - constructor(left: AttrLeft, right: AttrRight) { + constructor(left: AttrLeft, right: NodeName) { super(); this.left = ref(left); - this.right = ref(right); + this.name.set(right); } override analyze(ctx: AnalysisContext): void { super.analyze(ctx); ctx.analyze(this.left); - ctx.analyze(this.right); + ctx.analyze(this.name); } override toAst(ctx: AstContext) { const leftNode = this.$node(ctx, this.left); regexp.typeScriptIdentifier.lastIndex = 0; - if ( - typeof fromRef(this.right) === 'number' || - (typeof fromRef(this.right) === 'string' && - !regexp.typeScriptIdentifier.test(fromRef(this.right) as string)) - ) { + const right = fromRef(this.name); + if (!regexp.typeScriptIdentifier.test(this.name.toString())) { + let value = isSymbol(right) ? right.finalName : right; + if (typeof value === 'string') { + if ( + (value.startsWith("'") && value.endsWith("'")) || + (value.startsWith('"') && value.endsWith('"')) + ) { + value = value.slice(1, -1); + } + } if (this._optional) { return ts.factory.createElementAccessChain( leftNode, this.$node(ctx, new TokenTsDsl().questionDot()), - this.$node(ctx, new LiteralTsDsl(fromRef(this.right) as string)), + this.$node(ctx, new LiteralTsDsl(value)), ); } return ts.factory.createElementAccessExpression( leftNode, - this.$node(ctx, new LiteralTsDsl(fromRef(this.right) as string)), + this.$node(ctx, new LiteralTsDsl(value)), ); } if (this._optional) { return ts.factory.createPropertyAccessChain( leftNode, this.$node(ctx, new TokenTsDsl().questionDot()), - this.$node(ctx, this.right) as ts.MemberName, + this.$node(ctx, this.name) as ts.MemberName, ); } return ts.factory.createPropertyAccessExpression( leftNode, - this.$node(ctx, this.right) as ts.MemberName, + this.$node(ctx, this.name) as ts.MemberName, ); } } diff --git a/packages/openapi-ts/src/ts-dsl/expr/await.ts b/packages/openapi-ts/src/ts-dsl/expr/await.ts index fc4e254d5..edeae0610 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/await.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/await.ts @@ -1,8 +1,8 @@ import type { AnalysisContext, AstContext, + NodeName, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -12,7 +12,7 @@ import { TsDsl } from '../base'; import { ExprMixin } from '../mixins/expr'; import { f } from '../utils/factories'; -export type AwaitExpr = Symbol | string | MaybeTsDsl; +export type AwaitExpr = NodeName | MaybeTsDsl; export type AwaitCtor = (expr: AwaitExpr) => AwaitTsDsl; const Mixed = ExprMixin(TsDsl); diff --git a/packages/openapi-ts/src/ts-dsl/expr/binary.ts b/packages/openapi-ts/src/ts-dsl/expr/binary.ts index 42d45ee9c..ce8b326ff 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/binary.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/binary.ts @@ -1,8 +1,8 @@ import type { AnalysisContext, AstContext, + NodeName, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -12,7 +12,7 @@ import { TsDsl } from '../base'; import { AsMixin } from '../mixins/as'; import { ExprMixin } from '../mixins/expr'; -type Expr = Symbol | string | MaybeTsDsl; +type Expr = NodeName | MaybeTsDsl; type Op = Operator | ts.BinaryOperator; type Operator = | '!=' diff --git a/packages/openapi-ts/src/ts-dsl/expr/call.ts b/packages/openapi-ts/src/ts-dsl/expr/call.ts index 039aaad38..86c190612 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/call.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/call.ts @@ -1,7 +1,7 @@ import type { AnalysisContext, AstContext, - Symbol, + NodeName, } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -14,7 +14,7 @@ import { TypeArgsMixin } from '../mixins/type-args'; import { f } from '../utils/factories'; export type CallCallee = string | MaybeTsDsl; -export type CallArg = Symbol | string | MaybeTsDsl; +export type CallArg = NodeName | MaybeTsDsl; export type CallArgs = ReadonlyArray; export type CallCtor = (callee: CallCallee, ...args: CallArgs) => CallTsDsl; diff --git a/packages/openapi-ts/src/ts-dsl/expr/expr.ts b/packages/openapi-ts/src/ts-dsl/expr/expr.ts index 7cfe44d03..88ea28517 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/expr.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/expr.ts @@ -1,8 +1,8 @@ import type { AnalysisContext, AstContext, + NodeName, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import type ts from 'typescript'; @@ -14,7 +14,7 @@ import { ExprMixin } from '../mixins/expr'; import { OperatorMixin } from '../mixins/operator'; import { TypeExprMixin } from '../mixins/type-expr'; -type Id = Symbol | string | MaybeTsDsl; +type Id = NodeName | MaybeTsDsl; const Mixed = AsMixin( ExprMixin(OperatorMixin(TypeExprMixin(TsDsl))), diff --git a/packages/openapi-ts/src/ts-dsl/expr/id.ts b/packages/openapi-ts/src/ts-dsl/expr/id.ts index 744cefbdb..59d1f71c1 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/id.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/id.ts @@ -8,11 +8,9 @@ const Mixed = TsDsl; export class IdTsDsl extends Mixed { readonly '~dsl' = 'IdTsDsl'; - protected name: string; - constructor(name: string) { super(); - this.name = name; + this.name.set(name); } override analyze(ctx: AnalysisContext): void { @@ -20,6 +18,6 @@ export class IdTsDsl extends Mixed { } override toAst() { - return ts.factory.createIdentifier(this.name); + return ts.factory.createIdentifier(this.name.toString()); } } diff --git a/packages/openapi-ts/src/ts-dsl/expr/literal.ts b/packages/openapi-ts/src/ts-dsl/expr/literal.ts index 6bf8122eb..f57dfebd7 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/literal.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/literal.ts @@ -7,7 +7,16 @@ import { AsMixin } from '../mixins/as'; export type LiteralValue = string | number | boolean | bigint | null; -const Mixed = AsMixin(TsDsl); +const Mixed = AsMixin( + TsDsl< + | ts.BigIntLiteral + | ts.BooleanLiteral + | ts.NullLiteral + | ts.NumericLiteral + | ts.PrefixUnaryExpression + | ts.StringLiteral + >, +); export class LiteralTsDsl extends Mixed { readonly '~dsl' = 'LiteralTsDsl'; diff --git a/packages/openapi-ts/src/ts-dsl/expr/new.ts b/packages/openapi-ts/src/ts-dsl/expr/new.ts index 92f85ea39..475ed6e3b 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/new.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/new.ts @@ -1,8 +1,8 @@ import type { AnalysisContext, AstContext, + NodeName, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -13,7 +13,7 @@ import { ArgsMixin } from '../mixins/args'; import { ExprMixin } from '../mixins/expr'; import { TypeArgsMixin } from '../mixins/type-args'; -export type NewExpr = Symbol | string | MaybeTsDsl; +export type NewExpr = NodeName | MaybeTsDsl; const Mixed = ArgsMixin(ExprMixin(TypeArgsMixin(TsDsl))); diff --git a/packages/openapi-ts/src/ts-dsl/expr/object.ts b/packages/openapi-ts/src/ts-dsl/expr/object.ts index 93892dd5d..98baf7b35 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/object.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/object.ts @@ -1,7 +1,7 @@ import type { AnalysisContext, AstContext, - Symbol, + NodeName, } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -13,8 +13,8 @@ import { HintMixin } from '../mixins/hint'; import { LayoutMixin } from '../mixins/layout'; import { ObjectPropTsDsl } from './prop'; -type Expr = Symbol | string | MaybeTsDsl; -type Stmt = Symbol | string | MaybeTsDsl; +type Expr = NodeName | MaybeTsDsl; +type Stmt = NodeName | MaybeTsDsl; type ExprFn = Expr | ((p: ObjectPropTsDsl) => void); type StmtFn = Stmt | ((p: ObjectPropTsDsl) => void); diff --git a/packages/openapi-ts/src/ts-dsl/expr/prop.ts b/packages/openapi-ts/src/ts-dsl/expr/prop.ts index b3bac400b..aaf267a54 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/prop.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/prop.ts @@ -1,8 +1,8 @@ import type { AnalysisContext, AstContext, + NodeName, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -15,8 +15,8 @@ import { DocMixin } from '../mixins/doc'; import { safePropName } from '../utils/name'; import { IdTsDsl } from './id'; -type Expr = Symbol | string | MaybeTsDsl; -type Stmt = Symbol | string | MaybeTsDsl; +type Expr = NodeName | MaybeTsDsl; +type Stmt = NodeName | MaybeTsDsl; type Kind = 'computed' | 'getter' | 'prop' | 'setter' | 'spread'; type Meta = @@ -71,16 +71,12 @@ export class ObjectPropTsDsl extends Mixed { return this.$docs(ctx, result); } if (this.meta.kind === 'getter') { - const getter = new GetterTsDsl( - this.$node(ctx, safePropName(this.meta.name)), - ).do(node); + const getter = new GetterTsDsl(this.meta.name).do(node); const result = this.$node(ctx, getter); return this.$docs(ctx, result); } if (this.meta.kind === 'setter') { - const setter = new SetterTsDsl( - this.$node(ctx, safePropName(this.meta.name)), - ).do(node); + const setter = new SetterTsDsl(this.meta.name).do(node); const result = this.$node(ctx, setter); return this.$docs(ctx, result); } diff --git a/packages/openapi-ts/src/ts-dsl/expr/template.ts b/packages/openapi-ts/src/ts-dsl/expr/template.ts index 6b6690fba..be153b148 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/template.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/template.ts @@ -1,8 +1,9 @@ import type { AnalysisContext, AstContext, + NodeName, + NodeRole, Ref, - Symbol, } from '@hey-api/codegen-core'; import { fromRef, isSymbol, ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -10,12 +11,13 @@ import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; import { TsDsl } from '../base'; -export type TemplatePart = Symbol | string | MaybeTsDsl; +export type TemplatePart = NodeName | MaybeTsDsl; const Mixed = TsDsl; export class TemplateTsDsl extends Mixed { readonly '~dsl' = 'TemplateTsDsl'; + override role?: NodeRole = 'literal'; protected parts: Array> = []; @@ -59,6 +61,8 @@ export class TemplateTsDsl extends Mixed { index++; } normalized.push(merged); + } else if (typeof current === 'number') { + normalized.push(String(current)); } else { normalized.push(current); } diff --git a/packages/openapi-ts/src/ts-dsl/index.ts b/packages/openapi-ts/src/ts-dsl/index.ts index 1ffbb5879..5b95fae87 100644 --- a/packages/openapi-ts/src/ts-dsl/index.ts +++ b/packages/openapi-ts/src/ts-dsl/index.ts @@ -358,6 +358,7 @@ export type DollarTsDsl = { export type { MaybeTsDsl, TypeTsDsl } from './base'; export { TsDsl } from './base'; export { TypeScriptRenderer } from './render/typescript'; +export { astContext } from './utils/context'; export { keywords } from './utils/keywords'; export { regexp } from './utils/regexp'; export { reserved } from './utils/reserved'; diff --git a/packages/openapi-ts/src/ts-dsl/mixins/args.ts b/packages/openapi-ts/src/ts-dsl/mixins/args.ts index d11ce36b4..c46adf879 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/args.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/args.ts @@ -2,8 +2,8 @@ import type { AnalysisContext, AstContext, Node, + NodeName, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import type ts from 'typescript'; @@ -11,7 +11,7 @@ import type ts from 'typescript'; import type { MaybeTsDsl } from '../base'; import type { BaseCtor, MixinCtor } from './types'; -type Arg = Symbol | string | MaybeTsDsl; +type Arg = NodeName | MaybeTsDsl; export interface ArgsMethods extends Node { /** Renders the arguments into an array of `Expression`s. */ diff --git a/packages/openapi-ts/src/ts-dsl/mixins/decorator.ts b/packages/openapi-ts/src/ts-dsl/mixins/decorator.ts index ea7103f54..cce00bce3 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/decorator.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/decorator.ts @@ -2,7 +2,7 @@ import type { AnalysisContext, AstContext, Node, - Symbol, + NodeName, } from '@hey-api/codegen-core'; import type ts from 'typescript'; @@ -15,7 +15,7 @@ export interface DecoratorMethods extends Node { $decorators(ctx: AstContext): ReadonlyArray; /** Adds a decorator (e.g. `@sealed({ in: 'root' })`). */ decorator( - name: Symbol | string | MaybeTsDsl, + name: NodeName | MaybeTsDsl, ...args: ReadonlyArray> ): this; } @@ -34,7 +34,7 @@ export function DecoratorMixin>( } protected decorator( - name: Symbol | string | MaybeTsDsl, + name: NodeName, ...args: ReadonlyArray> ): this { this.decorators.push(new DecoratorTsDsl(name, ...args)); diff --git a/packages/openapi-ts/src/ts-dsl/mixins/operator.ts b/packages/openapi-ts/src/ts-dsl/mixins/operator.ts index 288579ade..ca01f16ad 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/operator.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/operator.ts @@ -1,11 +1,11 @@ -import type { AnalysisContext, Node, Symbol } from '@hey-api/codegen-core'; +import type { AnalysisContext, Node, NodeName } from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { MaybeTsDsl } from '../base'; import { BinaryTsDsl } from '../expr/binary'; import type { BaseCtor, MixinCtor } from './types'; -type Expr = Symbol | string | MaybeTsDsl; +type Expr = NodeName | MaybeTsDsl; export interface OperatorMethods extends Node { /** Logical AND — `this && expr` */ diff --git a/packages/openapi-ts/src/ts-dsl/mixins/param.ts b/packages/openapi-ts/src/ts-dsl/mixins/param.ts index e045ae823..7d6eac50e 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/param.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/param.ts @@ -1,8 +1,13 @@ -import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + Node, + NodeName, +} from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { MaybeTsDsl } from '../base'; -import type { ParamCtor, ParamName } from '../decl/param'; +import type { ParamCtor } from '../decl/param'; import { ParamTsDsl } from '../decl/param'; import type { BaseCtor, MixinCtor } from './types'; @@ -29,7 +34,7 @@ export function ParamMixin>( } protected param( - name: ParamName | ((p: ParamTsDsl) => void), + name: NodeName | ((p: ParamTsDsl) => void), fn?: (p: ParamTsDsl) => void, ): this { const p = new ParamTsDsl(name, fn); diff --git a/packages/openapi-ts/src/ts-dsl/mixins/type-args.ts b/packages/openapi-ts/src/ts-dsl/mixins/type-args.ts index c7118c1bf..d13119d36 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/type-args.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/type-args.ts @@ -2,8 +2,8 @@ import type { AnalysisContext, AstContext, Node, + NodeName, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import type ts from 'typescript'; @@ -11,7 +11,7 @@ import type ts from 'typescript'; import type { MaybeTsDsl, TypeTsDsl } from '../base'; import type { BaseCtor, MixinCtor } from './types'; -type Arg = Symbol | string | MaybeTsDsl; +type Arg = NodeName | MaybeTsDsl; export interface TypeArgsMethods extends Node { /** Returns the type arguments as an array of ts.TypeNode nodes. */ diff --git a/packages/openapi-ts/src/ts-dsl/mixins/type-params.ts b/packages/openapi-ts/src/ts-dsl/mixins/type-params.ts index 20fd20c6a..8988b1d6b 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/type-params.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/type-params.ts @@ -2,9 +2,9 @@ import type { AnalysisContext, AstContext, Node, - Symbol, + NodeName, } from '@hey-api/codegen-core'; -import { isSymbol } from '@hey-api/codegen-core'; +import { isRef, isSymbol } from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -19,9 +19,7 @@ export interface TypeParamsMethods extends Node { /** Adds a single type parameter (e.g. `T` in `Array`). */ generic(...args: ConstructorParameters): this; /** Adds type parameters (e.g. `Map`). */ - generics( - ...args: ReadonlyArray> - ): this; + generics(...args: ReadonlyArray>): this; } export function TypeParamsMixin>( @@ -46,10 +44,15 @@ export function TypeParamsMixin>( } protected generics( - ...args: ReadonlyArray> + ...args: ReadonlyArray> ): this { for (let arg of args) { - if (typeof arg === 'string' || isSymbol(arg)) { + if ( + typeof arg === 'string' || + typeof arg === 'number' || + isSymbol(arg) || + isRef(arg) + ) { arg = new TypeParamTsDsl(arg); } this._generics.push(arg); diff --git a/packages/openapi-ts/src/ts-dsl/mixins/type-returns.ts b/packages/openapi-ts/src/ts-dsl/mixins/type-returns.ts index 0454aa1de..db77b8c1e 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/type-returns.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/type-returns.ts @@ -1,8 +1,12 @@ -import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + Node, + NodeName, +} from '@hey-api/codegen-core'; import type ts from 'typescript'; import { TypeTsDsl } from '../base'; -import type { TypeExprName } from '../type/expr'; import { TypeExprTsDsl } from '../type/expr'; import type { BaseCtor, MixinCtor } from './types'; @@ -10,7 +14,7 @@ export interface TypeReturnsMethods extends Node { /** Returns the return type node. */ $returns(ctx: AstContext): ts.TypeNode | undefined; /** Sets the return type. */ - returns(type: TypeExprName | TypeTsDsl): this; + returns(type: NodeName | TypeTsDsl): this; } export function TypeReturnsMixin>( @@ -24,7 +28,7 @@ export function TypeReturnsMixin>( ctx.analyze(this._returns); } - protected returns(type: TypeExprName | TypeTsDsl): this { + protected returns(type: NodeName | TypeTsDsl): this { this._returns = type instanceof TypeTsDsl ? type : new TypeExprTsDsl(type); return this; diff --git a/packages/openapi-ts/src/ts-dsl/render/__tests__/typescript.test.ts b/packages/openapi-ts/src/ts-dsl/render/__tests__/typescript.test.ts index b65cae3cc..6a61f1ec5 100644 --- a/packages/openapi-ts/src/ts-dsl/render/__tests__/typescript.test.ts +++ b/packages/openapi-ts/src/ts-dsl/render/__tests__/typescript.test.ts @@ -3,6 +3,8 @@ import { Project } from '@hey-api/codegen-core'; import ts from 'typescript'; import { describe, expect, it } from 'vitest'; +import { astContext, type TsDsl } from '~/ts-dsl'; + import { TypeScriptRenderer } from '../typescript'; import type { ModuleExport, ModuleImport } from '../utils'; @@ -20,12 +22,7 @@ describe('TypeScriptRenderer', () => { const mockCtx = ( fileOverrides = {}, projectOverrides = {}, - ): RenderContext => ({ - astContext: { - getAccess(node) { - return node; - }, - }, + ): RenderContext => ({ file: mockFile(fileOverrides), project: new Project({ root: '/root', @@ -47,7 +44,6 @@ describe('TypeScriptRenderer', () => { }); it('renderImport() generates named and namespace imports correctly', () => { - const ctx = mockCtx(); const group: ModuleImport = { imports: [ { @@ -61,12 +57,11 @@ describe('TypeScriptRenderer', () => { modulePath: 'foo', namespaceImport: undefined, }; - const node = renderer['renderImport'](ctx, group); + const node = renderer['renderImport'](astContext, group); expect(ts.isImportDeclaration(node)).toBe(true); }); it('renderExport() generates named and namespace exports correctly', () => { - const ctx = mockCtx(); const group: ModuleExport = { canExportAll: false, exports: [ @@ -81,7 +76,7 @@ describe('TypeScriptRenderer', () => { modulePath: 'bar', namespaceExport: undefined, }; - const node = renderer['renderExport'](ctx, group); + const node = renderer['renderExport'](astContext, group); expect(ts.isExportDeclaration(node)).toBe(true); }); }); diff --git a/packages/openapi-ts/src/ts-dsl/render/typescript.ts b/packages/openapi-ts/src/ts-dsl/render/typescript.ts index 7933fd72e..97bcad12c 100644 --- a/packages/openapi-ts/src/ts-dsl/render/typescript.ts +++ b/packages/openapi-ts/src/ts-dsl/render/typescript.ts @@ -1,7 +1,12 @@ -import type { RenderContext, Renderer } from '@hey-api/codegen-core'; +import type { + AstContext, + RenderContext, + Renderer, +} from '@hey-api/codegen-core'; import ts from 'typescript'; -import { $ } from '~/ts-dsl'; +import type { TsDsl } from '~/ts-dsl'; +import { $, astContext } from '~/ts-dsl'; import type { ModuleExport, @@ -44,7 +49,7 @@ export class TypeScriptRenderer implements Renderer { this.resolveModuleName = args.resolveModuleName; } - render(ctx: RenderContext): string { + render(ctx: RenderContext): string { let text = ''; const header = '// This file is auto-generated by @hey-api/openapi-ts'; text += `${header}\n`; @@ -53,7 +58,7 @@ export class TypeScriptRenderer implements Renderer { for (const group of this.getImports(ctx)) { if (imports) imports += '\n'; for (const imp of group) { - imports += `${nodeToString(this.renderImport(ctx, imp))}\n`; + imports += `${nodeToString(this.renderImport(astContext, imp))}\n`; } } text = `${text}${text && imports ? '\n' : ''}${imports}`; @@ -61,8 +66,7 @@ export class TypeScriptRenderer implements Renderer { let nodes = ''; for (const node of ctx.file.nodes) { if (nodes) nodes += '\n'; - // @ts-expect-error - nodes += `${nodeToString(node.toAst(ctx.astContext))}\n`; + nodes += `${nodeToString(node.toAst(astContext))}\n`; } text = `${text}${text && nodes ? '\n' : ''}${nodes}`; @@ -70,7 +74,7 @@ export class TypeScriptRenderer implements Renderer { for (const group of this.getExports(ctx)) { if ((!exports && nodes) || exports) exports += '\n'; for (const exp of group) { - exports += `${nodeToString(this.renderExport(ctx, exp))}\n`; + exports += `${nodeToString(this.renderExport(astContext, exp))}\n`; } } text = `${text}${text && exports ? '\n' : ''}${exports}`; @@ -235,7 +239,7 @@ export class TypeScriptRenderer implements Renderer { } private renderExport( - ctx: RenderContext, + ctx: AstContext, group: ModuleExport, ): ts.ExportDeclaration { const specifiers = group.exports.map((exp) => { @@ -257,12 +261,12 @@ export class TypeScriptRenderer implements Renderer { undefined, group.isTypeOnly, exportClause, - $.literal(group.modulePath).toAst(ctx.astContext), + $.literal(group.modulePath).toAst(ctx), ); } private renderImport( - ctx: RenderContext, + ctx: AstContext, group: ModuleImport, ): ts.ImportDeclaration { const specifiers = group.imports.map((imp) => { @@ -285,7 +289,7 @@ export class TypeScriptRenderer implements Renderer { return ts.factory.createImportDeclaration( undefined, importClause, - $.literal(group.modulePath).toAst(ctx.astContext), + $.literal(group.modulePath).toAst(ctx), ); } } diff --git a/packages/openapi-ts/src/ts-dsl/stmt/return.ts b/packages/openapi-ts/src/ts-dsl/stmt/return.ts index 96cc107f4..83037f870 100644 --- a/packages/openapi-ts/src/ts-dsl/stmt/return.ts +++ b/packages/openapi-ts/src/ts-dsl/stmt/return.ts @@ -1,8 +1,8 @@ import type { AnalysisContext, AstContext, + NodeName, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -11,7 +11,7 @@ import type { MaybeTsDsl } from '../base'; import { TsDsl } from '../base'; import { f } from '../utils/factories'; -export type ReturnExpr = Symbol | string | MaybeTsDsl; +export type ReturnExpr = NodeName | MaybeTsDsl; export type ReturnCtor = (expr?: ReturnExpr) => ReturnTsDsl; const Mixed = TsDsl; diff --git a/packages/openapi-ts/src/ts-dsl/stmt/try.ts b/packages/openapi-ts/src/ts-dsl/stmt/try.ts index 3dccf8cee..11fb6fec0 100644 --- a/packages/openapi-ts/src/ts-dsl/stmt/try.ts +++ b/packages/openapi-ts/src/ts-dsl/stmt/try.ts @@ -1,7 +1,7 @@ import type { AnalysisContext, AstContext, - Symbol, + NodeName, } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -11,13 +11,11 @@ import { BlockTsDsl } from './block'; const Mixed = TsDsl; -type CatchParam = Symbol | string; - export class TryTsDsl extends Mixed { readonly '~dsl' = 'TryTsDsl'; protected _catch?: Array; - protected _catchArg?: CatchParam; + protected _catchArg?: NodeName; protected _finally?: Array; protected _try?: Array; @@ -65,7 +63,7 @@ export class TryTsDsl extends Mixed { return this; } - catchArg(arg: CatchParam): this { + catchArg(arg: NodeName): this { this._catchArg = arg; return this; } diff --git a/packages/openapi-ts/src/ts-dsl/stmt/var.ts b/packages/openapi-ts/src/ts-dsl/stmt/var.ts index 9881c48e7..014edffcd 100644 --- a/packages/openapi-ts/src/ts-dsl/stmt/var.ts +++ b/packages/openapi-ts/src/ts-dsl/stmt/var.ts @@ -1,10 +1,9 @@ import type { AnalysisContext, AstContext, - Ref, - Symbol, + NodeName, } from '@hey-api/codegen-core'; -import { isSymbol, ref } from '@hey-api/codegen-core'; +import { isSymbol } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl, TypeTsDsl } from '../base'; @@ -16,8 +15,6 @@ import { ValueMixin } from '../mixins/value'; import { TypeExprTsDsl } from '../type/expr'; import { safeRuntimeName } from '../utils/name'; -export type VarName = Symbol | string; - const Mixed = DefaultMixin( DocMixin( ExportMixin( @@ -28,17 +25,16 @@ const Mixed = DefaultMixin( export class VarTsDsl extends Mixed { readonly '~dsl' = 'VarTsDsl'; + override readonly nameSanitizer = safeRuntimeName; protected kind: ts.NodeFlags = ts.NodeFlags.None; - protected name?: Ref; protected _type?: TypeTsDsl; - constructor(name?: VarName) { + constructor(name?: NodeName) { super(); - if (name) this.name = ref(name); + if (name) this.name.set(name); if (isSymbol(name)) { name.setKind('var'); - name.setNameSanitizer(safeRuntimeName); name.setNode(this); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/alias.ts b/packages/openapi-ts/src/ts-dsl/type/alias.ts index 8f816295b..c6ed5fdf8 100644 --- a/packages/openapi-ts/src/ts-dsl/type/alias.ts +++ b/packages/openapi-ts/src/ts-dsl/type/alias.ts @@ -1,10 +1,10 @@ import type { AnalysisContext, AstContext, - Ref, - Symbol, + NodeName, + NodeScope, } from '@hey-api/codegen-core'; -import { fromRef, isSymbol, ref } from '@hey-api/codegen-core'; +import { isSymbol } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -14,7 +14,6 @@ import { ExportMixin } from '../mixins/modifiers'; import { TypeParamsMixin } from '../mixins/type-params'; import { safeTypeName } from '../utils/name'; -type Name = Symbol | string; type Value = MaybeTsDsl; const Mixed = DocMixin( @@ -23,16 +22,16 @@ const Mixed = DocMixin( export class TypeAliasTsDsl extends Mixed { readonly '~dsl' = 'TypeAliasTsDsl'; + override readonly nameSanitizer = safeTypeName; + override scope: NodeScope = 'type'; - protected name: Ref; protected value?: Value; - constructor(name: Name, fn?: (t: TypeAliasTsDsl) => void) { + constructor(name: NodeName, fn?: (t: TypeAliasTsDsl) => void) { super(); - this.name = ref(name); + this.name.set(name); if (isSymbol(name)) { name.setKind('type'); - name.setNameSanitizer(safeTypeName); name.setNode(this); } fn?.(this); @@ -53,7 +52,7 @@ export class TypeAliasTsDsl extends Mixed { override toAst(ctx: AstContext) { if (!this.value) throw new Error( - `Type alias '${fromRef(this.name)}' is missing a type definition`, + `Type alias '${this.name.toString()}' is missing a type definition`, ); const node = ts.factory.createTypeAliasDeclaration( this.modifiers, diff --git a/packages/openapi-ts/src/ts-dsl/type/and.ts b/packages/openapi-ts/src/ts-dsl/type/and.ts index 085602eb9..f708d57ad 100644 --- a/packages/openapi-ts/src/ts-dsl/type/and.ts +++ b/packages/openapi-ts/src/ts-dsl/type/and.ts @@ -1,8 +1,9 @@ import type { AnalysisContext, AstContext, + NodeName, + NodeScope, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -10,12 +11,13 @@ import ts from 'typescript'; import type { TypeTsDsl } from '../base'; import { TsDsl } from '../base'; -type Type = Symbol | string | ts.TypeNode | TypeTsDsl; +type Type = NodeName | ts.TypeNode | TypeTsDsl; const Mixed = TsDsl; export class TypeAndTsDsl extends Mixed { readonly '~dsl' = 'TypeAndTsDsl'; + override scope: NodeScope = 'type'; protected _types: Array> = []; diff --git a/packages/openapi-ts/src/ts-dsl/type/attr.ts b/packages/openapi-ts/src/ts-dsl/type/attr.ts index 59434b0ef..80d7daee5 100644 --- a/packages/openapi-ts/src/ts-dsl/type/attr.ts +++ b/packages/openapi-ts/src/ts-dsl/type/attr.ts @@ -1,8 +1,9 @@ import type { AnalysisContext, AstContext, + NodeName, + NodeScope, Ref, - Symbol, } from '@hey-api/codegen-core'; import { isRef, ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -11,13 +12,14 @@ import type { MaybeTsDsl } from '../base'; import { TsDsl } from '../base'; import { TypeExprMixin } from '../mixins/type-expr'; -type Base = Symbol | string | MaybeTsDsl; -type Right = Symbol | string | ts.Identifier; +type Base = NodeName | MaybeTsDsl; +type Right = NodeName | ts.Identifier; const Mixed = TypeExprMixin(TsDsl); export class TypeAttrTsDsl extends Mixed { readonly '~dsl' = 'TypeAttrTsDsl'; + override scope: NodeScope = 'type'; protected _base?: Ref; protected _right!: Ref; diff --git a/packages/openapi-ts/src/ts-dsl/type/expr.ts b/packages/openapi-ts/src/ts-dsl/type/expr.ts index 4712aabff..b97a1d5ea 100644 --- a/packages/openapi-ts/src/ts-dsl/type/expr.ts +++ b/packages/openapi-ts/src/ts-dsl/type/expr.ts @@ -1,8 +1,9 @@ import type { AnalysisContext, AstContext, + NodeName, + NodeScope, Ref, - Symbol, } from '@hey-api/codegen-core'; import { isNode, ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -13,11 +14,10 @@ import { TypeExprMixin } from '../mixins/type-expr'; import { f } from '../utils/factories'; import { TypeAttrTsDsl } from './attr'; -export type TypeExprName = Symbol | string; -export type TypeExprExpr = TypeExprName | TypeAttrTsDsl; +export type TypeExprExpr = NodeName | TypeAttrTsDsl; export type TypeExprFn = (t: TypeExprTsDsl) => void; export type TypeExprCtor = ( - nameOrFn?: TypeExprName | TypeExprFn, + nameOrFn?: NodeName | TypeExprFn, fn?: TypeExprFn, ) => TypeExprTsDsl; @@ -25,14 +25,15 @@ const Mixed = TypeArgsMixin(TypeExprMixin(TsDsl)); export class TypeExprTsDsl extends Mixed { readonly '~dsl' = 'TypeExprTsDsl'; + override scope: NodeScope = 'type'; protected _exprInput?: Ref; constructor(); constructor(fn: TypeExprFn); - constructor(name: TypeExprName); - constructor(name: TypeExprName, fn?: TypeExprFn); - constructor(name?: TypeExprName | TypeExprFn, fn?: TypeExprFn) { + constructor(name: NodeName); + constructor(name: NodeName, fn?: TypeExprFn); + constructor(name?: NodeName | TypeExprFn, fn?: TypeExprFn) { super(); if (typeof name === 'function') { name(this); diff --git a/packages/openapi-ts/src/ts-dsl/type/func.ts b/packages/openapi-ts/src/ts-dsl/type/func.ts index 871485b28..b0abaaa74 100644 --- a/packages/openapi-ts/src/ts-dsl/type/func.ts +++ b/packages/openapi-ts/src/ts-dsl/type/func.ts @@ -1,4 +1,8 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + NodeScope, +} from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -13,6 +17,7 @@ const Mixed = DocMixin( export class TypeFuncTsDsl extends Mixed { readonly '~dsl' = 'TypeFuncTsDsl'; + override scope: NodeScope = 'type'; override analyze(ctx: AnalysisContext): void { super.analyze(ctx); diff --git a/packages/openapi-ts/src/ts-dsl/type/idx-sig.ts b/packages/openapi-ts/src/ts-dsl/type/idx-sig.ts index 092c479e1..5c4120ad1 100644 --- a/packages/openapi-ts/src/ts-dsl/type/idx-sig.ts +++ b/packages/openapi-ts/src/ts-dsl/type/idx-sig.ts @@ -1,4 +1,9 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + NodeName, + NodeScope, +} from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -6,21 +11,20 @@ import { TsDsl } from '../base'; import { DocMixin } from '../mixins/doc'; import { ReadonlyMixin } from '../mixins/modifiers'; -export type TypeIdxSigName = string; export type TypeIdxSigType = string | MaybeTsDsl; const Mixed = DocMixin(ReadonlyMixin(TsDsl)); export class TypeIdxSigTsDsl extends Mixed { readonly '~dsl' = 'TypeIdxSigTsDsl'; + override scope: NodeScope = 'type'; protected _key?: TypeIdxSigType; - protected _name: TypeIdxSigName; protected _type?: TypeIdxSigType; - constructor(name: TypeIdxSigName, fn?: (i: TypeIdxSigTsDsl) => void) { + constructor(name: NodeName, fn?: (i: TypeIdxSigTsDsl) => void) { super(); - this._name = name; + this.name.set(name); fn?.(this); } @@ -55,7 +59,7 @@ export class TypeIdxSigTsDsl extends Mixed { ts.factory.createParameterDeclaration( undefined, undefined, - this._name, + this.$node(ctx, this.name) as ts.BindingName, undefined, this.$type(ctx, this._key), ), @@ -67,20 +71,19 @@ export class TypeIdxSigTsDsl extends Mixed { $validate(): asserts this is this & { _key: TypeIdxSigType; - _name: TypeIdxSigName; _type: TypeIdxSigType; } { const missing = this.missingRequiredCalls(); if (missing.length === 0) return; + const name = this.name.toString(); throw new Error( - `Index signature${this._name ? ` "${this._name}"` : ''} missing ${missing.join(' and ')}`, + `Index signature${name ? ` "${name}"` : ''} missing ${missing.join(' and ')}`, ); } private missingRequiredCalls(): ReadonlyArray { const missing: Array = []; if (!this._key) missing.push('.key()'); - if (!this._name) missing.push('.name()'); if (!this._type) missing.push('.\u200Btype()'); return missing; } diff --git a/packages/openapi-ts/src/ts-dsl/type/idx.ts b/packages/openapi-ts/src/ts-dsl/type/idx.ts index a6260a048..4817cd907 100644 --- a/packages/openapi-ts/src/ts-dsl/type/idx.ts +++ b/packages/openapi-ts/src/ts-dsl/type/idx.ts @@ -1,4 +1,8 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + NodeScope, +} from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -14,6 +18,7 @@ const Mixed = TypeExprMixin(TsDsl); export class TypeIdxTsDsl extends Mixed { readonly '~dsl' = 'TypeIdxTsDsl'; + override scope: NodeScope = 'type'; protected _base!: Base; protected _index!: Index; diff --git a/packages/openapi-ts/src/ts-dsl/type/literal.ts b/packages/openapi-ts/src/ts-dsl/type/literal.ts index e14101989..2b7356f37 100644 --- a/packages/openapi-ts/src/ts-dsl/type/literal.ts +++ b/packages/openapi-ts/src/ts-dsl/type/literal.ts @@ -1,4 +1,8 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + NodeScope, +} from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -8,6 +12,7 @@ const Mixed = TsDsl; export class TypeLiteralTsDsl extends Mixed { readonly '~dsl' = 'TypeLiteralTsDsl'; + override scope: NodeScope = 'type'; protected value: string | number | boolean | null; diff --git a/packages/openapi-ts/src/ts-dsl/type/mapped.ts b/packages/openapi-ts/src/ts-dsl/type/mapped.ts index 12d915822..5c1b5004e 100644 --- a/packages/openapi-ts/src/ts-dsl/type/mapped.ts +++ b/packages/openapi-ts/src/ts-dsl/type/mapped.ts @@ -1,4 +1,9 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + NodeName, + NodeScope, +} from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -9,6 +14,7 @@ const Mixed = TsDsl; export class TypeMappedTsDsl extends Mixed { readonly '~dsl' = 'TypeMappedTsDsl'; + override scope: NodeScope = 'type'; protected questionToken?: TokenTsDsl< | ts.SyntaxKind.QuestionToken @@ -21,12 +27,11 @@ export class TypeMappedTsDsl extends Mixed { | ts.SyntaxKind.PlusToken >; protected _key?: string | MaybeTsDsl; - protected _name?: string; protected _type?: string | MaybeTsDsl; - constructor(name?: string) { + constructor(name?: NodeName) { super(); - this.name(name); + if (name) this.name.set(name); } override analyze(ctx: AnalysisContext): void { @@ -54,12 +59,6 @@ export class TypeMappedTsDsl extends Mixed { return this; } - /** Sets the parameter name: `{ [Name in keyof T]: U }` */ - name(name?: string): this { - this._name = name; - return this; - } - /** Makes `[K in X]?:` optional. */ optional(): this { this.questionToken = new TokenTsDsl().optional(); @@ -90,7 +89,7 @@ export class TypeMappedTsDsl extends Mixed { this.$node(ctx, this.readonlyToken), ts.factory.createTypeParameterDeclaration( undefined, - this._name, + this.$node(ctx, this.name) as ts.Identifier, this.$type(ctx, this._key), undefined, ), @@ -103,20 +102,19 @@ export class TypeMappedTsDsl extends Mixed { $validate(): asserts this is this & { _key: string | MaybeTsDsl; - _name: string; _type: string | MaybeTsDsl; } { const missing = this.missingRequiredCalls(); if (missing.length === 0) return; + const name = this.name.toString(); throw new Error( - `Mapped type${this._name ? ` "${this._name}"` : ''} missing ${missing.join(' and ')}`, + `Mapped type${name ? ` "${name}"` : ''} missing ${missing.join(' and ')}`, ); } private missingRequiredCalls(): ReadonlyArray { const missing: Array = []; if (!this._key) missing.push('.key()'); - if (!this._name) missing.push('.name()'); if (!this._type) missing.push('.\u200Btype()'); return missing; } diff --git a/packages/openapi-ts/src/ts-dsl/type/object.ts b/packages/openapi-ts/src/ts-dsl/type/object.ts index b839624a2..f602832df 100644 --- a/packages/openapi-ts/src/ts-dsl/type/object.ts +++ b/packages/openapi-ts/src/ts-dsl/type/object.ts @@ -1,4 +1,8 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + NodeScope, +} from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -9,6 +13,7 @@ const Mixed = TsDsl; export class TypeObjectTsDsl extends Mixed { readonly '~dsl' = 'TypeObjectTsDsl'; + override scope: NodeScope = 'type'; protected props: Array = []; diff --git a/packages/openapi-ts/src/ts-dsl/type/operator.ts b/packages/openapi-ts/src/ts-dsl/type/operator.ts index 86dedd8ff..dfffd5e43 100644 --- a/packages/openapi-ts/src/ts-dsl/type/operator.ts +++ b/packages/openapi-ts/src/ts-dsl/type/operator.ts @@ -1,4 +1,8 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + NodeScope, +} from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -28,6 +32,7 @@ const Mixed = TsDsl; */ export class TypeOperatorTsDsl extends Mixed { readonly '~dsl' = 'TypeOperatorTsDsl'; + override scope: NodeScope = 'type'; protected _op?: Op; protected _type?: Type; diff --git a/packages/openapi-ts/src/ts-dsl/type/or.ts b/packages/openapi-ts/src/ts-dsl/type/or.ts index f317cba4f..2a4a07e76 100644 --- a/packages/openapi-ts/src/ts-dsl/type/or.ts +++ b/packages/openapi-ts/src/ts-dsl/type/or.ts @@ -1,8 +1,9 @@ import type { AnalysisContext, AstContext, + NodeName, + NodeScope, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -10,12 +11,13 @@ import ts from 'typescript'; import type { TypeTsDsl } from '../base'; import { TsDsl } from '../base'; -type Type = Symbol | string | ts.TypeNode | TypeTsDsl; +type Type = NodeName | ts.TypeNode | TypeTsDsl; const Mixed = TsDsl; export class TypeOrTsDsl extends Mixed { readonly '~dsl' = 'TypeOrTsDsl'; + override scope: NodeScope = 'type'; protected _types: Array> = []; diff --git a/packages/openapi-ts/src/ts-dsl/type/param.ts b/packages/openapi-ts/src/ts-dsl/type/param.ts index 2088f0229..95b3c5842 100644 --- a/packages/openapi-ts/src/ts-dsl/type/param.ts +++ b/packages/openapi-ts/src/ts-dsl/type/param.ts @@ -1,8 +1,9 @@ import type { AnalysisContext, AstContext, + NodeName, + NodeScope, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -10,21 +11,20 @@ import ts from 'typescript'; import type { MaybeTsDsl, TypeTsDsl } from '../base'; import { TsDsl } from '../base'; -export type TypeParamName = Symbol | string; -export type TypeParamExpr = Symbol | string | boolean | MaybeTsDsl; +export type TypeParamExpr = NodeName | boolean | MaybeTsDsl; const Mixed = TsDsl; export class TypeParamTsDsl extends Mixed { readonly '~dsl' = 'TypeParamTsDsl'; + override scope: NodeScope = 'type'; protected constraint?: Ref; protected defaultValue?: Ref; - protected name?: Ref; - constructor(name?: TypeParamName, fn?: (name: TypeParamTsDsl) => void) { + constructor(name?: NodeName, fn?: (name: TypeParamTsDsl) => void) { super(); - if (name) this.name = ref(name); + if (name) this.name.set(name); fn?.(this); } @@ -46,7 +46,8 @@ export class TypeParamTsDsl extends Mixed { } override toAst(ctx: AstContext) { - if (!this.name) throw new Error('Missing type name'); + const name = this.name.toString(); + if (!name) throw new Error('Missing type name'); return ts.factory.createTypeParameterDeclaration( undefined, this.$node(ctx, this.name) as ts.Identifier, diff --git a/packages/openapi-ts/src/ts-dsl/type/prop.ts b/packages/openapi-ts/src/ts-dsl/type/prop.ts index c46739b4c..79c9e6aeb 100644 --- a/packages/openapi-ts/src/ts-dsl/type/prop.ts +++ b/packages/openapi-ts/src/ts-dsl/type/prop.ts @@ -1,8 +1,9 @@ import type { AnalysisContext, AstContext, + NodeName, + NodeScope, Ref, - Symbol, } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -15,20 +16,19 @@ import { OptionalMixin } from '../mixins/optional'; import { TokenTsDsl } from '../token'; import { safePropName } from '../utils/name'; -export type TypePropName = string; -export type TypePropType = Symbol | string | MaybeTsDsl; +export type TypePropType = NodeName | MaybeTsDsl; const Mixed = DocMixin(OptionalMixin(ReadonlyMixin(TsDsl))); export class TypePropTsDsl extends Mixed { readonly '~dsl' = 'TypePropTsDsl'; + override scope: NodeScope = 'type'; - protected name: TypePropName; protected _type?: Ref; - constructor(name: TypePropName, fn: (p: TypePropTsDsl) => void) { + constructor(name: NodeName, fn: (p: TypePropTsDsl) => void) { super(); - this.name = name; + this.name.set(name); fn(this); } @@ -44,12 +44,13 @@ export class TypePropTsDsl extends Mixed { } override toAst(ctx: AstContext) { - if (!this._type) { - throw new Error(`Type not specified for property '${this.name}'`); + const name = this.name.toString(); + if (!this._type || !name) { + throw new Error(`Type not specified for property '${name}'`); } const node = ts.factory.createPropertySignature( this.modifiers, - this.$node(ctx, safePropName(this.name)), + this.$node(ctx, safePropName(name)), this._optional ? this.$node(ctx, new TokenTsDsl().optional()) : undefined, this.$type(ctx, this._type), ); diff --git a/packages/openapi-ts/src/ts-dsl/type/query.ts b/packages/openapi-ts/src/ts-dsl/type/query.ts index 860661721..f1560b88e 100644 --- a/packages/openapi-ts/src/ts-dsl/type/query.ts +++ b/packages/openapi-ts/src/ts-dsl/type/query.ts @@ -1,4 +1,8 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + NodeScope, +} from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl, TypeTsDsl } from '../base'; @@ -13,6 +17,7 @@ const Mixed = TypeExprMixin(TsDsl); export class TypeQueryTsDsl extends Mixed { readonly '~dsl' = 'TypeQueryTsDsl'; + override scope: NodeScope = 'type'; protected _expr: TypeQueryExpr; diff --git a/packages/openapi-ts/src/ts-dsl/type/template.ts b/packages/openapi-ts/src/ts-dsl/type/template.ts index 4d12c9202..a48aec033 100644 --- a/packages/openapi-ts/src/ts-dsl/type/template.ts +++ b/packages/openapi-ts/src/ts-dsl/type/template.ts @@ -1,4 +1,8 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + NodeScope, +} from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -8,6 +12,7 @@ const Mixed = TsDsl; export class TypeTemplateTsDsl extends Mixed { readonly '~dsl' = 'TypeTemplateTsDsl'; + override scope: NodeScope = 'type'; protected parts: Array> = []; diff --git a/packages/openapi-ts/src/ts-dsl/type/tuple.ts b/packages/openapi-ts/src/ts-dsl/type/tuple.ts index ae3170830..eb76d66ef 100644 --- a/packages/openapi-ts/src/ts-dsl/type/tuple.ts +++ b/packages/openapi-ts/src/ts-dsl/type/tuple.ts @@ -1,4 +1,8 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { + AnalysisContext, + AstContext, + NodeScope, +} from '@hey-api/codegen-core'; import ts from 'typescript'; import type { TypeTsDsl } from '../base'; @@ -8,6 +12,7 @@ const Mixed = TsDsl; export class TypeTupleTsDsl extends Mixed { readonly '~dsl' = 'TypeTupleTsDsl'; + override scope: NodeScope = 'type'; protected _elements: Array = []; diff --git a/packages/openapi-ts/src/ts-dsl/utils/context.ts b/packages/openapi-ts/src/ts-dsl/utils/context.ts new file mode 100644 index 000000000..65b5601d9 --- /dev/null +++ b/packages/openapi-ts/src/ts-dsl/utils/context.ts @@ -0,0 +1,113 @@ +import type { + AccessPatternOptions, + AstContext, + NodeScope, + Symbol, +} from '@hey-api/codegen-core'; +import { isSymbol } from '@hey-api/codegen-core'; + +import { $ } from '~/ts-dsl'; + +import type { TsDsl } from '../base'; + +const getScope = (node: TsDsl): NodeScope => node.scope ?? 'value'; + +function traverseStructuralParent(node: TsDsl): boolean { + if (node.role === 'literal') { + return false; + } + return true; +} + +function foldAccessChain( + chain: ReadonlyArray, +): ReadonlyArray { + const folded: Array = []; + + for (const node of chain) { + if (folded.length === 0) { + if (node.role === 'container') { + folded.push(node); + } + } else if (node.role === 'accessor') { + folded.push(node); + } + } + + return folded; +} + +function getAccessChain( + node: Node, +): ReadonlyArray { + const chain: Array = []; + const scope: NodeScope = getScope(node); + const visited = new Set(); + + let current: TsDsl | undefined = node; + while (current) { + if (visited.has(current)) break; + visited.add(current); + + chain.unshift(current); + + let foundParent = false; + for (const [parent] of current.structuralParents || []) { + if (getScope(parent) === scope && traverseStructuralParent(parent)) { + current = parent; + foundParent = true; + break; + } + } + + if (!foundParent) break; + } + + // trim any unreachable nodes before root + const rootIndex = chain.findIndex((node) => node.root); + if (rootIndex !== -1) { + chain.splice(0, rootIndex); + } + + return foldAccessChain(chain) as ReadonlyArray; +} + +export const astContext: AstContext = { + getAccess( + to: TsDsl | Symbol, + options?: AccessPatternOptions, + ): T { + const node = isSymbol(to) ? to.node! : to; + const chain = getAccessChain(node); + if (chain.length === 0) return node as T; + + let result!: ReturnType; + + for (let index = 0; index < chain.length; index++) { + const currentNode = chain[index]!; + + const transformed = currentNode.accessPattern?.( + currentNode, + { + context: 'runtime', + ...options, + }, + { + chain, + index, + isLeaf: index === chain.length - 1, + isRoot: index === 0, + length: chain.length, + }, + ) as typeof result | undefined; + + if (index === 0) { + result = transformed || $(currentNode.name); + } else { + result = result.attr(transformed?.name || currentNode.name); + } + } + + return result as T; + }, +}; diff --git a/packages/openapi-ts/src/ts-dsl/utils/lazy.ts b/packages/openapi-ts/src/ts-dsl/utils/lazy.ts index e31925503..786625471 100644 --- a/packages/openapi-ts/src/ts-dsl/utils/lazy.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/lazy.ts @@ -2,6 +2,7 @@ import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; import type ts from 'typescript'; import { TsDsl } from '../base'; +import { astContext } from './context'; export type LazyThunk = (ctx: AstContext) => TsDsl; @@ -17,15 +18,10 @@ export class LazyTsDsl extends TsDsl { override analyze(ctx: AnalysisContext): void { super.analyze(ctx); - const astContext: AstContext = { - getAccess(node) { - return node; - }, - }; ctx.analyze(this._thunk(astContext)); } - override toAst(ctx: AstContext) { + override toAst(ctx: AstContext): T { return this._thunk(ctx).toAst(ctx); } } diff --git a/packages/openapi-ts/src/ts-dsl/utils/name.ts b/packages/openapi-ts/src/ts-dsl/utils/name.ts index d3e6ec5f1..0886eac1e 100644 --- a/packages/openapi-ts/src/ts-dsl/utils/name.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/name.ts @@ -7,20 +7,37 @@ import { regexp } from './regexp'; import type { ReservedList } from './reserved'; import { reserved } from './reserved'; -export const safeMemberName = (name: string): TsDsl => { +export const safeAccessorName = (name: string): string => { + regexp.number.lastIndex = 0; + if (regexp.number.test(name)) { + return name.startsWith('-') ? `'${name}'` : name; + } + + regexp.typeScriptIdentifier.lastIndex = 0; + if (regexp.typeScriptIdentifier.test(name)) { + return name; + } + return `'${name}'`; +}; + +export const safeMemberName = ( + name: string, +): TsDsl | IdTsDsl => { regexp.typeScriptIdentifier.lastIndex = 0; if (regexp.typeScriptIdentifier.test(name)) { return new IdTsDsl(name); } - return new LiteralTsDsl(name) as TsDsl; + return new LiteralTsDsl(name) as TsDsl; }; -export const safePropName = (name: string): TsDsl => { +export const safePropName = ( + name: string, +): TsDsl | IdTsDsl => { regexp.number.lastIndex = 0; if (regexp.number.test(name)) { return name.startsWith('-') - ? (new LiteralTsDsl(name) as TsDsl) - : (new LiteralTsDsl(Number(name)) as TsDsl); + ? (new LiteralTsDsl(name) as TsDsl) + : (new LiteralTsDsl(Number(name)) as TsDsl); } regexp.typeScriptIdentifier.lastIndex = 0; @@ -28,7 +45,7 @@ export const safePropName = (name: string): TsDsl => { return new IdTsDsl(name); } - return new LiteralTsDsl(name) as TsDsl; + return new LiteralTsDsl(name) as TsDsl; }; const safeName = (name: string, reserved: ReservedList): string => { @@ -58,7 +75,8 @@ const safeName = (name: string, reserved: ReservedList): string => { return sanitized || '_'; }; -export const safeRuntimeName = (name: string) => +export const safeRuntimeName = (name: string): string => safeName(name, reserved.runtime); -export const safeTypeName = (name: string) => safeName(name, reserved.type); +export const safeTypeName = (name: string): string => + safeName(name, reserved.type); -- 2.51.2 From bed9a55845997b9a5347ccf2c0e9c83d94227f47 Mon Sep 17 00:00:00 2001 From: Lubos Date: Thu, 18 Dec 2025 23:08:18 +0800 Subject: [PATCH 05/15] refactor: clean up ast context --- dev/openapi-ts.config.ts | 13 +- dev/package.json | 3 +- dev/playground.ts | 20 +- .../src/__tests__/exports.test.ts | 7 +- packages/codegen-core/src/bindings.d.ts | 19 +- packages/codegen-core/src/index.ts | 6 +- packages/codegen-core/src/nodes/context.d.ts | 15 - packages/codegen-core/src/nodes/node.d.ts | 46 +-- packages/codegen-core/src/planner/analyzer.ts | 7 +- packages/codegen-core/src/planner/planner.ts | 8 +- .../plugins/@hey-api/sdk/model/resource.ts | 25 +- .../plugins/@pinia/colada/mutationOptions.ts | 2 +- .../src/plugins/@pinia/colada/queryOptions.ts | 2 +- .../src/plugins/@pinia/colada/types.d.ts | 8 +- .../angular-query-experimental/types.d.ts | 12 +- .../query-core/v5/infiniteQueryOptions.ts | 2 +- .../query-core/v5/mutationOptions.ts | 8 +- .../@tanstack/query-core/v5/queryOptions.ts | 2 +- .../plugins/@tanstack/react-query/types.d.ts | 12 +- .../plugins/@tanstack/solid-query/types.d.ts | 12 +- .../plugins/@tanstack/svelte-query/types.d.ts | 12 +- .../plugins/@tanstack/vue-query/types.d.ts | 12 +- .../openapi-ts/src/plugins/swr/types.d.ts | 12 +- .../openapi-ts/src/plugins/swr/v2/useSwr.ts | 2 +- packages/openapi-ts/src/ts-dsl/base.ts | 63 ++-- packages/openapi-ts/src/ts-dsl/decl/class.ts | 27 +- .../openapi-ts/src/ts-dsl/decl/decorator.ts | 12 +- packages/openapi-ts/src/ts-dsl/decl/enum.ts | 14 +- packages/openapi-ts/src/ts-dsl/decl/field.ts | 22 +- packages/openapi-ts/src/ts-dsl/decl/func.ts | 42 +-- packages/openapi-ts/src/ts-dsl/decl/getter.ts | 22 +- packages/openapi-ts/src/ts-dsl/decl/init.ts | 12 +- packages/openapi-ts/src/ts-dsl/decl/member.ts | 14 +- packages/openapi-ts/src/ts-dsl/decl/method.ts | 26 +- packages/openapi-ts/src/ts-dsl/decl/param.ts | 18 +- .../openapi-ts/src/ts-dsl/decl/pattern.ts | 14 +- packages/openapi-ts/src/ts-dsl/decl/setter.ts | 18 +- packages/openapi-ts/src/ts-dsl/expr/array.ts | 6 +- packages/openapi-ts/src/ts-dsl/expr/as.ts | 13 +- packages/openapi-ts/src/ts-dsl/expr/attr.ts | 23 +- packages/openapi-ts/src/ts-dsl/expr/await.ts | 11 +- packages/openapi-ts/src/ts-dsl/expr/binary.ts | 13 +- packages/openapi-ts/src/ts-dsl/expr/call.ts | 30 +- packages/openapi-ts/src/ts-dsl/expr/expr.ts | 18 +- .../openapi-ts/src/ts-dsl/expr/literal.ts | 8 +- packages/openapi-ts/src/ts-dsl/expr/new.ts | 33 +- packages/openapi-ts/src/ts-dsl/expr/object.ts | 12 +- packages/openapi-ts/src/ts-dsl/expr/prefix.ts | 6 +- packages/openapi-ts/src/ts-dsl/expr/prop.ts | 29 +- .../openapi-ts/src/ts-dsl/expr/template.ts | 12 +- .../openapi-ts/src/ts-dsl/expr/ternary.ts | 10 +- packages/openapi-ts/src/ts-dsl/expr/typeof.ts | 6 +- packages/openapi-ts/src/ts-dsl/index.ts | 4 +- packages/openapi-ts/src/ts-dsl/layout/doc.ts | 12 +- packages/openapi-ts/src/ts-dsl/layout/hint.ts | 12 +- .../openapi-ts/src/ts-dsl/layout/newline.ts | 6 +- packages/openapi-ts/src/ts-dsl/layout/note.ts | 12 +- packages/openapi-ts/src/ts-dsl/mixins/args.ts | 7 +- .../openapi-ts/src/ts-dsl/mixins/decorator.ts | 13 +- packages/openapi-ts/src/ts-dsl/mixins/do.ts | 11 +- packages/openapi-ts/src/ts-dsl/mixins/doc.ts | 8 +- packages/openapi-ts/src/ts-dsl/mixins/hint.ts | 8 +- .../openapi-ts/src/ts-dsl/mixins/modifiers.ts | 90 ++++- packages/openapi-ts/src/ts-dsl/mixins/note.ts | 8 +- .../openapi-ts/src/ts-dsl/mixins/param.ts | 13 +- .../openapi-ts/src/ts-dsl/mixins/pattern.ts | 8 +- .../openapi-ts/src/ts-dsl/mixins/type-args.ts | 9 +- .../src/ts-dsl/mixins/type-params.ts | 19 +- .../src/ts-dsl/mixins/type-returns.ts | 13 +- .../openapi-ts/src/ts-dsl/mixins/value.ts | 8 +- packages/openapi-ts/src/ts-dsl/stmt/block.ts | 6 +- packages/openapi-ts/src/ts-dsl/stmt/if.ts | 10 +- packages/openapi-ts/src/ts-dsl/stmt/return.ts | 11 +- packages/openapi-ts/src/ts-dsl/stmt/stmt.ts | 6 +- packages/openapi-ts/src/ts-dsl/stmt/throw.ts | 13 +- packages/openapi-ts/src/ts-dsl/stmt/try.ts | 16 +- packages/openapi-ts/src/ts-dsl/stmt/var.ts | 16 +- packages/openapi-ts/src/ts-dsl/type/alias.ts | 11 +- packages/openapi-ts/src/ts-dsl/type/and.ts | 5 +- packages/openapi-ts/src/ts-dsl/type/attr.ts | 7 +- packages/openapi-ts/src/ts-dsl/type/expr.ts | 7 +- packages/openapi-ts/src/ts-dsl/type/func.ts | 16 +- .../openapi-ts/src/ts-dsl/type/idx-sig.ts | 11 +- packages/openapi-ts/src/ts-dsl/type/idx.ts | 12 +- .../openapi-ts/src/ts-dsl/type/literal.ts | 10 +- packages/openapi-ts/src/ts-dsl/type/mapped.ts | 13 +- packages/openapi-ts/src/ts-dsl/type/object.ts | 10 +- .../openapi-ts/src/ts-dsl/type/operator.ts | 13 +- packages/openapi-ts/src/ts-dsl/type/or.ts | 5 +- packages/openapi-ts/src/ts-dsl/type/param.ts | 9 +- packages/openapi-ts/src/ts-dsl/type/prop.ts | 11 +- packages/openapi-ts/src/ts-dsl/type/query.ts | 10 +- .../openapi-ts/src/ts-dsl/type/template.ts | 10 +- packages/openapi-ts/src/ts-dsl/type/tuple.ts | 10 +- .../__tests__/render.test.ts} | 10 +- .../openapi-ts/src/ts-dsl/utils/context.ts | 319 +++++++++++++----- .../openapi-ts/src/ts-dsl/utils/factories.ts | 4 + packages/openapi-ts/src/ts-dsl/utils/lazy.ts | 16 +- .../utils.ts => utils/render-utils.ts} | 2 +- .../{render/typescript.ts => utils/render.ts} | 196 ++++++----- pnpm-lock.yaml | 22 +- 101 files changed, 957 insertions(+), 922 deletions(-) delete mode 100644 packages/codegen-core/src/nodes/context.d.ts rename packages/openapi-ts/src/ts-dsl/{render/__tests__/typescript.test.ts => utils/__tests__/render.test.ts} (87%) rename packages/openapi-ts/src/ts-dsl/{render/utils.ts => utils/render-utils.ts} (98%) rename packages/openapi-ts/src/ts-dsl/{render/typescript.ts => utils/render.ts} (74%) diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index 3a07fd1ba..93790be83 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -43,7 +43,7 @@ export default defineConfig(() => { // 'circular.yaml', // 'dutchie.json', // 'enum-names-values.yaml', - 'full.yaml', + // 'full.yaml', // 'integer-formats.yaml', // 'invalid', // 'object-property-names.yaml', @@ -54,7 +54,7 @@ export default defineConfig(() => { // 'sdk-instance.yaml', // 'sdk-method-class-conflict.yaml', // 'sdk-nested-classes.yaml', - // 'sdk-nested-conflict.yaml', + 'sdk-nested-conflict.yaml', // 'string-with-format.yaml', // 'transformers.json', // 'transformers-recursive.json', @@ -274,10 +274,9 @@ export default defineConfig(() => { // }, }, { - // asClass: true, + asClass: true, // auth: false, - // classNameBuilder: '{{name}}', - classNameBuilder: '{{name}}Service', + // classNameBuilder: '{{name}}',', // classStructure: 'off', // client: false, // getSignature: ({ fields, signature, operation }) => { @@ -285,8 +284,8 @@ export default defineConfig(() => { // fields.unwrap('path') // }, // include... - instance: 'Root', - methodNameBuilder: '{{name}}', + instance: 'OpencodeClient', + // methodNameBuilder: '{{name}}', name: '@hey-api/sdk', // operationId: false, // paramsStructure: 'flat', diff --git a/dev/package.json b/dev/package.json index 2e2a453fc..d44e7e2e7 100644 --- a/dev/package.json +++ b/dev/package.json @@ -1,5 +1,5 @@ { - "name": "@test/openapi-ts-playground", + "name": "@test/playground", "version": "0.0.0", "private": true, "type": "module", @@ -12,6 +12,7 @@ "devDependencies": { "@hey-api/codegen-core": "workspace:*", "@hey-api/openapi-ts": "workspace:*", + "@opencode-ai/sdk": "1.0.170", "@pinia/colada": "0.19.1", "@tanstack/angular-query-experimental": "5.73.3", "@tanstack/react-query": "5.73.3", diff --git a/dev/playground.ts b/dev/playground.ts index 6152ddd8a..8492f991f 100644 --- a/dev/playground.ts +++ b/dev/playground.ts @@ -1,6 +1,5 @@ import type { DefinePlugin, IR } from '@hey-api/openapi-ts'; - -import { authSet } from './.gen/index.ts'; +import { createOpencode } from '@opencode-ai/sdk'; type MyPluginConfig = { readonly name: 'myplugin' }; type MyPlugin = DefinePlugin; @@ -15,14 +14,9 @@ export const handler: MyPlugin['Handler'] = ({ plugin }) => { }); }; -console.log( - authSet({ - auth: { - access: '', - expires: 1, - refresh: '', - type: 'oauth', - }, - id: '123', - }), -); +async function run() { + const { client, server } = await createOpencode(); + console.log(client, server); +} + +run(); diff --git a/packages/codegen-core/src/__tests__/exports.test.ts b/packages/codegen-core/src/__tests__/exports.test.ts index 254c4c6c0..3cb71fb81 100644 --- a/packages/codegen-core/src/__tests__/exports.test.ts +++ b/packages/codegen-core/src/__tests__/exports.test.ts @@ -27,7 +27,6 @@ const constExports = [ // Type-level test: will fail to compile if any type export is missing or renamed export type _TypeExports = [ index.AnalysisContext, - index.AstContext, index.BindingKind, index.ExportMember, index.ExportModule, @@ -36,13 +35,17 @@ export type _TypeExports = [ index.FileIn, index.FromRef, index.FromRefs, - index.IProject, index.ImportMember, index.ImportModule, + index.IProject, index.Language, index.NameConflictResolver, index.NameConflictResolvers, index.Node, + index.NodeName, + index.NodeNameSanitizer, + index.NodeRelationship, + index.NodeScope, index.Output, index.Project, index.ProjectRenderMeta, diff --git a/packages/codegen-core/src/bindings.d.ts b/packages/codegen-core/src/bindings.d.ts index 27f639606..56b30d070 100644 --- a/packages/codegen-core/src/bindings.d.ts +++ b/packages/codegen-core/src/bindings.d.ts @@ -32,8 +32,6 @@ export type ExportModule = Pick & { export interface ImportMember { /** Whether this import is type-only. */ isTypeOnly: boolean; - /** Import flavor. */ - kind: BindingKind; /** * The name this symbol will have locally in this file. * This is where aliasing is applied: @@ -47,11 +45,12 @@ export interface ImportMember { sourceName: string; } -export type ImportModule = Pick & { - /** Source file. */ - from: File; - /** List of symbols imported from this module. */ - imports: Array; - /** Namespace import: `import * as name from 'module'`. Mutually exclusive with `imports`. */ - namespaceImport?: string; -}; +export type ImportModule = Pick & + Pick, 'localName'> & { + /** Source file. */ + from: File; + /** List of symbols imported from this module. */ + imports: Array; + /** Import flavor. */ + kind: BindingKind; + }; diff --git a/packages/codegen-core/src/index.ts b/packages/codegen-core/src/index.ts index b5659b96c..a78be42be 100644 --- a/packages/codegen-core/src/index.ts +++ b/packages/codegen-core/src/index.ts @@ -20,16 +20,12 @@ export type { Language, NameConflictResolvers, } from './languages/types'; -export type { AstContext } from './nodes/context'; export type { - AccessPatternContext, - AccessPatternOptions, INode as Node, NodeName, NodeNameSanitizer, - NodeRole, + NodeRelationship, NodeScope, - StructuralRelationship, } from './nodes/node'; export type { IOutput as Output } from './output'; export { diff --git a/packages/codegen-core/src/nodes/context.d.ts b/packages/codegen-core/src/nodes/context.d.ts deleted file mode 100644 index 733c7d871..000000000 --- a/packages/codegen-core/src/nodes/context.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Symbol } from '../symbols/symbol'; -import type { AccessPatternOptions, INode } from './node'; - -/** - * Context passed to `.toAst()` methods. - */ -export interface AstContext { - /** - * Returns the canonical node for accessing the provided node. - */ - getAccess( - node: INode | Symbol, - options?: AccessPatternOptions, - ): T; -} diff --git a/packages/codegen-core/src/nodes/node.d.ts b/packages/codegen-core/src/nodes/node.d.ts index 137c9b8f5..38e3f7b64 100644 --- a/packages/codegen-core/src/nodes/node.d.ts +++ b/packages/codegen-core/src/nodes/node.d.ts @@ -3,27 +3,6 @@ import type { Language } from '../languages/types'; import type { IAnalysisContext } from '../planner/types'; import type { Ref } from '../refs/types'; import type { Symbol } from '../symbols/symbol'; -import type { AstContext } from './context'; - -export type AccessContext = 'docs' | 'runtime'; - -export interface AccessPatternContext { - /** The full chain. */ - chain: ReadonlyArray; - /** Position in the chain (0 = root). */ - index: number; - /** Is this the leaf node? */ - isLeaf: boolean; - /** Is this the root node? */ - isRoot: boolean; - /** Total length of the chain. */ - length: number; -} - -export interface AccessPatternOptions { - /** The access context. */ - context: AccessContext; -} export type MaybeRef = T | Ref; @@ -31,26 +10,15 @@ export type NodeName = MaybeRef; export type NodeNameSanitizer = (name: string) => string; -export type NodeRole = - | 'accessor' - | 'container' - | 'control-flow' - | 'expression' - | 'literal'; +export type NodeRelationship = 'container' | 'reference'; export type NodeScope = 'type' | 'value'; -export type StructuralRelationship = 'container' | 'reference'; - export interface INode { - /** Custom access pattern for this node. */ - accessPattern?( - node: this, - options: AccessPatternOptions, - ctx: AccessPatternContext, - ): unknown | undefined; /** Perform semantic analysis. */ analyze(ctx: IAnalysisContext): void; + /** Create a shallow copy of this node. */ + clone(): this; /** Whether this node is exported from its file. */ exported?: boolean; /** The file this node belongs to. */ @@ -64,20 +32,18 @@ export interface INode { }; /** Optional function to sanitize the node name. */ readonly nameSanitizer?: NodeNameSanitizer; - /** The role of this node within the structure. */ - role?: NodeRole; /** Whether this node is a root node in the file. */ root?: boolean; /** The scope of this node. */ scope?: NodeScope; /** Semantic children in the structure hierarchy. */ - structuralChildren?: Map; + structuralChildren?: Map; /** Semantic parents in the structure hierarchy. */ - structuralParents?: Map; + structuralParents?: Map; /** The symbol associated with this node. */ symbol?: Symbol; /** Convert this node into AST representation. */ - toAst(ctx: AstContext): T; + toAst(): T; /** Brand used for renderer dispatch. */ readonly '~brand': string; } diff --git a/packages/codegen-core/src/planner/analyzer.ts b/packages/codegen-core/src/planner/analyzer.ts index 8231ecc0f..0ac5e082f 100644 --- a/packages/codegen-core/src/planner/analyzer.ts +++ b/packages/codegen-core/src/planner/analyzer.ts @@ -1,5 +1,5 @@ import { isNodeRef, isSymbolRef } from '../guards'; -import type { INode, StructuralRelationship } from '../nodes/node'; +import type { INode, NodeRelationship } from '../nodes/node'; import { fromRef, isRef, ref } from '../refs/refs'; import type { Ref } from '../refs/types'; import type { Symbol } from '../symbols/symbol'; @@ -35,10 +35,7 @@ export class AnalysisContext implements IAnalysisContext { /** * Register a child node under the current parent. */ - addChild( - child: INode, - relationship: StructuralRelationship = 'container', - ): void { + addChild(child: INode, relationship: NodeRelationship = 'container'): void { const parent = this.currentParent; if (!parent) return; diff --git a/packages/codegen-core/src/planner/planner.ts b/packages/codegen-core/src/planner/planner.ts index 8e50ef4d8..c2fa0b314 100644 --- a/packages/codegen-core/src/planner/planner.ts +++ b/packages/codegen-core/src/planner/planner.ts @@ -300,6 +300,7 @@ export class Planner { from: source, imports: [], isTypeOnly: true, + kind: 'named', }; } const isTypeOnly = [...entry.kinds].every((kind) => @@ -307,11 +308,14 @@ export class Planner { ); if (entry.symbol.importKind === 'namespace') { imp.imports = []; - imp.namespaceImport = entry.symbol.finalName; + imp.kind = 'namespace'; + imp.localName = entry.symbol.finalName; + } else if (entry.symbol.importKind === 'default') { + imp.kind = 'default'; + imp.localName = entry.symbol.finalName; } else { imp.imports.push({ isTypeOnly, - kind: entry.symbol.importKind, localName: entry.symbol.finalName, sourceName: entry.dep.finalName, }); diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts index 4b1fd8436..6f503319f 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts @@ -134,10 +134,12 @@ export class SdkResourceModel { node.do( this.implementFn({ node: $.method(this.createFnSymbol(plugin, event), (m) => - m + this.attachComment({ + node: m, + operation, + }) .public() - .static(!isAngularClient && !plugin.config.instance) - .$if(createOperationComment(operation), (m, v) => m.doc(v)), + .static(!isAngularClient && !plugin.config.instance), ), operation, plugin, @@ -154,9 +156,8 @@ export class SdkResourceModel { } else { this.operations.forEach((event) => { const { operation } = event; - const node = $.const(this.createFnSymbol(plugin, event)) + let node = $.const(this.createFnSymbol(plugin, event)) .export() - .$if(createOperationComment(operation), (c, v) => c.doc(v)) .assign( this.implementFn({ node: $.func(), @@ -164,6 +165,7 @@ export class SdkResourceModel { plugin, }), ); + node = this.attachComment({ node, operation }); nodes.push(node); }); } @@ -183,6 +185,13 @@ export class SdkResourceModel { yield this; } + private attachComment< + T extends ReturnType, + >(args: { node: T; operation: IR.OperationObject }): T { + const { node, operation } = args; + return node.$if(createOperationComment(operation), (m, v) => m.doc(v)) as T; + } + private createFnSymbol( plugin: HeyApiSdkPlugin['Instance'], event: Event, @@ -325,8 +334,10 @@ export class SdkResourceModel { const isClientRequired = !plugin.config.client || !plugin.getSymbol({ category: 'client' }); const registry = plugin.symbol('__registry'); - node.accessPattern = (node) => - $(node.name).attr(registry).attr('get').call(); + node.toAccessNode = (node, options) => { + if (options.context) return; + return $(node.name).attr(registry).attr('get').call(); + }; node.do( $.field(registry, (f) => f diff --git a/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts b/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts index 1b262bc77..206847a68 100644 --- a/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts +++ b/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts @@ -31,7 +31,7 @@ export const createMutationOptions = ({ const awaitSdkFn = $.lazy((ctx) => ctx - .getAccess>( + .access( plugin.referenceSymbol({ category: 'sdk', resource: 'operation', diff --git a/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts b/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts index fa618a150..83ee8b4b8 100644 --- a/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts +++ b/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts @@ -88,7 +88,7 @@ export const createQueryOptions = ({ const typeData = getPublicTypeData({ isNuxtClient, operation, plugin }); const awaitSdkFn = $.lazy((ctx) => ctx - .getAccess>( + .access( plugin.referenceSymbol({ category: 'sdk', resource: 'operation', diff --git a/packages/openapi-ts/src/plugins/@pinia/colada/types.d.ts b/packages/openapi-ts/src/plugins/@pinia/colada/types.d.ts index 2f705d804..22b991e4e 100644 --- a/packages/openapi-ts/src/plugins/@pinia/colada/types.d.ts +++ b/packages/openapi-ts/src/plugins/@pinia/colada/types.d.ts @@ -64,7 +64,7 @@ export type UserConfig = Plugin.Name<'@pinia/colada'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -166,7 +166,7 @@ export type UserConfig = Plugin.Name<'@pinia/colada'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -235,7 +235,7 @@ export type Config = Plugin.Name<'@pinia/colada'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -319,7 +319,7 @@ export type Config = Plugin.Name<'@pinia/colada'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, diff --git a/packages/openapi-ts/src/plugins/@tanstack/angular-query-experimental/types.d.ts b/packages/openapi-ts/src/plugins/@tanstack/angular-query-experimental/types.d.ts index a08cd042d..037052669 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/angular-query-experimental/types.d.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/angular-query-experimental/types.d.ts @@ -106,7 +106,7 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -165,7 +165,7 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -274,7 +274,7 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -379,7 +379,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -428,7 +428,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -517,7 +517,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts index 625ff5f38..ff684aa44 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts @@ -198,7 +198,7 @@ export const createInfiniteQueryOptions = ({ const awaitSdkFn = $.lazy((ctx) => ctx - .getAccess>( + .access( plugin.referenceSymbol({ category: 'sdk', resource: 'operation', diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts index 22b822847..4922cc46e 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts @@ -30,7 +30,7 @@ export const createMutationOptions = ({ const awaitSdkFn = $.lazy((ctx) => ctx - .getAccess>( + .access( plugin.referenceSymbol({ category: 'sdk', resource: 'operation', @@ -57,12 +57,12 @@ export const createMutationOptions = ({ } const mutationOptionsFn = 'mutationOptions'; - const symbolMutationOptions = plugin.registerSymbol({ - name: buildName({ + const symbolMutationOptions = plugin.symbol( + buildName({ config: plugin.config.mutationOptions, name: operation.id, }), - }); + ); const statement = $.const(symbolMutationOptions) .export() .$if(plugin.config.comments && createOperationComment(operation), (c, v) => diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts index 373821c69..6d1ab7650 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts @@ -69,7 +69,7 @@ export const createQueryOptions = ({ const awaitSdkFn = $.lazy((ctx) => ctx - .getAccess>( + .access( plugin.referenceSymbol({ category: 'sdk', resource: 'operation', diff --git a/packages/openapi-ts/src/plugins/@tanstack/react-query/types.d.ts b/packages/openapi-ts/src/plugins/@tanstack/react-query/types.d.ts index 83041ef51..417cff929 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/react-query/types.d.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/react-query/types.d.ts @@ -109,7 +109,7 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -170,7 +170,7 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -282,7 +282,7 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -427,7 +427,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -477,7 +477,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -567,7 +567,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, diff --git a/packages/openapi-ts/src/plugins/@tanstack/solid-query/types.d.ts b/packages/openapi-ts/src/plugins/@tanstack/solid-query/types.d.ts index 883c9877d..7aa9019e2 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/solid-query/types.d.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/solid-query/types.d.ts @@ -107,7 +107,7 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -166,7 +166,7 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -275,7 +275,7 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -380,7 +380,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -429,7 +429,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -518,7 +518,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, diff --git a/packages/openapi-ts/src/plugins/@tanstack/svelte-query/types.d.ts b/packages/openapi-ts/src/plugins/@tanstack/svelte-query/types.d.ts index a11142885..9d69a849e 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/svelte-query/types.d.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/svelte-query/types.d.ts @@ -106,7 +106,7 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -165,7 +165,7 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -274,7 +274,7 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -379,7 +379,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -428,7 +428,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -517,7 +517,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, diff --git a/packages/openapi-ts/src/plugins/@tanstack/vue-query/types.d.ts b/packages/openapi-ts/src/plugins/@tanstack/vue-query/types.d.ts index 5854e1f48..0423081dc 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/vue-query/types.d.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/vue-query/types.d.ts @@ -107,7 +107,7 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -167,7 +167,7 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -277,7 +277,7 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -383,7 +383,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -433,7 +433,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -523,7 +523,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, diff --git a/packages/openapi-ts/src/plugins/swr/types.d.ts b/packages/openapi-ts/src/plugins/swr/types.d.ts index ed557bdfa..2d32551ad 100644 --- a/packages/openapi-ts/src/plugins/swr/types.d.ts +++ b/packages/openapi-ts/src/plugins/swr/types.d.ts @@ -109,7 +109,7 @@ export type UserConfig = Plugin.Name<'swr'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -170,7 +170,7 @@ export type UserConfig = Plugin.Name<'swr'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -282,7 +282,7 @@ export type UserConfig = Plugin.Name<'swr'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -427,7 +427,7 @@ export type Config = Plugin.Name<'swr'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -477,7 +477,7 @@ export type Config = Plugin.Name<'swr'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, @@ -567,7 +567,7 @@ export type Config = Plugin.Name<'swr'> & * @returns A meta object with any properties you want to include * * @example - * ```typescript + * ```ts * meta: (operation) => ({ * customField: operation.id, * isDeprecated: operation.deprecated, diff --git a/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts b/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts index d8419cf06..6106ca74d 100644 --- a/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts +++ b/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts @@ -33,7 +33,7 @@ export const createUseSwr = ({ const awaitSdkFn = $.lazy((ctx) => ctx - .getAccess>( + .access( plugin.referenceSymbol({ category: 'sdk', resource: 'operation', diff --git a/packages/openapi-ts/src/ts-dsl/base.ts b/packages/openapi-ts/src/ts-dsl/base.ts index a52fba10f..6e7613382 100644 --- a/packages/openapi-ts/src/ts-dsl/base.ts +++ b/packages/openapi-ts/src/ts-dsl/base.ts @@ -1,19 +1,15 @@ // TODO: symbol should be protected, but needs to be public to satisfy types import type { - AccessPatternContext, - AccessPatternOptions, AnalysisContext, - AstContext, File, FromRef, Language, Node, NodeName, NodeNameSanitizer, - NodeRole, + NodeRelationship, NodeScope, Ref, - StructuralRelationship, Symbol, } from '@hey-api/codegen-core'; import { @@ -26,16 +22,18 @@ import { } from '@hey-api/codegen-core'; import ts from 'typescript'; +import type { AccessOptions } from './utils/context'; + export type MaybeArray = T | ReadonlyArray; export abstract class TsDsl implements Node { - accessPattern?( - node: this, - options: AccessPatternOptions, - ctx: AccessPatternContext, - ): unknown | undefined; // eslint-disable-next-line @typescript-eslint/no-unused-vars analyze(_: AnalysisContext): void {} + clone(): this { + const cloned = Object.create(Object.getPrototypeOf(this)); + Object.assign(cloned, this); + return cloned; + } exported?: boolean; file?: File; get name(): Node['name'] { @@ -50,18 +48,33 @@ export abstract class TsDsl implements Node { readonly nameSanitizer?: NodeNameSanitizer; language: Language = 'typescript'; parent?: Node; - role?: NodeRole; root: boolean = false; scope?: NodeScope = 'value'; - structuralChildren?: Map; - structuralParents?: Map; + structuralChildren?: Map; + structuralParents?: Map; symbol?: Symbol; - // eslint-disable-next-line @typescript-eslint/no-unused-vars - toAst(_: AstContext): T { + toAst(): T { return undefined as unknown as T; } readonly '~brand' = nodeBrand; + /** Access patterns for this node. */ + toAccessNode?( + node: this, + options: AccessOptions, + ctx: { + /** The full chain. */ + chain: ReadonlyArray; + /** Position in the chain (0 = root). */ + index: number; + /** Is this the leaf node? */ + isLeaf: boolean; + /** Is this the root node? */ + isRoot: boolean; + /** Total length of the chain. */ + length: number; + }, + ): TsDsl | undefined; /** Branding property to identify the DSL class at runtime. */ abstract readonly '~dsl': string & {}; @@ -160,7 +173,7 @@ export abstract class TsDsl implements Node { return String(value); } - protected $node(ctx: AstContext, value: I): NodeOfMaybe { + protected $node(value: I): NodeOfMaybe { if (value === undefined) { return undefined as NodeOfMaybe; } @@ -175,14 +188,13 @@ export abstract class TsDsl implements Node { if (value instanceof Array) { return value.map((item) => { if (isRef(item)) item = fromRef(item); - return this.unwrap(ctx, item); + return this.unwrap(item); }) as NodeOfMaybe; } - return this.unwrap(ctx, value as any) as NodeOfMaybe; + return this.unwrap(value as any) as NodeOfMaybe; } protected $type( - ctx: AstContext, value: I, args?: ReadonlyArray, ): TypeOfMaybe { @@ -212,21 +224,16 @@ export abstract class TsDsl implements Node { ) as TypeOfMaybe; } if (value instanceof Array) { - return value.map((item) => this.$type(ctx, item, args)) as TypeOfMaybe; + return value.map((item) => this.$type(item, args)) as TypeOfMaybe; } - return this.unwrap(ctx, value as any) as TypeOfMaybe; + return this.unwrap(value as any) as TypeOfMaybe; } private _name?: Ref; /** Unwraps nested nodes into raw TypeScript AST. */ - private unwrap( - ctx: AstContext, - value: I, - ): I extends TsDsl ? N : I { - return (isNode(value) ? value.toAst(ctx) : value) as I extends TsDsl< - infer N - > + private unwrap(value: I): I extends TsDsl ? N : I { + return (isNode(value) ? value.toAst() : value) as I extends TsDsl ? N : I; } diff --git a/packages/openapi-ts/src/ts-dsl/decl/class.ts b/packages/openapi-ts/src/ts-dsl/decl/class.ts index 16b5c7070..283325ff9 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/class.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/class.ts @@ -1,10 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - NodeRole, - Ref, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; import { isSymbol, ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -33,7 +27,6 @@ const Mixed = AbstractMixin( export class ClassTsDsl extends Mixed { readonly '~dsl' = 'ClassTsDsl'; override readonly nameSanitizer = safeRuntimeName; - override role?: NodeRole = 'container'; protected baseClass?: Ref; protected body: Body = []; @@ -106,21 +99,21 @@ export class ClassTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { - const body = this.$node(ctx, this.body) as ReadonlyArray; + override toAst() { + const body = this.$node(this.body) as ReadonlyArray; const node = ts.factory.createClassDeclaration( - [...this.$decorators(ctx), ...this.modifiers], - this.$node(ctx, this.name) as ts.Identifier, - this.$generics(ctx), - this._heritage(ctx), + [...this.$decorators(), ...this.modifiers], + this.$node(this.name) as ts.Identifier, + this.$generics(), + this._heritage(), body, ); - return this.$docs(ctx, node); + return this.$docs(node); } /** Builds heritage clauses (extends). */ - private _heritage(ctx: AstContext): ReadonlyArray { - const node = this.$node(ctx, this.baseClass); + private _heritage(): ReadonlyArray { + const node = this.$node(this.baseClass); if (!node) return []; return [ ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [ diff --git a/packages/openapi-ts/src/ts-dsl/decl/decorator.ts b/packages/openapi-ts/src/ts-dsl/decl/decorator.ts index 7506a7062..bb0ed36a6 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/decorator.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/decorator.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -30,9 +26,9 @@ export class DecoratorTsDsl extends Mixed { ctx.analyze(this.name); } - override toAst(ctx: AstContext) { - const target = this.$node(ctx, this.name); - const args = this.$args(ctx); + override toAst() { + const target = this.$node(this.name); + const args = this.$args(); return ts.factory.createDecorator( args.length ? ts.factory.createCallExpression(target, undefined, args) diff --git a/packages/openapi-ts/src/ts-dsl/decl/enum.ts b/packages/openapi-ts/src/ts-dsl/decl/enum.ts index f35f0bd6d..c4717d77a 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/enum.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/enum.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import { isSymbol } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -60,12 +56,12 @@ export class EnumTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { const node = ts.factory.createEnumDeclaration( this.modifiers, - this.$node(ctx, this.name) as ts.Identifier, - this.$node(ctx, this._members) as ReadonlyArray, + this.$node(this.name) as ts.Identifier, + this.$node(this._members) as ReadonlyArray, ); - return this.$docs(ctx, node); + return this.$docs(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/decl/field.ts b/packages/openapi-ts/src/ts-dsl/decl/field.ts index 3ecfff9b4..8f02dfc43 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/field.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/field.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - NodeRole, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl, TypeTsDsl } from '../base'; @@ -41,7 +36,6 @@ const Mixed = DecoratorMixin( export class FieldTsDsl extends Mixed { readonly '~dsl' = 'FieldTsDsl'; - override role?: NodeRole = 'accessor'; protected _type?: TypeTsDsl; @@ -63,14 +57,14 @@ export class FieldTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { const node = ts.factory.createPropertyDeclaration( - [...this.$decorators(ctx), ...this.modifiers], - this.$node(ctx, this.name) as ts.PropertyName, - this._optional ? this.$node(ctx, new TokenTsDsl().optional()) : undefined, - this.$type(ctx, this._type), - this.$value(ctx), + [...this.$decorators(), ...this.modifiers], + this.$node(this.name) as ts.PropertyName, + this._optional ? this.$node(new TokenTsDsl().optional()) : undefined, + this.$type(this._type), + this.$value(), ); - return this.$docs(ctx, node); + return this.$docs(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/decl/func.ts b/packages/openapi-ts/src/ts-dsl/decl/func.ts index ce7f80594..e9763603f 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/func.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/func.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import { isSymbol } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -111,48 +107,46 @@ class ImplFuncTsDsl extends Mixed { } // @ts-expect-error --- need to fix types --- - override toAst( - ctx: AstContext, - ): M extends 'decl' + override toAst(): M extends 'decl' ? ts.FunctionDeclaration : M extends 'expr' ? ts.FunctionExpression : ts.ArrowFunction { - const body = this.$node(ctx, new BlockTsDsl(...this._do).pretty()); + const body = this.$node(new BlockTsDsl(...this._do).pretty()); if (this.mode === 'decl') { const name = this.name.toString(); if (!name) throw new Error('Function declaration requires a name'); const node = ts.factory.createFunctionDeclaration( - [...this.$decorators(ctx), ...this.modifiers], + [...this.$decorators(), ...this.modifiers], undefined, - this.$node(ctx, this.name) as ts.Identifier, - this.$generics(ctx), - this.$params(ctx), - this.$returns(ctx), + this.$node(this.name) as ts.Identifier, + this.$generics(), + this.$params(), + this.$returns(), body, ) as any; - return this.$docs(ctx, node); + return this.$docs(node); } if (this.mode === 'expr') { const node = ts.factory.createFunctionExpression( this.modifiers, undefined, - this.$node(ctx, this.name) as ts.Identifier, - this.$generics(ctx), - this.$params(ctx), - this.$returns(ctx), + this.$node(this.name) as ts.Identifier, + this.$generics(), + this.$params(), + this.$returns(), body, ) as any; - return this.$docs(ctx, node); + return this.$docs(node); } const node = ts.factory.createArrowFunction( this.modifiers, - this.$generics(ctx), - this.$params(ctx), - this.$returns(ctx), + this.$generics(), + this.$params(), + this.$returns(), undefined, body.statements.length === 1 && ts.isReturnStatement(body.statements[0]!) && @@ -160,7 +154,7 @@ class ImplFuncTsDsl extends Mixed { ? body.statements[0].expression : body, ) as any; - return this.$docs(ctx, node); + return this.$docs(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/decl/getter.ts b/packages/openapi-ts/src/ts-dsl/decl/getter.ts index c8276fa38..f7005f566 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/getter.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/getter.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - NodeRole, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -48,7 +43,6 @@ const Mixed = AbstractMixin( export class GetterTsDsl extends Mixed { readonly '~dsl' = 'GetterTsDsl'; override readonly nameSanitizer = safeAccessorName; - override role?: NodeRole = 'accessor'; constructor(name: NodeName, fn?: (g: GetterTsDsl) => void) { super(); @@ -67,14 +61,14 @@ export class GetterTsDsl extends Mixed { } } - override toAst(ctx: AstContext) { + override toAst() { const node = ts.factory.createGetAccessorDeclaration( - [...this.$decorators(ctx), ...this.modifiers], - this.$node(ctx, this.name) as ts.PropertyName, - this.$params(ctx), - this.$returns(ctx), - this.$node(ctx, new BlockTsDsl(...this._do).pretty()), + [...this.$decorators(), ...this.modifiers], + this.$node(this.name) as ts.PropertyName, + this.$params(), + this.$returns(), + this.$node(new BlockTsDsl(...this._do).pretty()), ); - return this.$docs(ctx, node); + return this.$docs(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/decl/init.ts b/packages/openapi-ts/src/ts-dsl/decl/init.ts index 5e024ad5e..41df7fd65 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/init.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/init.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -38,12 +38,12 @@ export class InitTsDsl extends Mixed { } } - override toAst(ctx: AstContext) { + override toAst() { const node = ts.factory.createConstructorDeclaration( - [...this.$decorators(ctx), ...this.modifiers], - this.$params(ctx), - this.$node(ctx, new BlockTsDsl(...this._do).pretty()), + [...this.$decorators(), ...this.modifiers], + this.$params(), + this.$node(new BlockTsDsl(...this._do).pretty()), ); - return this.$docs(ctx, node); + return this.$docs(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/decl/member.ts b/packages/openapi-ts/src/ts-dsl/decl/member.ts index e3cc17d5b..ca7152a24 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/member.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/member.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -41,11 +37,11 @@ export class EnumMemberTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { const node = ts.factory.createEnumMember( - this.$node(ctx, safeMemberName(this.name.toString())), - this.$node(ctx, this._value), + this.$node(safeMemberName(this.name.toString())), + this.$node(this._value), ); - return this.$docs(ctx, node); + return this.$docs(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/decl/method.ts b/packages/openapi-ts/src/ts-dsl/decl/method.ts index 9c4b2653d..7cb4ad76c 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/method.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/method.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - NodeRole, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import { isSymbol } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -56,7 +51,6 @@ const Mixed = AbstractMixin( export class MethodTsDsl extends Mixed { readonly '~dsl' = 'MethodTsDsl'; override readonly nameSanitizer = safeAccessorName; - override role?: NodeRole = 'accessor'; constructor(name: NodeName, fn?: (m: MethodTsDsl) => void) { super(); @@ -78,17 +72,17 @@ export class MethodTsDsl extends Mixed { } } - override toAst(ctx: AstContext) { + override toAst() { const node = ts.factory.createMethodDeclaration( - [...this.$decorators(ctx), ...this.modifiers], + [...this.$decorators(), ...this.modifiers], undefined, - this.$node(ctx, this.name) as ts.PropertyName, - this._optional ? this.$node(ctx, new TokenTsDsl().optional()) : undefined, - this.$generics(ctx), - this.$params(ctx), - this.$returns(ctx), - this.$node(ctx, new BlockTsDsl(...this._do).pretty()), + this.$node(this.name) as ts.PropertyName, + this._optional ? this.$node(new TokenTsDsl().optional()) : undefined, + this.$generics(), + this.$params(), + this.$returns(), + this.$node(new BlockTsDsl(...this._do).pretty()), ); - return this.$docs(ctx, node); + return this.$docs(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/decl/param.ts b/packages/openapi-ts/src/ts-dsl/decl/param.ts index 9652a4c18..e0aa03f10 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/param.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/param.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl, TypeTsDsl } from '../base'; @@ -52,20 +48,20 @@ export class ParamTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { - const name = this.$pattern(ctx) || this.name.toString(); + override toAst() { + const name = this.$pattern() || this.name.toString(); if (!name) { throw new Error( 'Param must have either a name or a destructuring pattern', ); } return ts.factory.createParameterDeclaration( - this.$decorators(ctx), + this.$decorators(), undefined, name, - this._optional ? this.$node(ctx, new TokenTsDsl().optional()) : undefined, - this.$type(ctx, this._type), - this.$value(ctx), + this._optional ? this.$node(new TokenTsDsl().optional()) : undefined, + this.$type(this._type), + this.$value(), ); } } diff --git a/packages/openapi-ts/src/ts-dsl/decl/pattern.ts b/packages/openapi-ts/src/ts-dsl/decl/pattern.ts index 3d3390fd5..7358a684f 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/pattern.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/pattern.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeArray } from '../base'; @@ -53,7 +53,7 @@ export class PatternTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { if (!this.pattern) { throw new Error('PatternTsDsl requires object() or array() pattern'); } @@ -70,7 +70,7 @@ export class PatternTsDsl extends Mixed { ) : ts.factory.createBindingElement(undefined, key, alias, undefined), ); - const spread = this.createSpread(ctx); + const spread = this.createSpread(); if (spread) elements.push(spread); return ts.factory.createObjectBindingPattern(elements); } @@ -79,7 +79,7 @@ export class PatternTsDsl extends Mixed { const elements = this.pattern.values.map((p) => ts.factory.createBindingElement(undefined, undefined, p, undefined), ); - const spread = this.createSpread(ctx); + const spread = this.createSpread(); if (spread) elements.push(spread); return ts.factory.createArrayBindingPattern(elements); } @@ -87,12 +87,12 @@ export class PatternTsDsl extends Mixed { throw new Error('PatternTsDsl requires object() or array() pattern'); } - private createSpread(ctx: AstContext): ts.BindingElement | undefined { + private createSpread(): ts.BindingElement | undefined { return this._spread ? ts.factory.createBindingElement( - this.$node(ctx, new TokenTsDsl().spread()), + this.$node(new TokenTsDsl().spread()), undefined, - this.$node(ctx, new IdTsDsl(this._spread)), + this.$node(new IdTsDsl(this._spread)), ) : undefined; } diff --git a/packages/openapi-ts/src/ts-dsl/decl/setter.ts b/packages/openapi-ts/src/ts-dsl/decl/setter.ts index 352cab4ca..21715f240 100644 --- a/packages/openapi-ts/src/ts-dsl/decl/setter.ts +++ b/packages/openapi-ts/src/ts-dsl/decl/setter.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -60,13 +56,13 @@ export class SetterTsDsl extends Mixed { } } - override toAst(ctx: AstContext) { + override toAst() { const node = ts.factory.createSetAccessorDeclaration( - [...this.$decorators(ctx), ...this.modifiers], - this.$node(ctx, this.name) as ts.PropertyName, - this.$params(ctx), - this.$node(ctx, new BlockTsDsl(...this._do).pretty()), + [...this.$decorators(), ...this.modifiers], + this.$node(this.name) as ts.PropertyName, + this.$params(), + this.$node(new BlockTsDsl(...this._do).pretty()), ); - return this.$docs(ctx, node); + return this.$docs(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/expr/array.ts b/packages/openapi-ts/src/ts-dsl/expr/array.ts index b5b1d76eb..536178456 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/array.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/array.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -59,9 +59,9 @@ export class ArrayTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { const elements = this._elements.map((item) => { - const node = this.$node(ctx, item.expr); + const node = this.$node(item.expr); return item.kind === 'spread' ? ts.factory.createSpreadElement(node) : node; diff --git a/packages/openapi-ts/src/ts-dsl/expr/as.ts b/packages/openapi-ts/src/ts-dsl/expr/as.ts index 684a9b4fb..e8eda2d4c 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/as.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/as.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - Ref, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -37,10 +32,10 @@ export class AsTsDsl extends Mixed { ctx.analyze(this.type); } - override toAst(ctx: AstContext) { + override toAst() { return ts.factory.createAsExpression( - this.$node(ctx, this.expr), - this.$type(ctx, this.type), + this.$node(this.expr), + this.$type(this.type), ); } } diff --git a/packages/openapi-ts/src/ts-dsl/expr/attr.ts b/packages/openapi-ts/src/ts-dsl/expr/attr.ts index 5c2da3625..5950788bd 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/attr.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/attr.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - Ref, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; import { fromRef, isSymbol, ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -48,8 +43,8 @@ export class AttrTsDsl extends Mixed { ctx.analyze(this.name); } - override toAst(ctx: AstContext) { - const leftNode = this.$node(ctx, this.left); + override toAst() { + const leftNode = this.$node(this.left); regexp.typeScriptIdentifier.lastIndex = 0; const right = fromRef(this.name); if (!regexp.typeScriptIdentifier.test(this.name.toString())) { @@ -65,25 +60,25 @@ export class AttrTsDsl extends Mixed { if (this._optional) { return ts.factory.createElementAccessChain( leftNode, - this.$node(ctx, new TokenTsDsl().questionDot()), - this.$node(ctx, new LiteralTsDsl(value)), + this.$node(new TokenTsDsl().questionDot()), + this.$node(new LiteralTsDsl(value)), ); } return ts.factory.createElementAccessExpression( leftNode, - this.$node(ctx, new LiteralTsDsl(value)), + this.$node(new LiteralTsDsl(value)), ); } if (this._optional) { return ts.factory.createPropertyAccessChain( leftNode, - this.$node(ctx, new TokenTsDsl().questionDot()), - this.$node(ctx, this.name) as ts.MemberName, + this.$node(new TokenTsDsl().questionDot()), + this.$node(this.name) as ts.MemberName, ); } return ts.factory.createPropertyAccessExpression( leftNode, - this.$node(ctx, this.name) as ts.MemberName, + this.$node(this.name) as ts.MemberName, ); } } diff --git a/packages/openapi-ts/src/ts-dsl/expr/await.ts b/packages/openapi-ts/src/ts-dsl/expr/await.ts index edeae0610..dcec45c38 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/await.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/await.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - Ref, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -32,8 +27,8 @@ export class AwaitTsDsl extends Mixed { ctx.analyze(this._awaitExpr); } - override toAst(ctx: AstContext) { - return ts.factory.createAwaitExpression(this.$node(ctx, this._awaitExpr)); + override toAst() { + return ts.factory.createAwaitExpression(this.$node(this._awaitExpr)); } } diff --git a/packages/openapi-ts/src/ts-dsl/expr/binary.ts b/packages/openapi-ts/src/ts-dsl/expr/binary.ts index ce8b326ff..0af3c5400 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/binary.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/binary.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - Ref, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -140,15 +135,15 @@ export class BinaryTsDsl extends Mixed { return this.opAndExpr('*', expr); } - override toAst(ctx: AstContext) { + override toAst() { if (!this._op) { throw new Error('BinaryTsDsl: missing operator'); } - const expr = this.$node(ctx, this._expr); + const expr = this.$node(this._expr); if (!expr) { throw new Error('BinaryTsDsl: missing right-hand expression'); } - const base = this.$node(ctx, this._base); + const base = this.$node(this._base); const operator = typeof this._op === 'string' ? this.opToToken(this._op) : this._op; return ts.factory.createBinaryExpression(base, operator, expr); diff --git a/packages/openapi-ts/src/ts-dsl/expr/call.ts b/packages/openapi-ts/src/ts-dsl/expr/call.ts index 86c190612..1a56fdf08 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/call.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/call.ts @@ -1,8 +1,5 @@ -import type { - AnalysisContext, - AstContext, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; +import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -13,10 +10,9 @@ import { ExprMixin } from '../mixins/expr'; import { TypeArgsMixin } from '../mixins/type-args'; import { f } from '../utils/factories'; -export type CallCallee = string | MaybeTsDsl; -export type CallArg = NodeName | MaybeTsDsl; -export type CallArgs = ReadonlyArray; -export type CallCtor = (callee: CallCallee, ...args: CallArgs) => CallTsDsl; +export type CallArgs = ReadonlyArray; +export type CallExpr = NodeName | MaybeTsDsl; +export type CallCtor = (expr: CallExpr, ...args: CallArgs) => CallTsDsl; const Mixed = ArgsMixin( AsMixin(ExprMixin(TypeArgsMixin(TsDsl))), @@ -25,24 +21,24 @@ const Mixed = ArgsMixin( export class CallTsDsl extends Mixed { readonly '~dsl' = 'CallTsDsl'; - protected _callee: CallCallee; + protected _callExpr: Ref; - constructor(callee: CallCallee, ...args: CallArgs) { + constructor(expr: CallExpr, ...args: CallArgs) { super(); - this._callee = callee; + this._callExpr = ref(expr); this.args(...args); } override analyze(ctx: AnalysisContext): void { super.analyze(ctx); - ctx.analyze(this._callee); + ctx.analyze(this._callExpr); } - override toAst(ctx: AstContext) { + override toAst() { return ts.factory.createCallExpression( - this.$node(ctx, this._callee), - this.$generics(ctx), - this.$args(ctx), + this.$node(this._callExpr), + this.$generics(), + this.$args(), ); } } diff --git a/packages/openapi-ts/src/ts-dsl/expr/expr.ts b/packages/openapi-ts/src/ts-dsl/expr/expr.ts index 88ea28517..4c5916730 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/expr.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/expr.ts @@ -1,10 +1,5 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - Ref, -} from '@hey-api/codegen-core'; -import { ref } from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; +import { isNode, isSymbol, ref } from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -28,6 +23,11 @@ export class ExprTsDsl extends Mixed { constructor(id: Id) { super(); this._exprInput = ref(id); + if (typeof id === 'string' || isSymbol(id)) { + this.name.set(id); + } else if (isNode(id)) { + this.name.set(id.name); + } } override analyze(ctx: AnalysisContext): void { @@ -35,7 +35,7 @@ export class ExprTsDsl extends Mixed { ctx.analyze(this._exprInput); } - override toAst(ctx: AstContext) { - return this.$node(ctx, this._exprInput); + override toAst() { + return this.$node(this._exprInput); } } diff --git a/packages/openapi-ts/src/ts-dsl/expr/literal.ts b/packages/openapi-ts/src/ts-dsl/expr/literal.ts index f57dfebd7..39480d144 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/literal.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/literal.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -32,15 +32,13 @@ export class LiteralTsDsl extends Mixed { super.analyze(ctx); } - override toAst(ctx: AstContext) { + override toAst() { if (typeof this.value === 'boolean') { return this.value ? ts.factory.createTrue() : ts.factory.createFalse(); } if (typeof this.value === 'number') { const expr = ts.factory.createNumericLiteral(Math.abs(this.value)); - return this.value < 0 - ? this.$node(ctx, new PrefixTsDsl(expr).neg()) - : expr; + return this.value < 0 ? this.$node(new PrefixTsDsl(expr).neg()) : expr; } if (typeof this.value === 'string') { return ts.factory.createStringLiteral(this.value, true); diff --git a/packages/openapi-ts/src/ts-dsl/expr/new.ts b/packages/openapi-ts/src/ts-dsl/expr/new.ts index 475ed6e3b..b0c86e3ed 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/new.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/new.ts @@ -1,43 +1,46 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - Ref, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; import { TsDsl } from '../base'; import { ArgsMixin } from '../mixins/args'; +import { AsMixin } from '../mixins/as'; import { ExprMixin } from '../mixins/expr'; import { TypeArgsMixin } from '../mixins/type-args'; +import { f } from '../utils/factories'; +export type NewArgs = ReadonlyArray; export type NewExpr = NodeName | MaybeTsDsl; +export type NewCtor = (expr: NewExpr, ...args: NewArgs) => NewTsDsl; -const Mixed = ArgsMixin(ExprMixin(TypeArgsMixin(TsDsl))); +const Mixed = ArgsMixin( + AsMixin(ExprMixin(TypeArgsMixin(TsDsl))), +); export class NewTsDsl extends Mixed { readonly '~dsl' = 'NewTsDsl'; - protected classExpr: Ref; + protected _newExpr: Ref; - constructor(classExpr: NewExpr, ...args: ReadonlyArray) { + constructor(expr: NewExpr, ...args: NewArgs) { super(); - this.classExpr = ref(classExpr); + this._newExpr = ref(expr); this.args(...args); } override analyze(ctx: AnalysisContext): void { super.analyze(ctx); - ctx.analyze(this.classExpr); + ctx.analyze(this._newExpr); } - override toAst(ctx: AstContext) { + override toAst() { return ts.factory.createNewExpression( - this.$node(ctx, this.classExpr), - this.$generics(ctx), - this.$args(ctx), + this.$node(this._newExpr), + this.$generics(), + this.$args(), ); } } + +f.new.set((...args) => new NewTsDsl(...args)); diff --git a/packages/openapi-ts/src/ts-dsl/expr/object.ts b/packages/openapi-ts/src/ts-dsl/expr/object.ts index 98baf7b35..3f4b771f8 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/object.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/object.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -87,11 +83,11 @@ export class ObjectTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { const node = ts.factory.createObjectLiteralExpression( - this.$node(ctx, this._props), + this.$node(this._props), this.$multiline(this._props.length), ); - return this.$hint(ctx, node); + return this.$hint(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/expr/prefix.ts b/packages/openapi-ts/src/ts-dsl/expr/prefix.ts index d67bc4225..a1da1266d 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/prefix.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/prefix.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -50,7 +50,7 @@ export class PrefixTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { if (!this._expr) { throw new Error('Missing expression for prefix unary expression'); } @@ -59,7 +59,7 @@ export class PrefixTsDsl extends Mixed { } return ts.factory.createPrefixUnaryExpression( this._op, - this.$node(ctx, this._expr), + this.$node(this._expr), ); } } diff --git a/packages/openapi-ts/src/ts-dsl/expr/prop.ts b/packages/openapi-ts/src/ts-dsl/expr/prop.ts index aaf267a54..9a94b75fd 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/prop.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/prop.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - Ref, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -58,9 +53,9 @@ export class ObjectPropTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { this.$validate(); - const node = this.$node(ctx, this._value); + const node = this.$node(this._value); if (this.meta.kind === 'spread') { if (ts.isStatement(node)) { throw new Error( @@ -68,23 +63,23 @@ export class ObjectPropTsDsl extends Mixed { ); } const result = ts.factory.createSpreadAssignment(node); - return this.$docs(ctx, result); + return this.$docs(result); } if (this.meta.kind === 'getter') { const getter = new GetterTsDsl(this.meta.name).do(node); - const result = this.$node(ctx, getter); - return this.$docs(ctx, result); + const result = this.$node(getter); + return this.$docs(result); } if (this.meta.kind === 'setter') { const setter = new SetterTsDsl(this.meta.name).do(node); - const result = this.$node(ctx, setter); - return this.$docs(ctx, result); + const result = this.$node(setter); + return this.$docs(result); } if (ts.isIdentifier(node) && node.text === this.meta.name) { const result = ts.factory.createShorthandPropertyAssignment( this.meta.name, ); - return this.$docs(ctx, result); + return this.$docs(result); } if (ts.isStatement(node)) { throw new Error( @@ -94,12 +89,12 @@ export class ObjectPropTsDsl extends Mixed { const result = ts.factory.createPropertyAssignment( this.meta.kind === 'computed' ? ts.factory.createComputedPropertyName( - this.$node(ctx, new IdTsDsl(this.meta.name)), + this.$node(new IdTsDsl(this.meta.name)), ) - : this.$node(ctx, safePropName(this.meta.name)), + : this.$node(safePropName(this.meta.name)), node, ); - return this.$docs(ctx, result); + return this.$docs(result); } $validate(): asserts this is this & { diff --git a/packages/openapi-ts/src/ts-dsl/expr/template.ts b/packages/openapi-ts/src/ts-dsl/expr/template.ts index be153b148..581cabb26 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/template.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/template.ts @@ -1,10 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - NodeRole, - Ref, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; import { fromRef, isSymbol, ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -17,7 +11,6 @@ const Mixed = TsDsl; export class TemplateTsDsl extends Mixed { readonly '~dsl' = 'TemplateTsDsl'; - override role?: NodeRole = 'literal'; protected parts: Array> = []; @@ -38,9 +31,8 @@ export class TemplateTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { const parts = this.$node( - ctx, this.parts.map((p) => { const part = fromRef(p); return isSymbol(part) ? part.finalName : part; diff --git a/packages/openapi-ts/src/ts-dsl/expr/ternary.ts b/packages/openapi-ts/src/ts-dsl/expr/ternary.ts index c1c634ba2..b88091ff4 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/ternary.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/ternary.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -40,17 +40,17 @@ export class TernaryTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { if (!this._condition) throw new Error('Missing condition in ternary'); if (!this._then) throw new Error('Missing then expression in ternary'); if (!this._else) throw new Error('Missing else expression in ternary'); return ts.factory.createConditionalExpression( - this.$node(ctx, this._condition), + this.$node(this._condition), undefined, - this.$node(ctx, this._then), + this.$node(this._then), undefined, - this.$node(ctx, this._else), + this.$node(this._else), ); } } diff --git a/packages/openapi-ts/src/ts-dsl/expr/typeof.ts b/packages/openapi-ts/src/ts-dsl/expr/typeof.ts index 6d8de9b60..99dae0cdc 100644 --- a/packages/openapi-ts/src/ts-dsl/expr/typeof.ts +++ b/packages/openapi-ts/src/ts-dsl/expr/typeof.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -26,8 +26,8 @@ export class TypeOfExprTsDsl extends Mixed { ctx.analyze(this._expr); } - override toAst(ctx: AstContext) { - return ts.factory.createTypeOfExpression(this.$node(ctx, this._expr)); + override toAst() { + return ts.factory.createTypeOfExpression(this.$node(this._expr)); } } diff --git a/packages/openapi-ts/src/ts-dsl/index.ts b/packages/openapi-ts/src/ts-dsl/index.ts index 5b95fae87..17411ade3 100644 --- a/packages/openapi-ts/src/ts-dsl/index.ts +++ b/packages/openapi-ts/src/ts-dsl/index.ts @@ -357,8 +357,8 @@ export type DollarTsDsl = { export type { MaybeTsDsl, TypeTsDsl } from './base'; export { TsDsl } from './base'; -export { TypeScriptRenderer } from './render/typescript'; -export { astContext } from './utils/context'; +export { TsDslContext } from './utils/context'; export { keywords } from './utils/keywords'; export { regexp } from './utils/regexp'; +export { TypeScriptRenderer } from './utils/render'; export { reserved } from './utils/reserved'; diff --git a/packages/openapi-ts/src/ts-dsl/layout/doc.ts b/packages/openapi-ts/src/ts-dsl/layout/doc.ts index 487bd72f9..6ffc643cc 100644 --- a/packages/openapi-ts/src/ts-dsl/layout/doc.ts +++ b/packages/openapi-ts/src/ts-dsl/layout/doc.ts @@ -1,11 +1,12 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeArray } from '../base'; import { TsDsl } from '../base'; import { IdTsDsl } from '../expr/id'; +import { TsDslContext } from '../utils/context'; -type DocMaybeLazy = ((ctx: AstContext) => T) | T; +type DocMaybeLazy = ((ctx: TsDslContext) => T) | T; export type DocFn = (d: DocTsDsl) => void; export type DocLines = DocMaybeLazy>; @@ -29,7 +30,8 @@ export class DocTsDsl extends TsDsl { return this; } - apply(ctx: AstContext, node: T): T { + apply(node: T): T { + const ctx = new TsDslContext(); const lines = this._lines.reduce((lines: Array, line: DocLines) => { if (typeof line === 'function') line = line(ctx); for (const l of typeof line === 'string' ? [line] : line) { @@ -69,10 +71,10 @@ export class DocTsDsl extends TsDsl { return node; } - override toAst(ctx: AstContext): ts.Node { + override toAst(): ts.Node { // this class does not build a standalone node; // it modifies other nodes via `apply()`. // Return a dummy comment node for compliance. - return this.$node(ctx, new IdTsDsl('')); + return this.$node(new IdTsDsl('')); } } diff --git a/packages/openapi-ts/src/ts-dsl/layout/hint.ts b/packages/openapi-ts/src/ts-dsl/layout/hint.ts index ec133fa06..f36b54507 100644 --- a/packages/openapi-ts/src/ts-dsl/layout/hint.ts +++ b/packages/openapi-ts/src/ts-dsl/layout/hint.ts @@ -1,11 +1,12 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeArray } from '../base'; import { TsDsl } from '../base'; import { IdTsDsl } from '../expr/id'; +import { TsDslContext } from '../utils/context'; -type HintMaybeLazy = ((ctx: AstContext) => T) | T; +type HintMaybeLazy = ((ctx: TsDslContext) => T) | T; export type HintFn = (d: HintTsDsl) => void; export type HintLines = HintMaybeLazy>; @@ -29,7 +30,8 @@ export class HintTsDsl extends TsDsl { return this; } - apply(ctx: AstContext, node: T): T { + apply(node: T): T { + const ctx = new TsDslContext(); const lines = this._lines.reduce( (lines: Array, line: HintLines) => { if (typeof line === 'function') line = line(ctx); @@ -54,10 +56,10 @@ export class HintTsDsl extends TsDsl { return node; } - override toAst(ctx: AstContext): ts.Node { + override toAst(): ts.Node { // this class does not build a standalone node; // it modifies other nodes via `apply()`. // Return a dummy comment node for compliance. - return this.$node(ctx, new IdTsDsl('')); + return this.$node(new IdTsDsl('')); } } diff --git a/packages/openapi-ts/src/ts-dsl/layout/newline.ts b/packages/openapi-ts/src/ts-dsl/layout/newline.ts index 2a64ad2b5..7053cbd11 100644 --- a/packages/openapi-ts/src/ts-dsl/layout/newline.ts +++ b/packages/openapi-ts/src/ts-dsl/layout/newline.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import type ts from 'typescript'; import { TsDsl } from '../base'; @@ -11,7 +11,7 @@ export class NewlineTsDsl extends TsDsl { super.analyze(ctx); } - override toAst(ctx: AstContext): ts.Identifier { - return this.$node(ctx, new IdTsDsl('\n')); + override toAst(): ts.Identifier { + return this.$node(new IdTsDsl('\n')); } } diff --git a/packages/openapi-ts/src/ts-dsl/layout/note.ts b/packages/openapi-ts/src/ts-dsl/layout/note.ts index 2a4c85206..ebb639f4c 100644 --- a/packages/openapi-ts/src/ts-dsl/layout/note.ts +++ b/packages/openapi-ts/src/ts-dsl/layout/note.ts @@ -1,11 +1,12 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeArray } from '../base'; import { TsDsl } from '../base'; import { IdTsDsl } from '../expr/id'; +import { TsDslContext } from '../utils/context'; -type NoteMaybeLazy = ((ctx: AstContext) => T) | T; +type NoteMaybeLazy = ((ctx: TsDslContext) => T) | T; export type NoteFn = (d: NoteTsDsl) => void; export type NoteLines = NoteMaybeLazy>; @@ -29,7 +30,8 @@ export class NoteTsDsl extends TsDsl { return this; } - apply(ctx: AstContext, node: T): T { + apply(node: T): T { + const ctx = new TsDslContext(); const lines = this._lines.reduce( (lines: Array, line: NoteLines) => { if (typeof line === 'function') line = line(ctx); @@ -52,10 +54,10 @@ export class NoteTsDsl extends TsDsl { return node; } - override toAst(ctx: AstContext): ts.Node { + override toAst(): ts.Node { // this class does not build a standalone node; // it modifies other nodes via `apply()`. // Return a dummy comment node for compliance. - return this.$node(ctx, new IdTsDsl('')); + return this.$node(new IdTsDsl('')); } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/args.ts b/packages/openapi-ts/src/ts-dsl/mixins/args.ts index c46adf879..6c387cef6 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/args.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/args.ts @@ -1,6 +1,5 @@ import type { AnalysisContext, - AstContext, Node, NodeName, Ref, @@ -15,7 +14,7 @@ type Arg = NodeName | MaybeTsDsl; export interface ArgsMethods extends Node { /** Renders the arguments into an array of `Expression`s. */ - $args(ctx: AstContext): ReadonlyArray; + $args(): ReadonlyArray; /** Adds a single expression argument. */ arg(arg: Arg | undefined): this; /** Adds one or more expression arguments. */ @@ -52,8 +51,8 @@ export function ArgsMixin>( return this; } - protected $args(ctx: AstContext): ReadonlyArray { - return this.$node(ctx, this._args).map((arg) => this.$node(ctx, arg)); + protected $args(): ReadonlyArray { + return this.$node(this._args).map((arg) => this.$node(arg)); } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/decorator.ts b/packages/openapi-ts/src/ts-dsl/mixins/decorator.ts index cce00bce3..cdedeae26 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/decorator.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/decorator.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - Node, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, Node, NodeName } from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -12,7 +7,7 @@ import type { BaseCtor, MixinCtor } from './types'; export interface DecoratorMethods extends Node { /** Renders the decorators into an array of `ts.Decorator`s. */ - $decorators(ctx: AstContext): ReadonlyArray; + $decorators(): ReadonlyArray; /** Adds a decorator (e.g. `@sealed({ in: 'root' })`). */ decorator( name: NodeName | MaybeTsDsl, @@ -41,8 +36,8 @@ export function DecoratorMixin>( return this; } - protected $decorators(ctx: AstContext): ReadonlyArray { - return this.$node(ctx, this.decorators); + protected $decorators(): ReadonlyArray { + return this.$node(this.decorators); } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/do.ts b/packages/openapi-ts/src/ts-dsl/mixins/do.ts index be5c0f4b6..6093b2a8e 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/do.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/do.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; +import type { AnalysisContext, Node } from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -9,7 +9,7 @@ export type DoExpr = MaybeTsDsl; export interface DoMethods extends Node { /** Renders the collected `.do()` calls into an array of `Statement` nodes. */ - $do(ctx: AstContext): ReadonlyArray; + $do(): ReadonlyArray; _do: Array; /** Adds one or more expressions/statements to the body. */ do(...items: ReadonlyArray): this; @@ -41,11 +41,8 @@ export function DoMixin>( return this; } - protected $do(ctx: AstContext): ReadonlyArray { - return this.$node( - ctx, - this._do.map((item) => new StmtTsDsl(item)), - ); + protected $do(): ReadonlyArray { + return this.$node(this._do.map((item) => new StmtTsDsl(item))); } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/doc.ts b/packages/openapi-ts/src/ts-dsl/mixins/doc.ts index 20a6f7e61..034b8cc02 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/doc.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/doc.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; +import type { AnalysisContext, Node } from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { DocFn, DocLines } from '../layout/doc'; @@ -6,7 +6,7 @@ import { DocTsDsl } from '../layout/doc'; import type { BaseCtor, MixinCtor } from './types'; export interface DocMethods extends Node { - $docs(ctx: AstContext, node: T): T; + $docs(node: T): T; doc(lines?: DocLines, fn?: DocFn): this; } @@ -25,8 +25,8 @@ export function DocMixin>( return this; } - protected $docs(ctx: AstContext, node: T): T { - return this._doc ? this._doc.apply(ctx, node) : node; + protected $docs(node: T): T { + return this._doc ? this._doc.apply(node) : node; } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/hint.ts b/packages/openapi-ts/src/ts-dsl/mixins/hint.ts index 4f02443ec..0a2c65330 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/hint.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/hint.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; +import type { AnalysisContext, Node } from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { HintFn, HintLines } from '../layout/hint'; @@ -6,7 +6,7 @@ import { HintTsDsl } from '../layout/hint'; import type { BaseCtor, MixinCtor } from './types'; export interface HintMethods extends Node { - $hint(ctx: AstContext, node: T): T; + $hint(node: T): T; hint(lines?: HintLines, fn?: HintFn): this; } @@ -25,8 +25,8 @@ export function HintMixin>( return this; } - protected $hint(ctx: AstContext, node: T): T { - return this._hint ? this._hint.apply(ctx, node) : node; + protected $hint(node: T): T { + return this._hint ? this._hint.apply(node) : node; } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/modifiers.ts b/packages/openapi-ts/src/ts-dsl/mixins/modifiers.ts index 1182b1fd4..48f8633e2 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/modifiers.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/modifiers.ts @@ -4,18 +4,68 @@ import ts from 'typescript'; import type { BaseCtor, MixinCtor } from './types'; export type Modifiers = { + /** + * Checks if the specified modifier is present. + * + * @param modifier - The modifier to check. + * @returns True if the modifier is present, false otherwise. + */ + hasModifier(modifier: Modifier): boolean; modifiers: Array; }; +type Modifier = + | 'abstract' + | 'async' + | 'const' + | 'declare' + | 'default' + | 'export' + | 'override' + | 'private' + | 'protected' + | 'public' + | 'readonly' + | 'static'; + export interface ModifierMethods extends Modifiers { /** * Adds a modifier of the specified kind to the modifiers list if the condition is true. * - * @param kind - The syntax kind of the modifier to add. + * @param modifier - The modifier to add. * @param condition - Whether to add the modifier. * @returns The parent node for chaining. */ - _m(kind: ts.ModifierSyntaxKind, condition: boolean): this; + _m(modifier: Modifier, condition: boolean): this; +} + +function modifierToKind(modifier: Modifier): ts.ModifierSyntaxKind { + switch (modifier) { + case 'abstract': + return ts.SyntaxKind.AbstractKeyword; + case 'async': + return ts.SyntaxKind.AsyncKeyword; + case 'const': + return ts.SyntaxKind.ConstKeyword; + case 'declare': + return ts.SyntaxKind.DeclareKeyword; + case 'default': + return ts.SyntaxKind.DefaultKeyword; + case 'export': + return ts.SyntaxKind.ExportKeyword; + case 'override': + return ts.SyntaxKind.OverrideKeyword; + case 'private': + return ts.SyntaxKind.PrivateKeyword; + case 'protected': + return ts.SyntaxKind.ProtectedKeyword; + case 'public': + return ts.SyntaxKind.PublicKeyword; + case 'readonly': + return ts.SyntaxKind.ReadonlyKeyword; + case 'static': + return ts.SyntaxKind.StaticKeyword; + } } function ModifiersMixin>( @@ -28,8 +78,16 @@ function ModifiersMixin>( super.analyze(ctx); } - protected _m(kind: ts.ModifierSyntaxKind, condition: boolean): this { - if (condition) this.modifiers.push(ts.factory.createModifier(kind)); + protected hasModifier(modifier: Modifier): boolean { + const kind = modifierToKind(modifier); + return Boolean(this.modifiers.find((mod) => mod.kind === kind)); + } + + protected _m(modifier: Modifier, condition: boolean): this { + if (condition) { + const kind = modifierToKind(modifier); + this.modifiers.push(ts.factory.createModifier(kind)); + } return this; } } @@ -58,7 +116,7 @@ export function AbstractMixin>( abstract class Abstract extends Mixed { protected abstract(condition?: boolean): this { const cond = arguments.length === 0 ? true : Boolean(condition); - return this._m(ts.SyntaxKind.AbstractKeyword, cond); + return this._m('abstract', cond); } } @@ -86,7 +144,7 @@ export function AsyncMixin>( abstract class Async extends Mixed { protected async(condition?: boolean): this { const cond = arguments.length === 0 ? true : Boolean(condition); - return this._m(ts.SyntaxKind.AsyncKeyword, cond); + return this._m('async', cond); } } @@ -114,7 +172,7 @@ export function ConstMixin>( abstract class Const extends Mixed { protected const(condition?: boolean): this { const cond = arguments.length === 0 ? true : Boolean(condition); - return this._m(ts.SyntaxKind.ConstKeyword, cond); + return this._m('const', cond); } } @@ -142,7 +200,7 @@ export function DeclareMixin>( abstract class Declare extends Mixed { protected declare(condition?: boolean): this { const cond = arguments.length === 0 ? true : Boolean(condition); - return this._m(ts.SyntaxKind.DeclareKeyword, cond); + return this._m('declare', cond); } } @@ -176,7 +234,7 @@ export function DefaultMixin>( */ protected default(condition?: boolean): this { const cond = arguments.length === 0 ? true : Boolean(condition); - return this._m(ts.SyntaxKind.DefaultKeyword, cond); + return this._m('default', cond); } } @@ -213,7 +271,7 @@ export function ExportMixin>( this.exported = cond; // TODO: remove this side-effect once planner handles exported flag if (this.symbol) this.symbol.setExported(cond); - return this._m(ts.SyntaxKind.ExportKeyword, cond); + return this._m('export', cond); } } @@ -241,7 +299,7 @@ export function OverrideMixin>( abstract class Override extends Mixed { protected override(condition?: boolean): this { const cond = arguments.length === 0 ? true : Boolean(condition); - return this._m(ts.SyntaxKind.OverrideKeyword, cond); + return this._m('override', cond); } } @@ -269,7 +327,7 @@ export function PrivateMixin>( abstract class Private extends Mixed { protected private(condition?: boolean): this { const cond = arguments.length === 0 ? true : Boolean(condition); - return this._m(ts.SyntaxKind.PrivateKeyword, cond); + return this._m('private', cond); } } @@ -297,7 +355,7 @@ export function ProtectedMixin>( abstract class Protected extends Mixed { protected protected(condition?: boolean): this { const cond = arguments.length === 0 ? true : Boolean(condition); - return this._m(ts.SyntaxKind.ProtectedKeyword, cond); + return this._m('protected', cond); } } @@ -325,7 +383,7 @@ export function PublicMixin>( abstract class Public extends Mixed { protected public(condition?: boolean): this { const cond = arguments.length === 0 ? true : Boolean(condition); - return this._m(ts.SyntaxKind.PublicKeyword, cond); + return this._m('public', cond); } } @@ -353,7 +411,7 @@ export function ReadonlyMixin>( abstract class Readonly extends Mixed { protected readonly(condition?: boolean): this { const cond = arguments.length === 0 ? true : Boolean(condition); - return this._m(ts.SyntaxKind.ReadonlyKeyword, cond); + return this._m('readonly', cond); } } @@ -381,7 +439,7 @@ export function StaticMixin>( abstract class Static extends Mixed { protected static(condition?: boolean): this { const cond = arguments.length === 0 ? true : Boolean(condition); - return this._m(ts.SyntaxKind.StaticKeyword, cond); + return this._m('static', cond); } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/note.ts b/packages/openapi-ts/src/ts-dsl/mixins/note.ts index a0d26d97c..3f981e52c 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/note.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/note.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; +import type { AnalysisContext, Node } from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { NoteFn, NoteLines } from '../layout/note'; @@ -6,7 +6,7 @@ import { NoteTsDsl } from '../layout/note'; import type { BaseCtor, MixinCtor } from './types'; export interface NoteMethods extends Node { - $note(ctx: AstContext, node: T): T; + $note(node: T): T; note(lines?: NoteLines, fn?: NoteFn): this; } @@ -25,8 +25,8 @@ export function NoteMixin>( return this; } - protected $note(ctx: AstContext, node: T): T { - return this._note ? this._note.apply(ctx, node) : node; + protected $note(node: T): T { + return this._note ? this._note.apply(node) : node; } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/param.ts b/packages/openapi-ts/src/ts-dsl/mixins/param.ts index 7d6eac50e..d467559aa 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/param.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/param.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - Node, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, Node, NodeName } from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -13,7 +8,7 @@ import type { BaseCtor, MixinCtor } from './types'; export interface ParamMethods extends Node { /** Renders the parameters into an array of `ParameterDeclaration`s. */ - $params(ast: AstContext): ReadonlyArray; + $params(): ReadonlyArray; /** Adds a parameter. */ param(...args: Parameters): this; /** Adds multiple parameters. */ @@ -49,8 +44,8 @@ export function ParamMixin>( return this; } - protected $params(ctx: AstContext): ReadonlyArray { - return this.$node(ctx, this._params); + protected $params(): ReadonlyArray { + return this.$node(this._params); } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/pattern.ts b/packages/openapi-ts/src/ts-dsl/mixins/pattern.ts index a4df04d4d..b4a35e0aa 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/pattern.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/pattern.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; +import type { AnalysisContext, Node } from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { MaybeArray } from '../base'; @@ -7,7 +7,7 @@ import type { BaseCtor, MixinCtor } from './types'; export interface PatternMethods extends Node { /** Renders the pattern into a `BindingName`. */ - $pattern(ctx: AstContext): ts.BindingName | undefined; + $pattern(): ts.BindingName | undefined; /** Defines an array binding pattern. */ array(...props: ReadonlyArray | [ReadonlyArray]): this; /** Defines an object binding pattern. */ @@ -53,9 +53,9 @@ export function PatternMixin>( } /** Renders the pattern into a `BindingName`. */ - protected $pattern(ctx: AstContext): ts.BindingName | undefined { + protected $pattern(): ts.BindingName | undefined { if (!this.pattern) return; - return this.$node(ctx, this.pattern); + return this.$node(this.pattern); } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/type-args.ts b/packages/openapi-ts/src/ts-dsl/mixins/type-args.ts index d13119d36..d32eb0973 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/type-args.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/type-args.ts @@ -1,6 +1,5 @@ import type { AnalysisContext, - AstContext, Node, NodeName, Ref, @@ -15,7 +14,7 @@ type Arg = NodeName | MaybeTsDsl; export interface TypeArgsMethods extends Node { /** Returns the type arguments as an array of ts.TypeNode nodes. */ - $generics(ctx: AstContext): ReadonlyArray | undefined; + $generics(): ReadonlyArray | undefined; /** Adds a single type argument (e.g. `string` in `Foo`). */ generic(arg: Arg): this; /** Adds type arguments (e.g. `Map`). */ @@ -45,10 +44,8 @@ export function TypeArgsMixin>( return this; } - protected $generics( - ctx: AstContext, - ): ReadonlyArray | undefined { - return this.$type(ctx, this._generics); + protected $generics(): ReadonlyArray | undefined { + return this.$type(this._generics); } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/type-params.ts b/packages/openapi-ts/src/ts-dsl/mixins/type-params.ts index 8988b1d6b..9c37edc28 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/type-params.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/type-params.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - Node, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, Node, NodeName } from '@hey-api/codegen-core'; import { isRef, isSymbol } from '@hey-api/codegen-core'; import type ts from 'typescript'; @@ -13,9 +8,7 @@ import type { BaseCtor, MixinCtor } from './types'; export interface TypeParamsMethods extends Node { /** Returns the type parameters as an array of ts.TypeParameterDeclaration nodes. */ - $generics( - ast: AstContext, - ): ReadonlyArray | undefined; + $generics(): ReadonlyArray | undefined; /** Adds a single type parameter (e.g. `T` in `Array`). */ generic(...args: ConstructorParameters): this; /** Adds type parameters (e.g. `Map`). */ @@ -60,10 +53,10 @@ export function TypeParamsMixin>( return this; } - protected $generics( - ctx: AstContext, - ): ReadonlyArray | undefined { - return this.$node(ctx, this._generics); + protected $generics(): + | ReadonlyArray + | undefined { + return this.$node(this._generics); } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/type-returns.ts b/packages/openapi-ts/src/ts-dsl/mixins/type-returns.ts index db77b8c1e..6bad5b7d2 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/type-returns.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/type-returns.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - Node, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, Node, NodeName } from '@hey-api/codegen-core'; import type ts from 'typescript'; import { TypeTsDsl } from '../base'; @@ -12,7 +7,7 @@ import type { BaseCtor, MixinCtor } from './types'; export interface TypeReturnsMethods extends Node { /** Returns the return type node. */ - $returns(ctx: AstContext): ts.TypeNode | undefined; + $returns(): ts.TypeNode | undefined; /** Sets the return type. */ returns(type: NodeName | TypeTsDsl): this; } @@ -34,8 +29,8 @@ export function TypeReturnsMixin>( return this; } - protected $returns(ctx: AstContext): ts.TypeNode | undefined { - return this.$type(ctx, this._returns); + protected $returns(): ts.TypeNode | undefined { + return this.$type(this._returns); } } diff --git a/packages/openapi-ts/src/ts-dsl/mixins/value.ts b/packages/openapi-ts/src/ts-dsl/mixins/value.ts index 9166bab19..de3f21618 100644 --- a/packages/openapi-ts/src/ts-dsl/mixins/value.ts +++ b/packages/openapi-ts/src/ts-dsl/mixins/value.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; +import type { AnalysisContext, Node } from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -7,7 +7,7 @@ import type { BaseCtor, MixinCtor } from './types'; export type ValueExpr = string | MaybeTsDsl; export interface ValueMethods extends Node { - $value(ctx: AstContext): ts.Expression | undefined; + $value(): ts.Expression | undefined; /** Sets the initializer expression (e.g. `= expr`). */ assign(expr: ValueExpr): this; } @@ -28,8 +28,8 @@ export function ValueMixin>( return this; } - protected $value(ctx: AstContext): ts.Expression | undefined { - return this.$node(ctx, this.value); + protected $value(): ts.Expression | undefined { + return this.$node(this.value); } } diff --git a/packages/openapi-ts/src/ts-dsl/stmt/block.ts b/packages/openapi-ts/src/ts-dsl/stmt/block.ts index f69a1506a..7277be85a 100644 --- a/packages/openapi-ts/src/ts-dsl/stmt/block.ts +++ b/packages/openapi-ts/src/ts-dsl/stmt/block.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -20,8 +20,8 @@ export class BlockTsDsl extends Mixed { super.analyze(ctx); } - override toAst(ctx: AstContext) { - const statements = this.$do(ctx); + override toAst() { + const statements = this.$do(); return ts.factory.createBlock( statements, this.$multiline(statements.length), diff --git a/packages/openapi-ts/src/ts-dsl/stmt/if.ts b/packages/openapi-ts/src/ts-dsl/stmt/if.ts index 25b4a1df2..37b521853 100644 --- a/packages/openapi-ts/src/ts-dsl/stmt/if.ts +++ b/packages/openapi-ts/src/ts-dsl/stmt/if.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -47,15 +47,15 @@ export class IfTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { if (!this._condition) throw new Error('Missing condition in if'); if (!this._do) throw new Error('Missing then block in if'); return ts.factory.createIfStatement( - this.$node(ctx, this._condition), - this.$node(ctx, new BlockTsDsl(...this._do).pretty()), + this.$node(this._condition), + this.$node(new BlockTsDsl(...this._do).pretty()), this._else - ? this.$node(ctx, new BlockTsDsl(...this._else).pretty()) + ? this.$node(new BlockTsDsl(...this._else).pretty()) : undefined, ); } diff --git a/packages/openapi-ts/src/ts-dsl/stmt/return.ts b/packages/openapi-ts/src/ts-dsl/stmt/return.ts index 83037f870..259a521cc 100644 --- a/packages/openapi-ts/src/ts-dsl/stmt/return.ts +++ b/packages/openapi-ts/src/ts-dsl/stmt/return.ts @@ -1,9 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, - Ref, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; import { ref } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -31,8 +26,8 @@ export class ReturnTsDsl extends Mixed { ctx.analyze(this._returnExpr); } - override toAst(ctx: AstContext) { - return ts.factory.createReturnStatement(this.$node(ctx, this._returnExpr)); + override toAst() { + return ts.factory.createReturnStatement(this.$node(this._returnExpr)); } } diff --git a/packages/openapi-ts/src/ts-dsl/stmt/stmt.ts b/packages/openapi-ts/src/ts-dsl/stmt/stmt.ts index 24f455680..b5f1bd383 100644 --- a/packages/openapi-ts/src/ts-dsl/stmt/stmt.ts +++ b/packages/openapi-ts/src/ts-dsl/stmt/stmt.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -20,8 +20,8 @@ export class StmtTsDsl extends Mixed { ctx.analyze(this._inner); } - override toAst(ctx: AstContext) { - const node = this.$node(ctx, this._inner); + override toAst() { + const node = this.$node(this._inner); return ts.isStatement(node) ? node : ts.factory.createExpressionStatement(node); diff --git a/packages/openapi-ts/src/ts-dsl/stmt/throw.ts b/packages/openapi-ts/src/ts-dsl/stmt/throw.ts index 10f8f0d2b..bf9aa9a00 100644 --- a/packages/openapi-ts/src/ts-dsl/stmt/throw.ts +++ b/packages/openapi-ts/src/ts-dsl/stmt/throw.ts @@ -1,4 +1,4 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -31,13 +31,10 @@ export class ThrowTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { - const errorNode = this.$node(ctx, this.error); - const messageNode = this.$node(ctx, this.msg ? [this.msg] : []).map( - (expr) => - typeof expr === 'string' - ? this.$node(ctx, new LiteralTsDsl(expr)) - : expr, + override toAst() { + const errorNode = this.$node(this.error); + const messageNode = this.$node(this.msg ? [this.msg] : []).map((expr) => + typeof expr === 'string' ? this.$node(new LiteralTsDsl(expr)) : expr, ); if (this.useNew) { return ts.factory.createThrowStatement( diff --git a/packages/openapi-ts/src/ts-dsl/stmt/try.ts b/packages/openapi-ts/src/ts-dsl/stmt/try.ts index 11fb6fec0..781297558 100644 --- a/packages/openapi-ts/src/ts-dsl/stmt/try.ts +++ b/packages/openapi-ts/src/ts-dsl/stmt/try.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -78,23 +74,23 @@ export class TryTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { if (!this._try?.length) throw new Error('Missing try block'); const catchParam = this._catchArg - ? (this.$node(ctx, this._catchArg) as ts.BindingName) + ? (this.$node(this._catchArg) as ts.BindingName) : undefined; return ts.factory.createTryStatement( - this.$node(ctx, new BlockTsDsl(...this._try).pretty()), + this.$node(new BlockTsDsl(...this._try).pretty()), ts.factory.createCatchClause( catchParam ? ts.factory.createVariableDeclaration(catchParam) : undefined, - this.$node(ctx, new BlockTsDsl(...(this._catch ?? [])).pretty()), + this.$node(new BlockTsDsl(...(this._catch ?? [])).pretty()), ), this._finally - ? this.$node(ctx, new BlockTsDsl(...this._finally).pretty()) + ? this.$node(new BlockTsDsl(...this._finally).pretty()) : undefined, ); } diff --git a/packages/openapi-ts/src/ts-dsl/stmt/var.ts b/packages/openapi-ts/src/ts-dsl/stmt/var.ts index 014edffcd..a33942cbc 100644 --- a/packages/openapi-ts/src/ts-dsl/stmt/var.ts +++ b/packages/openapi-ts/src/ts-dsl/stmt/var.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeName, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; import { isSymbol } from '@hey-api/codegen-core'; import ts from 'typescript'; @@ -66,8 +62,8 @@ export class VarTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { - const name = this.$pattern(ctx) ?? this.$node(ctx, this.name); + override toAst() { + const name = this.$pattern() ?? this.$node(this.name); if (!name) throw new Error('Var must have either a name or a destructuring pattern'); const node = ts.factory.createVariableStatement( @@ -77,13 +73,13 @@ export class VarTsDsl extends Mixed { ts.factory.createVariableDeclaration( name as ts.BindingName, undefined, - this.$type(ctx, this._type), - this.$value(ctx), + this.$type(this._type), + this.$value(), ), ], this.kind, ), ); - return this.$docs(ctx, this.$hint(ctx, node)); + return this.$docs(this.$hint(node)); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/alias.ts b/packages/openapi-ts/src/ts-dsl/type/alias.ts index c6ed5fdf8..e70a470ac 100644 --- a/packages/openapi-ts/src/ts-dsl/type/alias.ts +++ b/packages/openapi-ts/src/ts-dsl/type/alias.ts @@ -1,6 +1,5 @@ import type { AnalysisContext, - AstContext, NodeName, NodeScope, } from '@hey-api/codegen-core'; @@ -49,17 +48,17 @@ export class TypeAliasTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { if (!this.value) throw new Error( `Type alias '${this.name.toString()}' is missing a type definition`, ); const node = ts.factory.createTypeAliasDeclaration( this.modifiers, - this.$node(ctx, this.name) as ts.Identifier, - this.$generics(ctx), - this.$type(ctx, this.value), + this.$node(this.name) as ts.Identifier, + this.$generics(), + this.$type(this.value), ); - return this.$docs(ctx, node); + return this.$docs(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/and.ts b/packages/openapi-ts/src/ts-dsl/type/and.ts index f708d57ad..dfea332be 100644 --- a/packages/openapi-ts/src/ts-dsl/type/and.ts +++ b/packages/openapi-ts/src/ts-dsl/type/and.ts @@ -1,6 +1,5 @@ import type { AnalysisContext, - AstContext, NodeName, NodeScope, Ref, @@ -38,11 +37,11 @@ export class TypeAndTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { const flat: Array = []; for (const node of this._types) { - const type = this.$type(ctx, node); + const type = this.$type(node); if (ts.isIntersectionTypeNode(type)) { flat.push(...type.types); } else { diff --git a/packages/openapi-ts/src/ts-dsl/type/attr.ts b/packages/openapi-ts/src/ts-dsl/type/attr.ts index 80d7daee5..fee185bdf 100644 --- a/packages/openapi-ts/src/ts-dsl/type/attr.ts +++ b/packages/openapi-ts/src/ts-dsl/type/attr.ts @@ -1,6 +1,5 @@ import type { AnalysisContext, - AstContext, NodeName, NodeScope, Ref, @@ -57,17 +56,17 @@ export class TypeAttrTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { if (!this._base) { throw new Error('TypeAttrTsDsl: missing base for qualified name'); } - const left = this.$node(ctx, this._base); + const left = this.$node(this._base); if (!ts.isEntityName(left)) { throw new Error('TypeAttrTsDsl: base must be an EntityName'); } return ts.factory.createQualifiedName( left, - this.$node(ctx, this._right) as ts.Identifier, + this.$node(this._right) as ts.Identifier, ); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/expr.ts b/packages/openapi-ts/src/ts-dsl/type/expr.ts index b97a1d5ea..7cb4a3073 100644 --- a/packages/openapi-ts/src/ts-dsl/type/expr.ts +++ b/packages/openapi-ts/src/ts-dsl/type/expr.ts @@ -1,6 +1,5 @@ import type { AnalysisContext, - AstContext, NodeName, NodeScope, Ref, @@ -56,11 +55,11 @@ export class TypeExprTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { if (!this._exprInput) throw new Error('TypeExpr must have an expression'); return ts.factory.createTypeReferenceNode( - this.$type(ctx, this._exprInput) as ts.EntityName, - this.$generics(ctx), + this.$type(this._exprInput) as ts.EntityName, + this.$generics(), ); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/func.ts b/packages/openapi-ts/src/ts-dsl/type/func.ts index b0abaaa74..5710924cc 100644 --- a/packages/openapi-ts/src/ts-dsl/type/func.ts +++ b/packages/openapi-ts/src/ts-dsl/type/func.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeScope, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeScope } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -23,16 +19,16 @@ export class TypeFuncTsDsl extends Mixed { super.analyze(ctx); } - override toAst(ctx: AstContext) { - const returns = this.$returns(ctx); + override toAst() { + const returns = this.$returns(); if (returns === undefined) { throw new Error('Missing return type in function type DSL'); } const node = ts.factory.createFunctionTypeNode( - this.$generics(ctx), - this.$params(ctx), + this.$generics(), + this.$params(), returns, ); - return this.$docs(ctx, node); + return this.$docs(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/idx-sig.ts b/packages/openapi-ts/src/ts-dsl/type/idx-sig.ts index 5c4120ad1..1bddd6030 100644 --- a/packages/openapi-ts/src/ts-dsl/type/idx-sig.ts +++ b/packages/openapi-ts/src/ts-dsl/type/idx-sig.ts @@ -1,6 +1,5 @@ import type { AnalysisContext, - AstContext, NodeName, NodeScope, } from '@hey-api/codegen-core'; @@ -51,7 +50,7 @@ export class TypeIdxSigTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { this.$validate(); const node = ts.factory.createIndexSignature( this.modifiers, @@ -59,14 +58,14 @@ export class TypeIdxSigTsDsl extends Mixed { ts.factory.createParameterDeclaration( undefined, undefined, - this.$node(ctx, this.name) as ts.BindingName, + this.$node(this.name) as ts.BindingName, undefined, - this.$type(ctx, this._key), + this.$type(this._key), ), ], - this.$type(ctx, this._type), + this.$type(this._type), ); - return this.$docs(ctx, node); + return this.$docs(node); } $validate(): asserts this is this & { diff --git a/packages/openapi-ts/src/ts-dsl/type/idx.ts b/packages/openapi-ts/src/ts-dsl/type/idx.ts index 4817cd907..ae2693045 100644 --- a/packages/openapi-ts/src/ts-dsl/type/idx.ts +++ b/packages/openapi-ts/src/ts-dsl/type/idx.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeScope, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeScope } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -45,10 +41,10 @@ export class TypeIdxTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { return ts.factory.createIndexedAccessTypeNode( - this.$type(ctx, this._base), - this.$type(ctx, this._index), + this.$type(this._base), + this.$type(this._index), ); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/literal.ts b/packages/openapi-ts/src/ts-dsl/type/literal.ts index 2b7356f37..006b0bc42 100644 --- a/packages/openapi-ts/src/ts-dsl/type/literal.ts +++ b/packages/openapi-ts/src/ts-dsl/type/literal.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeScope, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeScope } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -25,9 +21,9 @@ export class TypeLiteralTsDsl extends Mixed { super.analyze(ctx); } - override toAst(ctx: AstContext) { + override toAst() { return ts.factory.createLiteralTypeNode( - this.$node(ctx, new LiteralTsDsl(this.value)), + this.$node(new LiteralTsDsl(this.value)), ); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/mapped.ts b/packages/openapi-ts/src/ts-dsl/type/mapped.ts index 5c1b5004e..147751a98 100644 --- a/packages/openapi-ts/src/ts-dsl/type/mapped.ts +++ b/packages/openapi-ts/src/ts-dsl/type/mapped.ts @@ -1,6 +1,5 @@ import type { AnalysisContext, - AstContext, NodeName, NodeScope, } from '@hey-api/codegen-core'; @@ -83,19 +82,19 @@ export class TypeMappedTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { this.$validate(); return ts.factory.createMappedTypeNode( - this.$node(ctx, this.readonlyToken), + this.$node(this.readonlyToken), ts.factory.createTypeParameterDeclaration( undefined, - this.$node(ctx, this.name) as ts.Identifier, - this.$type(ctx, this._key), + this.$node(this.name) as ts.Identifier, + this.$type(this._key), undefined, ), undefined, - this.$node(ctx, this.questionToken), - this.$type(ctx, this._type), + this.$node(this.questionToken), + this.$type(this._type), undefined, ); } diff --git a/packages/openapi-ts/src/ts-dsl/type/object.ts b/packages/openapi-ts/src/ts-dsl/type/object.ts index f602832df..24091060f 100644 --- a/packages/openapi-ts/src/ts-dsl/type/object.ts +++ b/packages/openapi-ts/src/ts-dsl/type/object.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeScope, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeScope } from '@hey-api/codegen-core'; import ts from 'typescript'; import { TsDsl } from '../base'; @@ -48,7 +44,7 @@ export class TypeObjectTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { - return ts.factory.createTypeLiteralNode(this.$node(ctx, this.props)); + override toAst() { + return ts.factory.createTypeLiteralNode(this.$node(this.props)); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/operator.ts b/packages/openapi-ts/src/ts-dsl/type/operator.ts index dfffd5e43..06403ae96 100644 --- a/packages/openapi-ts/src/ts-dsl/type/operator.ts +++ b/packages/openapi-ts/src/ts-dsl/type/operator.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeScope, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeScope } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -75,12 +71,9 @@ export class TypeOperatorTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { this.$validate(); - return ts.factory.createTypeOperatorNode( - this._op, - this.$type(ctx, this._type), - ); + return ts.factory.createTypeOperatorNode(this._op, this.$type(this._type)); } /** Throws if required fields are not set. */ diff --git a/packages/openapi-ts/src/ts-dsl/type/or.ts b/packages/openapi-ts/src/ts-dsl/type/or.ts index 2a4a07e76..08bbeeb88 100644 --- a/packages/openapi-ts/src/ts-dsl/type/or.ts +++ b/packages/openapi-ts/src/ts-dsl/type/or.ts @@ -1,6 +1,5 @@ import type { AnalysisContext, - AstContext, NodeName, NodeScope, Ref, @@ -38,11 +37,11 @@ export class TypeOrTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { const flat: Array = []; for (const node of this._types) { - const type = this.$type(ctx, node); + const type = this.$type(node); if (ts.isUnionTypeNode(type)) { flat.push(...type.types); } else { diff --git a/packages/openapi-ts/src/ts-dsl/type/param.ts b/packages/openapi-ts/src/ts-dsl/type/param.ts index 95b3c5842..2cf522b76 100644 --- a/packages/openapi-ts/src/ts-dsl/type/param.ts +++ b/packages/openapi-ts/src/ts-dsl/type/param.ts @@ -1,6 +1,5 @@ import type { AnalysisContext, - AstContext, NodeName, NodeScope, Ref, @@ -45,14 +44,14 @@ export class TypeParamTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { const name = this.name.toString(); if (!name) throw new Error('Missing type name'); return ts.factory.createTypeParameterDeclaration( undefined, - this.$node(ctx, this.name) as ts.Identifier, - this.$type(ctx, this.constraint), - this.$type(ctx, this.defaultValue), + this.$node(this.name) as ts.Identifier, + this.$type(this.constraint), + this.$type(this.defaultValue), ); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/prop.ts b/packages/openapi-ts/src/ts-dsl/type/prop.ts index 79c9e6aeb..ec19c68f8 100644 --- a/packages/openapi-ts/src/ts-dsl/type/prop.ts +++ b/packages/openapi-ts/src/ts-dsl/type/prop.ts @@ -1,6 +1,5 @@ import type { AnalysisContext, - AstContext, NodeName, NodeScope, Ref, @@ -43,17 +42,17 @@ export class TypePropTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { const name = this.name.toString(); if (!this._type || !name) { throw new Error(`Type not specified for property '${name}'`); } const node = ts.factory.createPropertySignature( this.modifiers, - this.$node(ctx, safePropName(name)), - this._optional ? this.$node(ctx, new TokenTsDsl().optional()) : undefined, - this.$type(ctx, this._type), + this.$node(safePropName(name)), + this._optional ? this.$node(new TokenTsDsl().optional()) : undefined, + this.$type(this._type), ); - return this.$docs(ctx, node); + return this.$docs(node); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/query.ts b/packages/openapi-ts/src/ts-dsl/type/query.ts index f1560b88e..7f5c3606a 100644 --- a/packages/openapi-ts/src/ts-dsl/type/query.ts +++ b/packages/openapi-ts/src/ts-dsl/type/query.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeScope, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeScope } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl, TypeTsDsl } from '../base'; @@ -31,8 +27,8 @@ export class TypeQueryTsDsl extends Mixed { ctx.analyze(this._expr); } - override toAst(ctx: AstContext) { - const expr = this.$node(ctx, this._expr); + override toAst() { + const expr = this.$node(this._expr); return ts.factory.createTypeQueryNode(expr as unknown as ts.EntityName); } } diff --git a/packages/openapi-ts/src/ts-dsl/type/template.ts b/packages/openapi-ts/src/ts-dsl/type/template.ts index a48aec033..0b0400e35 100644 --- a/packages/openapi-ts/src/ts-dsl/type/template.ts +++ b/packages/openapi-ts/src/ts-dsl/type/template.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeScope, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeScope } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { MaybeTsDsl } from '../base'; @@ -34,8 +30,8 @@ export class TypeTemplateTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { - const parts = this.$node(ctx, this.parts); + override toAst() { + const parts = this.$node(this.parts); const normalized: Array = []; // merge consecutive string parts diff --git a/packages/openapi-ts/src/ts-dsl/type/tuple.ts b/packages/openapi-ts/src/ts-dsl/type/tuple.ts index eb76d66ef..9f1e88ca8 100644 --- a/packages/openapi-ts/src/ts-dsl/type/tuple.ts +++ b/packages/openapi-ts/src/ts-dsl/type/tuple.ts @@ -1,8 +1,4 @@ -import type { - AnalysisContext, - AstContext, - NodeScope, -} from '@hey-api/codegen-core'; +import type { AnalysisContext, NodeScope } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { TypeTsDsl } from '../base'; @@ -33,9 +29,9 @@ export class TypeTupleTsDsl extends Mixed { return this; } - override toAst(ctx: AstContext) { + override toAst() { return ts.factory.createTupleTypeNode( - this._elements.map((t) => this.$type(ctx, t)), + this._elements.map((t) => this.$type(t)), ); } } diff --git a/packages/openapi-ts/src/ts-dsl/render/__tests__/typescript.test.ts b/packages/openapi-ts/src/ts-dsl/utils/__tests__/render.test.ts similarity index 87% rename from packages/openapi-ts/src/ts-dsl/render/__tests__/typescript.test.ts rename to packages/openapi-ts/src/ts-dsl/utils/__tests__/render.test.ts index 6a61f1ec5..f748ce7e3 100644 --- a/packages/openapi-ts/src/ts-dsl/render/__tests__/typescript.test.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/__tests__/render.test.ts @@ -3,10 +3,10 @@ import { Project } from '@hey-api/codegen-core'; import ts from 'typescript'; import { describe, expect, it } from 'vitest'; -import { astContext, type TsDsl } from '~/ts-dsl'; +import type { TsDsl } from '~/ts-dsl'; -import { TypeScriptRenderer } from '../typescript'; -import type { ModuleExport, ModuleImport } from '../utils'; +import { TypeScriptRenderer } from '../render'; +import type { ModuleExport, ModuleImport } from '../render-utils'; describe('TypeScriptRenderer', () => { const renderer = new TypeScriptRenderer(); @@ -57,7 +57,7 @@ describe('TypeScriptRenderer', () => { modulePath: 'foo', namespaceImport: undefined, }; - const node = renderer['renderImport'](astContext, group); + const node = renderer['renderImport'](group); expect(ts.isImportDeclaration(node)).toBe(true); }); @@ -76,7 +76,7 @@ describe('TypeScriptRenderer', () => { modulePath: 'bar', namespaceExport: undefined, }; - const node = renderer['renderExport'](astContext, group); + const node = renderer['renderExport'](group); expect(ts.isExportDeclaration(node)).toBe(true); }); }); diff --git a/packages/openapi-ts/src/ts-dsl/utils/context.ts b/packages/openapi-ts/src/ts-dsl/utils/context.ts index 65b5601d9..f4e6b43b2 100644 --- a/packages/openapi-ts/src/ts-dsl/utils/context.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/context.ts @@ -1,113 +1,254 @@ -import type { - AccessPatternOptions, - AstContext, - NodeScope, - Symbol, -} from '@hey-api/codegen-core'; +import type { BindingKind, NodeScope, Symbol } from '@hey-api/codegen-core'; import { isSymbol } from '@hey-api/codegen-core'; +import type ts from 'typescript'; -import { $ } from '~/ts-dsl'; +import { $, TypeScriptRenderer } from '~/ts-dsl'; import type { TsDsl } from '../base'; +import type { CallArgs } from '../expr/call'; -const getScope = (node: TsDsl): NodeScope => node.scope ?? 'value'; +export type NodeChain = ReadonlyArray; -function traverseStructuralParent(node: TsDsl): boolean { - if (node.role === 'literal') { - return false; - } - return true; +export interface AccessOptions { + /** The access context. */ + context?: 'example'; } -function foldAccessChain( - chain: ReadonlyArray, -): ReadonlyArray { - const folded: Array = []; +export type AccessResult = ReturnType< + typeof $.expr | typeof $.attr | typeof $.call | typeof $.new +>; + +export interface ExampleOptions { + /** Import kind for the root node. */ + importKind?: BindingKind; + /** Import name for the root node. */ + importName?: string; + /** Setup to run before calling the example. */ + importSetup?: + | TsDsl + | ((imp: TsDsl) => TsDsl); + /** Module to import from. */ + moduleName: string; + /** Example request payload. */ + payload?: CallArgs | CallArgs[number]; + /** Variable name for setup node. */ + setupName?: string; +} - for (const node of chain) { - if (folded.length === 0) { - if (node.role === 'container') { - folded.push(node); - } - } else if (node.role === 'accessor') { - folded.push(node); +function accessChainToNode(accessChain: NodeChain): T { + let result!: AccessResult; + accessChain.forEach((node, index) => { + if (index === 0) { + // assume correct node + result = node as typeof result; + } else { + result = result.attr(node.name); } + }); + return result as T; +} + +function getAccessChainForNode(node: TsDsl): NodeChain { + const structuralChain = [...getStructuralChainForNode(node, new Set())]; + const accessChain = structuralToAccessChain(structuralChain); + if (accessChain.length === 0) { + throw new Error( + `Cannot build access chain for node ${node['~dsl']} (${node.name.toString()})`, + ); } + return accessChain.map((node) => node.clone()); +} - return folded; +function getScope(node: TsDsl): NodeScope { + return node.scope ?? 'value'; } -function getAccessChain( - node: Node, -): ReadonlyArray { - const chain: Array = []; - const scope: NodeScope = getScope(node); - const visited = new Set(); - - let current: TsDsl | undefined = node; - while (current) { - if (visited.has(current)) break; - visited.add(current); - - chain.unshift(current); - - let foundParent = false; - for (const [parent] of current.structuralParents || []) { - if (getScope(parent) === scope && traverseStructuralParent(parent)) { - current = parent; - foundParent = true; - break; - } - } +function getStructuralChainForNode( + node: TsDsl, + visited: Set, +): NodeChain { + if (visited.has(node)) return []; + visited.add(node); - if (!foundParent) break; + if (node['~dsl'] === 'TemplateTsDsl' || node['~dsl'] === 'FuncTsDsl') { + return []; } - // trim any unreachable nodes before root - const rootIndex = chain.findIndex((node) => node.root); - if (rootIndex !== -1) { - chain.splice(0, rootIndex); + if (node.structuralParents) { + for (const [parent] of node.structuralParents) { + if (getScope(parent) !== getScope(node)) continue; + + const chain = getStructuralChainForNode(parent, visited); + if (chain.length > 0) return [...chain, node]; + } } - return foldAccessChain(chain) as ReadonlyArray; + if (!node.root) return []; + + return [node]; } -export const astContext: AstContext = { - getAccess( - to: TsDsl | Symbol, - options?: AccessPatternOptions, - ): T { - const node = isSymbol(to) ? to.node! : to; - const chain = getAccessChain(node); - if (chain.length === 0) return node as T; - - let result!: ReturnType; - - for (let index = 0; index < chain.length; index++) { - const currentNode = chain[index]!; - - const transformed = currentNode.accessPattern?.( - currentNode, - { - context: 'runtime', - ...options, - }, - { - chain, - index, - isLeaf: index === chain.length - 1, - isRoot: index === 0, - length: chain.length, - }, - ) as typeof result | undefined; - - if (index === 0) { - result = transformed || $(currentNode.name); - } else { - result = result.attr(transformed?.name || currentNode.name); +/** + * Fold a structural chain to an access chain by removing + * non-accessor nodes. + */ +function structuralToAccessChain(structuralChain: NodeChain): NodeChain { + const accessChain: Array = []; + structuralChain.forEach((node, index) => { + // assume first node is always included + if (index === 0) { + accessChain.push(node); + } else if ( + node['~dsl'] === 'FieldTsDsl' || + node['~dsl'] === 'GetterTsDsl' || + node['~dsl'] === 'MethodTsDsl' + ) { + accessChain.push(node); + } + }); + return accessChain; +} + +function transformAccessChain( + accessChain: NodeChain, + options: AccessOptions = {}, +): NodeChain { + return accessChain.map((node, index) => { + const accessNode = node.toAccessNode?.(node, options, { + chain: accessChain, + index, + isLeaf: index === accessChain.length - 1, + isRoot: index === 0, + length: accessChain.length, + }); + if (accessNode) return accessNode; + if (index === 0) { + if (node['~dsl'] === 'ClassTsDsl') { + const nextNode = accessChain[index + 1]; + if (nextNode?.['~dsl'] === 'FieldTsDsl') { + if ((nextNode as ReturnType).hasModifier('static')) { + return $(node.name); + } + } + return $.new(node.name).args(); } + return $(node.name); + } + return node; + }); +} + +export class TsDslContext { + /** + * Build an expression for accessing the node. + * + * @param node - The node or symbol to build access for + * @param options - Access options + * @returns Expression for accessing the node + * + * @example + * ```ts + * ctx.access(node); // → Expression for accessing the node + * ``` + */ + access( + node: TsDsl | Symbol, + options?: AccessOptions, + ): T { + const n = isSymbol(node) ? node.node : node; + if (!n) { + throw new Error(`Symbol ${node.name} is not resolved to a node.`); + } + const accessChain = getAccessChainForNode(n); + const finalChain = transformAccessChain(accessChain, options); + return accessChainToNode(finalChain); + } + + /** + * Build an example. + * + * @param node - The node to generate an example for + * @param options - Example options + * @returns Full example string + * + * @example + * ```ts + * ctx.example(node, { moduleName: 'my-sdk' }); // → Full example string + * ``` + */ + example( + node: TsDsl, + options: ExampleOptions | undefined, + astOptions?: Parameters[0], + ): string { + if (astOptions) { + return TypeScriptRenderer.astToString(astOptions); } - return result as T; - }, -}; + if (!options) { + throw new Error('Example options are required.'); + } + + const accessChain = getAccessChainForNode(node); + if (options.importName) { + accessChain[0]!.name.set(options.importName); + } + const importNode = $(accessChain[0]!.name.toString()); // must store name before transform + const finalChain = transformAccessChain(accessChain, { + context: 'example', + }); + + const setupNode = options.importSetup + ? typeof options.importSetup === 'function' + ? options.importSetup(importNode) + : options.importSetup + : (finalChain[0]! as TsDsl); + const setupName = options.setupName; + const payload = + options.payload instanceof Array + ? options.payload + : options.payload + ? [options.payload] + : []; + + let nodes: Array = []; + if (setupName) { + nodes = [ + $.const(setupName).assign(setupNode), + accessChainToNode([$(setupName), ...finalChain.slice(1)]).call( + ...payload, + ), + ]; + } else { + nodes = [ + accessChainToNode([setupNode, ...finalChain.slice(1)]).call(...payload), + ]; + } + + const localName = importNode.name.toString(); + return TypeScriptRenderer.astToString({ + imports: [ + [ + { + imports: + !options.importKind || options.importKind === 'named' + ? [ + { + isTypeOnly: false, + localName, + sourceName: localName, + }, + ] + : [], + isTypeOnly: false, + kind: options.importKind ?? 'named', + localName: options.importKind !== 'named' ? localName : undefined, + modulePath: options.moduleName, + }, + ], + ], + nodes, + trailingNewline: false, + }); + } +} diff --git a/packages/openapi-ts/src/ts-dsl/utils/factories.ts b/packages/openapi-ts/src/ts-dsl/utils/factories.ts index b03a6fed8..3aba7b4ab 100644 --- a/packages/openapi-ts/src/ts-dsl/utils/factories.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/factories.ts @@ -2,6 +2,7 @@ import type { AsCtor } from '../expr/as'; import type { AttrCtor } from '../expr/attr'; import type { AwaitCtor } from '../expr/await'; import type { CallCtor } from '../expr/call'; +import type { NewCtor } from '../expr/new'; import type { TypeOfExprCtor } from '../expr/typeof'; import type { ReturnCtor } from '../stmt/return'; import type { TypeExprCtor } from '../type/expr'; @@ -45,6 +46,9 @@ export const f = { /** Factory for creating function or method call expressions (e.g. `fn(arg)`). */ call: createFactory('call'), + /** Factory for creating new expressions (e.g. `new ClassName()`). */ + new: createFactory('new'), + /** Factory for creating return statements. */ return: createFactory('return'), diff --git a/packages/openapi-ts/src/ts-dsl/utils/lazy.ts b/packages/openapi-ts/src/ts-dsl/utils/lazy.ts index 786625471..693a25035 100644 --- a/packages/openapi-ts/src/ts-dsl/utils/lazy.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/lazy.ts @@ -1,10 +1,10 @@ -import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; +import type { AnalysisContext } from '@hey-api/codegen-core'; import type ts from 'typescript'; import { TsDsl } from '../base'; -import { astContext } from './context'; +import { TsDslContext } from './context'; -export type LazyThunk = (ctx: AstContext) => TsDsl; +export type LazyThunk = (ctx: TsDslContext) => TsDsl; export class LazyTsDsl extends TsDsl { readonly '~dsl' = 'LazyTsDsl'; @@ -18,10 +18,14 @@ export class LazyTsDsl extends TsDsl { override analyze(ctx: AnalysisContext): void { super.analyze(ctx); - ctx.analyze(this._thunk(astContext)); + ctx.analyze(this.toResult()); } - override toAst(ctx: AstContext): T { - return this._thunk(ctx).toAst(ctx); + toResult(): TsDsl { + return this._thunk(new TsDslContext()); + } + + override toAst(): T { + return this.toResult().toAst(); } } diff --git a/packages/openapi-ts/src/ts-dsl/render/utils.ts b/packages/openapi-ts/src/ts-dsl/utils/render-utils.ts similarity index 98% rename from packages/openapi-ts/src/ts-dsl/render/utils.ts rename to packages/openapi-ts/src/ts-dsl/utils/render-utils.ts index 47f1deebf..b81ecfbda 100644 --- a/packages/openapi-ts/src/ts-dsl/render/utils.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/render-utils.ts @@ -17,7 +17,7 @@ const blankFile = ts.createSourceFile( ); /** Print a TypeScript node to a string. */ -export function nodeToString(node: ts.Node): string { +export function astToString(node: ts.Node): string { const result = printer.printNode(ts.EmitHint.Unspecified, node, blankFile); try { diff --git a/packages/openapi-ts/src/ts-dsl/render/typescript.ts b/packages/openapi-ts/src/ts-dsl/utils/render.ts similarity index 74% rename from packages/openapi-ts/src/ts-dsl/render/typescript.ts rename to packages/openapi-ts/src/ts-dsl/utils/render.ts index 97bcad12c..184634900 100644 --- a/packages/openapi-ts/src/ts-dsl/render/typescript.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/render.ts @@ -1,12 +1,8 @@ -import type { - AstContext, - RenderContext, - Renderer, -} from '@hey-api/codegen-core'; +import type { RenderContext, Renderer } from '@hey-api/codegen-core'; import ts from 'typescript'; import type { TsDsl } from '~/ts-dsl'; -import { $, astContext } from '~/ts-dsl'; +import { $ } from '~/ts-dsl'; import type { ModuleExport, @@ -14,8 +10,14 @@ import type { SortGroup, SortKey, SortModule, -} from './utils'; -import { moduleSortKey, nodeToString } from './utils'; +} from './render-utils'; +import { astToString, moduleSortKey } from './render-utils'; + +type Exports = ReadonlyArray>; +type ExportsOptions = { + preferExportAll?: boolean; +}; +type Imports = ReadonlyArray>; export class TypeScriptRenderer implements Renderer { /** @@ -50,45 +52,130 @@ export class TypeScriptRenderer implements Renderer { } render(ctx: RenderContext): string { - let text = ''; + // TODO: move header customization to options const header = '// This file is auto-generated by @hey-api/openapi-ts'; - text += `${header}\n`; + return TypeScriptRenderer.astToString({ + exports: this.getExports(ctx), + exportsOptions: { + preferExportAll: this.preferExportAll, + }, + headers: [header], + imports: this.getImports(ctx), + nodes: ctx.file.nodes, + }); + } + + supports(ctx: RenderContext): boolean { + return ctx.file.language === 'typescript'; + } + + static astToString(args: { + exports?: Exports; + exportsOptions?: ExportsOptions; + headers?: ReadonlyArray; + imports?: Imports; + nodes?: ReadonlyArray; + /** + * Whether to include a trailing newline at the end of the file. + * + * @default true + */ + trailingNewline?: boolean; + }): string { + let text = ''; + for (const header of args.headers ?? []) { + text += `${header}\n`; + } let imports = ''; - for (const group of this.getImports(ctx)) { + for (const group of args.imports ?? []) { if (imports) imports += '\n'; for (const imp of group) { - imports += `${nodeToString(this.renderImport(astContext, imp))}\n`; + imports += `${astToString(TypeScriptRenderer.toImportAst(imp))}\n`; } } text = `${text}${text && imports ? '\n' : ''}${imports}`; let nodes = ''; - for (const node of ctx.file.nodes) { + for (const node of args.nodes ?? []) { if (nodes) nodes += '\n'; - nodes += `${nodeToString(node.toAst(astContext))}\n`; + nodes += `${astToString(node.toAst())}\n`; } text = `${text}${text && nodes ? '\n' : ''}${nodes}`; let exports = ''; - for (const group of this.getExports(ctx)) { + for (const group of args.exports ?? []) { if ((!exports && nodes) || exports) exports += '\n'; for (const exp of group) { - exports += `${nodeToString(this.renderExport(astContext, exp))}\n`; + exports += `${astToString(TypeScriptRenderer.toExportAst(exp, args.exportsOptions))}\n`; } } text = `${text}${text && exports ? '\n' : ''}${exports}`; + if (args.trailingNewline === false && text.endsWith('\n')) { + text = text.slice(0, -1); + } + return text; } - supports(ctx: RenderContext): boolean { - return ctx.file.language === 'typescript'; + static toExportAst( + group: ModuleExport, + options?: ExportsOptions, + ): ts.ExportDeclaration { + const specifiers = group.exports.map((exp) => { + const specifier = ts.factory.createExportSpecifier( + exp.isTypeOnly, + exp.sourceName !== exp.exportedName + ? $.id(exp.sourceName).toAst() + : undefined, + $.id(exp.exportedName).toAst(), + ); + return specifier; + }); + const exportClause = group.namespaceExport + ? ts.factory.createNamespaceExport($.id(group.namespaceExport).toAst()) + : (!group.canExportAll || !options?.preferExportAll) && specifiers.length + ? ts.factory.createNamedExports(specifiers) + : undefined; + return ts.factory.createExportDeclaration( + undefined, + group.isTypeOnly, + exportClause, + $.literal(group.modulePath).toAst(), + ); } - private getExports( - ctx: RenderContext, - ): ReadonlyArray> { + static toImportAst(group: ModuleImport): ts.ImportDeclaration { + const specifiers = group.imports.map((imp) => { + const specifier = ts.factory.createImportSpecifier( + imp.isTypeOnly, + imp.sourceName !== imp.localName + ? $.id(imp.sourceName).toAst() + : undefined, + $.id(imp.localName).toAst(), + ); + return specifier; + }); + const importClause = ts.factory.createImportClause( + group.isTypeOnly, + group.kind === 'default' + ? $.id(group.localName ?? '').toAst() + : undefined, + group.kind === 'namespace' + ? ts.factory.createNamespaceImport($.id(group.localName ?? '').toAst()) + : specifiers.length > 0 + ? ts.factory.createNamedImports(specifiers) + : undefined, + ); + return ts.factory.createImportDeclaration( + undefined, + importClause, + $.literal(group.modulePath).toAst(), + ); + } + + private getExports(ctx: RenderContext): Exports { type ModuleEntry = { group: ModuleExport; sortKey: SortKey; @@ -158,9 +245,7 @@ export class TypeScriptRenderer implements Renderer { return exports; } - private getImports( - ctx: RenderContext, - ): ReadonlyArray> { + private getImports(ctx: RenderContext): Imports { type ModuleEntry = { group: ModuleImport; sortKey: SortKey; @@ -186,6 +271,7 @@ export class TypeScriptRenderer implements Renderer { group: { imports: [], isTypeOnly: false, + kind: imp.kind, modulePath, }, sortKey, @@ -195,9 +281,10 @@ export class TypeScriptRenderer implements Renderer { const entry = moduleMap.get(modulePath)!; const group = entry.group; - if (imp.namespaceImport) { + if (imp.kind !== 'named') { group.isTypeOnly = imp.isTypeOnly; - group.namespaceImport = imp.namespaceImport; + group.kind = imp.kind; + group.localName = imp.localName; } else { group.imports.push(...imp.imports); } @@ -217,7 +304,7 @@ export class TypeScriptRenderer implements Renderer { return entries.map((e) => { const group = e.group; - if (group.namespaceImport) { + if (group.kind === 'namespace') { group.imports = []; } else { const isTypeOnly = !group.imports.find((imp) => !imp.isTypeOnly); @@ -237,59 +324,4 @@ export class TypeScriptRenderer implements Renderer { return imports; } - - private renderExport( - ctx: AstContext, - group: ModuleExport, - ): ts.ExportDeclaration { - const specifiers = group.exports.map((exp) => { - const specifier = ts.factory.createExportSpecifier( - exp.isTypeOnly, - exp.sourceName !== exp.exportedName - ? $.id(exp.sourceName).toAst() - : undefined, - $.id(exp.exportedName).toAst(), - ); - return specifier; - }); - const exportClause = group.namespaceExport - ? ts.factory.createNamespaceExport($.id(group.namespaceExport).toAst()) - : (!group.canExportAll || !this.preferExportAll) && specifiers.length - ? ts.factory.createNamedExports(specifiers) - : undefined; - return ts.factory.createExportDeclaration( - undefined, - group.isTypeOnly, - exportClause, - $.literal(group.modulePath).toAst(ctx), - ); - } - - private renderImport( - ctx: AstContext, - group: ModuleImport, - ): ts.ImportDeclaration { - const specifiers = group.imports.map((imp) => { - const specifier = ts.factory.createImportSpecifier( - imp.isTypeOnly, - imp.sourceName !== imp.localName - ? $.id(imp.sourceName).toAst() - : undefined, - $.id(imp.localName).toAst(), - ); - return specifier; - }); - const importClause = ts.factory.createImportClause( - group.isTypeOnly, - undefined, // TODO: default imports - group.namespaceImport - ? ts.factory.createNamespaceImport($.id(group.namespaceImport).toAst()) - : ts.factory.createNamedImports(specifiers), - ); - return ts.factory.createImportDeclaration( - undefined, - importClause, - $.literal(group.modulePath).toAst(ctx), - ); - } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f09388b1a..c3865277e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -118,6 +118,9 @@ importers: '@hey-api/openapi-ts': specifier: workspace:* version: link:../packages/openapi-ts + '@opencode-ai/sdk': + specifier: 1.0.170 + version: 1.0.170 '@pinia/colada': specifier: 0.19.1 version: 0.19.1(pinia@3.0.3(typescript@5.9.3)(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) @@ -5042,6 +5045,9 @@ packages: '@one-ini/wasm@0.1.1': resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + '@opencode-ai/sdk@1.0.170': + resolution: {integrity: sha512-A44hiQib9cB/hAfeS9fAr5sTlz7B9teimfcz8dfIgpMLeT+ZAF5slf32vejhzOy4DoLGeLlJswN0UB+XzFPMrA==} + '@oxc-project/types@0.103.0': resolution: {integrity: sha512-bkiYX5kaXWwUessFRSoXFkGIQTmc6dLGdxuRTrC+h8PSnIdZyuXHHlLAeTmOue5Br/a0/a7dHH0Gca6eXn9MKg==} @@ -14597,7 +14603,7 @@ snapshots: '@vitejs/plugin-basic-ssl': 1.2.0(vite@7.2.2(@types/node@22.10.5)(jiti@2.6.1)(less@4.2.2)(sass@1.85.0)(terser@5.43.1)(yaml@2.8.2)) ansi-colors: 4.1.3 autoprefixer: 10.4.20(postcss@8.5.2) - babel-loader: 9.2.1(@babel/core@7.26.9)(webpack@5.98.0(esbuild@0.25.0)) + babel-loader: 9.2.1(@babel/core@7.26.9)(webpack@5.98.0) browserslist: 4.25.4 copy-webpack-plugin: 12.0.2(webpack@5.98.0) css-loader: 7.1.2(webpack@5.98.0) @@ -14617,7 +14623,7 @@ snapshots: picomatch: 4.0.2 piscina: 4.8.0 postcss: 8.5.2 - postcss-loader: 8.1.1(postcss@8.5.2)(typescript@5.8.3)(webpack@5.98.0(esbuild@0.25.0)) + postcss-loader: 8.1.1(postcss@8.5.2)(typescript@5.8.3)(webpack@5.98.0) resolve-url-loader: 5.0.0 rxjs: 7.8.1 sass: 1.85.0 @@ -14685,7 +14691,7 @@ snapshots: '@vitejs/plugin-basic-ssl': 1.2.0(vite@7.2.2(@types/node@22.10.5)(jiti@2.6.1)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.8.2)) ansi-colors: 4.1.3 autoprefixer: 10.4.20(postcss@8.5.2) - babel-loader: 9.2.1(@babel/core@7.26.9)(webpack@5.98.0(esbuild@0.25.0)) + babel-loader: 9.2.1(@babel/core@7.26.9)(webpack@5.98.0) browserslist: 4.25.4 copy-webpack-plugin: 12.0.2(webpack@5.98.0) css-loader: 7.1.2(webpack@5.98.0) @@ -14705,7 +14711,7 @@ snapshots: picomatch: 4.0.2 piscina: 4.8.0 postcss: 8.5.2 - postcss-loader: 8.1.1(postcss@8.5.2)(typescript@5.8.3)(webpack@5.98.0(esbuild@0.25.0)) + postcss-loader: 8.1.1(postcss@8.5.2)(typescript@5.8.3)(webpack@5.98.0) resolve-url-loader: 5.0.0 rxjs: 7.8.1 sass: 1.85.0 @@ -14793,7 +14799,7 @@ snapshots: picomatch: 4.0.2 piscina: 4.8.0 postcss: 8.5.2 - postcss-loader: 8.1.1(postcss@8.5.2)(typescript@5.8.3)(webpack@5.98.0(esbuild@0.25.0)) + postcss-loader: 8.1.1(postcss@8.5.2)(typescript@5.8.3)(webpack@5.98.0) resolve-url-loader: 5.0.0 rxjs: 7.8.1 sass: 1.85.0 @@ -19284,6 +19290,8 @@ snapshots: '@one-ini/wasm@0.1.1': {} + '@opencode-ai/sdk@1.0.170': {} + '@oxc-project/types@0.103.0': {} '@parcel/watcher-android-arm64@2.5.1': @@ -22272,7 +22280,7 @@ snapshots: schema-utils: 4.3.2 webpack: 5.98.0(esbuild@0.25.0) - babel-loader@9.2.1(@babel/core@7.26.9)(webpack@5.98.0(esbuild@0.25.0)): + babel-loader@9.2.1(@babel/core@7.26.9)(webpack@5.98.0): dependencies: '@babel/core': 7.26.9 find-cache-dir: 4.0.0 @@ -27762,7 +27770,7 @@ snapshots: ts-node: 10.9.2(@types/node@22.10.5)(typescript@5.9.3) optional: true - postcss-loader@8.1.1(postcss@8.5.2)(typescript@5.8.3)(webpack@5.98.0(esbuild@0.25.0)): + postcss-loader@8.1.1(postcss@8.5.2)(typescript@5.8.3)(webpack@5.98.0): dependencies: cosmiconfig: 9.0.0(typescript@5.8.3) jiti: 1.21.7 -- 2.51.2 From b2987ed454ab343aa707246c981eed795c43f92b Mon Sep 17 00:00:00 2001 From: Lubos Date: Sun, 21 Dec 2025 05:25:53 +0800 Subject: [PATCH 06/15] test: update snapshots --- dev/openapi-ts.config.ts | 31 +- .../src/__tests__/project.test.ts | 1 - .../client-fetch/sdk-nested-classes/index.ts | 2 +- .../sdk-nested-classes/sdk.gen.ts | 64 +- .../plugins/@pinia/colada/asClass/index.ts | 2 +- .../plugins/@pinia/colada/asClass/sdk.gen.ts | 16 +- .../asClass/index.ts | 2 +- .../asClass/sdk.gen.ts | 16 +- .../@tanstack/react-query/asClass/index.ts | 2 +- .../@tanstack/react-query/asClass/sdk.gen.ts | 16 +- .../@tanstack/solid-query/asClass/index.ts | 2 +- .../@tanstack/solid-query/asClass/sdk.gen.ts | 16 +- .../@tanstack/svelte-query/asClass/index.ts | 2 +- .../@tanstack/svelte-query/asClass/sdk.gen.ts | 16 +- .../@tanstack/vue-query/asClass/index.ts | 2 +- .../@tanstack/vue-query/asClass/sdk.gen.ts | 16 +- .../client-fetch/sdk-nested-classes/index.ts | 2 +- .../sdk-nested-classes/sdk.gen.ts | 64 +- .../plugins/@pinia/colada/asClass/index.ts | 2 +- .../plugins/@pinia/colada/asClass/sdk.gen.ts | 16 +- .../asClass/index.ts | 2 +- .../asClass/sdk.gen.ts | 16 +- .../@tanstack/react-query/asClass/index.ts | 2 +- .../@tanstack/react-query/asClass/sdk.gen.ts | 16 +- .../@tanstack/solid-query/asClass/index.ts | 2 +- .../@tanstack/solid-query/asClass/sdk.gen.ts | 16 +- .../@tanstack/svelte-query/asClass/index.ts | 2 +- .../@tanstack/svelte-query/asClass/sdk.gen.ts | 16 +- .../@tanstack/vue-query/asClass/index.ts | 2 +- .../@tanstack/vue-query/asClass/sdk.gen.ts | 16 +- .../client-fetch/sdk-nested-classes/index.ts | 2 +- .../sdk-nested-classes/sdk.gen.ts | 64 +- .../plugins/@pinia/colada/asClass/index.ts | 2 +- .../plugins/@pinia/colada/asClass/sdk.gen.ts | 16 +- .../asClass/index.ts | 2 +- .../asClass/sdk.gen.ts | 16 +- .../@tanstack/react-query/asClass/index.ts | 2 +- .../@tanstack/react-query/asClass/sdk.gen.ts | 16 +- .../@tanstack/solid-query/asClass/index.ts | 2 +- .../@tanstack/solid-query/asClass/sdk.gen.ts | 16 +- .../@tanstack/svelte-query/asClass/index.ts | 2 +- .../@tanstack/svelte-query/asClass/sdk.gen.ts | 16 +- .../@tanstack/vue-query/asClass/index.ts | 2 +- .../@tanstack/vue-query/asClass/sdk.gen.ts | 16 +- .../method-class-conflict/class/sdk.gen.ts | 1016 ++++++++++------- .../method-class-conflict/instance/sdk.gen.ts | 149 +-- .../openapi-ts/src/__tests__/internal.test.ts | 18 +- .../plugins/@hey-api/sdk/model/resource.ts | 20 +- .../src/ts-dsl/utils/__tests__/render.test.ts | 8 +- .../openapi-ts/src/ts-dsl/utils/context.ts | 24 +- 50 files changed, 1197 insertions(+), 592 deletions(-) diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index 93790be83..5e2676020 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -38,8 +38,9 @@ export default defineConfig(() => { // }, path: path.resolve( getSpecsPath(), - // '3.0.x', - '3.1.x', + // '2.0.x', + '3.0.x', + // '3.1.x', // 'circular.yaml', // 'dutchie.json', // 'enum-names-values.yaml', @@ -52,9 +53,9 @@ export default defineConfig(() => { // 'pagination-ref.yaml', // 'schema-const.yaml', // 'sdk-instance.yaml', - // 'sdk-method-class-conflict.yaml', + 'sdk-method-class-conflict.yaml', // 'sdk-nested-classes.yaml', - 'sdk-nested-conflict.yaml', + // 'sdk-nested-conflict.yaml', // 'string-with-format.yaml', // 'transformers.json', // 'transformers-recursive.json', @@ -109,10 +110,10 @@ export default defineConfig(() => { // importFileExtension: '.js', // indexFile: false, // lint: 'eslint', - nameConflictResolver({ attempt, baseName }) { - // console.log('resolving conflict for:', { attempt, baseName }); - return attempt === 0 ? baseName : `${baseName}_N${attempt + 1}`; - }, + // nameConflictResolver({ attempt, baseName }) { + // // console.log('resolving conflict for:', { attempt, baseName }); + // return attempt === 0 ? baseName : `${baseName}_N${attempt + 1}`; + // }, path: path.resolve(__dirname, '.gen'), // preferExportAll: true, resolveModuleName: (moduleName) => { @@ -260,7 +261,7 @@ export default defineConfig(() => { // name: '你們_errors_{{name}}', // }, // exportFromIndex: false, - name: '@hey-api/typescript', + // name: '@hey-api/typescript', // requests: '我們_data_{{name}}', // responses: { // name: '我_responses_{{name}}', @@ -274,9 +275,9 @@ export default defineConfig(() => { // }, }, { - asClass: true, + // asClass: true, // auth: false, - // classNameBuilder: '{{name}}',', + // classNameBuilder: '{{name}}Service', // classStructure: 'off', // client: false, // getSignature: ({ fields, signature, operation }) => { @@ -284,7 +285,7 @@ export default defineConfig(() => { // fields.unwrap('path') // }, // include... - instance: 'OpencodeClient', + // instance: 'OpencodeClient', // methodNameBuilder: '{{name}}', name: '@hey-api/sdk', // operationId: false, @@ -348,7 +349,7 @@ export default defineConfig(() => { // name: '{{name}}MO', // name: 'options', }, - name: '@tanstack/react-query', + // name: '@tanstack/react-query', queryKeys: { // name: '{{name}}QK', // name: 'options', @@ -490,7 +491,7 @@ export default defineConfig(() => { }, exportFromIndex: true, metadata: true, - name: 'zod', + // name: 'zod', // requests: { // // case: 'SCREAMING_SNAKE_CASE', // // name: 'z{{name}}TestData', @@ -609,7 +610,7 @@ export default defineConfig(() => { { exportFromIndex: true, // mutationOptions: '{{name}}Mutationssss', - // name: '@pinia/colada', + name: '@pinia/colada', // queryOptions: { // name: '{{name}}Queryyyyy', // }, diff --git a/packages/codegen-core/src/__tests__/project.test.ts b/packages/codegen-core/src/__tests__/project.test.ts index 9766ca0cf..485f9e5d6 100644 --- a/packages/codegen-core/src/__tests__/project.test.ts +++ b/packages/codegen-core/src/__tests__/project.test.ts @@ -48,7 +48,6 @@ describe('Project', () => { const renderer = file.renderer!; expect(renderer.render).toHaveBeenCalledWith({ - astContext: expect.any(Object), file, meta: { hello: true }, project: p, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts index 19b0bf7f4..e2e5496d6 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { Business, Domains, Locations, type Options, Providers } from './sdk.gen'; +export { Business, Business2, Business3, Business4, Business5, Domains, Domains2, Domains3, Domains4, Locations, type Options, Providers, Providers2, Providers3, Providers4 } from './sdk.gen'; export type { BusinessGetData, BusinessGetResponse, BusinessGetResponses, BusinessProvidersDomainsGetData, BusinessProvidersDomainsGetResponse, BusinessProvidersDomainsGetResponses, BusinessProvidersDomainsPostData, BusinessProvidersDomainsPostResponse, BusinessProvidersDomainsPostResponses, ClientOptions, GetData, GetResponse, GetResponses, PutBusinessProvidersDomainsData, PutBusinessProvidersDomainsResponse, PutBusinessProvidersDomainsResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts index 8c055a5e4..babd05bc9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts @@ -26,10 +26,6 @@ export class Domains { public static post(options?: Options) { return (options?.client ?? client).post({ url: '/business/providers/domains', ...options }); } - - public static putBusinessProvidersDomains(options?: Options) { - return (options?.client ?? client).put({ url: '/business/providers/domains', ...options }); - } } export class Providers { @@ -44,10 +40,68 @@ export class Business { static providers = Providers; } +export class Business2 { + static business = Business; +} + +export class Domains2 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/business/providers/domains', ...options }); + } + + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/business/providers/domains', ...options }); + } +} + +export class Providers2 { + static domains = Domains2; +} + +export class Business3 { + static providers = Providers2; +} + +export class Providers3 { + static business = Business3; +} + +export class Domains3 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/business/providers/domains', ...options }); + } + + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/business/providers/domains', ...options }); + } +} + +export class Providers4 { + static domains = Domains3; +} + +export class Business4 { + static providers = Providers4; +} + +export class Domains4 { + public static putBusinessProvidersDomains(options?: Options) { + return (options?.client ?? client).put({ url: '/business/providers/domains', ...options }); + } + + static business = Business4; +} + +export class Business5 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/locations/businesses', ...options }); + } +} + export class Locations { public static get(options?: Options) { return (options?.client ?? client).get({ url: '/locations', ...options }); } - static business = Business; + static business = Business5; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts index 19b0bf7f4..e2e5496d6 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { Business, Domains, Locations, type Options, Providers } from './sdk.gen'; +export { Business, Business2, Business3, Business4, Business5, Domains, Domains2, Domains3, Domains4, Locations, type Options, Providers, Providers2, Providers3, Providers4 } from './sdk.gen'; export type { BusinessGetData, BusinessGetResponse, BusinessGetResponses, BusinessProvidersDomainsGetData, BusinessProvidersDomainsGetResponse, BusinessProvidersDomainsGetResponses, BusinessProvidersDomainsPostData, BusinessProvidersDomainsPostResponse, BusinessProvidersDomainsPostResponses, ClientOptions, GetData, GetResponse, GetResponses, PutBusinessProvidersDomainsData, PutBusinessProvidersDomainsResponse, PutBusinessProvidersDomainsResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts index 8c055a5e4..babd05bc9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts @@ -26,10 +26,6 @@ export class Domains { public static post(options?: Options) { return (options?.client ?? client).post({ url: '/business/providers/domains', ...options }); } - - public static putBusinessProvidersDomains(options?: Options) { - return (options?.client ?? client).put({ url: '/business/providers/domains', ...options }); - } } export class Providers { @@ -44,10 +40,68 @@ export class Business { static providers = Providers; } +export class Business2 { + static business = Business; +} + +export class Domains2 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/business/providers/domains', ...options }); + } + + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/business/providers/domains', ...options }); + } +} + +export class Providers2 { + static domains = Domains2; +} + +export class Business3 { + static providers = Providers2; +} + +export class Providers3 { + static business = Business3; +} + +export class Domains3 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/business/providers/domains', ...options }); + } + + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/business/providers/domains', ...options }); + } +} + +export class Providers4 { + static domains = Domains3; +} + +export class Business4 { + static providers = Providers4; +} + +export class Domains4 { + public static putBusinessProvidersDomains(options?: Options) { + return (options?.client ?? client).put({ url: '/business/providers/domains', ...options }); + } + + static business = Business4; +} + +export class Business5 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/locations/businesses', ...options }); + } +} + export class Locations { public static get(options?: Options) { return (options?.client ?? client).get({ url: '/locations', ...options }); } - static business = Business; + static business = Business5; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/react-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/react-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/react-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/react-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/solid-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/solid-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/solid-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/solid-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/svelte-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/svelte-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/svelte-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/svelte-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/vue-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/vue-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/vue-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/vue-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts index 19b0bf7f4..e2e5496d6 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/client-fetch/sdk-nested-classes/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { Business, Domains, Locations, type Options, Providers } from './sdk.gen'; +export { Business, Business2, Business3, Business4, Business5, Domains, Domains2, Domains3, Domains4, Locations, type Options, Providers, Providers2, Providers3, Providers4 } from './sdk.gen'; export type { BusinessGetData, BusinessGetResponse, BusinessGetResponses, BusinessProvidersDomainsGetData, BusinessProvidersDomainsGetResponse, BusinessProvidersDomainsGetResponses, BusinessProvidersDomainsPostData, BusinessProvidersDomainsPostResponse, BusinessProvidersDomainsPostResponses, ClientOptions, GetData, GetResponse, GetResponses, PutBusinessProvidersDomainsData, PutBusinessProvidersDomainsResponse, PutBusinessProvidersDomainsResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts index 8c055a5e4..babd05bc9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts @@ -26,10 +26,6 @@ export class Domains { public static post(options?: Options) { return (options?.client ?? client).post({ url: '/business/providers/domains', ...options }); } - - public static putBusinessProvidersDomains(options?: Options) { - return (options?.client ?? client).put({ url: '/business/providers/domains', ...options }); - } } export class Providers { @@ -44,10 +40,68 @@ export class Business { static providers = Providers; } +export class Business2 { + static business = Business; +} + +export class Domains2 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/business/providers/domains', ...options }); + } + + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/business/providers/domains', ...options }); + } +} + +export class Providers2 { + static domains = Domains2; +} + +export class Business3 { + static providers = Providers2; +} + +export class Providers3 { + static business = Business3; +} + +export class Domains3 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/business/providers/domains', ...options }); + } + + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/business/providers/domains', ...options }); + } +} + +export class Providers4 { + static domains = Domains3; +} + +export class Business4 { + static providers = Providers4; +} + +export class Domains4 { + public static putBusinessProvidersDomains(options?: Options) { + return (options?.client ?? client).put({ url: '/business/providers/domains', ...options }); + } + + static business = Business4; +} + +export class Business5 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/locations/businesses', ...options }); + } +} + export class Locations { public static get(options?: Options) { return (options?.client ?? client).get({ url: '/locations', ...options }); } - static business = Business; + static business = Business5; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@pinia/colada/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@pinia/colada/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@pinia/colada/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@pinia/colada/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@pinia/colada/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@pinia/colada/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@pinia/colada/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@pinia/colada/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/angular-query-experimental/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/react-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/react-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/react-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/react-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/solid-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/solid-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/solid-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/solid-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/svelte-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/svelte-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/svelte-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/svelte-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/vue-query/asClass/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/vue-query/asClass/index.ts index bb82b04c1..41a5e25e9 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/vue-query/asClass/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/vue-query/asClass/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { BarBazService, BarService, FooBazService, FooService, type Options } from './sdk.gen'; +export { BarBazService, BarService, BarService2, FooBazService, FooService, FooService2, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts index 8b221a746..81b7e79ea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts @@ -48,10 +48,24 @@ export class FooBazService { static fooService = FooService; } +export class BarService2 { + public static post(options?: Options) { + return (options?.client ?? client).post({ url: '/foo/bar', ...options }); + } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/foo/bar', ...options }); + } +} + +export class FooService2 { + static barService = BarService2; +} + export class BarBazService { public static getFooBar(options?: Options) { return (options?.client ?? client).get({ url: '/foo/bar', ...options }); } - static fooService = FooService; + static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/method-class-conflict/class/sdk.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/method-class-conflict/class/sdk.gen.ts index 18c322e48..a3ef37413 100644 --- a/packages/openapi-ts-tests/sdks/__snapshots__/method-class-conflict/class/sdk.gen.ts +++ b/packages/openapi-ts-tests/sdks/__snapshots__/method-class-conflict/class/sdk.gen.ts @@ -18,7 +18,81 @@ export type Options; }; +export class AccountingCompanies { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/AccountingCompanies/$count', ...options }); + } +} + +export class Odata { + public static accountingCompanies(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/AccountingCompanies', ...options }); + } + + static accountingCompanies2 = AccountingCompanies; +} + +export class VVersionApiVersion { + static odata = Odata; +} + +export class Api { + static vVersionApiVersion = VVersionApiVersion; +} + +export class AccountingCompanies2 { + public static postApiV1AccountingCompanies(options?: Options) { + return (options?.client ?? client).post({ + url: '/api/v1/accounting-companies', + ...options, + headers: { + 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', + ...options?.headers + } + }); + } + + public static deleteApiV1AccountingCompaniesById(options: Options) { + return (options.client ?? client).delete({ url: '/api/v1/accounting-companies/{id}', ...options }); + } + + public static postApiV1AccountingCompaniesById(options: Options) { + return (options.client ?? client).post({ + url: '/api/v1/accounting-companies/{id}', + ...options, + headers: { + 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', + ...options.headers + } + }); + } + + static api = Api; +} + export class AccountingCompanyMemberships { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/AccountingCompanyMemberships/$count', ...options }); + } +} + +export class Odata2 { + public static accountingCompanyMemberships(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/AccountingCompanyMemberships', ...options }); + } + + static accountingCompanyMemberships2 = AccountingCompanyMemberships; +} + +export class VVersionApiVersion2 { + static odata = Odata2; +} + +export class Api2 { + static vVersionApiVersion = VVersionApiVersion2; +} + +export class AccountingCompanyMemberships2 { public static putApiV1AccountingCompanyMemberships(options?: Options) { return (options?.client ?? client).put({ url: '/api/v1/accounting-company-memberships', @@ -34,16 +108,32 @@ export class AccountingCompanyMemberships { return (options.client ?? client).delete({ url: '/api/v1/accounting-company-memberships/{id}', ...options }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/AccountingCompanyMemberships/$count', ...options }); + static api = Api2; +} + +export class BankAccounts { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/BankAccounts/$count', ...options }); } - - public static get api() { - return Api; +} + +export class Odata3 { + public static bankAccounts(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/BankAccounts', ...options }); } + + static bankAccounts2 = BankAccounts; } -export class BankAccounts { +export class VVersionApiVersion3 { + static odata = Odata3; +} + +export class Api3 { + static vVersionApiVersion = VVersionApiVersion3; +} + +export class BankAccounts2 { public static putApiV1BankAccounts(options?: Options) { return (options?.client ?? client).put({ url: '/api/v1/bank-accounts', @@ -59,16 +149,32 @@ export class BankAccounts { return (options.client ?? client).delete({ url: '/api/v1/bank-accounts/{id}', ...options }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/BankAccounts/$count', ...options }); + static api = Api3; +} + +export class BusinessAccountantAssignments { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessAccountantAssignments/$count', ...options }); } - - public static get api() { - return Api; +} + +export class Odata4 { + public static businessAccountantAssignments(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessAccountantAssignments', ...options }); } + + static businessAccountantAssignments2 = BusinessAccountantAssignments; } -export class BusinessAccountantAssignments { +export class VVersionApiVersion4 { + static odata = Odata4; +} + +export class Api4 { + static vVersionApiVersion = VVersionApiVersion4; +} + +export class BusinessAccountantAssignments2 { public static putApiV1BusinessAccountantAssignments(options?: Options) { return (options?.client ?? client).put({ url: '/api/v1/business-accountant-assignments', @@ -84,22 +190,44 @@ export class BusinessAccountantAssignments { return (options.client ?? client).delete({ url: '/api/v1/business-accountant-assignments/{id}', ...options }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessAccountantAssignments/$count', ...options }); - } - - public static get api() { - return Api; - } + static api = Api4; } export class BusinessDocumentActivities { - public static count(options?: Options) { + public static $count(options?: Options) { return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessDocumentActivities/$count', ...options }); } } export class BusinessDocuments { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessDocuments/$count', ...options }); + } +} + +export class Odata5 { + public static businessDocumentActivities(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessDocumentActivities', ...options }); + } + + public static businessDocuments(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessDocuments', ...options }); + } + + static businessDocumentActivities2 = BusinessDocumentActivities; + + static businessDocuments2 = BusinessDocuments; +} + +export class VVersionApiVersion5 { + static odata = Odata5; +} + +export class Api5 { + static vVersionApiVersion = VVersionApiVersion5; +} + +export class BusinessDocuments2 { public static getApiV1BusinessDocumentsByIdRaw(options: Options) { return (options.client ?? client).get({ url: '/api/v1/business-documents/{id}/raw', ...options }); } @@ -154,29 +282,72 @@ export class BusinessDocuments { }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessDocuments/$count', ...options }); - } - - public static get api() { - return Api; - } + static api = Api5; } export class BusinessDocumentsSummaries { /** * @deprecated */ - public static count(options?: Options) { + public static $count(options?: Options) { return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessDocumentsSummaries/$count', ...options }); } - - public static get api() { - return Api; +} + +export class Odata6 { + /** + * @deprecated + */ + public static businessDocumentsSummaries(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessDocumentsSummaries', ...options }); } + + static businessDocumentsSummaries2 = BusinessDocumentsSummaries; +} + +export class VVersionApiVersion6 { + static odata = Odata6; +} + +export class Api6 { + static vVersionApiVersion = VVersionApiVersion6; +} + +export class BusinessDocumentsSummaries2 { + static api = Api6; } export class Businesses { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Businesses/$count', ...options }); + } + + public static key(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Businesses/{key}', ...options }); + } +} + +export class Odata7 { + public static businesses(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Businesses', ...options }); + } + + public static businessesKey(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Businesses({key})', ...options }); + } + + static businesses2 = Businesses; +} + +export class VVersionApiVersion7 { + static odata = Odata7; +} + +export class Api7 { + static vVersionApiVersion = VVersionApiVersion7; +} + +export class Businesses2 { public static getApiV1BusinessesByIdDocumentTypesSummary(options: Options) { return (options.client ?? client).get({ url: '/api/v1/businesses/{id}/document-types-summary', ...options }); } @@ -222,30 +393,71 @@ export class Businesses { return (options.client ?? client).post({ url: '/api/v1/businesses/{id}/disconnect', ...options }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Businesses/$count', ...options }); - } - - public static key(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Businesses/{key}', ...options }); - } - - public static get api() { - return Api; + static api = Api7; +} + +export class BusinessesMemberships { + public static putApiV1BusinessMemberships(options?: Options) { + return (options?.client ?? client).put({ + url: '/api/v1/business-memberships', + ...options, + headers: { + 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', + ...options?.headers + } + }); } } export class BusinessSummaries { - public static count(options?: Options) { + public static $count(options?: Options) { return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessSummaries/$count', ...options }); } - - public static get api() { - return Api; +} + +export class Odata8 { + public static businessSummaries(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessSummaries', ...options }); } + + static businessSummaries2 = BusinessSummaries; +} + +export class VVersionApiVersion8 { + static odata = Odata8; +} + +export class Api8 { + static vVersionApiVersion = VVersionApiVersion8; +} + +export class BusinessSummaries2 { + static api = Api8; } export class Counterparties { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Counterparties/$count', ...options }); + } +} + +export class Odata9 { + public static counterparties(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Counterparties', ...options }); + } + + static counterparties2 = Counterparties; +} + +export class VVersionApiVersion9 { + static odata = Odata9; +} + +export class Api9 { + static vVersionApiVersion = VVersionApiVersion9; +} + +export class Counterparties2 { public static postApiV1Counterparties(options?: Options) { return (options?.client ?? client).post({ url: '/api/v1/counterparties', @@ -272,16 +484,32 @@ export class Counterparties { }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Counterparties/$count', ...options }); + static api = Api9; +} + +export class DataBoxCredentials { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/DataBoxCredentials/$count', ...options }); } - - public static get api() { - return Api; +} + +export class Odata10 { + public static dataBoxCredentials(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/DataBoxCredentials', ...options }); } + + static dataBoxCredentials2 = DataBoxCredentials; } -export class DataBoxCredentials { +export class VVersionApiVersion10 { + static odata = Odata10; +} + +export class Api10 { + static vVersionApiVersion = VVersionApiVersion10; +} + +export class DataBoxCredentials2 { public static putApiV1DataBoxCredentials(options?: Options) { return (options?.client ?? client).put({ url: '/api/v1/data-box-credentials', @@ -297,35 +525,158 @@ export class DataBoxCredentials { return (options.client ?? client).delete({ url: '/api/v1/data-box-credentials/{id}', ...options }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/DataBoxCredentials/$count', ...options }); - } - - public static get api() { - return Api; - } + static api = Api10; } -export class DocumentTypes { - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/DocumentTypes/$count', ...options }); +export class Dev { + public static getApiDev(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev', ...options }); } - public static get api() { - return Api; + public static getApiDevReseedDb(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/reseed-db', ...options }); } -} - -export class Invitations { - public static postApiV1Invitations(options?: Options) { - return (options?.client ?? client).post({ - url: '/api/v1/invitations', - ...options, - headers: { - 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', - ...options?.headers - } - }); + + public static getApiDevDbReset(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/db-reset', ...options }); + } + + public static getApiDevDbReset2(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/db/reset', ...options }); + } + + public static getApiDevDbCreate(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/db/create', ...options }); + } + + public static getApiDevDbTouch(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/db/touch', ...options }); + } + + public static getApiDevSeed(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/seed', ...options }); + } + + public static getApiDevSeedAll(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/seed-all', ...options }); + } + + public static getApiDevSeedProd(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/seed-prod', ...options }); + } + + public static getApiDevJobProcessRecurringTasks(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/job/process-recurring-tasks', ...options }); + } + + public static getApiDevNotificationsSendTest(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/notifications/send-test', ...options }); + } + + public static getApiDevConfirmEmail(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/confirm-email', ...options }); + } + + public static getApiDevEmailSendTest(options?: Options) { + return (options?.client ?? client).get({ url: '/api/dev/email/send-test', ...options }); + } +} + +export class DeviceTokens { + public static deleteApiV1NotificationsDeviceTokens(options?: Options) { + return (options?.client ?? client).delete({ + url: '/api/v1/notifications/device-tokens', + ...options, + headers: { + 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', + ...options?.headers + } + }); + } + + public static putApiV1NotificationsDeviceTokens(options?: Options) { + return (options?.client ?? client).put({ + url: '/api/v1/notifications/device-tokens', + ...options, + headers: { + 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', + ...options?.headers + } + }); + } +} + +export class DocumentTypes { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/DocumentTypes/$count', ...options }); + } +} + +export class Odata11 { + public static documentTypes(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/DocumentTypes', ...options }); + } + + static documentTypes2 = DocumentTypes; +} + +export class VVersionApiVersion11 { + static odata = Odata11; +} + +export class Api11 { + static vVersionApiVersion = VVersionApiVersion11; +} + +export class DocumentTypes2 { + static api = Api11; +} + +export class Feedback { + public static postApiV1Feedback(options?: Options) { + return (options?.client ?? client).post({ + url: '/api/v1/feedback', + ...options, + headers: { + 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', + ...options?.headers + } + }); + } +} + +export class Invitations { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Invitations/$count', ...options }); + } +} + +export class Odata12 { + public static invitations(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Invitations', ...options }); + } + + static invitations2 = Invitations; +} + +export class VVersionApiVersion12 { + static odata = Odata12; +} + +export class Api12 { + static vVersionApiVersion = VVersionApiVersion12; +} + +export class Invitations2 { + public static postApiV1Invitations(options?: Options) { + return (options?.client ?? client).post({ + url: '/api/v1/invitations', + ...options, + headers: { + 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', + ...options?.headers + } + }); } public static postApiV1InvitationsByIdAccept(options: Options) { @@ -358,16 +709,32 @@ export class Invitations { }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Invitations/$count', ...options }); + static api = Api12; +} + +export class Invoices { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Invoices/$count', ...options }); } - - public static get api() { - return Api; +} + +export class Odata13 { + public static invoices(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Invoices', ...options }); } + + static invoices2 = Invoices; } -export class Invoices { +export class VVersionApiVersion13 { + static odata = Odata13; +} + +export class Api13 { + static vVersionApiVersion = VVersionApiVersion13; +} + +export class Invoices2 { public static postApiV1Invoices(options?: Options) { return (options?.client ?? client).post({ url: '/api/v1/invoices', @@ -413,16 +780,32 @@ export class Invoices { return (options.client ?? client).post({ url: '/api/v1/invoices/{id}/snapshot', ...options }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Invoices/$count', ...options }); + static api = Api13; +} + +export class InvoiceSettings { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/InvoiceSettings/$count', ...options }); } - - public static get api() { - return Api; +} + +export class Odata14 { + public static invoiceSettings(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/InvoiceSettings', ...options }); } + + static invoiceSettings2 = InvoiceSettings; } -export class InvoiceSettings { +export class VVersionApiVersion14 { + static odata = Odata14; +} + +export class Api14 { + static vVersionApiVersion = VVersionApiVersion14; +} + +export class InvoiceSettings2 { public static putApiV1InvoiceSettings(options?: Options) { return (options?.client ?? client).put({ url: '/api/v1/invoice-settings', @@ -434,26 +817,71 @@ export class InvoiceSettings { }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/InvoiceSettings/$count', ...options }); - } - - public static get api() { - return Api; - } + static api = Api14; } export class Licenses { - public static count(options?: Options) { + public static $count(options?: Options) { return (options?.client ?? client).get({ url: '/api/v1/odata/Licenses/$count', ...options }); } +} + +export class Odata15 { + public static licenses(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Licenses', ...options }); + } - public static get api() { - return Api; + static licenses2 = Licenses; +} + +export class VVersionApiVersion15 { + static odata = Odata15; +} + +export class Api15 { + static vVersionApiVersion = VVersionApiVersion15; +} + +export class Licenses2 { + static api = Api15; +} + +export class Notifications { + public static postApiV1NotificationsTest(options?: Options) { + return (options?.client ?? client).post({ + url: '/api/v1/notifications/test', + ...options, + headers: { + 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', + ...options?.headers + } + }); } } export class PersonalDocuments { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/PersonalDocuments/$count', ...options }); + } +} + +export class Odata16 { + public static personalDocuments(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/PersonalDocuments', ...options }); + } + + static personalDocuments2 = PersonalDocuments; +} + +export class VVersionApiVersion16 { + static odata = Odata16; +} + +export class Api16 { + static vVersionApiVersion = VVersionApiVersion16; +} + +export class PersonalDocuments2 { public static getApiV1PersonalDocumentsByIdRaw(options: Options) { return (options.client ?? client).get({ url: '/api/v1/personal-documents/{id}/raw', ...options }); } @@ -489,16 +917,32 @@ export class PersonalDocuments { return (options?.client ?? client).get({ url: '/api/v1/personal-documents/summary', ...options }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/PersonalDocuments/$count', ...options }); + static api = Api16; +} + +export class RecurringTasks { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/RecurringTasks/$count', ...options }); } - - public static get api() { - return Api; +} + +export class Odata17 { + public static recurringTasks(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/RecurringTasks', ...options }); } + + static recurringTasks2 = RecurringTasks; } -export class RecurringTasks { +export class VVersionApiVersion17 { + static odata = Odata17; +} + +export class Api17 { + static vVersionApiVersion = VVersionApiVersion17; +} + +export class RecurringTasks2 { public static postApiV1RecurringTasks(options?: Options) { return (options?.client ?? client).post({ url: '/api/v1/recurring-tasks', @@ -525,16 +969,46 @@ export class RecurringTasks { }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/RecurringTasks/$count', ...options }); + static api = Api17; +} + +export class Root { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/', ...options }); + } +} + +export class Tasks { + public static $count(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Tasks/$count', ...options }); } - public static get api() { - return Api; + public static key(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Tasks/{key}', ...options }); } } -export class Tasks { +export class Odata18 { + public static tasks(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Tasks', ...options }); + } + + public static tasksKey(options?: Options) { + return (options?.client ?? client).get({ url: '/api/v1/odata/Tasks({key})', ...options }); + } + + static tasks2 = Tasks; +} + +export class VVersionApiVersion18 { + static odata = Odata18; +} + +export class Api18 { + static vVersionApiVersion = VVersionApiVersion18; +} + +export class Tasks2 { public static postApiV1Tasks(options?: Options) { return (options?.client ?? client).post({ url: '/api/v1/tasks', @@ -591,155 +1065,28 @@ export class Tasks { return (options.client ?? client).get({ url: '/api/v1/tasks/{id}/documents', ...options }); } - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Tasks/$count', ...options }); - } - - public static key(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Tasks/{key}', ...options }); - } - - public static get api() { - return Api; - } + static api = Api18; } -export class Odata { - public static accountingCompanies(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/AccountingCompanies', ...options }); - } - - public static accountingCompanyMemberships(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/AccountingCompanyMemberships', ...options }); - } - - public static bankAccounts(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/BankAccounts', ...options }); - } - - public static businessAccountantAssignments(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessAccountantAssignments', ...options }); - } - - public static businessDocumentActivities(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessDocumentActivities', ...options }); - } - - public static businessDocuments(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessDocuments', ...options }); - } - - /** - * @deprecated - */ - public static businessDocumentsSummaries(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessDocumentsSummaries', ...options }); - } - - public static businesses(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Businesses', ...options }); - } - - public static businessesKey(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Businesses({key})', ...options }); - } - - public static businessSummaries(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/BusinessSummaries', ...options }); - } - - public static counterparties(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Counterparties', ...options }); - } - - public static dataBoxCredentials(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/DataBoxCredentials', ...options }); - } - - public static documentTypes(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/DocumentTypes', ...options }); - } - - public static invitations(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Invitations', ...options }); - } - - public static invoices(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Invoices', ...options }); - } - - public static invoiceSettings(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/InvoiceSettings', ...options }); - } - - public static licenses(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Licenses', ...options }); - } - - public static personalDocuments(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/PersonalDocuments', ...options }); - } - - public static recurringTasks(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/RecurringTasks', ...options }); - } - - public static tasks(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Tasks', ...options }); - } - - public static tasksKey(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/Tasks({key})', ...options }); - } - - public static get accountingCompanies2() { - return AccountingCompanies; +export class User { + public static confirmEmail(options: Options) { + return (options.client ?? client).get({ url: '/api/v1/user/confirmEmail', ...options }); } - - static accountingCompanyMemberships2 = AccountingCompanyMemberships; - - static bankAccounts2 = BankAccounts; - - static businessAccountantAssignments2 = BusinessAccountantAssignments; - - static businessDocumentActivities2 = BusinessDocumentActivities; - - static businessDocuments2 = BusinessDocuments; - - static businessDocumentsSummaries2 = BusinessDocumentsSummaries; - - static businesses2 = Businesses; - - static businessSummaries2 = BusinessSummaries; - - static counterparties2 = Counterparties; - - static dataBoxCredentials2 = DataBoxCredentials; - - static documentTypes2 = DocumentTypes; - - static invitations2 = Invitations; - - static invoices2 = Invoices; - - static invoiceSettings2 = InvoiceSettings; - - static licenses2 = Licenses; - - static personalDocuments2 = PersonalDocuments; - - static recurringTasks2 = RecurringTasks; - - static tasks2 = Tasks; +} + +export class VVersionApiVersion19 { + static user = User; +} + +export class Api19 { + static vVersionApiVersion = VVersionApiVersion19; } export class MapIdentityApi { - public static get api() { - return Api; - } + static api = Api19; } -export class User { +export class User2 { public static postApiV1UserRegister(options: Options) { return (options.client ?? client).post({ url: '/api/v1/user/register', @@ -773,10 +1120,6 @@ export class User { }); } - public static confirmEmail(options: Options) { - return (options.client ?? client).get({ url: '/api/v1/user/confirmEmail', ...options }); - } - public static postApiV1UserResendConfirmationEmail(options: Options) { return (options.client ?? client).post({ url: '/api/v1/user/resendConfirmationEmail', @@ -861,173 +1204,6 @@ export class User { static mapIdentityApi = MapIdentityApi; } -export class VVersionApiVersion { - static odata = Odata; - - static user = User; -} - -export class Api { - static vVersionApiVersion = VVersionApiVersion; -} - -export class AccountingCompanies { - public static postApiV1AccountingCompanies(options?: Options) { - return (options?.client ?? client).post({ - url: '/api/v1/accounting-companies', - ...options, - headers: { - 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', - ...options?.headers - } - }); - } - - public static deleteApiV1AccountingCompaniesById(options: Options) { - return (options.client ?? client).delete({ url: '/api/v1/accounting-companies/{id}', ...options }); - } - - public static postApiV1AccountingCompaniesById(options: Options) { - return (options.client ?? client).post({ - url: '/api/v1/accounting-companies/{id}', - ...options, - headers: { - 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', - ...options.headers - } - }); - } - - public static count(options?: Options) { - return (options?.client ?? client).get({ url: '/api/v1/odata/AccountingCompanies/$count', ...options }); - } - - static api = Api; -} - -export class BusinessesMemberships { - public static putApiV1BusinessMemberships(options?: Options) { - return (options?.client ?? client).put({ - url: '/api/v1/business-memberships', - ...options, - headers: { - 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', - ...options?.headers - } - }); - } -} - -export class Dev { - public static getApiDev(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev', ...options }); - } - - public static getApiDevReseedDb(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/reseed-db', ...options }); - } - - public static getApiDevDbReset(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/db-reset', ...options }); - } - - public static getApiDevDbReset2(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/db/reset', ...options }); - } - - public static getApiDevDbCreate(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/db/create', ...options }); - } - - public static getApiDevDbTouch(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/db/touch', ...options }); - } - - public static getApiDevSeed(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/seed', ...options }); - } - - public static getApiDevSeedAll(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/seed-all', ...options }); - } - - public static getApiDevSeedProd(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/seed-prod', ...options }); - } - - public static getApiDevJobProcessRecurringTasks(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/job/process-recurring-tasks', ...options }); - } - - public static getApiDevNotificationsSendTest(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/notifications/send-test', ...options }); - } - - public static getApiDevConfirmEmail(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/confirm-email', ...options }); - } - - public static getApiDevEmailSendTest(options?: Options) { - return (options?.client ?? client).get({ url: '/api/dev/email/send-test', ...options }); - } -} - -export class DeviceTokens { - public static deleteApiV1NotificationsDeviceTokens(options?: Options) { - return (options?.client ?? client).delete({ - url: '/api/v1/notifications/device-tokens', - ...options, - headers: { - 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', - ...options?.headers - } - }); - } - - public static putApiV1NotificationsDeviceTokens(options?: Options) { - return (options?.client ?? client).put({ - url: '/api/v1/notifications/device-tokens', - ...options, - headers: { - 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', - ...options?.headers - } - }); - } -} - -export class Feedback { - public static postApiV1Feedback(options?: Options) { - return (options?.client ?? client).post({ - url: '/api/v1/feedback', - ...options, - headers: { - 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', - ...options?.headers - } - }); - } -} - -export class Notifications { - public static postApiV1NotificationsTest(options?: Options) { - return (options?.client ?? client).post({ - url: '/api/v1/notifications/test', - ...options, - headers: { - 'Content-Type': 'application/json;odata.metadata=minimal;odata.streaming=true', - ...options?.headers - } - }); - } -} - -export class Root { - public static get(options?: Options) { - return (options?.client ?? client).get({ url: '/', ...options }); - } -} - export class Users { public static getApiV1UsersMe(options?: Options) { return (options?.client ?? client).get({ url: '/api/v1/users/me', ...options }); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/method-class-conflict/instance/sdk.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/method-class-conflict/instance/sdk.gen.ts index 86dcdf974..cbf583ebb 100644 --- a/packages/openapi-ts-tests/sdks/__snapshots__/method-class-conflict/instance/sdk.gen.ts +++ b/packages/openapi-ts-tests/sdks/__snapshots__/method-class-conflict/instance/sdk.gen.ts @@ -47,37 +47,37 @@ class HeyApiRegistry { } export class AccountingCompanies extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/AccountingCompanies/$count', ...options }); } } export class AccountingCompanyMemberships extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/AccountingCompanyMemberships/$count', ...options }); } } export class BankAccounts extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/BankAccounts/$count', ...options }); } } export class BusinessAccountantAssignments extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/BusinessAccountantAssignments/$count', ...options }); } } export class BusinessDocumentActivities extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/BusinessDocumentActivities/$count', ...options }); } } export class BusinessDocuments extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/BusinessDocuments/$count', ...options }); } } @@ -86,13 +86,13 @@ export class BusinessDocumentsSummaries extends HeyApiClient { /** * @deprecated */ - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/BusinessDocumentsSummaries/$count', ...options }); } } export class Businesses extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/Businesses/$count', ...options }); } @@ -102,67 +102,67 @@ export class Businesses extends HeyApiClient { } export class BusinessSummaries extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/BusinessSummaries/$count', ...options }); } } export class Counterparties extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/Counterparties/$count', ...options }); } } export class DataBoxCredentials extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/DataBoxCredentials/$count', ...options }); } } export class DocumentTypes extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/DocumentTypes/$count', ...options }); } } export class Invitations extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/Invitations/$count', ...options }); } } export class Invoices extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/Invoices/$count', ...options }); } } export class InvoiceSettings extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/InvoiceSettings/$count', ...options }); } } export class Licenses extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/Licenses/$count', ...options }); } } export class PersonalDocuments extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/PersonalDocuments/$count', ...options }); } } export class RecurringTasks extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/RecurringTasks/$count', ...options }); } } export class Tasks extends HeyApiClient { - public count(options?: Options) { + public $count(options?: Options) { return (options?.client ?? this.client).get({ url: '/api/v1/odata/Tasks/$count', ...options }); } @@ -259,99 +259,113 @@ export class Odata extends HeyApiClient { return (options?.client ?? this.client).get({ url: '/api/v1/odata/Tasks({key})', ...options }); } - private _accountingCompanies2?: AccountingCompanies; + private _accountingCompanies?: AccountingCompanies; get accountingCompanies2(): AccountingCompanies { - return this._accountingCompanies2 ??= new AccountingCompanies({ client: this.client }); + return this._accountingCompanies ??= new AccountingCompanies({ client: this.client }); } - private _accountingCompanyMemberships2?: AccountingCompanyMemberships; + private _accountingCompanyMemberships?: AccountingCompanyMemberships; get accountingCompanyMemberships2(): AccountingCompanyMemberships { - return this._accountingCompanyMemberships2 ??= new AccountingCompanyMemberships({ client: this.client }); + return this._accountingCompanyMemberships ??= new AccountingCompanyMemberships({ client: this.client }); } - private _bankAccounts2?: BankAccounts; + private _bankAccounts?: BankAccounts; get bankAccounts2(): BankAccounts { - return this._bankAccounts2 ??= new BankAccounts({ client: this.client }); + return this._bankAccounts ??= new BankAccounts({ client: this.client }); } - private _businessAccountantAssignments2?: BusinessAccountantAssignments; + private _businessAccountantAssignments?: BusinessAccountantAssignments; get businessAccountantAssignments2(): BusinessAccountantAssignments { - return this._businessAccountantAssignments2 ??= new BusinessAccountantAssignments({ client: this.client }); + return this._businessAccountantAssignments ??= new BusinessAccountantAssignments({ client: this.client }); } - private _businessDocumentActivities2?: BusinessDocumentActivities; + private _businessDocumentActivities?: BusinessDocumentActivities; get businessDocumentActivities2(): BusinessDocumentActivities { - return this._businessDocumentActivities2 ??= new BusinessDocumentActivities({ client: this.client }); + return this._businessDocumentActivities ??= new BusinessDocumentActivities({ client: this.client }); } - private _businessDocuments2?: BusinessDocuments; + private _businessDocuments?: BusinessDocuments; get businessDocuments2(): BusinessDocuments { - return this._businessDocuments2 ??= new BusinessDocuments({ client: this.client }); + return this._businessDocuments ??= new BusinessDocuments({ client: this.client }); } - private _businessDocumentsSummaries2?: BusinessDocumentsSummaries; + private _businessDocumentsSummaries?: BusinessDocumentsSummaries; get businessDocumentsSummaries2(): BusinessDocumentsSummaries { - return this._businessDocumentsSummaries2 ??= new BusinessDocumentsSummaries({ client: this.client }); + return this._businessDocumentsSummaries ??= new BusinessDocumentsSummaries({ client: this.client }); } - private _businesses2?: Businesses; + private _businesses?: Businesses; get businesses2(): Businesses { - return this._businesses2 ??= new Businesses({ client: this.client }); + return this._businesses ??= new Businesses({ client: this.client }); } - private _businessSummaries2?: BusinessSummaries; + private _businessSummaries?: BusinessSummaries; get businessSummaries2(): BusinessSummaries { - return this._businessSummaries2 ??= new BusinessSummaries({ client: this.client }); + return this._businessSummaries ??= new BusinessSummaries({ client: this.client }); } - private _counterparties2?: Counterparties; + private _counterparties?: Counterparties; get counterparties2(): Counterparties { - return this._counterparties2 ??= new Counterparties({ client: this.client }); + return this._counterparties ??= new Counterparties({ client: this.client }); } - private _dataBoxCredentials2?: DataBoxCredentials; + private _dataBoxCredentials?: DataBoxCredentials; get dataBoxCredentials2(): DataBoxCredentials { - return this._dataBoxCredentials2 ??= new DataBoxCredentials({ client: this.client }); + return this._dataBoxCredentials ??= new DataBoxCredentials({ client: this.client }); } - private _documentTypes2?: DocumentTypes; + private _documentTypes?: DocumentTypes; get documentTypes2(): DocumentTypes { - return this._documentTypes2 ??= new DocumentTypes({ client: this.client }); + return this._documentTypes ??= new DocumentTypes({ client: this.client }); } - private _invitations2?: Invitations; + private _invitations?: Invitations; get invitations2(): Invitations { - return this._invitations2 ??= new Invitations({ client: this.client }); + return this._invitations ??= new Invitations({ client: this.client }); } - private _invoices2?: Invoices; + private _invoices?: Invoices; get invoices2(): Invoices { - return this._invoices2 ??= new Invoices({ client: this.client }); + return this._invoices ??= new Invoices({ client: this.client }); } - private _invoiceSettings2?: InvoiceSettings; + private _invoiceSettings?: InvoiceSettings; get invoiceSettings2(): InvoiceSettings { - return this._invoiceSettings2 ??= new InvoiceSettings({ client: this.client }); + return this._invoiceSettings ??= new InvoiceSettings({ client: this.client }); } - private _licenses2?: Licenses; + private _licenses?: Licenses; get licenses2(): Licenses { - return this._licenses2 ??= new Licenses({ client: this.client }); + return this._licenses ??= new Licenses({ client: this.client }); } - private _personalDocuments2?: PersonalDocuments; + private _personalDocuments?: PersonalDocuments; get personalDocuments2(): PersonalDocuments { - return this._personalDocuments2 ??= new PersonalDocuments({ client: this.client }); + return this._personalDocuments ??= new PersonalDocuments({ client: this.client }); } - private _recurringTasks2?: RecurringTasks; + private _recurringTasks?: RecurringTasks; get recurringTasks2(): RecurringTasks { - return this._recurringTasks2 ??= new RecurringTasks({ client: this.client }); + return this._recurringTasks ??= new RecurringTasks({ client: this.client }); } - private _tasks2?: Tasks; + private _tasks?: Tasks; get tasks2(): Tasks { - return this._tasks2 ??= new Tasks({ client: this.client }); + return this._tasks ??= new Tasks({ client: this.client }); + } +} + +export class VVersionApiVersion extends HeyApiClient { + private _odata?: Odata; + get odata(): Odata { + return this._odata ??= new Odata({ client: this.client }); + } +} + +export class Api extends HeyApiClient { + private _vVersionApiVersion?: VVersionApiVersion; + get vVersionApiVersion(): VVersionApiVersion { + return this._vVersionApiVersion ??= new VVersionApiVersion({ client: this.client }); } } @@ -361,29 +375,24 @@ export class User extends HeyApiClient { } } -export class VVersionApiVersion extends HeyApiClient { - private _odata?: Odata; - get odata(): Odata { - return this._odata ??= new Odata({ client: this.client }); - } - +export class VVersionApiVersion2 extends HeyApiClient { private _user?: User; get user(): User { return this._user ??= new User({ client: this.client }); } } -export class Api extends HeyApiClient { - private _vVersionApiVersion?: VVersionApiVersion; - get vVersionApiVersion(): VVersionApiVersion { - return this._vVersionApiVersion ??= new VVersionApiVersion({ client: this.client }); +export class Api2 extends HeyApiClient { + private _vVersionApiVersion?: VVersionApiVersion2; + get vVersionApiVersion(): VVersionApiVersion2 { + return this._vVersionApiVersion ??= new VVersionApiVersion2({ client: this.client }); } } export class MapIdentityApi extends HeyApiClient { - private _api?: Api; - get api(): Api { - return this._api ??= new Api({ client: this.client }); + private _api?: Api2; + get api(): Api2 { + return this._api ??= new Api2({ client: this.client }); } } diff --git a/packages/openapi-ts/src/__tests__/internal.test.ts b/packages/openapi-ts/src/__tests__/internal.test.ts index aa3ac5a13..9cdf0a59d 100644 --- a/packages/openapi-ts/src/__tests__/internal.test.ts +++ b/packages/openapi-ts/src/__tests__/internal.test.ts @@ -1,18 +1,10 @@ import { describe, expect, it } from 'vitest'; describe('internal entry index', () => { - it('getSpec should be exported', async () => { - const { getSpec } = await import('../internal'); - expect(getSpec).toBeDefined(); - }); - - it('initConfigs should be exported', async () => { - const { initConfigs } = await import('../internal'); - expect(initConfigs).toBeDefined(); - }); - - it('parseOpenApiSpec should be exported', async () => { - const { parseOpenApiSpec } = await import('../internal'); - expect(parseOpenApiSpec).toBeDefined(); + it('should be exported', async () => { + const internal = await import('../internal'); + expect(internal.getSpec).toBeDefined(); + expect(internal.initConfigs).toBeDefined(); + expect(internal.parseOpenApiSpec).toBeDefined(); }); }); diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts index 6f503319f..07fd57d3a 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts @@ -91,7 +91,7 @@ export class SdkResourceModel { this.name && plugin.config.classStructure === 'auto' && operation.operationId - ? operation.operationId.split(/[./]/).slice(0, -1) + ? this.splitOperationId(operation.operationId).slice(0, -1) : []; // eslint-disable-next-line @typescript-eslint/no-this-alias @@ -205,7 +205,10 @@ export class SdkResourceModel { plugin, value: extractFromOperationId && operation.operationId - ? toCase(operation.operationId.split(/[./]/).pop()!, 'camelCase') + ? toCase( + this.splitOperationId(operation.operationId).pop()!, + 'camelCase', + ) : operation.id, }), { @@ -231,13 +234,13 @@ export class SdkResourceModel { resourceId: resource.getPath().join('.'), tool: 'sdk', }); - const memberName = toCase(refChild.name, 'camelCase'); + const memberNameStr = toCase(refChild.name, 'camelCase'); + const memberName = plugin.symbol(memberNameStr); if (plugin.config.instance) { - const privateName = plugin.symbol(`_${memberName}`); - const getterName = plugin.symbol(memberName); + const privateName = plugin.symbol(`_${memberNameStr}`); return [ $.field(privateName, (f) => f.private().optional().type(refChild)), - $.getter(getterName, (g) => + $.getter(memberName, (g) => g.returns(refChild).do( $('this') .attr(privateName) @@ -441,4 +444,9 @@ export class SdkResourceModel { .params(...opParameters.parameters) .do(...statements) as T; } + + private splitOperationId(operationId: string): Array { + // TODO: expose this logic + return operationId.split(/[./]/).filter(Boolean); + } } diff --git a/packages/openapi-ts/src/ts-dsl/utils/__tests__/render.test.ts b/packages/openapi-ts/src/ts-dsl/utils/__tests__/render.test.ts index f748ce7e3..ff1ee31ac 100644 --- a/packages/openapi-ts/src/ts-dsl/utils/__tests__/render.test.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/__tests__/render.test.ts @@ -48,16 +48,16 @@ describe('TypeScriptRenderer', () => { imports: [ { isTypeOnly: false, - kind: 'named', localName: 'A', sourceName: 'A', }, ], isTypeOnly: false, + kind: 'named', + localName: undefined, modulePath: 'foo', - namespaceImport: undefined, }; - const node = renderer['renderImport'](group); + const node = TypeScriptRenderer.toImportAst(group); expect(ts.isImportDeclaration(node)).toBe(true); }); @@ -76,7 +76,7 @@ describe('TypeScriptRenderer', () => { modulePath: 'bar', namespaceExport: undefined, }; - const node = renderer['renderExport'](group); + const node = TypeScriptRenderer.toExportAst(group); expect(ts.isExportDeclaration(node)).toBe(true); }); }); diff --git a/packages/openapi-ts/src/ts-dsl/utils/context.ts b/packages/openapi-ts/src/ts-dsl/utils/context.ts index f4e6b43b2..5f31054e2 100644 --- a/packages/openapi-ts/src/ts-dsl/utils/context.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/context.ts @@ -70,9 +70,7 @@ function getStructuralChainForNode( if (visited.has(node)) return []; visited.add(node); - if (node['~dsl'] === 'TemplateTsDsl' || node['~dsl'] === 'FuncTsDsl') { - return []; - } + if (isStopNode(node)) return []; if (node.structuralParents) { for (const [parent] of node.structuralParents) { @@ -88,6 +86,18 @@ function getStructuralChainForNode( return [node]; } +function isAccessorNode(node: TsDsl): boolean { + return ( + node['~dsl'] === 'FieldTsDsl' || + node['~dsl'] === 'GetterTsDsl' || + node['~dsl'] === 'MethodTsDsl' + ); +} + +function isStopNode(node: TsDsl): boolean { + return node['~dsl'] === 'FuncTsDsl' || node['~dsl'] === 'TemplateTsDsl'; +} + /** * Fold a structural chain to an access chain by removing * non-accessor nodes. @@ -98,11 +108,7 @@ function structuralToAccessChain(structuralChain: NodeChain): NodeChain { // assume first node is always included if (index === 0) { accessChain.push(node); - } else if ( - node['~dsl'] === 'FieldTsDsl' || - node['~dsl'] === 'GetterTsDsl' || - node['~dsl'] === 'MethodTsDsl' - ) { + } else if (isAccessorNode(node)) { accessChain.push(node); } }); @@ -125,7 +131,7 @@ function transformAccessChain( if (index === 0) { if (node['~dsl'] === 'ClassTsDsl') { const nextNode = accessChain[index + 1]; - if (nextNode?.['~dsl'] === 'FieldTsDsl') { + if (nextNode && isAccessorNode(nextNode)) { if ((nextNode as ReturnType).hasModifier('static')) { return $(node.name); } -- 2.51.2 From 601ef707f360d79d4cf889bc3baae10770b27065 Mon Sep 17 00:00:00 2001 From: Lubos Date: Sun, 21 Dec 2025 07:03:59 +0800 Subject: [PATCH 07/15] chore: update Angular plugin --- dev/openapi-ts.config.ts | 26 +- dev/package.json | 2 + .../src/__tests__/exports.test.ts | 7 + packages/codegen-core/src/index.ts | 9 + packages/codegen-core/src/structure/model.ts | 90 ++++ packages/codegen-core/src/structure/node.ts | 93 ++++ .../codegen-core/src/structure/types.d.ts | 33 ++ packages/openapi-ts/src/ir/context.ts | 7 +- .../src/openApi/shared/locations/index.ts | 5 + .../src/openApi/shared/locations/operation.ts | 174 +++++++ .../src/openApi/shared/transforms/enums.ts | 15 +- .../openApi/shared/transforms/readWrite.ts | 12 +- .../src/openApi/shared/utils/name.ts | 22 - .../src/openApi/shared/utils/operation.ts | 2 +- .../src/plugins/@angular/common/config.ts | 4 +- .../plugins/@angular/common/httpRequests.ts | 272 +++++------ .../plugins/@angular/common/httpResources.ts | 250 ++++------ .../src/plugins/@angular/common/plugin.ts | 12 +- .../src/plugins/@angular/common/types.d.ts | 10 +- .../plugins/@hey-api/client-core/client.ts | 12 +- .../client-core/createClientConfig.ts | 10 +- .../src/plugins/@hey-api/schemas/plugin.ts | 9 +- .../src/plugins/@hey-api/sdk/config.ts | 35 +- .../plugins/@hey-api/sdk/model/resource.ts | 452 ------------------ .../plugins/@hey-api/sdk/model/structure.ts | 70 --- .../plugins/@hey-api/sdk/shared/operation.ts | 11 +- .../plugins/@hey-api/sdk/shared/signature.ts | 2 +- .../@hey-api/sdk/shared/typeOptions.ts | 12 +- .../plugins/@hey-api/sdk/structure/config.ts | 202 ++++++++ .../plugins/@hey-api/sdk/structure/index.ts | 6 + .../plugins/@hey-api/sdk/structure/types.d.ts | 195 ++++++++ .../src/plugins/@hey-api/sdk/types.d.ts | 260 +++++----- .../src/plugins/@hey-api/sdk/v1/plugin.ts | 430 ++++++++++++++++- .../plugins/@hey-api/transformers/plugin.ts | 38 +- .../typescript/shared/clientOptions.ts | 9 +- .../@hey-api/typescript/shared/export.ts | 103 ++-- .../@hey-api/typescript/shared/operation.ts | 149 +++--- .../@hey-api/typescript/shared/webhook.ts | 62 ++- .../plugins/@hey-api/typescript/types.d.ts | 72 +-- .../plugins/@hey-api/typescript/v1/plugin.ts | 9 +- .../@hey-api/typescript/v1/toAst/string.ts | 15 +- .../plugins/@pinia/colada/mutationOptions.ts | 11 +- .../src/plugins/@pinia/colada/queryKey.ts | 31 +- .../src/plugins/@pinia/colada/queryOptions.ts | 34 +- .../src/plugins/@pinia/colada/types.d.ts | 36 +- .../angular-query-experimental/types.d.ts | 56 +-- .../plugins/@tanstack/query-core/queryKey.ts | 28 +- .../query-core/v5/infiniteQueryOptions.ts | 43 +- .../query-core/v5/mutationOptions.ts | 7 +- .../@tanstack/query-core/v5/queryOptions.ts | 34 +- .../@tanstack/query-core/v5/useQuery.ts | 11 +- .../plugins/@tanstack/react-query/types.d.ts | 66 +-- .../plugins/@tanstack/solid-query/types.d.ts | 56 +-- .../plugins/@tanstack/svelte-query/types.d.ts | 56 +-- .../plugins/@tanstack/vue-query/types.d.ts | 56 +-- .../openapi-ts/src/plugins/arktype/types.d.ts | 92 ++-- .../src/plugins/arktype/v2/plugin.ts | 55 +-- .../openapi-ts/src/plugins/fastify/plugin.ts | 7 +- .../openapi-ts/src/plugins/swr/types.d.ts | 66 +-- .../openapi-ts/src/plugins/swr/v2/plugin.ts | 3 +- .../openapi-ts/src/plugins/swr/v2/useSwr.ts | 11 +- .../src/plugins/valibot/shared/operation.ts | 56 ++- .../src/plugins/valibot/shared/webhook.ts | 29 +- .../openapi-ts/src/plugins/valibot/types.d.ts | 46 +- .../src/plugins/valibot/v1/plugin.ts | 30 +- .../openapi-ts/src/plugins/zod/mini/plugin.ts | 57 ++- .../src/plugins/zod/shared/operation.ts | 22 +- .../src/plugins/zod/shared/webhook.ts | 58 ++- .../openapi-ts/src/plugins/zod/types.d.ts | 92 ++-- .../openapi-ts/src/plugins/zod/v3/plugin.ts | 57 ++- .../openapi-ts/src/plugins/zod/v4/plugin.ts | 57 ++- packages/openapi-ts/src/types/case.d.ts | 8 - packages/openapi-ts/src/types/output.d.ts | 16 +- packages/openapi-ts/src/types/parser.d.ts | 31 +- packages/openapi-ts/src/utils/exports.ts | 7 +- .../__tests__/naming.test.ts} | 7 +- packages/openapi-ts/src/utils/naming/index.ts | 7 + .../utils/{to-case.ts => naming/naming.ts} | 48 +- .../openapi-ts/src/utils/naming/types.d.ts | 43 ++ pnpm-lock.yaml | 6 + 80 files changed, 2605 insertions(+), 2039 deletions(-) create mode 100644 packages/codegen-core/src/structure/model.ts create mode 100644 packages/codegen-core/src/structure/node.ts create mode 100644 packages/codegen-core/src/structure/types.d.ts create mode 100644 packages/openapi-ts/src/openApi/shared/locations/index.ts create mode 100644 packages/openapi-ts/src/openApi/shared/locations/operation.ts delete mode 100644 packages/openapi-ts/src/openApi/shared/utils/name.ts delete mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts delete mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts create mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/structure/config.ts create mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/structure/index.ts create mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/structure/types.d.ts delete mode 100644 packages/openapi-ts/src/types/case.d.ts rename packages/openapi-ts/src/utils/{__tests__/to-case.test.ts => naming/__tests__/naming.test.ts} (97%) create mode 100644 packages/openapi-ts/src/utils/naming/index.ts rename packages/openapi-ts/src/utils/{to-case.ts => naming/naming.ts} (82%) create mode 100644 packages/openapi-ts/src/utils/naming/types.d.ts diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index 5e2676020..77a6a4971 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -39,8 +39,8 @@ export default defineConfig(() => { path: path.resolve( getSpecsPath(), // '2.0.x', - '3.0.x', - // '3.1.x', + // '3.0.x', + '3.1.x', // 'circular.yaml', // 'dutchie.json', // 'enum-names-values.yaml', @@ -49,11 +49,11 @@ export default defineConfig(() => { // 'invalid', // 'object-property-names.yaml', // 'openai.yaml', - // 'opencode.yaml', + 'opencode.yaml', // 'pagination-ref.yaml', // 'schema-const.yaml', // 'sdk-instance.yaml', - 'sdk-method-class-conflict.yaml', + // 'sdk-method-class-conflict.yaml', // 'sdk-nested-classes.yaml', // 'sdk-nested-conflict.yaml', // 'string-with-format.yaml', @@ -241,7 +241,7 @@ export default defineConfig(() => { { // baseUrl: false, // exportFromIndex: true, - // name: '@hey-api/client-nuxt', + // name: '@hey-api/client-angular', // runtimeConfigPath: path.resolve(__dirname, 'hey-api.ts'), // runtimeConfigPath: './src/hey-api.ts', // strictBaseUrl: true, @@ -275,7 +275,7 @@ export default defineConfig(() => { // }, }, { - // asClass: true, + asClass: true, // auth: false, // classNameBuilder: '{{name}}Service', // classStructure: 'off', @@ -285,7 +285,7 @@ export default defineConfig(() => { // fields.unwrap('path') // }, // include... - // instance: 'OpencodeClient', + instance: 'OpencodeClient', // methodNameBuilder: '{{name}}', name: '@hey-api/sdk', // operationId: false, @@ -294,6 +294,12 @@ export default defineConfig(() => { // signature: 'auto', // signature: 'client', // signature: 'object', + structure: { + operations: { + containerName: 'OpencodeClient', + strategy: 'single', + }, + }, // transformer: '@hey-api/transformers', // transformer: true, // validator: 'valibot', @@ -601,16 +607,18 @@ export default defineConfig(() => { exportFromIndex: true, httpRequests: { asClass: true, + // enabled: false, }, httpResources: { - asClass: true, + // asClass: true, + enabled: false, }, // name: '@angular/common', }, { exportFromIndex: true, // mutationOptions: '{{name}}Mutationssss', - name: '@pinia/colada', + // name: '@pinia/colada', // queryOptions: { // name: '{{name}}Queryyyyy', // }, diff --git a/dev/package.json b/dev/package.json index d44e7e2e7..46231f551 100644 --- a/dev/package.json +++ b/dev/package.json @@ -10,6 +10,8 @@ "dev": "ts-node ./playground.ts" }, "devDependencies": { + "@angular/common": "19.2.17", + "@angular/core": "19.2.17", "@hey-api/codegen-core": "workspace:*", "@hey-api/openapi-ts": "workspace:*", "@opencode-ai/sdk": "1.0.170", diff --git a/packages/codegen-core/src/__tests__/exports.test.ts b/packages/codegen-core/src/__tests__/exports.test.ts index 3cb71fb81..99b0e335f 100644 --- a/packages/codegen-core/src/__tests__/exports.test.ts +++ b/packages/codegen-core/src/__tests__/exports.test.ts @@ -53,6 +53,13 @@ export type _TypeExports = [ index.Refs, index.RenderContext, index.Renderer, + index.StructureInsert, + index.StructureItem, + index.StructureLocation, + index.StructureModel, + index.StructureNode, + index.StructureShell, + index.StructureShellResult, index.Symbol, index.SymbolIdentifier, index.SymbolIn, diff --git a/packages/codegen-core/src/index.ts b/packages/codegen-core/src/index.ts index a78be42be..6d306983d 100644 --- a/packages/codegen-core/src/index.ts +++ b/packages/codegen-core/src/index.ts @@ -41,6 +41,15 @@ export type { IProject } from './project/types'; export { fromRef, fromRefs, isRef, ref, refs } from './refs/refs'; export type { FromRef, FromRefs, Ref, Refs } from './refs/types'; export type { RenderContext, Renderer } from './renderer'; +export { StructureModel } from './structure/model'; +export { StructureNode } from './structure/node'; +export type { + StructureInsert, + StructureItem, + StructureLocation, + StructureShell, + StructureShellResult, +} from './structure/types'; export { Symbol } from './symbols/symbol'; export type { BindingKind, diff --git a/packages/codegen-core/src/structure/model.ts b/packages/codegen-core/src/structure/model.ts new file mode 100644 index 000000000..d38f3b80e --- /dev/null +++ b/packages/codegen-core/src/structure/model.ts @@ -0,0 +1,90 @@ +import { StructureNode } from './node'; +import type { StructureInsert } from './types'; + +export class StructureModel { + /** Root nodes mapped by their names. */ + private _roots: Map = new Map(); + /** Node for data without a specific root. */ + private _virtualRoot?: StructureNode; + + /** + * Get all root nodes. + */ + get roots(): ReadonlyArray { + const roots = Array.from(this._roots.values()); + if (this._virtualRoot) roots.unshift(this._virtualRoot); + return roots; + } + + /** + * Insert data into the structure. + */ + insert(args: StructureInsert): void { + const { data, locations, source } = args; + for (const location of locations) { + const { path, shell } = location; + const fullPath = path.filter((s): s is string => Boolean(s)); + const segments = fullPath.slice(0, -1); + const name = fullPath[fullPath.length - 1]; + + if (!name) { + throw new Error('Cannot insert data without path.'); + } + + let cursor: StructureNode | null = null; + + for (const segment of segments) { + if (!cursor) { + cursor = this.root(segment); + } else { + cursor = cursor.child(segment); + } + + if (shell && !cursor.shell) { + cursor.shell = shell; + cursor.shellSource = source; + } + } + + if (!cursor) { + cursor = this.root(null); + } + + cursor.items.push({ data, location: fullPath, source }); + } + } + + /** + * Gets or creates a root by name. + * + * If the root doesn't exist, it's created automatically. + * + * @param name - The name of the root + * @returns The root instance + */ + root(name: string | null): StructureNode { + if (!name) { + return (this._virtualRoot ??= new StructureNode('', undefined, { + virtual: true, + })); + } + if (!this._roots.has(name)) { + this._roots.set(name, new StructureNode(name)); + } + return this._roots.get(name)!; + } + + /** + * Walk all nodes in the structure (depth-first, post-order). + * + * @returns Generator of all structure nodes + */ + *walk(): Generator { + if (this._virtualRoot) { + yield* this._virtualRoot.walk(); + } + for (const root of this._roots.values()) { + yield* root.walk(); + } + } +} diff --git a/packages/codegen-core/src/structure/node.ts b/packages/codegen-core/src/structure/node.ts new file mode 100644 index 000000000..3ed78b519 --- /dev/null +++ b/packages/codegen-core/src/structure/node.ts @@ -0,0 +1,93 @@ +import type { StructureItem, StructureShell } from './types'; + +export class StructureNode { + /** Nested nodes within this node. */ + children: Map = new Map(); + /** Items contained in this node. */ + items: Array = []; + /** The name of this node (e.g., "Users", "Accounts"). */ + name: string; + /** Parent node in the hierarchy. Undefined if this is the root node. */ + parent?: StructureNode; + /** Shell claimed for this node. */ + shell?: StructureShell; + /** Source of the claimed shell. */ + shellSource?: symbol; + /** True if this is a virtual root. */ + virtual: boolean; + + constructor( + name: string, + parent?: StructureNode, + options?: { + virtual?: boolean; + }, + ) { + this.name = name; + this.parent = parent; + this.virtual = options?.virtual ?? false; + } + + get isRoot(): boolean { + return !this.parent; + } + + /** + * Gets or creates a child node. + * + * If the child doesn't exist, it's created automatically. + * + * @param name - The name of the child node + * @returns The child node instance + */ + child(name: string): StructureNode { + if (!this.children.has(name)) { + this.children.set(name, new StructureNode(name, this)); + } + return this.children.get(name)!; + } + + /** + * Gets the full path of this node in the hierarchy. + * + * @returns An array of node names from the root to this node + */ + getPath(): ReadonlyArray { + const path: Array = []; + // eslint-disable-next-line @typescript-eslint/no-this-alias + let cursor: StructureNode | undefined = this; + while (cursor) { + path.unshift(cursor.name); + cursor = cursor.parent; + } + return path; + } + + /** + * Yields items from a specific source with typed data. + * + * @param source - The source symbol to filter by + * @returns Generator of items from that source + */ + *itemsFrom( + source: symbol, + ): Generator { + for (const item of this.items) { + if (item.source === source) { + yield item as StructureItem & { data: T }; + } + } + } + + /** + * Walk all nodes in the structure (depth-first, post-order). + * + * @returns Generator of all structure nodes + */ + *walk(): Generator { + for (const node of this.children.values()) { + yield* node.walk(); + } + yield this; + } +} diff --git a/packages/codegen-core/src/structure/types.d.ts b/packages/codegen-core/src/structure/types.d.ts new file mode 100644 index 000000000..05df27b1e --- /dev/null +++ b/packages/codegen-core/src/structure/types.d.ts @@ -0,0 +1,33 @@ +import type { INode } from '../nodes/node'; +import type { StructureNode } from './node'; + +export interface StructureInsert { + /** Inserted data. */ + data: unknown; + /** Locations where the data should be inserted. */ + locations: ReadonlyArray; + /** Source of the inserted data. */ + source: symbol; +} + +export interface StructureItem + extends Pick { + /** Location of this item within the structure. */ + location: ReadonlyArray; +} + +export interface StructureLocation { + /** Path within the structure where the data should be inserted. */ + path: ReadonlyArray; + /** Shell to apply at this location. */ + shell?: StructureShell; +} + +export interface StructureShell { + define: (node: StructureNode) => StructureShellResult; +} + +export interface StructureShellResult { + dependencies?: Array; + node: INode; +} diff --git a/packages/openapi-ts/src/ir/context.ts b/packages/openapi-ts/src/ir/context.ts index 416a10b93..958a24567 100644 --- a/packages/openapi-ts/src/ir/context.ts +++ b/packages/openapi-ts/src/ir/context.ts @@ -3,13 +3,13 @@ import { Project } from '@hey-api/codegen-core'; import type { Package } from '~/config/utils/package'; import { packageFactory } from '~/config/utils/package'; import type { Graph } from '~/graph'; -import { buildName } from '~/openApi/shared/utils/name'; import type { PluginConfigMap } from '~/plugins/config'; import { PluginInstance } from '~/plugins/shared/utils/instance'; import type { PluginNames } from '~/plugins/types'; import { TypeScriptRenderer } from '~/ts-dsl'; import type { Config } from '~/types/config'; import type { Logger } from '~/utils/logger'; +import { applyNaming } from '~/utils/naming'; import { resolveRef } from '~/utils/ref'; import type { IR } from './types'; @@ -72,10 +72,7 @@ export class Context = any> { this.gen = new Project({ defaultFileName: 'index', fileName: (base) => { - const name = buildName({ - config: config.output.fileName, - name: base, - }); + const name = applyNaming(base, config.output.fileName); const { suffix } = config.output.fileName; if (!suffix) { return name; diff --git a/packages/openapi-ts/src/openApi/shared/locations/index.ts b/packages/openapi-ts/src/openApi/shared/locations/index.ts new file mode 100644 index 000000000..e1b443d73 --- /dev/null +++ b/packages/openapi-ts/src/openApi/shared/locations/index.ts @@ -0,0 +1,5 @@ +export type { + OperationLocationStrategy, + OperationPathStrategy, +} from './operation'; +export { OperationLocations, OperationPath } from './operation'; diff --git a/packages/openapi-ts/src/openApi/shared/locations/operation.ts b/packages/openapi-ts/src/openApi/shared/locations/operation.ts new file mode 100644 index 000000000..749649f48 --- /dev/null +++ b/packages/openapi-ts/src/openApi/shared/locations/operation.ts @@ -0,0 +1,174 @@ +import type { StructureLocation, StructureShell } from '@hey-api/codegen-core'; + +import type { IR } from '~/ir/types'; + +/** + * A function that determines where an operation appears in the structure. + * + * Returns one or more locations, each with a full path and optional shell. + */ +export type OperationLocationStrategy = ( + operation: IR.OperationObject, +) => ReadonlyArray; + +/** + * A function that derives path segments from an operation. + * + * Used by location strategies to build paths within containers. + */ +export type OperationPathStrategy = ( + operation: IR.OperationObject, +) => ReadonlyArray; + +/** + * Built-in location strategies for operations. + */ +export const OperationLocations = { + /** + * Creates one root container per operation tag. + * + * Operations with multiple tags appear in multiple root containers. + * Operations without tags use the fallback root container. + * + * @example + * // Operation with tags: ['users', 'admin'] + * // Path function returns: ['list'] + * // Result: [{ path: ['users', 'list'], shell }, { path: ['admin', 'list'], shell }] + */ + byTags: + (config: { + /** + * Root name for operations without tags. + * + * @default 'default' + */ + fallback?: string; + /** + * Derives path segments from the operation. + * + * @default OperationPath.fromOperationId() + */ + path?: OperationPathStrategy; + /** + * Shell to apply to all created nodes. + */ + shell: StructureShell; + }): OperationLocationStrategy => + (operation) => { + const tags = + operation.tags && operation.tags.length > 0 + ? operation.tags + : [config.fallback ?? 'default']; + const pathSegments = (config.path ?? OperationPath.fromOperationId())( + operation, + ); + return tags.map((tag) => ({ + path: [tag, ...pathSegments], + shell: config.shell, + })); + }, + + /** + * Creates flat functions without any container. + * + * Each operation becomes a standalone function at the root level. + * No shell is applied. + * + * @example + * // Operation id: 'getUsers' + * // Result: [{ path: ['getUsers'] }] + */ + flat: + (config?: { + /** + * Derives the function name from the operation. + * + * @default operation.id + */ + name?: (operation: IR.OperationObject) => string; + }): OperationLocationStrategy => + (operation) => [ + { + path: [(config?.name ?? ((operation) => operation.id))(operation)], + }, + ], + + /** + * Places all operations under a single root container. + * + * @example + * // Root: 'Sdk', path function returns: ['users', 'list'] + * // Result: [{ path: ['Sdk', 'users', 'list'], shell }] + */ + single: + (config: { + /** + * Derives path segments within the root from the operation. + * + * @default OperationPath.fromOperationId() + */ + path?: OperationPathStrategy; + /** + * Name of the container. + */ + root: string; + /** + * Shell to apply to all created nodes. + */ + shell: StructureShell; + }): OperationLocationStrategy => + (operation) => [ + { + path: [ + config.root, + ...(config.path ?? OperationPath.fromOperationId())(operation), + ], + shell: config.shell, + }, + ], +}; + +/** + * Built-in path derivation helpers for operations. + */ +export const OperationPath = { + /** + * Splits operationId by delimiters to create nested paths. + * + * The last segment is converted to camelCase. + * Falls back to operation.id if operationId is missing. + * + * @example + * // operationId: 'users.accounts.list' + * // Result: ['users', 'accounts', 'list'] + * + * @example + * // operationId: 'users/accounts/getAll' + * // Result: ['users', 'accounts', 'getAll'] + */ + fromOperationId: + (config?: { + /** + * Pattern to split operationId. + * + * @default /[./]/ + */ + delimiters: RegExp; + }): OperationPathStrategy => + (operation) => { + if (!operation.operationId) return [operation.id]; + const segments = operation.operationId + .split(config?.delimiters ?? /[./]/) + .filter(Boolean); + return segments.length > 0 ? segments : [operation.id]; + }, + + /** + * Uses operation.id as a single path segment. + * + * @example + * // operation.id: 'getUserById' + * // Result: ['getUserById'] + */ + id: (): OperationPathStrategy => (operation) => [operation.id], +}; diff --git a/packages/openapi-ts/src/openApi/shared/transforms/enums.ts b/packages/openapi-ts/src/openApi/shared/transforms/enums.ts index c8c4f0d86..600af1e07 100644 --- a/packages/openapi-ts/src/openApi/shared/transforms/enums.ts +++ b/packages/openapi-ts/src/openApi/shared/transforms/enums.ts @@ -1,7 +1,7 @@ +import { applyNaming } from '~/utils/naming'; import { jsonPointerToPath } from '~/utils/ref'; import type { Config } from '../../../types/config'; -import { buildName } from '../utils/name'; import { deepClone } from '../utils/schema'; import { childSchemaRelationships } from '../utils/schemaChildRelationships'; import { getSchemasObject } from '../utils/transforms'; @@ -215,16 +215,15 @@ const rootMode = ({ config, spec }: { config: EnumsConfig; spec: unknown }) => { } // Generate a unique name for the new root enum using config - const base = buildName({ - config, - name: - typeof node === 'object' && + const base = applyNaming( + typeof node === 'object' && node && 'title' in node && typeof node.title === 'string' - ? node.title - : String(key), - }); + ? node.title + : String(key), + config, + ); const name = getUniqueComponentName({ base, components: schemasObj, diff --git a/packages/openapi-ts/src/openApi/shared/transforms/readWrite.ts b/packages/openapi-ts/src/openApi/shared/transforms/readWrite.ts index a280237a7..080151b13 100644 --- a/packages/openapi-ts/src/openApi/shared/transforms/readWrite.ts +++ b/packages/openapi-ts/src/openApi/shared/transforms/readWrite.ts @@ -1,11 +1,11 @@ import type { Graph } from '~/graph'; import type { Logger } from '~/utils/logger'; +import { applyNaming } from '~/utils/naming'; import { jsonPointerToPath } from '~/utils/ref'; import type { Config } from '../../../types/config'; import deepEqual from '../utils/deepEqual'; import { buildGraph, type Scope } from '../utils/graph'; -import { buildName } from '../utils/name'; import { deepClone } from '../utils/schema'; import { childSchemaRelationships } from '../utils/schemaChildRelationships'; import { @@ -404,10 +404,7 @@ export const splitSchemas = ({ // read variant const readSchema = deepClone(nodeInfo.node); pruneSchemaByScope(graph, readSchema, 'writeOnly'); - const readBase = buildName({ - config: config.responses, - name, - }); + const readBase = applyNaming(name, config.responses); const readName = readBase === name ? readBase @@ -448,10 +445,7 @@ export const splitSchemas = ({ ) { continue; } - const writeBase = buildName({ - config: config.requests, - name, - }); + const writeBase = applyNaming(name, config.requests); const writeName = writeBase === name && writeBase !== readName ? writeBase diff --git a/packages/openapi-ts/src/openApi/shared/utils/name.ts b/packages/openapi-ts/src/openApi/shared/utils/name.ts deleted file mode 100644 index 74424495e..000000000 --- a/packages/openapi-ts/src/openApi/shared/utils/name.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { StringCase, StringName } from '~/types/case'; -import { toCase } from '~/utils/to-case'; - -export const buildName = ({ - config, - name, -}: { - config: { - case: StringCase; - name?: StringName; - }; - name: string; -}): string => { - if (typeof config.name === 'function') { - name = config.name(name); - } else if (config.name) { - const separator = config.case === 'preserve' ? '' : '-'; - name = config.name.replace('{{name}}', `${separator}${name}${separator}`); - } - - return toCase(name, config.case); -}; diff --git a/packages/openapi-ts/src/openApi/shared/utils/operation.ts b/packages/openapi-ts/src/openApi/shared/utils/operation.ts index 7d75734ea..dbb3d15e5 100644 --- a/packages/openapi-ts/src/openApi/shared/utils/operation.ts +++ b/packages/openapi-ts/src/openApi/shared/utils/operation.ts @@ -1,7 +1,7 @@ import type { Context } from '~/ir/context'; import { createOperationKey } from '~/ir/operation'; import { sanitizeNamespaceIdentifier } from '~/openApi/common/parser/sanitize'; -import { toCase } from '~/utils/to-case'; +import { toCase } from '~/utils/naming'; import type { State } from '../types/state'; diff --git a/packages/openapi-ts/src/plugins/@angular/common/config.ts b/packages/openapi-ts/src/plugins/@angular/common/config.ts index 156ba8be7..66398724a 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/config.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/config.ts @@ -26,7 +26,7 @@ export const defaultConfig: AngularCommonPlugin['Config'] = { if (!plugin.config.httpRequests.methodNameBuilder) { const { asClass } = plugin.config.httpRequests; plugin.config.httpRequests.methodNameBuilder = (operation) => - asClass ? String(operation.id) : `${String(operation.id)}Request`; + asClass ? `${operation.id}` : `${operation.id}Request`; } plugin.config.httpResources = context.valueToObject({ @@ -44,7 +44,7 @@ export const defaultConfig: AngularCommonPlugin['Config'] = { if (!plugin.config.httpResources.methodNameBuilder) { const { asClass } = plugin.config.httpResources; plugin.config.httpResources.methodNameBuilder = (operation) => - asClass ? String(operation.id) : `${String(operation.id)}Resource`; + asClass ? `${operation.id}` : `${operation.id}Resource`; } }, }; diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts b/packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts index c5fd134ac..c984384df 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts @@ -1,14 +1,11 @@ -import type { Symbol } from '@hey-api/codegen-core'; - import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; import { createOperationComment, isOperationOptionsRequired, } from '~/plugins/shared/utils/operation'; import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/to-case'; +import { applyNaming, toCase } from '~/utils/naming'; import type { AngularCommonPlugin } from './types'; @@ -20,7 +17,7 @@ interface AngularRequestClassEntry { root: boolean; } -const generateAngularClassRequests = ({ +const generateClassRequests = ({ plugin, }: { plugin: AngularCommonPlugin['Instance']; @@ -28,6 +25,20 @@ const generateAngularClassRequests = ({ const requestClasses = new Map(); const generatedClasses = new Set(); + const symbolHttpRequest = plugin.referenceSymbol({ + category: 'external', + resource: '@angular/common/http.HttpRequest', + }); + const symbolOptions = plugin.referenceSymbol({ + category: 'type', + resource: 'client-options', + tool: 'sdk', + }); + const symbolInjectable = plugin.referenceSymbol({ + category: 'external', + resource: '@angular/core.Injectable', + }); + const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); plugin.forEach( @@ -73,13 +84,35 @@ const generateAngularClassRequests = ({ return; } - const methodNode = generateAngularRequestMethod({ - isRequiredOptions, - methodName: requestMethodName, - operation, - plugin, + const symbolDataType = plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'data', + tool: 'typescript', }); + const methodNode = $.method(requestMethodName) + .public() + .$if(createOperationComment(operation), (c, v) => c.doc(v)) + .param('options', (p) => + p.required(isRequiredOptions).type( + $.type(symbolOptions) + .generic(symbolDataType ?? 'unknown') + .generic('ThrowOnError'), + ), + ) + .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) + .returns($.type(symbolHttpRequest).generic('unknown')) + .do( + $.return( + generateRequestCallExpression({ + operation, + plugin, + }), + ), + ); + if (!currentClass.nodes.length) { currentClass.nodes.push(methodNode); } else { @@ -109,12 +142,9 @@ const generateAngularClassRequests = ({ currentClass.nodes.push( $.field(toCase(childClass.className, 'camelCase')).assign( $.new( - buildName({ - config: { - case: 'preserve', - name: plugin.config.httpRequests.classNameBuilder, - }, - name: childClass.className, + applyNaming(childClass.className, { + case: 'preserve', + name: plugin.config.httpRequests.classNameBuilder, }), ), ), @@ -122,25 +152,20 @@ const generateAngularClassRequests = ({ } } - const symbolInjectable = plugin.referenceSymbol({ - category: 'external', - resource: '@angular/core.Injectable', - }); - const symbolClass = plugin.registerSymbol({ - meta: { - category: 'utility', - resource: 'class', - resourceId: currentClass.className, - tool: 'angular', - }, - name: buildName({ - config: { - case: 'preserve', - name: plugin.config.httpRequests.classNameBuilder, - }, - name: currentClass.className, + const symbolClass = plugin.symbol( + applyNaming(currentClass.className, { + case: 'preserve', + name: plugin.config.httpRequests.classNameBuilder, }), - }); + { + meta: { + category: 'utility', + resource: 'class', + resourceId: currentClass.className, + tool: 'angular', + }, + }, + ); const node = $.class(symbolClass) .export() .$if(currentClass.root, (c) => @@ -160,11 +185,21 @@ const generateAngularClassRequests = ({ } }; -const generateAngularFunctionRequests = ({ +const generateFunctionRequests = ({ plugin, }: { plugin: AngularCommonPlugin['Instance']; }) => { + const symbolHttpRequest = plugin.referenceSymbol({ + category: 'external', + resource: '@angular/common/http.HttpRequest', + }); + const symbolOptions = plugin.referenceSymbol({ + category: 'type', + resource: 'client-options', + tool: 'sdk', + }); + plugin.forEach( 'operation', ({ operation }) => { @@ -173,22 +208,50 @@ const generateAngularFunctionRequests = ({ operation, }); - const symbol = plugin.registerSymbol({ - meta: { - category: 'utility', - resource: 'operation', - resourceId: operation.id, - role: 'data', - tool: 'angular', + const symbol = plugin.symbol( + plugin.config.httpRequests.methodNameBuilder(operation), + { + meta: { + category: 'utility', + resource: 'operation', + resourceId: operation.id, + role: 'data', + tool: 'angular', + }, }, - name: plugin.config.httpRequests.methodNameBuilder(operation), - }); - const node = generateAngularRequestFunction({ - isRequiredOptions, - operation, - plugin, - symbol, + ); + + const symbolDataType = plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'data', + tool: 'typescript', }); + + const node = $.const(symbol) + .export() + .$if(createOperationComment(operation), (c, v) => c.doc(v)) + .assign( + $.func() + .param('options', (p) => + p.required(isRequiredOptions).type( + $.type(symbolOptions) + .generic(symbolDataType ?? 'unknown') + .generic('ThrowOnError'), + ), + ) + .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) + .returns($.type(symbolHttpRequest).generic('unknown')) + .do( + $.return( + generateRequestCallExpression({ + operation, + plugin, + }), + ), + ), + ); plugin.node(node); }, { @@ -224,119 +287,12 @@ const generateRequestCallExpression = ({ ); }; -const generateAngularRequestMethod = ({ - isRequiredOptions, - methodName, - operation, - plugin, -}: { - isRequiredOptions: boolean; - methodName: string; - operation: IR.OperationObject; - plugin: AngularCommonPlugin['Instance']; -}) => { - const symbolHttpRequest = plugin.referenceSymbol({ - category: 'external', - resource: '@angular/common/http.HttpRequest', - }); - - const symbolOptions = plugin.referenceSymbol({ - category: 'type', - resource: 'client-options', - tool: 'sdk', - }); - - const symbolDataType = plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'data', - tool: 'typescript', - }); - - return $.method(methodName) - .public() - .$if(createOperationComment(operation), (c, v) => c.doc(v)) - .param('options', (p) => - p.required(isRequiredOptions).type( - $.type(symbolOptions) - .generic(symbolDataType ?? 'unknown') - .generic('ThrowOnError'), - ), - ) - .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) - .returns($.type(symbolHttpRequest).generic('unknown')) - .do( - $.return( - generateRequestCallExpression({ - operation, - plugin, - }), - ), - ); -}; - -const generateAngularRequestFunction = ({ - isRequiredOptions, - operation, - plugin, - symbol, -}: { - isRequiredOptions: boolean; - operation: IR.OperationObject; - plugin: AngularCommonPlugin['Instance']; - symbol: Symbol; -}) => { - const symbolHttpRequest = plugin.referenceSymbol({ - category: 'external', - resource: '@angular/common/http.HttpRequest', - }); - - const symbolOptions = plugin.referenceSymbol({ - category: 'type', - resource: 'client-options', - tool: 'sdk', - }); - - const symbolDataType = plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'data', - tool: 'typescript', - }); - - return $.const(symbol) - .export() - .$if(createOperationComment(operation), (c, v) => c.doc(v)) - .assign( - $.func() - .param('options', (p) => - p.required(isRequiredOptions).type( - $.type(symbolOptions) - .generic(symbolDataType ?? 'unknown') - .generic('ThrowOnError'), - ), - ) - .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) - .returns($.type(symbolHttpRequest).generic('unknown')) - .do( - $.return( - generateRequestCallExpression({ - operation, - plugin, - }), - ), - ), - ); -}; - export const createHttpRequests: AngularCommonPlugin['Handler'] = ({ plugin, }) => { if (plugin.config.httpRequests.asClass) { - generateAngularClassRequests({ plugin }); + generateClassRequests({ plugin }); } else { - generateAngularFunctionRequests({ plugin }); + generateFunctionRequests({ plugin }); } }; diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpResources.ts b/packages/openapi-ts/src/plugins/@angular/common/httpResources.ts index fee0c24b0..9fe5177c6 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/httpResources.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/httpResources.ts @@ -1,14 +1,11 @@ -import type { Symbol } from '@hey-api/codegen-core'; - import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; import { createOperationComment, isOperationOptionsRequired, } from '~/plugins/shared/utils/operation'; import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/to-case'; +import { applyNaming, toCase } from '~/utils/naming'; import type { AngularCommonPlugin } from './types'; @@ -20,7 +17,7 @@ interface AngularServiceClassEntry { root: boolean; } -const generateAngularClassServices = ({ +const generateClassServices = ({ plugin, }: { plugin: AngularCommonPlugin['Instance']; @@ -28,6 +25,16 @@ const generateAngularClassServices = ({ const serviceClasses = new Map(); const generatedClasses = new Set(); + const symbolInjectable = plugin.referenceSymbol({ + category: 'external', + resource: '@angular/core.Injectable', + }); + const symbolOptions = plugin.referenceSymbol({ + category: 'type', + resource: 'client-options', + tool: 'sdk', + }); + const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); plugin.forEach( @@ -73,13 +80,39 @@ const generateAngularClassServices = ({ return; } - const methodNode = generateAngularResourceMethod({ - isRequiredOptions, - methodName: resourceMethodName, - operation, - plugin, + const symbolDataType = plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'data', + tool: 'typescript', }); + const methodNode = $.method(resourceMethodName) + .public() + .$if(createOperationComment(operation), (c, v) => c.doc(v)) + .param('options', (p) => + p.required(isRequiredOptions).type( + $.type.func().returns( + $.type.or( + $.type(symbolOptions) + .generic(symbolDataType ?? 'unknown') + .generic('ThrowOnError'), + $.type('undefined'), + ), + ), + ), + ) + .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) + .do( + $.return( + generateResourceCallExpression({ + operation, + plugin, + }), + ), + ); + if (!currentClass.nodes.length) { currentClass.nodes.push(methodNode); } else { @@ -109,12 +142,9 @@ const generateAngularClassServices = ({ currentClass.nodes.push( $.field(toCase(childClass.className, 'camelCase')).assign( $.new( - buildName({ - config: { - case: 'preserve', - name: plugin.config.httpResources.classNameBuilder, - }, - name: childClass.className, + applyNaming(childClass.className, { + case: 'preserve', + name: plugin.config.httpResources.classNameBuilder, }), ), ), @@ -122,19 +152,12 @@ const generateAngularClassServices = ({ } } - const symbolInjectable = plugin.referenceSymbol({ - category: 'external', - resource: '@angular/core.Injectable', - }); - const symbolClass = plugin.registerSymbol({ - name: buildName({ - config: { - case: 'preserve', - name: plugin.config.httpResources.classNameBuilder, - }, - name: currentClass.className, + const symbolClass = plugin.symbol( + applyNaming(currentClass.className, { + case: 'preserve', + name: plugin.config.httpResources.classNameBuilder, }), - }); + ); const node = $.class(symbolClass) .export() .$if(currentClass.root, (c) => @@ -154,11 +177,17 @@ const generateAngularClassServices = ({ } }; -const generateAngularFunctionServices = ({ +const generateFunctionServices = ({ plugin, }: { plugin: AngularCommonPlugin['Instance']; }) => { + const symbolOptions = plugin.referenceSymbol({ + category: 'type', + resource: 'client-options', + tool: 'sdk', + }); + plugin.forEach( 'operation', ({ operation }) => { @@ -167,15 +196,45 @@ const generateAngularFunctionServices = ({ operation, }); - const symbol = plugin.registerSymbol({ - name: plugin.config.httpResources.methodNameBuilder(operation), - }); - const node = generateAngularResourceFunction({ - isRequiredOptions, - operation, - plugin, - symbol, + const symbol = plugin.symbol( + plugin.config.httpResources.methodNameBuilder(operation), + ); + + const symbolDataType = plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'data', + tool: 'typescript', }); + + const node = $.const(symbol) + .export() + .$if(createOperationComment(operation), (c, v) => c.doc(v)) + .assign( + $.func() + .param('options', (p) => + p.required(isRequiredOptions).type( + $.type.func().returns( + $.type.or( + $.type(symbolOptions) + .generic(symbolDataType ?? 'unknown') + .generic('ThrowOnError'), + $.type('undefined'), + ), + ), + ), + ) + .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) + .do( + $.return( + generateResourceCallExpression({ + operation, + plugin, + }), + ), + ), + ); plugin.node(node); }, { @@ -197,6 +256,10 @@ const generateResourceCallExpression = ({ category: 'external', resource: '@angular/common/http.httpResource', }); + const symbolInject = plugin.referenceSymbol({ + category: 'external', + resource: '@angular/core.inject', + }); const symbolResponseType = plugin.querySymbol({ category: 'type', @@ -221,10 +284,6 @@ const generateResourceCallExpression = ({ }); // Build the method access path using inject - const symbolInject = plugin.referenceSymbol({ - category: 'external', - resource: '@angular/core.inject', - }); let methodAccess: ReturnType = $(symbolInject).call(symbolClass); @@ -292,117 +351,12 @@ const generateResourceCallExpression = ({ ); }; -const generateAngularResourceMethod = ({ - isRequiredOptions, - methodName, - operation, - plugin, -}: { - isRequiredOptions: boolean; - methodName: string; - operation: IR.OperationObject; - plugin: AngularCommonPlugin['Instance']; -}) => { - const symbolOptions = plugin.referenceSymbol({ - category: 'type', - resource: 'client-options', - tool: 'sdk', - }); - - const symbolDataType = plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'data', - tool: 'typescript', - }); - - return $.method(methodName) - .public() - .$if(createOperationComment(operation), (c, v) => c.doc(v)) - .param('options', (p) => - p.required(isRequiredOptions).type( - $.type.func().returns( - $.type.or( - $.type(symbolOptions) - .generic(symbolDataType ?? 'unknown') - .generic('ThrowOnError'), - $.type('undefined'), - ), - ), - ), - ) - .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) - .do( - $.return( - generateResourceCallExpression({ - operation, - plugin, - }), - ), - ); -}; - -const generateAngularResourceFunction = ({ - isRequiredOptions, - operation, - plugin, - symbol, -}: { - isRequiredOptions: boolean; - operation: IR.OperationObject; - plugin: AngularCommonPlugin['Instance']; - symbol: Symbol; -}) => { - const symbolOptions = plugin.referenceSymbol({ - category: 'type', - resource: 'client-options', - tool: 'sdk', - }); - - const symbolDataType = plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'data', - tool: 'typescript', - }); - - return $.const(symbol) - .export() - .$if(createOperationComment(operation), (c, v) => c.doc(v)) - .assign( - $.func() - .param('options', (p) => - p.required(isRequiredOptions).type( - $.type.func().returns( - $.type.or( - $.type(symbolOptions) - .generic(symbolDataType ?? 'unknown') - .generic('ThrowOnError'), - $.type('undefined'), - ), - ), - ), - ) - .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) - .do( - $.return( - generateResourceCallExpression({ - operation, - plugin, - }), - ), - ), - ); -}; - export const createHttpResources: AngularCommonPlugin['Handler'] = ({ plugin, }) => { if (plugin.config.httpResources.asClass) { - generateAngularClassServices({ plugin }); + generateClassServices({ plugin }); } else { - generateAngularFunctionServices({ plugin }); + generateFunctionServices({ plugin }); } }; diff --git a/packages/openapi-ts/src/plugins/@angular/common/plugin.ts b/packages/openapi-ts/src/plugins/@angular/common/plugin.ts index d898110db..d9a4f3cfd 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/plugin.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/plugin.ts @@ -3,38 +3,34 @@ import { createHttpResources } from './httpResources'; import type { AngularCommonPlugin } from './types'; export const handler: AngularCommonPlugin['Handler'] = ({ plugin }) => { - plugin.registerSymbol({ + plugin.symbol('HttpRequest', { external: '@angular/common/http', kind: 'type', meta: { category: 'external', resource: '@angular/common/http.HttpRequest', }, - name: 'HttpRequest', }); - plugin.registerSymbol({ + plugin.symbol('inject', { external: '@angular/core', meta: { category: 'external', resource: '@angular/core.inject', }, - name: 'inject', }); - plugin.registerSymbol({ + plugin.symbol('Injectable', { external: '@angular/core', meta: { category: 'external', resource: '@angular/core.Injectable', }, - name: 'Injectable', }); - plugin.registerSymbol({ + plugin.symbol('httpResource', { external: '@angular/common/http', meta: { category: 'external', resource: '@angular/common/http.httpResource', }, - name: 'httpResource', }); if (plugin.config.httpRequests.enabled) { diff --git a/packages/openapi-ts/src/plugins/@angular/common/types.d.ts b/packages/openapi-ts/src/plugins/@angular/common/types.d.ts index 7518441bc..d304523aa 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/types.d.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/types.d.ts @@ -1,5 +1,5 @@ import type { DefinePlugin, Plugin } from '~/plugins'; -import type { StringName } from '~/types/case'; +import type { NameTransformer } from '~/utils/naming'; export type UserConfig = Plugin.Name<'@angular/common'> & Plugin.Hooks & { @@ -28,7 +28,7 @@ export type UserConfig = Plugin.Name<'@angular/common'> & * Builds the class name for the generated resource. * By default, the class name is suffixed with "Resources". */ - classNameBuilder?: StringName; + classNameBuilder?: NameTransformer; /** * Whether or not to create HTTP Request instances. * @@ -59,7 +59,7 @@ export type UserConfig = Plugin.Name<'@angular/common'> & * Builds the class name for the generated resource. * By default, the class name is suffixed with "Resources". */ - classNameBuilder?: StringName; + classNameBuilder?: NameTransformer; /** * Whether or not to create HTTP resource APIs. * @@ -98,7 +98,7 @@ export type Config = Plugin.Name<'@angular/common'> & * Builds the class name for the generated resource. * By default, the class name is suffixed with "Resources". */ - classNameBuilder: StringName; + classNameBuilder: NameTransformer; /** * Whether or not to create HTTP Request instances. * @@ -125,7 +125,7 @@ export type Config = Plugin.Name<'@angular/common'> & * Builds the class name for the generated resource. * By default, the class name is suffixed with "Resources". */ - classNameBuilder: StringName; + classNameBuilder: NameTransformer; /** * Whether or not to create HTTP resource APIs. * diff --git a/packages/openapi-ts/src/plugins/@hey-api/client-core/client.ts b/packages/openapi-ts/src/plugins/@hey-api/client-core/client.ts index 56f5275ca..c45982551 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/client-core/client.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/client-core/client.ts @@ -29,13 +29,11 @@ const resolveBaseUrlString = ({ export const createClient: PluginHandler = ({ plugin }) => { const clientModule = clientFolderAbsolutePath(plugin.context.config); - const symbolCreateClient = plugin.registerSymbol({ + const symbolCreateClient = plugin.symbol('createClient', { external: clientModule, - name: 'createClient', }); - const symbolCreateConfig = plugin.registerSymbol({ + const symbolCreateConfig = plugin.symbol('createConfig', { external: clientModule, - name: 'createConfig', }); const symbolClientOptions = plugin.referenceSymbol({ category: 'type', @@ -45,9 +43,8 @@ export const createClient: PluginHandler = ({ plugin }) => { const { runtimeConfigPath } = plugin.config; const symbolCreateClientConfig = runtimeConfigPath - ? plugin.registerSymbol({ + ? plugin.symbol('createClientConfig', { external: runtimeConfigPath, - name: 'createClientConfig', }) : undefined; @@ -84,11 +81,10 @@ export const createClient: PluginHandler = ({ plugin }) => { .generic(symbolClientOptions), ]; - const symbolClient = plugin.registerSymbol({ + const symbolClient = plugin.symbol('client', { meta: { category: 'client', }, - name: 'client', }); const statement = $.const(symbolClient) .export() diff --git a/packages/openapi-ts/src/plugins/@hey-api/client-core/createClientConfig.ts b/packages/openapi-ts/src/plugins/@hey-api/client-core/createClientConfig.ts index a491ac634..eb1b417ca 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/client-core/createClientConfig.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/client-core/createClientConfig.ts @@ -12,19 +12,15 @@ export const createClientConfigType = ({ resource: 'client', role: 'options', }); - const symbolConfig = plugin.registerSymbol({ + const symbolConfig = plugin.symbol('Config', { external: clientModule, kind: 'type', - name: 'Config', }); - const symbolDefaultClientOptions = plugin.registerSymbol({ + const symbolDefaultClientOptions = plugin.symbol('ClientOptions', { external: clientModule, kind: 'type', - name: 'ClientOptions', - }); - const symbolCreateClientConfig = plugin.registerSymbol({ - name: 'CreateClientConfig', }); + const symbolCreateClientConfig = plugin.symbol('CreateClientConfig'); const typeCreateClientConfig = $.type .alias(symbolCreateClientConfig) diff --git a/packages/openapi-ts/src/plugins/@hey-api/schemas/plugin.ts b/packages/openapi-ts/src/plugins/@hey-api/schemas/plugin.ts index ffa63da1f..a7867b62c 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/schemas/plugin.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/schemas/plugin.ts @@ -367,14 +367,13 @@ const schemasV2_0_X = ({ for (const name in context.spec.definitions) { const schema = context.spec.definitions[name]!; - const symbol = plugin.registerSymbol({ + const symbol = plugin.symbol(schemaName({ name, plugin, schema }), { meta: { category: 'schema', resource: 'definition', resourceId: name, tool: 'json-schema', }, - name: schemaName({ name, plugin, schema }), }); const obj = schemaToJsonSchemaDraft_04({ context, @@ -407,14 +406,13 @@ const schemasV3_0_X = ({ for (const name in context.spec.components.schemas) { const schema = context.spec.components.schemas[name]!; - const symbol = plugin.registerSymbol({ + const symbol = plugin.symbol(schemaName({ name, plugin, schema }), { meta: { category: 'schema', resource: 'definition', resourceId: name, tool: 'json-schema', }, - name: schemaName({ name, plugin, schema }), }); const obj = schemaToJsonSchemaDraft_05({ context, @@ -447,14 +445,13 @@ const schemasV3_1_X = ({ for (const name in context.spec.components.schemas) { const schema = context.spec.components.schemas[name]!; - const symbol = plugin.registerSymbol({ + const symbol = plugin.symbol(schemaName({ name, plugin, schema }), { meta: { category: 'schema', resource: 'definition', resourceId: name, tool: 'json-schema', }, - name: schemaName({ name, plugin, schema }), }); const obj = schemaToJsonSchema2020_12({ context, diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts index aa5dc94ab..67a7b8df2 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts @@ -1,24 +1,28 @@ import { definePluginConfig } from '~/plugins/shared/utils/config'; import { handler } from './plugin'; +import { resolveStructure } from './structure'; import type { HeyApiSdkPlugin } from './types'; export const defaultConfig: HeyApiSdkPlugin['Config'] = { config: { - asClass: false, auth: true, - classNameBuilder: '{{name}}', - classStructure: 'auto', client: true, exportFromIndex: true, - instance: '', - methodNameBuilder: '{{name}}', - operationId: true, paramsStructure: 'grouped', - response: 'body', responseStyle: 'fields', transformer: false, validator: false, + + // Deprecated - kept for backward compatibility + // eslint-disable-next-line sort-keys-fix/sort-keys-fix + asClass: false, + classNameBuilder: '{{name}}', + classStructure: 'auto', + instance: '', + methodNameBuilder: '{{name}}', + operationId: true, + response: 'body', }, dependencies: ['@hey-api/typescript'], handler, @@ -73,22 +77,7 @@ export const defaultConfig: HeyApiSdkPlugin['Config'] = { plugin.config.validator.response = false; } - if (plugin.config.instance) { - if (typeof plugin.config.instance !== 'string') { - plugin.config.instance = 'Sdk'; - } - - plugin.config.asClass = true; - } else { - plugin.config.instance = ''; - } - - // Set default classNameBuilder based on client type - if (plugin.config.classNameBuilder === '{{name}}') { - if (plugin.config.client === '@hey-api/client-angular') { - plugin.config.classNameBuilder = '{{name}}Service'; - } - } + plugin.config.structure = resolveStructure(plugin.config, context); }, }; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts deleted file mode 100644 index 07fd57d3a..000000000 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/resource.ts +++ /dev/null @@ -1,452 +0,0 @@ -import type { Symbol } from '@hey-api/codegen-core'; - -import type { IR } from '~/ir/types'; -import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; -import { - createOperationComment, - isOperationOptionsRequired, -} from '~/plugins/shared/utils/operation'; -import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/to-case'; - -import { createClientClass, createRegistryClass } from '../shared/class'; -import { nuxtTypeComposable, nuxtTypeDefault } from '../shared/constants'; -import { - operationClassName, - operationMethodName, - operationParameters, - operationStatements, -} from '../shared/operation'; -import type { HeyApiSdkPlugin } from '../types'; - -export type Event = { - operation: IR.OperationObject; - path: ReadonlyArray; - tags: ReadonlyArray | undefined; -}; - -/** - * Represents a resource layer in the SDK hierarchy. - * - * Resources can be nested (via children) and contain operations (methods). - */ -export class SdkResourceModel { - /** Nested resources within this resource. */ - children: Map = new Map(); - /** The name of this resource (e.g., "Users", "Accounts"). */ - name: string; - /** Operations that will become methods in this resource. */ - operations: Array = []; - /** Parent resource in the hierarchy. Undefined if this is the root resource. */ - parent?: SdkResourceModel; - - constructor(name: string, parent?: SdkResourceModel) { - this.name = name; - this.parent = parent; - } - - get isRoot(): boolean { - return !this.parent; - } - - /** - * Gets or creates a child resource. - * - * If the child doesn't exist, it's created automatically. - * - * @param name - The name of the child resource - * @returns The child resource instance - */ - child(name: string): SdkResourceModel { - if (!this.children.has(name)) { - this.children.set(name, new SdkResourceModel(name, this)); - } - return this.children.get(name)!; - } - - /** - * Gets the full path of this resource in the hierarchy. - * - * @returns An array of resource names from the root to this resource - */ - getPath(): ReadonlyArray { - const path: Array = []; - // eslint-disable-next-line @typescript-eslint/no-this-alias - let cursor: SdkResourceModel | undefined = this; - while (cursor) { - path.unshift(cursor.name); - cursor = cursor.parent; - } - return path; - } - - /** - * Inserts an operation event into the resource tree. - * - * Parses the operation ID and creates the resource hierarchy. - */ - insert(event: Event, plugin: HeyApiSdkPlugin['Instance']): void { - const { operation } = event; - const classSegments = - this.name && - plugin.config.classStructure === 'auto' && - operation.operationId - ? this.splitOperationId(operation.operationId).slice(0, -1) - : []; - - // eslint-disable-next-line @typescript-eslint/no-this-alias - let cursor: SdkResourceModel = this; - for (const segment of classSegments) { - cursor = cursor.child(segment); - } - - cursor.operations.push(event); - } - - /** - * Converts this class group to a class node. - */ - toNode(plugin: HeyApiSdkPlugin['Instance']): { - dependencies: Array>; - nodes: ReadonlyArray>; - } { - const dependencies: Array> = []; - const nodes: Array> = []; - - const client = getClientPlugin(plugin.context.config); - const isAngularClient = client.name === '@hey-api/client-angular'; - - if (this.name) { - const { node, symbol: symbolClass } = this.classToNode(plugin); - - if (this.isRoot && plugin.config.instance) { - this.enrichRootClass({ - dependencies, - node, - plugin, - symbol: symbolClass, - }); - } - - this.operations.forEach((event, index) => { - const { operation } = event; - if (index > 0 || node.hasBody) node.newline(); - node.do( - this.implementFn({ - node: $.method(this.createFnSymbol(plugin, event), (m) => - this.attachComment({ - node: m, - operation, - }) - .public() - .static(!isAngularClient && !plugin.config.instance), - ), - operation, - plugin, - }), - ); - }); - - for (const child of this.children.values()) { - if (node.hasBody) node.newline(); - node.do(...this.childToNode(child, plugin)); - } - - nodes.push(node); - } else { - this.operations.forEach((event) => { - const { operation } = event; - let node = $.const(this.createFnSymbol(plugin, event)) - .export() - .assign( - this.implementFn({ - node: $.func(), - operation, - plugin, - }), - ); - node = this.attachComment({ node, operation }); - nodes.push(node); - }); - } - - return { dependencies, nodes }; - } - - /** - * Recursively walks the tree depth-first. - * - * Yields this node, then all descendants. - */ - *walk(): Generator { - for (const child of this.children.values()) { - yield* child.walk(); - } - yield this; - } - - private attachComment< - T extends ReturnType, - >(args: { node: T; operation: IR.OperationObject }): T { - const { node, operation } = args; - return node.$if(createOperationComment(operation), (m, v) => m.doc(v)) as T; - } - - private createFnSymbol( - plugin: HeyApiSdkPlugin['Instance'], - event: Event, - ): Symbol { - const { operation, path, tags } = event; - const extractFromOperationId = - this.name && plugin.config.classStructure === 'auto'; - return plugin.symbol( - operationMethodName({ - operation, - plugin, - value: - extractFromOperationId && operation.operationId - ? toCase( - this.splitOperationId(operation.operationId).pop()!, - 'camelCase', - ) - : operation.id, - }), - { - meta: { - category: 'sdk', - path, - resource: 'operation', - resourceId: operation.id, - tags, - tool: 'sdk', - }, - }, - ); - } - - private childToNode( - resource: SdkResourceModel, - plugin: HeyApiSdkPlugin['Instance'], - ): ReadonlyArray> { - const refChild = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: resource.getPath().join('.'), - tool: 'sdk', - }); - const memberNameStr = toCase(refChild.name, 'camelCase'); - const memberName = plugin.symbol(memberNameStr); - if (plugin.config.instance) { - const privateName = plugin.symbol(`_${memberNameStr}`); - return [ - $.field(privateName, (f) => f.private().optional().type(refChild)), - $.getter(memberName, (g) => - g.returns(refChild).do( - $('this') - .attr(privateName) - .nullishAssign( - $.new(refChild).args( - $.object().prop('client', $('this').attr('client')), - ), - ) - .return(), - ), - ), - ]; - } - if (plugin.isSymbolRegistered(refChild.id)) { - return [$.field(memberName, (f) => f.static().assign($(refChild)))]; - } - return [ - $.getter(memberName, (g) => g.public().static().do($.return(refChild))), - ]; - } - - private classToNode(plugin: HeyApiSdkPlugin['Instance']): { - node: ReturnType; - symbol: Symbol; - } { - const client = getClientPlugin(plugin.context.config); - const isAngularClient = client.name === '@hey-api/client-angular'; - const symbol = plugin.symbol( - operationClassName({ plugin, value: this.name }), - { - meta: { - category: 'utility', - resource: 'class', - resourceId: this.getPath().join('.'), - tool: 'sdk', - }, - }, - ); - const node = $.class(symbol) - .export() - .$if(plugin.config.instance, (c) => - c.extends( - plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: 'HeyApiClient', - tool: 'sdk', - }), - ), - ) - .$if(isAngularClient && this.isRoot, (c) => - c.decorator( - plugin.referenceSymbol({ - category: 'external', - resource: '@angular/core.Injectable', - }), - $.object().prop('providedIn', $.literal('root')), - ), - ); - return { node, symbol }; - } - - private enrichRootClass(args: { - dependencies: Array>; - node: ReturnType; - plugin: HeyApiSdkPlugin['Instance']; - symbol: Symbol; - }): void { - const { dependencies, node, plugin, symbol } = args; - const symbolClient = plugin.symbol('HeyApiClient', { - meta: { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiClient', - tool: 'sdk', - }, - }); - dependencies.push(createClientClass({ plugin, symbol: symbolClient })); - const symbolRegistry = plugin.symbol('HeyApiRegistry', { - meta: { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiRegistry', - tool: 'sdk', - }, - }); - dependencies.push( - createRegistryClass({ - plugin, - sdkSymbol: symbol, - symbol: symbolRegistry, - }), - ); - const isClientRequired = - !plugin.config.client || !plugin.getSymbol({ category: 'client' }); - const registry = plugin.symbol('__registry'); - node.toAccessNode = (node, options) => { - if (options.context) return; - return $(node.name).attr(registry).attr('get').call(); - }; - node.do( - $.field(registry, (f) => - f - .public() - .static() - .readonly() - .assign($.new(symbolRegistry).generic(symbol)), - ), - $.newline(), - $.init((i) => - i - .param('args', (p) => - p.required(isClientRequired).type( - $.type - .object() - .prop('client', (p) => - p.required(isClientRequired).type( - plugin.referenceSymbol({ - category: 'external', - resource: 'client.Client', - }), - ), - ) - .prop('key', (p) => p.optional().type('string')), - ), - ) - .do( - $('super').call('args'), - $(symbol) - .attr(registry) - .attr('set') - .call('this', $('args').attr('key').required(isClientRequired)), - ), - ), - ); - } - - private implementFn< - T extends ReturnType, - >(args: { - node: T; - operation: IR.OperationObject; - plugin: HeyApiSdkPlugin['Instance']; - }): T { - const { node, operation, plugin } = args; - const client = getClientPlugin(plugin.context.config); - const isNuxtClient = client.name === '@hey-api/client-nuxt'; - const isRequiredOptions = isOperationOptionsRequired({ - context: plugin.context, - operation, - }); - const opParameters = operationParameters({ - isRequiredOptions, - operation, - plugin, - }); - const statements = operationStatements({ - isRequiredOptions, - opParameters, - operation, - plugin, - }); - return node - .$if( - isNuxtClient, - (m) => - m - .generic(nuxtTypeComposable, (t) => - t - .extends( - plugin.referenceSymbol({ - category: 'external', - resource: 'client.Composable', - }), - ) - .default($.type.literal('$fetch')), - ) - .generic(nuxtTypeDefault, (t) => - t.$if( - plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'response', - }), - (t, s) => t.extends(s).default(s), - (t) => t.default('undefined'), - ), - ), - (m) => - m.generic('ThrowOnError', (t) => - t - .extends('boolean') - .default( - ('throwOnError' in client.config - ? client.config.throwOnError - : false) ?? false, - ), - ), - ) - .params(...opParameters.parameters) - .do(...statements) as T; - } - - private splitOperationId(operationId: string): Array { - // TODO: expose this logic - return operationId.split(/[./]/).filter(Boolean); - } -} diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts deleted file mode 100644 index 91b7553b8..000000000 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/model/structure.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { HeyApiSdkPlugin } from '../types'; -import type { Event } from './resource'; -import { SdkResourceModel } from './resource'; - -export class SdkStructureModel { - /** If true, generates a flat SDK without resource hierarchy. */ - private _flat: boolean; - /** Name of the SDK. If empty, we fallback to operation tags. */ - private _name: string; - /** Root resources mapped by their names. */ - private _roots: Map = new Map(); - - constructor( - name: string, - options?: { - /** If true, generates a flat SDK without resource hierarchy. */ - flat?: boolean; - }, - ) { - this._flat = options?.flat ?? false; - this._name = name; - } - - /** - * Inserts an operation event into the structure. - * - * Parses the operation ID and organizes it into classes based on tags. - */ - insert(event: Event, plugin: HeyApiSdkPlugin['Instance']): void { - const { operation } = event; - const roots = this._name - ? [this._name] - : this._flat - ? [''] - : operation.tags && operation.tags.length > 0 - ? operation.tags - : ['default']; - - for (const name of roots) { - const resource = this.root(name); - resource.insert(event, plugin); - } - } - - /** - * Gets or creates a root resource by name. - * - * If the root doesn't exist, it's created automatically. - * - * @param name - The name of the root resource - * @returns The root resource instance - */ - root(name: string): SdkResourceModel { - if (!this._roots.has(name)) { - this._roots.set(name, new SdkResourceModel(name)); - } - return this._roots.get(name)!; - } - - /** - * Recursively walks the structure. - * - * Yields all resources in the structure. - */ - *walk(): Generator { - for (const resource of this._roots.values()) { - yield* resource.walk(); - } - } -} diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts index b8c80e4aa..9e2ba9692 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts @@ -6,7 +6,7 @@ import type { IR } from '~/ir/types'; import { sanitizeNamespaceIdentifier } from '~/openApi/common/parser/sanitize'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/to-case'; +import { toCase } from '~/utils/naming'; import type { Field, Fields } from '../../client-core/bundle/params'; import type { HeyApiSdkPlugin } from '../types'; @@ -30,6 +30,9 @@ interface ClassNameEntry { path: ReadonlyArray; } +/** + * @deprecated + */ export const operationClassName = ({ plugin, value, @@ -46,6 +49,9 @@ export const operationClassName = ({ ); }; +/** + * @deprecated + */ export const operationMethodName = ({ operation, plugin, @@ -60,7 +66,8 @@ export const operationMethodName = ({ return ( (typeof plugin.config.methodNameBuilder === 'string' ? plugin.config.methodNameBuilder.replace('{{name}}', name) - : plugin.config.methodNameBuilder?.(name, operation)) || name + : // @ts-expect-error TODO: remove + plugin.config.methodNameBuilder?.(name, operation)) || name ); }; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/signature.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/signature.ts index bf11fc7b7..16eb2c65d 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/signature.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/signature.ts @@ -1,7 +1,7 @@ import type { IR } from '~/ir/types'; import type { PluginInstance } from '~/plugins/shared/utils/instance'; +import { toCase } from '~/utils/naming'; import { refToName } from '~/utils/ref'; -import { toCase } from '~/utils/to-case'; import type { Field } from '../../client-core/bundle/params'; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts index 1c5c6697f..e739545c1 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts @@ -14,12 +14,11 @@ export const createTypeOptions = ({ const client = getClientPlugin(plugin.context.config); const isNuxtClient = client.name === '@hey-api/client-nuxt'; - const symbolTDataShape = plugin.registerSymbol({ + const symbolTDataShape = plugin.symbol('TDataShape', { external: clientModule, kind: 'type', - name: 'TDataShape', }); - const symbolClient = plugin.registerSymbol({ + const symbolClient = plugin.symbol('Client', { external: clientModule, kind: 'type', meta: { @@ -27,20 +26,17 @@ export const createTypeOptions = ({ resource: 'client.Client', tool: client.name, }, - name: 'Client', }); - const symbolClientOptions = plugin.registerSymbol({ + const symbolClientOptions = plugin.symbol('Options', { external: clientModule, kind: 'type', - name: 'Options', }); - const symbolOptions = plugin.registerSymbol({ + const symbolOptions = plugin.symbol('Options', { meta: { category: 'type', resource: 'client-options', tool: 'sdk', }, - name: 'Options', }); const typeOptions = $.type diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/config.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/config.ts new file mode 100644 index 000000000..0cb13d707 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/config.ts @@ -0,0 +1,202 @@ +import type { PluginContext } from '~/plugins/types'; +import type { NamingConfig, NamingRule } from '~/utils/naming'; +import { resolveNaming } from '~/utils/naming'; + +import type { UserConfig } from '../types'; +import type { + StructureConfig, + StructureStrategy, + UserStructureConfig, +} from './types'; + +type Config = Omit; + +// container: 'class', +// containerName: {}, +// defaultTag: 'default', +// delimiters: /[./]/, +// methodName: {}, +// methods: 'instance', +// nesting: 'operationId', +// segmentName: {}, +// strategy: 'flat', + +export function resolveStructure( + config: Config, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _context: PluginContext, +): StructureConfig { + // if (plugin.config.instance) { + // if (typeof plugin.config.instance !== 'string') { + // plugin.config.instance = 'Sdk'; + // } + + // plugin.config.asClass = true; + // } else { + // plugin.config.instance = ''; + // } + + // // Set default classNameBuilder based on client type + // if (plugin.config.classNameBuilder === '{{name}}') { + // if (plugin.config.client === '@hey-api/client-angular') { + // plugin.config.classNameBuilder = '{{name}}Service'; + // } + // } + + // Check for deprecated options and warn + if (config.asClass !== undefined) { + console.warn( + '`asClass` is deprecated. Use `grouping: "byTags"` or `grouping: "single"` instead.', + ); + } + + if (config.instance !== undefined) { + console.warn( + '`instance` is deprecated. Use `grouping: { strategy: "single", containerName: "Name", methods: "instance" }` instead.', + ); + } + + if (config.classStructure !== undefined) { + console.warn( + '`classStructure` is deprecated. Use `grouping: { nesting: "operationId" }` or `grouping: { nesting: "id" }` instead.', + ); + } + + if (config.classNameBuilder !== undefined) { + console.warn( + '`classNameBuilder` is deprecated. Use `grouping.containerName` instead.', + ); + } + + if (config.methodNameBuilder !== undefined) { + console.warn( + '`methodNameBuilder` is deprecated. Use `grouping.methodName` instead.', + ); + } + + if (config.operationId !== undefined) { + console.warn( + '`operationId` is deprecated. Use `grouping: { nesting: "operationId" }` or `grouping: { nesting: "id" }` instead.', + ); + } + + // If new grouping config is provided, use it + if (config.structure !== undefined) { + return normalizeStructureConfig(config.structure); + } + + // Otherwise, map legacy config to new grouping config + return mapLegacyToGrouping(config); +} + +function normalizeStructureConfig( + input: StructureStrategy | UserStructureConfig, +): StructureConfig { + // String shorthand + if (typeof input === 'string') { + return { + container: 'class', + containerName: input === 'single' ? { name: 'Sdk' } : {}, + defaultTag: 'default', + delimiters: /[./]/, + methodName: {}, + methods: 'instance', + nesting: 'operationId', + segmentName: {}, + strategy: input, + }; + } + + // Custom function + if (typeof input === 'function') { + return { + container: 'class', + containerName: {}, + defaultTag: 'default', + delimiters: /[./]/, + methodName: {}, + methods: 'instance', + nesting: 'operationId', + segmentName: {}, + strategy: input, + }; + } + + // Full config object + const strategy = input.strategy ?? 'flat'; + + return { + container: input.container ?? 'class', + containerName: resolveContainerName(input.containerName, strategy), + defaultTag: input.defaultTag ?? 'default', + delimiters: input.delimiters ?? /[./]/, + methodName: resolveNaming(input.methodName), + methods: input.methods ?? 'instance', + nesting: input.nesting ?? 'operationId', + segmentName: resolveNaming(input.segmentName), + strategy, + }; +} + +function resolveContainerName( + input: NamingRule | undefined, + strategy: StructureStrategy, +): NamingConfig { + const resolved = resolveNaming(input); + + // Default name for 'single' strategy + if (strategy === 'single' && !resolved.name) { + resolved.name = 'Sdk'; + } + + return resolved; +} + +function mapLegacyToGrouping(config: Config): StructureConfig { + // Determine strategy from legacy options + let strategy: StructureStrategy = 'flat'; + + if (config.asClass) { + strategy = config.instance ? 'single' : 'byTags'; + } + + // Determine container name + let containerName: NamingConfig = {}; + + if (config.instance && typeof config.instance === 'string') { + containerName = { name: config.instance }; + } else if (config.classNameBuilder) { + containerName = resolveNaming(config.classNameBuilder); + } + + if (strategy === 'single' && !containerName.name) { + containerName.name = 'Sdk'; + } + + // Determine method name + const methodName: NamingConfig = config.methodNameBuilder + ? resolveNaming(config.methodNameBuilder) + : {}; + + // Determine nesting + let nesting: 'operationId' | 'id' = 'operationId'; + + if (config.classStructure === 'off' || config.operationId === false) { + nesting = 'id'; + } + + // Determine methods style + const methods = config.instance ? 'instance' : 'static'; + + return { + container: 'class', + containerName, + defaultTag: 'default', + delimiters: /[./]/, + methodName, + methods, + nesting, + segmentName: {}, + strategy, + }; +} diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/index.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/index.ts new file mode 100644 index 000000000..735fbf6b8 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/index.ts @@ -0,0 +1,6 @@ +export { resolveStructure } from './config'; +export type { + StructureConfig, + StructureStrategy, + UserStructureConfig, +} from './types'; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/types.d.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/types.d.ts new file mode 100644 index 000000000..025d7bcd6 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/types.d.ts @@ -0,0 +1,195 @@ +import type { IR } from '~/ir/types'; +import type { OperationPathStrategy } from '~/openApi/shared/locations'; +import type { NamingConfig, NamingRule } from '~/utils/naming'; + +type CustomStructureStrategy = ( + operation: IR.OperationObject, +) => ReadonlyArray>; + +export type StructureStrategy = + | 'byTags' + | 'flat' + | 'single' + | CustomStructureStrategy; + +export interface UserStructureConfig { + /** + * Type of container for grouped operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'class'` - Class with methods + * - `'object'` - Plain object literal + * + * @default 'class' + */ + container?: 'class' | 'object'; + /** + * Customize container names (class or object variable names). + * + * For `'single'` strategy, this sets the root container name. + * For `'byTags'` strategy, this transforms tag names. + * + * @default 'Sdk' for `'single'` strategy + * + * @example + * // Set root name for single strategy + * containerName: 'MyApi' + * + * @example + * // Transform tag names with suffix + * containerName: '{{name}}Service' + * + * @example + * // With casing + * containerName: { name: '{{name}}Service', case: 'PascalCase' } + */ + containerName?: NamingRule; + /** + * Default container name for operations without tags. + * + * Only applies when `strategy` is `'byTags'`. + * + * @default 'default' + */ + defaultTag?: string; + /** + * Delimiters for splitting operationId. + * + * Only applies when `nesting` is `'operationId'`. + * + * @default /[./]/ + */ + delimiters?: RegExp; + /** + * Customize method/function names. + * + * Applied to the final segment of the path (the method name). + */ + methodName?: NamingRule; + /** + * How methods are attached to class containers. + * + * Only applies when `container` is `'class'`. + * + * - `'static'` - Static methods, no instantiation required + * - `'instance'` - Instance methods, requires `new ClassName(config)` + * + * @default 'instance' + */ + methods?: 'instance' | 'static'; + /** + * How to derive nesting structure from operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'operationId'` - Split operationId by delimiters (e.g., `users.list` → `Users.list()`) + * - `'id'` - Use operation id as-is, no nesting + * - Custom function for full control + * + * @default 'operationId' + */ + nesting?: 'operationId' | 'id' | OperationPathStrategy; + /** + * Customize nesting segment names. + * + * Applied to intermediate path segments (not the method name). + */ + segmentName?: NamingRule; + /** + * Grouping strategy. + * + * - `'flat'` - Standalone functions, no grouping + * - `'byTags'` - One container per operation tag + * - `'single'` - All operations in one container + * - Custom function for full control + * + * @default 'flat' + */ + strategy?: StructureStrategy; +} + +export interface StructureConfig { + /** + * Type of container for grouped operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'class'` - Class with methods + * - `'object'` - Plain object literal + */ + container: 'class' | 'object'; + /** + * Customize container names (class or object variable names). + * + * For `'single'` strategy, this sets the root container name. + * For `'byTags'` strategy, this transforms tag names. + * + * @default 'Sdk' for `'single'` strategy + * + * @example + * // Set root name for single strategy + * containerName: 'MyApi' + * + * @example + * // Transform tag names with suffix + * containerName: '{{name}}Service' + * + * @example + * // With casing + * containerName: { name: '{{name}}Service', case: 'PascalCase' } + */ + containerName: NamingConfig; + /** + * Default container name for operations without tags. + * + * Only applies when `strategy` is `'byTags'`. + */ + defaultTag: string; + /** + * Delimiters for splitting operationId. + * + * Only applies when `nesting` is `'operationId'`. + */ + delimiters: RegExp; + /** + * Customize method/function names. + * + * Applied to the final segment of the path (the method name). + */ + methodName: NamingConfig; + /** + * How methods are attached to class containers. + * + * Only applies when `container` is `'class'`. + * + * - `'static'` - Static methods, no instantiation required + * - `'instance'` - Instance methods, requires `new ClassName(config)` + */ + methods: 'instance' | 'static'; + /** + * How to derive nesting structure from operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'operationId'` - Split operationId by delimiters (e.g., `users.list` → `Users.list()`) + * - `'id'` - Use operation id as-is, no nesting + * - Custom function for full control + */ + nesting: 'operationId' | 'id' | OperationPathStrategy; + /** + * Customize nesting segment names. + * + * Applied to intermediate path segments (not the method name). + */ + segmentName: NamingConfig; + /** + * Grouping strategy. + * + * - `'flat'` - Standalone functions, no grouping + * - `'byTags'` - One container per operation tag + * - `'single'` - All operations in one container + * - Custom function for full control + */ + strategy: StructureStrategy; +} diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts index b947f5b72..c64209330 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts @@ -1,22 +1,15 @@ -import type { IR } from '~/ir/types'; import type { DefinePlugin, Plugin } from '~/plugins'; import type { PluginClientNames, PluginValidatorNames } from '~/plugins/types'; -import type { StringName } from '~/types/case'; +import type { NameTransformer } from '~/utils/naming'; + +import type { + StructureConfig, + StructureStrategy, + UserStructureConfig, +} from './structure'; export type UserConfig = Plugin.Name<'@hey-api/sdk'> & Plugin.Hooks & { - /** - * Group operation methods into classes? When enabled, you can select which - * classes to export with `sdk.include` and/or transform their names with - * `sdk.classNameBuilder`. - * - * Note that by enabling this option, your SDKs will **NOT** - * support {@link https://developer.mozilla.org/docs/Glossary/Tree_shaking tree-shaking}. - * For this reason, it is disabled by default. - * - * @default false - */ - asClass?: boolean; /** * Should the generated functions contain auth mechanisms? You may want to * disable this option if you're handling auth yourself or defining it @@ -25,21 +18,6 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * @default true */ auth?: boolean; - /** - * Customize the generated class names. The name variable is obtained from - * your OpenAPI specification tags or `instance` value. - * - * This option has no effect if `sdk.asClass` is `false`. - */ - classNameBuilder?: StringName; - /** - * How should we structure your SDK? By default, we try to infer the ideal - * structure using `operationId` keywords. If you prefer a flatter structure, - * you can set `classStructure` to `off` to disable this behavior. - * - * @default 'auto' - */ - classStructure?: 'auto' | 'off'; /** * Use an internal client instance to send HTTP requests? This is useful if * you don't want to manually pass the client to each SDK function. @@ -59,34 +37,6 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * @default true */ exportFromIndex?: boolean; - /** - * Include only service classes with names matching regular expression - * - * This option has no effect if `sdk.asClass` is `false`. - */ - include?: string; - /** - * Set `instance` to create an instantiable SDK. Using `true` will use the - * default instance name; in practice, you want to define your own by passing - * a string value. - * - * @default false - */ - instance?: string | boolean; - /** - * Customise the name of methods within the service. By default, - * `operation.id` is used. - */ - methodNameBuilder?: - | string - | ((name: string, operation: IR.OperationObject) => string); - // TODO: parser - rename operationId option to something like inferId?: boolean - /** - * Use operation ID to generate operation names? - * - * @default true - */ - operationId?: boolean; /** * Define how request parameters are structured in generated SDK methods. * @@ -106,6 +56,25 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * @default 'fields' */ responseStyle?: 'data' | 'fields'; + /** + * Define how generated outputs are structurally organized. + */ + structure?: { + /** + * Define the structure of generated SDK operations. + * + * String shorthand: + * - `'flat'` – standalone functions, no container + * - `'byTags'` – one container per operation tag + * - `'single'` – all operations in a single container + * - custom function for full control + * + * Use the object form for advanced configuration. + * + * @default 'flat' + */ + operations?: StructureStrategy | UserStructureConfig; + }; /** * Transform response data before returning. This is useful if you want to * convert for example ISO strings into Date objects. However, transformation @@ -162,30 +131,6 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & // DEPRECATED OPTIONS BELOW - /** - * **This feature works only with the legacy parser** - * - * Filter endpoints to be included in the generated SDK. The provided - * string should be a regular expression where matched results will be - * included in the output. The input pattern this string will be tested - * against is `{method} {path}`. For example, you can match - * `POST /api/v1/foo` with `^POST /api/v1/foo$`. - * - * @deprecated - */ - // eslint-disable-next-line typescript-sort-keys/interface - filter?: string; - /** - * Define shape of returned value from service calls - * - * @deprecated - * @default 'body' - */ - response?: 'body' | 'response'; - }; - -export type Config = Plugin.Name<'@hey-api/sdk'> & - Plugin.Hooks & { /** * Group operation methods into classes? When enabled, you can select which * classes to export with `sdk.include` and/or transform their names with @@ -195,77 +140,90 @@ export type Config = Plugin.Name<'@hey-api/sdk'> & * support {@link https://developer.mozilla.org/docs/Glossary/Tree_shaking tree-shaking}. * For this reason, it is disabled by default. * + * @deprecated Use `grouping: 'byTags'` or `grouping: 'single'` instead. * @default false */ - asClass: boolean; - /** - * Should the generated functions contain auth mechanisms? You may want to - * disable this option if you're handling auth yourself or defining it - * globally on the client and want to reduce the size of generated code. - * - * @default true - */ - auth: boolean; + // eslint-disable-next-line typescript-sort-keys/interface + asClass?: boolean; /** * Customize the generated class names. The name variable is obtained from * your OpenAPI specification tags or `instance` value. * * This option has no effect if `sdk.asClass` is `false`. + * + * @deprecated Use `grouping.containerName` instead. */ - classNameBuilder: StringName; + classNameBuilder?: NameTransformer; /** * How should we structure your SDK? By default, we try to infer the ideal * structure using `operationId` keywords. If you prefer a flatter structure, * you can set `classStructure` to `off` to disable this behavior. * + * @deprecated Use `grouping: { nesting: 'operationId' }` or `grouping: { nesting: 'id' }` instead. * @default 'auto' */ - classStructure: 'auto' | 'off'; + classStructure?: 'auto' | 'off'; /** - * Use an internal client instance to send HTTP requests? This is useful if - * you don't want to manually pass the client to each SDK function. + * Set `instance` to create an instantiable SDK. Using `true` will use the + * default instance name; in practice, you want to define your own by passing + * a string value. * - * You can customize the selected client output through its plugin. You can - * also set `client` to `true` to automatically choose the client from your - * defined plugins. If we can't detect a client plugin when using `true`, we - * will default to `@hey-api/client-fetch`. + * @deprecated Use `grouping: { strategy: 'single', as: 'Name', methods: 'instance' }` instead. + * @default false + */ + instance?: string | boolean; + /** + * Customise the name of methods within the service. By default, + * `operation.id` is used. * - * @default true + * @deprecated Use `grouping.methodName` instead. */ - client: PluginClientNames | false; + methodNameBuilder?: NameTransformer; /** - * Should the exports from the generated files be re-exported in the index - * barrel file? + * Use operation ID to generate operation names? * + * @deprecated Use `grouping.nesting: 'operationId'` or `grouping.nesting: 'id'` instead. * @default true */ - exportFromIndex: boolean; + operationId?: boolean; /** - * Include only service classes with names matching regular expression + * Define shape of returned value from service calls * - * This option has no effect if `sdk.asClass` is `false`. + * @deprecated + * @default 'body' */ - include: string | undefined; + response?: 'body' | 'response'; + }; + +export type Config = Plugin.Name<'@hey-api/sdk'> & + Plugin.Hooks & { /** - * Set `instance` to create an instantiable SDK. Using `true` will use the - * default instance name; in practice, you want to define your own by passing - * a string value. + * Should the generated functions contain auth mechanisms? You may want to + * disable this option if you're handling auth yourself or defining it + * globally on the client and want to reduce the size of generated code. + * + * @default true */ - instance: string; + auth: boolean; /** - * Customise the name of methods within the service. By default, - * `operation.id` is used. + * Use an internal client instance to send HTTP requests? This is useful if + * you don't want to manually pass the client to each SDK function. + * + * You can customize the selected client output through its plugin. You can + * also set `client` to `true` to automatically choose the client from your + * defined plugins. If we can't detect a client plugin when using `true`, we + * will default to `@hey-api/client-fetch`. + * + * @default true */ - methodNameBuilder: - | string - | ((name: string, operation: IR.OperationObject) => string); - // TODO: parser - rename operationId option to something like inferId?: boolean + client: PluginClientNames | false; /** - * Use operation ID to generate operation names? + * Should the exports from the generated files be re-exported in the index + * barrel file? * * @default true */ - operationId: boolean; + exportFromIndex: boolean; /** * Define how request parameters are structured in generated SDK methods. * @@ -285,6 +243,15 @@ export type Config = Plugin.Name<'@hey-api/sdk'> & * @default 'fields' */ responseStyle: 'data' | 'fields'; + /** + * Define how generated outputs are structurally organized. + */ + structure: { + /** + * Define the structure of generated SDK operations. + */ + operations: StructureConfig; + }; /** * Transform response data before returning. This is useful if you want to * convert for example ISO strings into Date objects. However, transformation @@ -321,18 +288,59 @@ export type Config = Plugin.Name<'@hey-api/sdk'> & // DEPRECATED OPTIONS BELOW /** - * **This feature works only with the legacy parser** + * Group operation methods into classes? When enabled, you can select which + * classes to export with `sdk.include` and/or transform their names with + * `sdk.classNameBuilder`. * - * Filter endpoints to be included in the generated SDK. The provided - * string should be a regular expression where matched results will be - * included in the output. The input pattern this string will be tested - * against is `{method} {path}`. For example, you can match - * `POST /api/v1/foo` with `^POST /api/v1/foo$`. + * Note that by enabling this option, your SDKs will **NOT** + * support {@link https://developer.mozilla.org/docs/Glossary/Tree_shaking tree-shaking}. + * For this reason, it is disabled by default. * - * @deprecated + * @deprecated Use `grouping: 'byTags'` or `grouping: 'single'` instead. + * @default false */ // eslint-disable-next-line typescript-sort-keys/interface - filter?: string; + asClass: boolean; + /** + * Customize the generated class names. The name variable is obtained from + * your OpenAPI specification tags or `instance` value. + * + * This option has no effect if `sdk.asClass` is `false`. + * + * @deprecated Use `grouping.containerName` instead. + */ + classNameBuilder: NameTransformer; + /** + * How should we structure your SDK? By default, we try to infer the ideal + * structure using `operationId` keywords. If you prefer a flatter structure, + * you can set `classStructure` to `off` to disable this behavior. + * + * @deprecated Use `grouping: { nesting: 'operationId' }` or `grouping: { nesting: 'id' }` instead. + * @default 'auto' + */ + classStructure: 'auto' | 'off'; + /** + * Set `instance` to create an instantiable SDK. Using `true` will use the + * default instance name; in practice, you want to define your own by passing + * a string value. + * + * @deprecated Use `grouping: { strategy: 'single', as: 'Name', methods: 'instance' }` instead. + */ + instance: string; + /** + * Customise the name of methods within the service. By default, + * `operation.id` is used. + * + * @deprecated Use `grouping.methodName` instead. + */ + methodNameBuilder: NameTransformer; + /** + * Use operation ID to generate operation names? + * + * @deprecated Use `grouping.nesting: 'operationId'` or `grouping.nesting: 'id'` instead. + * @default true + */ + operationId: boolean; /** * Define shape of returned value from service calls * diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts index f5d199461..f60381391 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts @@ -1,11 +1,414 @@ +import type { + StructureItem, + StructureNode, + StructureShell, + Symbol, +} from '@hey-api/codegen-core'; +import { StructureModel } from '@hey-api/codegen-core'; + import { clientFolderAbsolutePath } from '~/generate/client'; +import type { IR } from '~/ir/types'; +import { + OperationLocations, + type OperationLocationStrategy, + OperationPath, +} from '~/openApi/shared/locations'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; -import type { $ } from '~/ts-dsl'; +import { + createOperationComment, + isOperationOptionsRequired, +} from '~/plugins/shared/utils/operation'; +import { $ } from '~/ts-dsl'; +import { toCase } from '~/utils/naming'; -import { SdkStructureModel } from '../model/structure'; +import { createClientClass, createRegistryClass } from '../shared/class'; +import { nuxtTypeComposable, nuxtTypeDefault } from '../shared/constants'; +import { + operationClassName, + operationMethodName, + operationParameters, + operationStatements, +} from '../shared/operation'; import { createTypeOptions } from '../shared/typeOptions'; import type { HeyApiSdkPlugin } from '../types'; +interface OperationItem { + operation: IR.OperationObject; + path: ReadonlyArray; + tags: ReadonlyArray | undefined; +} + +const source = globalThis.Symbol('@hey-api/sdk'); + +function attachComment< + T extends ReturnType, +>(args: { node: T; operation: IR.OperationObject }): T { + const { node, operation } = args; + return node.$if(createOperationComment(operation), (m, v) => m.doc(v)) as T; +} + +function createFnSymbol( + plugin: HeyApiSdkPlugin['Instance'], + item: StructureItem & { data: OperationItem }, +): Symbol { + const { operation, path, tags } = item.data; + const name = item.location[item.location.length - 1]; + return plugin.symbol( + operationMethodName({ + operation, + plugin, + value: name, + }), + { + meta: { + category: 'sdk', + path, + resource: 'operation', + resourceId: operation.id, + tags, + tool: 'sdk', + }, + }, + ); +} + +function childToNode( + resource: StructureNode, + plugin: HeyApiSdkPlugin['Instance'], +): ReadonlyArray> { + const refChild = plugin.referenceSymbol({ + category: 'utility', + resource: 'class', + resourceId: resource.getPath().join('.'), + tool: 'sdk', + }); + const memberNameStr = toCase(refChild.name, 'camelCase'); + const memberName = plugin.symbol(memberNameStr); + if (plugin.config.instance) { + const privateName = plugin.symbol(`_${memberNameStr}`); + return [ + $.field(privateName, (f) => f.private().optional().type(refChild)), + $.getter(memberName, (g) => + g.returns(refChild).do( + $('this') + .attr(privateName) + .nullishAssign( + $.new(refChild).args( + $.object().prop('client', $('this').attr('client')), + ), + ) + .return(), + ), + ), + ]; + } + if (plugin.isSymbolRegistered(refChild.id)) { + return [$.field(memberName, (f) => f.static().assign($(refChild)))]; + } + return [ + $.getter(memberName, (g) => g.public().static().do($.return(refChild))), + ]; +} + +function enrichRootClass(args: { + dependencies: Array>; + node: ReturnType; + plugin: HeyApiSdkPlugin['Instance']; + symbol: Symbol; +}): void { + const { dependencies, node, plugin, symbol } = args; + const symbolClient = plugin.symbol('HeyApiClient', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiClient', + tool: 'sdk', + }, + }); + dependencies.push(createClientClass({ plugin, symbol: symbolClient })); + const symbolRegistry = plugin.symbol('HeyApiRegistry', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiRegistry', + tool: 'sdk', + }, + }); + dependencies.push( + createRegistryClass({ + plugin, + sdkSymbol: symbol, + symbol: symbolRegistry, + }), + ); + const isClientRequired = + !plugin.config.client || !plugin.getSymbol({ category: 'client' }); + const registry = plugin.symbol('__registry'); + node.toAccessNode = (node, options) => { + if (options.context) return; + return $(node.name).attr(registry).attr('get').call(); + }; + node.do( + $.field(registry, (f) => + f + .public() + .static() + .readonly() + .assign($.new(symbolRegistry).generic(symbol)), + ), + $.newline(), + $.init((i) => + i + .param('args', (p) => + p.required(isClientRequired).type( + $.type + .object() + .prop('client', (p) => + p.required(isClientRequired).type( + plugin.referenceSymbol({ + category: 'external', + resource: 'client.Client', + }), + ), + ) + .prop('key', (p) => p.optional().type('string')), + ), + ) + .do( + $('super').call('args'), + $(symbol) + .attr(registry) + .attr('set') + .call('this', $('args').attr('key').required(isClientRequired)), + ), + ), + ); +} + +function implementFn< + T extends ReturnType, +>(args: { + node: T; + operation: IR.OperationObject; + plugin: HeyApiSdkPlugin['Instance']; +}): T { + const { node, operation, plugin } = args; + const client = getClientPlugin(plugin.context.config); + const isNuxtClient = client.name === '@hey-api/client-nuxt'; + const isRequiredOptions = isOperationOptionsRequired({ + context: plugin.context, + operation, + }); + const opParameters = operationParameters({ + isRequiredOptions, + operation, + plugin, + }); + const statements = operationStatements({ + isRequiredOptions, + opParameters, + operation, + plugin, + }); + return node + .$if( + isNuxtClient, + (m) => + m + .generic(nuxtTypeComposable, (t) => + t + .extends( + plugin.referenceSymbol({ + category: 'external', + resource: 'client.Composable', + }), + ) + .default($.type.literal('$fetch')), + ) + .generic(nuxtTypeDefault, (t) => + t.$if( + plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'response', + }), + (t, s) => t.extends(s).default(s), + (t) => t.default('undefined'), + ), + ), + (m) => + m.generic('ThrowOnError', (t) => + t + .extends('boolean') + .default( + ('throwOnError' in client.config + ? client.config.throwOnError + : false) ?? false, + ), + ), + ) + .params(...opParameters.parameters) + .do(...statements) as T; +} + +/** + * Converts this class group to a class node. + */ +function toNode( + model: StructureNode, + plugin: HeyApiSdkPlugin['Instance'], +): { + dependencies?: Array>; + nodes: ReadonlyArray>; +} { + if (model.virtual) { + const nodes: Array> = []; + for (const item of model.itemsFrom(source)) { + const { operation } = item.data; + let node = $.const(createFnSymbol(plugin, item)) + .export() + .assign( + implementFn({ + node: $.func(), + operation, + plugin, + }), + ); + node = attachComment({ node, operation }); + nodes.push(node); + } + return { nodes }; + } + + if (!model.shell) { + return { nodes: [] }; + } + + const nodes: Array> = []; + + const client = getClientPlugin(plugin.context.config); + const isAngularClient = client.name === '@hey-api/client-angular'; + + const shell = model.shell.define(model); + const node = shell.node as ReturnType; + + let index = 0; + for (const item of model.itemsFrom(source)) { + const { operation } = item.data; + if (index > 0 || node.hasBody) node.newline(); + node.do( + implementFn({ + node: $.method(createFnSymbol(plugin, item), (m) => + attachComment({ + node: m, + operation, + }) + .public() + .static(!isAngularClient && !plugin.config.instance), + ), + operation, + plugin, + }), + ); + index += 1; + } + + for (const child of model.children.values()) { + if (node.hasBody) node.newline(); + node.do(...childToNode(child, plugin)); + } + + nodes.push(node); + + return { + dependencies: shell.dependencies as Array>, + nodes, + }; +} + +function createShell(plugin: HeyApiSdkPlugin['Instance']): StructureShell { + const client = getClientPlugin(plugin.context.config); + const isAngularClient = client.name === '@hey-api/client-angular'; + return { + define: (node) => { + const symbol = plugin.symbol( + operationClassName({ plugin, value: node.name }), + { + meta: { + category: 'utility', + resource: 'class', + resourceId: node.getPath().join('.'), + tool: 'sdk', + }, + }, + ); + const c = $.class(symbol) + .export() + .$if(plugin.config.instance, (c) => + c.extends( + plugin.referenceSymbol({ + category: 'utility', + resource: 'class', + resourceId: 'HeyApiClient', + tool: 'sdk', + }), + ), + ) + .$if(isAngularClient && node.isRoot, (c) => + c.decorator( + plugin.referenceSymbol({ + category: 'external', + resource: '@angular/core.Injectable', + }), + $.object().prop('providedIn', $.literal('root')), + ), + ); + + const dependencies: Array> = []; + + if (node.isRoot && plugin.config.instance) { + enrichRootClass({ + dependencies, + node: c, + plugin, + symbol, + }); + } + + return { dependencies, node: c }; + }, + }; +} + +function resolveLocationStrategy( + plugin: HeyApiSdkPlugin['Instance'], +): OperationLocationStrategy { + const shell = createShell(plugin); + const path = + plugin.config.classStructure === 'auto' + ? OperationPath.fromOperationId() + : OperationPath.id(); + + if (!plugin.config.asClass) { + return OperationLocations.flat(); + } + + if (plugin.config.instance) { + return OperationLocations.single({ + path, + root: plugin.config.instance, + shell, + }); + } + + return OperationLocations.byTags({ + fallback: 'default', + path, + shell, + }); +} + export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { const clientModule = clientFolderAbsolutePath(plugin.context.config); const client = getClientPlugin(plugin.context.config); @@ -59,21 +462,22 @@ export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { createTypeOptions({ plugin }); - const structure = plugin.config.asClass - ? new SdkStructureModel(plugin.config.instance) - : new SdkStructureModel('', { flat: true }); + const structure = new StructureModel(); + const locationStrategy = resolveLocationStrategy(plugin); plugin.forEach( 'operation', (event) => { - structure.insert( - { + structure.insert({ + data: { operation: event.operation, path: event._path, tags: event.tags, - }, - plugin, - ); + } satisfies OperationItem, + // TODO: expose this logic + locations: locationStrategy(event.operation), + source, + }); }, { order: 'declarations' }, ); @@ -81,9 +485,9 @@ export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { const allDependencies: Array> = []; const allNodes: Array> = []; - for (const model of structure.walk()) { - const { dependencies, nodes } = model.toNode(plugin); - allDependencies.push(...dependencies); + for (const node of structure.walk()) { + const { dependencies, nodes } = toNode(node, plugin); + allDependencies.push(...(dependencies ?? [])); allNodes.push(...nodes); } diff --git a/packages/openapi-ts/src/plugins/@hey-api/transformers/plugin.ts b/packages/openapi-ts/src/plugins/@hey-api/transformers/plugin.ts index 8d41104ca..a6622a0b8 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/transformers/plugin.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/transformers/plugin.ts @@ -3,8 +3,8 @@ import type ts from 'typescript'; import { createOperationKey, operationResponsesMap } from '~/ir/operation'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { refToName } from '~/utils/ref'; import type { HeyApiTransformersPlugin } from './types'; @@ -62,12 +62,9 @@ const processSchemaType = ({ const symbol = plugin.getSymbol(query) ?? plugin.symbol( - buildName({ - config: { - case: 'camelCase', - name: '{{name}}SchemaResponseTransformer', - }, - name: refToName(schema.$ref), + applyNaming(refToName(schema.$ref), { + case: 'camelCase', + name: '{{name}}SchemaResponseTransformer', }), { meta: query, @@ -311,21 +308,20 @@ export const handler: HeyApiTransformersPlugin['Handler'] = ({ plugin }) => { schema: response, }); if (!nodes.length) return; - const symbol = plugin.registerSymbol({ - meta: { - category: 'transform', - resource: 'operation', - resourceId: operation.id, - role: 'response', - }, - name: buildName({ - config: { - case: 'camelCase', - name: '{{name}}ResponseTransformer', - }, - name: operation.id, + const symbol = plugin.symbol( + applyNaming(operation.id, { + case: 'camelCase', + name: '{{name}}ResponseTransformer', }), - }); + { + meta: { + category: 'transform', + resource: 'operation', + resourceId: operation.id, + role: 'response', + }, + }, + ); const value = $.const(symbol) .export() .assign( diff --git a/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/clientOptions.ts b/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/clientOptions.ts index 88340c969..c7bd15b93 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/clientOptions.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/clientOptions.ts @@ -1,11 +1,11 @@ import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { getClientBaseUrlKey, getClientPlugin, } from '~/plugins/@hey-api/client-core/utils'; import type { TypeTsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { parseUrl } from '~/utils/url'; import type { HeyApiTypeScriptPlugin } from '../types'; @@ -50,11 +50,8 @@ export const createClientOptions = ({ } const symbol = plugin.symbol( - buildName({ - config: { - case: plugin.config.case, - }, - name: 'ClientOptions', + applyNaming('ClientOptions', { + case: plugin.config.case, }), { meta: { diff --git a/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/export.ts b/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/export.ts index 986488b99..4a0370fad 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/export.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/export.ts @@ -1,12 +1,11 @@ import { fromRef } from '@hey-api/codegen-core'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { createSchemaComment } from '~/plugins/shared/utils/schema'; import type { MaybeTsDsl, TypeTsDsl } from '~/ts-dsl'; import { $, regexp } from '~/ts-dsl'; +import { applyNaming, toCase } from '~/utils/naming'; import { pathToJsonPointer, refToName } from '~/utils/ref'; -import { toCase } from '~/utils/to-case'; import type { HeyApiTypeScriptPlugin } from '../types'; import type { IrSchemaToAstOptions } from './types'; @@ -106,20 +105,19 @@ export const exportType = ({ ); } - const symbolObject = plugin.registerSymbol({ - meta: { - category: 'utility', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'typescript', + const symbolObject = plugin.symbol( + applyNaming(refToName($ref), plugin.config.definitions), + { + meta: { + category: 'utility', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'typescript', + }, }, - name: buildName({ - config: plugin.config.definitions, - name: refToName($ref), - }), - }); + ); const objectNode = $.const(symbolObject) .export() .$if(createSchemaComment(schema), (c, v) => c.doc(v)) @@ -134,20 +132,19 @@ export const exportType = ({ ); plugin.node(objectNode); - const symbol = plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'typescript', + const symbol = plugin.symbol( + applyNaming(refToName($ref), plugin.config.definitions), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'typescript', + }, }, - name: buildName({ - config: plugin.config.definitions, - name: refToName($ref), - }), - }); + ); const node = $.type .alias(symbol) .export() @@ -166,20 +163,19 @@ export const exportType = ({ (type) => type !== 'number' && type !== 'string', ); if (shouldCreateTypeScriptEnum) { - const symbol = plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'typescript', + const symbol = plugin.symbol( + applyNaming(refToName($ref), plugin.config.definitions), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'typescript', + }, }, - name: buildName({ - config: plugin.config.definitions, - name: refToName($ref), - }), - }); + ); const enumNode = $.enum(symbol) .export() .$if(createSchemaComment(schema), (e, v) => e.doc(v)) @@ -197,20 +193,19 @@ export const exportType = ({ } } - const symbol = plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'typescript', + const symbol = plugin.symbol( + applyNaming(refToName($ref), plugin.config.definitions), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'typescript', + }, }, - name: buildName({ - config: plugin.config.definitions, - name: refToName($ref), - }), - }); + ); const node = $.type .alias(symbol) .export() diff --git a/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/operation.ts b/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/operation.ts index 80d5c9114..ef73b0bcb 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/operation.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/operation.ts @@ -3,8 +3,8 @@ import { fromRef } from '@hey-api/codegen-core'; import { operationResponsesMap } from '~/ir/operation'; import { deduplicateSchema } from '~/ir/schema'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { irSchemaToAst } from '../v1/plugin'; import type { IrSchemaToAstOptions } from './types'; @@ -122,21 +122,20 @@ const operationToDataType = ({ data.required = dataRequired; - const symbol = plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'operation', - resourceId: operation.id, - role: 'data', - tags: fromRef(state.tags), - tool: 'typescript', + const symbol = plugin.symbol( + applyNaming(operation.id, plugin.config.requests), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'operation', + resourceId: operation.id, + role: 'data', + tags: fromRef(state.tags), + tool: 'typescript', + }, }, - name: buildName({ - config: plugin.config.requests, - name: operation.id, - }), - }); + ); const node = $.type .alias(symbol) .export() @@ -163,21 +162,20 @@ export const operationToType = ({ operationResponsesMap(operation); if (errors) { - const symbolErrors = plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'operation', - resourceId: operation.id, - role: 'errors', - tags: fromRef(state.tags), - tool: 'typescript', + const symbolErrors = plugin.symbol( + applyNaming(operation.id, plugin.config.errors), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'operation', + resourceId: operation.id, + role: 'errors', + tags: fromRef(state.tags), + tool: 'typescript', + }, }, - name: buildName({ - config: plugin.config.errors, - name: operation.id, - }), - }); + ); const node = $.type .alias(symbolErrors) .export() @@ -191,24 +189,23 @@ export const operationToType = ({ plugin.node(node); if (error) { - const symbol = plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'operation', - resourceId: operation.id, - role: 'error', - tags: fromRef(state.tags), - tool: 'typescript', - }, - name: buildName({ - config: { - case: plugin.config.errors.case, - name: plugin.config.errors.error, - }, - name: operation.id, + const symbol = plugin.symbol( + applyNaming(operation.id, { + case: plugin.config.errors.case, + name: plugin.config.errors.error, }), - }); + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'operation', + resourceId: operation.id, + role: 'error', + tags: fromRef(state.tags), + tool: 'typescript', + }, + }, + ); const node = $.type .alias(symbol) .export() @@ -218,21 +215,20 @@ export const operationToType = ({ } if (responses) { - const symbolResponses = plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'operation', - resourceId: operation.id, - role: 'responses', - tags: fromRef(state.tags), - tool: 'typescript', + const symbolResponses = plugin.symbol( + applyNaming(operation.id, plugin.config.responses), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'operation', + resourceId: operation.id, + role: 'responses', + tags: fromRef(state.tags), + tool: 'typescript', + }, }, - name: buildName({ - config: plugin.config.responses, - name: operation.id, - }), - }); + ); const node = $.type .alias(symbolResponses) .export() @@ -246,24 +242,23 @@ export const operationToType = ({ plugin.node(node); if (response) { - const symbol = plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'operation', - resourceId: operation.id, - role: 'response', - tags: fromRef(state.tags), - tool: 'typescript', - }, - name: buildName({ - config: { - case: plugin.config.responses.case, - name: plugin.config.responses.response, - }, - name: operation.id, + const symbol = plugin.symbol( + applyNaming(operation.id, { + case: plugin.config.responses.case, + name: plugin.config.responses.response, }), - }); + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'operation', + resourceId: operation.id, + role: 'response', + tags: fromRef(state.tags), + tool: 'typescript', + }, + }, + ); const node = $.type .alias(symbol) .export() diff --git a/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/webhook.ts b/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/webhook.ts index 4494761b9..48791e240 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/webhook.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/typescript/shared/webhook.ts @@ -2,9 +2,9 @@ import type { Symbol } from '@hey-api/codegen-core'; import { fromRef } from '@hey-api/codegen-core'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { createSchemaComment } from '~/plugins/shared/utils/schema'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { irSchemaToAst } from '../v1/plugin'; import type { IrSchemaToAstOptions } from './types'; @@ -26,24 +26,23 @@ const operationToDataType = ({ } if (operation.body) { - const symbolWebhookPayload = plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'webhook', - resourceId: operation.id, - role: 'data', - tags: fromRef(state.tags), - tool: 'typescript', - }, - name: buildName({ - config: { - case: plugin.config.webhooks.case, - name: plugin.config.webhooks.payload, - }, - name: operation.id, + const symbolWebhookPayload = plugin.symbol( + applyNaming(operation.id, { + case: plugin.config.webhooks.case, + name: plugin.config.webhooks.payload, }), - }); + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'webhook', + resourceId: operation.id, + role: 'data', + tags: fromRef(state.tags), + tool: 'typescript', + }, + }, + ); const node = $.type .alias(symbolWebhookPayload) .export() @@ -74,21 +73,20 @@ const operationToDataType = ({ data.required = dataRequired; - const symbolWebhookRequest = plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'webhook', - resourceId: operation.id, - role: 'data', - tags: fromRef(state.tags), - tool: 'typescript', + const symbolWebhookRequest = plugin.symbol( + applyNaming(operation.id, plugin.config.webhooks), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'webhook', + resourceId: operation.id, + role: 'data', + tags: fromRef(state.tags), + tool: 'typescript', + }, }, - name: buildName({ - config: plugin.config.webhooks, - name: operation.id, - }), - }); + ); const node = $.type .alias(symbolWebhookRequest) .export() diff --git a/packages/openapi-ts/src/plugins/@hey-api/typescript/types.d.ts b/packages/openapi-ts/src/plugins/@hey-api/typescript/types.d.ts index b1dd85645..06cb15485 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/typescript/types.d.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/typescript/types.d.ts @@ -1,5 +1,5 @@ import type { DefinePlugin, Plugin } from '~/plugins'; -import type { StringCase, StringName } from '~/types/case'; +import type { Casing, NameTransformer } from '~/utils/naming'; import type { IApi } from './api'; @@ -12,7 +12,7 @@ export type UserConfig = Plugin.Name<'@hey-api/typescript'> & * * @default 'PascalCase' */ - case?: Exclude; + case?: Exclude; /** * Configuration for reusable schema definitions. * @@ -26,21 +26,21 @@ export type UserConfig = Plugin.Name<'@hey-api/typescript'> & * @default '{{name}}' */ definitions?: - | StringName + | NameTransformer | { /** * The casing convention to use for generated definition names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Custom naming pattern for generated definition names. The name variable * is obtained from the schema name. * * @default '{{name}}' */ - name?: StringName; + name?: NameTransformer; }; /** * By default, enums are emitted as types to preserve runtime-free output. @@ -60,7 +60,7 @@ export type UserConfig = Plugin.Name<'@hey-api/typescript'> & * * @default 'SCREAMING_SNAKE_CASE' */ - case?: StringCase; + case?: Casing; /** * When generating enums as JavaScript objects, they'll contain a null * value if they're nullable. This might be undesirable if you want to do @@ -101,28 +101,28 @@ export type UserConfig = Plugin.Name<'@hey-api/typescript'> & * @default '{{name}}Errors' */ errors?: - | StringName + | NameTransformer | { /** * The casing convention to use for generated error type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Custom naming pattern for generated error type names. The name * variable is obtained from the operation name. * * @default '{{name}}Error' */ - error?: StringName; + error?: NameTransformer; /** * Custom naming pattern for generated error type names. The name * variable is obtained from the operation name. * * @default '{{name}}Errors' */ - name?: StringName; + name?: NameTransformer; }; /** * Should the exports from the generated files be re-exported in the index @@ -144,21 +144,21 @@ export type UserConfig = Plugin.Name<'@hey-api/typescript'> & * @default '{{name}}Data' */ requests?: - | StringName + | NameTransformer | { /** * The casing convention to use for generated request type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Custom naming pattern for generated request type names. The name * variable is obtained from the operation name. * * @default '{{name}}Data' */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for response-specific types. @@ -172,28 +172,28 @@ export type UserConfig = Plugin.Name<'@hey-api/typescript'> & * @default '{{name}}Responses' */ responses?: - | StringName + | NameTransformer | { /** * The casing convention to use for generated response type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Custom naming pattern for generated response type names. The name * variable is obtained from the operation name. * * @default '{{name}}Responses' */ - name?: StringName; + name?: NameTransformer; /** * Custom naming pattern for generated response type names. The name * variable is obtained from the operation name. * * @default '{{name}}Response' */ - response?: StringName; + response?: NameTransformer; }; /** * The top type to use for untyped or unspecified schema values. @@ -217,28 +217,28 @@ export type UserConfig = Plugin.Name<'@hey-api/typescript'> & * @default '{{name}}WebhookRequest' */ webhooks?: - | StringName + | NameTransformer | { /** * The casing convention to use for generated webhook type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Custom naming pattern for generated webhook type names. The name * variable is obtained from the webhook key. * * @default '{{name}}WebhookRequest' */ - name?: StringName; + name?: NameTransformer; /** * Custom naming pattern for generated webhook type names. The name * variable is obtained from the webhook key. * * @default '{{name}}WebhookPayload' */ - payload?: StringName; + payload?: NameTransformer; }; }; @@ -249,7 +249,7 @@ export type Config = Plugin.Name<'@hey-api/typescript'> & * * @default 'PascalCase' */ - case: Exclude; + case: Exclude; /** * Configuration for reusable schema definitions. * @@ -262,14 +262,14 @@ export type Config = Plugin.Name<'@hey-api/typescript'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Custom naming pattern for generated definition names. The name variable * is obtained from the schema name. * * @default '{{name}}' */ - name: StringName; + name: NameTransformer; }; /** * By default, enums are emitted as types to preserve runtime-free output. @@ -284,7 +284,7 @@ export type Config = Plugin.Name<'@hey-api/typescript'> & * * @default 'SCREAMING_SNAKE_CASE' */ - case: StringCase; + case: Casing; /** * When generating enums as JavaScript objects, they'll contain a null * value if they're nullable. This might be undesirable if you want to do @@ -328,21 +328,21 @@ export type Config = Plugin.Name<'@hey-api/typescript'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Custom naming pattern for generated error type names. The name * variable is obtained from the operation name. * * @default '{{name}}Error' */ - error: StringName; + error: NameTransformer; /** * Custom naming pattern for generated error type names. The name * variable is obtained from the operation name. * * @default '{{name}}Errors' */ - name: StringName; + name: NameTransformer; }; /** * Should the exports from the generated files be re-exported in the index @@ -363,14 +363,14 @@ export type Config = Plugin.Name<'@hey-api/typescript'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Custom naming pattern for generated request type names. The name * variable is obtained from the operation name. * * @default '{{name}}Data' */ - name: StringName; + name: NameTransformer; }; /** * Configuration for response-specific types. @@ -383,21 +383,21 @@ export type Config = Plugin.Name<'@hey-api/typescript'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Custom naming pattern for generated response type names. The name * variable is obtained from the operation name. * * @default '{{name}}Responses' */ - name: StringName; + name: NameTransformer; /** * Custom naming pattern for generated response type names. The name * variable is obtained from the operation name. * * @default '{{name}}Response' */ - response: StringName; + response: NameTransformer; }; /** * The top type to use for untyped or unspecified schema values. @@ -416,21 +416,21 @@ export type Config = Plugin.Name<'@hey-api/typescript'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Custom naming pattern for generated webhook type names. The name * variable is obtained from the webhook key. * * @default '{{name}}WebhookRequest' */ - name: StringName; + name: NameTransformer; /** * Custom naming pattern for generated webhook type names. The name * variable is obtained from the webhook key. * * @default '{{name}}WebhookPayload' */ - payload: StringName; + payload: NameTransformer; }; }; diff --git a/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/plugin.ts b/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/plugin.ts index 28224e6a9..1d1c81d78 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/plugin.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/plugin.ts @@ -3,10 +3,10 @@ import { refs } from '@hey-api/codegen-core'; import { deduplicateSchema } from '~/ir/schema'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import type { SchemaWithType } from '~/plugins'; import type { MaybeTsDsl, TypeTsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { createClientOptions } from '../shared/clientOptions'; import { exportType } from '../shared/export'; @@ -175,11 +175,8 @@ export const handlerV1: HeyApiTypeScriptPlugin['Handler'] = ({ plugin }) => { if (webhooks.length > 0) { const symbol = plugin.symbol( - buildName({ - config: { - case: plugin.config.case, - }, - name: 'Webhooks', + applyNaming('Webhooks', { + case: plugin.config.case, }), { meta: { diff --git a/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/toAst/string.ts b/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/toAst/string.ts index 132bd6193..20b1fa5ee 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/toAst/string.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/typescript/v1/toAst/string.ts @@ -3,7 +3,7 @@ import type { SymbolMeta } from '@hey-api/codegen-core'; import type { SchemaWithType } from '~/plugins'; import type { TypeTsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/to-case'; +import { toCase } from '~/utils/naming'; import type { IrSchemaToAstOptions } from '../../shared/types'; @@ -49,9 +49,8 @@ export const stringToAst = ({ }; if (!plugin.getSymbol(queryTypeId)) { - const symbolTypeId = plugin.registerSymbol({ + const symbolTypeId = plugin.symbol('TypeID', { meta: queryTypeId, - name: 'TypeID', }); const nodeTypeId = $.type .alias(symbolTypeId) @@ -64,10 +63,12 @@ export const stringToAst = ({ } const symbolTypeId = plugin.referenceSymbol(queryTypeId); - const symbolTypeName = plugin.registerSymbol({ - meta: query, - name: toCase(`${type}_id`, plugin.config.case), - }); + const symbolTypeName = plugin.symbol( + toCase(`${type}_id`, plugin.config.case), + { + meta: query, + }, + ); const node = $.type .alias(symbolTypeName) .export() diff --git a/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts b/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts index 206847a68..1699ce288 100644 --- a/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts +++ b/packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts @@ -1,8 +1,8 @@ import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; import { createOperationComment } from '~/plugins/shared/utils/operation'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { handleMeta } from './meta'; import type { PiniaColadaPlugin } from './types'; @@ -75,12 +75,9 @@ export const createMutationOptions = ({ .$if(handleMeta(plugin, operation, 'mutationOptions'), (o, v) => o.prop('meta', v), ); - const symbolMutationOptions = plugin.registerSymbol({ - name: buildName({ - config: plugin.config.mutationOptions, - name: operation.id, - }), - }); + const symbolMutationOptions = plugin.symbol( + applyNaming(operation.id, plugin.config.mutationOptions), + ); const statement = $.const(symbolMutationOptions) .export() .$if(plugin.config.comments && createOperationComment(operation), (c, v) => diff --git a/packages/openapi-ts/src/plugins/@pinia/colada/queryKey.ts b/packages/openapi-ts/src/plugins/@pinia/colada/queryKey.ts index 3651f3aa8..e53e83d8b 100644 --- a/packages/openapi-ts/src/plugins/@pinia/colada/queryKey.ts +++ b/packages/openapi-ts/src/plugins/@pinia/colada/queryKey.ts @@ -3,12 +3,12 @@ import type { Symbol } from '@hey-api/codegen-core'; import { clientFolderAbsolutePath } from '~/generate/client'; import { hasOperationDataRequired } from '~/ir/operation'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { getClientBaseUrlKey, getClientPlugin, } from '~/plugins/@hey-api/client-core/utils'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import type { PiniaColadaPlugin } from './types'; import { getPublicTypeData } from './utils'; @@ -20,19 +20,18 @@ export const createQueryKeyFunction = ({ }: { plugin: PiniaColadaPlugin['Instance']; }) => { - const symbolCreateQueryKey = plugin.registerSymbol({ - meta: { - category: 'utility', - resource: 'createQueryKey', - tool: plugin.name, - }, - name: buildName({ - config: { - case: plugin.config.case, - }, - name: 'createQueryKey', + const symbolCreateQueryKey = plugin.symbol( + applyNaming('createQueryKey', { + case: plugin.config.case, }), - }); + { + meta: { + category: 'utility', + resource: 'createQueryKey', + tool: plugin.name, + }, + }, + ); const symbolQueryKeyType = plugin.referenceSymbol({ category: 'type', resource: 'QueryKey', @@ -57,13 +56,12 @@ export const createQueryKeyFunction = ({ }); const clientModule = clientFolderAbsolutePath(plugin.context.config); - const symbolSerializeQueryValue = plugin.registerSymbol({ + const symbolSerializeQueryValue = plugin.symbol('serializeQueryKeyValue', { external: clientModule, meta: { category: 'external', resource: `${clientModule}.serializeQueryKeyValue`, }, - name: 'serializeQueryKeyValue', }); const fn = $.const(symbolCreateQueryKey).assign( @@ -169,13 +167,12 @@ export const createQueryKeyType = ({ resource: 'client-options', tool: 'sdk', }); - const symbolQueryKeyType = plugin.registerSymbol({ + const symbolQueryKeyType = plugin.symbol('QueryKey', { meta: { category: 'type', resource: 'QueryKey', tool: plugin.name, }, - name: 'QueryKey', }); const queryKeyType = $.type .alias(symbolQueryKeyType) diff --git a/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts b/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts index 83ee8b4b8..1158576b2 100644 --- a/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts +++ b/packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts @@ -1,5 +1,4 @@ import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; import { createOperationComment, @@ -7,6 +6,7 @@ import { isOperationOptionsRequired, } from '~/plugins/shared/utils/operation'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { handleMeta } from './meta'; import { @@ -48,12 +48,9 @@ export const createQueryOptions = ({ let keyExpression: ReturnType; if (plugin.config.queryKeys.enabled) { - const symbolQueryKey = plugin.registerSymbol({ - name: buildName({ - config: plugin.config.queryKeys, - name: operation.id, - }), - }); + const symbolQueryKey = plugin.symbol( + applyNaming(operation.id, plugin.config.queryKeys), + ); const node = queryKeyStatement({ operation, plugin, @@ -128,19 +125,18 @@ export const createQueryOptions = ({ o.prop('meta', v), ); - const symbolQueryOptionsFn = plugin.registerSymbol({ - meta: { - category: 'hook', - resource: 'operation', - resourceId: operation.id, - role: 'queryOptions', - tool: plugin.name, + const symbolQueryOptionsFn = plugin.symbol( + applyNaming(operation.id, plugin.config.queryOptions), + { + meta: { + category: 'hook', + resource: 'operation', + resourceId: operation.id, + role: 'queryOptions', + tool: plugin.name, + }, }, - name: buildName({ - config: plugin.config.queryOptions, - name: operation.id, - }), - }); + ); const symbolDefineQueryOptions = plugin.referenceSymbol({ category: 'external', resource: `${plugin.name}.defineQueryOptions`, diff --git a/packages/openapi-ts/src/plugins/@pinia/colada/types.d.ts b/packages/openapi-ts/src/plugins/@pinia/colada/types.d.ts index 22b991e4e..894885aa8 100644 --- a/packages/openapi-ts/src/plugins/@pinia/colada/types.d.ts +++ b/packages/openapi-ts/src/plugins/@pinia/colada/types.d.ts @@ -1,6 +1,6 @@ import type { IR } from '~/ir/types'; import type { DefinePlugin, Plugin } from '~/plugins'; -import type { StringCase, StringName } from '~/types/case'; +import type { Casing, NameTransformer } from '~/utils/naming'; export type UserConfig = Plugin.Name<'@pinia/colada'> & Plugin.Hooks & { @@ -9,7 +9,7 @@ export type UserConfig = Plugin.Name<'@pinia/colada'> & * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Add comments from SDK functions to the generated Pinia Colada code? * @@ -42,14 +42,14 @@ export type UserConfig = Plugin.Name<'@pinia/colada'> & */ mutationOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate mutation options helpers. * @@ -85,7 +85,7 @@ export type UserConfig = Plugin.Name<'@pinia/colada'> & * * @default '{{name}}Mutation' */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated query keys. @@ -101,14 +101,14 @@ export type UserConfig = Plugin.Name<'@pinia/colada'> & */ queryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query keys. * @@ -121,7 +121,7 @@ export type UserConfig = Plugin.Name<'@pinia/colada'> & * * @default '{{name}}QueryKey' */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -144,14 +144,14 @@ export type UserConfig = Plugin.Name<'@pinia/colada'> & */ queryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query options helpers. * @@ -187,7 +187,7 @@ export type UserConfig = Plugin.Name<'@pinia/colada'> & * * @default '{{name}}Query' */ - name?: StringName; + name?: NameTransformer; }; }; @@ -198,7 +198,7 @@ export type Config = Plugin.Name<'@pinia/colada'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Add comments from SDK functions to the generated Pinia Colada code? * @@ -220,7 +220,7 @@ export type Config = Plugin.Name<'@pinia/colada'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate mutation options helpers. * @@ -258,7 +258,7 @@ export type Config = Plugin.Name<'@pinia/colada'> & * * @default '{{name}}Mutation' */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated query keys. @@ -271,7 +271,7 @@ export type Config = Plugin.Name<'@pinia/colada'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query keys. * @@ -284,7 +284,7 @@ export type Config = Plugin.Name<'@pinia/colada'> & * * @default '{{name}}QueryKey' */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -304,7 +304,7 @@ export type Config = Plugin.Name<'@pinia/colada'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query options helpers. * @@ -342,7 +342,7 @@ export type Config = Plugin.Name<'@pinia/colada'> & * * @default '{{name}}Query' */ - name: StringName; + name: NameTransformer; }; }; diff --git a/packages/openapi-ts/src/plugins/@tanstack/angular-query-experimental/types.d.ts b/packages/openapi-ts/src/plugins/@tanstack/angular-query-experimental/types.d.ts index 037052669..7cb834542 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/angular-query-experimental/types.d.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/angular-query-experimental/types.d.ts @@ -1,6 +1,6 @@ import type { IR } from '~/ir/types'; import type { DefinePlugin, Plugin } from '~/plugins'; -import type { StringCase, StringName } from '~/types/case'; +import type { Casing, NameTransformer } from '~/utils/naming'; export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & Plugin.Hooks & { @@ -9,7 +9,7 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Add comments from SDK functions to the generated TanStack Query code? * @@ -41,14 +41,14 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & */ infiniteQueryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query key helpers. * @@ -62,7 +62,7 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & * @default '{{name}}InfiniteQueryKey' * @see https://tanstack.com/query/v5/docs/framework/angular/reference/infiniteQueryOptions */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -85,14 +85,14 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & */ infiniteQueryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query options helpers. * @@ -128,7 +128,7 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & * @default '{{name}}InfiniteOptions' * @see https://tanstack.com/query/v5/docs/framework/angular/reference/infiniteQueryOptions */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated mutation options helpers. @@ -144,14 +144,14 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & */ mutationOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate mutation options helpers. * @@ -187,7 +187,7 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & * @default '{{name}}Mutation' * @see https://tanstack.com/query/v5/docs/framework/angular/reference/useMutation */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated query keys. @@ -203,14 +203,14 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & */ queryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query keys. * @@ -224,7 +224,7 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & * @default '{{name}}QueryKey' * @see https://tanstack.com/query/v5/docs/framework/angular/reference/queryKey */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -247,14 +247,14 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & */ queryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query options helpers. * @@ -296,7 +296,7 @@ export type UserConfig = Plugin.Name<'@tanstack/angular-query-experimental'> & * @default '{{name}}Options' * @see https://tanstack.com/query/v5/docs/framework/angular/reference/queryOptions */ - name?: StringName; + name?: NameTransformer; }; }; @@ -307,7 +307,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Add comments from SDK functions to the generated TanStack Query code? * @@ -331,7 +331,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query key helpers. * @@ -345,7 +345,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * @default '{{name}}InfiniteQueryKey' * @see https://tanstack.com/query/v5/docs/framework/angular/reference/infiniteQueryOptions */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -365,7 +365,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query options helpers. * @@ -401,7 +401,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * @default '{{name}}InfiniteOptions' * @see https://tanstack.com/query/v5/docs/framework/angular/reference/infiniteQueryOptions */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated mutation options helpers. @@ -414,7 +414,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate mutation options helpers. * @@ -450,7 +450,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * @default '{{name}}Mutation' * @see https://tanstack.com/query/v5/docs/framework/angular/reference/useMutation */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated query keys. @@ -463,7 +463,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query keys. * @@ -477,7 +477,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * @default '{{name}}QueryKey' * @see https://tanstack.com/query/v5/docs/framework/angular/reference/queryKey */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -497,7 +497,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query options helpers. * @@ -539,7 +539,7 @@ export type Config = Plugin.Name<'@tanstack/angular-query-experimental'> & * @default '{{name}}Options' * @see https://tanstack.com/query/v5/docs/framework/angular/reference/queryOptions */ - name: StringName; + name: NameTransformer; }; }; diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/queryKey.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/queryKey.ts index 84dbd7d11..d59416aec 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/queryKey.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/queryKey.ts @@ -3,10 +3,10 @@ import type ts from 'typescript'; import { hasOperationDataRequired } from '~/ir/operation'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { getClientBaseUrlKey } from '~/plugins/@hey-api/client-core/utils'; import type { TsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { useTypeData } from './shared/useType'; import type { PluginInstance } from './types'; @@ -18,19 +18,18 @@ export const createQueryKeyFunction = ({ }: { plugin: PluginInstance; }) => { - const symbolCreateQueryKey = plugin.registerSymbol({ - meta: { - category: 'utility', - resource: 'createQueryKey', - tool: plugin.name, - }, - name: buildName({ - config: { - case: plugin.config.case, - }, - name: 'createQueryKey', + const symbolCreateQueryKey = plugin.symbol( + applyNaming('createQueryKey', { + case: plugin.config.case, }), - }); + { + meta: { + category: 'utility', + resource: 'createQueryKey', + tool: plugin.name, + }, + }, + ); const symbolQueryKeyType = plugin.referenceSymbol({ category: 'type', resource: 'QueryKey', @@ -140,13 +139,12 @@ export const createQueryKeyType = ({ plugin }: { plugin: PluginInstance }) => { resource: 'client-options', tool: 'sdk', }); - const symbolQueryKeyType = plugin.registerSymbol({ + const symbolQueryKeyType = plugin.symbol('QueryKey', { meta: { category: 'type', resource: 'QueryKey', tool: plugin.name, }, - name: 'QueryKey', }); const queryKeyType = $.type .alias(symbolQueryKeyType) diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts index ff684aa44..dcca19314 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts @@ -2,13 +2,13 @@ import { ref } from '@hey-api/codegen-core'; import { operationPagination } from '~/ir/operation'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { createOperationComment, isOperationOptionsRequired, } from '~/plugins/shared/utils/operation'; import type { TsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { createQueryKeyFunction, @@ -24,19 +24,18 @@ const createInfiniteParamsFunction = ({ }: { plugin: PluginInstance; }) => { - const symbolCreateInfiniteParams = plugin.registerSymbol({ - meta: { - category: 'utility', - resource: 'createInfiniteParams', - tool: plugin.name, - }, - name: buildName({ - config: { - case: plugin.config.case, - }, - name: 'createInfiniteParams', + const symbolCreateInfiniteParams = plugin.symbol( + applyNaming('createInfiniteParams', { + case: plugin.config.case, }), - }); + { + meta: { + category: 'utility', + resource: 'createInfiniteParams', + tool: plugin.name, + }, + }, + ); const fn = $.const(symbolCreateInfiniteParams).assign( $.func() @@ -181,12 +180,9 @@ export const createInfiniteQueryOptions = ({ }, }); - const symbolInfiniteQueryKey = plugin.registerSymbol({ - name: buildName({ - config: plugin.config.infiniteQueryKeys, - name: operation.id, - }), - }); + const symbolInfiniteQueryKey = plugin.symbol( + applyNaming(operation.id, plugin.config.infiniteQueryKeys), + ); const node = queryKeyStatement({ isInfinite: true, operation, @@ -251,12 +247,9 @@ export const createInfiniteQueryOptions = ({ ); } - const symbolInfiniteQueryOptionsFn = plugin.registerSymbol({ - name: buildName({ - config: plugin.config.infiniteQueryOptions, - name: operation.id, - }), - }); + const symbolInfiniteQueryOptionsFn = plugin.symbol( + applyNaming(operation.id, plugin.config.infiniteQueryOptions), + ); const statement = $.const(symbolInfiniteQueryOptionsFn) .export() .$if(plugin.config.comments && createOperationComment(operation), (c, v) => diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts index 4922cc46e..1a42526ee 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts @@ -1,8 +1,8 @@ import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { createOperationComment } from '~/plugins/shared/utils/operation'; import type { TsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { handleMeta } from '../shared/meta'; import { useTypeData, useTypeError, useTypeResponse } from '../shared/useType'; @@ -58,10 +58,7 @@ export const createMutationOptions = ({ const mutationOptionsFn = 'mutationOptions'; const symbolMutationOptions = plugin.symbol( - buildName({ - config: plugin.config.mutationOptions, - name: operation.id, - }), + applyNaming(operation.id, plugin.config.mutationOptions), ); const statement = $.const(symbolMutationOptions) .export() diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts index 6d1ab7650..61dc8a667 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts @@ -1,5 +1,4 @@ import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { createOperationComment, hasOperationSse, @@ -7,6 +6,7 @@ import { } from '~/plugins/shared/utils/operation'; import type { TsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { createQueryKeyFunction, @@ -51,12 +51,9 @@ export const createQueryOptions = ({ resource: `${plugin.name}.queryOptions`, }); - const symbolQueryKey = plugin.registerSymbol({ - name: buildName({ - config: plugin.config.queryKeys, - name: operation.id, - }), - }); + const symbolQueryKey = plugin.symbol( + applyNaming(operation.id, plugin.config.queryKeys), + ); const node = queryKeyStatement({ isInfinite: false, operation, @@ -110,19 +107,18 @@ export const createQueryOptions = ({ o.prop('meta', v), ); - const symbolQueryOptionsFn = plugin.registerSymbol({ - meta: { - category: 'hook', - resource: 'operation', - resourceId: operation.id, - role: 'queryOptions', - tool: plugin.name, + const symbolQueryOptionsFn = plugin.symbol( + applyNaming(operation.id, plugin.config.queryOptions), + { + meta: { + category: 'hook', + resource: 'operation', + resourceId: operation.id, + role: 'queryOptions', + tool: plugin.name, + }, }, - name: buildName({ - config: plugin.config.queryOptions, - name: operation.id, - }), - }); + ); // TODO: add type error // TODO: AxiosError const statement = $.const(symbolQueryOptionsFn) diff --git a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/useQuery.ts b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/useQuery.ts index a053528df..fa08ff11b 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/useQuery.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/query-core/v5/useQuery.ts @@ -1,11 +1,11 @@ import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { createOperationComment, hasOperationSse, isOperationOptionsRequired, } from '~/plugins/shared/utils/operation'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { useTypeData } from '../shared/useType'; import type { PluginInstance } from '../types'; @@ -27,12 +27,9 @@ export const createUseQuery = ({ return; } - const symbolUseQueryFn = plugin.registerSymbol({ - name: buildName({ - config: plugin.config.useQuery, - name: operation.id, - }), - }); + const symbolUseQueryFn = plugin.symbol( + applyNaming(operation.id, plugin.config.useQuery), + ); const symbolUseQuery = plugin.referenceSymbol({ category: 'external', diff --git a/packages/openapi-ts/src/plugins/@tanstack/react-query/types.d.ts b/packages/openapi-ts/src/plugins/@tanstack/react-query/types.d.ts index 417cff929..1a65195a5 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/react-query/types.d.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/react-query/types.d.ts @@ -1,6 +1,6 @@ import type { IR } from '~/ir/types'; import type { DefinePlugin, Plugin } from '~/plugins'; -import type { StringCase, StringName } from '~/types/case'; +import type { Casing, NameTransformer } from '~/utils/naming'; export type UserConfig = Plugin.Name<'@tanstack/react-query'> & Plugin.Hooks & { @@ -9,7 +9,7 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Add comments from SDK functions to the generated TanStack Query code? * @@ -42,14 +42,14 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & */ infiniteQueryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query key helpers. * @@ -64,7 +64,7 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & * * @default '{{name}}InfiniteQueryKey' */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -87,14 +87,14 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & */ infiniteQueryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query options helpers. * @@ -132,7 +132,7 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & * * @default '{{name}}InfiniteOptions' */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated mutation options helpers. @@ -148,14 +148,14 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & */ mutationOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate mutation options helpers. * @@ -193,7 +193,7 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & * * @default '{{name}}Mutation' */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated query keys. @@ -209,14 +209,14 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & */ queryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query keys. * @@ -231,7 +231,7 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & * * @default '{{name}}QueryKey' */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -254,14 +254,14 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & */ queryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query options helpers. * @@ -305,7 +305,7 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & * * @default '{{name}}Options' */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated `useQuery()` function helpers. @@ -321,14 +321,14 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & */ useQuery?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate `useQuery()` function helpers. * @@ -343,7 +343,7 @@ export type UserConfig = Plugin.Name<'@tanstack/react-query'> & * * @default 'use{{name}}Query' */ - name?: StringName; + name?: NameTransformer; }; }; @@ -354,7 +354,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Add comments from SDK functions to the generated TanStack Query code? * @@ -378,7 +378,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query key helpers. * @@ -392,7 +392,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default '{{name}}InfiniteQueryKey' */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -412,7 +412,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query options helpers. * @@ -449,7 +449,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default '{{name}}InfiniteOptions' */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated mutation options helpers. @@ -462,7 +462,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate mutation options helpers. * @@ -499,7 +499,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default '{{name}}Mutation' */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated query keys. @@ -512,7 +512,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query keys. * @@ -526,7 +526,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default '{{name}}QueryKey' */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -546,7 +546,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query options helpers. * @@ -589,7 +589,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default '{{name}}Options' */ - name: StringName; + name: NameTransformer; }; /** * Configuration for generated `useQuery()` function helpers. @@ -602,7 +602,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate `useQuery()` function helpers. * @@ -617,7 +617,7 @@ export type Config = Plugin.Name<'@tanstack/react-query'> & * * @default 'use{{name}}Query' */ - name: StringName; + name: NameTransformer; }; }; diff --git a/packages/openapi-ts/src/plugins/@tanstack/solid-query/types.d.ts b/packages/openapi-ts/src/plugins/@tanstack/solid-query/types.d.ts index 7aa9019e2..7e81b0575 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/solid-query/types.d.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/solid-query/types.d.ts @@ -1,6 +1,6 @@ import type { IR } from '~/ir/types'; import type { DefinePlugin, Plugin } from '~/plugins'; -import type { StringCase, StringName } from '~/types/case'; +import type { Casing, NameTransformer } from '~/utils/naming'; export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & Plugin.Hooks & { @@ -9,7 +9,7 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Add comments from SDK functions to the generated TanStack Query code? * @@ -41,14 +41,14 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & */ infiniteQueryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query key helpers. * @@ -62,7 +62,7 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & * @default '{{name}}InfiniteQueryKey' * @see https://tanstack.com/query/v5/docs/framework/solid/reference/createInfiniteQuery */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -85,14 +85,14 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & */ infiniteQueryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query options helpers. * @@ -129,7 +129,7 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & * @default '{{name}}InfiniteOptions' * @see https://tanstack.com/query/v5/docs/framework/solid/reference/createInfiniteQuery */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated mutation options helpers. @@ -145,14 +145,14 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & */ mutationOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate mutation options helpers. * @@ -188,7 +188,7 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & * @default '{{name}}Mutation' * @see https://tanstack.com/query/v5/docs/framework/solid/reference/createMutation */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated query keys. @@ -204,14 +204,14 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & */ queryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query keys. * @@ -225,7 +225,7 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & * @default '{{name}}QueryKey' * @see https://tanstack.com/query/v5/docs/framework/solid/reference/queryKey */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -248,14 +248,14 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & */ queryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query options helpers. * @@ -297,7 +297,7 @@ export type UserConfig = Plugin.Name<'@tanstack/solid-query'> & * @default '{{name}}Options' * @see https://tanstack.com/query/v5/docs/framework/solid/reference/createQuery */ - name?: StringName; + name?: NameTransformer; }; }; @@ -308,7 +308,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Add comments from SDK functions to the generated TanStack Query code? * @@ -332,7 +332,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query key helpers. * @@ -346,7 +346,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * @default '{{name}}InfiniteQueryKey' * @see https://tanstack.com/query/v5/docs/framework/solid/reference/createInfiniteQuery */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -366,7 +366,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query options helpers. * @@ -402,7 +402,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * @default '{{name}}InfiniteOptions' * @see https://tanstack.com/query/v5/docs/framework/solid/reference/createInfiniteQuery */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated mutation options helpers. @@ -415,7 +415,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate mutation options helpers. * @@ -451,7 +451,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * @default '{{name}}Mutation' * @see https://tanstack.com/query/v5/docs/framework/solid/reference/createMutation */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated query keys. @@ -464,7 +464,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query keys. * @@ -478,7 +478,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * @default '{{name}}QueryKey' * @see https://tanstack.com/query/v5/docs/framework/solid/reference/queryKey */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -498,7 +498,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query options helpers. * @@ -540,7 +540,7 @@ export type Config = Plugin.Name<'@tanstack/solid-query'> & * @default '{{name}}Options' * @see https://tanstack.com/query/v5/docs/framework/solid/reference/createQuery */ - name: StringName; + name: NameTransformer; }; }; diff --git a/packages/openapi-ts/src/plugins/@tanstack/svelte-query/types.d.ts b/packages/openapi-ts/src/plugins/@tanstack/svelte-query/types.d.ts index 9d69a849e..e6bd35155 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/svelte-query/types.d.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/svelte-query/types.d.ts @@ -1,6 +1,6 @@ import type { IR } from '~/ir/types'; import type { DefinePlugin, Plugin } from '~/plugins'; -import type { StringCase, StringName } from '~/types/case'; +import type { Casing, NameTransformer } from '~/utils/naming'; export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & Plugin.Hooks & { @@ -9,7 +9,7 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Add comments from SDK functions to the generated TanStack Query code? * @@ -41,14 +41,14 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & */ infiniteQueryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query key helpers. * @@ -62,7 +62,7 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & * @default '{{name}}InfiniteQueryKey' * @see https://tanstack.com/query/v5/docs/framework/svelte/reference/functions/createinfinitequery */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -85,14 +85,14 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & */ infiniteQueryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query options helpers. * @@ -128,7 +128,7 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & * @default '{{name}}InfiniteOptions' * @see https://tanstack.com/query/v5/docs/framework/svelte/reference/functions/createinfinitequery */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated mutation options helpers. @@ -144,14 +144,14 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & */ mutationOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate mutation options helpers. * @@ -187,7 +187,7 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & * @default '{{name}}Mutation' * @see https://tanstack.com/query/v5/docs/framework/svelte/reference/functions/createmutation */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated query keys. @@ -203,14 +203,14 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & */ queryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query keys. * @@ -224,7 +224,7 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & * @default '{{name}}QueryKey' * @see https://tanstack.com/query/v5/docs/framework/react/guides/query-keys */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -247,14 +247,14 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & */ queryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query options helpers. * @@ -296,7 +296,7 @@ export type UserConfig = Plugin.Name<'@tanstack/svelte-query'> & * @default '{{name}}Options' * @see https://tanstack.com/query/v5/docs/framework/svelte/reference/functions/createquery */ - name?: StringName; + name?: NameTransformer; }; }; @@ -307,7 +307,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Add comments from SDK functions to the generated TanStack Query code? * @@ -331,7 +331,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query key helpers. * @@ -345,7 +345,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * @default '{{name}}InfiniteQueryKey' * @see https://tanstack.com/query/v5/docs/framework/svelte/reference/functions/createinfinitequery */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -365,7 +365,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query options helpers. * @@ -401,7 +401,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * @default '{{name}}InfiniteOptions' * @see https://tanstack.com/query/v5/docs/framework/svelte/reference/functions/createinfinitequery */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated mutation options helpers. @@ -414,7 +414,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate mutation options helpers. * @@ -450,7 +450,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * @default '{{name}}Mutation' * @see https://tanstack.com/query/v5/docs/framework/svelte/reference/functions/createmutation */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated query keys. @@ -463,7 +463,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query keys. * @@ -477,7 +477,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * @default '{{name}}QueryKey' * @see https://tanstack.com/query/v5/docs/framework/react/guides/query-keys */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -497,7 +497,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query options helpers. * @@ -539,7 +539,7 @@ export type Config = Plugin.Name<'@tanstack/svelte-query'> & * @default '{{name}}Options' * @see https://tanstack.com/query/v5/docs/framework/svelte/reference/functions/createquery */ - name: StringName; + name: NameTransformer; }; }; diff --git a/packages/openapi-ts/src/plugins/@tanstack/vue-query/types.d.ts b/packages/openapi-ts/src/plugins/@tanstack/vue-query/types.d.ts index 0423081dc..14dac984a 100644 --- a/packages/openapi-ts/src/plugins/@tanstack/vue-query/types.d.ts +++ b/packages/openapi-ts/src/plugins/@tanstack/vue-query/types.d.ts @@ -1,6 +1,6 @@ import type { IR } from '~/ir/types'; import type { DefinePlugin, Plugin } from '~/plugins'; -import type { StringCase, StringName } from '~/types/case'; +import type { Casing, NameTransformer } from '~/utils/naming'; export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & Plugin.Hooks & { @@ -9,7 +9,7 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Add comments from SDK functions to the generated TanStack Query code? * @@ -41,14 +41,14 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & */ infiniteQueryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query key helpers. * @@ -62,7 +62,7 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & * @default '{{name}}InfiniteQueryKey' * @see https://tanstack.com/query/v5/docs/framework/vue/reference/infiniteQueryOptions */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -85,14 +85,14 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & */ infiniteQueryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query options helpers. * @@ -129,7 +129,7 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & * @default '{{name}}InfiniteOptions' * @see https://tanstack.com/query/v5/docs/framework/vue/reference/infiniteQueryOptions */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated mutation options helpers. @@ -145,14 +145,14 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & */ mutationOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate mutation options helpers. * @@ -189,7 +189,7 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & * @default '{{name}}Mutation' * @see https://tanstack.com/query/v5/docs/framework/vue/reference/useMutation */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated query keys. @@ -205,14 +205,14 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & */ queryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query keys. * @@ -226,7 +226,7 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & * @default '{{name}}QueryKey' * @see https://tanstack.com/query/v5/docs/framework/vue/reference/queryKey */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -249,14 +249,14 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & */ queryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query options helpers. * @@ -299,7 +299,7 @@ export type UserConfig = Plugin.Name<'@tanstack/vue-query'> & * @default '{{name}}Options' * @see https://tanstack.com/query/v5/docs/framework/vue/reference/queryOptions */ - name?: StringName; + name?: NameTransformer; }; }; @@ -310,7 +310,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Add comments from SDK functions to the generated TanStack Query code? * @@ -334,7 +334,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query key helpers. * @@ -348,7 +348,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * @default '{{name}}InfiniteQueryKey' * @see https://tanstack.com/query/v5/docs/framework/vue/reference/infiniteQueryOptions */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -368,7 +368,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query options helpers. * @@ -405,7 +405,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * @default '{{name}}InfiniteOptions' * @see https://tanstack.com/query/v5/docs/framework/vue/reference/infiniteQueryOptions */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated mutation options helpers. @@ -418,7 +418,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate mutation options helpers. * @@ -455,7 +455,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * @default '{{name}}Mutation' * @see https://tanstack.com/query/v5/docs/framework/vue/reference/useMutation */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated query keys. @@ -468,7 +468,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query keys. * @@ -482,7 +482,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * @default '{{name}}QueryKey' * @see https://tanstack.com/query/v5/docs/framework/vue/reference/queryKey */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -502,7 +502,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query options helpers. * @@ -545,7 +545,7 @@ export type Config = Plugin.Name<'@tanstack/vue-query'> & * @default '{{name}}Options' * @see https://tanstack.com/query/v5/docs/framework/vue/reference/queryOptions */ - name: StringName; + name: NameTransformer; }; }; diff --git a/packages/openapi-ts/src/plugins/arktype/types.d.ts b/packages/openapi-ts/src/plugins/arktype/types.d.ts index 744ac7c62..54c984810 100644 --- a/packages/openapi-ts/src/plugins/arktype/types.d.ts +++ b/packages/openapi-ts/src/plugins/arktype/types.d.ts @@ -1,5 +1,5 @@ import type { DefinePlugin, Plugin } from '~/plugins'; -import type { StringCase, StringName } from '~/types/case'; +import type { Casing, NameTransformer } from '~/utils/naming'; import type { IApi } from './api'; @@ -10,7 +10,7 @@ export type UserConfig = Plugin.Name<'arktype'> & * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Add comments from input to the generated Arktype schemas? * @@ -30,14 +30,14 @@ export type UserConfig = Plugin.Name<'arktype'> & */ definitions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Arktype schemas for reusable definitions. * @@ -50,7 +50,7 @@ export type UserConfig = Plugin.Name<'arktype'> & * * @default '{{name}}' */ - name?: StringName; + name?: NameTransformer; /** * Configuration for TypeScript type generation from Arktype schemas. * @@ -69,14 +69,14 @@ export type UserConfig = Plugin.Name<'arktype'> & */ infer?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate TypeScript types from Arktype schemas. * @@ -89,7 +89,7 @@ export type UserConfig = Plugin.Name<'arktype'> & * * @default '{{name}}' */ - name?: StringName; + name?: NameTransformer; }; }; }; @@ -123,14 +123,14 @@ export type UserConfig = Plugin.Name<'arktype'> & */ requests?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Arktype schemas for request definitions. * @@ -143,7 +143,7 @@ export type UserConfig = Plugin.Name<'arktype'> & * * @default '{{name}}Data' */ - name?: StringName; + name?: NameTransformer; /** * Configuration for TypeScript type generation from Arktype schemas. * @@ -162,14 +162,14 @@ export type UserConfig = Plugin.Name<'arktype'> & */ infer?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate TypeScript types from Arktype schemas. * @@ -182,7 +182,7 @@ export type UserConfig = Plugin.Name<'arktype'> & * * @default '{{name}}Data' */ - name?: StringName; + name?: NameTransformer; }; }; }; @@ -201,14 +201,14 @@ export type UserConfig = Plugin.Name<'arktype'> & */ responses?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Arktype schemas for response definitions. * @@ -221,7 +221,7 @@ export type UserConfig = Plugin.Name<'arktype'> & * * @default '{{name}}Response' */ - name?: StringName; + name?: NameTransformer; /** * Configuration for TypeScript type generation from Arktype schemas. * @@ -240,14 +240,14 @@ export type UserConfig = Plugin.Name<'arktype'> & */ infer?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate TypeScript types from Arktype schemas. * @@ -260,7 +260,7 @@ export type UserConfig = Plugin.Name<'arktype'> & * * @default '{{name}}Response' */ - name?: StringName; + name?: NameTransformer; }; }; }; @@ -282,14 +282,14 @@ export type UserConfig = Plugin.Name<'arktype'> & */ infer?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate TypeScript types from Arktype schemas. * @@ -312,14 +312,14 @@ export type UserConfig = Plugin.Name<'arktype'> & */ webhooks?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Arktype schemas for webhook definitions. * @@ -332,7 +332,7 @@ export type UserConfig = Plugin.Name<'arktype'> & * * @default '{{name}}WebhookRequest' */ - name?: StringName; + name?: NameTransformer; /** * Configuration for TypeScript type generation from Arktype schemas. * @@ -351,14 +351,14 @@ export type UserConfig = Plugin.Name<'arktype'> & */ infer?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate TypeScript types from Arktype schemas. * @@ -371,7 +371,7 @@ export type UserConfig = Plugin.Name<'arktype'> & * * @default '{{name}}WebhookRequest' */ - name?: StringName; + name?: NameTransformer; }; }; }; @@ -384,7 +384,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Add comments from input to the generated Arktype schemas? * @@ -403,7 +403,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Arktype schemas for reusable definitions. * @@ -416,7 +416,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default '{{name}}' */ - name: StringName; + name: NameTransformer; /** * Configuration for TypeScript type generation from Arktype schemas. * @@ -432,7 +432,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate TypeScript types from Arktype schemas. * @@ -445,7 +445,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default '{{name}}' */ - name: StringName; + name: NameTransformer; }; }; }; @@ -476,7 +476,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Arktype schemas for request definitions. * @@ -489,7 +489,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default '{{name}}Data' */ - name: StringName; + name: NameTransformer; /** * Configuration for TypeScript type generation from Arktype schemas. * @@ -505,7 +505,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate TypeScript types from Arktype schemas. * @@ -518,7 +518,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default '{{name}}Data' */ - name: StringName; + name: NameTransformer; }; }; }; @@ -534,7 +534,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Arktype schemas for response definitions. * @@ -547,7 +547,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default '{{name}}Response' */ - name: StringName; + name: NameTransformer; /** * Configuration for TypeScript type generation from Arktype schemas. * @@ -563,7 +563,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate TypeScript types from Arktype schemas. * @@ -576,7 +576,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default '{{name}}Response' */ - name: StringName; + name: NameTransformer; }; }; }; @@ -595,7 +595,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate TypeScript types from Arktype schemas. * @@ -615,7 +615,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Arktype schemas for webhook definitions. * @@ -628,7 +628,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default '{{name}}WebhookRequest' */ - name: StringName; + name: NameTransformer; /** * Configuration for TypeScript type generation from Arktype schemas. * @@ -644,7 +644,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate TypeScript types from Arktype schemas. * @@ -657,7 +657,7 @@ export type Config = Plugin.Name<'arktype'> & * * @default '{{name}}WebhookRequest' */ - name: StringName; + name: NameTransformer; }; }; }; diff --git a/packages/openapi-ts/src/plugins/arktype/v2/plugin.ts b/packages/openapi-ts/src/plugins/arktype/v2/plugin.ts index fb8273a0a..757aff340 100644 --- a/packages/openapi-ts/src/plugins/arktype/v2/plugin.ts +++ b/packages/openapi-ts/src/plugins/arktype/v2/plugin.ts @@ -3,9 +3,9 @@ import { fromRef, refs } from '@hey-api/codegen-core'; import { deduplicateSchema } from '~/ir/schema'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import type { SchemaWithType } from '~/plugins/shared/types/schema'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { pathToJsonPointer, refToName } from '~/utils/ref'; import { exportAst } from '../shared/export'; @@ -242,35 +242,33 @@ const handleComponent = ({ const $ref = pathToJsonPointer(fromRef(state.path)); const ast = irSchemaToAst({ plugin, schema, state }); const baseName = refToName($ref); - const symbol = plugin.registerSymbol({ - meta: { - category: 'schema', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'arktype', + const symbol = plugin.symbol( + applyNaming(baseName, plugin.config.definitions), + { + meta: { + category: 'schema', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'arktype', + }, }, - name: buildName({ - config: plugin.config.definitions, - name: baseName, - }), - }); + ); const typeInferSymbol = plugin.config.definitions.types.infer.enabled - ? plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tool: 'arktype', - variant: 'infer', + ? plugin.symbol( + applyNaming(baseName, plugin.config.definitions.types.infer), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tool: 'arktype', + variant: 'infer', + }, }, - name: buildName({ - config: plugin.config.definitions.types.infer, - name: baseName, - }), - }) + ) : undefined; exportAst({ ast, @@ -282,13 +280,12 @@ const handleComponent = ({ }; export const handlerV2: ArktypePlugin['Handler'] = ({ plugin }) => { - plugin.registerSymbol({ + plugin.symbol('type', { external: 'arktype', meta: { category: 'external', resource: 'arktype.type', }, - name: 'type', }); plugin.forEach( diff --git a/packages/openapi-ts/src/plugins/fastify/plugin.ts b/packages/openapi-ts/src/plugins/fastify/plugin.ts index 93037101d..3c157600d 100644 --- a/packages/openapi-ts/src/plugins/fastify/plugin.ts +++ b/packages/openapi-ts/src/plugins/fastify/plugin.ts @@ -130,7 +130,7 @@ const operationToRouteHandler = ({ }; export const handler: FastifyPlugin['Handler'] = ({ plugin }) => { - plugin.registerSymbol({ + plugin.symbol('RouteHandler', { external: 'fastify', kind: 'type', meta: { @@ -138,12 +138,9 @@ export const handler: FastifyPlugin['Handler'] = ({ plugin }) => { resource: 'route-handler', tool: 'fastify', }, - name: 'RouteHandler', }); - const symbolRouteHandlers = plugin.registerSymbol({ - name: 'RouteHandlers', - }); + const symbolRouteHandlers = plugin.symbol('RouteHandlers'); const type = $.type.object(); diff --git a/packages/openapi-ts/src/plugins/swr/types.d.ts b/packages/openapi-ts/src/plugins/swr/types.d.ts index 2d32551ad..35f5f1164 100644 --- a/packages/openapi-ts/src/plugins/swr/types.d.ts +++ b/packages/openapi-ts/src/plugins/swr/types.d.ts @@ -1,6 +1,6 @@ import type { IR } from '~/ir/types'; import type { DefinePlugin, Plugin } from '~/plugins'; -import type { StringCase, StringName } from '~/types/case'; +import type { Casing, NameTransformer } from '~/utils/naming'; export type UserConfig = Plugin.Name<'swr'> & Plugin.Hooks & { @@ -9,7 +9,7 @@ export type UserConfig = Plugin.Name<'swr'> & * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Add comments from SDK functions to the generated SWR code? * @@ -42,14 +42,14 @@ export type UserConfig = Plugin.Name<'swr'> & */ infiniteQueryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query key helpers. * @@ -64,7 +64,7 @@ export type UserConfig = Plugin.Name<'swr'> & * * @default '{{name}}InfiniteQueryKey' */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -87,14 +87,14 @@ export type UserConfig = Plugin.Name<'swr'> & */ infiniteQueryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate infinite query options helpers. * @@ -132,7 +132,7 @@ export type UserConfig = Plugin.Name<'swr'> & * * @default '{{name}}InfiniteOptions' */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated mutation options helpers. @@ -148,14 +148,14 @@ export type UserConfig = Plugin.Name<'swr'> & */ mutationOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate mutation options helpers. * @@ -193,7 +193,7 @@ export type UserConfig = Plugin.Name<'swr'> & * * @default '{{name}}Mutation' */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated query keys. @@ -209,14 +209,14 @@ export type UserConfig = Plugin.Name<'swr'> & */ queryKeys?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query keys. * @@ -231,7 +231,7 @@ export type UserConfig = Plugin.Name<'swr'> & * * @default '{{name}}QueryKey' */ - name?: StringName; + name?: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -254,14 +254,14 @@ export type UserConfig = Plugin.Name<'swr'> & */ queryOptions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate query options helpers. * @@ -305,7 +305,7 @@ export type UserConfig = Plugin.Name<'swr'> & * * @default '{{name}}Options' */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated `useSwr()` function helpers. @@ -321,14 +321,14 @@ export type UserConfig = Plugin.Name<'swr'> & */ useSwr?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate `useSwr()` function helpers. * @@ -343,7 +343,7 @@ export type UserConfig = Plugin.Name<'swr'> & * * @default 'use{{name}}' */ - name?: StringName; + name?: NameTransformer; }; }; @@ -354,7 +354,7 @@ export type Config = Plugin.Name<'swr'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Add comments from SDK functions to the generated SWR code? * @@ -378,7 +378,7 @@ export type Config = Plugin.Name<'swr'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query key helpers. * @@ -392,7 +392,7 @@ export type Config = Plugin.Name<'swr'> & * * @default '{{name}}InfiniteQueryKey' */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in infinite query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -412,7 +412,7 @@ export type Config = Plugin.Name<'swr'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate infinite query options helpers. * @@ -449,7 +449,7 @@ export type Config = Plugin.Name<'swr'> & * * @default '{{name}}InfiniteOptions' */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated mutation options helpers. @@ -462,7 +462,7 @@ export type Config = Plugin.Name<'swr'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate mutation options helpers. * @@ -499,7 +499,7 @@ export type Config = Plugin.Name<'swr'> & * * @default '{{name}}Mutation' */ - name: StringName; + name: NameTransformer; }; /** * Resolved configuration for generated query keys. @@ -512,7 +512,7 @@ export type Config = Plugin.Name<'swr'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query keys. * @@ -526,7 +526,7 @@ export type Config = Plugin.Name<'swr'> & * * @default '{{name}}QueryKey' */ - name: StringName; + name: NameTransformer; /** * Whether to include operation tags in query keys. * This will make query keys larger but provides better cache invalidation capabilities. @@ -546,7 +546,7 @@ export type Config = Plugin.Name<'swr'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate query options helpers. * @@ -589,7 +589,7 @@ export type Config = Plugin.Name<'swr'> & * * @default '{{name}}Options' */ - name: StringName; + name: NameTransformer; }; /** * Configuration for generated `useSwr()` function helpers. @@ -602,7 +602,7 @@ export type Config = Plugin.Name<'swr'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate `useSwr()` function helpers. * @@ -617,7 +617,7 @@ export type Config = Plugin.Name<'swr'> & * * @default 'use{{name}}' */ - name: StringName; + name: NameTransformer; }; }; diff --git a/packages/openapi-ts/src/plugins/swr/v2/plugin.ts b/packages/openapi-ts/src/plugins/swr/v2/plugin.ts index 8554dc7f8..61be0e93e 100644 --- a/packages/openapi-ts/src/plugins/swr/v2/plugin.ts +++ b/packages/openapi-ts/src/plugins/swr/v2/plugin.ts @@ -2,7 +2,7 @@ import type { SwrPlugin } from '../types'; import { createUseSwr } from './useSwr'; export const handlerV2: SwrPlugin['Handler'] = ({ plugin }) => { - plugin.registerSymbol({ + plugin.symbol('useSWR', { external: 'swr', importKind: 'default', kind: 'function', @@ -10,7 +10,6 @@ export const handlerV2: SwrPlugin['Handler'] = ({ plugin }) => { category: 'external', resource: 'swr', }, - name: 'useSWR', }); plugin.forEach( diff --git a/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts b/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts index 6106ca74d..ff0de7994 100644 --- a/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts +++ b/packages/openapi-ts/src/plugins/swr/v2/useSwr.ts @@ -1,11 +1,11 @@ import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import { createOperationComment, hasOperationSse, } from '~/plugins/shared/utils/operation'; import type { TsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import type { SwrPlugin } from '../types'; @@ -24,12 +24,9 @@ export const createUseSwr = ({ category: 'external', resource: 'swr', }); - const symbolUseQueryFn = plugin.registerSymbol({ - name: buildName({ - config: plugin.config.useSwr, - name: operation.id, - }), - }); + const symbolUseQueryFn = plugin.symbol( + applyNaming(operation.id, plugin.config.useSwr), + ); const awaitSdkFn = $.lazy((ctx) => ctx diff --git a/packages/openapi-ts/src/plugins/valibot/shared/operation.ts b/packages/openapi-ts/src/plugins/valibot/shared/operation.ts index 60aea87a2..1964f3a2d 100644 --- a/packages/openapi-ts/src/plugins/valibot/shared/operation.ts +++ b/packages/openapi-ts/src/plugins/valibot/shared/operation.ts @@ -2,7 +2,7 @@ import { fromRef } from '@hey-api/codegen-core'; import { operationResponsesMap } from '~/ir/operation'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; +import { applyNaming } from '~/utils/naming'; import { exportAst } from './export'; import type { Ast, IrSchemaToAstOptions } from './types'; @@ -118,21 +118,20 @@ export const irOperationToAst = ({ schemaData.required = [...requiredProperties]; const ast = getAst(schemaData, fromRef(state.path)); - const symbol = plugin.registerSymbol({ - meta: { - category: 'schema', - path: fromRef(state.path), - resource: 'operation', - resourceId: operation.id, - role: 'data', - tags: fromRef(state.tags), - tool: 'valibot', + const symbol = plugin.symbol( + applyNaming(operation.id, plugin.config.requests), + { + meta: { + category: 'schema', + path: fromRef(state.path), + resource: 'operation', + resourceId: operation.id, + role: 'data', + tags: fromRef(state.tags), + tool: 'valibot', + }, }, - name: buildName({ - config: plugin.config.requests, - name: operation.id, - }), - }); + ); exportAst({ ast, plugin, @@ -149,21 +148,20 @@ export const irOperationToAst = ({ if (response) { const path = [...fromRef(state.path), 'responses']; const ast = getAst(response, path); - const symbol = plugin.registerSymbol({ - meta: { - category: 'schema', - path, - resource: 'operation', - resourceId: operation.id, - role: 'responses', - tags: fromRef(state.tags), - tool: 'valibot', + const symbol = plugin.symbol( + applyNaming(operation.id, plugin.config.responses), + { + meta: { + category: 'schema', + path, + resource: 'operation', + resourceId: operation.id, + role: 'responses', + tags: fromRef(state.tags), + tool: 'valibot', + }, }, - name: buildName({ - config: plugin.config.responses, - name: operation.id, - }), - }); + ); exportAst({ ast, plugin, diff --git a/packages/openapi-ts/src/plugins/valibot/shared/webhook.ts b/packages/openapi-ts/src/plugins/valibot/shared/webhook.ts index 1480049ff..eaab0b654 100644 --- a/packages/openapi-ts/src/plugins/valibot/shared/webhook.ts +++ b/packages/openapi-ts/src/plugins/valibot/shared/webhook.ts @@ -1,7 +1,7 @@ import { fromRef } from '@hey-api/codegen-core'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; +import { applyNaming } from '~/utils/naming'; import { exportAst } from './export'; import type { Ast, IrSchemaToAstOptions } from './types'; @@ -117,21 +117,20 @@ export const irWebhookToAst = ({ schemaData.required = [...requiredProperties]; const ast = getAst(schemaData, fromRef(state.path)); - const symbol = plugin.registerSymbol({ - meta: { - category: 'schema', - path: fromRef(state.path), - resource: 'webhook', - resourceId: operation.id, - role: 'data', - tags: fromRef(state.tags), - tool: 'valibot', + const symbol = plugin.symbol( + applyNaming(operation.id, plugin.config.webhooks), + { + meta: { + category: 'schema', + path: fromRef(state.path), + resource: 'webhook', + resourceId: operation.id, + role: 'data', + tags: fromRef(state.tags), + tool: 'valibot', + }, }, - name: buildName({ - config: plugin.config.webhooks, - name: operation.id, - }), - }); + ); exportAst({ ast, plugin, diff --git a/packages/openapi-ts/src/plugins/valibot/types.d.ts b/packages/openapi-ts/src/plugins/valibot/types.d.ts index 6083251f4..85f76335f 100644 --- a/packages/openapi-ts/src/plugins/valibot/types.d.ts +++ b/packages/openapi-ts/src/plugins/valibot/types.d.ts @@ -8,7 +8,7 @@ import type { } from '~/plugins/shared/utils/coerce'; import type { GetIntegerLimit } from '~/plugins/shared/utils/formats'; import type { $, DollarTsDsl } from '~/ts-dsl'; -import type { StringCase, StringName } from '~/types/case'; +import type { Casing, NameTransformer } from '~/utils/naming'; import type { IApi } from './api'; import type { Pipe, PipeResult, PipesUtils } from './shared/pipes'; @@ -22,7 +22,7 @@ export type UserConfig = Plugin.Name<'valibot'> & * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Add comments from input to the generated Valibot schemas? * @@ -42,14 +42,14 @@ export type UserConfig = Plugin.Name<'valibot'> & */ definitions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Valibot schemas for reusable definitions. * @@ -62,7 +62,7 @@ export type UserConfig = Plugin.Name<'valibot'> & * * @default 'v{{name}}' */ - name?: StringName; + name?: NameTransformer; }; /** * Should the exports from the generated files be re-exported in the index @@ -92,14 +92,14 @@ export type UserConfig = Plugin.Name<'valibot'> & */ requests?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Valibot schemas for request definitions. * @@ -112,7 +112,7 @@ export type UserConfig = Plugin.Name<'valibot'> & * * @default 'v{{name}}Data' */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for response-specific Valibot schemas. @@ -127,14 +127,14 @@ export type UserConfig = Plugin.Name<'valibot'> & */ responses?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Valibot schemas for response definitions. * @@ -147,7 +147,7 @@ export type UserConfig = Plugin.Name<'valibot'> & * * @default 'v{{name}}Response' */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for webhook-specific Valibot schemas. @@ -163,14 +163,14 @@ export type UserConfig = Plugin.Name<'valibot'> & */ webhooks?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Valibot schemas for webhook definitions. * @@ -183,7 +183,7 @@ export type UserConfig = Plugin.Name<'valibot'> & * * @default 'v{{name}}WebhookRequest' */ - name?: StringName; + name?: NameTransformer; }; }; @@ -195,7 +195,7 @@ export type Config = Plugin.Name<'valibot'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Add comments from input to the generated Valibot schemas? * @@ -214,7 +214,7 @@ export type Config = Plugin.Name<'valibot'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Valibot schemas for reusable definitions. * @@ -227,7 +227,7 @@ export type Config = Plugin.Name<'valibot'> & * * @default 'v{{name}}' */ - name: StringName; + name: NameTransformer; }; /** * Should the exports from the generated files be re-exported in the index @@ -256,7 +256,7 @@ export type Config = Plugin.Name<'valibot'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Valibot schemas for request definitions. * @@ -269,7 +269,7 @@ export type Config = Plugin.Name<'valibot'> & * * @default 'v{{name}}Data' */ - name: StringName; + name: NameTransformer; }; /** * Configuration for response-specific Valibot schemas. @@ -283,7 +283,7 @@ export type Config = Plugin.Name<'valibot'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Valibot schemas for response definitions. * @@ -296,7 +296,7 @@ export type Config = Plugin.Name<'valibot'> & * * @default 'v{{name}}Response' */ - name: StringName; + name: NameTransformer; }; /** * Configuration for webhook-specific Valibot schemas. @@ -309,7 +309,7 @@ export type Config = Plugin.Name<'valibot'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Valibot schemas for webhook definitions. * @@ -322,7 +322,7 @@ export type Config = Plugin.Name<'valibot'> & * * @default 'v{{name}}WebhookRequest' */ - name: StringName; + name: NameTransformer; }; }; diff --git a/packages/openapi-ts/src/plugins/valibot/v1/plugin.ts b/packages/openapi-ts/src/plugins/valibot/v1/plugin.ts index 6708f2f3b..e6f401c55 100644 --- a/packages/openapi-ts/src/plugins/valibot/v1/plugin.ts +++ b/packages/openapi-ts/src/plugins/valibot/v1/plugin.ts @@ -3,10 +3,10 @@ import { fromRef, ref, refs } from '@hey-api/codegen-core'; import { deduplicateSchema } from '~/ir/schema'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import type { SchemaWithType } from '~/plugins'; import { maybeBigInt } from '~/plugins/shared/utils/coerce'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { pathToJsonPointer, refToName } from '~/utils/ref'; import { exportAst } from '../shared/export'; @@ -157,20 +157,19 @@ const handleComponent = ({ const $ref = pathToJsonPointer(fromRef(state.path)); const ast = irSchemaToAst({ plugin, schema, state }); const baseName = refToName($ref); - const symbol = plugin.registerSymbol({ - meta: { - category: 'schema', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'valibot', + const symbol = plugin.symbol( + applyNaming(baseName, plugin.config.definitions), + { + meta: { + category: 'schema', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'valibot', + }, }, - name: buildName({ - config: plugin.config.definitions, - name: baseName, - }), - }); + ); exportAst({ ast, plugin, @@ -181,14 +180,13 @@ const handleComponent = ({ }; export const handlerV1: ValibotPlugin['Handler'] = ({ plugin }) => { - plugin.registerSymbol({ + plugin.symbol('v', { external: 'valibot', importKind: 'namespace', meta: { category: 'external', resource: 'valibot.v', }, - name: 'v', }); plugin.forEach( diff --git a/packages/openapi-ts/src/plugins/zod/mini/plugin.ts b/packages/openapi-ts/src/plugins/zod/mini/plugin.ts index da510afd6..80c43a60c 100644 --- a/packages/openapi-ts/src/plugins/zod/mini/plugin.ts +++ b/packages/openapi-ts/src/plugins/zod/mini/plugin.ts @@ -3,10 +3,10 @@ import { fromRef, ref, refs } from '@hey-api/codegen-core'; import { deduplicateSchema } from '~/ir/schema'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import type { SchemaWithType } from '~/plugins'; import { maybeBigInt } from '~/plugins/shared/utils/coerce'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { pathToJsonPointer, refToName } from '~/utils/ref'; import { identifiers } from '../constants'; @@ -176,36 +176,34 @@ const handleComponent = ({ const $ref = pathToJsonPointer(fromRef(state.path)); const ast = irSchemaToAst({ plugin, schema, state }); const baseName = refToName($ref); - const symbol = plugin.registerSymbol({ - meta: { - category: 'schema', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'zod', + const symbol = plugin.symbol( + applyNaming(baseName, plugin.config.definitions), + { + meta: { + category: 'schema', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'zod', + }, }, - name: buildName({ - config: plugin.config.definitions, - name: baseName, - }), - }); + ); const typeInferSymbol = plugin.config.definitions.types.infer.enabled - ? plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'zod', - variant: 'infer', + ? plugin.symbol( + applyNaming(baseName, plugin.config.definitions.types.infer), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'zod', + variant: 'infer', + }, }, - name: buildName({ - config: plugin.config.definitions.types.infer, - name: baseName, - }), - }) + ) : undefined; exportAst({ ast, @@ -217,14 +215,13 @@ const handleComponent = ({ }; export const handlerMini: ZodPlugin['Handler'] = ({ plugin }) => { - plugin.registerSymbol({ + plugin.symbol('z', { external: getZodModule({ plugin }), importKind: 'namespace', meta: { category: 'external', resource: 'zod.z', }, - name: 'z', }); plugin.forEach( diff --git a/packages/openapi-ts/src/plugins/zod/shared/operation.ts b/packages/openapi-ts/src/plugins/zod/shared/operation.ts index 7bc41c05c..85e9e828b 100644 --- a/packages/openapi-ts/src/plugins/zod/shared/operation.ts +++ b/packages/openapi-ts/src/plugins/zod/shared/operation.ts @@ -2,7 +2,7 @@ import { fromRef } from '@hey-api/codegen-core'; import { operationResponsesMap } from '~/ir/operation'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; +import { applyNaming } from '~/utils/naming'; import { exportAst } from './export'; import type { Ast, IrSchemaToAstOptions } from './types'; @@ -119,10 +119,7 @@ export const irOperationToAst = ({ const ast = getAst(schemaData, fromRef(state.path)); const symbol = plugin.symbol( - buildName({ - config: plugin.config.requests, - name: operation.id, - }), + applyNaming(operation.id, plugin.config.requests), { meta: { category: 'schema', @@ -137,10 +134,7 @@ export const irOperationToAst = ({ ); const typeInferSymbol = plugin.config.requests.types.infer.enabled ? plugin.symbol( - buildName({ - config: plugin.config.requests.types.infer, - name: operation.id, - }), + applyNaming(operation.id, plugin.config.requests.types.infer), { meta: { category: 'type', @@ -172,10 +166,7 @@ export const irOperationToAst = ({ const path = [...fromRef(state.path), 'responses']; const ast = getAst(response, path); const symbol = plugin.symbol( - buildName({ - config: plugin.config.responses, - name: operation.id, - }), + applyNaming(operation.id, plugin.config.responses), { meta: { category: 'schema', @@ -190,10 +181,7 @@ export const irOperationToAst = ({ ); const typeInferSymbol = plugin.config.responses.types.infer.enabled ? plugin.symbol( - buildName({ - config: plugin.config.responses.types.infer, - name: operation.id, - }), + applyNaming(operation.id, plugin.config.responses.types.infer), { meta: { category: 'type', diff --git a/packages/openapi-ts/src/plugins/zod/shared/webhook.ts b/packages/openapi-ts/src/plugins/zod/shared/webhook.ts index 9fdff26aa..a1e268e4f 100644 --- a/packages/openapi-ts/src/plugins/zod/shared/webhook.ts +++ b/packages/openapi-ts/src/plugins/zod/shared/webhook.ts @@ -1,7 +1,7 @@ import { fromRef } from '@hey-api/codegen-core'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; +import { applyNaming } from '~/utils/naming'; import { exportAst } from './export'; import type { Ast, IrSchemaToAstOptions } from './types'; @@ -117,38 +117,36 @@ export const irWebhookToAst = ({ schemaData.required = [...requiredProperties]; const ast = getAst(schemaData, fromRef(state.path)); - const symbol = plugin.registerSymbol({ - meta: { - category: 'schema', - path: fromRef(state.path), - resource: 'webhook', - resourceId: operation.id, - role: 'data', - tags: fromRef(state.tags), - tool: 'zod', + const symbol = plugin.symbol( + applyNaming(operation.id, plugin.config.webhooks), + { + meta: { + category: 'schema', + path: fromRef(state.path), + resource: 'webhook', + resourceId: operation.id, + role: 'data', + tags: fromRef(state.tags), + tool: 'zod', + }, }, - name: buildName({ - config: plugin.config.webhooks, - name: operation.id, - }), - }); + ); const typeInferSymbol = plugin.config.webhooks.types.infer.enabled - ? plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'webhook', - resourceId: operation.id, - role: 'data', - tags: fromRef(state.tags), - tool: 'zod', - variant: 'infer', + ? plugin.symbol( + applyNaming(operation.id, plugin.config.webhooks.types.infer), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'webhook', + resourceId: operation.id, + role: 'data', + tags: fromRef(state.tags), + tool: 'zod', + variant: 'infer', + }, }, - name: buildName({ - config: plugin.config.webhooks.types.infer, - name: operation.id, - }), - }) + ) : undefined; exportAst({ ast, diff --git a/packages/openapi-ts/src/plugins/zod/types.d.ts b/packages/openapi-ts/src/plugins/zod/types.d.ts index 9c0429190..bc4350105 100644 --- a/packages/openapi-ts/src/plugins/zod/types.d.ts +++ b/packages/openapi-ts/src/plugins/zod/types.d.ts @@ -9,8 +9,8 @@ import type { } from '~/plugins/shared/utils/coerce'; import type { GetIntegerLimit } from '~/plugins/shared/utils/formats'; import type { $, DollarTsDsl, TsDsl } from '~/ts-dsl'; -import type { StringCase, StringName } from '~/types/case'; import type { MaybeArray } from '~/types/utils'; +import type { Casing, NameTransformer } from '~/utils/naming'; import type { IApi } from './api'; import type { Chain } from './shared/chain'; @@ -24,7 +24,7 @@ export type UserConfig = Plugin.Name<'zod'> & * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Add comments from input to the generated Zod schemas? * @@ -83,14 +83,14 @@ export type UserConfig = Plugin.Name<'zod'> & */ definitions?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Zod schemas for reusable definitions. * @@ -103,7 +103,7 @@ export type UserConfig = Plugin.Name<'zod'> & * * @default 'z{{name}}' */ - name?: StringName; + name?: NameTransformer; /** * Configuration for TypeScript type generation from Zod schemas. * @@ -122,14 +122,14 @@ export type UserConfig = Plugin.Name<'zod'> & */ infer?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate TypeScript types from Zod schemas. * @@ -142,7 +142,7 @@ export type UserConfig = Plugin.Name<'zod'> & * * @default '{{name}}ZodType' */ - name?: StringName; + name?: NameTransformer; }; }; }; @@ -176,14 +176,14 @@ export type UserConfig = Plugin.Name<'zod'> & */ requests?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Zod schemas for request definitions. * @@ -196,7 +196,7 @@ export type UserConfig = Plugin.Name<'zod'> & * * @default 'z{{name}}Data' */ - name?: StringName; + name?: NameTransformer; /** * Configuration for TypeScript type generation from Zod schemas. * @@ -215,14 +215,14 @@ export type UserConfig = Plugin.Name<'zod'> & */ infer?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate TypeScript types from Zod schemas. * @@ -235,7 +235,7 @@ export type UserConfig = Plugin.Name<'zod'> & * * @default '{{name}}DataZodType' */ - name?: StringName; + name?: NameTransformer; }; }; }; @@ -254,14 +254,14 @@ export type UserConfig = Plugin.Name<'zod'> & */ responses?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Zod schemas for response definitions. * @@ -274,7 +274,7 @@ export type UserConfig = Plugin.Name<'zod'> & * * @default 'z{{name}}Response' */ - name?: StringName; + name?: NameTransformer; /** * Configuration for TypeScript type generation from Zod schemas. * @@ -293,14 +293,14 @@ export type UserConfig = Plugin.Name<'zod'> & */ infer?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate TypeScript types from Zod schemas. * @@ -313,7 +313,7 @@ export type UserConfig = Plugin.Name<'zod'> & * * @default '{{name}}ResponseZodType' */ - name?: StringName; + name?: NameTransformer; }; }; }; @@ -335,14 +335,14 @@ export type UserConfig = Plugin.Name<'zod'> & */ infer?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate TypeScript types from Zod schemas. * @@ -365,14 +365,14 @@ export type UserConfig = Plugin.Name<'zod'> & */ webhooks?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'camelCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate Zod schemas for webhook definitions. * @@ -385,7 +385,7 @@ export type UserConfig = Plugin.Name<'zod'> & * * @default 'z{{name}}WebhookRequest' */ - name?: StringName; + name?: NameTransformer; /** * Configuration for TypeScript type generation from Zod schemas. * @@ -404,14 +404,14 @@ export type UserConfig = Plugin.Name<'zod'> & */ infer?: | boolean - | StringName + | NameTransformer | { /** * The casing convention to use for generated type names. * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to generate TypeScript types from Zod schemas. * @@ -424,7 +424,7 @@ export type UserConfig = Plugin.Name<'zod'> & * * @default '{{name}}WebhookRequestZodType' */ - name?: StringName; + name?: NameTransformer; }; }; }; @@ -438,7 +438,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Add comments from input to the generated Zod schemas? * @@ -494,7 +494,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Zod schemas for reusable definitions. * @@ -507,7 +507,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'z{{name}}' */ - name: StringName; + name: NameTransformer; /** * Configuration for TypeScript type generation from Zod schemas. * @@ -523,7 +523,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate TypeScript types from Zod schemas. * @@ -536,7 +536,7 @@ export type Config = Plugin.Name<'zod'> & * * @default '{{name}}ZodType' */ - name: StringName; + name: NameTransformer; }; }; }; @@ -567,7 +567,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Zod schemas for request definitions. * @@ -580,7 +580,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'z{{name}}Data' */ - name: StringName; + name: NameTransformer; /** * Configuration for TypeScript type generation from Zod schemas. * @@ -596,7 +596,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate TypeScript types from Zod schemas. * @@ -609,7 +609,7 @@ export type Config = Plugin.Name<'zod'> & * * @default '{{name}}DataZodType' */ - name: StringName; + name: NameTransformer; }; }; }; @@ -625,7 +625,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Zod schemas for response definitions. * @@ -638,7 +638,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'z{{name}}Response' */ - name: StringName; + name: NameTransformer; /** * Configuration for TypeScript type generation from Zod schemas. * @@ -654,7 +654,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate TypeScript types from Zod schemas. * @@ -667,7 +667,7 @@ export type Config = Plugin.Name<'zod'> & * * @default '{{name}}ResponseZodType' */ - name: StringName; + name: NameTransformer; }; }; }; @@ -686,7 +686,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate TypeScript types from Zod schemas. * @@ -706,7 +706,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'camelCase' */ - case: StringCase; + case: Casing; /** * Whether to generate Zod schemas for webhook definitions. * @@ -719,7 +719,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'z{{name}}WebhookRequest' */ - name: StringName; + name: NameTransformer; /** * Configuration for TypeScript type generation from Zod schemas. * @@ -735,7 +735,7 @@ export type Config = Plugin.Name<'zod'> & * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to generate TypeScript types from Zod schemas. * @@ -748,7 +748,7 @@ export type Config = Plugin.Name<'zod'> & * * @default '{{name}}WebhookRequestZodType' */ - name: StringName; + name: NameTransformer; }; }; }; diff --git a/packages/openapi-ts/src/plugins/zod/v3/plugin.ts b/packages/openapi-ts/src/plugins/zod/v3/plugin.ts index e9eae2eaa..fcbb7b588 100644 --- a/packages/openapi-ts/src/plugins/zod/v3/plugin.ts +++ b/packages/openapi-ts/src/plugins/zod/v3/plugin.ts @@ -3,10 +3,10 @@ import { fromRef, ref, refs } from '@hey-api/codegen-core'; import { deduplicateSchema } from '~/ir/schema'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import type { SchemaWithType } from '~/plugins'; import { maybeBigInt } from '~/plugins/shared/utils/coerce'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { pathToJsonPointer, refToName } from '~/utils/ref'; import { identifiers } from '../constants'; @@ -170,36 +170,34 @@ const handleComponent = ({ const $ref = pathToJsonPointer(fromRef(state.path)); const ast = irSchemaToAst({ plugin, schema, state }); const baseName = refToName($ref); - const symbol = plugin.registerSymbol({ - meta: { - category: 'schema', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'zod', + const symbol = plugin.symbol( + applyNaming(baseName, plugin.config.definitions), + { + meta: { + category: 'schema', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'zod', + }, }, - name: buildName({ - config: plugin.config.definitions, - name: baseName, - }), - }); + ); const typeInferSymbol = plugin.config.definitions.types.infer.enabled - ? plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'zod', - variant: 'infer', + ? plugin.symbol( + applyNaming(baseName, plugin.config.definitions.types.infer), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'zod', + variant: 'infer', + }, }, - name: buildName({ - config: plugin.config.definitions.types.infer, - name: baseName, - }), - }) + ) : undefined; exportAst({ ast, @@ -211,13 +209,12 @@ const handleComponent = ({ }; export const handlerV3: ZodPlugin['Handler'] = ({ plugin }) => { - plugin.registerSymbol({ + plugin.symbol('z', { external: getZodModule({ plugin }), meta: { category: 'external', resource: 'zod.z', }, - name: 'z', }); plugin.forEach( diff --git a/packages/openapi-ts/src/plugins/zod/v4/plugin.ts b/packages/openapi-ts/src/plugins/zod/v4/plugin.ts index be71113d6..169e99122 100644 --- a/packages/openapi-ts/src/plugins/zod/v4/plugin.ts +++ b/packages/openapi-ts/src/plugins/zod/v4/plugin.ts @@ -3,10 +3,10 @@ import { fromRef, ref, refs } from '@hey-api/codegen-core'; import { deduplicateSchema } from '~/ir/schema'; import type { IR } from '~/ir/types'; -import { buildName } from '~/openApi/shared/utils/name'; import type { SchemaWithType } from '~/plugins'; import { maybeBigInt } from '~/plugins/shared/utils/coerce'; import { $ } from '~/ts-dsl'; +import { applyNaming } from '~/utils/naming'; import { pathToJsonPointer, refToName } from '~/utils/ref'; import { identifiers } from '../constants'; @@ -178,36 +178,34 @@ const handleComponent = ({ const $ref = pathToJsonPointer(fromRef(state.path)); const ast = irSchemaToAst({ plugin, schema, state }); const baseName = refToName($ref); - const symbol = plugin.registerSymbol({ - meta: { - category: 'schema', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'zod', + const symbol = plugin.symbol( + applyNaming(baseName, plugin.config.definitions), + { + meta: { + category: 'schema', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'zod', + }, }, - name: buildName({ - config: plugin.config.definitions, - name: baseName, - }), - }); + ); const typeInferSymbol = plugin.config.definitions.types.infer.enabled - ? plugin.registerSymbol({ - meta: { - category: 'type', - path: fromRef(state.path), - resource: 'definition', - resourceId: $ref, - tags: fromRef(state.tags), - tool: 'zod', - variant: 'infer', + ? plugin.symbol( + applyNaming(baseName, plugin.config.definitions.types.infer), + { + meta: { + category: 'type', + path: fromRef(state.path), + resource: 'definition', + resourceId: $ref, + tags: fromRef(state.tags), + tool: 'zod', + variant: 'infer', + }, }, - name: buildName({ - config: plugin.config.definitions.types.infer, - name: baseName, - }), - }) + ) : undefined; exportAst({ ast, @@ -219,13 +217,12 @@ const handleComponent = ({ }; export const handlerV4: ZodPlugin['Handler'] = ({ plugin }) => { - plugin.registerSymbol({ + plugin.symbol('z', { external: getZodModule({ plugin }), meta: { category: 'external', resource: 'zod.z', }, - name: 'z', }); plugin.forEach( diff --git a/packages/openapi-ts/src/types/case.d.ts b/packages/openapi-ts/src/types/case.d.ts deleted file mode 100644 index 6e911faba..000000000 --- a/packages/openapi-ts/src/types/case.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type StringCase = - | 'camelCase' - | 'PascalCase' - | 'preserve' - | 'snake_case' - | 'SCREAMING_SNAKE_CASE'; - -export type StringName = string | ((name: string) => string); diff --git a/packages/openapi-ts/src/types/output.d.ts b/packages/openapi-ts/src/types/output.d.ts index 7d5dc639b..7becc612a 100644 --- a/packages/openapi-ts/src/types/output.d.ts +++ b/packages/openapi-ts/src/types/output.d.ts @@ -1,7 +1,7 @@ import type { NameConflictResolver } from '@hey-api/codegen-core'; import type ts from 'typescript'; -import type { StringCase, StringName } from './case'; +import type { Casing, NameTransformer } from '~/utils/naming'; export type Formatters = 'biome' | 'prettier'; @@ -16,7 +16,7 @@ export type UserOutput = { * * @default undefined */ - case?: StringCase; + case?: Casing; /** * Clean the `output` folder on every run? If disabled, this folder may * be used to store additional files. The default option is `true` to @@ -34,20 +34,20 @@ export type UserOutput = { * @default '{{name}}' */ fileName?: - | StringName + | NameTransformer | { /** * The casing convention to use for generated file names. * * @default 'preserve' */ - case?: StringCase; + case?: Casing; /** * Custom naming pattern for generated file names. * * @default '{{name}}' */ - name?: StringName; + name?: NameTransformer; /** * Suffix to append to file names (before the extension). For example, * with a suffix of `.gen`, `example.ts` becomes `example.gen.ts`. @@ -128,7 +128,7 @@ export type Output = { * Defines casing of the output fields. By default, we preserve `input` * values as data transforms incur a performance penalty at runtime. */ - case: StringCase | undefined; + case: Casing | undefined; /** * Clean the `output` folder on every run? If disabled, this folder may * be used to store additional files. The default option is `true` to @@ -146,11 +146,11 @@ export type Output = { /** * The casing convention to use for generated file names. */ - case: StringCase; + case: Casing; /** * Custom naming pattern for generated file names. */ - name: StringName; + name: NameTransformer; /** * Suffix to append to file names (before the extension). For example, * with a suffix of `.gen`, `example.ts` becomes `example.gen.ts`. diff --git a/packages/openapi-ts/src/types/parser.d.ts b/packages/openapi-ts/src/types/parser.d.ts index db0a8152c..e79069d06 100644 --- a/packages/openapi-ts/src/types/parser.d.ts +++ b/packages/openapi-ts/src/types/parser.d.ts @@ -7,8 +7,7 @@ import type { OpenApiSchemaObject, } from '~/openApi/types'; import type { Hooks } from '~/parser/types/hooks'; - -import type { StringCase, StringName } from './case'; +import type { Casing, NameTransformer } from '~/utils/naming'; type EnumsMode = 'inline' | 'root'; @@ -73,7 +72,7 @@ export type UserParser = { * * @default 'PascalCase' */ - case?: StringCase; + case?: Casing; /** * Whether to transform all enums. * @@ -92,7 +91,7 @@ export type UserParser = { * * @default '{{name}}Enum' */ - name?: StringName; + name?: NameTransformer; }; /** * By default, any object schema with a missing `required` keyword is @@ -137,21 +136,21 @@ export type UserParser = { * @default '{{name}}Writable' */ requests?: - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'preserve' */ - case?: StringCase; + case?: Casing; /** * Customize the generated name of schemas used in requests or * containing write-only fields. * * @default '{{name}}Writable' */ - name?: StringName; + name?: NameTransformer; }; /** * Configuration for generated response-specific schemas. @@ -163,14 +162,14 @@ export type UserParser = { * @default '{{name}}' */ responses?: - | StringName + | NameTransformer | { /** * The casing convention to use for generated names. * * @default 'preserve' */ - case?: StringCase; + case?: Casing; /** * Customize the generated name of schemas used in responses or * containing read-only fields. We default to the original name @@ -178,7 +177,7 @@ export type UserParser = { * * @default '{{name}}' */ - name?: StringName; + name?: NameTransformer; }; }; }; @@ -250,7 +249,7 @@ export type Parser = { * * @default 'PascalCase' */ - case: StringCase; + case: Casing; /** * Whether to transform all enums. * @@ -269,7 +268,7 @@ export type Parser = { * * @default '{{name}}Enum' */ - name: StringName; + name: NameTransformer; }; /** * By default, any object schema with a missing `required` keyword is @@ -309,14 +308,14 @@ export type Parser = { * * @default 'preserve' */ - case: StringCase; + case: Casing; /** * Customize the generated name of schemas used in requests or * containing write-only fields. * * @default '{{name}}Writable' */ - name: StringName; + name: NameTransformer; }; /** * Configuration for generated response-specific schemas. @@ -327,7 +326,7 @@ export type Parser = { * * @default 'preserve' */ - case: StringCase; + case: Casing; /** * Customize the generated name of schemas used in responses or * containing read-only fields. We default to the original name @@ -335,7 +334,7 @@ export type Parser = { * * @default '{{name}}' */ - name: StringName; + name: NameTransformer; }; }; }; diff --git a/packages/openapi-ts/src/utils/exports.ts b/packages/openapi-ts/src/utils/exports.ts index 4082989a5..6cbd2110d 100644 --- a/packages/openapi-ts/src/utils/exports.ts +++ b/packages/openapi-ts/src/utils/exports.ts @@ -1,6 +1,5 @@ -import type { StringCase } from '~/types/case'; - -import { toCase } from './to-case'; +import type { Casing } from './naming'; +import { toCase } from './naming'; /** * Utilities shared across the package. @@ -14,7 +13,7 @@ export const utils = { stripLeadingSeparators, value, }: { - readonly case: StringCase | undefined; + readonly case: Casing | undefined; /** * If leading separators have a semantic meaning, we might not want to * remove them. diff --git a/packages/openapi-ts/src/utils/__tests__/to-case.test.ts b/packages/openapi-ts/src/utils/naming/__tests__/naming.test.ts similarity index 97% rename from packages/openapi-ts/src/utils/__tests__/to-case.test.ts rename to packages/openapi-ts/src/utils/naming/__tests__/naming.test.ts index ffaca396f..11aeb2667 100644 --- a/packages/openapi-ts/src/utils/__tests__/to-case.test.ts +++ b/packages/openapi-ts/src/utils/naming/__tests__/naming.test.ts @@ -1,10 +1,9 @@ import { describe, expect, it } from 'vitest'; -import type { StringCase } from '~/types/case'; +import { toCase } from '../naming'; +import type { Casing } from '../types'; -import { toCase } from '../to-case'; - -const cases: ReadonlyArray = [ +const cases: ReadonlyArray = [ 'camelCase', 'PascalCase', 'SCREAMING_SNAKE_CASE', diff --git a/packages/openapi-ts/src/utils/naming/index.ts b/packages/openapi-ts/src/utils/naming/index.ts new file mode 100644 index 000000000..91b874be0 --- /dev/null +++ b/packages/openapi-ts/src/utils/naming/index.ts @@ -0,0 +1,7 @@ +export { applyNaming, resolveNaming, toCase } from './naming'; +export type { + Casing, + NameTransformer, + NamingConfig, + NamingRule, +} from './types'; diff --git a/packages/openapi-ts/src/utils/to-case.ts b/packages/openapi-ts/src/utils/naming/naming.ts similarity index 82% rename from packages/openapi-ts/src/utils/to-case.ts rename to packages/openapi-ts/src/utils/naming/naming.ts index 255fbc6e1..c2014480b 100644 --- a/packages/openapi-ts/src/utils/to-case.ts +++ b/packages/openapi-ts/src/utils/naming/naming.ts @@ -1,4 +1,4 @@ -import type { StringCase } from '~/types/case'; +import type { Casing, NamingConfig, NamingRule } from './types'; const uppercaseRegExp = /[\p{Lu}]/u; const lowercaseRegExp = /[\p{Ll}]/u; @@ -15,7 +15,7 @@ const numbersAndIdentifierRegExp = new RegExp( 'gu', ); -const preserveCase = (value: string, casing: StringCase) => { +const preserveCase = (value: string, casing: Casing) => { let isLastCharLower = false; let isLastCharUpper = false; let isLastLastCharUpper = false; @@ -84,7 +84,7 @@ const preserveCase = (value: string, casing: StringCase) => { }; /** - * Converts the given string to the specified casing. + * Convert a string to the specified casing. * * @param value - The string to convert * @param casing - The target casing @@ -93,7 +93,7 @@ const preserveCase = (value: string, casing: StringCase) => { */ export const toCase = ( value: string, - casing: StringCase | undefined, + casing: Casing | undefined, options: { /** * If leading separators have a semantic meaning, we might not want to @@ -188,3 +188,43 @@ export const toCase = ( return result; }; + +/** + * Normalize a NamingRule to NamingConfig. + */ +export function resolveNaming(rule: NamingRule | undefined): NamingConfig { + if (!rule) { + return {}; + } + if (typeof rule === 'string' || typeof rule === 'function') { + return { name: rule }; + } + return rule; +} + +/** + * Apply naming configuration to a value. + * + * Casing is applied first, then transformation. + */ +export function applyNaming(value: string, config: NamingConfig): string { + let result = value; + + const casing = config.casing ?? config.case; + + if (config.name) { + if (typeof config.name === 'function') { + result = config.name(result); + } else { + // TODO: refactor so there's no need for separators? + const separator = casing === 'preserve' ? '' : '-'; + result = config.name.replace( + '{{name}}', + `${separator}${result}${separator}`, + ); + } + } + + // TODO: apply case before name? + return toCase(result, casing); +} diff --git a/packages/openapi-ts/src/utils/naming/types.d.ts b/packages/openapi-ts/src/utils/naming/types.d.ts new file mode 100644 index 000000000..29f0cf521 --- /dev/null +++ b/packages/openapi-ts/src/utils/naming/types.d.ts @@ -0,0 +1,43 @@ +/** + * Available casing strategies. + */ +export type Casing = + | 'camelCase' + | 'PascalCase' + | 'preserve' + | 'snake_case' + | 'SCREAMING_SNAKE_CASE'; + +/** + * Name transformer: template string or function. + * + * Template supports `{{name}}` variable. + */ +export type NameTransformer = string | ((name: string) => string); + +/** + * Full naming configuration. + */ +export interface NamingConfig { + /** + * Casing strategy applied after transformation. + * + * @deprecated Use `casing` instead. + */ + case?: Casing; + /** + * Casing strategy applied after transformation. + */ + casing?: Casing; + /** + * Name template or transformer function. + * + * Applied before `casing` transformation. + */ + name?: NameTransformer; +} + +/** + * Name customization: shorthand or full configuration. + */ +export type NamingRule = NameTransformer | NamingConfig; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c3865277e..7c82863a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -112,6 +112,12 @@ importers: dev: devDependencies: + '@angular/common': + specifier: 19.2.17 + version: 19.2.17(@angular/core@19.2.17(rxjs@7.8.2)(zone.js@0.16.0))(rxjs@7.8.2) + '@angular/core': + specifier: 19.2.17 + version: 19.2.17(rxjs@7.8.2)(zone.js@0.16.0) '@hey-api/codegen-core': specifier: workspace:* version: link:../packages/codegen-core -- 2.51.2 From 572d7e23d655b0e22916fdf4dfbfd8c61dee48dc Mon Sep 17 00:00:00 2001 From: Lubos Date: Sat, 27 Dec 2025 22:25:55 +0800 Subject: [PATCH 08/15] chore: expose file header --- dev/openapi-ts.config.ts | 1 + packages/openapi-ts/src/config/output.ts | 1 + .../openapi-ts/src/config/utils/config.ts | 19 ++++--- packages/openapi-ts/src/ir/context.ts | 1 + .../src/plugins/shared/utils/config.ts | 2 +- packages/openapi-ts/src/ts-dsl/base.ts | 10 ++++ .../openapi-ts/src/ts-dsl/utils/render.ts | 55 +++++++++++++------ packages/openapi-ts/src/types/output.d.ts | 19 ++++++- packages/openapi-ts/src/types/utils.d.ts | 9 ++- 9 files changed, 90 insertions(+), 27 deletions(-) diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index 77a6a4971..04ecd5b9d 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -107,6 +107,7 @@ export default defineConfig(() => { // suffix: '.meh', // }, // format: 'prettier', + header: null, // importFileExtension: '.js', // indexFile: false, // lint: 'eslint', diff --git a/packages/openapi-ts/src/config/output.ts b/packages/openapi-ts/src/config/output.ts index 846ae2474..85907a08e 100644 --- a/packages/openapi-ts/src/config/output.ts +++ b/packages/openapi-ts/src/config/output.ts @@ -21,6 +21,7 @@ export const getOutput = (userConfig: UserConfig): Config['output'] => { suffix: '.gen', }, format: null, + header: '// This file is auto-generated by @hey-api/openapi-ts', indexFile: true, lint: null, path: '', diff --git a/packages/openapi-ts/src/config/utils/config.ts b/packages/openapi-ts/src/config/utils/config.ts index 60b36492f..00fec4178 100644 --- a/packages/openapi-ts/src/config/utils/config.ts +++ b/packages/openapi-ts/src/config/utils/config.ts @@ -3,8 +3,8 @@ type ObjectType = ? Record : Extract>; -type NotArray = T extends any[] ? never : T; -type NotFunction = T extends (...args: any[]) => any ? never : T; +type NotArray = T extends Array ? never : T; +type NotFunction = T extends (...args: Array) => any ? never : T; type PlainObject = T extends object ? NotFunction extends never ? never @@ -17,8 +17,8 @@ type MappersType = { boolean: T extends boolean ? (value: boolean) => Partial> : never; - function: T extends (...args: any[]) => any - ? (value: (...args: any[]) => any) => Partial> + function: T extends (...args: Array) => any + ? (value: (...args: Array) => any) => Partial> : never; number: T extends number ? (value: number) => Partial> : never; object?: PlainObject extends never @@ -35,7 +35,7 @@ type MappersType = { type IsObjectOnly = T extends Record | undefined ? Extract< T, - string | boolean | number | ((...args: any[]) => any) + string | boolean | number | ((...args: Array) => any) > extends never ? true : false @@ -47,7 +47,7 @@ export type ValueToObject = < | string | boolean | number - | ((...args: any[]) => any) + | ((...args: Array) => any) | Record, >( args: { @@ -99,9 +99,12 @@ export const valueToObject: ValueToObject = ({ case 'function': if (mappers && 'function' in mappers) { const mapper = mappers.function as ( - value: (...args: any[]) => any, + value: (...args: Array) => any, ) => Record; - result = mergeResult(result, mapper(value as (...args: any[]) => any)); + result = mergeResult( + result, + mapper(value as (...args: Array) => any), + ); } break; case 'number': diff --git a/packages/openapi-ts/src/ir/context.ts b/packages/openapi-ts/src/ir/context.ts index 958a24567..bdd726e0e 100644 --- a/packages/openapi-ts/src/ir/context.ts +++ b/packages/openapi-ts/src/ir/context.ts @@ -88,6 +88,7 @@ export class Context = any> { : undefined, renderers: [ new TypeScriptRenderer({ + header: config.output.header, preferExportAll: config.output.preferExportAll, preferFileExtension: config.output.importFileExtension || undefined, resolveModuleName: config.output.resolveModuleName, diff --git a/packages/openapi-ts/src/plugins/shared/utils/config.ts b/packages/openapi-ts/src/plugins/shared/utils/config.ts index 76307471b..ae219a5ae 100644 --- a/packages/openapi-ts/src/plugins/shared/utils/config.ts +++ b/packages/openapi-ts/src/plugins/shared/utils/config.ts @@ -25,6 +25,6 @@ export const definePluginConfig = */ export const mappers = { boolean: (enabled: boolean) => ({ enabled }), - function: (name: (...args: any[]) => any) => ({ name }), + function: (name: (...args: Array) => any) => ({ name }), string: (name: string) => ({ name }), } as const; diff --git a/packages/openapi-ts/src/ts-dsl/base.ts b/packages/openapi-ts/src/ts-dsl/base.ts index 6e7613382..5295d1d1b 100644 --- a/packages/openapi-ts/src/ts-dsl/base.ts +++ b/packages/openapi-ts/src/ts-dsl/base.ts @@ -24,8 +24,18 @@ import ts from 'typescript'; import type { AccessOptions } from './utils/context'; +/** + * Accepts a value or a readonly array of values of type T. + */ export type MaybeArray = T | ReadonlyArray; +/** + * Accepts a value or a function returning a value. + */ +export type MaybeFunc) => any> = + | T + | ReturnType; + export abstract class TsDsl implements Node { // eslint-disable-next-line @typescript-eslint/no-unused-vars analyze(_: AnalysisContext): void {} diff --git a/packages/openapi-ts/src/ts-dsl/utils/render.ts b/packages/openapi-ts/src/ts-dsl/utils/render.ts index 184634900..549643efe 100644 --- a/packages/openapi-ts/src/ts-dsl/utils/render.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/render.ts @@ -4,6 +4,7 @@ import ts from 'typescript'; import type { TsDsl } from '~/ts-dsl'; import { $ } from '~/ts-dsl'; +import type { MaybeArray, MaybeFunc } from '../base'; import type { ModuleExport, ModuleImport, @@ -17,49 +18,71 @@ type Exports = ReadonlyArray>; type ExportsOptions = { preferExportAll?: boolean; }; +type Header = MaybeArray | null | undefined; type Imports = ReadonlyArray>; +function headerToLines(header: Header): ReadonlyArray { + if (!header) return []; + const lines: Array = []; + if (typeof header === 'string') { + lines.push(...header.split(/\r?\n/)); + return lines; + } + for (const line of header) { + lines.push(...line.split(/\r?\n/)); + } + return lines; +} + export class TypeScriptRenderer implements Renderer { + /** + * Function to generate a file header. + * + * @private + */ + private _header?: MaybeFunc<(ctx: RenderContext) => Header>; /** * Whether `export * from 'module'` should be used when possible instead of named exports. * * @private */ - private preferExportAll: boolean; + private _preferExportAll: boolean; /** * Controls whether imports/exports include a file extension (e.g., '.ts' or '.js'). * * @private */ - private preferFileExtension: string; + private _preferFileExtension: string; /** * Optional function to transform module specifiers. * * @private */ - private resolveModuleName?: (moduleName: string) => string | undefined; + private _resolveModuleName?: (moduleName: string) => string | undefined; constructor( args: { + header?: MaybeFunc<(ctx: RenderContext) => Header>; preferExportAll?: boolean; preferFileExtension?: string; resolveModuleName?: (moduleName: string) => string | undefined; } = {}, ) { - this.preferExportAll = args.preferExportAll ?? false; - this.preferFileExtension = args.preferFileExtension ?? ''; - this.resolveModuleName = args.resolveModuleName; + this._header = args.header; + this._preferExportAll = args.preferExportAll ?? false; + this._preferFileExtension = args.preferFileExtension ?? ''; + this._resolveModuleName = args.resolveModuleName; } render(ctx: RenderContext): string { - // TODO: move header customization to options - const header = '// This file is auto-generated by @hey-api/openapi-ts'; + const header = + typeof this._header === 'function' ? this._header(ctx) : this._header; return TypeScriptRenderer.astToString({ exports: this.getExports(ctx), exportsOptions: { - preferExportAll: this.preferExportAll, + preferExportAll: this._preferExportAll, }, - headers: [header], + header, imports: this.getImports(ctx), nodes: ctx.file.nodes, }); @@ -72,7 +95,7 @@ export class TypeScriptRenderer implements Renderer { static astToString(args: { exports?: Exports; exportsOptions?: ExportsOptions; - headers?: ReadonlyArray; + header?: Header; imports?: Imports; nodes?: ReadonlyArray; /** @@ -83,7 +106,7 @@ export class TypeScriptRenderer implements Renderer { trailingNewline?: boolean; }): string { let text = ''; - for (const header of args.headers ?? []) { + for (const header of headerToLines(args.header)) { text += `${header}\n`; } @@ -187,10 +210,10 @@ export class TypeScriptRenderer implements Renderer { const sortKey = moduleSortKey({ file: ctx.file, fromFile: exp.from, - preferFileExtension: this.preferFileExtension, + preferFileExtension: this._preferFileExtension, root: ctx.project.root, }); - const modulePath = this.resolveModuleName?.(sortKey[2]) ?? sortKey[2]; + const modulePath = this._resolveModuleName?.(sortKey[2]) ?? sortKey[2]; const [groupIndex] = sortKey; if (!groups.has(groupIndex)) groups.set(groupIndex, new Map()); @@ -257,10 +280,10 @@ export class TypeScriptRenderer implements Renderer { const sortKey = moduleSortKey({ file: ctx.file, fromFile: imp.from, - preferFileExtension: this.preferFileExtension, + preferFileExtension: this._preferFileExtension, root: ctx.project.root, }); - const modulePath = this.resolveModuleName?.(sortKey[2]) ?? sortKey[2]; + const modulePath = this._resolveModuleName?.(sortKey[2]) ?? sortKey[2]; const [groupIndex] = sortKey; if (!groups.has(groupIndex)) groups.set(groupIndex, new Map()); diff --git a/packages/openapi-ts/src/types/output.d.ts b/packages/openapi-ts/src/types/output.d.ts index 7becc612a..ae8789ede 100644 --- a/packages/openapi-ts/src/types/output.d.ts +++ b/packages/openapi-ts/src/types/output.d.ts @@ -1,14 +1,23 @@ -import type { NameConflictResolver } from '@hey-api/codegen-core'; +import type { + NameConflictResolver, + RenderContext, +} from '@hey-api/codegen-core'; import type ts from 'typescript'; import type { Casing, NameTransformer } from '~/utils/naming'; +import type { MaybeArray, MaybeFunc } from './utils'; + export type Formatters = 'biome' | 'prettier'; export type Linters = 'biome' | 'eslint' | 'oxlint'; type ImportFileExtensions = '.js' | '.ts'; +type Header = MaybeFunc< + (ctx: RenderContext) => MaybeArray | null | undefined +>; + export type UserOutput = { /** * Defines casing of the output fields. By default, we preserve `input` @@ -67,6 +76,10 @@ export type UserOutput = { * @default null */ format?: Formatters | null; + /** + * Text to include at the top of every generated file. + */ + header?: Header; /** * If specified, this will be the file extension used when importing * other modules. By default, we don't add a file extension and let the @@ -167,6 +180,10 @@ export type Output = { * Which formatter to use to process output folder? */ format: Formatters | null; + /** + * Text to include at the top of every generated file. + */ + header: Header; /** * If specified, this will be the file extension used when importing * other modules. By default, we don't add a file extension and let the diff --git a/packages/openapi-ts/src/types/utils.d.ts b/packages/openapi-ts/src/types/utils.d.ts index 41e9a180d..9c3f94596 100644 --- a/packages/openapi-ts/src/types/utils.d.ts +++ b/packages/openapi-ts/src/types/utils.d.ts @@ -9,7 +9,7 @@ export type ArrayOnly = { * Recursively makes all non-function properties optional. */ export type DeepPartial = { - [K in keyof T]?: T[K] extends (...args: any[]) => any + [K in keyof T]?: T[K] extends (...args: Array) => any ? T[K] : T[K] extends object ? DeepPartial @@ -26,6 +26,13 @@ export type LazyOrAsync = T | (() => T) | (() => Promise); */ export type MaybeArray = T | ReadonlyArray; +/** + * Accepts a value or a function returning a value. + */ +export type MaybeFunc) => any> = + | T + | ReturnType; + /** * Converts all top-level Array properties to ReadonlyArray (shallow). */ -- 2.51.2 From 13dc23332f763318e313755129132babd4685a12 Mon Sep 17 00:00:00 2001 From: Lubos Date: Sun, 28 Dec 2025 04:38:04 +0800 Subject: [PATCH 09/15] chore: add log utilities --- dev/openapi-ts.config.ts | 25 +- .../src/__tests__/exports.test.ts | 2 +- packages/codegen-core/src/debug.ts | 36 --- packages/codegen-core/src/files/file.ts | 4 +- packages/codegen-core/src/index.ts | 2 +- packages/codegen-core/src/log.ts | 115 +++++++ packages/codegen-core/src/symbols/symbol.ts | 12 +- .../src/openApi/shared/locations/index.ts | 4 +- .../src/openApi/shared/locations/operation.ts | 95 ++---- .../src/openApi/shared/utils/operation.ts | 11 +- .../src/plugins/@hey-api/sdk/config.ts | 10 +- .../plugins/@hey-api/sdk/shared/operation.ts | 7 +- .../@hey-api/sdk/shared/typeOptions.ts | 3 +- .../plugins/@hey-api/sdk/structure/config.ts | 302 ++++++++++-------- .../plugins/@hey-api/sdk/structure/resolve.ts | 50 +++ .../plugins/@hey-api/sdk/structure/types.d.ts | 68 ++-- .../src/plugins/@hey-api/sdk/v1/plugin.ts | 83 ++--- .../src/plugins/shared/utils/operation.ts | 12 +- .../openapi-ts/src/utils/naming/naming.ts | 2 +- .../openapi-ts/src/utils/naming/types.d.ts | 4 +- 20 files changed, 489 insertions(+), 358 deletions(-) delete mode 100644 packages/codegen-core/src/debug.ts create mode 100644 packages/codegen-core/src/log.ts create mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/structure/resolve.ts diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index 04ecd5b9d..05b3b87bd 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -276,7 +276,7 @@ export default defineConfig(() => { // }, }, { - asClass: true, + // asClass: true, // auth: false, // classNameBuilder: '{{name}}Service', // classStructure: 'off', @@ -286,10 +286,11 @@ export default defineConfig(() => { // fields.unwrap('path') // }, // include... - instance: 'OpencodeClient', + // instance: true, + // instance: 'OpencodeClient', // methodNameBuilder: '{{name}}', name: '@hey-api/sdk', - // operationId: false, + // operationId: true, // paramsStructure: 'flat', // responseStyle: 'data', // signature: 'auto', @@ -297,8 +298,20 @@ export default defineConfig(() => { // signature: 'object', structure: { operations: { - containerName: 'OpencodeClient', - strategy: 'single', + // container: 'object', + containerName: { + // casing: 'snake_case', + // name: 'OpencodeClient' + }, + methodName: { + // casing: 'SCREAMING_SNAKE_CASE', + name: '{{name}}Yummy', + }, + methods: 'static', + nesting: 'id', + segmentName: '{{name}}Seggy', + strategy: 'byTags', + strategyDefaultTag: 'DaxLikedThis', }, }, // transformer: '@hey-api/transformers', @@ -614,7 +627,7 @@ export default defineConfig(() => { // asClass: true, enabled: false, }, - // name: '@angular/common', + name: '@angular/common', }, { exportFromIndex: true, diff --git a/packages/codegen-core/src/__tests__/exports.test.ts b/packages/codegen-core/src/__tests__/exports.test.ts index 99b0e335f..0e4b19392 100644 --- a/packages/codegen-core/src/__tests__/exports.test.ts +++ b/packages/codegen-core/src/__tests__/exports.test.ts @@ -3,7 +3,6 @@ import { describe, expect, it } from 'vitest'; import * as index from '../index'; const constExports = [ - 'debug', 'defaultExtensions', 'defaultNameConflictResolvers', 'File', @@ -14,6 +13,7 @@ const constExports = [ 'isRef', 'isSymbol', 'isSymbolRef', + 'log', 'nodeBrand', 'Project', 'ref', diff --git a/packages/codegen-core/src/debug.ts b/packages/codegen-core/src/debug.ts deleted file mode 100644 index 44aa6afac..000000000 --- a/packages/codegen-core/src/debug.ts +++ /dev/null @@ -1,36 +0,0 @@ -import colors from 'ansi-colors'; -// @ts-expect-error -import colorSupport from 'color-support'; - -colors.enabled = colorSupport().hasBasic; - -const DEBUG_GROUPS = { - analyzer: colors.greenBright, - dsl: colors.cyanBright, - file: colors.yellowBright, - registry: colors.blueBright, - symbol: colors.magentaBright, -} as const; - -export function debug(message: string, group: keyof typeof DEBUG_GROUPS) { - const value = process.env.DEBUG; - if (!value) return; - - const groups = value.split(',').map((x) => x.trim().toLowerCase()); - - if ( - !( - groups.includes('*') || - groups.includes('heyapi:*') || - groups.includes(`heyapi:${group}`) || - groups.includes(group) - ) - ) { - return; - } - - const color = DEBUG_GROUPS[group] ?? colors.whiteBright; - const prefix = color(`heyapi:${group}`); - - console.debug(`${prefix} ${message}`); -} diff --git a/packages/codegen-core/src/files/file.ts b/packages/codegen-core/src/files/file.ts index 14c040ff2..514beb626 100644 --- a/packages/codegen-core/src/files/file.ts +++ b/packages/codegen-core/src/files/file.ts @@ -2,8 +2,8 @@ import path from 'node:path'; import type { ExportModule, ImportModule } from '../bindings'; import { fileBrand } from '../brands'; -import { debug } from '../debug'; import type { Language } from '../languages/types'; +import { log } from '../log'; import type { INode } from '../nodes/node'; import type { NameScopes } from '../planner/scope'; import type { IProject } from '../project/types'; @@ -135,7 +135,7 @@ export class File { const name = this._logicalFilePath.split('/').pop(); if (name) return name; const message = `File ${this.toString()} has no name`; - debug(message, 'file'); + log.debug(message, 'file'); throw new Error(message); } diff --git a/packages/codegen-core/src/index.ts b/packages/codegen-core/src/index.ts index 6d306983d..e3a89641d 100644 --- a/packages/codegen-core/src/index.ts +++ b/packages/codegen-core/src/index.ts @@ -5,7 +5,6 @@ export type { ImportModule, } from './bindings'; export { nodeBrand, symbolBrand } from './brands'; -export { debug } from './debug'; export type { IProjectRenderMeta as ProjectRenderMeta, ISymbolMeta as SymbolMeta, @@ -20,6 +19,7 @@ export type { Language, NameConflictResolvers, } from './languages/types'; +export { log } from './log'; export type { INode as Node, NodeName, diff --git a/packages/codegen-core/src/log.ts b/packages/codegen-core/src/log.ts new file mode 100644 index 000000000..95073f33f --- /dev/null +++ b/packages/codegen-core/src/log.ts @@ -0,0 +1,115 @@ +import colors from 'ansi-colors'; +// @ts-expect-error +import colorSupport from 'color-support'; + +colors.enabled = colorSupport().hasBasic; + +/** + * Accepts a value or a readonly array of values of type T. + */ +export type MaybeArray = T | ReadonlyArray; + +/** + * Accepts a value or a function returning a value. + */ +export type MaybeFunc) => any> = + | T + | ReturnType; + +const DEBUG_NAMESPACE = 'heyapi'; + +const NO_WARNINGS = /^(1|true|yes|on)$/i.test( + process.env.HEYAPI_DISABLE_WARNINGS ?? '', +); + +const DebugGroups = { + analyzer: colors.greenBright, + dsl: colors.cyanBright, + file: colors.yellowBright, + registry: colors.blueBright, + symbol: colors.magentaBright, +} as const; + +const WarnGroups = { + deprecated: colors.magentaBright, +} as const; + +let cachedDebugGroups: Set | undefined; +function getDebugGroups(): Set { + if (cachedDebugGroups) return cachedDebugGroups; + + const value = process.env.DEBUG; + cachedDebugGroups = new Set( + value ? value.split(',').map((x) => x.trim().toLowerCase()) : [], + ); + + return cachedDebugGroups; +} + +/** + * Tracks which deprecations have been shown to avoid spam. + */ +const shownDeprecations = new Set(); + +function debug(message: string, group: keyof typeof DebugGroups) { + const groups = getDebugGroups(); + if ( + !( + groups.has('*') || + groups.has(`${DEBUG_NAMESPACE}:*`) || + groups.has(`${DEBUG_NAMESPACE}:${group}`) || + groups.has(group) + ) + ) { + return; + } + + const color = DebugGroups[group] ?? colors.whiteBright; + const prefix = color(`${DEBUG_NAMESPACE}:${group}`); + + console.debug(`${prefix} ${message}`); +} + +function warn(message: string, group: keyof typeof WarnGroups) { + if (NO_WARNINGS) return; + + const color = WarnGroups[group] ?? colors.yellowBright; + + console.warn(color(`${message}`)); +} + +function warnDeprecated({ + context, + field, + replacement, +}: { + context?: string; + field: string; + replacement?: MaybeFunc<(field: string) => MaybeArray>; +}) { + const key = context + ? `${context}:${field}:${JSON.stringify(replacement)}` + : `${field}:${JSON.stringify(replacement)}`; + + if (shownDeprecations.has(key)) return; + shownDeprecations.add(key); + + let message = `\`${field}\` is deprecated.`; + + if (replacement) { + const reps = + typeof replacement === 'function' ? replacement(field) : replacement; + const repArray = reps instanceof Array ? reps : [reps]; + const repString = repArray.map((r) => `\`${r}\``).join(' or '); + message += ` Use ${repString} instead.`; + } + + const prefix = context ? `[${context}] ` : ''; + warn(`${prefix}${message}`, 'deprecated'); +} + +export const log = { + debug, + warn, + warnDeprecated, +}; diff --git a/packages/codegen-core/src/symbols/symbol.ts b/packages/codegen-core/src/symbols/symbol.ts index 0517ca3e7..ca6bc880f 100644 --- a/packages/codegen-core/src/symbols/symbol.ts +++ b/packages/codegen-core/src/symbols/symbol.ts @@ -1,7 +1,7 @@ import { symbolBrand } from '../brands'; -import { debug } from '../debug'; import type { ISymbolMeta } from '../extensions'; import type { File } from '../files/file'; +import { log } from '../log'; import type { INode } from '../nodes/node'; import type { BindingKind, ISymbolIn, SymbolKind } from './types'; @@ -142,7 +142,7 @@ export class Symbol { get finalName(): string { if (!this.canonical._finalName) { const message = `Symbol finalName has not been resolved yet for ${this.canonical.toString()}`; - debug(message, 'symbol'); + log.debug(message, 'symbol'); throw new Error(message); } return this.canonical._finalName; @@ -238,7 +238,7 @@ export class Symbol { this.assertCanonical(); if (this._file && this._file !== file) { const message = `Symbol ${this.canonical.toString()} is already assigned to a different file.`; - debug(message, 'symbol'); + log.debug(message, 'symbol'); throw new Error(message); } this._file = file; @@ -253,7 +253,7 @@ export class Symbol { this.assertCanonical(); if (this._finalName && this._finalName !== name) { const message = `Symbol finalName has already been resolved for ${this.canonical.toString()}.`; - debug(message, 'symbol'); + log.debug(message, 'symbol'); throw new Error(message); } this._finalName = name; @@ -298,7 +298,7 @@ export class Symbol { this.assertCanonical(); if (this._node && this._node !== node) { const message = `Symbol ${this.canonical.toString()} is already bound to a different node.`; - debug(message, 'symbol'); + log.debug(message, 'symbol'); throw new Error(message); } this._node = node; @@ -329,7 +329,7 @@ export class Symbol { private assertCanonical(): void { if (this._canonical && this._canonical !== this) { const message = `Illegal mutation of stub symbol ${this.toString()} → canonical: ${this._canonical.toString()}`; - debug(message, 'symbol'); + log.debug(message, 'symbol'); throw new Error(message); } } diff --git a/packages/openapi-ts/src/openApi/shared/locations/index.ts b/packages/openapi-ts/src/openApi/shared/locations/index.ts index e1b443d73..8e6ed6e77 100644 --- a/packages/openapi-ts/src/openApi/shared/locations/index.ts +++ b/packages/openapi-ts/src/openApi/shared/locations/index.ts @@ -1,5 +1,5 @@ export type { - OperationLocationStrategy, OperationPathStrategy, + OperationStructureStrategy, } from './operation'; -export { OperationLocations, OperationPath } from './operation'; +export { OperationPath, OperationStrategies } from './operation'; diff --git a/packages/openapi-ts/src/openApi/shared/locations/operation.ts b/packages/openapi-ts/src/openApi/shared/locations/operation.ts index 749649f48..be2ca1eb7 100644 --- a/packages/openapi-ts/src/openApi/shared/locations/operation.ts +++ b/packages/openapi-ts/src/openApi/shared/locations/operation.ts @@ -1,29 +1,29 @@ -import type { StructureLocation, StructureShell } from '@hey-api/codegen-core'; +import type { StructureLocation } from '@hey-api/codegen-core'; import type { IR } from '~/ir/types'; /** - * A function that determines where an operation appears in the structure. + * A function that derives path segments from an operation. * - * Returns one or more locations, each with a full path and optional shell. + * Used by location strategies to build paths within containers. */ -export type OperationLocationStrategy = ( +export type OperationPathStrategy = ( operation: IR.OperationObject, -) => ReadonlyArray; +) => ReadonlyArray; /** - * A function that derives path segments from an operation. + * A function that determines where an operation appears in the structure. * - * Used by location strategies to build paths within containers. + * Returns one or more locations, each with a full path. */ -export type OperationPathStrategy = ( +export type OperationStructureStrategy = ( operation: IR.OperationObject, -) => ReadonlyArray; +) => ReadonlyArray; /** - * Built-in location strategies for operations. + * Built-in strategies for operations. */ -export const OperationLocations = { +export const OperationStrategies = { /** * Creates one root container per operation tag. * @@ -39,33 +39,20 @@ export const OperationLocations = { (config: { /** * Root name for operations without tags. - * - * @default 'default' */ - fallback?: string; + fallback: string; /** * Derives path segments from the operation. - * - * @default OperationPath.fromOperationId() */ - path?: OperationPathStrategy; - /** - * Shell to apply to all created nodes. - */ - shell: StructureShell; - }): OperationLocationStrategy => + path: OperationPathStrategy; + }): OperationStructureStrategy => (operation) => { const tags = operation.tags && operation.tags.length > 0 ? operation.tags - : [config.fallback ?? 'default']; - const pathSegments = (config.path ?? OperationPath.fromOperationId())( - operation, - ); - return tags.map((tag) => ({ - path: [tag, ...pathSegments], - shell: config.shell, - })); + : [config.fallback]; + const pathSegments = config.path(operation); + return tags.map((tag) => [tag, ...pathSegments]); }, /** @@ -79,19 +66,16 @@ export const OperationLocations = { * // Result: [{ path: ['getUsers'] }] */ flat: - (config?: { + (config: { /** - * Derives the function name from the operation. - * - * @default operation.id + * Derives path segments within the root from the operation. */ - name?: (operation: IR.OperationObject) => string; - }): OperationLocationStrategy => - (operation) => [ - { - path: [(config?.name ?? ((operation) => operation.id))(operation)], - }, - ], + path: OperationPathStrategy; + }): OperationStructureStrategy => + (operation) => { + const pathSegments = config.path(operation); + return [[pathSegments[pathSegments.length - 1]!]]; + }, /** * Places all operations under a single root container. @@ -104,28 +88,17 @@ export const OperationLocations = { (config: { /** * Derives path segments within the root from the operation. - * - * @default OperationPath.fromOperationId() */ - path?: OperationPathStrategy; + path: OperationPathStrategy; /** * Name of the container. */ root: string; - /** - * Shell to apply to all created nodes. - */ - shell: StructureShell; - }): OperationLocationStrategy => - (operation) => [ - { - path: [ - config.root, - ...(config.path ?? OperationPath.fromOperationId())(operation), - ], - shell: config.shell, - }, - ], + }): OperationStructureStrategy => + (operation) => { + const pathSegments = config.path(operation); + return [[config.root, ...pathSegments]]; + }, }; /** @@ -147,18 +120,16 @@ export const OperationPath = { * // Result: ['users', 'accounts', 'getAll'] */ fromOperationId: - (config?: { + (config: { /** * Pattern to split operationId. - * - * @default /[./]/ */ delimiters: RegExp; }): OperationPathStrategy => (operation) => { if (!operation.operationId) return [operation.id]; const segments = operation.operationId - .split(config?.delimiters ?? /[./]/) + .split(config.delimiters) .filter(Boolean); return segments.length > 0 ? segments : [operation.id]; }, diff --git a/packages/openapi-ts/src/openApi/shared/utils/operation.ts b/packages/openapi-ts/src/openApi/shared/utils/operation.ts index dbb3d15e5..99aa47b39 100644 --- a/packages/openapi-ts/src/openApi/shared/utils/operation.ts +++ b/packages/openapi-ts/src/openApi/shared/utils/operation.ts @@ -20,6 +20,8 @@ export const httpMethods = [ * Returns an operation ID to use across the application. By default, we try * to use the provided ID. If it's not provided or the SDK is configured * to exclude it, we generate operation ID from its location. + * + * @deprecated */ export const operationToId = ({ context, @@ -47,7 +49,14 @@ export const operationToId = ({ if ( id && (!context.config.plugins['@hey-api/sdk'] || - context.config.plugins['@hey-api/sdk'].config.operationId) + // TODO: needs to be refactored... + (context.config.plugins['@hey-api/sdk'].config.structure?.operations && + typeof context.config.plugins['@hey-api/sdk'].config.structure + ?.operations !== 'function' && + typeof context.config.plugins['@hey-api/sdk'].config.structure + ?.operations === 'object' && + context.config.plugins['@hey-api/sdk'].config.structure?.operations + .nesting === 'operationId')) ) { result = toCase(sanitizeNamespaceIdentifier(id), targetCase); } else { diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts index 67a7b8df2..4617426a9 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts @@ -16,12 +16,6 @@ export const defaultConfig: HeyApiSdkPlugin['Config'] = { // Deprecated - kept for backward compatibility // eslint-disable-next-line sort-keys-fix/sort-keys-fix - asClass: false, - classNameBuilder: '{{name}}', - classStructure: 'auto', - instance: '', - methodNameBuilder: '{{name}}', - operationId: true, response: 'body', }, dependencies: ['@hey-api/typescript'], @@ -77,7 +71,9 @@ export const defaultConfig: HeyApiSdkPlugin['Config'] = { plugin.config.validator.response = false; } - plugin.config.structure = resolveStructure(plugin.config, context); + plugin.config.structure = { + operations: resolveStructure(plugin.config, context), + }; }, }; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts index 9e2ba9692..3eab17de2 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts @@ -10,6 +10,7 @@ import { toCase } from '~/utils/naming'; import type { Field, Fields } from '../../client-core/bundle/params'; import type { HeyApiSdkPlugin } from '../types'; +import { isInstance } from '../v1/plugin'; import { operationAuth } from './auth'; import { nuxtTypeComposable, nuxtTypeDefault } from './constants'; import { getSignatureParameters } from './signature'; @@ -33,7 +34,7 @@ interface ClassNameEntry { /** * @deprecated */ -export const operationClassName = ({ +const operationClassName = ({ plugin, value, }: { @@ -52,7 +53,7 @@ export const operationClassName = ({ /** * @deprecated */ -export const operationMethodName = ({ +const operationMethodName = ({ operation, plugin, value, @@ -584,7 +585,7 @@ export const operationStatements = ({ let clientExpression: ReturnType; const optionsClient = $('options').attr('client').required(isRequiredOptions); - if (plugin.config.instance) { + if (isInstance(plugin)) { clientExpression = optionsClient.coalesce($('this').attr('client')); } else if (symbolClient) { clientExpression = optionsClient.coalesce(symbolClient); diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts index e739545c1..b7c20bc3e 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts @@ -3,6 +3,7 @@ import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; import { $ } from '~/ts-dsl'; import type { HeyApiSdkPlugin } from '../types'; +import { isInstance } from '../v1/plugin'; import { nuxtTypeDefault, nuxtTypeResponse } from './constants'; export const createTypeOptions = ({ @@ -91,7 +92,7 @@ export const createTypeOptions = ({ 'individual options. This might be also useful if you want to implement a', 'custom client.', ]) - .required(!plugin.config.client && !plugin.config.instance) + .required(!plugin.config.client && !isInstance(plugin)) .type(symbolClient), ) .prop('meta', (p) => diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/config.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/config.ts index 0cb13d707..e8296da56 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/config.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/config.ts @@ -1,6 +1,6 @@ +import { log } from '@hey-api/codegen-core'; + import type { PluginContext } from '~/plugins/types'; -import type { NamingConfig, NamingRule } from '~/utils/naming'; -import { resolveNaming } from '~/utils/naming'; import type { UserConfig } from '../types'; import type { @@ -11,192 +11,216 @@ import type { type Config = Omit; -// container: 'class', -// containerName: {}, -// defaultTag: 'default', -// delimiters: /[./]/, -// methodName: {}, -// methods: 'instance', -// nesting: 'operationId', -// segmentName: {}, -// strategy: 'flat', - export function resolveStructure( config: Config, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _context: PluginContext, + context: PluginContext, ): StructureConfig { - // if (plugin.config.instance) { - // if (typeof plugin.config.instance !== 'string') { - // plugin.config.instance = 'Sdk'; - // } - - // plugin.config.asClass = true; - // } else { - // plugin.config.instance = ''; - // } - - // // Set default classNameBuilder based on client type - // if (plugin.config.classNameBuilder === '{{name}}') { - // if (plugin.config.client === '@hey-api/client-angular') { - // plugin.config.classNameBuilder = '{{name}}Service'; - // } - // } - - // Check for deprecated options and warn if (config.asClass !== undefined) { - console.warn( - '`asClass` is deprecated. Use `grouping: "byTags"` or `grouping: "single"` instead.', - ); + log.warnDeprecated({ + context: '@hey-api/sdk', + field: 'asClass', + replacement: [ + 'structure.operations: { strategy: "byTags" }', + 'structure.operations: { strategy: "single" }', + ], + }); } - if (config.instance !== undefined) { - console.warn( - '`instance` is deprecated. Use `grouping: { strategy: "single", containerName: "Name", methods: "instance" }` instead.', - ); + if (config.classNameBuilder !== undefined) { + log.warnDeprecated({ + context: '@hey-api/sdk', + field: 'classNameBuilder', + replacement: 'structure.operations: { containerName: "..." }', + }); } if (config.classStructure !== undefined) { - console.warn( - '`classStructure` is deprecated. Use `grouping: { nesting: "operationId" }` or `grouping: { nesting: "id" }` instead.', - ); + log.warnDeprecated({ + context: '@hey-api/sdk', + field: 'classStructure', + replacement: [ + 'structure.operations: { nesting: "operationId" }', + 'structure.operations: { nesting: "id" }', + ], + }); } - if (config.classNameBuilder !== undefined) { - console.warn( - '`classNameBuilder` is deprecated. Use `grouping.containerName` instead.', - ); + if (config.instance !== undefined) { + log.warnDeprecated({ + context: '@hey-api/sdk', + field: 'instance', + replacement: `structure.operations: { strategy: "single", containerName: "${config.instance || 'Name'}", methods: "instance" }`, + }); } if (config.methodNameBuilder !== undefined) { - console.warn( - '`methodNameBuilder` is deprecated. Use `grouping.methodName` instead.', - ); + log.warnDeprecated({ + context: '@hey-api/sdk', + field: 'methodNameBuilder', + replacement: 'structure.operations: { methodName: "..." }', + }); } if (config.operationId !== undefined) { - console.warn( - '`operationId` is deprecated. Use `grouping: { nesting: "operationId" }` or `grouping: { nesting: "id" }` instead.', - ); - } - - // If new grouping config is provided, use it - if (config.structure !== undefined) { - return normalizeStructureConfig(config.structure); + log.warnDeprecated({ + context: '@hey-api/sdk', + field: 'operationId', + replacement: [ + 'structure.operations: { nesting: "operationId" }', + 'structure.operations: { nesting: "id" }', + ], + }); } - // Otherwise, map legacy config to new grouping config - return mapLegacyToGrouping(config); + const legacy = mapLegacyToConfig(config); + return config.structure?.operations + ? normalizeStructureConfig(config.structure.operations, legacy, context) + : context.valueToObject({ + defaultValue: { + container: 'class', + containerName: {}, + methodName: {}, + methods: 'instance', + nesting: 'operationId', + nestingDelimiters: /[./]/, + segmentName: {}, + strategy: 'flat', + strategyDefaultTag: 'default', + }, + value: legacy as StructureConfig, + }); } function normalizeStructureConfig( input: StructureStrategy | UserStructureConfig, + legacy: Partial, + context: PluginContext, ): StructureConfig { - // String shorthand - if (typeof input === 'string') { - return { - container: 'class', - containerName: input === 'single' ? { name: 'Sdk' } : {}, - defaultTag: 'default', - delimiters: /[./]/, - methodName: {}, - methods: 'instance', - nesting: 'operationId', - segmentName: {}, - strategy: input, - }; + if (typeof input === 'string' || typeof input === 'function') { + input = { strategy: input }; } - // Custom function - if (typeof input === 'function') { - return { + const strategy = legacy.strategy ?? input.strategy ?? 'flat'; + + return context.valueToObject({ + defaultValue: { container: 'class', - containerName: {}, - defaultTag: 'default', - delimiters: /[./]/, - methodName: {}, methods: 'instance', - nesting: 'operationId', - segmentName: {}, - strategy: input, - }; - } - - // Full config object - const strategy = input.strategy ?? 'flat'; - - return { - container: input.container ?? 'class', - containerName: resolveContainerName(input.containerName, strategy), - defaultTag: input.defaultTag ?? 'default', - delimiters: input.delimiters ?? /[./]/, - methodName: resolveNaming(input.methodName), - methods: input.methods ?? 'instance', - nesting: input.nesting ?? 'operationId', - segmentName: resolveNaming(input.segmentName), - strategy, - }; + nesting: strategy === 'flat' ? 'id' : 'operationId', + nestingDelimiters: /[./]/, + strategy, + strategyDefaultTag: 'default', + }, + mappers: { + object(value) { + value.containerName = context.valueToObject({ + defaultValue: + strategy === 'single' + ? { casing: 'PascalCase', name: 'Sdk' } + : { casing: 'PascalCase' }, + mappers: { + function: (name) => ({ name }), + string: (name) => ({ name }), + }, + value: value.containerName, + }); + value.methodName = context.valueToObject({ + defaultValue: { casing: 'camelCase' }, + mappers: { + function: (name) => ({ name }), + string: (name) => ({ name }), + }, + value: value.methodName, + }); + value.segmentName = context.valueToObject({ + defaultValue: { casing: 'PascalCase' }, + mappers: { + function: (name) => ({ name }), + string: (name) => ({ name }), + }, + value: value.segmentName, + }); + return value; + }, + }, + value: { + ...legacy, + ...input, + } as UserStructureConfig, + }) as StructureConfig; } -function resolveContainerName( - input: NamingRule | undefined, - strategy: StructureStrategy, -): NamingConfig { - const resolved = resolveNaming(input); - - // Default name for 'single' strategy - if (strategy === 'single' && !resolved.name) { - resolved.name = 'Sdk'; +function mapLegacyToConfig(config: Config): Partial { + // TODO: refactor... + // Set default classNameBuilder based on client type + if (config.classNameBuilder === '{{name}}') { + if (config.client === '@hey-api/client-angular') { + config.classNameBuilder = '{{name}}Service'; + } } - return resolved; -} - -function mapLegacyToGrouping(config: Config): StructureConfig { - // Determine strategy from legacy options - let strategy: StructureStrategy = 'flat'; - - if (config.asClass) { - strategy = config.instance ? 'single' : 'byTags'; + let strategy: StructureConfig['strategy'] | undefined; + if (config.instance) { + strategy = 'single'; + } else if (config.asClass) { + strategy = 'byTags'; + } else if (config.instance === false || config.asClass === false) { + strategy = 'flat'; } - // Determine container name - let containerName: NamingConfig = {}; - - if (config.instance && typeof config.instance === 'string') { - containerName = { name: config.instance }; + let containerName: StructureConfig['containerName'] | undefined; + let segmentName: StructureConfig['segmentName'] | undefined; + if (config.instance) { + let name = typeof config.instance === 'string' ? config.instance : 'Sdk'; + segmentName = { casing: 'PascalCase' }; + if (config.classNameBuilder) { + segmentName.name = config.classNameBuilder; + if (typeof config.classNameBuilder === 'string') { + name = config.classNameBuilder.replace('{{name}}', name); + } else { + name = config.classNameBuilder(name); + } + } + containerName = { casing: 'PascalCase', name }; } else if (config.classNameBuilder) { - containerName = resolveNaming(config.classNameBuilder); + containerName = { + casing: 'PascalCase', + name: config.classNameBuilder, + }; + segmentName = { ...containerName }; + } else if (config.asClass) { + containerName = { casing: 'PascalCase' }; + segmentName = { ...containerName }; } - if (strategy === 'single' && !containerName.name) { - containerName.name = 'Sdk'; + let methods: StructureConfig['methods'] | undefined; + if (config.instance) { + methods = 'instance'; + } else if (config.asClass) { + methods = 'static'; } - // Determine method name - const methodName: NamingConfig = config.methodNameBuilder - ? resolveNaming(config.methodNameBuilder) - : {}; - - // Determine nesting - let nesting: 'operationId' | 'id' = 'operationId'; - + let nesting: StructureConfig['nesting'] | undefined; if (config.classStructure === 'off' || config.operationId === false) { nesting = 'id'; + } else if (config.classStructure === 'auto') { + nesting = 'operationId'; } - // Determine methods style - const methods = config.instance ? 'instance' : 'static'; + let methodName: StructureConfig['methodName'] | undefined; + if (config.methodNameBuilder) { + methodName = { + casing: 'camelCase', + name: config.methodNameBuilder, + }; + } return { - container: 'class', containerName, - defaultTag: 'default', - delimiters: /[./]/, methodName, methods, nesting, - segmentName: {}, + segmentName, strategy, }; } diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/resolve.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/resolve.ts new file mode 100644 index 000000000..3ab669e0b --- /dev/null +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/resolve.ts @@ -0,0 +1,50 @@ +import type { + OperationPathStrategy, + OperationStructureStrategy, +} from '~/openApi/shared/locations'; +import { OperationPath, OperationStrategies } from '~/openApi/shared/locations'; + +import type { HeyApiSdkPlugin } from '../types'; + +function resolvePath( + plugin: HeyApiSdkPlugin['Instance'], +): OperationPathStrategy { + if (plugin.config.structure.operations.nesting === 'id') { + return OperationPath.id(); + } + + if (plugin.config.structure.operations.nesting === 'operationId') { + return OperationPath.fromOperationId({ + delimiters: plugin.config.structure.operations.nestingDelimiters, + }); + } + + return plugin.config.structure.operations.nesting; +} + +export function resolveStrategy( + plugin: HeyApiSdkPlugin['Instance'], +): OperationStructureStrategy { + if (plugin.config.structure.operations.strategy === 'flat') { + return OperationStrategies.flat({ + path: resolvePath(plugin), + }); + } + + if (plugin.config.structure.operations.strategy === 'single') { + const root = plugin.config.structure.operations.containerName; + return OperationStrategies.single({ + path: resolvePath(plugin), + root: typeof root.name === 'string' ? root.name : (root.name?.('') ?? ''), + }); + } + + if (plugin.config.structure.operations.strategy === 'byTags') { + return OperationStrategies.byTags({ + fallback: plugin.config.structure.operations.strategyDefaultTag, + path: resolvePath(plugin), + }); + } + + return plugin.config.structure.operations.strategy; +} diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/types.d.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/types.d.ts index 025d7bcd6..e74fadbde 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/types.d.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/types.d.ts @@ -1,16 +1,14 @@ -import type { IR } from '~/ir/types'; -import type { OperationPathStrategy } from '~/openApi/shared/locations'; +import type { + OperationPathStrategy, + OperationStructureStrategy, +} from '~/openApi/shared/locations'; import type { NamingConfig, NamingRule } from '~/utils/naming'; -type CustomStructureStrategy = ( - operation: IR.OperationObject, -) => ReadonlyArray>; - export type StructureStrategy = | 'byTags' | 'flat' | 'single' - | CustomStructureStrategy; + | OperationStructureStrategy; export interface UserStructureConfig { /** @@ -45,22 +43,6 @@ export interface UserStructureConfig { * containerName: { name: '{{name}}Service', case: 'PascalCase' } */ containerName?: NamingRule; - /** - * Default container name for operations without tags. - * - * Only applies when `strategy` is `'byTags'`. - * - * @default 'default' - */ - defaultTag?: string; - /** - * Delimiters for splitting operationId. - * - * Only applies when `nesting` is `'operationId'`. - * - * @default /[./]/ - */ - delimiters?: RegExp; /** * Customize method/function names. * @@ -90,6 +72,14 @@ export interface UserStructureConfig { * @default 'operationId' */ nesting?: 'operationId' | 'id' | OperationPathStrategy; + /** + * Delimiters for splitting operationId. + * + * Only applies when `nesting` is `'operationId'`. + * + * @default /[./]/ + */ + nestingDelimiters?: RegExp; /** * Customize nesting segment names. * @@ -107,6 +97,14 @@ export interface UserStructureConfig { * @default 'flat' */ strategy?: StructureStrategy; + /** + * Default container name for operations without tags. + * + * Only applies when `strategy` is `'byTags'`. + * + * @default 'default' + */ + strategyDefaultTag?: string; } export interface StructureConfig { @@ -140,18 +138,6 @@ export interface StructureConfig { * containerName: { name: '{{name}}Service', case: 'PascalCase' } */ containerName: NamingConfig; - /** - * Default container name for operations without tags. - * - * Only applies when `strategy` is `'byTags'`. - */ - defaultTag: string; - /** - * Delimiters for splitting operationId. - * - * Only applies when `nesting` is `'operationId'`. - */ - delimiters: RegExp; /** * Customize method/function names. * @@ -177,6 +163,12 @@ export interface StructureConfig { * - Custom function for full control */ nesting: 'operationId' | 'id' | OperationPathStrategy; + /** + * Delimiters for splitting operationId. + * + * Only applies when `nesting` is `'operationId'`. + */ + nestingDelimiters: RegExp; /** * Customize nesting segment names. * @@ -192,4 +184,10 @@ export interface StructureConfig { * - Custom function for full control */ strategy: StructureStrategy; + /** + * Default container name for operations without tags. + * + * Only applies when `strategy` is `'byTags'`. + */ + strategyDefaultTag: string; } diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts index f60381391..cc06e6f17 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts @@ -8,28 +8,19 @@ import { StructureModel } from '@hey-api/codegen-core'; import { clientFolderAbsolutePath } from '~/generate/client'; import type { IR } from '~/ir/types'; -import { - OperationLocations, - type OperationLocationStrategy, - OperationPath, -} from '~/openApi/shared/locations'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; import { createOperationComment, isOperationOptionsRequired, } from '~/plugins/shared/utils/operation'; import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/naming'; +import { applyNaming, toCase } from '~/utils/naming'; import { createClientClass, createRegistryClass } from '../shared/class'; import { nuxtTypeComposable, nuxtTypeDefault } from '../shared/constants'; -import { - operationClassName, - operationMethodName, - operationParameters, - operationStatements, -} from '../shared/operation'; +import { operationParameters, operationStatements } from '../shared/operation'; import { createTypeOptions } from '../shared/typeOptions'; +import { resolveStrategy } from '../structure/resolve'; import type { HeyApiSdkPlugin } from '../types'; interface OperationItem { @@ -52,13 +43,9 @@ function createFnSymbol( item: StructureItem & { data: OperationItem }, ): Symbol { const { operation, path, tags } = item.data; - const name = item.location[item.location.length - 1]; + const name = item.location[item.location.length - 1]!; return plugin.symbol( - operationMethodName({ - operation, - plugin, - value: name, - }), + applyNaming(name, plugin.config.structure.operations.methodName), { meta: { category: 'sdk', @@ -84,7 +71,7 @@ function childToNode( }); const memberNameStr = toCase(refChild.name, 'camelCase'); const memberName = plugin.symbol(memberNameStr); - if (plugin.config.instance) { + if (isInstance(plugin)) { const privateName = plugin.symbol(`_${memberNameStr}`); return [ $.field(privateName, (f) => f.private().optional().type(refChild)), @@ -305,7 +292,7 @@ function toNode( operation, }) .public() - .static(!isAngularClient && !plugin.config.instance), + .static(!isAngularClient && !isInstance(plugin)), ), operation, plugin, @@ -333,7 +320,12 @@ function createShell(plugin: HeyApiSdkPlugin['Instance']): StructureShell { return { define: (node) => { const symbol = plugin.symbol( - operationClassName({ plugin, value: node.name }), + applyNaming( + node.name, + node.isRoot + ? plugin.config.structure.operations.containerName + : plugin.config.structure.operations.segmentName, + ), { meta: { category: 'utility', @@ -345,7 +337,7 @@ function createShell(plugin: HeyApiSdkPlugin['Instance']): StructureShell { ); const c = $.class(symbol) .export() - .$if(plugin.config.instance, (c) => + .$if(isInstance(plugin), (c) => c.extends( plugin.referenceSymbol({ category: 'utility', @@ -367,7 +359,7 @@ function createShell(plugin: HeyApiSdkPlugin['Instance']): StructureShell { const dependencies: Array> = []; - if (node.isRoot && plugin.config.instance) { + if (node.isRoot && isInstance(plugin)) { enrichRootClass({ dependencies, node: c, @@ -381,32 +373,13 @@ function createShell(plugin: HeyApiSdkPlugin['Instance']): StructureShell { }; } -function resolveLocationStrategy( - plugin: HeyApiSdkPlugin['Instance'], -): OperationLocationStrategy { - const shell = createShell(plugin); - const path = - plugin.config.classStructure === 'auto' - ? OperationPath.fromOperationId() - : OperationPath.id(); - - if (!plugin.config.asClass) { - return OperationLocations.flat(); - } - - if (plugin.config.instance) { - return OperationLocations.single({ - path, - root: plugin.config.instance, - shell, - }); - } - - return OperationLocations.byTags({ - fallback: 'default', - path, - shell, - }); +export function isInstance(plugin: HeyApiSdkPlugin['Instance']): boolean { + const config = plugin.config.structure.operations; + return ( + config.container === 'class' && + config.methods === 'instance' && + config.strategy !== 'flat' + ); } export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { @@ -450,7 +423,11 @@ export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { }, }); } - if (isAngularClient && plugin.config.asClass) { + if ( + isAngularClient && + plugin.config.structure.operations.container === 'class' && + plugin.config.structure.operations.strategy !== 'flat' + ) { plugin.symbol('Injectable', { external: '@angular/core', meta: { @@ -463,7 +440,8 @@ export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { createTypeOptions({ plugin }); const structure = new StructureModel(); - const locationStrategy = resolveLocationStrategy(plugin); + const shell = createShell(plugin); + const strategy = resolveStrategy(plugin); plugin.forEach( 'operation', @@ -474,8 +452,7 @@ export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { path: event._path, tags: event.tags, } satisfies OperationItem, - // TODO: expose this logic - locations: locationStrategy(event.operation), + locations: strategy(event.operation).map((path) => ({ path, shell })), source, }); }, diff --git a/packages/openapi-ts/src/plugins/shared/utils/operation.ts b/packages/openapi-ts/src/plugins/shared/utils/operation.ts index 1f3199c73..cbb41c72f 100644 --- a/packages/openapi-ts/src/plugins/shared/utils/operation.ts +++ b/packages/openapi-ts/src/plugins/shared/utils/operation.ts @@ -2,6 +2,8 @@ import type { Context } from '~/ir/context'; import { hasOperationDataRequired } from '~/ir/operation'; import type { IR } from '~/ir/types'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; +import type { HeyApiSdkPlugin } from '~/plugins/@hey-api/sdk'; +import { isInstance } from '~/plugins/@hey-api/sdk/v1/plugin'; import { escapeComment } from '~/utils/escape'; export const createOperationComment = ( @@ -32,6 +34,11 @@ export const createOperationComment = ( return comments.length ? comments : undefined; }; +/** + * TODO: replace with plugin logic... + * + * @deprecated this needs to be refactored + */ export const isOperationOptionsRequired = ({ context, operation, @@ -43,7 +50,10 @@ export const isOperationOptionsRequired = ({ const isNuxtClient = client.name === '@hey-api/client-nuxt'; const plugin = context.config.plugins['@hey-api/sdk']; if (plugin) { - if (!plugin.config.client && !plugin.config.instance) { + if ( + !plugin.config.client && + !isInstance(plugin as unknown as HeyApiSdkPlugin['Instance']) + ) { return true; } if (plugin.config.paramsStructure === 'flat') { diff --git a/packages/openapi-ts/src/utils/naming/naming.ts b/packages/openapi-ts/src/utils/naming/naming.ts index c2014480b..9685bfe1d 100644 --- a/packages/openapi-ts/src/utils/naming/naming.ts +++ b/packages/openapi-ts/src/utils/naming/naming.ts @@ -217,7 +217,7 @@ export function applyNaming(value: string, config: NamingConfig): string { result = config.name(result); } else { // TODO: refactor so there's no need for separators? - const separator = casing === 'preserve' ? '' : '-'; + const separator = !casing || casing === 'preserve' ? '' : '-'; result = config.name.replace( '{{name}}', `${separator}${result}${separator}`, diff --git a/packages/openapi-ts/src/utils/naming/types.d.ts b/packages/openapi-ts/src/utils/naming/types.d.ts index 29f0cf521..1971666cb 100644 --- a/packages/openapi-ts/src/utils/naming/types.d.ts +++ b/packages/openapi-ts/src/utils/naming/types.d.ts @@ -1,3 +1,5 @@ +import type { MaybeFunc } from '~/types/utils'; + /** * Available casing strategies. */ @@ -13,7 +15,7 @@ export type Casing = * * Template supports `{{name}}` variable. */ -export type NameTransformer = string | ((name: string) => string); +export type NameTransformer = MaybeFunc<(name: string) => string>; /** * Full naming configuration. -- 2.51.2 From 316a7899d5c90c34895d0265d2fb6c9a77a55fee Mon Sep 17 00:00:00 2001 From: Lubos Date: Mon, 29 Dec 2025 01:49:57 +0800 Subject: [PATCH 10/15] chore: clean up operations config --- dev/openapi-ts.config.ts | 38 +++--- .../src/openApi/shared/utils/operation.ts | 14 +- .../src/plugins/@angular/common/plugin.ts | 4 +- .../common/{ => shared}/httpRequests.ts | 2 +- .../common/{ => shared}/httpResources.ts | 2 +- .../src/plugins/@hey-api/sdk/config.ts | 6 +- .../sdk/{structure => operations}/config.ts | 60 ++++----- .../plugins/@hey-api/sdk/operations/index.ts | 6 + .../sdk/{structure => operations}/resolve.ts | 20 +-- .../sdk/{structure => operations}/types.d.ts | 10 +- .../plugins/@hey-api/sdk/shared/operation.ts | 16 ++- .../plugins/@hey-api/sdk/structure/index.ts | 6 - .../src/plugins/@hey-api/sdk/types.d.ts | 121 +++++------------- .../src/plugins/@hey-api/sdk/v1/plugin.ts | 33 +++-- 14 files changed, 138 insertions(+), 200 deletions(-) rename packages/openapi-ts/src/plugins/@angular/common/{ => shared}/httpRequests.ts (99%) rename packages/openapi-ts/src/plugins/@angular/common/{ => shared}/httpResources.ts (99%) rename packages/openapi-ts/src/plugins/@hey-api/sdk/{structure => operations}/config.ts (76%) create mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/operations/index.ts rename packages/openapi-ts/src/plugins/@hey-api/sdk/{structure => operations}/resolve.ts (57%) rename packages/openapi-ts/src/plugins/@hey-api/sdk/{structure => operations}/types.d.ts (96%) delete mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/structure/index.ts diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index 05b3b87bd..907e5d760 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -291,29 +291,27 @@ export default defineConfig(() => { // methodNameBuilder: '{{name}}', name: '@hey-api/sdk', // operationId: true, + operations: { + // container: 'object', + containerName: { + // casing: 'snake_case', + // name: 'OpencodeClient' + }, + methodName: { + // casing: 'SCREAMING_SNAKE_CASE', + name: '{{name}}Yummy', + }, + methods: 'static', + nesting: 'id', + segmentName: '{{name}}Seggy', + strategy: 'byTags', + strategyDefaultTag: 'DaxLikedThis', + }, // paramsStructure: 'flat', // responseStyle: 'data', // signature: 'auto', // signature: 'client', // signature: 'object', - structure: { - operations: { - // container: 'object', - containerName: { - // casing: 'snake_case', - // name: 'OpencodeClient' - }, - methodName: { - // casing: 'SCREAMING_SNAKE_CASE', - name: '{{name}}Yummy', - }, - methods: 'static', - nesting: 'id', - segmentName: '{{name}}Seggy', - strategy: 'byTags', - strategyDefaultTag: 'DaxLikedThis', - }, - }, // transformer: '@hey-api/transformers', // transformer: true, // validator: 'valibot', @@ -620,8 +618,8 @@ export default defineConfig(() => { { exportFromIndex: true, httpRequests: { - asClass: true, - // enabled: false, + // asClass: true, + enabled: false, }, httpResources: { // asClass: true, diff --git a/packages/openapi-ts/src/openApi/shared/utils/operation.ts b/packages/openapi-ts/src/openApi/shared/utils/operation.ts index 99aa47b39..2b8eb68f7 100644 --- a/packages/openapi-ts/src/openApi/shared/utils/operation.ts +++ b/packages/openapi-ts/src/openApi/shared/utils/operation.ts @@ -50,13 +50,13 @@ export const operationToId = ({ id && (!context.config.plugins['@hey-api/sdk'] || // TODO: needs to be refactored... - (context.config.plugins['@hey-api/sdk'].config.structure?.operations && - typeof context.config.plugins['@hey-api/sdk'].config.structure - ?.operations !== 'function' && - typeof context.config.plugins['@hey-api/sdk'].config.structure - ?.operations === 'object' && - context.config.plugins['@hey-api/sdk'].config.structure?.operations - .nesting === 'operationId')) + (context.config.plugins['@hey-api/sdk'].config.operations && + typeof context.config.plugins['@hey-api/sdk'].config.operations !== + 'function' && + typeof context.config.plugins['@hey-api/sdk'].config.operations === + 'object' && + context.config.plugins['@hey-api/sdk'].config.operations.nesting === + 'operationId')) ) { result = toCase(sanitizeNamespaceIdentifier(id), targetCase); } else { diff --git a/packages/openapi-ts/src/plugins/@angular/common/plugin.ts b/packages/openapi-ts/src/plugins/@angular/common/plugin.ts index d9a4f3cfd..e44fc08b8 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/plugin.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/plugin.ts @@ -1,5 +1,5 @@ -import { createHttpRequests } from './httpRequests'; -import { createHttpResources } from './httpResources'; +import { createHttpRequests } from './shared/httpRequests'; +import { createHttpResources } from './shared/httpResources'; import type { AngularCommonPlugin } from './types'; export const handler: AngularCommonPlugin['Handler'] = ({ plugin }) => { diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts b/packages/openapi-ts/src/plugins/@angular/common/shared/httpRequests.ts similarity index 99% rename from packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts rename to packages/openapi-ts/src/plugins/@angular/common/shared/httpRequests.ts index c984384df..438fe72b9 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/shared/httpRequests.ts @@ -7,7 +7,7 @@ import { import { $ } from '~/ts-dsl'; import { applyNaming, toCase } from '~/utils/naming'; -import type { AngularCommonPlugin } from './types'; +import type { AngularCommonPlugin } from '../types'; interface AngularRequestClassEntry { className: string; diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpResources.ts b/packages/openapi-ts/src/plugins/@angular/common/shared/httpResources.ts similarity index 99% rename from packages/openapi-ts/src/plugins/@angular/common/httpResources.ts rename to packages/openapi-ts/src/plugins/@angular/common/shared/httpResources.ts index 9fe5177c6..a077c7816 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/httpResources.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/shared/httpResources.ts @@ -7,7 +7,7 @@ import { import { $ } from '~/ts-dsl'; import { applyNaming, toCase } from '~/utils/naming'; -import type { AngularCommonPlugin } from './types'; +import type { AngularCommonPlugin } from '../types'; interface AngularServiceClassEntry { className: string; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts index 4617426a9..2f85ba9f2 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts @@ -1,7 +1,7 @@ import { definePluginConfig } from '~/plugins/shared/utils/config'; +import { resolveOperations } from './operations'; import { handler } from './plugin'; -import { resolveStructure } from './structure'; import type { HeyApiSdkPlugin } from './types'; export const defaultConfig: HeyApiSdkPlugin['Config'] = { @@ -71,9 +71,7 @@ export const defaultConfig: HeyApiSdkPlugin['Config'] = { plugin.config.validator.response = false; } - plugin.config.structure = { - operations: resolveStructure(plugin.config, context), - }; + plugin.config.operations = resolveOperations(plugin.config, context); }, }; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/config.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/config.ts similarity index 76% rename from packages/openapi-ts/src/plugins/@hey-api/sdk/structure/config.ts rename to packages/openapi-ts/src/plugins/@hey-api/sdk/operations/config.ts index e8296da56..1e711bc1a 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/config.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/config.ts @@ -4,24 +4,24 @@ import type { PluginContext } from '~/plugins/types'; import type { UserConfig } from '../types'; import type { - StructureConfig, - StructureStrategy, - UserStructureConfig, + OperationsConfig, + OperationsStrategy, + UserOperationsConfig, } from './types'; type Config = Omit; -export function resolveStructure( +export function resolveOperations( config: Config, context: PluginContext, -): StructureConfig { +): OperationsConfig { if (config.asClass !== undefined) { log.warnDeprecated({ context: '@hey-api/sdk', field: 'asClass', replacement: [ - 'structure.operations: { strategy: "byTags" }', - 'structure.operations: { strategy: "single" }', + 'operations: { strategy: "byTags" }', + 'operations: { strategy: "single" }', ], }); } @@ -30,7 +30,7 @@ export function resolveStructure( log.warnDeprecated({ context: '@hey-api/sdk', field: 'classNameBuilder', - replacement: 'structure.operations: { containerName: "..." }', + replacement: 'operations: { containerName: "..." }', }); } @@ -39,8 +39,8 @@ export function resolveStructure( context: '@hey-api/sdk', field: 'classStructure', replacement: [ - 'structure.operations: { nesting: "operationId" }', - 'structure.operations: { nesting: "id" }', + 'operations: { nesting: "operationId" }', + 'operations: { nesting: "id" }', ], }); } @@ -49,7 +49,7 @@ export function resolveStructure( log.warnDeprecated({ context: '@hey-api/sdk', field: 'instance', - replacement: `structure.operations: { strategy: "single", containerName: "${config.instance || 'Name'}", methods: "instance" }`, + replacement: `operations: { strategy: "single", containerName: "${config.instance || 'Name'}", methods: "instance" }`, }); } @@ -57,7 +57,7 @@ export function resolveStructure( log.warnDeprecated({ context: '@hey-api/sdk', field: 'methodNameBuilder', - replacement: 'structure.operations: { methodName: "..." }', + replacement: 'operations: { methodName: "..." }', }); } @@ -66,15 +66,15 @@ export function resolveStructure( context: '@hey-api/sdk', field: 'operationId', replacement: [ - 'structure.operations: { nesting: "operationId" }', - 'structure.operations: { nesting: "id" }', + 'operations: { nesting: "operationId" }', + 'operations: { nesting: "id" }', ], }); } const legacy = mapLegacyToConfig(config); - return config.structure?.operations - ? normalizeStructureConfig(config.structure.operations, legacy, context) + return config.operations + ? normalizeConfig(config.operations, legacy, context) : context.valueToObject({ defaultValue: { container: 'class', @@ -87,15 +87,15 @@ export function resolveStructure( strategy: 'flat', strategyDefaultTag: 'default', }, - value: legacy as StructureConfig, + value: legacy as OperationsConfig, }); } -function normalizeStructureConfig( - input: StructureStrategy | UserStructureConfig, - legacy: Partial, +function normalizeConfig( + input: OperationsStrategy | UserOperationsConfig, + legacy: Partial, context: PluginContext, -): StructureConfig { +): OperationsConfig { if (typeof input === 'string' || typeof input === 'function') { input = { strategy: input }; } @@ -146,11 +146,11 @@ function normalizeStructureConfig( value: { ...legacy, ...input, - } as UserStructureConfig, - }) as StructureConfig; + } as UserOperationsConfig, + }) as OperationsConfig; } -function mapLegacyToConfig(config: Config): Partial { +function mapLegacyToConfig(config: Config): Partial { // TODO: refactor... // Set default classNameBuilder based on client type if (config.classNameBuilder === '{{name}}') { @@ -159,7 +159,7 @@ function mapLegacyToConfig(config: Config): Partial { } } - let strategy: StructureConfig['strategy'] | undefined; + let strategy: OperationsConfig['strategy'] | undefined; if (config.instance) { strategy = 'single'; } else if (config.asClass) { @@ -168,8 +168,8 @@ function mapLegacyToConfig(config: Config): Partial { strategy = 'flat'; } - let containerName: StructureConfig['containerName'] | undefined; - let segmentName: StructureConfig['segmentName'] | undefined; + let containerName: OperationsConfig['containerName'] | undefined; + let segmentName: OperationsConfig['segmentName'] | undefined; if (config.instance) { let name = typeof config.instance === 'string' ? config.instance : 'Sdk'; segmentName = { casing: 'PascalCase' }; @@ -193,21 +193,21 @@ function mapLegacyToConfig(config: Config): Partial { segmentName = { ...containerName }; } - let methods: StructureConfig['methods'] | undefined; + let methods: OperationsConfig['methods'] | undefined; if (config.instance) { methods = 'instance'; } else if (config.asClass) { methods = 'static'; } - let nesting: StructureConfig['nesting'] | undefined; + let nesting: OperationsConfig['nesting'] | undefined; if (config.classStructure === 'off' || config.operationId === false) { nesting = 'id'; } else if (config.classStructure === 'auto') { nesting = 'operationId'; } - let methodName: StructureConfig['methodName'] | undefined; + let methodName: OperationsConfig['methodName'] | undefined; if (config.methodNameBuilder) { methodName = { casing: 'camelCase', diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/index.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/index.ts new file mode 100644 index 000000000..a9f588fd0 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/index.ts @@ -0,0 +1,6 @@ +export { resolveOperations } from './config'; +export type { + OperationsConfig, + OperationsStrategy, + UserOperationsConfig, +} from './types'; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/resolve.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/resolve.ts similarity index 57% rename from packages/openapi-ts/src/plugins/@hey-api/sdk/structure/resolve.ts rename to packages/openapi-ts/src/plugins/@hey-api/sdk/operations/resolve.ts index 3ab669e0b..f57e41554 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/resolve.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/resolve.ts @@ -9,42 +9,42 @@ import type { HeyApiSdkPlugin } from '../types'; function resolvePath( plugin: HeyApiSdkPlugin['Instance'], ): OperationPathStrategy { - if (plugin.config.structure.operations.nesting === 'id') { + if (plugin.config.operations.nesting === 'id') { return OperationPath.id(); } - if (plugin.config.structure.operations.nesting === 'operationId') { + if (plugin.config.operations.nesting === 'operationId') { return OperationPath.fromOperationId({ - delimiters: plugin.config.structure.operations.nestingDelimiters, + delimiters: plugin.config.operations.nestingDelimiters, }); } - return plugin.config.structure.operations.nesting; + return plugin.config.operations.nesting; } export function resolveStrategy( plugin: HeyApiSdkPlugin['Instance'], ): OperationStructureStrategy { - if (plugin.config.structure.operations.strategy === 'flat') { + if (plugin.config.operations.strategy === 'flat') { return OperationStrategies.flat({ path: resolvePath(plugin), }); } - if (plugin.config.structure.operations.strategy === 'single') { - const root = plugin.config.structure.operations.containerName; + if (plugin.config.operations.strategy === 'single') { + const root = plugin.config.operations.containerName; return OperationStrategies.single({ path: resolvePath(plugin), root: typeof root.name === 'string' ? root.name : (root.name?.('') ?? ''), }); } - if (plugin.config.structure.operations.strategy === 'byTags') { + if (plugin.config.operations.strategy === 'byTags') { return OperationStrategies.byTags({ - fallback: plugin.config.structure.operations.strategyDefaultTag, + fallback: plugin.config.operations.strategyDefaultTag, path: resolvePath(plugin), }); } - return plugin.config.structure.operations.strategy; + return plugin.config.operations.strategy; } diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/types.d.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/types.d.ts similarity index 96% rename from packages/openapi-ts/src/plugins/@hey-api/sdk/structure/types.d.ts rename to packages/openapi-ts/src/plugins/@hey-api/sdk/operations/types.d.ts index e74fadbde..76abe54ad 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/types.d.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/types.d.ts @@ -4,13 +4,13 @@ import type { } from '~/openApi/shared/locations'; import type { NamingConfig, NamingRule } from '~/utils/naming'; -export type StructureStrategy = +export type OperationsStrategy = | 'byTags' | 'flat' | 'single' | OperationStructureStrategy; -export interface UserStructureConfig { +export interface UserOperationsConfig { /** * Type of container for grouped operations. * @@ -96,7 +96,7 @@ export interface UserStructureConfig { * * @default 'flat' */ - strategy?: StructureStrategy; + strategy?: OperationsStrategy; /** * Default container name for operations without tags. * @@ -107,7 +107,7 @@ export interface UserStructureConfig { strategyDefaultTag?: string; } -export interface StructureConfig { +export interface OperationsConfig { /** * Type of container for grouped operations. * @@ -183,7 +183,7 @@ export interface StructureConfig { * - `'single'` - All operations in one container * - Custom function for full control */ - strategy: StructureStrategy; + strategy: OperationsStrategy; /** * Default container name for operations without tags. * diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts index 3eab17de2..19365f72d 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts @@ -44,9 +44,12 @@ const operationClassName = ({ // TODO: expose casing option const name = toCase(value, 'PascalCase'); return ( + // @ts-expect-error (typeof plugin.config.classNameBuilder === 'string' - ? plugin.config.classNameBuilder.replace('{{name}}', name) - : plugin.config.classNameBuilder(name)) || name + ? // @ts-expect-error + plugin.config.classNameBuilder.replace('{{name}}', name) + : // @ts-expect-error + plugin.config.classNameBuilder(name)) || name ); }; @@ -65,8 +68,10 @@ const operationMethodName = ({ // TODO: expose casing option const name = toCase(value || operation.id, 'camelCase'); return ( + // @ts-expect-error (typeof plugin.config.methodNameBuilder === 'string' - ? plugin.config.methodNameBuilder.replace('{{name}}', name) + ? // @ts-expect-error + plugin.config.methodNameBuilder.replace('{{name}}', name) : // @ts-expect-error TODO: remove plugin.config.methodNameBuilder?.(name, operation)) || name ); @@ -90,6 +95,7 @@ export const operationClasses = ({ let methodName: string | undefined; let classCandidates: Array = []; + // @ts-expect-error if (plugin.config.classStructure === 'auto' && operation.operationId) { classCandidates = operation.operationId.split(/[./]/).filter(Boolean); if (classCandidates.length >= 2) { @@ -102,8 +108,10 @@ export const operationClasses = ({ } } + // @ts-expect-error const rootClasses = plugin.config.instance - ? [plugin.config.instance] + ? // @ts-expect-error + [plugin.config.instance] : (operation.tags ?? ['default']); for (const rootClass of rootClasses) { diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/index.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/index.ts deleted file mode 100644 index 735fbf6b8..000000000 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/structure/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { resolveStructure } from './config'; -export type { - StructureConfig, - StructureStrategy, - UserStructureConfig, -} from './types'; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts index c64209330..00504200e 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts @@ -3,10 +3,10 @@ import type { PluginClientNames, PluginValidatorNames } from '~/plugins/types'; import type { NameTransformer } from '~/utils/naming'; import type { - StructureConfig, - StructureStrategy, - UserStructureConfig, -} from './structure'; + OperationsConfig, + OperationsStrategy, + UserOperationsConfig, +} from './operations'; export type UserConfig = Plugin.Name<'@hey-api/sdk'> & Plugin.Hooks & { @@ -37,6 +37,20 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * @default true */ exportFromIndex?: boolean; + /** + * Define the structure of generated SDK operations. + * + * String shorthand: + * - `'byTags'` – one container per operation tag + * - `'flat'` – standalone functions, no container + * - `'single'` – all operations in a single container + * - custom function for full control + * + * Use the object form for advanced configuration. + * + * @default 'flat' + */ + operations?: OperationsStrategy | UserOperationsConfig; /** * Define how request parameters are structured in generated SDK methods. * @@ -56,25 +70,6 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * @default 'fields' */ responseStyle?: 'data' | 'fields'; - /** - * Define how generated outputs are structurally organized. - */ - structure?: { - /** - * Define the structure of generated SDK operations. - * - * String shorthand: - * - `'flat'` – standalone functions, no container - * - `'byTags'` – one container per operation tag - * - `'single'` – all operations in a single container - * - custom function for full control - * - * Use the object form for advanced configuration. - * - * @default 'flat' - */ - operations?: StructureStrategy | UserStructureConfig; - }; /** * Transform response data before returning. This is useful if you want to * convert for example ISO strings into Date objects. However, transformation @@ -140,7 +135,7 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * support {@link https://developer.mozilla.org/docs/Glossary/Tree_shaking tree-shaking}. * For this reason, it is disabled by default. * - * @deprecated Use `grouping: 'byTags'` or `grouping: 'single'` instead. + * @deprecated Use `operations: { strategy: "byTags" }` or `operations: { strategy: "single" }` instead. * @default false */ // eslint-disable-next-line typescript-sort-keys/interface @@ -151,7 +146,7 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * * This option has no effect if `sdk.asClass` is `false`. * - * @deprecated Use `grouping.containerName` instead. + * @deprecated Use `operations: { containerName: "..." }` instead. */ classNameBuilder?: NameTransformer; /** @@ -159,7 +154,7 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * structure using `operationId` keywords. If you prefer a flatter structure, * you can set `classStructure` to `off` to disable this behavior. * - * @deprecated Use `grouping: { nesting: 'operationId' }` or `grouping: { nesting: 'id' }` instead. + * @deprecated Use `operations: { nesting: "operationId" }` or `operations: { nesting: "id" }` instead. * @default 'auto' */ classStructure?: 'auto' | 'off'; @@ -168,7 +163,7 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * default instance name; in practice, you want to define your own by passing * a string value. * - * @deprecated Use `grouping: { strategy: 'single', as: 'Name', methods: 'instance' }` instead. + * @deprecated Use `operations: { strategy: "single", containerName: "Name", methods: "instance" }` instead. * @default false */ instance?: string | boolean; @@ -176,13 +171,13 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * Customise the name of methods within the service. By default, * `operation.id` is used. * - * @deprecated Use `grouping.methodName` instead. + * @deprecated Use `operations: { methodName: "..." }` instead. */ methodNameBuilder?: NameTransformer; /** * Use operation ID to generate operation names? * - * @deprecated Use `grouping.nesting: 'operationId'` or `grouping.nesting: 'id'` instead. + * @deprecated Use `operations: { nesting: "operationId" }` or `operations: { nesting: "id" }` instead. * @default true */ operationId?: boolean; @@ -224,6 +219,10 @@ export type Config = Plugin.Name<'@hey-api/sdk'> & * @default true */ exportFromIndex: boolean; + /** + * Define the structure of generated SDK operations. + */ + operations: OperationsConfig; /** * Define how request parameters are structured in generated SDK methods. * @@ -243,15 +242,6 @@ export type Config = Plugin.Name<'@hey-api/sdk'> & * @default 'fields' */ responseStyle: 'data' | 'fields'; - /** - * Define how generated outputs are structurally organized. - */ - structure: { - /** - * Define the structure of generated SDK operations. - */ - operations: StructureConfig; - }; /** * Transform response data before returning. This is useful if you want to * convert for example ISO strings into Date objects. However, transformation @@ -287,66 +277,13 @@ export type Config = Plugin.Name<'@hey-api/sdk'> & // DEPRECATED OPTIONS BELOW - /** - * Group operation methods into classes? When enabled, you can select which - * classes to export with `sdk.include` and/or transform their names with - * `sdk.classNameBuilder`. - * - * Note that by enabling this option, your SDKs will **NOT** - * support {@link https://developer.mozilla.org/docs/Glossary/Tree_shaking tree-shaking}. - * For this reason, it is disabled by default. - * - * @deprecated Use `grouping: 'byTags'` or `grouping: 'single'` instead. - * @default false - */ - // eslint-disable-next-line typescript-sort-keys/interface - asClass: boolean; - /** - * Customize the generated class names. The name variable is obtained from - * your OpenAPI specification tags or `instance` value. - * - * This option has no effect if `sdk.asClass` is `false`. - * - * @deprecated Use `grouping.containerName` instead. - */ - classNameBuilder: NameTransformer; - /** - * How should we structure your SDK? By default, we try to infer the ideal - * structure using `operationId` keywords. If you prefer a flatter structure, - * you can set `classStructure` to `off` to disable this behavior. - * - * @deprecated Use `grouping: { nesting: 'operationId' }` or `grouping: { nesting: 'id' }` instead. - * @default 'auto' - */ - classStructure: 'auto' | 'off'; - /** - * Set `instance` to create an instantiable SDK. Using `true` will use the - * default instance name; in practice, you want to define your own by passing - * a string value. - * - * @deprecated Use `grouping: { strategy: 'single', as: 'Name', methods: 'instance' }` instead. - */ - instance: string; - /** - * Customise the name of methods within the service. By default, - * `operation.id` is used. - * - * @deprecated Use `grouping.methodName` instead. - */ - methodNameBuilder: NameTransformer; - /** - * Use operation ID to generate operation names? - * - * @deprecated Use `grouping.nesting: 'operationId'` or `grouping.nesting: 'id'` instead. - * @default true - */ - operationId: boolean; /** * Define shape of returned value from service calls * * @deprecated * @default 'body' */ + // eslint-disable-next-line typescript-sort-keys/interface response: 'body' | 'response'; }; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts index cc06e6f17..967170cc4 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts @@ -16,11 +16,11 @@ import { import { $ } from '~/ts-dsl'; import { applyNaming, toCase } from '~/utils/naming'; +import { resolveStrategy } from '../operations/resolve'; import { createClientClass, createRegistryClass } from '../shared/class'; import { nuxtTypeComposable, nuxtTypeDefault } from '../shared/constants'; import { operationParameters, operationStatements } from '../shared/operation'; import { createTypeOptions } from '../shared/typeOptions'; -import { resolveStrategy } from '../structure/resolve'; import type { HeyApiSdkPlugin } from '../types'; interface OperationItem { @@ -44,19 +44,16 @@ function createFnSymbol( ): Symbol { const { operation, path, tags } = item.data; const name = item.location[item.location.length - 1]!; - return plugin.symbol( - applyNaming(name, plugin.config.structure.operations.methodName), - { - meta: { - category: 'sdk', - path, - resource: 'operation', - resourceId: operation.id, - tags, - tool: 'sdk', - }, + return plugin.symbol(applyNaming(name, plugin.config.operations.methodName), { + meta: { + category: 'sdk', + path, + resource: 'operation', + resourceId: operation.id, + tags, + tool: 'sdk', }, - ); + }); } function childToNode( @@ -323,8 +320,8 @@ function createShell(plugin: HeyApiSdkPlugin['Instance']): StructureShell { applyNaming( node.name, node.isRoot - ? plugin.config.structure.operations.containerName - : plugin.config.structure.operations.segmentName, + ? plugin.config.operations.containerName + : plugin.config.operations.segmentName, ), { meta: { @@ -374,7 +371,7 @@ function createShell(plugin: HeyApiSdkPlugin['Instance']): StructureShell { } export function isInstance(plugin: HeyApiSdkPlugin['Instance']): boolean { - const config = plugin.config.structure.operations; + const config = plugin.config.operations; return ( config.container === 'class' && config.methods === 'instance' && @@ -425,8 +422,8 @@ export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { } if ( isAngularClient && - plugin.config.structure.operations.container === 'class' && - plugin.config.structure.operations.strategy !== 'flat' + plugin.config.operations.container === 'class' && + plugin.config.operations.strategy !== 'flat' ) { plugin.symbol('Injectable', { external: '@angular/core', -- 2.51.2 From 206d5acac7ae873557b2765a0ab4d5292ce94ca9 Mon Sep 17 00:00:00 2001 From: Lubos Date: Mon, 29 Dec 2025 03:57:33 +0800 Subject: [PATCH 11/15] chore: angular plugin structure --- dev/openapi-ts.config.ts | 16 +- .../src/openApi/common/parser/sanitize.ts | 21 - .../src/openApi/shared/locations/index.ts | 1 + .../src/openApi/shared/locations/operation.ts | 6 + .../utils}/__tests__/sanitize.test.ts | 2 +- .../src/openApi/shared/utils/operation.ts | 23 +- .../src/plugins/@angular/common/config.ts | 39 +- .../@angular/common/httpRequests/config.ts | 68 +++ .../@angular/common/httpRequests/index.ts | 3 + .../@angular/common/httpRequests/resolve.ts | 50 ++ .../@angular/common/httpRequests/types.d.ts | 193 +++++++ .../@angular/common/httpResources/config.ts | 68 +++ .../@angular/common/httpResources/index.ts | 3 + .../@angular/common/httpResources/resolve.ts | 50 ++ .../@angular/common/httpResources/types.d.ts | 193 +++++++ .../src/plugins/@angular/common/plugin.ts | 82 ++- .../@angular/common/shared/httpRequests.ts | 298 ----------- .../@angular/common/shared/httpResources.ts | 362 ------------- .../plugins/@angular/common/shared/node.ts | 475 ++++++++++++++++++ .../src/plugins/@angular/common/types.d.ts | 120 +---- .../plugins/@hey-api/sdk/operations/config.ts | 15 +- .../plugins/@hey-api/sdk/operations/index.ts | 7 +- .../@hey-api/sdk/operations/types.d.ts | 24 +- .../plugins/@hey-api/sdk/shared/operation.ts | 125 +---- .../@hey-api/sdk/shared/typeOptions.ts | 2 +- .../src/plugins/@hey-api/sdk/types.d.ts | 7 +- .../src/plugins/@hey-api/sdk/v1/node.ts | 380 ++++++++++++++ .../src/plugins/@hey-api/sdk/v1/plugin.ts | 384 +------------- .../src/plugins/shared/utils/operation.ts | 2 +- .../openapi-ts/src/ts-dsl/utils/context.ts | 9 +- 30 files changed, 1654 insertions(+), 1374 deletions(-) delete mode 100644 packages/openapi-ts/src/openApi/common/parser/sanitize.ts rename packages/openapi-ts/src/openApi/{common/parser => shared/utils}/__tests__/sanitize.test.ts (89%) create mode 100644 packages/openapi-ts/src/plugins/@angular/common/httpRequests/config.ts create mode 100644 packages/openapi-ts/src/plugins/@angular/common/httpRequests/index.ts create mode 100644 packages/openapi-ts/src/plugins/@angular/common/httpRequests/resolve.ts create mode 100644 packages/openapi-ts/src/plugins/@angular/common/httpRequests/types.d.ts create mode 100644 packages/openapi-ts/src/plugins/@angular/common/httpResources/config.ts create mode 100644 packages/openapi-ts/src/plugins/@angular/common/httpResources/index.ts create mode 100644 packages/openapi-ts/src/plugins/@angular/common/httpResources/resolve.ts create mode 100644 packages/openapi-ts/src/plugins/@angular/common/httpResources/types.d.ts delete mode 100644 packages/openapi-ts/src/plugins/@angular/common/shared/httpRequests.ts delete mode 100644 packages/openapi-ts/src/plugins/@angular/common/shared/httpResources.ts create mode 100644 packages/openapi-ts/src/plugins/@angular/common/shared/node.ts create mode 100644 packages/openapi-ts/src/plugins/@hey-api/sdk/v1/node.ts diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index 907e5d760..d0f3b808e 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -242,7 +242,7 @@ export default defineConfig(() => { { // baseUrl: false, // exportFromIndex: true, - // name: '@hey-api/client-angular', + name: '@hey-api/client-angular', // runtimeConfigPath: path.resolve(__dirname, 'hey-api.ts'), // runtimeConfigPath: './src/hey-api.ts', // strictBaseUrl: true, @@ -295,7 +295,7 @@ export default defineConfig(() => { // container: 'object', containerName: { // casing: 'snake_case', - // name: 'OpencodeClient' + name: 'OpencodeClient', }, methodName: { // casing: 'SCREAMING_SNAKE_CASE', @@ -304,8 +304,8 @@ export default defineConfig(() => { methods: 'static', nesting: 'id', segmentName: '{{name}}Seggy', - strategy: 'byTags', - strategyDefaultTag: 'DaxLikedThis', + strategy: 'flat', + // strategyDefaultTag: 'DaxLikedThis', }, // paramsStructure: 'flat', // responseStyle: 'data', @@ -618,12 +618,14 @@ export default defineConfig(() => { { exportFromIndex: true, httpRequests: { - // asClass: true, - enabled: false, + // enabled: false, + containerName: 'AngularTest', + segmentName: '{{name}}Seggy', + strategy: 'single', }, httpResources: { // asClass: true, - enabled: false, + // enabled: false, }, name: '@angular/common', }, diff --git a/packages/openapi-ts/src/openApi/common/parser/sanitize.ts b/packages/openapi-ts/src/openApi/common/parser/sanitize.ts deleted file mode 100644 index c8803f974..000000000 --- a/packages/openapi-ts/src/openApi/common/parser/sanitize.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Sanitizes namespace identifiers so they are valid TypeScript identifiers of a certain form. - * - * 1: Remove any leading characters that are illegal as starting character of a typescript identifier. - * 2: Replace illegal characters in remaining part of type name with hyphen (-). - * - * Step 1 should perhaps instead also replace illegal characters with underscore, or prefix with it, like sanitizeEnumName - * does. The way this is now one could perhaps end up removing all characters, if all are illegal start characters. It - * would be sort of a breaking change to do so, though, previously generated code might change then. - * - * JavaScript identifier regexp pattern retrieved from https://developer.mozilla.org/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers - * - * The output of this is expected to be converted to PascalCase - * - * @deprecated - */ -export const sanitizeNamespaceIdentifier = (name: string) => - name - .replace(/^[^\p{ID_Start}]+/u, '') - .replace(/[^$\u200c\u200d\p{ID_Continue}]/gu, '-') - .replace(/[$+]/g, '-'); diff --git a/packages/openapi-ts/src/openApi/shared/locations/index.ts b/packages/openapi-ts/src/openApi/shared/locations/index.ts index 8e6ed6e77..f687be48c 100644 --- a/packages/openapi-ts/src/openApi/shared/locations/index.ts +++ b/packages/openapi-ts/src/openApi/shared/locations/index.ts @@ -1,5 +1,6 @@ export type { OperationPathStrategy, + OperationsStrategy, OperationStructureStrategy, } from './operation'; export { OperationPath, OperationStrategies } from './operation'; diff --git a/packages/openapi-ts/src/openApi/shared/locations/operation.ts b/packages/openapi-ts/src/openApi/shared/locations/operation.ts index be2ca1eb7..ab4ae350f 100644 --- a/packages/openapi-ts/src/openApi/shared/locations/operation.ts +++ b/packages/openapi-ts/src/openApi/shared/locations/operation.ts @@ -20,6 +20,12 @@ export type OperationStructureStrategy = ( operation: IR.OperationObject, ) => ReadonlyArray; +export type OperationsStrategy = + | 'byTags' + | 'flat' + | 'single' + | OperationStructureStrategy; + /** * Built-in strategies for operations. */ diff --git a/packages/openapi-ts/src/openApi/common/parser/__tests__/sanitize.test.ts b/packages/openapi-ts/src/openApi/shared/utils/__tests__/sanitize.test.ts similarity index 89% rename from packages/openapi-ts/src/openApi/common/parser/__tests__/sanitize.test.ts rename to packages/openapi-ts/src/openApi/shared/utils/__tests__/sanitize.test.ts index 6d656b407..89a6c6245 100644 --- a/packages/openapi-ts/src/openApi/common/parser/__tests__/sanitize.test.ts +++ b/packages/openapi-ts/src/openApi/shared/utils/__tests__/sanitize.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { sanitizeNamespaceIdentifier } from '../sanitize'; +import { sanitizeNamespaceIdentifier } from '../operation'; describe('sanitizeNamespaceIdentifier', () => { it.each([ diff --git a/packages/openapi-ts/src/openApi/shared/utils/operation.ts b/packages/openapi-ts/src/openApi/shared/utils/operation.ts index 2b8eb68f7..20587396a 100644 --- a/packages/openapi-ts/src/openApi/shared/utils/operation.ts +++ b/packages/openapi-ts/src/openApi/shared/utils/operation.ts @@ -1,6 +1,5 @@ import type { Context } from '~/ir/context'; import { createOperationKey } from '~/ir/operation'; -import { sanitizeNamespaceIdentifier } from '~/openApi/common/parser/sanitize'; import { toCase } from '~/utils/naming'; import type { State } from '../types/state'; @@ -16,6 +15,28 @@ export const httpMethods = [ 'trace', ] as const; +/** + * Sanitizes namespace identifiers so they are valid TypeScript identifiers of a certain form. + * + * 1: Remove any leading characters that are illegal as starting character of a typescript identifier. + * 2: Replace illegal characters in remaining part of type name with hyphen (-). + * + * Step 1 should perhaps instead also replace illegal characters with underscore, or prefix with it, like sanitizeEnumName + * does. The way this is now one could perhaps end up removing all characters, if all are illegal start characters. It + * would be sort of a breaking change to do so, though, previously generated code might change then. + * + * JavaScript identifier regexp pattern retrieved from https://developer.mozilla.org/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers + * + * The output of this is expected to be converted to PascalCase + * + * @deprecated + */ +export const sanitizeNamespaceIdentifier = (name: string) => + name + .replace(/^[^\p{ID_Start}]+/u, '') + .replace(/[^$\u200c\u200d\p{ID_Continue}]/gu, '-') + .replace(/[$+]/g, '-'); + /** * Returns an operation ID to use across the application. By default, we try * to use the provided ID. If it's not provided or the SDK is configured diff --git a/packages/openapi-ts/src/plugins/@angular/common/config.ts b/packages/openapi-ts/src/plugins/@angular/common/config.ts index 66398724a..2fbb3c00a 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/config.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/config.ts @@ -1,5 +1,7 @@ import { definePluginConfig } from '~/plugins/shared/utils/config'; +import { resolveHttpRequests } from './httpRequests'; +import { resolveHttpResources } from './httpResources'; import { handler } from './plugin'; import type { AngularCommonPlugin } from './types'; @@ -11,41 +13,8 @@ export const defaultConfig: AngularCommonPlugin['Config'] = { handler, name: '@angular/common', resolveConfig: (plugin, context) => { - plugin.config.httpRequests = context.valueToObject({ - defaultValue: { - asClass: false, - classNameBuilder: '{{name}}Requests', - enabled: true, - }, - mappers: { - boolean: (enabled) => ({ enabled }), - }, - value: plugin.config.httpRequests, - }); - - if (!plugin.config.httpRequests.methodNameBuilder) { - const { asClass } = plugin.config.httpRequests; - plugin.config.httpRequests.methodNameBuilder = (operation) => - asClass ? `${operation.id}` : `${operation.id}Request`; - } - - plugin.config.httpResources = context.valueToObject({ - defaultValue: { - asClass: false, - classNameBuilder: '{{name}}Resources', - enabled: true, - }, - mappers: { - boolean: (enabled) => ({ enabled }), - }, - value: plugin.config.httpResources, - }); - - if (!plugin.config.httpResources.methodNameBuilder) { - const { asClass } = plugin.config.httpResources; - plugin.config.httpResources.methodNameBuilder = (operation) => - asClass ? `${operation.id}` : `${operation.id}Resource`; - } + plugin.config.httpRequests = resolveHttpRequests(plugin.config, context); + plugin.config.httpResources = resolveHttpResources(plugin.config, context); }, }; diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpRequests/config.ts b/packages/openapi-ts/src/plugins/@angular/common/httpRequests/config.ts new file mode 100644 index 000000000..ab62aba99 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@angular/common/httpRequests/config.ts @@ -0,0 +1,68 @@ +import type { PluginContext } from '~/plugins/types'; + +import type { UserConfig } from '../types'; +import type { HttpRequestsConfig, UserHttpRequestsConfig } from './types'; + +type Config = Omit; + +export function resolveHttpRequests( + config: Config, + context: PluginContext, +): HttpRequestsConfig { + let input = config.httpRequests; + if (typeof input === 'string' || typeof input === 'function') { + input = { strategy: input }; + } else if (typeof input === 'boolean' || !input) { + input = { enabled: Boolean(input) }; + } + + const strategy = input.strategy ?? 'flat'; + + return context.valueToObject({ + defaultValue: { + container: 'class', + enabled: true, + methods: 'static', + nesting: strategy === 'flat' ? 'id' : 'operationId', + nestingDelimiters: /[./]/, + strategy, + strategyDefaultTag: 'default', + }, + mappers: { + object(value) { + value.containerName = context.valueToObject({ + defaultValue: + strategy === 'single' + ? { casing: 'PascalCase', name: 'HttpRequests' } + : { casing: 'PascalCase' }, + mappers: { + function: (name) => ({ name }), + string: (name) => ({ name }), + }, + value: value.containerName, + }); + value.methodName = context.valueToObject({ + defaultValue: + strategy === 'flat' + ? { casing: 'camelCase', name: '{{name}}Request' } + : { casing: 'camelCase' }, + mappers: { + function: (name) => ({ name }), + string: (name) => ({ name }), + }, + value: value.methodName, + }); + value.segmentName = context.valueToObject({ + defaultValue: { casing: 'PascalCase', name: '{{name}}Requests' }, + mappers: { + function: (name) => ({ name }), + string: (name) => ({ name }), + }, + value: value.segmentName, + }); + return value; + }, + }, + value: input as UserHttpRequestsConfig, + }) as HttpRequestsConfig; +} diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpRequests/index.ts b/packages/openapi-ts/src/plugins/@angular/common/httpRequests/index.ts new file mode 100644 index 000000000..b9bc8730b --- /dev/null +++ b/packages/openapi-ts/src/plugins/@angular/common/httpRequests/index.ts @@ -0,0 +1,3 @@ +export { resolveHttpRequests } from './config'; +export { resolveHttpRequestsStrategy } from './resolve'; +export type { HttpRequestsConfig, UserHttpRequestsConfig } from './types'; diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpRequests/resolve.ts b/packages/openapi-ts/src/plugins/@angular/common/httpRequests/resolve.ts new file mode 100644 index 000000000..0cbd6cf06 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@angular/common/httpRequests/resolve.ts @@ -0,0 +1,50 @@ +import type { + OperationPathStrategy, + OperationStructureStrategy, +} from '~/openApi/shared/locations'; +import { OperationPath, OperationStrategies } from '~/openApi/shared/locations'; + +import type { AngularCommonPlugin } from '../types'; + +function resolvePath( + plugin: AngularCommonPlugin['Instance'], +): OperationPathStrategy { + if (plugin.config.httpRequests.nesting === 'id') { + return OperationPath.id(); + } + + if (plugin.config.httpRequests.nesting === 'operationId') { + return OperationPath.fromOperationId({ + delimiters: plugin.config.httpRequests.nestingDelimiters, + }); + } + + return plugin.config.httpRequests.nesting; +} + +export function resolveHttpRequestsStrategy( + plugin: AngularCommonPlugin['Instance'], +): OperationStructureStrategy { + if (plugin.config.httpRequests.strategy === 'flat') { + return OperationStrategies.flat({ + path: resolvePath(plugin), + }); + } + + if (plugin.config.httpRequests.strategy === 'single') { + const root = plugin.config.httpRequests.containerName; + return OperationStrategies.single({ + path: resolvePath(plugin), + root: typeof root.name === 'string' ? root.name : (root.name?.('') ?? ''), + }); + } + + if (plugin.config.httpRequests.strategy === 'byTags') { + return OperationStrategies.byTags({ + fallback: plugin.config.httpRequests.strategyDefaultTag, + path: resolvePath(plugin), + }); + } + + return plugin.config.httpRequests.strategy; +} diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpRequests/types.d.ts b/packages/openapi-ts/src/plugins/@angular/common/httpRequests/types.d.ts new file mode 100644 index 000000000..7a3723387 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@angular/common/httpRequests/types.d.ts @@ -0,0 +1,193 @@ +import type { + OperationPathStrategy, + OperationsStrategy, +} from '~/openApi/shared/locations'; +import type { NamingConfig, NamingRule } from '~/utils/naming'; + +export interface UserHttpRequestsConfig { + /** + * Type of container for grouped operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'class'` - Class with methods + * + * @default 'class' + */ + container?: 'class'; + /** + * Customize container names. + * + * For `'single'` strategy, this sets the root container name. + * For `'byTags'` strategy, this transforms tag names. + * + * @default 'Sdk' for `'single'` strategy + * + * @example + * // Set root name for single strategy + * containerName: 'MyApi' + * + * @example + * // Transform tag names with suffix + * containerName: '{{name}}Service' + * + * @example + * // With casing + * containerName: { name: '{{name}}Service', case: 'PascalCase' } + */ + containerName?: NamingRule; + /** + * Whether or not to create HTTP Request instances. + * + * @default true + */ + enabled?: boolean; + /** + * Customize method/function names. + * + * Applied to the final segment of the path (the method name). + */ + methodName?: NamingRule; + /** + * How methods are attached to class containers. + * + * Only applies when `container` is `'class'`. + * + * - `'static'` - Static methods, no instantiation required + * + * @default 'static' + */ + methods?: 'static'; + /** + * How to derive nesting structure from operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'operationId'` - Split operationId by delimiters (e.g., `users.list` → `Users.list()`) + * - `'id'` - Use operation id as-is, no nesting + * - Custom function for full control + * + * @default 'operationId' + */ + nesting?: 'operationId' | 'id' | OperationPathStrategy; + /** + * Delimiters for splitting operationId. + * + * Only applies when `nesting` is `'operationId'`. + * + * @default /[./]/ + */ + nestingDelimiters?: RegExp; + /** + * Customize nesting segment names. + * + * Applied to intermediate path segments (not the method name). + */ + segmentName?: NamingRule; + /** + * Grouping strategy. + * + * - `'flat'` - Standalone functions, no grouping + * - `'byTags'` - One container per operation tag + * - `'single'` - All operations in one container + * - Custom function for full control + * + * @default 'flat' + */ + strategy?: OperationsStrategy; + /** + * Default container name for operations without tags. + * + * Only applies when `strategy` is `'byTags'`. + * + * @default 'default' + */ + strategyDefaultTag?: string; +} + +export interface HttpRequestsConfig { + /** + * Type of container for grouped operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'class'` - Class with methods + */ + container: 'class'; + /** + * Customize container names. + * + * For `'single'` strategy, this sets the root container name. + * For `'byTags'` strategy, this transforms tag names. + * + * @default 'Sdk' for `'single'` strategy + * + * @example + * // Set root name for single strategy + * containerName: 'MyApi' + * + * @example + * // Transform tag names with suffix + * containerName: '{{name}}Service' + * + * @example + * // With casing + * containerName: { name: '{{name}}Service', case: 'PascalCase' } + */ + containerName: NamingConfig; + /** + * Whether or not to create HTTP Request instances. + */ + enabled: boolean; + /** + * Customize method/function names. + * + * Applied to the final segment of the path (the method name). + */ + methodName: NamingConfig; + /** + * How methods are attached to class containers. + * + * Only applies when `container` is `'class'`. + * + * - `'static'` - Static methods, no instantiation required + */ + methods: 'static'; + /** + * How to derive nesting structure from operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'operationId'` - Split operationId by delimiters (e.g., `users.list` → `Users.list()`) + * - `'id'` - Use operation id as-is, no nesting + * - Custom function for full control + */ + nesting: 'operationId' | 'id' | OperationPathStrategy; + /** + * Delimiters for splitting operationId. + * + * Only applies when `nesting` is `'operationId'`. + */ + nestingDelimiters: RegExp; + /** + * Customize nesting segment names. + * + * Applied to intermediate path segments (not the method name). + */ + segmentName: NamingConfig; + /** + * Grouping strategy. + * + * - `'flat'` - Standalone functions, no grouping + * - `'byTags'` - One container per operation tag + * - `'single'` - All operations in one container + * - Custom function for full control + */ + strategy: OperationsStrategy; + /** + * Default container name for operations without tags. + * + * Only applies when `strategy` is `'byTags'`. + */ + strategyDefaultTag: string; +} diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpResources/config.ts b/packages/openapi-ts/src/plugins/@angular/common/httpResources/config.ts new file mode 100644 index 000000000..c3a570f81 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@angular/common/httpResources/config.ts @@ -0,0 +1,68 @@ +import type { PluginContext } from '~/plugins/types'; + +import type { UserConfig } from '../types'; +import type { HttpResourcesConfig, UserHttpResourcesConfig } from './types'; + +type Config = Omit; + +export function resolveHttpResources( + config: Config, + context: PluginContext, +): HttpResourcesConfig { + let input = config.httpResources; + if (typeof input === 'string' || typeof input === 'function') { + input = { strategy: input }; + } else if (typeof input === 'boolean' || !input) { + input = { enabled: Boolean(input) }; + } + + const strategy = input.strategy ?? 'flat'; + + return context.valueToObject({ + defaultValue: { + container: 'class', + enabled: true, + methods: 'static', + nesting: strategy === 'flat' ? 'id' : 'operationId', + nestingDelimiters: /[./]/, + strategy, + strategyDefaultTag: 'default', + }, + mappers: { + object(value) { + value.containerName = context.valueToObject({ + defaultValue: + strategy === 'single' + ? { casing: 'PascalCase', name: 'HttpResources' } + : { casing: 'PascalCase' }, + mappers: { + function: (name) => ({ name }), + string: (name) => ({ name }), + }, + value: value.containerName, + }); + value.methodName = context.valueToObject({ + defaultValue: + strategy === 'flat' + ? { casing: 'camelCase', name: '{{name}}Resource' } + : { casing: 'camelCase' }, + mappers: { + function: (name) => ({ name }), + string: (name) => ({ name }), + }, + value: value.methodName, + }); + value.segmentName = context.valueToObject({ + defaultValue: { casing: 'PascalCase', name: '{{name}}Resources' }, + mappers: { + function: (name) => ({ name }), + string: (name) => ({ name }), + }, + value: value.segmentName, + }); + return value; + }, + }, + value: input as UserHttpResourcesConfig, + }) as HttpResourcesConfig; +} diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpResources/index.ts b/packages/openapi-ts/src/plugins/@angular/common/httpResources/index.ts new file mode 100644 index 000000000..e99060061 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@angular/common/httpResources/index.ts @@ -0,0 +1,3 @@ +export { resolveHttpResources } from './config'; +export { resolveHttpResourcesStrategy } from './resolve'; +export type { HttpResourcesConfig, UserHttpResourcesConfig } from './types'; diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpResources/resolve.ts b/packages/openapi-ts/src/plugins/@angular/common/httpResources/resolve.ts new file mode 100644 index 000000000..c1af5acf0 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@angular/common/httpResources/resolve.ts @@ -0,0 +1,50 @@ +import type { + OperationPathStrategy, + OperationStructureStrategy, +} from '~/openApi/shared/locations'; +import { OperationPath, OperationStrategies } from '~/openApi/shared/locations'; + +import type { AngularCommonPlugin } from '../types'; + +function resolvePath( + plugin: AngularCommonPlugin['Instance'], +): OperationPathStrategy { + if (plugin.config.httpResources.nesting === 'id') { + return OperationPath.id(); + } + + if (plugin.config.httpResources.nesting === 'operationId') { + return OperationPath.fromOperationId({ + delimiters: plugin.config.httpResources.nestingDelimiters, + }); + } + + return plugin.config.httpResources.nesting; +} + +export function resolveHttpResourcesStrategy( + plugin: AngularCommonPlugin['Instance'], +): OperationStructureStrategy { + if (plugin.config.httpResources.strategy === 'flat') { + return OperationStrategies.flat({ + path: resolvePath(plugin), + }); + } + + if (plugin.config.httpResources.strategy === 'single') { + const root = plugin.config.httpResources.containerName; + return OperationStrategies.single({ + path: resolvePath(plugin), + root: typeof root.name === 'string' ? root.name : (root.name?.('') ?? ''), + }); + } + + if (plugin.config.httpResources.strategy === 'byTags') { + return OperationStrategies.byTags({ + fallback: plugin.config.httpResources.strategyDefaultTag, + path: resolvePath(plugin), + }); + } + + return plugin.config.httpResources.strategy; +} diff --git a/packages/openapi-ts/src/plugins/@angular/common/httpResources/types.d.ts b/packages/openapi-ts/src/plugins/@angular/common/httpResources/types.d.ts new file mode 100644 index 000000000..e10c244ad --- /dev/null +++ b/packages/openapi-ts/src/plugins/@angular/common/httpResources/types.d.ts @@ -0,0 +1,193 @@ +import type { + OperationPathStrategy, + OperationsStrategy, +} from '~/openApi/shared/locations'; +import type { NamingConfig, NamingRule } from '~/utils/naming'; + +export interface UserHttpResourcesConfig { + /** + * Type of container for grouped operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'class'` - Class with methods + * + * @default 'class' + */ + container?: 'class'; + /** + * Customize container names. + * + * For `'single'` strategy, this sets the root container name. + * For `'byTags'` strategy, this transforms tag names. + * + * @default 'Sdk' for `'single'` strategy + * + * @example + * // Set root name for single strategy + * containerName: 'MyApi' + * + * @example + * // Transform tag names with suffix + * containerName: '{{name}}Service' + * + * @example + * // With casing + * containerName: { name: '{{name}}Service', case: 'PascalCase' } + */ + containerName?: NamingRule; + /** + * Whether or not to create HTTP resource APIs. + * + * @default true + */ + enabled?: boolean; + /** + * Customize method/function names. + * + * Applied to the final segment of the path (the method name). + */ + methodName?: NamingRule; + /** + * How methods are attached to class containers. + * + * Only applies when `container` is `'class'`. + * + * - `'static'` - Static methods, no instantiation required + * + * @default 'static' + */ + methods?: 'static'; + /** + * How to derive nesting structure from operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'operationId'` - Split operationId by delimiters (e.g., `users.list` → `Users.list()`) + * - `'id'` - Use operation id as-is, no nesting + * - Custom function for full control + * + * @default 'operationId' + */ + nesting?: 'operationId' | 'id' | OperationPathStrategy; + /** + * Delimiters for splitting operationId. + * + * Only applies when `nesting` is `'operationId'`. + * + * @default /[./]/ + */ + nestingDelimiters?: RegExp; + /** + * Customize nesting segment names. + * + * Applied to intermediate path segments (not the method name). + */ + segmentName?: NamingRule; + /** + * Grouping strategy. + * + * - `'flat'` - Standalone functions, no grouping + * - `'byTags'` - One container per operation tag + * - `'single'` - All operations in one container + * - Custom function for full control + * + * @default 'flat' + */ + strategy?: OperationsStrategy; + /** + * Default container name for operations without tags. + * + * Only applies when `strategy` is `'byTags'`. + * + * @default 'default' + */ + strategyDefaultTag?: string; +} + +export interface HttpResourcesConfig { + /** + * Type of container for grouped operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'class'` - Class with methods + */ + container: 'class'; + /** + * Customize container names. + * + * For `'single'` strategy, this sets the root container name. + * For `'byTags'` strategy, this transforms tag names. + * + * @default 'Sdk' for `'single'` strategy + * + * @example + * // Set root name for single strategy + * containerName: 'MyApi' + * + * @example + * // Transform tag names with suffix + * containerName: '{{name}}Service' + * + * @example + * // With casing + * containerName: { name: '{{name}}Service', case: 'PascalCase' } + */ + containerName: NamingConfig; + /** + * Whether or not to create HTTP resource APIs. + */ + enabled: boolean; + /** + * Customize method/function names. + * + * Applied to the final segment of the path (the method name). + */ + methodName: NamingConfig; + /** + * How methods are attached to class containers. + * + * Only applies when `container` is `'class'`. + * + * - `'static'` - Static methods, no instantiation required + */ + methods: 'static'; + /** + * How to derive nesting structure from operations. + * + * Ignored when `strategy` is `'flat'`. + * + * - `'operationId'` - Split operationId by delimiters (e.g., `users.list` → `Users.list()`) + * - `'id'` - Use operation id as-is, no nesting + * - Custom function for full control + */ + nesting: 'operationId' | 'id' | OperationPathStrategy; + /** + * Delimiters for splitting operationId. + * + * Only applies when `nesting` is `'operationId'`. + */ + nestingDelimiters: RegExp; + /** + * Customize nesting segment names. + * + * Applied to intermediate path segments (not the method name). + */ + segmentName: NamingConfig; + /** + * Grouping strategy. + * + * - `'flat'` - Standalone functions, no grouping + * - `'byTags'` - One container per operation tag + * - `'single'` - All operations in one container + * - Custom function for full control + */ + strategy: OperationsStrategy; + /** + * Default container name for operations without tags. + * + * Only applies when `strategy` is `'byTags'`. + */ + strategyDefaultTag: string; +} diff --git a/packages/openapi-ts/src/plugins/@angular/common/plugin.ts b/packages/openapi-ts/src/plugins/@angular/common/plugin.ts index e44fc08b8..e971909a4 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/plugin.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/plugin.ts @@ -1,5 +1,17 @@ -import { createHttpRequests } from './shared/httpRequests'; -import { createHttpResources } from './shared/httpResources'; +import { StructureModel } from '@hey-api/codegen-core'; + +import type { $ } from '~/ts-dsl'; + +import { resolveHttpRequestsStrategy } from './httpRequests'; +import { resolveHttpResourcesStrategy } from './httpResources'; +import type { OperationItem } from './shared/node'; +import { + createHttpRequestShell, + createHttpResourceShell, + source, + toHttpRequestNode, + toHttpResourceNode, +} from './shared/node'; import type { AngularCommonPlugin } from './types'; export const handler: AngularCommonPlugin['Handler'] = ({ plugin }) => { @@ -33,11 +45,73 @@ export const handler: AngularCommonPlugin['Handler'] = ({ plugin }) => { }, }); + const httpRequestStructure = new StructureModel(); + const httpResourceStructure = new StructureModel(); + if (plugin.config.httpRequests.enabled) { - createHttpRequests({ plugin }); + const shell = createHttpRequestShell(plugin); + const strategy = resolveHttpRequestsStrategy(plugin); + + plugin.forEach( + 'operation', + ({ operation }) => { + httpRequestStructure.insert({ + data: { + operation, + } satisfies OperationItem, + locations: strategy(operation).map((path) => ({ path, shell })), + source, + }); + }, + { order: 'declarations' }, + ); } if (plugin.config.httpResources.enabled) { - createHttpResources({ plugin }); + const shell = createHttpResourceShell(plugin); + const strategy = resolveHttpResourcesStrategy(plugin); + + plugin.forEach( + 'operation', + ({ operation }) => { + httpResourceStructure.insert({ + data: { + operation, + } satisfies OperationItem, + locations: strategy(operation).map((path) => ({ path, shell })), + source, + }); + }, + { order: 'declarations' }, + ); + } + + const allDependencies: Array> = []; + const allNodes: Array> = []; + + for (const node of httpRequestStructure.walk()) { + const { dependencies, nodes } = toHttpRequestNode(node, plugin); + allDependencies.push(...(dependencies ?? [])); + allNodes.push(...nodes); + } + for (const node of httpResourceStructure.walk()) { + const { dependencies, nodes } = toHttpResourceNode(node, plugin); + allDependencies.push(...(dependencies ?? [])); + allNodes.push(...nodes); + } + + const uniqueDependencies = new Map< + number, + ReturnType + >(); + for (const dep of allDependencies) { + if (dep.symbol) uniqueDependencies.set(dep.symbol.id, dep); + } + for (const dep of uniqueDependencies.values()) { + plugin.node(dep); + } + + for (const node of allNodes) { + plugin.node(node); } }; diff --git a/packages/openapi-ts/src/plugins/@angular/common/shared/httpRequests.ts b/packages/openapi-ts/src/plugins/@angular/common/shared/httpRequests.ts deleted file mode 100644 index 438fe72b9..000000000 --- a/packages/openapi-ts/src/plugins/@angular/common/shared/httpRequests.ts +++ /dev/null @@ -1,298 +0,0 @@ -import type { IR } from '~/ir/types'; -import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; -import { - createOperationComment, - isOperationOptionsRequired, -} from '~/plugins/shared/utils/operation'; -import { $ } from '~/ts-dsl'; -import { applyNaming, toCase } from '~/utils/naming'; - -import type { AngularCommonPlugin } from '../types'; - -interface AngularRequestClassEntry { - className: string; - classes: Set; - methods: Set; - nodes: Array>; - root: boolean; -} - -const generateClassRequests = ({ - plugin, -}: { - plugin: AngularCommonPlugin['Instance']; -}) => { - const requestClasses = new Map(); - const generatedClasses = new Set(); - - const symbolHttpRequest = plugin.referenceSymbol({ - category: 'external', - resource: '@angular/common/http.HttpRequest', - }); - const symbolOptions = plugin.referenceSymbol({ - category: 'type', - resource: 'client-options', - tool: 'sdk', - }); - const symbolInjectable = plugin.referenceSymbol({ - category: 'external', - resource: '@angular/core.Injectable', - }); - - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); - - plugin.forEach( - 'operation', - ({ operation }) => { - const isRequiredOptions = isOperationOptionsRequired({ - context: plugin.context, - operation, - }); - - const classes = operationClasses({ operation, plugin: sdkPlugin }); - - for (const entry of classes.values()) { - entry.path.forEach((currentClassName, index) => { - if (!requestClasses.has(currentClassName)) { - requestClasses.set(currentClassName, { - className: currentClassName, - classes: new Set(), - methods: new Set(), - nodes: [], - root: !index, - }); - } - - const parentClassName = entry.path[index - 1]; - if (parentClassName && parentClassName !== currentClassName) { - const parentClass = requestClasses.get(parentClassName)!; - parentClass.classes.add(currentClassName); - requestClasses.set(parentClassName, parentClass); - } - - const isLast = entry.path.length === index + 1; - if (!isLast) { - return; - } - - const currentClass = requestClasses.get(currentClassName)!; - - const requestMethodName = - plugin.config.httpRequests.methodNameBuilder(operation); - - if (currentClass.methods.has(requestMethodName)) { - return; - } - - const symbolDataType = plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'data', - tool: 'typescript', - }); - - const methodNode = $.method(requestMethodName) - .public() - .$if(createOperationComment(operation), (c, v) => c.doc(v)) - .param('options', (p) => - p.required(isRequiredOptions).type( - $.type(symbolOptions) - .generic(symbolDataType ?? 'unknown') - .generic('ThrowOnError'), - ), - ) - .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) - .returns($.type(symbolHttpRequest).generic('unknown')) - .do( - $.return( - generateRequestCallExpression({ - operation, - plugin, - }), - ), - ); - - if (!currentClass.nodes.length) { - currentClass.nodes.push(methodNode); - } else { - currentClass.nodes.push($.newline(), methodNode); - } - - currentClass.methods.add(requestMethodName); - requestClasses.set(currentClassName, currentClass); - }); - } - }, - { - order: 'declarations', - }, - ); - - const generateClass = (currentClass: AngularRequestClassEntry) => { - if (generatedClasses.has(currentClass.className)) { - return; - } - - if (currentClass.classes.size) { - for (const childClassName of currentClass.classes) { - const childClass = requestClasses.get(childClassName)!; - generateClass(childClass); - - currentClass.nodes.push( - $.field(toCase(childClass.className, 'camelCase')).assign( - $.new( - applyNaming(childClass.className, { - case: 'preserve', - name: plugin.config.httpRequests.classNameBuilder, - }), - ), - ), - ); - } - } - - const symbolClass = plugin.symbol( - applyNaming(currentClass.className, { - case: 'preserve', - name: plugin.config.httpRequests.classNameBuilder, - }), - { - meta: { - category: 'utility', - resource: 'class', - resourceId: currentClass.className, - tool: 'angular', - }, - }, - ); - const node = $.class(symbolClass) - .export() - .$if(currentClass.root, (c) => - c.decorator( - symbolInjectable, - $.object().prop('providedIn', $.literal('root')), - ), - ) - .do(...currentClass.nodes); - plugin.node(node); - - generatedClasses.add(currentClass.className); - }; - - for (const requestClass of requestClasses.values()) { - generateClass(requestClass); - } -}; - -const generateFunctionRequests = ({ - plugin, -}: { - plugin: AngularCommonPlugin['Instance']; -}) => { - const symbolHttpRequest = plugin.referenceSymbol({ - category: 'external', - resource: '@angular/common/http.HttpRequest', - }); - const symbolOptions = plugin.referenceSymbol({ - category: 'type', - resource: 'client-options', - tool: 'sdk', - }); - - plugin.forEach( - 'operation', - ({ operation }) => { - const isRequiredOptions = isOperationOptionsRequired({ - context: plugin.context, - operation, - }); - - const symbol = plugin.symbol( - plugin.config.httpRequests.methodNameBuilder(operation), - { - meta: { - category: 'utility', - resource: 'operation', - resourceId: operation.id, - role: 'data', - tool: 'angular', - }, - }, - ); - - const symbolDataType = plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'data', - tool: 'typescript', - }); - - const node = $.const(symbol) - .export() - .$if(createOperationComment(operation), (c, v) => c.doc(v)) - .assign( - $.func() - .param('options', (p) => - p.required(isRequiredOptions).type( - $.type(symbolOptions) - .generic(symbolDataType ?? 'unknown') - .generic('ThrowOnError'), - ), - ) - .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) - .returns($.type(symbolHttpRequest).generic('unknown')) - .do( - $.return( - generateRequestCallExpression({ - operation, - plugin, - }), - ), - ), - ); - plugin.node(node); - }, - { - order: 'declarations', - }, - ); -}; - -const generateRequestCallExpression = ({ - operation, - plugin, -}: { - operation: IR.OperationObject; - plugin: AngularCommonPlugin['Instance']; -}) => { - const symbolClient = plugin.getSymbol({ - category: 'client', - }); - - const optionsClient = $('options') - .attr('client') - .optional() - .$if(symbolClient, (c, s) => c.coalesce(s)); - - return optionsClient - .attr('requestOptions') - .call( - $.object() - .prop('responseStyle', $.literal('data')) - .prop('method', $.literal(operation.method.toUpperCase())) - .prop('url', $.literal(operation.path)) - .spread('options'), - ); -}; - -export const createHttpRequests: AngularCommonPlugin['Handler'] = ({ - plugin, -}) => { - if (plugin.config.httpRequests.asClass) { - generateClassRequests({ plugin }); - } else { - generateFunctionRequests({ plugin }); - } -}; diff --git a/packages/openapi-ts/src/plugins/@angular/common/shared/httpResources.ts b/packages/openapi-ts/src/plugins/@angular/common/shared/httpResources.ts deleted file mode 100644 index a077c7816..000000000 --- a/packages/openapi-ts/src/plugins/@angular/common/shared/httpResources.ts +++ /dev/null @@ -1,362 +0,0 @@ -import type { IR } from '~/ir/types'; -import { operationClasses } from '~/plugins/@hey-api/sdk/shared/operation'; -import { - createOperationComment, - isOperationOptionsRequired, -} from '~/plugins/shared/utils/operation'; -import { $ } from '~/ts-dsl'; -import { applyNaming, toCase } from '~/utils/naming'; - -import type { AngularCommonPlugin } from '../types'; - -interface AngularServiceClassEntry { - className: string; - classes: Set; - methods: Set; - nodes: Array>; - root: boolean; -} - -const generateClassServices = ({ - plugin, -}: { - plugin: AngularCommonPlugin['Instance']; -}) => { - const serviceClasses = new Map(); - const generatedClasses = new Set(); - - const symbolInjectable = plugin.referenceSymbol({ - category: 'external', - resource: '@angular/core.Injectable', - }); - const symbolOptions = plugin.referenceSymbol({ - category: 'type', - resource: 'client-options', - tool: 'sdk', - }); - - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); - - plugin.forEach( - 'operation', - ({ operation }) => { - const isRequiredOptions = isOperationOptionsRequired({ - context: plugin.context, - operation, - }); - - const classes = operationClasses({ operation, plugin: sdkPlugin }); - - for (const entry of classes.values()) { - entry.path.forEach((currentClassName, index) => { - if (!serviceClasses.has(currentClassName)) { - serviceClasses.set(currentClassName, { - className: currentClassName, - classes: new Set(), - methods: new Set(), - nodes: [], - root: !index, - }); - } - - const parentClassName = entry.path[index - 1]; - if (parentClassName && parentClassName !== currentClassName) { - const parentClass = serviceClasses.get(parentClassName)!; - parentClass.classes.add(currentClassName); - serviceClasses.set(parentClassName, parentClass); - } - - const isLast = entry.path.length === index + 1; - if (!isLast) { - return; - } - - const currentClass = serviceClasses.get(currentClassName)!; - - const resourceMethodName = - plugin.config.httpResources.methodNameBuilder(operation); - - if (currentClass.methods.has(resourceMethodName)) { - return; - } - - const symbolDataType = plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'data', - tool: 'typescript', - }); - - const methodNode = $.method(resourceMethodName) - .public() - .$if(createOperationComment(operation), (c, v) => c.doc(v)) - .param('options', (p) => - p.required(isRequiredOptions).type( - $.type.func().returns( - $.type.or( - $.type(symbolOptions) - .generic(symbolDataType ?? 'unknown') - .generic('ThrowOnError'), - $.type('undefined'), - ), - ), - ), - ) - .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) - .do( - $.return( - generateResourceCallExpression({ - operation, - plugin, - }), - ), - ); - - if (!currentClass.nodes.length) { - currentClass.nodes.push(methodNode); - } else { - currentClass.nodes.push($.newline(), methodNode); - } - - currentClass.methods.add(resourceMethodName); - serviceClasses.set(currentClassName, currentClass); - }); - } - }, - { - order: 'declarations', - }, - ); - - const generateClass = (currentClass: AngularServiceClassEntry) => { - if (generatedClasses.has(currentClass.className)) { - return; - } - - if (currentClass.classes.size) { - for (const childClassName of currentClass.classes) { - const childClass = serviceClasses.get(childClassName)!; - generateClass(childClass); - - currentClass.nodes.push( - $.field(toCase(childClass.className, 'camelCase')).assign( - $.new( - applyNaming(childClass.className, { - case: 'preserve', - name: plugin.config.httpResources.classNameBuilder, - }), - ), - ), - ); - } - } - - const symbolClass = plugin.symbol( - applyNaming(currentClass.className, { - case: 'preserve', - name: plugin.config.httpResources.classNameBuilder, - }), - ); - const node = $.class(symbolClass) - .export() - .$if(currentClass.root, (c) => - c.decorator( - symbolInjectable, - $.object().prop('providedIn', $.literal('root')), - ), - ) - .do(...currentClass.nodes); - plugin.node(node); - - generatedClasses.add(currentClass.className); - }; - - for (const serviceClass of serviceClasses.values()) { - generateClass(serviceClass); - } -}; - -const generateFunctionServices = ({ - plugin, -}: { - plugin: AngularCommonPlugin['Instance']; -}) => { - const symbolOptions = plugin.referenceSymbol({ - category: 'type', - resource: 'client-options', - tool: 'sdk', - }); - - plugin.forEach( - 'operation', - ({ operation }) => { - const isRequiredOptions = isOperationOptionsRequired({ - context: plugin.context, - operation, - }); - - const symbol = plugin.symbol( - plugin.config.httpResources.methodNameBuilder(operation), - ); - - const symbolDataType = plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'data', - tool: 'typescript', - }); - - const node = $.const(symbol) - .export() - .$if(createOperationComment(operation), (c, v) => c.doc(v)) - .assign( - $.func() - .param('options', (p) => - p.required(isRequiredOptions).type( - $.type.func().returns( - $.type.or( - $.type(symbolOptions) - .generic(symbolDataType ?? 'unknown') - .generic('ThrowOnError'), - $.type('undefined'), - ), - ), - ), - ) - .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) - .do( - $.return( - generateResourceCallExpression({ - operation, - plugin, - }), - ), - ), - ); - plugin.node(node); - }, - { - order: 'declarations', - }, - ); -}; - -const generateResourceCallExpression = ({ - operation, - plugin, -}: { - operation: IR.OperationObject; - plugin: AngularCommonPlugin['Instance']; -}) => { - const sdkPlugin = plugin.getPluginOrThrow('@hey-api/sdk'); - - const symbolHttpResource = plugin.referenceSymbol({ - category: 'external', - resource: '@angular/common/http.httpResource', - }); - const symbolInject = plugin.referenceSymbol({ - category: 'external', - resource: '@angular/core.inject', - }); - - const symbolResponseType = plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'response', - }); - - if (plugin.config.httpRequests.asClass) { - // For class-based request methods, use inject and class hierarchy - const classes = operationClasses({ operation, plugin: sdkPlugin }); - - const firstEntry = Array.from(classes.values())[0]; - if (firstEntry) { - // Import the root class from HTTP requests - const rootClassName = firstEntry.path[0]!; - const symbolClass = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: rootClassName, - tool: 'angular', - }); - - // Build the method access path using inject - let methodAccess: ReturnType = - $(symbolInject).call(symbolClass); - - // Navigate through the class hierarchy - for (let i = 1; i < firstEntry.path.length; i++) { - const className = firstEntry.path[i]; - if (className) { - methodAccess = methodAccess.attr(toCase(className, 'camelCase')); - } - } - - methodAccess = methodAccess.attr( - plugin.config.httpRequests.methodNameBuilder(operation), - ); - - return $(symbolHttpResource) - .call( - $.func().do( - $.const('opts').assign( - $.ternary('options') - .do($('options').call()) - .otherwise($.id('undefined')), - ), - $.return( - $.ternary('opts') - .do(methodAccess.call('opts')) - .otherwise($.id('undefined')), - ), - ), - ) - .generic(symbolResponseType ?? 'unknown'); - } - } else { - const symbolHttpRequest = plugin.referenceSymbol({ - category: 'utility', - resource: 'operation', - resourceId: operation.id, - role: 'data', - tool: 'angular', - }); - - return $(symbolHttpResource) - .call( - $.func().do( - $.const('opts').assign( - $.ternary('options') - .do($('options').call()) - .otherwise($.id('undefined')), - ), - $.return( - $.ternary('opts') - .do($(symbolHttpRequest).call('opts')) - .otherwise($.id('undefined')), - ), - ), - ) - .generic(symbolResponseType ?? 'unknown'); - } - - // Fallback return (should not reach here) - return $(symbolHttpResource).call( - $.func() - .do($.return($.id('undefined'))) - .generic(symbolResponseType ?? 'unknown'), - ); -}; - -export const createHttpResources: AngularCommonPlugin['Handler'] = ({ - plugin, -}) => { - if (plugin.config.httpResources.asClass) { - generateClassServices({ plugin }); - } else { - generateFunctionServices({ plugin }); - } -}; diff --git a/packages/openapi-ts/src/plugins/@angular/common/shared/node.ts b/packages/openapi-ts/src/plugins/@angular/common/shared/node.ts new file mode 100644 index 000000000..674910f00 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@angular/common/shared/node.ts @@ -0,0 +1,475 @@ +import type { + StructureItem, + StructureNode, + StructureShell, + Symbol, + SymbolMeta, +} from '@hey-api/codegen-core'; + +import type { IR } from '~/ir/types'; +import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; +import { + createOperationComment, + isOperationOptionsRequired, +} from '~/plugins/shared/utils/operation'; +import { $ } from '~/ts-dsl'; +import { applyNaming, toCase } from '~/utils/naming'; + +import type { AngularCommonPlugin } from '../types'; + +export interface OperationItem { + operation: IR.OperationObject; +} + +export const source = globalThis.Symbol('@angular/common'); + +function attachComment< + T extends ReturnType, +>(args: { node: T; operation: IR.OperationObject }): T { + const { node, operation } = args; + return node.$if(createOperationComment(operation), (n, v) => n.doc(v)) as T; +} + +function createHttpRequestFnMeta(operation: IR.OperationObject): SymbolMeta { + return { + category: 'utility', + resource: 'operation', + resourceId: operation.id, + role: 'request', + tool: 'angular', + }; +} + +function createHttpRequestShellMeta(node: StructureNode): SymbolMeta { + return { + category: 'utility', + resource: 'shell', + resourceId: node.getPath().join('.'), + role: 'request', + tool: 'angular', + }; +} + +function createHttpResourceFnMeta(operation: IR.OperationObject): SymbolMeta { + return { + category: 'utility', + resource: 'operation', + resourceId: operation.id, + role: 'resource', + tool: 'angular', + }; +} + +function createHttpResourceShellMeta(node: StructureNode): SymbolMeta { + return { + category: 'utility', + resource: 'shell', + resourceId: node.getPath().join('.'), + role: 'resource', + tool: 'angular', + }; +} + +function createHttpRequestFnSymbol( + plugin: AngularCommonPlugin['Instance'], + item: StructureItem & { data: OperationItem }, +): Symbol { + const { operation } = item.data; + const name = item.location[item.location.length - 1]!; + return plugin.symbol( + applyNaming(name, plugin.config.httpRequests.methodName), + { + meta: createHttpRequestFnMeta(operation), + }, + ); +} + +function createHttpResourceFnSymbol( + plugin: AngularCommonPlugin['Instance'], + item: StructureItem & { data: OperationItem }, +): Symbol { + const { operation } = item.data; + const name = item.location[item.location.length - 1]!; + return plugin.symbol( + applyNaming(name, plugin.config.httpResources.methodName), + { + meta: createHttpResourceFnMeta(operation), + }, + ); +} + +function childToHttpRequestNode( + resource: StructureNode, + plugin: AngularCommonPlugin['Instance'], +): ReadonlyArray> { + const refChild = plugin.referenceSymbol(createHttpRequestShellMeta(resource)); + const memberNameStr = toCase(refChild.name, 'camelCase'); + const memberName = plugin.symbol(memberNameStr); + if (plugin.isSymbolRegistered(refChild.id)) { + return [$.field(memberName, (f) => f.static().assign($(refChild)))]; + } + return [ + $.getter(memberName, (g) => g.public().static().do($.return(refChild))), + ]; +} + +function childToHttpResourceNode( + resource: StructureNode, + plugin: AngularCommonPlugin['Instance'], +): ReadonlyArray> { + const refChild = plugin.referenceSymbol( + createHttpResourceShellMeta(resource), + ); + const memberNameStr = toCase(refChild.name, 'camelCase'); + const memberName = plugin.symbol(memberNameStr); + if (plugin.isSymbolRegistered(refChild.id)) { + return [$.field(memberName, (f) => f.static().assign($(refChild)))]; + } + return [ + $.getter(memberName, (g) => g.public().static().do($.return(refChild))), + ]; +} + +export function createHttpRequestShell( + plugin: AngularCommonPlugin['Instance'], +): StructureShell { + const client = getClientPlugin(plugin.context.config); + const isAngularClient = client.name === '@hey-api/client-angular'; + + const symbolInjectable = plugin.external('@angular/core.Injectable'); + + return { + define: (node) => { + const symbol = plugin.symbol( + applyNaming( + node.name, + node.isRoot + ? plugin.config.httpRequests.containerName + : plugin.config.httpRequests.segmentName, + ), + { + meta: createHttpRequestShellMeta(node), + }, + ); + + const c = $.class(symbol) + .export() + .$if(isAngularClient && node.isRoot, (c) => + c.decorator( + symbolInjectable, + $.object().prop('providedIn', $.literal('root')), + ), + ); + + return { dependencies: [], node: c }; + }, + }; +} + +export function createHttpResourceShell( + plugin: AngularCommonPlugin['Instance'], +): StructureShell { + const symbolInjectable = plugin.external('@angular/core.Injectable'); + + return { + define: (node) => { + const symbol = plugin.symbol( + applyNaming( + node.name, + node.isRoot + ? plugin.config.httpResources.containerName + : plugin.config.httpResources.segmentName, + ), + { + meta: createHttpResourceShellMeta(node), + }, + ); + + const c = $.class(symbol) + .export() + .$if(node.isRoot, (c) => + c.decorator( + symbolInjectable, + $.object().prop('providedIn', $.literal('root')), + ), + ); + + return { dependencies: [], node: c }; + }, + }; +} + +function implementHttpRequestFn< + T extends ReturnType, +>(args: { + node: T; + operation: IR.OperationObject; + plugin: AngularCommonPlugin['Instance']; +}): T { + const { node, operation, plugin } = args; + const isRequiredOptions = isOperationOptionsRequired({ + context: plugin.context, + operation, + }); + + const symbolHttpRequest = plugin.external('@angular/common/http.HttpRequest'); + const symbolClient = plugin.getSymbol({ category: 'client' }); + const symbolOptions = plugin.referenceSymbol({ + category: 'type', + resource: 'client-options', + tool: 'sdk', + }); + const symbolDataType = plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'data', + tool: 'typescript', + }); + + return node + .param('options', (p) => + p.required(isRequiredOptions).type( + $.type(symbolOptions) + .generic(symbolDataType ?? 'unknown') + .generic('ThrowOnError'), + ), + ) + .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) + .returns($.type(symbolHttpRequest).generic('unknown')) + .do( + $.return( + $('options') + .attr('client') + .optional() + .$if(symbolClient, (c, s) => c.coalesce(s)) + .attr('requestOptions') + .call( + $.object() + .prop('responseStyle', $.literal('data')) + .prop('method', $.literal(operation.method.toUpperCase())) + .prop('url', $.literal(operation.path)) + .spread('options'), + ), + ), + ) as T; +} + +function implementHttpResourceFn< + T extends ReturnType, +>(args: { + node: T; + operation: IR.OperationObject; + plugin: AngularCommonPlugin['Instance']; +}): T { + const { node, operation, plugin } = args; + const isRequiredOptions = isOperationOptionsRequired({ + context: plugin.context, + operation, + }); + + const symbolHttpResource = plugin.external( + '@angular/common/http.httpResource', + ); + const symbolOptions = plugin.referenceSymbol({ + category: 'type', + resource: 'client-options', + tool: 'sdk', + }); + const symbolDataType = plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'data', + tool: 'typescript', + }); + const symbolResponseType = plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'response', + }); + + return node + .param('options', (p) => + p.required(isRequiredOptions).type( + $.type.func().returns( + $.type.or( + $.type(symbolOptions) + .generic(symbolDataType ?? 'unknown') + .generic('ThrowOnError'), + $.type('undefined'), + ), + ), + ), + ) + .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) + .do( + $.return( + $(symbolHttpResource) + .call( + $.func().do( + $.const('opts').assign( + $.ternary('options') + .do($('options').call()) + .otherwise($.id('undefined')), + ), + $.return( + $.ternary('opts') + .do( + $.lazy((ctx) => + ctx + .access( + plugin.referenceSymbol( + createHttpRequestFnMeta(operation), + ), + ) + .call('opts'), + ), + ) + .otherwise($.id('undefined')), + ), + ), + ) + .generic(symbolResponseType ?? 'unknown'), + ), + ) as T; +} + +export function toHttpRequestNode( + model: StructureNode, + plugin: AngularCommonPlugin['Instance'], +): { + dependencies?: Array>; + nodes: ReadonlyArray>; +} { + if (model.virtual) { + const nodes: Array> = []; + for (const item of model.itemsFrom(source)) { + const { operation } = item.data; + let node = $.const(createHttpRequestFnSymbol(plugin, item)) + .export() + .assign( + implementHttpRequestFn({ + node: $.func(), + operation, + plugin, + }), + ); + node = attachComment({ node, operation }); + nodes.push(node); + } + return { nodes }; + } + + if (!model.shell) { + return { nodes: [] }; + } + + const nodes: Array> = []; + + const shell = model.shell.define(model); + const node = shell.node as ReturnType; + + let index = 0; + for (const item of model.itemsFrom(source)) { + const { operation } = item.data; + if (index > 0 || node.hasBody) node.newline(); + node.do( + implementHttpRequestFn({ + node: $.method(createHttpRequestFnSymbol(plugin, item), (m) => + attachComment({ + node: m, + operation, + }) + .public() + .static(), + ), + operation, + plugin, + }), + ); + index += 1; + } + + for (const child of model.children.values()) { + if (node.hasBody) node.newline(); + node.do(...childToHttpRequestNode(child, plugin)); + } + + nodes.push(node); + + return { + dependencies: shell.dependencies as Array>, + nodes, + }; +} + +export function toHttpResourceNode( + model: StructureNode, + plugin: AngularCommonPlugin['Instance'], +): { + dependencies?: Array>; + nodes: ReadonlyArray>; +} { + if (model.virtual) { + const nodes: Array> = []; + for (const item of model.itemsFrom(source)) { + const { operation } = item.data; + let node = $.const(createHttpResourceFnSymbol(plugin, item)) + .export() + .assign( + implementHttpResourceFn({ + node: $.func(), + operation, + plugin, + }), + ); + node = attachComment({ node, operation }); + nodes.push(node); + } + return { nodes }; + } + + if (!model.shell) { + return { nodes: [] }; + } + + const nodes: Array> = []; + + const shell = model.shell.define(model); + const node = shell.node as ReturnType; + + let index = 0; + for (const item of model.itemsFrom(source)) { + const { operation } = item.data; + if (index > 0 || node.hasBody) node.newline(); + node.do( + implementHttpResourceFn({ + node: $.method(createHttpResourceFnSymbol(plugin, item), (m) => + attachComment({ + node: m, + operation, + }) + .public() + .static(), + ), + operation, + plugin, + }), + ); + index += 1; + } + + for (const child of model.children.values()) { + if (node.hasBody) node.newline(); + node.do(...childToHttpResourceNode(child, plugin)); + } + + nodes.push(node); + + return { + dependencies: shell.dependencies as Array>, + nodes, + }; +} diff --git a/packages/openapi-ts/src/plugins/@angular/common/types.d.ts b/packages/openapi-ts/src/plugins/@angular/common/types.d.ts index d304523aa..d64dd666c 100644 --- a/packages/openapi-ts/src/plugins/@angular/common/types.d.ts +++ b/packages/openapi-ts/src/plugins/@angular/common/types.d.ts @@ -1,5 +1,14 @@ +import type { OperationsStrategy } from '~/openApi/shared/locations'; import type { DefinePlugin, Plugin } from '~/plugins'; -import type { NameTransformer } from '~/utils/naming'; + +import type { + HttpRequestsConfig, + UserHttpRequestsConfig, +} from './httpRequests'; +import type { + HttpResourcesConfig, + UserHttpResourcesConfig, +} from './httpResources'; export type UserConfig = Plugin.Name<'@angular/common'> & Plugin.Hooks & { @@ -13,66 +22,15 @@ export type UserConfig = Plugin.Name<'@angular/common'> & /** * Options for generating HTTP Request instances. * - * @default true + * @default 'flat' */ - httpRequests?: - | boolean - | { - /** - * Whether to generate the resource as a class. - * - * @default false - */ - asClass?: boolean; - /** - * Builds the class name for the generated resource. - * By default, the class name is suffixed with "Resources". - */ - classNameBuilder?: NameTransformer; - /** - * Whether or not to create HTTP Request instances. - * - * @default true - */ - enabled?: boolean; - /** - * Builds the method name for the generated resource. - * - * By default, the operation id is used, if `asClass` is false, the method is also suffixed with "Resource". - */ - methodNameBuilder?: (operation: IR.OperationObject) => string; - }; + httpRequests?: boolean | OperationsStrategy | UserHttpRequestsConfig; /** * Options for generating HTTP resource APIs. * - * @default true + * @default 'flat' */ - httpResources?: - | boolean - | { - /** - * Whether to generate the resource as a class. - * @default false - */ - asClass?: boolean; - /** - * Builds the class name for the generated resource. - * By default, the class name is suffixed with "Resources". - */ - classNameBuilder?: NameTransformer; - /** - * Whether or not to create HTTP resource APIs. - * - * @default true - */ - enabled?: boolean; - /** - * Builds the method name for the generated resource. - * - * By default, the operation id is used, if `asClass` is false, the method is also suffixed with "Resource". - */ - methodNameBuilder?: (operation: IR.OperationObject) => string; - }; + httpResources?: boolean | OperationsStrategy | UserHttpResourcesConfig; }; export type Config = Plugin.Name<'@angular/common'> & @@ -87,57 +45,11 @@ export type Config = Plugin.Name<'@angular/common'> & /** * Options for generating HTTP Request instances. */ - httpRequests: { - /** - * Whether to generate the resource as a class. - * - * @default false - */ - asClass: boolean; - /** - * Builds the class name for the generated resource. - * By default, the class name is suffixed with "Resources". - */ - classNameBuilder: NameTransformer; - /** - * Whether or not to create HTTP Request instances. - * - * @default true - */ - enabled: boolean; - /** - * Builds the method name for the generated resource. - * By default, the operation id is used, if `asClass` is false, the method is also suffixed with "Resource". - */ - methodNameBuilder: (operation: IR.OperationObject) => string; - }; + httpRequests: HttpRequestsConfig; /** * Options for generating HTTP resource APIs. */ - httpResources: { - /** - * Whether to generate the resource as a class. - * - * @default false - */ - asClass: boolean; - /** - * Builds the class name for the generated resource. - * By default, the class name is suffixed with "Resources". - */ - classNameBuilder: NameTransformer; - /** - * Whether or not to create HTTP resource APIs. - * - * @default true - */ - enabled: boolean; - /** - * Builds the method name for the generated resource. - * By default, the operation id is used, if `asClass` is false, the method is also suffixed with "Resource". - */ - methodNameBuilder: (operation: IR.OperationObject) => string; - }; + httpResources: HttpResourcesConfig; }; export type AngularCommonPlugin = DefinePlugin; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/config.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/config.ts index 1e711bc1a..fdaec7bc0 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/config.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/config.ts @@ -1,13 +1,10 @@ import { log } from '@hey-api/codegen-core'; +import type { OperationsStrategy } from '~/openApi/shared/locations'; import type { PluginContext } from '~/plugins/types'; import type { UserConfig } from '../types'; -import type { - OperationsConfig, - OperationsStrategy, - UserOperationsConfig, -} from './types'; +import type { OperationsConfig, UserOperationsConfig } from './types'; type Config = Omit; @@ -151,14 +148,6 @@ function normalizeConfig( } function mapLegacyToConfig(config: Config): Partial { - // TODO: refactor... - // Set default classNameBuilder based on client type - if (config.classNameBuilder === '{{name}}') { - if (config.client === '@hey-api/client-angular') { - config.classNameBuilder = '{{name}}Service'; - } - } - let strategy: OperationsConfig['strategy'] | undefined; if (config.instance) { strategy = 'single'; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/index.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/index.ts index a9f588fd0..a472cd1ec 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/index.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/index.ts @@ -1,6 +1,3 @@ export { resolveOperations } from './config'; -export type { - OperationsConfig, - OperationsStrategy, - UserOperationsConfig, -} from './types'; +export { resolveStrategy } from './resolve'; +export type { OperationsConfig, UserOperationsConfig } from './types'; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/types.d.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/types.d.ts index 76abe54ad..935f77b90 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/types.d.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/operations/types.d.ts @@ -1,15 +1,9 @@ import type { OperationPathStrategy, - OperationStructureStrategy, + OperationsStrategy, } from '~/openApi/shared/locations'; import type { NamingConfig, NamingRule } from '~/utils/naming'; -export type OperationsStrategy = - | 'byTags' - | 'flat' - | 'single' - | OperationStructureStrategy; - export interface UserOperationsConfig { /** * Type of container for grouped operations. @@ -17,13 +11,14 @@ export interface UserOperationsConfig { * Ignored when `strategy` is `'flat'`. * * - `'class'` - Class with methods - * - `'object'` - Plain object literal * * @default 'class' */ - container?: 'class' | 'object'; + container?: 'class'; + // * - `'object'` - Plain object literal + // container?: 'class' | 'object'; /** - * Customize container names (class or object variable names). + * Customize container names. * * For `'single'` strategy, this sets the root container name. * For `'byTags'` strategy, this transforms tag names. @@ -40,7 +35,7 @@ export interface UserOperationsConfig { * * @example * // With casing - * containerName: { name: '{{name}}Service', case: 'PascalCase' } + * containerName: { name: '{{name}}Service', casing: 'PascalCase' } */ containerName?: NamingRule; /** @@ -114,11 +109,12 @@ export interface OperationsConfig { * Ignored when `strategy` is `'flat'`. * * - `'class'` - Class with methods - * - `'object'` - Plain object literal */ - container: 'class' | 'object'; + container: 'class'; + // * - `'object'` - Plain object literal + // container: 'class' | 'object'; /** - * Customize container names (class or object variable names). + * Customize container names. * * For `'single'` strategy, this sets the root container name. * For `'byTags'` strategy, this transforms tag names. diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts index 19365f72d..b43f5a41a 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/operation.ts @@ -3,140 +3,17 @@ import { refs } from '@hey-api/codegen-core'; import { statusCodeToGroup } from '~/ir/operation'; import type { IR } from '~/ir/types'; -import { sanitizeNamespaceIdentifier } from '~/openApi/common/parser/sanitize'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; import { $ } from '~/ts-dsl'; -import { toCase } from '~/utils/naming'; import type { Field, Fields } from '../../client-core/bundle/params'; import type { HeyApiSdkPlugin } from '../types'; -import { isInstance } from '../v1/plugin'; +import { isInstance } from '../v1/node'; import { operationAuth } from './auth'; import { nuxtTypeComposable, nuxtTypeDefault } from './constants'; import { getSignatureParameters } from './signature'; import { createRequestValidator, createResponseValidator } from './validator'; -interface ClassNameEntry { - /** - * Name of the class where this function appears. - */ - className: string; - /** - * Name of the function within the class. - */ - methodName: string; - /** - * JSONPath-like array to class location. - */ - path: ReadonlyArray; -} - -/** - * @deprecated - */ -const operationClassName = ({ - plugin, - value, -}: { - plugin: HeyApiSdkPlugin['Instance']; - value: string; -}) => { - // TODO: expose casing option - const name = toCase(value, 'PascalCase'); - return ( - // @ts-expect-error - (typeof plugin.config.classNameBuilder === 'string' - ? // @ts-expect-error - plugin.config.classNameBuilder.replace('{{name}}', name) - : // @ts-expect-error - plugin.config.classNameBuilder(name)) || name - ); -}; - -/** - * @deprecated - */ -const operationMethodName = ({ - operation, - plugin, - value, -}: { - operation: IR.OperationObject; - plugin: HeyApiSdkPlugin['Instance']; - value?: string; -}) => { - // TODO: expose casing option - const name = toCase(value || operation.id, 'camelCase'); - return ( - // @ts-expect-error - (typeof plugin.config.methodNameBuilder === 'string' - ? // @ts-expect-error - plugin.config.methodNameBuilder.replace('{{name}}', name) - : // @ts-expect-error TODO: remove - plugin.config.methodNameBuilder?.(name, operation)) || name - ); -}; - -/** - * Returns a list of classes where this operation appears in the generated SDK. - * - * @deprecated - */ -export const operationClasses = ({ - operation, - plugin, -}: { - operation: IR.OperationObject; - plugin: HeyApiSdkPlugin['Instance']; -}): Map => { - const classNames = new Map(); - - let className: string | undefined; - let methodName: string | undefined; - let classCandidates: Array = []; - - // @ts-expect-error - if (plugin.config.classStructure === 'auto' && operation.operationId) { - classCandidates = operation.operationId.split(/[./]/).filter(Boolean); - if (classCandidates.length >= 2) { - const methodCandidate = classCandidates.pop()!; - methodName = toCase( - sanitizeNamespaceIdentifier(methodCandidate), - 'camelCase', - ); - className = classCandidates.pop()!; - } - } - - // @ts-expect-error - const rootClasses = plugin.config.instance - ? // @ts-expect-error - [plugin.config.instance] - : (operation.tags ?? ['default']); - - for (const rootClass of rootClasses) { - // Default path - let path = [rootClass]; - if (className) { - // If root class is already within classCandidates or the same as className - // do not add it again as this will cause a recursion issue. - if (classCandidates.includes(rootClass) || rootClass === className) { - path = [...classCandidates, className]; - } else { - path = [rootClass, ...classCandidates, className]; - } - } - - classNames.set(rootClass, { - className: operationClassName({ plugin, value: className || rootClass }), - methodName: methodName || operationMethodName({ operation, plugin }), - path: path.map((value) => operationClassName({ plugin, value })), - }); - } - - return classNames; -}; - /** TODO: needs complete refactor */ export const operationOptionsType = ({ isDataAllowed = true, diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts index b7c20bc3e..034ed45bb 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts @@ -3,7 +3,7 @@ import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; import { $ } from '~/ts-dsl'; import type { HeyApiSdkPlugin } from '../types'; -import { isInstance } from '../v1/plugin'; +import { isInstance } from '../v1/node'; import { nuxtTypeDefault, nuxtTypeResponse } from './constants'; export const createTypeOptions = ({ diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts index 00504200e..00575088d 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts @@ -1,12 +1,9 @@ +import type { OperationsStrategy } from '~/openApi/shared/locations'; import type { DefinePlugin, Plugin } from '~/plugins'; import type { PluginClientNames, PluginValidatorNames } from '~/plugins/types'; import type { NameTransformer } from '~/utils/naming'; -import type { - OperationsConfig, - OperationsStrategy, - UserOperationsConfig, -} from './operations'; +import type { OperationsConfig, UserOperationsConfig } from './operations'; export type UserConfig = Plugin.Name<'@hey-api/sdk'> & Plugin.Hooks & { diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/node.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/node.ts new file mode 100644 index 000000000..fabbc0406 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/node.ts @@ -0,0 +1,380 @@ +import type { + StructureItem, + StructureNode, + StructureShell, + Symbol, + SymbolMeta, +} from '@hey-api/codegen-core'; + +import type { IR } from '~/ir/types'; +import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; +import { + createOperationComment, + isOperationOptionsRequired, +} from '~/plugins/shared/utils/operation'; +import { $ } from '~/ts-dsl'; +import { applyNaming, toCase } from '~/utils/naming'; + +import { createClientClass, createRegistryClass } from '../shared/class'; +import { nuxtTypeComposable, nuxtTypeDefault } from '../shared/constants'; +import { operationParameters, operationStatements } from '../shared/operation'; +import type { HeyApiSdkPlugin } from '../types'; + +export interface OperationItem { + operation: IR.OperationObject; + path: ReadonlyArray; + tags: ReadonlyArray | undefined; +} + +export const source = globalThis.Symbol('@hey-api/sdk'); + +export function isInstance(plugin: HeyApiSdkPlugin['Instance']): boolean { + const config = plugin.config.operations; + return ( + config.container === 'class' && + config.methods === 'instance' && + config.strategy !== 'flat' + ); +} + +function attachComment< + T extends ReturnType, +>(args: { node: T; operation: IR.OperationObject }): T { + const { node, operation } = args; + return node.$if(createOperationComment(operation), (n, v) => n.doc(v)) as T; +} + +function createShellMeta(node: StructureNode): SymbolMeta { + return { + category: 'utility', + resource: 'class', + resourceId: node.getPath().join('.'), + tool: 'sdk', + }; +} + +function createFnSymbol( + plugin: HeyApiSdkPlugin['Instance'], + item: StructureItem & { data: OperationItem }, +): Symbol { + const { operation, path, tags } = item.data; + const name = item.location[item.location.length - 1]!; + return plugin.symbol(applyNaming(name, plugin.config.operations.methodName), { + meta: { + category: 'sdk', + path, + resource: 'operation', + resourceId: operation.id, + tags, + tool: 'sdk', + }, + }); +} + +function childToNode( + resource: StructureNode, + plugin: HeyApiSdkPlugin['Instance'], +): ReadonlyArray> { + const refChild = plugin.referenceSymbol(createShellMeta(resource)); + const memberNameStr = toCase(refChild.name, 'camelCase'); + const memberName = plugin.symbol(memberNameStr); + if (isInstance(plugin)) { + const privateName = plugin.symbol(`_${memberNameStr}`); + return [ + $.field(privateName, (f) => f.private().optional().type(refChild)), + $.getter(memberName, (g) => + g.returns(refChild).do( + $('this') + .attr(privateName) + .nullishAssign( + $.new(refChild).args( + $.object().prop('client', $('this').attr('client')), + ), + ) + .return(), + ), + ), + ]; + } + if (plugin.isSymbolRegistered(refChild.id)) { + return [$.field(memberName, (f) => f.static().assign($(refChild)))]; + } + return [ + $.getter(memberName, (g) => g.public().static().do($.return(refChild))), + ]; +} + +export function createShell( + plugin: HeyApiSdkPlugin['Instance'], +): StructureShell { + const client = getClientPlugin(plugin.context.config); + const isAngularClient = client.name === '@hey-api/client-angular'; + return { + define: (node) => { + const symbol = plugin.symbol( + applyNaming( + node.name, + node.isRoot + ? plugin.config.operations.containerName + : plugin.config.operations.segmentName, + ), + { + meta: createShellMeta(node), + }, + ); + + // if (plugin.config.operations.container === 'object') { + // const o = $.const(symbol).export().assign($.object()); + // return { dependencies: [], node: o }; + // } + + const c = $.class(symbol) + .export() + .$if(isInstance(plugin), (c) => + c.extends( + plugin.referenceSymbol({ + category: 'utility', + resource: 'class', + resourceId: 'HeyApiClient', + tool: 'sdk', + }), + ), + ) + .$if(isAngularClient && node.isRoot, (c) => + c.decorator( + plugin.external('@angular/core.Injectable'), + $.object().prop('providedIn', $.literal('root')), + ), + ); + + const dependencies: Array> = []; + + if (node.isRoot && isInstance(plugin)) { + enrichRootClass({ + dependencies, + node: c, + plugin, + symbol, + }); + } + + return { dependencies, node: c }; + }, + }; +} + +function enrichRootClass(args: { + dependencies: Array>; + node: ReturnType; + plugin: HeyApiSdkPlugin['Instance']; + symbol: Symbol; +}): void { + const { dependencies, node, plugin, symbol } = args; + const symbolClient = plugin.symbol('HeyApiClient', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiClient', + tool: 'sdk', + }, + }); + dependencies.push(createClientClass({ plugin, symbol: symbolClient })); + const symbolRegistry = plugin.symbol('HeyApiRegistry', { + meta: { + category: 'utility', + resource: 'class', + resourceId: 'HeyApiRegistry', + tool: 'sdk', + }, + }); + dependencies.push( + createRegistryClass({ + plugin, + sdkSymbol: symbol, + symbol: symbolRegistry, + }), + ); + const isClientRequired = + !plugin.config.client || !plugin.getSymbol({ category: 'client' }); + const registry = plugin.symbol('__registry'); + node.toAccessNode = (node, options) => { + if (options.context) return; + return $(node.name).attr(registry).attr('get').call(); + }; + node.do( + $.field(registry, (f) => + f + .public() + .static() + .readonly() + .assign($.new(symbolRegistry).generic(symbol)), + ), + $.newline(), + $.init((i) => + i + .param('args', (p) => + p.required(isClientRequired).type( + $.type + .object() + .prop('client', (p) => + p + .required(isClientRequired) + .type(plugin.external('client.Client')), + ) + .prop('key', (p) => p.optional().type('string')), + ), + ) + .do( + $('super').call('args'), + $(symbol) + .attr(registry) + .attr('set') + .call('this', $('args').attr('key').required(isClientRequired)), + ), + ), + ); +} + +function implementFn< + T extends ReturnType, +>(args: { + node: T; + operation: IR.OperationObject; + plugin: HeyApiSdkPlugin['Instance']; +}): T { + const { node, operation, plugin } = args; + const client = getClientPlugin(plugin.context.config); + const isNuxtClient = client.name === '@hey-api/client-nuxt'; + const isRequiredOptions = isOperationOptionsRequired({ + context: plugin.context, + operation, + }); + const opParameters = operationParameters({ + isRequiredOptions, + operation, + plugin, + }); + const statements = operationStatements({ + isRequiredOptions, + opParameters, + operation, + plugin, + }); + return node + .$if( + isNuxtClient, + (m) => + m + .generic(nuxtTypeComposable, (t) => + t + .extends(plugin.external('client.Composable')) + .default($.type.literal('$fetch')), + ) + .generic(nuxtTypeDefault, (t) => + t.$if( + plugin.querySymbol({ + category: 'type', + resource: 'operation', + resourceId: operation.id, + role: 'response', + }), + (t, s) => t.extends(s).default(s), + (t) => t.default('undefined'), + ), + ), + (m) => + m.generic('ThrowOnError', (t) => + t + .extends('boolean') + .default( + ('throwOnError' in client.config + ? client.config.throwOnError + : false) ?? false, + ), + ), + ) + .params(...opParameters.parameters) + .do(...statements) as T; +} + +export function toNode( + model: StructureNode, + plugin: HeyApiSdkPlugin['Instance'], +): { + dependencies?: Array>; + nodes: ReadonlyArray>; +} { + if (model.virtual) { + const nodes: Array> = []; + for (const item of model.itemsFrom(source)) { + const { operation } = item.data; + let node = $.const(createFnSymbol(plugin, item)) + .export() + .assign( + implementFn({ + node: $.func(), + operation, + plugin, + }), + ); + node = attachComment({ node, operation }); + nodes.push(node); + } + return { nodes }; + } + + if (!model.shell) { + return { nodes: [] }; + } + + const nodes: Array> = []; + + const client = getClientPlugin(plugin.context.config); + const isAngularClient = client.name === '@hey-api/client-angular'; + + const shell = model.shell.define(model); + const node = shell.node as ReturnType; + + let index = 0; + for (const item of model.itemsFrom(source)) { + const { operation } = item.data; + if (node['~dsl'] === 'VarTsDsl') { + // TODO: object + } else { + if (index > 0 || node.hasBody) node.newline(); + node.do( + implementFn({ + node: $.method(createFnSymbol(plugin, item), (m) => + attachComment({ + node: m, + operation, + }) + .public() + .static(!isAngularClient && !isInstance(plugin)), + ), + operation, + plugin, + }), + ); + } + index += 1; + } + + for (const child of model.children.values()) { + if (node['~dsl'] === 'VarTsDsl') { + // TODO: object + } else { + if (node.hasBody) node.newline(); + node.do(...childToNode(child, plugin)); + } + } + + nodes.push(node); + + return { + dependencies: shell.dependencies as Array< + ReturnType + >, + nodes, + }; +} diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts index 967170cc4..6e9ca55a3 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/plugin.ts @@ -1,383 +1,14 @@ -import type { - StructureItem, - StructureNode, - StructureShell, - Symbol, -} from '@hey-api/codegen-core'; import { StructureModel } from '@hey-api/codegen-core'; import { clientFolderAbsolutePath } from '~/generate/client'; -import type { IR } from '~/ir/types'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; -import { - createOperationComment, - isOperationOptionsRequired, -} from '~/plugins/shared/utils/operation'; -import { $ } from '~/ts-dsl'; -import { applyNaming, toCase } from '~/utils/naming'; +import type { $ } from '~/ts-dsl'; -import { resolveStrategy } from '../operations/resolve'; -import { createClientClass, createRegistryClass } from '../shared/class'; -import { nuxtTypeComposable, nuxtTypeDefault } from '../shared/constants'; -import { operationParameters, operationStatements } from '../shared/operation'; +import { resolveStrategy } from '../operations'; import { createTypeOptions } from '../shared/typeOptions'; import type { HeyApiSdkPlugin } from '../types'; - -interface OperationItem { - operation: IR.OperationObject; - path: ReadonlyArray; - tags: ReadonlyArray | undefined; -} - -const source = globalThis.Symbol('@hey-api/sdk'); - -function attachComment< - T extends ReturnType, ->(args: { node: T; operation: IR.OperationObject }): T { - const { node, operation } = args; - return node.$if(createOperationComment(operation), (m, v) => m.doc(v)) as T; -} - -function createFnSymbol( - plugin: HeyApiSdkPlugin['Instance'], - item: StructureItem & { data: OperationItem }, -): Symbol { - const { operation, path, tags } = item.data; - const name = item.location[item.location.length - 1]!; - return plugin.symbol(applyNaming(name, plugin.config.operations.methodName), { - meta: { - category: 'sdk', - path, - resource: 'operation', - resourceId: operation.id, - tags, - tool: 'sdk', - }, - }); -} - -function childToNode( - resource: StructureNode, - plugin: HeyApiSdkPlugin['Instance'], -): ReadonlyArray> { - const refChild = plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: resource.getPath().join('.'), - tool: 'sdk', - }); - const memberNameStr = toCase(refChild.name, 'camelCase'); - const memberName = plugin.symbol(memberNameStr); - if (isInstance(plugin)) { - const privateName = plugin.symbol(`_${memberNameStr}`); - return [ - $.field(privateName, (f) => f.private().optional().type(refChild)), - $.getter(memberName, (g) => - g.returns(refChild).do( - $('this') - .attr(privateName) - .nullishAssign( - $.new(refChild).args( - $.object().prop('client', $('this').attr('client')), - ), - ) - .return(), - ), - ), - ]; - } - if (plugin.isSymbolRegistered(refChild.id)) { - return [$.field(memberName, (f) => f.static().assign($(refChild)))]; - } - return [ - $.getter(memberName, (g) => g.public().static().do($.return(refChild))), - ]; -} - -function enrichRootClass(args: { - dependencies: Array>; - node: ReturnType; - plugin: HeyApiSdkPlugin['Instance']; - symbol: Symbol; -}): void { - const { dependencies, node, plugin, symbol } = args; - const symbolClient = plugin.symbol('HeyApiClient', { - meta: { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiClient', - tool: 'sdk', - }, - }); - dependencies.push(createClientClass({ plugin, symbol: symbolClient })); - const symbolRegistry = plugin.symbol('HeyApiRegistry', { - meta: { - category: 'utility', - resource: 'class', - resourceId: 'HeyApiRegistry', - tool: 'sdk', - }, - }); - dependencies.push( - createRegistryClass({ - plugin, - sdkSymbol: symbol, - symbol: symbolRegistry, - }), - ); - const isClientRequired = - !plugin.config.client || !plugin.getSymbol({ category: 'client' }); - const registry = plugin.symbol('__registry'); - node.toAccessNode = (node, options) => { - if (options.context) return; - return $(node.name).attr(registry).attr('get').call(); - }; - node.do( - $.field(registry, (f) => - f - .public() - .static() - .readonly() - .assign($.new(symbolRegistry).generic(symbol)), - ), - $.newline(), - $.init((i) => - i - .param('args', (p) => - p.required(isClientRequired).type( - $.type - .object() - .prop('client', (p) => - p.required(isClientRequired).type( - plugin.referenceSymbol({ - category: 'external', - resource: 'client.Client', - }), - ), - ) - .prop('key', (p) => p.optional().type('string')), - ), - ) - .do( - $('super').call('args'), - $(symbol) - .attr(registry) - .attr('set') - .call('this', $('args').attr('key').required(isClientRequired)), - ), - ), - ); -} - -function implementFn< - T extends ReturnType, ->(args: { - node: T; - operation: IR.OperationObject; - plugin: HeyApiSdkPlugin['Instance']; -}): T { - const { node, operation, plugin } = args; - const client = getClientPlugin(plugin.context.config); - const isNuxtClient = client.name === '@hey-api/client-nuxt'; - const isRequiredOptions = isOperationOptionsRequired({ - context: plugin.context, - operation, - }); - const opParameters = operationParameters({ - isRequiredOptions, - operation, - plugin, - }); - const statements = operationStatements({ - isRequiredOptions, - opParameters, - operation, - plugin, - }); - return node - .$if( - isNuxtClient, - (m) => - m - .generic(nuxtTypeComposable, (t) => - t - .extends( - plugin.referenceSymbol({ - category: 'external', - resource: 'client.Composable', - }), - ) - .default($.type.literal('$fetch')), - ) - .generic(nuxtTypeDefault, (t) => - t.$if( - plugin.querySymbol({ - category: 'type', - resource: 'operation', - resourceId: operation.id, - role: 'response', - }), - (t, s) => t.extends(s).default(s), - (t) => t.default('undefined'), - ), - ), - (m) => - m.generic('ThrowOnError', (t) => - t - .extends('boolean') - .default( - ('throwOnError' in client.config - ? client.config.throwOnError - : false) ?? false, - ), - ), - ) - .params(...opParameters.parameters) - .do(...statements) as T; -} - -/** - * Converts this class group to a class node. - */ -function toNode( - model: StructureNode, - plugin: HeyApiSdkPlugin['Instance'], -): { - dependencies?: Array>; - nodes: ReadonlyArray>; -} { - if (model.virtual) { - const nodes: Array> = []; - for (const item of model.itemsFrom(source)) { - const { operation } = item.data; - let node = $.const(createFnSymbol(plugin, item)) - .export() - .assign( - implementFn({ - node: $.func(), - operation, - plugin, - }), - ); - node = attachComment({ node, operation }); - nodes.push(node); - } - return { nodes }; - } - - if (!model.shell) { - return { nodes: [] }; - } - - const nodes: Array> = []; - - const client = getClientPlugin(plugin.context.config); - const isAngularClient = client.name === '@hey-api/client-angular'; - - const shell = model.shell.define(model); - const node = shell.node as ReturnType; - - let index = 0; - for (const item of model.itemsFrom(source)) { - const { operation } = item.data; - if (index > 0 || node.hasBody) node.newline(); - node.do( - implementFn({ - node: $.method(createFnSymbol(plugin, item), (m) => - attachComment({ - node: m, - operation, - }) - .public() - .static(!isAngularClient && !isInstance(plugin)), - ), - operation, - plugin, - }), - ); - index += 1; - } - - for (const child of model.children.values()) { - if (node.hasBody) node.newline(); - node.do(...childToNode(child, plugin)); - } - - nodes.push(node); - - return { - dependencies: shell.dependencies as Array>, - nodes, - }; -} - -function createShell(plugin: HeyApiSdkPlugin['Instance']): StructureShell { - const client = getClientPlugin(plugin.context.config); - const isAngularClient = client.name === '@hey-api/client-angular'; - return { - define: (node) => { - const symbol = plugin.symbol( - applyNaming( - node.name, - node.isRoot - ? plugin.config.operations.containerName - : plugin.config.operations.segmentName, - ), - { - meta: { - category: 'utility', - resource: 'class', - resourceId: node.getPath().join('.'), - tool: 'sdk', - }, - }, - ); - const c = $.class(symbol) - .export() - .$if(isInstance(plugin), (c) => - c.extends( - plugin.referenceSymbol({ - category: 'utility', - resource: 'class', - resourceId: 'HeyApiClient', - tool: 'sdk', - }), - ), - ) - .$if(isAngularClient && node.isRoot, (c) => - c.decorator( - plugin.referenceSymbol({ - category: 'external', - resource: '@angular/core.Injectable', - }), - $.object().prop('providedIn', $.literal('root')), - ), - ); - - const dependencies: Array> = []; - - if (node.isRoot && isInstance(plugin)) { - enrichRootClass({ - dependencies, - node: c, - plugin, - symbol, - }); - } - - return { dependencies, node: c }; - }, - }; -} - -export function isInstance(plugin: HeyApiSdkPlugin['Instance']): boolean { - const config = plugin.config.operations; - return ( - config.container === 'class' && - config.methods === 'instance' && - config.strategy !== 'flat' - ); -} +import type { OperationItem } from './node'; +import { createShell, source, toNode } from './node'; export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { const clientModule = clientFolderAbsolutePath(plugin.context.config); @@ -456,7 +87,7 @@ export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { { order: 'declarations' }, ); - const allDependencies: Array> = []; + const allDependencies: Array> = []; const allNodes: Array> = []; for (const node of structure.walk()) { @@ -465,7 +96,10 @@ export const handlerV1: HeyApiSdkPlugin['Handler'] = ({ plugin }) => { allNodes.push(...nodes); } - const uniqueDependencies = new Map>(); + const uniqueDependencies = new Map< + number, + ReturnType + >(); for (const dep of allDependencies) { if (dep.symbol) uniqueDependencies.set(dep.symbol.id, dep); } diff --git a/packages/openapi-ts/src/plugins/shared/utils/operation.ts b/packages/openapi-ts/src/plugins/shared/utils/operation.ts index cbb41c72f..d625c882c 100644 --- a/packages/openapi-ts/src/plugins/shared/utils/operation.ts +++ b/packages/openapi-ts/src/plugins/shared/utils/operation.ts @@ -3,7 +3,7 @@ import { hasOperationDataRequired } from '~/ir/operation'; import type { IR } from '~/ir/types'; import { getClientPlugin } from '~/plugins/@hey-api/client-core/utils'; import type { HeyApiSdkPlugin } from '~/plugins/@hey-api/sdk'; -import { isInstance } from '~/plugins/@hey-api/sdk/v1/plugin'; +import { isInstance } from '~/plugins/@hey-api/sdk/v1/node'; import { escapeComment } from '~/utils/escape'; export const createOperationComment = ( diff --git a/packages/openapi-ts/src/ts-dsl/utils/context.ts b/packages/openapi-ts/src/ts-dsl/utils/context.ts index 5f31054e2..ebbd0e360 100644 --- a/packages/openapi-ts/src/ts-dsl/utils/context.ts +++ b/packages/openapi-ts/src/ts-dsl/utils/context.ts @@ -12,6 +12,8 @@ export type NodeChain = ReadonlyArray; export interface AccessOptions { /** The access context. */ context?: 'example'; + /** Enable debug mode. */ + debug?: boolean; } export type AccessResult = ReturnType< @@ -52,9 +54,10 @@ function getAccessChainForNode(node: TsDsl): NodeChain { const structuralChain = [...getStructuralChainForNode(node, new Set())]; const accessChain = structuralToAccessChain(structuralChain); if (accessChain.length === 0) { - throw new Error( - `Cannot build access chain for node ${node['~dsl']} (${node.name.toString()})`, - ); + // I _think_ this should not happen, but it does and this fix works for now. + // I assume this will cause issues with imports in some cases, investigate + // when it actually happens. + return [node.clone()]; } return accessChain.map((node) => node.clone()); } -- 2.51.2 From 817ed8f074a09c48e474b9cabfb3b4aece55ca7a Mon Sep 17 00:00:00 2001 From: Lubos Date: Fri, 2 Jan 2026 02:27:00 +0800 Subject: [PATCH 12/15] chore: fallback to path in operation id --- dev/openapi-ts.config.ts | 67 +- .../openapi-ts.config.ts | 3 +- .../src/client/@angular/common.gen.ts | 40 +- .../openapi-ts-angular/src/client/index.ts | 160 +- .../openapi-ts-angular/src/client/sdk.gen.ts | 8 +- packages/codegen-core/src/files/file.ts | 3 +- .../angular-query-experimental.gen.ts | 6 +- .../meta/@tanstack/react-query.gen.ts | 6 +- .../meta/@tanstack/solid-query.gen.ts | 6 +- .../meta/@tanstack/svelte-query.gen.ts | 6 +- .../@tanstack/meta/@tanstack/vue-query.gen.ts | 6 +- .../plugins/@tanstack/meta/index.ts | 2 +- .../plugins/@tanstack/meta/sdk.gen.ts | 4 +- .../2.0.x/body-response-text-plain/index.ts | 2 +- .../2.0.x/body-response-text-plain/sdk.gen.ts | 2 +- .../__snapshots__/2.0.x/form-data/index.ts | 2 +- .../__snapshots__/2.0.x/form-data/sdk.gen.ts | 2 +- .../default-class/@angular/common.gen.ts | 405 ++-- .../@angular/common/default-class/index.ts | 2 +- .../@angular/common/default-class/sdk.gen.ts | 6 +- .../plugins/@angular/common/default/index.ts | 2 +- .../@angular/common/default/sdk.gen.ts | 6 +- .../sdk-nested-classes-instance/sdk.gen.ts | 8 +- .../sdk-nested-classes/sdk.gen.ts | 8 +- .../plugins/@hey-api/sdk/default/index.ts | 2 +- .../plugins/@hey-api/sdk/default/sdk.gen.ts | 6 +- .../plugins/@hey-api/sdk/instance/sdk.gen.ts | 16 +- .../@hey-api/sdk/throwOnError/index.ts | 2 +- .../@hey-api/sdk/throwOnError/sdk.gen.ts | 6 +- .../transformers/type-format-valibot/index.ts | 2 +- .../type-format-valibot/sdk.gen.ts | 2 +- .../transformers/type-format-zod/index.ts | 2 +- .../transformers/type-format-zod/sdk.gen.ts | 2 +- .../colada/asClass/@pinia/colada.gen.ts | 4 +- .../plugins/@pinia/colada/asClass/sdk.gen.ts | 16 +- .../@pinia/colada/fetch/@pinia/colada.gen.ts | 8 +- .../plugins/@pinia/colada/fetch/index.ts | 2 +- .../plugins/@pinia/colada/fetch/sdk.gen.ts | 6 +- .../angular-query-experimental.gen.ts | 4 +- .../asClass/sdk.gen.ts | 16 +- .../angular-query-experimental.gen.ts | 8 +- .../angular-query-experimental/axios/index.ts | 2 +- .../axios/sdk.gen.ts | 6 +- .../angular-query-experimental.gen.ts | 8 +- .../angular-query-experimental/fetch/index.ts | 2 +- .../fetch/sdk.gen.ts | 6 +- .../angular-query-experimental.gen.ts | 6 +- .../name-builder/index.ts | 2 +- .../name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/react-query.gen.ts | 4 +- .../@tanstack/react-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/react-query.gen.ts | 8 +- .../@tanstack/react-query/axios/index.ts | 2 +- .../@tanstack/react-query/axios/sdk.gen.ts | 6 +- .../fetch/@tanstack/react-query.gen.ts | 8 +- .../@tanstack/react-query/fetch/index.ts | 2 +- .../@tanstack/react-query/fetch/sdk.gen.ts | 6 +- .../name-builder/@tanstack/react-query.gen.ts | 6 +- .../react-query/name-builder/index.ts | 2 +- .../react-query/name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/solid-query.gen.ts | 4 +- .../@tanstack/solid-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/solid-query.gen.ts | 8 +- .../@tanstack/solid-query/axios/index.ts | 2 +- .../@tanstack/solid-query/axios/sdk.gen.ts | 6 +- .../fetch/@tanstack/solid-query.gen.ts | 8 +- .../@tanstack/solid-query/fetch/index.ts | 2 +- .../@tanstack/solid-query/fetch/sdk.gen.ts | 6 +- .../name-builder/@tanstack/solid-query.gen.ts | 6 +- .../solid-query/name-builder/index.ts | 2 +- .../solid-query/name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/svelte-query.gen.ts | 4 +- .../@tanstack/svelte-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/svelte-query.gen.ts | 8 +- .../@tanstack/svelte-query/axios/index.ts | 2 +- .../@tanstack/svelte-query/axios/sdk.gen.ts | 6 +- .../fetch/@tanstack/svelte-query.gen.ts | 8 +- .../@tanstack/svelte-query/fetch/index.ts | 2 +- .../@tanstack/svelte-query/fetch/sdk.gen.ts | 6 +- .../@tanstack/svelte-query.gen.ts | 6 +- .../svelte-query/name-builder/index.ts | 2 +- .../svelte-query/name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/vue-query.gen.ts | 4 +- .../@tanstack/vue-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/vue-query.gen.ts | 8 +- .../@tanstack/vue-query/axios/index.ts | 2 +- .../@tanstack/vue-query/axios/sdk.gen.ts | 6 +- .../fetch/@tanstack/vue-query.gen.ts | 8 +- .../@tanstack/vue-query/fetch/index.ts | 2 +- .../@tanstack/vue-query/fetch/sdk.gen.ts | 6 +- .../name-builder/@tanstack/vue-query.gen.ts | 6 +- .../@tanstack/vue-query/name-builder/index.ts | 2 +- .../vue-query/name-builder/sdk.gen.ts | 4 +- .../2.0.x/security-api-key/index.ts | 2 +- .../2.0.x/security-api-key/sdk.gen.ts | 2 +- .../2.0.x/security-basic/index.ts | 2 +- .../2.0.x/security-basic/sdk.gen.ts | 2 +- .../2.0.x/security-false/index.ts | 2 +- .../2.0.x/security-false/sdk.gen.ts | 2 +- .../2.0.x/security-oauth2/index.ts | 2 +- .../2.0.x/security-oauth2/sdk.gen.ts | 2 +- .../3.0.x/body-response-text-plain/index.ts | 2 +- .../3.0.x/body-response-text-plain/sdk.gen.ts | 2 +- .../3.0.x/content-types/index.ts | 2 +- .../3.0.x/content-types/sdk.gen.ts | 2 +- .../parameter-explode-false-axios/index.ts | 2 +- .../parameter-explode-false-axios/sdk.gen.ts | 2 +- .../3.0.x/parameter-explode-false/index.ts | 2 +- .../3.0.x/parameter-explode-false/sdk.gen.ts | 2 +- .../default-class/@angular/common.gen.ts | 583 ++--- .../@angular/common/default-class/index.ts | 2 +- .../@angular/common/default-class/sdk.gen.ts | 12 +- .../plugins/@angular/common/default/index.ts | 2 +- .../@angular/common/default/sdk.gen.ts | 12 +- .../sdk-nested-classes-instance/sdk.gen.ts | 8 +- .../sdk-nested-classes/sdk.gen.ts | 8 +- .../plugins/@hey-api/sdk/default/index.ts | 2 +- .../plugins/@hey-api/sdk/default/sdk.gen.ts | 12 +- .../plugins/@hey-api/sdk/instance/sdk.gen.ts | 16 +- .../@hey-api/sdk/throwOnError/index.ts | 2 +- .../@hey-api/sdk/throwOnError/sdk.gen.ts | 12 +- .../transformers/type-format-valibot/index.ts | 2 +- .../type-format-valibot/sdk.gen.ts | 2 +- .../transformers/type-format-zod/index.ts | 2 +- .../transformers/type-format-zod/sdk.gen.ts | 2 +- .../colada/asClass/@pinia/colada.gen.ts | 4 +- .../plugins/@pinia/colada/asClass/sdk.gen.ts | 16 +- .../@pinia/colada/fetch/@pinia/colada.gen.ts | 14 +- .../plugins/@pinia/colada/fetch/index.ts | 2 +- .../plugins/@pinia/colada/fetch/sdk.gen.ts | 12 +- .../angular-query-experimental.gen.ts | 4 +- .../asClass/sdk.gen.ts | 16 +- .../angular-query-experimental.gen.ts | 14 +- .../angular-query-experimental/axios/index.ts | 2 +- .../axios/sdk.gen.ts | 12 +- .../angular-query-experimental.gen.ts | 14 +- .../angular-query-experimental/fetch/index.ts | 2 +- .../fetch/sdk.gen.ts | 12 +- .../angular-query-experimental.gen.ts | 6 +- .../name-builder/index.ts | 2 +- .../name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/react-query.gen.ts | 4 +- .../@tanstack/react-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/react-query.gen.ts | 14 +- .../@tanstack/react-query/axios/index.ts | 2 +- .../@tanstack/react-query/axios/sdk.gen.ts | 12 +- .../fetch/@tanstack/react-query.gen.ts | 14 +- .../@tanstack/react-query/fetch/index.ts | 2 +- .../@tanstack/react-query/fetch/sdk.gen.ts | 12 +- .../name-builder/@tanstack/react-query.gen.ts | 6 +- .../react-query/name-builder/index.ts | 2 +- .../react-query/name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/solid-query.gen.ts | 4 +- .../@tanstack/solid-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/solid-query.gen.ts | 14 +- .../@tanstack/solid-query/axios/index.ts | 2 +- .../@tanstack/solid-query/axios/sdk.gen.ts | 12 +- .../fetch/@tanstack/solid-query.gen.ts | 14 +- .../@tanstack/solid-query/fetch/index.ts | 2 +- .../@tanstack/solid-query/fetch/sdk.gen.ts | 12 +- .../name-builder/@tanstack/solid-query.gen.ts | 6 +- .../solid-query/name-builder/index.ts | 2 +- .../solid-query/name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/svelte-query.gen.ts | 4 +- .../@tanstack/svelte-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/svelte-query.gen.ts | 14 +- .../@tanstack/svelte-query/axios/index.ts | 2 +- .../@tanstack/svelte-query/axios/sdk.gen.ts | 12 +- .../fetch/@tanstack/svelte-query.gen.ts | 14 +- .../@tanstack/svelte-query/fetch/index.ts | 2 +- .../@tanstack/svelte-query/fetch/sdk.gen.ts | 12 +- .../@tanstack/svelte-query.gen.ts | 6 +- .../svelte-query/name-builder/index.ts | 2 +- .../svelte-query/name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/vue-query.gen.ts | 4 +- .../@tanstack/vue-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/vue-query.gen.ts | 14 +- .../@tanstack/vue-query/axios/index.ts | 2 +- .../@tanstack/vue-query/axios/sdk.gen.ts | 12 +- .../fetch/@tanstack/vue-query.gen.ts | 14 +- .../@tanstack/vue-query/fetch/index.ts | 2 +- .../@tanstack/vue-query/fetch/sdk.gen.ts | 12 +- .../name-builder/@tanstack/vue-query.gen.ts | 6 +- .../@tanstack/vue-query/name-builder/index.ts | 2 +- .../vue-query/name-builder/sdk.gen.ts | 4 +- .../3.0.x/security-api-key/index.ts | 2 +- .../3.0.x/security-api-key/sdk.gen.ts | 4 +- .../3.0.x/security-false/index.ts | 2 +- .../3.0.x/security-false/sdk.gen.ts | 2 +- .../3.0.x/security-http-bearer/index.ts | 2 +- .../3.0.x/security-http-bearer/sdk.gen.ts | 2 +- .../3.0.x/security-oauth2/index.ts | 2 +- .../3.0.x/security-oauth2/sdk.gen.ts | 2 +- .../3.0.x/security-open-id-connect/index.ts | 2 +- .../3.0.x/security-open-id-connect/sdk.gen.ts | 2 +- .../3.1.x/body-response-text-plain/index.ts | 2 +- .../3.1.x/body-response-text-plain/sdk.gen.ts | 2 +- .../client-angular/clean-false/index.ts | 2 +- .../client-angular/clean-false/sdk.gen.ts | 12 +- .../@hey-api/client-angular/default/index.ts | 2 +- .../client-angular/default/sdk.gen.ts | 12 +- .../import-file-extension-ts/index.ts | 2 +- .../import-file-extension-ts/sdk.gen.ts | 12 +- .../sdk-client-optional/index.ts | 2 +- .../sdk-client-optional/sdk.gen.ts | 12 +- .../sdk-client-required/index.ts | 2 +- .../sdk-client-required/sdk.gen.ts | 12 +- .../tsconfig-node16-sdk/index.ts | 2 +- .../tsconfig-node16-sdk/sdk.gen.ts | 12 +- .../tsconfig-nodenext-sdk/index.ts | 2 +- .../tsconfig-nodenext-sdk/sdk.gen.ts | 12 +- .../client-axios/clean-false/index.ts | 2 +- .../client-axios/clean-false/sdk.gen.ts | 12 +- .../@hey-api/client-axios/default/index.ts | 2 +- .../@hey-api/client-axios/default/sdk.gen.ts | 12 +- .../import-file-extension-ts/index.ts | 2 +- .../import-file-extension-ts/sdk.gen.ts | 12 +- .../client-axios/sdk-client-optional/index.ts | 2 +- .../sdk-client-optional/sdk.gen.ts | 12 +- .../client-axios/sdk-client-required/index.ts | 2 +- .../sdk-client-required/sdk.gen.ts | 12 +- .../client-axios/tsconfig-node16-sdk/index.ts | 2 +- .../tsconfig-node16-sdk/sdk.gen.ts | 12 +- .../tsconfig-nodenext-sdk/index.ts | 2 +- .../tsconfig-nodenext-sdk/sdk.gen.ts | 12 +- .../client-fetch/clean-false/index.ts | 2 +- .../client-fetch/clean-false/sdk.gen.ts | 12 +- .../@hey-api/client-fetch/default/index.ts | 2 +- .../@hey-api/client-fetch/default/sdk.gen.ts | 12 +- .../import-file-extension-ts/index.ts | 2 +- .../import-file-extension-ts/sdk.gen.ts | 12 +- .../client-fetch/sdk-client-optional/index.ts | 2 +- .../sdk-client-optional/sdk.gen.ts | 12 +- .../client-fetch/sdk-client-required/index.ts | 2 +- .../sdk-client-required/sdk.gen.ts | 12 +- .../client-fetch/tsconfig-node16-sdk/index.ts | 2 +- .../tsconfig-node16-sdk/sdk.gen.ts | 12 +- .../tsconfig-nodenext-sdk/index.ts | 2 +- .../tsconfig-nodenext-sdk/sdk.gen.ts | 12 +- .../@hey-api/client-ky/clean-false/index.ts | 2 +- .../@hey-api/client-ky/clean-false/sdk.gen.ts | 12 +- .../@hey-api/client-ky/default/index.ts | 2 +- .../@hey-api/client-ky/default/sdk.gen.ts | 12 +- .../import-file-extension-ts/index.ts | 2 +- .../import-file-extension-ts/sdk.gen.ts | 12 +- .../client-ky/sdk-client-optional/index.ts | 2 +- .../client-ky/sdk-client-optional/sdk.gen.ts | 12 +- .../client-ky/sdk-client-required/index.ts | 2 +- .../client-ky/sdk-client-required/sdk.gen.ts | 12 +- .../client-ky/tsconfig-node16-sdk/index.ts | 2 +- .../client-ky/tsconfig-node16-sdk/sdk.gen.ts | 12 +- .../client-ky/tsconfig-nodenext-sdk/index.ts | 2 +- .../tsconfig-nodenext-sdk/sdk.gen.ts | 12 +- .../@hey-api/client-next/clean-false/index.ts | 2 +- .../client-next/clean-false/sdk.gen.ts | 12 +- .../@hey-api/client-next/default/index.ts | 2 +- .../@hey-api/client-next/default/sdk.gen.ts | 12 +- .../import-file-extension-ts/index.ts | 2 +- .../import-file-extension-ts/sdk.gen.ts | 12 +- .../client-next/sdk-client-optional/index.ts | 2 +- .../sdk-client-optional/sdk.gen.ts | 12 +- .../client-next/sdk-client-required/index.ts | 2 +- .../sdk-client-required/sdk.gen.ts | 12 +- .../client-next/tsconfig-node16-sdk/index.ts | 2 +- .../tsconfig-node16-sdk/sdk.gen.ts | 12 +- .../tsconfig-nodenext-sdk/index.ts | 2 +- .../tsconfig-nodenext-sdk/sdk.gen.ts | 12 +- .../@hey-api/client-nuxt/clean-false/index.ts | 2 +- .../client-nuxt/clean-false/sdk.gen.ts | 12 +- .../@hey-api/client-nuxt/default/index.ts | 2 +- .../@hey-api/client-nuxt/default/sdk.gen.ts | 12 +- .../import-file-extension-ts/index.ts | 2 +- .../import-file-extension-ts/sdk.gen.ts | 12 +- .../client-nuxt/sdk-client-optional/index.ts | 2 +- .../sdk-client-optional/sdk.gen.ts | 12 +- .../client-nuxt/sdk-client-required/index.ts | 2 +- .../sdk-client-required/sdk.gen.ts | 12 +- .../client-nuxt/tsconfig-node16-sdk/index.ts | 2 +- .../tsconfig-node16-sdk/sdk.gen.ts | 12 +- .../tsconfig-nodenext-sdk/index.ts | 2 +- .../tsconfig-nodenext-sdk/sdk.gen.ts | 12 +- .../client-ofetch/clean-false/index.ts | 2 +- .../client-ofetch/clean-false/sdk.gen.ts | 12 +- .../@hey-api/client-ofetch/default/index.ts | 2 +- .../@hey-api/client-ofetch/default/sdk.gen.ts | 12 +- .../import-file-extension-ts/index.ts | 2 +- .../import-file-extension-ts/sdk.gen.ts | 12 +- .../sdk-client-optional/index.ts | 2 +- .../sdk-client-optional/sdk.gen.ts | 12 +- .../sdk-client-required/index.ts | 2 +- .../sdk-client-required/sdk.gen.ts | 12 +- .../tsconfig-node16-sdk/index.ts | 2 +- .../tsconfig-node16-sdk/sdk.gen.ts | 12 +- .../tsconfig-nodenext-sdk/index.ts | 2 +- .../tsconfig-nodenext-sdk/sdk.gen.ts | 12 +- .../clients/client-custom/bundle/index.ts | 2 +- .../clients/client-custom/bundle/sdk.gen.ts | 12 +- .../clients/client-custom/default/index.ts | 2 +- .../clients/client-custom/default/sdk.gen.ts | 12 +- .../sdk-client-optional/index.ts | 2 +- .../sdk-client-optional/sdk.gen.ts | 12 +- .../sdk-client-required/index.ts | 2 +- .../sdk-client-required/sdk.gen.ts | 12 +- .../3.1.x/clients/my-client/bundle/index.ts | 2 +- .../3.1.x/clients/my-client/bundle/sdk.gen.ts | 12 +- .../3.1.x/clients/my-client/default/index.ts | 2 +- .../clients/my-client/default/sdk.gen.ts | 12 +- .../my-client/sdk-client-optional/index.ts | 2 +- .../my-client/sdk-client-optional/sdk.gen.ts | 12 +- .../my-client/sdk-client-required/index.ts | 2 +- .../my-client/sdk-client-required/sdk.gen.ts | 12 +- .../3.1.x/content-types/index.ts | 2 +- .../3.1.x/content-types/sdk.gen.ts | 2 +- .../test/__snapshots__/3.1.x/headers/index.ts | 2 +- .../__snapshots__/3.1.x/headers/sdk.gen.ts | 8 +- .../@tanstack/react-query.gen.ts | 8 +- .../3.1.x/pagination-ref/index.ts | 2 +- .../3.1.x/pagination-ref/sdk.gen.ts | 4 +- .../parameter-explode-false-axios/index.ts | 2 +- .../parameter-explode-false-axios/sdk.gen.ts | 2 +- .../3.1.x/parameter-explode-false/index.ts | 2 +- .../3.1.x/parameter-explode-false/sdk.gen.ts | 2 +- .../default-class/@angular/common.gen.ts | 629 +++--- .../@angular/common/default-class/index.ts | 2 +- .../@angular/common/default-class/sdk.gen.ts | 12 +- .../plugins/@angular/common/default/index.ts | 2 +- .../@angular/common/default/sdk.gen.ts | 12 +- .../sdk-nested-classes-instance/sdk.gen.ts | 8 +- .../sdk-nested-classes/sdk.gen.ts | 8 +- .../plugins/@hey-api/sdk/default/index.ts | 2 +- .../plugins/@hey-api/sdk/default/sdk.gen.ts | 12 +- .../plugins/@hey-api/sdk/instance/sdk.gen.ts | 16 +- .../@hey-api/sdk/throwOnError/index.ts | 2 +- .../@hey-api/sdk/throwOnError/sdk.gen.ts | 12 +- .../transformers/type-format-valibot/index.ts | 2 +- .../type-format-valibot/sdk.gen.ts | 2 +- .../transformers/type-format-zod/index.ts | 2 +- .../transformers/type-format-zod/sdk.gen.ts | 2 +- .../colada/asClass/@pinia/colada.gen.ts | 4 +- .../plugins/@pinia/colada/asClass/sdk.gen.ts | 16 +- .../@pinia/colada/fetch/@pinia/colada.gen.ts | 14 +- .../plugins/@pinia/colada/fetch/index.ts | 2 +- .../plugins/@pinia/colada/fetch/sdk.gen.ts | 12 +- .../angular-query-experimental.gen.ts | 4 +- .../asClass/sdk.gen.ts | 16 +- .../angular-query-experimental.gen.ts | 14 +- .../angular-query-experimental/axios/index.ts | 2 +- .../axios/sdk.gen.ts | 12 +- .../angular-query-experimental.gen.ts | 14 +- .../angular-query-experimental/fetch/index.ts | 2 +- .../fetch/sdk.gen.ts | 12 +- .../angular-query-experimental.gen.ts | 6 +- .../name-builder/index.ts | 2 +- .../name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/react-query.gen.ts | 4 +- .../@tanstack/react-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/react-query.gen.ts | 14 +- .../@tanstack/react-query/axios/index.ts | 2 +- .../@tanstack/react-query/axios/sdk.gen.ts | 12 +- .../fetch/@tanstack/react-query.gen.ts | 14 +- .../@tanstack/react-query/fetch/index.ts | 2 +- .../@tanstack/react-query/fetch/sdk.gen.ts | 12 +- .../name-builder/@tanstack/react-query.gen.ts | 6 +- .../react-query/name-builder/index.ts | 2 +- .../react-query/name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/solid-query.gen.ts | 4 +- .../@tanstack/solid-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/solid-query.gen.ts | 14 +- .../@tanstack/solid-query/axios/index.ts | 2 +- .../@tanstack/solid-query/axios/sdk.gen.ts | 12 +- .../fetch/@tanstack/solid-query.gen.ts | 14 +- .../@tanstack/solid-query/fetch/index.ts | 2 +- .../@tanstack/solid-query/fetch/sdk.gen.ts | 12 +- .../name-builder/@tanstack/solid-query.gen.ts | 6 +- .../solid-query/name-builder/index.ts | 2 +- .../solid-query/name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/svelte-query.gen.ts | 4 +- .../@tanstack/svelte-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/svelte-query.gen.ts | 14 +- .../@tanstack/svelte-query/axios/index.ts | 2 +- .../@tanstack/svelte-query/axios/sdk.gen.ts | 12 +- .../fetch/@tanstack/svelte-query.gen.ts | 14 +- .../@tanstack/svelte-query/fetch/index.ts | 2 +- .../@tanstack/svelte-query/fetch/sdk.gen.ts | 12 +- .../@tanstack/svelte-query.gen.ts | 6 +- .../svelte-query/name-builder/index.ts | 2 +- .../svelte-query/name-builder/sdk.gen.ts | 4 +- .../asClass/@tanstack/vue-query.gen.ts | 4 +- .../@tanstack/vue-query/asClass/sdk.gen.ts | 16 +- .../axios/@tanstack/vue-query.gen.ts | 14 +- .../@tanstack/vue-query/axios/index.ts | 2 +- .../@tanstack/vue-query/axios/sdk.gen.ts | 12 +- .../fetch/@tanstack/vue-query.gen.ts | 14 +- .../@tanstack/vue-query/fetch/index.ts | 2 +- .../@tanstack/vue-query/fetch/sdk.gen.ts | 12 +- .../name-builder/@tanstack/vue-query.gen.ts | 6 +- .../@tanstack/vue-query/name-builder/index.ts | 2 +- .../vue-query/name-builder/sdk.gen.ts | 4 +- .../3.1.x/security-api-key/index.ts | 2 +- .../3.1.x/security-api-key/sdk.gen.ts | 4 +- .../3.1.x/security-false/index.ts | 2 +- .../3.1.x/security-false/sdk.gen.ts | 2 +- .../3.1.x/security-http-bearer/index.ts | 2 +- .../3.1.x/security-http-bearer/sdk.gen.ts | 2 +- .../3.1.x/security-oauth2/index.ts | 2 +- .../3.1.x/security-oauth2/sdk.gen.ts | 2 +- .../3.1.x/security-open-id-connect/index.ts | 2 +- .../3.1.x/security-open-id-connect/sdk.gen.ts | 2 +- .../main/test/plugins.test.ts | 4 +- .../method-class-conflict/class/sdk.gen.ts | 1378 ++++++++---- .../method-class-conflict/flat/sdk.gen.ts | 212 +- .../method-class-conflict/instance/sdk.gen.ts | 1926 +++++++++++------ packages/openapi-ts/src/index.ts | 1 + .../src/openApi/shared/locations/index.ts | 2 +- .../src/openApi/shared/locations/operation.ts | 23 +- .../@angular/common/httpRequests/config.ts | 2 +- .../@angular/common/httpRequests/resolve.ts | 10 +- .../@angular/common/httpResources/config.ts | 2 +- .../@angular/common/httpResources/resolve.ts | 10 +- .../plugins/@hey-api/sdk/operations/config.ts | 27 +- .../@hey-api/sdk/operations/resolve.ts | 10 +- .../src/plugins/@hey-api/sdk/v1/plugin.ts | 6 +- .../openapi-ts/src/ts-dsl/decl/decorator.ts | 4 + packages/openapi-ts/src/ts-dsl/decl/field.ts | 6 + packages/openapi-ts/src/ts-dsl/decl/getter.ts | 4 + packages/openapi-ts/src/ts-dsl/decl/setter.ts | 4 + .../src/ts-dsl/utils/__tests__/render.test.ts | 8 - 427 files changed, 4632 insertions(+), 3459 deletions(-) diff --git a/dev/openapi-ts.config.ts b/dev/openapi-ts.config.ts index d0f3b808e..7c8e9a8b6 100644 --- a/dev/openapi-ts.config.ts +++ b/dev/openapi-ts.config.ts @@ -4,8 +4,16 @@ import path from 'node:path'; // @ts-ignore import { customClientPlugin } from '@hey-api/custom-client/plugin'; -// @ts-ignore -import { defineConfig, reserved, utils } from '@hey-api/openapi-ts'; +import { + defineConfig, + // @ts-ignore + OperationPath, + // @ts-ignore + OperationStrategy, + reserved, + // @ts-ignore + utils, +} from '@hey-api/openapi-ts'; // @ts-ignore import { myClientPlugin } from '../packages/openapi-ts-tests/main/test/custom/client/plugin'; @@ -39,8 +47,8 @@ export default defineConfig(() => { path: path.resolve( getSpecsPath(), // '2.0.x', - // '3.0.x', - '3.1.x', + '3.0.x', + // '3.1.x', // 'circular.yaml', // 'dutchie.json', // 'enum-names-values.yaml', @@ -49,11 +57,11 @@ export default defineConfig(() => { // 'invalid', // 'object-property-names.yaml', // 'openai.yaml', - 'opencode.yaml', + // 'opencode.yaml', // 'pagination-ref.yaml', // 'schema-const.yaml', // 'sdk-instance.yaml', - // 'sdk-method-class-conflict.yaml', + 'sdk-method-class-conflict.yaml', // 'sdk-nested-classes.yaml', // 'sdk-nested-conflict.yaml', // 'string-with-format.yaml', @@ -108,7 +116,7 @@ export default defineConfig(() => { // }, // format: 'prettier', header: null, - // importFileExtension: '.js', + importFileExtension: '.js', // indexFile: false, // lint: 'eslint', // nameConflictResolver({ attempt, baseName }) { @@ -293,18 +301,32 @@ export default defineConfig(() => { // operationId: true, operations: { // container: 'object', - containerName: { - // casing: 'snake_case', - name: 'OpencodeClient', - }, - methodName: { - // casing: 'SCREAMING_SNAKE_CASE', - name: '{{name}}Yummy', - }, - methods: 'static', - nesting: 'id', - segmentName: '{{name}}Seggy', - strategy: 'flat', + // containerName: { + // // casing: 'snake_case', + // name: 'OpencodeClient', + // }, + // methodName: { + // // casing: 'SCREAMING_SNAKE_CASE', + // name: '{{name}}Yummy', + // }, + // methods: 'static', + // nesting: 'operationId', + // segmentName: '{{name}}Seggy', + strategy: 'byTags', + // strategy(operation) { + // const locations = OperationStrategy.byTags({ + // fallback: 'default', + // path: OperationPath.fromOperationId({ + // delimiters: /[./]/, + // }), + // })(operation) + // return locations.map((loc) => { + // if (loc[0] && loc[1] && loc[0] === loc[1]) { + // return loc.slice(1); + // } + // return loc; + // }); + // }, // strategyDefaultTag: 'DaxLikedThis', }, // paramsStructure: 'flat', @@ -314,7 +336,7 @@ export default defineConfig(() => { // signature: 'object', // transformer: '@hey-api/transformers', // transformer: true, - // validator: 'valibot', + validator: 'valibot', // validator: { // request: 'zod', // response: 'zod', @@ -619,13 +641,14 @@ export default defineConfig(() => { exportFromIndex: true, httpRequests: { // enabled: false, - containerName: 'AngularTest', + // containerName: 'AngularTest', segmentName: '{{name}}Seggy', strategy: 'single', }, httpResources: { - // asClass: true, // enabled: false, + segmentName: '{{name}}Seggy', + strategy: 'single', }, name: '@angular/common', }, diff --git a/examples/openapi-ts-angular-common/openapi-ts.config.ts b/examples/openapi-ts-angular-common/openapi-ts.config.ts index f9b24282e..dfd11e54e 100644 --- a/examples/openapi-ts-angular-common/openapi-ts.config.ts +++ b/examples/openapi-ts-angular-common/openapi-ts.config.ts @@ -17,7 +17,8 @@ export default defineConfig({ exportFromIndex: true, httpRequests: true, httpResources: { - asClass: true, + containerName: '{{name}}ServiceResources', + strategy: 'byTags', }, name: '@angular/common', }, diff --git a/examples/openapi-ts-angular-common/src/client/@angular/common.gen.ts b/examples/openapi-ts-angular-common/src/client/@angular/common.gen.ts index 50f07b383..992353f06 100644 --- a/examples/openapi-ts-angular-common/src/client/@angular/common.gen.ts +++ b/examples/openapi-ts-angular-common/src/client/@angular/common.gen.ts @@ -335,7 +335,7 @@ export class PetServiceResources { * * Add a new pet to the store. */ - public addPet( + public static addPet( options: () => Options | undefined, ) { return httpResource(() => { @@ -349,7 +349,7 @@ export class PetServiceResources { * * Update an existing pet by Id. */ - public updatePet( + public static updatePet( options: () => Options | undefined, ) { return httpResource(() => { @@ -363,7 +363,7 @@ export class PetServiceResources { * * Multiple status values can be provided with comma separated strings. */ - public findPetsByStatus( + public static findPetsByStatus( options: () => Options | undefined, ) { return httpResource(() => { @@ -377,7 +377,7 @@ export class PetServiceResources { * * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. */ - public findPetsByTags( + public static findPetsByTags( options: () => Options | undefined, ) { return httpResource(() => { @@ -391,7 +391,7 @@ export class PetServiceResources { * * Delete a pet. */ - public deletePet( + public static deletePet( options: () => Options | undefined, ) { return httpResource(() => { @@ -405,7 +405,7 @@ export class PetServiceResources { * * Returns a single pet. */ - public getPetById( + public static getPetById( options: () => Options | undefined, ) { return httpResource(() => { @@ -419,7 +419,7 @@ export class PetServiceResources { * * Updates a pet resource based on the form data. */ - public updatePetWithForm( + public static updatePetWithForm( options: () => Options | undefined, ) { return httpResource(() => { @@ -433,7 +433,7 @@ export class PetServiceResources { * * Upload image of the pet. */ - public uploadFile( + public static uploadFile( options: () => Options | undefined, ) { return httpResource(() => { @@ -443,14 +443,13 @@ export class PetServiceResources { } } -@Injectable({ providedIn: 'root' }) export class StoreServiceResources { /** * Returns pet inventories by status. * * Returns a map of status codes to quantities. */ - public getInventory( + public static getInventory( options?: () => Options | undefined, ) { return httpResource(() => { @@ -464,7 +463,7 @@ export class StoreServiceResources { * * Place a new order in the store. */ - public placeOrder( + public static placeOrder( options?: () => Options | undefined, ) { return httpResource(() => { @@ -478,7 +477,7 @@ export class StoreServiceResources { * * For valid response try integer IDs with value < 1000. Anything above 1000 or non-integers will generate API errors. */ - public deleteOrder( + public static deleteOrder( options: () => Options | undefined, ) { return httpResource(() => { @@ -492,7 +491,7 @@ export class StoreServiceResources { * * For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions. */ - public getOrderById( + public static getOrderById( options: () => Options | undefined, ) { return httpResource(() => { @@ -502,14 +501,13 @@ export class StoreServiceResources { } } -@Injectable({ providedIn: 'root' }) export class UserServiceResources { /** * Create user. * * This can only be done by the logged in user. */ - public createUser( + public static createUser( options?: () => Options | undefined, ) { return httpResource(() => { @@ -523,7 +521,7 @@ export class UserServiceResources { * * Creates list of users with given input array. */ - public createUsersWithListInput( + public static createUsersWithListInput( options?: () => | Options | undefined, @@ -539,7 +537,7 @@ export class UserServiceResources { * * Log into the system. */ - public loginUser( + public static loginUser( options?: () => Options | undefined, ) { return httpResource(() => { @@ -553,7 +551,7 @@ export class UserServiceResources { * * Log user out of the system. */ - public logoutUser( + public static logoutUser( options?: () => Options | undefined, ) { return httpResource(() => { @@ -567,7 +565,7 @@ export class UserServiceResources { * * This can only be done by the logged in user. */ - public deleteUser( + public static deleteUser( options: () => Options | undefined, ) { return httpResource(() => { @@ -581,7 +579,7 @@ export class UserServiceResources { * * Get user detail based on username. */ - public getUserByName( + public static getUserByName( options: () => Options | undefined, ) { return httpResource(() => { @@ -595,7 +593,7 @@ export class UserServiceResources { * * This can only be done by the logged in user. */ - public updateUser( + public static updateUser( options: () => Options | undefined, ) { return httpResource(() => { diff --git a/examples/openapi-ts-angular/src/client/index.ts b/examples/openapi-ts-angular/src/client/index.ts index 12450a715..b686cfff6 100644 --- a/examples/openapi-ts-angular/src/client/index.ts +++ b/examples/openapi-ts-angular/src/client/index.ts @@ -1,85 +1,85 @@ // This file is auto-generated by @hey-api/openapi-ts -export { type Options, PetService, StoreService, UserService } from './sdk.gen'; -export type { - AddPetData, - AddPetErrors, - AddPetResponse, - AddPetResponses, - ApiResponse, - Category, - ClientOptions, - CreateUserData, - CreateUserErrors, - CreateUserResponse, - CreateUserResponses, - CreateUsersWithListInputData, - CreateUsersWithListInputErrors, - CreateUsersWithListInputResponse, - CreateUsersWithListInputResponses, - DeleteOrderData, - DeleteOrderErrors, - DeleteOrderResponses, - DeletePetData, - DeletePetErrors, - DeletePetResponses, - DeleteUserData, - DeleteUserErrors, - DeleteUserResponses, - FindPetsByStatusData, - FindPetsByStatusErrors, - FindPetsByStatusResponse, - FindPetsByStatusResponses, - FindPetsByTagsData, - FindPetsByTagsErrors, - FindPetsByTagsResponse, - FindPetsByTagsResponses, - GetInventoryData, - GetInventoryErrors, - GetInventoryResponse, - GetInventoryResponses, - GetOrderByIdData, - GetOrderByIdErrors, - GetOrderByIdResponse, - GetOrderByIdResponses, - GetPetByIdData, - GetPetByIdErrors, - GetPetByIdResponse, - GetPetByIdResponses, - GetUserByNameData, - GetUserByNameErrors, - GetUserByNameResponse, - GetUserByNameResponses, - LoginUserData, - LoginUserErrors, - LoginUserResponse, - LoginUserResponses, - LogoutUserData, - LogoutUserErrors, - LogoutUserResponses, - Order, +export { type Options, Store } from './sdk.gen'; +export { + type AddPetData, + type AddPetErrors, + type AddPetResponse, + type AddPetResponses, + type ApiResponse, + type Category, + type ClientOptions, + type CreateUserData, + type CreateUserErrors, + type CreateUserResponse, + type CreateUserResponses, + type CreateUsersWithListInputData, + type CreateUsersWithListInputErrors, + type CreateUsersWithListInputResponse, + type CreateUsersWithListInputResponses, + type DeleteOrderData, + type DeleteOrderErrors, + type DeleteOrderResponses, + type DeletePetData, + type DeletePetErrors, + type DeletePetResponses, + type DeleteUserData, + type DeleteUserErrors, + type DeleteUserResponses, + type FindPetsByStatusData, + type FindPetsByStatusErrors, + type FindPetsByStatusResponse, + type FindPetsByStatusResponses, + type FindPetsByTagsData, + type FindPetsByTagsErrors, + type FindPetsByTagsResponse, + type FindPetsByTagsResponses, + type GetInventoryData, + type GetInventoryErrors, + type GetInventoryResponse, + type GetInventoryResponses, + type GetOrderByIdData, + type GetOrderByIdErrors, + type GetOrderByIdResponse, + type GetOrderByIdResponses, + type GetPetByIdData, + type GetPetByIdErrors, + type GetPetByIdResponse, + type GetPetByIdResponses, + type GetUserByNameData, + type GetUserByNameErrors, + type GetUserByNameResponse, + type GetUserByNameResponses, + type LoginUserData, + type LoginUserErrors, + type LoginUserResponse, + type LoginUserResponses, + type LogoutUserData, + type LogoutUserErrors, + type LogoutUserResponses, + type Order, Pet, - Pet2, - PlaceOrderData, - PlaceOrderErrors, - PlaceOrderResponse, - PlaceOrderResponses, - Tag, - UpdatePetData, - UpdatePetErrors, - UpdatePetResponse, - UpdatePetResponses, - UpdatePetWithFormData, - UpdatePetWithFormErrors, - UpdatePetWithFormResponse, - UpdatePetWithFormResponses, - UpdateUserData, - UpdateUserErrors, - UpdateUserResponses, - UploadFileData, - UploadFileErrors, - UploadFileResponse, - UploadFileResponses, + type Pet2, + type PlaceOrderData, + type PlaceOrderErrors, + type PlaceOrderResponse, + type PlaceOrderResponses, + type Tag, + type UpdatePetData, + type UpdatePetErrors, + type UpdatePetResponse, + type UpdatePetResponses, + type UpdatePetWithFormData, + type UpdatePetWithFormErrors, + type UpdatePetWithFormResponse, + type UpdatePetWithFormResponses, + type UpdateUserData, + type UpdateUserErrors, + type UpdateUserResponses, + type UploadFileData, + type UploadFileErrors, + type UploadFileResponse, + type UploadFileResponses, User, - UserArray, + type UserArray, } from './types.gen'; diff --git a/examples/openapi-ts-angular/src/client/sdk.gen.ts b/examples/openapi-ts-angular/src/client/sdk.gen.ts index d7d470137..104a85812 100644 --- a/examples/openapi-ts-angular/src/client/sdk.gen.ts +++ b/examples/openapi-ts-angular/src/client/sdk.gen.ts @@ -82,7 +82,7 @@ export type Options< }; @Injectable({ providedIn: 'root' }) -export class PetService { +export class Pet { /** * Add a new pet to the store. * @@ -252,8 +252,7 @@ export class PetService { } } -@Injectable({ providedIn: 'root' }) -export class StoreService { +export class Store { /** * Returns pet inventories by status. * @@ -326,8 +325,7 @@ export class StoreService { } } -@Injectable({ providedIn: 'root' }) -export class UserService { +export class User { /** * Create user. * diff --git a/packages/codegen-core/src/files/file.ts b/packages/codegen-core/src/files/file.ts index 514beb626..78e09e41c 100644 --- a/packages/codegen-core/src/files/file.ts +++ b/packages/codegen-core/src/files/file.ts @@ -99,7 +99,8 @@ export class File { const dirs = this._logicalFilePath ? this._logicalFilePath.split('/').slice(0, -1) : []; - return [...dirs, `${this.name}${this.extension ?? ''}`].join('/'); + const extension = this.external ? '' : (this.extension ?? ''); + return [...dirs, `${this.name}${extension}`].join('/'); } /** diff --git a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/angular-query-experimental.gen.ts b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/angular-query-experimental.gen.ts index a168141eb..71c901e89 100644 --- a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/angular-query-experimental.gen.ts +++ b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/angular-query-experimental.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, queryOptions } from '@tanstack/angular-query-experimental'; import { client } from '../client.gen'; -import { getBar, getFoo, type Options } from '../sdk.gen'; +import { barGet, fooGet, type Options } from '../sdk.gen'; import type { GetBarData, GetFooData } from '../types.gen'; export type QueryKey = [ @@ -43,7 +43,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFoo({ + const { data } = await fooGet({ ...options, ...queryKey[0], signal, @@ -63,7 +63,7 @@ export const getBarQueryKey = (options?: Options) => createQueryKey( export const getBarOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getBar({ + const { data } = await barGet({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/react-query.gen.ts b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/react-query.gen.ts index 5a6a25034..9c6cc88e9 100644 --- a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/react-query.gen.ts +++ b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/react-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, queryOptions } from '@tanstack/react-query'; import { client } from '../client.gen'; -import { getBar, getFoo, type Options } from '../sdk.gen'; +import { barGet, fooGet, type Options } from '../sdk.gen'; import type { GetBarData, GetFooData } from '../types.gen'; export type QueryKey = [ @@ -43,7 +43,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFoo({ + const { data } = await fooGet({ ...options, ...queryKey[0], signal, @@ -63,7 +63,7 @@ export const getBarQueryKey = (options?: Options) => createQueryKey( export const getBarOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getBar({ + const { data } = await barGet({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/solid-query.gen.ts b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/solid-query.gen.ts index 8b6d32356..7723aa46c 100644 --- a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/solid-query.gen.ts +++ b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/solid-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, queryOptions } from '@tanstack/solid-query'; import { client } from '../client.gen'; -import { getBar, getFoo, type Options } from '../sdk.gen'; +import { barGet, fooGet, type Options } from '../sdk.gen'; import type { GetBarData, GetFooData } from '../types.gen'; export type QueryKey = [ @@ -43,7 +43,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFoo({ + const { data } = await fooGet({ ...options, ...queryKey[0], signal, @@ -63,7 +63,7 @@ export const getBarQueryKey = (options?: Options) => createQueryKey( export const getBarOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getBar({ + const { data } = await barGet({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/svelte-query.gen.ts b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/svelte-query.gen.ts index 4c50bd620..7f2a74fbe 100644 --- a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/svelte-query.gen.ts +++ b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/svelte-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, queryOptions } from '@tanstack/svelte-query'; import { client } from '../client.gen'; -import { getBar, getFoo, type Options } from '../sdk.gen'; +import { barGet, fooGet, type Options } from '../sdk.gen'; import type { GetBarData, GetFooData } from '../types.gen'; export type QueryKey = [ @@ -43,7 +43,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFoo({ + const { data } = await fooGet({ ...options, ...queryKey[0], signal, @@ -63,7 +63,7 @@ export const getBarQueryKey = (options?: Options) => createQueryKey( export const getBarOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getBar({ + const { data } = await barGet({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/vue-query.gen.ts b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/vue-query.gen.ts index 4793f41da..9ebea5291 100644 --- a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/vue-query.gen.ts +++ b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/@tanstack/vue-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, queryOptions } from '@tanstack/vue-query'; import { client } from '../client.gen'; -import { getBar, getFoo, type Options } from '../sdk.gen'; +import { barGet, fooGet, type Options } from '../sdk.gen'; import type { GetBarData, GetFooData } from '../types.gen'; export type QueryKey = [ @@ -43,7 +43,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFoo({ + const { data } = await fooGet({ ...options, ...queryKey[0], signal, @@ -63,7 +63,7 @@ export const getBarQueryKey = (options?: Options) => createQueryKey( export const getBarOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getBar({ + const { data } = await barGet({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/index.ts b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/index.ts index afbfb3822..6fd0ae1e8 100644 --- a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/index.ts +++ b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { getBar, getFoo, type Options } from './sdk.gen'; +export { barGet, fooGet, type Options } from './sdk.gen'; export type { ClientOptions, GetBarData, GetBarResponses, GetFooData, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/sdk.gen.ts b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/sdk.gen.ts index e2081efc5..059319152 100644 --- a/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/sdk.gen.ts +++ b/packages/openapi-ts-tests/__snapshots__/plugins/@tanstack/meta/sdk.gen.ts @@ -18,7 +18,7 @@ export type Options; }; -export const getFoo = (options?: Options) => (options?.client ?? client).get({ +export const fooGet = (options?: Options) => (options?.client ?? client).get({ security: [{ in: 'query', name: 'foo', @@ -28,7 +28,7 @@ export const getFoo = (options?: Options(options?: Options) => (options?.client ?? client).get({ +export const barGet = (options?: Options) => (options?.client ?? client).get({ security: [{ in: 'cookie', name: 'bar', diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/body-response-text-plain/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/body-response-text-plain/index.ts index de1daea43..cffa17616 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/body-response-text-plain/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/body-response-text-plain/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { type Options, postFoo } from './sdk.gen'; +export { fooPost, type Options } from './sdk.gen'; export type { ClientOptions, PostFooData, PostFooResponse, PostFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/body-response-text-plain/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/body-response-text-plain/sdk.gen.ts index 275283fad..aadd6a1be 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/body-response-text-plain/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/body-response-text-plain/sdk.gen.ts @@ -18,7 +18,7 @@ export type Options; }; -export const postFoo = (options: Options) => (options.client ?? client).post({ +export const fooPost = (options: Options) => (options.client ?? client).post({ bodySerializer: null, url: '/foo', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/form-data/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/form-data/index.ts index 8dc7240b1..e4bb63d5f 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/form-data/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/form-data/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { type Options, postV1Foo } from './sdk.gen'; +export { type Options, v1FooPost } from './sdk.gen'; export type { ClientOptions, Foo, PostV1FooData, PostV1FooResponse, PostV1FooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/form-data/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/form-data/sdk.gen.ts index dc1a7f150..0d29b6201 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/form-data/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/form-data/sdk.gen.ts @@ -18,7 +18,7 @@ export type Options; }; -export const postV1Foo = (options: Options) => (options.client ?? client).post({ +export const v1FooPost = (options: Options) => (options.client ?? client).post({ ...formDataBodySerializer, url: '/v1/foo', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/@angular/common.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/@angular/common.gen.ts index 8d12fcbb0..cfa3d8426 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/@angular/common.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/@angular/common.gen.ts @@ -1,59 +1,74 @@ // This file is auto-generated by @hey-api/openapi-ts import { type HttpRequest, httpResource } from '@angular/common/http'; -import { inject, Injectable } from '@angular/core'; +import { Injectable } from '@angular/core'; import { client } from '../client.gen'; import type { Options } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, OptionsCallWithoutParametersAndResponseData, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData, TypesResponse } from '../types.gen'; -@Injectable({ providedIn: 'root' }) -export class DefaultServiceRequests { - public serviceWithEmptyTag(options?: Options): HttpRequest { +export class No_tagRequests { + public static patch(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', - method: 'GET', + method: 'PATCH', url: '/api/v{api-version}/no+tag', ...options }); } - - public patchApiVbyApiVersionNoTag(options?: Options): HttpRequest { +} + +export class BodyRequests { + /** + * Body should not be unknown + * + * Body should not be unknown + */ + public static post(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', - method: 'PATCH', - url: '/api/v{api-version}/no+tag', + method: 'POST', + url: '/api/v{api-version}/body', ...options }); } +} + +export class VApiVersionRequests { + static 'no+tagRequests' = No_tagRequests; - public fooWow(options?: Options): HttpRequest { + static bodyRequests = BodyRequests; +} + +export class ApiRequests { + static vApiVersionRequests = VApiVersionRequests; +} + +@Injectable({ providedIn: 'root' }) +export class Default { + public static serviceWithEmptyTag(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', - method: 'PUT', + method: 'GET', url: '/api/v{api-version}/no+tag', ...options }); } - /** - * Body should not be unknown - * - * Body should not be unknown - */ - public postApiVbyApiVersionBody(options: Options): HttpRequest { + public static 'foo+Wow'(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', - method: 'POST', - url: '/api/v{api-version}/body', + method: 'PUT', + url: '/api/v{api-version}/no+tag', ...options }); } + + static apiRequests = ApiRequests; } -@Injectable({ providedIn: 'root' }) -export class SimpleServiceRequests { - public deleteCallWithoutParametersAndResponse(options?: Options): HttpRequest { +export class Simple { + public static deleteCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'DELETE', @@ -62,7 +77,7 @@ export class SimpleServiceRequests { }); } - public getCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static getCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -71,7 +86,7 @@ export class SimpleServiceRequests { }); } - public headCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static headCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'HEAD', @@ -80,7 +95,7 @@ export class SimpleServiceRequests { }); } - public optionsCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static optionsCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'OPTIONS', @@ -89,7 +104,7 @@ export class SimpleServiceRequests { }); } - public patchCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static patchCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PATCH', @@ -98,7 +113,7 @@ export class SimpleServiceRequests { }); } - public postCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static postCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -107,7 +122,7 @@ export class SimpleServiceRequests { }); } - public putCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static putCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PUT', @@ -117,9 +132,8 @@ export class SimpleServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class DescriptionsServiceRequests { - public callWithDescriptions(options?: Options): HttpRequest { +export class Descriptions { + public static callWithDescriptions(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -129,9 +143,8 @@ export class DescriptionsServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class ParametersServiceRequests { - public callWithParameters(options: Options): HttpRequest { +export class Parameters { + public static callWithParameters(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -140,7 +153,7 @@ export class ParametersServiceRequests { }); } - public callWithWeirdParameterNames(options: Options): HttpRequest { + public static callWithWeirdParameterNames(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -150,9 +163,8 @@ export class ParametersServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class DefaultsServiceRequests { - public callWithDefaultParameters(options: Options): HttpRequest { +export class Defaults { + public static callWithDefaultParameters(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -161,7 +173,7 @@ export class DefaultsServiceRequests { }); } - public callWithDefaultOptionalParameters(options?: Options): HttpRequest { + public static callWithDefaultOptionalParameters(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -170,7 +182,7 @@ export class DefaultsServiceRequests { }); } - public callToTestOrderOfParams(options: Options): HttpRequest { + public static callToTestOrderOfParams(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PUT', @@ -180,9 +192,8 @@ export class DefaultsServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class DuplicateServiceRequests { - public duplicateName(options?: Options): HttpRequest { +export class Duplicate { + public static duplicateName(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'DELETE', @@ -191,7 +202,7 @@ export class DuplicateServiceRequests { }); } - public duplicateName2(options?: Options): HttpRequest { + public static duplicateName2(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -200,7 +211,7 @@ export class DuplicateServiceRequests { }); } - public duplicateName3(options?: Options): HttpRequest { + public static duplicateName3(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -209,7 +220,7 @@ export class DuplicateServiceRequests { }); } - public duplicateName4(options?: Options): HttpRequest { + public static duplicateName4(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PUT', @@ -219,9 +230,8 @@ export class DuplicateServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class NoContentServiceRequests { - public callWithNoContentResponse(options?: Options): HttpRequest { +export class NoContent { + public static callWithNoContentResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -230,7 +240,7 @@ export class NoContentServiceRequests { }); } - public callWithResponseAndNoContentResponse(options?: Options): HttpRequest { + public static callWithResponseAndNoContentResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -240,9 +250,8 @@ export class NoContentServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class ResponseServiceRequests { - public callWithResponseAndNoContentResponse(options?: Options): HttpRequest { +export class Response { + public static callWithResponseAndNoContentResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -251,7 +260,7 @@ export class ResponseServiceRequests { }); } - public callWithResponse(options?: Options): HttpRequest { + public static callWithResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -260,7 +269,7 @@ export class ResponseServiceRequests { }); } - public callWithDuplicateResponses(options?: Options): HttpRequest { + public static callWithDuplicateResponses(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -269,7 +278,7 @@ export class ResponseServiceRequests { }); } - public callWithResponses(options?: Options): HttpRequest { + public static callWithResponses(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PUT', @@ -279,9 +288,8 @@ export class ResponseServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags1ServiceRequests { - public dummyA(options?: Options): HttpRequest { +export class MultipleTags1 { + public static dummyA(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -290,7 +298,7 @@ export class MultipleTags1ServiceRequests { }); } - public dummyB(options?: Options): HttpRequest { + public static dummyB(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -300,9 +308,8 @@ export class MultipleTags1ServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags2ServiceRequests { - public dummyA(options?: Options): HttpRequest { +export class MultipleTags2 { + public static dummyA(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -311,7 +318,7 @@ export class MultipleTags2ServiceRequests { }); } - public dummyB(options?: Options): HttpRequest { + public static dummyB(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -321,9 +328,8 @@ export class MultipleTags2ServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags3ServiceRequests { - public dummyB(options?: Options): HttpRequest { +export class MultipleTags3 { + public static dummyB(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -333,9 +339,8 @@ export class MultipleTags3ServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class CollectionFormatServiceRequests { - public collectionFormat(options: Options): HttpRequest { +export class CollectionFormat { + public static collectionFormat(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -345,9 +350,8 @@ export class CollectionFormatServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class TypesServiceRequests { - public types(options: Options): HttpRequest { +export class Types { + public static types(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -357,9 +361,8 @@ export class TypesServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class ComplexServiceRequests { - public complexTypes(options: Options): HttpRequest { +export class Complex { + public static complexTypes(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -369,9 +372,8 @@ export class ComplexServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class HeaderServiceRequests { - public callWithResultFromHeader(options?: Options): HttpRequest { +export class Header { + public static callWithResultFromHeader(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -381,9 +383,8 @@ export class HeaderServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class ErrorServiceRequests { - public testErrorCode(options: Options): HttpRequest { +export class Error_ { + public static testErrorCode(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -393,9 +394,8 @@ export class ErrorServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class NonAsciiÆøåÆøÅöôêÊServiceRequests { - public nonAsciiæøåÆøÅöôêÊ字符串(options: Options): HttpRequest { +export class NonAsciiÆøåÆøÅöôêÊ { + public static nonAsciiæøåÆøÅöôêÊ字符串(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -405,324 +405,323 @@ export class NonAsciiÆøåÆøÅöôêÊServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class DefaultServiceResources { - public serviceWithEmptyTag(options?: () => Options | undefined) { +export class No_tagResources { + public static patch(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultServiceRequests).serviceWithEmptyTag(opts) : undefined; + return opts ? Default.apiRequests.vApiVersionRequests['no+tagRequests'].patch(opts) : undefined; }); } - - public patchApiVbyApiVersionNoTag(options?: () => Options | undefined) { - return httpResource(() => { +} + +export class BodyResources { + /** + * Body should not be unknown + * + * Body should not be unknown + */ + public static post(options: () => Options | undefined) { + return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultServiceRequests).patchApiVbyApiVersionNoTag(opts) : undefined; + return opts ? Default.apiRequests.vApiVersionRequests.bodyRequests.post(opts) : undefined; }); } +} + +export class VApiVersionResources { + static 'no+tagResources' = No_tagResources; - public fooWow(options?: () => Options | undefined) { + static bodyResources = BodyResources; +} + +export class ApiResources { + static vApiVersionResources = VApiVersionResources; +} + +export class Default2 { + public static serviceWithEmptyTag(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultServiceRequests).fooWow(opts) : undefined; + return opts ? Default.serviceWithEmptyTag(opts) : undefined; }); } - /** - * Body should not be unknown - * - * Body should not be unknown - */ - public postApiVbyApiVersionBody(options: () => Options | undefined) { - return httpResource(() => { + public static 'foo+Wow'(options?: () => Options | undefined) { + return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultServiceRequests).postApiVbyApiVersionBody(opts) : undefined; + return opts ? Default['foo+Wow'](opts) : undefined; }); } + + static apiResources = ApiResources; } -@Injectable({ providedIn: 'root' }) -export class SimpleServiceResources { - public deleteCallWithoutParametersAndResponse(options?: () => Options | undefined) { +export class Simple2 { + public static deleteCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).deleteCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.deleteCallWithoutParametersAndResponse(opts) : undefined; }); } - public getCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static getCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).getCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.getCallWithoutParametersAndResponse(opts) : undefined; }); } - public headCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static headCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).headCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.headCallWithoutParametersAndResponse(opts) : undefined; }); } - public optionsCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static optionsCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).optionsCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.optionsCallWithoutParametersAndResponse(opts) : undefined; }); } - public patchCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static patchCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).patchCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.patchCallWithoutParametersAndResponse(opts) : undefined; }); } - public postCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static postCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).postCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.postCallWithoutParametersAndResponse(opts) : undefined; }); } - public putCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static putCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).putCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.putCallWithoutParametersAndResponse(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class DescriptionsServiceResources { - public callWithDescriptions(options?: () => Options | undefined) { +export class Descriptions2 { + public static callWithDescriptions(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DescriptionsServiceRequests).callWithDescriptions(opts) : undefined; + return opts ? Descriptions.callWithDescriptions(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class ParametersServiceResources { - public callWithParameters(options: () => Options | undefined) { +export class Parameters2 { + public static callWithParameters(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ParametersServiceRequests).callWithParameters(opts) : undefined; + return opts ? Parameters.callWithParameters(opts) : undefined; }); } - public callWithWeirdParameterNames(options: () => Options | undefined) { + public static callWithWeirdParameterNames(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ParametersServiceRequests).callWithWeirdParameterNames(opts) : undefined; + return opts ? Parameters.callWithWeirdParameterNames(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class DefaultsServiceResources { - public callWithDefaultParameters(options: () => Options | undefined) { +export class Defaults2 { + public static callWithDefaultParameters(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultsServiceRequests).callWithDefaultParameters(opts) : undefined; + return opts ? Defaults.callWithDefaultParameters(opts) : undefined; }); } - public callWithDefaultOptionalParameters(options?: () => Options | undefined) { + public static callWithDefaultOptionalParameters(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultsServiceRequests).callWithDefaultOptionalParameters(opts) : undefined; + return opts ? Defaults.callWithDefaultOptionalParameters(opts) : undefined; }); } - public callToTestOrderOfParams(options: () => Options | undefined) { + public static callToTestOrderOfParams(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultsServiceRequests).callToTestOrderOfParams(opts) : undefined; + return opts ? Defaults.callToTestOrderOfParams(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class DuplicateServiceResources { - public duplicateName(options?: () => Options | undefined) { +export class Duplicate2 { + public static duplicateName(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DuplicateServiceRequests).duplicateName(opts) : undefined; + return opts ? Duplicate.duplicateName(opts) : undefined; }); } - public duplicateName2(options?: () => Options | undefined) { + public static duplicateName2(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DuplicateServiceRequests).duplicateName2(opts) : undefined; + return opts ? Duplicate.duplicateName2(opts) : undefined; }); } - public duplicateName3(options?: () => Options | undefined) { + public static duplicateName3(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DuplicateServiceRequests).duplicateName3(opts) : undefined; + return opts ? Duplicate.duplicateName3(opts) : undefined; }); } - public duplicateName4(options?: () => Options | undefined) { + public static duplicateName4(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DuplicateServiceRequests).duplicateName4(opts) : undefined; + return opts ? Duplicate.duplicateName4(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class NoContentServiceResources { - public callWithNoContentResponse(options?: () => Options | undefined) { +export class NoContent2 { + public static callWithNoContentResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(NoContentServiceRequests).callWithNoContentResponse(opts) : undefined; + return opts ? NoContent.callWithNoContentResponse(opts) : undefined; }); } - public callWithResponseAndNoContentResponse(options?: () => Options | undefined) { + public static callWithResponseAndNoContentResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ResponseServiceRequests).callWithResponseAndNoContentResponse(opts) : undefined; + return opts ? NoContent.callWithResponseAndNoContentResponse(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class ResponseServiceResources { - public callWithResponseAndNoContentResponse(options?: () => Options | undefined) { +export class Response2 { + public static callWithResponseAndNoContentResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ResponseServiceRequests).callWithResponseAndNoContentResponse(opts) : undefined; + return opts ? NoContent.callWithResponseAndNoContentResponse(opts) : undefined; }); } - public callWithResponse(options?: () => Options | undefined) { + public static callWithResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ResponseServiceRequests).callWithResponse(opts) : undefined; + return opts ? Response.callWithResponse(opts) : undefined; }); } - public callWithDuplicateResponses(options?: () => Options | undefined) { + public static callWithDuplicateResponses(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ResponseServiceRequests).callWithDuplicateResponses(opts) : undefined; + return opts ? Response.callWithDuplicateResponses(opts) : undefined; }); } - public callWithResponses(options?: () => Options | undefined) { + public static callWithResponses(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ResponseServiceRequests).callWithResponses(opts) : undefined; + return opts ? Response.callWithResponses(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags1ServiceResources { - public dummyA(options?: () => Options | undefined) { +export class MultipleTags12 { + public static dummyA(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipleTags1ServiceRequests).dummyA(opts) : undefined; + return opts ? MultipleTags1.dummyA(opts) : undefined; }); } - public dummyB(options?: () => Options | undefined) { + public static dummyB(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipleTags1ServiceRequests).dummyB(opts) : undefined; + return opts ? MultipleTags1.dummyB(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags2ServiceResources { - public dummyA(options?: () => Options | undefined) { +export class MultipleTags22 { + public static dummyA(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipleTags1ServiceRequests).dummyA(opts) : undefined; + return opts ? MultipleTags1.dummyA(opts) : undefined; }); } - public dummyB(options?: () => Options | undefined) { + public static dummyB(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipleTags1ServiceRequests).dummyB(opts) : undefined; + return opts ? MultipleTags1.dummyB(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags3ServiceResources { - public dummyB(options?: () => Options | undefined) { +export class MultipleTags32 { + public static dummyB(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipleTags1ServiceRequests).dummyB(opts) : undefined; + return opts ? MultipleTags1.dummyB(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class CollectionFormatServiceResources { - public collectionFormat(options: () => Options | undefined) { +export class CollectionFormat2 { + public static collectionFormat(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(CollectionFormatServiceRequests).collectionFormat(opts) : undefined; + return opts ? CollectionFormat.collectionFormat(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class TypesServiceResources { - public types(options: () => Options | undefined) { +export class Types2 { + public static types(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(TypesServiceRequests).types(opts) : undefined; + return opts ? Types.types(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class ComplexServiceResources { - public complexTypes(options: () => Options | undefined) { +export class Complex2 { + public static complexTypes(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ComplexServiceRequests).complexTypes(opts) : undefined; + return opts ? Complex.complexTypes(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class HeaderServiceResources { - public callWithResultFromHeader(options?: () => Options | undefined) { +export class Header2 { + public static callWithResultFromHeader(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(HeaderServiceRequests).callWithResultFromHeader(opts) : undefined; + return opts ? Header.callWithResultFromHeader(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class ErrorServiceResources { - public testErrorCode(options: () => Options | undefined) { +export class Error2 { + public static testErrorCode(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ErrorServiceRequests).testErrorCode(opts) : undefined; + return opts ? Error_.testErrorCode(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class NonAsciiÆøåÆøÅöôêÊServiceResources { - public nonAsciiæøåÆøÅöôêÊ字符串(options: () => Options | undefined) { +export class NonAsciiÆøåÆøÅöôêÊ2 { + public static nonAsciiæøåÆøÅöôêÊ字符串(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(NonAsciiÆøåÆøÅöôêÊServiceRequests).nonAsciiæøåÆøÅöôêÊ字符串(opts) : undefined; + return opts ? NonAsciiÆøåÆøÅöôêÊ.nonAsciiæøåÆøÅöôêÊ字符串(opts) : undefined; }); } } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/sdk.gen.ts index 6776488ce..fdc344691 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default-class/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -117,7 +117,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/body', ...options, headers: { diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default/sdk.gen.ts index 6776488ce..fdc344691 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@angular/common/default/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -117,7 +117,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/body', ...options, headers: { diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes-instance/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes-instance/sdk.gen.ts index fafb8ed66..a1beb0a63 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes-instance/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes-instance/sdk.gen.ts @@ -54,6 +54,10 @@ export class Domains extends HeyApiClient { public post(options?: Options) { return (options?.client ?? this.client).post({ url: '/business/providers/domains', ...options }); } + + public put(options?: Options) { + return (options?.client ?? this.client).put({ url: '/business/providers/domains', ...options }); + } } export class Providers extends HeyApiClient { @@ -85,10 +89,6 @@ export class NestedSdkWithInstance extends HeyApiClient { NestedSdkWithInstance.__registry.set(this, args?.key); } - public putBusinessProvidersDomains(options?: Options) { - return (options?.client ?? this.client).put({ url: '/business/providers/domains', ...options }); - } - public get(options?: Options) { return (options?.client ?? this.client).get({ url: '/locations', ...options }); } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts index babd05bc9..505a12a57 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts @@ -74,6 +74,10 @@ export class Domains3 { public static post(options?: Options) { return (options?.client ?? client).post({ url: '/business/providers/domains', ...options }); } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/business/providers/domains', ...options }); + } } export class Providers4 { @@ -85,10 +89,6 @@ export class Business4 { } export class Domains4 { - public static putBusinessProvidersDomains(options?: Options) { - return (options?.client ?? client).put({ url: '/business/providers/domains', ...options }); - } - static business = Business4; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/default/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/default/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/default/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/default/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/default/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/default/sdk.gen.ts index 6776488ce..fdc344691 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/default/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/default/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -117,7 +117,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/body', ...options, headers: { diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/instance/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/instance/sdk.gen.ts index af464f9b9..060d7ded1 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/instance/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/instance/sdk.gen.ts @@ -47,6 +47,10 @@ class HeyApiRegistry { } export class Bar extends HeyApiClient { + public get(options?: Options) { + return (options?.client ?? this.client).get({ url: '/foo/bar', ...options }); + } + public post(options?: Options) { return (options?.client ?? this.client).post({ url: '/foo/bar', ...options }); } @@ -57,6 +61,10 @@ export class Bar extends HeyApiClient { } export class Foo extends HeyApiClient { + public get(options?: Options) { + return (options?.client ?? this.client).get({ url: '/foo', ...options }); + } + public post(options?: Options) { return (options?.client ?? this.client).post({ url: '/foo', ...options }); } @@ -82,14 +90,6 @@ export class Sdk extends HeyApiClient { Sdk.__registry.set(this, args?.key); } - public getFoo(options?: Options) { - return (options?.client ?? this.client).get({ url: '/foo', ...options }); - } - - public getFooBar(options?: Options) { - return (options?.client ?? this.client).get({ url: '/foo/bar', ...options }); - } - private _foo?: Foo; get foo(): Foo { return this._foo ??= new Foo({ client: this.client }); diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/throwOnError/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/throwOnError/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/throwOnError/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/throwOnError/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/throwOnError/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/throwOnError/sdk.gen.ts index 9cfe2097f..bca22f7cc 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/throwOnError/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/sdk/throwOnError/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -117,7 +117,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/body', ...options, headers: { diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-valibot/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-valibot/index.ts index 8dc6d0499..61e4b126b 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-valibot/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-valibot/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { type Options, postFoo } from './sdk.gen'; +export { fooPost, type Options } from './sdk.gen'; export type { Bar, ClientOptions, Foo, PostFooData, PostFooResponse, PostFooResponses, TypeID, UserId } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-valibot/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-valibot/sdk.gen.ts index b443e6ac2..8d5af124b 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-valibot/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-valibot/sdk.gen.ts @@ -22,7 +22,7 @@ export type Options; }; -export const postFoo = (options?: Options) => (options?.client ?? client).post({ +export const fooPost = (options?: Options) => (options?.client ?? client).post({ requestValidator: async (data) => await v.parseAsync(vPostFooData, data), responseTransformer: postFooResponseTransformer, responseValidator: async (data) => await v.parseAsync(vPostFooResponse, data), diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-zod/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-zod/index.ts index 8dc6d0499..61e4b126b 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-zod/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-zod/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { type Options, postFoo } from './sdk.gen'; +export { fooPost, type Options } from './sdk.gen'; export type { Bar, ClientOptions, Foo, PostFooData, PostFooResponse, PostFooResponses, TypeID, UserId } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-zod/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-zod/sdk.gen.ts index db455df67..56a6a3fd7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-zod/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@hey-api/transformers/type-format-zod/sdk.gen.ts @@ -20,7 +20,7 @@ export type Options; }; -export const postFoo = (options?: Options) => (options?.client ?? client).post({ +export const fooPost = (options?: Options) => (options?.client ?? client).post({ requestValidator: async (data) => await zPostFooData.parseAsync(data), responseTransformer: postFooResponseTransformer, responseValidator: async (data) => await zPostFooResponse.parseAsync(data), diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/@pinia/colada.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/@pinia/colada.gen.ts index 3aeed5221..84f186999 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/@pinia/colada.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/@pinia/colada.gen.ts @@ -47,7 +47,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooQuery = defineQueryOptions((options?: Options) => ({ key: getFooQueryKey(options), query: async (context) => { - const { data } = await FooBazService.getFoo({ + const { data } = await FooBazService.fooService.get({ ...options, ...context, throwOnError: true @@ -83,7 +83,7 @@ export const getFooBarQueryKey = (options?: Options) => createQue export const getFooBarQuery = defineQueryOptions((options?: Options) => ({ key: getFooBarQueryKey(options), query: async (context) => { - const { data } = await BarBazService.getFooBar({ + const { data } = await BarBazService.fooService.barService.get({ ...options, ...context, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts index 81b7e79ea..951c71fca 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts @@ -29,6 +29,10 @@ export class BarService { } export class FooService { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo', ...options }); } @@ -41,14 +45,14 @@ export class FooService { } export class FooBazService { - public static getFoo(options?: Options) { - return (options?.client ?? client).get({ url: '/foo', ...options }); - } - static fooService = FooService; } export class BarService2 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo/bar', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo/bar', ...options }); } @@ -63,9 +67,5 @@ export class FooService2 { } export class BarBazService { - public static getFooBar(options?: Options) { - return (options?.client ?? client).get({ url: '/foo/bar', ...options }); - } - static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/@pinia/colada.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/@pinia/colada.gen.ts index 14aff2882..6d802c7a7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/@pinia/colada.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/@pinia/colada.gen.ts @@ -4,7 +4,7 @@ import { type _JSONValue, defineQueryOptions, type UseMutationOptions } from '@p import { serializeQueryKeyValue } from '../client'; import { client } from '../client.gen'; -import { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; +import { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseData, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData } from '../types.gen'; export type QueryKey = [ @@ -58,7 +58,7 @@ export const serviceWithEmptyTagQuery = defineQueryOptions((options?: Options>): UseMutationOptions, Error> => ({ mutation: async (vars) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...vars, throwOnError: true @@ -69,7 +69,7 @@ export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): UseMutationOptions, Error> => ({ mutation: async (vars) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...vars, throwOnError: true @@ -426,7 +426,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串Mutation = (options?: Partial< */ export const postApiVbyApiVersionBodyMutation = (options?: Partial>): UseMutationOptions, PostApiVbyApiVersionBodyError> => ({ mutation: async (vars) => { - const { data } = await postApiVbyApiVersionBody({ + const { data } = await apiVApiVersionBodyPost({ ...options, ...vars, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/sdk.gen.ts index 6776488ce..fdc344691 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@pinia/colada/fetch/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -117,7 +117,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/body', ...options, headers: { diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/@tanstack/angular-query-experimental.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/@tanstack/angular-query-experimental.gen.ts index 6f71bcc40..72bb39e1a 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/@tanstack/angular-query-experimental.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/@tanstack/angular-query-experimental.gen.ts @@ -43,7 +43,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await FooBazService.getFoo({ + const { data } = await FooBazService.fooService.get({ ...options, ...queryKey[0], signal, @@ -86,7 +86,7 @@ export const getFooBarQueryKey = (options?: Options) => createQue export const getFooBarOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await BarBazService.getFooBar({ + const { data } = await BarBazService.fooService.barService.get({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts index 81b7e79ea..951c71fca 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/asClass/sdk.gen.ts @@ -29,6 +29,10 @@ export class BarService { } export class FooService { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo', ...options }); } @@ -41,14 +45,14 @@ export class FooService { } export class FooBazService { - public static getFoo(options?: Options) { - return (options?.client ?? client).get({ url: '/foo', ...options }); - } - static fooService = FooService; } export class BarService2 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo/bar', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo/bar', ...options }); } @@ -63,9 +67,5 @@ export class FooService2 { } export class BarBazService { - public static getFooBar(options?: Options) { - return (options?.client ?? client).get({ url: '/foo/bar', ...options }); - } - static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/@tanstack/angular-query-experimental.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/@tanstack/angular-query-experimental.gen.ts index cef8fd363..b8871211a 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/@tanstack/angular-query-experimental.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/@tanstack/angular-query-experimental.gen.ts @@ -4,7 +4,7 @@ import { type DefaultError, type MutationOptions, queryOptions } from '@tanstack import type { AxiosError } from 'axios'; import { client } from '../client.gen'; -import { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; +import { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData, TypesResponse } from '../types.gen'; export type QueryKey = [ @@ -58,7 +58,7 @@ export const serviceWithEmptyTagOptions = (options?: Options>): MutationOptions, Options> => { const mutationOptions: MutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...fnOptions, throwOnError: true @@ -72,7 +72,7 @@ export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): MutationOptions, Options> => { const mutationOptions: MutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...fnOptions, throwOnError: true @@ -494,7 +494,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串Mutation = (options?: Partial< export const postApiVbyApiVersionBodyMutation = (options?: Partial>): MutationOptions, Options> => { const mutationOptions: MutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await postApiVbyApiVersionBody({ + const { data } = await apiVApiVersionBodyPost({ ...options, ...fnOptions, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/sdk.gen.ts index 9359ba9fe..fae730b98 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/axios/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -155,7 +155,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ responseType: 'json', url: '/api/v{api-version}/body', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/@tanstack/angular-query-experimental.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/@tanstack/angular-query-experimental.gen.ts index 5087360ef..36c7f22f5 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/@tanstack/angular-query-experimental.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/@tanstack/angular-query-experimental.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, type MutationOptions, queryOptions } from '@tanstack/angular-query-experimental'; import { client } from '../client.gen'; -import { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; +import { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData, TypesResponse } from '../types.gen'; export type QueryKey = [ @@ -57,7 +57,7 @@ export const serviceWithEmptyTagOptions = (options?: Options>): MutationOptions> => { const mutationOptions: MutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...fnOptions, throwOnError: true @@ -71,7 +71,7 @@ export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): MutationOptions> => { const mutationOptions: MutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...fnOptions, throwOnError: true @@ -493,7 +493,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串Mutation = (options?: Partial< export const postApiVbyApiVersionBodyMutation = (options?: Partial>): MutationOptions> => { const mutationOptions: MutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await postApiVbyApiVersionBody({ + const { data } = await apiVApiVersionBodyPost({ ...options, ...fnOptions, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/sdk.gen.ts index 6776488ce..fdc344691 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/fetch/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -117,7 +117,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/body', ...options, headers: { diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/@tanstack/angular-query-experimental.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/@tanstack/angular-query-experimental.gen.ts index b144ed7a2..1f27d6e82 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/@tanstack/angular-query-experimental.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/@tanstack/angular-query-experimental.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, type MutationOptions, queryOptions } from '@tanstack/angular-query-experimental'; import { client } from '../client.gen'; -import { fooBarPost, fooBarPut, fooPost, fooPut, getFoo, getFooBar, type Options } from '../sdk.gen'; +import { fooBarGet, fooBarPost, fooBarPut, fooGet, fooPost, fooPut, type Options } from '../sdk.gen'; import type { FooBarPostData, FooBarPostResponse, FooBarPutData, FooBarPutResponse, FooPostData, FooPostResponse, FooPutData, FooPutResponse, GetFooBarData, GetFooBarResponse, GetFooData, GetFooResponse } from '../types.gen'; export type QueryKey = [ @@ -43,7 +43,7 @@ export const getFooD = (options?: Options) => createQueryKey('getFoo export const getFooE = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFoo({ + const { data } = await fooGet({ ...options, ...queryKey[0], signal, @@ -86,7 +86,7 @@ export const getFooBarD = (options?: Options) => createQueryKey(' export const getFooBarE = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFooBar({ + const { data } = await fooBarGet({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/index.ts index b3d19ebcd..e42ffea2a 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { fooBarPost, fooBarPut, fooPost, fooPut, getFoo, getFooBar, type Options } from './sdk.gen'; +export { fooBarGet, fooBarPost, fooBarPut, fooGet, fooPost, fooPut, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/sdk.gen.ts index a70249590..a52716c48 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/angular-query-experimental/name-builder/sdk.gen.ts @@ -18,13 +18,13 @@ export type Options; }; -export const getFoo = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); +export const fooGet = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); export const fooPost = (options?: Options) => (options?.client ?? client).post({ url: '/foo', ...options }); export const fooPut = (options?: Options) => (options?.client ?? client).put({ url: '/foo', ...options }); -export const getFooBar = (options?: Options) => (options?.client ?? client).get({ url: '/foo/bar', ...options }); +export const fooBarGet = (options?: Options) => (options?.client ?? client).get({ url: '/foo/bar', ...options }); export const fooBarPost = (options?: Options) => (options?.client ?? client).post({ url: '/foo/bar', ...options }); diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/@tanstack/react-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/@tanstack/react-query.gen.ts index 74f3f999f..8971e2a33 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/@tanstack/react-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/@tanstack/react-query.gen.ts @@ -43,7 +43,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await FooBazService.getFoo({ + const { data } = await FooBazService.fooService.get({ ...options, ...queryKey[0], signal, @@ -86,7 +86,7 @@ export const getFooBarQueryKey = (options?: Options) => createQue export const getFooBarOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await BarBazService.getFooBar({ + const { data } = await BarBazService.fooService.barService.get({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts index 81b7e79ea..951c71fca 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/asClass/sdk.gen.ts @@ -29,6 +29,10 @@ export class BarService { } export class FooService { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo', ...options }); } @@ -41,14 +45,14 @@ export class FooService { } export class FooBazService { - public static getFoo(options?: Options) { - return (options?.client ?? client).get({ url: '/foo', ...options }); - } - static fooService = FooService; } export class BarService2 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo/bar', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo/bar', ...options }); } @@ -63,9 +67,5 @@ export class FooService2 { } export class BarBazService { - public static getFooBar(options?: Options) { - return (options?.client ?? client).get({ url: '/foo/bar', ...options }); - } - static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/@tanstack/react-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/@tanstack/react-query.gen.ts index da398d170..0749df981 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/@tanstack/react-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/@tanstack/react-query.gen.ts @@ -4,7 +4,7 @@ import { type DefaultError, queryOptions, type UseMutationOptions } from '@tanst import type { AxiosError } from 'axios'; import { client } from '../client.gen'; -import { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; +import { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData, TypesResponse } from '../types.gen'; export type QueryKey = [ @@ -58,7 +58,7 @@ export const serviceWithEmptyTagOptions = (options?: Options>): UseMutationOptions, Options> => { const mutationOptions: UseMutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...fnOptions, throwOnError: true @@ -72,7 +72,7 @@ export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): UseMutationOptions, Options> => { const mutationOptions: UseMutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...fnOptions, throwOnError: true @@ -494,7 +494,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串Mutation = (options?: Partial< export const postApiVbyApiVersionBodyMutation = (options?: Partial>): UseMutationOptions, Options> => { const mutationOptions: UseMutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await postApiVbyApiVersionBody({ + const { data } = await apiVApiVersionBodyPost({ ...options, ...fnOptions, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/sdk.gen.ts index 9359ba9fe..fae730b98 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/axios/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -155,7 +155,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ responseType: 'json', url: '/api/v{api-version}/body', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/@tanstack/react-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/@tanstack/react-query.gen.ts index ef023fe2c..946c6f502 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/@tanstack/react-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/@tanstack/react-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, queryOptions, type UseMutationOptions } from '@tanstack/react-query'; import { client } from '../client.gen'; -import { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; +import { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData, TypesResponse } from '../types.gen'; export type QueryKey = [ @@ -57,7 +57,7 @@ export const serviceWithEmptyTagOptions = (options?: Options>): UseMutationOptions> => { const mutationOptions: UseMutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...fnOptions, throwOnError: true @@ -71,7 +71,7 @@ export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): UseMutationOptions> => { const mutationOptions: UseMutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...fnOptions, throwOnError: true @@ -493,7 +493,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串Mutation = (options?: Partial< export const postApiVbyApiVersionBodyMutation = (options?: Partial>): UseMutationOptions> => { const mutationOptions: UseMutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await postApiVbyApiVersionBody({ + const { data } = await apiVApiVersionBodyPost({ ...options, ...fnOptions, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/sdk.gen.ts index 6776488ce..fdc344691 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/fetch/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -117,7 +117,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/body', ...options, headers: { diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/@tanstack/react-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/@tanstack/react-query.gen.ts index 43c90277c..f6cb04a06 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/@tanstack/react-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/@tanstack/react-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, queryOptions, type UseMutationOptions } from '@tanstack/react-query'; import { client } from '../client.gen'; -import { fooBarPost, fooBarPut, fooPost, fooPut, getFoo, getFooBar, type Options } from '../sdk.gen'; +import { fooBarGet, fooBarPost, fooBarPut, fooGet, fooPost, fooPut, type Options } from '../sdk.gen'; import type { FooBarPostData, FooBarPostResponse, FooBarPutData, FooBarPutResponse, FooPostData, FooPostResponse, FooPutData, FooPutResponse, GetFooBarData, GetFooBarResponse, GetFooData, GetFooResponse } from '../types.gen'; export type QueryKey = [ @@ -43,7 +43,7 @@ export const getFooD = (options?: Options) => createQueryKey('getFoo export const getFooE = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFoo({ + const { data } = await fooGet({ ...options, ...queryKey[0], signal, @@ -86,7 +86,7 @@ export const getFooBarD = (options?: Options) => createQueryKey(' export const getFooBarE = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFooBar({ + const { data } = await fooBarGet({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/index.ts index b3d19ebcd..e42ffea2a 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { fooBarPost, fooBarPut, fooPost, fooPut, getFoo, getFooBar, type Options } from './sdk.gen'; +export { fooBarGet, fooBarPost, fooBarPut, fooGet, fooPost, fooPut, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/sdk.gen.ts index a70249590..a52716c48 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/react-query/name-builder/sdk.gen.ts @@ -18,13 +18,13 @@ export type Options; }; -export const getFoo = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); +export const fooGet = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); export const fooPost = (options?: Options) => (options?.client ?? client).post({ url: '/foo', ...options }); export const fooPut = (options?: Options) => (options?.client ?? client).put({ url: '/foo', ...options }); -export const getFooBar = (options?: Options) => (options?.client ?? client).get({ url: '/foo/bar', ...options }); +export const fooBarGet = (options?: Options) => (options?.client ?? client).get({ url: '/foo/bar', ...options }); export const fooBarPost = (options?: Options) => (options?.client ?? client).post({ url: '/foo/bar', ...options }); diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/@tanstack/solid-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/@tanstack/solid-query.gen.ts index 908344e1b..94993b462 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/@tanstack/solid-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/@tanstack/solid-query.gen.ts @@ -43,7 +43,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await FooBazService.getFoo({ + const { data } = await FooBazService.fooService.get({ ...options, ...queryKey[0], signal, @@ -86,7 +86,7 @@ export const getFooBarQueryKey = (options?: Options) => createQue export const getFooBarOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await BarBazService.getFooBar({ + const { data } = await BarBazService.fooService.barService.get({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts index 81b7e79ea..951c71fca 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/asClass/sdk.gen.ts @@ -29,6 +29,10 @@ export class BarService { } export class FooService { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo', ...options }); } @@ -41,14 +45,14 @@ export class FooService { } export class FooBazService { - public static getFoo(options?: Options) { - return (options?.client ?? client).get({ url: '/foo', ...options }); - } - static fooService = FooService; } export class BarService2 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo/bar', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo/bar', ...options }); } @@ -63,9 +67,5 @@ export class FooService2 { } export class BarBazService { - public static getFooBar(options?: Options) { - return (options?.client ?? client).get({ url: '/foo/bar', ...options }); - } - static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/@tanstack/solid-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/@tanstack/solid-query.gen.ts index 7a51e436a..5d2514fea 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/@tanstack/solid-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/@tanstack/solid-query.gen.ts @@ -4,7 +4,7 @@ import { type DefaultError, type MutationOptions, queryOptions } from '@tanstack import type { AxiosError } from 'axios'; import { client } from '../client.gen'; -import { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; +import { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData, TypesResponse } from '../types.gen'; export type QueryKey = [ @@ -58,7 +58,7 @@ export const serviceWithEmptyTagOptions = (options?: Options>): MutationOptions, Options> => { const mutationOptions: MutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...fnOptions, throwOnError: true @@ -72,7 +72,7 @@ export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): MutationOptions, Options> => { const mutationOptions: MutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...fnOptions, throwOnError: true @@ -494,7 +494,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串Mutation = (options?: Partial< export const postApiVbyApiVersionBodyMutation = (options?: Partial>): MutationOptions, Options> => { const mutationOptions: MutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await postApiVbyApiVersionBody({ + const { data } = await apiVApiVersionBodyPost({ ...options, ...fnOptions, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/sdk.gen.ts index 9359ba9fe..fae730b98 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/axios/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -155,7 +155,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ responseType: 'json', url: '/api/v{api-version}/body', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/@tanstack/solid-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/@tanstack/solid-query.gen.ts index c4092a30b..14c5d1367 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/@tanstack/solid-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/@tanstack/solid-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, type MutationOptions, queryOptions } from '@tanstack/solid-query'; import { client } from '../client.gen'; -import { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; +import { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData, TypesResponse } from '../types.gen'; export type QueryKey = [ @@ -57,7 +57,7 @@ export const serviceWithEmptyTagOptions = (options?: Options>): MutationOptions> => { const mutationOptions: MutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...fnOptions, throwOnError: true @@ -71,7 +71,7 @@ export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): MutationOptions> => { const mutationOptions: MutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...fnOptions, throwOnError: true @@ -493,7 +493,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串Mutation = (options?: Partial< export const postApiVbyApiVersionBodyMutation = (options?: Partial>): MutationOptions> => { const mutationOptions: MutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await postApiVbyApiVersionBody({ + const { data } = await apiVApiVersionBodyPost({ ...options, ...fnOptions, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/sdk.gen.ts index 6776488ce..fdc344691 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/fetch/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -117,7 +117,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/body', ...options, headers: { diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/@tanstack/solid-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/@tanstack/solid-query.gen.ts index ba1febdda..f01de6af2 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/@tanstack/solid-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/@tanstack/solid-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, type MutationOptions, queryOptions } from '@tanstack/solid-query'; import { client } from '../client.gen'; -import { fooBarPost, fooBarPut, fooPost, fooPut, getFoo, getFooBar, type Options } from '../sdk.gen'; +import { fooBarGet, fooBarPost, fooBarPut, fooGet, fooPost, fooPut, type Options } from '../sdk.gen'; import type { FooBarPostData, FooBarPostResponse, FooBarPutData, FooBarPutResponse, FooPostData, FooPostResponse, FooPutData, FooPutResponse, GetFooBarData, GetFooBarResponse, GetFooData, GetFooResponse } from '../types.gen'; export type QueryKey = [ @@ -43,7 +43,7 @@ export const getFooD = (options?: Options) => createQueryKey('getFoo export const getFooE = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFoo({ + const { data } = await fooGet({ ...options, ...queryKey[0], signal, @@ -86,7 +86,7 @@ export const getFooBarD = (options?: Options) => createQueryKey(' export const getFooBarE = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFooBar({ + const { data } = await fooBarGet({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/index.ts index b3d19ebcd..e42ffea2a 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { fooBarPost, fooBarPut, fooPost, fooPut, getFoo, getFooBar, type Options } from './sdk.gen'; +export { fooBarGet, fooBarPost, fooBarPut, fooGet, fooPost, fooPut, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/sdk.gen.ts index a70249590..a52716c48 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/solid-query/name-builder/sdk.gen.ts @@ -18,13 +18,13 @@ export type Options; }; -export const getFoo = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); +export const fooGet = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); export const fooPost = (options?: Options) => (options?.client ?? client).post({ url: '/foo', ...options }); export const fooPut = (options?: Options) => (options?.client ?? client).put({ url: '/foo', ...options }); -export const getFooBar = (options?: Options) => (options?.client ?? client).get({ url: '/foo/bar', ...options }); +export const fooBarGet = (options?: Options) => (options?.client ?? client).get({ url: '/foo/bar', ...options }); export const fooBarPost = (options?: Options) => (options?.client ?? client).post({ url: '/foo/bar', ...options }); diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/@tanstack/svelte-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/@tanstack/svelte-query.gen.ts index 4f7ad47a7..00aec8126 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/@tanstack/svelte-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/@tanstack/svelte-query.gen.ts @@ -43,7 +43,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await FooBazService.getFoo({ + const { data } = await FooBazService.fooService.get({ ...options, ...queryKey[0], signal, @@ -86,7 +86,7 @@ export const getFooBarQueryKey = (options?: Options) => createQue export const getFooBarOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await BarBazService.getFooBar({ + const { data } = await BarBazService.fooService.barService.get({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts index 81b7e79ea..951c71fca 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/asClass/sdk.gen.ts @@ -29,6 +29,10 @@ export class BarService { } export class FooService { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo', ...options }); } @@ -41,14 +45,14 @@ export class FooService { } export class FooBazService { - public static getFoo(options?: Options) { - return (options?.client ?? client).get({ url: '/foo', ...options }); - } - static fooService = FooService; } export class BarService2 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo/bar', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo/bar', ...options }); } @@ -63,9 +67,5 @@ export class FooService2 { } export class BarBazService { - public static getFooBar(options?: Options) { - return (options?.client ?? client).get({ url: '/foo/bar', ...options }); - } - static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/@tanstack/svelte-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/@tanstack/svelte-query.gen.ts index 8900d4a58..e2c388b63 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/@tanstack/svelte-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/@tanstack/svelte-query.gen.ts @@ -4,7 +4,7 @@ import { type DefaultError, type MutationOptions, queryOptions } from '@tanstack import type { AxiosError } from 'axios'; import { client } from '../client.gen'; -import { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; +import { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData, TypesResponse } from '../types.gen'; export type QueryKey = [ @@ -58,7 +58,7 @@ export const serviceWithEmptyTagOptions = (options?: Options>): MutationOptions, Options> => { const mutationOptions: MutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...fnOptions, throwOnError: true @@ -72,7 +72,7 @@ export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): MutationOptions, Options> => { const mutationOptions: MutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...fnOptions, throwOnError: true @@ -494,7 +494,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串Mutation = (options?: Partial< export const postApiVbyApiVersionBodyMutation = (options?: Partial>): MutationOptions, Options> => { const mutationOptions: MutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await postApiVbyApiVersionBody({ + const { data } = await apiVApiVersionBodyPost({ ...options, ...fnOptions, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/sdk.gen.ts index 9359ba9fe..fae730b98 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/axios/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -155,7 +155,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ responseType: 'json', url: '/api/v{api-version}/body', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/@tanstack/svelte-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/@tanstack/svelte-query.gen.ts index e14c0d70c..8495eca14 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/@tanstack/svelte-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/@tanstack/svelte-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, type MutationOptions, queryOptions } from '@tanstack/svelte-query'; import { client } from '../client.gen'; -import { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; +import { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData, TypesResponse } from '../types.gen'; export type QueryKey = [ @@ -57,7 +57,7 @@ export const serviceWithEmptyTagOptions = (options?: Options>): MutationOptions> => { const mutationOptions: MutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...fnOptions, throwOnError: true @@ -71,7 +71,7 @@ export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): MutationOptions> => { const mutationOptions: MutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...fnOptions, throwOnError: true @@ -493,7 +493,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串Mutation = (options?: Partial< export const postApiVbyApiVersionBodyMutation = (options?: Partial>): MutationOptions> => { const mutationOptions: MutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await postApiVbyApiVersionBody({ + const { data } = await apiVApiVersionBodyPost({ ...options, ...fnOptions, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/sdk.gen.ts index 6776488ce..fdc344691 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/fetch/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -117,7 +117,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/body', ...options, headers: { diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/@tanstack/svelte-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/@tanstack/svelte-query.gen.ts index 6a831b5b3..1de44f6db 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/@tanstack/svelte-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/@tanstack/svelte-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, type MutationOptions, queryOptions } from '@tanstack/svelte-query'; import { client } from '../client.gen'; -import { fooBarPost, fooBarPut, fooPost, fooPut, getFoo, getFooBar, type Options } from '../sdk.gen'; +import { fooBarGet, fooBarPost, fooBarPut, fooGet, fooPost, fooPut, type Options } from '../sdk.gen'; import type { FooBarPostData, FooBarPostResponse, FooBarPutData, FooBarPutResponse, FooPostData, FooPostResponse, FooPutData, FooPutResponse, GetFooBarData, GetFooBarResponse, GetFooData, GetFooResponse } from '../types.gen'; export type QueryKey = [ @@ -43,7 +43,7 @@ export const getFooD = (options?: Options) => createQueryKey('getFoo export const getFooE = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFoo({ + const { data } = await fooGet({ ...options, ...queryKey[0], signal, @@ -86,7 +86,7 @@ export const getFooBarD = (options?: Options) => createQueryKey(' export const getFooBarE = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFooBar({ + const { data } = await fooBarGet({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/index.ts index b3d19ebcd..e42ffea2a 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { fooBarPost, fooBarPut, fooPost, fooPut, getFoo, getFooBar, type Options } from './sdk.gen'; +export { fooBarGet, fooBarPost, fooBarPut, fooGet, fooPost, fooPut, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/sdk.gen.ts index a70249590..a52716c48 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/svelte-query/name-builder/sdk.gen.ts @@ -18,13 +18,13 @@ export type Options; }; -export const getFoo = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); +export const fooGet = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); export const fooPost = (options?: Options) => (options?.client ?? client).post({ url: '/foo', ...options }); export const fooPut = (options?: Options) => (options?.client ?? client).put({ url: '/foo', ...options }); -export const getFooBar = (options?: Options) => (options?.client ?? client).get({ url: '/foo/bar', ...options }); +export const fooBarGet = (options?: Options) => (options?.client ?? client).get({ url: '/foo/bar', ...options }); export const fooBarPost = (options?: Options) => (options?.client ?? client).post({ url: '/foo/bar', ...options }); diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/@tanstack/vue-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/@tanstack/vue-query.gen.ts index 767635c77..1c0b7cb8c 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/@tanstack/vue-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/@tanstack/vue-query.gen.ts @@ -43,7 +43,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await FooBazService.getFoo({ + const { data } = await FooBazService.fooService.get({ ...options, ...queryKey[0], signal, @@ -86,7 +86,7 @@ export const getFooBarQueryKey = (options?: Options) => createQue export const getFooBarOptions = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await BarBazService.getFooBar({ + const { data } = await BarBazService.fooService.barService.get({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts index 81b7e79ea..951c71fca 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/asClass/sdk.gen.ts @@ -29,6 +29,10 @@ export class BarService { } export class FooService { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo', ...options }); } @@ -41,14 +45,14 @@ export class FooService { } export class FooBazService { - public static getFoo(options?: Options) { - return (options?.client ?? client).get({ url: '/foo', ...options }); - } - static fooService = FooService; } export class BarService2 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo/bar', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo/bar', ...options }); } @@ -63,9 +67,5 @@ export class FooService2 { } export class BarBazService { - public static getFooBar(options?: Options) { - return (options?.client ?? client).get({ url: '/foo/bar', ...options }); - } - static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/@tanstack/vue-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/@tanstack/vue-query.gen.ts index 5a5ce3b11..68a9133d8 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/@tanstack/vue-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/@tanstack/vue-query.gen.ts @@ -4,7 +4,7 @@ import { type DefaultError, queryOptions, type UseMutationOptions } from '@tanst import type { AxiosError } from 'axios'; import { client } from '../client.gen'; -import { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; +import { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData, TypesResponse } from '../types.gen'; export type QueryKey = [ @@ -58,7 +58,7 @@ export const serviceWithEmptyTagOptions = (options?: Options>): UseMutationOptions, Options> => { const mutationOptions: UseMutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...fnOptions, throwOnError: true @@ -72,7 +72,7 @@ export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): UseMutationOptions, Options> => { const mutationOptions: UseMutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...fnOptions, throwOnError: true @@ -494,7 +494,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串Mutation = (options?: Partial< export const postApiVbyApiVersionBodyMutation = (options?: Partial>): UseMutationOptions, Options> => { const mutationOptions: UseMutationOptions, Options> = { mutationFn: async (fnOptions) => { - const { data } = await postApiVbyApiVersionBody({ + const { data } = await apiVApiVersionBodyPost({ ...options, ...fnOptions, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/sdk.gen.ts index 9359ba9fe..fae730b98 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/axios/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -155,7 +155,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ responseType: 'json', url: '/api/v{api-version}/body', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/@tanstack/vue-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/@tanstack/vue-query.gen.ts index b545d1817..e161cdaf0 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/@tanstack/vue-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/@tanstack/vue-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, queryOptions, type UseMutationOptions } from '@tanstack/vue-query'; import { client } from '../client.gen'; -import { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; +import { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from '../sdk.gen'; import type { CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, FooWowData, GetCallWithoutParametersAndResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ServiceWithEmptyTagData, TestErrorCodeData, TypesData, TypesResponse } from '../types.gen'; export type QueryKey = [ @@ -57,7 +57,7 @@ export const serviceWithEmptyTagOptions = (options?: Options>): UseMutationOptions> => { const mutationOptions: UseMutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...fnOptions, throwOnError: true @@ -71,7 +71,7 @@ export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): UseMutationOptions> => { const mutationOptions: UseMutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...fnOptions, throwOnError: true @@ -493,7 +493,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串Mutation = (options?: Partial< export const postApiVbyApiVersionBodyMutation = (options?: Partial>): UseMutationOptions> => { const mutationOptions: UseMutationOptions> = { mutationFn: async (fnOptions) => { - const { data } = await postApiVbyApiVersionBody({ + const { data } = await apiVApiVersionBodyPost({ ...options, ...fnOptions, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/index.ts index e45478b1d..c6833c00d 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, fooWow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionBody, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; +export { apiVApiVersionBodyPost, apiVApiVersionNo_tagPatch, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexTypes, deleteCallWithoutParametersAndResponse, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, foo_Wow, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, serviceWithEmptyTag, testErrorCode, types } from './sdk.gen'; export type { ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, Date, Default, DeleteCallWithoutParametersAndResponseData, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponses, DummyBData, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithStrings, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, FailureFailure, FooWowData, FooWowResponses, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ModelThatExtends, ModelThatExtendsExtends, ModelWithArray, ModelWithBoolean, ModelWithCircularReference, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithInteger, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableString, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, OptionsCallWithoutParametersAndResponseData, ParameterActivityParams, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyErrors, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyResponses, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, ResponsePostActivityResponse, ServiceWithEmptyTagData, SimpleBoolean, SimpleFile, SimpleInteger, SimpleReference, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/sdk.gen.ts index 6776488ce..fdc344691 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/fetch/sdk.gen.ts @@ -20,9 +20,9 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); -export const fooWow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -117,7 +117,7 @@ export const nonAsciiæøåÆøÅöôêÊ字符串 = (options: Options) => (options.client ?? client).post({ +export const apiVApiVersionBodyPost = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/body', ...options, headers: { diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/@tanstack/vue-query.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/@tanstack/vue-query.gen.ts index bfd35f1d6..720c42465 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/@tanstack/vue-query.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/@tanstack/vue-query.gen.ts @@ -3,7 +3,7 @@ import { type DefaultError, queryOptions, type UseMutationOptions } from '@tanstack/vue-query'; import { client } from '../client.gen'; -import { fooBarPost, fooBarPut, fooPost, fooPut, getFoo, getFooBar, type Options } from '../sdk.gen'; +import { fooBarGet, fooBarPost, fooBarPut, fooGet, fooPost, fooPut, type Options } from '../sdk.gen'; import type { FooBarPostData, FooBarPostResponse, FooBarPutData, FooBarPutResponse, FooPostData, FooPostResponse, FooPutData, FooPutResponse, GetFooBarData, GetFooBarResponse, GetFooData, GetFooResponse } from '../types.gen'; export type QueryKey = [ @@ -43,7 +43,7 @@ export const getFooD = (options?: Options) => createQueryKey('getFoo export const getFooE = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFoo({ + const { data } = await fooGet({ ...options, ...queryKey[0], signal, @@ -86,7 +86,7 @@ export const getFooBarD = (options?: Options) => createQueryKey(' export const getFooBarE = (options?: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getFooBar({ + const { data } = await fooBarGet({ ...options, ...queryKey[0], signal, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/index.ts index b3d19ebcd..e42ffea2a 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { fooBarPost, fooBarPut, fooPost, fooPut, getFoo, getFooBar, type Options } from './sdk.gen'; +export { fooBarGet, fooBarPost, fooBarPut, fooGet, fooPost, fooPut, type Options } from './sdk.gen'; export type { ClientOptions, FooBarPostData, FooBarPostResponse, FooBarPostResponses, FooBarPutData, FooBarPutResponse, FooBarPutResponses, FooPostData, FooPostResponse, FooPostResponses, FooPutData, FooPutResponse, FooPutResponses, GetFooBarData, GetFooBarResponse, GetFooBarResponses, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/sdk.gen.ts index a70249590..a52716c48 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/@tanstack/vue-query/name-builder/sdk.gen.ts @@ -18,13 +18,13 @@ export type Options; }; -export const getFoo = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); +export const fooGet = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); export const fooPost = (options?: Options) => (options?.client ?? client).post({ url: '/foo', ...options }); export const fooPut = (options?: Options) => (options?.client ?? client).put({ url: '/foo', ...options }); -export const getFooBar = (options?: Options) => (options?.client ?? client).get({ url: '/foo/bar', ...options }); +export const fooBarGet = (options?: Options) => (options?.client ?? client).get({ url: '/foo/bar', ...options }); export const fooBarPost = (options?: Options) => (options?.client ?? client).post({ url: '/foo/bar', ...options }); diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-api-key/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-api-key/index.ts index 14b322279..be3520b11 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-api-key/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-api-key/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { getFoo, type Options } from './sdk.gen'; +export { fooGet, type Options } from './sdk.gen'; export type { ClientOptions, GetFooData, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-api-key/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-api-key/sdk.gen.ts index 5bc66f5a1..109acae08 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-api-key/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-api-key/sdk.gen.ts @@ -18,7 +18,7 @@ export type Options; }; -export const getFoo = (options?: Options) => (options?.client ?? client).get({ +export const fooGet = (options?: Options) => (options?.client ?? client).get({ security: [{ in: 'query', name: 'foo', diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-basic/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-basic/index.ts index 14b322279..be3520b11 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-basic/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-basic/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { getFoo, type Options } from './sdk.gen'; +export { fooGet, type Options } from './sdk.gen'; export type { ClientOptions, GetFooData, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-basic/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-basic/sdk.gen.ts index 8a29a51e2..96b60f170 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-basic/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-basic/sdk.gen.ts @@ -18,7 +18,7 @@ export type Options; }; -export const getFoo = (options?: Options) => (options?.client ?? client).get({ +export const fooGet = (options?: Options) => (options?.client ?? client).get({ security: [{ scheme: 'basic', type: 'http' }], url: '/foo', ...options diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-false/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-false/index.ts index 14b322279..be3520b11 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-false/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-false/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { getFoo, type Options } from './sdk.gen'; +export { fooGet, type Options } from './sdk.gen'; export type { ClientOptions, GetFooData, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-false/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-false/sdk.gen.ts index ab8ff3b10..4b61145cf 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-false/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-false/sdk.gen.ts @@ -18,4 +18,4 @@ export type Options; }; -export const getFoo = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); +export const fooGet = (options?: Options) => (options?.client ?? client).get({ url: '/foo', ...options }); diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-oauth2/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-oauth2/index.ts index 14b322279..be3520b11 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-oauth2/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-oauth2/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { getFoo, type Options } from './sdk.gen'; +export { fooGet, type Options } from './sdk.gen'; export type { ClientOptions, GetFooData, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-oauth2/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-oauth2/sdk.gen.ts index 491c86a21..9ae405876 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-oauth2/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/security-oauth2/sdk.gen.ts @@ -18,7 +18,7 @@ export type Options; }; -export const getFoo = (options?: Options) => (options?.client ?? client).get({ +export const fooGet = (options?: Options) => (options?.client ?? client).get({ security: [{ scheme: 'bearer', type: 'http' }], url: '/foo', ...options diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/body-response-text-plain/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/body-response-text-plain/index.ts index de1daea43..cffa17616 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/body-response-text-plain/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/body-response-text-plain/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { type Options, postFoo } from './sdk.gen'; +export { fooPost, type Options } from './sdk.gen'; export type { ClientOptions, PostFooData, PostFooResponse, PostFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/body-response-text-plain/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/body-response-text-plain/sdk.gen.ts index 275283fad..aadd6a1be 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/body-response-text-plain/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/body-response-text-plain/sdk.gen.ts @@ -18,7 +18,7 @@ export type Options; }; -export const postFoo = (options: Options) => (options.client ?? client).post({ +export const fooPost = (options: Options) => (options.client ?? client).post({ bodySerializer: null, url: '/foo', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/content-types/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/content-types/index.ts index b8bd9b308..0fd2c35c2 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/content-types/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/content-types/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { getFoo, type Options } from './sdk.gen'; +export { fooGet, type Options } from './sdk.gen'; export type { ClientOptions, GetFooData, GetFooResponse, GetFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/content-types/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/content-types/sdk.gen.ts index bd418b635..497898597 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/content-types/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/content-types/sdk.gen.ts @@ -18,7 +18,7 @@ export type Options; }; -export const getFoo = (options?: Options) => (options?.client ?? client).get({ +export const fooGet = (options?: Options) => (options?.client ?? client).get({ responseType: 'json', url: '/foo', ...options diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false-axios/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false-axios/index.ts index 878d240fe..b7d647ad4 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false-axios/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false-axios/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { type Options, postFoo } from './sdk.gen'; +export { fooPost, type Options } from './sdk.gen'; export type { ClientOptions, PostFooData, PostFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false-axios/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false-axios/sdk.gen.ts index 11ce35052..7f967b14f 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false-axios/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false-axios/sdk.gen.ts @@ -18,7 +18,7 @@ export type Options; }; -export const postFoo = (options?: Options) => (options?.client ?? client).post({ +export const fooPost = (options?: Options) => (options?.client ?? client).post({ querySerializer: { parameters: { foo: { array: { explode: false } } } }, url: '/foo', ...options diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false/index.ts index 878d240fe..b7d647ad4 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { type Options, postFoo } from './sdk.gen'; +export { fooPost, type Options } from './sdk.gen'; export type { ClientOptions, PostFooData, PostFooResponses } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false/sdk.gen.ts index 11ce35052..7f967b14f 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/parameter-explode-false/sdk.gen.ts @@ -18,7 +18,7 @@ export type Options; }; -export const postFoo = (options?: Options) => (options?.client ?? client).post({ +export const fooPost = (options?: Options) => (options?.client ?? client).post({ querySerializer: { parameters: { foo: { array: { explode: false } } } }, url: '/foo', ...options diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/@angular/common.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/@angular/common.gen.ts index 2cb208158..bd7df901f 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/@angular/common.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/@angular/common.gen.ts @@ -1,62 +1,78 @@ // This file is auto-generated by @hey-api/openapi-ts import { type HttpRequest, httpResource } from '@angular/common/http'; -import { inject, Injectable } from '@angular/core'; +import { Injectable } from '@angular/core'; import { client } from '../client.gen'; import type { Options } from '../sdk.gen'; import type { ApiVVersionODataControllerCountData, ApiVVersionODataControllerCountResponse, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithNoContentResponseResponse, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseData, CallWithResponseResponse, CallWithResponsesData, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexParamsData, ComplexParamsResponse, ComplexTypesData, ComplexTypesResponse, DeleteCallWithoutParametersAndResponseData, DeleteFooData3, DeprecatedCallData, DummyAData, DummyAResponse, DummyBData, DummyBResponse, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, ExportData, FileResponseData, FileResponseResponse, FooWowData, GetApiVbyApiVersionSimpleOperationData, GetApiVbyApiVersionSimpleOperationResponse, GetCallWithOptionalParamData, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, ImportData, ImportResponse, MultipartRequestData, MultipartResponseData, MultipartResponseResponse, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, OptionsCallWithoutParametersAndResponseData, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionFormDataData, PostApiVbyApiVersionRequestBodyData, PostCallWithOptionalParamData, PostCallWithOptionalParamResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, PutWithFormUrlEncodedData, TestErrorCodeData, TypesData, TypesResponse, UploadFileData, UploadFileResponse } from '../types.gen'; -@Injectable({ providedIn: 'root' }) -export class DefaultServiceRequests { - public export(options?: Options): HttpRequest { +export class No_tagRequests { + public static patch(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', - method: 'GET', + method: 'PATCH', url: '/api/v{api-version}/no+tag', ...options }); } - - public patchApiVbyApiVersionNoTag(options?: Options): HttpRequest { +} + +export class SimpleOperationRequests { + public static get(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', - method: 'PATCH', - url: '/api/v{api-version}/no+tag', + method: 'GET', + url: '/api/v{api-version}/simple:operation', ...options }); } +} + +export class VApiVersionRequests { + static 'no+tagRequests' = No_tagRequests; - public import(options: Options): HttpRequest { + static simpleOperationRequests = SimpleOperationRequests; +} + +export class ApiRequests { + static vApiVersionRequests = VApiVersionRequests; +} + +@Injectable({ providedIn: 'root' }) +export class Default { + public static export(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', - method: 'POST', + method: 'GET', url: '/api/v{api-version}/no+tag', ...options }); } - public fooWow(options?: Options): HttpRequest { + public static import(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', - method: 'PUT', + method: 'POST', url: '/api/v{api-version}/no+tag', ...options }); } - public getApiVbyApiVersionSimpleOperation(options: Options): HttpRequest { + public static 'foo+Wow'(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', - method: 'GET', - url: '/api/v{api-version}/simple:operation', + method: 'PUT', + url: '/api/v{api-version}/no+tag', ...options }); } + + static apiRequests = ApiRequests; } -export class ODataControllerServiceRequests { - public apiVVersionODataControllerCount(options?: Options): HttpRequest { +export class ODataControllerRequests { + public static $count(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -66,17 +82,16 @@ export class ODataControllerServiceRequests { } } -export class VVersionServiceRequests { - oDataControllerService = new ODataControllerServiceRequests(); +export class VVersionRequests { + static oDataControllerRequests = ODataControllerRequests; } -export class ApiServiceRequests { - vVersionService = new VVersionServiceRequests(); +export class ApiRequests2 { + static vVersionRequests = VVersionRequests; } -@Injectable({ providedIn: 'root' }) -export class SimpleServiceRequests { - public deleteCallWithoutParametersAndResponse(options?: Options): HttpRequest { +export class Simple { + public static deleteCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'DELETE', @@ -85,7 +100,7 @@ export class SimpleServiceRequests { }); } - public getCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static getCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -94,7 +109,7 @@ export class SimpleServiceRequests { }); } - public headCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static headCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'HEAD', @@ -103,7 +118,7 @@ export class SimpleServiceRequests { }); } - public optionsCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static optionsCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'OPTIONS', @@ -112,7 +127,7 @@ export class SimpleServiceRequests { }); } - public patchCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static patchCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PATCH', @@ -121,7 +136,7 @@ export class SimpleServiceRequests { }); } - public postCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static postCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -130,7 +145,7 @@ export class SimpleServiceRequests { }); } - public putCallWithoutParametersAndResponse(options?: Options): HttpRequest { + public static putCallWithoutParametersAndResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PUT', @@ -138,12 +153,12 @@ export class SimpleServiceRequests { ...options }); } - apiService = new ApiServiceRequests(); + + static apiRequests = ApiRequests2; } -@Injectable({ providedIn: 'root' }) -export class ParametersServiceRequests { - public deleteFoo(options: Options): HttpRequest { +export class Parameters { + public static deleteFoo(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'DELETE', @@ -152,7 +167,7 @@ export class ParametersServiceRequests { }); } - public callWithParameters(options: Options): HttpRequest { + public static callWithParameters(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -161,7 +176,7 @@ export class ParametersServiceRequests { }); } - public callWithWeirdParameterNames(options: Options): HttpRequest { + public static callWithWeirdParameterNames(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -170,7 +185,7 @@ export class ParametersServiceRequests { }); } - public getCallWithOptionalParam(options: Options): HttpRequest { + public static getCallWithOptionalParam(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -179,7 +194,7 @@ export class ParametersServiceRequests { }); } - public postCallWithOptionalParam(options: Options): HttpRequest { + public static postCallWithOptionalParam(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -189,9 +204,8 @@ export class ParametersServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class DescriptionsServiceRequests { - public callWithDescriptions(options?: Options): HttpRequest { +export class Descriptions { + public static callWithDescriptions(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -201,12 +215,11 @@ export class DescriptionsServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class DeprecatedServiceRequests { +export class Deprecated { /** * @deprecated */ - public deprecatedCall(options: Options): HttpRequest { + public static deprecatedCall(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -216,9 +229,8 @@ export class DeprecatedServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class RequestBodyServiceRequests { - public postApiVbyApiVersionRequestBody(options?: Options): HttpRequest { +export class RequestBodyRequests { + public static post(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -228,9 +240,20 @@ export class RequestBodyServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class FormDataServiceRequests { - public postApiVbyApiVersionFormData(options?: Options): HttpRequest { +export class VApiVersionRequests2 { + static requestBodyRequests = RequestBodyRequests; +} + +export class ApiRequests3 { + static vApiVersionRequests = VApiVersionRequests2; +} + +export class RequestBody { + static apiRequests = ApiRequests3; +} + +export class FormDataRequests { + public static post(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -240,9 +263,20 @@ export class FormDataServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class DefaultsServiceRequests { - public callWithDefaultParameters(options?: Options): HttpRequest { +export class VApiVersionRequests3 { + static formDataRequests = FormDataRequests; +} + +export class ApiRequests4 { + static vApiVersionRequests = VApiVersionRequests3; +} + +export class FormData { + static apiRequests = ApiRequests4; +} + +export class Defaults { + public static callWithDefaultParameters(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -251,7 +285,7 @@ export class DefaultsServiceRequests { }); } - public callWithDefaultOptionalParameters(options?: Options): HttpRequest { + public static callWithDefaultOptionalParameters(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -260,7 +294,7 @@ export class DefaultsServiceRequests { }); } - public callToTestOrderOfParams(options: Options): HttpRequest { + public static callToTestOrderOfParams(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PUT', @@ -270,9 +304,8 @@ export class DefaultsServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class DuplicateServiceRequests { - public duplicateName(options?: Options): HttpRequest { +export class Duplicate { + public static duplicateName(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'DELETE', @@ -281,7 +314,7 @@ export class DuplicateServiceRequests { }); } - public duplicateName2(options?: Options): HttpRequest { + public static duplicateName2(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -290,7 +323,7 @@ export class DuplicateServiceRequests { }); } - public duplicateName3(options?: Options): HttpRequest { + public static duplicateName3(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -299,7 +332,7 @@ export class DuplicateServiceRequests { }); } - public duplicateName4(options?: Options): HttpRequest { + public static duplicateName4(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PUT', @@ -309,9 +342,8 @@ export class DuplicateServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class NoContentServiceRequests { - public callWithNoContentResponse(options?: Options): HttpRequest { +export class NoContent { + public static callWithNoContentResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -320,7 +352,7 @@ export class NoContentServiceRequests { }); } - public callWithResponseAndNoContentResponse(options?: Options): HttpRequest { + public static callWithResponseAndNoContentResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -330,9 +362,8 @@ export class NoContentServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class ResponseServiceRequests { - public callWithResponseAndNoContentResponse(options?: Options): HttpRequest { +export class Response { + public static callWithResponseAndNoContentResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -341,7 +372,7 @@ export class ResponseServiceRequests { }); } - public callWithResponse(options?: Options): HttpRequest { + public static callWithResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -350,7 +381,7 @@ export class ResponseServiceRequests { }); } - public callWithDuplicateResponses(options?: Options): HttpRequest { + public static callWithDuplicateResponses(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -359,7 +390,7 @@ export class ResponseServiceRequests { }); } - public callWithResponses(options?: Options): HttpRequest { + public static callWithResponses(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PUT', @@ -369,9 +400,8 @@ export class ResponseServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags1ServiceRequests { - public dummyA(options?: Options): HttpRequest { +export class MultipleTags1 { + public static dummyA(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -380,7 +410,7 @@ export class MultipleTags1ServiceRequests { }); } - public dummyB(options?: Options): HttpRequest { + public static dummyB(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -390,9 +420,8 @@ export class MultipleTags1ServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags2ServiceRequests { - public dummyA(options?: Options): HttpRequest { +export class MultipleTags2 { + public static dummyA(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -401,7 +430,7 @@ export class MultipleTags2ServiceRequests { }); } - public dummyB(options?: Options): HttpRequest { + public static dummyB(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -411,9 +440,8 @@ export class MultipleTags2ServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags3ServiceRequests { - public dummyB(options?: Options): HttpRequest { +export class MultipleTags3 { + public static dummyB(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -423,9 +451,8 @@ export class MultipleTags3ServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class CollectionFormatServiceRequests { - public collectionFormat(options: Options): HttpRequest { +export class CollectionFormat { + public static collectionFormat(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -435,9 +462,8 @@ export class CollectionFormatServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class TypesServiceRequests { - public types(options: Options): HttpRequest { +export class Types { + public static types(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -447,9 +473,8 @@ export class TypesServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class UploadServiceRequests { - public uploadFile(options: Options): HttpRequest { +export class Upload { + public static uploadFile(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -459,9 +484,8 @@ export class UploadServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class FileResponseServiceRequests { - public fileResponse(options: Options): HttpRequest { +export class FileResponse { + public static fileResponse(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -471,9 +495,8 @@ export class FileResponseServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class ComplexServiceRequests { - public complexTypes(options: Options): HttpRequest { +export class Complex { + public static complexTypes(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -482,7 +505,7 @@ export class ComplexServiceRequests { }); } - public complexParams(options: Options): HttpRequest { + public static complexParams(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PUT', @@ -492,9 +515,8 @@ export class ComplexServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class MultipartServiceRequests { - public multipartResponse(options?: Options): HttpRequest { +export class Multipart { + public static multipartResponse(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'GET', @@ -503,7 +525,7 @@ export class MultipartServiceRequests { }); } - public multipartRequest(options?: Options): HttpRequest { + public static multipartRequest(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -513,9 +535,8 @@ export class MultipartServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class HeaderServiceRequests { - public callWithResultFromHeader(options?: Options): HttpRequest { +export class Header { + public static callWithResultFromHeader(options?: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -525,9 +546,8 @@ export class HeaderServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class ErrorServiceRequests { - public testErrorCode(options: Options): HttpRequest { +export class Error_ { + public static testErrorCode(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -537,9 +557,8 @@ export class ErrorServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class NonAsciiÆøåÆøÅöôêÊServiceRequests { - public nonAsciiæøåÆøÅöôêÊ字符串(options: Options): HttpRequest { +export class NonAsciiÆøåÆøÅöôêÊ { + public static nonAsciiæøåÆøÅöôêÊ字符串(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'POST', @@ -551,7 +570,7 @@ export class NonAsciiÆøåÆøÅöôêÊServiceRequests { /** * Login User */ - public putWithFormUrlEncoded(options: Options): HttpRequest { + public static putWithFormUrlEncoded(options: Options): HttpRequest { return (options?.client ?? client).requestOptions({ responseStyle: 'data', method: 'PUT', @@ -561,452 +580,470 @@ export class NonAsciiÆøåÆøÅöôêÊServiceRequests { } } -@Injectable({ providedIn: 'root' }) -export class DefaultServiceResources { - public export(options?: () => Options | undefined) { +export class No_tagResources { + public static patch(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultServiceRequests).export(opts) : undefined; + return opts ? Default.apiRequests.vApiVersionRequests['no+tagRequests'].patch(opts) : undefined; + }); + } +} + +export class SimpleOperationResources { + public static get(options: () => Options | undefined) { + return httpResource(() => { + const opts = options ? options() : undefined; + return opts ? Default.apiRequests.vApiVersionRequests.simpleOperationRequests.get(opts) : undefined; }); } +} + +export class VApiVersionResources { + static 'no+tagResources' = No_tagResources; - public patchApiVbyApiVersionNoTag(options?: () => Options | undefined) { + static simpleOperationResources = SimpleOperationResources; +} + +export class ApiResources { + static vApiVersionResources = VApiVersionResources; +} + +export class Default2 { + public static export(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultServiceRequests).patchApiVbyApiVersionNoTag(opts) : undefined; + return opts ? Default.export(opts) : undefined; }); } - public import(options: () => Options | undefined) { + public static import(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultServiceRequests).import(opts) : undefined; + return opts ? Default.import(opts) : undefined; }); } - public fooWow(options?: () => Options | undefined) { + public static 'foo+Wow'(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultServiceRequests).fooWow(opts) : undefined; + return opts ? Default['foo+Wow'](opts) : undefined; }); } - public getApiVbyApiVersionSimpleOperation(options: () => Options | undefined) { - return httpResource(() => { - const opts = options ? options() : undefined; - return opts ? inject(DefaultServiceRequests).getApiVbyApiVersionSimpleOperation(opts) : undefined; - }); - } + static apiResources = ApiResources; } -export class ODataControllerServiceResources { - public apiVVersionODataControllerCount(options?: () => Options | undefined) { +export class ODataControllerResources { + public static $count(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).apiService.vVersionService.oDataControllerService.apiVVersionODataControllerCount(opts) : undefined; + return opts ? Simple.apiRequests.vVersionRequests.oDataControllerRequests.$count(opts) : undefined; }); } } -export class VVersionServiceResources { - oDataControllerService = new ODataControllerServiceResources(); +export class VVersionResources { + static oDataControllerResources = ODataControllerResources; } -export class ApiServiceResources { - vVersionService = new VVersionServiceResources(); +export class ApiResources2 { + static vVersionResources = VVersionResources; } -@Injectable({ providedIn: 'root' }) -export class SimpleServiceResources { - public deleteCallWithoutParametersAndResponse(options?: () => Options | undefined) { +export class Simple2 { + public static deleteCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).deleteCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.deleteCallWithoutParametersAndResponse(opts) : undefined; }); } - public getCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static getCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).getCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.getCallWithoutParametersAndResponse(opts) : undefined; }); } - public headCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static headCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).headCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.headCallWithoutParametersAndResponse(opts) : undefined; }); } - public optionsCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static optionsCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).optionsCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.optionsCallWithoutParametersAndResponse(opts) : undefined; }); } - public patchCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static patchCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).patchCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.patchCallWithoutParametersAndResponse(opts) : undefined; }); } - public postCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static postCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).postCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.postCallWithoutParametersAndResponse(opts) : undefined; }); } - public putCallWithoutParametersAndResponse(options?: () => Options | undefined) { + public static putCallWithoutParametersAndResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(SimpleServiceRequests).putCallWithoutParametersAndResponse(opts) : undefined; + return opts ? Simple.putCallWithoutParametersAndResponse(opts) : undefined; }); } - apiService = new ApiServiceResources(); + + static apiResources = ApiResources2; } -@Injectable({ providedIn: 'root' }) -export class ParametersServiceResources { - public deleteFoo(options: () => Options | undefined) { +export class Parameters2 { + public static deleteFoo(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ParametersServiceRequests).deleteFoo(opts) : undefined; + return opts ? Parameters.deleteFoo(opts) : undefined; }); } - public callWithParameters(options: () => Options | undefined) { + public static callWithParameters(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ParametersServiceRequests).callWithParameters(opts) : undefined; + return opts ? Parameters.callWithParameters(opts) : undefined; }); } - public callWithWeirdParameterNames(options: () => Options | undefined) { + public static callWithWeirdParameterNames(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ParametersServiceRequests).callWithWeirdParameterNames(opts) : undefined; + return opts ? Parameters.callWithWeirdParameterNames(opts) : undefined; }); } - public getCallWithOptionalParam(options: () => Options | undefined) { + public static getCallWithOptionalParam(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ParametersServiceRequests).getCallWithOptionalParam(opts) : undefined; + return opts ? Parameters.getCallWithOptionalParam(opts) : undefined; }); } - public postCallWithOptionalParam(options: () => Options | undefined) { + public static postCallWithOptionalParam(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ParametersServiceRequests).postCallWithOptionalParam(opts) : undefined; + return opts ? Parameters.postCallWithOptionalParam(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class DescriptionsServiceResources { - public callWithDescriptions(options?: () => Options | undefined) { +export class Descriptions2 { + public static callWithDescriptions(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DescriptionsServiceRequests).callWithDescriptions(opts) : undefined; + return opts ? Descriptions.callWithDescriptions(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class DeprecatedServiceResources { +export class Deprecated2 { /** * @deprecated */ - public deprecatedCall(options: () => Options | undefined) { + public static deprecatedCall(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DeprecatedServiceRequests).deprecatedCall(opts) : undefined; + return opts ? Deprecated.deprecatedCall(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class RequestBodyServiceResources { - public postApiVbyApiVersionRequestBody(options?: () => Options | undefined) { +export class RequestBodyResources { + public static post(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(RequestBodyServiceRequests).postApiVbyApiVersionRequestBody(opts) : undefined; + return opts ? RequestBody.apiRequests.vApiVersionRequests.requestBodyRequests.post(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class FormDataServiceResources { - public postApiVbyApiVersionFormData(options?: () => Options | undefined) { +export class VApiVersionResources2 { + static requestBodyResources = RequestBodyResources; +} + +export class ApiResources3 { + static vApiVersionResources = VApiVersionResources2; +} + +export class RequestBody2 { + static apiResources = ApiResources3; +} + +export class FormDataResources { + public static post(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(FormDataServiceRequests).postApiVbyApiVersionFormData(opts) : undefined; + return opts ? FormData.apiRequests.vApiVersionRequests.formDataRequests.post(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class DefaultsServiceResources { - public callWithDefaultParameters(options?: () => Options | undefined) { +export class VApiVersionResources3 { + static formDataResources = FormDataResources; +} + +export class ApiResources4 { + static vApiVersionResources = VApiVersionResources3; +} + +export class FormData2 { + static apiResources = ApiResources4; +} + +export class Defaults2 { + public static callWithDefaultParameters(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultsServiceRequests).callWithDefaultParameters(opts) : undefined; + return opts ? Defaults.callWithDefaultParameters(opts) : undefined; }); } - public callWithDefaultOptionalParameters(options?: () => Options | undefined) { + public static callWithDefaultOptionalParameters(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultsServiceRequests).callWithDefaultOptionalParameters(opts) : undefined; + return opts ? Defaults.callWithDefaultOptionalParameters(opts) : undefined; }); } - public callToTestOrderOfParams(options: () => Options | undefined) { + public static callToTestOrderOfParams(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DefaultsServiceRequests).callToTestOrderOfParams(opts) : undefined; + return opts ? Defaults.callToTestOrderOfParams(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class DuplicateServiceResources { - public duplicateName(options?: () => Options | undefined) { +export class Duplicate2 { + public static duplicateName(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DuplicateServiceRequests).duplicateName(opts) : undefined; + return opts ? Duplicate.duplicateName(opts) : undefined; }); } - public duplicateName2(options?: () => Options | undefined) { + public static duplicateName2(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DuplicateServiceRequests).duplicateName2(opts) : undefined; + return opts ? Duplicate.duplicateName2(opts) : undefined; }); } - public duplicateName3(options?: () => Options | undefined) { + public static duplicateName3(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DuplicateServiceRequests).duplicateName3(opts) : undefined; + return opts ? Duplicate.duplicateName3(opts) : undefined; }); } - public duplicateName4(options?: () => Options | undefined) { + public static duplicateName4(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(DuplicateServiceRequests).duplicateName4(opts) : undefined; + return opts ? Duplicate.duplicateName4(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class NoContentServiceResources { - public callWithNoContentResponse(options?: () => Options | undefined) { +export class NoContent2 { + public static callWithNoContentResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(NoContentServiceRequests).callWithNoContentResponse(opts) : undefined; + return opts ? NoContent.callWithNoContentResponse(opts) : undefined; }); } - public callWithResponseAndNoContentResponse(options?: () => Options | undefined) { + public static callWithResponseAndNoContentResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ResponseServiceRequests).callWithResponseAndNoContentResponse(opts) : undefined; + return opts ? NoContent.callWithResponseAndNoContentResponse(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class ResponseServiceResources { - public callWithResponseAndNoContentResponse(options?: () => Options | undefined) { +export class Response2 { + public static callWithResponseAndNoContentResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ResponseServiceRequests).callWithResponseAndNoContentResponse(opts) : undefined; + return opts ? NoContent.callWithResponseAndNoContentResponse(opts) : undefined; }); } - public callWithResponse(options?: () => Options | undefined) { + public static callWithResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ResponseServiceRequests).callWithResponse(opts) : undefined; + return opts ? Response.callWithResponse(opts) : undefined; }); } - public callWithDuplicateResponses(options?: () => Options | undefined) { + public static callWithDuplicateResponses(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ResponseServiceRequests).callWithDuplicateResponses(opts) : undefined; + return opts ? Response.callWithDuplicateResponses(opts) : undefined; }); } - public callWithResponses(options?: () => Options | undefined) { + public static callWithResponses(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ResponseServiceRequests).callWithResponses(opts) : undefined; + return opts ? Response.callWithResponses(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags1ServiceResources { - public dummyA(options?: () => Options | undefined) { +export class MultipleTags12 { + public static dummyA(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipleTags1ServiceRequests).dummyA(opts) : undefined; + return opts ? MultipleTags1.dummyA(opts) : undefined; }); } - public dummyB(options?: () => Options | undefined) { + public static dummyB(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipleTags1ServiceRequests).dummyB(opts) : undefined; + return opts ? MultipleTags1.dummyB(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags2ServiceResources { - public dummyA(options?: () => Options | undefined) { +export class MultipleTags22 { + public static dummyA(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipleTags1ServiceRequests).dummyA(opts) : undefined; + return opts ? MultipleTags1.dummyA(opts) : undefined; }); } - public dummyB(options?: () => Options | undefined) { + public static dummyB(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipleTags1ServiceRequests).dummyB(opts) : undefined; + return opts ? MultipleTags1.dummyB(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class MultipleTags3ServiceResources { - public dummyB(options?: () => Options | undefined) { +export class MultipleTags32 { + public static dummyB(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipleTags1ServiceRequests).dummyB(opts) : undefined; + return opts ? MultipleTags1.dummyB(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class CollectionFormatServiceResources { - public collectionFormat(options: () => Options | undefined) { +export class CollectionFormat2 { + public static collectionFormat(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(CollectionFormatServiceRequests).collectionFormat(opts) : undefined; + return opts ? CollectionFormat.collectionFormat(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class TypesServiceResources { - public types(options: () => Options | undefined) { +export class Types2 { + public static types(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(TypesServiceRequests).types(opts) : undefined; + return opts ? Types.types(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class UploadServiceResources { - public uploadFile(options: () => Options | undefined) { +export class Upload2 { + public static uploadFile(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(UploadServiceRequests).uploadFile(opts) : undefined; + return opts ? Upload.uploadFile(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class FileResponseServiceResources { - public fileResponse(options: () => Options | undefined) { +export class FileResponse2 { + public static fileResponse(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(FileResponseServiceRequests).fileResponse(opts) : undefined; + return opts ? FileResponse.fileResponse(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class ComplexServiceResources { - public complexTypes(options: () => Options | undefined) { +export class Complex2 { + public static complexTypes(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ComplexServiceRequests).complexTypes(opts) : undefined; + return opts ? Complex.complexTypes(opts) : undefined; }); } - public complexParams(options: () => Options | undefined) { + public static complexParams(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ComplexServiceRequests).complexParams(opts) : undefined; + return opts ? Complex.complexParams(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class MultipartServiceResources { - public multipartResponse(options?: () => Options | undefined) { +export class Multipart2 { + public static multipartResponse(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipartServiceRequests).multipartResponse(opts) : undefined; + return opts ? Multipart.multipartResponse(opts) : undefined; }); } - public multipartRequest(options?: () => Options | undefined) { + public static multipartRequest(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(MultipartServiceRequests).multipartRequest(opts) : undefined; + return opts ? Multipart.multipartRequest(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class HeaderServiceResources { - public callWithResultFromHeader(options?: () => Options | undefined) { +export class Header2 { + public static callWithResultFromHeader(options?: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(HeaderServiceRequests).callWithResultFromHeader(opts) : undefined; + return opts ? Header.callWithResultFromHeader(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class ErrorServiceResources { - public testErrorCode(options: () => Options | undefined) { +export class Error2 { + public static testErrorCode(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(ErrorServiceRequests).testErrorCode(opts) : undefined; + return opts ? Error_.testErrorCode(opts) : undefined; }); } } -@Injectable({ providedIn: 'root' }) -export class NonAsciiÆøåÆøÅöôêÊServiceResources { - public nonAsciiæøåÆøÅöôêÊ字符串(options: () => Options | undefined) { +export class NonAsciiÆøåÆøÅöôêÊ2 { + public static nonAsciiæøåÆøÅöôêÊ字符串(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(NonAsciiÆøåÆøÅöôêÊServiceRequests).nonAsciiæøåÆøÅöôêÊ字符串(opts) : undefined; + return opts ? NonAsciiÆøåÆøÅöôêÊ.nonAsciiæøåÆøÅöôêÊ字符串(opts) : undefined; }); } /** * Login User */ - public putWithFormUrlEncoded(options: () => Options | undefined) { + public static putWithFormUrlEncoded(options: () => Options | undefined) { return httpResource(() => { const opts = options ? options() : undefined; - return opts ? inject(NonAsciiÆøåÆøÅöôêÊServiceRequests).putWithFormUrlEncoded(opts) : undefined; + return opts ? NonAsciiÆøåÆøÅöôêÊ.putWithFormUrlEncoded(opts) : undefined; }); } } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/index.ts index 62e4bbff0..ae3813b44 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { apiVVersionODataControllerCount, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexParams, complexTypes, deleteCallWithoutParametersAndResponse, deleteFoo, deprecatedCall, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, export_, fileResponse, fooWow, getApiVbyApiVersionSimpleOperation, getCallWithOptionalParam, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, import_, multipartRequest, multipartResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionFormData, postApiVbyApiVersionRequestBody, postCallWithOptionalParam, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, putWithFormUrlEncoded, testErrorCode, types, uploadFile } from './sdk.gen'; +export { apiVApiVersionFormDataPost, apiVApiVersionNo_tagPatch, apiVApiVersionRequestBodyPost, apiVApiVersionSimpleOperationGet, apiVVersionODataController__count, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexParams, complexTypes, deleteCallWithoutParametersAndResponse, deleteFoo, deprecatedCall, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, export_, fileResponse, foo_Wow, getCallWithOptionalParam, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, import_, multipartRequest, multipartResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithOptionalParam, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, putWithFormUrlEncoded, testErrorCode, types, uploadFile } from './sdk.gen'; export type { _3eNum1Период, _400, AdditionalPropertiesIntegerIssue, AdditionalPropertiesUnknownIssue, AdditionalPropertiesUnknownIssue2, AdditionalPropertiesUnknownIssue3, AdditionalPropertiesUnknownIssueWritable, AnyOfAnyAndNull, AnyOfArrays, ApiVVersionODataControllerCountData, ApiVVersionODataControllerCountResponse, ApiVVersionODataControllerCountResponses, ArrayWithAnyOfProperties, ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponse, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, CamelCaseCommentWithBreaks, CharactersInDescription, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexParamsData, ComplexParamsResponse, ComplexParamsResponses, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, CompositionBaseModel, CompositionExtendedModel, CompositionWithAllOfAndNullable, CompositionWithAnyOf, CompositionWithAnyOfAndNullable, CompositionWithAnyOfAnonymous, CompositionWithNestedAnyAndTypeNull, CompositionWithNestedAnyOfAndNull, CompositionWithOneOf, CompositionWithOneOfAndComplexArrayDictionary, CompositionWithOneOfAndNullable, CompositionWithOneOfAndProperties, CompositionWithOneOfAndSimpleArrayDictionary, CompositionWithOneOfAndSimpleDictionary, CompositionWithOneOfAnonymous, CompositionWithOneOfDiscriminator, ConstValue, Default, DeleteCallWithoutParametersAndResponseData, DeleteFooData, DeleteFooData2, DeleteFooData3, DeprecatedCallData, DeprecatedModel, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithPropertiesAndAdditionalProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponse, DummyAResponses, DummyBData, DummyBResponse, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithReplacedCharacters, EnumWithStrings, EnumWithXEnumNames, ExportData, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, File, FileResponseData, FileResponseResponse, FileResponseResponses, FileWritable, FooWowData, FooWowResponses, FreeFormObjectWithAdditionalPropertiesEqEmptyObject, FreeFormObjectWithAdditionalPropertiesEqTrue, FreeFormObjectWithoutAdditionalProperties, GenericSchemaDuplicateIssue1SystemBoolean, GenericSchemaDuplicateIssue1SystemBooleanWritable, GenericSchemaDuplicateIssue1SystemString, GenericSchemaDuplicateIssue1SystemStringWritable, GetApiVbyApiVersionSimpleOperationData, GetApiVbyApiVersionSimpleOperationError, GetApiVbyApiVersionSimpleOperationErrors, GetApiVbyApiVersionSimpleOperationResponse, GetApiVbyApiVersionSimpleOperationResponses, GetCallWithOptionalParamData, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, Import, ImportData, ImportResponse, ImportResponses, IoK8sApimachineryPkgApisMetaV1DeleteOptions, IoK8sApimachineryPkgApisMetaV1Preconditions, ModelCircle, ModelFromZendesk, ModelSquare, ModelThatExtends, ModelThatExtendsExtends, ModelWithAdditionalPropertiesEqTrue, ModelWithAnyOfConstantSizeArray, ModelWithAnyOfConstantSizeArrayAndIntersect, ModelWithAnyOfConstantSizeArrayNullable, ModelWithAnyOfConstantSizeArrayWithNSizeAndOptions, ModelWithAnyOfConstantSizeArrayWithNSizeAndOptionsWritable, ModelWithArray, ModelWithArrayReadOnlyAndWriteOnly, ModelWithArrayReadOnlyAndWriteOnlyWritable, ModelWithBackticksInDescription, ModelWithBoolean, ModelWithCircularReference, ModelWithConst, ModelWithConstantSizeArray, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithEnumWithHyphen, ModelWithInteger, ModelWithNestedArrayEnums, ModelWithNestedArrayEnumsData, ModelWithNestedArrayEnumsDataBar, ModelWithNestedArrayEnumsDataFoo, ModelWithNestedCompositionEnums, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableObject, ModelWithNullableString, ModelWithNumericEnumUnion, ModelWithOneOfAndProperties, ModelWithOneOfEnum, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithPrefixItemsConstantSizeArray, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReadOnlyAndWriteOnly, ModelWithReadOnlyAndWriteOnlyWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, MultipartRequestData, MultipartResponseData, MultipartResponseResponse, MultipartResponseResponses, NestedAnyOfArraysNullable, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, NullableObject, OneOfAllOfIssue, OneOfAllOfIssueWritable, OptionsCallWithoutParametersAndResponseData, Pageable, ParameterSimpleParameterUnused, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionFormDataData, PostApiVbyApiVersionRequestBodyData, PostCallWithOptionalParamData, PostCallWithOptionalParamResponse, PostCallWithOptionalParamResponses, PostCallWithoutParametersAndResponseData, PostServiceWithEmptyTagResponse, PostServiceWithEmptyTagResponse2, PutCallWithoutParametersAndResponseData, PutWithFormUrlEncodedData, SchemaWithFormRestrictedKeys, SimpleBoolean, SimpleFile, SimpleFormData, SimpleInteger, SimpleParameter, SimpleReference, SimpleRequestBody, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses, UploadFileData, UploadFileResponse, UploadFileResponses, XFooBar } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/sdk.gen.ts index e48dcff8c..277bf8ef3 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default-class/sdk.gen.ts @@ -20,7 +20,7 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); export const import_ = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/no+tag', @@ -31,11 +31,11 @@ export const import_ = (options: Options(options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); -export const apiVVersionODataControllerCount = (options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/simple/$count', ...options }); +export const apiVVersionODataController__count = (options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/simple/$count', ...options }); -export const getApiVbyApiVersionSimpleOperation = (options: Options) => (options.client ?? client).get({ url: '/api/v{api-version}/simple:operation', ...options }); +export const apiVApiVersionSimpleOperationGet = (options: Options) => (options.client ?? client).get({ url: '/api/v{api-version}/simple:operation', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -96,7 +96,7 @@ export const postCallWithOptionalParam = ( } }); -export const postApiVbyApiVersionRequestBody = (options?: Options) => (options?.client ?? client).post({ +export const apiVApiVersionRequestBodyPost = (options?: Options) => (options?.client ?? client).post({ url: '/api/v{api-version}/requestBody', ...options, headers: { @@ -105,7 +105,7 @@ export const postApiVbyApiVersionRequestBody = (options?: Options) => (options?.client ?? client).post({ +export const apiVApiVersionFormDataPost = (options?: Options) => (options?.client ?? client).post({ ...formDataBodySerializer, url: '/api/v{api-version}/formData', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default/index.ts index 62e4bbff0..ae3813b44 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { apiVVersionODataControllerCount, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexParams, complexTypes, deleteCallWithoutParametersAndResponse, deleteFoo, deprecatedCall, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, export_, fileResponse, fooWow, getApiVbyApiVersionSimpleOperation, getCallWithOptionalParam, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, import_, multipartRequest, multipartResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionFormData, postApiVbyApiVersionRequestBody, postCallWithOptionalParam, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, putWithFormUrlEncoded, testErrorCode, types, uploadFile } from './sdk.gen'; +export { apiVApiVersionFormDataPost, apiVApiVersionNo_tagPatch, apiVApiVersionRequestBodyPost, apiVApiVersionSimpleOperationGet, apiVVersionODataController__count, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexParams, complexTypes, deleteCallWithoutParametersAndResponse, deleteFoo, deprecatedCall, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, export_, fileResponse, foo_Wow, getCallWithOptionalParam, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, import_, multipartRequest, multipartResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithOptionalParam, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, putWithFormUrlEncoded, testErrorCode, types, uploadFile } from './sdk.gen'; export type { _3eNum1Период, _400, AdditionalPropertiesIntegerIssue, AdditionalPropertiesUnknownIssue, AdditionalPropertiesUnknownIssue2, AdditionalPropertiesUnknownIssue3, AdditionalPropertiesUnknownIssueWritable, AnyOfAnyAndNull, AnyOfArrays, ApiVVersionODataControllerCountData, ApiVVersionODataControllerCountResponse, ApiVVersionODataControllerCountResponses, ArrayWithAnyOfProperties, ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponse, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, CamelCaseCommentWithBreaks, CharactersInDescription, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexParamsData, ComplexParamsResponse, ComplexParamsResponses, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, CompositionBaseModel, CompositionExtendedModel, CompositionWithAllOfAndNullable, CompositionWithAnyOf, CompositionWithAnyOfAndNullable, CompositionWithAnyOfAnonymous, CompositionWithNestedAnyAndTypeNull, CompositionWithNestedAnyOfAndNull, CompositionWithOneOf, CompositionWithOneOfAndComplexArrayDictionary, CompositionWithOneOfAndNullable, CompositionWithOneOfAndProperties, CompositionWithOneOfAndSimpleArrayDictionary, CompositionWithOneOfAndSimpleDictionary, CompositionWithOneOfAnonymous, CompositionWithOneOfDiscriminator, ConstValue, Default, DeleteCallWithoutParametersAndResponseData, DeleteFooData, DeleteFooData2, DeleteFooData3, DeprecatedCallData, DeprecatedModel, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithPropertiesAndAdditionalProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponse, DummyAResponses, DummyBData, DummyBResponse, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithReplacedCharacters, EnumWithStrings, EnumWithXEnumNames, ExportData, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, File, FileResponseData, FileResponseResponse, FileResponseResponses, FileWritable, FooWowData, FooWowResponses, FreeFormObjectWithAdditionalPropertiesEqEmptyObject, FreeFormObjectWithAdditionalPropertiesEqTrue, FreeFormObjectWithoutAdditionalProperties, GenericSchemaDuplicateIssue1SystemBoolean, GenericSchemaDuplicateIssue1SystemBooleanWritable, GenericSchemaDuplicateIssue1SystemString, GenericSchemaDuplicateIssue1SystemStringWritable, GetApiVbyApiVersionSimpleOperationData, GetApiVbyApiVersionSimpleOperationError, GetApiVbyApiVersionSimpleOperationErrors, GetApiVbyApiVersionSimpleOperationResponse, GetApiVbyApiVersionSimpleOperationResponses, GetCallWithOptionalParamData, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, Import, ImportData, ImportResponse, ImportResponses, IoK8sApimachineryPkgApisMetaV1DeleteOptions, IoK8sApimachineryPkgApisMetaV1Preconditions, ModelCircle, ModelFromZendesk, ModelSquare, ModelThatExtends, ModelThatExtendsExtends, ModelWithAdditionalPropertiesEqTrue, ModelWithAnyOfConstantSizeArray, ModelWithAnyOfConstantSizeArrayAndIntersect, ModelWithAnyOfConstantSizeArrayNullable, ModelWithAnyOfConstantSizeArrayWithNSizeAndOptions, ModelWithAnyOfConstantSizeArrayWithNSizeAndOptionsWritable, ModelWithArray, ModelWithArrayReadOnlyAndWriteOnly, ModelWithArrayReadOnlyAndWriteOnlyWritable, ModelWithBackticksInDescription, ModelWithBoolean, ModelWithCircularReference, ModelWithConst, ModelWithConstantSizeArray, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithEnumWithHyphen, ModelWithInteger, ModelWithNestedArrayEnums, ModelWithNestedArrayEnumsData, ModelWithNestedArrayEnumsDataBar, ModelWithNestedArrayEnumsDataFoo, ModelWithNestedCompositionEnums, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableObject, ModelWithNullableString, ModelWithNumericEnumUnion, ModelWithOneOfAndProperties, ModelWithOneOfEnum, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithPrefixItemsConstantSizeArray, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReadOnlyAndWriteOnly, ModelWithReadOnlyAndWriteOnlyWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, MultipartRequestData, MultipartResponseData, MultipartResponseResponse, MultipartResponseResponses, NestedAnyOfArraysNullable, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, NullableObject, OneOfAllOfIssue, OneOfAllOfIssueWritable, OptionsCallWithoutParametersAndResponseData, Pageable, ParameterSimpleParameterUnused, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionFormDataData, PostApiVbyApiVersionRequestBodyData, PostCallWithOptionalParamData, PostCallWithOptionalParamResponse, PostCallWithOptionalParamResponses, PostCallWithoutParametersAndResponseData, PostServiceWithEmptyTagResponse, PostServiceWithEmptyTagResponse2, PutCallWithoutParametersAndResponseData, PutWithFormUrlEncodedData, SchemaWithFormRestrictedKeys, SimpleBoolean, SimpleFile, SimpleFormData, SimpleInteger, SimpleParameter, SimpleReference, SimpleRequestBody, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses, UploadFileData, UploadFileResponse, UploadFileResponses, XFooBar } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default/sdk.gen.ts index e48dcff8c..277bf8ef3 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@angular/common/default/sdk.gen.ts @@ -20,7 +20,7 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); export const import_ = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/no+tag', @@ -31,11 +31,11 @@ export const import_ = (options: Options(options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); -export const apiVVersionODataControllerCount = (options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/simple/$count', ...options }); +export const apiVVersionODataController__count = (options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/simple/$count', ...options }); -export const getApiVbyApiVersionSimpleOperation = (options: Options) => (options.client ?? client).get({ url: '/api/v{api-version}/simple:operation', ...options }); +export const apiVApiVersionSimpleOperationGet = (options: Options) => (options.client ?? client).get({ url: '/api/v{api-version}/simple:operation', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -96,7 +96,7 @@ export const postCallWithOptionalParam = ( } }); -export const postApiVbyApiVersionRequestBody = (options?: Options) => (options?.client ?? client).post({ +export const apiVApiVersionRequestBodyPost = (options?: Options) => (options?.client ?? client).post({ url: '/api/v{api-version}/requestBody', ...options, headers: { @@ -105,7 +105,7 @@ export const postApiVbyApiVersionRequestBody = (options?: Options) => (options?.client ?? client).post({ +export const apiVApiVersionFormDataPost = (options?: Options) => (options?.client ?? client).post({ ...formDataBodySerializer, url: '/api/v{api-version}/formData', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes-instance/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes-instance/sdk.gen.ts index fafb8ed66..a1beb0a63 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes-instance/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes-instance/sdk.gen.ts @@ -54,6 +54,10 @@ export class Domains extends HeyApiClient { public post(options?: Options) { return (options?.client ?? this.client).post({ url: '/business/providers/domains', ...options }); } + + public put(options?: Options) { + return (options?.client ?? this.client).put({ url: '/business/providers/domains', ...options }); + } } export class Providers extends HeyApiClient { @@ -85,10 +89,6 @@ export class NestedSdkWithInstance extends HeyApiClient { NestedSdkWithInstance.__registry.set(this, args?.key); } - public putBusinessProvidersDomains(options?: Options) { - return (options?.client ?? this.client).put({ url: '/business/providers/domains', ...options }); - } - public get(options?: Options) { return (options?.client ?? this.client).get({ url: '/locations', ...options }); } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts index babd05bc9..505a12a57 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/client-fetch/sdk-nested-classes/sdk.gen.ts @@ -74,6 +74,10 @@ export class Domains3 { public static post(options?: Options) { return (options?.client ?? client).post({ url: '/business/providers/domains', ...options }); } + + public static put(options?: Options) { + return (options?.client ?? client).put({ url: '/business/providers/domains', ...options }); + } } export class Providers4 { @@ -85,10 +89,6 @@ export class Business4 { } export class Domains4 { - public static putBusinessProvidersDomains(options?: Options) { - return (options?.client ?? client).put({ url: '/business/providers/domains', ...options }); - } - static business = Business4; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/default/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/default/index.ts index 62e4bbff0..ae3813b44 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/default/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/default/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { apiVVersionODataControllerCount, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexParams, complexTypes, deleteCallWithoutParametersAndResponse, deleteFoo, deprecatedCall, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, export_, fileResponse, fooWow, getApiVbyApiVersionSimpleOperation, getCallWithOptionalParam, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, import_, multipartRequest, multipartResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionFormData, postApiVbyApiVersionRequestBody, postCallWithOptionalParam, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, putWithFormUrlEncoded, testErrorCode, types, uploadFile } from './sdk.gen'; +export { apiVApiVersionFormDataPost, apiVApiVersionNo_tagPatch, apiVApiVersionRequestBodyPost, apiVApiVersionSimpleOperationGet, apiVVersionODataController__count, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexParams, complexTypes, deleteCallWithoutParametersAndResponse, deleteFoo, deprecatedCall, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, export_, fileResponse, foo_Wow, getCallWithOptionalParam, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, import_, multipartRequest, multipartResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithOptionalParam, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, putWithFormUrlEncoded, testErrorCode, types, uploadFile } from './sdk.gen'; export type { _3eNum1Период, _400, AdditionalPropertiesIntegerIssue, AdditionalPropertiesUnknownIssue, AdditionalPropertiesUnknownIssue2, AdditionalPropertiesUnknownIssue3, AdditionalPropertiesUnknownIssueWritable, AnyOfAnyAndNull, AnyOfArrays, ApiVVersionODataControllerCountData, ApiVVersionODataControllerCountResponse, ApiVVersionODataControllerCountResponses, ArrayWithAnyOfProperties, ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponse, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, CamelCaseCommentWithBreaks, CharactersInDescription, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexParamsData, ComplexParamsResponse, ComplexParamsResponses, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, CompositionBaseModel, CompositionExtendedModel, CompositionWithAllOfAndNullable, CompositionWithAnyOf, CompositionWithAnyOfAndNullable, CompositionWithAnyOfAnonymous, CompositionWithNestedAnyAndTypeNull, CompositionWithNestedAnyOfAndNull, CompositionWithOneOf, CompositionWithOneOfAndComplexArrayDictionary, CompositionWithOneOfAndNullable, CompositionWithOneOfAndProperties, CompositionWithOneOfAndSimpleArrayDictionary, CompositionWithOneOfAndSimpleDictionary, CompositionWithOneOfAnonymous, CompositionWithOneOfDiscriminator, ConstValue, Default, DeleteCallWithoutParametersAndResponseData, DeleteFooData, DeleteFooData2, DeleteFooData3, DeprecatedCallData, DeprecatedModel, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithPropertiesAndAdditionalProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponse, DummyAResponses, DummyBData, DummyBResponse, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithReplacedCharacters, EnumWithStrings, EnumWithXEnumNames, ExportData, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, File, FileResponseData, FileResponseResponse, FileResponseResponses, FileWritable, FooWowData, FooWowResponses, FreeFormObjectWithAdditionalPropertiesEqEmptyObject, FreeFormObjectWithAdditionalPropertiesEqTrue, FreeFormObjectWithoutAdditionalProperties, GenericSchemaDuplicateIssue1SystemBoolean, GenericSchemaDuplicateIssue1SystemBooleanWritable, GenericSchemaDuplicateIssue1SystemString, GenericSchemaDuplicateIssue1SystemStringWritable, GetApiVbyApiVersionSimpleOperationData, GetApiVbyApiVersionSimpleOperationError, GetApiVbyApiVersionSimpleOperationErrors, GetApiVbyApiVersionSimpleOperationResponse, GetApiVbyApiVersionSimpleOperationResponses, GetCallWithOptionalParamData, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, Import, ImportData, ImportResponse, ImportResponses, IoK8sApimachineryPkgApisMetaV1DeleteOptions, IoK8sApimachineryPkgApisMetaV1Preconditions, ModelCircle, ModelFromZendesk, ModelSquare, ModelThatExtends, ModelThatExtendsExtends, ModelWithAdditionalPropertiesEqTrue, ModelWithAnyOfConstantSizeArray, ModelWithAnyOfConstantSizeArrayAndIntersect, ModelWithAnyOfConstantSizeArrayNullable, ModelWithAnyOfConstantSizeArrayWithNSizeAndOptions, ModelWithAnyOfConstantSizeArrayWithNSizeAndOptionsWritable, ModelWithArray, ModelWithArrayReadOnlyAndWriteOnly, ModelWithArrayReadOnlyAndWriteOnlyWritable, ModelWithBackticksInDescription, ModelWithBoolean, ModelWithCircularReference, ModelWithConst, ModelWithConstantSizeArray, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithEnumWithHyphen, ModelWithInteger, ModelWithNestedArrayEnums, ModelWithNestedArrayEnumsData, ModelWithNestedArrayEnumsDataBar, ModelWithNestedArrayEnumsDataFoo, ModelWithNestedCompositionEnums, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableObject, ModelWithNullableString, ModelWithNumericEnumUnion, ModelWithOneOfAndProperties, ModelWithOneOfEnum, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithPrefixItemsConstantSizeArray, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReadOnlyAndWriteOnly, ModelWithReadOnlyAndWriteOnlyWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, MultipartRequestData, MultipartResponseData, MultipartResponseResponse, MultipartResponseResponses, NestedAnyOfArraysNullable, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, NullableObject, OneOfAllOfIssue, OneOfAllOfIssueWritable, OptionsCallWithoutParametersAndResponseData, Pageable, ParameterSimpleParameterUnused, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionFormDataData, PostApiVbyApiVersionRequestBodyData, PostCallWithOptionalParamData, PostCallWithOptionalParamResponse, PostCallWithOptionalParamResponses, PostCallWithoutParametersAndResponseData, PostServiceWithEmptyTagResponse, PostServiceWithEmptyTagResponse2, PutCallWithoutParametersAndResponseData, PutWithFormUrlEncodedData, SchemaWithFormRestrictedKeys, SimpleBoolean, SimpleFile, SimpleFormData, SimpleInteger, SimpleParameter, SimpleReference, SimpleRequestBody, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses, UploadFileData, UploadFileResponse, UploadFileResponses, XFooBar } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/default/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/default/sdk.gen.ts index e48dcff8c..277bf8ef3 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/default/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/default/sdk.gen.ts @@ -20,7 +20,7 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); export const import_ = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/no+tag', @@ -31,11 +31,11 @@ export const import_ = (options: Options(options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); -export const apiVVersionODataControllerCount = (options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/simple/$count', ...options }); +export const apiVVersionODataController__count = (options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/simple/$count', ...options }); -export const getApiVbyApiVersionSimpleOperation = (options: Options) => (options.client ?? client).get({ url: '/api/v{api-version}/simple:operation', ...options }); +export const apiVApiVersionSimpleOperationGet = (options: Options) => (options.client ?? client).get({ url: '/api/v{api-version}/simple:operation', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -96,7 +96,7 @@ export const postCallWithOptionalParam = ( } }); -export const postApiVbyApiVersionRequestBody = (options?: Options) => (options?.client ?? client).post({ +export const apiVApiVersionRequestBodyPost = (options?: Options) => (options?.client ?? client).post({ url: '/api/v{api-version}/requestBody', ...options, headers: { @@ -105,7 +105,7 @@ export const postApiVbyApiVersionRequestBody = (options?: Options) => (options?.client ?? client).post({ +export const apiVApiVersionFormDataPost = (options?: Options) => (options?.client ?? client).post({ ...formDataBodySerializer, url: '/api/v{api-version}/formData', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/instance/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/instance/sdk.gen.ts index af464f9b9..060d7ded1 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/instance/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/instance/sdk.gen.ts @@ -47,6 +47,10 @@ class HeyApiRegistry { } export class Bar extends HeyApiClient { + public get(options?: Options) { + return (options?.client ?? this.client).get({ url: '/foo/bar', ...options }); + } + public post(options?: Options) { return (options?.client ?? this.client).post({ url: '/foo/bar', ...options }); } @@ -57,6 +61,10 @@ export class Bar extends HeyApiClient { } export class Foo extends HeyApiClient { + public get(options?: Options) { + return (options?.client ?? this.client).get({ url: '/foo', ...options }); + } + public post(options?: Options) { return (options?.client ?? this.client).post({ url: '/foo', ...options }); } @@ -82,14 +90,6 @@ export class Sdk extends HeyApiClient { Sdk.__registry.set(this, args?.key); } - public getFoo(options?: Options) { - return (options?.client ?? this.client).get({ url: '/foo', ...options }); - } - - public getFooBar(options?: Options) { - return (options?.client ?? this.client).get({ url: '/foo/bar', ...options }); - } - private _foo?: Foo; get foo(): Foo { return this._foo ??= new Foo({ client: this.client }); diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/throwOnError/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/throwOnError/index.ts index 62e4bbff0..ae3813b44 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/throwOnError/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/throwOnError/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { apiVVersionODataControllerCount, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexParams, complexTypes, deleteCallWithoutParametersAndResponse, deleteFoo, deprecatedCall, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, export_, fileResponse, fooWow, getApiVbyApiVersionSimpleOperation, getCallWithOptionalParam, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, import_, multipartRequest, multipartResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionFormData, postApiVbyApiVersionRequestBody, postCallWithOptionalParam, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, putWithFormUrlEncoded, testErrorCode, types, uploadFile } from './sdk.gen'; +export { apiVApiVersionFormDataPost, apiVApiVersionNo_tagPatch, apiVApiVersionRequestBodyPost, apiVApiVersionSimpleOperationGet, apiVVersionODataController__count, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexParams, complexTypes, deleteCallWithoutParametersAndResponse, deleteFoo, deprecatedCall, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, export_, fileResponse, foo_Wow, getCallWithOptionalParam, getCallWithoutParametersAndResponse, headCallWithoutParametersAndResponse, import_, multipartRequest, multipartResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, optionsCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, postCallWithOptionalParam, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, putWithFormUrlEncoded, testErrorCode, types, uploadFile } from './sdk.gen'; export type { _3eNum1Период, _400, AdditionalPropertiesIntegerIssue, AdditionalPropertiesUnknownIssue, AdditionalPropertiesUnknownIssue2, AdditionalPropertiesUnknownIssue3, AdditionalPropertiesUnknownIssueWritable, AnyOfAnyAndNull, AnyOfArrays, ApiVVersionODataControllerCountData, ApiVVersionODataControllerCountResponse, ApiVVersionODataControllerCountResponses, ArrayWithAnyOfProperties, ArrayWithArray, ArrayWithBooleans, ArrayWithNumbers, ArrayWithProperties, ArrayWithReferences, ArrayWithStrings, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesErrors, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesResponses, CallWithNoContentResponseData, CallWithNoContentResponseResponse, CallWithNoContentResponseResponses, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, CallWithResponseAndNoContentResponseResponses, CallWithResponseData, CallWithResponseResponse, CallWithResponseResponses, CallWithResponsesData, CallWithResponsesError, CallWithResponsesErrors, CallWithResponsesResponse, CallWithResponsesResponses, CallWithResultFromHeaderData, CallWithResultFromHeaderErrors, CallWithResultFromHeaderResponses, CallWithWeirdParameterNamesData, CamelCaseCommentWithBreaks, CharactersInDescription, ClientOptions, CollectionFormatData, CommentWithBackticks, CommentWithBackticksAndQuotes, CommentWithBreaks, CommentWithExpressionPlaceholders, CommentWithQuotes, CommentWithReservedCharacters, CommentWithSlashes, ComplexParamsData, ComplexParamsResponse, ComplexParamsResponses, ComplexTypesData, ComplexTypesErrors, ComplexTypesResponse, ComplexTypesResponses, CompositionBaseModel, CompositionExtendedModel, CompositionWithAllOfAndNullable, CompositionWithAnyOf, CompositionWithAnyOfAndNullable, CompositionWithAnyOfAnonymous, CompositionWithNestedAnyAndTypeNull, CompositionWithNestedAnyOfAndNull, CompositionWithOneOf, CompositionWithOneOfAndComplexArrayDictionary, CompositionWithOneOfAndNullable, CompositionWithOneOfAndProperties, CompositionWithOneOfAndSimpleArrayDictionary, CompositionWithOneOfAndSimpleDictionary, CompositionWithOneOfAnonymous, CompositionWithOneOfDiscriminator, ConstValue, Default, DeleteCallWithoutParametersAndResponseData, DeleteFooData, DeleteFooData2, DeleteFooData3, DeprecatedCallData, DeprecatedModel, DictionaryWithArray, DictionaryWithDictionary, DictionaryWithProperties, DictionaryWithPropertiesAndAdditionalProperties, DictionaryWithReference, DictionaryWithString, DummyAData, DummyAResponse, DummyAResponses, DummyBData, DummyBResponse, DummyBResponses, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, EnumFromDescription, EnumWithExtensions, EnumWithNumbers, EnumWithReplacedCharacters, EnumWithStrings, EnumWithXEnumNames, ExportData, ExternalRefA, ExternalRefB, ExternalSharedExternalSharedModel, File, FileResponseData, FileResponseResponse, FileResponseResponses, FileWritable, FooWowData, FooWowResponses, FreeFormObjectWithAdditionalPropertiesEqEmptyObject, FreeFormObjectWithAdditionalPropertiesEqTrue, FreeFormObjectWithoutAdditionalProperties, GenericSchemaDuplicateIssue1SystemBoolean, GenericSchemaDuplicateIssue1SystemBooleanWritable, GenericSchemaDuplicateIssue1SystemString, GenericSchemaDuplicateIssue1SystemStringWritable, GetApiVbyApiVersionSimpleOperationData, GetApiVbyApiVersionSimpleOperationError, GetApiVbyApiVersionSimpleOperationErrors, GetApiVbyApiVersionSimpleOperationResponse, GetApiVbyApiVersionSimpleOperationResponses, GetCallWithOptionalParamData, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, Import, ImportData, ImportResponse, ImportResponses, IoK8sApimachineryPkgApisMetaV1DeleteOptions, IoK8sApimachineryPkgApisMetaV1Preconditions, ModelCircle, ModelFromZendesk, ModelSquare, ModelThatExtends, ModelThatExtendsExtends, ModelWithAdditionalPropertiesEqTrue, ModelWithAnyOfConstantSizeArray, ModelWithAnyOfConstantSizeArrayAndIntersect, ModelWithAnyOfConstantSizeArrayNullable, ModelWithAnyOfConstantSizeArrayWithNSizeAndOptions, ModelWithAnyOfConstantSizeArrayWithNSizeAndOptionsWritable, ModelWithArray, ModelWithArrayReadOnlyAndWriteOnly, ModelWithArrayReadOnlyAndWriteOnlyWritable, ModelWithBackticksInDescription, ModelWithBoolean, ModelWithCircularReference, ModelWithConst, ModelWithConstantSizeArray, ModelWithDictionary, ModelWithDuplicateImports, ModelWithDuplicateProperties, ModelWithEnum, ModelWithEnumFromDescription, ModelWithEnumWithHyphen, ModelWithInteger, ModelWithNestedArrayEnums, ModelWithNestedArrayEnumsData, ModelWithNestedArrayEnumsDataBar, ModelWithNestedArrayEnumsDataFoo, ModelWithNestedCompositionEnums, ModelWithNestedEnums, ModelWithNestedProperties, ModelWithNullableObject, ModelWithNullableString, ModelWithNumericEnumUnion, ModelWithOneOfAndProperties, ModelWithOneOfEnum, ModelWithOrderedProperties, ModelWithPattern, ModelWithPatternWritable, ModelWithPrefixItemsConstantSizeArray, ModelWithProperties, ModelWithPropertiesWritable, ModelWithReadOnlyAndWriteOnly, ModelWithReadOnlyAndWriteOnlyWritable, ModelWithReference, ModelWithReferenceWritable, ModelWithString, ModelWithStringError, MultipartRequestData, MultipartResponseData, MultipartResponseResponse, MultipartResponseResponses, NestedAnyOfArraysNullable, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, NonAsciiæøåÆøÅöôêÊ字符串Responses, NonAsciiStringæøåÆøÅöôêÊ字符串, NullableObject, OneOfAllOfIssue, OneOfAllOfIssueWritable, OptionsCallWithoutParametersAndResponseData, Pageable, ParameterSimpleParameterUnused, PatchApiVbyApiVersionNoTagData, PatchApiVbyApiVersionNoTagResponses, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionFormDataData, PostApiVbyApiVersionRequestBodyData, PostCallWithOptionalParamData, PostCallWithOptionalParamResponse, PostCallWithOptionalParamResponses, PostCallWithoutParametersAndResponseData, PostServiceWithEmptyTagResponse, PostServiceWithEmptyTagResponse2, PutCallWithoutParametersAndResponseData, PutWithFormUrlEncodedData, SchemaWithFormRestrictedKeys, SimpleBoolean, SimpleFile, SimpleFormData, SimpleInteger, SimpleParameter, SimpleReference, SimpleRequestBody, SimpleString, SimpleStringWithPattern, TestErrorCodeData, TestErrorCodeErrors, TestErrorCodeResponses, TypesData, TypesResponse, TypesResponses, UploadFileData, UploadFileResponse, UploadFileResponses, XFooBar } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/throwOnError/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/throwOnError/sdk.gen.ts index 8d362960f..a805c6bc1 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/throwOnError/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/sdk/throwOnError/sdk.gen.ts @@ -20,7 +20,7 @@ export type Options(options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/no+tag', ...options }); -export const patchApiVbyApiVersionNoTag = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); +export const apiVApiVersionNo_tagPatch = (options?: Options) => (options?.client ?? client).patch({ url: '/api/v{api-version}/no+tag', ...options }); export const import_ = (options: Options) => (options.client ?? client).post({ url: '/api/v{api-version}/no+tag', @@ -31,11 +31,11 @@ export const import_ = (options: Options(options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); +export const foo_Wow = (options?: Options) => (options?.client ?? client).put({ url: '/api/v{api-version}/no+tag', ...options }); -export const apiVVersionODataControllerCount = (options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/simple/$count', ...options }); +export const apiVVersionODataController__count = (options?: Options) => (options?.client ?? client).get({ url: '/api/v{api-version}/simple/$count', ...options }); -export const getApiVbyApiVersionSimpleOperation = (options: Options) => (options.client ?? client).get({ url: '/api/v{api-version}/simple:operation', ...options }); +export const apiVApiVersionSimpleOperationGet = (options: Options) => (options.client ?? client).get({ url: '/api/v{api-version}/simple:operation', ...options }); export const deleteCallWithoutParametersAndResponse = (options?: Options) => (options?.client ?? client).delete({ url: '/api/v{api-version}/simple', ...options }); @@ -96,7 +96,7 @@ export const postCallWithOptionalParam = (o } }); -export const postApiVbyApiVersionRequestBody = (options?: Options) => (options?.client ?? client).post({ +export const apiVApiVersionRequestBodyPost = (options?: Options) => (options?.client ?? client).post({ url: '/api/v{api-version}/requestBody', ...options, headers: { @@ -105,7 +105,7 @@ export const postApiVbyApiVersionRequestBody = (options?: Options) => (options?.client ?? client).post({ +export const apiVApiVersionFormDataPost = (options?: Options) => (options?.client ?? client).post({ ...formDataBodySerializer, url: '/api/v{api-version}/formData', ...options, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-valibot/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-valibot/index.ts index 8dc6d0499..61e4b126b 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-valibot/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-valibot/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { type Options, postFoo } from './sdk.gen'; +export { fooPost, type Options } from './sdk.gen'; export type { Bar, ClientOptions, Foo, PostFooData, PostFooResponse, PostFooResponses, TypeID, UserId } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-valibot/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-valibot/sdk.gen.ts index b443e6ac2..8d5af124b 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-valibot/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-valibot/sdk.gen.ts @@ -22,7 +22,7 @@ export type Options; }; -export const postFoo = (options?: Options) => (options?.client ?? client).post({ +export const fooPost = (options?: Options) => (options?.client ?? client).post({ requestValidator: async (data) => await v.parseAsync(vPostFooData, data), responseTransformer: postFooResponseTransformer, responseValidator: async (data) => await v.parseAsync(vPostFooResponse, data), diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-zod/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-zod/index.ts index 8dc6d0499..61e4b126b 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-zod/index.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-zod/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { type Options, postFoo } from './sdk.gen'; +export { fooPost, type Options } from './sdk.gen'; export type { Bar, ClientOptions, Foo, PostFooData, PostFooResponse, PostFooResponses, TypeID, UserId } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-zod/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-zod/sdk.gen.ts index db455df67..56a6a3fd7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-zod/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@hey-api/transformers/type-format-zod/sdk.gen.ts @@ -20,7 +20,7 @@ export type Options; }; -export const postFoo = (options?: Options) => (options?.client ?? client).post({ +export const fooPost = (options?: Options) => (options?.client ?? client).post({ requestValidator: async (data) => await zPostFooData.parseAsync(data), responseTransformer: postFooResponseTransformer, responseValidator: async (data) => await zPostFooResponse.parseAsync(data), diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/@pinia/colada.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/@pinia/colada.gen.ts index 3aeed5221..84f186999 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/@pinia/colada.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/@pinia/colada.gen.ts @@ -47,7 +47,7 @@ export const getFooQueryKey = (options?: Options) => createQueryKey( export const getFooQuery = defineQueryOptions((options?: Options) => ({ key: getFooQueryKey(options), query: async (context) => { - const { data } = await FooBazService.getFoo({ + const { data } = await FooBazService.fooService.get({ ...options, ...context, throwOnError: true @@ -83,7 +83,7 @@ export const getFooBarQueryKey = (options?: Options) => createQue export const getFooBarQuery = defineQueryOptions((options?: Options) => ({ key: getFooBarQueryKey(options), query: async (context) => { - const { data } = await BarBazService.getFooBar({ + const { data } = await BarBazService.fooService.barService.get({ ...options, ...context, throwOnError: true diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts index 81b7e79ea..951c71fca 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/asClass/sdk.gen.ts @@ -29,6 +29,10 @@ export class BarService { } export class FooService { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo', ...options }); } @@ -41,14 +45,14 @@ export class FooService { } export class FooBazService { - public static getFoo(options?: Options) { - return (options?.client ?? client).get({ url: '/foo', ...options }); - } - static fooService = FooService; } export class BarService2 { + public static get(options?: Options) { + return (options?.client ?? client).get({ url: '/foo/bar', ...options }); + } + public static post(options?: Options) { return (options?.client ?? client).post({ url: '/foo/bar', ...options }); } @@ -63,9 +67,5 @@ export class FooService2 { } export class BarBazService { - public static getFooBar(options?: Options) { - return (options?.client ?? client).get({ url: '/foo/bar', ...options }); - } - static fooService = FooService2; } diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/fetch/@pinia/colada.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/fetch/@pinia/colada.gen.ts index 81651e8f9..6eba11388 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/fetch/@pinia/colada.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/@pinia/colada/fetch/@pinia/colada.gen.ts @@ -4,7 +4,7 @@ import { type _JSONValue, defineQueryOptions, type UseMutationOptions } from '@p import { serializeQueryKeyValue } from '../client'; import { client } from '../client.gen'; -import { apiVVersionODataControllerCount, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexParams, complexTypes, deleteCallWithoutParametersAndResponse, deleteFoo, deprecatedCall, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, export_, fileResponse, fooWow, getApiVbyApiVersionSimpleOperation, getCallWithOptionalParam, getCallWithoutParametersAndResponse, import_, multipartRequest, multipartResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchApiVbyApiVersionNoTag, patchCallWithoutParametersAndResponse, postApiVbyApiVersionFormData, postApiVbyApiVersionRequestBody, postCallWithOptionalParam, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, putWithFormUrlEncoded, testErrorCode, types, uploadFile } from '../sdk.gen'; +import { apiVApiVersionFormDataPost, apiVApiVersionNo_tagPatch, apiVApiVersionRequestBodyPost, apiVApiVersionSimpleOperationGet, apiVVersionODataController__count, callToTestOrderOfParams, callWithDefaultOptionalParameters, callWithDefaultParameters, callWithDescriptions, callWithDuplicateResponses, callWithNoContentResponse, callWithParameters, callWithResponse, callWithResponseAndNoContentResponse, callWithResponses, callWithResultFromHeader, callWithWeirdParameterNames, collectionFormat, complexParams, complexTypes, deleteCallWithoutParametersAndResponse, deleteFoo, deprecatedCall, dummyA, dummyB, duplicateName, duplicateName2, duplicateName3, duplicateName4, export_, fileResponse, foo_Wow, getCallWithOptionalParam, getCallWithoutParametersAndResponse, import_, multipartRequest, multipartResponse, nonAsciiæøåÆøÅöôêÊ字符串, type Options, patchCallWithoutParametersAndResponse, postCallWithOptionalParam, postCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, putWithFormUrlEncoded, testErrorCode, types, uploadFile } from '../sdk.gen'; import type { ApiVVersionODataControllerCountData, CallToTestOrderOfParamsData, CallWithDefaultOptionalParametersData, CallWithDefaultParametersData, CallWithDescriptionsData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithNoContentResponseData, CallWithParametersData, CallWithResponseAndNoContentResponseData, CallWithResponseData, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CallWithResultFromHeaderData, CallWithWeirdParameterNamesData, CollectionFormatData, ComplexParamsData, ComplexParamsResponse, ComplexTypesData, DeleteCallWithoutParametersAndResponseData, DeleteFooData3, DeprecatedCallData, DummyAData, DummyBData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, DuplicateNameData, ExportData, FileResponseData, FooWowData, GetApiVbyApiVersionSimpleOperationData, GetCallWithOptionalParamData, GetCallWithoutParametersAndResponseData, ImportData, ImportResponse, MultipartRequestData, MultipartResponseData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PatchApiVbyApiVersionNoTagData, PatchCallWithoutParametersAndResponseData, PostApiVbyApiVersionFormDataData, PostApiVbyApiVersionRequestBodyData, PostCallWithOptionalParamData, PostCallWithOptionalParamResponse, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, PutWithFormUrlEncodedData, TestErrorCodeData, TypesData, UploadFileData, UploadFileResponse } from '../types.gen'; export type QueryKey = [ @@ -58,7 +58,7 @@ export const exportQuery = defineQueryOptions((options?: Options) => export const patchApiVbyApiVersionNoTagMutation = (options?: Partial>): UseMutationOptions, Error> => ({ mutation: async (vars) => { - const { data } = await patchApiVbyApiVersionNoTag({ + const { data } = await apiVApiVersionNo_tagPatch({ ...options, ...vars, throwOnError: true @@ -80,7 +80,7 @@ export const importMutation = (options?: Partial>): UseMutat export const fooWowMutation = (options?: Partial>): UseMutationOptions, Error> => ({ mutation: async (vars) => { - const { data } = await fooWow({ + const { data } = await foo_Wow({ ...options, ...vars, throwOnError: true @@ -94,7 +94,7 @@ export const apiVVersionODataControllerCountQueryKey = (options?: Options) => ({ key: apiVVersionODataControllerCountQueryKey(options), query: async (context) => { - const { data } = await apiVVersionODataControllerCount({ + const { data } = await apiVVersionODataController__count({ ...options, ...context, throwOnError: true @@ -108,7 +108,7 @@ export const getApiVbyApiVersionSimpleOperationQueryKey = (options: Options) => ({ key: getApiVbyApiVersionSimpleOperationQueryKey(options), query: async (context) => { - const { data } = await getApiVbyApiVersionSimpleOperation({ + const { data } = await apiVApiVersionSimpleOperationGet({ ...options, ...context, throwOnError: true @@ -260,7 +260,7 @@ export const postCallWithOptionalParamMutation = (options?: Partial>): UseMutationOptions, Error> => ({ mutation: async (vars) => { - const { data } = await postApiVbyApiVersionRequestBody({ + const { data } = await apiVApiVersionRequestBodyPost({ ...options, ...vars, throwOnError: true @@ -271,7 +271,7 @@ export const postApiVbyApiVersionRequestBodyMutation = (options?: Partial