UNPKG

@roboplay/sage

Version:
177 lines (173 loc) 7.23 kB
import { Command } from 'commander'; import depcheck from 'depcheck'; import { select, Separator } from '@inquirer/prompts'; import { color, composeColors } from '../core/color.js'; import { logger } from '../core/logger.js'; import { getPackageManager, checkSageUpdates, isRoboProject, getPackageExecutor, exec } from '../core/utils.js'; import path from 'node:path'; import { readFile, access, mkdir, rm, cp, writeFile } from 'node:fs/promises'; const command = new Command("export").arguments("[modules...]").description("Export module(s) from your Robo as plugins").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(exportAction); var export_default = command; async function exportAction(modules, options) { logger({ enabled: !options.silent, level: options.verbose ? "debug" : "info" }).info(`Exporting ${modules.length} module${modules.length === 1 ? "" : "s"}...`); logger.debug(`CLI Options:`, options); logger.debug(`Package manager:`, getPackageManager()); logger.debug(`Current working directory:`, process.cwd()); if (options.selfCheck) { await checkSageUpdates(); } if (modules.length < 1) { logger.error("Please provide at least one module to export!"); process.exit(1); } if (!await isRoboProject()) { logger.error(`This does not appear to be a Robo project!`); process.exit(1); } logger.debug(`Reading project package.json...`); const packageJsonPath = path.join(process.cwd(), "package.json"); const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8")); const projectInfo = { hasEslint: !!packageJson.devDependencies["eslint"], hasPrettier: !!packageJson.devDependencies["prettier"], hasTypescript: !!packageJson.devDependencies["typescript"], hasWorkspaces: !!packageJson.workspaces, roboversion: packageJson.dependencies["robo.js"] }; const results = []; for (const module of modules) { try { const result = await exportModule(module, projectInfo, options); results.push(result); } catch (error) { logger.error(`Failed to export module "${color.bold(module)}":`, error); } } } async function exportModule(module, project, commandOptions) { logger.debug(`Checking if module "${color.bold(module)}" exists...`); const modulePath = path.join(process.cwd(), "src", "modules", module); const moduleExists = await access(modulePath).then(() => true).catch(() => false); if (!moduleExists) { throw new Error(`Module "${color.bold(module)}" does not exist!`); } const packageName = "robo-plugin-" + module; const exportPath = path.join(process.cwd(), "..", packageName); mkdir(exportPath, { recursive: true }); const packageExecutor = getPackageExecutor(); const command2 = getPackageManager() == "npm" && !project.hasWorkspaces ? "npx" : getPackageManager(); const features = []; if (project.hasEslint) { features.push("eslint"); } if (project.hasPrettier) { features.push("prettier"); } const options = ["--no-install", "--plugin"]; if (project.roboversion) { options.push(`--robo-version ${project.roboversion}`); } if (project.hasTypescript) { options.push("--typescript"); } if (features.length > 0) { options.push("--features", features.join(",")); } if (commandOptions.verbose) { options.push("--verbose"); } logger.debug(`Creating plugin project in "${color.bold(exportPath)}"...`); await exec(`${packageExecutor} create-robo ${options.join(" ")}`, { cwd: exportPath }); logger.debug(`Cleaning generated project template...`); const srcPath = path.join(exportPath, "src"); await rm(srcPath, { recursive: true, force: true }); logger.debug(`Copying module files...`); await cp(modulePath, srcPath, { recursive: true }); const readmePath = path.join(process.cwd(), "README.md"); const readmeExists = await access(readmePath).then(() => true).catch(() => false); if (readmeExists) { logger.debug(`Appending to README.md...`); const readme = await readFile(readmePath, "utf-8"); const note = ` > Original module README.md below ${readme}`; const generatedReadmePath = path.join(exportPath, "README.md"); const generatedReadme = await readFile(generatedReadmePath, "utf-8"); await writeFile(generatedReadmePath, generatedReadme + note); } const licensePath = path.join(process.cwd(), "LICENSE"); const licenseExists = await access(licensePath).then(() => true).catch(() => false); if (licenseExists) { logger.debug(`Copying LICENSE...`); await cp(licensePath, path.join(exportPath, "LICENSE")); } logger.debug(`Reading generated package.json...`); const generatedPackageJsonPath = path.join(exportPath, "package.json"); const generatedPackageJson = JSON.parse(await readFile(generatedPackageJsonPath, "utf-8")); logger.debug(`Checking for missing dependencies...`); const depResults = await depcheck(srcPath, { package: generatedPackageJson }); const missingDeps = Object.keys(depResults.missing ?? {}); if (missingDeps) { logger.debug(`Missing dependencies:`, depResults.missing); logger.info(`Installing missing dependencies...`); try { await exec(`${command2} ${await usesLocalWorkaround(command2, project.hasWorkspaces)} ${missingDeps.join(" ")}`, { cwd: exportPath }); } catch (error) { logger.error(`Failed to install missing dependencies:`, error); } } else { logger.info(`Installing dependencies...`); await exec( `${command2} ${await usesLocalWorkaround(command2, project.hasWorkspaces)} `, { cwd: exportPath } ); } logger.debug(`Building plugin...`); await exec(`${packageExecutor} robo build plugin${commandOptions.verbose ? " --verbose" : ""}`, { cwd: exportPath }); logger.ready(`Successfully exported module "${color.bold(module)}" as a plugin!`); logger.info(`You can find the plugin project here:`, color.bold(exportPath)); logger.log(""); const addPlugin = await select({ message: color.blue(`Want to add ${packageName} to your Robo?`), choices: [ { name: "Yes", value: true }, { name: "No", value: false }, new Separator( color.reset(` ${composeColors(color.bold, color.yellow)("Warning:")} this will delete the original module!`) ) ] }); if (addPlugin) { logger.debug(`Adding plugin to project...`); const absolutePath = path.join(process.cwd(), "..", packageName); await exec(`${packageExecutor} robo add ${absolutePath}${commandOptions.verbose ? " --verbose" : ""}`, { cwd: process.cwd() }); logger.debug(`Removing module from project...`); await rm(modulePath, { recursive: true, force: true }); logger.ready(`Successfully added plugin "${color.bold(packageName)}" to your Robo!`); } } async function usesLocalWorkaround(packageManager, hasWorkspaces) { if (packageManager === "npm" && !hasWorkspaces) { return "install-local"; } else { return "install"; } } export { export_default as default }; //# sourceMappingURL=out.js.map //# sourceMappingURL=export.js.map