107 lines
2.7 KiB
JavaScript
107 lines
2.7 KiB
JavaScript
/**
|
|
* Codemod to replace namespaced React calls with named imports
|
|
*
|
|
* Before:
|
|
* import * as Toast from '#/view/com/util/Toast'
|
|
* Toast.show(message, 'xmark')
|
|
*
|
|
* After:
|
|
* import * as Toast from '#/components/Toast'
|
|
* Toast.show(message, {type: 'error'})
|
|
*
|
|
* Usage: jscodeshift -t .jscodeshift/repo/toast-v2.js <file-path>
|
|
* Example: jscodeshift -t .jscodeshift/repo/toast-v2.js src/App.native.tsx
|
|
*/
|
|
|
|
/* eslint-disable */
|
|
|
|
export const parser = 'tsx'
|
|
|
|
const OLD_IMPORT = '#/view/com/util/Toast'
|
|
const NEW_IMPORT = '#/components/Toast'
|
|
|
|
const convertLegacyToastType = type => {
|
|
switch (type) {
|
|
// these ones are fine
|
|
case 'default':
|
|
case 'success':
|
|
case 'error':
|
|
case 'warning':
|
|
case 'info':
|
|
return type
|
|
// legacy ones need conversion
|
|
case 'xmark':
|
|
return 'error'
|
|
case 'exclamation-circle':
|
|
return 'warning'
|
|
case 'check':
|
|
return 'success'
|
|
case 'clipboard-check':
|
|
return 'success'
|
|
case 'circle-exclamation':
|
|
case 'exclamation-circle':
|
|
return 'warning'
|
|
default:
|
|
return 'default'
|
|
}
|
|
}
|
|
|
|
export default function transformer(file, api) {
|
|
const j = api.jscodeshift
|
|
const root = j(file.source)
|
|
|
|
// Find Toast import declarations using the old path
|
|
const toastImports = root
|
|
.find(j.ImportDeclaration)
|
|
.filter(path => path.value.source.value === OLD_IMPORT)
|
|
|
|
if (toastImports.length === 0) {
|
|
return file.source
|
|
}
|
|
|
|
// Update import path
|
|
toastImports.forEach(path => {
|
|
path.value.source.value = NEW_IMPORT
|
|
})
|
|
|
|
// Collect all local names the Toast namespace is bound to
|
|
const toastLocalNames = new Set()
|
|
toastImports.forEach(path => {
|
|
path.value.specifiers.forEach(spec => {
|
|
if (spec.type === 'ImportNamespaceSpecifier') {
|
|
toastLocalNames.add(spec.local.name)
|
|
}
|
|
})
|
|
})
|
|
|
|
// Transform Toast.show(message, type) calls
|
|
root.find(j.CallExpression).forEach(path => {
|
|
const {callee, arguments: args} = path.value
|
|
|
|
// Match <ToastName>.show(...)
|
|
if (
|
|
callee.type !== 'MemberExpression' ||
|
|
callee.object.type !== 'Identifier' ||
|
|
!toastLocalNames.has(callee.object.name) ||
|
|
callee.property.name !== 'show'
|
|
) {
|
|
return
|
|
}
|
|
|
|
// Only transform 2-arg calls where the second arg is a string literal
|
|
if (args.length !== 2) return
|
|
const typeArg = args[1]
|
|
if (typeArg.type !== 'StringLiteral' && typeArg.type !== 'Literal') return
|
|
|
|
const legacyType = typeArg.value
|
|
const newType = convertLegacyToastType(legacyType)
|
|
|
|
// Replace the second argument with an options object: {type: 'newType'}
|
|
args[1] = j.objectExpression([
|
|
j.property('init', j.identifier('type'), j.stringLiteral(newType)),
|
|
])
|
|
})
|
|
|
|
return root.toSource()
|
|
}
|