Skip to content

Commit

Permalink
perf: parse config after report generation
Browse files Browse the repository at this point in the history
  • Loading branch information
jdanil committed Jun 6, 2022
1 parent 3df883f commit 6a2bc46
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 177 deletions.
52 changes: 24 additions & 28 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,6 @@ export const cli = async (): Promise<void> => {
const packageManager = args["package-manager"] as PackageManager;
const all = args["all"] as boolean;
const json = args["json"] as boolean;
const { overrides, threshold } = await getConfiguration(args);
const driftCollective = validateThreshold(threshold?.drift?.collective);
const driftIndividual = validateThreshold(threshold?.drift?.individual);
const pulseCollective = validateThreshold(threshold?.pulse?.collective);
const pulseIndividual = validateThreshold(threshold?.pulse?.individual);
const releasesCollective = validateThreshold(threshold?.releases?.collective);
const releasesIndividual = validateThreshold(threshold?.releases?.individual);
const majorCollective = validateThreshold(threshold?.major?.collective);
const majorIndividual = validateThreshold(threshold?.major?.individual);
const minorCollective = validateThreshold(threshold?.minor?.collective);
const minorIndividual = validateThreshold(threshold?.minor?.individual);
const patchCollective = validateThreshold(threshold?.patch?.collective);
const patchIndividual = validateThreshold(threshold?.patch?.individual);

// run libyear
try {
Expand All @@ -44,24 +31,33 @@ export const cli = async (): Promise<void> => {
{ all },
);

const threshold = {
driftCollective,
driftIndividual,
pulseCollective,
pulseIndividual,
releasesCollective,
releasesIndividual,
majorCollective,
majorIndividual,
minorCollective,
minorIndividual,
patchCollective,
patchIndividual,
};

if (json) {
console.log(JSON.stringify(report));
} else {
const { overrides, threshold } = await getConfiguration(args).then(
({ overrides, threshold }) => ({
overrides,
threshold: {
driftCollective: validateThreshold(threshold?.drift?.collective),
driftIndividual: validateThreshold(threshold?.drift?.individual),
pulseCollective: validateThreshold(threshold?.pulse?.collective),
pulseIndividual: validateThreshold(threshold?.pulse?.individual),
releasesCollective: validateThreshold(
threshold?.releases?.collective,
),
releasesIndividual: validateThreshold(
threshold?.releases?.individual,
),
majorCollective: validateThreshold(threshold?.major?.collective),
majorIndividual: validateThreshold(threshold?.major?.individual),
minorCollective: validateThreshold(threshold?.minor?.collective),
minorIndividual: validateThreshold(threshold?.minor?.individual),
patchCollective: validateThreshold(threshold?.patch?.collective),
patchIndividual: validateThreshold(threshold?.patch?.individual),
},
}),
);

print(report, threshold, overrides);
}
} catch (error) {
Expand Down
110 changes: 55 additions & 55 deletions src/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,46 +18,45 @@ type ParsedDependencies = Record<
const getParsedDependencies = async (
packageManager: PackageManager,
cmd: string,
): Promise<ParsedDependencies> => {
const stdout = await execute(cmd);

switch (packageManager) {
case "pnpm":
return merge(
...(JSON.parse(stdout) as [
ParsedDependencies,
...ParsedDependencies[],
]),
) as ParsedDependencies;
case "berry":
return {
dependencies: merge(
...(stdout
.split("\n")
.map(
(dependency) =>
JSON.parse(dependency) as {
value: string;
children: {
Version: string;
};
): Promise<ParsedDependencies> =>
execute(cmd).then((stdout) => {
switch (packageManager) {
case "pnpm":
return merge(
...(JSON.parse(stdout) as [
ParsedDependencies,
...ParsedDependencies[],
]),
) as ParsedDependencies;
case "berry":
return {
dependencies: merge(
...(stdout
.split("\n")
.map(
(dependency) =>
JSON.parse(dependency) as {
value: string;
children: {
Version: string;
};
},
)
.filter((dependency) => !/@workspace:/.test(dependency.value))
.map((dependency) => ({
[dependency.value.split(/@(npm|patch|workspace):/)[0]]: {
version: dependency.children.Version,
},
)
.filter((dependency) => !/@workspace:/.test(dependency.value))
.map((dependency) => ({
[dependency.value.split(/@(npm|patch|workspace):/)[0]]: {
version: dependency.children.Version,
},
})) as [ParsedDependency, ...ParsedDependency[]]),
) as ParsedDependency,
devDependencies: {},
};
case "npm":
case "yarn":
default:
return JSON.parse(stdout) as ParsedDependencies;
}
};
})) as [ParsedDependency, ...ParsedDependency[]]),
) as ParsedDependency,
devDependencies: {},
};
case "npm":
case "yarn":
default:
return JSON.parse(stdout) as ParsedDependencies;
}
});

export const getDependencies = async (
packageManager: PackageManager,
Expand All @@ -71,21 +70,22 @@ export const getDependencies = async (
} as Record<PackageManager, string>
)[packageManager] ?? "npm ls --depth=0 --json --silent";

const json = await getParsedDependencies(packageManager, cmd);

return new Map(
Object.entries({
...json.dependencies,
...json.devDependencies,
})
.map(([dependency, data]) => [
dependency,
data.version ??
(
(data.required as { version?: string })?.version ||
(data.required as string)
).replace(/[<=>^~]+/u, ""),
])
.filter(([_, version]) => valid(version)) as [[string, string]],
return getParsedDependencies(packageManager, cmd).then(
(json) =>
new Map(
Object.entries({
...json.dependencies,
...json.devDependencies,
})
.map(([dependency, data]) => [
dependency,
data.version ??
(
(data.required as { version?: string })?.version ||
(data.required as string)
).replace(/[<=>^~]+/u, ""),
])
.filter(([_, version]) => valid(version)) as [[string, string]],
),
);
};
13 changes: 5 additions & 8 deletions src/execute.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { ExecaReturnValue, execaCommand } from "execa";
import { execaCommand } from "execa";

export const execute = async (cmd: string): Promise<string> => {
try {
return (await execaCommand(cmd)).stdout;
} catch (error) {
return (error as ExecaReturnValue).stdout;
}
};
export const execute = async (cmd: string): Promise<string> =>
execaCommand(cmd)
.then(({ stdout }) => stdout)
.catch(({ stdout }) => stdout as string);
124 changes: 63 additions & 61 deletions src/libyear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,69 +15,71 @@ const { compare, sort, valid } = semver;
export const libyear = async (
packageManager: PackageManager,
flags?: { all?: boolean },
): Promise<Dependencies> => {
const awaitedDependencies = Array.from(
(await getDependencies(packageManager, flags)).entries(),
).map(async ([dependency, currentVersion]) => {
const releaseTimeObj =
(await getReleaseTime(packageManager, dependency)) ?? {};
const releaseTimeMap = new Map(Object.entries(releaseTimeObj));
): Promise<Dependencies> =>
Promise.all(
Array.from((await getDependencies(packageManager, flags)).entries()).map(
([dependency, currentVersion]) =>
getReleaseTime(packageManager, dependency).then((releaseTimeObj) => {
const releaseTimeMap = new Map(Object.entries(releaseTimeObj));

const allVersionsMap = getSanitisedReleases(releaseTimeMap);
const stableVersionsMap = getStableReleases(allVersionsMap);
const allVersions = Array.from(allVersionsMap.keys());
const stableVersions = Array.from(stableVersionsMap.keys());
const allVersionsMap = getSanitisedReleases(releaseTimeMap);
const stableVersionsMap = getStableReleases(allVersionsMap);
const allVersions = Array.from(allVersionsMap.keys());
const stableVersions = Array.from(stableVersionsMap.keys());

const latestAllVersion = sort(allVersions).slice(-1)[0];
const latestStableVersion = sort(stableVersions).slice(-1)[0];
const latestAllVersion = sort(allVersions).slice(-1)[0];
const latestStableVersion = sort(stableVersions).slice(-1)[0];

const diffAllVersions = allVersions.slice(
allVersions.findIndex((version) => version === currentVersion) + 1,
allVersions.findIndex((version) => version === latestStableVersion) + 1,
);
const diffStableVersions = diffAllVersions.filter((version) =>
stableVersions.includes(version),
);
const diffAllVersions = allVersions.slice(
allVersions.findIndex((version) => version === currentVersion) + 1,
allVersions.findIndex(
(version) => version === latestStableVersion,
) + 1,
);
const diffStableVersions = diffAllVersions.filter((version) =>
stableVersions.includes(version),
);

const drift = calculateDrift(
allVersionsMap.get(currentVersion),
allVersionsMap.get(latestStableVersion),
);
const pulse = calculatePulse(
Array.from(allVersionsMap.values()).sort().slice(-1)[0],
);
const releases = diffStableVersions.length;
const major = getReleasesByType(
[currentVersion, ...diffStableVersions],
"major",
).length;
const minor = getReleasesByType(
[currentVersion, ...diffStableVersions],
"minor",
).length;
const patch = getReleasesByType(
[currentVersion, ...diffStableVersions],
"patch",
).length;
const available =
[latestStableVersion, latestAllVersion]
.filter((version) => valid(version))
.find(
(version) =>
compare(currentVersion, version, { includePrerelease: true }) < 0,
) ?? "N/A";
const drift = calculateDrift(
allVersionsMap.get(currentVersion),
allVersionsMap.get(latestStableVersion),
);
const pulse = calculatePulse(
Array.from(allVersionsMap.values()).sort().slice(-1)[0],
);
const releases = diffStableVersions.length;
const major = getReleasesByType(
[currentVersion, ...diffStableVersions],
"major",
).length;
const minor = getReleasesByType(
[currentVersion, ...diffStableVersions],
"minor",
).length;
const patch = getReleasesByType(
[currentVersion, ...diffStableVersions],
"patch",
).length;
const available =
[latestStableVersion, latestAllVersion]
.filter((version) => valid(version))
.find(
(version) =>
compare(currentVersion, version, {
includePrerelease: true,

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.

Check failure on line 69 in src/libyear.ts

View workflow job for this annotation

GitHub Actions / Scheduled fitness function verification

Argument of type '{ includePrerelease: boolean; }' is not assignable to parameter of type 'boolean | Options'.
}) < 0,
) ?? "N/A";

return {
dependency,
drift,
pulse,
releases,
major,
minor,
patch,
available,
};
});

return Promise.all(awaitedDependencies);
};
return {
dependency,
drift,
pulse,
releases,
major,
minor,
patch,
available,
};
}),
),
);
7 changes: 4 additions & 3 deletions src/package-manager.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as path from "node:path";

import { execaCommand } from "execa";
import { default as semver } from "semver";

import { execute } from "./execute.js";
import type { PackageManager } from "./types.js";

const { satisfies } = semver;
Expand All @@ -24,8 +24,9 @@ export const getParsedPackageManager = (
export const getInferredPackageManager = async (): Promise<PackageManager> => {
const packageManager = path.basename(process.env.npm_execpath || "npm");
if (packageManager.startsWith("yarn")) {
const { stdout } = await execaCommand("yarn --version");
return satisfies(stdout, "^0 || ^1") ? "yarn" : "berry";
return satisfies(await execute("yarn --version"), "^0 || ^1")
? "yarn"
: "berry";
} else if (packageManager.startsWith("pnpm")) {
return Promise.resolve("pnpm");
} else {
Expand Down
Loading

0 comments on commit 6a2bc46

Please sign in to comment.