Skip to content

Commit

Permalink
refactor: dependency resolving logic
Browse files Browse the repository at this point in the history
Currently, you can either pass a semantic version or "latest" to the dependency-resolve service. The service will then resolve the packages latest version if no semantic version was given.

This complicates the logic inside the service. For this reason, now the client calling the service needs to determine the latest version and pass it to the service.
  • Loading branch information
ComradeVanti committed Jul 7, 2024
1 parent de7e3e8 commit dfbf212
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/cli/cmd-add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export function makeAddCmd(
const [depsValid, depsInvalid] = await resolveDependencies(
[env.registry, env.upstreamRegistry],
name,
requestedVersion,
versionToAdd,
true
);

Expand Down
25 changes: 19 additions & 6 deletions src/cli/cmd-deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { logValidDependency } from "./dependency-logging";
import { VersionNotFoundError } from "../domain/packument";
import { DebugLog } from "../logging";
import { ResultCodes } from "./result-codes";
import { ResolveLatestVersion } from "../services/resolve-latest-version";
import { isSemanticVersion } from "../domain/semantic-version";

export type DepsOptions = CmdOptions<{
deep?: boolean;
Expand Down Expand Up @@ -47,26 +49,37 @@ function errorPrefixForError(error: ResolvePackumentVersionError): string {
export function makeDepsCmd(
parseEnv: ParseEnv,
resolveDependencies: ResolveDependencies,
resolveLatestVersion: ResolveLatestVersion,
log: Logger,
debugLog: DebugLog
): DepsCmd {
return async (pkg, options) => {
// parse env
const env = await parseEnv(options);
const sources = [env.registry, env.upstreamRegistry];

const [name, version] = splitPackageReference(pkg);
const [packageName, requestedVersion] = splitPackageReference(pkg);

if (version !== undefined && isPackageUrl(version)) {
if (requestedVersion !== undefined && isPackageUrl(requestedVersion)) {
log.error("", "cannot get dependencies for url-version");
return ResultCodes.Error;
}

const latestVersion =
requestedVersion !== undefined && isSemanticVersion(requestedVersion)
? requestedVersion
: (await resolveLatestVersion(sources, packageName))?.value ?? null;

if (latestVersion === null) throw new PackumentNotFoundError(packageName);

const deep = options.deep || false;
debugLog(`fetch: ${makePackageReference(name, version)}, deep=${deep}`);
debugLog(
`fetch: ${makePackageReference(packageName, latestVersion)}, deep=${deep}`
);
const [depsValid, depsInvalid] = await resolveDependencies(
[env.registry, env.upstreamRegistry],
name,
version,
sources,
packageName,
latestVersion,
deep
);

Expand Down
9 changes: 7 additions & 2 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ const checkIsBuiltInPackage = makeCheckIsBuiltInPackage(
);
const resolveDependencies = makeResolveDependency(
resolveRemovePackumentVersion,
resolveLatestVersion,
checkIsBuiltInPackage
);
const saveAuthToUpmConfig = makeSaveAuthToUpmConfig(
Expand All @@ -137,7 +136,13 @@ const addCmd = makeAddCmd(
);
const loginCmd = makeLoginCmd(parseEnv, getUpmConfigPath, login, log);
const searchCmd = makeSearchCmd(parseEnv, searchPackages, log, debugLog);
const depsCmd = makeDepsCmd(parseEnv, resolveDependencies, log, debugLog);
const depsCmd = makeDepsCmd(
parseEnv,
resolveDependencies,
resolveLatestVersion,
log,
debugLog
);
const removeCmd = makeRemoveCmd(parseEnv, removePackages, log);
const viewCmd = makeViewCmd(parseEnv, fetchPackument, log);

Expand Down
15 changes: 2 additions & 13 deletions src/services/dependency-resolving.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { Registry } from "../domain/registry";
import { ResolveRemotePackumentVersion } from "./resolve-remote-packument-version";
import { areArraysEqual } from "../utils/array-utils";
import { dependenciesOf } from "../domain/package-manifest";
import { ResolveLatestVersion } from "./resolve-latest-version";
import { Err, Result } from "ts-results-es";
import { PackumentNotFoundError } from "../common-errors";
import { CheckIsBuiltInPackage } from "./built-in-package-check";
Expand Down Expand Up @@ -64,7 +63,7 @@ type NameVersionPair = Readonly<[DomainName, SemanticVersion]>;
export type ResolveDependencies = (
sources: ReadonlyArray<Registry>,
name: DomainName,
version: SemanticVersion | "latest" | undefined,
version: SemanticVersion,
deep: boolean
) => Promise<[ValidDependency[], InvalidDependency[]]>;

Expand All @@ -73,23 +72,13 @@ export type ResolveDependencies = (
*/
export function makeResolveDependency(
resolveRemovePackumentVersion: ResolveRemotePackumentVersion,
resolveLatestVersion: ResolveLatestVersion,
checkIsBuiltInPackage: CheckIsBuiltInPackage
): ResolveDependencies {
// TODO: Add tests for this service

return async (sources, name, version, deep) => {
const latestVersion =
version === undefined || version === "latest"
? await resolveLatestVersion(sources, name).then(
(it) => it?.value || null
)
: version;

if (latestVersion == null) throw new PackumentNotFoundError(name);

// a list of pending dependency {name, version}
const pendingList = Array.of<NameVersionPair>([name, latestVersion]);
const pendingList = Array.of<NameVersionPair>([name, version]);
// a list of processed dependency {name, version}
const processedList = Array.of<NameVersionPair>();
// a list of dependency entry exists on the registry
Expand Down
34 changes: 32 additions & 2 deletions test/cli/cmd-deps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { mockService } from "../services/service.mock";
import { VersionNotFoundError } from "../../src/domain/packument";
import { noopLogger } from "../../src/logging";
import { ResultCodes } from "../../src/cli/result-codes";
import { ResolveLatestVersion } from "../../src/services/resolve-latest-version";

const somePackage = makeDomainName("com.some.package");
const otherPackage = makeDomainName("com.other.package");
Expand Down Expand Up @@ -44,10 +45,28 @@ function makeDependencies() {
[],
]);

const resolveLatestVersion = mockService<ResolveLatestVersion>();
resolveLatestVersion.mockResolvedValue({
source: exampleRegistryUrl,
value: makeSemanticVersion("1.2.3"),
});

const log = makeMockLogger();

const depsCmd = makeDepsCmd(parseEnv, resolveDependencies, log, noopLogger);
return { depsCmd, parseEnv, resolveDependencies, log } as const;
const depsCmd = makeDepsCmd(
parseEnv,
resolveDependencies,
resolveLatestVersion,
log,
noopLogger
);
return {
depsCmd,
parseEnv,
resolveDependencies,
resolveLatestVersion,
log,
} as const;
}

describe("cmd-deps", () => {
Expand All @@ -64,6 +83,17 @@ describe("cmd-deps", () => {
expect(resultCode).toEqual(ResultCodes.Error);
});

it("should fail if latest version could not be r esolved", async () => {
const { depsCmd, resolveLatestVersion } = makeDependencies();
resolveLatestVersion.mockResolvedValue(null);

await expect(
depsCmd(somePackage, {
_global: {},
})
).rejects.toBeInstanceOf(PackumentNotFoundError);
});

it("should notify if package-reference has url-version", async () => {
const { depsCmd, log } = makeDependencies();

Expand Down

0 comments on commit dfbf212

Please sign in to comment.