@kubb/plugin-react-query 5.0.0-alpha.9 → 5.0.0-beta.10

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.
Files changed (54) hide show
  1. package/LICENSE +17 -10
  2. package/README.md +34 -85
  3. package/dist/components-Dow6tde8.js +1459 -0
  4. package/dist/components-Dow6tde8.js.map +1 -0
  5. package/dist/components-HwdCDefj.cjs +1603 -0
  6. package/dist/components-HwdCDefj.cjs.map +1 -0
  7. package/dist/components.cjs +1 -1
  8. package/dist/components.d.ts +49 -179
  9. package/dist/components.js +1 -1
  10. package/dist/generators-CcOmnTPa.cjs +1454 -0
  11. package/dist/generators-CcOmnTPa.cjs.map +1 -0
  12. package/dist/generators-yfZr_qfT.js +1412 -0
  13. package/dist/generators-yfZr_qfT.js.map +1 -0
  14. package/dist/generators.cjs +1 -1
  15. package/dist/generators.d.ts +9 -505
  16. package/dist/generators.js +1 -1
  17. package/dist/index.cjs +197 -126
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +4 -4
  20. package/dist/index.js +193 -126
  21. package/dist/index.js.map +1 -1
  22. package/dist/types-DG_OxOym.d.ts +363 -0
  23. package/extension.yaml +911 -0
  24. package/package.json +59 -64
  25. package/src/components/InfiniteQuery.tsx +79 -138
  26. package/src/components/InfiniteQueryOptions.tsx +55 -166
  27. package/src/components/Mutation.tsx +74 -111
  28. package/src/components/MutationOptions.tsx +61 -80
  29. package/src/components/Query.tsx +66 -142
  30. package/src/components/QueryOptions.tsx +56 -138
  31. package/src/components/SuspenseInfiniteQuery.tsx +79 -138
  32. package/src/components/SuspenseInfiniteQueryOptions.tsx +55 -166
  33. package/src/components/SuspenseQuery.tsx +66 -152
  34. package/src/generators/customHookOptionsFileGenerator.tsx +37 -51
  35. package/src/generators/hookOptionsGenerator.tsx +111 -174
  36. package/src/generators/infiniteQueryGenerator.tsx +158 -178
  37. package/src/generators/mutationGenerator.tsx +112 -139
  38. package/src/generators/queryGenerator.tsx +128 -142
  39. package/src/generators/suspenseInfiniteQueryGenerator.tsx +157 -156
  40. package/src/generators/suspenseQueryGenerator.tsx +126 -152
  41. package/src/index.ts +1 -1
  42. package/src/plugin.ts +134 -187
  43. package/src/resolvers/resolverReactQuery.ts +107 -0
  44. package/src/types.ts +172 -49
  45. package/src/utils.ts +10 -0
  46. package/dist/components-BHQT9ZLc.cjs +0 -1634
  47. package/dist/components-BHQT9ZLc.cjs.map +0 -1
  48. package/dist/components-CpyHYGOw.js +0 -1520
  49. package/dist/components-CpyHYGOw.js.map +0 -1
  50. package/dist/generators-DP07m3rH.cjs +0 -1469
  51. package/dist/generators-DP07m3rH.cjs.map +0 -1
  52. package/dist/generators-DkQwKTc2.js +0 -1427
  53. package/dist/generators-DkQwKTc2.js.map +0 -1
  54. package/dist/types-D5S7Ny9r.d.ts +0 -270
package/package.json CHANGED
@@ -1,35 +1,53 @@
1
1
  {
2
2
  "name": "@kubb/plugin-react-query",
3
- "version": "5.0.0-alpha.9",
4
- "description": "React Query hooks generator plugin for Kubb, creating type-safe API client hooks from OpenAPI specifications for React applications.",
3
+ "version": "5.0.0-beta.10",
4
+ "description": "Generate type-safe TanStack Query (React Query) hooks from your OpenAPI specification. Covers useQuery, useMutation, useInfiniteQuery, and queryOptions with full TypeScript support.",
5
5
  "keywords": [
6
- "react-query",
7
- "tanstack-query",
8
- "react",
9
- "react-hooks",
10
- "hooks",
6
+ "code-generation",
7
+ "codegen",
11
8
  "data-fetching",
12
- "api-client",
13
- "sdk-generator",
14
- "typescript",
15
- "type-safe",
9
+ "hooks",
10
+ "kubb",
16
11
  "openapi",
12
+ "react",
13
+ "react-query",
17
14
  "swagger",
18
- "oas",
19
- "code-generator",
20
- "codegen",
21
- "plugins",
22
- "kubb"
15
+ "tanstack",
16
+ "tanstack-query",
17
+ "typescript",
18
+ "use-mutation",
19
+ "use-query"
23
20
  ],
21
+ "license": "MIT",
22
+ "author": "stijnvanhulle",
24
23
  "repository": {
25
24
  "type": "git",
26
- "url": "git+https://github.com/kubb-labs/kubb.git",
25
+ "url": "git+https://github.com/kubb-labs/plugins.git",
27
26
  "directory": "packages/plugin-react-query"
28
27
  },
29
- "license": "MIT",
30
- "author": "stijnvanhulle",
31
- "sideEffects": false,
28
+ "files": [
29
+ "src",
30
+ "dist",
31
+ "extension.yaml",
32
+ "!/**/**.test.**",
33
+ "!/**/__tests__/**",
34
+ "!/**/__snapshots__/**"
35
+ ],
32
36
  "type": "module",
37
+ "sideEffects": false,
38
+ "main": "./dist/index.cjs",
39
+ "module": "./dist/index.js",
40
+ "types": "./dist/index.d.ts",
41
+ "typesVersions": {
42
+ "*": {
43
+ "components": [
44
+ "./dist/components.d.ts"
45
+ ],
46
+ "generators": [
47
+ "./dist/generators.d.ts"
48
+ ]
49
+ }
50
+ },
33
51
  "exports": {
34
52
  ".": {
35
53
  "import": "./dist/index.js",
@@ -45,24 +63,26 @@
45
63
  },
46
64
  "./package.json": "./package.json"
47
65
  },
48
- "types": "./dist/index.d.ts",
49
- "typesVersions": {
50
- "*": {
51
- "components": [
52
- "./dist/components.d.ts"
53
- ],
54
- "generators": [
55
- "./dist/generators.d.ts"
56
- ]
57
- }
66
+ "publishConfig": {
67
+ "access": "public",
68
+ "registry": "https://registry.npmjs.org/"
69
+ },
70
+ "dependencies": {
71
+ "@kubb/core": "5.0.0-beta.10",
72
+ "@kubb/renderer-jsx": "5.0.0-beta.10",
73
+ "remeda": "^2.34.0",
74
+ "@kubb/plugin-client": "5.0.0-beta.10",
75
+ "@kubb/plugin-ts": "5.0.0-beta.10",
76
+ "@kubb/plugin-zod": "5.0.0-beta.10"
77
+ },
78
+ "devDependencies": {
79
+ "@internals/shared": "0.0.0",
80
+ "@internals/tanstack-query": "0.0.0",
81
+ "@internals/utils": "0.0.0"
82
+ },
83
+ "peerDependencies": {
84
+ "@kubb/renderer-jsx": "5.0.0-beta.10"
58
85
  },
59
- "files": [
60
- "src",
61
- "dist",
62
- "!/**/**.test.**",
63
- "!/**/__tests__/**",
64
- "!/**/__snapshots__/**"
65
- ],
66
86
  "size-limit": [
67
87
  {
68
88
  "path": "./dist/*.js",
@@ -70,39 +90,14 @@
70
90
  "gzip": true
71
91
  }
72
92
  ],
73
- "dependencies": {
74
- "@kubb/fabric-core": "0.14.0",
75
- "@kubb/react-fabric": "0.14.0",
76
- "remeda": "^2.33.6",
77
- "@kubb/core": "5.0.0-alpha.9",
78
- "@kubb/oas": "5.0.0-alpha.9",
79
- "@kubb/plugin-client": "5.0.0-alpha.9",
80
- "@kubb/plugin-oas": "5.0.0-alpha.9",
81
- "@kubb/plugin-ts": "5.0.0-alpha.9",
82
- "@kubb/plugin-zod": "5.0.0-alpha.9"
83
- },
84
- "peerDependencies": {
85
- "@kubb/fabric-core": "0.14.0",
86
- "@kubb/react-fabric": "0.14.0"
87
- },
88
93
  "engines": {
89
94
  "node": ">=22"
90
95
  },
91
- "publishConfig": {
92
- "access": "public",
93
- "registry": "https://registry.npmjs.org/"
94
- },
95
- "main": "./dist/index.cjs",
96
- "module": "./dist/index.js",
97
- "devDependencies": {
98
- "@internals/tanstack-query": "0.0.0",
99
- "@internals/utils": "0.0.0"
100
- },
101
96
  "scripts": {
102
97
  "build": "tsdown && size-limit",
103
98
  "clean": "npx rimraf ./dist",
104
- "lint": "bun biome lint .",
105
- "lint:fix": "bun biome lint --fix --unsafe .",
99
+ "lint": "oxlint .",
100
+ "lint:fix": "oxlint --fix .",
106
101
  "release": "pnpm publish --no-git-check",
107
102
  "release:canary": "bash ../../.github/canary.sh && node ../../scripts/build.js canary && pnpm publish --no-git-check",
108
103
  "start": "tsdown --watch",
@@ -1,22 +1,20 @@
1
- import { isAllOptional, isOptional, type Operation } from '@kubb/oas'
2
- import type { OperationSchemas } from '@kubb/plugin-oas'
3
- import { getComments, getPathParams } from '@kubb/plugin-oas/utils'
4
- import { File, Function, FunctionParams } from '@kubb/react-fabric'
5
- import type { FabricReactNode } from '@kubb/react-fabric/types'
1
+ import { getOperationParameters } from '@internals/shared'
2
+ import { ast } from '@kubb/core'
3
+ import type { ResolverTs } from '@kubb/plugin-ts'
4
+ import { functionPrinter } from '@kubb/plugin-ts'
5
+ import { File, Function } from '@kubb/renderer-jsx'
6
+ import type { KubbReactNode } from '@kubb/renderer-jsx/types'
6
7
  import type { Infinite, PluginReactQuery } from '../types.ts'
7
- import { QueryKey } from './QueryKey.tsx'
8
- import { QueryOptions } from './QueryOptions.tsx'
8
+ import { buildQueryKeyParams, getComments, resolveErrorNames } from '../utils.ts'
9
+ import { getQueryOptionsParams } from './QueryOptions.tsx'
9
10
 
10
11
  type Props = {
11
- /**
12
- * Name of the function
13
- */
14
12
  name: string
15
13
  queryOptionsName: string
16
14
  queryKeyName: string
17
15
  queryKeyTypeName: string
18
- typeSchemas: OperationSchemas
19
- operation: Operation
16
+ node: ast.OperationNode
17
+ tsResolver: ResolverTs
20
18
  paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
21
19
  paramsType: PluginReactQuery['resolvedOptions']['paramsType']
22
20
  pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
@@ -26,99 +24,41 @@ type Props = {
26
24
  customOptions: PluginReactQuery['resolvedOptions']['customOptions']
27
25
  }
28
26
 
29
- type GetParamsProps = {
30
- paramsType: PluginReactQuery['resolvedOptions']['paramsType']
31
- paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
32
- pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
33
- typeSchemas: OperationSchemas
34
- pageParamGeneric: string
35
- }
27
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
28
+ const callPrinter = functionPrinter({ mode: 'call' })
36
29
 
37
- function getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas, pageParamGeneric }: GetParamsProps) {
38
- if (paramsType === 'object') {
39
- const pathParams = getPathParams(typeSchemas.pathParams, {
40
- typed: true,
41
- casing: paramsCasing,
42
- })
43
-
44
- const children = {
45
- ...pathParams,
46
- data: typeSchemas.request?.name
47
- ? {
48
- type: typeSchemas.request?.name,
49
- optional: isOptional(typeSchemas.request?.schema),
50
- }
51
- : undefined,
52
- params: typeSchemas.queryParams?.name
53
- ? {
54
- type: typeSchemas.queryParams?.name,
55
- optional: isOptional(typeSchemas.queryParams?.schema),
56
- }
57
- : undefined,
58
- headers: typeSchemas.headerParams?.name
59
- ? {
60
- type: typeSchemas.headerParams?.name,
61
- optional: isOptional(typeSchemas.headerParams?.schema),
62
- }
63
- : undefined,
64
- }
65
-
66
- // Check if all children are optional or undefined
67
- const allChildrenAreOptional = Object.values(children).every((child) => !child || child.optional)
68
-
69
- return FunctionParams.factory({
70
- data: {
71
- mode: 'object',
72
- children,
73
- default: allChildrenAreOptional ? '{}' : undefined,
74
- },
75
- options: {
76
- type: `
77
- {
78
- query?: Partial<InfiniteQueryObserverOptions<TQueryFnData, TError, TData, TQueryKey, ${pageParamGeneric}>> & { client?: QueryClient },
79
- client?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
80
- }
81
- `,
82
- default: '{}',
83
- },
84
- })
85
- }
86
-
87
- return FunctionParams.factory({
88
- pathParams: typeSchemas.pathParams?.name
89
- ? {
90
- mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
91
- children: getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing }),
92
- default: isAllOptional(typeSchemas.pathParams?.schema) ? '{}' : undefined,
93
- }
94
- : undefined,
95
- data: typeSchemas.request?.name
96
- ? {
97
- type: typeSchemas.request?.name,
98
- optional: isOptional(typeSchemas.request?.schema),
99
- }
100
- : undefined,
101
- params: typeSchemas.queryParams?.name
102
- ? {
103
- type: typeSchemas.queryParams?.name,
104
- optional: isOptional(typeSchemas.queryParams?.schema),
105
- }
106
- : undefined,
107
- headers: typeSchemas.headerParams?.name
108
- ? {
109
- type: typeSchemas.headerParams?.name,
110
- optional: isOptional(typeSchemas.headerParams?.schema),
111
- }
112
- : undefined,
113
- options: {
114
- type: `
115
- {
30
+ function buildInfiniteQueryParamsNode(
31
+ node: ast.OperationNode,
32
+ options: {
33
+ paramsType: PluginReactQuery['resolvedOptions']['paramsType']
34
+ paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
35
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
36
+ dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
37
+ resolver: ResolverTs
38
+ pageParamGeneric: string
39
+ },
40
+ ): ast.FunctionParametersNode {
41
+ const { paramsType, paramsCasing, pathParamsType, resolver, pageParamGeneric } = options
42
+ const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : undefined
43
+
44
+ const optionsParam = ast.createFunctionParameter({
45
+ name: 'options',
46
+ type: ast.createParamsType({
47
+ variant: 'reference',
48
+ name: `{
116
49
  query?: Partial<InfiniteQueryObserverOptions<TQueryFnData, TError, TData, TQueryKey, ${pageParamGeneric}>> & { client?: QueryClient },
117
- client?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
118
- }
119
- `,
120
- default: '{}',
121
- },
50
+ client?: ${requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
51
+ }`,
52
+ }),
53
+ default: '{}',
54
+ })
55
+
56
+ return ast.createOperationParams(node, {
57
+ paramsType,
58
+ pathParamsType: paramsType === 'object' ? 'object' : pathParamsType === 'object' ? 'object' : 'inline',
59
+ paramsCasing,
60
+ resolver,
61
+ extraParams: [optionsParam],
122
62
  })
123
63
  }
124
64
 
@@ -131,14 +71,18 @@ export function InfiniteQuery({
131
71
  paramsCasing,
132
72
  pathParamsType,
133
73
  dataReturnType,
134
- typeSchemas,
135
- operation,
74
+ node,
75
+ tsResolver,
136
76
  initialPageParam,
137
77
  queryParam,
138
78
  customOptions,
139
- }: Props): FabricReactNode {
140
- const responseType = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
141
- const errorType = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
79
+ }: Props): KubbReactNode {
80
+ const responseName = tsResolver.resolveResponseName(node)
81
+ const errorNames = resolveErrorNames(node, tsResolver)
82
+
83
+ const responseType = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
84
+ const errorType = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
85
+
142
86
  const isInitialPageParamDefined = initialPageParam !== undefined && initialPageParam !== null
143
87
  const fallbackPageParamType =
144
88
  typeof initialPageParam === 'number'
@@ -153,8 +97,20 @@ export function InfiniteQuery({
153
97
  : typeof initialPageParam === 'boolean'
154
98
  ? 'boolean'
155
99
  : 'unknown'
156
- const queryParamType = queryParam && typeSchemas.queryParams?.name ? `${typeSchemas.queryParams?.name}['${queryParam}']` : undefined
100
+
101
+ const rawQueryParams = getOperationParameters(node).query
102
+ const queryParamsTypeName =
103
+ rawQueryParams.length > 0
104
+ ? (() => {
105
+ const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]!)
106
+ const individualName = tsResolver.resolveParamName(node, rawQueryParams[0]!)
107
+ return groupName !== individualName ? groupName : undefined
108
+ })()
109
+ : undefined
110
+
111
+ const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : undefined
157
112
  const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
113
+
158
114
  const returnType = 'UseInfiniteQueryResult<TData, TError> & { queryKey: TQueryKey }'
159
115
  const generics = [
160
116
  `TQueryFnData = ${responseType}`,
@@ -164,46 +120,33 @@ export function InfiniteQuery({
164
120
  `TPageParam = ${pageParamType}`,
165
121
  ]
166
122
 
167
- const queryKeyParams = QueryKey.getParams({
168
- pathParamsType,
169
- typeSchemas,
170
- paramsCasing,
171
- })
172
- const queryOptionsParams = QueryOptions.getParams({
123
+ const queryKeyParamsNode = buildQueryKeyParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
124
+ const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
125
+
126
+ const queryOptionsParamsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
127
+ const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? ''
128
+
129
+ const paramsNode = buildInfiniteQueryParamsNode(node, {
173
130
  paramsType,
174
- pathParamsType,
175
- typeSchemas,
176
- paramsCasing,
177
- })
178
- const params = getParams({
179
131
  paramsCasing,
180
- paramsType,
181
132
  pathParamsType,
182
- typeSchemas,
133
+ dataReturnType,
134
+ resolver: tsResolver,
183
135
  pageParamGeneric: 'TPageParam',
184
136
  })
185
-
186
- const queryOptions = `${queryOptionsName}(${queryOptionsParams.toCall()})`
137
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
187
138
 
188
139
  return (
189
140
  <File.Source name={name} isExportable isIndexable>
190
- <Function
191
- name={name}
192
- export
193
- generics={generics.join(', ')}
194
- params={params.toConstructor()}
195
- JSDoc={{
196
- comments: getComments(operation),
197
- }}
198
- >
141
+ <Function name={name} export generics={generics.join(', ')} params={paramsSignature} returnType={undefined} JSDoc={{ comments: getComments(node) }}>
199
142
  {`
200
143
  const { query: queryConfig = {}, client: config = {} } = options ?? {}
201
144
  const { client: queryClient, ...resolvedOptions } = queryConfig
202
- const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyParams.toCall()})
203
- ${customOptions ? `const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${operation.getOperationId()}' })` : ''}
145
+ const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyParamsCall})
146
+ ${customOptions ? `const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${node.operationId}' })` : ''}
204
147
 
205
148
  const query = useInfiniteQuery({
206
- ...${queryOptions},${customOptions ? '\n...customOptions,' : ''}
149
+ ...${queryOptionsName}(${queryOptionsParamsCall}),${customOptions ? '\n...customOptions,' : ''}
207
150
  ...resolvedOptions,
208
151
  queryKey,
209
152
  } as unknown as InfiniteQueryObserverOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, queryClient) as ${returnType}
@@ -216,5 +159,3 @@ export function InfiniteQuery({
216
159
  </File.Source>
217
160
  )
218
161
  }
219
-
220
- InfiniteQuery.getParams = getParams