@tanstack/react-query 5.0.0-alpha.6 → 5.0.0-alpha.62

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 (232) hide show
  1. package/build/codemods/__testfixtures__/default-import.input.tsx +94 -0
  2. package/build/codemods/__testfixtures__/default-import.output.tsx +96 -0
  3. package/build/codemods/__testfixtures__/named-import.input.tsx +96 -0
  4. package/build/codemods/__testfixtures__/named-import.output.tsx +98 -0
  5. package/build/codemods/__testfixtures__/namespaced-import.input.tsx +86 -0
  6. package/build/codemods/__testfixtures__/namespaced-import.output.tsx +88 -0
  7. package/build/codemods/__testfixtures__/parameter-is-identifier.input.tsx +49 -0
  8. package/build/codemods/__testfixtures__/parameter-is-identifier.output.tsx +49 -0
  9. package/build/codemods/__testfixtures__/parameter-is-object-expression.input.tsx +128 -0
  10. package/build/codemods/__testfixtures__/parameter-is-object-expression.output.tsx +175 -0
  11. package/build/codemods/__testfixtures__/replace-import-specifier.input.tsx +10 -0
  12. package/build/codemods/__testfixtures__/replace-import-specifier.output.tsx +10 -0
  13. package/build/codemods/__testfixtures__/type-arguments.input.tsx +25 -0
  14. package/build/codemods/__testfixtures__/type-arguments.output.tsx +31 -0
  15. package/build/codemods/__tests__/key-transformation.test.js +32 -0
  16. package/build/codemods/__tests__/replace-import-specifier.test.js +12 -0
  17. package/build/codemods/remove-overloads/__testfixtures__/default-import.input.tsx +199 -0
  18. package/build/codemods/remove-overloads/__testfixtures__/default-import.output.tsx +484 -0
  19. package/build/codemods/remove-overloads/__tests__/remove-overloads.test.js +6 -0
  20. package/build/codemods/remove-overloads/remove-overloads.js +59 -0
  21. package/build/codemods/remove-overloads/transformers/filter-aware-usage-transformer.js +153 -0
  22. package/build/codemods/remove-overloads/transformers/query-fn-aware-usage-transformer.js +188 -0
  23. package/build/codemods/remove-overloads/utils/index.js +124 -0
  24. package/build/codemods/remove-overloads/utils/unknown-usage-error.js +27 -0
  25. package/build/codemods/src/utils/index.js +205 -0
  26. package/build/codemods/src/v4/key-transformation.js +138 -0
  27. package/build/codemods/src/v4/replace-import-specifier.js +25 -0
  28. package/build/codemods/transformers/query-cache-transformer.js +116 -0
  29. package/build/codemods/transformers/query-client-transformer.js +48 -0
  30. package/build/codemods/transformers/use-query-like-transformer.js +32 -0
  31. package/build/codemods/utils/replacers/key-replacer.js +164 -0
  32. package/build/lib/HydrationBoundary.cjs +50 -0
  33. package/build/lib/{HydrationBoundary.mjs.map → HydrationBoundary.cjs.map} +1 -1
  34. package/build/lib/HydrationBoundary.d.ts +1 -0
  35. package/build/lib/HydrationBoundary.d.ts.map +1 -0
  36. package/build/lib/HydrationBoundary.js +9 -29
  37. package/build/lib/HydrationBoundary.js.map +1 -1
  38. package/build/lib/QueryClientProvider.cjs +54 -0
  39. package/build/lib/QueryClientProvider.cjs.map +1 -0
  40. package/build/lib/QueryClientProvider.d.ts +2 -1
  41. package/build/lib/QueryClientProvider.d.ts.map +1 -0
  42. package/build/lib/QueryClientProvider.js +7 -29
  43. package/build/lib/QueryClientProvider.js.map +1 -1
  44. package/build/lib/QueryErrorResetBoundary.cjs +60 -0
  45. package/build/lib/{QueryErrorResetBoundary.mjs.map → QueryErrorResetBoundary.cjs.map} +1 -1
  46. package/build/lib/QueryErrorResetBoundary.d.ts +2 -1
  47. package/build/lib/QueryErrorResetBoundary.d.ts.map +1 -0
  48. package/build/lib/QueryErrorResetBoundary.js +7 -28
  49. package/build/lib/QueryErrorResetBoundary.js.map +1 -1
  50. package/build/lib/__tests__/HydrationBoundary.test.d.ts +1 -0
  51. package/build/lib/__tests__/HydrationBoundary.test.d.ts.map +1 -0
  52. package/build/lib/__tests__/QueryClientProvider.test.d.ts +1 -0
  53. package/build/lib/__tests__/QueryClientProvider.test.d.ts.map +1 -0
  54. package/build/lib/__tests__/QueryResetErrorBoundary.test.d.ts +1 -0
  55. package/build/lib/__tests__/QueryResetErrorBoundary.test.d.ts.map +1 -0
  56. package/build/lib/__tests__/ssr-hydration.test.d.ts +1 -0
  57. package/build/lib/__tests__/ssr-hydration.test.d.ts.map +1 -0
  58. package/build/lib/__tests__/ssr.test.d.ts +1 -0
  59. package/build/lib/__tests__/ssr.test.d.ts.map +1 -0
  60. package/build/lib/__tests__/suspense.test.d.ts +1 -0
  61. package/build/lib/__tests__/suspense.test.d.ts.map +1 -0
  62. package/build/lib/__tests__/useInfiniteQuery.test.d.ts +1 -0
  63. package/build/lib/__tests__/useInfiniteQuery.test.d.ts.map +1 -0
  64. package/build/lib/__tests__/useInfiniteQuery.type.test.d.ts +1 -0
  65. package/build/lib/__tests__/useInfiniteQuery.type.test.d.ts.map +1 -0
  66. package/build/lib/__tests__/useIsFetching.test.d.ts +1 -0
  67. package/build/lib/__tests__/useIsFetching.test.d.ts.map +1 -0
  68. package/build/lib/__tests__/useMutation.test.d.ts +1 -0
  69. package/build/lib/__tests__/useMutation.test.d.ts.map +1 -0
  70. package/build/lib/__tests__/useMutationState.test.d.ts +1 -0
  71. package/build/lib/__tests__/useMutationState.test.d.ts.map +1 -0
  72. package/build/lib/__tests__/useQueries.test.d.ts +1 -0
  73. package/build/lib/__tests__/useQueries.test.d.ts.map +1 -0
  74. package/build/lib/__tests__/useQuery.test.d.ts +1 -0
  75. package/build/lib/__tests__/useQuery.test.d.ts.map +1 -0
  76. package/build/lib/__tests__/useQuery.types.test.d.ts +1 -0
  77. package/build/lib/__tests__/useQuery.types.test.d.ts.map +1 -0
  78. package/build/lib/__tests__/utils.d.ts +6 -5
  79. package/build/lib/__tests__/utils.d.ts.map +1 -0
  80. package/build/lib/errorBoundaryUtils.cjs +51 -0
  81. package/build/lib/errorBoundaryUtils.cjs.map +1 -0
  82. package/build/lib/errorBoundaryUtils.d.ts +4 -3
  83. package/build/lib/errorBoundaryUtils.d.ts.map +1 -0
  84. package/build/lib/errorBoundaryUtils.js +8 -30
  85. package/build/lib/errorBoundaryUtils.js.map +1 -1
  86. package/build/lib/index.cjs +39 -0
  87. package/build/lib/index.cjs.map +1 -0
  88. package/build/lib/index.d.ts +2 -1
  89. package/build/lib/index.d.ts.map +1 -0
  90. package/build/lib/index.js +11 -37
  91. package/build/lib/index.js.map +1 -1
  92. package/build/lib/isRestoring.cjs +31 -0
  93. package/build/lib/isRestoring.cjs.map +1 -0
  94. package/build/lib/isRestoring.d.ts +1 -0
  95. package/build/lib/isRestoring.d.ts.map +1 -0
  96. package/build/lib/isRestoring.js +5 -26
  97. package/build/lib/isRestoring.js.map +1 -1
  98. package/build/lib/{suspense.mjs → suspense.cjs} +8 -10
  99. package/build/lib/suspense.cjs.map +1 -0
  100. package/build/lib/suspense.d.ts +3 -5
  101. package/build/lib/suspense.d.ts.map +1 -0
  102. package/build/lib/suspense.js +3 -15
  103. package/build/lib/suspense.js.map +1 -1
  104. package/build/lib/types.d.ts +11 -10
  105. package/build/lib/types.d.ts.map +1 -0
  106. package/build/lib/useBaseQuery.cjs +80 -0
  107. package/build/lib/useBaseQuery.cjs.map +1 -0
  108. package/build/lib/useBaseQuery.d.ts +1 -0
  109. package/build/lib/useBaseQuery.d.ts.map +1 -0
  110. package/build/lib/useBaseQuery.js +30 -54
  111. package/build/lib/useBaseQuery.js.map +1 -1
  112. package/build/lib/useInfiniteQuery.cjs +15 -0
  113. package/build/lib/useInfiniteQuery.cjs.map +1 -0
  114. package/build/lib/useInfiniteQuery.d.ts +1 -0
  115. package/build/lib/useInfiniteQuery.d.ts.map +1 -0
  116. package/build/lib/useInfiniteQuery.js +6 -7
  117. package/build/lib/useInfiniteQuery.js.map +1 -1
  118. package/build/lib/useIsFetching.cjs +34 -0
  119. package/build/lib/useIsFetching.cjs.map +1 -0
  120. package/build/lib/useIsFetching.d.ts +1 -0
  121. package/build/lib/useIsFetching.d.ts.map +1 -0
  122. package/build/lib/useIsFetching.js +7 -27
  123. package/build/lib/useIsFetching.js.map +1 -1
  124. package/build/lib/useMutation.cjs +54 -0
  125. package/build/lib/useMutation.cjs.map +1 -0
  126. package/build/lib/useMutation.d.ts +1 -0
  127. package/build/lib/useMutation.d.ts.map +1 -0
  128. package/build/lib/useMutation.js +12 -32
  129. package/build/lib/useMutation.js.map +1 -1
  130. package/build/lib/useMutationState.cjs +60 -0
  131. package/build/lib/useMutationState.cjs.map +1 -0
  132. package/build/lib/useMutationState.d.ts +4 -3
  133. package/build/lib/useMutationState.d.ts.map +1 -0
  134. package/build/lib/useMutationState.js +13 -34
  135. package/build/lib/useMutationState.js.map +1 -1
  136. package/build/lib/useQueries.cjs +99 -0
  137. package/build/lib/useQueries.cjs.map +1 -0
  138. package/build/lib/useQueries.d.ts +10 -8
  139. package/build/lib/useQueries.d.ts.map +1 -0
  140. package/build/lib/useQueries.js +52 -67
  141. package/build/lib/useQueries.js.map +1 -1
  142. package/build/lib/useQuery.cjs +19 -0
  143. package/build/lib/useQuery.cjs.map +1 -0
  144. package/build/lib/useQuery.d.ts +5 -2
  145. package/build/lib/useQuery.d.ts.map +1 -0
  146. package/build/lib/useQuery.js +8 -5
  147. package/build/lib/useQuery.js.map +1 -1
  148. package/build/lib/{utils.esm.js → utils.cjs} +4 -2
  149. package/build/lib/{utils.mjs.map → utils.cjs.map} +1 -1
  150. package/build/lib/utils.d.ts +1 -0
  151. package/build/lib/utils.d.ts.map +1 -0
  152. package/build/lib/utils.js +1 -3
  153. package/build/lib/utils.js.map +1 -1
  154. package/package.json +24 -15
  155. package/src/__tests__/QueryResetErrorBoundary.test.tsx +752 -620
  156. package/src/__tests__/ssr-hydration.test.tsx +2 -2
  157. package/src/__tests__/suspense.test.tsx +6 -88
  158. package/src/__tests__/useInfiniteQuery.type.test.tsx +0 -27
  159. package/src/__tests__/useMutation.test.tsx +4 -4
  160. package/src/__tests__/useMutationState.test.tsx +23 -0
  161. package/src/__tests__/useQueries.test.tsx +206 -83
  162. package/src/__tests__/useQuery.test.tsx +246 -338
  163. package/src/__tests__/useQuery.types.test.tsx +21 -1
  164. package/src/errorBoundaryUtils.ts +6 -5
  165. package/src/index.ts +1 -1
  166. package/src/suspense.ts +9 -15
  167. package/src/useBaseQuery.ts +12 -23
  168. package/src/useInfiniteQuery.ts +1 -0
  169. package/src/useIsFetching.ts +1 -0
  170. package/src/useMutation.ts +2 -1
  171. package/src/useMutationState.ts +4 -3
  172. package/src/useQueries.ts +44 -26
  173. package/src/useQuery.ts +23 -0
  174. package/build/lib/HydrationBoundary.esm.js +0 -28
  175. package/build/lib/HydrationBoundary.esm.js.map +0 -1
  176. package/build/lib/HydrationBoundary.mjs +0 -28
  177. package/build/lib/QueryClientProvider.esm.js +0 -30
  178. package/build/lib/QueryClientProvider.esm.js.map +0 -1
  179. package/build/lib/QueryClientProvider.mjs +0 -30
  180. package/build/lib/QueryClientProvider.mjs.map +0 -1
  181. package/build/lib/QueryErrorResetBoundary.esm.js +0 -37
  182. package/build/lib/QueryErrorResetBoundary.esm.js.map +0 -1
  183. package/build/lib/QueryErrorResetBoundary.mjs +0 -37
  184. package/build/lib/errorBoundaryUtils.esm.js +0 -27
  185. package/build/lib/errorBoundaryUtils.esm.js.map +0 -1
  186. package/build/lib/errorBoundaryUtils.mjs +0 -27
  187. package/build/lib/errorBoundaryUtils.mjs.map +0 -1
  188. package/build/lib/index.esm.js +0 -12
  189. package/build/lib/index.esm.js.map +0 -1
  190. package/build/lib/index.mjs +0 -12
  191. package/build/lib/index.mjs.map +0 -1
  192. package/build/lib/isRestoring.esm.js +0 -8
  193. package/build/lib/isRestoring.esm.js.map +0 -1
  194. package/build/lib/isRestoring.mjs +0 -8
  195. package/build/lib/isRestoring.mjs.map +0 -1
  196. package/build/lib/suspense.esm.js +0 -24
  197. package/build/lib/suspense.esm.js.map +0 -1
  198. package/build/lib/suspense.mjs.map +0 -1
  199. package/build/lib/useBaseQuery.esm.js +0 -62
  200. package/build/lib/useBaseQuery.esm.js.map +0 -1
  201. package/build/lib/useBaseQuery.mjs +0 -62
  202. package/build/lib/useBaseQuery.mjs.map +0 -1
  203. package/build/lib/useInfiniteQuery.esm.js +0 -12
  204. package/build/lib/useInfiniteQuery.esm.js.map +0 -1
  205. package/build/lib/useInfiniteQuery.mjs +0 -12
  206. package/build/lib/useInfiniteQuery.mjs.map +0 -1
  207. package/build/lib/useIsFetching.esm.js +0 -12
  208. package/build/lib/useIsFetching.esm.js.map +0 -1
  209. package/build/lib/useIsFetching.mjs +0 -12
  210. package/build/lib/useIsFetching.mjs.map +0 -1
  211. package/build/lib/useMutation.esm.js +0 -32
  212. package/build/lib/useMutation.esm.js.map +0 -1
  213. package/build/lib/useMutation.mjs +0 -32
  214. package/build/lib/useMutation.mjs.map +0 -1
  215. package/build/lib/useMutationState.esm.js +0 -37
  216. package/build/lib/useMutationState.esm.js.map +0 -1
  217. package/build/lib/useMutationState.mjs +0 -37
  218. package/build/lib/useMutationState.mjs.map +0 -1
  219. package/build/lib/useQueries.esm.js +0 -72
  220. package/build/lib/useQueries.esm.js.map +0 -1
  221. package/build/lib/useQueries.mjs +0 -69
  222. package/build/lib/useQueries.mjs.map +0 -1
  223. package/build/lib/useQuery.esm.js +0 -11
  224. package/build/lib/useQuery.esm.js.map +0 -1
  225. package/build/lib/useQuery.mjs +0 -11
  226. package/build/lib/useQuery.mjs.map +0 -1
  227. package/build/lib/utils.esm.js.map +0 -1
  228. package/build/lib/utils.mjs +0 -10
  229. package/build/umd/index.development.js +0 -3040
  230. package/build/umd/index.development.js.map +0 -1
  231. package/build/umd/index.production.js +0 -2
  232. package/build/umd/index.production.js.map +0 -1
@@ -0,0 +1,188 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
2
+ const createV5UtilsObject = require('../utils')
3
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
4
+ const UnknownUsageError = require('../utils/unknown-usage-error')
5
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
6
+ const createQueryClientTransformer = require('../../../utils/transformers/query-client-transformer')
7
+
8
+ /**
9
+ * @param {import('jscodeshift').api} jscodeshift
10
+ * @param {Object} utils
11
+ * @param {import('jscodeshift').Collection} root
12
+ * @param {string} filePath
13
+ * @param {{keyName: "mutationKey"|"queryKey", queryClientMethods: ReadonlyArray<string>, hooks: ReadonlyArray<string>}} config
14
+ */
15
+ const transformQueryFnAwareUsages = ({
16
+ jscodeshift,
17
+ utils,
18
+ root,
19
+ filePath,
20
+ config,
21
+ }) => {
22
+ const v5Utils = createV5UtilsObject({ jscodeshift, utils })
23
+
24
+ /**
25
+ * @param {import('jscodeshift').CallExpression} node
26
+ * @returns {boolean}
27
+ */
28
+ const canSkipReplacement = (node) => {
29
+ const callArguments = node.arguments
30
+
31
+ const hasKeyProperty = () =>
32
+ callArguments[0].properties.some(
33
+ (property) =>
34
+ utils.isObjectProperty(property) &&
35
+ [config.keyName, 'queryFn'].includes(property.key.name),
36
+ )
37
+
38
+ return (
39
+ callArguments.length > 0 &&
40
+ utils.isObjectExpression(callArguments[0]) &&
41
+ hasKeyProperty()
42
+ )
43
+ }
44
+
45
+ const predicate = (property) => {
46
+ const isSpreadElement = utils.isSpreadElement(property)
47
+ const isObjectProperty = utils.isObjectProperty(property)
48
+
49
+ return (
50
+ isSpreadElement ||
51
+ (isObjectProperty && property.key.name !== config.keyName)
52
+ )
53
+ }
54
+
55
+ const transformArgumentToQueryFunction = (path, node) => {
56
+ const isIdentifier = utils.isIdentifier(node)
57
+ const isFunctionDefinition = utils.isFunctionDefinition(node)
58
+
59
+ if (!isIdentifier && !isFunctionDefinition) {
60
+ return undefined
61
+ }
62
+
63
+ if (isFunctionDefinition) {
64
+ return jscodeshift.property(
65
+ 'init',
66
+ jscodeshift.identifier('queryFn'),
67
+ node,
68
+ )
69
+ }
70
+
71
+ const binding = v5Utils.getBindingFromScope(path, node.name, filePath)
72
+ const initializer = v5Utils.getInitializerByDeclarator(binding)
73
+
74
+ if (!utils.isFunctionDefinition(initializer)) {
75
+ return undefined
76
+ }
77
+
78
+ return jscodeshift.property(
79
+ 'init',
80
+ jscodeshift.identifier('queryFn'),
81
+ binding.id,
82
+ )
83
+ }
84
+
85
+ const transformArgumentToOptionsObject = (path, node) => {
86
+ if (!utils.isIdentifier(node)) {
87
+ return undefined
88
+ }
89
+
90
+ const binding = v5Utils.getBindingFromScope(path, node.name, filePath)
91
+ const initializer = v5Utils.getInitializerByDeclarator(binding)
92
+
93
+ if (utils.isObjectExpression(initializer)) {
94
+ return jscodeshift.spreadElement(binding.id)
95
+ }
96
+ }
97
+
98
+ const replacer = (path) => {
99
+ const node = path.node
100
+
101
+ try {
102
+ // If the given method/function call matches certain criteria, the node doesn't need to be replaced, this step can be skipped.
103
+ if (canSkipReplacement(node)) {
104
+ return node
105
+ }
106
+
107
+ const keyProperty = v5Utils.transformArgumentToKey(
108
+ path,
109
+ node.arguments[0],
110
+ config.keyName,
111
+ filePath,
112
+ )
113
+
114
+ if (!keyProperty) {
115
+ throw new UnknownUsageError(node, filePath)
116
+ }
117
+
118
+ const parameters = [jscodeshift.objectExpression([keyProperty])]
119
+ const createdObjectExpression = parameters[0]
120
+ const secondParameter = node.arguments[1]
121
+
122
+ if (secondParameter) {
123
+ const queryFnProperty = transformArgumentToQueryFunction(
124
+ path,
125
+ secondParameter,
126
+ )
127
+
128
+ if (queryFnProperty) {
129
+ createdObjectExpression.properties.push(queryFnProperty)
130
+
131
+ const thirdParameter = node.arguments[2]
132
+
133
+ if (utils.isObjectExpression(thirdParameter)) {
134
+ v5Utils.copyPropertiesFromSource(
135
+ thirdParameter,
136
+ createdObjectExpression,
137
+ predicate,
138
+ )
139
+ } else {
140
+ createdObjectExpression.properties.push(
141
+ jscodeshift.spreadElement(thirdParameter),
142
+ )
143
+ }
144
+
145
+ return jscodeshift.callExpression(node.original.callee, parameters)
146
+ }
147
+
148
+ const optionsProperty = transformArgumentToOptionsObject(
149
+ path,
150
+ secondParameter,
151
+ )
152
+
153
+ if (optionsProperty) {
154
+ createdObjectExpression.properties.push(optionsProperty)
155
+
156
+ return jscodeshift.callExpression(node.original.callee, parameters)
157
+ }
158
+
159
+ if (utils.isObjectExpression(secondParameter)) {
160
+ v5Utils.copyPropertiesFromSource(
161
+ secondParameter,
162
+ createdObjectExpression,
163
+ predicate,
164
+ )
165
+ }
166
+
167
+ return jscodeshift.callExpression(node.original.callee, parameters)
168
+ }
169
+
170
+ return jscodeshift.callExpression(node.original.callee, parameters)
171
+ } catch (error) {
172
+ utils.warn(
173
+ error.name === UnknownUsageError.name
174
+ ? error.message
175
+ : `An unknown error occurred while processing the "${filePath}" file. Please review this file, because the codemod couldn't be applied.`,
176
+ )
177
+
178
+ return node
179
+ }
180
+ }
181
+
182
+ createQueryClientTransformer({ jscodeshift, utils, root }).execute(
183
+ config.queryClientMethods,
184
+ replacer,
185
+ )
186
+ }
187
+
188
+ module.exports = transformQueryFnAwareUsages
@@ -0,0 +1,124 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
2
+ const UnknownUsageError = require('./unknown-usage-error')
3
+
4
+ module.exports = ({ jscodeshift, utils }) => {
5
+ /**
6
+ *
7
+ * @param {import('jscodeshift').ObjectExpression} source
8
+ * @param {import('jscodeshift').ObjectExpression} target
9
+ * @param {(node: import('jscodeshift').Node) => boolean} predicate
10
+ */
11
+ const copyPropertiesFromSource = (source, target, predicate) => {
12
+ source.properties.forEach((property) => {
13
+ if (predicate(property)) {
14
+ target.properties.push(property)
15
+ }
16
+ })
17
+ }
18
+
19
+ /**
20
+ * @param {import('jscodeshift').NodePath} path
21
+ * @param {string} argumentName
22
+ * @param {string} filePath
23
+ * @returns {*}
24
+ */
25
+ const getBindingFromScope = (path, argumentName, filePath) => {
26
+ /**
27
+ * If the current scope contains the declaration then we can use the actual one else we attempt to find the
28
+ * binding from above.
29
+ */
30
+ const scope = path.scope.declares(argumentName)
31
+ ? path.scope
32
+ : path.scope.lookup(argumentName)
33
+
34
+ /**
35
+ * The declaration couldn't be found for some reason, time to move on. We warn the user it needs to be rewritten
36
+ * by themselves.
37
+ */
38
+ if (!scope) {
39
+ return undefined
40
+ }
41
+
42
+ const binding = scope.bindings[argumentName]
43
+ .filter((item) => utils.isIdentifier(item.value))
44
+ .map((item) => item.parentPath.value)
45
+ .at(0)
46
+
47
+ if (!binding) {
48
+ throw new UnknownUsageError(path.node, filePath)
49
+ }
50
+
51
+ return binding
52
+ }
53
+
54
+ /**
55
+ * @param {import('jscodeshift').VariableDeclarator} binding
56
+ * @returns {import('jscodeshift').Node|undefined}
57
+ */
58
+ const getInitializerByDeclarator = (binding) => {
59
+ const isVariableDeclaration = jscodeshift.match(binding, {
60
+ type: jscodeshift.VariableDeclarator.name,
61
+ })
62
+
63
+ if (!isVariableDeclaration) {
64
+ return undefined
65
+ }
66
+
67
+ const isTSAsExpression = jscodeshift.match(binding.init, {
68
+ type: jscodeshift.TSAsExpression.name,
69
+ })
70
+
71
+ return isTSAsExpression ? binding.init.expression : binding.init
72
+ }
73
+
74
+ /**
75
+ * @param {import('jscodeshift').Node} node
76
+ * @returns {boolean}
77
+ */
78
+ const isArrayExpressionVariable = (node) =>
79
+ jscodeshift.match(node, {
80
+ type: jscodeshift.VariableDeclarator.name,
81
+ init: {
82
+ type: jscodeshift.ArrayExpression.name,
83
+ },
84
+ })
85
+
86
+ /**
87
+ * @param {import('jscodeshift').NodePath} path
88
+ * @param {import('jscodeshift').Node} node
89
+ * @param {"queryKey"|"mutationKey"} keyName
90
+ * @param {string} filePath
91
+ * @returns {import('jscodeshift').Property|undefined}
92
+ */
93
+ const transformArgumentToKey = (path, node, keyName, filePath) => {
94
+ // If the first argument is an identifier we have to infer its type if possible.
95
+ if (utils.isIdentifier(node)) {
96
+ const binding = getBindingFromScope(path, node.name, filePath)
97
+
98
+ if (isArrayExpressionVariable(binding)) {
99
+ return jscodeshift.property(
100
+ 'init',
101
+ jscodeshift.identifier(keyName),
102
+ jscodeshift.identifier(binding.id.name),
103
+ )
104
+ }
105
+ }
106
+
107
+ // If the first argument is an array, then it matches the following overload:
108
+ // methodName(queryKey?: QueryKey, firstObject?: TFirstObject, secondObject?: TSecondObject)
109
+ if (utils.isArrayExpression(node)) {
110
+ // Then we create the 'queryKey' property based on it, because it will be passed to the first argument
111
+ // that should be an object according to the new signature.
112
+ return jscodeshift.property('init', jscodeshift.identifier(keyName), node)
113
+ }
114
+
115
+ return undefined
116
+ }
117
+
118
+ return {
119
+ copyPropertiesFromSource,
120
+ getInitializerByDeclarator,
121
+ getBindingFromScope,
122
+ transformArgumentToKey,
123
+ }
124
+ }
@@ -0,0 +1,27 @@
1
+ class UnknownUsageError extends Error {
2
+ /**
3
+ * @param {import('jscodeshift').CallExpression} callExpression
4
+ * @param {string} filePath
5
+ */
6
+ constructor(callExpression, filePath) {
7
+ super('')
8
+ this.message = this.buildMessage(callExpression, filePath)
9
+ this.name = 'UnknownUsageError'
10
+ }
11
+
12
+ /**
13
+ *
14
+ * @param {import('jscodeshift').CallExpression} callExpression
15
+ * @param {string} filePath
16
+ * @returns {string}
17
+ */
18
+ buildMessage(callExpression, filePath) {
19
+ const location = callExpression.callee.loc
20
+ const start = location.start.line
21
+ const end = location.end.line
22
+
23
+ return `The usage in file "${filePath}" at line ${start}:${end} could not be transformed into the new syntax. Please do this manually.`
24
+ }
25
+ }
26
+
27
+ module.exports = UnknownUsageError
@@ -0,0 +1,205 @@
1
+ module.exports = ({ root, jscodeshift }) => {
2
+ const findImportIdentifierOf = (importSpecifiers, identifier) => {
3
+ const specifier = importSpecifiers
4
+ .filter((node) => node.value.imported.name === identifier)
5
+ .paths()
6
+
7
+ if (specifier.length > 0) {
8
+ return specifier[0].value.local
9
+ }
10
+
11
+ return jscodeshift.identifier(identifier)
12
+ }
13
+
14
+ const findImportSpecifiers = () =>
15
+ root
16
+ .find(jscodeshift.ImportDeclaration, {
17
+ source: {
18
+ value: 'react-query',
19
+ },
20
+ })
21
+ .find(jscodeshift.ImportSpecifier, {})
22
+
23
+ const locateImports = (identifiers) => {
24
+ const findNamespaceImportIdentifier = () => {
25
+ const specifier = root
26
+ .find(jscodeshift.ImportDeclaration, {
27
+ source: {
28
+ value: 'react-query',
29
+ },
30
+ })
31
+ .find(jscodeshift.ImportNamespaceSpecifier)
32
+ .paths()
33
+
34
+ return specifier.length > 0 ? specifier[0].value.local : null
35
+ }
36
+
37
+ /**
38
+ * First, we search for the namespace import identifier because if we have any, we assume the consumer uses
39
+ * namespace imports. In this case, we won't search for named imports at all.
40
+ */
41
+ const namespaceImportIdentifier = findNamespaceImportIdentifier()
42
+
43
+ if (namespaceImportIdentifier) {
44
+ const identifierMap = {}
45
+
46
+ for (const identifier of identifiers) {
47
+ identifierMap[identifier] = jscodeshift.identifier(identifier)
48
+ }
49
+
50
+ return {
51
+ namespace: namespaceImportIdentifier,
52
+ ...identifierMap,
53
+ }
54
+ }
55
+
56
+ const importSpecifiers = findImportSpecifiers()
57
+ const identifierMap = {}
58
+
59
+ for (const identifier of identifiers) {
60
+ identifierMap[identifier] = findImportIdentifierOf(
61
+ importSpecifiers,
62
+ identifier,
63
+ )
64
+ }
65
+
66
+ return {
67
+ namespace: null,
68
+ ...identifierMap,
69
+ }
70
+ }
71
+
72
+ const findAllMethodCalls = () =>
73
+ root
74
+ // First, we need to find all method calls.
75
+ .find(jscodeshift.CallExpression, {
76
+ callee: {
77
+ type: jscodeshift.MemberExpression.name,
78
+ property: {
79
+ type: jscodeshift.Identifier.name,
80
+ },
81
+ },
82
+ })
83
+
84
+ const findQueryClientIdentifiers = (importIdentifiers) =>
85
+ root
86
+ .find(jscodeshift.VariableDeclarator, {})
87
+ .filter((node) => {
88
+ if (node.value.init) {
89
+ const initializer = node.value.init
90
+
91
+ return (
92
+ isClassInstantiationOf(
93
+ initializer,
94
+ getSelectorByImports(importIdentifiers, 'QueryClient'),
95
+ ) ||
96
+ isFunctionCallOf(
97
+ initializer,
98
+ getSelectorByImports(importIdentifiers, 'useQueryClient'),
99
+ )
100
+ )
101
+ }
102
+
103
+ return false
104
+ })
105
+ .paths()
106
+ .map((node) => node.value.id.name)
107
+
108
+ const isCallExpression = (node) =>
109
+ jscodeshift.match(node, { type: jscodeshift.CallExpression.name })
110
+
111
+ const isIdentifier = (node) =>
112
+ jscodeshift.match(node, { type: jscodeshift.Identifier.name })
113
+
114
+ const isMemberExpression = (node) =>
115
+ jscodeshift.match(node, { type: jscodeshift.MemberExpression.name })
116
+
117
+ const isNewExpression = (node) =>
118
+ jscodeshift.match(node, { type: jscodeshift.NewExpression.name })
119
+
120
+ const isArrayExpression = (node) =>
121
+ jscodeshift.match(node, { type: jscodeshift.ArrayExpression.name })
122
+
123
+ const isObjectExpression = (node) =>
124
+ jscodeshift.match(node, { type: jscodeshift.ObjectExpression.name })
125
+
126
+ const isObjectProperty = (node) =>
127
+ jscodeshift.match(node, { type: jscodeshift.ObjectProperty.name })
128
+
129
+ const isSpreadElement = (node) =>
130
+ jscodeshift.match(node, { type: jscodeshift.SpreadElement.name })
131
+
132
+ /**
133
+ * @param {import('jscodeshift').Node} node
134
+ * @returns {boolean}
135
+ */
136
+ const isFunctionDefinition = (node) => {
137
+ const isArrowFunctionExpression = jscodeshift.match(node, {
138
+ type: jscodeshift.ArrowFunctionExpression.name,
139
+ })
140
+ const isFunctionExpression = jscodeshift.match(node, {
141
+ type: jscodeshift.FunctionExpression.name,
142
+ })
143
+
144
+ return isArrowFunctionExpression || isFunctionExpression
145
+ }
146
+
147
+ const warn = (message) => {
148
+ if (process.env.NODE_ENV !== 'test') {
149
+ console.warn(message)
150
+ }
151
+ }
152
+
153
+ const isClassInstantiationOf = (node, selector) => {
154
+ if (!isNewExpression(node)) {
155
+ return false
156
+ }
157
+
158
+ const parts = selector.split('.')
159
+
160
+ return parts.length === 1
161
+ ? isIdentifier(node.callee) && node.callee.name === parts[0]
162
+ : isMemberExpression(node.callee) &&
163
+ node.callee.object.name === parts[0] &&
164
+ node.callee.property.name === parts[1]
165
+ }
166
+
167
+ const isFunctionCallOf = (node, selector) => {
168
+ if (!isCallExpression(node)) {
169
+ return false
170
+ }
171
+
172
+ const parts = selector.split('.')
173
+
174
+ return parts.length === 1
175
+ ? isIdentifier(node.callee) && node.callee.name === parts[0]
176
+ : isMemberExpression(node.callee) &&
177
+ node.callee.object.name === parts[0] &&
178
+ node.callee.property.name === parts[1]
179
+ }
180
+
181
+ const getSelectorByImports = (imports, path) =>
182
+ imports.namespace
183
+ ? `${imports.namespace.name}.${imports[path].name}`
184
+ : imports[path].name
185
+
186
+ return {
187
+ findAllMethodCalls,
188
+ getSelectorByImports,
189
+ isCallExpression,
190
+ isClassInstantiationOf,
191
+ isFunctionCallOf,
192
+ isIdentifier,
193
+ isMemberExpression,
194
+ isArrayExpression,
195
+ isObjectExpression,
196
+ isObjectProperty,
197
+ isSpreadElement,
198
+ isFunctionDefinition,
199
+ locateImports,
200
+ warn,
201
+ queryClient: {
202
+ findQueryClientIdentifiers,
203
+ },
204
+ }
205
+ }
@@ -0,0 +1,138 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
2
+ const createUtilsObject = require('../utils')
3
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
4
+ const createKeyReplacer = require('./utils/replacers/key-replacer')
5
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
6
+ const createUseQueryLikeTransformer = require('../utils/transformers/use-query-like-transformer')
7
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
8
+ const createQueryClientTransformer = require('../utils/transformers/query-client-transformer')
9
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
10
+ const createQueryCacheTransformer = require('../utils/transformers/query-cache-transformer')
11
+
12
+ const transformQueryClientUsages = ({ jscodeshift, utils, root, filePath }) => {
13
+ const transformer = createQueryClientTransformer({ jscodeshift, utils, root })
14
+ const replacer = createKeyReplacer({ jscodeshift, root, filePath })
15
+
16
+ transformer.execute(
17
+ [
18
+ // Not object syntax-aware methods.
19
+ 'getMutationDefaults',
20
+ 'getQueriesData',
21
+ 'getQueryData',
22
+ 'getQueryDefaults',
23
+ 'getQueryState',
24
+ 'isFetching',
25
+ 'setMutationDefaults',
26
+ 'setQueriesData',
27
+ 'setQueryData',
28
+ 'setQueryDefaults',
29
+ // Object syntax-aware methods.
30
+ 'cancelQueries',
31
+ 'fetchInfiniteQuery',
32
+ 'fetchQuery',
33
+ 'invalidateQueries',
34
+ 'prefetchInfiniteQuery',
35
+ 'prefetchQuery',
36
+ 'refetchQueries',
37
+ 'removeQueries',
38
+ 'resetQueries',
39
+ ],
40
+ replacer,
41
+ )
42
+ }
43
+
44
+ const transformUseQueriesUsages = ({ jscodeshift, utils, root }) => {
45
+ const transformer = createUseQueryLikeTransformer({
46
+ jscodeshift,
47
+ utils,
48
+ root,
49
+ })
50
+ const replacer = ({ node }) => {
51
+ /**
52
+ * When the node doesn't have the 'original' property, that means the codemod has been already applied,
53
+ * so we don't need to do any changes.
54
+ */
55
+ if (!node.original) {
56
+ return node
57
+ }
58
+
59
+ const newCallExpression = jscodeshift.callExpression(node.original.callee, [
60
+ jscodeshift.objectExpression([
61
+ jscodeshift.property(
62
+ 'init',
63
+ jscodeshift.identifier('queries'),
64
+ node.original.arguments[0],
65
+ ),
66
+ ]),
67
+ ])
68
+
69
+ // TODO: This should be part of one function!
70
+ if (node.typeParameters) {
71
+ newCallExpression.typeArguments = node.typeParameters
72
+ }
73
+
74
+ return newCallExpression
75
+ }
76
+
77
+ transformer.execute(['useQueries'], replacer)
78
+ }
79
+
80
+ const transformUseQueryLikeUsages = ({
81
+ jscodeshift,
82
+ utils,
83
+ root,
84
+ filePath,
85
+ }) => {
86
+ const transformer = createUseQueryLikeTransformer({
87
+ jscodeshift,
88
+ utils,
89
+ root,
90
+ })
91
+
92
+ transformer.execute(
93
+ ['useQuery', 'useInfiniteQuery', 'useIsFetching', 'useIsMutating'],
94
+ createKeyReplacer({
95
+ jscodeshift,
96
+ root,
97
+ filePath,
98
+ keyName: 'queryKey',
99
+ }),
100
+ )
101
+ transformer.execute(
102
+ ['useMutation'],
103
+ createKeyReplacer({
104
+ jscodeshift,
105
+ root,
106
+ filePath,
107
+ keyName: 'mutationKey',
108
+ }),
109
+ )
110
+ }
111
+
112
+ const transformQueryCacheUsages = ({ jscodeshift, utils, root, filePath }) => {
113
+ const transformer = createQueryCacheTransformer({ jscodeshift, utils, root })
114
+ const replacer = createKeyReplacer({ jscodeshift, root, filePath })
115
+
116
+ transformer.execute(replacer)
117
+ }
118
+
119
+ module.exports = (file, api) => {
120
+ const jscodeshift = api.jscodeshift
121
+ const root = jscodeshift(file.source)
122
+
123
+ // TODO: Execute the transformers only when it contains a `react-query` import!
124
+
125
+ const utils = createUtilsObject({ root, jscodeshift })
126
+ const filePath = file.path
127
+
128
+ // This function transforms usages like `useQuery` and `useMutation`.
129
+ transformUseQueryLikeUsages({ jscodeshift, utils, root, filePath })
130
+ // This function transforms usages of `useQueries`.
131
+ transformUseQueriesUsages({ jscodeshift, utils, root })
132
+ // This function transforms usages of `QueryClient`.
133
+ transformQueryClientUsages({ jscodeshift, utils, root, filePath })
134
+ // This function transforms usages of `QueryCache`.
135
+ transformQueryCacheUsages({ jscodeshift, utils, root, filePath })
136
+
137
+ return root.toSource({ quote: 'single' })
138
+ }
@@ -0,0 +1,25 @@
1
+ module.exports = (file, api) => {
2
+ const jscodeshift = api.jscodeshift
3
+ const root = jscodeshift(file.source)
4
+
5
+ const replacements = [
6
+ { from: 'react-query', to: '@tanstack/react-query' },
7
+ { from: 'react-query/devtools', to: '@tanstack/react-query-devtools' },
8
+ ]
9
+
10
+ replacements.forEach(({ from, to }) => {
11
+ root
12
+ .find(jscodeshift.ImportDeclaration, {
13
+ source: {
14
+ value: from,
15
+ },
16
+ })
17
+ .replaceWith(({ node }) => {
18
+ node.source.value = to
19
+
20
+ return node
21
+ })
22
+ })
23
+
24
+ return root.toSource({ quote: 'single' })
25
+ }