Skip to content

Commit d82a0cb

Browse files
feat(codemod): add codemod that renames the cacheTime and useErrorBoundary object properties and TypeScript property signatures (#5765)
1 parent e14a171 commit d82a0cb

File tree

6 files changed

+301
-0
lines changed

6 files changed

+301
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import * as React from 'react'
2+
import { QueryClient, useInfiniteQuery } from '@tanstack/react-query'
3+
import { search } from './algolia'
4+
5+
// Since the `cacheTime` property is string literal and not computed, the codemod should change it.
6+
export type UseAlgoliaOptionsButWithStringLiterals = {
7+
'indexName': string
8+
'query': string
9+
'hitsPerPage'?: number
10+
'staleTime'?: number
11+
'cacheTime'?: number
12+
'enabled'?: boolean
13+
}
14+
15+
// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.
16+
export type UseAlgoliaOptions = {
17+
indexName: string
18+
query: string
19+
hitsPerPage?: number
20+
staleTime?: number
21+
cacheTime?: number
22+
enabled?: boolean
23+
}
24+
25+
// Since the `cacheTime` property is an identifier and not computed, and shorthand, the codemod should change it.
26+
export function useAlgolia<TData>({
27+
indexName,
28+
query,
29+
hitsPerPage = 10,
30+
staleTime,
31+
cacheTime,
32+
enabled,
33+
}: UseAlgoliaOptions) {
34+
const queryInfo = useInfiniteQuery({
35+
queryKey: ['algolia', indexName, query, hitsPerPage],
36+
queryFn: ({ pageParam }) =>
37+
search<TData>({ indexName, query, pageParam, hitsPerPage }),
38+
defaultPageParam: 0,
39+
getNextPageParam: (lastPage) => lastPage?.nextPage,
40+
staleTime,
41+
cacheTime,
42+
enabled,
43+
})
44+
45+
const hits = queryInfo.data?.pages.map((page) => page.hits).flat()
46+
47+
return { ...queryInfo, hits }
48+
}
49+
50+
// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.
51+
export const asIdentifierExample = () =>
52+
new QueryClient({
53+
defaultOptions: {
54+
queries: {
55+
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
56+
},
57+
},
58+
})
59+
60+
// Since the `cacheTime` property is a string literal and not computed, the codemod should change it.
61+
export const asStringLiteralExample = () =>
62+
new QueryClient({
63+
defaultOptions: {
64+
queries: {
65+
'cacheTime': 1000 * 60 * 60 * 24, // 24 hours
66+
},
67+
},
68+
})
69+
70+
// Since the `cacheTime` property is computed, the codemod shouldn't touch this example.
71+
export const asComputedExample = () => {
72+
const cacheTime = 'foo'
73+
74+
return new QueryClient({
75+
defaultOptions: {
76+
queries: {
77+
[cacheTime]: 1000 * 60 * 60 * 24, // 24 hours
78+
},
79+
},
80+
})
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import * as React from 'react'
2+
import { QueryClient, useInfiniteQuery } from '@tanstack/react-query'
3+
import { search } from './algolia'
4+
5+
// Since the `cacheTime` property is string literal and not computed, the codemod should change it.
6+
export type UseAlgoliaOptionsButWithStringLiterals = {
7+
'indexName': string
8+
'query': string
9+
'hitsPerPage'?: number
10+
'staleTime'?: number
11+
'gcTime'?: number
12+
'enabled'?: boolean
13+
}
14+
15+
// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.
16+
export type UseAlgoliaOptions = {
17+
indexName: string
18+
query: string
19+
hitsPerPage?: number
20+
staleTime?: number
21+
gcTime?: number
22+
enabled?: boolean
23+
}
24+
25+
// Since the `cacheTime` property is an identifier and not computed, and shorthand, the codemod should change it.
26+
export function useAlgolia<TData>({
27+
indexName,
28+
query,
29+
hitsPerPage = 10,
30+
staleTime,
31+
gcTime,
32+
enabled,
33+
}: UseAlgoliaOptions) {
34+
const queryInfo = useInfiniteQuery({
35+
queryKey: ['algolia', indexName, query, hitsPerPage],
36+
queryFn: ({ pageParam }) =>
37+
search<TData>({ indexName, query, pageParam, hitsPerPage }),
38+
defaultPageParam: 0,
39+
getNextPageParam: (lastPage) => lastPage?.nextPage,
40+
staleTime,
41+
gcTime,
42+
enabled,
43+
})
44+
45+
const hits = queryInfo.data?.pages.map((page) => page.hits).flat()
46+
47+
return { ...queryInfo, hits }
48+
}
49+
50+
// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.
51+
export const asIdentifierExample = () =>
52+
new QueryClient({
53+
defaultOptions: {
54+
queries: {
55+
gcTime: 1000 * 60 * 60 * 24, // 24 hours
56+
},
57+
},
58+
})
59+
60+
// Since the `cacheTime` property is a string literal and not computed, the codemod should change it.
61+
export const asStringLiteralExample = () =>
62+
new QueryClient({
63+
defaultOptions: {
64+
queries: {
65+
'gcTime': 1000 * 60 * 60 * 24, // 24 hours
66+
},
67+
},
68+
})
69+
70+
// Since the `cacheTime` property is computed, the codemod shouldn't touch this example.
71+
export const asComputedExample = () => {
72+
const cacheTime = 'foo'
73+
74+
return new QueryClient({
75+
defaultOptions: {
76+
queries: {
77+
[cacheTime]: 1000 * 60 * 60 * 24, // 24 hours
78+
},
79+
},
80+
})
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as React from 'react'
2+
3+
// Since the `useErrorBoundary` property is string literal and not computed, the codemod should change it.
4+
export type Type1 = {
5+
'useErrorBoundary'?: boolean
6+
}
7+
8+
// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.
9+
export type Type2 = {
10+
useErrorBoundary?: boolean
11+
}
12+
13+
// Since the `useErrorBoundary` property is an identifier and not computed, and shorthand, the codemod should change it.
14+
export function useSomething() {
15+
const queryInfo = useSomethingElse({
16+
useErrorBoundary,
17+
enabled,
18+
})
19+
20+
return queryInfo
21+
}
22+
23+
// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.
24+
export const asIdentifierExample = () => {
25+
return {
26+
useErrorBoundary: true
27+
}
28+
}
29+
30+
// Since the `useErrorBoundary` property is a string literal and not computed, the codemod should change it.
31+
export const asStringLiteralExample = () => {
32+
return {
33+
'useErrorBoundary': true
34+
}
35+
}
36+
37+
// Since the `useErrorBoundary` property is computed, the codemod shouldn't touch this example.
38+
export const asComputedExample = () => {
39+
const useErrorBoundary = 'foo'
40+
41+
return {
42+
[useErrorBoundary]: false
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as React from 'react'
2+
3+
// Since the `useErrorBoundary` property is string literal and not computed, the codemod should change it.
4+
export type Type1 = {
5+
'throwOnError'?: boolean
6+
}
7+
8+
// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.
9+
export type Type2 = {
10+
throwOnError?: boolean
11+
}
12+
13+
// Since the `useErrorBoundary` property is an identifier and not computed, and shorthand, the codemod should change it.
14+
export function useSomething() {
15+
const queryInfo = useSomethingElse({
16+
throwOnError,
17+
enabled,
18+
})
19+
20+
return queryInfo
21+
}
22+
23+
// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.
24+
export const asIdentifierExample = () => {
25+
return {
26+
throwOnError: true
27+
};
28+
}
29+
30+
// Since the `useErrorBoundary` property is a string literal and not computed, the codemod should change it.
31+
export const asStringLiteralExample = () => {
32+
return {
33+
'throwOnError': true
34+
};
35+
}
36+
37+
// Since the `useErrorBoundary` property is computed, the codemod shouldn't touch this example.
38+
export const asComputedExample = () => {
39+
const useErrorBoundary = 'foo'
40+
41+
return {
42+
[useErrorBoundary]: false
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// eslint-disable-next-line @typescript-eslint/no-var-requires
2+
const defineTest = require('jscodeshift/dist/testUtils').defineTest
3+
4+
defineTest(__dirname, 'rename-properties', null, 'rename-cache-time', {
5+
parser: 'tsx',
6+
})
7+
8+
defineTest(__dirname, 'rename-properties', null, 'rename-use-error-boundary', {
9+
parser: 'tsx',
10+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
module.exports = (file, api) => {
2+
const jscodeshift = api.jscodeshift
3+
const root = jscodeshift(file.source)
4+
5+
const baseRenameLogic = (kind, from, to) => {
6+
root
7+
.find(kind, (node) => {
8+
return (
9+
node.computed === false &&
10+
(node.key?.name === from || node.key?.value === from)
11+
)
12+
})
13+
.replaceWith(({ node: mutableNode }) => {
14+
if (mutableNode.key.name !== undefined) {
15+
mutableNode.key.name = to
16+
}
17+
18+
if (mutableNode.key.value !== undefined) {
19+
mutableNode.key.value = to
20+
}
21+
22+
return mutableNode
23+
})
24+
}
25+
26+
const renameObjectProperty = (from, to) => {
27+
baseRenameLogic(jscodeshift.ObjectProperty, from, to)
28+
}
29+
30+
const renameTypeScriptPropertySignature = (from, to) => {
31+
baseRenameLogic(jscodeshift.TSPropertySignature, from, to)
32+
}
33+
34+
renameObjectProperty('cacheTime', 'gcTime')
35+
renameObjectProperty('useErrorBoundary', 'throwOnError')
36+
37+
renameTypeScriptPropertySignature('cacheTime', 'gcTime')
38+
renameTypeScriptPropertySignature('useErrorBoundary', 'throwOnError')
39+
40+
return root.toSource({ quote: 'single', lineTerminator: '\n' })
41+
}

0 commit comments

Comments
 (0)