@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
JavaScript
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;
}
}