@7nohe/openapi-react-query-codegen 1.2.2 → 1.3.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
@@ -201,12 +201,17 @@ import {
201
201
 
202
202
  // App.tsx
203
203
  function App() {
204
- const { data } = usePetServiceFindPetsByStatus({ status: ["available"] });
204
+ const [status, setStatus] = React.useState(["available"]);
205
+ const { data } = usePetServiceFindPetsByStatus({ status });
205
206
  const { mutate } = usePetServiceAddPet({
206
207
  onSuccess: () => {
207
208
  queryClient.invalidateQueries({
208
- // Call the query key function to get the query key, this is important to ensure the query key is created the same way as the query hook, this insures the cache is invalidated correctly and is typed correctly
209
- queryKey: [UsePetServiceFindPetsByStatusKeyFn()],
209
+ // Call the query key function to get the query key
210
+ // This is important to ensure the query key is created the same way as the query hook
211
+ // This insures the cache is invalidated correctly and is typed correctly
212
+ queryKey: [UsePetServiceFindPetsByStatusKeyFn({
213
+ status
214
+ })],
210
215
  });
211
216
  },
212
217
  });
@@ -257,6 +262,39 @@ ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
257
262
 
258
263
  ```
259
264
 
265
+ ## Development
266
+
267
+ ### Install dependencies
268
+
269
+ ```bash
270
+ pnpm install
271
+ ```
272
+
273
+ ### Run tests
274
+ ```bash
275
+ pnpm test
276
+ ```
277
+
278
+ ### Run linter
279
+ ```bash
280
+ pnpm lint
281
+ ```
282
+
283
+ ### Run linter and fix
284
+ ```bash
285
+ pnpm lint:fix
286
+ ```
287
+
288
+ ### Update snapshots
289
+ ```bash
290
+ pnpm snapshot
291
+ ```
292
+
293
+ ### Build example and validate generated code
294
+ ```bash
295
+ npm run build && pnpm --filter @7nohe/react-app generate:api && pnpm --filter @7nohe/react-app test:generated
296
+ ```
297
+
260
298
  ## License
261
299
 
262
300
  MIT
package/dist/cli.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { generate } from "./generate.mjs";
3
- import { Command, Option } from "commander";
4
- import { readFile } from "fs/promises";
5
- import { dirname, join } from "path";
2
+ import { readFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
6
4
  import { fileURLToPath } from "node:url";
5
+ import { Command, Option } from "commander";
7
6
  import { defaultOutputPath } from "./constants.mjs";
7
+ import { generate } from "./generate.mjs";
8
8
  const program = new Command();
9
9
  async function setupProgram() {
10
10
  const __filename = fileURLToPath(import.meta.url);
package/dist/common.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { stat } from "fs/promises";
1
+ import { stat } from "node:fs/promises";
2
+ import path from "node:path";
2
3
  import ts from "typescript";
3
- import path from "path";
4
4
  import { queriesOutputPath, requestsOutputPath } from "./constants.mjs";
5
5
  export const TData = ts.factory.createIdentifier("TData");
6
6
  export const TError = ts.factory.createIdentifier("TError");
@@ -51,10 +51,10 @@ export function BuildCommonTypeName(name) {
51
51
  */
52
52
  export function safeParseNumber(value) {
53
53
  const parsed = Number(value);
54
- if (!isNaN(parsed) && isFinite(parsed)) {
54
+ if (!Number.isNaN(parsed) && Number.isFinite(parsed)) {
55
55
  return parsed;
56
56
  }
57
- return NaN;
57
+ return Number.NaN;
58
58
  }
59
59
  export function extractPropertiesFromObjectParam(param) {
60
60
  const referenced = param.findReferences()[0];
@@ -119,7 +119,7 @@ export function formatOptions(options) {
119
119
  else if (value === "false" || value === false) {
120
120
  acc[typedKey] = false;
121
121
  }
122
- else if (!isNaN(parsedNumber)) {
122
+ else if (!Number.isNaN(parsedNumber)) {
123
123
  acc[typedKey] = parsedNumber;
124
124
  }
125
125
  else {
@@ -1,9 +1,9 @@
1
- import { createUseQuery } from "./createUseQuery.mjs";
2
- import { createUseMutation } from "./createUseMutation.mjs";
3
1
  import { createPrefetch } from "./createPrefetch.mjs";
2
+ import { createUseMutation } from "./createUseMutation.mjs";
3
+ import { createUseQuery } from "./createUseQuery.mjs";
4
4
  export const createExports = (service) => {
5
5
  const { klasses } = service;
6
- const methods = klasses.map((k) => k.methods).flat();
6
+ const methods = klasses.flatMap((k) => k.methods);
7
7
  const allGet = methods.filter((m) => m.httpMethodName.toUpperCase().includes("GET"));
8
8
  const allPost = methods.filter((m) => m.httpMethodName.toUpperCase().includes("POST"));
9
9
  const allPut = methods.filter((m) => m.httpMethodName.toUpperCase().includes("PUT"));
@@ -22,30 +22,28 @@ export const createExports = (service) => {
22
22
  ...allPatchMutations,
23
23
  ...allDeleteMutations,
24
24
  ];
25
- const commonInQueries = allQueries
26
- .map(({ apiResponse, returnType, key, queryKeyFn }) => [
25
+ const commonInQueries = allQueries.flatMap(({ apiResponse, returnType, key, queryKeyFn }) => [
27
26
  apiResponse,
28
27
  returnType,
29
28
  key,
30
29
  queryKeyFn,
31
- ])
32
- .flat();
33
- const commonInMutations = allMutations
34
- .map(({ mutationResult }) => [mutationResult])
35
- .flat();
30
+ ]);
31
+ const commonInMutations = allMutations.flatMap(({ mutationResult }) => [
32
+ mutationResult,
33
+ ]);
36
34
  const allCommon = [...commonInQueries, ...commonInMutations];
37
- const mainQueries = allQueries.map(({ queryHook }) => [queryHook]).flat();
38
- const mainMutations = allMutations
39
- .map(({ mutationHook }) => [mutationHook])
40
- .flat();
35
+ const mainQueries = allQueries.flatMap(({ queryHook }) => [queryHook]);
36
+ const mainMutations = allMutations.flatMap(({ mutationHook }) => [
37
+ mutationHook,
38
+ ]);
41
39
  const mainExports = [...mainQueries, ...mainMutations];
42
- const suspenseQueries = allQueries
43
- .map(({ suspenseQueryHook }) => [suspenseQueryHook])
44
- .flat();
40
+ const suspenseQueries = allQueries.flatMap(({ suspenseQueryHook }) => [
41
+ suspenseQueryHook,
42
+ ]);
45
43
  const suspenseExports = [...suspenseQueries];
46
- const allPrefetches = allPrefetchQueries
47
- .map(({ prefetchHook }) => [prefetchHook])
48
- .flat();
44
+ const allPrefetches = allPrefetchQueries.flatMap(({ prefetchHook }) => [
45
+ prefetchHook,
46
+ ]);
49
47
  const allPrefetchExports = [...allPrefetches];
50
48
  return {
51
49
  /**
@@ -1,5 +1,5 @@
1
+ import { posix } from "node:path";
1
2
  import ts from "typescript";
2
- import { posix } from "path";
3
3
  import { modalsFileName, serviceFileName } from "./constants.mjs";
4
4
  const { join } = posix;
5
5
  export const createImports = ({ serviceEndName, project, }) => {
@@ -19,6 +19,7 @@ export const createImports = ({ serviceEndName, project, }) => {
19
19
  const serviceNames = serviceExports.filter((name) => name.endsWith(serviceEndName));
20
20
  const imports = [
21
21
  ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(false, undefined, ts.factory.createNamedImports([
22
+ ts.factory.createImportSpecifier(true, undefined, ts.factory.createIdentifier("QueryClient")),
22
23
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("useQuery")),
23
24
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("useSuspenseQuery")),
24
25
  ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("useMutation")),
@@ -25,8 +25,7 @@ function createPrefetchHook({ requestParams, method, className, }) {
25
25
  ? ts.factory.createArrayLiteralExpression([
26
26
  ts.factory.createObjectLiteralExpression(method
27
27
  .getParameters()
28
- .map((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))
29
- .flat()),
28
+ .flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
30
29
  ])
31
30
  : ts.factory.createArrayLiteralExpression([]),
32
31
  ], false)),
@@ -34,8 +33,7 @@ function createPrefetchHook({ requestParams, method, className, }) {
34
33
  ? [
35
34
  ts.factory.createObjectLiteralExpression(method
36
35
  .getParameters()
37
- .map((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))
38
- .flat()),
36
+ .flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
39
37
  ]
40
38
  : undefined))),
41
39
  ]),
@@ -1,9 +1,9 @@
1
- import ts from "typescript";
1
+ import { join } from "node:path";
2
2
  import { Project } from "ts-morph";
3
- import { join } from "path";
3
+ import ts from "typescript";
4
4
  import { OpenApiRqFiles } from "./constants.mjs";
5
- import { createImports } from "./createImports.mjs";
6
5
  import { createExports } from "./createExports.mjs";
6
+ import { createImports } from "./createImports.mjs";
7
7
  import { getServices } from "./service.mjs";
8
8
  const createSourceFile = async (outputPath, serviceEndName) => {
9
9
  const project = new Project({
@@ -20,15 +20,12 @@ export const createUseMutation = ({ className, method, jsDoc, }) => {
20
20
  const mutationResult = ts.factory.createTypeAliasDeclaration([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(`${className}${capitalizeFirstLetter(methodName)}MutationResult`), undefined, awaitedResponseDataType);
21
21
  const responseDataType = ts.factory.createTypeParameterDeclaration(undefined, TData, undefined, ts.factory.createTypeReferenceNode(BuildCommonTypeName(mutationResult.name)));
22
22
  const methodParameters = method.getParameters().length !== 0
23
- ? ts.factory.createTypeLiteralNode(method
24
- .getParameters()
25
- .map((param) => {
23
+ ? ts.factory.createTypeLiteralNode(method.getParameters().flatMap((param) => {
26
24
  const paramNodes = extractPropertiesFromObjectParam(param);
27
25
  return paramNodes.map((refParam) => ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier(refParam.name), refParam.optional
28
26
  ? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
29
27
  : undefined, ts.factory.createTypeReferenceNode(getShortType(refParam.type.getText(param)))));
30
- })
31
- .flat())
28
+ }))
32
29
  : ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword);
33
30
  const exportHook = ts.factory.createVariableStatement([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
34
31
  ts.factory.createVariableDeclaration(ts.factory.createIdentifier(`use${className}${capitalizeFirstLetter(methodName)}`), undefined, undefined, ts.factory.createArrowFunction(undefined, ts.factory.createNodeArray([
@@ -54,23 +51,17 @@ export const createUseMutation = ({ className, method, jsDoc, }) => {
54
51
  ts.factory.createObjectLiteralExpression([
55
52
  ts.factory.createPropertyAssignment(ts.factory.createIdentifier("mutationFn"), ts.factory.createArrowFunction(undefined, undefined, method.getParameters().length !== 0
56
53
  ? [
57
- ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createObjectBindingPattern(method
58
- .getParameters()
59
- .map((param) => {
54
+ ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createObjectBindingPattern(method.getParameters().flatMap((param) => {
60
55
  const paramNodes = extractPropertiesFromObjectParam(param);
61
56
  return paramNodes.map((refParam) => ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier(refParam.name), undefined));
62
- })
63
- .flat()), undefined, undefined, undefined),
57
+ })), undefined, undefined, undefined),
64
58
  ]
65
59
  : [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createAsExpression(ts.factory.createAsExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(className), ts.factory.createIdentifier(methodName)), undefined, method.getParameters().length !== 0
66
60
  ? [
67
- ts.factory.createObjectLiteralExpression(method
68
- .getParameters()
69
- .map((params) => {
61
+ ts.factory.createObjectLiteralExpression(method.getParameters().flatMap((params) => {
70
62
  const paramNodes = extractPropertiesFromObjectParam(params);
71
63
  return paramNodes.map((refParam) => ts.factory.createShorthandPropertyAssignment(refParam.name));
72
- })
73
- .flat()),
64
+ })),
74
65
  ]
75
66
  : []), ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Promise"), [ts.factory.createTypeReferenceNode(TData)])))),
76
67
  ts.factory.createSpreadAssignment(ts.factory.createIdentifier("options")),
@@ -1,5 +1,5 @@
1
1
  import ts from "typescript";
2
- import { BuildCommonTypeName, capitalizeFirstLetter, EqualsOrGreaterThanToken, extractPropertiesFromObjectParam, getNameFromMethod, getShortType, queryKeyConstraint, queryKeyGenericType, QuestionToken, TData, TError, } from "./common.mjs";
2
+ import { BuildCommonTypeName, EqualsOrGreaterThanToken, QuestionToken, TData, TError, capitalizeFirstLetter, extractPropertiesFromObjectParam, getNameFromMethod, getShortType, queryKeyConstraint, queryKeyGenericType, } from "./common.mjs";
3
3
  import { addJSDocToNode } from "./util.mjs";
4
4
  export const createApiResponseType = ({ className, methodName, }) => {
5
5
  /** Awaited<ReturnType<typeof myClass.myMethod>> */
@@ -32,17 +32,14 @@ export function getRequestParamFromMethod(method) {
32
32
  if (!method.getParameters().length) {
33
33
  return null;
34
34
  }
35
- const params = method
36
- .getParameters()
37
- .map((param) => {
35
+ const params = method.getParameters().flatMap((param) => {
38
36
  const paramNodes = extractPropertiesFromObjectParam(param);
39
37
  return paramNodes.map((refParam) => ({
40
38
  name: refParam.name,
41
39
  typeName: getShortType(refParam.type.getText()),
42
40
  optional: refParam.optional,
43
41
  }));
44
- })
45
- .flat();
42
+ });
46
43
  const areAllPropertiesOptional = params.every((param) => param.optional);
47
44
  return ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createObjectBindingPattern(params.map((refParam) => ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier(refParam.name), undefined))), undefined, ts.factory.createTypeLiteralNode(params.map((refParam) => {
48
45
  return ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier(refParam.name), refParam.optional
@@ -122,8 +119,7 @@ export function createQueryHook({ queryString, suffix, responseDataType, request
122
119
  ? [
123
120
  ts.factory.createObjectLiteralExpression(method
124
121
  .getParameters()
125
- .map((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))
126
- .flat()),
122
+ .flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
127
123
  ts.factory.createIdentifier("queryKey"),
128
124
  ]
129
125
  : [])),
@@ -131,8 +127,7 @@ export function createQueryHook({ queryString, suffix, responseDataType, request
131
127
  ? [
132
128
  ts.factory.createObjectLiteralExpression(method
133
129
  .getParameters()
134
- .map((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))
135
- .flat()),
130
+ .flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
136
131
  ]
137
132
  : undefined), ts.factory.createTypeReferenceNode(TData)))),
138
133
  ts.factory.createSpreadAssignment(ts.factory.createIdentifier("options")),
@@ -212,8 +207,7 @@ function queryKeyFn(queryKey, method) {
212
207
  ? ts.factory.createArrayLiteralExpression([
213
208
  ts.factory.createObjectLiteralExpression(method
214
209
  .getParameters()
215
- .map((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))
216
- .flat()),
210
+ .flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
217
211
  ])
218
212
  : ts.factory.createArrayLiteralExpression([])))),
219
213
  ], false);
package/dist/generate.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { createClient } from "@hey-api/openapi-ts";
2
- import { print } from "./print.mjs";
3
- import { createSource } from "./createSource.mjs";
4
2
  import { buildQueriesOutputPath, buildRequestsOutputPath, formatOptions, } from "./common.mjs";
3
+ import { createSource } from "./createSource.mjs";
5
4
  import { formatOutput } from "./format.mjs";
5
+ import { print } from "./print.mjs";
6
6
  export async function generate(options, version) {
7
7
  const openApiOutputPath = buildRequestsOutputPath(options.output);
8
8
  const formattedOptions = formatOptions(options);
@@ -11,7 +11,6 @@ export async function generate(options, version) {
11
11
  client: formattedOptions.client,
12
12
  debug: formattedOptions.debug,
13
13
  dryRun: false,
14
- enums: formattedOptions.enums,
15
14
  exportCore: true,
16
15
  format: formattedOptions.format,
17
16
  input: formattedOptions.input,
@@ -29,6 +28,7 @@ export async function generate(options, version) {
29
28
  types: {
30
29
  dates: formattedOptions.useDateType,
31
30
  export: true,
31
+ enums: formattedOptions.enums,
32
32
  },
33
33
  useOptions: true,
34
34
  };
package/dist/print.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { mkdir, writeFile } from "fs/promises";
2
- import path from "path";
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
3
  import { buildQueriesOutputPath, exists } from "./common.mjs";
4
4
  async function printGeneratedTS(result, options) {
5
5
  const dir = buildQueriesOutputPath(options.output);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7nohe/openapi-react-query-codegen",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "OpenAPI React Query Codegen",
5
5
  "bin": {
6
6
  "openapi-rq": "dist/cli.mjs"
@@ -30,19 +30,22 @@
30
30
  ],
31
31
  "author": "Daiki Urata (@7nohe)",
32
32
  "license": "MIT",
33
+ "dependencies": {
34
+ "@hey-api/openapi-ts": "0.43.0"
35
+ },
33
36
  "devDependencies": {
34
- "@hey-api/openapi-ts": "0.42.1",
37
+ "@biomejs/biome": "^1.7.2",
35
38
  "@types/node": "^20.10.6",
36
39
  "@vitest/coverage-v8": "^1.5.0",
37
40
  "commander": "^12.0.0",
38
41
  "glob": "^10.3.10",
42
+ "lefthook": "^1.6.10",
39
43
  "rimraf": "^5.0.5",
40
44
  "ts-morph": "^22.0.0",
41
45
  "typescript": "^5.3.3",
42
46
  "vitest": "^1.5.0"
43
47
  },
44
48
  "peerDependencies": {
45
- "@hey-api/openapi-ts": "0.42.1",
46
49
  "commander": "12.x",
47
50
  "glob": "10.x",
48
51
  "ts-morph": "22.x",
@@ -53,8 +56,11 @@
53
56
  },
54
57
  "scripts": {
55
58
  "build": "rimraf dist && tsc -p tsconfig.json",
59
+ "lint": "biome check .",
60
+ "lint:fix": "biome check --apply .",
56
61
  "preview": "npm run build && npm -C examples/react-app run generate:api",
57
62
  "release": "npx git-ensure -a && npx bumpp --commit --tag --push",
58
- "test": "vitest --coverage.enabled true"
63
+ "test": "vitest --coverage.enabled true",
64
+ "snapshot": "vitest --update"
59
65
  }
60
66
  }