Skip to content

Commit

Permalink
Merge pull request #1096 from hey-api/fix/tanstack-query-class-services
Browse files Browse the repository at this point in the history
fix: make TanStack Query plugin work with class-based services
  • Loading branch information
mrlubos authored Sep 26, 2024
2 parents 867682d + b6e350a commit c43c949
Show file tree
Hide file tree
Showing 91 changed files with 18,222 additions and 9,394 deletions.
5 changes: 5 additions & 0 deletions .changeset/clean-badgers-heal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hey-api/openapi-ts': patch
---

fix: make TanStack Query plugin work with class-based services
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export default tseslint.config(
'packages/openapi-ts/src/legacy/handlebars/templates/**/*.hbs',
'**/test/e2e/generated/',
'**/test/generated/',
'**/__snapshots__/',
'**/.svelte-kit/',
'**/.vitepress/cache',
'**/.vitepress/dist',
Expand Down
3 changes: 2 additions & 1 deletion packages/openapi-ts/src/generate/transformers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ts from 'typescript';

import { compiler } from '../compiler';
import { getOperationKey } from '../openApi/common/parser/operation';
import type { ModelMeta, OperationResponse } from '../types/client';
import { getConfig } from '../utils/config';
import { isModelDate, unsetUniqueTypeName } from '../utils/type';
Expand Down Expand Up @@ -270,7 +271,7 @@ export const generateResponseTransformers = async ({
if (nonVoidResponses.length > 1) {
if (config.debug) {
console.warn(
`❗️ Transformers warning: route ${operation.method} ${operation.path} has ${nonVoidResponses.length} non-void success responses. This is currently not handled and we will not generate a response transformer. Please open an issue if you'd like this feature https://github.com/hey-api/openapi-ts/issues`,
`❗️ Transformers warning: route ${getOperationKey(operation)} has ${nonVoidResponses.length} non-void success responses. This is currently not handled and we will not generate a response transformer. Please open an issue if you'd like this feature https://github.com/hey-api/openapi-ts/issues`,
);
}
continue;
Expand Down
8 changes: 8 additions & 0 deletions packages/openapi-ts/src/openApi/common/parser/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ import type {
OperationResponse,
} from '../interfaces/client';

export const getOperationKey = (operation: {
method: string;
path: string;
}) => {
const operationKey = `${operation.method} ${operation.path}`;
return operationKey;
};

export const getOperationResponseHeader = (
operationResponses: OperationResponse[],
): string | null => {
Expand Down
18 changes: 11 additions & 7 deletions packages/openapi-ts/src/openApi/v2/parser/getOperations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Client, Operation } from '../../common/interfaces/client';
import { getOperationKey } from '../../common/parser/operation';
import { allowedServiceMethods } from '../../common/parser/service';
import { getConfig } from '../../config';
import type { OpenApi } from '../interfaces/OpenApi';
Expand All @@ -17,21 +18,24 @@ export const getOperations = ({
const operationIds = new Map<string, string>();
const operations: Operation[] = [];

for (const url in openApi.paths) {
const path = openApi.paths[url];
for (const path in openApi.paths) {
const pathItem = openApi.paths[path];
const pathParameters = getOperationParameters({
openApi,
parameters: path.parameters ?? [],
parameters: pathItem.parameters ?? [],
types,
});

for (const key in path) {
for (const key in pathItem) {
const method = key as Lowercase<Operation['method']>;

const operationKey = `${method.toUpperCase()} ${url}`;
const operationKey = getOperationKey({
method: method.toUpperCase(),
path,
});

if (allowedServiceMethods.includes(method)) {
const op = path[method]!;
const op = pathItem[method]!;

if (op.operationId) {
if (operationIds.has(op.operationId)) {
Expand All @@ -53,7 +57,7 @@ export const getOperations = ({
openApi,
pathParams: pathParameters,
types,
url,
url: path,
});
operations.push(operation);
}
Expand Down
18 changes: 11 additions & 7 deletions packages/openapi-ts/src/openApi/v3/parser/getOperations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Client, Operation } from '../../common/interfaces/client';
import { getOperationKey } from '../../common/parser/operation';
import { allowedServiceMethods } from '../../common/parser/service';
import { getConfig } from '../../config';
import type { OpenApi } from '../interfaces/OpenApi';
Expand All @@ -17,21 +18,24 @@ export const getOperations = ({
const operationIds = new Map<string, string>();
const operations: Operation[] = [];

for (const url in openApi.paths) {
const path = openApi.paths[url];
for (const path in openApi.paths) {
const pathItem = openApi.paths[path];
const pathParameters = getOperationParameters({
openApi,
parameters: path.parameters ?? [],
parameters: pathItem.parameters ?? [],
types,
});

for (const key in path) {
for (const key in pathItem) {
const method = key as Lowercase<Operation['method']>;

const operationKey = `${method.toUpperCase()} ${url}`;
const operationKey = getOperationKey({
method: method.toUpperCase(),
path,
});

if (allowedServiceMethods.includes(method)) {
const op = path[method]!;
const op = pathItem[method]!;

if (op.operationId) {
if (operationIds.has(op.operationId)) {
Expand All @@ -53,7 +57,7 @@ export const getOperations = ({
openApi,
pathParams: pathParameters,
types,
url,
url: path,
});
operations.push(operation);
}
Expand Down
21 changes: 19 additions & 2 deletions packages/openapi-ts/src/plugins/@tanstack/query-core/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
toOperationName,
} from '../../../generate/services';
import { isOperationParameterRequired } from '../../../openApi';
import { getOperationKey } from '../../../openApi/common/parser/operation';
import type { Client } from '../../../types/client';
import type {
Method,
Expand All @@ -25,6 +26,7 @@ import type {
} from '../../../types/client';
import type { Files } from '../../../types/utils';
import { getConfig } from '../../../utils/config';
import { transformServiceName } from '../../../utils/transform';
import type { PluginDefinition } from '../../types';

const toInfiniteQueryOptionsName = (operation: Operation) =>
Expand Down Expand Up @@ -471,6 +473,7 @@ export const handler: PluginDefinition['handler'] = ({

checkPrerequisites({ files });

const config = getConfig();
const file = files[plugin.name];

file.import({
Expand All @@ -495,9 +498,23 @@ export const handler: PluginDefinition['handler'] = ({
let hasMutations = false;
let hasQueries = false;

const processedOperations = new Map<string, boolean>();

for (const service of client.services) {
for (const operation of service.operations) {
const queryFn = toOperationName(operation, true);
// track processed operations to avoid creating duplicates
const operationKey = getOperationKey(operation);
if (processedOperations.has(operationKey)) {
continue;
}
processedOperations.set(operationKey, true);

const queryFn = [
config.services.asClass && transformServiceName(service.name),
toOperationName(operation, !config.services.asClass),
]
.filter(Boolean)
.join('.');
let hasUsedQueryFn = false;

// queries
Expand Down Expand Up @@ -1149,7 +1166,7 @@ export const handler: PluginDefinition['handler'] = ({
if (hasUsedQueryFn) {
file.import({
module: servicesModulePath,
name: queryFn,
name: queryFn.split('.')[0],
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/openapi-ts/test/__snapshots__/3.1.0/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// This file is auto-generated by @hey-api/openapi-ts
export * from './types.gen';
export * from './types.gen';
Loading

0 comments on commit c43c949

Please sign in to comment.