src/Helper/source/index.ts
/**
*
* get_source will return path for plugins
* source can be url - relative local path or "superplate"
*
*/
import { DownloadHelper, FSHelper, GitHelper, HumanizeChoices } from "@Helper";
import chalk from "chalk";
import { prompt } from "enquirer";
import ora from "ora";
type SourceResponse = { path?: string; error?: string };
type GetSourceFn = (
source: string | undefined,
branch?: string,
downloadType?: "zip" | "git",
) => Promise<SourceResponse>;
export const get_source: GetSourceFn = async (source, branch, downloadType) => {
/**
* Replace path if default
*/
const sourceSpinner = ora(
`Checking provided source ${chalk.bold`"${source}${
branch ? ` - ${branch}` : ""
}"`}`,
);
sourceSpinner.start();
const sourcePath =
source ?? "https://github.com/pankod/superplate-core-plugins.git";
const isPathExists = await FSHelper.IsPathExists(sourcePath);
if (isPathExists) {
/**
* check local path
*/
sourceSpinner.succeed("Found local source.");
return { path: sourcePath };
} else if (downloadType === "zip") {
sourceSpinner.text = "Checking remote source...";
sourceSpinner.text = "Remote source found. Downloading...";
try {
const cloneResponse = await DownloadHelper.DownloadAndGetPath(
sourcePath,
branch,
);
if (cloneResponse) {
sourceSpinner.succeed("Downloaded remote source successfully.");
return { path: cloneResponse };
}
sourceSpinner.fail("Could not retrieve source repository.");
return { error: "Could not retrieve source repository." };
} catch (e) {
sourceSpinner.fail("Could not retrieve source repository.");
sourceSpinner.text = "Try to use git instead of zip...";
return { error: "Could not retrieve source repository." };
}
} else {
/**
* Check repo exists
* clone and return path if exists
*/
sourceSpinner.text = "Checking remote source...";
const repoStatus = await GitHelper.IsRepoExist(sourcePath);
if (repoStatus.exists === true) {
sourceSpinner.text = "Remote source found. Cloning...";
try {
const cloneResponse = await GitHelper.CloneAndGetPath(
sourcePath,
branch,
);
if (cloneResponse) {
sourceSpinner.succeed("Cloned remote source successfully.");
return { path: cloneResponse };
}
sourceSpinner.fail("Could not retrieve source repository.");
return { error: "Could not retrieve source repository." };
} catch (e) {
`${e}`;
sourceSpinner.fail("Could not retrieve source repository.");
return { error: "Could not retrieve source repository." };
}
} else {
sourceSpinner.fail("Could not found source repository.");
return { error: repoStatus.error };
}
}
};
export const is_multi_type = async (
source: string | undefined,
): Promise<boolean> => {
if (source) {
const checkRootPrompt = await FSHelper.IsPathExists(
`${source}/prompt.js`,
);
return !checkRootPrompt;
}
return false;
};
export const sort_project_types = (
projectTypes: { title: string; value: string }[],
): { title: string; value: string }[] => {
const order: Record<string, number> = {
"refine-vite": 1,
"refine-nextjs": 2,
"refine-remix": 3,
"refine-react": 4,
react: 5,
nextjs: 6,
};
const newProjectTypes = [...projectTypes];
newProjectTypes.sort((a, b) => {
const firstValue = order[a?.value] ?? 1;
const secondValue = order[b?.value] ?? 1;
return firstValue - secondValue;
});
return newProjectTypes;
};
export const get_project_types = async (source: string): Promise<any[]> => {
const projectTypes: any[] = [];
// get project types => react,nextjs,refine ...etc
const files = await FSHelper.ReadDir(source);
for (const file of files) {
const existPromptFile = await FSHelper.IsPathExists(
`${source}/${file}/prompt.js`,
);
if (existPromptFile) {
projectTypes.push({
title: file,
value: file,
});
}
}
return sort_project_types(projectTypes);
};
export const prompt_project_types = async (
source: string,
types: any[],
typeFromArgs?: string,
): Promise<[projectTypePath: string, projectType: string]> => {
let projectType = "";
if (
types.find((p) => p.title === typeFromArgs) &&
typeof typeFromArgs === "string"
) {
projectType = typeFromArgs;
} else {
const filteredWithContains = types.filter((p) =>
p.title.includes(typeFromArgs ?? ""),
);
const response = await prompt({
type: "select",
name: "projectType",
message: "Choose a project template",
choices: (filteredWithContains.length > 0
? filteredWithContains
: types
)
.map((p) => HumanizeChoices.get(p.title, typeFromArgs))
.map((p) => ({
type: "select",
name: p.value,
message: p.title,
hint: p.description,
})),
});
projectType = (response as { projectType: string }).projectType;
}
return [`${source}/${projectType}`, projectType];
};