Skip to content

Instantly share code, notes, and snippets.

@AugustoCalaca
Created March 16, 2022 00:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AugustoCalaca/63e9be0fee73ed8db437732224eec9c5 to your computer and use it in GitHub Desktop.
Save AugustoCalaca/63e9be0fee73ed8db437732224eec9c5 to your computer and use it in GitHub Desktop.
codemod to convert lodash get to use optional chaining
const lodashGetToOptionalChaining = (file, api) => {
const codeShift = api.jscodeshift;
const root = codeShift(file.source);
const importDeclaration = root.find(codeShift.ImportDeclaration, {
source: {
type: 'Literal',
value: 'lodash/get',
},
});
if (importDeclaration.__paths.length === 0) {
return;
}
importDeclaration.remove();
const getExpression = root
.find(codeShift.CallExpression, {
callee: {
type: 'Identifier',
name: 'get',
},
})
.replaceWith((nodePath) => {
const { node } = nodePath;
const { arguments: args } = node;
const firstArg = args[0];
const secondArg = args[1];
const thirdArg = args[2];
const secondElement = (nodeArgument) => {
if (nodeArgument?.type === 'TemplateLiteral') {
const templateLiteral = codeShift.templateLiteral(secondArg.quasis, secondArg.expressions);
return codeShift.arrayExpression([templateLiteral]);
}
if (nodeArgument?.type === 'Identifier') {
const identifier = codeShift.identifier(nodeArgument.name);
return codeShift.arrayExpression([identifier]);
}
if (nodeArgument.type === 'Literal') {
return codeShift.identifier(nodeArgument.value.split('.').join('?.'));
}
return nodeArgument;
};
const optionalChaining = codeShift.optionalMemberExpression(firstArg, secondElement(secondArg));
if (
!thirdArg ||
(thirdArg?.type === 'Literal' && thirdArg?.value === null) ||
(thirdArg?.type === 'Identifier' && thirdArg?.name === 'undefined')
) {
return optionalChaining;
}
const rightLogicalElement = (nodeArgument) => {
if (nodeArgument.type === 'Literal' && (nodeArgument?.raw === 'true' || nodeArgument?.raw === 'false')) {
return codeShift.callExpression(codeShift.identifier('Boolean'), [optionalChaining]);
}
return nodeArgument;
};
const right = rightLogicalElement(thirdArg);
if (right?.type === 'CallExpression' && right?.callee?.name === 'Boolean') {
return right;
}
const logicalExpression = {
type: 'LogicalExpression',
operator: '??',
left: optionalChaining,
right,
};
return logicalExpression;
});
return getExpression.toSource({ quote: 'single' });
};
export default lodashGetToOptionalChaining;
import get from 'lodash/get';
const obj = {
a: 'a',
b: 'b',
c: 'c',
d: 'd',
e: 'e',
};
const transform = () => {
const fooArray = ['foo'];
const fooObj = { foo: 'foo' };
const field = 'field';
const func = () => 'foo';
return {
a: get(obj, 'a', ''),
b: get(obj, 'b', 'foo'),
c: get(obj, 'c'),
d: get(obj, 'd', null),
e: get(obj, 'e', undefined),
f: get(obj, 'f', true),
g: get(obj, 'g', ['foo']),
h: get(obj, 'h', fooArray),
i: get(obj, 'i', { foo: 'foo' }),
j: get(obj, 'j', fooObj),
k: get(obj, `${field}`),
l: get(obj, 'l.l.l'),
m: get(obj, field),
n: get(obj, 'n', false),
o: get(obj, 'o', func()),
p: get(obj, 'p', func(param)),
};
};
export default transform;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment