UNPKG

@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

149 lines (148 loc) 5.1 kB
import { getOrCreateRseConfig } from "@reliverse/cfg"; import path from "@reliverse/pathkit"; import { ensuredir } from "@reliverse/relifso"; import fs from "@reliverse/relifso"; import { relinka } from "@reliverse/relinka"; import { confirmPrompt } from "@reliverse/rempts"; import { homeDir } from "../constants.js"; import { initGithubSDK } from "../utils/instanceGithub.js"; import { askUsernameFrontend } from "../utils/prompts/askUsernameFrontend.js"; import { getOrCreateReliverseMemory } from "../utils/reliverseMemory.js"; export const mrseVerbose = false; export function logVerbose(msg, data) { if (mrseVerbose) { console.log(`Debug - ${msg}`, data ?? ""); } } export function getEnvCacheDir() { return path.join(homeDir, ".reliverse", "envs"); } export async function ensureEnvCacheDir() { const cacheDir = getEnvCacheDir(); await ensuredir(cacheDir); return cacheDir; } export function getEnvCachePath(repo, branch = "main") { const cacheDir = getEnvCacheDir(); const safeRepoName = repo.replace(/[/\\:]/g, "_"); return path.join(cacheDir, `${safeRepoName}_${branch}.env.example`); } export async function downloadFileFromGitHub(repo, filePath, branch = "main", useCache = true, useFresh = false) { if (useCache && !useFresh) { const cachePath = getEnvCachePath(repo, branch); const cacheExists = await fs.pathExists(cachePath); if (cacheExists) { const stats = await fs.stat(cachePath); const fileAge = Date.now() - stats.mtimeMs; const oneDayMs = 24 * 60 * 60 * 1e3; if (fileAge < oneDayMs) { logVerbose(`Using cached .env.example for ${repo} (${branch}).`); return fs.readFile(cachePath, "utf-8"); } } } let repoOwner = ""; let repoName = ""; try { if (repo.includes("/")) { const repoParts = repo.split("/"); if (repoParts.length !== 2) { throw new Error( `Invalid repository format: "${repo}". Expected format: "owner/repo".` ); } repoOwner = repoParts[0]; repoName = repoParts[1]; } const maskInput = await confirmPrompt({ title: "Do you want to mask secret inputs (e.g., GitHub token) in the next steps?", content: "Regardless of your choice, your data will be securely stored on your device." }); const memory = await getOrCreateReliverseMemory(); const { config } = await getOrCreateRseConfig({ projectPath: process.cwd(), isDev: false, overrides: {} }); const frontendUsername = await askUsernameFrontend(config, false); if (!frontendUsername) { throw new Error( "Failed to determine your frontend username. Please try again or notify the CLI developers." ); } 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; if (repoOwner !== githubUsername && repoOwner !== "") { throw new Error( `Private repository ${repo} owned by a different user (${repoOwner}) cannot be accessed. Please use a repository you own or a public repository.` ); } if (!repoOwner || !repoName) { throw new Error( `Invalid repository format: "${repo}". Expected format: "owner/repo".` ); } logVerbose( `${useFresh ? "Fresh mode - d" : "D"}ownloading file from GitHub: ${repoOwner}/${repoName}/${filePath} (branch: ${branch}).` ); const response = await githubInstance.rest.repos.getContent({ owner: repoOwner, repo: repoName, path: filePath, ref: `refs/heads/${branch}`, headers: { authorization: `Bearer ${githubToken}` } }); if (response.status !== 200) { relinka( "warn", `Failed to download ${filePath} from ${repo} (${branch}): ${response.status}` ); return null; } const data = response.data; if (Array.isArray(data) || data.type !== "file" || !data.content || !data.encoding) { relinka( "warn", `Unexpected response format for ${filePath} from ${repo} (${branch}).` ); return null; } if (data.encoding !== "base64") { relinka( "warn", `Unexpected encoding for ${filePath} from ${repo} (${branch}): ${data.encoding}.` ); return null; } const decodedContent = Buffer.from(data.content, "base64").toString( "utf-8" ); if (useCache) { const cachePath = getEnvCachePath(repo, branch); await ensureEnvCacheDir(); await fs.writeFile(cachePath, decodedContent); logVerbose( `Cached .env.example for ${repo} (${branch}) at ${cachePath}.` ); } return decodedContent; } catch (error) { relinka( "warn", `Failed to download ${filePath} from ${repo} (${branch}): ${error instanceof Error ? error.message : String(error)}` ); return null; } }