diff --git a/examples/nextjs-app/app/components/PaginatedPets.tsx b/examples/nextjs-app/app/components/PaginatedPets.tsx
index bfaee46..56e64e6 100644
--- a/examples/nextjs-app/app/components/PaginatedPets.tsx
+++ b/examples/nextjs-app/app/components/PaginatedPets.tsx
@@ -1,13 +1,15 @@
"use client";
-import { useDefaultServiceFindPaginatedPetsInfinite } from "@/openapi/queries/infiniteQueries";
+import { useFindPaginatedPetsInfinite } from "@/openapi/queries/infiniteQueries";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import React from "react";
export default function PaginatedPets() {
- const { data, fetchNextPage } = useDefaultServiceFindPaginatedPetsInfinite({
- limit: 10,
- tags: [],
+ const { data, fetchNextPage } = useFindPaginatedPetsInfinite({
+ query: {
+ limit: 10,
+ tags: [],
+ },
});
return (
@@ -15,8 +17,8 @@ export default function PaginatedPets() {
Pet List with Pagination
{data?.pages.map((group, i) => (
-
- {group.pets?.map((pet) => (
+
+ {group?.pets?.map((pet) => (
- {pet.name}
))}
diff --git a/examples/nextjs-app/package.json b/examples/nextjs-app/package.json
index 9c5c6d5..08e8db6 100644
--- a/examples/nextjs-app/package.json
+++ b/examples/nextjs-app/package.json
@@ -9,7 +9,7 @@
"build": "next build",
"start": "next start",
"lint": "next lint",
- "generate:api": "rimraf ./openapi && node ../../dist/cli.mjs -i ../petstore.yaml --request ./request.ts --format=biome --lint=biome --base http://localhost:4010"
+ "generate:api": "rimraf ./openapi && node ../../dist/cli.mjs -i ../petstore.yaml --format=biome --lint=biome"
},
"dependencies": {
"@tanstack/react-query": "^5.32.1",
diff --git a/examples/nextjs-app/request.ts b/examples/nextjs-app/request.ts
deleted file mode 100644
index 98e0a7f..0000000
--- a/examples/nextjs-app/request.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import axios from "axios";
-import type { RawAxiosRequestHeaders } from "axios";
-
-import type { ApiRequestOptions } from "./ApiRequestOptions";
-import { CancelablePromise } from "./CancelablePromise";
-import type { OpenAPIConfig } from "./OpenAPI";
-
-// Optional: Get and link the cancelation token, so the request can be aborted.
-const source = axios.CancelToken.source();
-
-const axiosInstance = axios.create({
- // Your custom Axios instance config
- baseURL: "http://localhost:4010",
- headers: {
- // Your custom headers
- } satisfies RawAxiosRequestHeaders,
-});
-
-// Add a request interceptor
-axiosInstance.interceptors.request.use(
- (config) => {
- // Do something before request is sent
- if (!config.url || !config.params) {
- return config;
- }
-
- for (const [key, value] of Object.entries(config.params)) {
- const stringToSearch = `{${key}}`;
- if (
- config.url !== undefined &&
- config.url.search(stringToSearch) !== -1
- ) {
- config.url = config.url.replace(`{${key}}`, encodeURIComponent(value));
- delete config.params[key];
- }
- }
-
- return config;
- },
- (error) => {
- // Do something with request error
- return Promise.reject(error);
- },
-);
-
-// Add a response interceptor
-axiosInstance.interceptors.response.use(
- (response) => {
- // Any status code that lie within the range of 2xx cause this function to trigger
- // Do something with response data
- return response;
- },
- (error) => {
- // Any status codes that falls outside the range of 2xx cause this function to trigger
- // Do something with response error
- return Promise.reject(error);
- },
-);
-
-export const request = (
- config: OpenAPIConfig,
- options: ApiRequestOptions,
-): CancelablePromise => {
- return new CancelablePromise((resolve, reject, onCancel) => {
- onCancel(() => source.cancel("The user aborted a request."));
-
- let formattedHeaders = options.headers as RawAxiosRequestHeaders;
- if (options.mediaType) {
- formattedHeaders = {
- ...options.headers,
- "Content-Type": options.mediaType,
- } satisfies RawAxiosRequestHeaders;
- }
-
- return axiosInstance
- .request({
- url: options.url,
- data: options.body,
- method: options.method,
- params: {
- ...options.query,
- ...options.path,
- },
- headers: formattedHeaders,
- cancelToken: source.token,
- })
- .then((res) => {
- resolve(res.data);
- })
- .catch((error) => {
- reject(error);
- });
- });
-};
diff --git a/examples/tanstack-router-app/package.json b/examples/tanstack-router-app/package.json
index c4e5cc3..1904496 100644
--- a/examples/tanstack-router-app/package.json
+++ b/examples/tanstack-router-app/package.json
@@ -11,7 +11,7 @@
"build": "vite build",
"serve": "vite preview",
"start": "vite",
- "generate:api": "rimraf ./openapi && node ../../dist/cli.mjs -i ../petstore.yaml -c axios --request ./request.ts --format=biome --lint=biome"
+ "generate:api": "rimraf ./openapi && node ../../dist/cli.mjs -i ../petstore.yaml --format=biome --lint=biome"
},
"devDependencies": {
"@stoplight/prism-cli": "^5.5.2",
@@ -29,7 +29,6 @@
"@tanstack/react-router-with-query": "^1.58.7",
"@tanstack/router-devtools": "^1.58.7",
"@tanstack/start": "^1.58.7",
- "axios": "^1.6.7",
"react": "^18.3.1",
"react-dom": "^18.3.1"
}
diff --git a/examples/tanstack-router-app/request.ts b/examples/tanstack-router-app/request.ts
deleted file mode 100644
index 98e0a7f..0000000
--- a/examples/tanstack-router-app/request.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import axios from "axios";
-import type { RawAxiosRequestHeaders } from "axios";
-
-import type { ApiRequestOptions } from "./ApiRequestOptions";
-import { CancelablePromise } from "./CancelablePromise";
-import type { OpenAPIConfig } from "./OpenAPI";
-
-// Optional: Get and link the cancelation token, so the request can be aborted.
-const source = axios.CancelToken.source();
-
-const axiosInstance = axios.create({
- // Your custom Axios instance config
- baseURL: "http://localhost:4010",
- headers: {
- // Your custom headers
- } satisfies RawAxiosRequestHeaders,
-});
-
-// Add a request interceptor
-axiosInstance.interceptors.request.use(
- (config) => {
- // Do something before request is sent
- if (!config.url || !config.params) {
- return config;
- }
-
- for (const [key, value] of Object.entries(config.params)) {
- const stringToSearch = `{${key}}`;
- if (
- config.url !== undefined &&
- config.url.search(stringToSearch) !== -1
- ) {
- config.url = config.url.replace(`{${key}}`, encodeURIComponent(value));
- delete config.params[key];
- }
- }
-
- return config;
- },
- (error) => {
- // Do something with request error
- return Promise.reject(error);
- },
-);
-
-// Add a response interceptor
-axiosInstance.interceptors.response.use(
- (response) => {
- // Any status code that lie within the range of 2xx cause this function to trigger
- // Do something with response data
- return response;
- },
- (error) => {
- // Any status codes that falls outside the range of 2xx cause this function to trigger
- // Do something with response error
- return Promise.reject(error);
- },
-);
-
-export const request = (
- config: OpenAPIConfig,
- options: ApiRequestOptions,
-): CancelablePromise => {
- return new CancelablePromise((resolve, reject, onCancel) => {
- onCancel(() => source.cancel("The user aborted a request."));
-
- let formattedHeaders = options.headers as RawAxiosRequestHeaders;
- if (options.mediaType) {
- formattedHeaders = {
- ...options.headers,
- "Content-Type": options.mediaType,
- } satisfies RawAxiosRequestHeaders;
- }
-
- return axiosInstance
- .request({
- url: options.url,
- data: options.body,
- method: options.method,
- params: {
- ...options.query,
- ...options.path,
- },
- headers: formattedHeaders,
- cancelToken: source.token,
- })
- .then((res) => {
- resolve(res.data);
- })
- .catch((error) => {
- reject(error);
- });
- });
-};
diff --git a/examples/tanstack-router-app/src/fetchClient.ts b/examples/tanstack-router-app/src/fetchClient.ts
new file mode 100644
index 0000000..7497a3b
--- /dev/null
+++ b/examples/tanstack-router-app/src/fetchClient.ts
@@ -0,0 +1,5 @@
+import { client } from "../openapi/requests/services.gen";
+
+client.setConfig({
+ baseUrl: "http://localhost:4010",
+});
diff --git a/examples/tanstack-router-app/src/main.tsx b/examples/tanstack-router-app/src/main.tsx
index 0c552dc..dbdfd37 100644
--- a/examples/tanstack-router-app/src/main.tsx
+++ b/examples/tanstack-router-app/src/main.tsx
@@ -1,6 +1,6 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { RouterProvider, createRouter } from "@tanstack/react-router";
-import React from "react";
+import "./fetchClient";
import ReactDOM from "react-dom/client";
import { routeTree } from "./routeTree.gen";
diff --git a/examples/tanstack-router-app/src/routes/about.tsx b/examples/tanstack-router-app/src/routes/about.tsx
index de88d2a..494ba18 100644
--- a/examples/tanstack-router-app/src/routes/about.tsx
+++ b/examples/tanstack-router-app/src/routes/about.tsx
@@ -1,5 +1,4 @@
import { createFileRoute } from "@tanstack/react-router";
-import * as React from "react";
export const Route = createFileRoute("/about")({
component: AboutComponent,
diff --git a/examples/tanstack-router-app/src/routes/index.tsx b/examples/tanstack-router-app/src/routes/index.tsx
index 03174ee..af7ed6b 100644
--- a/examples/tanstack-router-app/src/routes/index.tsx
+++ b/examples/tanstack-router-app/src/routes/index.tsx
@@ -1,19 +1,19 @@
import { createFileRoute } from "@tanstack/react-router";
-import { ensureUseDefaultServiceFindPetsData } from "../../openapi/queries/ensureQueryData";
-import { useDefaultServiceFindPetsSuspense } from "../../openapi/queries/suspense";
+import { ensureUseFindPetsData } from "../../openapi/queries/ensureQueryData";
+import { useFindPetsSuspense } from "../../openapi/queries/suspense";
export const Route = createFileRoute("/")({
loader: async ({ context }) => {
- await ensureUseDefaultServiceFindPetsData(context.queryClient);
+ await ensureUseFindPetsData(context.queryClient);
},
component: HomeComponent,
});
function HomeComponent() {
- const petsSuspense = useDefaultServiceFindPetsSuspense();
+ const petsSuspense = useFindPetsSuspense();
return (
- {petsSuspense.data.map((post) => {
+ {petsSuspense.data?.map?.((post) => {
return (
-
{post.name}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 626bd17..3aa9ef4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -167,9 +167,6 @@ importers:
'@tanstack/start':
specifier: ^1.58.7
version: 1.62.1(@types/node@22.7.4)(ioredis@5.4.1)(magicast@0.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(terser@5.34.1)(typescript@5.6.2)(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1))
- axios:
- specifier: ^1.6.7
- version: 1.7.2
react:
specifier: ^18.3.1
version: 18.3.1
diff --git a/src/cli.mts b/src/cli.mts
index f1128c1..4ca7b06 100644
--- a/src/cli.mts
+++ b/src/cli.mts
@@ -110,11 +110,7 @@ async function setupProgram() {
"Name of the response parameter used for next page",
"nextPage",
)
- .option(
- "--initialPageParam ",
- "Initial page value to query",
- "initialPageParam",
- )
+ .option("--initialPageParam ", "Initial page value to query", "1")
.parse();
const options = program.opts();
diff --git a/src/constants.mts b/src/constants.mts
index f44bf11..651e6e8 100644
--- a/src/constants.mts
+++ b/src/constants.mts
@@ -3,7 +3,7 @@ export const queriesOutputPath = "queries";
export const requestsOutputPath = "requests";
export const serviceFileName = "services.gen";
-export const modalsFileName = "types.gen";
+export const modelsFileName = "types.gen";
export const OpenApiRqFiles = {
queries: "queries",
diff --git a/src/createExports.mts b/src/createExports.mts
index 7b2ff4e..334c612 100644
--- a/src/createExports.mts
+++ b/src/createExports.mts
@@ -1,4 +1,7 @@
-import type ts from "typescript";
+import type { Project } from "ts-morph";
+import ts from "typescript";
+import { capitalizeFirstLetter } from "./common.mjs";
+import { modelsFileName } from "./constants.mjs";
import { createPrefetchOrEnsure } from "./createPrefetchOrEnsure.mjs";
import { createUseMutation } from "./createUseMutation.mjs";
import { createUseQuery } from "./createUseQuery.mjs";
@@ -6,11 +9,51 @@ import type { Service } from "./service.mjs";
export const createExports = (
service: Service,
+ project: Project,
pageParam: string,
nextPageParam: string,
initialPageParam: string,
) => {
const { methods } = service;
+ const methodDataNames = methods.reduce(
+ (acc, data) => {
+ const methodName = data.method.getName();
+ acc[`${capitalizeFirstLetter(methodName)}Data`] = methodName;
+ return acc;
+ },
+ {} as { [key: string]: string },
+ );
+ const modelsFile = project
+ .getSourceFiles?.()
+ .find((sourceFile) => sourceFile.getFilePath().includes(modelsFileName));
+
+ const modelDeclarations = modelsFile?.getExportedDeclarations();
+ const entries = modelDeclarations?.entries();
+ const modelNames: string[] = [];
+ const paginatableMethods: string[] = [];
+ for (const [key, value] of entries ?? []) {
+ modelNames.push(key);
+ const node = value[0].compilerNode;
+ if (ts.isTypeAliasDeclaration(node) && methodDataNames[key] !== undefined) {
+ // get the type alias declaration
+ const typeAliasDeclaration = node.type;
+ if (typeAliasDeclaration.kind === ts.SyntaxKind.TypeLiteral) {
+ const query = (typeAliasDeclaration as ts.TypeLiteralNode).members.find(
+ (m) =>
+ m.kind === ts.SyntaxKind.PropertySignature &&
+ m.name?.getText() === "query",
+ );
+ if (
+ query &&
+ ((query as ts.PropertySignature).type as ts.TypeLiteralNode).members
+ .map((m) => m.name?.getText())
+ .includes(pageParam)
+ ) {
+ paginatableMethods.push(methodDataNames[key]);
+ }
+ }
+ }
+ }
const allGet = methods.filter((m) =>
m.httpMethodName.toUpperCase().includes("GET"),
@@ -29,19 +72,34 @@ export const createExports = (
);
const allGetQueries = allGet.map((m) =>
- createUseQuery(m, pageParam, nextPageParam, initialPageParam),
+ createUseQuery(
+ m,
+ pageParam,
+ nextPageParam,
+ initialPageParam,
+ paginatableMethods,
+ modelNames,
+ ),
);
const allPrefetchQueries = allGet.map((m) =>
- createPrefetchOrEnsure({ ...m, functionType: "prefetch" }),
+ createPrefetchOrEnsure({ ...m, functionType: "prefetch", modelNames }),
);
const allEnsureQueries = allGet.map((m) =>
- createPrefetchOrEnsure({ ...m, functionType: "ensure" }),
+ createPrefetchOrEnsure({ ...m, functionType: "ensure", modelNames }),
);
- const allPostMutations = allPost.map((m) => createUseMutation(m));
- const allPutMutations = allPut.map((m) => createUseMutation(m));
- const allPatchMutations = allPatch.map((m) => createUseMutation(m));
- const allDeleteMutations = allDelete.map((m) => createUseMutation(m));
+ const allPostMutations = allPost.map((m) =>
+ createUseMutation({ ...m, modelNames }),
+ );
+ const allPutMutations = allPut.map((m) =>
+ createUseMutation({ ...m, modelNames }),
+ );
+ const allPatchMutations = allPatch.map((m) =>
+ createUseMutation({ ...m, modelNames }),
+ );
+ const allDeleteMutations = allDelete.map((m) =>
+ createUseMutation({ ...m, modelNames }),
+ );
const allQueries = [...allGetQueries];
const allMutations = [
diff --git a/src/createImports.mts b/src/createImports.mts
index 3f86b1b..2e367b5 100644
--- a/src/createImports.mts
+++ b/src/createImports.mts
@@ -1,7 +1,7 @@
import { posix } from "node:path";
import type { Project } from "ts-morph";
import ts from "typescript";
-import { modalsFileName, serviceFileName } from "./constants.mjs";
+import { modelsFileName, serviceFileName } from "./constants.mjs";
const { join } = posix;
@@ -12,7 +12,7 @@ export const createImports = ({
}) => {
const modelsFile = project
.getSourceFiles()
- .find((sourceFile) => sourceFile.getFilePath().includes(modalsFileName));
+ .find((sourceFile) => sourceFile.getFilePath().includes(modelsFileName));
const serviceFile = project.getSourceFileOrThrow(`${serviceFileName}.ts`);
@@ -122,7 +122,7 @@ export const createImports = ({
),
]),
),
- ts.factory.createStringLiteral(join("../requests/", modalsFileName)),
+ ts.factory.createStringLiteral(join("../requests/", modelsFileName)),
undefined,
),
);
diff --git a/src/createPrefetchOrEnsure.mts b/src/createPrefetchOrEnsure.mts
index 33181a6..eb8817d 100644
--- a/src/createPrefetchOrEnsure.mts
+++ b/src/createPrefetchOrEnsure.mts
@@ -2,7 +2,7 @@ import type { VariableDeclaration } from "ts-morph";
import ts from "typescript";
import {
BuildCommonTypeName,
- extractPropertiesFromObjectParam,
+ EqualsOrGreaterThanToken,
getNameFromVariable,
getVariableArrowFunctionParameters,
} from "./common.mjs";
@@ -66,7 +66,7 @@ function createPrefetchOrEnsureHook({
...requestParams,
],
undefined,
- ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
+ EqualsOrGreaterThanToken,
ts.factory.createCallExpression(
ts.factory.createIdentifier(
`queryClient.${functionType === "prefetch" ? "prefetchQuery" : "ensureQueryData"}`,
@@ -80,22 +80,7 @@ function createPrefetchOrEnsureHook({
BuildCommonTypeName(getQueryKeyFnName(queryKey)),
undefined,
- getVariableArrowFunctionParameters(method).length
- ? [
- ts.factory.createObjectLiteralExpression(
- getVariableArrowFunctionParameters(
- method,
- ).flatMap((param) =>
- extractPropertiesFromObjectParam(param).map(
- (p) =>
- ts.factory.createShorthandPropertyAssignment(
- ts.factory.createIdentifier(p.name),
- ),
- ),
- ),
- ),
- ]
- : [],
+ [ts.factory.createIdentifier("clientOptions")],
),
),
ts.factory.createPropertyAssignment(
@@ -105,29 +90,53 @@ function createPrefetchOrEnsureHook({
undefined,
[],
undefined,
- ts.factory.createToken(
- ts.SyntaxKind.EqualsGreaterThanToken,
- ),
+ EqualsOrGreaterThanToken,
ts.factory.createCallExpression(
- ts.factory.createIdentifier(methodName),
+ ts.factory.createPropertyAccessExpression(
+ ts.factory.createCallExpression(
+ ts.factory.createIdentifier(methodName),
- undefined,
- getVariableArrowFunctionParameters(method).length
- ? [
- ts.factory.createObjectLiteralExpression(
- getVariableArrowFunctionParameters(
- method,
- ).flatMap((param) =>
- extractPropertiesFromObjectParam(param).map(
- (p) =>
- ts.factory.createShorthandPropertyAssignment(
- ts.factory.createIdentifier(p.name),
+ undefined,
+ // { ...clientOptions }
+ getVariableArrowFunctionParameters(method).length
+ ? [
+ ts.factory.createObjectLiteralExpression([
+ ts.factory.createSpreadAssignment(
+ ts.factory.createIdentifier(
+ "clientOptions",
),
- ),
- ),
+ ),
+ ]),
+ ]
+ : undefined,
+ ),
+ ts.factory.createIdentifier("then"),
+ ),
+ undefined,
+ [
+ ts.factory.createArrowFunction(
+ undefined,
+ undefined,
+ [
+ ts.factory.createParameterDeclaration(
+ undefined,
+ undefined,
+ ts.factory.createIdentifier("response"),
+ undefined,
+ undefined,
+ undefined,
),
- ]
- : undefined,
+ ],
+ undefined,
+ ts.factory.createToken(
+ ts.SyntaxKind.EqualsGreaterThanToken,
+ ),
+ ts.factory.createPropertyAccessExpression(
+ ts.factory.createIdentifier("response"),
+ ts.factory.createIdentifier("data"),
+ ),
+ ),
+ ],
),
),
),
@@ -147,8 +156,12 @@ export const createPrefetchOrEnsure = ({
method,
jsDoc,
functionType,
-}: FunctionDescription & { functionType: "prefetch" | "ensure" }) => {
- const requestParam = getRequestParamFromMethod(method);
+ modelNames,
+}: FunctionDescription & {
+ functionType: "prefetch" | "ensure";
+ modelNames: string[];
+}) => {
+ const requestParam = getRequestParamFromMethod(method, undefined, modelNames);
const requestParams = requestParam ? [requestParam] : [];
diff --git a/src/createSource.mts b/src/createSource.mts
index 2a02c40..e29929d 100644
--- a/src/createSource.mts
+++ b/src/createSource.mts
@@ -31,6 +31,7 @@ const createSourceFile = async (
const exports = createExports(
service,
+ project,
pageParam,
nextPageParam,
initialPageParam,
diff --git a/src/createUseMutation.mts b/src/createUseMutation.mts
index 8372abd..b20d27e 100644
--- a/src/createUseMutation.mts
+++ b/src/createUseMutation.mts
@@ -1,14 +1,13 @@
import ts from "typescript";
import {
BuildCommonTypeName,
+ EqualsOrGreaterThanToken,
type FunctionDescription,
TContext,
TData,
TError,
capitalizeFirstLetter,
- extractPropertiesFromObjectParam,
getNameFromVariable,
- getShortType,
getVariableArrowFunctionParameters,
} from "./common.mjs";
import { addJSDocToNode } from "./util.mjs";
@@ -38,7 +37,11 @@ function generateAwaitedReturnType({
);
}
-export const createUseMutation = ({ method, jsDoc }: FunctionDescription) => {
+export const createUseMutation = ({
+ method,
+ jsDoc,
+ modelNames,
+}: FunctionDescription & { modelNames: string[] }) => {
const methodName = getNameFromVariable(method);
const awaitedResponseDataType = generateAwaitedReturnType({
methodName,
@@ -64,22 +67,16 @@ export const createUseMutation = ({ method, jsDoc }: FunctionDescription) => {
const methodParameters =
getVariableArrowFunctionParameters(method).length !== 0
- ? ts.factory.createTypeLiteralNode(
- getVariableArrowFunctionParameters(method).flatMap((param) => {
- const paramNodes = extractPropertiesFromObjectParam(param);
- return paramNodes.map((refParam) =>
- ts.factory.createPropertySignature(
- undefined,
- ts.factory.createIdentifier(refParam.name),
- refParam.optional
- ? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
- : undefined,
- ts.factory.createTypeReferenceNode(
- getShortType(refParam.type?.getText(param) ?? ""),
- ),
- ),
- );
- }),
+ ? ts.factory.createTypeReferenceNode(
+ ts.factory.createIdentifier("Options"),
+ [
+ ts.factory.createTypeReferenceNode(
+ modelNames.includes(`${capitalizeFirstLetter(methodName)}Data`)
+ ? `${capitalizeFirstLetter(methodName)}Data`
+ : "unknown",
+ ),
+ ts.factory.createLiteralTypeNode(ts.factory.createTrue()),
+ ],
)
: ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword);
@@ -150,68 +147,31 @@ export const createUseMutation = ({ method, jsDoc }: FunctionDescription) => {
ts.factory.createObjectLiteralExpression([
ts.factory.createPropertyAssignment(
ts.factory.createIdentifier("mutationFn"),
+ // (clientOptions) => addPet(clientOptions).then(response => response.data as TData) as unknown as Promise
ts.factory.createArrowFunction(
undefined,
undefined,
- getVariableArrowFunctionParameters(method).length !== 0
- ? [
- ts.factory.createParameterDeclaration(
- undefined,
- undefined,
- ts.factory.createObjectBindingPattern(
- getVariableArrowFunctionParameters(
- method,
- ).flatMap((param) => {
- const paramNodes =
- extractPropertiesFromObjectParam(param);
- return paramNodes.map((refParam) =>
- ts.factory.createBindingElement(
- undefined,
- undefined,
- ts.factory.createIdentifier(
- refParam.name,
- ),
- undefined,
- ),
- );
- }),
- ),
- undefined,
- undefined,
- undefined,
- ),
- ]
- : [],
+ [
+ ts.factory.createParameterDeclaration(
+ undefined,
+ undefined,
+ ts.factory.createIdentifier("clientOptions"),
+ undefined,
+ undefined,
+ undefined,
+ ),
+ ],
undefined,
- ts.factory.createToken(
- ts.SyntaxKind.EqualsGreaterThanToken,
- ),
+ EqualsOrGreaterThanToken,
ts.factory.createAsExpression(
ts.factory.createAsExpression(
ts.factory.createCallExpression(
ts.factory.createIdentifier(methodName),
-
undefined,
- getVariableArrowFunctionParameters(method)
- .length !== 0
- ? [
- ts.factory.createObjectLiteralExpression(
- getVariableArrowFunctionParameters(
- method,
- ).flatMap((params) => {
- const paramNodes =
- extractPropertiesFromObjectParam(
- params,
- );
- return paramNodes.map((refParam) =>
- ts.factory.createShorthandPropertyAssignment(
- refParam.name,
- ),
- );
- }),
- ),
- ]
- : [],
+ getVariableArrowFunctionParameters(method).length >
+ 0
+ ? [ts.factory.createIdentifier("clientOptions")]
+ : undefined,
),
ts.factory.createKeywordTypeNode(
ts.SyntaxKind.UnknownKeyword,
diff --git a/src/createUseQuery.mts b/src/createUseQuery.mts
index df5deea..e2a9bb2 100644
--- a/src/createUseQuery.mts
+++ b/src/createUseQuery.mts
@@ -75,10 +75,12 @@ export const createApiResponseType = ({
export function getRequestParamFromMethod(
method: VariableDeclaration,
pageParam?: string,
+ modelNames: string[] = [],
) {
if (!getVariableArrowFunctionParameters(method).length) {
return null;
}
+ const methodName = getNameFromVariable(method);
const params = getVariableArrowFunctionParameters(method).flatMap((param) => {
const paramNodes = extractPropertiesFromObjectParam(param);
@@ -87,6 +89,7 @@ export function getRequestParamFromMethod(
.filter((p) => p.name !== pageParam)
.map((refParam) => ({
name: refParam.name,
+ // TODO: Client -> Client
typeName: getShortType(refParam.type?.getText() ?? ""),
optional: refParam.optional,
}));
@@ -97,29 +100,17 @@ export function getRequestParamFromMethod(
return ts.factory.createParameterDeclaration(
undefined,
undefined,
- ts.factory.createObjectBindingPattern(
- params.map((refParam) =>
- ts.factory.createBindingElement(
- undefined,
- undefined,
- ts.factory.createIdentifier(refParam.name),
- undefined,
- ),
- ),
- ),
+ // options
+ ts.factory.createIdentifier("clientOptions"),
undefined,
- ts.factory.createTypeLiteralNode(
- params.map((refParam) => {
- return ts.factory.createPropertySignature(
- undefined,
- ts.factory.createIdentifier(refParam.name),
- refParam.optional
- ? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
- : undefined,
- ts.factory.createTypeReferenceNode(refParam.typeName),
- );
- }),
- ),
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Options"), [
+ ts.factory.createTypeReferenceNode(
+ modelNames.includes(`${capitalizeFirstLetter(methodName)}Data`)
+ ? `${capitalizeFirstLetter(methodName)}Data`
+ : "unknown",
+ ),
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("true")),
+ ]),
// if all params are optional, we create an empty object literal
// so the hook can be called without any parameters
areAllPropertiesOptional
@@ -359,24 +350,10 @@ export function createQueryHook({
ts.factory.createCallExpression(
BuildCommonTypeName(getQueryKeyFnName(queryKey)),
undefined,
- getVariableArrowFunctionParameters(method).length
- ? [
- ts.factory.createObjectLiteralExpression(
- getVariableArrowFunctionParameters(
- method,
- ).flatMap((param) =>
- extractPropertiesFromObjectParam(param)
- .filter((p) => p.name !== pageParam)
- .map((p) =>
- ts.factory.createShorthandPropertyAssignment(
- ts.factory.createIdentifier(p.name),
- ),
- ),
- ),
- ),
- ts.factory.createIdentifier("queryKey"),
- ]
- : [ts.factory.createIdentifier("queryKey")],
+ [
+ ts.factory.createIdentifier("clientOptions"),
+ ts.factory.createIdentifier("queryKey"),
+ ],
),
),
ts.factory.createPropertyAssignment(
@@ -410,39 +387,60 @@ export function createQueryHook({
ts.factory.createCallExpression(
ts.factory.createIdentifier(methodName),
undefined,
- getVariableArrowFunctionParameters(method).length
+ pageParam && isInfiniteQuery
? [
- ts.factory.createObjectLiteralExpression(
- getVariableArrowFunctionParameters(
- method,
- ).flatMap((param) =>
- extractPropertiesFromObjectParam(
- param,
- ).map((p) =>
- p.name === pageParam
- ? ts.factory.createPropertyAssignment(
+ // { ...clientOptions, query: { ...clientOptions.query, page: pageParam as number } }
+ ts.factory.createObjectLiteralExpression([
+ ts.factory.createSpreadAssignment(
+ ts.factory.createIdentifier(
+ "clientOptions",
+ ),
+ ),
+ ts.factory.createPropertyAssignment(
+ ts.factory.createIdentifier("query"),
+ ts.factory.createObjectLiteralExpression(
+ [
+ ts.factory.createSpreadAssignment(
+ ts.factory.createPropertyAccessExpression(
ts.factory.createIdentifier(
- p.name,
+ "clientOptions",
),
- ts.factory.createAsExpression(
- ts.factory.createIdentifier(
- "pageParam",
- ),
- ts.factory.createKeywordTypeNode(
- ts.SyntaxKind.NumberKeyword,
- ),
+ ts.factory.createIdentifier(
+ "query",
),
- )
- : ts.factory.createShorthandPropertyAssignment(
+ ),
+ ),
+ ts.factory.createPropertyAssignment(
+ ts.factory.createIdentifier(
+ pageParam,
+ ),
+ ts.factory.createAsExpression(
ts.factory.createIdentifier(
- p.name,
+ "pageParam",
+ ),
+ ts.factory.createKeywordTypeNode(
+ ts.SyntaxKind.NumberKeyword,
),
),
+ ),
+ ],
),
),
- ),
+ ]),
]
- : undefined,
+ : // { ...clientOptions }
+ getVariableArrowFunctionParameters(method)
+ .length > 0
+ ? [
+ ts.factory.createObjectLiteralExpression([
+ ts.factory.createSpreadAssignment(
+ ts.factory.createIdentifier(
+ "clientOptions",
+ ),
+ ),
+ ]),
+ ]
+ : undefined,
),
ts.factory.createIdentifier("then"),
),
@@ -502,6 +500,8 @@ export const createUseQuery = (
pageParam: string,
nextPageParam: string,
initialPageParam: string,
+ paginatableMethods: string[],
+ modelNames: string[],
) => {
const methodName = getNameFromVariable(method);
const queryKey = createQueryKeyFromMethod({ method });
@@ -510,19 +510,15 @@ export const createUseQuery = (
methodName,
});
- const requestParam = getRequestParamFromMethod(method);
- const infiniteRequestParam = getRequestParamFromMethod(method, pageParam);
+ const requestParam = getRequestParamFromMethod(method, undefined, modelNames);
+ const infiniteRequestParam = getRequestParamFromMethod(
+ method,
+ pageParam,
+ modelNames,
+ );
const requestParams = requestParam ? [requestParam] : [];
- const requestParamNames = requestParams
- .filter((p) => p.name.kind === ts.SyntaxKind.ObjectBindingPattern)
- .map((p) => p.name as ts.ObjectBindingPattern);
- const requestParamTexts = requestParamNames
- .at(0)
- ?.elements.filter((e) => e.name.kind === ts.SyntaxKind.Identifier)
- .map((e) => (e.name as ts.Identifier).escapedText as string);
-
const queryHook = createQueryHook({
queryString: "useQuery",
suffix: "",
@@ -538,7 +534,8 @@ export const createUseQuery = (
requestParams,
method,
});
- const isInfiniteQuery = requestParamTexts?.includes(pageParam) ?? false;
+ const isInfiniteQuery = paginatableMethods.includes(methodName);
+
const infiniteQueryHook = isInfiniteQuery
? createQueryHook({
queryString: "useInfiniteQuery",
@@ -633,19 +630,12 @@ function queryKeyFn(
ts.factory.createIdentifier("queryKey"),
ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken),
getVariableArrowFunctionParameters(method)
- ? ts.factory.createArrayLiteralExpression([
- ts.factory.createObjectLiteralExpression(
- getVariableArrowFunctionParameters(method).flatMap(
- (param) =>
- extractPropertiesFromObjectParam(param).map((p) =>
- ts.factory.createShorthandPropertyAssignment(
- ts.factory.createIdentifier(p.name),
- ),
- ),
- ),
- ),
+ ? // [...clientOptions]
+ ts.factory.createArrayLiteralExpression([
+ ts.factory.createIdentifier("clientOptions"),
])
- : ts.factory.createArrayLiteralExpression([]),
+ : // []
+ ts.factory.createArrayLiteralExpression(),
),
),
),
diff --git a/src/service.mts b/src/service.mts
index 4b42f7c..8baa695 100644
--- a/src/service.mts
+++ b/src/service.mts
@@ -24,7 +24,7 @@ export async function getServices(project: Project): Promise {
} satisfies Service;
}
-function getMethodsFromService(node: SourceFile): FunctionDescription[] {
+export function getMethodsFromService(node: SourceFile): FunctionDescription[] {
const variableStatements = node.getVariableStatements();
// The first variable statement is `const client = createClient(createConfig())`, so we skip it
diff --git a/tests/__snapshots__/createSource.test.ts.snap b/tests/__snapshots__/createSource.test.ts.snap
index d63a6ed..cbd8243 100644
--- a/tests/__snapshots__/createSource.test.ts.snap
+++ b/tests/__snapshots__/createSource.test.ts.snap
@@ -17,28 +17,19 @@ import { Pet, NewPet, Error, FindPetsData, FindPetsResponse, FindPetsError, AddP
export type FindPetsDefaultResponse = Awaited>["data"];
export type FindPetsQueryResult = UseQueryResult;
export const useFindPetsKey = "FindPets";
-export const UseFindPetsKeyFn = ({ query, client }: {
- query?: { limit?: number; tags?: string[]; };
- client?: Client;
-} = {}, queryKey?: Array) => [useFindPetsKey, ...(queryKey ?? [{ query, client }])];
+export const UseFindPetsKeyFn = (clientOptions: Options = {}, queryKey?: Array) => [useFindPetsKey, ...(queryKey ?? [clientOptions])];
export type GetNotDefinedDefaultResponse = Awaited>["data"];
export type GetNotDefinedQueryResult = UseQueryResult;
export const useGetNotDefinedKey = "GetNotDefined";
-export const UseGetNotDefinedKeyFn = ({}: {} = {}, queryKey?: Array) => [useGetNotDefinedKey, ...(queryKey ?? [{}])];
+export const UseGetNotDefinedKeyFn = (clientOptions: Options = {}, queryKey?: Array) => [useGetNotDefinedKey, ...(queryKey ?? [clientOptions])];
export type FindPetByIdDefaultResponse = Awaited>["data"];
export type FindPetByIdQueryResult = UseQueryResult;
export const useFindPetByIdKey = "FindPetById";
-export const UseFindPetByIdKeyFn = ({ path, client }: {
- path: { id: number; };
- client?: Client;
-}, queryKey?: Array) => [useFindPetByIdKey, ...(queryKey ?? [{ path, client }])];
+export const UseFindPetByIdKeyFn = (clientOptions: Options, queryKey?: Array) => [useFindPetByIdKey, ...(queryKey ?? [clientOptions])];
export type FindPaginatedPetsDefaultResponse = Awaited>["data"];
export type FindPaginatedPetsQueryResult = UseQueryResult;
export const useFindPaginatedPetsKey = "FindPaginatedPets";
-export const UseFindPaginatedPetsKeyFn = ({ query, client }: {
- query?: { limit?: number; page?: number; tags?: string[]; };
- client?: Client;
-} = {}, queryKey?: Array) => [useFindPaginatedPetsKey, ...(queryKey ?? [{ query, client }])];
+export const UseFindPaginatedPetsKeyFn = (clientOptions: Options = {}, queryKey?: Array) => [useFindPaginatedPetsKey, ...(queryKey ?? [clientOptions])];
export type AddPetMutationResult = Awaited>;
export type PostNotDefinedMutationResult = Awaited>;
export type DeletePetMutationResult = Awaited>;
@@ -52,32 +43,13 @@ import * as Common from "./common";
import { type QueryClient, useQuery, useSuspenseQuery, useMutation, UseQueryResult, UseQueryOptions, UseMutationOptions, UseMutationResult } from "@tanstack/react-query";
import { client, findPets, addPet, getNotDefined, postNotDefined, findPetById, deletePet, findPaginatedPets } from "../requests/services.gen";
import { Pet, NewPet, Error, FindPetsData, FindPetsResponse, FindPetsError, AddPetData, AddPetResponse, AddPetError, GetNotDefinedResponse, GetNotDefinedError, PostNotDefinedResponse, PostNotDefinedError, FindPetByIdData, FindPetByIdResponse, FindPetByIdError, DeletePetData, DeletePetResponse, DeletePetError, FindPaginatedPetsData, FindPaginatedPetsResponse, FindPaginatedPetsError } from "../requests/types.gen";
-export const useFindPets = = unknown[]>({ query, client }: {
- query?: { limit?: number; tags?: string[]; };
- client?: Client;
-} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPetsKeyFn({ query, client }, queryKey), queryFn: () => findPets({ query, client }).then(response => response.data as TData) as TData, ...options });
-export const useGetNotDefined = = unknown[]>({}: {} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseGetNotDefinedKeyFn({}, queryKey), queryFn: () => getNotDefined({}).then(response => response.data as TData) as TData, ...options });
-export const useFindPetById = = unknown[]>({ path, client }: {
- path: { id: number; };
- client?: Client;
-}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPetByIdKeyFn({ path, client }, queryKey), queryFn: () => findPetById({ path, client }).then(response => response.data as TData) as TData, ...options });
-export const useFindPaginatedPets = = unknown[]>({ query, client }: {
- query?: { limit?: number; page?: number; tags?: string[]; };
- client?: Client;
-} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPaginatedPetsKeyFn({ query, client }, queryKey), queryFn: () => findPaginatedPets({ query, client }).then(response => response.data as TData) as TData, ...options });
-export const useAddPet = (options?: Omit, "mutationFn">) => useMutation({ mutationFn: ({ body }) => addPet({ body }) as unknown as Promise, ...options });
-export const usePostNotDefined = (options?: Omit, "mutationFn">) => useMutation({ mutationFn: ({}) => postNotDefined({}) as unknown as Promise, ...options });
-export const useDeletePet = (options?: Omit & Config & { headers: Headers; }>;
-}, TContext>, "mutationFn">) => useMutation & Config & { headers: Headers; }>;
-}, TContext>({ mutationFn: ({ path, client }) => deletePet({ path, client }) as unknown as Promise, ...options });
+export const useFindPets = = unknown[]>(clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPetsKeyFn(clientOptions, queryKey), queryFn: () => findPets({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
+export const useGetNotDefined = = unknown[]>(clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseGetNotDefinedKeyFn(clientOptions, queryKey), queryFn: () => getNotDefined({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
+export const useFindPetById = = unknown[]>(clientOptions: Options, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPetByIdKeyFn(clientOptions, queryKey), queryFn: () => findPetById({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
+export const useFindPaginatedPets = = unknown[]>(clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPaginatedPetsKeyFn(clientOptions, queryKey), queryFn: () => findPaginatedPets({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
+export const useAddPet = (options?: Omit, TContext>, "mutationFn">) => useMutation, TContext>({ mutationFn: clientOptions => addPet(clientOptions) as unknown as Promise, ...options });
+export const usePostNotDefined = (options?: Omit, TContext>, "mutationFn">) => useMutation, TContext>({ mutationFn: clientOptions => postNotDefined(clientOptions) as unknown as Promise, ...options });
+export const useDeletePet = (options?: Omit, TContext>, "mutationFn">) => useMutation, TContext>({ mutationFn: clientOptions => deletePet(clientOptions) as unknown as Promise, ...options });
"
`;
@@ -88,19 +60,10 @@ import * as Common from "./common";
import { type QueryClient, useQuery, useSuspenseQuery, useMutation, UseQueryResult, UseQueryOptions, UseMutationOptions, UseMutationResult } from "@tanstack/react-query";
import { client, findPets, addPet, getNotDefined, postNotDefined, findPetById, deletePet, findPaginatedPets } from "../requests/services.gen";
import { Pet, NewPet, Error, FindPetsData, FindPetsResponse, FindPetsError, AddPetData, AddPetResponse, AddPetError, GetNotDefinedResponse, GetNotDefinedError, PostNotDefinedResponse, PostNotDefinedError, FindPetByIdData, FindPetByIdResponse, FindPetByIdError, DeletePetData, DeletePetResponse, DeletePetError, FindPaginatedPetsData, FindPaginatedPetsResponse, FindPaginatedPetsError } from "../requests/types.gen";
-export const useFindPetsSuspense = = unknown[]>({ query, client }: {
- query?: { limit?: number; tags?: string[]; };
- client?: Client;
-} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseFindPetsKeyFn({ query, client }, queryKey), queryFn: () => findPets({ query, client }).then(response => response.data as TData) as TData, ...options });
-export const useGetNotDefinedSuspense = = unknown[]>({}: {} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseGetNotDefinedKeyFn({}, queryKey), queryFn: () => getNotDefined({}).then(response => response.data as TData) as TData, ...options });
-export const useFindPetByIdSuspense = = unknown[]>({ path, client }: {
- path: { id: number; };
- client?: Client;
-}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseFindPetByIdKeyFn({ path, client }, queryKey), queryFn: () => findPetById({ path, client }).then(response => response.data as TData) as TData, ...options });
-export const useFindPaginatedPetsSuspense = = unknown[]>({ query, client }: {
- query?: { limit?: number; page?: number; tags?: string[]; };
- client?: Client;
-} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseFindPaginatedPetsKeyFn({ query, client }, queryKey), queryFn: () => findPaginatedPets({ query, client }).then(response => response.data as TData) as TData, ...options });
+export const useFindPetsSuspense = = unknown[]>(clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseFindPetsKeyFn(clientOptions, queryKey), queryFn: () => findPets({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
+export const useGetNotDefinedSuspense = = unknown[]>(clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseGetNotDefinedKeyFn(clientOptions, queryKey), queryFn: () => getNotDefined({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
+export const useFindPetByIdSuspense = = unknown[]>(clientOptions: Options, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseFindPetByIdKeyFn(clientOptions, queryKey), queryFn: () => findPetById({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
+export const useFindPaginatedPetsSuspense = = unknown[]>(clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseFindPaginatedPetsKeyFn(clientOptions, queryKey), queryFn: () => findPaginatedPets({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
"
`;
@@ -111,18 +74,9 @@ import * as Common from "./common";
import { type QueryClient, useQuery, useSuspenseQuery, useMutation, UseQueryResult, UseQueryOptions, UseMutationOptions, UseMutationResult } from "@tanstack/react-query";
import { client, findPets, addPet, getNotDefined, postNotDefined, findPetById, deletePet, findPaginatedPets } from "../requests/services.gen";
import { Pet, NewPet, Error, FindPetsData, FindPetsResponse, FindPetsError, AddPetData, AddPetResponse, AddPetError, GetNotDefinedResponse, GetNotDefinedError, PostNotDefinedResponse, PostNotDefinedError, FindPetByIdData, FindPetByIdResponse, FindPetByIdError, DeletePetData, DeletePetResponse, DeletePetError, FindPaginatedPetsData, FindPaginatedPetsResponse, FindPaginatedPetsError } from "../requests/types.gen";
-export const prefetchUseFindPets = (queryClient: QueryClient, { query, client }: {
- query?: { limit?: number; tags?: string[]; };
- client?: Client;
-} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseFindPetsKeyFn({ query, client }), queryFn: () => findPets({ query, client }) });
-export const prefetchUseGetNotDefined = (queryClient: QueryClient, {}: {} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseGetNotDefinedKeyFn({}), queryFn: () => getNotDefined({}) });
-export const prefetchUseFindPetById = (queryClient: QueryClient, { path, client }: {
- path: { id: number; };
- client?: Client;
-}) => queryClient.prefetchQuery({ queryKey: Common.UseFindPetByIdKeyFn({ path, client }), queryFn: () => findPetById({ path, client }) });
-export const prefetchUseFindPaginatedPets = (queryClient: QueryClient, { query, client }: {
- query?: { limit?: number; page?: number; tags?: string[]; };
- client?: Client;
-} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseFindPaginatedPetsKeyFn({ query, client }), queryFn: () => findPaginatedPets({ query, client }) });
+export const prefetchUseFindPets = (queryClient: QueryClient, clientOptions: Options = {}) => queryClient.prefetchQuery({ queryKey: Common.UseFindPetsKeyFn(clientOptions), queryFn: () => findPets({ ...clientOptions }).then(response => response.data) });
+export const prefetchUseGetNotDefined = (queryClient: QueryClient, clientOptions: Options = {}) => queryClient.prefetchQuery({ queryKey: Common.UseGetNotDefinedKeyFn(clientOptions), queryFn: () => getNotDefined({ ...clientOptions }).then(response => response.data) });
+export const prefetchUseFindPetById = (queryClient: QueryClient, clientOptions: Options) => queryClient.prefetchQuery({ queryKey: Common.UseFindPetByIdKeyFn(clientOptions), queryFn: () => findPetById({ ...clientOptions }).then(response => response.data) });
+export const prefetchUseFindPaginatedPets = (queryClient: QueryClient, clientOptions: Options = {}) => queryClient.prefetchQuery({ queryKey: Common.UseFindPaginatedPetsKeyFn(clientOptions), queryFn: () => findPaginatedPets({ ...clientOptions }).then(response => response.data) });
"
`;
diff --git a/tests/__snapshots__/generate.test.ts.snap b/tests/__snapshots__/generate.test.ts.snap
index d52f9fd..923d6fe 100644
--- a/tests/__snapshots__/generate.test.ts.snap
+++ b/tests/__snapshots__/generate.test.ts.snap
@@ -3,34 +3,25 @@
exports[`generate > common.ts 1`] = `
"// generated with @7nohe/openapi-react-query-codegen@1.0.0
-import { Client } from "@hey-api/client-fetch";
+import { Options } from "@hey-api/client-fetch";
import { UseQueryResult } from "@tanstack/react-query";
import { addPet, deletePet, findPaginatedPets, findPetById, findPets, getNotDefined, postNotDefined } from "../requests/services.gen";
export type FindPetsDefaultResponse = Awaited>["data"];
export type FindPetsQueryResult = UseQueryResult;
export const useFindPetsKey = "FindPets";
-export const UseFindPetsKeyFn = ({ query, client }: {
- query?: { limit?: number; tags?: string[]; };
- client?: Client;
-} = {}, queryKey?: Array) => [useFindPetsKey, ...(queryKey ?? [{ query, client }])];
+export const UseFindPetsKeyFn = (clientOptions: Options = {}, queryKey?: Array) => [useFindPetsKey, ...(queryKey ?? [clientOptions])];
export type GetNotDefinedDefaultResponse = Awaited>["data"];
export type GetNotDefinedQueryResult = UseQueryResult;
export const useGetNotDefinedKey = "GetNotDefined";
-export const UseGetNotDefinedKeyFn = ({ }: {} = {}, queryKey?: Array) => [useGetNotDefinedKey, ...(queryKey ?? [{}])];
+export const UseGetNotDefinedKeyFn = (clientOptions: Options = {}, queryKey?: Array) => [useGetNotDefinedKey, ...(queryKey ?? [clientOptions])];
export type FindPetByIdDefaultResponse = Awaited>["data"];
export type FindPetByIdQueryResult = UseQueryResult;
export const useFindPetByIdKey = "FindPetById";
-export const UseFindPetByIdKeyFn = ({ path, client }: {
- path: { id: number; };
- client?: Client;
-}, queryKey?: Array) => [useFindPetByIdKey, ...(queryKey ?? [{ path, client }])];
+export const UseFindPetByIdKeyFn = (clientOptions: Options, queryKey?: Array) => [useFindPetByIdKey, ...(queryKey ?? [clientOptions])];
export type FindPaginatedPetsDefaultResponse = Awaited>["data"];
export type FindPaginatedPetsQueryResult = UseQueryResult;
export const useFindPaginatedPetsKey = "FindPaginatedPets";
-export const UseFindPaginatedPetsKeyFn = ({ query, client }: {
- query?: { limit?: number; page?: number; tags?: string[]; };
- client?: Client;
-} = {}, queryKey?: Array) => [useFindPaginatedPetsKey, ...(queryKey ?? [{ query, client }])];
+export const UseFindPaginatedPetsKeyFn = (clientOptions: Options = {}, queryKey?: Array) => [useFindPaginatedPetsKey, ...(queryKey ?? [clientOptions])];
export type AddPetMutationResult = Awaited>;
export type PostNotDefinedMutationResult = Awaited>;
export type DeletePetMutationResult = Awaited>;
@@ -40,23 +31,15 @@ export type DeletePetMutationResult = Awaited>;
exports[`generate > ensureQueryData.ts 1`] = `
"// generated with @7nohe/openapi-react-query-codegen@1.0.0
-import { Client } from "@hey-api/client-fetch";
+import { Options } from "@hey-api/client-fetch";
import { type QueryClient } from "@tanstack/react-query";
import { findPaginatedPets, findPetById, findPets, getNotDefined } from "../requests/services.gen";
+import { FindPaginatedPetsData, FindPetByIdData, FindPetsData } from "../requests/types.gen";
import * as Common from "./common";
-export const ensureUseFindPetsData = (queryClient: QueryClient, { query, client }: {
- query?: { limit?: number; tags?: string[]; };
- client?: Client;
-} = {}) => queryClient.ensureQueryData({ queryKey: Common.UseFindPetsKeyFn({ query, client }), queryFn: () => findPets({ query, client }) });
-export const ensureUseGetNotDefinedData = (queryClient: QueryClient, { }: {} = {}) => queryClient.ensureQueryData({ queryKey: Common.UseGetNotDefinedKeyFn({}), queryFn: () => getNotDefined({}) });
-export const ensureUseFindPetByIdData = (queryClient: QueryClient, { path, client }: {
- path: { id: number; };
- client?: Client;
-}) => queryClient.ensureQueryData({ queryKey: Common.UseFindPetByIdKeyFn({ path, client }), queryFn: () => findPetById({ path, client }) });
-export const ensureUseFindPaginatedPetsData = (queryClient: QueryClient, { query, client }: {
- query?: { limit?: number; page?: number; tags?: string[]; };
- client?: Client;
-} = {}) => queryClient.ensureQueryData({ queryKey: Common.UseFindPaginatedPetsKeyFn({ query, client }), queryFn: () => findPaginatedPets({ query, client }) });
+export const ensureUseFindPetsData = (queryClient: QueryClient, clientOptions: Options = {}) => queryClient.ensureQueryData({ queryKey: Common.UseFindPetsKeyFn(clientOptions), queryFn: () => findPets({ ...clientOptions }).then(response => response.data) });
+export const ensureUseGetNotDefinedData = (queryClient: QueryClient, clientOptions: Options = {}) => queryClient.ensureQueryData({ queryKey: Common.UseGetNotDefinedKeyFn(clientOptions), queryFn: () => getNotDefined({ ...clientOptions }).then(response => response.data) });
+export const ensureUseFindPetByIdData = (queryClient: QueryClient, clientOptions: Options) => queryClient.ensureQueryData({ queryKey: Common.UseFindPetByIdKeyFn(clientOptions), queryFn: () => findPetById({ ...clientOptions }).then(response => response.data) });
+export const ensureUseFindPaginatedPetsData = (queryClient: QueryClient, clientOptions: Options = {}) => queryClient.ensureQueryData({ queryKey: Common.UseFindPaginatedPetsKeyFn(clientOptions), queryFn: () => findPaginatedPets({ ...clientOptions }).then(response => response.data) });
"
`;
@@ -71,88 +54,64 @@ export * from "./queries";
exports[`generate > infiniteQueries.ts 1`] = `
"// generated with @7nohe/openapi-react-query-codegen@1.0.0
+import { Options } from "@hey-api/client-fetch";
+import { findPaginatedPets } from "../requests/services.gen";
+import { FindPaginatedPetsData } from "../requests/types.gen";
+import * as Common from "./common";
+export const useFindPaginatedPetsInfinite = , TError = unknown, TQueryKey extends Array = unknown[]>(clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useInfiniteQuery({
+ queryKey: Common.UseFindPaginatedPetsKeyFn(clientOptions, queryKey), queryFn: ({ pageParam }) => findPaginatedPets({ ...clientOptions, query: { ...clientOptions.query, page: pageParam as number } }).then(response => response.data as TData) as TData, initialPageParam: "initial", getNextPageParam: response => (response as {
+ meta: {
+ next: number;
+ };
+ }).meta.next, ...options
+});
"
`;
exports[`generate > prefetch.ts 1`] = `
"// generated with @7nohe/openapi-react-query-codegen@1.0.0
-import { Client } from "@hey-api/client-fetch";
+import { Options } from "@hey-api/client-fetch";
import { type QueryClient } from "@tanstack/react-query";
import { findPaginatedPets, findPetById, findPets, getNotDefined } from "../requests/services.gen";
+import { FindPaginatedPetsData, FindPetByIdData, FindPetsData } from "../requests/types.gen";
import * as Common from "./common";
-export const prefetchUseFindPets = (queryClient: QueryClient, { query, client }: {
- query?: { limit?: number; tags?: string[]; };
- client?: Client;
-} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseFindPetsKeyFn({ query, client }), queryFn: () => findPets({ query, client }) });
-export const prefetchUseGetNotDefined = (queryClient: QueryClient, { }: {} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseGetNotDefinedKeyFn({}), queryFn: () => getNotDefined({}) });
-export const prefetchUseFindPetById = (queryClient: QueryClient, { path, client }: {
- path: { id: number; };
- client?: Client;
-}) => queryClient.prefetchQuery({ queryKey: Common.UseFindPetByIdKeyFn({ path, client }), queryFn: () => findPetById({ path, client }) });
-export const prefetchUseFindPaginatedPets = (queryClient: QueryClient, { query, client }: {
- query?: { limit?: number; page?: number; tags?: string[]; };
- client?: Client;
-} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseFindPaginatedPetsKeyFn({ query, client }), queryFn: () => findPaginatedPets({ query, client }) });
+export const prefetchUseFindPets = (queryClient: QueryClient, clientOptions: Options = {}) => queryClient.prefetchQuery({ queryKey: Common.UseFindPetsKeyFn(clientOptions), queryFn: () => findPets({ ...clientOptions }).then(response => response.data) });
+export const prefetchUseGetNotDefined = (queryClient: QueryClient, clientOptions: Options = {}) => queryClient.prefetchQuery({ queryKey: Common.UseGetNotDefinedKeyFn(clientOptions), queryFn: () => getNotDefined({ ...clientOptions }).then(response => response.data) });
+export const prefetchUseFindPetById = (queryClient: QueryClient, clientOptions: Options) => queryClient.prefetchQuery({ queryKey: Common.UseFindPetByIdKeyFn(clientOptions), queryFn: () => findPetById({ ...clientOptions }).then(response => response.data) });
+export const prefetchUseFindPaginatedPets = (queryClient: QueryClient, clientOptions: Options = {}) => queryClient.prefetchQuery({ queryKey: Common.UseFindPaginatedPetsKeyFn(clientOptions), queryFn: () => findPaginatedPets({ ...clientOptions }).then(response => response.data) });
"
`;
exports[`generate > queries.ts 1`] = `
"// generated with @7nohe/openapi-react-query-codegen@1.0.0
-import { Client, Config, RequestOptionsBase } from "@hey-api/client-fetch";
+import { Options } from "@hey-api/client-fetch";
import { useMutation, UseMutationOptions, useQuery, UseQueryOptions } from "@tanstack/react-query";
import { addPet, deletePet, findPaginatedPets, findPetById, findPets, getNotDefined, postNotDefined } from "../requests/services.gen";
-import { NewPet } from "../requests/types.gen";
+import { AddPetData, DeletePetData, FindPaginatedPetsData, FindPetByIdData, FindPetsData } from "../requests/types.gen";
import * as Common from "./common";
-export const useFindPets = = unknown[]>({ query, client }: {
- query?: { limit?: number; tags?: string[]; };
- client?: Client;
-} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPetsKeyFn({ query, client }, queryKey), queryFn: () => findPets({ query, client }).then(response => response.data as TData) as TData, ...options });
-export const useGetNotDefined = = unknown[]>({ }: {} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseGetNotDefinedKeyFn({}, queryKey), queryFn: () => getNotDefined({}).then(response => response.data as TData) as TData, ...options });
-export const useFindPetById = = unknown[]>({ path, client }: {
- path: { id: number; };
- client?: Client;
-}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPetByIdKeyFn({ path, client }, queryKey), queryFn: () => findPetById({ path, client }).then(response => response.data as TData) as TData, ...options });
-export const useFindPaginatedPets = = unknown[]>({ query, client }: {
- query?: { limit?: number; page?: number; tags?: string[]; };
- client?: Client;
-} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPaginatedPetsKeyFn({ query, client }, queryKey), queryFn: () => findPaginatedPets({ query, client }).then(response => response.data as TData) as TData, ...options });
-export const useAddPet = (options?: Omit, "mutationFn">) => useMutation({ mutationFn: ({ body }) => addPet({ body }) as unknown as Promise, ...options });
-export const usePostNotDefined = (options?: Omit, "mutationFn">) => useMutation({ mutationFn: ({ }) => postNotDefined({}) as unknown as Promise, ...options });
-export const useDeletePet = (options?: Omit & Config & { headers: Headers; }>;
-}, TContext>, "mutationFn">) => useMutation & Config & { headers: Headers; }>;
-}, TContext>({ mutationFn: ({ path, client }) => deletePet({ path, client }) as unknown as Promise, ...options });
+export const useFindPets = = unknown[]>(clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPetsKeyFn(clientOptions, queryKey), queryFn: () => findPets({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
+export const useGetNotDefined = = unknown[]>(clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseGetNotDefinedKeyFn(clientOptions, queryKey), queryFn: () => getNotDefined({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
+export const useFindPetById = = unknown[]>(clientOptions: Options, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPetByIdKeyFn(clientOptions, queryKey), queryFn: () => findPetById({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
+export const useFindPaginatedPets = = unknown[]>(clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseFindPaginatedPetsKeyFn(clientOptions, queryKey), queryFn: () => findPaginatedPets({ ...clientOptions }).then(response => response.data as TData) as TData, ...options });
+export const useAddPet = (options?: Omit, TContext>, "mutationFn">) => useMutation, TContext>({ mutationFn: clientOptions => addPet(clientOptions) as unknown as Promise, ...options });
+export const usePostNotDefined = (options?: Omit, TContext>, "mutationFn">) => useMutation, TContext>({ mutationFn: clientOptions => postNotDefined(clientOptions) as unknown as Promise, ...options });
+export const useDeletePet = (options?: Omit, TContext>, "mutationFn">) => useMutation, TContext>({ mutationFn: clientOptions => deletePet(clientOptions) as unknown as Promise, ...options });
"
`;
exports[`generate > suspense.ts 1`] = `
"// generated with @7nohe/openapi-react-query-codegen@1.0.0
-import { Client } from "@hey-api/client-fetch";
+import { Options } from "@hey-api/client-fetch";
import { UseQueryOptions, useSuspenseQuery } from "@tanstack/react-query";
import { findPaginatedPets, findPetById, findPets, getNotDefined } from "../requests/services.gen";
+import { FindPaginatedPetsData, FindPetByIdData, FindPetsData } from "../requests/types.gen";
import * as Common from "./common";
-export const useFindPetsSuspense = = unknown[]>({ query, client }: {
- query?: { limit?: number; tags?: string[]; };
- client?: Client;
-} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseFindPetsKeyFn({ query, client }, queryKey), queryFn: () => findPets({ query, client }).then(response => response.data as TData) as TData, ...options });
-export const useGetNotDefinedSuspense =