beez-rp 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/LICENSE.md +21 -0
- package/README.md +82 -0
- package/bin/beez-rp.js +36 -0
- package/package.json +77 -0
- package/src/build-gate.js +93 -0
- package/src/changelog-ai.js +52 -0
- package/src/changelog.js +109 -0
- package/src/constants/build-gate.js +24 -0
- package/src/constants/changelog-ai.js +14 -0
- package/src/constants/changelog.js +32 -0
- package/src/constants/cli.js +10 -0
- package/src/constants/index.js +12 -0
- package/src/constants/terminal-ui.js +93 -0
- package/src/constants/versions.js +39 -0
- package/src/index.js +37 -0
- package/src/terminal-ui.js +517 -0
- package/src/testing.js +70 -0
- package/src/versions.js +211 -0
- package/types/build-gate.d.ts +34 -0
- package/types/changelog-ai.d.ts +27 -0
- package/types/changelog.d.ts +52 -0
- package/types/constants/build-gate.d.ts +19 -0
- package/types/constants/changelog-ai.d.ts +11 -0
- package/types/constants/changelog.d.ts +23 -0
- package/types/constants/cli.d.ts +9 -0
- package/types/constants/index.d.ts +11 -0
- package/types/constants/terminal-ui.d.ts +73 -0
- package/types/constants/versions.d.ts +29 -0
- package/types/index.d.ts +18 -0
- package/types/terminal-ui.d.ts +180 -0
- package/types/testing.d.ts +31 -0
- package/types/versions.d.ts +102 -0
package/src/testing.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version bump fixtures for the test suites of every repository that uses
|
|
3
|
+
* `beez-rp`, so `create-version`, the Vercel build gate and any custom release
|
|
4
|
+
* command are checked against the same rule: from a stable version only the
|
|
5
|
+
* next patch, minor or major is allowed.
|
|
6
|
+
*
|
|
7
|
+
* @module testing
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Stable version every fixture bumps from. */
|
|
11
|
+
export const CURRENT_STABLE_VERSION = "1.2.3";
|
|
12
|
+
|
|
13
|
+
/** The only versions allowed after {@link CURRENT_STABLE_VERSION}: next patch, minor and major. */
|
|
14
|
+
export const ALLOWED_NEXT_VERSIONS = Object.freeze(["1.2.4", "1.3.0", "2.0.0"]);
|
|
15
|
+
|
|
16
|
+
/** Every rejected kind of bump from {@link CURRENT_STABLE_VERSION}, grouped by why it is rejected. */
|
|
17
|
+
export const REJECTED_VERSION_BUMPS = Object.freeze({
|
|
18
|
+
unchanged: Object.freeze(["1.2.3"]),
|
|
19
|
+
lower: Object.freeze(["1.2.2", "1.1.9", "0.9.9", "1.2.0", "0.0.1"]),
|
|
20
|
+
"skips patches": Object.freeze(["1.2.5", "1.2.10"]),
|
|
21
|
+
"skips minors": Object.freeze(["1.4.0", "1.10.0"]),
|
|
22
|
+
"skips majors": Object.freeze(["3.0.0", "10.0.0"]),
|
|
23
|
+
"minor bump without resetting the patch": Object.freeze(["1.3.3", "1.3.1"]),
|
|
24
|
+
"major bump without resetting minor and patch": Object.freeze(["2.2.3", "2.0.3", "2.3.0", "2.0.1"]),
|
|
25
|
+
prerelease: Object.freeze([
|
|
26
|
+
"1.2.4-alpha",
|
|
27
|
+
"1.2.4-alpha.1",
|
|
28
|
+
"1.3.0-beta.2",
|
|
29
|
+
"2.0.0-rc.1",
|
|
30
|
+
"1.2.4-canary.0",
|
|
31
|
+
"1.2.4-next.3",
|
|
32
|
+
"1.2.4-dev",
|
|
33
|
+
"1.2.4-snapshot",
|
|
34
|
+
"1.2.4-0",
|
|
35
|
+
"1.2.4-alpha.beta.1",
|
|
36
|
+
"1.2.4-SNAPSHOT-20260926",
|
|
37
|
+
]),
|
|
38
|
+
"build metadata": Object.freeze(["1.2.4+build.5", "1.3.0+sha.8fc0245", "2.0.0-beta.1+exp"]),
|
|
39
|
+
"not a plain X.Y.Z": Object.freeze([
|
|
40
|
+
"1.3",
|
|
41
|
+
"2",
|
|
42
|
+
"1.2.4.0",
|
|
43
|
+
"01.2.4",
|
|
44
|
+
"1.02.4",
|
|
45
|
+
"1.3.00",
|
|
46
|
+
"x.y.z",
|
|
47
|
+
"1.2.x",
|
|
48
|
+
"latest",
|
|
49
|
+
"",
|
|
50
|
+
" 1.2.4",
|
|
51
|
+
"1.2.4 ",
|
|
52
|
+
"v1.2.4",
|
|
53
|
+
"V1.2.4",
|
|
54
|
+
"^1.2.4",
|
|
55
|
+
"~1.3.0",
|
|
56
|
+
">=2.0.0",
|
|
57
|
+
"1.2.4 || 1.3.0",
|
|
58
|
+
]),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* All rejected bumps as `[reason, version]` pairs for table-driven tests.
|
|
63
|
+
*
|
|
64
|
+
* @type {ReadonlyArray<readonly [string, string]>}
|
|
65
|
+
*/
|
|
66
|
+
export const REJECTED_VERSION_BUMP_CASES = Object.freeze(
|
|
67
|
+
Object.entries(REJECTED_VERSION_BUMPS).flatMap(([reason, versions]) =>
|
|
68
|
+
versions.map((version) => /** @type {const} */ ([reason, version]))
|
|
69
|
+
)
|
|
70
|
+
);
|
package/src/versions.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Release version rules: only stable `X.Y.Z` versions exist, and after a
|
|
3
|
+
* version only its next patch, minor or major is allowed (from `1.2.3`:
|
|
4
|
+
* `1.2.4`, `1.3.0` or `2.0.0`). No version can be skipped, repeated or
|
|
5
|
+
* lowered, and prereleases or build metadata are never released.
|
|
6
|
+
*
|
|
7
|
+
* @module versions
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
BREAKING_CHANGE_FOOTER_PATTERN,
|
|
12
|
+
CONVENTIONAL_HEADER_PATTERN,
|
|
13
|
+
FEATURE_COMMIT_TYPE,
|
|
14
|
+
LEGACY_FEATURE_SUBJECT_PATTERN,
|
|
15
|
+
RELEASE_TAG_PREFIX,
|
|
16
|
+
RELEASE_TYPE,
|
|
17
|
+
RELEASE_TYPE_ORDER,
|
|
18
|
+
RELEASE_VERSION_PATTERN,
|
|
19
|
+
SEMVER_PATTERN,
|
|
20
|
+
} from "./constants/versions.js";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {"patch" | "minor" | "major"} ReleaseType
|
|
24
|
+
* @typedef {{ releaseType: ReleaseType, version: string }} NextVersion
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Returns whether a value is a stable `X.Y.Z` release version.
|
|
29
|
+
*
|
|
30
|
+
* @param {unknown} version - Candidate version.
|
|
31
|
+
* @returns {boolean} `true` only for plain `X.Y.Z` without prerelease, metadata, prefix or leading zeros.
|
|
32
|
+
*/
|
|
33
|
+
export function isStableReleaseVersion(version) {
|
|
34
|
+
return typeof version === "string" && RELEASE_VERSION_PATTERN.test(version);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Parses a stable `X.Y.Z` version.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} version - Version such as `0.93.0`.
|
|
41
|
+
* @returns {[number, number, number]} Major, minor and patch numbers.
|
|
42
|
+
* @throws {Error} When the version is not a stable release version.
|
|
43
|
+
*/
|
|
44
|
+
export function parseReleaseVersion(version) {
|
|
45
|
+
const match = RELEASE_VERSION_PATTERN.exec(String(version));
|
|
46
|
+
|
|
47
|
+
if (!match) {
|
|
48
|
+
throw new Error(`beez-rp:parseReleaseVersion expected X.Y.Z, received "${version}"`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Returns the next version for a semver release type.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} version - Current `X.Y.Z` version.
|
|
58
|
+
* @param {ReleaseType} releaseType - One of {@link RELEASE_TYPE}.
|
|
59
|
+
* @returns {string} Next `X.Y.Z` version.
|
|
60
|
+
* @throws {Error} When the version is not stable or the release type is unknown.
|
|
61
|
+
*/
|
|
62
|
+
export function bumpReleaseVersion(version, releaseType) {
|
|
63
|
+
const [major, minor, patch] = parseReleaseVersion(version);
|
|
64
|
+
|
|
65
|
+
switch (releaseType) {
|
|
66
|
+
case RELEASE_TYPE.major:
|
|
67
|
+
return `${major + 1}.0.0`;
|
|
68
|
+
case RELEASE_TYPE.minor:
|
|
69
|
+
return `${major}.${minor + 1}.0`;
|
|
70
|
+
case RELEASE_TYPE.patch:
|
|
71
|
+
return `${major}.${minor}.${patch + 1}`;
|
|
72
|
+
default:
|
|
73
|
+
throw new Error(`beez-rp:bumpReleaseVersion unknown release type "${releaseType}"`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Lists the only versions allowed after the current one: the next patch,
|
|
79
|
+
* minor and major. Anything else would skip versions or go backwards.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} currentVersion - Current `X.Y.Z` version.
|
|
82
|
+
* @returns {NextVersion[]} Allowed next versions, patch first.
|
|
83
|
+
*/
|
|
84
|
+
export function listNextVersions(currentVersion) {
|
|
85
|
+
return RELEASE_TYPE_ORDER.map((releaseType) => ({
|
|
86
|
+
releaseType,
|
|
87
|
+
version: bumpReleaseVersion(currentVersion, releaseType),
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Lists the versions allowed after any previous semver version. A previous
|
|
93
|
+
* prerelease is also followed by its own stable release (`1.0.0-beta.1` →
|
|
94
|
+
* `1.0.0`).
|
|
95
|
+
*
|
|
96
|
+
* @param {string} previousVersion - Previous version, stable or prerelease.
|
|
97
|
+
* @returns {string[] | null} Allowed versions, or `null` when the previous version is not semver.
|
|
98
|
+
*/
|
|
99
|
+
export function listAllowedVersionsAfter(previousVersion) {
|
|
100
|
+
const match = SEMVER_PATTERN.exec(String(previousVersion));
|
|
101
|
+
|
|
102
|
+
if (!match) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const [, core, prerelease] = match;
|
|
107
|
+
const nextVersions = listNextVersions(core).map((candidate) => candidate.version);
|
|
108
|
+
|
|
109
|
+
return prerelease ? [core, ...nextVersions] : nextVersions;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Resolves the version requested through `--bump` or `--set-version`.
|
|
114
|
+
*
|
|
115
|
+
* @param {string} currentVersion - Current `X.Y.Z` version.
|
|
116
|
+
* @param {{ bump: ReleaseType | null, setVersion: string | null }} request - Parsed CLI options.
|
|
117
|
+
* @returns {NextVersion | null} Requested version, or `null` to ask interactively.
|
|
118
|
+
* @throws {Error} With a Spanish message when the request is invalid.
|
|
119
|
+
*/
|
|
120
|
+
export function resolveRequestedVersion(currentVersion, { bump, setVersion }) {
|
|
121
|
+
const nextVersions = listNextVersions(currentVersion);
|
|
122
|
+
|
|
123
|
+
if (bump) {
|
|
124
|
+
return nextVersions.find((candidate) => candidate.releaseType === bump) ?? null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (setVersion === null || setVersion === undefined) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!isStableReleaseVersion(setVersion)) {
|
|
132
|
+
throw new Error(`--set-version espera el formato X.Y.Z y recibió "${setVersion}".`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const match = nextVersions.find((candidate) => candidate.version === setVersion);
|
|
136
|
+
|
|
137
|
+
if (!match) {
|
|
138
|
+
const allowed = nextVersions.map((candidate) => candidate.version).join(", ");
|
|
139
|
+
throw new Error(
|
|
140
|
+
`--set-version ${setVersion} no es válida después de ${currentVersion}: tiene que ser mayor y no saltear versiones. Opciones: ${allowed}.`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return match;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Builds the Git tag name of a release version.
|
|
149
|
+
*
|
|
150
|
+
* @param {string} version - `X.Y.Z` version.
|
|
151
|
+
* @returns {string} Tag such as `v0.94.0`.
|
|
152
|
+
*/
|
|
153
|
+
export function toReleaseTag(version) {
|
|
154
|
+
return `${RELEASE_TAG_PREFIX}${version}`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Returns whether a commit subject is a release bump commit (`0.93.0`).
|
|
159
|
+
*
|
|
160
|
+
* @param {string} subject - Commit subject.
|
|
161
|
+
* @returns {boolean} `true` for version-only subjects.
|
|
162
|
+
*/
|
|
163
|
+
export function isReleaseCommitSubject(subject) {
|
|
164
|
+
return isStableReleaseVersion(subject.trim());
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Suggests the semver release type for the commits that will ship.
|
|
169
|
+
*
|
|
170
|
+
* Breaking changes suggest `major`; features (conventional `feat` or legacy
|
|
171
|
+
* imperative subjects such as "Add ...") suggest `minor`; a set made only of
|
|
172
|
+
* conventional maintenance commits (`fix`, `chore`, `docs`, ...) suggests
|
|
173
|
+
* `patch`. Unknown legacy subjects suggest `minor`.
|
|
174
|
+
*
|
|
175
|
+
* @param {{ subject: string, body?: string }[]} commits - Commits since the last release.
|
|
176
|
+
* @returns {{ releaseType: ReleaseType, reason: string }} Suggested type and a Spanish explanation.
|
|
177
|
+
*/
|
|
178
|
+
export function suggestReleaseType(commits) {
|
|
179
|
+
const shippedCommits = commits.filter((commit) => !isReleaseCommitSubject(commit.subject));
|
|
180
|
+
let hasFeature = false;
|
|
181
|
+
let hasUnknownSubject = false;
|
|
182
|
+
|
|
183
|
+
for (const commit of shippedCommits) {
|
|
184
|
+
const header = CONVENTIONAL_HEADER_PATTERN.exec(commit.subject);
|
|
185
|
+
|
|
186
|
+
if (header?.groups?.breaking || BREAKING_CHANGE_FOOTER_PATTERN.test(commit.body ?? "")) {
|
|
187
|
+
return { releaseType: RELEASE_TYPE.major, reason: "hay cambios incompatibles (breaking change)" };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (header?.groups) {
|
|
191
|
+
hasFeature ||= header.groups.type.toLowerCase() === FEATURE_COMMIT_TYPE;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (LEGACY_FEATURE_SUBJECT_PATTERN.test(commit.subject)) {
|
|
196
|
+
hasFeature = true;
|
|
197
|
+
} else {
|
|
198
|
+
hasUnknownSubject = true;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (hasFeature) {
|
|
203
|
+
return { releaseType: RELEASE_TYPE.minor, reason: "hay funcionalidades nuevas" };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (hasUnknownSubject || shippedCommits.length === 0) {
|
|
207
|
+
return { releaseType: RELEASE_TYPE.minor, reason: "criterio habitual del repositorio" };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return { releaseType: RELEASE_TYPE.patch, reason: "solo hay arreglos y mantenimiento" };
|
|
211
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decides whether Vercel builds a commit (`vercel.json` → `ignoreCommand`).
|
|
3
|
+
*
|
|
4
|
+
* Only a stable `X.Y.Z` version that is the next patch, minor or major of the
|
|
5
|
+
* previous commit's version ships, the same rule `create-version` applies. An
|
|
6
|
+
* unchanged, lower or skipped version (`1.0.0` → `3.0.0`) and any prerelease
|
|
7
|
+
* or build-metadata version skip the build. When the previous version cannot
|
|
8
|
+
* be read there is nothing to compare, so a stable version builds.
|
|
9
|
+
*
|
|
10
|
+
* @module build-gate
|
|
11
|
+
*/
|
|
12
|
+
export type BuildDecision = {
|
|
13
|
+
shouldBuild: boolean;
|
|
14
|
+
reason: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {{ shouldBuild: boolean, reason: string }} BuildDecision
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Decides whether a commit is built.
|
|
21
|
+
*
|
|
22
|
+
* @param {string | null} previousVersion - Version of the previous commit, or `null` when unreadable.
|
|
23
|
+
* @param {string | null} currentVersion - Version of the commit being deployed, or `null` when unreadable.
|
|
24
|
+
* @returns {BuildDecision} Decision and a log line.
|
|
25
|
+
*/
|
|
26
|
+
export declare function decideBuild(previousVersion: string | null, currentVersion: string | null): BuildDecision;
|
|
27
|
+
/**
|
|
28
|
+
* Reads the previous and the current `package.json` versions of a Git
|
|
29
|
+
* checkout and decides whether it is built.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} repositoryRoot - Checkout whose `HEAD` is being deployed.
|
|
32
|
+
* @returns {BuildDecision} Decision and a log line.
|
|
33
|
+
*/
|
|
34
|
+
export declare function decideBuildForCheckout(repositoryRoot: string): BuildDecision;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asks Codex to fill the CHANGELOG `[Unreleased]` block when a release finds it empty.
|
|
3
|
+
*
|
|
4
|
+
* The prompt travels through stdin (`codex exec -`), so the shell command stays a
|
|
5
|
+
* fixed string on Windows, where `codex` is a `.cmd` shim that needs a shell.
|
|
6
|
+
*
|
|
7
|
+
* @module changelog-ai
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Builds the instructions for Codex from the commits that will ship.
|
|
11
|
+
*
|
|
12
|
+
* @param {{ sha: string, subject: string }[]} commits - Unreleased commits, newest first.
|
|
13
|
+
* @param {string} audience - Who reads the changelog, e.g. "quien consume el paquete".
|
|
14
|
+
* @returns {string} Prompt in Spanish.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildChangelogPrompt(commits: {
|
|
17
|
+
sha: string;
|
|
18
|
+
subject: string;
|
|
19
|
+
}[], audience: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Runs Codex non-interactively with the prompt on stdin, showing its progress.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} root - Repository directory where Codex edits CHANGELOG.md.
|
|
24
|
+
* @param {string} prompt - Instructions from {@link buildChangelogPrompt}.
|
|
25
|
+
* @returns {Promise<number>} Codex exit code; {@link CODEX_NOT_FOUND_EXIT_CODE} when the CLI is not installed.
|
|
26
|
+
*/
|
|
27
|
+
export declare function runCodex(root: string, prompt: string): Promise<number>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads and releases CHANGELOG.md in the Keep a Changelog format.
|
|
3
|
+
*
|
|
4
|
+
* Every change adds its entries under `## [Unreleased]`, grouped by change
|
|
5
|
+
* type (`### Added`, `### Changed`, `### Deprecated`, `### Removed`,
|
|
6
|
+
* `### Fixed`, `### Security`). Releasing moves that block under
|
|
7
|
+
* `## [X.Y.Z] - YYYY-MM-DD` and leaves an empty `## [Unreleased]` on top.
|
|
8
|
+
* Headings of older releases without brackets (`## 0.6.0 - 2026-09-23`)
|
|
9
|
+
* remain valid.
|
|
10
|
+
*
|
|
11
|
+
* @module changelog
|
|
12
|
+
*/
|
|
13
|
+
export type ChangelogBlock = {
|
|
14
|
+
label: string;
|
|
15
|
+
heading: string;
|
|
16
|
+
start: number;
|
|
17
|
+
bodyStart: number;
|
|
18
|
+
end: number;
|
|
19
|
+
};
|
|
20
|
+
export type UnreleasedState = {
|
|
21
|
+
exists: boolean;
|
|
22
|
+
entryCount: number;
|
|
23
|
+
unknownSections: string[];
|
|
24
|
+
body: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Describes the `## [Unreleased]` block.
|
|
28
|
+
*
|
|
29
|
+
* @param {string} changelog - CHANGELOG.md contents.
|
|
30
|
+
* @returns {UnreleasedState} Unreleased state.
|
|
31
|
+
*/
|
|
32
|
+
export declare function readUnreleased(changelog: string): UnreleasedState;
|
|
33
|
+
/**
|
|
34
|
+
* Returns the newest released block (the first one that is not `[Unreleased]`).
|
|
35
|
+
*
|
|
36
|
+
* @param {string} changelog - CHANGELOG.md contents.
|
|
37
|
+
* @returns {{ version: string, entryCount: number } | null} Latest release entry.
|
|
38
|
+
*/
|
|
39
|
+
export declare function readLatestRelease(changelog: string): {
|
|
40
|
+
version: string;
|
|
41
|
+
entryCount: number;
|
|
42
|
+
} | null;
|
|
43
|
+
/**
|
|
44
|
+
* Moves the `[Unreleased]` changes under a new version heading and leaves an empty `[Unreleased]` block.
|
|
45
|
+
*
|
|
46
|
+
* @param {string} changelog - CHANGELOG.md contents.
|
|
47
|
+
* @param {string} version - Version being released.
|
|
48
|
+
* @param {string} releaseDate - Date in `YYYY-MM-DD` format.
|
|
49
|
+
* @returns {string} Released changelog.
|
|
50
|
+
* @throws {Error} When `[Unreleased]` is missing, empty or uses an unknown section.
|
|
51
|
+
*/
|
|
52
|
+
export declare function releaseUnreleased(changelog: string, version: string, releaseDate: string): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract between the `beez-rp ignore-build` command and the Vercel
|
|
3
|
+
* `ignoreCommand` wrapper that reads its output.
|
|
4
|
+
*
|
|
5
|
+
* @module constants/build-gate
|
|
6
|
+
*/
|
|
7
|
+
/** Decision printed as the last output line of `beez-rp ignore-build`. */
|
|
8
|
+
export declare const BUILD_DECISION: Readonly<{
|
|
9
|
+
build: "BUILD";
|
|
10
|
+
skip: "SKIP";
|
|
11
|
+
}>;
|
|
12
|
+
/** Git revision whose `package.json` holds the previous version. */
|
|
13
|
+
export declare const PREVIOUS_REVISION = "HEAD^";
|
|
14
|
+
/** Manifest that holds the version. */
|
|
15
|
+
export declare const PACKAGE_MANIFEST_FILE = "package.json";
|
|
16
|
+
/** Exit code of `beez-rp ignore-build` when a decision was printed. */
|
|
17
|
+
export declare const DECISION_EXIT_CODE = 0;
|
|
18
|
+
/** Exit code of `beez-rp ignore-build` when it could not decide; wrappers must skip the build. */
|
|
19
|
+
export declare const GATE_FAILURE_EXIT_CODE = 2;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex invocation used to fill an empty `[Unreleased]` block.
|
|
3
|
+
*
|
|
4
|
+
* @module constants/changelog-ai
|
|
5
|
+
*/
|
|
6
|
+
/** Exit code shells use when a command does not exist. */
|
|
7
|
+
export declare const CODEX_NOT_FOUND_EXIT_CODE = 127;
|
|
8
|
+
/** Fixed Codex command: non-interactive, allowed to edit the workspace, no saved session, prompt on stdin. */
|
|
9
|
+
export declare const CODEX_COMMAND = "codex exec --sandbox workspace-write --ephemeral --color never -";
|
|
10
|
+
/** Length of the abbreviated commit ids listed in the prompt. */
|
|
11
|
+
export declare const PROMPT_SHORT_SHA_LENGTH = 7;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keep a Changelog contract used to read and release `CHANGELOG.md`.
|
|
3
|
+
*
|
|
4
|
+
* @module constants/changelog
|
|
5
|
+
*/
|
|
6
|
+
/** Changelog file released together with `package.json`. */
|
|
7
|
+
export declare const CHANGELOG_FILE = "CHANGELOG.md";
|
|
8
|
+
/** Heading of the block that collects changes not yet released. */
|
|
9
|
+
export declare const UNRELEASED_HEADING = "## [Unreleased]";
|
|
10
|
+
/** Change types allowed as `###` sections, in Keep a Changelog order. */
|
|
11
|
+
export declare const CHANGE_TYPES: readonly string[];
|
|
12
|
+
/** Any release-level heading: `## [Unreleased]`, `## [0.7.0] - 2026-09-26` or `## 0.6.0 - 2026-09-23`. */
|
|
13
|
+
export declare const RELEASE_HEADING_PATTERN: RegExp;
|
|
14
|
+
/** Unreleased heading, case-insensitive, as its own line. */
|
|
15
|
+
export declare const UNRELEASED_LINE_PATTERN: RegExp;
|
|
16
|
+
/** A change entry line. */
|
|
17
|
+
export declare const ENTRY_LINE_PATTERN: RegExp;
|
|
18
|
+
/** A change-type section heading inside a release block. */
|
|
19
|
+
export declare const SECTION_HEADING_PATTERN: RegExp;
|
|
20
|
+
/** Leading whitespace left before the next block after moving `[Unreleased]`. */
|
|
21
|
+
export declare const LEADING_WHITESPACE_PATTERN: RegExp;
|
|
22
|
+
/** Line break in a changelog written on any platform. */
|
|
23
|
+
export declare const LINE_BREAK_PATTERN: RegExp;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Facade of every `beez-rp` constant, grouped by domain.
|
|
3
|
+
*
|
|
4
|
+
* @module constants
|
|
5
|
+
*/
|
|
6
|
+
export * from "./build-gate.js";
|
|
7
|
+
export * from "./changelog.js";
|
|
8
|
+
export * from "./changelog-ai.js";
|
|
9
|
+
export * from "./cli.js";
|
|
10
|
+
export * from "./terminal-ui.js";
|
|
11
|
+
export * from "./versions.js";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout, ANSI and key contracts of the dependency-free terminal UI.
|
|
3
|
+
*
|
|
4
|
+
* @module constants/terminal-ui
|
|
5
|
+
*/
|
|
6
|
+
/** Widest box drawn, so lines stay readable on large terminals. */
|
|
7
|
+
export declare const MAX_BOX_WIDTH = 84;
|
|
8
|
+
/** Width assumed when stdout does not report its columns. */
|
|
9
|
+
export declare const FALLBACK_TERMINAL_WIDTH = 80;
|
|
10
|
+
/** Columns kept free at the right of the terminal when sizing a box. */
|
|
11
|
+
export declare const TERMINAL_RIGHT_MARGIN = 2;
|
|
12
|
+
/** Horizontal padding inside a box, per side. */
|
|
13
|
+
export declare const BOX_PADDING = 1;
|
|
14
|
+
/** Width of the label column of status rows. */
|
|
15
|
+
export declare const ROW_LABEL_WIDTH = 16;
|
|
16
|
+
/** Spinner animation frames. */
|
|
17
|
+
export declare const SPINNER_FRAMES: readonly string[];
|
|
18
|
+
/** Delay between spinner frames. */
|
|
19
|
+
export declare const SPINNER_INTERVAL_MS = 80;
|
|
20
|
+
/** Exit code conventionally used after Ctrl+C. */
|
|
21
|
+
export declare const INTERRUPTED_EXIT_CODE = 130;
|
|
22
|
+
/** Splits styled text into ANSI escape sequences and single code points. */
|
|
23
|
+
export declare const ANSI_TOKEN_PATTERN: RegExp;
|
|
24
|
+
/** First character of every ANSI escape sequence. */
|
|
25
|
+
export declare const ANSI_ESCAPE = "\u001B";
|
|
26
|
+
/** ANSI control sequences used by boxes, spinners and prompts. */
|
|
27
|
+
export declare const ANSI_SEQUENCE: Readonly<{
|
|
28
|
+
reset: "\u001B[0m";
|
|
29
|
+
hideCursor: "\u001B[?25l";
|
|
30
|
+
showCursor: "\u001B[?25h";
|
|
31
|
+
clearLine: "\r\u001B[2K";
|
|
32
|
+
clearBelow: "\u001B[0J";
|
|
33
|
+
}>;
|
|
34
|
+
/** Border color of each box tone. */
|
|
35
|
+
export declare const BOX_TONE: Readonly<{
|
|
36
|
+
neutral: "gray";
|
|
37
|
+
info: "cyan";
|
|
38
|
+
success: "green";
|
|
39
|
+
warning: "yellow";
|
|
40
|
+
danger: "red";
|
|
41
|
+
accent: "magenta";
|
|
42
|
+
}>;
|
|
43
|
+
/** Nerd Font glyphs (Font Awesome and Octicons sets) used as status icons. */
|
|
44
|
+
export declare const ICON_GLYPH: Readonly<{
|
|
45
|
+
success: "";
|
|
46
|
+
failure: "";
|
|
47
|
+
warning: "";
|
|
48
|
+
info: "";
|
|
49
|
+
pending: "";
|
|
50
|
+
arrow: "";
|
|
51
|
+
bullet: "";
|
|
52
|
+
star: "";
|
|
53
|
+
rocket: "";
|
|
54
|
+
}>;
|
|
55
|
+
/** Label/value rows (`renderRow`): the value starts after a gap of two or more spaces. */
|
|
56
|
+
export declare const VALUE_COLUMN_PATTERN: RegExp;
|
|
57
|
+
/** Leading marker (icon, arrow, bullet or `1.`, never a word) followed by a space, used as hanging indent. */
|
|
58
|
+
export declare const HANGING_MARKER_PATTERN: RegExp;
|
|
59
|
+
/** Options that can be picked with a single digit key (1-9). */
|
|
60
|
+
export declare const MAX_NUMBERED_OPTIONS = 9;
|
|
61
|
+
/** A single digit key that picks a numbered option. */
|
|
62
|
+
export declare const NUMBER_KEY_PATTERN: RegExp;
|
|
63
|
+
/** Seconds in a minute, used to format durations. */
|
|
64
|
+
export declare const SECONDS_PER_MINUTE = 60;
|
|
65
|
+
/** Milliseconds in a second, used to format durations. */
|
|
66
|
+
export declare const MILLISECONDS_PER_SECOND = 1000;
|
|
67
|
+
/** Key names (`readline` keypress events) handled by the select prompt. */
|
|
68
|
+
export declare const PROMPT_KEY: Readonly<{
|
|
69
|
+
interrupt: "c";
|
|
70
|
+
previous: readonly string[];
|
|
71
|
+
next: readonly string[];
|
|
72
|
+
confirm: readonly string[];
|
|
73
|
+
}>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Release version rules shared by `create-version` and the Vercel build gate.
|
|
3
|
+
*
|
|
4
|
+
* @module constants/versions
|
|
5
|
+
*/
|
|
6
|
+
/** Semver release types, from the smallest to the largest change. */
|
|
7
|
+
export declare const RELEASE_TYPE: Readonly<{
|
|
8
|
+
patch: "patch";
|
|
9
|
+
minor: "minor";
|
|
10
|
+
major: "major";
|
|
11
|
+
}>;
|
|
12
|
+
/** Release types in the order they are offered: patch, minor, major. */
|
|
13
|
+
export declare const RELEASE_TYPE_ORDER: readonly ("major" | "minor" | "patch")[];
|
|
14
|
+
/** Stable `X.Y.Z` release version: no prerelease, build metadata, prefix or leading zeros. */
|
|
15
|
+
export declare const RELEASE_VERSION_PATTERN: RegExp;
|
|
16
|
+
/** Any semver version, capturing its `X.Y.Z` core and optional prerelease. */
|
|
17
|
+
export declare const SEMVER_PATTERN: RegExp;
|
|
18
|
+
/** Prefix of the annotated Git tags that mark each release (`v0.93.0`). */
|
|
19
|
+
export declare const RELEASE_TAG_PREFIX = "v";
|
|
20
|
+
/** `git log --grep` pattern of release commit subjects (`0.93.0`). */
|
|
21
|
+
export declare const RELEASE_COMMIT_SUBJECT_GREP: string;
|
|
22
|
+
/** Conventional commit header: `type(scope)!: subject`. */
|
|
23
|
+
export declare const CONVENTIONAL_HEADER_PATTERN: RegExp;
|
|
24
|
+
/** Footer that marks a breaking change in a conventional commit body. */
|
|
25
|
+
export declare const BREAKING_CHANGE_FOOTER_PATTERN: RegExp;
|
|
26
|
+
/** Conventional commit type that ships user-visible features. */
|
|
27
|
+
export declare const FEATURE_COMMIT_TYPE = "feat";
|
|
28
|
+
/** Imperative verbs used by legacy, non-conventional feature subjects. */
|
|
29
|
+
export declare const LEGACY_FEATURE_SUBJECT_PATTERN: RegExp;
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `beez-rp`: dependency-free release process shared by the Beez projects.
|
|
3
|
+
*
|
|
4
|
+
* - `beez-rp/versions`: stable `X.Y.Z` rules; only the next patch, minor or major is allowed.
|
|
5
|
+
* - `beez-rp/build-gate`: Vercel `ignoreCommand` decision built on those rules.
|
|
6
|
+
* - `beez-rp/changelog` and `beez-rp/changelog-ai`: Keep a Changelog release and Codex fill-in.
|
|
7
|
+
* - `beez-rp/terminal-ui`: boxes, spinners and prompts for release commands.
|
|
8
|
+
* - `beez-rp/testing`: shared version bump fixtures for consumer test suites.
|
|
9
|
+
* - `beez-rp/constants`: every constant above, grouped by domain.
|
|
10
|
+
*
|
|
11
|
+
* @module beez-rp
|
|
12
|
+
*/
|
|
13
|
+
export * from "./build-gate.js";
|
|
14
|
+
export * from "./changelog.js";
|
|
15
|
+
export * from "./changelog-ai.js";
|
|
16
|
+
export * from "./versions.js";
|
|
17
|
+
export { ICON, countTerminalRows, formatDuration, getPromptWaitMs, measureActiveMs, paint, print, renderBanner, renderBox, renderRow, renderStepHeader, resolveBoxWidth, resolveNumberKey, select, startSpinner, visibleWidth, wrapStyledLine, } from "./terminal-ui.js";
|
|
18
|
+
export * from "./constants/index.js";
|