Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(lib): merge files #56

Merged
merged 3 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import { URI } from "./lib/uri.ts";
import { DependencyUpdate } from "./lib/update.ts";
import { FileUpdate } from "./lib/file.ts";
import { GitCommitSequence } from "./lib/git.ts";
import { parseSemVer } from "./lib/semver.ts";
import { resolveLatestSemVer } from "./lib/dependency.ts";
import { parseSemVer, resolveLatestSemVer } from "./lib/dependency.ts";

const { gray, yellow, bold, cyan } = colors;

Expand Down
22 changes: 21 additions & 1 deletion lib/dependency.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
import { assertExists } from "./std/assert.ts";
import { Mutex } from "./x/async.ts";
import type { Maybe, Path, SemVerString } from "./types.ts";
import { parseSemVer } from "./semver.ts";

// Ref: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
const SEMVER_REGEXP =
/@v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?/g;

export function parseSemVer(
specifier: string,
): Maybe<SemVerString> {
const match = specifier.match(SEMVER_REGEXP);
if (!match) {
return undefined;
}
if (match.length > 1) {
console.warn(
"Multiple semvers in a single specifier is not supported:",
specifier,
);
return undefined;
}
return match[0].slice(1) as SemVerString;
}

export interface Dependency {
name: string;
Expand Down
15 changes: 14 additions & 1 deletion lib/dependency_test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import { describe, it } from "./std/testing.ts";
import { assertEquals } from "./std/assert.ts";
import { Dependency } from "./dependency.ts";
import { Dependency, parseSemVer } from "./dependency.ts";

describe("parseSemVer", () => {
it("https://deno.land/std", () =>
assertEquals(
parseSemVer("https://deno.land/[email protected]"),
"0.1.0",
));
it("https://deno.land/std (no semver)", () =>
assertEquals(
parseSemVer("https://deno.land/std"),
undefined,
));
});

describe("parseProps()", () => {
it("https://deno.land/std", () =>
Expand Down
3 changes: 1 addition & 2 deletions lib/git.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { DependencyUpdate } from "./update.ts";
import { createVersionProp, DependencyUpdate, VersionProp } from "./update.ts";
import { FileUpdate } from "./file.ts";
import { createVersionProp, type VersionProp } from "./versions.ts";
import { URI } from "./uri.ts";

export interface CommitProps {
Expand Down
28 changes: 0 additions & 28 deletions lib/loader.ts

This file was deleted.

22 changes: 0 additions & 22 deletions lib/semver.ts

This file was deleted.

16 changes: 0 additions & 16 deletions lib/semver_test.ts

This file was deleted.

73 changes: 51 additions & 22 deletions lib/update.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { distinct } from "./std/collections.ts";
import {
createGraph,
type CreateGraphOptions,
init as initDenoGraph,
load as defaultLoad,
type ModuleJson,
} from "./x/deno_graph.ts";
import { RelativePath, URI } from "./uri.ts";
import type { SemVerString } from "./types.ts";
import type { Maybe, SemVerString } from "./types.ts";
import { ImportMap, ImportMapJson } from "./import_map.ts";
import { Dependency } from "./dependency.ts";
import { load } from "./loader.ts";

type DependencyJson = NonNullable<ModuleJson["dependencies"]>[number];

Expand Down Expand Up @@ -46,7 +48,6 @@ export const DependencyUpdate = {
collect,
applyToModule,
applyToImportMap,
withRelativePath,
};

class DenoGraph {
Expand All @@ -61,6 +62,30 @@ class DenoGraph {
}
}

const load: NonNullable<CreateGraphOptions["load"]> = async (
specifier,
) => {
const url = new URL(specifier); // should not throw
switch (url.protocol) {
case "node:":
case "npm:":
return {
kind: "external",
specifier,
};
case "http:":
case "https:":
return {
kind: "external",
specifier,
};
case "file:":
return await defaultLoad(specifier);
default:
throw new Error(`Unsupported protocol: ${url.protocol}`);
}
};

export async function collect(
entrypoints: string | string[],
options: {
Expand Down Expand Up @@ -197,24 +222,28 @@ export type DependencyUpdateWithRelativePath =
};
};

/**
* Convert specifiers in the dependency update to relative paths for subsequent operations.
*/
function withRelativePath(
update: DependencyUpdate,
): DependencyUpdateWithRelativePath {
return {
...update,
specifier: _relativeIfFile(update.specifier),
map: update.map && {
...update.map,
source: URI.relative(update.map.source),
},
} as DependencyUpdateWithRelativePath;
}
export type VersionProp = {
from?: string;
to: string;
};

function _relativeIfFile(
specifier: URI<"file" | "http" | "https" | "npm">,
) {
return URI.is(specifier, "file") ? URI.relative(specifier) : specifier;
export function createVersionProp(
dependencies: DependencyUpdate[],
): Maybe<VersionProp> {
const modules = distinct(dependencies.map((d) => d.name));
if (modules.length > 1) {
// Cannot provide a well-defined version prop
return;
}
const tos = distinct(dependencies.map((d) => d.version.to));
if (tos.length > 1) {
throw new Error(
"Multiple target versions are specified for a single module",
);
}
const froms = distinct(dependencies.map((d) => d.version.from));
return {
from: froms.length === 1 ? froms[0] : undefined,
to: tos[0],
};
}
88 changes: 82 additions & 6 deletions lib/update_test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// deno-lint-ignore-file no-explicit-any
import { beforeAll, describe, it } from "./std/testing.ts";
import {
assertEquals,
assertExists,
assertNotEquals,
assertObjectMatch,
assertThrows,
} from "./std/assert.ts";
import { URI } from "./uri.ts";
import { _create, DependencyUpdate } from "./update.ts";
import { _create, createVersionProp, DependencyUpdate } from "./update.ts";
import { ImportMap } from "./import_map.ts";

describe("_create", () => {
Expand All @@ -15,7 +17,6 @@ describe("_create", () => {
specifier: "https://deno.land/[email protected]/version.ts",
code: {
specifier: "https://deno.land/[email protected]/version.ts",
// deno-lint-ignore no-explicit-any
} as any,
}, URI.from("test/fixtures/direct-import/mod.ts"));
assertExists(update);
Expand All @@ -25,7 +26,6 @@ describe("_create", () => {
specifier: "https://deno.land/std/version.ts",
code: {
specifier: "https://deno.land/std/version.ts",
// deno-lint-ignore no-explicit-any
} as any,
}, URI.from("test/fixtures/direct-import/mod.ts"));
assertEquals(update, undefined);
Expand All @@ -35,7 +35,6 @@ describe("_create", () => {
specifier: "https://deno.land/x/[email protected]/mod.ts",
code: {
specifier: "https://deno.land/x/[email protected]/mod.ts",
// deno-lint-ignore no-explicit-any
} as any,
}, URI.from("test/fixtures/direct-import/mod.ts"));
assertExists(update);
Expand All @@ -45,7 +44,6 @@ describe("_create", () => {
specifier: "npm:[email protected]",
code: {
specifier: "npm:[email protected]",
// deno-lint-ignore no-explicit-any
} as any,
}, URI.from("test/fixtures/direct-import/mod.ts"));
assertExists(update);
Expand All @@ -65,7 +63,6 @@ describe("_create - with import map", () => {
specifier: "std/version.ts",
code: {
specifier: "https://deno.land/[email protected]/version.ts",
// deno-lint-ignore no-explicit-any
} as any,
},
URI.from("test/fixtures/import-map/mod.ts"),
Expand Down Expand Up @@ -164,3 +161,82 @@ describe("applyToImportMap", () => {
assertNotEquals(result, content);
});
});

describe("createVersionProps()", () => {
it("single version", () => {
assertEquals(
createVersionProp([
{
name: "deno_graph",
version: { from: "0.0.1", to: "0.1.0" },
},
] as any),
{
from: "0.0.1",
to: "0.1.0",
},
);
});
it("multiple versions with different names", () => {
assertEquals(
createVersionProp([{
name: "deno_graph",
version: { from: "0.0.1", to: "0.1.0" },
}, {
name: "node-emoji",
version: { from: "0.0.1", to: "0.1.0" },
}] as any),
undefined,
);
});
it("multiple versions with different `from`s and a common `to`", () => {
assertEquals(
createVersionProp([
{
name: "deno_graph",
version: { from: "0.0.1", to: "0.1.0" },
},
{
name: "deno_graph",
version: { from: "0.0.2", to: "0.1.0" },
},
] as any),
{
from: undefined,
to: "0.1.0",
},
);
});
it("multiple versions with a common `from` and `to`", () => {
assertEquals(
createVersionProp([
{
name: "deno_graph",
version: { from: "0.0.1", to: "0.2.0" },
},
{
name: "deno_graph",
version: { from: "0.0.1", to: "0.2.0" },
},
] as any),
{
from: "0.0.1",
to: "0.2.0",
},
);
});
it("multiple versions with a common `from` and different `to`s", () => {
assertThrows(() =>
createVersionProp([
{
name: "deno_graph",
version: { from: "0.0.1", to: "0.1.0" },
},
{
name: "deno_graph",
version: { from: "0.0.1", to: "0.2.0" },
},
] as any)
);
});
});
Loading