@7nohe/openapi-react-query-codegen 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## Features
8
8
 
9
- - Generates custom react hooks that use React Query's `useQuery`, `useSuspenseQuery` and `useMutation` hooks
9
+ - Generates custom react hooks that use React Query's `useQuery`, `useSuspenseQuery`, `useMutation` and `useInfiniteQuery` hooks
10
10
  - Generates query keys and functions for query caching
11
11
  - Generates pure TypeScript clients generated by [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts)
12
12
 
@@ -45,18 +45,20 @@ Options:
45
45
  -V, --version output the version number
46
46
  -i, --input <value> OpenAPI specification, can be a path, url or string content (required)
47
47
  -o, --output <value> Output directory (default: "openapi")
48
- -c, --client <value> HTTP client to generate [fetch, xhr, node, axios, angular] (default: "fetch")
48
+ -c, --client <value> HTTP client to generate (choices: "angular", "axios", "fetch", "node", "xhr", default: "fetch")
49
49
  --request <value> Path to custom request file
50
- --format <value> Process output folder with formatter? ['biome', 'prettier']
51
- --lint <value> Process output folder with linter? ['eslint', 'biome']
50
+ --format <value> Process output folder with formatter? (choices: "biome", "prettier")
51
+ --lint <value> Process output folder with linter? (choices: "biome", "eslint")
52
52
  --operationId Use operation ID to generate operation names?
53
- --serviceResponse <value> Define shape of returned value from service calls ['body', 'response'] (default: "body")
53
+ --serviceResponse <value> Define shape of returned value from service calls (choices: "body", "response", default: "body")
54
54
  --base <value> Manually set base in OpenAPI config instead of inferring from server value
55
- --enums <value> Generate JavaScript objects from enum definitions? ['javascript', 'typescript']
55
+ --enums <value> Generate JavaScript objects from enum definitions? (choices: "javascript", "typescript")
56
56
  --useDateType Use Date type instead of string for date types for models, this will not convert the data to a Date object
57
- --debug Enable debug mode
58
- --noSchemas Disable generating schemas for request and response objects
59
- --schemaTypes <value> Define the type of schema generation ['form', 'json'] (default: "json")
57
+ --debug Run in debug mode?
58
+ --noSchemas Disable generating JSON schemas
59
+ --schemaType <value> Type of JSON schema [Default: 'json'] (choices: "form", "json")
60
+ --pageParam <value> Name of the query parameter used for pagination (default: "page")
61
+ --nextPageParam <value> Name of the response parameter used for next page (default: "nextPage")
60
62
  -h, --help display help for command
61
63
  ```
62
64
 
@@ -234,6 +236,72 @@ function App() {
234
236
  export default App;
235
237
  ```
236
238
 
239
+ ##### Using Infinite Query hooks
240
+
241
+ This feature will generate a function in infiniteQueries.ts when the name specified by the `pageParam` option exists in the query parameters and the name specified by the `nextPageParam` option exists in the response.
242
+
243
+ Example Schema:
244
+
245
+ ```yml
246
+ paths:
247
+ /paginated-pets:
248
+ get:
249
+ description: |
250
+ Returns paginated pets from the system that the user has access to
251
+ operationId: findPaginatedPets
252
+ parameters:
253
+ - name: page
254
+ in: query
255
+ description: page number
256
+ required: false
257
+ schema:
258
+ type: integer
259
+ format: int32
260
+ - name: tags
261
+ in: query
262
+ description: tags to filter by
263
+ required: false
264
+ style: form
265
+ schema:
266
+ type: array
267
+ items:
268
+ type: string
269
+ - name: limit
270
+ in: query
271
+ description: maximum number of results to return
272
+ required: false
273
+ schema:
274
+ type: integer
275
+ format: int32
276
+ responses:
277
+ '200':
278
+ description: pet response
279
+ content:
280
+ application/json:
281
+ schema:
282
+ type: object
283
+ properties:
284
+ pets:
285
+ type: array
286
+ items:
287
+ $ref: '#/components/schemas/Pet'
288
+ nextPage:
289
+ type: integer
290
+ format: int32
291
+ minimum: 1
292
+ ```
293
+
294
+ Usage of Generated Hooks:
295
+
296
+ ```ts
297
+ import { useDefaultServiceFindPaginatedPetsInfinite } from "@/openapi/queries/infiniteQueries";
298
+
299
+ const { data, fetchNextPage } = useDefaultServiceFindPaginatedPetsInfinite({
300
+ limit: 10,
301
+ tags: [],
302
+ });
303
+ ```
304
+
237
305
  ##### Runtime Configuration
238
306
 
239
307
  You can modify the default values used by the generated service calls by modifying the OpenAPI configuration singleton object.
package/dist/cli.mjs CHANGED
@@ -34,6 +34,8 @@ async function setupProgram() {
34
34
  .option("--debug", "Run in debug mode?")
35
35
  .option("--noSchemas", "Disable generating JSON schemas")
36
36
  .addOption(new Option("--schemaType <value>", "Type of JSON schema [Default: 'json']").choices(["form", "json"]))
37
+ .option("--pageParam <value>", "Name of the query parameter used for pagination", "page")
38
+ .option("--nextPageParam <value>", "Name of the response parameter used for next page", "nextPage")
37
39
  .parse();
38
40
  const options = program.opts();
39
41
  await generate(options, version);
@@ -5,6 +5,7 @@ export const serviceFileName = "services.gen";
5
5
  export const modalsFileName = "types.gen";
6
6
  export const OpenApiRqFiles = {
7
7
  queries: "queries",
8
+ infiniteQueries: "infiniteQueries",
8
9
  common: "common",
9
10
  suspense: "suspense",
10
11
  index: "index",
@@ -1,7 +1,7 @@
1
1
  import { createPrefetch } from "./createPrefetch.mjs";
2
2
  import { createUseMutation } from "./createUseMutation.mjs";
3
3
  import { createUseQuery } from "./createUseQuery.mjs";
4
- export const createExports = (service) => {
4
+ export const createExports = (service, pageParam, nextPageParam) => {
5
5
  const { klasses } = service;
6
6
  const methods = klasses.flatMap((k) => k.methods);
7
7
  const allGet = methods.filter((m) => m.httpMethodName.toUpperCase().includes("GET"));
@@ -9,7 +9,7 @@ export const createExports = (service) => {
9
9
  const allPut = methods.filter((m) => m.httpMethodName.toUpperCase().includes("PUT"));
10
10
  const allPatch = methods.filter((m) => m.httpMethodName.toUpperCase().includes("PATCH"));
11
11
  const allDelete = methods.filter((m) => m.httpMethodName.toUpperCase().includes("DELETE"));
12
- const allGetQueries = allGet.map((m) => createUseQuery(m));
12
+ const allGetQueries = allGet.map((m) => createUseQuery(m, pageParam, nextPageParam));
13
13
  const allPrefetchQueries = allGet.map((m) => createPrefetch(m));
14
14
  const allPostMutations = allPost.map((m) => createUseMutation(m));
15
15
  const allPutMutations = allPut.map((m) => createUseMutation(m));
@@ -37,6 +37,9 @@ export const createExports = (service) => {
37
37
  mutationHook,
38
38
  ]);
39
39
  const mainExports = [...mainQueries, ...mainMutations];
40
+ const infiniteQueriesExports = allQueries
41
+ .flatMap(({ infiniteQueryHook }) => [infiniteQueryHook])
42
+ .filter(Boolean);
40
43
  const suspenseQueries = allQueries.flatMap(({ suspenseQueryHook }) => [
41
44
  suspenseQueryHook,
42
45
  ]);
@@ -54,6 +57,10 @@ export const createExports = (service) => {
54
57
  * Main exports are the hooks that are used in the components
55
58
  */
56
59
  mainExports,
60
+ /**
61
+ * Infinite queries exports are the hooks that are used in the infinite scroll components
62
+ */
63
+ infiniteQueriesExports,
57
64
  /**
58
65
  * Suspense exports are the hooks that are used in the suspense components
59
66
  */
@@ -5,7 +5,7 @@ import { OpenApiRqFiles } from "./constants.mjs";
5
5
  import { createExports } from "./createExports.mjs";
6
6
  import { createImports } from "./createImports.mjs";
7
7
  import { getServices } from "./service.mjs";
8
- const createSourceFile = async (outputPath, serviceEndName) => {
8
+ const createSourceFile = async (outputPath, serviceEndName, pageParam, nextPageParam) => {
9
9
  const project = new Project({
10
10
  // Optionally specify compiler options, tsconfig.json, in-memory file system, and more here.
11
11
  // If you initialize with a tsconfig.json, then it will automatically populate the project
@@ -20,25 +20,28 @@ const createSourceFile = async (outputPath, serviceEndName) => {
20
20
  serviceEndName,
21
21
  project,
22
22
  });
23
- const exports = createExports(service);
23
+ const exports = createExports(service, pageParam, nextPageParam);
24
24
  const commonSource = ts.factory.createSourceFile([...imports, ...exports.allCommon], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None);
25
25
  const commonImport = ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(false, ts.factory.createIdentifier("* as Common"), undefined), ts.factory.createStringLiteral(`./${OpenApiRqFiles.common}`), undefined);
26
26
  const commonExport = ts.factory.createExportDeclaration(undefined, false, undefined, ts.factory.createStringLiteral(`./${OpenApiRqFiles.common}`), undefined);
27
27
  const queriesExport = ts.factory.createExportDeclaration(undefined, false, undefined, ts.factory.createStringLiteral(`./${OpenApiRqFiles.queries}`), undefined);
28
28
  const mainSource = ts.factory.createSourceFile([commonImport, ...imports, ...exports.mainExports], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None);
29
+ const infiniteQueriesSource = ts.factory.createSourceFile([commonImport, ...imports, ...exports.infiniteQueriesExports], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None);
29
30
  const suspenseSource = ts.factory.createSourceFile([commonImport, ...imports, ...exports.suspenseExports], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None);
30
31
  const indexSource = ts.factory.createSourceFile([commonExport, queriesExport], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None);
31
32
  const prefetchSource = ts.factory.createSourceFile([commonImport, ...imports, ...exports.allPrefetchExports], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None);
32
33
  return {
33
34
  commonSource,
35
+ infiniteQueriesSource,
34
36
  mainSource,
35
37
  suspenseSource,
36
38
  indexSource,
37
39
  prefetchSource,
38
40
  };
39
41
  };
40
- export const createSource = async ({ outputPath, version, serviceEndName, }) => {
42
+ export const createSource = async ({ outputPath, version, serviceEndName, pageParam, nextPageParam, }) => {
41
43
  const queriesFile = ts.createSourceFile(`${OpenApiRqFiles.queries}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
44
+ const infiniteQueriesFile = ts.createSourceFile(`${OpenApiRqFiles.infiniteQueries}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
42
45
  const commonFile = ts.createSourceFile(`${OpenApiRqFiles.common}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
43
46
  const suspenseFile = ts.createSourceFile(`${OpenApiRqFiles.suspense}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
44
47
  const indexFile = ts.createSourceFile(`${OpenApiRqFiles.index}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
@@ -47,12 +50,14 @@ export const createSource = async ({ outputPath, version, serviceEndName, }) =>
47
50
  newLine: ts.NewLineKind.LineFeed,
48
51
  removeComments: false,
49
52
  });
50
- const { commonSource, mainSource, suspenseSource, indexSource, prefetchSource, } = await createSourceFile(outputPath, serviceEndName);
53
+ const { commonSource, mainSource, infiniteQueriesSource, suspenseSource, indexSource, prefetchSource, } = await createSourceFile(outputPath, serviceEndName, pageParam, nextPageParam);
51
54
  const comment = `// generated with @7nohe/openapi-react-query-codegen@${version} \n\n`;
52
55
  const commonResult = comment +
53
56
  printer.printNode(ts.EmitHint.Unspecified, commonSource, commonFile);
54
57
  const mainResult = comment +
55
58
  printer.printNode(ts.EmitHint.Unspecified, mainSource, queriesFile);
59
+ const infiniteQueriesResult = comment +
60
+ printer.printNode(ts.EmitHint.Unspecified, infiniteQueriesSource, infiniteQueriesFile);
56
61
  const suspenseResult = comment +
57
62
  printer.printNode(ts.EmitHint.Unspecified, suspenseSource, suspenseFile);
58
63
  const indexResult = comment +
@@ -68,6 +73,10 @@ export const createSource = async ({ outputPath, version, serviceEndName, }) =>
68
73
  name: `${OpenApiRqFiles.common}.ts`,
69
74
  content: commonResult,
70
75
  },
76
+ {
77
+ name: `${OpenApiRqFiles.infiniteQueries}.ts`,
78
+ content: infiniteQueriesResult,
79
+ },
71
80
  {
72
81
  name: `${OpenApiRqFiles.queries}.ts`,
73
82
  content: mainResult,
@@ -28,13 +28,15 @@ export const createApiResponseType = ({ className, methodName, }) => {
28
28
  responseDataType,
29
29
  };
30
30
  };
31
- export function getRequestParamFromMethod(method) {
31
+ export function getRequestParamFromMethod(method, pageParam) {
32
32
  if (!method.getParameters().length) {
33
33
  return null;
34
34
  }
35
35
  const params = method.getParameters().flatMap((param) => {
36
36
  const paramNodes = extractPropertiesFromObjectParam(param);
37
- return paramNodes.map((refParam) => ({
37
+ return paramNodes
38
+ .filter((p) => p.name !== pageParam)
39
+ .map((refParam) => ({
38
40
  name: refParam.name,
39
41
  typeName: getShortType(refParam.type.getText()),
40
42
  optional: refParam.optional,
@@ -88,20 +90,33 @@ export function createQueryKeyFromMethod({ method, className, }) {
88
90
  * @param queryString The type of query to use from react-query
89
91
  * @param suffix The suffix to append to the hook name
90
92
  */
91
- export function createQueryHook({ queryString, suffix, responseDataType, requestParams, method, className, }) {
93
+ export function createQueryHook({ queryString, suffix, responseDataType, requestParams, method, className, pageParam, nextPageParam, }) {
92
94
  const methodName = getNameFromMethod(method);
93
95
  const customHookName = hookNameFromMethod({ method, className });
94
96
  const queryKey = createQueryKeyFromMethod({ method, className });
97
+ if (queryString === "useInfiniteQuery" &&
98
+ (pageParam === undefined || nextPageParam === undefined)) {
99
+ throw new Error("pageParam and nextPageParam are required for infinite queries");
100
+ }
101
+ const isInfiniteQuery = queryString === "useInfiniteQuery";
102
+ const responseDataTypeRef = responseDataType.default;
103
+ const responseDataTypeIdentifier = responseDataTypeRef.typeName;
95
104
  const hookExport = ts.factory.createVariableStatement([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
96
105
  ts.factory.createVariableDeclaration(ts.factory.createIdentifier(`${customHookName}${suffix}`), undefined, undefined, ts.factory.createArrowFunction(undefined, ts.factory.createNodeArray([
97
- responseDataType,
106
+ isInfiniteQuery
107
+ ? ts.factory.createTypeParameterDeclaration(undefined, TData, undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("InfiniteData"), [
108
+ ts.factory.createTypeReferenceNode(responseDataTypeIdentifier),
109
+ ]))
110
+ : responseDataType,
98
111
  ts.factory.createTypeParameterDeclaration(undefined, TError, undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)),
99
112
  ts.factory.createTypeParameterDeclaration(undefined, "TQueryKey", queryKeyConstraint, ts.factory.createArrayTypeNode(ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword))),
100
113
  ]), [
101
114
  ...requestParams,
102
115
  ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier("queryKey"), ts.factory.createToken(ts.SyntaxKind.QuestionToken), queryKeyGenericType),
103
116
  ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier("options"), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Omit"), [
104
- ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("UseQueryOptions"), [
117
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(isInfiniteQuery
118
+ ? "UseInfiniteQueryOptions"
119
+ : "UseQueryOptions"), [
105
120
  ts.factory.createTypeReferenceNode(TData),
106
121
  ts.factory.createTypeReferenceNode(TError),
107
122
  ]),
@@ -110,33 +125,44 @@ export function createQueryHook({ queryString, suffix, responseDataType, request
110
125
  ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("queryFn")),
111
126
  ]),
112
127
  ])),
113
- ], undefined, EqualsOrGreaterThanToken, ts.factory.createCallExpression(ts.factory.createIdentifier(queryString), [
114
- ts.factory.createTypeReferenceNode(TData),
115
- ts.factory.createTypeReferenceNode(TError),
116
- ], [
128
+ ], undefined, EqualsOrGreaterThanToken, ts.factory.createCallExpression(ts.factory.createIdentifier(queryString), isInfiniteQuery
129
+ ? []
130
+ : [
131
+ ts.factory.createTypeReferenceNode(TData),
132
+ ts.factory.createTypeReferenceNode(TError),
133
+ ], [
117
134
  ts.factory.createObjectLiteralExpression([
118
135
  ts.factory.createPropertyAssignment(ts.factory.createIdentifier("queryKey"), ts.factory.createCallExpression(BuildCommonTypeName(getQueryKeyFnName(queryKey)), undefined, method.getParameters().length
119
136
  ? [
120
- ts.factory.createObjectLiteralExpression(method
121
- .getParameters()
122
- .flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
137
+ ts.factory.createObjectLiteralExpression(method.getParameters().flatMap((param) => extractPropertiesFromObjectParam(param)
138
+ .filter((p) => p.name !== pageParam)
139
+ .map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
123
140
  ts.factory.createIdentifier("queryKey"),
124
141
  ]
125
142
  : [ts.factory.createIdentifier("queryKey")])),
126
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier("queryFn"), ts.factory.createArrowFunction(undefined, undefined, [], undefined, EqualsOrGreaterThanToken, ts.factory.createAsExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(className), ts.factory.createIdentifier(methodName)), undefined, method.getParameters().length
143
+ ts.factory.createPropertyAssignment(ts.factory.createIdentifier("queryFn"), ts.factory.createArrowFunction(undefined, undefined, isInfiniteQuery
144
+ ? [
145
+ ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createObjectBindingPattern([
146
+ ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier("pageParam"), undefined),
147
+ ]), undefined, undefined),
148
+ ]
149
+ : [], undefined, EqualsOrGreaterThanToken, ts.factory.createAsExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(className), ts.factory.createIdentifier(methodName)), undefined, method.getParameters().length
127
150
  ? [
128
151
  ts.factory.createObjectLiteralExpression(method
129
152
  .getParameters()
130
- .flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
153
+ .flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => p.name === pageParam
154
+ ? ts.factory.createPropertyAssignment(ts.factory.createIdentifier(p.name), ts.factory.createAsExpression(ts.factory.createIdentifier("pageParam"), ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)))
155
+ : ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
131
156
  ]
132
157
  : undefined), ts.factory.createTypeReferenceNode(TData)))),
158
+ ...createInfiniteQueryParams(pageParam, nextPageParam),
133
159
  ts.factory.createSpreadAssignment(ts.factory.createIdentifier("options")),
134
160
  ]),
135
161
  ]))),
136
162
  ], ts.NodeFlags.Const));
137
163
  return hookExport;
138
164
  }
139
- export const createUseQuery = ({ className, method, jsDoc, }) => {
165
+ export const createUseQuery = ({ className, method, jsDoc }, pageParam, nextPageParam) => {
140
166
  const methodName = getNameFromMethod(method);
141
167
  const queryKey = createQueryKeyFromMethod({ method, className });
142
168
  const { apiResponse: defaultApiResponse, responseDataType } = createApiResponseType({
@@ -144,7 +170,15 @@ export const createUseQuery = ({ className, method, jsDoc, }) => {
144
170
  methodName,
145
171
  });
146
172
  const requestParam = getRequestParamFromMethod(method);
173
+ const infiniteRequestParam = getRequestParamFromMethod(method, pageParam);
147
174
  const requestParams = requestParam ? [requestParam] : [];
175
+ const requestParamNames = requestParams
176
+ .filter((p) => p.name.kind === ts.SyntaxKind.ObjectBindingPattern)
177
+ .map((p) => p.name);
178
+ const requestParamTexts = requestParamNames
179
+ .at(0)
180
+ ?.elements.filter((e) => e.name.kind === ts.SyntaxKind.Identifier)
181
+ .map((e) => e.name.escapedText);
148
182
  const queryHook = createQueryHook({
149
183
  queryString: "useQuery",
150
184
  suffix: "",
@@ -161,8 +195,24 @@ export const createUseQuery = ({ className, method, jsDoc, }) => {
161
195
  method,
162
196
  className,
163
197
  });
198
+ const isInfiniteQuery = requestParamTexts?.includes(pageParam) ?? false;
199
+ const infiniteQueryHook = isInfiniteQuery
200
+ ? createQueryHook({
201
+ queryString: "useInfiniteQuery",
202
+ suffix: "Infinite",
203
+ responseDataType,
204
+ requestParams: infiniteRequestParam ? [infiniteRequestParam] : [],
205
+ method,
206
+ className,
207
+ pageParam,
208
+ nextPageParam,
209
+ })
210
+ : undefined;
164
211
  const hookWithJsDoc = addJSDocToNode(queryHook, jsDoc);
165
212
  const suspenseHookWithJsDoc = addJSDocToNode(suspenseQueryHook, jsDoc);
213
+ const infiniteHookWithJsDoc = infiniteQueryHook
214
+ ? addJSDocToNode(infiniteQueryHook, jsDoc)
215
+ : undefined;
166
216
  const returnTypeExport = createReturnTypeExport({
167
217
  className,
168
218
  methodName,
@@ -180,6 +230,7 @@ export const createUseQuery = ({ className, method, jsDoc, }) => {
180
230
  key: queryKeyExport,
181
231
  queryHook: hookWithJsDoc,
182
232
  suspenseQueryHook: suspenseHookWithJsDoc,
233
+ infiniteQueryHook: infiniteHookWithJsDoc,
183
234
  queryKeyFn,
184
235
  };
185
236
  };
@@ -206,3 +257,16 @@ function queryKeyFn(queryKey, method) {
206
257
  : ts.factory.createArrayLiteralExpression([])))),
207
258
  ], false);
208
259
  }
260
+ function createInfiniteQueryParams(pageParam, nextPageParam) {
261
+ if (pageParam === undefined || nextPageParam === undefined) {
262
+ return [];
263
+ }
264
+ return [
265
+ ts.factory.createPropertyAssignment(ts.factory.createIdentifier("initialPageParam"), ts.factory.createNumericLiteral(1)),
266
+ ts.factory.createPropertyAssignment(ts.factory.createIdentifier("getNextPageParam"),
267
+ // (response) => (response as { nextPage: number }).nextPage,
268
+ ts.factory.createArrowFunction(undefined, undefined, [
269
+ ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier("response"), undefined, undefined),
270
+ ], undefined, EqualsOrGreaterThanToken, ts.factory.createPropertyAccessExpression(ts.factory.createParenthesizedExpression(ts.factory.createAsExpression(ts.factory.createIdentifier("response"), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(`{ ${nextPageParam}: number }`)))), ts.factory.createIdentifier(nextPageParam)))),
271
+ ];
272
+ }
package/dist/generate.mjs CHANGED
@@ -39,6 +39,8 @@ export async function generate(options, version) {
39
39
  outputPath: openApiOutputPath,
40
40
  version,
41
41
  serviceEndName: "Service", // we are hard coding this because changing the service end name was depreciated in @hey-api/openapi-ts
42
+ pageParam: formattedOptions.pageParam,
43
+ nextPageParam: formattedOptions.nextPageParam,
42
44
  });
43
45
  await print(source, formattedOptions);
44
46
  const queriesOutputPath = buildQueriesOutputPath(options.output);
package/package.json CHANGED
@@ -1,23 +1,7 @@
1
1
  {
2
2
  "name": "@7nohe/openapi-react-query-codegen",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "OpenAPI React Query Codegen",
5
- "bin": {
6
- "openapi-rq": "dist/cli.mjs"
7
- },
8
- "type": "module",
9
- "workspaces": [
10
- "examples/*"
11
- ],
12
- "repository": {
13
- "type": "git",
14
- "url": "git+https://github.com/7nohe/openapi-react-query-codegen.git"
15
- },
16
- "homepage": "https://github.com/7nohe/openapi-react-query-codegen",
17
- "bugs": "https://github.com/7nohe/openapi-react-query-codegen/issues",
18
- "files": [
19
- "dist"
20
- ],
21
5
  "keywords": [
22
6
  "codegen",
23
7
  "react-query",
@@ -28,8 +12,24 @@
28
12
  "openapi-typescript-codegen",
29
13
  "@hey-api/openapi-ts"
30
14
  ],
31
- "author": "Daiki Urata (@7nohe)",
15
+ "homepage": "https://github.com/7nohe/openapi-react-query-codegen",
16
+ "bugs": "https://github.com/7nohe/openapi-react-query-codegen/issues",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/7nohe/openapi-react-query-codegen.git"
20
+ },
32
21
  "license": "MIT",
22
+ "author": "Daiki Urata (@7nohe)",
23
+ "type": "module",
24
+ "bin": {
25
+ "openapi-rq": "dist/cli.mjs"
26
+ },
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "workspaces": [
31
+ "examples/*"
32
+ ],
33
33
  "dependencies": {
34
34
  "@hey-api/openapi-ts": "0.45.1"
35
35
  },
@@ -53,7 +53,8 @@
53
53
  "typescript": "5.x"
54
54
  },
55
55
  "engines": {
56
- "node": ">=14"
56
+ "node": ">=14",
57
+ "pnpm": ">=9"
57
58
  },
58
59
  "scripts": {
59
60
  "build": "rimraf dist && tsc -p tsconfig.json",
@@ -61,7 +62,7 @@
61
62
  "lint:fix": "biome check --apply .",
62
63
  "preview": "npm run build && npm -C examples/react-app run generate:api",
63
64
  "release": "npx git-ensure -a && npx bumpp --commit --tag --push",
64
- "test": "vitest --coverage.enabled true",
65
- "snapshot": "vitest --update"
65
+ "snapshot": "vitest --update",
66
+ "test": "vitest --coverage.enabled true"
66
67
  }
67
68
  }