@7nohe/openapi-react-query-codegen 1.6.0 → 1.6.2
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 +24 -19
- package/dist/cli.mjs +1 -0
- package/dist/constants.mjs +1 -0
- package/dist/createExports.mjs +11 -7
- package/dist/{createPrefetch.mjs → createPrefetchOrEnsure.mjs} +12 -8
- package/dist/createSource.mjs +13 -4
- package/dist/createUseQuery.mjs +47 -7
- package/dist/generate.mjs +2 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- Generates custom react hooks that use React Query's `useQuery`, `useSuspenseQuery`, `useMutation` and `useInfiniteQuery` hooks
|
|
10
|
+
- Generates custom functions that use React Query's `ensureQueryData` and `prefetchQuery` functions
|
|
10
11
|
- Generates query keys and functions for query caching
|
|
11
12
|
- Generates pure TypeScript clients generated by [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts)
|
|
12
13
|
|
|
@@ -42,24 +43,25 @@ Usage: openapi-rq [options]
|
|
|
42
43
|
Generate React Query code based on OpenAPI
|
|
43
44
|
|
|
44
45
|
Options:
|
|
45
|
-
-V, --version
|
|
46
|
-
-i, --input <value>
|
|
47
|
-
-o, --output <value>
|
|
48
|
-
-c, --client <value>
|
|
49
|
-
--request <value>
|
|
50
|
-
--format <value>
|
|
51
|
-
--lint <value>
|
|
52
|
-
--operationId
|
|
53
|
-
--serviceResponse <value>
|
|
54
|
-
--base <value>
|
|
55
|
-
--enums <value>
|
|
56
|
-
--enums <value>
|
|
57
|
-
--useDateType
|
|
58
|
-
--debug
|
|
59
|
-
--noSchemas
|
|
60
|
-
--schemaType <value>
|
|
61
|
-
--pageParam <value>
|
|
62
|
-
--nextPageParam <value>
|
|
46
|
+
-V, --version output the version number
|
|
47
|
+
-i, --input <value> OpenAPI specification, can be a path, url or string content (required)
|
|
48
|
+
-o, --output <value> Output directory (default: "openapi")
|
|
49
|
+
-c, --client <value> HTTP client to generate (choices: "angular", "axios", "fetch", "node", "xhr", default: "fetch")
|
|
50
|
+
--request <value> Path to custom request file
|
|
51
|
+
--format <value> Process output folder with formatter? (choices: "biome", "prettier")
|
|
52
|
+
--lint <value> Process output folder with linter? (choices: "biome", "eslint")
|
|
53
|
+
--operationId Use operation ID to generate operation names?
|
|
54
|
+
--serviceResponse <value> Define shape of returned value from service calls (choices: "body", "response", default: "body")
|
|
55
|
+
--base <value> Manually set base in OpenAPI config instead of inferring from server value
|
|
56
|
+
--enums <value> Generate JavaScript objects from enum definitions? ['javascript', 'typescript', 'typescript+namespace']
|
|
57
|
+
--enums <value> Generate JavaScript objects from enum definitions? (choices: "javascript", "typescript")
|
|
58
|
+
--useDateType Use Date type instead of string for date types for models, this will not convert the data to a Date object
|
|
59
|
+
--debug Run in debug mode?
|
|
60
|
+
--noSchemas Disable generating JSON schemas
|
|
61
|
+
--schemaType <value> Type of JSON schema [Default: 'json'] (choices: "form", "json")
|
|
62
|
+
--pageParam <value> Name of the query parameter used for pagination (default: "page")
|
|
63
|
+
--nextPageParam <value> Name of the response parameter used for next page (default: "nextPage")
|
|
64
|
+
--initialPageParam <value> Initial value for the pagination parameter (default: "1")
|
|
63
65
|
-h, --help display help for command
|
|
64
66
|
```
|
|
65
67
|
|
|
@@ -78,9 +80,10 @@ $ openapi-rq -i ./petstore.yaml
|
|
|
78
80
|
- queries
|
|
79
81
|
- index.ts <- main file that exports common types, variables, and queries. Does not export suspense or prefetch hooks
|
|
80
82
|
- common.ts <- common types
|
|
83
|
+
- ensureQueryData.ts <- generated ensureQueryData functions
|
|
81
84
|
- queries.ts <- generated query hooks
|
|
82
85
|
- suspenses.ts <- generated suspense hooks
|
|
83
|
-
- prefetch.ts <- generated prefetch
|
|
86
|
+
- prefetch.ts <- generated prefetch functions learn more about prefetching in in link below
|
|
84
87
|
- requests <- output code generated by @hey-api/openapi-ts
|
|
85
88
|
```
|
|
86
89
|
|
|
@@ -241,6 +244,8 @@ export default App;
|
|
|
241
244
|
|
|
242
245
|
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.
|
|
243
246
|
|
|
247
|
+
The `initialPageParam` option can be specified to set the intial page to load, defaults to 1. The `nextPageParam` supports dot notation for nested values (i.e. `meta.next`).
|
|
248
|
+
|
|
244
249
|
Example Schema:
|
|
245
250
|
|
|
246
251
|
```yml
|
package/dist/cli.mjs
CHANGED
|
@@ -36,6 +36,7 @@ async function setupProgram() {
|
|
|
36
36
|
.addOption(new Option("--schemaType <value>", "Type of JSON schema [Default: 'json']").choices(["form", "json"]))
|
|
37
37
|
.option("--pageParam <value>", "Name of the query parameter used for pagination", "page")
|
|
38
38
|
.option("--nextPageParam <value>", "Name of the response parameter used for next page", "nextPage")
|
|
39
|
+
.option("--initialPageParam <value>", "Initial page value to query", "1")
|
|
39
40
|
.parse();
|
|
40
41
|
const options = program.opts();
|
|
41
42
|
await generate(options, version);
|
package/dist/constants.mjs
CHANGED
package/dist/createExports.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createPrefetchOrEnsure } from "./createPrefetchOrEnsure.mjs";
|
|
2
2
|
import { createUseMutation } from "./createUseMutation.mjs";
|
|
3
3
|
import { createUseQuery } from "./createUseQuery.mjs";
|
|
4
|
-
export const createExports = (service, pageParam, nextPageParam) => {
|
|
4
|
+
export const createExports = (service, pageParam, nextPageParam, initialPageParam) => {
|
|
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,8 +9,9 @@ export const createExports = (service, pageParam, nextPageParam) => {
|
|
|
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, pageParam, nextPageParam));
|
|
13
|
-
const allPrefetchQueries = allGet.map((m) =>
|
|
12
|
+
const allGetQueries = allGet.map((m) => createUseQuery(m, pageParam, nextPageParam, initialPageParam));
|
|
13
|
+
const allPrefetchQueries = allGet.map((m) => createPrefetchOrEnsure({ ...m, functionType: "prefetch" }));
|
|
14
|
+
const allEnsureQueries = allGet.map((m) => createPrefetchOrEnsure({ ...m, functionType: "ensure" }));
|
|
14
15
|
const allPostMutations = allPost.map((m) => createUseMutation(m));
|
|
15
16
|
const allPutMutations = allPut.map((m) => createUseMutation(m));
|
|
16
17
|
const allPatchMutations = allPatch.map((m) => createUseMutation(m));
|
|
@@ -44,9 +45,8 @@ export const createExports = (service, pageParam, nextPageParam) => {
|
|
|
44
45
|
suspenseQueryHook,
|
|
45
46
|
]);
|
|
46
47
|
const suspenseExports = [...suspenseQueries];
|
|
47
|
-
const allPrefetches = allPrefetchQueries.flatMap(({
|
|
48
|
-
|
|
49
|
-
]);
|
|
48
|
+
const allPrefetches = allPrefetchQueries.flatMap(({ hook }) => [hook]);
|
|
49
|
+
const allEnsures = allEnsureQueries.flatMap(({ hook }) => [hook]);
|
|
50
50
|
const allPrefetchExports = [...allPrefetches];
|
|
51
51
|
return {
|
|
52
52
|
/**
|
|
@@ -69,5 +69,9 @@ export const createExports = (service, pageParam, nextPageParam) => {
|
|
|
69
69
|
* Prefetch exports are the hooks that are used in the prefetch components
|
|
70
70
|
*/
|
|
71
71
|
allPrefetchExports,
|
|
72
|
+
/**
|
|
73
|
+
* Ensure exports are the hooks that are used in the loader components
|
|
74
|
+
*/
|
|
75
|
+
allEnsures,
|
|
72
76
|
};
|
|
73
77
|
};
|
|
@@ -3,12 +3,15 @@ import { BuildCommonTypeName, extractPropertiesFromObjectParam, getNameFromMetho
|
|
|
3
3
|
import { createQueryKeyFromMethod, getQueryKeyFnName, getRequestParamFromMethod, hookNameFromMethod, } from "./createUseQuery.mjs";
|
|
4
4
|
import { addJSDocToNode } from "./util.mjs";
|
|
5
5
|
/**
|
|
6
|
-
* Creates a prefetch function for a query
|
|
6
|
+
* Creates a prefetch/ensure function for a query
|
|
7
7
|
*/
|
|
8
|
-
function
|
|
8
|
+
function createPrefetchOrEnsureHook({ requestParams, method, className, functionType, }) {
|
|
9
9
|
const methodName = getNameFromMethod(method);
|
|
10
10
|
const queryName = hookNameFromMethod({ method, className });
|
|
11
|
-
|
|
11
|
+
let customHookName = `prefetch${queryName.charAt(0).toUpperCase() + queryName.slice(1)}`;
|
|
12
|
+
if (functionType === "ensure") {
|
|
13
|
+
customHookName = `ensure${queryName.charAt(0).toUpperCase() + queryName.slice(1)}Data`;
|
|
14
|
+
}
|
|
12
15
|
const queryKey = createQueryKeyFromMethod({ method, className });
|
|
13
16
|
// const
|
|
14
17
|
const hookExport = ts.factory.createVariableStatement(
|
|
@@ -17,7 +20,7 @@ function createPrefetchHook({ requestParams, method, className, }) {
|
|
|
17
20
|
ts.factory.createVariableDeclaration(ts.factory.createIdentifier(customHookName), undefined, undefined, ts.factory.createArrowFunction(undefined, undefined, [
|
|
18
21
|
ts.factory.createParameterDeclaration(undefined, undefined, "queryClient", undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("QueryClient"))),
|
|
19
22
|
...requestParams,
|
|
20
|
-
], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createCallExpression(ts.factory.createIdentifier("
|
|
23
|
+
], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createCallExpression(ts.factory.createIdentifier(`queryClient.${functionType === "prefetch" ? "prefetchQuery" : "ensureQueryData"}`), undefined, [
|
|
21
24
|
ts.factory.createObjectLiteralExpression([
|
|
22
25
|
ts.factory.createPropertyAssignment(ts.factory.createIdentifier("queryKey"), ts.factory.createCallExpression(BuildCommonTypeName(getQueryKeyFnName(queryKey)), undefined, method.getParameters().length
|
|
23
26
|
? [
|
|
@@ -38,16 +41,17 @@ function createPrefetchHook({ requestParams, method, className, }) {
|
|
|
38
41
|
], ts.NodeFlags.Const));
|
|
39
42
|
return hookExport;
|
|
40
43
|
}
|
|
41
|
-
export const
|
|
44
|
+
export const createPrefetchOrEnsure = ({ className, method, jsDoc, functionType, }) => {
|
|
42
45
|
const requestParam = getRequestParamFromMethod(method);
|
|
43
46
|
const requestParams = requestParam ? [requestParam] : [];
|
|
44
|
-
const
|
|
47
|
+
const prefetchOrEnsureHook = createPrefetchOrEnsureHook({
|
|
45
48
|
requestParams,
|
|
46
49
|
method,
|
|
47
50
|
className,
|
|
51
|
+
functionType,
|
|
48
52
|
});
|
|
49
|
-
const hookWithJsDoc = addJSDocToNode(
|
|
53
|
+
const hookWithJsDoc = addJSDocToNode(prefetchOrEnsureHook, jsDoc);
|
|
50
54
|
return {
|
|
51
|
-
|
|
55
|
+
hook: hookWithJsDoc,
|
|
52
56
|
};
|
|
53
57
|
};
|
package/dist/createSource.mjs
CHANGED
|
@@ -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, pageParam, nextPageParam) => {
|
|
8
|
+
const createSourceFile = async (outputPath, serviceEndName, pageParam, nextPageParam, initialPageParam) => {
|
|
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,7 +20,7 @@ const createSourceFile = async (outputPath, serviceEndName, pageParam, nextPageP
|
|
|
20
20
|
serviceEndName,
|
|
21
21
|
project,
|
|
22
22
|
});
|
|
23
|
-
const exports = createExports(service, pageParam, nextPageParam);
|
|
23
|
+
const exports = createExports(service, pageParam, nextPageParam, initialPageParam);
|
|
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);
|
|
@@ -30,6 +30,7 @@ const createSourceFile = async (outputPath, serviceEndName, pageParam, nextPageP
|
|
|
30
30
|
const suspenseSource = ts.factory.createSourceFile([commonImport, ...imports, ...exports.suspenseExports], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None);
|
|
31
31
|
const indexSource = ts.factory.createSourceFile([commonExport, queriesExport], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None);
|
|
32
32
|
const prefetchSource = ts.factory.createSourceFile([commonImport, ...imports, ...exports.allPrefetchExports], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None);
|
|
33
|
+
const ensureSource = ts.factory.createSourceFile([commonImport, ...imports, ...exports.allEnsures], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None);
|
|
33
34
|
return {
|
|
34
35
|
commonSource,
|
|
35
36
|
infiniteQueriesSource,
|
|
@@ -37,20 +38,22 @@ const createSourceFile = async (outputPath, serviceEndName, pageParam, nextPageP
|
|
|
37
38
|
suspenseSource,
|
|
38
39
|
indexSource,
|
|
39
40
|
prefetchSource,
|
|
41
|
+
ensureSource,
|
|
40
42
|
};
|
|
41
43
|
};
|
|
42
|
-
export const createSource = async ({ outputPath, version, serviceEndName, pageParam, nextPageParam, }) => {
|
|
44
|
+
export const createSource = async ({ outputPath, version, serviceEndName, pageParam, nextPageParam, initialPageParam, }) => {
|
|
43
45
|
const queriesFile = ts.createSourceFile(`${OpenApiRqFiles.queries}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
44
46
|
const infiniteQueriesFile = ts.createSourceFile(`${OpenApiRqFiles.infiniteQueries}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
45
47
|
const commonFile = ts.createSourceFile(`${OpenApiRqFiles.common}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
46
48
|
const suspenseFile = ts.createSourceFile(`${OpenApiRqFiles.suspense}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
47
49
|
const indexFile = ts.createSourceFile(`${OpenApiRqFiles.index}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
48
50
|
const prefetchFile = ts.createSourceFile(`${OpenApiRqFiles.prefetch}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
51
|
+
const ensureQueryDataFile = ts.createSourceFile(`${OpenApiRqFiles.ensureQueryData}.ts`, "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
49
52
|
const printer = ts.createPrinter({
|
|
50
53
|
newLine: ts.NewLineKind.LineFeed,
|
|
51
54
|
removeComments: false,
|
|
52
55
|
});
|
|
53
|
-
const { commonSource, mainSource, infiniteQueriesSource, suspenseSource, indexSource, prefetchSource, } = await createSourceFile(outputPath, serviceEndName, pageParam, nextPageParam);
|
|
56
|
+
const { commonSource, mainSource, infiniteQueriesSource, suspenseSource, indexSource, prefetchSource, ensureSource, } = await createSourceFile(outputPath, serviceEndName, pageParam, nextPageParam, initialPageParam);
|
|
54
57
|
const comment = `// generated with @7nohe/openapi-react-query-codegen@${version} \n\n`;
|
|
55
58
|
const commonResult = comment +
|
|
56
59
|
printer.printNode(ts.EmitHint.Unspecified, commonSource, commonFile);
|
|
@@ -64,6 +67,8 @@ export const createSource = async ({ outputPath, version, serviceEndName, pagePa
|
|
|
64
67
|
printer.printNode(ts.EmitHint.Unspecified, indexSource, indexFile);
|
|
65
68
|
const prefetchResult = comment +
|
|
66
69
|
printer.printNode(ts.EmitHint.Unspecified, prefetchSource, prefetchFile);
|
|
70
|
+
const enqureResult = comment +
|
|
71
|
+
printer.printNode(ts.EmitHint.Unspecified, ensureSource, ensureQueryDataFile);
|
|
67
72
|
return [
|
|
68
73
|
{
|
|
69
74
|
name: `${OpenApiRqFiles.index}.ts`,
|
|
@@ -89,5 +94,9 @@ export const createSource = async ({ outputPath, version, serviceEndName, pagePa
|
|
|
89
94
|
name: `${OpenApiRqFiles.prefetch}.ts`,
|
|
90
95
|
content: prefetchResult,
|
|
91
96
|
},
|
|
97
|
+
{
|
|
98
|
+
name: `${OpenApiRqFiles.ensureQueryData}.ts`,
|
|
99
|
+
content: enqureResult,
|
|
100
|
+
},
|
|
92
101
|
];
|
|
93
102
|
};
|
package/dist/createUseQuery.mjs
CHANGED
|
@@ -85,12 +85,36 @@ export function createQueryKeyFromMethod({ method, className, }) {
|
|
|
85
85
|
const queryKey = `${customHookName}Key`;
|
|
86
86
|
return queryKey;
|
|
87
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Extracts the type of the next page parameter from the given properties.
|
|
90
|
+
*
|
|
91
|
+
* @param properties The properties to search through.
|
|
92
|
+
* @param nextPageParam The name of the next page parameter.
|
|
93
|
+
* @returns The type of the next page parameter, if found.
|
|
94
|
+
*/
|
|
95
|
+
function findNextPageParamType(properties, nextPageParam) {
|
|
96
|
+
if (!properties)
|
|
97
|
+
return undefined;
|
|
98
|
+
for (const property of properties) {
|
|
99
|
+
if (property.getName() === nextPageParam) {
|
|
100
|
+
return property?.getDeclarations()?.at(0)?.getType()?.getText();
|
|
101
|
+
}
|
|
102
|
+
const type = property.getDeclarations().at(0)?.getType();
|
|
103
|
+
const nestedProperties = type?.getProperties();
|
|
104
|
+
if (!type?.isObject() || type.isArray())
|
|
105
|
+
continue;
|
|
106
|
+
const result = findNextPageParamType(nestedProperties, nextPageParam);
|
|
107
|
+
if (result)
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
88
112
|
/**
|
|
89
113
|
* Creates a custom hook for a query
|
|
90
114
|
* @param queryString The type of query to use from react-query
|
|
91
115
|
* @param suffix The suffix to append to the hook name
|
|
92
116
|
*/
|
|
93
|
-
export function createQueryHook({ queryString, suffix, responseDataType, requestParams, method, className, pageParam, nextPageParam, }) {
|
|
117
|
+
export function createQueryHook({ queryString, suffix, responseDataType, requestParams, method, className, pageParam, nextPageParam, initialPageParam, }) {
|
|
94
118
|
const methodName = getNameFromMethod(method);
|
|
95
119
|
const customHookName = hookNameFromMethod({ method, className });
|
|
96
120
|
const queryKey = createQueryKeyFromMethod({ method, className });
|
|
@@ -101,6 +125,11 @@ export function createQueryHook({ queryString, suffix, responseDataType, request
|
|
|
101
125
|
const isInfiniteQuery = queryString === "useInfiniteQuery";
|
|
102
126
|
const responseDataTypeRef = responseDataType.default;
|
|
103
127
|
const responseDataTypeIdentifier = responseDataTypeRef.typeName;
|
|
128
|
+
const arg = method.getReturnType().getTypeArguments().at(0);
|
|
129
|
+
const nextPageParamTypePropetires = arg?.getProperties();
|
|
130
|
+
const nextPageParamType = arg?.isObject() && nextPageParam
|
|
131
|
+
? findNextPageParamType(nextPageParamTypePropetires, nextPageParam.split(".").at(-1) ?? "")
|
|
132
|
+
: undefined;
|
|
104
133
|
const hookExport = ts.factory.createVariableStatement([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
|
|
105
134
|
ts.factory.createVariableDeclaration(ts.factory.createIdentifier(`${customHookName}${suffix}`), undefined, undefined, ts.factory.createArrowFunction(undefined, ts.factory.createNodeArray([
|
|
106
135
|
isInfiniteQuery
|
|
@@ -151,18 +180,22 @@ export function createQueryHook({ queryString, suffix, responseDataType, request
|
|
|
151
180
|
ts.factory.createObjectLiteralExpression(method
|
|
152
181
|
.getParameters()
|
|
153
182
|
.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(
|
|
183
|
+
? ts.factory.createPropertyAssignment(ts.factory.createIdentifier(p.name), ts.factory.createAsExpression(ts.factory.createIdentifier("pageParam"), ts.factory.createKeywordTypeNode(p.type?.getText() === "number"
|
|
184
|
+
? ts.SyntaxKind
|
|
185
|
+
.NumberKeyword
|
|
186
|
+
: ts.SyntaxKind
|
|
187
|
+
.StringKeyword)))
|
|
155
188
|
: ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
|
|
156
189
|
]
|
|
157
190
|
: undefined), ts.factory.createTypeReferenceNode(TData)))),
|
|
158
|
-
...createInfiniteQueryParams(pageParam, nextPageParam),
|
|
191
|
+
...createInfiniteQueryParams(pageParam, nextPageParam, initialPageParam, nextPageParamType),
|
|
159
192
|
ts.factory.createSpreadAssignment(ts.factory.createIdentifier("options")),
|
|
160
193
|
]),
|
|
161
194
|
]))),
|
|
162
195
|
], ts.NodeFlags.Const));
|
|
163
196
|
return hookExport;
|
|
164
197
|
}
|
|
165
|
-
export const createUseQuery = ({ className, method, jsDoc }, pageParam, nextPageParam) => {
|
|
198
|
+
export const createUseQuery = ({ className, method, jsDoc }, pageParam, nextPageParam, initialPageParam) => {
|
|
166
199
|
const methodName = getNameFromMethod(method);
|
|
167
200
|
const queryKey = createQueryKeyFromMethod({ method, className });
|
|
168
201
|
const { apiResponse: defaultApiResponse, responseDataType } = createApiResponseType({
|
|
@@ -206,6 +239,7 @@ export const createUseQuery = ({ className, method, jsDoc }, pageParam, nextPage
|
|
|
206
239
|
className,
|
|
207
240
|
pageParam,
|
|
208
241
|
nextPageParam,
|
|
242
|
+
initialPageParam,
|
|
209
243
|
})
|
|
210
244
|
: undefined;
|
|
211
245
|
const hookWithJsDoc = addJSDocToNode(queryHook, jsDoc);
|
|
@@ -257,16 +291,22 @@ function queryKeyFn(queryKey, method) {
|
|
|
257
291
|
: ts.factory.createArrayLiteralExpression([])))),
|
|
258
292
|
], false);
|
|
259
293
|
}
|
|
260
|
-
function createInfiniteQueryParams(pageParam, nextPageParam) {
|
|
294
|
+
function createInfiniteQueryParams(pageParam, nextPageParam, initialPageParam = "1", type) {
|
|
261
295
|
if (pageParam === undefined || nextPageParam === undefined) {
|
|
262
296
|
return [];
|
|
263
297
|
}
|
|
264
298
|
return [
|
|
265
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier("initialPageParam"), ts.factory.
|
|
299
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier("initialPageParam"), ts.factory.createStringLiteral(initialPageParam)),
|
|
266
300
|
ts.factory.createPropertyAssignment(ts.factory.createIdentifier("getNextPageParam"),
|
|
267
301
|
// (response) => (response as { nextPage: number }).nextPage,
|
|
268
302
|
ts.factory.createArrowFunction(undefined, undefined, [
|
|
269
303
|
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"),
|
|
304
|
+
], undefined, EqualsOrGreaterThanToken, ts.factory.createPropertyAccessExpression(ts.factory.createParenthesizedExpression(ts.factory.createAsExpression(ts.factory.createIdentifier("response"), nextPageParam.split(".").reduceRight((acc, segment) => {
|
|
305
|
+
return ts.factory.createTypeLiteralNode([
|
|
306
|
+
ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier(segment), undefined, acc),
|
|
307
|
+
]);
|
|
308
|
+
}, ts.factory.createKeywordTypeNode(type === "number"
|
|
309
|
+
? ts.SyntaxKind.NumberKeyword
|
|
310
|
+
: ts.SyntaxKind.StringKeyword)))), ts.factory.createIdentifier(nextPageParam)))),
|
|
271
311
|
];
|
|
272
312
|
}
|
package/dist/generate.mjs
CHANGED
|
@@ -27,6 +27,7 @@ export async function generate(options, version) {
|
|
|
27
27
|
export: true,
|
|
28
28
|
response: formattedOptions.serviceResponse,
|
|
29
29
|
asClass: true,
|
|
30
|
+
operationId: formattedOptions.operationId ?? false,
|
|
30
31
|
},
|
|
31
32
|
types: {
|
|
32
33
|
dates: formattedOptions.useDateType,
|
|
@@ -42,6 +43,7 @@ export async function generate(options, version) {
|
|
|
42
43
|
serviceEndName: "Service", // we are hard coding this because changing the service end name was depreciated in @hey-api/openapi-ts
|
|
43
44
|
pageParam: formattedOptions.pageParam,
|
|
44
45
|
nextPageParam: formattedOptions.nextPageParam,
|
|
46
|
+
initialPageParam: formattedOptions.initialPageParam.toString(),
|
|
45
47
|
});
|
|
46
48
|
await print(source, formattedOptions);
|
|
47
49
|
const queriesOutputPath = buildQueriesOutputPath(options.output);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@7nohe/openapi-react-query-codegen",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"description": "OpenAPI React Query Codegen",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"codegen",
|
|
@@ -59,9 +59,9 @@
|
|
|
59
59
|
"scripts": {
|
|
60
60
|
"build": "rimraf dist && tsc -p tsconfig.json",
|
|
61
61
|
"lint": "biome check .",
|
|
62
|
-
"lint:fix": "biome check --
|
|
62
|
+
"lint:fix": "biome check --write .",
|
|
63
63
|
"preview": "npm run build && npm -C examples/react-app run generate:api",
|
|
64
|
-
"release": "npx git-ensure -a && npx bumpp --commit --tag --push",
|
|
64
|
+
"release": "npx git-ensure -a -b v1 && npx bumpp --commit --tag --push",
|
|
65
65
|
"snapshot": "vitest --update",
|
|
66
66
|
"test": "vitest --coverage.enabled true"
|
|
67
67
|
}
|