Skip to content
Snippets Groups Projects
Unverified Commit 000dfe1b authored by Phoomparin Mano's avatar Phoomparin Mano Committed by GitHub
Browse files

fix(sdk): allow CLI to check React version without installing and allow...

fix(sdk): allow CLI to check React version without installing and allow continuing setup if React is missing (#48491)

* check sdk version via package.json and allow continuing setup

* make package version checks more flexible
parent e423bc34
No related branches found
No related tags found
No related merge requests found
......@@ -74,3 +74,5 @@ export const SETUP_PRO_LICENSE_MESSAGE = `
export const SDK_LEARN_MORE_MESSAGE = `All done! 🚀 Learn more about the SDK here: ${green(
SDK_NPM_LINK,
)}`;
export const CONTINUE_SETUP_ON_WARNING_MESSAGE = `Do you want to continue setup?`;
......@@ -6,12 +6,13 @@ import {
PACKAGE_JSON_NOT_FOUND_MESSAGE,
UNSUPPORTED_REACT_VERSION,
} from "embedding-sdk/cli/constants/messages";
import {
getPackageVersion,
hasPackageJson,
} from "embedding-sdk/cli/utils/get-package-version";
import type { CliStepMethod } from "../types/cli";
import {
getPackageVersions,
hasPackageJson,
} from "../utils/get-package-version";
import { showWarningAndAskToContinue } from "../utils/show-warning-prompt";
const isReactVersionSupported = (version: string) =>
semver.satisfies(semver.coerce(version)!, "18.x");
......@@ -21,49 +22,40 @@ export const checkIfReactProject: CliStepMethod = async state => {
if (!(await hasPackageJson())) {
spinner.fail();
return [
{
type: "error",
message: PACKAGE_JSON_NOT_FOUND_MESSAGE,
},
state,
];
return [{ type: "error", message: PACKAGE_JSON_NOT_FOUND_MESSAGE }, state];
}
const reactDep = await getPackageVersion("react");
const reactDomDep = await getPackageVersion("react-dom");
const dependencyVersions = await getPackageVersions("react", "react-dom");
const reactDep = dependencyVersions["react"];
const reactDomDep = dependencyVersions["react-dom"];
const hasReactDependency = reactDep && reactDomDep;
const hasSupportedReactVersion =
isReactVersionSupported(reactDep) && isReactVersionSupported(reactDomDep);
hasReactDependency &&
isReactVersionSupported(reactDep) &&
isReactVersionSupported(reactDomDep);
let warningMessage: string | null = null;
if (!hasReactDependency) {
spinner.fail();
return [
{
type: "error",
message: MISSING_REACT_DEPENDENCY,
},
state,
];
warningMessage = MISSING_REACT_DEPENDENCY;
} else if (!hasSupportedReactVersion) {
warningMessage = UNSUPPORTED_REACT_VERSION;
}
if (!hasSupportedReactVersion) {
if (warningMessage) {
spinner.fail();
return [
{
type: "error",
message: UNSUPPORTED_REACT_VERSION,
},
state,
];
const shouldContinue = await showWarningAndAskToContinue(warningMessage);
if (!shouldContinue) {
return [{ type: "error", message: "Canceled." }, state];
}
} else {
spinner.succeed(`React ${reactDep} and React DOM ${reactDomDep} found`);
}
spinner.succeed(`React v${reactDep} and React DOM v${reactDomDep} found`);
return [
{
type: "success",
},
state,
];
return [{ type: "success" }, state];
};
import ora from "ora";
import { SDK_PACKAGE_NAME } from "embedding-sdk/cli/constants/config";
import { installSdk } from "embedding-sdk/cli/steps/install-sdk";
import { getPackageVersion } from "embedding-sdk/cli/utils/get-package-version";
import { SDK_PACKAGE_NAME } from "../constants/config";
import { installSdk } from "../steps/install-sdk";
import type { CliStepMethod } from "../types/cli";
import { getPackageVersions } from "../utils/get-package-version";
export const checkSdkAvailable: CliStepMethod = async state => {
const spinner = ora("Checking if SDK is installed…").start();
const sdkVersion = await getPackageVersion(SDK_PACKAGE_NAME);
const projectDependencies = await getPackageVersions(SDK_PACKAGE_NAME);
const sdkVersion = projectDependencies?.[SDK_PACKAGE_NAME];
// skip install step if we already have the SDK installed
if (sdkVersion) {
spinner.succeed(`SDK v${sdkVersion} found`);
return [
{
type: "success",
},
state,
];
return [{ type: "success" }, state];
}
spinner.fail("SDK not found");
......
......@@ -11,28 +11,52 @@ export const hasPackageJson = async () => {
}
};
export const getPackageVersion = async (packageName: string) => {
type DependencyMap = Record<string, string>;
export const getPackageVersions = async (...packageNames: string[]) => {
const versions: Record<string, string> = {};
const projectDeps = await getProjectDependenciesFromPackageJson();
for (const name of packageNames) {
versions[name] =
(await getPackageVersionFromModule(name)) || projectDeps?.[name] || null;
}
return versions;
};
export const readJson = async (path: string) => {
const packageJson = await fs.readFile(path, "utf8");
return JSON.parse(packageJson);
};
export const getProjectDependenciesFromPackageJson =
async (): Promise<DependencyMap | null> => {
try {
const packageJsonPath = path.join(process.cwd(), "package.json");
const packageInfo = await readJson(packageJsonPath);
return packageInfo?.dependencies || null;
} catch (error) {
return null;
}
};
export const getPackageVersionFromModule = async (packageName: string) => {
try {
const packagePath = path.join(
const packageJsonPath = path.join(
process.cwd(),
"node_modules",
packageName,
"package.json",
);
const packageJson = await fs.readFile(packagePath, "utf8");
const packageInfo = JSON.parse(packageJson);
const packageInfo = await readJson(packageJsonPath);
return packageInfo.version || null;
} catch (error) {
if ((error as { code: string }).code === "ENOENT") {
// Package not found
return null;
}
console.error(
`Error checking package version: ${
(error as { message: string }).message
}`,
);
return null;
}
};
......@@ -7,6 +7,7 @@ export const OUTPUT_STYLES = {
version: chalk.hex("#509EE3"),
link: chalk.underline.blueBright,
error: chalk.red.bold,
warning: chalk.yellow.bold,
success: chalk.green.bold,
info: chalk.bold,
};
......@@ -37,6 +38,9 @@ export const printLink = (text: string) => _print(OUTPUT_STYLES.link, text);
export const printError = (message: string) =>
console.error(OUTPUT_STYLES.error(message));
export const printWarning = (message: string) =>
console.warn(OUTPUT_STYLES.warning(message));
export const printSuccess = (message: string) =>
_print(OUTPUT_STYLES.success, message);
......
import { select } from "@inquirer/prompts";
import { CONTINUE_SETUP_ON_WARNING_MESSAGE } from "../constants/messages";
import { printWarning } from "./print";
/**
* @returns {boolean} whether the user wants to continue setup or not
*/
export async function showWarningAndAskToContinue(
message: string,
): Promise<boolean> {
printWarning(message);
return select({
message: CONTINUE_SETUP_ON_WARNING_MESSAGE,
choices: [
{ name: "Continue", value: true },
{ name: "Exit setup", value: false },
],
default: true,
});
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment