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

192 lines (191 loc) 6.56 kB
import path from "@reliverse/pathkit"; import { ensuredir } from "@reliverse/relifso"; import fs from "@reliverse/relifso"; import { relinka } from "@reliverse/relinka"; import { execa } from "execa"; import { readPackageJSON, writePackageJSON } from "pkg-types"; var PackageManager = /* @__PURE__ */ ((PackageManager2) => { PackageManager2["Bun"] = "bun"; PackageManager2["Pnpm"] = "pnpm"; PackageManager2["Yarn"] = "yarn"; PackageManager2["Npm"] = "npm"; return PackageManager2; })(PackageManager || {}); async function detectPackageManager(cwd) { if (await fs.pathExists(path.join(cwd, "bun.lock"))) { return "bun" /* Bun */; } if (await fs.pathExists(path.join(cwd, "pnpm-lock.yaml"))) { return "pnpm" /* Pnpm */; } if (await fs.pathExists(path.join(cwd, "yarn.lock"))) { return "yarn" /* Yarn */; } return "npm" /* Npm */; } async function installDependencies(cwd, dependencies, isDev) { const pm = await detectPackageManager(cwd); const installCmd = pm === "npm" /* Npm */ ? "install" : "add"; const args = [installCmd, ...dependencies]; if (isDev) { args.push(pm === "npm" /* Npm */ ? "--save-dev" : "-D"); } try { await execa(pm, args, { cwd }); relinka( "success", `Installed ${isDev ? "dev " : ""}dependencies with ${pm}` ); } catch (error) { relinka( "error", `Failed to install dependencies: ${error instanceof Error ? error.message : String(error)}` ); throw error; } } export async function updatePackageJson(projectPath, options = {}) { try { const packageJson = await readPackageJSON(projectPath); if (!packageJson) { throw new Error("package.json not found or could not be read"); } if (options.fields) { Object.assign(packageJson, options.fields); } if (options.scripts) { packageJson.scripts = { ...packageJson.scripts, ...options.scripts }; } const packageJsonPath = path.join(projectPath, "package.json"); await writePackageJSON(packageJsonPath, packageJson); return true; } catch (error) { relinka("error", "Error updating package.json:", String(error)); if (options.throwOnError) { throw error; } return false; } } async function updateEnvFile(cwd, envVars) { const envPath = path.join(cwd, ".env"); const envExamplePath = path.join(cwd, ".env.example"); try { let envContent = await fs.pathExists(envPath) ? await fs.readFile(envPath, "utf-8") : ""; let envExampleContent = await fs.pathExists(envExamplePath) ? await fs.readFile(envExamplePath, "utf-8") : ""; for (const [key, value] of Object.entries(envVars)) { if (!envContent.includes(key)) { envContent += `\\n${key}=${value}`; } if (!envExampleContent.includes(key)) { envExampleContent += `\\n${key}=your_${key.toLowerCase()}_here`; } } await fs.writeFile(envPath, envContent.trim()); await fs.writeFile(envExamplePath, envExampleContent.trim()); } catch (error) { relinka( "error", `Failed to update env files: ${error instanceof Error ? error.message : String(error)}` ); throw error; } } export async function installIntegration(cwd, config, isDev) { try { relinka("info", `Installing ${config.name}...`); for (const file of config.files) { const filePath = path.join(cwd, file.path); await ensuredir(path.dirname(filePath)); await fs.writeFile(filePath, file.content); relinka("success", `Created ${file.path}`); } if (config.dependencies.length > 0) { await installDependencies(cwd, config.dependencies, isDev); } if (config.devDependencies?.length) { await installDependencies(cwd, config.devDependencies, isDev); } if (config.scripts) { try { await updatePackageJson(cwd, { scripts: config.scripts, throwOnError: true }); } catch (error) { relinka( "error", `Failed to update package.json: ${error instanceof Error ? error.message : String(error)}` ); throw error; } } if (config.envVars) { await updateEnvFile(cwd, config.envVars); } if (config.postInstall) { await config.postInstall(cwd); } relinka("success", `Successfully installed ${config.name}`); } catch (error) { relinka( "error", `Failed to install ${config.name}: ${error instanceof Error ? error.message : String(error)}` ); throw error; } } export async function removeIntegration(cwd, config) { try { relinka("info", `Removing ${config.name}...`); const packageJsonPath = path.join(cwd, "package.json"); const pkg = await readPackageJSON(packageJsonPath); if (!pkg) { throw new Error("package.json not found or could not be read"); } config.dependencies.forEach((dep) => delete pkg.dependencies?.[dep]); config.devDependencies.forEach((dep) => delete pkg.devDependencies?.[dep]); config.scripts.forEach((script) => delete pkg.scripts?.[script]); await writePackageJSON(packageJsonPath, pkg); for (const file of config.files) { const filePath = path.join(cwd, file); if (await fs.pathExists(filePath)) { await fs.remove(filePath); relinka("success", `Removed ${file}`); } } for (const dir of config.directories) { const dirPath = path.join(cwd, dir); if (await fs.pathExists(dirPath)) { await fs.remove(dirPath); relinka("success", `Removed ${dir}`); } } const envPath = path.join(cwd, ".env"); const envExamplePath = path.join(cwd, ".env.example"); if (await fs.pathExists(envPath)) { let envContent = await fs.readFile(envPath, "utf-8"); config.envVars.forEach((key) => { envContent = envContent.replace(new RegExp(`^${key}=.*$\\n?`, "m"), ""); }); await fs.writeFile(envPath, envContent.trim()); } if (await fs.pathExists(envExamplePath)) { let envExampleContent = await fs.readFile(envExamplePath, "utf-8"); config.envVars.forEach((key) => { envExampleContent = envExampleContent.replace( new RegExp(`^${key}=.*$\\n?`, "m"), "" ); }); await fs.writeFile(envExamplePath, envExampleContent.trim()); } relinka("success", `Successfully removed ${config.name}`); } catch (error) { relinka( "error", `Failed to remove ${config.name}: ${error instanceof Error ? error.message : String(error)}` ); throw error; } }