/**
* @file plugin/release/ap.js
* @copyright @spmhome @_2025
* @author Scott Meesseman @spmeesseman\
*//** */
const WpwPlugin = require("../base");
/**
* @augments WpwPlugin
*/
class WpwApPlugin extends WpwPlugin
{
/**
* @private
* @type {string}
*/
currentVersion;
/**
* @private
* @type {string}
*/
nextVersion;
/**
* @private
* @type {boolean}
*/
hasFileUpdates;
/**
* @private
* @type {string}
*/
versionBump;
/**
* @param {WpwPluginOptions} options Plugin options to be applied
*/
constructor(options)
{
super(options);
this.buildOptions = /** @type {WpwBuildOptionsPluginConfig<"ap">} */(this.buildOptions); // reset for typings
}
/**
* @override
*/
static create = WpwApPlugin.wrap.bind(this);
/**
* @override
* @returns {WpwPluginTapOptions<any, any, boolean>}
*/
onApply()
{
/** @type {WpwPluginTapOptions<any, any, boolean>} */
const hooksConfig = {
printApInfo: {
hook: "beforeRun",
async: true,
callback: this.printApInfo.bind(this)
},
getVersions: {
hook: "run",
async: true,
callback: this.getVersions.bind(this)
}
};
if (!this.buildOptions.printVersionsOnly)
{
this._obj_.apply(hooksConfig, {
updateVersionFiles: {
hook: "beforeCompile",
async: true,
callback: this.updateVersionFiles.bind(this)
},
cleanup: {
hook: "shutdown",
forceRun: true,
callback: this.cleanup.bind(this)
},
updateChangelog: {
hook: "done",
callback: this.updateChangelog.bind(this)
}
});
if (this.buildOptions.github)
{
hooksConfig.executeGithubRelease = {
hook: "done",
async: true,
callback: this.executeGithubRelease.bind(this)
};
}
else if (this.buildOptions.gitlab)
{
hooksConfig.executeGitlabRelease = {
hook: "done",
async: true,
callback: this.executeGitlabRelease.bind(this)
};
}
if (this.buildOptions.mantis)
{
hooksConfig.executeMantisRelease = {
hook: "done",
async: true,
callback: this.executeMantisRelease.bind(this)
};
}
if (this.buildOptions.npm)
{
hooksConfig.executeNpmRelease = {
hook: "done",
async: true,
callback: this.executeNpmRelease.bind(this)
};
}
}
return hooksConfig;
}
/**
* @private
*/
async cleanup()
{
if (this.buildOptions.dryRun || (this.build.hasError && this.hasFileUpdates))
{
await this.execAp({ logPad: " " }, "--task-revert");
}
}
/**
* @param {Omit<WpwExecOptions, "command"|"program"|"logger"|"basePath"|"owner">} [options]
* @param {string[]} args
* @returns {Promise<WpwExecResult>} Promise<PluginExecResult>
*/
execAp(options, ...args)
{
args.push("--no-ci");
if (this.buildOptions.dryRun) {
args.push("--dry-run");
}
if (this.buildOptions.promptVersion && !args.includes("--prompt-version-disable")) {
args.push("--prompt-version");
}
//
// Can't be verbose if we are reading stdout as a value i.e. versions
//
if (!options?.stdinOn)
{
if (this.buildOptions.verbose) {
args.push("--verbose");
}
if (this.buildOptions.veryVerbose) {
args.push("--verboseEx");
}
}
return this.exec(`app-publisher ${args.join(" ")}`, "app-publisher", true, options);
}
/**
* @private
*/
async executeGithubRelease()
{
await this.execAp({ logPad: " " }, "--task-github-release");
}
/**
* @private
*/
async executeGitlabRelease()
{ //
// TODO - app-publisher gitlab release
//
// await this.execAp("--task-gitlab-release");
throw this.addMessage({
code: this.MsgCode.ERROR_NOT_IMPLEMENTED, message: "app-publisher: --task-gitlab-release"
});
}
/**
* @private
*/
async executeMantisRelease()
{
await this.execAp({ logPad: " " }, "--task-mantis-release");
}
/**
* @private
* @returns {Promise<void>}
*/
async executeNpmRelease()
{
await this.execAp({ logPad: " " }, "--task-npm-release");
}
/**
* @private
*/
async getVersions()
{
const args = [ "--task-version-info" ],
preTag = this.buildOptions.preVersion;
//
// a 1st release will auto-prompt, disable if not explicitly set
//
if (this.build.pkgJson.version === "0.0.1" && !this.buildOptions.promptVersion) {
// args.push("--version-force-next", "0.0.1");
args.push("--prompt-version-disable");
}
if (preTag) {
args.push("--version-pre-release-id", preTag);
}
const versions = (await this.execAp({ stdinOn: true, logPad: " " }, ...args)).stdout.split("|");
this.currentVersion = versions[0];
this.nextVersion = versions[1];
this.versionBump = versions[2];
this.build.logger.value("current version", this.currentVersion, 1);
this.build.logger.value("next version", this.nextVersion, 1);
this.build.logger.value("version bump", this.versionBump, 2);
}
/**
* @private
*/
async printApInfo()
{
await this.execAp({ logStdio: true, logPad: " " }, "--version");
this.hasFileUpdates = this.hasFileUpdates || !this.build.hasError;
}
/**
* @private
*/
async updateChangelog()
{
await this.execAp({ logPad: " " }, "--task-changelog");
this.hasFileUpdates = this.hasFileUpdates || !this.build.hasError;
}
/**
* @private
*/
async updateVersionFiles()
{
const preTag = this.buildOptions.preVersion;
this.build.logger.write("update version files", 1);
if (this.buildOptions.promptVersion)
{
// TODO - prompt for version, get npm package 'prompt'
}
if (!preTag) {
await this.execAp({ logPad: " " }, "--task-version-update", "--version-force-next", this.nextVersion);
}
else {
await this.execAp({ logPad: " " },
"--task-version-update", "--version-pre-release-id", preTag, "--version-force-next", this.nextVersion
);
}
this.hasFileUpdates = this.hasFileUpdates || !this.build.hasError;
}
}
module.exports = WpwApPlugin.create;