Skip to content

Commit

Permalink
refactor: better tree shaping
Browse files Browse the repository at this point in the history
  • Loading branch information
mxdvl committed Jan 24, 2023
1 parent 2f2b82b commit ce37682
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 95 deletions.
4 changes: 4 additions & 0 deletions colours.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {
blue,
cyan,
gray,
green,
red,
yellow,
} from "https://deno.land/[email protected]/fmt/colors.ts";

Expand All @@ -12,6 +14,8 @@ export const colour = {
file: cyan,
subdued: gray,
version: yellow,
valid: green,
invalid: red,
};

export const format = (name: string, range: Range) =>
Expand Down
15 changes: 10 additions & 5 deletions fetch_peer_dependencies.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ Deno.test("Can get peer dependencies", async () => {
{
name: "@guardian/core-web-vitals",
range: new Range("2.0.2"),
versions: [new SemVer("2.0.2")],
version: new SemVer("2.0.2"),
dependencies: [],
peers: [
{
name: "@guardian/libs",
Expand Down Expand Up @@ -50,7 +51,8 @@ Deno.test("Can get optional peer dependencies", async () => {
{
name: "@guardian/libs",
range: new Range("12.0.0"),
versions: [new SemVer("12.0.0")],
version: new SemVer("12.0.0"),
dependencies: [],
peers: [
{
name: "tslib",
Expand Down Expand Up @@ -78,7 +80,8 @@ Deno.test("Will fail on optional dependencies that are defined locally", async (
{
name: "@guardian/libs",
range: new Range("12.0.0"),
versions: [new SemVer("12.0.0")],
version: new SemVer("12.0.0"),
dependencies: [],
peers: [
{
name: "tslib",
Expand All @@ -95,13 +98,15 @@ Deno.test("Will fail on optional dependencies that are defined locally", async (
{
name: "tslib",
range: new Range("2.4.1"),
versions: [new SemVer("2.4.1")],
version: new SemVer("2.4.1"),
dependencies: [],
peers: [],
},
{
name: "typescript",
range: new Range("4.2.2"),
versions: [new SemVer("4.2.2")],
version: new SemVer("4.2.2"),
dependencies: [],
peers: [],
},
]);
Expand Down
85 changes: 42 additions & 43 deletions fetch_peer_dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,19 @@ import {
import type { Dependency, RegistryDependency } from "./types.ts";

const { parseAsync: parse_peers } = object({
versions: record(object({
version: string(),
dependencies: record(string()).optional(),
peerDependencies: record(string()).optional(),
peerDependenciesMeta: record(object({ optional: boolean() }))
.optional(),
})),
versions: record(
object({
version: string(),
dependencies: record(string()).optional(),
peerDependencies: record(string()).optional(),
peerDependenciesMeta: record(object({ optional: boolean() })).optional(),
}),
),
});

export const fetch_peer_dependencies = (
dependencies: Dependency[],
{ verbose = false, cache = false } = {},
{ cache = false } = {},
): Promise<RegistryDependency[]> =>
Promise.all(
dependencies.map((dependency) =>
Expand All @@ -38,29 +39,20 @@ export const fetch_peer_dependencies = (
.then((res) => res.json())
.then(parse_peers)
.then((registry) => {
const [version, ...versions] = Object.values(registry.versions)
.filter(({ version }) => satisfies(version, dependency.range));
const version = Object.values(registry.versions).find(({ version }) =>
satisfies(version, dependency.range)
);

if (!version) {
throw new Error(
`Could not find ${dependency.name}@${dependency.range.range}`,
);
}

if (verbose && Object.keys(version.dependencies ?? {}).length > 0) {
console.warn(
`🔍 ${
format(dependency.name, dependency.range)
} – futher deps not analysed`,
`Could not find ${format(dependency.name, dependency.range)}`,
);
}

const peers = version.peerDependencies
? Object.entries(version.peerDependencies).map((
[name, range],
) => {
const local_version = dependencies.find((dependency) =>
dependency.name === name
? Object.entries(version.peerDependencies).map(([name, range]) => {
const local_version = dependencies.find(
(dependency) => dependency.name === name,
)?.range;

const local_min_version = local_version
Expand All @@ -77,21 +69,22 @@ export const fetch_peer_dependencies = (
? local_version_matches
: is_optional;

return ({
return {
name,
range: new Range(range),
satisfied,
});
};
})
: [];

return ({
return {
...dependency,
peers,
versions: [version, ...versions].map(({ version }) =>
new SemVer(version)
dependencies: Object.entries(version.dependencies ?? {}).map(
([name, range]) => ({ name, range: new Range(range) }),
),
});
peers,
version: new SemVer(version.version),
};
})
.catch((error) => {
console.error("🚨 Failed to parse package.json for", dependency.name);
Expand All @@ -101,19 +94,25 @@ export const fetch_peer_dependencies = (
);

Deno.bench("Fetch with cache", async () => {
await fetch_peer_dependencies([
{
name: "@guardian/core-web-vitals",
range: new Range("2.0.2"),
},
], { cache: true });
await fetch_peer_dependencies(
[
{
name: "@guardian/core-web-vitals",
range: new Range("2.0.2"),
},
],
{ cache: true },
);
});

Deno.bench("Fetch without cache", async () => {
await fetch_peer_dependencies([
{
name: "@guardian/core-web-vitals",
range: new Range("2.0.2"),
},
], { cache: false });
await fetch_peer_dependencies(
[
{
name: "@guardian/core-web-vitals",
range: new Range("2.0.2"),
},
],
{ cache: false },
);
});
12 changes: 8 additions & 4 deletions find_mismatches.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ Deno.test("Works when all dependencies are matched", () => {
{
name: "one",
range: new Range("1.0.0"),
versions: [new SemVer("1.0.0")],
version: new SemVer("1.0.0"),
dependencies: [],
peers: [
{
name: "two",
Expand All @@ -25,7 +26,8 @@ Deno.test("Works when all dependencies are matched", () => {
{
name: "two",
range: new Range("2.0.2"),
versions: [new SemVer("2.0.2")],
version: new SemVer("2.0.2"),
dependencies: [],
peers: [
{ name: "four", satisfied: true, range: new Range("^4") },
],
Expand All @@ -41,7 +43,8 @@ Deno.test("Fails on invalid range", () => {
{
name: "one",
range: new Range("1.0.0"),
versions: [new SemVer("1.0.0")],
version: new SemVer("1.0.0"),
dependencies: [],
peers: [
{
name: "two",
Expand All @@ -53,7 +56,8 @@ Deno.test("Fails on invalid range", () => {
{
name: "two",
range: new Range("2.0.2"),
versions: [new SemVer("2.0.2")],
version: new SemVer("2.0.2"),
dependencies: [],
peers: [],
},
]),
Expand Down
51 changes: 28 additions & 23 deletions find_mismatches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,45 @@ import { RegistryDependency } from "./types.ts";

export const count_unsatisfied_peer_dependencies = (
dependencies: RegistryDependency[],
verbose = true,
) =>
dependencies.map(({ name, range, peers }) => {
if (peers.length === 0) return 0;
dependencies.map(({ peers }) =>
peers.filter((peer) => !peer.satisfied).length
)
.reduce((acc, curr) => acc + curr);

const { length: unsatisfied } = peers.filter((peer) => !peer.satisfied);
export const format_dependencies = (
dependencies: RegistryDependency[],
verbose = true,
): void => {
dependencies.map(({ name, range, dependencies, peers }) => {
console.info(
`├─ ${format(name, range)}`,
);

if (unsatisfied === 0) {
if (verbose) {
console.info(
`✅ ${format(name, range)} – all ${
colour.file("peerDependencies")
} satisfied`,
);
}
return 0;
let count = dependencies.length;
for (const dependency of dependencies) {
const angle = peers.length === 0 && --count === 0 ? "╰" : "├";
console.warn(
`│ ${angle}${colour.version("▲")} ${
format(dependency.name, dependency.range)
} – futher ${colour.file("dependencies")} not analysed`,
);
}

console.error(
`🚨 ${format(name, range)} – unsatisfied ${
colour.file("peerDependencies")
}`,
);

count = peers.length;
for (const { name, range, satisfied } of peers) {
const angle = --count === 0 ? "╰" : "├";
if (satisfied) {
if (verbose) {
console.info(` - ✅ ${format(name, range)}`);
console.info(
`│ ${angle}${colour.valid("○")} ${format(name, range)}`,
);
}
} else {
console.error(
` - 🚨 ${format(name, range)}`,
`${angle}${colour.invalid("✕")} ${format(name, range)}`,
);
}
}
return unsatisfied;
}).reduce((acc, curr) => acc + curr);
});
};
2 changes: 2 additions & 0 deletions fixtures/package.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"name": "npm-dependencies",
"version": "0.0.1",
"dependencies": {
"@guardian/source-foundations": "8.0.0",
"@guardian/core-web-vitals": "2.0.2"
Expand Down
2 changes: 2 additions & 0 deletions fixtures/package_valid.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"name": "npm-dependencies",
"version": "0.0.1",
"dependencies": {
"@guardian/ab-core": "2.0.0",
"@guardian/core-web-vitals": "2.0.2",
Expand Down
Loading

0 comments on commit ce37682

Please sign in to comment.