(function FieldMessage({ className, children, justify = 'start', intent = 'idle', ...props }, forwardedRef) {
return (
, 'className'> & {
- children: string;
- },
+ descriptor,
+ }: HTMLAttributes &
+ VariantProps & {
+ children: string;
+ },
ref: React.ForwardedRef,
) {
+ const { elements } = useAppearance().parsedAppearance;
return (
{children}
diff --git a/packages/ui/src/themes/buildTheme.ts b/packages/ui/src/themes/buildTheme.ts
index f42b20343a..96f2517670 100644
--- a/packages/ui/src/themes/buildTheme.ts
+++ b/packages/ui/src/themes/buildTheme.ts
@@ -1,22 +1,43 @@
-import type { PartialTheme, ParsedElements } from '~/contexts/AppearanceContext';
+import type { ParsedElements, PartialTheme } from '~/contexts/AppearanceContext';
+import { DESCRIPTORS } from '~/descriptors';
/**
- * Given a complete theme object minus descriptors, returns a full ParsedElements object with generated descriptors.
+ * Given an object containing partial descriptors, returns a full ParsedElements object with generated descriptors.
*/
export function buildTheme(p: PartialTheme): ParsedElements {
const theme: Partial = {};
+ // Setup base theme containing empty objects for each descriptor.
+ DESCRIPTORS.forEach(descriptor => {
+ theme[descriptor] = {
+ descriptor: `cl-${descriptor}`,
+ className: '',
+ style: {},
+ };
+ });
+
for (const descriptor in p) {
- if (p[descriptor as keyof PartialTheme]) {
- const { className, style } = p[descriptor as keyof PartialTheme]!;
- theme[descriptor as keyof ParsedElements] = {
- descriptor: `cl-${descriptor}`,
- className: className ?? '',
- style: style ?? {},
- };
+ const key = descriptor as keyof ParsedElements;
+
+ if (p[key]) {
+ if (!(key in theme)) {
+ console.warn(`Clerk: Unknown descriptor: ${descriptor}`);
+ continue;
+ }
+
+ // These non-null assertions are okay since we confirmed that theme contains the descriptor above.
+ const { className, style } = p[key]!;
+ if (className) {
+ theme[key]!.className = className;
+ }
+
+ if (style) {
+ theme[key]!.style = style;
+ }
}
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
return theme as ParsedElements;
}
@@ -34,3 +55,20 @@ export function mergeTheme(a: ParsedElements, b: ParsedElements): ParsedElements
return mergedTheme;
}
+
+if (import.meta.vitest) {
+ const { it, expect, describe } = import.meta.vitest;
+
+ describe('buildTheme', () => {
+ it('returns a theme containing all descriptors', () => {
+ const theme = buildTheme({});
+ expect(Object.keys(theme).sort()).toStrictEqual([...DESCRIPTORS].sort());
+
+ for (const [k, v] of Object.entries(theme)) {
+ expect(v.descriptor).toEqual(`cl-${k}`);
+ expect(v.className).toEqual('');
+ expect(v.style).toStrictEqual({});
+ }
+ });
+ });
+}
diff --git a/packages/ui/src/themes/full.ts b/packages/ui/src/themes/full.ts
index 28bb8c96b5..061534c26d 100644
--- a/packages/ui/src/themes/full.ts
+++ b/packages/ui/src/themes/full.ts
@@ -1,8 +1,19 @@
-import { visualStyle as alertVisualStyle } from '~/primitives/alert';
-import { visualStyle as separatorVisualStyle } from '~/primitives/separator';
+import { visualStyle as connections } from '~/common/connections';
+import { visualStyle as alert } from '~/primitives/alert';
+import { visualStyle as button } from '~/primitives/button';
+import { visualStyle as card } from '~/primitives/card';
+import { visualStyle as separator } from '~/primitives/separator';
+import { visualStyle as spinner } from '~/primitives/spinner';
import { buildTheme, mergeTheme } from './buildTheme';
import { layoutTheme } from './layout';
-const visualTheme = buildTheme({ ...alertVisualStyle, ...separatorVisualStyle });
+const visualTheme = buildTheme({
+ ...alert,
+ ...button,
+ ...card,
+ ...connections,
+ ...separator,
+ ...spinner,
+});
export const fullTheme = mergeTheme(layoutTheme, visualTheme);
diff --git a/packages/ui/src/themes/layout.ts b/packages/ui/src/themes/layout.ts
index 5a05cfefae..b76dd7ff05 100644
--- a/packages/ui/src/themes/layout.ts
+++ b/packages/ui/src/themes/layout.ts
@@ -1,6 +1,17 @@
-import { layoutStyle as alertLayoutStyle } from '~/primitives/alert';
-import { layoutStyle as separatorStyle } from '~/primitives/separator';
+import { layoutStyle as connections } from '~/common/connections';
+import { layoutStyle as alert } from '~/primitives/alert';
+import { layoutStyle as button } from '~/primitives/button';
+import { layoutStyle as card } from '~/primitives/card';
+import { layoutStyle as separator } from '~/primitives/separator';
+import { layoutStyle as spinner } from '~/primitives/spinner';
import { buildTheme } from './buildTheme';
-export const layoutTheme = buildTheme({ ...alertLayoutStyle, ...separatorStyle });
+export const layoutTheme = buildTheme({
+ ...alert,
+ ...button,
+ ...card,
+ ...connections,
+ ...separator,
+ ...spinner,
+});
diff --git a/packages/ui/src/utils/dva.ts b/packages/ui/src/utils/dva.ts
new file mode 100644
index 0000000000..e6132664cb
--- /dev/null
+++ b/packages/ui/src/utils/dva.ts
@@ -0,0 +1,230 @@
+/**
+ * Copyright 2022 Joe Bell. All rights reserved.
+ *
+ * This file is licensed to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+import { clsx } from 'clsx';
+
+import { type DescriptorIdentifier, mergeDescriptors, type ParsedElements } from '~/contexts/AppearanceContext';
+
+/* Types
+ ============================================ */
+
+/* clsx
+ ---------------------------------- */
+
+// When compiling with `declaration: true`, many projects experience the dreaded
+// TS2742 error. To combat this, we copy clsx's types manually.
+// Should this project move to JSDoc, this workaround would no longer be needed.
+
+type ClassValue = ClassArray | ClassDictionary | DescriptorIdentifier | number | null | boolean | undefined;
+type ClassDictionary = Record;
+type ClassArray = ClassValue[];
+
+/* Utils
+ ---------------------------------- */
+
+type OmitUndefined = T extends undefined ? never : T;
+type StringToBoolean = T extends 'true' | 'false' ? boolean : T;
+type UnionToIntersection = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
+
+export type VariantProps any> = Omit<
+ OmitUndefined[0]>,
+ 'class' | 'className'
+>;
+
+/* compose
+ ---------------------------------- */
+
+export interface Compose {
+ []>(
+ ...components: [...T]
+ ): (
+ props?: (
+ | UnionToIntersection<
+ {
+ [K in keyof T]: VariantProps;
+ }[number]
+ >
+ | undefined
+ ) &
+ DVAClassProp,
+ ) => string;
+}
+
+/* cx
+ ---------------------------------- */
+
+export interface CX {
+ (...inputs: ClassValue[]): string;
+}
+
+export type CXOptions = Parameters;
+export type CXReturn = ReturnType;
+
+/* dva
+ ============================================ */
+
+type DVAConfigBase = { base?: ClassValue };
+type DVAVariantShape = Record>;
+type DVAVariantSchema = {
+ [Variant in keyof V]?: StringToBoolean | undefined;
+};
+type DVAClassProp = { descriptor?: ClassValue };
+
+export interface DVA {
+ <_ extends "dva's generic parameters are restricted to internal use only.", V>(
+ config: V extends DVAVariantShape
+ ? DVAConfigBase & {
+ variants?: V;
+ compoundVariants?: (V extends DVAVariantShape
+ ? (
+ | DVAVariantSchema
+ | {
+ [Variant in keyof V]?:
+ | StringToBoolean
+ | StringToBoolean[]
+ | undefined;
+ }
+ ) &
+ DVAClassProp
+ : DVAClassProp)[];
+ defaultVariants?: DVAVariantSchema;
+ }
+ : DVAConfigBase & {
+ variants?: never;
+ compoundVariants?: never;
+ defaultVariants?: never;
+ },
+ ): (props?: V extends DVAVariantShape ? DVAVariantSchema & DVAClassProp : DVAClassProp) => string;
+}
+
+/* defineConfig
+ ---------------------------------- */
+
+export interface DefineConfigOptions {
+ hooks?: {
+ /**
+ * @deprecated please use `onComplete`
+ */
+ 'cx:done'?: (className: string) => string;
+ /**
+ * Returns the completed string of concatenated classes/classNames.
+ */
+ onComplete?: (className: string) => string;
+ };
+}
+
+export interface DefineConfig {
+ (options?: DefineConfigOptions): {
+ compose: Compose;
+ cx: CX;
+ dva: DVA;
+ };
+}
+
+/* Exports
+ ============================================ */
+
+const falsyToString = (value: T) => (typeof value === 'boolean' ? `${value}` : value === 0 ? '0' : value);
+
+export const defineConfig: DefineConfig = options => {
+ const cx: CX = (...inputs) => {
+ if (typeof options?.hooks?.['cx:done'] !== 'undefined') {
+ return options?.hooks['cx:done'](clsx(inputs));
+ }
+
+ if (typeof options?.hooks?.onComplete !== 'undefined') {
+ return options?.hooks.onComplete(clsx(inputs));
+ }
+
+ return clsx(inputs);
+ };
+
+ const dva: DVA = config => props => {
+ if (config?.variants == null) {
+ return cx(config?.base, props?.descriptor);
+ }
+
+ const { variants, defaultVariants } = config;
+
+ const getVariantClassNames = Object.keys(variants).map((variant: keyof typeof variants) => {
+ const variantProp = props?.[variant as keyof typeof props];
+ const defaultVariantProp = defaultVariants?.[variant];
+
+ const variantKey = (falsyToString(variantProp) ||
+ falsyToString(defaultVariantProp)) as keyof (typeof variants)[typeof variant];
+
+ return variants[variant][variantKey];
+ });
+
+ const defaultsAndProps = {
+ ...defaultVariants,
+ // remove `undefined` props
+ ...(props &&
+ Object.entries(props).reduce(
+ (acc, [key, value]) => (typeof value === 'undefined' ? acc : { ...acc, [key]: value }),
+ {} as typeof props,
+ )),
+ };
+
+ const getCompoundVariantClassNames = config?.compoundVariants?.reduce(
+ (acc, { descriptor, ...cvConfig }) =>
+ Object.entries(cvConfig).every(([cvKey, cvSelector]) => {
+ const selector = defaultsAndProps[cvKey as keyof typeof defaultsAndProps];
+
+ return Array.isArray(cvSelector) ? cvSelector.includes(selector) : selector === cvSelector;
+ })
+ ? [...acc, descriptor]
+ : acc,
+ [] as ClassValue[],
+ );
+
+ return cx(config?.base, getVariantClassNames, getCompoundVariantClassNames, props?.descriptor);
+ };
+
+ const compose: Compose =
+ (...components) =>
+ props => {
+ const propsWithoutDescriptor = Object.fromEntries(
+ Object.entries(props || {}).filter(([key]) => !['descriptor'].includes(key)),
+ );
+
+ return cx(components.map(component => component(propsWithoutDescriptor)) as ClassValue[], props?.descriptor);
+ };
+
+ return {
+ compose,
+ dva,
+ cx,
+ };
+};
+
+export const { compose, dva, cx } = defineConfig();
+
+export function getDescriptors(elements: ParsedElements, descriptorList: string) {
+ const descriptors = descriptorList.split(' ') as (keyof ParsedElements)[];
+ return descriptors.map(d => {
+ const value = elements[d];
+ if (!value) {
+ console.warn(`Clerk: unable to access style configuration for descriptor: ${d}`);
+ }
+
+ return value;
+ });
+}
+
+export function applyDescriptors(elements: ParsedElements, descriptorList: string) {
+ const descriptors = getDescriptors(elements, descriptorList);
+ return mergeDescriptors(...descriptors);
+}
diff --git a/packages/ui/theme-builder/package-lock.json b/packages/ui/theme-builder/package-lock.json
index 10ac055703..e88492fe10 100644
--- a/packages/ui/theme-builder/package-lock.json
+++ b/packages/ui/theme-builder/package-lock.json
@@ -43,7 +43,6 @@
"version": "0.1.9",
"license": "MIT",
"dependencies": {
- "@clerk/clerk-react": "file:../react",
"@clerk/elements": "file:../elements",
"@clerk/shared": "file:../shared",
"@clerk/types": "file:../types",
@@ -58,6 +57,7 @@
"@clerk/tailwindcss-transformer": "*",
"@testing-library/react": "^16.0.0",
"@vitejs/plugin-react": "^4.3.1",
+ "bundlewatch": "^0.4.0",
"concurrently": "^8.2.2",
"jsdom": "^24.1.1",
"vitest": "^2.0.5"
@@ -65,10 +65,10 @@
},
"../../localizations": {
"name": "@clerk/localizations",
- "version": "3.1.2",
+ "version": "3.3.0",
"license": "MIT",
"dependencies": {
- "@clerk/types": "4.25.0"
+ "@clerk/types": "4.26.0"
},
"devDependencies": {
"@clerk/eslint-config-custom": "*",
@@ -81,13 +81,13 @@
},
"../../nextjs": {
"name": "@clerk/nextjs",
- "version": "5.7.1",
+ "version": "5.7.5",
"license": "MIT",
"dependencies": {
- "@clerk/backend": "1.13.8",
- "@clerk/clerk-react": "5.11.0",
- "@clerk/shared": "2.9.0",
- "@clerk/types": "4.25.0",
+ "@clerk/backend": "1.14.1",
+ "@clerk/clerk-react": "5.12.0",
+ "@clerk/shared": "2.9.2",
+ "@clerk/types": "4.26.0",
"crypto-js": "4.2.0",
"server-only": "0.0.1",
"tslib": "2.4.1"
diff --git a/packages/ui/tsup.config.ts b/packages/ui/tsup.config.ts
index 9d45f79196..aea6489615 100644
--- a/packages/ui/tsup.config.ts
+++ b/packages/ui/tsup.config.ts
@@ -47,7 +47,7 @@ export default defineConfig(overrideOptions => {
'components/sign-up': 'src/components/sign-up/index.tsx',
contexts: 'src/contexts/index.ts',
},
- external: ['react', 'react-dom'],
+ external: ['react', 'react-dom', '@clerk/shared'],
format: ['cjs', 'esm'],
minify: false,
sourcemap: true,
diff --git a/packages/upgrade/CHANGELOG.md b/packages/upgrade/CHANGELOG.md
index d1be9523ef..aa5a9dc2df 100644
--- a/packages/upgrade/CHANGELOG.md
+++ b/packages/upgrade/CHANGELOG.md
@@ -1,5 +1,108 @@
# @clerk/upgrade
+## 1.1.2
+
+### Patch Changes
+
+- Updating the CLI output to match the DX of core-1 to core-2 migration ([#4393](https://github.com/clerk/javascript/pull/4393)) by [@jacekradko](https://github.com/jacekradko)
+
+## 1.1.1
+
+### Patch Changes
+
+- Adding fallback to properly link up transform ([#4386](https://github.com/clerk/javascript/pull/4386)) by [@jacekradko](https://github.com/jacekradko)
+
+## 1.1.0
+
+### Minor Changes
+
+- @clerk/nextjs: Converting auth() and clerkClient() interfaces to be async ([#4366](https://github.com/clerk/javascript/pull/4366)) by [@jacekradko](https://github.com/jacekradko)
+
+ @clerk/upgrade: Adding required codemod for @clerk/nextjs breaking changes
+
+ # Migration guide
+
+ ## `auth()` is now async
+
+ Previously the `auth()` method from `@clerk/nextjs/server` was synchronous.
+
+ ```typescript
+ import { auth } from "@clerk/nextjs/server";
+
+ export function GET() {
+ const { userId } = auth();
+ return new Response(JSON.stringify({ userId }));
+ }
+ ```
+
+ The `auth` method now becomes asynchronous. You will need to make the following changes to the snippet above to make it compatible.
+
+ ```diff
+ - export function GET() {
+ + export async function GET() {
+ - const { userId } = auth();
+ + const { userId } = await auth();
+ return new Response(JSON.stringify({ userId }));
+ }
+ ```
+
+ ## Clerk middleware auth is now async
+
+ ```typescript
+ import { clerkClient, clerkMiddleware } from '@clerk/nextjs/server';
+ import { NextResponse } from 'next/server';
+
+ export default clerkMiddleware(async (auth, request) => {
+ const resolvedAuth = await auth();
+
+ const count = await resolvedAuth.users.getCount();
+
+ if (count) {
+ return NextResponse.redirect(new URL('/new-url', request.url));
+ }
+ });
+
+ export const config = {
+ matcher: [...],
+ };
+ ```
+
+ ## clerkClient() is now async
+
+ Previously the `clerkClient()` method from `@clerk/nextjs/server` was synchronous.
+
+ ```typescript
+ import { clerkClient, clerkMiddleware } from '@clerk/nextjs/server';
+ import { NextResponse } from 'next/server';
+
+ export default clerkMiddleware((auth, request) => {
+ const client = clerkClient();
+
+ const count = await client.users?.getCount();
+
+ if (count) {
+ return NextResponse.redirect(new URL('/new-url', request.url));
+ }
+ });
+
+ export const config = {
+ matcher: [...],
+ };
+ ```
+
+ The method now becomes async. You will need to make the following changes to the snippet above to make it compatible.
+
+ ```diff
+ - export default clerkMiddleware((auth, request) => {
+ - const client = clerkClient();
+ + export default clerkMiddleware(async (auth, request) => {
+ + const client = await clerkClient();
+ const count = await client.users?.getCount();
+
+ if (count) {
+ }
+ ```
+
## 1.0.9
### Patch Changes
diff --git a/packages/upgrade/package.json b/packages/upgrade/package.json
index 0b5b73c8b1..fc93eeef7a 100644
--- a/packages/upgrade/package.json
+++ b/packages/upgrade/package.json
@@ -1,6 +1,11 @@
{
"name": "@clerk/upgrade",
- "version": "1.0.9",
+ "version": "1.1.2",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/clerk/javascript.git",
+ "directory": "packages/upgrade"
+ },
"license": "MIT",
"type": "module",
"main": "dist/cli.js",
@@ -11,16 +16,12 @@
"dist"
],
"scripts": {
- "build": "npm run clean && NODE_ENV=production babel --out-dir=dist src --copy-files",
+ "build": "npm run clean && NODE_ENV=production babel --keep-file-extension --out-dir=dist src --copy-files",
"clean": "del-cli dist/*",
- "dev": "babel --out-dir=dist --watch src --copy-files",
+ "dev": "babel --keep-file-extension --out-dir=dist --watch src --copy-files",
"lint": "eslint src/",
- "lint:publint": "publint"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/clerk/javascript.git",
- "directory": "packages/upgrade"
+ "lint:publint": "publint",
+ "test": "vitest"
},
"babel": {
"presets": [
@@ -28,16 +29,18 @@
]
},
"dependencies": {
- "@inkjs/ui": "^1.0.0",
+ "@inkjs/ui": "^2.0.0",
"@jescalan/ink-markdown": "^2.0.0",
"ejs": "3.1.10",
+ "execa": "9.4.1",
"globby": "^14.0.1",
"gray-matter": "^4.0.3",
"index-to-position": "^0.1.2",
- "ink": "^4.4.1",
+ "ink": "^5.0.1",
"ink-big-text": "^2.0.0",
"ink-gradient": "^3.0.0",
- "ink-link": "^3.0.0",
+ "ink-link": "^4.1.0",
+ "jscodeshift": "^17.0.0",
"marked": "^11.1.1",
"meow": "^11.0.0",
"react": "^18.3.1",
@@ -48,9 +51,10 @@
"devDependencies": {
"@babel/cli": "^7.24.7",
"@babel/preset-react": "^7.24.7",
- "chalk": "^5.3.0",
+ "@types/jscodeshift": "^0.12.0",
"del-cli": "^5.1.0",
- "eslint-config-custom": "*"
+ "eslint-config-custom": "*",
+ "vitest": "^2.1.3"
},
"engines": {
"node": ">=18.17.0"
diff --git a/packages/upgrade/src/app.js b/packages/upgrade/src/app.js
index 332530a2dc..10b9bff442 100644
--- a/packages/upgrade/src/app.js
+++ b/packages/upgrade/src/app.js
@@ -1,37 +1,44 @@
import { MultiSelect, Select, TextInput } from '@inkjs/ui';
-import { Newline, Text } from 'ink';
-import BigText from 'ink-big-text';
-import Gradient from 'ink-gradient';
-import React, { useState } from 'react';
+import { Newline, Text, useApp } from 'ink';
+import React, { useEffect, useState } from 'react';
+import { Header } from './components/Header.js';
+import { Scan } from './components/Scan.js';
+import { SDKWorkflow } from './components/SDKWorkflow.js';
import SDKS from './constants/sdks.js';
-import Scan from './scan.js';
-import getClerkMajorVersion from './util/get-clerk-version.js';
+import { getClerkMajorVersion } from './util/get-clerk-version.js';
import guessFrameworks from './util/guess-framework.js';
-export default function App({
- _fromVersion,
- _toVersion,
- _sdk,
- _dir = false,
- _ignore = [],
- _yolo = false,
- noWarnings = false,
- disableTelemetry = false,
-}) {
- const [yolo, setYolo] = useState(_yolo);
- const [sdks, setSdks] = useState(_sdk ? [_sdk] : []);
+/**
+ * Main CLI application component for handling Clerk SDK upgrades.
+ *
+ * @param {Object} props - The `props` object.
+ * @param {string} [props.dir] - The directory to scan for files.
+ * @param {boolean} [props.disableTelemetry=false] - Flag to disable telemetry.
+ * @param {string} [props.fromVersion] - The current version of the SDK.
+ * @param {Array} [props.ignore] - List of files or directories to ignore.
+ * @param {boolean} [props.noWarnings=false] - Flag to disable warnings.
+ * @param {string} [props.sdk] - The SDK to upgrade.
+ * @param {string} [props.toVersion] - The target version of the SDK.
+ * @param {boolean} [props.yolo=false] - Flag to enable YOLO mode.
+ *
+ * @returns {JSX.Element} The rendered component.
+ */
+export default function App(props) {
+ const { noWarnings = false, disableTelemetry = false } = props;
+ const { exit } = useApp();
+
+ const [yolo, setYolo] = useState(props.yolo ?? false);
+ const [sdks, setSdks] = useState(props.sdk ? [props.sdk] : []);
const [sdkGuesses, setSdkGuesses] = useState([]);
const [sdkGuessConfirmed, setSdkGuessConfirmed] = useState(false);
const [sdkGuessAttempted, setSdkGuessAttempted] = useState(false);
- // See comments below, can be enabled on next major
- // eslint-disable-next-line no-unused-vars
- const [fromVersion, setFromVersion] = useState(_fromVersion);
+ const [fromVersion, setFromVersion] = useState(props.fromVersion);
const [fromVersionGuessAttempted, setFromVersionGuessAttempted] = useState(false);
- // eslint-disable-next-line no-unused-vars
- const [toVersion, setToVersion] = useState(_toVersion);
- const [dir, setDir] = useState(_dir);
- const [ignore, setIgnore] = useState(_ignore);
+
+ const [toVersion, setToVersion] = useState(props.toVersion);
+ const [dir, setDir] = useState(props.dir);
+ const [ignore, setIgnore] = useState(props.ignore ?? []);
const [configComplete, setConfigComplete] = useState(false);
const [configVerified, setConfigVerified] = useState(false);
const [uuid, setUuid] = useState();
@@ -42,20 +49,36 @@ export default function App({
setYolo(false);
}
+ useEffect(() => {
+ if (toVersion === 'core-2') {
+ setFromVersion('core-1');
+ }
+ }, [toVersion]);
+
+ useEffect(() => {
+ if (fromVersion === 'core-1') {
+ setToVersion('core-2');
+ }
+ }, [fromVersion]);
+
+ // Handle the individual SDK upgrade
+ if (!fromVersion && !toVersion && sdks[0] === 'nextjs') {
+ return ;
+ }
+
// We try to guess which SDK they are using
if (isEmpty(sdks) && isEmpty(sdkGuesses) && !sdkGuessAttempted) {
if (!dir) {
return setDir(process.cwd());
}
const { guesses, _uuid } = guessFrameworks(dir, disableTelemetry);
- console.log({ guesses, _uuid });
setUuid(_uuid);
setSdkGuesses(guesses);
setSdkGuessAttempted(true);
}
// We try to guess which version of Clerk they are using
- if (!fromVersion && !fromVersionGuess && !fromVersionGuessAttempted) {
+ if (isEmpty(sdks) && !fromVersion && !fromVersionGuess && !fromVersionGuessAttempted) {
fromVersionGuess = getClerkMajorVersion();
setFromVersionGuessAttempted(true);
}
@@ -72,20 +95,14 @@ export default function App({
return (
<>
-
-
-
+
{/* Welcome to the upgrade script! */}
{!configComplete && (
<>
- Hello friend! We're excited to help you upgrade Clerk
- {fromVersion ? ` from ${fromVersion}` : ''}
- {toVersion ? ` to ${toVersion}` : ''}. Before we get started, a couple questions...
+ Hello friend! We're excited to help you upgrade Clerk modules. Before we get
+ started, a couple questions...
>
@@ -106,7 +123,8 @@ export default function App({
>
) : (
- It looks like you are using the "{sdkGuesses[0].label}" Clerk SDK in your project. Is that right?
+ It looks like you are using the {sdkGuesses[0].label} Clerk SDK in your project. Is that
+ right?
)}
@@ -120,6 +138,8 @@ export default function App({
// if true, we were right so we set the sdk
if (item === 'yes') {
setSdks(sdkGuesses.map(guess => guess.value));
+ } else {
+ setSdkGuesses([]);
}
}}
/>
@@ -186,7 +206,7 @@ export default function App({
/>
>
)} */}
- {!isEmpty(sdks) > 0 && fromVersion && toVersion && !dir && (
+ {!isEmpty(sdks) && fromVersion && toVersion && !dir && (
<>
Where would you like for us to scan for files in your project?
(globstar syntax supported)
@@ -243,12 +263,12 @@ export default function App({
Does this look right?