[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EENDTW3EFX4T1TPKZ6P3SF":3,"skill-same:01M6EENDTW3EFX4T1TPKZ6P3SF":53},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":26,"linkOnly":27,"markdownContent":28,"markdownBody":28,"frontMatter":29,"refName":30,"commitSha":31,"skillDirectory":32,"forksCount":33,"repositoryHtmlUrl":34,"repositoryHomepageUrl":35,"ownerHtmlUrl":36,"ownerBlogUrl":6,"ownerDescription":37,"updatedAt":38,"install":39,"resources":52},"01M6EENDTW3EFX4T1TPKZ6P3SF","code-migration",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Fcode-migration\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[23,24,25],"code","migration","code migration","2026-11-10 10:12:30",false,"# Code Migration\n\n## Overview\n\nMigrate codebases between frameworks, languages, and API versions with automated, incremental transformations. This skill handles JavaScript-to-TypeScript conversions, framework upgrades, deprecated API replacements, and ORM migrations while preserving functionality and maintaining backward compatibility.\n\n## Instructions\n\nWhen a user asks to migrate or modernize their code, follow these steps:\n\n### Step 1: Assess the migration scope\n\nAnalyze the codebase to understand:\n- **Source**: Current framework\u002Flanguage version\n- **Target**: Desired framework\u002Flanguage version\n- **Size**: Number of files and lines affected\n- **Dependencies**: Libraries that need updating or replacing\n- **Risk areas**: Custom patches, monkey-patches, or framework internals usage\n\n```bash\n# Count affected files\nfind src -name \"*.js\" | wc -l       # JS→TS migration\ngrep -rl \"React.Component\" src\u002F     # Class→hooks migration\ngrep -rl \"Vue.component\" src\u002F       # Vue 2 patterns\n```\n\n### Step 2: Create a migration plan\n\nBefore changing code, produce a migration plan:\n\n```markdown\n## Migration Plan: JS → TypeScript\n\n**Files to migrate:** 47\n**Estimated effort:** ~2 hours with AI assistance\n\n### Phase 1: Setup (non-breaking)\n- Add tsconfig.json with allowJs: true\n- Install TypeScript and type packages\n- Rename entry point to .ts\n\n### Phase 2: Incremental conversion (file by file)\n- Rename .js → .ts\u002F.tsx\n- Add type annotations to function signatures\n- Replace `any` with proper types\n- Fix type errors\n\n### Phase 3: Strict mode\n- Enable strict: true in tsconfig\n- Resolve remaining `any` types\n- Add return type annotations\n```\n\n### Step 3: Execute the migration file by file\n\nProcess files incrementally, verifying each change:\n\n**JavaScript → TypeScript:**\n\n```typescript\n\u002F\u002F BEFORE: src\u002Futils\u002Fapi.js\nconst fetchUser = async (id) => {\n  const response = await fetch(`\u002Fapi\u002Fusers\u002F${id}`);\n  if (!response.ok) throw new Error('User not found');\n  return response.json();\n};\nmodule.exports = { fetchUser };\n\n\u002F\u002F AFTER: src\u002Futils\u002Fapi.ts\ninterface User {\n  id: string;\n  email: string;\n  name: string;\n  createdAt: string;\n}\n\nexport const fetchUser = async (id: string): Promise\u003CUser> => {\n  const response = await fetch(`\u002Fapi\u002Fusers\u002F${id}`);\n  if (!response.ok) throw new Error('User not found');\n  return response.json() as Promise\u003CUser>;\n};\n```\n\n**React class → hooks:**\n\n```tsx\n\u002F\u002F BEFORE\nclass UserProfile extends React.Component {\n  state = { user: null, loading: true };\n\n  componentDidMount() {\n    fetchUser(this.props.id).then(user =>\n      this.setState({ user, loading: false })\n    );\n  }\n\n  componentDidUpdate(prevProps) {\n    if (prevProps.id !== this.props.id) {\n      this.setState({ loading: true });\n      fetchUser(this.props.id).then(user =>\n        this.setState({ user, loading: false })\n      );\n    }\n  }\n\n  render() {\n    if (this.state.loading) return \u003CSpinner \u002F>;\n    return \u003Cdiv>{this.state.user.name}\u003C\u002Fdiv>;\n  }\n}\n\n\u002F\u002F AFTER\nfunction UserProfile({ id }: { id: string }) {\n  const [user, setUser] = useState\u003CUser | null>(null);\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() => {\n    setLoading(true);\n    fetchUser(id).then(user => {\n      setUser(user);\n      setLoading(false);\n    });\n  }, [id]);\n\n  if (loading) return \u003CSpinner \u002F>;\n  return \u003Cdiv>{user?.name}\u003C\u002Fdiv>;\n}\n```\n\n**Vue 2 → Vue 3 (Options → Composition API):**\n\n```vue\n\u003C!-- BEFORE: Vue 2 Options API -->\n\u003Cscript>\nexport default {\n  data() {\n    return { count: 0, items: [] };\n  },\n  computed: {\n    total() { return this.items.reduce((s, i) => s + i.price, 0); }\n  },\n  mounted() { this.fetchItems(); },\n  methods: {\n    async fetchItems() {\n      this.items = await api.getItems();\n    }\n  }\n};\n\u003C\u002Fscript>\n\n\u003C!-- AFTER: Vue 3 Composition API -->\n\u003Cscript setup lang=\"ts\">\nimport { ref, computed, onMounted } from 'vue';\n\nconst count = ref(0);\nconst items = ref\u003CItem[]>([]);\nconst total = computed(() => items.value.reduce((s, i) => s + i.price, 0));\n\nasync function fetchItems() {\n  items.value = await api.getItems();\n}\n\nonMounted(fetchItems);\n\u003C\u002Fscript>\n```\n\n### Step 4: Update dependencies and configuration\n\n```bash\n# For JS→TS\nnpm install -D typescript @types\u002Fnode @types\u002Freact\nnpx tsc --init\n\n# For Vue 2→3\nnpm install vue@3 @vue\u002Fcompiler-sfc\nnpm uninstall vue-template-compiler\n\n# Update import paths, build config (vite\u002Fwebpack), and aliases\n```\n\n### Step 5: Verify after migration\n\nAfter each file or batch:\n1. Run the type checker: `npx tsc --noEmit`\n2. Run existing tests: `npm test`\n3. Run the linter: `npx eslint src\u002F`\n4. Build the project: `npm run build`\n\nReport any errors and fix them before proceeding.\n\n## Examples\n\n### Example 1: Migrate an Express.js project from JavaScript to TypeScript\n\n**User request:** \"Convert my Express app from JS to TS\"\n\n**Actions taken:**\n1. Analyzed project: 23 JS files, Express 4.18, no existing types\n2. Installed TypeScript, `@types\u002Fexpress`, `@types\u002Fnode`, `ts-node`\n3. Created `tsconfig.json` with `allowJs: true` for incremental migration\n4. Renamed files `.js` → `.ts` starting from leaf modules (utils, models)\n5. Added interfaces for request\u002Fresponse bodies\n6. Converted `require` → `import`, `module.exports` → `export`\n7. Added type annotations to route handlers\n\n**Result:**\n```\nFiles migrated: 23\u002F23\nType errors fixed: 41\nNew interfaces created: 8 (User, Product, Order, ApiError, etc.)\nBuild: ✅ passing\nTests: ✅ 34\u002F34 passing\n```\n\n### Example 2: Update deprecated React Router v5 to v6\n\n**User request:** \"Upgrade our app from React Router 5 to 6\"\n\n**Actions taken:**\n1. Identified 12 files using React Router v5 APIs\n2. Applied transformations:\n   - `\u003CSwitch>` → `\u003CRoutes>`\n   - `\u003CRoute component={X}>` → `\u003CRoute element={\u003CX \u002F>}>`\n   - `useHistory()` → `useNavigate()`\n   - `\u003CRedirect to=\"\u002F\">` → `\u003CNavigate to=\"\u002F\" replace>`\n   - Nested routes restructured with `\u003COutlet \u002F>`\n3. Updated `react-router-dom` to v6.20\n\n**Before\u002FAfter:**\n```tsx\n\u002F\u002F v5\n\u003CSwitch>\n  \u003CRoute exact path=\"\u002F\" component={Home} \u002F>\n  \u003CRoute path=\"\u002Fusers\u002F:id\" component={UserProfile} \u002F>\n  \u003CRedirect to=\"\u002F\" \u002F>\n\u003C\u002FSwitch>\n\n\u002F\u002F v6\n\u003CRoutes>\n  \u003CRoute path=\"\u002F\" element={\u003CHome \u002F>} \u002F>\n  \u003CRoute path=\"\u002Fusers\u002F:id\" element={\u003CUserProfile \u002F>} \u002F>\n  \u003CRoute path=\"*\" element={\u003CNavigate to=\"\u002F\" replace \u002F>} \u002F>\n\u003C\u002FRoutes>\n```\n\n**Result:** 12 files updated, 0 type errors, all 28 tests passing.\n\n## Guidelines\n\n- Always migrate incrementally — one file or module at a time. Never attempt a big-bang rewrite.\n- Create the migration plan before writing any code. Share it with the user for approval on large projects.\n- For JS→TS, start with `strict: false` and `allowJs: true`, then tighten after all files are converted.\n- Preserve existing behavior exactly. Migration should not change functionality.\n- Run tests after every file migration. If tests break, fix before proceeding.\n- When migrating frameworks, check the official migration guide first (e.g., Vue 2→3, Angular upgrade guide).\n- Handle deprecated APIs by checking the library's changelog for the recommended replacement.\n- For large codebases (100+ files), suggest migrating in phases across multiple PRs.\n- Keep `require`\u002F`import` style consistent within each file during migration — don't mix.\n- Add type annotations starting with function signatures, then variables, then generics. Don't over-type.\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002FTerminalSkills\u002Fskills\u002Fcode-migration",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":40,"prompt":50,"zipAvailable":51},[41,44,47],{"tool":42,"command":43},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill code-migration",{"tool":45,"command":46},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill code-migration",{"tool":48,"command":49},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill code-migration","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Fcode-migration\u002FSKILL.md",true,[],[54,68,78,87,93,100],{"skillNo":55,"name":56,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":57,"categories":58,"keywords":64,"publishedAt":26},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[59],{"categoryNo":60,"categoryName":61,"taxonomyType":62,"taxonomyTypeDesc":63},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[65,66,67],"model","model hierarchy","model hierarchy skill",{"skillNo":69,"name":70,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":74,"publishedAt":26},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[73],{"categoryNo":60,"categoryName":61,"taxonomyType":62,"taxonomyTypeDesc":63},[75,76,77],"MCP","zoom","zoom mcp",{"skillNo":79,"name":80,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":83,"publishedAt":26},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[84,85,86,76],"sdk","zoom apps sdk","apps",{"skillNo":88,"name":89,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":92,"publishedAt":26},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[89],{"skillNo":94,"name":95,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":99,"publishedAt":26},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[98],{"categoryNo":60,"categoryName":61,"taxonomyType":62,"taxonomyTypeDesc":63},[95],{"skillNo":101,"name":102,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":105,"publishedAt":26},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[102]]