first commit
This commit is contained in:
Generated
Vendored
+244
@@ -0,0 +1,244 @@
|
||||
const createUtilsObject = require('../../utils/index.cjs')
|
||||
const createUseQueryLikeTransformer = require('../../utils/transformers/use-query-like-transformer.cjs')
|
||||
const createQueryClientTransformer = require('../../utils/transformers/query-client-transformer.cjs')
|
||||
|
||||
const originalName = 'isLoading'
|
||||
const newName = 'isPending'
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift')} jscodeshift
|
||||
* @param {Object} utils
|
||||
* @param {import('jscodeshift').Collection} root
|
||||
* @param {string} filePath
|
||||
* @param {{keyName: "mutationKey"|"queryKey", queryClientMethods: ReadonlyArray<string>, hooks: ReadonlyArray<string>}} config
|
||||
*/
|
||||
const transformUsages = ({ jscodeshift, utils, root, filePath, config }) => {
|
||||
/**
|
||||
* @param {import('jscodeshift').CallExpression | import('jscodeshift').ExpressionStatement} node
|
||||
* @returns {{start: number, end: number}}
|
||||
*/
|
||||
const getNodeLocation = (node) => {
|
||||
const location = utils.isCallExpression(node) ? node.callee.loc : node.loc
|
||||
const start = location.start.line
|
||||
const end = location.end.line
|
||||
|
||||
return { start, end }
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').ASTNode} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isObjectExpression = (node) => {
|
||||
return jscodeshift.match(node, {
|
||||
type: jscodeshift.ObjectExpression.name,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').ASTNode} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isObjectPattern = (node) => {
|
||||
return jscodeshift.match(node, {
|
||||
type: jscodeshift.ObjectPattern.name,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').ASTNode} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isVariableDeclarator = (node) => {
|
||||
return jscodeshift.match(node, {
|
||||
type: jscodeshift.VariableDeclarator.name,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').Node} node
|
||||
* @param {import('jscodeshift').Identifier} identifier
|
||||
* @returns {Collection<import('jscodeshift').MemberExpression>}
|
||||
*/
|
||||
const findIsLoadingPropertiesOfIdentifier = (node, identifier) => {
|
||||
return jscodeshift(node).find(jscodeshift.MemberExpression, {
|
||||
object: {
|
||||
type: jscodeshift.Identifier.name,
|
||||
name: identifier.name,
|
||||
},
|
||||
property: {
|
||||
type: jscodeshift.Identifier.name,
|
||||
name: originalName,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').ObjectPattern} node
|
||||
* @returns {import('jscodeshift').ObjectProperty|null}
|
||||
*/
|
||||
const findIsLoadingObjectPropertyInObjectPattern = (node) => {
|
||||
return (
|
||||
node.properties.find((property) =>
|
||||
jscodeshift.match(property, {
|
||||
key: {
|
||||
type: jscodeshift.Identifier.name,
|
||||
name: originalName,
|
||||
},
|
||||
}),
|
||||
) ?? null
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').ObjectPattern} node
|
||||
* @returns {import('jscodeshift').RestElement|null}
|
||||
*/
|
||||
const findRestElementInObjectPattern = (node) => {
|
||||
return (
|
||||
node.properties.find((property) =>
|
||||
jscodeshift.match(property, {
|
||||
type: jscodeshift.RestElement.name,
|
||||
}),
|
||||
) ?? null
|
||||
)
|
||||
}
|
||||
|
||||
const replacer = (path, transformNode) => {
|
||||
const node = path.node
|
||||
const parentNode = path.parentPath.value
|
||||
const { start, end } = getNodeLocation(node)
|
||||
|
||||
try {
|
||||
if (!isVariableDeclarator(parentNode)) {
|
||||
// The parent node is not a variable declarator, the transformation will be skipped.
|
||||
return node
|
||||
}
|
||||
|
||||
const lookupNode = path.scope.node
|
||||
const variableDeclaratorId = parentNode.id
|
||||
|
||||
if (isObjectPattern(variableDeclaratorId)) {
|
||||
const isLoadingObjectProperty =
|
||||
findIsLoadingObjectPropertyInObjectPattern(variableDeclaratorId)
|
||||
|
||||
if (isLoadingObjectProperty) {
|
||||
jscodeshift(lookupNode)
|
||||
.find(jscodeshift.ObjectProperty, {
|
||||
key: {
|
||||
type: jscodeshift.Identifier.name,
|
||||
name: originalName,
|
||||
},
|
||||
})
|
||||
.replaceWith((mutablePath) => {
|
||||
if (isObjectPattern(mutablePath.parent)) {
|
||||
const affectedProperty = mutablePath.value.value.shorthand
|
||||
? 'value'
|
||||
: 'key'
|
||||
|
||||
mutablePath.value[affectedProperty].name = newName
|
||||
|
||||
return mutablePath.value
|
||||
}
|
||||
|
||||
if (isObjectExpression(mutablePath.parent)) {
|
||||
const affectedProperty = mutablePath.value.value.shorthand
|
||||
? 'key'
|
||||
: 'value'
|
||||
|
||||
mutablePath.value[affectedProperty].name = newName
|
||||
|
||||
return mutablePath.value
|
||||
}
|
||||
|
||||
return mutablePath.value
|
||||
})
|
||||
|
||||
// Renaming all other 'isLoading' references that are object properties.
|
||||
jscodeshift(lookupNode)
|
||||
.find(jscodeshift.Identifier, { name: originalName })
|
||||
.replaceWith((mutablePath) => {
|
||||
if (
|
||||
!jscodeshift.match(mutablePath.parent, {
|
||||
type: jscodeshift.ObjectProperty.name,
|
||||
})
|
||||
) {
|
||||
mutablePath.value.name = newName
|
||||
}
|
||||
|
||||
return mutablePath.value
|
||||
})
|
||||
}
|
||||
|
||||
const restElement = findRestElementInObjectPattern(variableDeclaratorId)
|
||||
|
||||
if (restElement) {
|
||||
findIsLoadingPropertiesOfIdentifier(
|
||||
lookupNode,
|
||||
restElement.argument,
|
||||
).replaceWith(({ node: mutableNode }) => {
|
||||
mutableNode.property.name = newName
|
||||
|
||||
return mutableNode
|
||||
})
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
if (utils.isIdentifier(variableDeclaratorId)) {
|
||||
findIsLoadingPropertiesOfIdentifier(
|
||||
lookupNode,
|
||||
variableDeclaratorId,
|
||||
).replaceWith(({ node: mutableNode }) => {
|
||||
mutableNode.property.name = newName
|
||||
|
||||
return mutableNode
|
||||
})
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
utils.warn(
|
||||
`The usage in file "${filePath}" at line ${start}:${end} could not be transformed. Please migrate this usage manually.`,
|
||||
)
|
||||
|
||||
return node
|
||||
} catch (error) {
|
||||
utils.warn(
|
||||
`An unknown error occurred while processing the "${filePath}" file. Please review this file, because the codemod couldn't be applied.`,
|
||||
)
|
||||
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
createUseQueryLikeTransformer({ jscodeshift, utils, root }).execute(
|
||||
config.hooks,
|
||||
replacer,
|
||||
)
|
||||
|
||||
createQueryClientTransformer({ jscodeshift, utils, root }).execute(
|
||||
config.queryClientMethods,
|
||||
replacer,
|
||||
)
|
||||
}
|
||||
|
||||
module.exports = (file, api) => {
|
||||
const jscodeshift = api.jscodeshift
|
||||
const root = jscodeshift(file.source)
|
||||
const utils = createUtilsObject({ root, jscodeshift })
|
||||
const filePath = file.path
|
||||
|
||||
const dependencies = { jscodeshift, utils, root, filePath }
|
||||
|
||||
transformUsages({
|
||||
...dependencies,
|
||||
config: {
|
||||
hooks: ['useQuery', 'useMutation'],
|
||||
queryClientMethods: [],
|
||||
},
|
||||
})
|
||||
|
||||
return root.toSource({ quote: 'single', lineTerminator: '\n' })
|
||||
}
|
||||
Generated
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
### Intro
|
||||
|
||||
The prerequisite for this code mod is to migrate your usages to the new syntax, so overloads for hooks and `QueryClient` methods shouldn't be available anymore.
|
||||
|
||||
### Affected usages
|
||||
|
||||
Please note, this code mod transforms usages only where the first argument is an object expression.
|
||||
|
||||
The following usage should be transformed by the code mod:
|
||||
|
||||
```ts
|
||||
const { data } = useQuery({
|
||||
queryKey: ['posts'],
|
||||
queryFn: queryFn,
|
||||
keepPreviousData: true,
|
||||
})
|
||||
```
|
||||
|
||||
But the following usage won't be transformed by the code mod, because the first argument an identifier:
|
||||
|
||||
```ts
|
||||
const hookArgument = {
|
||||
queryKey: ['posts'],
|
||||
queryFn: queryFn,
|
||||
keepPreviousData: true,
|
||||
}
|
||||
const { data } = useQuery(hookArgument)
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
In case of any errors, feel free to reach us out via Discord or open an issue. If you open an issue, please provide a code snippet as well, because without a snippet we cannot find the bug in the code mod.
|
||||
Generated
Vendored
+271
@@ -0,0 +1,271 @@
|
||||
const createUtilsObject = require('../../utils/index.cjs')
|
||||
const createUseQueryLikeTransformer = require('../../utils/transformers/use-query-like-transformer.cjs')
|
||||
const createQueryClientTransformer = require('../../utils/transformers/query-client-transformer.cjs')
|
||||
const AlreadyHasPlaceholderDataProperty = require('./utils/already-has-placeholder-data-property.cjs')
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift')} jscodeshift
|
||||
* @param {Object} utils
|
||||
* @param {import('jscodeshift').Collection} root
|
||||
* @param {string} filePath
|
||||
* @param {{keyName: "mutationKey"|"queryKey", queryClientMethods: ReadonlyArray<string>, hooks: ReadonlyArray<string>}} config
|
||||
*/
|
||||
const transformUsages = ({ jscodeshift, utils, root, filePath, config }) => {
|
||||
/**
|
||||
* @param {import('jscodeshift').CallExpression | import('jscodeshift').ExpressionStatement} node
|
||||
* @returns {{start: number, end: number}}
|
||||
*/
|
||||
const getNodeLocation = (node) => {
|
||||
const location = utils.isCallExpression(node) ? node.callee.loc : node.loc
|
||||
const start = location.start.line
|
||||
const end = location.end.line
|
||||
|
||||
return { start, end }
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').ObjectProperty} objectProperty
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isKeepPreviousDataObjectProperty = (objectProperty) => {
|
||||
return jscodeshift.match(objectProperty.key, {
|
||||
type: jscodeshift.Identifier.name,
|
||||
name: 'keepPreviousData',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').ObjectProperty} objectProperty
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isObjectPropertyHasTrueBooleanLiteralValue = (objectProperty) => {
|
||||
return jscodeshift.match(objectProperty.value, {
|
||||
type: jscodeshift.BooleanLiteral.name,
|
||||
value: true,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').ObjectExpression} objectExpression
|
||||
* @returns {Array<import('jscodeshift').ObjectProperty>}
|
||||
*/
|
||||
const filterKeepPreviousDataProperty = (objectExpression) => {
|
||||
return objectExpression.properties.filter((objectProperty) => {
|
||||
return !isKeepPreviousDataObjectProperty(objectProperty)
|
||||
})
|
||||
}
|
||||
|
||||
const createPlaceholderDataObjectProperty = () => {
|
||||
return jscodeshift.objectProperty(
|
||||
jscodeshift.identifier('placeholderData'),
|
||||
jscodeshift.identifier('keepPreviousData'),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').ObjectExpression} objectExpression
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const hasPlaceholderDataProperty = (objectExpression) => {
|
||||
return (
|
||||
objectExpression.properties.findIndex((objectProperty) => {
|
||||
return jscodeshift.match(objectProperty.key, {
|
||||
type: jscodeshift.Identifier.name,
|
||||
name: 'placeholderData',
|
||||
})
|
||||
}) !== -1
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').ObjectExpression} objectExpression
|
||||
* @returns {import('jscodeshift').ObjectProperty | undefined}
|
||||
*/
|
||||
const getKeepPreviousDataProperty = (objectExpression) => {
|
||||
return objectExpression.properties.find(isKeepPreviousDataObjectProperty)
|
||||
}
|
||||
|
||||
let shouldAddKeepPreviousDataImport = false
|
||||
|
||||
const replacer = (path, resolveTargetArgument, transformNode) => {
|
||||
const node = path.node
|
||||
const { start, end } = getNodeLocation(node)
|
||||
|
||||
try {
|
||||
const targetArgument = resolveTargetArgument(node)
|
||||
|
||||
if (targetArgument && utils.isObjectExpression(targetArgument)) {
|
||||
const isPlaceholderDataPropertyPresent =
|
||||
hasPlaceholderDataProperty(targetArgument)
|
||||
|
||||
if (hasPlaceholderDataProperty(targetArgument)) {
|
||||
throw new AlreadyHasPlaceholderDataProperty(node, filePath)
|
||||
}
|
||||
|
||||
const keepPreviousDataProperty =
|
||||
getKeepPreviousDataProperty(targetArgument)
|
||||
|
||||
const keepPreviousDataPropertyHasTrueValue =
|
||||
isObjectPropertyHasTrueBooleanLiteralValue(keepPreviousDataProperty)
|
||||
|
||||
if (!keepPreviousDataPropertyHasTrueValue) {
|
||||
utils.warn(
|
||||
`The usage in file "${filePath}" at line ${start}:${end} already contains a "keepPreviousData" property but its value is not "true". Please migrate this usage manually.`,
|
||||
)
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
if (keepPreviousDataPropertyHasTrueValue) {
|
||||
// Removing the `keepPreviousData` property from the object.
|
||||
const mutableObjectExpressionProperties =
|
||||
filterKeepPreviousDataProperty(targetArgument)
|
||||
|
||||
if (!isPlaceholderDataPropertyPresent) {
|
||||
shouldAddKeepPreviousDataImport = true
|
||||
|
||||
// When the `placeholderData` property is not present, the `placeholderData: keepPreviousData` property will be added.
|
||||
mutableObjectExpressionProperties.push(
|
||||
createPlaceholderDataObjectProperty(),
|
||||
)
|
||||
}
|
||||
|
||||
return transformNode(
|
||||
node,
|
||||
jscodeshift.objectExpression(mutableObjectExpressionProperties),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
utils.warn(
|
||||
`The usage in file "${filePath}" at line ${start}:${end} could not be transformed, because the first parameter is not an object expression. Please migrate this usage manually.`,
|
||||
)
|
||||
|
||||
return node
|
||||
} catch (error) {
|
||||
utils.warn(
|
||||
error.name === AlreadyHasPlaceholderDataProperty.name
|
||||
? error.message
|
||||
: `An unknown error occurred while processing the "${filePath}" file. Please review this file, because the codemod couldn't be applied.`,
|
||||
)
|
||||
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
createUseQueryLikeTransformer({ jscodeshift, utils, root }).execute(
|
||||
config.hooks,
|
||||
(path) => {
|
||||
const resolveTargetArgument = (node) => node.arguments[0] ?? null
|
||||
const transformNode = (node, transformedArgument) =>
|
||||
jscodeshift.callExpression(node.original.callee, [transformedArgument])
|
||||
|
||||
return replacer(path, resolveTargetArgument, transformNode)
|
||||
},
|
||||
)
|
||||
|
||||
createQueryClientTransformer({ jscodeshift, utils, root }).execute(
|
||||
config.queryClientMethods,
|
||||
(path) => {
|
||||
const resolveTargetArgument = (node) => node.arguments[1] ?? null
|
||||
const transformNode = (node, transformedArgument) => {
|
||||
return jscodeshift.callExpression(node.original.callee, [
|
||||
node.arguments[0],
|
||||
transformedArgument,
|
||||
...node.arguments.slice(2, 0),
|
||||
])
|
||||
}
|
||||
|
||||
return replacer(path, resolveTargetArgument, transformNode)
|
||||
},
|
||||
)
|
||||
|
||||
const importIdentifierOfQueryClient = utils.getSelectorByImports(
|
||||
utils.locateImports(['QueryClient']),
|
||||
'QueryClient',
|
||||
)
|
||||
|
||||
root
|
||||
.find(jscodeshift.ExpressionStatement, {
|
||||
expression: {
|
||||
type: jscodeshift.NewExpression.name,
|
||||
callee: {
|
||||
type: jscodeshift.Identifier.name,
|
||||
name: importIdentifierOfQueryClient,
|
||||
},
|
||||
},
|
||||
})
|
||||
.filter((path) => path.node.expression)
|
||||
.replaceWith((path) => {
|
||||
const resolveTargetArgument = (node) => {
|
||||
const paths = jscodeshift(node)
|
||||
.find(jscodeshift.ObjectProperty, {
|
||||
key: {
|
||||
type: jscodeshift.Identifier.name,
|
||||
name: 'keepPreviousData',
|
||||
},
|
||||
})
|
||||
.paths()
|
||||
|
||||
return paths.length > 0 ? paths[0].parent.node : null
|
||||
}
|
||||
const transformNode = (node, transformedArgument) => {
|
||||
jscodeshift(node.expression)
|
||||
.find(jscodeshift.ObjectProperty, {
|
||||
key: {
|
||||
type: jscodeshift.Identifier.name,
|
||||
name: 'queries',
|
||||
},
|
||||
})
|
||||
.replaceWith(({ node: mutableNode }) => {
|
||||
mutableNode.value.properties = transformedArgument.properties
|
||||
|
||||
return mutableNode
|
||||
})
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
return replacer(path, resolveTargetArgument, transformNode)
|
||||
})
|
||||
|
||||
return { shouldAddKeepPreviousDataImport }
|
||||
}
|
||||
|
||||
module.exports = (file, api) => {
|
||||
const jscodeshift = api.jscodeshift
|
||||
const root = jscodeshift(file.source)
|
||||
const utils = createUtilsObject({ root, jscodeshift })
|
||||
const filePath = file.path
|
||||
|
||||
const dependencies = { jscodeshift, utils, root, filePath }
|
||||
|
||||
const { shouldAddKeepPreviousDataImport } = transformUsages({
|
||||
...dependencies,
|
||||
config: {
|
||||
hooks: ['useInfiniteQuery', 'useQueries', 'useQuery'],
|
||||
queryClientMethods: ['setQueryDefaults'],
|
||||
},
|
||||
})
|
||||
|
||||
if (shouldAddKeepPreviousDataImport) {
|
||||
root
|
||||
.find(jscodeshift.ImportDeclaration, {
|
||||
source: {
|
||||
value: '@tanstack/react-query',
|
||||
},
|
||||
})
|
||||
.replaceWith(({ node: mutableNode }) => {
|
||||
mutableNode.specifiers = [
|
||||
jscodeshift.importSpecifier(
|
||||
jscodeshift.identifier('keepPreviousData'),
|
||||
),
|
||||
...mutableNode.specifiers,
|
||||
]
|
||||
|
||||
return mutableNode
|
||||
})
|
||||
}
|
||||
|
||||
return root.toSource({ quote: 'single', lineTerminator: '\n' })
|
||||
}
|
||||
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
class AlreadyHasPlaceholderDataProperty extends Error {
|
||||
/**
|
||||
* @param {import('jscodeshift').CallExpression} callExpression
|
||||
* @param {string} filePath
|
||||
*/
|
||||
constructor(callExpression, filePath) {
|
||||
super('')
|
||||
this.message = this.buildMessage(callExpression, filePath)
|
||||
this.name = 'AlreadyHasPlaceholderDataProperty'
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').CallExpression} callExpression
|
||||
* @param {string} filePath
|
||||
* @returns {string}
|
||||
*/
|
||||
buildMessage(callExpression, filePath) {
|
||||
const location = callExpression.callee.loc
|
||||
const start = location.start.line
|
||||
const end = location.end.line
|
||||
|
||||
return `The usage in file "${filePath}" at line ${start}:${end} already contains a a "placeholderData" property. Please migrate this usage manually.`
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AlreadyHasPlaceholderDataProperty
|
||||
Generated
Vendored
+58
@@ -0,0 +1,58 @@
|
||||
const createUtilsObject = require('../../utils/index.cjs')
|
||||
const transformFilterAwareUsages = require('./transformers/filter-aware-usage-transformer.cjs')
|
||||
const transformQueryFnAwareUsages = require('./transformers/query-fn-aware-usage-transformer.cjs')
|
||||
|
||||
module.exports = (file, api) => {
|
||||
const jscodeshift = api.jscodeshift
|
||||
const root = jscodeshift(file.source)
|
||||
const utils = createUtilsObject({ root, jscodeshift })
|
||||
const filePath = file.path
|
||||
|
||||
const dependencies = { jscodeshift, utils, root, filePath }
|
||||
|
||||
transformFilterAwareUsages({
|
||||
...dependencies,
|
||||
config: {
|
||||
keyName: 'queryKey',
|
||||
fnName: 'queryFn',
|
||||
queryClientMethods: [
|
||||
'cancelQueries',
|
||||
'getQueriesData',
|
||||
'invalidateQueries',
|
||||
'isFetching',
|
||||
'refetchQueries',
|
||||
'removeQueries',
|
||||
'resetQueries',
|
||||
// 'setQueriesData',
|
||||
],
|
||||
hooks: ['useIsFetching', 'useQuery'],
|
||||
},
|
||||
})
|
||||
|
||||
transformFilterAwareUsages({
|
||||
...dependencies,
|
||||
config: {
|
||||
keyName: 'mutationKey',
|
||||
fnName: 'mutationFn',
|
||||
queryClientMethods: [],
|
||||
hooks: ['useIsMutating', 'useMutation'],
|
||||
},
|
||||
})
|
||||
|
||||
transformQueryFnAwareUsages({
|
||||
...dependencies,
|
||||
config: {
|
||||
keyName: 'queryKey',
|
||||
queryClientMethods: [
|
||||
'ensureQueryData',
|
||||
'fetchQuery',
|
||||
'prefetchQuery',
|
||||
'fetchInfiniteQuery',
|
||||
'prefetchInfiniteQuery',
|
||||
],
|
||||
hooks: [],
|
||||
},
|
||||
})
|
||||
|
||||
return root.toSource({ quote: 'single', lineTerminator: '\n' })
|
||||
}
|
||||
Generated
Vendored
+271
@@ -0,0 +1,271 @@
|
||||
const createV5UtilsObject = require('../utils/index.cjs')
|
||||
const UnknownUsageError = require('../utils/unknown-usage-error.cjs')
|
||||
const createQueryClientTransformer = require('../../../utils/transformers/query-client-transformer.cjs')
|
||||
const createQueryCacheTransformer = require('../../../utils/transformers/query-cache-transformer.cjs')
|
||||
const createUseQueryLikeTransformer = require('../../../utils/transformers/use-query-like-transformer.cjs')
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').api} jscodeshift
|
||||
* @param {Object} utils
|
||||
* @param {import('jscodeshift').Collection} root
|
||||
* @param {string} filePath
|
||||
* @param {{keyName: "mutationKey"|"queryKey", fnName: "mutationFn"|"queryFn", queryClientMethods: ReadonlyArray<string>, hooks: ReadonlyArray<string>}} config
|
||||
*/
|
||||
const transformFilterAwareUsages = ({
|
||||
jscodeshift,
|
||||
utils,
|
||||
root,
|
||||
filePath,
|
||||
config,
|
||||
}) => {
|
||||
const v5Utils = createV5UtilsObject({ jscodeshift, utils })
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').CallExpression} node
|
||||
* @param {"mutationKey"|"queryKey"} keyName
|
||||
* @param {"mutationFn"|"queryFn"} fnName
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const canSkipReplacement = (node, keyName, fnName) => {
|
||||
const callArguments = node.arguments
|
||||
|
||||
const hasKeyOrFnProperty = () =>
|
||||
callArguments[0].properties.some(
|
||||
(property) =>
|
||||
utils.isObjectProperty(property) &&
|
||||
property.key.name !== keyName &&
|
||||
property.key.name !== fnName,
|
||||
)
|
||||
|
||||
/**
|
||||
* This call has at least one argument. If it's an object expression and contains the "queryKey" or "mutationKey"
|
||||
* field, the transformation can be skipped, because it's already matching the expected signature.
|
||||
*/
|
||||
return (
|
||||
callArguments.length > 0 &&
|
||||
utils.isObjectExpression(callArguments[0]) &&
|
||||
hasKeyOrFnProperty()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks whether the given object property is a spread element or a property that's not named
|
||||
* "queryKey" or "mutationKey".
|
||||
*
|
||||
* @param {import('jscodeshift').ObjectProperty} property
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const predicate = (property) => {
|
||||
const isSpreadElement = utils.isSpreadElement(property)
|
||||
const isObjectProperty = utils.isObjectProperty(property)
|
||||
|
||||
return (
|
||||
isSpreadElement ||
|
||||
(isObjectProperty && property.key.name !== config.keyName)
|
||||
)
|
||||
}
|
||||
|
||||
const replacer = (path) => {
|
||||
const node = path.node
|
||||
|
||||
const isFunctionDefinition = (functionArgument) => {
|
||||
if (utils.isFunctionDefinition(functionArgument)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (utils.isIdentifier(functionArgument)) {
|
||||
const binding = v5Utils.getBindingFromScope(
|
||||
path,
|
||||
functionArgument.name,
|
||||
filePath,
|
||||
)
|
||||
|
||||
const isVariableDeclarator = jscodeshift.match(binding, {
|
||||
type: jscodeshift.VariableDeclarator.name,
|
||||
})
|
||||
|
||||
return isVariableDeclarator && utils.isFunctionDefinition(binding.init)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// If the given method/function call matches certain criteria, the node doesn't need to be replaced, this step can be skipped.
|
||||
if (canSkipReplacement(node, config.keyName, config.fnName)) {
|
||||
return node
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we attempt to determine the first parameter of the function call.
|
||||
* If it's a function definition, we can create an object property from it (the mutation fn).
|
||||
*/
|
||||
const firstArgument = node.arguments[0]
|
||||
if (isFunctionDefinition(firstArgument)) {
|
||||
const objectExpression = jscodeshift.objectExpression([
|
||||
jscodeshift.property(
|
||||
'init',
|
||||
jscodeshift.identifier(config.fnName),
|
||||
firstArgument,
|
||||
),
|
||||
])
|
||||
|
||||
const secondArgument = node.arguments[1]
|
||||
|
||||
if (secondArgument) {
|
||||
// If it's an object expression, we can copy the properties from it to the newly created object expression.
|
||||
if (utils.isObjectExpression(secondArgument)) {
|
||||
v5Utils.copyPropertiesFromSource(
|
||||
secondArgument,
|
||||
objectExpression,
|
||||
predicate,
|
||||
)
|
||||
} else {
|
||||
// Otherwise, we simply spread the second argument in the newly created object expression.
|
||||
objectExpression.properties.push(
|
||||
jscodeshift.spreadElement(secondArgument),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return jscodeshift.callExpression(node.original.callee, [
|
||||
objectExpression,
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* If, instead, the first parameter is an array expression or an identifier that references
|
||||
* an array expression, then we create an object property from it (the query or mutation key).
|
||||
*
|
||||
* @type {import('jscodeshift').Property|undefined}
|
||||
*/
|
||||
const keyProperty = v5Utils.transformArgumentToKey(
|
||||
path,
|
||||
node.arguments[0],
|
||||
config.keyName,
|
||||
filePath,
|
||||
)
|
||||
|
||||
/**
|
||||
* The first parameter couldn't be transformed into an object property, so it's time to throw an exception,
|
||||
* it will notify the consumers that they need to rewrite this usage manually.
|
||||
*/
|
||||
if (!keyProperty) {
|
||||
const secondArgument =
|
||||
node.arguments.length > 1 ? node.arguments[1] : null
|
||||
|
||||
if (!secondArgument) {
|
||||
throw new UnknownUsageError(node, filePath)
|
||||
}
|
||||
|
||||
if (utils.isFunctionDefinition(secondArgument)) {
|
||||
const originalArguments = node.arguments
|
||||
const firstArgument = jscodeshift.objectExpression([
|
||||
jscodeshift.property(
|
||||
'init',
|
||||
jscodeshift.identifier(config.keyName),
|
||||
originalArguments[0],
|
||||
),
|
||||
jscodeshift.property(
|
||||
'init',
|
||||
jscodeshift.identifier(config.fnName),
|
||||
secondArgument,
|
||||
),
|
||||
])
|
||||
|
||||
return jscodeshift.callExpression(node.original.callee, [
|
||||
firstArgument,
|
||||
...originalArguments.slice(2),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
const functionArguments = [jscodeshift.objectExpression([keyProperty])]
|
||||
const secondParameter = node.arguments[1]
|
||||
|
||||
if (secondParameter) {
|
||||
const createdObjectExpression = functionArguments[0]
|
||||
|
||||
if (isFunctionDefinition(secondParameter)) {
|
||||
const objectExpression = jscodeshift.objectExpression([
|
||||
jscodeshift.property(
|
||||
'init',
|
||||
jscodeshift.identifier(config.keyName),
|
||||
node.arguments[0],
|
||||
),
|
||||
jscodeshift.property(
|
||||
'init',
|
||||
jscodeshift.identifier(config.fnName),
|
||||
secondParameter,
|
||||
),
|
||||
])
|
||||
|
||||
const thirdArgument = node.arguments[2]
|
||||
|
||||
if (thirdArgument) {
|
||||
// If it's an object expression, we can copy the properties from it to the newly created object expression.
|
||||
if (utils.isObjectExpression(thirdArgument)) {
|
||||
v5Utils.copyPropertiesFromSource(
|
||||
thirdArgument,
|
||||
objectExpression,
|
||||
predicate,
|
||||
)
|
||||
} else {
|
||||
// Otherwise, we simply spread the third argument in the newly created object expression.
|
||||
objectExpression.properties.push(
|
||||
jscodeshift.spreadElement(thirdArgument),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return jscodeshift.callExpression(node.original.callee, [
|
||||
objectExpression,
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* If it has a second argument, and it's an object expression, then we get the properties from it
|
||||
* (except the "queryKey" or "mutationKey" properties), because these arguments will also be moved to the
|
||||
* newly created object expression.
|
||||
*/
|
||||
if (utils.isObjectExpression(secondParameter)) {
|
||||
v5Utils.copyPropertiesFromSource(
|
||||
secondParameter,
|
||||
createdObjectExpression,
|
||||
predicate,
|
||||
)
|
||||
} else {
|
||||
// Otherwise, we simply spread the second parameter in the newly created object expression.
|
||||
createdObjectExpression.properties.push(
|
||||
jscodeshift.spreadElement(secondParameter),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// The rest of the function arguments can be simply pushed to the function arguments object so all will be kept.
|
||||
functionArguments.push(...node.arguments.slice(2))
|
||||
|
||||
return jscodeshift.callExpression(node.original.callee, functionArguments)
|
||||
} catch (error) {
|
||||
utils.warn(
|
||||
error.name === UnknownUsageError.name
|
||||
? error.message
|
||||
: `An unknown error occurred while processing the "${filePath}" file. Please review this file, because the codemod couldn't be applied.`,
|
||||
)
|
||||
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
createQueryClientTransformer({ jscodeshift, utils, root }).execute(
|
||||
config.queryClientMethods,
|
||||
replacer,
|
||||
)
|
||||
|
||||
createUseQueryLikeTransformer({ jscodeshift, utils, root }).execute(
|
||||
config.hooks,
|
||||
replacer,
|
||||
)
|
||||
|
||||
createQueryCacheTransformer({ jscodeshift, utils, root }).execute(replacer)
|
||||
}
|
||||
|
||||
module.exports = transformFilterAwareUsages
|
||||
Generated
Vendored
+185
@@ -0,0 +1,185 @@
|
||||
const createV5UtilsObject = require('../utils/index.cjs')
|
||||
const UnknownUsageError = require('../utils/unknown-usage-error.cjs')
|
||||
const createQueryClientTransformer = require('../../../utils/transformers/query-client-transformer.cjs')
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').api} jscodeshift
|
||||
* @param {Object} utils
|
||||
* @param {import('jscodeshift').Collection} root
|
||||
* @param {string} filePath
|
||||
* @param {{keyName: "mutationKey"|"queryKey", queryClientMethods: ReadonlyArray<string>, hooks: ReadonlyArray<string>}} config
|
||||
*/
|
||||
const transformQueryFnAwareUsages = ({
|
||||
jscodeshift,
|
||||
utils,
|
||||
root,
|
||||
filePath,
|
||||
config,
|
||||
}) => {
|
||||
const v5Utils = createV5UtilsObject({ jscodeshift, utils })
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').CallExpression} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const canSkipReplacement = (node) => {
|
||||
const callArguments = node.arguments
|
||||
|
||||
const hasKeyProperty = () =>
|
||||
callArguments[0].properties.some(
|
||||
(property) =>
|
||||
utils.isObjectProperty(property) &&
|
||||
[config.keyName, 'queryFn'].includes(property.key.name),
|
||||
)
|
||||
|
||||
return (
|
||||
callArguments.length > 0 &&
|
||||
utils.isObjectExpression(callArguments[0]) &&
|
||||
hasKeyProperty()
|
||||
)
|
||||
}
|
||||
|
||||
const predicate = (property) => {
|
||||
const isSpreadElement = utils.isSpreadElement(property)
|
||||
const isObjectProperty = utils.isObjectProperty(property)
|
||||
|
||||
return (
|
||||
isSpreadElement ||
|
||||
(isObjectProperty && property.key.name !== config.keyName)
|
||||
)
|
||||
}
|
||||
|
||||
const transformArgumentToQueryFunction = (path, node) => {
|
||||
const isIdentifier = utils.isIdentifier(node)
|
||||
const isFunctionDefinition = utils.isFunctionDefinition(node)
|
||||
|
||||
if (!isIdentifier && !isFunctionDefinition) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
if (isFunctionDefinition) {
|
||||
return jscodeshift.property(
|
||||
'init',
|
||||
jscodeshift.identifier('queryFn'),
|
||||
node,
|
||||
)
|
||||
}
|
||||
|
||||
const binding = v5Utils.getBindingFromScope(path, node.name, filePath)
|
||||
const initializer = v5Utils.getInitializerByDeclarator(binding)
|
||||
|
||||
if (!utils.isFunctionDefinition(initializer)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return jscodeshift.property(
|
||||
'init',
|
||||
jscodeshift.identifier('queryFn'),
|
||||
binding.id,
|
||||
)
|
||||
}
|
||||
|
||||
const transformArgumentToOptionsObject = (path, node) => {
|
||||
if (!utils.isIdentifier(node)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const binding = v5Utils.getBindingFromScope(path, node.name, filePath)
|
||||
const initializer = v5Utils.getInitializerByDeclarator(binding)
|
||||
|
||||
if (utils.isObjectExpression(initializer)) {
|
||||
return jscodeshift.spreadElement(binding.id)
|
||||
}
|
||||
}
|
||||
|
||||
const replacer = (path) => {
|
||||
const node = path.node
|
||||
|
||||
try {
|
||||
// If the given method/function call matches certain criteria, the node doesn't need to be replaced, this step can be skipped.
|
||||
if (canSkipReplacement(node)) {
|
||||
return node
|
||||
}
|
||||
|
||||
const keyProperty = v5Utils.transformArgumentToKey(
|
||||
path,
|
||||
node.arguments[0],
|
||||
config.keyName,
|
||||
filePath,
|
||||
)
|
||||
|
||||
if (!keyProperty) {
|
||||
throw new UnknownUsageError(node, filePath)
|
||||
}
|
||||
|
||||
const parameters = [jscodeshift.objectExpression([keyProperty])]
|
||||
const createdObjectExpression = parameters[0]
|
||||
const secondParameter = node.arguments[1]
|
||||
|
||||
if (secondParameter) {
|
||||
const queryFnProperty = transformArgumentToQueryFunction(
|
||||
path,
|
||||
secondParameter,
|
||||
)
|
||||
|
||||
if (queryFnProperty) {
|
||||
createdObjectExpression.properties.push(queryFnProperty)
|
||||
|
||||
const thirdParameter = node.arguments[2]
|
||||
|
||||
if (utils.isObjectExpression(thirdParameter)) {
|
||||
v5Utils.copyPropertiesFromSource(
|
||||
thirdParameter,
|
||||
createdObjectExpression,
|
||||
predicate,
|
||||
)
|
||||
} else {
|
||||
createdObjectExpression.properties.push(
|
||||
jscodeshift.spreadElement(thirdParameter),
|
||||
)
|
||||
}
|
||||
|
||||
return jscodeshift.callExpression(node.original.callee, parameters)
|
||||
}
|
||||
|
||||
const optionsProperty = transformArgumentToOptionsObject(
|
||||
path,
|
||||
secondParameter,
|
||||
)
|
||||
|
||||
if (optionsProperty) {
|
||||
createdObjectExpression.properties.push(optionsProperty)
|
||||
|
||||
return jscodeshift.callExpression(node.original.callee, parameters)
|
||||
}
|
||||
|
||||
if (utils.isObjectExpression(secondParameter)) {
|
||||
v5Utils.copyPropertiesFromSource(
|
||||
secondParameter,
|
||||
createdObjectExpression,
|
||||
predicate,
|
||||
)
|
||||
}
|
||||
|
||||
return jscodeshift.callExpression(node.original.callee, parameters)
|
||||
}
|
||||
|
||||
return jscodeshift.callExpression(node.original.callee, parameters)
|
||||
} catch (error) {
|
||||
utils.warn(
|
||||
error.name === UnknownUsageError.name
|
||||
? error.message
|
||||
: `An unknown error occurred while processing the "${filePath}" file. Please review this file, because the codemod couldn't be applied.`,
|
||||
)
|
||||
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
createQueryClientTransformer({ jscodeshift, utils, root }).execute(
|
||||
config.queryClientMethods,
|
||||
replacer,
|
||||
)
|
||||
}
|
||||
|
||||
module.exports = transformQueryFnAwareUsages
|
||||
Generated
Vendored
+123
@@ -0,0 +1,123 @@
|
||||
const UnknownUsageError = require('./unknown-usage-error.cjs')
|
||||
|
||||
module.exports = ({ jscodeshift, utils }) => {
|
||||
/**
|
||||
*
|
||||
* @param {import('jscodeshift').ObjectExpression} source
|
||||
* @param {import('jscodeshift').ObjectExpression} target
|
||||
* @param {(node: import('jscodeshift').Node) => boolean} predicate
|
||||
*/
|
||||
const copyPropertiesFromSource = (source, target, predicate) => {
|
||||
source.properties.forEach((property) => {
|
||||
if (predicate(property)) {
|
||||
target.properties.push(property)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').NodePath} path
|
||||
* @param {string} argumentName
|
||||
* @param {string} filePath
|
||||
* @returns {*}
|
||||
*/
|
||||
const getBindingFromScope = (path, argumentName, filePath) => {
|
||||
/**
|
||||
* If the current scope contains the declaration then we can use the actual one else we attempt to find the
|
||||
* binding from above.
|
||||
*/
|
||||
const scope = path.scope.declares(argumentName)
|
||||
? path.scope
|
||||
: path.scope.lookup(argumentName)
|
||||
|
||||
/**
|
||||
* The declaration couldn't be found for some reason, time to move on. We warn the user it needs to be rewritten
|
||||
* by themselves.
|
||||
*/
|
||||
if (!scope) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const binding = scope.bindings[argumentName]
|
||||
.filter((item) => utils.isIdentifier(item.value))
|
||||
.map((item) => item.parentPath.value)
|
||||
.at(0)
|
||||
|
||||
if (!binding) {
|
||||
throw new UnknownUsageError(path.node, filePath)
|
||||
}
|
||||
|
||||
return binding
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').VariableDeclarator} binding
|
||||
* @returns {import('jscodeshift').Node|undefined}
|
||||
*/
|
||||
const getInitializerByDeclarator = (binding) => {
|
||||
const isVariableDeclaration = jscodeshift.match(binding, {
|
||||
type: jscodeshift.VariableDeclarator.name,
|
||||
})
|
||||
|
||||
if (!isVariableDeclaration) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const isTSAsExpression = jscodeshift.match(binding.init, {
|
||||
type: jscodeshift.TSAsExpression.name,
|
||||
})
|
||||
|
||||
return isTSAsExpression ? binding.init.expression : binding.init
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').Node} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isArrayExpressionVariable = (node) =>
|
||||
jscodeshift.match(node, {
|
||||
type: jscodeshift.VariableDeclarator.name,
|
||||
init: {
|
||||
type: jscodeshift.ArrayExpression.name,
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* @param {import('jscodeshift').NodePath} path
|
||||
* @param {import('jscodeshift').Node} node
|
||||
* @param {"queryKey"|"mutationKey"} keyName
|
||||
* @param {string} filePath
|
||||
* @returns {import('jscodeshift').Property|undefined}
|
||||
*/
|
||||
const transformArgumentToKey = (path, node, keyName, filePath) => {
|
||||
// If the first argument is an identifier we have to infer its type if possible.
|
||||
if (utils.isIdentifier(node)) {
|
||||
const binding = getBindingFromScope(path, node.name, filePath)
|
||||
|
||||
if (isArrayExpressionVariable(binding)) {
|
||||
return jscodeshift.property(
|
||||
'init',
|
||||
jscodeshift.identifier(keyName),
|
||||
jscodeshift.identifier(binding.id.name),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// If the first argument is an array, then it matches the following overload:
|
||||
// methodName(queryKey?: QueryKey, firstObject?: TFirstObject, secondObject?: TSecondObject)
|
||||
if (utils.isArrayExpression(node)) {
|
||||
// Then we create the 'queryKey' property based on it, because it will be passed to the first argument
|
||||
// that should be an object according to the new signature.
|
||||
return jscodeshift.property('init', jscodeshift.identifier(keyName), node)
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
return {
|
||||
copyPropertiesFromSource,
|
||||
getInitializerByDeclarator,
|
||||
getBindingFromScope,
|
||||
transformArgumentToKey,
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
class UnknownUsageError extends Error {
|
||||
/**
|
||||
* @param {import('jscodeshift').CallExpression} callExpression
|
||||
* @param {string} filePath
|
||||
*/
|
||||
constructor(callExpression, filePath) {
|
||||
super('')
|
||||
this.message = this.buildMessage(callExpression, filePath)
|
||||
this.name = 'UnknownUsageError'
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('jscodeshift').CallExpression} callExpression
|
||||
* @param {string} filePath
|
||||
* @returns {string}
|
||||
*/
|
||||
buildMessage(callExpression, filePath) {
|
||||
const location = callExpression.callee.loc
|
||||
const start = location.start.line
|
||||
const end = location.end.line
|
||||
|
||||
return `The usage in file "${filePath}" at line ${start}:${end} could not be transformed into the new syntax. Please do this manually.`
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UnknownUsageError
|
||||
Generated
Vendored
+55
@@ -0,0 +1,55 @@
|
||||
module.exports = (file, api) => {
|
||||
const jscodeshift = api.jscodeshift
|
||||
const root = jscodeshift(file.source)
|
||||
|
||||
const importSpecifiers = root
|
||||
.find(jscodeshift.ImportDeclaration, {
|
||||
source: {
|
||||
value: '@tanstack/react-query',
|
||||
},
|
||||
})
|
||||
.find(jscodeshift.ImportSpecifier, {
|
||||
imported: {
|
||||
name: 'Hydrate',
|
||||
},
|
||||
})
|
||||
|
||||
if (importSpecifiers.length > 0) {
|
||||
const names = {
|
||||
searched: 'Hydrate', // By default, we want to replace the `Hydrate` usages.
|
||||
target: 'HydrationBoundary', // We want to replace them with `HydrationBoundary`.
|
||||
}
|
||||
|
||||
importSpecifiers.replaceWith(({ node: mutableNode }) => {
|
||||
/**
|
||||
* When the local and imported names match which means the code doesn't contain import aliases, we need
|
||||
* to replace only the import specifier.
|
||||
* @type {boolean}
|
||||
*/
|
||||
const usesDefaultImport =
|
||||
mutableNode.local.name === mutableNode.imported.name
|
||||
|
||||
if (!usesDefaultImport) {
|
||||
// If the code uses import aliases, we must re-use the alias.
|
||||
names.searched = mutableNode.local.name
|
||||
names.target = mutableNode.local.name
|
||||
}
|
||||
|
||||
// Override the import specifier.
|
||||
mutableNode.imported.name = 'HydrationBoundary'
|
||||
|
||||
return mutableNode
|
||||
})
|
||||
|
||||
root
|
||||
.findJSXElements(names.searched)
|
||||
.replaceWith(({ node: mutableNode }) => {
|
||||
mutableNode.openingElement.name.name = names.target
|
||||
mutableNode.closingElement.name.name = names.target
|
||||
|
||||
return mutableNode
|
||||
})
|
||||
}
|
||||
|
||||
return root.toSource({ quote: 'single', lineTerminator: '\n' })
|
||||
}
|
||||
Generated
Vendored
+41
@@ -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' })
|
||||
}
|
||||
Reference in New Issue
Block a user