Skip to content

Commit

Permalink
refactor: cleanup ts types
Browse files Browse the repository at this point in the history
  • Loading branch information
eglavin committed Sep 29, 2023
1 parent d609182 commit 46570f7
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 69 deletions.
23 changes: 13 additions & 10 deletions src/changelog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { resolve } from "node:path";
import { constants, accessSync, writeFileSync, readFileSync } from "node:fs";
import conventionalChangelog from "conventional-changelog";
import type { ForkConfigOptions } from "./configuration.js";
import type { bumpVersion } from "./version.js";
import type { BumpVersion } from "./version.js";

function createChangelog(options: ForkConfigOptions) {
function createChangelog(options: ForkConfigOptions): string {
const changelogPath = resolve(options.changelog);

try {
Expand All @@ -31,7 +31,7 @@ const RELEASE_PATTERN = /(^#+ \[?[0-9]+\.[0-9]+\.[0-9]+|<a name=)/m;
* Gets the rest of the changelog from the latest release onwards.
* @see {@link RELEASE_PATTERN}
*/
function getOldReleaseContent(changelogPath: string) {
function getOldReleaseContent(changelogPath: string): string {
const fileContents = readFileSync(changelogPath, "utf-8");
const oldContentStart = fileContents.search(RELEASE_PATTERN);

Expand All @@ -41,10 +41,7 @@ function getOldReleaseContent(changelogPath: string) {
return "";
}

function getChanges(
options: ForkConfigOptions,
bumpResult: Awaited<ReturnType<typeof bumpVersion>>,
) {
function getChanges(options: ForkConfigOptions, bumpResult: BumpVersion): Promise<string> {
return new Promise<string>((resolve, reject) => {
let newContent = "";

Expand All @@ -58,7 +55,7 @@ function getChanges(
warn: (...message: string[]) => options.log("conventional-changelog: ", ...message),
},
{
version: bumpResult.next,
version: bumpResult.nextVersion,
},
{
merges: null,
Expand All @@ -78,10 +75,16 @@ function getChanges(
});
}

type UpdateChangelog = {
changelogPath: string;
oldContent: string;
newContent: string;
};

export async function updateChangelog(
options: ForkConfigOptions,
bumpResult: Awaited<ReturnType<typeof bumpVersion>>,
) {
bumpResult: BumpVersion,
): Promise<UpdateChangelog> {
if (options.header.search(RELEASE_PATTERN) !== -1) {
throw new Error("Header cannot contain release pattern"); // Need to ensure the header doesn't contain the release pattern
}
Expand Down
16 changes: 11 additions & 5 deletions src/commit.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { createExecute } from "./utils/execute-file.js";
import { formatCommitMessage } from "./utils/format-commit-message.js";
import type { ForkConfigOptions } from "./configuration.js";
import type { bumpVersion } from "./version.js";
import type { BumpVersion } from "./version.js";

type CommitChanges = {
filesToCommit: string[];
gitAddOutput?: string;
gitCommitOutput?: string;
};

export async function commitChanges(
options: ForkConfigOptions,
bumpResult: Awaited<ReturnType<typeof bumpVersion>>,
) {
bumpResult: BumpVersion,
): Promise<CommitChanges> {
const filesToCommit: string[] = [options.changelog];

for (const file of bumpResult.files) {
Expand Down Expand Up @@ -35,8 +41,8 @@ export async function commitChanges(
...shouldCommitAll,
"-m",
formatCommitMessage(
options.changelogPresetConfig?.releaseCommitMessageFormat || "chore(release): {{currentTag}}",
bumpResult.next,
options.changelogPresetConfig?.releaseCommitMessageFormat,
bumpResult.nextVersion,
),
);

Expand Down
39 changes: 30 additions & 9 deletions src/tag.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,54 @@
import { createExecute } from "./utils/execute-file.js";
import { formatCommitMessage } from "./utils/format-commit-message.js";
import type { ForkConfigOptions } from "./configuration.js";
import type { bumpVersion } from "./version.js";
import type { BumpVersion } from "./version.js";

type TagChanges = {
gitTagOutput: string;
currentBranchName: string;
hasPackageJson: boolean;
pushMessage: string;
publishMessage: string;
};

export async function tagChanges(
options: ForkConfigOptions,
bumpResult: Awaited<ReturnType<typeof bumpVersion>>,
) {
bumpResult: BumpVersion,
): Promise<TagChanges> {
const { executeGit } = createExecute(options);

const shouldSign = options.sign ? "-s" : "-a";
const tag = `${options.tagPrefix}${bumpResult.next}`;
/** @example "v1.2.3" or "version/1.2.3" */
const tag = `${options.tagPrefix}${bumpResult.nextVersion}`;

const gitTagOutput = await executeGit(
"tag",
shouldSign,
tag,
"-m",
formatCommitMessage(
options.changelogPresetConfig?.releaseCommitMessageFormat || "chore(release): {{currentTag}}",
bumpResult.next,
options.changelogPresetConfig?.releaseCommitMessageFormat,
bumpResult.nextVersion,
),
);

// Get the current branch name
const gitRevParse = await executeGit("rev-parse", "--abbrev-ref", "HEAD");
const currentBranchName = await executeGit("rev-parse", "--abbrev-ref", "HEAD");

const pushMessage = `Run \`git push --follow-tags origin ${currentBranchName.trim()}\` to push the tag.`;

const hasPackageJson = bumpResult.files.some((file) => file.name === "package.json");
const isPreRelease = `${bumpResult.releaseType}`.startsWith("pre");
const publishMessage = isPreRelease
? `Run \`npm publish --tag ${
typeof options.preReleaseTag === "string" ? options.preReleaseTag : "prerelease"
}\` to publish the package.`
: `Run \`npm publish\` to publish the package.`;

return {
gitTagOutput,
gitRevParse,
currentBranchName,
hasPackageJson,
pushMessage,
publishMessage,
};
}
6 changes: 4 additions & 2 deletions src/utils/execute-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import type { ForkConfigOptions } from "../configuration.js";

export function createExecute(options: ForkConfigOptions) {
/**
* Executes a git command with the given arguments.
* Executes a git command with the given arguments and returns the output.
*/
async function executeGit(...execArgs: (string | undefined)[]) {
async function executeGit(...execArgs: (string | undefined)[]): Promise<string> {
const args = execArgs.filter(Boolean) as string[];

options.log(`Executing: git ${args.join(" ")}`);
Expand All @@ -22,6 +22,8 @@ export function createExecute(options: ForkConfigOptions) {
});
});
}

return "";
}

return {
Expand Down
12 changes: 11 additions & 1 deletion src/utils/format-commit-message.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
export function formatCommitMessage(message: string, newVersion: string): string {
/**
* Formats the commit message by replacing the `{{currentTag}}` placeholder
* globally with the new version.
*
* Falls back to `chore(release): {{currentTag}}` if message is argument is falsy.
*/
export function formatCommitMessage(message: string | undefined, newVersion: string): string {
if (!message) {
message = "chore(release): {{currentTag}}";
}

return message.replace(new RegExp("{{currentTag}}", "g"), newVersion);
}
87 changes: 45 additions & 42 deletions src/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@ import detectNewLine from "detect-newline";
import { stringifyPackage } from "./libs/stringify-package.js";
import type { ForkConfigOptions } from "./configuration.js";

function getFile(options: ForkConfigOptions, fileToGet: string) {
type FileState = {
name: string;
path: string;
type: "package-file" | ({} & string); // eslint-disable-line @typescript-eslint/ban-types
version: string;
isPrivate: boolean;
};

function getFile(options: ForkConfigOptions, fileToGet: string): FileState | undefined {
try {
const fileExtension = extname(fileToGet);
if (fileExtension === ".json") {
Expand All @@ -20,9 +28,13 @@ function getFile(options: ForkConfigOptions, fileToGet: string) {
// Return if version property exists
if (parsedJson.version) {
return {
name: fileToGet,
path: filePath,
type: "package-file",
version: parsedJson.version,
isPrivate:
"private" in parsedJson &&
(typeof parsedJson.private === "boolean" ? parsedJson.private : false),
};
}
}
Expand All @@ -32,7 +44,7 @@ function getFile(options: ForkConfigOptions, fileToGet: string) {
}
}

async function getLatestGitTagVersion(tagPrefix: string | undefined) {
async function getLatestGitTagVersion(tagPrefix: string | undefined): Promise<string> {
const gitTags = await gitSemverTags({ tagPrefix });
if (!gitTags.length) {
return "1.0.0";
Expand All @@ -51,21 +63,22 @@ async function getLatestGitTagVersion(tagPrefix: string | undefined) {
return cleanedTags.sort(semver.rcompare)[0];
}

type CurrentVersion = {
currentVersion: string;
files: FileState[];
};

/**
* Get the current version from the given files and find their locations.
*/
async function getCurrentVersion(options: ForkConfigOptions) {
const files: { path: string; name: string; type: string }[] = [];
async function getCurrentVersion(options: ForkConfigOptions): Promise<CurrentVersion> {
const files: FileState[] = [];
const versions: string[] = [];

for (const file of options.outFiles) {
const fileState = getFile(options, file);
if (fileState) {
files.push({
name: file,
path: fileState.path,
type: fileState.type,
});
files.push(fileState);

if (options.currentVersion) {
continue;
Expand All @@ -87,7 +100,7 @@ async function getCurrentVersion(options: ForkConfigOptions) {
if (version) {
return {
files: [],
version,
currentVersion: version,
};
}
}
Expand All @@ -99,7 +112,7 @@ async function getCurrentVersion(options: ForkConfigOptions) {

return {
files,
version: versions[0],
currentVersion: versions[0],
};
}

Expand All @@ -110,7 +123,7 @@ async function getCurrentVersion(options: ForkConfigOptions) {
* - "minor" => 1
* - "major" => 2
*/
function getPriority(type?: string) {
function getPriority(type?: string): number {
return ["patch", "minor", "major"].indexOf(type || "");
}

Expand All @@ -121,7 +134,7 @@ function getPriority(type?: string) {
* - "minor"
* - "major"
*/
function getVersionType(version: string) {
function getVersionType(version: string): "patch" | "minor" | "major" | undefined {
const parseVersion = semver.parse(version);
if (parseVersion?.major) {
return "major";
Expand Down Expand Up @@ -160,22 +173,23 @@ function getReleaseType(
return `pre${releaseType}`;
}

type NextVersion = {
nextVersion: string;
level?: number;
preMajor?: boolean;
reason?: string;
releaseType?: ReleaseType;
};

/**
* Get the next version from the given files.
*/
async function getNextVersion(
options: ForkConfigOptions,
currentVersion: string,
): Promise<{
version: string;

level?: number;
preMajor?: boolean;
reason?: string;
releaseType?: ReleaseType;
}> {
): Promise<NextVersion> {
if (options.nextVersion && semver.valid(options.nextVersion)) {
return { version: options.nextVersion };
return { nextVersion: options.nextVersion };
}

const preMajor = semver.lt(currentVersion, "1.0.0");
Expand All @@ -199,7 +213,7 @@ async function getNextVersion(
return Object.assign(recommendedBump, {
preMajor,
releaseType,
version:
nextVersion:
semver.inc(
currentVersion,
releaseType,
Expand All @@ -216,7 +230,7 @@ function updateFile(
fileToUpdate: string,
type: string,
nextVersion: string,
) {
): void {
try {
if (type === "package-file") {
if (!lstatSync(fileToUpdate).isFile()) return;
Expand All @@ -240,32 +254,21 @@ function updateFile(
}
}

export async function bumpVersion(options: ForkConfigOptions): Promise<{
current: string;
next: string;
export type BumpVersion = CurrentVersion & NextVersion;

files: {
name: string;
path: string;
type: string;
}[];
level?: number;
preMajor?: boolean;
reason?: string;
releaseType?: ReleaseType;
}> {
export async function bumpVersion(options: ForkConfigOptions): Promise<BumpVersion> {
const current = await getCurrentVersion(options);
const next = await getNextVersion(options, current.version);
const next = await getNextVersion(options, current.currentVersion);

for (const outFile of current.files) {
updateFile(options, outFile.path, outFile.type, next.version);
updateFile(options, outFile.path, outFile.type, next.nextVersion);
}

return {
current: current.version,
next: next.version,

currentVersion: current.currentVersion,
files: current.files,

nextVersion: next.nextVersion,
level: next.level,
preMajor: next.preMajor,
reason: next.reason,
Expand Down

0 comments on commit 46570f7

Please sign in to comment.