diff --git a/.changeset/real-boats-promise.md b/.changeset/real-boats-promise.md new file mode 100644 index 00000000000..8769bcdb667 --- /dev/null +++ b/.changeset/real-boats-promise.md @@ -0,0 +1,5 @@ +--- +"@clerk/upgrade": minor +--- + +Enhancing error handling throughout the SDK upgrade flow diff --git a/packages/upgrade/src/app.js b/packages/upgrade/src/app.js index ee181f62fa1..10b9bff4427 100644 --- a/packages/upgrade/src/app.js +++ b/packages/upgrade/src/app.js @@ -63,12 +63,7 @@ export default function App(props) { // Handle the individual SDK upgrade if (!fromVersion && !toVersion && sdks[0] === 'nextjs') { - return ( - - ); + return ; } // We try to guess which SDK they are using diff --git a/packages/upgrade/src/cli.js b/packages/upgrade/src/cli.js index 78ad8769b33..da191342805 100644 --- a/packages/upgrade/src/cli.js +++ b/packages/upgrade/src/cli.js @@ -17,7 +17,6 @@ const cli = meow( --sdk Name of the SDK you're upgrading --dir Directory you'd like to scan for files --ignore Any files or directories you'd like to ignore - --packageManager The package manager you're using (npm, yarn, pnpm) --noWarnings Do not print warnings, only items that must be fixed --disableTelemetry Do not send anonymous usage telemetry @@ -34,7 +33,6 @@ const cli = meow( sdk: { type: 'string', choices: sdks.map(i => i.value) }, dir: { type: 'string' }, ignore: { type: 'string', isMultiple: true }, - packageManager: { type: 'string' }, yolo: { type: 'boolean' }, noWarnings: { type: 'boolean' }, disableTelemetry: { type: 'boolean' }, diff --git a/packages/upgrade/src/components/Codemod.js b/packages/upgrade/src/components/Codemod.js index 9350dd110ad..9498dd800f4 100644 --- a/packages/upgrade/src/components/Codemod.js +++ b/packages/upgrade/src/components/Codemod.js @@ -58,7 +58,7 @@ export function Codemod(props) { )} - {!result && !error && glob && codemod... ${transform}`} />} + {!result && !error && glob && } {result && ( <> diff --git a/packages/upgrade/src/components/SDKWorkflow.js b/packages/upgrade/src/components/SDKWorkflow.js index 4c734e18ca6..bf07c29f5c0 100644 --- a/packages/upgrade/src/components/SDKWorkflow.js +++ b/packages/upgrade/src/components/SDKWorkflow.js @@ -16,13 +16,12 @@ import { UpgradeSDK } from './UpgradeSDK.js'; * * @component * @param {Object} props - * @param {string} props.packageManager - The package manager to use for the upgrade, if needed. * @param {string} props.sdk - The SDK to be upgraded. * * @returns {JSX.Element} The rendered component. */ export function SDKWorkflow(props) { - const { packageManager, sdk } = props; + const { sdk } = props; const [done, setDone] = useState(false); const [runCodemod, setRunCodemod] = useState(false); @@ -59,7 +58,6 @@ export function SDKWorkflow(props) { <> {upgradeComplete ? ( diff --git a/packages/upgrade/src/components/UpgradeSDK.js b/packages/upgrade/src/components/UpgradeSDK.js index 1f52fffbb25..1fc3f3113a7 100644 --- a/packages/upgrade/src/components/UpgradeSDK.js +++ b/packages/upgrade/src/components/UpgradeSDK.js @@ -1,7 +1,7 @@ -import { Spinner, StatusMessage } from '@inkjs/ui'; +import { Select, Spinner, StatusMessage } from '@inkjs/ui'; import { execa } from 'execa'; import { existsSync } from 'fs'; -import { Text } from 'ink'; +import { Newline, Text } from 'ink'; import React, { useEffect, useState } from 'react'; function detectPackageManager() { @@ -11,13 +11,12 @@ function detectPackageManager() { return 'yarn'; } else if (existsSync('pnpm-lock.yaml')) { return 'pnpm'; - } else { - return 'npm'; } + return undefined; } function upgradeCommand(sdk, packageManager) { - switch (packageManager || detectPackageManager()) { + switch (packageManager) { case 'yarn': return `yarn add @clerk/${sdk}@latest`; case 'pnpm': @@ -33,39 +32,85 @@ function upgradeCommand(sdk, packageManager) { * @component * @param {Object} props * @param {Function} props.callback - The callback function to be called after the command execution. - * @param {string} props.packageManager - The package manager used in the project in case we cannot detect it automatically. * @param {string} props.sdk - The SDK for which the upgrade command is run. * @returns {JSX.Element} The rendered component. * * @example * */ -export function UpgradeSDK({ callback, packageManager, sdk }) { +export function UpgradeSDK({ callback, sdk }) { + const [command, setCommand] = useState(); const [error, setError] = useState(); + const [packageManager, setPackageManager] = useState(detectPackageManager()); const [result, setResult] = useState(); - const command = upgradeCommand(sdk, packageManager); - useEffect(() => { + if (!packageManager) { + return; + } + setCommand(previous => { + if (previous) { + return previous; + } + return upgradeCommand(sdk, packageManager); + }); + if (!command) { + return; + } + execa({ shell: true })`${command}` .then(res => { setResult(res); - callback(true); }) .catch(err => { setError(err); + }) + .finally(() => { + callback(true); }); - }, [command]); + }, [command, packageManager, sdk]); return ( <> - {!result && !error && } + {packageManager ? null : ( + <> + + We could not detect the package manager used in your project. Please select the package manager you are + using + +