· 6 years ago · Sep 09, 2019, 04:00 AM
1import { FileInfo, API, Options, CallExpression, StringLiteral, ObjectExpression, ImportDeclaration } from "jscodeshift";
2
3/**
4 * Converts intl.formatMessage({id: 'xpack.infra.metricsExplorer.aggregationSelectLabel', {defaultMessage: ''}}) to
5 * i18n.translate('xpack.infra.metricsExplorer.aggregationSelectLabel', { defaultMessage: '' })
6 **/
7module.exports = function(fileInfo: FileInfo, api: API , options: Options) {
8 const j = api.jscodeshift;
9 const root = j(fileInfo.source);
10 let hasModifications = false;
11 root
12 .find(CallExpression)
13 .forEach(function(path) {
14 const memberExpression = path.node.callee;
15 if (
16 memberExpression.type === 'MemberExpression' &&
17 memberExpression.object.type === 'Identifier' &&
18 memberExpression.object.name === 'intl' &&
19 path.node.arguments &&
20 path.node.arguments.length
21 ) {
22 const paramNode = path.node.arguments[0];
23 if (paramNode.type === 'ObjectExpression') {
24 const properties: {key: string, value: string}[] = []
25 paramNode.properties.forEach(p => {
26 if (p.type == 'ObjectProperty' && p.value.type === 'StringLiteral' && p.key.type === 'Identifier') {
27 properties.push({
28 key: p.key.name,
29 value: p.value.value
30 })
31 }
32 });
33 hasModifications = true;
34 const args: (StringLiteral | ObjectExpression)[] = []
35 properties.forEach(p => {
36 if (p.key === 'id') {
37 args.splice(0, 0, j.stringLiteral(p.value));
38 } else if (p.key && p.value) {
39 let properties = [j.objectProperty(j.stringLiteral(p.key), j.stringLiteral(p.value))];
40 const param2Node = path.node.arguments[1];
41 if (param2Node && param2Node.type === 'ObjectExpression') {
42 // Handles interpolation variables.
43 properties.push(j.objectProperty(
44 j.stringLiteral('values'), param2Node
45 ))
46 }
47 args.push(j.objectExpression(properties));
48 }
49 });
50
51 const newExpression = j.callExpression(
52 j.memberExpression(
53 j.identifier('i18n'),
54 j.identifier('translate')
55 ),
56 args
57 );
58 j(path).replaceWith(newExpression);
59 }
60 }
61 });
62
63 // Make sure there's an import of `i18n` from `@kbn/i18n`
64 const ensureImports = () => {
65 const importDeclarations = root.find(ImportDeclaration);
66 const hasImport = importDeclarations.filter(p => p.node.source.value === '@kbn/i18n').length > 0;
67 if (!hasImport) {
68 const i18nImport = j.importDeclaration(
69 [j.importSpecifier(j.identifier('i18n'))],
70 j.literal('@kbn/i18n')
71 );
72 const imports = importDeclarations.paths();
73 j(imports[imports.length-1]).insertAfter(i18nImport)
74 }
75 }
76
77 // Get rid of `injectI18n` HOC and intl prop
78 const removeHOC = () => {
79 root
80 .find(CallExpression)
81 .forEach((p) => {
82 if (
83 p.node.callee.type === 'Identifier' &&
84 p.node.callee.name === 'injectI18n'
85 ) {
86 const newComp = p.node.arguments[0];
87
88 if (newComp.type === 'ArrowFunctionExpression' || newComp.type === 'FunctionExpression') {
89 const props = newComp.params[0];
90 if (props.type === 'ObjectPattern') {
91 props.properties = props.properties.filter((p) => {
92 if (p.type === 'ObjectProperty' && p.key.type === 'Identifier' && p.key.name === 'intl') {
93 return false
94 }
95 return true
96 });
97 }
98 }
99 j(p).replaceWith(newComp);
100 }
101 })
102 }
103
104 if (hasModifications) {
105 removeHOC()
106 ensureImports()
107 }
108 return root.toSource()
109 };