codemod to migrate chalk => nanocolors

September 26, 2021 ยท View on GitHub

module.exports = function(fileInfo, api, options) { const j = api.jscodeshift const root = j(fileInfo.source)

var usedMethods = new Set()

const chalkImport = root.find(j.ImportDeclaration, {
    source: {
        value: 'chalk'
    }, 
    specifiers: [{
            type: 'ImportDefaultSpecifier'
        }
    ]
}).paths()[0]

if (!chalkImport) return root.toSource()

const chalkId = chalkImport.getValueProperty('specifiers')
    .find(e => e.type === 'ImportDefaultSpecifier')
    .local
    .name



root.find(j.MemberExpression, {
    object: {
        type: 'Identifier', 
        name: chalkId
    }
}).forEach(path => {
    
    var chalkMethod = path.get('property', 'name').value
    usedMethods.add(chalkMethod)
    const innerCall = j.callExpression(j.identifier(chalkMethod), [])
    var outerCall = innerCall

    var currentPath = path
    while(true) {
        const parent = currentPath.parentPath 
        if (parent.getValueProperty('type') === 'MemberExpression') {
            chalkMethod = parent.get('property', 'name').value
            usedMethods.add(chalkMethod)
            const newCall = j.callExpression(j.identifier(chalkMethod), [outerCall])
            outerCall = newCall
            currentPath = parent
        } else {
            break
        }
    }
    
    if (currentPath.parentPath.getValueProperty('type') == 'CallExpression') {
        const callPath = currentPath.parentPath
        innerCall.arguments = callPath.getValueProperty('arguments')
        callPath.replace(outerCall)
    }        
})

if (usedMethods.size > 0) {
    chalkImport.replace(j.importDeclaration(
        Array.from(usedMethods).map(name => j.importSpecifier(j.identifier(name)))
    , j.literal('nanocolors')))
}

return root.toSource()

}