@reliverse/rse
Version:
@reliverse/rse is your all-in-one companion for bootstrapping and improving any kind of projects (especially web apps built with frameworks like Next.js) — whether you're kicking off something new or upgrading an existing app. It is also a little AI-power
114 lines (113 loc) • 3.88 kB
JavaScript
import { relinka } from "@reliverse/relinka";
import {
multiselectPrompt,
selectPrompt,
confirmPrompt
} from "@reliverse/rempts";
import { projectsDeleteProject } from "@vercel/sdk/funcs/projectsDeleteProject";
import { projectsGetProjects } from "@vercel/sdk/funcs/projectsGetProjects";
import { withRateLimit } from "../init/use-template/cp-modules/git-deploy-prompts/vercel/vercel-api.js";
import { getPrimaryVercelTeam } from "../init/use-template/cp-modules/git-deploy-prompts/vercel/vercel-team.js";
import {
initVercelSDK
} from "../utils/instanceVercel.js";
import { getMaxHeightSize, sleep } from "../utils/microHelpers.js";
export async function openVercelTools(memory) {
const result = await initVercelSDK(memory, true);
if (!result) {
throw new Error(
"Failed to initialize Vercel SDK. Please notify the @rseevelopers if the problem persists."
);
}
const [token, vercel] = result;
const choice = await selectPrompt({
title: "Vercel Tools",
options: [{ label: "Delete projects", value: "delete-projects" }]
});
const maxItems = getMaxHeightSize().toString();
if (choice === "delete-projects") {
await deleteVercelProjects(vercel, memory, maxItems, token);
}
}
async function getVercelProjects(vercelInstance, maxItems, team) {
const res = await withRateLimit(async () => {
return await projectsGetProjects(vercelInstance, {
teamId: team?.id,
slug: team?.slug,
limit: maxItems
});
});
if (!res.ok) {
throw res.error;
}
return res.value.projects;
}
async function deleteVercelProjects(vercelInstance, memory, maxItems, token) {
if (!token) {
throw new Error("No Vercel token provided");
}
const team = await getPrimaryVercelTeam(vercelInstance, memory);
const allProjects = await getVercelProjects(vercelInstance, maxItems, team);
const protectedNames = [
"relivator",
"rse",
"relidocs",
"versator",
"bleverse",
"mfpiano",
"blefnk"
];
const projects = allProjects.filter(
(p) => !protectedNames.includes(p.name.toLowerCase())
);
const projectNames = new Map(projects.map((p) => [p.id, p.name]));
const info = `If you do not see some projects, restart the CLI with a higher terminal height (current: ${maxItems})`;
const excludedProjectsInfo = protectedNames.length > 0 ? `${info}
Intentionally excluded projects: ${protectedNames.join(", ")}` : info;
const projectsToDelete = await multiselectPrompt({
title: "Delete Vercel projects (ctrl+c to exit)",
content: excludedProjectsInfo,
options: projects.map((project, index) => ({
label: `${index + 1}. ${project.name}`,
value: project.id
}))
});
if (projectsToDelete.length === 0) {
relinka("info", "No projects selected for deletion.");
return;
}
const selectedNames = projectsToDelete.map((id) => projectNames.get(id) ?? id).join(", ");
const confirmed = await confirmPrompt({
title: "Are you sure you want to delete these projects?",
content: selectedNames,
defaultValue: false
});
if (!confirmed) {
relinka("info", "Operation cancelled.");
return;
}
for (const projectId of projectsToDelete) {
const projectName = projectNames.get(projectId) ?? projectId;
try {
relinka("verbose", `Deleting project ${projectName}...`);
const res = await withRateLimit(async () => {
return await projectsDeleteProject(vercelInstance, {
idOrName: projectId,
teamId: team?.id,
slug: team?.slug
});
});
if (!res.ok) {
throw res.error;
}
relinka("success", `Successfully deleted project ${projectName}`);
await sleep(2e3);
} catch (error) {
relinka(
"error",
`Failed to delete project ${projectName}:`,
error instanceof Error ? error.message : String(error)
);
}
}
}