UNPKG

verz

Version:

[![NPM Version](https://img.shields.io/npm/v/verz)](https://www.npmjs.com/package/verz)

262 lines (253 loc) 9.04 kB
#!/usr/bin/env node var __defProp = Object.defineProperty; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) { if (typeof require !== "undefined") return require.apply(this, arguments); throw Error('Dynamic require of "' + x + '" is not supported'); }); var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // src/index.ts import { readFileSync as readFileSync2, writeFileSync } from "fs"; import { join as join2 } from "path"; import { Command } from "commander"; import semver from "semver"; // src/lib/logger.ts import { inspect } from "util"; var COLORS = { reset: "\x1B[0m", red: "\x1B[31m", yellow: "\x1B[33m", blue: "\x1B[34m", green: "\x1B[32m", magenta: "\x1B[35m", gray: "\x1B[90m" }; var Logger = class { constructor(_level = "info") { this._level = _level; this.COLORS = COLORS; } debug(...args) { if (this.shouldLog("debug")) console.log(`${COLORS.gray}[DEBUG] ${COLORS.reset}`, ...args.map((arg) => typeof arg === "object" ? inspect(arg) : arg), COLORS.reset); } info(...args) { if (this.shouldLog("info")) console.log(`${COLORS.blue}[INFO] ${COLORS.reset}`, ...args.map((arg) => typeof arg === "object" ? inspect(arg) : arg), COLORS.reset); } warn(...args) { if (this.shouldLog("warn")) console.warn(`${COLORS.yellow}[WARN] ${COLORS.reset}`, ...args.map((arg) => typeof arg === "object" ? inspect(arg) : arg), COLORS.reset); } error(...args) { if (this.shouldLog("error")) console.error(`${COLORS.red}[ERROR] ${COLORS.reset}`, ...args.map((arg) => typeof arg === "object" ? inspect(arg) : arg), COLORS.reset); } level(level) { this._level = level; } shouldLog(level) { const levels = ["error", "warn", "info", "debug"]; return levels.indexOf(this._level) >= levels.indexOf(level); } }; var logger_default = new Logger(); // src/lib/exec.ts import { spawnSync } from "child_process"; // src/lib/config.ts import { join } from "path"; import { existsSync, readFileSync } from "fs"; // src/lib/utils.ts var deepMerge = (target, source) => { if (typeof source !== "object" || source === null) return source; const output = __spreadValues({}, target); for (const key in source) { if (source[key] === void 0 || source[key] === null) continue; if (typeof source[key] === "object" && !Array.isArray(source[key])) { output[key] = deepMerge(output[key] || {}, source[key]); } else { output[key] = source[key]; } } return output; }; // src/lib/config.ts var defaultConfig = { commit: { message: "chore: version %v" }, tag: { name: "%v" }, dryRun: false }; var Config = class { constructor() { this.config = defaultConfig; } fileLoad() { return __async(this, null, function* () { const configFiles = ["verz.config.json", "verz.config.js", "verz.config.mjs"]; for (const file of configFiles) { const configPath = join(process.cwd(), file); if (existsSync(configPath)) { logger_default.debug(`Loading config from ${file}`); try { if (file.endsWith(".json")) { return JSON.parse(readFileSync(configPath, "utf-8")); } else if (file.endsWith(".mjs")) { const module = yield import(configPath); return module.default; } else { return __require(configPath); } } catch (error) { logger_default.warn(`Failed to load config from ${file}:`, error); } } } return {}; }); } load() { return __async(this, arguments, function* (override = {}) { const fileConfig = yield this.fileLoad(); this.config = deepMerge(deepMerge(this.config, fileConfig), override); return this.config; }); } get() { return this.config; } }; var config_default = new Config(); // src/lib/exec.ts var exec = (command, args, options) => { var _a, _b; const config = config_default.get(); logger_default.debug(`Running command${logger_default.COLORS.gray}`, command, args); if (config.dryRun) return ""; const p = spawnSync(command, args.map(String), { stdio: "pipe" }); if (!(options == null ? void 0 : options.ignoreReturnCode)) { if (p.error) { throw p.error; } if (p.status !== 0) { throw new Error(`Command failed with exit code ${p.status}`); } } const stdout = (_b = (_a = p.stdout) == null ? void 0 : _a.toString()) != null ? _b : ""; if (stdout) { } return stdout; }; var exec_default = exec; // src/index.ts function bumpVersion(type) { var _a; const config = config_default.get(); const packagePath = join2(process.cwd(), "package.json"); const packageContent = readFileSync2(packagePath, "utf-8"); const packageJson = JSON.parse(packageContent); const newVersion = semver.inc(packageJson.version, type); if (!newVersion) { throw new Error(`Failed to bump version: ${packageJson.version}`); } const packageJsonStatus = exec_default("git", ["status", "--porcelain", "package.json"], { ignoreReturnCode: true }); if (packageJsonStatus.length > 0) { throw new Error("package.json has uncommitted changes. Please commit or stash them first."); } const hasChanges = exec_default("git", ["diff", "HEAD"], { ignoreReturnCode: true }).length > 0; if (hasChanges) { exec_default("git", ["stash", "push", "--keep-index"]); } packageJson.version = newVersion; logger_default.debug(`Updating ${logger_default.COLORS.gray}package.json`); const match = packageContent.match(/^(?:( +)|\t+)/m); const indent = (_a = match == null ? void 0 : match[0]) != null ? _a : " "; if (!config.dryRun) writeFileSync(packagePath, JSON.stringify(packageJson, null, indent) + "\n"); try { exec_default("git", ["add", "package.json"]); const commitMessage = config.commit.message.replace("%v", newVersion); logger_default.info(`Committing changes with message${logger_default.COLORS.magenta}`, commitMessage); exec_default("git", ["commit", "-m", commitMessage]); const tagName = config.tag.name.replace("%v", newVersion); logger_default.info(`Creating tag${logger_default.COLORS.magenta}`, tagName); exec_default("git", ["tag", tagName]); } catch (e) { logger_default.error("Failed to commit and tag:", e); } finally { if (hasChanges) { exec_default("git", ["stash", "pop"]); } } return newVersion; } function main() { return __async(this, null, function* () { const program = new Command(); program.name("verz").description("Version bumping tool").option("--patch", "bump patch version").option("--minor", "bump minor version").option("--major", "bump major version").option("--commit.message <message>", "custom commit message").option("-v, --verbose", "enable verbose logging").option("--dry-run", "dry run").action((options) => __async(null, null, function* () { if (options.verbose) { logger_default.level("debug"); } try { const type = options.major ? "major" : options.minor ? "minor" : options.patch ? "patch" : void 0; if (!type) { logger_default.error("Please specify one of: --patch, --minor, or --major"); process.exit(1); } const cliConfig = { commit: { message: options["commit.message"] }, dryRun: options["dryRun"] }; yield config_default.load(cliConfig); const newVersion = bumpVersion(type); logger_default.info(`Version bumped to${logger_default.COLORS.magenta}`, newVersion); } catch (error) { logger_default.error("Error:", error); process.exit(1); } })); program.parse(); }); } main();