UNPKG

@reliverse/rse-sdk

Version:

@reliverse/rse-sdk without cli. @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).

181 lines (180 loc) 6.15 kB
import path from "@reliverse/pathkit"; import { ensuredir } from "@reliverse/relifso"; import fs from "@reliverse/relifso"; import { setHiddenAttribute } from "@reliverse/relifso"; import { relinka } from "@reliverse/relinka"; import { confirmPrompt } from "@reliverse/rempts"; import { simpleGit } from "simple-git"; import tar from "tar-stream"; import { promisify } from "util"; import { gzip } from "zlib"; import { cliConfigJsonc, cliConfigJsoncTmp, cliHomeTmp } from "../../../../constants.js"; const gzipAsync = promisify(gzip); async function createArchive(files) { const pack = tar.pack(); for (const file of files) { pack.entry({ name: file.name }, file.data); } pack.finalize(); const chunks = []; for await (const chunk of pack) { chunks.push(chunk); } const tarBuffer = Buffer.concat(chunks); return gzipAsync(tarBuffer); } export async function archiveExistingRepoContent(repoUrl, projectPath) { const tempDir = path.join(cliHomeTmp, Date.now().toString()); try { await ensuredir(tempDir); const git = simpleGit(); await git.clone(repoUrl, tempDir); const shouldArchive = await confirmPrompt({ title: "Would you like to create an archive of the existing repository content?", content: "In the future, you will be able to run `rse cli` to use merge operations on the project's old and new content. The term `cluster` is used as the name for the old content.", defaultValue: false }); if (shouldArchive) { const fileInputs = []; const tempFiles = await fs.readdir(tempDir); for (const file of tempFiles) { if (file !== ".git") { const filePath = path.join(tempDir, file); const stats = await fs.stat(filePath); if (stats.isFile()) { const data = await fs.readFile(filePath); fileInputs.push({ name: file, data: Buffer.isBuffer(data) ? data : Buffer.from(data) }); } else if (stats.isDirectory()) { const dirFiles = await fs.readdir(filePath, { recursive: true }); for (const dirFile of dirFiles) { const fullPath = path.join(tempDir, file, dirFile); if ((await fs.stat(fullPath)).isFile()) { const data = await fs.readFile(fullPath); fileInputs.push({ name: `${file}/${dirFile}`, data: Buffer.isBuffer(data) ? data : Buffer.from(data) }); } } } } } if (fileInputs.length > 0) { const archiveName = "cluster.tar.gz"; const archivePath = path.join(projectPath, archiveName); const tarData = await createArchive(fileInputs); await fs.writeFile(archivePath, tarData); relinka( "info", `Created archive of repository content at ${archiveName}` ); } } const gitDir = path.join(tempDir, ".git"); if (await fs.pathExists(gitDir)) { const targetGitDir = path.join(projectPath, ".git"); if (await fs.pathExists(targetGitDir)) { await fs.remove(targetGitDir); relinka("verbose", "Removed existing .git directory"); } await fs.copy(gitDir, path.join(projectPath, ".git"), { preserveTimestamps: true, dereference: false, errorOnExist: false }); const gitFolderPath = path.join(projectPath, ".git"); await setHiddenAttribute(gitFolderPath); relinka("verbose", "Copied .git folder from existing repository"); } else { throw new Error("Required .git folder not found"); } const filesToCopy = [ { name: "README.md", required: false }, { alternatives: ["LICENSE", "LICENSE.md"], required: false }, { name: cliConfigJsonc, required: false, targetName: cliConfigJsoncTmp, hidden: true } ]; let externalrseth; for (const file of filesToCopy) { if (file.name) { const sourcePath = path.join(tempDir, file.name); if (await fs.pathExists(sourcePath)) { const targetPath = path.join( projectPath, file.targetName ?? file.name ); await fs.copy(sourcePath, targetPath); if (!file.hidden) { relinka("info", `Copied ${file.name} from existing repository`); } if (file.name === cliConfigJsonc) { externalrseth = targetPath; } } } else if (file.alternatives) { for (const name of file.alternatives) { const filePath = path.join(tempDir, name); if (await fs.pathExists(filePath)) { await fs.copy(filePath, path.join(projectPath, name)); relinka("info", `Copied ${name} from existing repository`); break; } } } } return { success: true, ...externalrseth && { externalRseConfig: externalrseth } }; } catch (error) { relinka( "error", "Failed to clone repository:", error instanceof Error ? error.message : String(error) ); return { success: false }; } finally { try { await fs.remove(tempDir); } catch (error) { relinka("warn", "Failed to cleanup temporary directory:", String(error)); } } } export async function handleExistingRepoContent(memory, repoOwner, repoName, projectPath) { try { const repoUrl = `https://oauth2:${memory.githubKey}@github.com/${repoOwner}/${repoName}.git`; const { success, externalRseConfig } = await archiveExistingRepoContent( repoUrl, projectPath ); if (!success) { throw new Error("Failed to retrieve repository git data"); } relinka("success", "Retrieved repository git directory data"); return { success: true, ...externalRseConfig && { externalRseConfig } }; } catch (error) { relinka( "error", "Failed to set up existing repository:", error instanceof Error ? error.message : String(error) ); return { success: false }; } }