Skip to content

Instantly share code, notes, and snippets.

@seonghyeonkimm
Last active November 28, 2022 12:26
Show Gist options
  • Save seonghyeonkimm/a937115e1401369a7015f69de7906fb1 to your computer and use it in GitHub Desktop.
Save seonghyeonkimm/a937115e1401369a7015f69de7906fb1 to your computer and use it in GitHub Desktop.
useNavigator -> useFlow codemod
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.parser = void 0;
exports.parser = 'tsx';
function transformer(file, api) {
let useNavigatorIdentifier;
let usedUserFlowIdentifiers = [];
const j = api.jscodeshift;
const { statement } = j.template;
const tree = j(file.source);
const useNavigatorImport = tree
.find(j.ImportDeclaration, {
source: { value: '@karrotframe/navigator' },
})
.filter((path) => {
return (
path.value.specifiers.findIndex((specifier) => {
return specifier.type === 'ImportSpecifier' && specifier.imported.name === 'useNavigator';
}) > -1
);
});
if (useNavigatorImport.length === 0) {
return tree.toSource();
}
// Before: import { useNavigator } from '@karrotframe/navigator';
// After: import { useFlow } from '@src/stackflow/useFlow';
tree
.find(j.ImportDeclaration, {
source: { value: '@karrotframe/navigator' },
})
.forEach((navigatorImport) => {
j(navigatorImport).replaceWith(
j.importDeclaration(
[
j.importSpecifier(j.identifier('useFlow')),
// 💡 comment out the line below when you are using default export
// j.importDefaultSpecifier(j.identifier('useFlow')),
],
// 💡 replace with your own useFlow import path
j.stringLiteral('@src/stackflow/useFlow')
)
);
});
const useNavigatorDeclaration = tree.find(j.VariableDeclaration).filter((path) => {
const declaration = path.node.declarations[0];
const isUseNavigator =
declaration.type === 'VariableDeclarator' &&
declaration.init.type === 'CallExpression' &&
declaration.init.callee.type === 'Identifier' &&
declaration.init.callee.name === 'useNavigator';
// get useNavigator callExpression identifier
if (isUseNavigator && declaration.id.type === 'Identifier') {
useNavigatorIdentifier = declaration.id.name;
}
return isUseNavigator;
});
if (useNavigatorIdentifier) {
// Before: navigator.push('routeName');
// After: push('routeName');
tree
.find(j.CallExpression)
.filter((path) => {
return (
path.value.callee.type === 'MemberExpression' &&
path.value.callee.object.type === 'Identifier' &&
path.value.callee.object.name === useNavigatorIdentifier
);
})
.forEach((path) => {
if (path.value.callee.type === 'MemberExpression' && path.value.callee.property.type === 'Identifier') {
usedUserFlowIdentifiers.push(path.value.callee.property.name);
j(path).replaceWith(j.callExpression(j.identifier(path.value.callee.property.name), path.value.arguments));
}
});
// Before: onClick={navigator.push}
// After: onClick={push}
tree
.find(j.JSXExpressionContainer, {
expression: {
type: 'MemberExpression',
object: {
type: 'Identifier',
name: 'navigator',
},
},
})
.forEach((path) => {
if (path.value.expression.type === 'MemberExpression' && path.value.expression.property.type === 'Identifier') {
usedUserFlowIdentifiers.push(path.value.expression.property.name);
j(path).replaceWith(j.jsxExpressionContainer(j.identifier(path.value.expression.property.name)));
}
});
}
// Before: const navigator = useNavigator();
// After: const { push, pop } = useFlow();
const hasNoUseFlowExpression =
tree.find(j.CallExpression).filter((path) => {
return path.node.callee.type === 'Identifier' && path.node.callee.name === 'useFlow';
}).length === 0;
if (hasNoUseFlowExpression) {
const statementTemplate = `const { ${[...new Set(usedUserFlowIdentifiers)].join(',')} } = useFlow()`;
const useFlowExpression = statement([statementTemplate]);
j(useNavigatorDeclaration.at(0).get()).insertBefore(useFlowExpression);
}
// After: remove useNavigator() function usages
useNavigatorDeclaration.remove();
return tree.toSource();
}
exports.default = transformer;
//# sourceMappingURL=karrotframe-to-stackflow.js.map
@seonghyeonkimm
Copy link
Author

seonghyeonkimm commented Nov 28, 2022

위 gist를 download 받고 아래 커맨드 실행하면 jscodeshift가 파일을 수정하기 시작해요. [FOLDER_PATH]를 수정할 path로 바꿔서 실행해주세요.

npx jscodeshift --extensions=tsx,ts,jsx,js --parser=tsx --transform useNavigator-to-useflow.js [FOLDER_PATH]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment