beesbuild
Version:
构建工具链
412 lines (411 loc) • 13.6 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import path from "path";
import logger from "logsets";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import input from "@inquirer/input";
import confirm from "@inquirer/confirm";
import select, { Separator } from "@inquirer/select";
import {
consola,
getPackageManifest,
git,
incNextVersion,
isValidPreRelease,
parseVersion,
versionTransformer
} from "@beesbuild/utils";
import semver from "semver";
import {
ALL_RELEASE_TYPES,
CONTINUATION_TYPES,
PRERELEASE_TYPES,
PRE_RELEASE_TYPES,
RELEASE_TYPES
} from "../../variables.mjs";
dayjs.extend(relativeTime);
const CHOICES = {
latestIsPreRelease: [...RELEASE_TYPES, CONTINUATION_TYPES[0]],
preRelease: PRERELEASE_TYPES,
default: [...RELEASE_TYPES, ...PRERELEASE_TYPES]
};
const PRE_RELEASE_ID = "beta";
const defsContextOptions = () => {
return {
rootDir: process.cwd(),
logs: [],
debug: false,
excludes: [],
report: "versions.md",
changeLogs: "changeLogs",
increment: "patch",
preReleaseId: "",
isPreRelease: false,
silent: true,
includeDescendants: false,
distTag: [],
test: false,
force: false
};
};
class Context {
constructor(options) {
__publicField(this, "options", defsContextOptions());
var _a, _b;
const rootDir = this.options.rootDir = (_a = options.rootDir) != null ? _a : process.cwd();
const workspace = this.options.workspace = getPackageManifest(path.resolve(rootDir, ".", "package.json"));
const defs = defsContextOptions();
const context = {
...defs,
rootDir,
...(_b = workspace == null ? void 0 : workspace.publishConfig) != null ? _b : {},
...options
};
Object.entries(context).forEach(([key]) => {
var _a2;
switch (true) {
case key === "preReleaseId":
if (!(context == null ? void 0 : context.preReleaseId) || !PRE_RELEASE_TYPES.includes(context == null ? void 0 : context.preReleaseId)) {
this.options.preReleaseId = "";
} else {
this.options.preReleaseId = context == null ? void 0 : context.preReleaseId;
}
return;
case key === "increment":
if (!(context == null ? void 0 : context.increment) || (context == null ? void 0 : context.increment) === "none") {
this.options.increment = "";
} else {
this.options.increment = context == null ? void 0 : context.increment;
}
return;
default:
}
this.options[key] = (_a2 = context[key]) != null ? _a2 : defs[key];
});
}
shortDate(time, format = "MM/DD hh:mm:ss") {
return dayjs(time).format(format);
}
relativeTime(time) {
return dayjs(time).fromNow();
}
log(info) {
this.options.logs.push(info);
}
/**
* 切换到发布分支
*/
async switchToReleaseBranch(options) {
const releaseBranch = this.options.releaseBranch;
let currentBranch;
let isCheckout = false;
try {
currentBranch = git.getCurrentBranch();
logger.log("- \u5F53\u524D\u5206\u652F: {}", currentBranch);
logger.log("- \u53D1\u5E03\u5206\u652F: {}", releaseBranch || currentBranch);
if (releaseBranch && releaseBranch !== currentBranch) {
logger.log("- \u5207\u6362\u5230\u53D1\u5E03\u5206\u652F: {}", releaseBranch);
await git.checkoutBranch(releaseBranch);
isCheckout = true;
}
} catch (e) {
this.log(`ERROR: ${e == null ? void 0 : e.stack}`);
throw e;
} finally {
if (isCheckout) {
this.options.oldBranch = currentBranch;
}
}
}
/**
*
*/
packagesFilter(options) {
var _a;
let packages = this.options.packages;
const excludes = this.options.excludes;
if (!packages || (packages == null ? void 0 : packages.length) === 0) return [];
packages = packages.filter(
(value) => !excludes.includes(value == null ? void 0 : value.name) || (value == null ? void 0 : value.private) === true
);
for (let i = 0; i < packages.length; i++) {
const pkgInfo1 = packages[i];
const dependencies1 = Object.keys((_a = pkgInfo1 == null ? void 0 : pkgInfo1.dependencies) != null ? _a : {});
if (dependencies1.length === 0) continue;
for (let j = i; j < packages.length; j++) {
const pkgInfo2 = packages[j];
if (dependencies1.includes(pkgInfo2.name)) {
const p = packages[i];
packages[i] = packages[j];
packages[j] = p;
}
}
}
return packages;
}
getReleaseTypes({
increment,
latestIsPreRelease,
isPreRelease
} = {}) {
if (increment && ALL_RELEASE_TYPES.includes(increment)) {
return [increment];
}
return latestIsPreRelease ? CHOICES.latestIsPreRelease : isPreRelease ? CHOICES.preRelease : CHOICES.default;
}
get releaseConfig() {
let increment = this.options.increment;
const preReleaseId = this.options.preReleaseId;
let isPreRelease = false;
let latestIsPreRelease = false;
switch (true) {
case CHOICES.preRelease.includes(increment):
case CONTINUATION_TYPES.includes(increment):
isPreRelease = true;
latestIsPreRelease = true;
if (increment === "pre") {
increment = "";
}
break;
case !CHOICES.default.includes(increment):
increment = "";
break;
}
return {
increment,
latestIsPreRelease,
isPreRelease,
preReleaseId: typeof preReleaseId === "string" ? preReleaseId : PRE_RELEASE_ID
};
}
get isPreRelease() {
return this.releaseConfig.isPreRelease;
}
get packages() {
return this.packagesFilter();
}
getPackageChoices(options) {
return this.packages.reduce((prev = [], value) => {
const { isPreRelease, preReleaseId: _preReleaseId, version } = parseVersion(value.version);
if (!version) return prev;
let latestIsPreRelease = false;
if (typeof value.version === "string") {
latestIsPreRelease = isValidPreRelease(version);
}
const types = this.getReleaseTypes({ latestIsPreRelease, isPreRelease });
const choices = types.map((increment) => {
const preReleaseId = !RELEASE_TYPES.includes(increment) ? _preReleaseId != null ? _preReleaseId : this.releaseConfig.preReleaseId : "";
const nextVersion = incNextVersion(version, increment, preReleaseId);
return {
name: `${increment} (${value.name}@${nextVersion})`,
value: [increment, value.name, nextVersion],
increment,
latestVersion: version,
nextVersion,
pkgName: value.name,
pkg: value
};
});
return prev.concat(choices);
}, []);
}
async confirmRelease(choice) {
const answer = await confirm({
message: `\u786E\u8BA4\u662F\u5426\u7ACB\u5373\u53D1\u5E03 ${choice.name}?`
});
if (answer === true) return choice.value;
return answer;
}
async selectIncrement(choices, one = false) {
if (one === false) {
const otherChoice = {
name: "\u6309\u6B65\u9AA4\u6267\u884C\u53D1\u5E03\uFF1F",
value: null
};
choices = [
otherChoice,
new Separator("-- \u5206\u5272\u7EBF - start --"),
...choices,
new Separator("-- \u5206\u5272\u7EBF - end --")
];
} else {
const otherChoice = {
name: "\u5176\u4ED6\uFF0C\u8BF7\u6307\u5B9A\u7248\u672C...",
value: null
};
choices = [...choices, otherChoice];
}
const answer = await select({
message: `\u9009\u62E9\u589E\u91CF\uFF08\u4E0B\u4E00\u4E2A\u7248\u672C\uFF09\uFF1A`,
choices,
pageSize: 9
});
if (answer === null && one !== false) {
const latestVersion = choices[0].latestVersion;
const nextVersion = choices[0].nextVersion;
const value = ["customize", choices[0].pkgName];
const transformer = versionTransformer(latestVersion);
const answer2 = await input({
message: "\u8BF7\u8F93\u5165\u6709\u6548\u7248\u672C\uFF1A",
default: nextVersion,
transformer,
validate(input2) {
return !!semver.valid(input2) || "\u7248\u672C\u5FC5\u987B\u7B26\u5408 semver \u6807\u51C6\u3002";
}
});
if (!answer2) return [];
return value.concat(answer2);
}
return answer;
}
async promptListRelease(prompts) {
const answers = [];
const prompt = {
select: (message, choices) => select({
message,
choices,
pageSize: 9
}),
confirm: (message, choices) => confirm({
message
})
};
for (let { type, message, choices, transformerValue } of prompts) {
if (typeof message === "function") {
message = await message(answers);
}
let answer = await prompt[type](message, choices);
if (typeof transformerValue === "function") {
answer = await transformerValue(answer, answers);
}
if (!answer) break;
answers.push(answer);
}
return answers;
}
/**
* 向用户询问要发布哪些包
* @returns {selectedPackages,distTag,increment }
*/
async askForPublishPackages(options) {
let packageChoices = this.getPackageChoices(options);
const { increment, isPreRelease, preReleaseId } = this.releaseConfig;
if (packageChoices.length === 0) return {};
consola.log(packageChoices.length, "packageChoices");
const packages = packageChoices.reduce((prev, value) => {
if (!prev.some((choice) => choice.name === value.pkgName)) {
prev.push(value.pkg);
}
return prev;
}, []);
if (increment) {
packageChoices = packageChoices.filter((value) => value.increment === increment);
}
if (packageChoices.length === 1) {
const answer2 = await this.confirmRelease(packageChoices[0]);
return answer2;
}
if (packages.length === 1 && packageChoices.length > 0) {
const answer2 = await this.selectIncrement(packageChoices, true);
return answer2;
}
const types = this.getReleaseTypes({
increment,
isPreRelease
});
let choices = types.map((increment2) => {
const { version } = parseVersion("0.0.0");
const filter = typeof (options == null ? void 0 : options.filter) === "string" ? `\u3010${options == null ? void 0 : options.filter}\u3011` : "";
const nextVersion = incNextVersion(version != null ? version : "", increment2, preReleaseId != null ? preReleaseId : "");
return {
name: `${increment2} +(${nextVersion == null ? void 0 : nextVersion.replace(/0/gi, "*")})`,
value: [increment2],
description: `\u53D1\u5E03${filter != null ? filter : ""} \u5168\u91CF\u5305 ${increment2} \u7248\u672C`,
increment: increment2
};
});
if (increment) {
choices = choices.filter((value) => value.increment === increment);
}
const typesChoices = choices;
if (choices.length === 1) {
const increment2 = choices[0].increment;
choices = packageChoices.filter((value) => value.increment === increment2);
} else {
const d = new Separator("-- \u4EE5\u4E0B\u9009\u62E9\u72EC\u7ACB\u5305\u7248\u672C\u53D1\u5E03 --");
choices = choices.concat(d).concat(packageChoices);
}
if (choices.length === 1) {
return this.confirmRelease(packageChoices[0]);
}
const answer = await this.selectIncrement(choices);
if (answer === null) {
const prompts = [
{
type: "select",
key: "increment",
message: `\u9009\u62E9\u589E\u91CF\u65B9\u5F0F\uFF1A${CHOICES.default.join("\u3001")}`,
choices: typesChoices.map((value) => {
return {
name: value.increment,
value: value.increment
};
})
},
{
type: "select",
key: "name",
message: `\u9009\u62E9\u9700\u8981\u53D1\u5E03\u7684\u5305\uFF1A`,
choices: packages.map((value) => {
return {
name: value.name,
value: value.name
};
})
},
{
type: "confirm",
message: (answer2) => `\u786E\u8BA4\u662F\u5426\u7ACB\u5373\u53D1\u5E03 ${answer2[1]}?`,
transformerValue: (answer2, answers) => {
const [increment2, name] = answers;
if (answer2 === true) {
const choice = packageChoices.find(
(value) => value.increment === increment2 && name === value.pkgName
);
return choice && (choice == null ? void 0 : choice.latestVersion) ? choice.latestVersion : false;
}
return false;
}
}
];
return this.promptListRelease(prompts);
}
}
/**
* 发布指定的包
*
* - 并且在package.json中记录最后发布时间
*
* 本命令只能在包文件夹下执行
*
* @param task
*/
// publishPackage(task) {
// const {
// rootDir,
// distTag,
// build,
// test,
// buildScript,
// increment,
// silent,
// package: currentPackage,
// } = this;
// }
}
export {
Context,
defsContextOptions
};