@gabortorma/mwm
Version:
Multi-repo Workspace Manager
292 lines (276 loc) • 8.44 kB
JavaScript
;
const git = require('simple-git');
const path = require('node:path');
const consola = require('consola');
const config = require('./mwm.b-NRmH8L.cjs');
const args = require('./mwm.Bc81aV-e.cjs');
const rest = require('@octokit/rest');
const pkgTypes = require('pkg-types');
const replaceInFile = require('replace-in-file');
const changeCase = require('change-case');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
const git__default = /*#__PURE__*/_interopDefaultCompat(git);
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
async function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function getRepoUrl({
owner: { id, token },
name
}) {
return `https://${id}:${token}@github.com/${id}/${name}.git`;
}
async function cloneRepo(repo) {
const repoUrl = getRepoUrl(repo);
return git__default().clone(repoUrl, repo.path);
}
async function selectOwner(owner, owners) {
if (!owners) {
throw new Error("No owners found! Please add owners to the config file");
}
const ownersWithToken = {};
for (const key of Object.keys(owners)) {
if (owners[key].token)
ownersWithToken[key] = owners[key];
}
const options = Object.keys(ownersWithToken);
if (options.length === 0) {
throw new Error("No owners with token found! Please add owners with token to the config file");
}
if (!ownersWithToken[owner]) {
owner = await consola.consola.prompt("Select Owner", {
type: "select",
options
});
args.checkCancel(owner);
}
return {
id: owner,
...ownersWithToken[owner]
};
}
async function getName(name) {
return args.getStringArg(name, "Enter the name of the new repo");
}
async function getDescription(description) {
return args.getStringArg(description, "Enter the description of the new repo");
}
async function getPath(dir, name, template) {
if (dir) {
return dir;
}
const repoPath = path__default.join(template.path, name);
const result = consola.consola.prompt("Set the path of the new repo", {
type: "text",
placeholder: repoPath,
default: repoPath
});
args.checkCancel(result);
return result;
}
async function getPrivate(arg) {
return args.getBoolArg(arg, "Create a private repository?");
}
async function getClone(arg) {
return args.getBoolArg(arg, "Clone the repo instead of submodule?");
}
async function getAddRemoteTemplate(arg) {
return args.getBoolArg(arg, "Add remote template repository?");
}
async function getFixReplacements(arg) {
return args.getBoolArg(arg, "Fix replacements?");
}
function getKeywords(arg) {
if (typeof arg === "string")
return arg.split(",").map((keyword) => keyword.trim());
}
async function getRepo(args, template) {
const { config: config$1 } = await config.loadConfig();
const name = await getName(args.name);
return {
owner: await selectOwner(args.owner, config$1.owners),
name,
description: await getDescription(args.description),
path: await getPath(args.dir, name, template),
private: await getPrivate(args.private),
keywords: getKeywords(args.keywords)
};
}
async function generateGitHubRepo(template, repo) {
const octokit = new rest.Octokit({
auth: repo.owner.token
});
await octokit.request(`POST /repos/${template.owner}/${template.repo}/generate`, {
owner: repo.owner.id,
name: repo.name,
description: repo.description,
private: repo.private,
include_all_branches: false,
headers: {
"X-GitHub-Api-Version": "2022-11-28"
}
});
}
async function fixReplacements(replacements, repo) {
for (const replacement of replacements) {
if (replacement.type === "replace") {
let files = replacement.files;
if (!Array.isArray(files)) {
files = [files];
}
replacement.files = files.map((file) => path.join(".", repo.path, file));
await replaceInFile.replaceInFile(replacement);
} else if (replacement.type === "pkg") {
const file = path.resolve(".", repo.path, "package.json");
const packageJson = await pkgTypes.readPackageJSON(file);
await pkgTypes.writePackageJSON(file, replacement.replace(packageJson, repo));
}
}
}
const packageReplacement = {
type: "pkg",
replace: (packageJson, repo) => {
const fullRepo = `${repo.owner.id}/${repo.name}`;
packageJson.name = `@${repo.owner.id.toLowerCase()}/${repo.name}`;
packageJson.author = repo.owner.name || repo.owner.id;
packageJson.description = repo.description;
packageJson.version = "0.0.1";
packageJson.repository = {
type: "github",
url: `git+ssh://git@github.com/${fullRepo}.git`
};
if (repo.keywords)
packageJson.keywords = repo.keywords;
if (packageJson.homepage)
packageJson.homepage = `https://github.com/${fullRepo}`;
if (packageJson.bugs)
packageJson.bugs = `https://github.com/${fullRepo}/issues`;
return packageJson;
}
};
function getReadmeReplacement(template, repo) {
return {
type: "replace",
files: ["README.md"],
from: [
new RegExp(template.owner, "gi"),
new RegExp(template.repo, "g"),
new RegExp(changeCase.camelCase(template.repo), "g"),
new RegExp(changeCase.pascalCase(template.repo), "g"),
"_description_"
],
to: [
repo.owner.id.toLowerCase(),
repo.name,
changeCase.camelCase(repo.name),
changeCase.pascalCase(repo.name),
repo.description
]
};
}
const nitroPluginTemplate = {
path: "releases",
owner: "GaborTorma",
repo: "mwm-nitro-plugin-template",
branch: "main",
getReplacements(repo) {
return [
packageReplacement,
getReadmeReplacement(this, repo)
];
}
};
const nuxtLayerTemplate = {
path: "layers",
owner: "GaborTorma",
repo: "mwm-nuxt-layer-template",
branch: "main",
getReplacements(repo) {
return [
packageReplacement,
getReadmeReplacement(this, repo)
];
}
};
const nuxtModuleTemplate = {
path: "modules",
owner: "GaborTorma",
repo: "mwm-nuxt-module-template",
branch: "main",
getReplacements(repo) {
return [
packageReplacement,
getReadmeReplacement(this, repo),
{
// configKey
type: "replace",
files: [
"playground/nuxt.config.ts",
"src/module.ts"
],
from: new RegExp(changeCase.camelCase(this.repo), "g"),
to: changeCase.camelCase(repo.name)
},
{
// module name
type: "replace",
files: [
"src/module.ts",
"src/runtime/plugin.ts"
],
from: new RegExp(this.repo, "g"),
to: repo.name
}
];
}
};
const templateTypes = ["nuxt-layer", "nuxt-module", "nitro-plugin"];
const templates = {
"nuxt-layer": nuxtLayerTemplate,
"nuxt-module": nuxtModuleTemplate,
"nitro-plugin": nitroPluginTemplate
};
async function selectTemplate(template) {
if (!templates[template]) {
template = await consola.consola.prompt("Select template", {
type: "select",
options: templateTypes
});
args.checkCancel(template);
}
return templates[template];
}
async function getGit(repo) {
return git__default({
baseDir: path__default.resolve(repo.path)
});
}
async function addRemoteTemplate(template, repo) {
const git = await getGit(repo);
await git.addRemote("template", `git@github.com:${template.owner}/${template.repo}.git`);
await git.fetch("template", "main");
await git.merge([`template/${template.branch}`, "--allow-unrelated-histories", "--message=Merge template"]);
}
async function commitInitChanges(repo) {
const git = await getGit(repo);
await git.add(".");
await git.commit("Customize template");
}
async function pushChanges(repo) {
const git = await getGit(repo);
await git.push("origin", "main");
}
exports.addRemoteTemplate = addRemoteTemplate;
exports.cloneRepo = cloneRepo;
exports.commitInitChanges = commitInitChanges;
exports.fixReplacements = fixReplacements;
exports.generateGitHubRepo = generateGitHubRepo;
exports.getAddRemoteTemplate = getAddRemoteTemplate;
exports.getClone = getClone;
exports.getFixReplacements = getFixReplacements;
exports.getRepo = getRepo;
exports.getRepoUrl = getRepoUrl;
exports.packageReplacement = packageReplacement;
exports.pushChanges = pushChanges;
exports.selectTemplate = selectTemplate;
exports.sleep = sleep;