UNPKG

@tanstack/react-query

Version:

Hooks for managing, caching and syncing asynchronous and remote data in React

245 lines (206 loc) 6.98 kB
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' }) }