Skip to content

Commit

Permalink
feat(codemod): add codemod that renames the cacheTime and `useError…
Browse files Browse the repository at this point in the history
…Boundary` object properties and TypeScript property signatures (#5765)
  • Loading branch information
balazsmatepetro authored Jul 22, 2023
1 parent e14a171 commit d82a0cb
Show file tree
Hide file tree
Showing 6 changed files with 301 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import * as React from 'react'
import { QueryClient, useInfiniteQuery } from '@tanstack/react-query'
import { search } from './algolia'

// Since the `cacheTime` property is string literal and not computed, the codemod should change it.
export type UseAlgoliaOptionsButWithStringLiterals = {
'indexName': string
'query': string
'hitsPerPage'?: number
'staleTime'?: number
'cacheTime'?: number
'enabled'?: boolean
}

// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.
export type UseAlgoliaOptions = {
indexName: string
query: string
hitsPerPage?: number
staleTime?: number
cacheTime?: number
enabled?: boolean
}

// Since the `cacheTime` property is an identifier and not computed, and shorthand, the codemod should change it.
export function useAlgolia<TData>({
indexName,
query,
hitsPerPage = 10,
staleTime,
cacheTime,
enabled,
}: UseAlgoliaOptions) {
const queryInfo = useInfiniteQuery({
queryKey: ['algolia', indexName, query, hitsPerPage],
queryFn: ({ pageParam }) =>
search<TData>({ indexName, query, pageParam, hitsPerPage }),
defaultPageParam: 0,
getNextPageParam: (lastPage) => lastPage?.nextPage,
staleTime,
cacheTime,
enabled,
})

const hits = queryInfo.data?.pages.map((page) => page.hits).flat()

return { ...queryInfo, hits }
}

// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.
export const asIdentifierExample = () =>
new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})

// Since the `cacheTime` property is a string literal and not computed, the codemod should change it.
export const asStringLiteralExample = () =>
new QueryClient({
defaultOptions: {
queries: {
'cacheTime': 1000 * 60 * 60 * 24, // 24 hours
},
},
})

// Since the `cacheTime` property is computed, the codemod shouldn't touch this example.
export const asComputedExample = () => {
const cacheTime = 'foo'

return new QueryClient({
defaultOptions: {
queries: {
[cacheTime]: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import * as React from 'react'
import { QueryClient, useInfiniteQuery } from '@tanstack/react-query'
import { search } from './algolia'

// Since the `cacheTime` property is string literal and not computed, the codemod should change it.
export type UseAlgoliaOptionsButWithStringLiterals = {
'indexName': string
'query': string
'hitsPerPage'?: number
'staleTime'?: number
'gcTime'?: number
'enabled'?: boolean
}

// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.
export type UseAlgoliaOptions = {
indexName: string
query: string
hitsPerPage?: number
staleTime?: number
gcTime?: number
enabled?: boolean
}

// Since the `cacheTime` property is an identifier and not computed, and shorthand, the codemod should change it.
export function useAlgolia<TData>({
indexName,
query,
hitsPerPage = 10,
staleTime,
gcTime,
enabled,
}: UseAlgoliaOptions) {
const queryInfo = useInfiniteQuery({
queryKey: ['algolia', indexName, query, hitsPerPage],
queryFn: ({ pageParam }) =>
search<TData>({ indexName, query, pageParam, hitsPerPage }),
defaultPageParam: 0,
getNextPageParam: (lastPage) => lastPage?.nextPage,
staleTime,
gcTime,
enabled,
})

const hits = queryInfo.data?.pages.map((page) => page.hits).flat()

return { ...queryInfo, hits }
}

// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.
export const asIdentifierExample = () =>
new QueryClient({
defaultOptions: {
queries: {
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})

// Since the `cacheTime` property is a string literal and not computed, the codemod should change it.
export const asStringLiteralExample = () =>
new QueryClient({
defaultOptions: {
queries: {
'gcTime': 1000 * 60 * 60 * 24, // 24 hours
},
},
})

// Since the `cacheTime` property is computed, the codemod shouldn't touch this example.
export const asComputedExample = () => {
const cacheTime = 'foo'

return new QueryClient({
defaultOptions: {
queries: {
[cacheTime]: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as React from 'react'

// Since the `useErrorBoundary` property is string literal and not computed, the codemod should change it.
export type Type1 = {
'useErrorBoundary'?: boolean
}

// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.
export type Type2 = {
useErrorBoundary?: boolean
}

// Since the `useErrorBoundary` property is an identifier and not computed, and shorthand, the codemod should change it.
export function useSomething() {
const queryInfo = useSomethingElse({
useErrorBoundary,
enabled,
})

return queryInfo
}

// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.
export const asIdentifierExample = () => {
return {
useErrorBoundary: true
}
}

// Since the `useErrorBoundary` property is a string literal and not computed, the codemod should change it.
export const asStringLiteralExample = () => {
return {
'useErrorBoundary': true
}
}

// Since the `useErrorBoundary` property is computed, the codemod shouldn't touch this example.
export const asComputedExample = () => {
const useErrorBoundary = 'foo'

return {
[useErrorBoundary]: false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as React from 'react'

// Since the `useErrorBoundary` property is string literal and not computed, the codemod should change it.
export type Type1 = {
'throwOnError'?: boolean
}

// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.
export type Type2 = {
throwOnError?: boolean
}

// Since the `useErrorBoundary` property is an identifier and not computed, and shorthand, the codemod should change it.
export function useSomething() {
const queryInfo = useSomethingElse({
throwOnError,
enabled,
})

return queryInfo
}

// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.
export const asIdentifierExample = () => {
return {
throwOnError: true
};
}

// Since the `useErrorBoundary` property is a string literal and not computed, the codemod should change it.
export const asStringLiteralExample = () => {
return {
'throwOnError': true
};
}

// Since the `useErrorBoundary` property is computed, the codemod shouldn't touch this example.
export const asComputedExample = () => {
const useErrorBoundary = 'foo'

return {
[useErrorBoundary]: false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const defineTest = require('jscodeshift/dist/testUtils').defineTest

defineTest(__dirname, 'rename-properties', null, 'rename-cache-time', {
parser: 'tsx',
})

defineTest(__dirname, 'rename-properties', null, 'rename-use-error-boundary', {
parser: 'tsx',
})
41 changes: 41 additions & 0 deletions packages/codemods/src/v5/rename-properties/rename-properties.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module.exports = (file, api) => {
const jscodeshift = api.jscodeshift
const root = jscodeshift(file.source)

const baseRenameLogic = (kind, from, to) => {
root
.find(kind, (node) => {
return (
node.computed === false &&
(node.key?.name === from || node.key?.value === from)
)
})
.replaceWith(({ node: mutableNode }) => {
if (mutableNode.key.name !== undefined) {
mutableNode.key.name = to
}

if (mutableNode.key.value !== undefined) {
mutableNode.key.value = to
}

return mutableNode
})
}

const renameObjectProperty = (from, to) => {
baseRenameLogic(jscodeshift.ObjectProperty, from, to)
}

const renameTypeScriptPropertySignature = (from, to) => {
baseRenameLogic(jscodeshift.TSPropertySignature, from, to)
}

renameObjectProperty('cacheTime', 'gcTime')
renameObjectProperty('useErrorBoundary', 'throwOnError')

renameTypeScriptPropertySignature('cacheTime', 'gcTime')
renameTypeScriptPropertySignature('useErrorBoundary', 'throwOnError')

return root.toSource({ quote: 'single', lineTerminator: '\n' })
}

0 comments on commit d82a0cb

Please sign in to comment.