mirror of
https://github.com/stefanpejcic/openpanel
synced 2025-06-26 18:28:26 +00:00
packages
This commit is contained in:
123
packages/cli/src/components/swizzle-message/index.tsx
Normal file
123
packages/cli/src/components/swizzle-message/index.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
import React from "react";
|
||||
import dedent from "dedent";
|
||||
import { SWIZZLE_CODES } from "@utils/swizzle/codes";
|
||||
import chalk from "chalk";
|
||||
import { markedTerminalRenderer } from "@utils/marked-terminal-renderer";
|
||||
|
||||
type Params = {
|
||||
label: string;
|
||||
files: [targetPath: string, statusCode: string][];
|
||||
message?: string;
|
||||
};
|
||||
|
||||
export const printSwizzleMessage = ({
|
||||
label,
|
||||
files,
|
||||
message = "**`Warning:`** You should use the component where you want to use it.",
|
||||
}: Params) => {
|
||||
const errors = files.filter(([, statusCode]) =>
|
||||
Object.values(SWIZZLE_CODES)
|
||||
.filter((code) => code !== SWIZZLE_CODES.SUCCESS)
|
||||
.includes(statusCode),
|
||||
);
|
||||
|
||||
let status = "success";
|
||||
|
||||
switch (errors.length) {
|
||||
// no errors
|
||||
case 0:
|
||||
status = "success";
|
||||
break;
|
||||
// all errors
|
||||
case files.length:
|
||||
status = "error";
|
||||
break;
|
||||
// some errors
|
||||
default:
|
||||
status = "warning";
|
||||
break;
|
||||
}
|
||||
|
||||
const clearFilePath = (filePath: string) => {
|
||||
const relative = filePath?.replace(process.cwd(), "");
|
||||
|
||||
if (relative?.startsWith("/")) {
|
||||
return relative.slice(1);
|
||||
}
|
||||
if (relative?.startsWith("./")) {
|
||||
return relative.slice(2);
|
||||
}
|
||||
return relative;
|
||||
};
|
||||
|
||||
const printStatusMessage = () => {
|
||||
switch (status) {
|
||||
case "success":
|
||||
console.log(
|
||||
chalk.blueBright(`Successfully swizzled ${chalk.bold(label)}`),
|
||||
);
|
||||
return;
|
||||
case "warning":
|
||||
console.log(
|
||||
chalk.yellowBright(
|
||||
`Swizzle completed with errors for ${chalk.bold(label)}`,
|
||||
),
|
||||
);
|
||||
return;
|
||||
case "error":
|
||||
console.log(chalk.redBright(`Swizzle failed for ${chalk.bold(label)}`));
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const printFiles = () => {
|
||||
const chalks = [];
|
||||
|
||||
chalks.push(chalk.dim(`File${files.length > 1 ? "s" : ""} created:`));
|
||||
chalks.push(
|
||||
files
|
||||
.map(([targetPath, statusCode]) => {
|
||||
if (statusCode === SWIZZLE_CODES.SUCCESS) {
|
||||
return chalk.cyanBright.dim(` - ${clearFilePath(targetPath)}`);
|
||||
}
|
||||
if (statusCode === SWIZZLE_CODES.TARGET_ALREADY_EXISTS) {
|
||||
return chalk.cyanBright.dim(
|
||||
` - ${chalk.yellowBright.bold(
|
||||
"[FILE_ALREADY_EXISTS] ",
|
||||
)}${clearFilePath(targetPath)}`,
|
||||
);
|
||||
}
|
||||
if (statusCode === SWIZZLE_CODES.SOURCE_PATH_NOT_A_FILE) {
|
||||
return chalk.cyanBright.dim(
|
||||
` - ${chalk.yellowBright.bold(
|
||||
"[SOURCE NOT FOUND] ",
|
||||
)}${clearFilePath(targetPath)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return chalk.cyanBright.dim(
|
||||
` - ${chalk.yellowBright.bold(`[${statusCode}]`)}${clearFilePath(
|
||||
targetPath,
|
||||
)}`,
|
||||
);
|
||||
})
|
||||
.join("\n"),
|
||||
);
|
||||
|
||||
console.log(chalks.join("\n"));
|
||||
};
|
||||
|
||||
const printSwizzleMessage = () => {
|
||||
if (message && status !== "error") {
|
||||
console.log(markedTerminalRenderer(dedent(`\n${message}`)));
|
||||
}
|
||||
};
|
||||
|
||||
console.log("");
|
||||
printStatusMessage();
|
||||
printFiles();
|
||||
console.log("");
|
||||
printSwizzleMessage();
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./table";
|
||||
@@ -0,0 +1,48 @@
|
||||
import * as packageUtils from "@utils/package";
|
||||
import { getInstallCommand } from "./table";
|
||||
|
||||
test("Update warning npm command", async () => {
|
||||
const testCases: {
|
||||
output: string;
|
||||
dependencies: string[];
|
||||
scripts: Record<string, string>;
|
||||
}[] = [
|
||||
// have script, have dependency
|
||||
{
|
||||
output: "pnpm run refine update",
|
||||
dependencies: ["@refinedev/cli"],
|
||||
scripts: {
|
||||
refine: "refine",
|
||||
},
|
||||
},
|
||||
// has script, no dependency
|
||||
{
|
||||
output: "pnpm run refine update",
|
||||
dependencies: ["@pankod/refine-cli"],
|
||||
scripts: {
|
||||
refine: "refine",
|
||||
},
|
||||
},
|
||||
// no script, has dependency
|
||||
{
|
||||
output: "npx refine update",
|
||||
dependencies: ["@refinedev/cli"],
|
||||
scripts: {},
|
||||
},
|
||||
// no script, no dependency
|
||||
{
|
||||
output: "npx @refinedev/cli update",
|
||||
dependencies: [],
|
||||
scripts: {},
|
||||
},
|
||||
];
|
||||
|
||||
for (const testCase of testCases) {
|
||||
jest
|
||||
.spyOn(packageUtils, "getDependencies")
|
||||
.mockReturnValue(testCase.dependencies);
|
||||
jest.spyOn(packageUtils, "getScripts").mockReturnValue(testCase.scripts);
|
||||
|
||||
expect(await getInstallCommand()).toBe(testCase.output);
|
||||
}
|
||||
});
|
||||
79
packages/cli/src/components/update-warning-table/table.ts
Normal file
79
packages/cli/src/components/update-warning-table/table.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import type { RefinePackageInstalledVersionData } from "@definitions/package";
|
||||
import chalk from "chalk";
|
||||
import center from "center-align";
|
||||
import { getDependencies, getPreferedPM, getScripts } from "@utils/package";
|
||||
import { getVersionTable } from "@components/version-table";
|
||||
|
||||
export interface UpdateWarningTableParams {
|
||||
data: RefinePackageInstalledVersionData[];
|
||||
}
|
||||
|
||||
export const printUpdateWarningTable = async (
|
||||
params: UpdateWarningTableParams,
|
||||
) => {
|
||||
const data = params?.data;
|
||||
const tableHead = Object.keys(data?.[0] || {});
|
||||
if (!data || !tableHead.length) return;
|
||||
|
||||
const { table, width } = getVersionTable(data);
|
||||
console.log();
|
||||
console.log(center("Update Available", width));
|
||||
console.log();
|
||||
console.log(
|
||||
`- ${chalk.yellow(
|
||||
chalk.bold("Current"),
|
||||
)}: The version of the package that is currently installed`,
|
||||
);
|
||||
console.log(
|
||||
`- ${chalk.yellow(
|
||||
chalk.bold("Wanted"),
|
||||
)}: The maximum version of the package that satisfies the semver range specified in \`package.json\``,
|
||||
);
|
||||
console.log(
|
||||
`- ${chalk.yellow(
|
||||
chalk.bold("Latest"),
|
||||
)}: The latest version of the package available on npm`,
|
||||
);
|
||||
console.log(table);
|
||||
console.log(
|
||||
center(
|
||||
`To update ${chalk.bold("`Refine`")} packages with wanted version`,
|
||||
width,
|
||||
),
|
||||
);
|
||||
console.log(
|
||||
center(
|
||||
` Run the following command: ${chalk.yellowBright(
|
||||
await getInstallCommand(),
|
||||
)}`,
|
||||
width,
|
||||
),
|
||||
);
|
||||
console.log();
|
||||
};
|
||||
|
||||
export const getInstallCommand = async () => {
|
||||
const fallbackCommand = "npx @refinedev/cli update";
|
||||
|
||||
const dependencies = getDependencies();
|
||||
const scriptKeys = Object.keys(getScripts());
|
||||
|
||||
const hasCli = dependencies.includes("@refinedev/cli");
|
||||
const hasScript = scriptKeys.includes("refine");
|
||||
|
||||
if (!hasCli && !hasScript) {
|
||||
return fallbackCommand;
|
||||
}
|
||||
|
||||
const pm = await getPreferedPM();
|
||||
|
||||
if (hasScript) {
|
||||
return `${pm.name} run refine update`;
|
||||
}
|
||||
|
||||
if (hasCli) {
|
||||
return "npx refine update";
|
||||
}
|
||||
|
||||
return fallbackCommand;
|
||||
};
|
||||
151
packages/cli/src/components/version-table/index.ts
Normal file
151
packages/cli/src/components/version-table/index.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
import type { RefinePackageInstalledVersionData } from "@definitions/package";
|
||||
import Table from "cli-table3";
|
||||
import chalk from "chalk";
|
||||
import { removeANSIColors } from "@utils/text";
|
||||
|
||||
const columns = {
|
||||
name: "name",
|
||||
current: "current",
|
||||
wanted: "wanted",
|
||||
latest: "latest",
|
||||
changelog: "changelog",
|
||||
} as const;
|
||||
|
||||
const orderedColumns: (typeof columns)[keyof typeof columns][] = [
|
||||
columns.name,
|
||||
columns.current,
|
||||
columns.wanted,
|
||||
columns.latest,
|
||||
columns.changelog,
|
||||
];
|
||||
|
||||
export const getVersionTable = (
|
||||
packages: RefinePackageInstalledVersionData[] = [],
|
||||
) => {
|
||||
const tableHead = Object.keys(packages?.[0] || {});
|
||||
if (!packages || !tableHead.length) return { table: "", width: 0 };
|
||||
|
||||
const terminalWidth = process.stdout.columns || 80;
|
||||
|
||||
const nameColumnWidth =
|
||||
Math.max(...packages.map((row) => row.name.length)) + 2;
|
||||
const versionColumnWidth = 7 + 2;
|
||||
const bordersWidth = 6;
|
||||
const changelogColumnWidth = Math.min(
|
||||
35,
|
||||
terminalWidth - nameColumnWidth - versionColumnWidth * 3 - bordersWidth,
|
||||
);
|
||||
|
||||
const columnWidths = {
|
||||
name: nameColumnWidth,
|
||||
current: versionColumnWidth,
|
||||
wanted: versionColumnWidth,
|
||||
latest: versionColumnWidth,
|
||||
changelog: changelogColumnWidth,
|
||||
} as const;
|
||||
|
||||
const table = new Table({
|
||||
head: orderedColumns,
|
||||
wordWrap: false,
|
||||
wrapOnWordBoundary: true,
|
||||
colWidths: orderedColumns.map((column) => columnWidths[column]),
|
||||
style: {
|
||||
head: ["blue"],
|
||||
},
|
||||
});
|
||||
|
||||
const ellipsisFromCenter = (text: string, length: number) => {
|
||||
// if text is longer than length, cut it from the center to fit the length (add ellipsis)
|
||||
if (text.length > length) {
|
||||
const fitLength = length - 3;
|
||||
const start = text.slice(0, Math.floor(fitLength / 2));
|
||||
const end = text.slice(-Math.ceil(fitLength / 2));
|
||||
return `${start}...${end}`;
|
||||
}
|
||||
return text;
|
||||
};
|
||||
|
||||
packages.forEach((row) => {
|
||||
table.push(
|
||||
orderedColumns.map((column) => {
|
||||
const columnValue = row[column];
|
||||
if (!columnValue) return columnValue;
|
||||
|
||||
if (column === "latest" || column === "wanted") {
|
||||
const installedVersion = parseVersions(row.current);
|
||||
const latestVersion = parseVersions(columnValue);
|
||||
const colors = getColorsByVersionDiffrence(
|
||||
installedVersion,
|
||||
latestVersion,
|
||||
);
|
||||
const textMajor = chalk[colors.major](latestVersion.major);
|
||||
const textMinor = chalk[colors.minor](latestVersion.minor);
|
||||
const textPatch = chalk[colors.patch](latestVersion.patch);
|
||||
return `${textMajor}.${textMinor}.${textPatch}`;
|
||||
}
|
||||
|
||||
if (column === "changelog") {
|
||||
return chalk.blueBright.underline(columnValue);
|
||||
}
|
||||
|
||||
return columnValue;
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
const tableString = table.toString();
|
||||
const tableWidth = removeANSIColors(
|
||||
tableString.split("\n")?.[0] || "",
|
||||
).length;
|
||||
|
||||
return { table: tableString, width: tableWidth };
|
||||
};
|
||||
|
||||
const parseVersions = (text: string) => {
|
||||
const versions = text.split(".");
|
||||
return {
|
||||
major: versions[0],
|
||||
minor: versions[1],
|
||||
patch: versions[2],
|
||||
};
|
||||
};
|
||||
|
||||
const getColorsByVersionDiffrence = (
|
||||
installedVersion: ReturnType<typeof parseVersions>,
|
||||
nextVersion: ReturnType<typeof parseVersions>,
|
||||
) => {
|
||||
const isMajorDiffrence =
|
||||
installedVersion.major.trim() !== nextVersion.major.trim();
|
||||
|
||||
if (isMajorDiffrence)
|
||||
return {
|
||||
major: "red",
|
||||
minor: "red",
|
||||
patch: "red",
|
||||
} as const;
|
||||
|
||||
const isMinorDiffrence =
|
||||
installedVersion.minor.trim() !== nextVersion.minor.trim();
|
||||
|
||||
if (isMinorDiffrence)
|
||||
return {
|
||||
major: "white",
|
||||
minor: "yellow",
|
||||
patch: "yellow",
|
||||
} as const;
|
||||
|
||||
const isPatchDiffrence =
|
||||
installedVersion.patch.trim() !== nextVersion.patch.trim();
|
||||
if (isPatchDiffrence)
|
||||
return {
|
||||
major: "white",
|
||||
minor: "white",
|
||||
patch: "green",
|
||||
} as const;
|
||||
|
||||
return {
|
||||
major: "white",
|
||||
minor: "white",
|
||||
patch: "white",
|
||||
} as const;
|
||||
};
|
||||
Reference in New Issue
Block a user