@roboplay/sage
Version:
Codemod for Robo.js
177 lines (173 loc) • 7.23 kB
JavaScript
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