UNPKG

@reliverse/rse-sdk

Version:

@reliverse/rse-sdk allows you to create new plugins for @reliverse/rse CLI, interact with reliverse.org, and even extend your own CLI functionality (you may also try @reliverse/dler-sdk for this case).

493 lines (492 loc) 13.7 kB
import { relinka } from "@reliverse/relinka"; import { selectPrompt } from "@reliverse/rempts"; import { decide } from "../../../../utils/decideHelper.js"; import { initGithubSDK } from "../../../../utils/instanceGithub.js"; import { initVercelSDK } from "../../../../utils/instanceVercel.js"; import { getOrCreateReliverseMemory } from "../../../../utils/reliverseMemory.js"; import { deployProject } from "./deploy.js"; import { handleGithubRepo, initGitDir } from "./git.js"; import { isSpecialDomain } from "./helpers/domainHelpers.js"; import { ensureDbInitialized } from "./helpers/handlePkgJsonScripts.js"; import { promptForDomain } from "./helpers/promptForDomain.js"; import { checkVercelDeployment } from "./vercel/vercel-check.js"; import { getVercelProjectDomain } from "./vercel/vercel-domain.js"; export async function handleGitInit(cwd, isDev, projectName, projectPath, config, isTemplateDownload) { relinka("verbose", "[B] initGitDir"); const gitInitialized = await initGitDir({ cwd, isDev, projectName, projectPath, allowReInit: true, createCommit: true, config, isTemplateDownload }); if (!gitInitialized) { relinka("error", "Failed to initialize git. Stopping git/deploy process."); return false; } return true; } export async function configureGithubRepo(githubInstance, githubToken, skipPrompts, cwd, isDev, memory, config, projectName, projectPath, maskInput, selectedTemplate, isTemplateDownload, githubUsername) { if (!memory) { relinka("error", "Failed to read rsey"); return { success: false }; } const repoCreated = await handleGithubRepo({ skipPrompts, cwd, isDev, memory, config, projectName, projectPath, maskInput, selectedTemplate, isTemplateDownload, githubInstance, githubToken, githubUsername }); if (!repoCreated) { relinka( "error", "Failed to create GitHub repository. Stopping deploy process." ); return { success: false }; } const updatedMemory = await getOrCreateReliverseMemory(); if (!updatedMemory?.githubKey) { relinka("error", "GitHub token still not found after setup"); return { success: false }; } return { success: true }; } export async function promptGitDeploy({ isLib, projectName, config, projectPath, primaryDomain: initialPrimaryDomain, hasDbPush, shouldRunDbPush, shouldInstallDeps, isDev, memory, cwd, maskInput, skipPrompts, selectedTemplate, isTemplateDownload, frontendUsername }) { let allDomains = []; let primaryDomain = initialPrimaryDomain; try { const useGithubRepo = await decide( config, "gitBehavior", "Do you want to create/connect a GitHub repository for this project?", "This will allow you to store your code on GitHub, collaborate with others, deploy, and track changes automatically.", true, skipPrompts ); if (!useGithubRepo) { const initLocalGit = await decide( config, "gitBehavior", "Do you want to initialize git locally? (recommended)", "This allows you to track changes, create commits, and work with branches.", true, skipPrompts ); if (!initLocalGit) { relinka("info", "Skipping git initialization entirely."); return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } if (!await handleGitInit( cwd, isDev, projectName, projectPath, config, isTemplateDownload )) { relinka("error", "Failed to initialize git locally."); return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } relinka("info", "Skipping GitHub repository creation step."); return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } const githubResult = await initGithubSDK( memory, frontendUsername, maskInput ); if (!githubResult) { throw new Error( "Failed to initialize Octokit SDK. Please notify CLI developers if the problem persists." ); } const [githubToken, githubInstance, githubUsername] = githubResult; let githubRetryCount = 0; let skipGithub = false; let githubData = { success: false }; while (githubRetryCount < 3 && !skipGithub) { try { githubData = await configureGithubRepo( githubInstance, githubToken, skipPrompts, cwd, isDev, memory, config, projectName, projectPath, maskInput, selectedTemplate, isTemplateDownload, githubUsername ); if (githubData.success) break; githubRetryCount++; } catch (error) { githubRetryCount++; relinka( "error", "GitHub setup encountered an error:", error instanceof Error ? error.message : String(error) ); } if (githubRetryCount < 3 && !skipPrompts) { const userAction = await selectPrompt({ title: "GitHub setup failed. What would you like to do?", options: [ { label: "Try again", value: "retry", hint: "Attempt GitHub setup again" }, { label: "Continue without GitHub", value: "skip", hint: "Proceed without GitHub" }, { label: "Close the application", value: "close", hint: "Exit setup" } ] }); if (userAction === "retry") continue; else if (userAction === "skip") { skipGithub = true; if (!await handleGitInit( cwd, isDev, projectName, projectPath, config, false )) { relinka( "error", "Failed to initialize local git after skipping GitHub." ); return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } } else { relinka("info", "Setup cancelled by user."); return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } } } if (githubRetryCount === 3 && !skipGithub && !skipPrompts) { const userAction = await selectPrompt({ title: "GitHub setup failed after 3 attempts. What do you want to do?", options: [ { label: "Continue without GitHub", value: "skip", hint: "Proceed using local git" }, { label: "Close the application", value: "close", hint: "Exit setup" } ] }); if (userAction === "skip") { if (!await handleGitInit( cwd, isDev, projectName, projectPath, config, false )) { relinka("error", "Failed to initialize local git after final skip."); return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } skipGithub = true; } else { relinka("info", "Setup cancelled by user."); return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } } if (skipGithub) { relinka( "success", "Git initialized locally! GitHub & deployments can be set up later by running the CLI inside your project folder." ); return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } if (!githubData.success) { relinka( "error", "GitHub setup did not complete successfully after multiple attempts." ); return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } if (isLib) { return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } let alreadyDeployed = false; try { alreadyDeployed = await checkVercelDeployment( projectName, githubUsername, githubToken, githubInstance ); } catch (vercelError) { relinka( "warn", "Could not check existing Vercel deployments. Assuming none:", vercelError instanceof Error ? vercelError.message : String(vercelError) ); } if (alreadyDeployed) { relinka( "success", "Project already has Vercel deployments configured on GitHub.", "New deployments are triggered automatically on new commits." ); return { deployService: "vercel", primaryDomain, isDeployed: true, allDomains }; } const shouldDeployProject = await decide( config, "deployBehavior", "Do you want to deploy this project?", "This will set up deployment configuration, environment variables, and deploy to your chosen platform.", true, skipPrompts ); if (!shouldDeployProject) { relinka("info", "Skipping project deployment."); return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } const dbStatus = await ensureDbInitialized( hasDbPush, shouldRunDbPush, shouldInstallDeps, projectPath ); if (dbStatus === "cancel") { relinka("info", "Deployment cancelled during database initialization."); return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } const vercelResult = await initVercelSDK(memory, maskInput); if (!vercelResult) { throw new Error( "Failed to initialize Vercel SDK. Please notify CLI developers if the problem persists." ); } const [vercelToken, vercelInstance] = vercelResult; if (!alreadyDeployed) { if (skipPrompts && config.projectDomain && !isSpecialDomain(config.projectDomain)) { primaryDomain = config.projectDomain.replace(/^https?:\/\//, ""); } else { primaryDomain = await promptForDomain(projectName); } } else { const domainResult = await getVercelProjectDomain( vercelInstance, vercelToken, projectName ); primaryDomain = domainResult.primary; allDomains = domainResult.domains; } const deploymentCheck = await checkVercelDeployment( projectName, githubUsername, githubToken, githubInstance ); if (deploymentCheck) { relinka("info", `Project ${projectName} is already deployed to Vercel`); return { deployService: "vercel", primaryDomain, isDeployed: true, allDomains: [primaryDomain] }; } let deployRetryCount = 0; while (deployRetryCount < 3) { try { const deployResult = await deployProject( githubInstance, vercelInstance, vercelToken, githubToken, skipPrompts, projectName, config, projectPath, primaryDomain, memory, "new", githubUsername ); if (deployResult.deployService !== "none") { relinka( "success", "Git, GitHub, and deployment completed successfully! \u{1F389}" ); return deployResult; } deployRetryCount++; if (deployRetryCount < 3 && !skipPrompts) { const retryChoice = await decide( config, "deployBehavior", "Deployment failed. Retry?", "This may help if the error was temporary.", true, skipPrompts ); if (!retryChoice) break; } else { break; } } catch (error) { deployRetryCount++; relinka( "error", "Deployment failed:", error instanceof Error ? error.message : String(error) ); if (deployRetryCount < 3 && !skipPrompts) { const retryChoice = await decide( config, "deployBehavior", "Retry deployment?", "This may help if the error was temporary.", true, skipPrompts ); if (!retryChoice) break; } else { break; } } } if (deployRetryCount === 3) { relinka("error", "Deployment failed after 3 attempts."); } return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } catch (globalError) { if (globalError instanceof Error) { relinka("error", `Process failed: ${globalError.message}`); if (globalError.stack) { relinka("verbose", "Stack trace:", globalError.stack); } } else { relinka("error", "An unexpected error occurred:", String(globalError)); } return { deployService: "none", primaryDomain, isDeployed: false, allDomains }; } }