// Expert in code migrations, version upgrades, breaking change handling, automated codemods, deprecation warnings, and migration testing
| name | migration-assistant |
| description | Expert in code migrations, version upgrades, breaking change handling, automated codemods, deprecation warnings, and migration testing |
| allowed-tools | ["Read","Write","Edit","Bash","Glob","Grep","Task"] |
Expert skill for handling code migrations and version upgrades. Specializes in codemods, breaking change detection, automated migrations, and upgrade strategies.
// React 18 Codemod
// Class component โ Function component with hooks
// Before (React 16/17)
class Counter extends React.Component {
state = { count: 0 }
increment = () => {
this.setState({ count: this.state.count + 1 })
}
render() {
return (
<div>
<p>{this.state.count}</p>
<button onClick={this.increment}>+</button>
</div>
)
}
}
// After (React 18)
function Counter() {
const [count, setCount] = useState(0)
const increment = () => {
setCount(count + 1)
}
return (
<div>
<p>{count}</p>
<button onClick={increment}>+</button>
</div>
)
}
// React 18 Root API
// Before
import ReactDOM from 'react-dom'
ReactDOM.render(<App />, document.getElementById('root'))
// After
import { createRoot } from 'react-dom/client'
const root = createRoot(document.getElementById('root')!)
root.render(<App />)
// codemod/class-to-function.ts
import { Transform } from 'jscodeshift'
const transform: Transform = (file, api) => {
const j = api.jscodeshift
const root = j(file.source)
// Find class components
root.find(j.ClassDeclaration).forEach(path => {
const className = path.value.id.name
// Convert to function component
const functionComponent = j.functionDeclaration(
j.identifier(className),
[],
j.blockStatement([
// Add hooks based on state and lifecycle
// ... transformation logic
])
)
j(path).replaceWith(functionComponent)
})
return root.toSource()
}
export default transform
// Run codemod
// npx jscodeshift -t codemod/class-to-function.ts src/
# React 18 Migration Checklist
## Pre-migration
- [ ] Audit current React version
- [ ] Read React 18 migration guide
- [ ] Update TypeScript to 4.5+
- [ ] Backup codebase
- [ ] Run current tests
## Dependencies
- [ ] Update react to 18.x
- [ ] Update react-dom to 18.x
- [ ] Update @types/react
- [ ] Update testing library
- [ ] Check all dependencies compatibility
## Code Changes
- [ ] Update root rendering API
- [ ] Replace deprecated APIs
- [ ] Add types for new features
- [ ] Update tests
- [ ] Fix TypeScript errors
## Testing
- [ ] Run unit tests
- [ ] Run integration tests
- [ ] Manual QA testing
- [ ] Performance testing
## Post-migration
- [ ] Update documentation
- [ ] Train team on new features
- [ ] Monitor production
- [ ] Clean up deprecated code
// utils/deprecation.ts
export function deprecationWarning(
oldAPI: string,
newAPI: string,
version: string
) {
if (process.env.NODE_ENV === 'development') {
console.warn(
`[Deprecation] ${oldAPI} is deprecated and will be removed in v${version}. ` +
`Please use ${newAPI} instead.`
)
}
}
// Usage
function OldComponent(props: Props) {
deprecationWarning('OldComponent', 'NewComponent', '2.0.0')
return <div>{/* ... */}</div>
}
// scripts/detect-breaking-changes.ts
import { Project } from 'ts-morph'
const project = new Project()
project.addSourceFilesAtPaths('src/**/*.{ts,tsx}')
const breakingChanges = []
// Detect usage of deprecated APIs
project.getSourceFiles().forEach(sourceFile => {
const deprecatedAPIs = sourceFile
.getDescendantsOfKind(ts.SyntaxKind.CallExpression)
.filter(call => {
const name = call.getExpression().getText()
return DEPRECATED_APIS.includes(name)
})
if (deprecatedAPIs.length > 0) {
breakingChanges.push({
file: sourceFile.getFilePath(),
apis: deprecatedAPIs.map(api => api.getText()),
})
}
})
console.log('Breaking changes found:', breakingChanges)
Use when you need to:
Provide: