diff --git a/codemods/jest.config.js b/codemods/jest.config.js new file mode 100644 index 0000000000..5b36187188 --- /dev/null +++ b/codemods/jest.config.js @@ -0,0 +1,3 @@ +module.exports = { + testMatch: ['/**/*.test.js'], +} diff --git a/codemods/v4/__testfixtures__/default-import.input.tsx b/codemods/v4/__testfixtures__/default-import.input.tsx new file mode 100644 index 0000000000..23c1c4c490 --- /dev/null +++ b/codemods/v4/__testfixtures__/default-import.input.tsx @@ -0,0 +1,94 @@ +import * as React from 'react' +import { + QueryCache, + QueryClient, + useInfiniteQuery, + useIsFetching, + useIsMutating, + useMutation, + useQueries, + useQuery, + useQueryClient, +} from 'react-query' + +export const Examples = () => { + useQuery('todos') + useInfiniteQuery('todos') + useMutation('todos') + useIsFetching('todos') + useIsMutating('todos') + useQueries([query1, query2]) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.getMutationDefaults('todos') + queryClient.getQueriesData('todos') + queryClient.getQueryData('todos') + queryClient.getQueryDefaults('todos') + queryClient.getQueryState('todos') + queryClient.isFetching('todos') + queryClient.setMutationDefaults('todos', { mutationFn: async () => null }) + queryClient.setQueriesData('todos', () => null) + queryClient.setQueryData('todos', () => null) + queryClient.setQueryDefaults('todos', { queryFn: async () => null }) + queryClient.cancelQueries('todos') + queryClient.fetchInfiniteQuery('todos') + queryClient.fetchQuery('todos') + queryClient.invalidateQueries('todos') + queryClient.prefetchInfiniteQuery('todos') + queryClient.prefetchQuery('todos') + queryClient.refetchQueries('todos') + queryClient.removeQueries('todos') + queryClient.resetQueries('todos') + // --- Direct hook call. + useQueryClient().getMutationDefaults('todos') + useQueryClient().getQueriesData('todos') + useQueryClient().getQueryData('todos') + useQueryClient().getQueryDefaults('todos') + useQueryClient().getQueryState('todos') + useQueryClient().isFetching('todos') + useQueryClient().setMutationDefaults('todos', { + mutationFn: async () => null, + }) + useQueryClient().setQueriesData('todos', () => null) + useQueryClient().setQueryData('todos', () => null) + useQueryClient().setQueryDefaults('todos', { queryFn: async () => null }) + useQueryClient().cancelQueries('todos') + useQueryClient().fetchInfiniteQuery('todos') + useQueryClient().fetchQuery('todos') + useQueryClient().invalidateQueries('todos') + useQueryClient().prefetchInfiniteQuery('todos') + useQueryClient().prefetchQuery('todos') + useQueryClient().refetchQueries('todos') + useQueryClient().removeQueries('todos') + useQueryClient().resetQueries('todos') + // QueryCache + // --- NewExpression + const queryCache1 = new QueryCache({ + onError: (error) => console.log(error), + onSuccess: (success) => console.log(success) + }) + queryCache1.find('todos') + queryCache1.findAll('todos') + // --- Instantiated hook call. + const queryClient1 = useQueryClient() + queryClient1.getQueryCache().find('todos') + queryClient1.getQueryCache().findAll('todos') + // + const queryClient2 = new QueryClient({}) + queryClient2.getQueryCache().find('todos') + queryClient2.getQueryCache().findAll('todos') + // + const queryCache2 = queryClient1.getQueryCache() + queryCache2.find('todos') + queryCache2.findAll('todos') + // --- Direct hook call. + useQueryClient().getQueryCache().find('todos') + useQueryClient().getQueryCache().findAll('todos') + // + const queryCache3 = useQueryClient().getQueryCache() + queryCache3.find('todos') + queryCache3.findAll('todos') + + return
Example Component
+} diff --git a/codemods/v4/__testfixtures__/default-import.output.tsx b/codemods/v4/__testfixtures__/default-import.output.tsx new file mode 100644 index 0000000000..56cee68386 --- /dev/null +++ b/codemods/v4/__testfixtures__/default-import.output.tsx @@ -0,0 +1,96 @@ +import * as React from 'react' +import { + QueryCache, + QueryClient, + useInfiniteQuery, + useIsFetching, + useIsMutating, + useMutation, + useQueries, + useQuery, + useQueryClient, +} from 'react-query' + +export const Examples = () => { + useQuery(['todos']) + useInfiniteQuery(['todos']) + useMutation(['todos']) + useIsFetching(['todos']) + useIsMutating(['todos']) + useQueries({ + queries: [query1, query2] + }) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.getMutationDefaults(['todos']) + queryClient.getQueriesData(['todos']) + queryClient.getQueryData(['todos']) + queryClient.getQueryDefaults(['todos']) + queryClient.getQueryState(['todos']) + queryClient.isFetching(['todos']) + queryClient.setMutationDefaults(['todos'], { mutationFn: async () => null }) + queryClient.setQueriesData(['todos'], () => null) + queryClient.setQueryData(['todos'], () => null) + queryClient.setQueryDefaults(['todos'], { queryFn: async () => null }) + queryClient.cancelQueries(['todos']) + queryClient.fetchInfiniteQuery(['todos']) + queryClient.fetchQuery(['todos']) + queryClient.invalidateQueries(['todos']) + queryClient.prefetchInfiniteQuery(['todos']) + queryClient.prefetchQuery(['todos']) + queryClient.refetchQueries(['todos']) + queryClient.removeQueries(['todos']) + queryClient.resetQueries(['todos']) + // --- Direct hook call. + useQueryClient().getMutationDefaults(['todos']) + useQueryClient().getQueriesData(['todos']) + useQueryClient().getQueryData(['todos']) + useQueryClient().getQueryDefaults(['todos']) + useQueryClient().getQueryState(['todos']) + useQueryClient().isFetching(['todos']) + useQueryClient().setMutationDefaults(['todos'], { + mutationFn: async () => null, + }) + useQueryClient().setQueriesData(['todos'], () => null) + useQueryClient().setQueryData(['todos'], () => null) + useQueryClient().setQueryDefaults(['todos'], { queryFn: async () => null }) + useQueryClient().cancelQueries(['todos']) + useQueryClient().fetchInfiniteQuery(['todos']) + useQueryClient().fetchQuery(['todos']) + useQueryClient().invalidateQueries(['todos']) + useQueryClient().prefetchInfiniteQuery(['todos']) + useQueryClient().prefetchQuery(['todos']) + useQueryClient().refetchQueries(['todos']) + useQueryClient().removeQueries(['todos']) + useQueryClient().resetQueries(['todos']) + // QueryCache + // --- NewExpression + const queryCache1 = new QueryCache({ + onError: (error) => console.log(error), + onSuccess: (success) => console.log(success) + }) + queryCache1.find(['todos']) + queryCache1.findAll(['todos']) + // --- Instantiated hook call. + const queryClient1 = useQueryClient() + queryClient1.getQueryCache().find(['todos']) + queryClient1.getQueryCache().findAll(['todos']) + // + const queryClient2 = new QueryClient({}) + queryClient2.getQueryCache().find(['todos']) + queryClient2.getQueryCache().findAll(['todos']) + // + const queryCache2 = queryClient1.getQueryCache() + queryCache2.find(['todos']) + queryCache2.findAll(['todos']) + // --- Direct hook call. + useQueryClient().getQueryCache().find(['todos']) + useQueryClient().getQueryCache().findAll(['todos']) + // + const queryCache3 = useQueryClient().getQueryCache() + queryCache3.find(['todos']) + queryCache3.findAll(['todos']) + + return
Example Component
+} diff --git a/codemods/v4/__testfixtures__/named-import.input.tsx b/codemods/v4/__testfixtures__/named-import.input.tsx new file mode 100644 index 0000000000..2d8d594762 --- /dev/null +++ b/codemods/v4/__testfixtures__/named-import.input.tsx @@ -0,0 +1,96 @@ +import * as React from 'react' +import { + QueryCache as RenamedQueryCache, + QueryClient as RenamedQueryClient, + useInfiniteQuery as useRenamedInfiniteQuery, + useIsFetching as useRenamedIsFetching, + useIsMutating as useRenamedIsMutating, + useMutation as useRenamedMutation, + useQueries as useRenamedQueries, + useQuery as useRenamedQuery, + useQueryClient as useRenamedQueryClient, +} from 'react-query' + +export const Examples = () => { + useRenamedQuery('todos') + useRenamedInfiniteQuery('todos') + useRenamedMutation('todos') + useRenamedIsFetching('todos') + useRenamedIsMutating('todos') + useRenamedQueries([query1, query2]) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useRenamedQueryClient() + queryClient.getMutationDefaults('todos') + queryClient.getQueriesData('todos') + queryClient.getQueryData('todos') + queryClient.getQueryDefaults('todos') + queryClient.getQueryState('todos') + queryClient.isFetching('todos') + queryClient.setMutationDefaults('todos', { mutationFn: async () => null }) + queryClient.setQueriesData('todos', () => null) + queryClient.setQueryData('todos', () => null) + queryClient.setQueryDefaults('todos', { queryFn: async () => null }) + queryClient.cancelQueries('todos') + queryClient.fetchInfiniteQuery('todos') + queryClient.fetchQuery('todos') + queryClient.invalidateQueries('todos') + queryClient.prefetchInfiniteQuery('todos') + queryClient.prefetchQuery('todos') + queryClient.refetchQueries('todos') + queryClient.removeQueries('todos') + queryClient.resetQueries('todos') + // --- Direct hook call. + useRenamedQueryClient().getMutationDefaults('todos') + useRenamedQueryClient().getQueriesData('todos') + useRenamedQueryClient().getQueryData('todos') + useRenamedQueryClient().getQueryDefaults('todos') + useRenamedQueryClient().getQueryState('todos') + useRenamedQueryClient().isFetching('todos') + useRenamedQueryClient().setMutationDefaults('todos', { + mutationFn: async () => null, + }) + useRenamedQueryClient().setQueriesData('todos', () => null) + useRenamedQueryClient().setQueryData('todos', () => null) + useRenamedQueryClient().setQueryDefaults('todos', { + queryFn: async () => null, + }) + useRenamedQueryClient().cancelQueries('todos') + useRenamedQueryClient().fetchInfiniteQuery('todos') + useRenamedQueryClient().fetchQuery('todos') + useRenamedQueryClient().invalidateQueries('todos') + useRenamedQueryClient().prefetchInfiniteQuery('todos') + useRenamedQueryClient().prefetchQuery('todos') + useRenamedQueryClient().refetchQueries('todos') + useRenamedQueryClient().removeQueries('todos') + useRenamedQueryClient().resetQueries('todos') + // QueryCache + // --- NewExpression + const queryCache1 = new RenamedQueryCache({ + onError: (error) => console.log(error), + onSuccess: (success) => console.log(success) + }) + queryCache1.find('todos') + queryCache1.findAll('todos') + // --- Instantiated hook call. + const queryClient1 = useRenamedQueryClient() + queryClient1.getQueryCache().find('todos') + queryClient1.getQueryCache().findAll('todos') + // + const queryClient2 = new RenamedQueryClient({}) + queryClient2.getQueryCache().find('todos') + queryClient2.getQueryCache().findAll('todos') + // + const queryCache2 = queryClient1.getQueryCache() + queryCache2.find('todos') + queryCache2.findAll('todos') + // --- Direct hook call. + useRenamedQueryClient().getQueryCache().find('todos') + useRenamedQueryClient().getQueryCache().findAll('todos') + // + const queryCache3 = useRenamedQueryClient().getQueryCache() + queryCache3.find('todos') + queryCache3.findAll('todos') + + return
Example Component
+} diff --git a/codemods/v4/__testfixtures__/named-import.output.tsx b/codemods/v4/__testfixtures__/named-import.output.tsx new file mode 100644 index 0000000000..716f56be06 --- /dev/null +++ b/codemods/v4/__testfixtures__/named-import.output.tsx @@ -0,0 +1,98 @@ +import * as React from 'react' +import { + QueryCache as RenamedQueryCache, + QueryClient as RenamedQueryClient, + useInfiniteQuery as useRenamedInfiniteQuery, + useIsFetching as useRenamedIsFetching, + useIsMutating as useRenamedIsMutating, + useMutation as useRenamedMutation, + useQueries as useRenamedQueries, + useQuery as useRenamedQuery, + useQueryClient as useRenamedQueryClient, +} from 'react-query' + +export const Examples = () => { + useRenamedQuery(['todos']) + useRenamedInfiniteQuery(['todos']) + useRenamedMutation(['todos']) + useRenamedIsFetching(['todos']) + useRenamedIsMutating(['todos']) + useRenamedQueries({ + queries: [query1, query2] + }) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useRenamedQueryClient() + queryClient.getMutationDefaults(['todos']) + queryClient.getQueriesData(['todos']) + queryClient.getQueryData(['todos']) + queryClient.getQueryDefaults(['todos']) + queryClient.getQueryState(['todos']) + queryClient.isFetching(['todos']) + queryClient.setMutationDefaults(['todos'], { mutationFn: async () => null }) + queryClient.setQueriesData(['todos'], () => null) + queryClient.setQueryData(['todos'], () => null) + queryClient.setQueryDefaults(['todos'], { queryFn: async () => null }) + queryClient.cancelQueries(['todos']) + queryClient.fetchInfiniteQuery(['todos']) + queryClient.fetchQuery(['todos']) + queryClient.invalidateQueries(['todos']) + queryClient.prefetchInfiniteQuery(['todos']) + queryClient.prefetchQuery(['todos']) + queryClient.refetchQueries(['todos']) + queryClient.removeQueries(['todos']) + queryClient.resetQueries(['todos']) + // --- Direct hook call. + useRenamedQueryClient().getMutationDefaults(['todos']) + useRenamedQueryClient().getQueriesData(['todos']) + useRenamedQueryClient().getQueryData(['todos']) + useRenamedQueryClient().getQueryDefaults(['todos']) + useRenamedQueryClient().getQueryState(['todos']) + useRenamedQueryClient().isFetching(['todos']) + useRenamedQueryClient().setMutationDefaults(['todos'], { + mutationFn: async () => null, + }) + useRenamedQueryClient().setQueriesData(['todos'], () => null) + useRenamedQueryClient().setQueryData(['todos'], () => null) + useRenamedQueryClient().setQueryDefaults(['todos'], { + queryFn: async () => null, + }) + useRenamedQueryClient().cancelQueries(['todos']) + useRenamedQueryClient().fetchInfiniteQuery(['todos']) + useRenamedQueryClient().fetchQuery(['todos']) + useRenamedQueryClient().invalidateQueries(['todos']) + useRenamedQueryClient().prefetchInfiniteQuery(['todos']) + useRenamedQueryClient().prefetchQuery(['todos']) + useRenamedQueryClient().refetchQueries(['todos']) + useRenamedQueryClient().removeQueries(['todos']) + useRenamedQueryClient().resetQueries(['todos']) + // QueryCache + // --- NewExpression + const queryCache1 = new RenamedQueryCache({ + onError: (error) => console.log(error), + onSuccess: (success) => console.log(success) + }) + queryCache1.find(['todos']) + queryCache1.findAll(['todos']) + // --- Instantiated hook call. + const queryClient1 = useRenamedQueryClient() + queryClient1.getQueryCache().find(['todos']) + queryClient1.getQueryCache().findAll(['todos']) + // + const queryClient2 = new RenamedQueryClient({}) + queryClient2.getQueryCache().find(['todos']) + queryClient2.getQueryCache().findAll(['todos']) + // + const queryCache2 = queryClient1.getQueryCache() + queryCache2.find(['todos']) + queryCache2.findAll(['todos']) + // --- Direct hook call. + useRenamedQueryClient().getQueryCache().find(['todos']) + useRenamedQueryClient().getQueryCache().findAll(['todos']) + // + const queryCache3 = useRenamedQueryClient().getQueryCache() + queryCache3.find(['todos']) + queryCache3.findAll(['todos']) + + return
Example Component
+} diff --git a/codemods/v4/__testfixtures__/namespaced-import.input.tsx b/codemods/v4/__testfixtures__/namespaced-import.input.tsx new file mode 100644 index 0000000000..95d2b282ac --- /dev/null +++ b/codemods/v4/__testfixtures__/namespaced-import.input.tsx @@ -0,0 +1,86 @@ +import * as React from 'react' +import * as RQ from 'react-query' + +export const Examples = () => { + RQ.useQuery('todos') + RQ.useInfiniteQuery('todos') + RQ.useMutation('todos') + RQ.useIsFetching('todos') + RQ.useIsMutating('todos') + RQ.useQueries([query1, query2]) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = RQ.useQueryClient() + queryClient.getMutationDefaults('todos') + queryClient.getQueriesData('todos') + queryClient.getQueryData('todos') + queryClient.getQueryDefaults('todos') + queryClient.getQueryState('todos') + queryClient.isFetching('todos') + queryClient.setMutationDefaults('todos', { mutationFn: async () => null }) + queryClient.setQueriesData('todos', () => null) + queryClient.setQueryData('todos', () => null) + queryClient.setQueryDefaults('todos', { queryFn: async () => null }) + queryClient.cancelQueries('todos') + queryClient.fetchInfiniteQuery('todos') + queryClient.fetchQuery('todos') + queryClient.invalidateQueries('todos') + queryClient.prefetchInfiniteQuery('todos') + queryClient.prefetchQuery('todos') + queryClient.refetchQueries('todos') + queryClient.removeQueries('todos') + queryClient.resetQueries('todos') + // --- Direct hook call. + RQ.useQueryClient().getMutationDefaults('todos') + RQ.useQueryClient().getQueriesData('todos') + RQ.useQueryClient().getQueryData('todos') + RQ.useQueryClient().getQueryDefaults('todos') + RQ.useQueryClient().getQueryState('todos') + RQ.useQueryClient().isFetching('todos') + RQ.useQueryClient().setMutationDefaults('todos', { + mutationFn: async () => null, + }) + RQ.useQueryClient().setQueriesData('todos', () => null) + RQ.useQueryClient().setQueryData('todos', () => null) + RQ.useQueryClient().setQueryDefaults('todos', { + queryFn: async () => null, + }) + RQ.useQueryClient().cancelQueries('todos') + RQ.useQueryClient().fetchInfiniteQuery('todos') + RQ.useQueryClient().fetchQuery('todos') + RQ.useQueryClient().invalidateQueries('todos') + RQ.useQueryClient().prefetchInfiniteQuery('todos') + RQ.useQueryClient().prefetchQuery('todos') + RQ.useQueryClient().refetchQueries('todos') + RQ.useQueryClient().removeQueries('todos') + RQ.useQueryClient().resetQueries('todos') + // QueryCache + // --- NewExpression + const queryCache1 = new RQ.QueryCache({ + onError: (error) => console.log(error), + onSuccess: (success) => console.log(success) + }) + queryCache1.find('todos') + queryCache1.findAll('todos') + // --- Instantiated hook call. + const queryClient1 = RQ.useQueryClient() + queryClient1.getQueryCache().find('todos') + queryClient1.getQueryCache().findAll('todos') + // + const queryClient2 = new RQ.QueryClient({}) + queryClient2.getQueryCache().find('todos') + queryClient2.getQueryCache().findAll('todos') + // + const queryCache2 = queryClient1.getQueryCache() + queryCache2.find('todos') + queryCache2.findAll('todos') + // --- Direct hook call. + RQ.useQueryClient().getQueryCache().find('todos') + RQ.useQueryClient().getQueryCache().findAll('todos') + // + const queryCache3 = RQ.useQueryClient().getQueryCache() + queryCache3.find('todos') + queryCache3.findAll('todos') + + return
Example Component
+} diff --git a/codemods/v4/__testfixtures__/namespaced-import.output.tsx b/codemods/v4/__testfixtures__/namespaced-import.output.tsx new file mode 100644 index 0000000000..b6b13f36cf --- /dev/null +++ b/codemods/v4/__testfixtures__/namespaced-import.output.tsx @@ -0,0 +1,88 @@ +import * as React from 'react' +import * as RQ from 'react-query' + +export const Examples = () => { + RQ.useQuery(['todos']) + RQ.useInfiniteQuery(['todos']) + RQ.useMutation(['todos']) + RQ.useIsFetching(['todos']) + RQ.useIsMutating(['todos']) + RQ.useQueries({ + queries: [query1, query2] + }) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = RQ.useQueryClient() + queryClient.getMutationDefaults(['todos']) + queryClient.getQueriesData(['todos']) + queryClient.getQueryData(['todos']) + queryClient.getQueryDefaults(['todos']) + queryClient.getQueryState(['todos']) + queryClient.isFetching(['todos']) + queryClient.setMutationDefaults(['todos'], { mutationFn: async () => null }) + queryClient.setQueriesData(['todos'], () => null) + queryClient.setQueryData(['todos'], () => null) + queryClient.setQueryDefaults(['todos'], { queryFn: async () => null }) + queryClient.cancelQueries(['todos']) + queryClient.fetchInfiniteQuery(['todos']) + queryClient.fetchQuery(['todos']) + queryClient.invalidateQueries(['todos']) + queryClient.prefetchInfiniteQuery(['todos']) + queryClient.prefetchQuery(['todos']) + queryClient.refetchQueries(['todos']) + queryClient.removeQueries(['todos']) + queryClient.resetQueries(['todos']) + // --- Direct hook call. + RQ.useQueryClient().getMutationDefaults(['todos']) + RQ.useQueryClient().getQueriesData(['todos']) + RQ.useQueryClient().getQueryData(['todos']) + RQ.useQueryClient().getQueryDefaults(['todos']) + RQ.useQueryClient().getQueryState(['todos']) + RQ.useQueryClient().isFetching(['todos']) + RQ.useQueryClient().setMutationDefaults(['todos'], { + mutationFn: async () => null, + }) + RQ.useQueryClient().setQueriesData(['todos'], () => null) + RQ.useQueryClient().setQueryData(['todos'], () => null) + RQ.useQueryClient().setQueryDefaults(['todos'], { + queryFn: async () => null, + }) + RQ.useQueryClient().cancelQueries(['todos']) + RQ.useQueryClient().fetchInfiniteQuery(['todos']) + RQ.useQueryClient().fetchQuery(['todos']) + RQ.useQueryClient().invalidateQueries(['todos']) + RQ.useQueryClient().prefetchInfiniteQuery(['todos']) + RQ.useQueryClient().prefetchQuery(['todos']) + RQ.useQueryClient().refetchQueries(['todos']) + RQ.useQueryClient().removeQueries(['todos']) + RQ.useQueryClient().resetQueries(['todos']) + // QueryCache + // --- NewExpression + const queryCache1 = new RQ.QueryCache({ + onError: (error) => console.log(error), + onSuccess: (success) => console.log(success) + }) + queryCache1.find(['todos']) + queryCache1.findAll(['todos']) + // --- Instantiated hook call. + const queryClient1 = RQ.useQueryClient() + queryClient1.getQueryCache().find(['todos']) + queryClient1.getQueryCache().findAll(['todos']) + // + const queryClient2 = new RQ.QueryClient({}) + queryClient2.getQueryCache().find(['todos']) + queryClient2.getQueryCache().findAll(['todos']) + // + const queryCache2 = queryClient1.getQueryCache() + queryCache2.find(['todos']) + queryCache2.findAll(['todos']) + // --- Direct hook call. + RQ.useQueryClient().getQueryCache().find(['todos']) + RQ.useQueryClient().getQueryCache().findAll(['todos']) + // + const queryCache3 = RQ.useQueryClient().getQueryCache() + queryCache3.find(['todos']) + queryCache3.findAll(['todos']) + + return
Example Component
+} diff --git a/codemods/v4/__testfixtures__/parameter-is-identifier.input.tsx b/codemods/v4/__testfixtures__/parameter-is-identifier.input.tsx new file mode 100644 index 0000000000..a6126bdcef --- /dev/null +++ b/codemods/v4/__testfixtures__/parameter-is-identifier.input.tsx @@ -0,0 +1,49 @@ +import * as React from 'react' +import { useMutation, useQuery, useQueryClient } from 'react-query' + +export const ExampleWithStringLiteralKey = () => { + const stringLiteralKey = 'todos' + useQuery(stringLiteralKey) + useMutation(stringLiteralKey) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries(stringLiteralKey) + // --- Direct hook call. + useQueryClient().cancelQueries(stringLiteralKey) + + return
Example Component
+} + +export const ExampleWithTemplateLiteral = () => { + const templateLiteralKey = `todos` + useQuery(templateLiteralKey) + useMutation(templateLiteralKey) +} + +export const ExampleWithArrayExpressionKey = () => { + const arrayExpressionKey = ['todos'] + useQuery(arrayExpressionKey) + useMutation(arrayExpressionKey) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries(queryKey2) + // --- Direct hook call. + useQueryClient().cancelQueries(queryKey2) + + return
Example Component
+} + +export const ExampleWithUnknownKey = () => { + useQuery(unknownQueryKey) + useMutation(unknownQueryKey) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries(unknownQueryKey) + // --- Direct hook call. + useQueryClient().cancelQueries(unknownQueryKey) + + return
Example Component
+} diff --git a/codemods/v4/__testfixtures__/parameter-is-identifier.output.tsx b/codemods/v4/__testfixtures__/parameter-is-identifier.output.tsx new file mode 100644 index 0000000000..94c2ca1e75 --- /dev/null +++ b/codemods/v4/__testfixtures__/parameter-is-identifier.output.tsx @@ -0,0 +1,49 @@ +import * as React from 'react' +import { useMutation, useQuery, useQueryClient } from 'react-query' + +export const ExampleWithStringLiteralKey = () => { + const stringLiteralKey = 'todos' + useQuery([stringLiteralKey]) + useMutation([stringLiteralKey]) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries([stringLiteralKey]) + // --- Direct hook call. + useQueryClient().cancelQueries([stringLiteralKey]) + + return
Example Component
+} + +export const ExampleWithTemplateLiteral = () => { + const templateLiteralKey = `todos` + useQuery([templateLiteralKey]) + useMutation([templateLiteralKey]) +} + +export const ExampleWithArrayExpressionKey = () => { + const arrayExpressionKey = ['todos'] + useQuery(arrayExpressionKey) + useMutation(arrayExpressionKey) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries(queryKey2) + // --- Direct hook call. + useQueryClient().cancelQueries(queryKey2) + + return
Example Component
+} + +export const ExampleWithUnknownKey = () => { + useQuery(unknownQueryKey) + useMutation(unknownQueryKey) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries(unknownQueryKey) + // --- Direct hook call. + useQueryClient().cancelQueries(unknownQueryKey) + + return
Example Component
+} diff --git a/codemods/v4/__testfixtures__/parameter-is-object-expression.input.tsx b/codemods/v4/__testfixtures__/parameter-is-object-expression.input.tsx new file mode 100644 index 0000000000..4319c965ec --- /dev/null +++ b/codemods/v4/__testfixtures__/parameter-is-object-expression.input.tsx @@ -0,0 +1,128 @@ +import * as React from 'react' +import { useMutation, useQuery, useQueryClient } from 'react-query' + +const options = {} + +export const ExampleWithStringLiteral = () => { + useQuery({ queryKey: 'todos', exact: true }, options) + useMutation({ mutationKey: 'todos', exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: 'todos', exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: 'todos', exact: true }, options) + + return
Example Component
+} + +export const ExampleWithStringLiteralIdentifier = () => { + const stringLiteralKey = 'todos' + useQuery({ queryKey: stringLiteralKey, exact: true }, options) + useMutation({ mutationKey: stringLiteralKey, exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: stringLiteralKey, exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: stringLiteralKey, exact: true }, options) + + return
Example Component
+} + +export const ExampleWithTemplateLiteral = () => { + useQuery({ queryKey: `todos`, exact: true }, options) + useMutation({ mutationKey: `todos`, exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: `todos`, exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: `todos`, exact: true }, options) + + return
Example Component
+} + +export const ExampleWithTemplateLiteralIdentifier = () => { + const templateLiteralKey = `todos` + useQuery({ queryKey: templateLiteralKey, exact: true }, options) + useMutation({ mutationKey: templateLiteralKey, exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: templateLiteralKey, exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: templateLiteralKey, exact: true }, options) + + return
Example Component
+} + +export const ExampleWithArrayExpression = () => { + useQuery({ queryKey: ['todos'], exact: true }, options) + useMutation({ mutationKey: ['todos'], exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: ['todos'], exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: ['todos'], exact: true }, options) + + return
Example Component
+} + +export const ExampleWithArrayExpressionIdentifier = () => { + const arrayExpressionKey = ['todos'] + useQuery({ queryKey: arrayExpressionKey, exact: true }, options) + useMutation({ mutationKey: arrayExpressionKey, exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: arrayExpressionKey, exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: arrayExpressionKey, exact: true }, options) + + return
Example Component
+} + +export const ExampleWithUnknownIdentifier1 = () => { + const createKey = (id) => ['todos', id] + const createdKey1 = createKey(1) + useQuery({ queryKey: createdKey1, exact: true }, options) + useMutation({ mutationKey: createdKey1, exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: createdKey1, exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: createdKey1, exact: true }, options) + + return
Example Component
+} + +export const ExampleWithUnknownIdentifier2 = () => { + const createdKey2 = createKey() + useQuery({ queryKey: createdKey2, exact: true }, options) + useMutation({ mutationKey: createdKey2, exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: createdKey2, exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: createdKey2, exact: true }, options) + + return
Example Component
+} + +export const ExampleWithUnknownIdentifier3 = () => { + useQuery({ queryKey: unknownQueryKey, exact: true }, options) + useMutation({ mutationKey: unknownQueryKey, exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: unknownQueryKey, exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: unknownQueryKey, exact: true }, options) + + return
Example Component
+} + diff --git a/codemods/v4/__testfixtures__/parameter-is-object-expression.output.tsx b/codemods/v4/__testfixtures__/parameter-is-object-expression.output.tsx new file mode 100644 index 0000000000..232a61e4c0 --- /dev/null +++ b/codemods/v4/__testfixtures__/parameter-is-object-expression.output.tsx @@ -0,0 +1,175 @@ +import * as React from 'react' +import { useMutation, useQuery, useQueryClient } from 'react-query' + +const options = {} + +export const ExampleWithStringLiteral = () => { + useQuery({ + queryKey: ['todos'], + exact: true + }, options) + useMutation({ + mutationKey: ['todos'], + exact: true + }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ + queryKey: ['todos'], + exact: true + }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ + queryKey: ['todos'], + exact: true + }, options) + + return
Example Component
+} + +export const ExampleWithStringLiteralIdentifier = () => { + const stringLiteralKey = 'todos' + useQuery({ + queryKey: [stringLiteralKey], + exact: true + }, options) + useMutation({ + mutationKey: [stringLiteralKey], + exact: true + }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ + queryKey: [stringLiteralKey], + exact: true + }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ + queryKey: [stringLiteralKey], + exact: true + }, options) + + return
Example Component
+} + +export const ExampleWithTemplateLiteral = () => { + useQuery({ + queryKey: [`todos`], + exact: true + }, options) + useMutation({ + mutationKey: [`todos`], + exact: true + }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ + queryKey: [`todos`], + exact: true + }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ + queryKey: [`todos`], + exact: true + }, options) + + return
Example Component
+} + +export const ExampleWithTemplateLiteralIdentifier = () => { + const templateLiteralKey = `todos` + useQuery({ + queryKey: [templateLiteralKey], + exact: true + }, options) + useMutation({ + mutationKey: [templateLiteralKey], + exact: true + }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ + queryKey: [templateLiteralKey], + exact: true + }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ + queryKey: [templateLiteralKey], + exact: true + }, options) + + return
Example Component
+} + +export const ExampleWithArrayExpression = () => { + useQuery({ queryKey: ['todos'], exact: true }, options) + useMutation({ mutationKey: ['todos'], exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: ['todos'], exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: ['todos'], exact: true }, options) + + return
Example Component
+} + +export const ExampleWithArrayExpressionIdentifier = () => { + const arrayExpressionKey = ['todos'] + useQuery({ queryKey: arrayExpressionKey, exact: true }, options) + useMutation({ mutationKey: arrayExpressionKey, exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: arrayExpressionKey, exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: arrayExpressionKey, exact: true }, options) + + return
Example Component
+} + +export const ExampleWithUnknownIdentifier1 = () => { + const createKey = (id) => ['todos', id] + const createdKey1 = createKey(1) + useQuery({ queryKey: createdKey1, exact: true }, options) + useMutation({ mutationKey: createdKey1, exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: createdKey1, exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: createdKey1, exact: true }, options) + + return
Example Component
+} + +export const ExampleWithUnknownIdentifier2 = () => { + const createdKey2 = createKey() + useQuery({ queryKey: createdKey2, exact: true }, options) + useMutation({ mutationKey: createdKey2, exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: createdKey2, exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: createdKey2, exact: true }, options) + + return
Example Component
+} + +export const ExampleWithUnknownIdentifier3 = () => { + useQuery({ queryKey: unknownQueryKey, exact: true }, options) + useMutation({ mutationKey: unknownQueryKey, exact: true }, options) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.cancelQueries({ queryKey: unknownQueryKey, exact: true }, options) + // --- Direct hook call. + useQueryClient().cancelQueries({ queryKey: unknownQueryKey, exact: true }, options) + + return
Example Component
+} diff --git a/codemods/v4/__testfixtures__/type-arguments.input.tsx b/codemods/v4/__testfixtures__/type-arguments.input.tsx new file mode 100644 index 0000000000..cb81fb81b9 --- /dev/null +++ b/codemods/v4/__testfixtures__/type-arguments.input.tsx @@ -0,0 +1,25 @@ +import * as React from 'react' +import { useQueries, useQuery, useQueryClient } from 'react-query' + +type Todos = { + items: readonly { + id: string + text: string + }[] + ts: number +} + +export const Examples = () => { + useQuery('todos') + useQueries>([query1, query2]) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.getQueriesData('todos') + queryClient.getQueriesData({ queryKey: 'todos' }) + // --- Direct hook call. + useQueryClient().getQueriesData('todos') + useQueryClient().getQueriesData({ queryKey: 'todos' }) + + return
Example Component
+} diff --git a/codemods/v4/__testfixtures__/type-arguments.output.tsx b/codemods/v4/__testfixtures__/type-arguments.output.tsx new file mode 100644 index 0000000000..619c7b95ac --- /dev/null +++ b/codemods/v4/__testfixtures__/type-arguments.output.tsx @@ -0,0 +1,31 @@ +import * as React from 'react' +import { useQueries, useQuery, useQueryClient } from 'react-query' + +type Todos = { + items: readonly { + id: string + text: string + }[] + ts: number +} + +export const Examples = () => { + useQuery(['todos']) + useQueries>({ + queries: [query1, query2] + }) + // QueryClient methods + // --- Instantiated hook call. + const queryClient = useQueryClient() + queryClient.getQueriesData(['todos']) + queryClient.getQueriesData({ + queryKey: ['todos'] + }) + // --- Direct hook call. + useQueryClient().getQueriesData(['todos']) + useQueryClient().getQueriesData({ + queryKey: ['todos'] + }) + + return
Example Component
+} diff --git a/codemods/v4/__tests__/key-transformation.test.js b/codemods/v4/__tests__/key-transformation.test.js new file mode 100644 index 0000000000..b22431aec4 --- /dev/null +++ b/codemods/v4/__tests__/key-transformation.test.js @@ -0,0 +1,34 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const defineTest = require('jscodeshift/dist/testUtils').defineTest + +jest.autoMockOff() + +defineTest(__dirname, 'key-transformation', null, 'default-import', { + parser: 'tsx', +}) + +defineTest(__dirname, 'key-transformation', null, 'named-import', { + parser: 'tsx', +}) + +defineTest(__dirname, 'key-transformation', null, 'namespaced-import', { + parser: 'tsx', +}) + +defineTest(__dirname, 'key-transformation', null, 'parameter-is-identifier', { + parser: 'tsx', +}) + +defineTest( + __dirname, + 'key-transformation', + null, + 'parameter-is-object-expression', + { + parser: 'tsx', + } +) + +defineTest(__dirname, 'key-transformation', null, 'type-arguments', { + parser: 'tsx', +}) diff --git a/codemods/v4/key-transformation.js b/codemods/v4/key-transformation.js new file mode 100644 index 0000000000..8c6b1bc1b5 --- /dev/null +++ b/codemods/v4/key-transformation.js @@ -0,0 +1,138 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const createUtilsObject = require('./utils') +// eslint-disable-next-line @typescript-eslint/no-var-requires +const createKeyReplacer = require('./utils/replacers/key-replacer') +// eslint-disable-next-line @typescript-eslint/no-var-requires +const createUseQueryLikeTransformer = require('./utils/transformers/use-query-like-transformer') +// eslint-disable-next-line @typescript-eslint/no-var-requires +const createQueryClientTransformer = require('./utils/transformers/query-client-transformer') +// eslint-disable-next-line @typescript-eslint/no-var-requires +const createQueryCacheTransformer = require('./utils/transformers/query-cache-transformer') + +const transformQueryClientUsages = ({ jscodeshift, utils, root, filePath }) => { + const transformer = createQueryClientTransformer({ jscodeshift, utils, root }) + const replacer = createKeyReplacer({ jscodeshift, root, filePath }) + + transformer.execute( + [ + // Not object syntax-aware methods. + 'getMutationDefaults', + 'getQueriesData', + 'getQueryData', + 'getQueryDefaults', + 'getQueryState', + 'isFetching', + 'setMutationDefaults', + 'setQueriesData', + 'setQueryData', + 'setQueryDefaults', + // Object syntax-aware methods. + 'cancelQueries', + 'fetchInfiniteQuery', + 'fetchQuery', + 'invalidateQueries', + 'prefetchInfiniteQuery', + 'prefetchQuery', + 'refetchQueries', + 'removeQueries', + 'resetQueries', + ], + replacer + ) +} + +const transformUseQueriesUsages = ({ jscodeshift, utils, root }) => { + const transformer = createUseQueryLikeTransformer({ + jscodeshift, + utils, + root, + }) + const replacer = ({ node }) => { + /** + * When the node doesn't have the 'original' property, that means the codemod has been already applied, + * so we don't need to do any changes. + */ + if (!node.original) { + return node + } + + const newCallExpression = jscodeshift.callExpression(node.original.callee, [ + jscodeshift.objectExpression([ + jscodeshift.property( + 'init', + jscodeshift.identifier('queries'), + node.original.arguments[0] + ), + ]), + ]) + + // TODO: This should be part of one function! + if (node.typeParameters) { + newCallExpression.typeArguments = node.typeParameters + } + + return newCallExpression + } + + transformer.execute(['useQueries'], replacer) +} + +const transformUseQueryLikeUsages = ({ + jscodeshift, + utils, + root, + filePath, +}) => { + const transformer = createUseQueryLikeTransformer({ + jscodeshift, + utils, + root, + }) + + transformer.execute( + ['useQuery', 'useInfiniteQuery', 'useIsFetching', 'useIsMutating'], + createKeyReplacer({ + jscodeshift, + root, + filePath, + keyName: 'queryKey', + }) + ) + transformer.execute( + ['useMutation'], + createKeyReplacer({ + jscodeshift, + root, + filePath, + keyName: 'mutationKey', + }) + ) +} + +const transformQueryCacheUsages = ({ jscodeshift, utils, root, filePath }) => { + const transformer = createQueryCacheTransformer({ jscodeshift, utils, root }) + const replacer = createKeyReplacer({ jscodeshift, root, filePath }) + + transformer.execute(replacer) +} + +module.exports = (file, api) => { + const jscodeshift = api.jscodeshift + const root = jscodeshift(file.source) + + // TODO: Execute the transformers only when it contains a `react-query` import! + + const utils = createUtilsObject({ root, jscodeshift }) + const filePath = file.path + + // This function transforms usages like `useQuery` and `useMutation`. + transformUseQueryLikeUsages({ jscodeshift, utils, root, filePath }) + // This function transforms usages of `useQueries`. + transformUseQueriesUsages({ jscodeshift, utils, root }) + // This function transforms usages of `QueryClient`. + transformQueryClientUsages({ jscodeshift, utils, root, filePath }) + // This function transforms usages of `QueryCache`. + transformQueryCacheUsages({ jscodeshift, utils, root, filePath }) + + return root.toSource({ quote: 'single' }) +} diff --git a/codemods/v4/utils/index.js b/codemods/v4/utils/index.js new file mode 100644 index 0000000000..4706ade268 --- /dev/null +++ b/codemods/v4/utils/index.js @@ -0,0 +1,166 @@ +module.exports = ({ root, jscodeshift }) => { + const findImportIdentifierOf = (importSpecifiers, identifier) => { + const specifier = importSpecifiers + .filter(node => node.value.imported.name === identifier) + .paths() + + if (specifier.length > 0) { + return specifier[0].value.local + } + + return jscodeshift.identifier(identifier) + } + + const findImportSpecifiers = () => + root + .find(jscodeshift.ImportDeclaration, { + source: { + value: 'react-query', + }, + }) + .find(jscodeshift.ImportSpecifier, {}) + + const locateImports = identifiers => { + const findNamespaceImportIdentifier = () => { + const specifier = root + .find(jscodeshift.ImportDeclaration, { + source: { + value: 'react-query', + }, + }) + .find(jscodeshift.ImportNamespaceSpecifier) + .paths() + + return specifier.length > 0 ? specifier[0].value.local : null + } + + /** + * First, we search for the namespace import identifier because if we have any, we assume the consumer uses + * namespace imports. In this case, we won't search for named imports at all. + */ + const namespaceImportIdentifier = findNamespaceImportIdentifier() + + if (namespaceImportIdentifier) { + const identifierMap = {} + + for (const identifier of identifiers) { + identifierMap[identifier] = jscodeshift.identifier(identifier) + } + + return { + namespace: namespaceImportIdentifier, + ...identifierMap, + } + } + + const importSpecifiers = findImportSpecifiers() + const identifierMap = {} + + for (const identifier of identifiers) { + identifierMap[identifier] = findImportIdentifierOf( + importSpecifiers, + identifier + ) + } + + return { + namespace: null, + ...identifierMap, + } + } + + const findAllMethodCalls = () => + root + // First, we need to find all method calls. + .find(jscodeshift.CallExpression, { + callee: { + type: jscodeshift.MemberExpression.name, + property: { + type: jscodeshift.Identifier.name, + }, + }, + }) + + const findQueryClientIdentifiers = importIdentifiers => + root + .find(jscodeshift.VariableDeclarator, {}) + .filter(node => { + if (node.value.init) { + const initializer = node.value.init + + return ( + isClassInstantiationOf( + initializer, + getSelectorByImports(importIdentifiers, 'QueryClient') + ) || + isFunctionCallOf( + initializer, + getSelectorByImports(importIdentifiers, 'useQueryClient') + ) + ) + } + + return false + }) + .paths() + .map(node => node.value.id.name) + + const isCallExpression = node => + jscodeshift.match(node, { type: jscodeshift.CallExpression.name }) + + const isIdentifier = node => + jscodeshift.match(node, { type: jscodeshift.Identifier.name }) + + const isMemberExpression = node => + jscodeshift.match(node, { type: jscodeshift.MemberExpression.name }) + + const isNewExpression = node => + jscodeshift.match(node, { type: jscodeshift.NewExpression.name }) + + const isClassInstantiationOf = (node, selector) => { + if (!isNewExpression(node)) { + return false + } + + const parts = selector.split('.') + + return parts.length === 1 + ? isIdentifier(node.callee) && node.callee.name === parts[0] + : isMemberExpression(node.callee) && + node.callee.object.name === parts[0] && + node.callee.property.name === parts[1] + } + + const isFunctionCallOf = (node, selector) => { + if (!isCallExpression(node)) { + return false + } + + const parts = selector.split('.') + + return parts.length === 1 + ? isIdentifier(node.callee) && node.callee.name === parts[0] + : isMemberExpression(node.callee) && + node.callee.object.name === parts[0] && + node.callee.property.name === parts[1] + } + + const getSelectorByImports = (imports, path) => + imports.namespace + ? `${imports.namespace.name}.${imports[path].name}` + : imports[path].name + + return { + findAllMethodCalls, + getSelectorByImports, + isCallExpression, + isClassInstantiationOf, + isFunctionCallOf, + isIdentifier, + isMemberExpression, + locateImports, + queryClient: { + findQueryClientIdentifiers, + }, + } +} diff --git a/codemods/v4/utils/replacers/key-replacer.js b/codemods/v4/utils/replacers/key-replacer.js new file mode 100644 index 0000000000..621902edb5 --- /dev/null +++ b/codemods/v4/utils/replacers/key-replacer.js @@ -0,0 +1,160 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const UnprocessableKeyError = require('../unprocessable-key-error') + +module.exports = ({ jscodeshift, root, filePath, keyName = 'queryKey' }) => { + const isArrayExpression = node => + jscodeshift.match(node, { type: jscodeshift.ArrayExpression.name }) + + const isStringLiteral = node => + jscodeshift.match(node, { type: jscodeshift.StringLiteral.name }) || + jscodeshift.match(node, { type: jscodeshift.Literal.name }) + + const isTemplateLiteral = node => + jscodeshift.match(node, { type: jscodeshift.TemplateLiteral.name }) + + const findVariableDeclaration = node => { + const declarations = root + .find(jscodeshift.VariableDeclarator, { + id: { + type: jscodeshift.Identifier.name, + name: node.name, + }, + }) + .paths() + + return declarations.length > 0 ? declarations[0] : null + } + + const createKeyValue = node => { + // When the node is a string literal we convert it into an array of strings. + if (isStringLiteral(node)) { + return jscodeshift.arrayExpression([ + jscodeshift.stringLiteral(node.value), + ]) + } + + // When the node is a template literal we convert it into an array of template literals. + if (isTemplateLiteral(node)) { + return jscodeshift.arrayExpression([ + jscodeshift.templateLiteral(node.quasis, node.expressions), + ]) + } + + if (jscodeshift.match(node, { type: jscodeshift.Identifier.name })) { + // When the node is an identifier at first, we try to find its declaration, because we will try + // to guess its type. + const variableDeclaration = findVariableDeclaration(node) + + if (!variableDeclaration) { + throw new UnprocessableKeyError( + `In file ${filePath} at line ${node.loc.start.line} the type of identifier \`${node.name}\` couldn't be recognized, so the codemod couldn't be applied. Please migrate manually.` + ) + } + + const initializer = variableDeclaration.value.init + + // When it's a string, we just wrap it into an array expression. + if (isStringLiteral(initializer) || isTemplateLiteral(initializer)) { + return jscodeshift.arrayExpression([node]) + } + } + + throw new UnprocessableKeyError( + `In file ${filePath} at line ${node.loc.start.line} the type of the \`${keyName}\` couldn't be recognized, so the codemod couldn't be applied. Please migrate manually.` + ) + } + + const createKeyProperty = node => + jscodeshift.property( + 'init', + jscodeshift.identifier(keyName), + createKeyValue(node) + ) + + const getPropertyFromObjectExpression = (objectExpression, propertyName) => + objectExpression.properties.find( + property => property.key.name === propertyName + ) ?? null + + const buildWithTypeArguments = (node, builder) => { + const newNode = builder(node) + + if (node.typeParameters) { + newNode.typeArguments = node.typeParameters + } + + return newNode + } + + return ({ node }) => { + // When the node doesn't have the 'original' property, that means the codemod has been already applied, + // so we don't need to do any changes. + if (!node.original) { + return node + } + + const methodArguments = node.arguments + + // The method call doesn't have any arguments, we have nothing to do in this case. + if (methodArguments.length === 0) { + return node + } + + try { + const [firstArgument, ...restOfTheArguments] = methodArguments + + if ( + jscodeshift.match(firstArgument, { + type: jscodeshift.ObjectExpression.name, + }) + ) { + const originalKey = getPropertyFromObjectExpression( + firstArgument, + keyName + ) + + if (!originalKey) { + throw new UnprocessableKeyError( + `In file ${filePath} at line ${node.loc.start.line} the \`${keyName}\` couldn't be found. Did you forget to add it?` + ) + } + + const restOfTheProperties = firstArgument.properties.filter( + item => item.key.name !== keyName + ) + + return buildWithTypeArguments(node, originalNode => + jscodeshift.callExpression(originalNode.original.callee, [ + jscodeshift.objectExpression([ + createKeyProperty(originalKey.value), + ...restOfTheProperties, + ]), + ...restOfTheArguments, + ]) + ) + } + + // When the node is an array expression we just simply return it because we want query keys to be arrays. + if (isArrayExpression(firstArgument)) { + return node + } + + return buildWithTypeArguments(node, originalNode => + jscodeshift.callExpression(originalNode.original.callee, [ + createKeyValue(firstArgument), + ...restOfTheArguments, + ]) + ) + } catch (error) { + if (error.name === 'UnprocessableKeyError') { + if (process.env.NODE_ENV !== 'test') { + console.warn(error.message) + } + + return node + } + + throw error + } + } +} diff --git a/codemods/v4/utils/transformers/query-cache-transformer.js b/codemods/v4/utils/transformers/query-cache-transformer.js new file mode 100644 index 0000000000..acdea9550c --- /dev/null +++ b/codemods/v4/utils/transformers/query-cache-transformer.js @@ -0,0 +1,115 @@ +module.exports = ({ jscodeshift, utils, root }) => { + const isGetQueryCacheMethodCall = ( + initializer, + importIdentifiers, + knownQueryClientIds + ) => { + const isKnownQueryClient = node => + utils.isIdentifier(node) && knownQueryClientIds.includes(node.name) + + const isGetQueryCacheIdentifier = node => + utils.isIdentifier(node) && node.name === 'getQueryCache' + + const isValidInitializer = node => + utils.isCallExpression(node) && utils.isMemberExpression(node.callee) + + if (isValidInitializer(initializer)) { + const instance = initializer.callee.object + + return ( + isGetQueryCacheIdentifier(initializer.callee.property) && + (isKnownQueryClient(instance) || + utils.isFunctionCallOf( + instance, + utils.getSelectorByImports(importIdentifiers, 'useQueryClient') + )) + ) + } + + return false + } + + const findQueryCacheInstantiations = ( + importIdentifiers, + knownQueryClientIds + ) => + root.find(jscodeshift.VariableDeclarator, {}).filter(node => { + if (node.value.init) { + const initializer = node.value.init + + return ( + utils.isClassInstantiationOf( + initializer, + utils.getSelectorByImports(importIdentifiers, 'QueryCache') + ) || + isGetQueryCacheMethodCall( + initializer, + importIdentifiers, + knownQueryClientIds + ) + ) + } + + return false + }) + + const filterQueryCacheMethodCalls = node => + utils.isIdentifier(node) && ['find', 'findAll'].includes(node.name) + + const findQueryCacheMethodCalls = importIdentifiers => { + /** + * Here we collect all query client instantiations. We have to make aware of them because the query cache can be + * accessed by the query client as well. + */ + const queryClientIdentifiers = utils.queryClient.findQueryClientIdentifiers( + importIdentifiers + ) + /** + * Here we collect all query cache instantiations. The reason is simple: the methods can be called on query cache + * instances, to locate the possible usages we need to be aware of the identifier names. + */ + const queryCacheIdentifiers = findQueryCacheInstantiations( + importIdentifiers, + queryClientIdentifiers + ) + .paths() + .map(node => node.value.id.name) + + return ( + utils + // First, we need to find all method calls. + .findAllMethodCalls() + // Then we narrow the collection to all `fetch` and `fetchAll` methods. + .filter(node => filterQueryCacheMethodCalls(node.value.callee.property)) + .filter(node => { + const object = node.value.callee.object + + // If the method is called on a `QueryCache` instance, we keep it in the collection. + if (utils.isIdentifier(object)) { + return queryCacheIdentifiers.includes(object.name) + } + + // If the method is called on a `QueryClient` instance, we keep it in the collection. + if (utils.isCallExpression(object)) { + return isGetQueryCacheMethodCall( + object, + importIdentifiers, + queryClientIdentifiers + ) + } + + return false + }) + ) + } + + const execute = replacer => { + findQueryCacheMethodCalls( + utils.locateImports(['QueryCache', 'QueryClient', 'useQueryClient']) + ).replaceWith(replacer) + } + + return { + execute, + } +} diff --git a/codemods/v4/utils/transformers/query-client-transformer.js b/codemods/v4/utils/transformers/query-client-transformer.js new file mode 100644 index 0000000000..a1fd70f232 --- /dev/null +++ b/codemods/v4/utils/transformers/query-client-transformer.js @@ -0,0 +1,49 @@ +module.exports = ({ jscodeshift, utils, root }) => { + const filterQueryClientMethodCalls = (node, methods) => + utils.isIdentifier(node) && methods.includes(node.name) + + const findQueryClientMethodCalls = (importIdentifiers, methods) => { + /** + * Here we collect all query client instantiations. We have to make aware of them because some method calls might + * be invoked on these instances. + */ + const queryClientIdentifiers = utils.queryClient.findQueryClientIdentifiers( + importIdentifiers + ) + + return ( + utils + // First, we need to find all method calls. + .findAllMethodCalls() + // Then we narrow the collection to `QueryClient` methods. + .filter(node => + filterQueryClientMethodCalls(node.value.callee.property, methods) + ) + .filter(node => { + const object = node.value.callee.object + + // If the method is called on a `QueryClient` instance, we keep it in the collection. + if (utils.isIdentifier(object)) { + return queryClientIdentifiers.includes(object.name) + } + + // If the method is called on the return value of `useQueryClient` hook, we keep it in the collection. + return utils.isFunctionCallOf( + object, + utils.getSelectorByImports(importIdentifiers, 'useQueryClient') + ) + }) + ) + } + + const execute = (methods, replacer) => { + findQueryClientMethodCalls( + utils.locateImports(['QueryClient', 'useQueryClient']), + methods + ).replaceWith(replacer) + } + + return { + execute, + } +} diff --git a/codemods/v4/utils/transformers/use-query-like-transformer.js b/codemods/v4/utils/transformers/use-query-like-transformer.js new file mode 100644 index 0000000000..da3a6d527d --- /dev/null +++ b/codemods/v4/utils/transformers/use-query-like-transformer.js @@ -0,0 +1,32 @@ +module.exports = ({ jscodeshift, utils, root }) => { + const filterUseQueryLikeHookCalls = (node, importIdentifiers, hooks) => { + for (const hook of hooks) { + const selector = utils.getSelectorByImports(importIdentifiers, hook) + + if (utils.isFunctionCallOf(node, selector)) { + return true + } + } + + return false + } + + const findUseQueryLikeHookCalls = (importIdentifiers, hooks) => + root + // First, we need to find all call expressions. + .find(jscodeshift.CallExpression, {}) + // Then we narrow the collection to the `useQuery` like hook calls. + .filter(node => + filterUseQueryLikeHookCalls(node.value, importIdentifiers, hooks) + ) + + const execute = (hooks, replacer) => { + findUseQueryLikeHookCalls(utils.locateImports(hooks), hooks).replaceWith( + replacer + ) + } + + return { + execute, + } +} diff --git a/codemods/v4/utils/unprocessable-key-error.js b/codemods/v4/utils/unprocessable-key-error.js new file mode 100644 index 0000000000..87935c584b --- /dev/null +++ b/codemods/v4/utils/unprocessable-key-error.js @@ -0,0 +1,8 @@ +class UnprocessableKeyError extends Error { + constructor(message) { + super(message) + this.name = 'UnprocessableKeyError' + } +} + +module.exports = UnprocessableKeyError diff --git a/docs/src/pages/guides/migrating-to-react-query-4.md b/docs/src/pages/guides/migrating-to-react-query-4.md index a2ac3d02ef..6c28599c3c 100644 --- a/docs/src/pages/guides/migrating-to-react-query-4.md +++ b/docs/src/pages/guides/migrating-to-react-query-4.md @@ -18,6 +18,26 @@ To streamline all apis, we've decided to make all keys Arrays only: + useQuery(['todos'], fetchTodos) ``` +#### Codemod + +To make this migration easier, we decided to deliver a codemod. + +> The codemod is a best efforts attempt to help you migrate the breaking change. Please review the generated code thoroughly! Also, there are edge cases that cannot be found by the code mod, so please keep an eye on the log output. + +You can easily apply it by using one (or both) of the following commands: + +If you want to run it against `.js` or `.jsx` files, please use the command below: + +`npx jscodeshift --extensions=js,jsx --transform=./node_modules/react-query/codemods/v4/key-transformation.js ./path/to/src/` + +If you want to run it against `.ts` or `.tsx` files, please use the command below: + +`npx jscodeshift --extensions=ts,tsx --parser=tsx --transform=./node_modules/react-query/codemods/v4/key-transformation.js ./path/to/src/` + +Please note in the case of `TypeScript` you need to use `tsx` as the parser otherwise, the codemod won't be applied properly! + +**Note:** Applying the codemod might break your code formatting, so please don't forget to run `prettier` and/or `eslint` after you've applied the codemod! + ### Separate hydration exports have been removed With version [3.22.0](https://github.com/tannerlinsley/react-query/releases/tag/v3.22.0), hydration utilities moved into the React Query core. With v3, you could still use the old exports from `react-query/hydration`, but these exports have been removed with v4. diff --git a/examples/auto-refetching/pages/index.js b/examples/auto-refetching/pages/index.js index d8a87e237f..22285b2cb3 100755 --- a/examples/auto-refetching/pages/index.js +++ b/examples/auto-refetching/pages/index.js @@ -28,7 +28,7 @@ function Example() { const [value, setValue] = React.useState('') const { status, data, error, isFetching } = useQuery( - 'todos', + ['todos'], async () => { const res = await axios.get('/api/data') return res.data @@ -40,11 +40,11 @@ function Example() { ) const addMutation = useMutation(value => fetch(`/api/data?add=${value}`), { - onSuccess: () => queryClient.invalidateQueries('todos'), + onSuccess: () => queryClient.invalidateQueries(['todos']), }) const clearMutation = useMutation(() => fetch(`/api/data?clear=1`), { - onSuccess: () => queryClient.invalidateQueries('todos'), + onSuccess: () => queryClient.invalidateQueries(['todos']), }) if (status === 'loading') return

Loading...

diff --git a/examples/basic-graphql-request/src/index.js b/examples/basic-graphql-request/src/index.js index bdf8581d64..e8724bfd47 100644 --- a/examples/basic-graphql-request/src/index.js +++ b/examples/basic-graphql-request/src/index.js @@ -40,7 +40,7 @@ function App() { } function usePosts() { - return useQuery("posts", async () => { + return useQuery(['posts'], async () => { const { posts: { data }, } = await request( diff --git a/examples/custom-hooks/src/hooks/usePosts.js b/examples/custom-hooks/src/hooks/usePosts.js index cf49ca98ab..4fb688149b 100755 --- a/examples/custom-hooks/src/hooks/usePosts.js +++ b/examples/custom-hooks/src/hooks/usePosts.js @@ -9,5 +9,5 @@ const getPosts = async () => { }; export default function usePosts() { - return useQuery("posts", getPosts); + return useQuery(['posts'], getPosts); } diff --git a/examples/default-query-function/src/index.js b/examples/default-query-function/src/index.js index 3a5a5c406a..51836d9698 100644 --- a/examples/default-query-function/src/index.js +++ b/examples/default-query-function/src/index.js @@ -56,7 +56,7 @@ function Posts({ setPostId }) { const queryClient = useQueryClient(); // All you have to do now is pass a key! - const { status, data, error, isFetching } = useQuery("/posts"); + const { status, data, error, isFetching } = useQuery(['/posts']); return (
@@ -100,7 +100,7 @@ function Posts({ setPostId }) { function Post({ postId, setPostId }) { // You can even leave out the queryFn and just go straight into options - const { status, data, error, isFetching } = useQuery(`/posts/${postId}`, { + const { status, data, error, isFetching } = useQuery([`/posts/${postId}`], { enabled: !!postId, }); diff --git a/examples/focus-refetching/pages/index.js b/examples/focus-refetching/pages/index.js index 7e17c034d0..816a0259ab 100755 --- a/examples/focus-refetching/pages/index.js +++ b/examples/focus-refetching/pages/index.js @@ -23,17 +23,17 @@ export default function App() { function Example() { const queryClient = useQueryClient() - const { status, data, error } = useQuery('user', async () => { + const { status, data, error } = useQuery(['user'], async () => { const res = await axios.get('/api/user') return res.data }) const logoutMutation = useMutation(logout, { - onSuccess: () => queryClient.invalidateQueries('user'), + onSuccess: () => queryClient.invalidateQueries(['user']), }) const loginMutation = useMutation(login, { - onSuccess: () => queryClient.invalidateQueries('user'), + onSuccess: () => queryClient.invalidateQueries(['user']), }) return ( diff --git a/examples/load-more-infinite-scroll/pages/index.js b/examples/load-more-infinite-scroll/pages/index.js index 44113c9320..d91d365547 100755 --- a/examples/load-more-infinite-scroll/pages/index.js +++ b/examples/load-more-infinite-scroll/pages/index.js @@ -32,7 +32,7 @@ function Example() { hasNextPage, hasPreviousPage, } = useInfiniteQuery( - 'projects', + ['projects'], async ({ pageParam = 0 }) => { const res = await axios.get('/api/projects?cursor=' + pageParam) return res.data diff --git a/examples/optimistic-updates-typescript/pages/index.tsx b/examples/optimistic-updates-typescript/pages/index.tsx index f4988b34eb..5113d51520 100755 --- a/examples/optimistic-updates-typescript/pages/index.tsx +++ b/examples/optimistic-updates-typescript/pages/index.tsx @@ -29,7 +29,7 @@ async function fetchTodos(): Promise { function useTodos( options?: UseQueryOptions ) { - return useQuery('todos', fetchTodos, options) + return useQuery(['todos'], fetchTodos, options) } function TodoCounter() { @@ -59,14 +59,14 @@ function Example() { onMutate: async (newTodo: string) => { setText('') // Cancel any outgoing refetches (so they don't overwrite our optimistic update) - await queryClient.cancelQueries('todos') + await queryClient.cancelQueries(['todos']) // Snapshot the previous value - const previousTodos = queryClient.getQueryData('todos') + const previousTodos = queryClient.getQueryData(['todos']) // Optimistically update to the new value if (previousTodos) { - queryClient.setQueryData('todos', { + queryClient.setQueryData(['todos'], { ...previousTodos, items: [ ...previousTodos.items, @@ -80,12 +80,12 @@ function Example() { // If the mutation fails, use the context returned from onMutate to roll back onError: (err, variables, context) => { if (context?.previousTodos) { - queryClient.setQueryData('todos', context.previousTodos) + queryClient.setQueryData(['todos'], context.previousTodos) } }, // Always refetch after error or success: onSettled: () => { - queryClient.invalidateQueries('todos') + queryClient.invalidateQueries(['todos']) }, } ) diff --git a/examples/optimistic-updates/pages/index.js b/examples/optimistic-updates/pages/index.js index c720be41d9..06dad6e0d8 100755 --- a/examples/optimistic-updates/pages/index.js +++ b/examples/optimistic-updates/pages/index.js @@ -24,7 +24,7 @@ function Example() { const queryClient = useQueryClient() const [text, setText] = React.useState('') - const { status, data, error, isFetching } = useQuery('todos', async () => { + const { status, data, error, isFetching } = useQuery(['todos'], async () => { const res = await axios.get('/api/data') return res.data }) @@ -37,11 +37,11 @@ function Example() { // an error onMutate: async text => { setText('') - await queryClient.cancelQueries('todos') + await queryClient.cancelQueries(['todos']) - const previousValue = queryClient.getQueryData('todos') + const previousValue = queryClient.getQueryData(['todos']) - queryClient.setQueryData('todos', old => ({ + queryClient.setQueryData(['todos'], old => ({ ...old, items: [...old.items, text], })) @@ -50,10 +50,10 @@ function Example() { }, // On failure, roll back to the previous value onError: (err, variables, previousValue) => - queryClient.setQueryData('todos', previousValue), + queryClient.setQueryData(['todos'], previousValue), // After success or failure, refetch the todos query onSettled: () => { - queryClient.invalidateQueries('todos') + queryClient.invalidateQueries(['todos']) }, } ) diff --git a/examples/playground/src/index.js b/examples/playground/src/index.js index 886d24c182..8ae322a4f2 100644 --- a/examples/playground/src/index.js +++ b/examples/playground/src/index.js @@ -136,7 +136,7 @@ function App() { return (
-
@@ -254,7 +254,7 @@ function EditTodo({ editingIndex, setEditingIndex }) { const saveMutation = useMutation(patchTodo, { onSuccess: (data) => { // Update `todos` and the individual todo queries when this mutation succeeds - queryClient.invalidateQueries("todos"); + queryClient.invalidateQueries(['todos']); queryClient.setQueryData(["todo", { id: editingIndex }], data); }, }); @@ -340,7 +340,7 @@ function AddTodo() { const addMutation = useMutation(postTodo, { onSuccess: () => { - queryClient.invalidateQueries("todos"); + queryClient.invalidateQueries(['todos']); }, }); diff --git a/examples/prefetching/pages/index.js b/examples/prefetching/pages/index.js index cd4d3a4af6..6bfe7f0e64 100755 --- a/examples/prefetching/pages/index.js +++ b/examples/prefetching/pages/index.js @@ -37,7 +37,7 @@ function Example() { const rerender = React.useState(0)[1] const [selectedChar, setSelectedChar] = React.useState(1) - const charactersQuery = useQuery('characters', getCharacters) + const charactersQuery = useQuery(['characters'], getCharacters) const characterQuery = useQuery(['character', selectedChar], () => getCharacter(selectedChar) diff --git a/examples/rick-morty/src/Character.js b/examples/rick-morty/src/Character.js index a75bcd6e06..5c7a66a0d3 100644 --- a/examples/rick-morty/src/Character.js +++ b/examples/rick-morty/src/Character.js @@ -17,7 +17,7 @@ import fetch from "./fetch"; function Character() { const { characterId } = useParams(); - const { status, data } = useQuery(`character-${characterId}`, () => + const { status, data } = useQuery([`character-${characterId}`], () => fetch(`https://rickandmortyapi.com/api/character/${characterId}`) ); @@ -77,7 +77,7 @@ function Character() { } function Episode({ id }) { - const { data, status } = useQuery(`episode-${id}`, () => + const { data, status } = useQuery([`episode-${id}`], () => fetch(`https://rickandmortyapi.com/api/episode/${id}`) ); @@ -97,7 +97,7 @@ function Episode({ id }) { } function Location({ id }) { - const { data, status } = useQuery(`location-${id}`, () => + const { data, status } = useQuery([`location-${id}`], () => fetch(`https://rickandmortyapi.com/api/location/${id}`) ); diff --git a/examples/rick-morty/src/Characters.js b/examples/rick-morty/src/Characters.js index 39706a93af..0fca9f84fc 100644 --- a/examples/rick-morty/src/Characters.js +++ b/examples/rick-morty/src/Characters.js @@ -5,7 +5,7 @@ import { useQuery } from "react-query"; import fetch from "./fetch"; export default function Characters() { - const { status, data } = useQuery("characters", () => + const { status, data } = useQuery(["characters"], () => fetch("https://rickandmortyapi.com/api/character/") ); diff --git a/examples/rick-morty/src/Episode.js b/examples/rick-morty/src/Episode.js index 47872f0189..6fad12ccb2 100644 --- a/examples/rick-morty/src/Episode.js +++ b/examples/rick-morty/src/Episode.js @@ -7,7 +7,7 @@ import fetch from "./fetch"; function Episode() { const { episodeId } = useParams(); - const { data, status } = useQuery(`episode-${episodeId}`, () => + const { data, status } = useQuery([`episode-${episodeId}`], () => fetch(`https://rickandmortyapi.com/api/episode/${episodeId}`) ); @@ -30,7 +30,7 @@ function Episode() { } function Character({ id }) { - const { data, status } = useQuery(`character-${id}`, () => + const { data, status } = useQuery([`character-${id}`], () => fetch(`https://rickandmortyapi.com/api/character/${id}`) ); diff --git a/examples/rick-morty/src/Episodes.js b/examples/rick-morty/src/Episodes.js index 88cf6b0552..cc228a0eee 100644 --- a/examples/rick-morty/src/Episodes.js +++ b/examples/rick-morty/src/Episodes.js @@ -5,7 +5,7 @@ import { useQuery } from "react-query"; import fetch from "./fetch"; export default function Episodes() { - const { data, status } = useQuery("episodes", () => + const { data, status } = useQuery(["episodes"], () => fetch("https://rickandmortyapi.com/api/episode") ); diff --git a/examples/simple/src/index.js b/examples/simple/src/index.js index a20a52a4ac..1d63f87aeb 100644 --- a/examples/simple/src/index.js +++ b/examples/simple/src/index.js @@ -15,7 +15,7 @@ export default function App() { } function Example() { - const { isLoading, error, data, isFetching } = useQuery("repoData", () => + const { isLoading, error, data, isFetching } = useQuery(["repoData"], () => fetch( "https://api.github.com/repos/tannerlinsley/react-query" ).then((res) => res.json()) diff --git a/examples/star-wars/src/Character.js b/examples/star-wars/src/Character.js index 6de9faf173..ab04544926 100644 --- a/examples/star-wars/src/Character.js +++ b/examples/star-wars/src/Character.js @@ -17,7 +17,7 @@ import fetch from "./fetch"; function Character(props) { const characterId = props.match.params.characterId; - const { status, error, data } = useQuery(`character-${characterId}`, () => + const { status, error, data } = useQuery([`character-${characterId}`], () => fetch(`https://swapi.dev/api/people/${characterId}/`) ); @@ -85,7 +85,7 @@ function Character(props) { function Film(props) { const { id } = props; - const { data, status, error } = useQuery(`film-${id}`, () => + const { data, status, error } = useQuery([`film-${id}`], () => fetch(`https://swapi.dev/api/films/${id}/`) ); @@ -105,7 +105,7 @@ function Film(props) { function Homeworld(props) { const { id } = props; - const { data, status } = useQuery(`homeworld-${id}`, () => + const { data, status } = useQuery([`homeworld-${id}`], () => fetch(`https://swapi.dev/api/planets/${id}/`) ); diff --git a/examples/star-wars/src/Characters.js b/examples/star-wars/src/Characters.js index a93eaaef23..a350dad2a9 100644 --- a/examples/star-wars/src/Characters.js +++ b/examples/star-wars/src/Characters.js @@ -5,7 +5,7 @@ import { useQuery } from "react-query"; import fetch from "./fetch"; export default function Characters(props) { - const { status, error, data } = useQuery("characters", () => + const { status, error, data } = useQuery(["characters"], () => fetch(`https://swapi.dev/api/people/`) ); diff --git a/examples/star-wars/src/Film.js b/examples/star-wars/src/Film.js index 82155934ec..7d730550f9 100644 --- a/examples/star-wars/src/Film.js +++ b/examples/star-wars/src/Film.js @@ -7,7 +7,7 @@ import fetch from "./fetch"; function Film(props) { const filmId = props.match.params.filmId; - const { data, status, error } = useQuery(`film-${filmId}`, () => + const { data, status, error } = useQuery([`film-${filmId}`], () => fetch(`https://swapi.dev/api/films/${filmId}/`) ); @@ -35,7 +35,7 @@ function Film(props) { function Character(props) { const { id } = props; - const { data, status, error } = useQuery(`character-${id}`, () => + const { data, status, error } = useQuery([`character-${id}`], () => fetch(`https://swapi.dev/api/people/${props.id}/`) ); diff --git a/examples/star-wars/src/Films.js b/examples/star-wars/src/Films.js index 1f254b83f1..5fc0e5f2d0 100644 --- a/examples/star-wars/src/Films.js +++ b/examples/star-wars/src/Films.js @@ -5,7 +5,7 @@ import { useQuery } from "react-query"; import fetch from "./fetch"; export default function Films(props) { - const { data, status, error } = useQuery("films", () => + const { data, status, error } = useQuery(["films"], () => fetch("https://swapi.dev/api/films/") ); diff --git a/examples/suspense/src/components/Projects.js b/examples/suspense/src/components/Projects.js index 2d449c71a3..f95f316a54 100644 --- a/examples/suspense/src/components/Projects.js +++ b/examples/suspense/src/components/Projects.js @@ -8,7 +8,7 @@ import { fetchProjects, fetchProject } from "../queries"; export default function Projects({ setActiveProject }) { const queryClient = useQueryClient(); - const { data, isFetching } = useQuery("projects", fetchProjects); + const { data, isFetching } = useQuery(['projects'], fetchProjects); return (
diff --git a/examples/suspense/src/index.js b/examples/suspense/src/index.js index c25576061d..da1f194823 100755 --- a/examples/suspense/src/index.js +++ b/examples/suspense/src/index.js @@ -46,7 +46,7 @@ function Example() { onClick={() => { setShowProjects((old) => { if (!old) { - queryClient.prefetchQuery("projects", fetchProjects); + queryClient.prefetchQuery(["projects"], fetchProjects); } return !old; }); diff --git a/package.json b/package.json index eefa599c04..326031572d 100644 --- a/package.json +++ b/package.json @@ -26,13 +26,14 @@ ], "scripts": { "test": "is-ci \"test:ci\" \"test:dev\"", - "test:dev": "npm run test:types && npm run test:format && npm run test:eslint && jest --watch", - "test:ci": "npm run test:types && npm run test:format && npm run test:eslint && jest", + "test:dev": "npm run test:types && npm run test:format && npm run test:eslint && npm run test:codemod && jest --watch", + "test:ci": "npm run test:types && npm run test:format && npm run test:eslint && npm run test:codemod && jest", "test:coverage": "yarn test:ci; open coverage/lcov-report/index.html", "test:format": "yarn prettier --check", "test:types": "tsc", "test:eslint": "eslint --ext .ts,.tsx ./src", "test:size": "yarn build:umd && bundlewatch", + "test:codemod": "jest --config codemods/jest.config.js", "build": "yarn build:commonjs && yarn build:es && yarn build:umd && yarn build:types", "build:commonjs": "rimraf ./lib && cross-env BABEL_ENV=commonjs babel --extensions .ts,.tsx --ignore ./src/**/tests/**/* ./src --out-dir lib", "build:es": "rimraf ./es && babel --extensions .ts,.tsx --ignore ./src/**/tests/**/* ./src --out-dir es", @@ -62,7 +63,11 @@ "lib", "reactjs", "scripts", - "types" + "types", + "codemods", + "!codemods/jest.config.js", + "!codemods/**/__testfixtures__", + "!codemods/**/__tests__" ], "dependencies": { "@babel/runtime": "^7.5.5", @@ -89,9 +94,10 @@ "@babel/preset-typescript": "^7.10.4", "@rollup/plugin-replace": "^3.0.0", "@svgr/rollup": "^6.1.1", - "@testing-library/react": "^10.4.7", "@testing-library/jest-dom": "^5.14.1", + "@testing-library/react": "^10.4.7", "@types/jest": "^26.0.4", + "@types/jscodeshift": "^0.11.3", "@types/react": "^16.9.41", "@types/react-dom": "^16.9.8", "@typescript-eslint/eslint-plugin": "^5.6.0", @@ -117,6 +123,7 @@ "eslint-plugin-standard": "^4.0.1", "is-ci-cli": "^2.1.1", "jest": "^26.0.1", + "jscodeshift": "^0.13.1", "prettier": "2.2.1", "react": "^16.13.0", "react-dom": "^16.13.1", diff --git a/yarn.lock b/yarn.lock index 433e909f92..404b8357c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -46,6 +46,13 @@ dependencies: "@babel/highlight" "^7.16.0" +"@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + "@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" @@ -102,6 +109,27 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/core@^7.13.16": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.7.tgz#db990f931f6d40cb9b87a0dc7d2adc749f1dcbcf" + integrity sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.7" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + "@babel/core@^7.15.5": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.0.tgz#c4ff44046f5fe310525cc9eb4ef5147f0c5374d4" @@ -182,6 +210,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.16.7", "@babel/generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" + integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== + dependencies: + "@babel/types" "^7.16.8" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/generator@^7.6.3": version "7.6.4" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.4.tgz#a4f8437287bf9671b07f483b76e3bb731bc97671" @@ -223,6 +260,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-annotate-as-pure@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" + integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" @@ -277,6 +321,16 @@ browserslist "^4.17.5" semver "^6.3.0" +"@babel/helper-compilation-targets@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" + integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" + browserslist "^4.17.5" + semver "^6.3.0" + "@babel/helper-create-class-features-plugin@^7.10.4", "@babel/helper-create-class-features-plugin@^7.10.5": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" @@ -301,6 +355,19 @@ "@babel/helper-replace-supers" "^7.16.0" "@babel/helper-split-export-declaration" "^7.16.0" +"@babel/helper-create-class-features-plugin@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.7.tgz#9c5b34b53a01f2097daf10678d65135c1b9f84ba" + integrity sha512-kIFozAvVfK05DM4EVQYKK+zteWvY85BFdGBRQBytRyY3y+6PX0DkDOn/CZ3lEuczCfrCxEzwt0YtP/87YPTWSw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-create-regexp-features-plugin@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.1.tgz#1b8feeab1594cbcfbf3ab5a3bbcabac0468efdbd" @@ -350,6 +417,13 @@ resolve "^1.14.2" semver "^6.1.2" +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-explode-assignable-expression@^7.10.4": version "7.11.4" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz#2d8e3470252cc17aba917ede7803d4a7a276a41b" @@ -400,6 +474,15 @@ "@babel/template" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== + dependencies: + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helper-function-name@^7.7.4": version "7.7.4" resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" @@ -437,6 +520,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-get-function-arity@^7.7.4": version "7.7.4" resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" @@ -458,6 +548,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-member-expression-to-functions@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz#432967fd7e12a4afef66c4687d4ca22bc0456f15" @@ -479,6 +576,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-member-expression-to-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" + integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-module-imports@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" @@ -507,6 +611,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-module-transforms@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz#24e2f08ee6832c60b157bb0936c86bef7210c622" @@ -547,6 +658,20 @@ "@babel/traverse" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/helper-module-transforms@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" + integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helper-optimise-call-expression@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz#b4a1f2561870ce1247ceddb02a3860fa96d72543" @@ -568,6 +693,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-optimise-call-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" + integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-plugin-utils@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" @@ -588,6 +720,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== +"@babel/helper-plugin-utils@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" + integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + "@babel/helper-plugin-utils@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" @@ -656,6 +793,17 @@ "@babel/traverse" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/helper-replace-supers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" + integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helper-simple-access@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz#08fb7e22ace9eb8326f7e3920a1c2052f13d851e" @@ -679,6 +827,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-simple-access@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" + integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" @@ -721,6 +876,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-split-export-declaration@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" @@ -750,11 +912,21 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + "@babel/helper-validator-option@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== + "@babel/helper-wrap-function@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" @@ -802,6 +974,15 @@ "@babel/traverse" "^7.16.3" "@babel/types" "^7.16.0" +"@babel/helpers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.7.tgz#7e3504d708d50344112767c3542fc5e357fffefc" + integrity sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helpers@^7.7.4": version "7.7.4" resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302" @@ -847,6 +1028,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.7.tgz#81a01d7d675046f0d96f82450d9d9578bdfd6b0b" + integrity sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/parser@^7.1.0", "@babel/parser@^7.7.4": version "7.7.4" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.7.4.tgz#75ab2d7110c2cf2fa949959afb05fa346d2231bb" @@ -867,6 +1057,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== +"@babel/parser@^7.13.16", "@babel/parser@^7.16.7", "@babel/parser@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.8.tgz#61c243a3875f7d0b0962b0543a33ece6ff2f1f17" + integrity sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw== + "@babel/parser@^7.16.0", "@babel/parser@^7.16.3": version "7.16.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.4.tgz#d5f92f57cf2c74ffe9b37981c0e72fee7311372e" @@ -919,6 +1114,14 @@ "@babel/helper-create-class-features-plugin" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-proposal-class-properties@^7.13.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" + integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-proposal-class-properties@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.0.tgz#c029618267ddebc7280fa286e0f8ca2a278a2d1a" @@ -1008,6 +1211,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" +"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" + integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.0.tgz#44e1cce08fe2427482cf446a91bb451528ed0596" @@ -1077,6 +1288,15 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" +"@babel/plugin-proposal-optional-chaining@^7.13.12": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" + integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-proposal-optional-chaining@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.0.tgz#56dbc3970825683608e9efb55ea82c2a2d6c8dc0" @@ -1192,6 +1412,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-syntax-flow@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.16.7.tgz#202b147e5892b8452bbb0bb269c7ed2539ab8832" + integrity sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" @@ -1297,6 +1524,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-syntax-typescript@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8" + integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-transform-arrow-functions@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" @@ -1466,6 +1700,14 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-flow-strip-types@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.16.7.tgz#291fb140c78dabbf87f2427e7c7c332b126964b8" + integrity sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-flow" "^7.16.7" + "@babel/plugin-transform-for-of@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" @@ -1552,6 +1794,16 @@ "@babel/helper-simple-access" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-commonjs@^7.13.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" + integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== + dependencies: + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-commonjs@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.0.tgz#add58e638c8ddc4875bd9a9ecb5c594613f6c922" @@ -1883,6 +2135,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-typescript" "^7.10.4" +"@babel/plugin-transform-typescript@^7.16.7": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz#591ce9b6b83504903fa9dd3652c357c2ba7a1ee0" + integrity sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-typescript" "^7.16.7" + "@babel/plugin-transform-unicode-escapes@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" @@ -2067,6 +2328,15 @@ core-js-compat "^3.19.1" semver "^6.3.0" +"@babel/preset-flow@^7.13.13": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.16.7.tgz#7fd831323ab25eeba6e4b77a589f680e30581cbd" + integrity sha512-6ceP7IyZdUYQ3wUVqyRSQXztd1YmFHWI4Xv11MIqAlE4WqxBSd/FZ61V9k+TS5Gd4mkHOtQtPp9ymRpxH4y1Ug== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-transform-flow-strip-types" "^7.16.7" + "@babel/preset-modules@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" @@ -2122,6 +2392,26 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-typescript" "^7.10.4" +"@babel/preset-typescript@^7.13.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" + integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-transform-typescript" "^7.16.7" + +"@babel/register@^7.13.16": + version "7.16.9" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.16.9.tgz#fcfb23cfdd9ad95c9771e58183de83b513857806" + integrity sha512-jJ72wcghdRIlENfvALcyODhNoGE5j75cYHdC+aQMh6cU/P86tiiXTp9XYZct1UxUMo/4+BgQRyNZEGx0KWGS+g== + dependencies: + clone-deep "^4.0.1" + find-cache-dir "^2.0.0" + make-dir "^2.1.0" + pirates "^4.0.0" + source-map-support "^0.5.16" + "@babel/runtime-corejs3@^7.10.2": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.3.tgz#931ed6941d3954924a7aa967ee440e60c507b91a" @@ -2230,6 +2520,15 @@ "@babel/parser" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/template@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/template@^7.7.4": version "7.7.4" resolved "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" @@ -2314,6 +2613,22 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.16.7": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.8.tgz#bab2f2b09a5fe8a8d9cad22cbfe3ba1d126fef9c" + integrity sha512-xe+H7JlvKsDQwXRsBhSnq1/+9c+LlQcCK3Tn/l5sbx02HYns/cn7ibp9+RV1sIUqu7hKg91NWsgHurO9dowITQ== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.8" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.16.8" + "@babel/types" "^7.16.8" + debug "^4.1.0" + globals "^11.1.0" + "@babel/traverse@^7.7.4": version "7.7.4" resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" @@ -2373,6 +2688,14 @@ "@babel/helper-validator-identifier" "^7.15.7" to-fast-properties "^2.0.0" +"@babel/types@^7.16.7", "@babel/types@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" + integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + "@babel/types@^7.7.4": version "7.7.4" resolved "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" @@ -2895,6 +3218,14 @@ jest-diff "^25.2.1" pretty-format "^25.2.1" +"@types/jscodeshift@^0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@types/jscodeshift/-/jscodeshift-0.11.3.tgz#8dcab24ced39dcab1c8ff3461b3d171aafee3d48" + integrity sha512-pM0JD9kWVDH9DQp5Y6td16924V3MwZHei8P3cTeuFhXpzpk0K+iWraBZz8wF61QkFs9fZeAQNX0q8SG0+TFm2w== + dependencies: + ast-types "^0.14.1" + recast "^0.20.3" + "@types/json-schema@^7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" @@ -3260,6 +3591,13 @@ ast-types-flow@0.0.7, ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= +ast-types@0.14.2, ast-types@^0.14.1: + version "0.14.2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd" + integrity sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA== + dependencies: + tslib "^2.0.1" + astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" @@ -3312,6 +3650,11 @@ axobject-query@^2.0.2: dependencies: ast-types-flow "0.0.7" +babel-core@^7.0.0-bridge.0: + version "7.0.0-bridge.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" + integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== + babel-eslint@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" @@ -3657,6 +4000,14 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" @@ -3741,6 +4092,15 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -3810,6 +4170,11 @@ commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -4576,7 +4941,7 @@ espree@^7.1.0: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.2.0" -esprima@^4.0.0, esprima@^4.0.1: +esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -4835,6 +5200,15 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +find-cache-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -4842,6 +5216,13 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -4864,6 +5245,11 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== +flow-parser@0.*: + version "0.169.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.169.0.tgz#4f77d61dd4241f8063f734ef1f71c684ec03ab52" + integrity sha512-X1DFb6wxXpZLLqM9NX0Wm+4xoN6xAyJn8OwuiHsV0JJvLfD18Z+wbgJ1lM7ykTVINdu8v7Mu0gIzWMvnhKWBkA== + follow-redirects@1.5.10: version "1.5.10" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" @@ -6048,6 +6434,31 @@ jscc@^1.1.1: perf-regexes "^1.0.1" skip-regex "^1.0.2" +jscodeshift@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.13.1.tgz#69bfe51e54c831296380585c6d9e733512aecdef" + integrity sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ== + dependencies: + "@babel/core" "^7.13.16" + "@babel/parser" "^7.13.16" + "@babel/plugin-proposal-class-properties" "^7.13.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.8" + "@babel/plugin-proposal-optional-chaining" "^7.13.12" + "@babel/plugin-transform-modules-commonjs" "^7.13.8" + "@babel/preset-flow" "^7.13.13" + "@babel/preset-typescript" "^7.13.0" + "@babel/register" "^7.13.16" + babel-core "^7.0.0-bridge.0" + chalk "^4.1.2" + flow-parser "0.*" + graceful-fs "^4.2.4" + micromatch "^3.1.10" + neo-async "^2.5.0" + node-dir "^0.1.17" + recast "^0.20.4" + temp "^0.8.4" + write-file-atomic "^2.3.0" + jsdom@^16.2.2: version "16.2.2" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.2.2.tgz#76f2f7541646beb46a938f5dc476b88705bedf2b" @@ -6239,6 +6650,14 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -6326,7 +6745,7 @@ magic-string@^0.25.2: dependencies: sourcemap-codec "^1.4.4" -make-dir@^2.1.0: +make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== @@ -6437,7 +6856,7 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -minimatch@3.0.4, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -6528,11 +6947,23 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= +neo-async@^2.5.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-dir@^0.1.17: + version "0.1.17" + resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" + integrity sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU= + dependencies: + minimatch "^3.0.2" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -6777,7 +7208,7 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.2.0: +p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== @@ -6791,6 +7222,13 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.0" +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + p-locate@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" @@ -6919,6 +7357,11 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== +pirates@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.4.tgz#07df81e61028e402735cdd49db701e4885b4e6e6" + integrity sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw== + pirates@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" @@ -6933,6 +7376,13 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -7170,6 +7620,16 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +recast@^0.20.3, recast@^0.20.4: + version "0.20.5" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.20.5.tgz#8e2c6c96827a1b339c634dd232957d230553ceae" + integrity sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ== + dependencies: + ast-types "0.14.2" + esprima "~4.0.0" + source-map "~0.6.1" + tslib "^2.0.1" + redent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" @@ -7427,7 +7887,7 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@2.6.3: +rimraf@2.6.3, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -7667,6 +8127,13 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -7815,18 +8282,18 @@ source-map-resolve@^0.6.0: atob "^2.1.2" decode-uri-component "^0.2.0" -source-map-support@^0.5.6: - version "0.5.16" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" - integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== +source-map-support@^0.5.16, source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== +source-map-support@^0.5.6: + version "0.5.16" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -8117,6 +8584,13 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" +temp@^0.8.4: + version "0.8.4" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2" + integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg== + dependencies: + rimraf "~2.6.2" + terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -8251,6 +8725,11 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tslib@^2.0.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -8573,6 +9052,15 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +write-file-atomic@^2.3.0: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + write-file-atomic@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"