UNPKG

@roboplay/sage

Version:
146 lines (143 loc) 6.79 kB
import { Command } from 'commander'; import tar from 'tar'; import { color, composeColors } from '../core/color.js'; import { logger } from '../core/logger.js'; import { getPackageManager, checkSageUpdates, isRoboProject, downloadFile, exec } from '../core/utils.js'; import path from 'node:path'; import { mkdirSync } from 'node:fs'; import { readFile, access, cp, writeFile } from 'node:fs/promises'; import { cleanTempDir } from 'robo.js/utils.js'; const command = new Command("import").arguments("[plugins...]").description("Import plugin(s) as modules into your Robo").option("-ns --no-self-check", "do not check for updates to Sage CLI").option("-s --silent", "do not print anything").option("-v --verbose", "print more information for debugging").action(importAction); var import_default = command; async function importAction(plugins, options) { logger({ enabled: !options.silent, level: options.verbose ? "debug" : "info" }).info(`Importing ${plugins.length} plugin${plugins.length === 1 ? "" : "s"}...`); logger.debug(`CLI Options:`, options); logger.debug(`Package manager:`, getPackageManager()); logger.debug(`Current working directory:`, process.cwd()); logger.debug(`Plugins:`, plugins); if (options.selfCheck) { await checkSageUpdates(); } if (plugins.length < 1) { logger.error("Please provide at least one plugin to import!"); process.exit(1); } if (!await isRoboProject()) { logger.error(`This does not appear to be a Robo project!`); process.exit(1); } const packageJsonPath = path.join(process.cwd(), "package.json"); const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8")); const success = []; try { await cleanTempDir(); } catch (error) { logger.debug(`Failed to clean temp directory:`, error); } let needsTypescript = false; for (const plugin of plugins) { try { const result = await importPlugin(plugin, packageJson); if (result.typescript) { needsTypescript = true; } success.push(plugin); } catch (error) { logger.error(`Failed to import plugin "${color.bold(plugin)}":`, error); } } if (success.length > 0) { logger.ready(`Successfully imported ${success.length} plugin${success.length === 1 ? "" : "s"}!`); } else { logger.error(`Failed to import any plugins.`); } const tsPath = path.join(process.cwd(), "tsconfig.json"); const tsExists = await access(tsPath).then(() => true).catch(() => false); if (needsTypescript && !tsExists) { const docs = composeColors(color.underline, color.cyan)("https://docs.roboplay.dev/docs/advanced/typescript"); logger.warn(`One or more of your plugins requires TypeScript.`); logger.warn(`See the following docs for more information:`, docs); } } async function importPlugin(plugin, packageJson) { const npmResponse = await fetch(`https://registry.npmjs.org/${plugin}/latest`); const info = await npmResponse.json(); const prefix = color.bold(plugin + " >"); logger.debug(prefix, `Registry info:`, info); if (!npmResponse.ok) { throw new Error(`Plugin "${color.bold(plugin)}" does not exist!`); } const packageName = info.name.replace("/", "_").replace("@", ""); const distDir = path.join(".robo", "temp", `${packageName}_${info.version}`); const sourceTar = distDir + ".tgz"; logger.info(prefix, `Downloading tarball...`); await downloadFile(info.dist.tarball, sourceTar); mkdirSync(distDir, { recursive: true }); logger.debug(prefix, `Extracting tarball...`); await tar.x({ file: sourceTar, cwd: distDir }); logger.debug(prefix, `Verifying "src" directory...`); const pluginDir = path.join(distDir, "package"); const pluginSrcDir = path.join(pluginDir, "src"); const pluginSrcDirExists = await access(pluginSrcDir).then(() => true).catch(() => false); if (!pluginSrcDirExists) { throw new Error(`Plugin "${color.bold(plugin)}" does not have a "src" directory!`); } logger.info(prefix, "Copying plugin source files to Robo project..."); const roboSrcDir = path.join(process.cwd(), "src", "modules", packageName); mkdirSync(roboSrcDir, { recursive: true }); await cp(pluginSrcDir, roboSrcDir, { recursive: true }); const pluginReadmePath = path.join(pluginDir, "README.md"); const pluginReadmeExists = await access(pluginReadmePath).then(() => true).catch(() => false); if (pluginReadmeExists) { const readmeContents = await readFile(pluginReadmePath, "utf-8"); const readmeSource = `**[View original source](https://www.npmjs.com/package/${plugin})**`; const readmeHeader = `> ***Import*ant:** This module was imported from the plugin package "${plugin}". ${readmeSource} `; await writeFile(pluginReadmePath, readmeHeader + readmeContents); await cp(pluginReadmePath, path.join(roboSrcDir, "README.md")); } logger.debug(prefix, `Reading plugin's package.json...`); const pluginPackageJson = JSON.parse(await readFile(path.join(pluginDir, "package.json"), "utf-8")); const pluginDeps = pluginPackageJson.dependencies ?? {}; const pluginDevDeps = pluginPackageJson.devDependencies ?? {}; const projectDeps = packageJson.dependencies ?? {}; const projectDevDeps = packageJson.devDependencies ?? {}; logger.info(prefix, `Checking for TypeScript...`); const pluginHasTs = Object.keys(pluginDevDeps).includes("typescript"); logger.debug(prefix, `Plugin ${pluginHasTs ? "contains" : "does not contain"} TypeScript.`); delete pluginDevDeps["robo.js"]; delete projectDevDeps["discord.js"]; logger.debug(prefix, `Comparing dependencies...`); const depsToInstall = Object.keys(pluginDeps).filter((dep) => !projectDeps[dep]); const devDepsToInstall = Object.keys(pluginDevDeps).filter((dep) => !projectDevDeps[dep]); logger.debug(prefix, `Dependencies to install:`, depsToInstall); logger.debug(prefix, `Dev dependencies to install:`, devDepsToInstall); if (depsToInstall.length > 0) { logger.info(prefix, `Installing dependencies...`); const packageManager = getPackageManager(); const command2 = packageManager === "npm" ? "install" : "add"; await exec(`${packageManager} ${command2} ${depsToInstall.join(" ")}`); } if (devDepsToInstall.length > 0) { logger.info(prefix, `Installing dev dependencies...`); const packageManager = getPackageManager(); const command2 = packageManager === "npm" ? "install" : "add"; const commandOption = packageManager === "npm" ? "--save-dev" : "--dev"; await exec(`${packageManager} ${command2} ${commandOption} ${devDepsToInstall.join(" ")}`); } logger.info(prefix, `Successfully imported!`); return { typescript: pluginHasTs }; } export { import_default as default }; //# sourceMappingURL=out.js.map //# sourceMappingURL=import.js.map