diff --git a/packages/next-codemod/bin/transform.ts b/packages/next-codemod/bin/transform.ts index ff36f5fb1a0c1..af7f71441758a 100644 --- a/packages/next-codemod/bin/transform.ts +++ b/packages/next-codemod/bin/transform.ts @@ -63,7 +63,15 @@ export async function runTransform( type: 'select', name: 'transformer', message: 'Which transform would you like to apply?', - choices: TRANSFORMER_INQUIRER_CHOICES, + choices: TRANSFORMER_INQUIRER_CHOICES.reverse().map( + ({ title, value, version }) => { + return { + title: `(v${version}) ${value}`, + description: title, + value, + } + } + ), }, { onCancel } ) diff --git a/packages/next-codemod/bin/upgrade.ts b/packages/next-codemod/bin/upgrade.ts index 1407736a674fe..a9c9064c16c17 100644 --- a/packages/next-codemod/bin/upgrade.ts +++ b/packages/next-codemod/bin/upgrade.ts @@ -4,10 +4,9 @@ import { execSync } from 'child_process' import path from 'path' import { compareVersions } from 'compare-versions' import chalk from 'chalk' -import { availableCodemods } from '../lib/codemods' import { getPkgManager, installPackages } from '../lib/handle-package' import { runTransform } from './transform' -import { onCancel } from '../lib/utils' +import { onCancel, TRANSFORMER_INQUIRER_CHOICES } from '../lib/utils' type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun' @@ -200,7 +199,7 @@ async function suggestCodemods( initialNextVersion: string, targetNextVersion: string ): Promise { - const initialVersionIndex = availableCodemods.findIndex( + const initialVersionIndex = TRANSFORMER_INQUIRER_CHOICES.findIndex( (versionCodemods) => compareVersions(versionCodemods.version, initialNextVersion) > 0 ) @@ -208,17 +207,18 @@ async function suggestCodemods( return [] } - let targetVersionIndex = availableCodemods.findIndex( + let targetVersionIndex = TRANSFORMER_INQUIRER_CHOICES.findIndex( (versionCodemods) => compareVersions(versionCodemods.version, targetNextVersion) > 0 ) if (targetVersionIndex === -1) { - targetVersionIndex = availableCodemods.length + targetVersionIndex = TRANSFORMER_INQUIRER_CHOICES.length } - const relevantCodemods = availableCodemods - .slice(initialVersionIndex, targetVersionIndex) - .flatMap((versionCodemods) => versionCodemods.codemods) + const relevantCodemods = TRANSFORMER_INQUIRER_CHOICES.slice( + initialVersionIndex, + targetVersionIndex + ) if (relevantCodemods.length === 0) { return [] @@ -229,10 +229,11 @@ async function suggestCodemods( type: 'multiselect', name: 'codemods', message: `\nThe following ${chalk.blue('codemods')} are recommended for your upgrade. Would you like to apply them?`, - choices: relevantCodemods.map((codemod) => { + choices: relevantCodemods.reverse().map(({ title, value, version }) => { return { - title: `${codemod.title} ${chalk.grey(`(${codemod.value})`)}`, - value: codemod.value, + title: `(v${version}) ${value}`, + description: title, + value, selected: true, } }), diff --git a/packages/next-codemod/lib/codemods.ts b/packages/next-codemod/lib/codemods.ts deleted file mode 100644 index 42dd10aef757c..0000000000000 --- a/packages/next-codemod/lib/codemods.ts +++ /dev/null @@ -1,114 +0,0 @@ -type Codemod = { - title: string - value: string -} - -type VersionCodemods = { - version: string - codemods: Codemod[] -} - -export const availableCodemods: VersionCodemods[] = [ - { - version: '6', - codemods: [ - { - title: 'Use withRouter', - value: 'url-to-withrouter', - }, - ], - }, - { - version: '8', - codemods: [ - { - title: 'Transform AMP HOC into page config', - value: 'withamp-to-config', - }, - ], - }, - { - version: '9', - codemods: [ - { - title: 'Transform Anonymous Components into Named Components', - value: 'name-default-component', - }, - ], - }, - { - version: '10', - codemods: [ - { - title: 'Add React Import', - value: 'add-missing-react-import', - }, - ], - }, - { - version: '11', - codemods: [ - { - title: 'Migrate from CRA', - value: 'cra-to-next', - }, - ], - }, - { - version: '13.0', - codemods: [ - { - title: 'Remove Tags From Link Components', - value: 'new-link', - }, - { - title: 'Migrate to the New Image Component', - value: 'next-image-experimental', - }, - { - title: 'Rename Next Image Imports', - value: 'next-image-to-legacy-image', - }, - ], - }, - { - version: '13.2', - codemods: [ - { - title: 'Use Built-in Font', - value: 'built-in-next-font', - }, - ], - }, - { - version: '14.0', - codemods: [ - { - title: 'Migrate ImageResponse imports', - value: 'next-og-import', - }, - { - title: 'Use viewport export', - value: 'metadata-to-viewport-export', - }, - ], - }, - { - version: '15.0.0-canary.153', - codemods: [ - { - title: 'Migrate `geo` and `ip` properties on `NextRequest`', - value: 'next-request-geo-ip', - }, - ], - }, - { - version: '15.0.0-canary.171', - codemods: [ - { - title: 'Transforms usage of Next.js async Request APIs', - value: 'next-async-request-api', - }, - ], - }, -] diff --git a/packages/next-codemod/lib/utils.ts b/packages/next-codemod/lib/utils.ts index 0e8aa3066fbe1..17e4083973286 100644 --- a/packages/next-codemod/lib/utils.ts +++ b/packages/next-codemod/lib/utils.ts @@ -38,71 +38,82 @@ export function onCancel() { export const TRANSFORMER_INQUIRER_CHOICES = [ { title: - 'name-default-component: Transforms anonymous components into named components to make sure they work with Fast Refresh', - value: 'name-default-component', + 'Transform the deprecated automatically injected url property on top level pages to using withRouter', + value: 'url-to-withrouter', + version: '6.0', }, { - title: - 'add-missing-react-import: Transforms files that do not import `React` to include the import in order for the new React JSX transform', - value: 'add-missing-react-import', + title: 'Transforms the withAmp HOC into Next.js 9 page configuration', + value: 'withamp-to-config', + version: '8.0', }, { title: - 'withamp-to-config: Transforms the withAmp HOC into Next.js 9 page configuration', - value: 'withamp-to-config', + 'Transforms anonymous components into named components to make sure they work with Fast Refresh', + value: 'name-default-component', + version: '9.0', }, { title: - 'url-to-withrouter: Transforms the deprecated automatically injected url property on top level pages to using withRouter', - value: 'url-to-withrouter', + 'Transforms files that do not import `React` to include the import in order for the new React JSX transform', + value: 'add-missing-react-import', + version: '10.0', }, { title: - 'cra-to-next (experimental): automatically migrates a Create React App project to Next.js', + 'Automatically migrates a Create React App project to Next.js (experimental)', value: 'cra-to-next', + version: '11.0', }, { - title: 'new-link: Ensures your usage is backwards compatible.', + title: 'Ensures your usage is backwards compatible', value: 'new-link', + version: '13.0', }, { title: - 'next-og-import: Transforms imports from `next/server` to `next/og` for usage of Dynamic OG Image Generation.', - value: 'next-og-import', + 'Dangerously migrates from `next/legacy/image` to the new `next/image` by adding inline styles and removing unused props (experimental)', + value: 'next-image-experimental', + version: '13.0', }, { title: - 'metadata-to-viewport-export: Migrates certain viewport related metadata from the `metadata` export to a new `viewport` export.', - value: 'metadata-to-viewport-export', + 'Safely migrate Next.js 10, 11, 12 applications importing `next/image` to the renamed `next/legacy/image` import in Next.js 13', + value: 'next-image-to-legacy-image', + version: '13.0', }, { - title: - 'next-dynamic-access-named-export: Transforms dynamic imports that return the named export itself to a module like object.', - value: 'next-dynamic-access-named-export', + title: 'Uninstall `@next/font` and transform imports to `next/font`', + value: 'built-in-next-font', + version: '13.2', }, { title: - 'next-image-to-legacy-image: safely migrate Next.js 10, 11, 12 applications importing `next/image` to the renamed `next/legacy/image` import in Next.js 13', - value: 'next-image-to-legacy-image', + 'Migrates certain viewport related metadata from the `metadata` export to a new `viewport` export', + value: 'metadata-to-viewport-export', + version: '14.0', }, { title: - 'next-image-experimental (experimental): dangerously migrates from `next/legacy/image` to the new `next/image` by adding inline styles and removing unused props', - value: 'next-image-experimental', + 'Transforms imports from `next/server` to `next/og` for usage of Dynamic OG Image Generation', + value: 'next-og-import', + version: '14.0', }, { title: - 'built-in-next-font: Uninstall `@next/font` and transform imports to `next/font`', - value: 'built-in-next-font', + 'Transforms dynamic imports that return the named export itself to a module like object', + value: 'next-dynamic-access-named-export', + version: '15.0.0-canary.44', }, { title: - 'next-async-request-api: Transforms usage of Next.js async Request APIs', - value: 'next-async-request-api', + 'Install `@vercel/functions` to replace `geo` and `ip` properties on `NextRequest`', + value: 'next-request-geo-ip', + version: '15.0.0-canary.153', }, { - title: - 'next-request-geo-ip: Install `@vercel/functions` to replace `geo` and `ip` properties on `NextRequest`', - value: 'next-request-geo-ip', + title: 'Transforms usage of Next.js async Request APIs', + value: 'next-async-request-api', + version: '15.0.0-canary.171', }, ]