Skip to content

refactor: extract service #346

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

Merged
merged 1 commit into from
May 28, 2024
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
20 changes: 15 additions & 5 deletions src/cli/cmd-add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { areArraysEqual } from "../utils/array-utils";
import { Err, Ok, Result } from "ts-results-es";
import { CustomError } from "ts-custom-error";
import {
logDetermineEditorError,
logEnvParseError,
logManifestLoadError,
logManifestSaveError,
Expand All @@ -54,6 +55,7 @@ import { tryGetTargetEditorVersionFor } from "../domain/package-manifest";
import { VersionNotFoundError } from "../domain/packument";
import { FetchPackumentError } from "../io/packument-io";
import { DebugLog } from "../logging";
import { DetermineEditorVersion } from "../services/determine-editor-version";

export class InvalidPackumentDataError extends CustomError {
private readonly _class = "InvalidPackumentDataError";
Expand Down Expand Up @@ -113,6 +115,7 @@ export function makeAddCmd(
resolveDependencies: ResolveDependenciesService,
loadProjectManifest: LoadProjectManifest,
writeProjectManifest: WriteProjectManifest,
determineEditorVersion: DetermineEditorVersion,
log: Logger,
debugLog: DebugLog
): AddCmd {
Expand All @@ -126,10 +129,17 @@ export function makeAddCmd(
}
const env = envResult.value;

if (typeof env.editorVersion === "string")
const editorVersionResult = await determineEditorVersion(env.cwd).promise;
if (editorVersionResult.isErr()) {
logDetermineEditorError(log, editorVersionResult.error);
return editorVersionResult;
}
const editorVersion = editorVersionResult.value;

if (typeof editorVersion === "string")
log.warn(
"editor.version",
`${env.editorVersion} is unknown, the editor version check is disabled`
`${editorVersion} is unknown, the editor version check is disabled`
);

const tryAddToManifest = async function (
Expand Down Expand Up @@ -194,13 +204,13 @@ export function makeAddCmd(
// verify editor version
if (
targetEditorVersion !== null &&
typeof env.editorVersion !== "string" &&
compareEditorVersion(env.editorVersion, targetEditorVersion) < 0
typeof editorVersion !== "string" &&
compareEditorVersion(editorVersion, targetEditorVersion) < 0
) {
log.warn(
"editor.version",
`requires ${targetEditorVersion} but found ${stringifyEditorVersion(
env.editorVersion
editorVersion
)}`
);
if (!options.force) {
Expand Down
27 changes: 23 additions & 4 deletions src/cli/error-logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ChildProcessError } from "../utils/process";
import { RequiredEnvMissingError } from "../io/upm-config-io";
import { FileMissingError, GenericIOError } from "../io/common-errors";
import { StringFormatError } from "../utils/string-parsing";
import { DetermineEditorVersionError } from "../services/determine-editor-version";

/**
* Logs a {@link ManifestLoadError} to the console.
Expand Down Expand Up @@ -70,14 +71,10 @@ export function logEnvParseError(log: Logger, error: EnvParseError) {
const reason =
error instanceof NoWslError
? "you attempted to use wsl even though you are not running openupm inside wsl"
: error instanceof FileMissingError
? `the projects version file (ProjectVersion.txt) could not be found at "${error.path}"`
: error instanceof GenericIOError
? `a file-system interaction failed`
: error instanceof ChildProcessError
? "a required child process failed"
: error instanceof FileParseError
? `the project version file (ProjectVersion.txt) has an invalid structure`
: error instanceof RequiredEnvMissingError
? `none of the following environment variables were set: ${error.keyNames.join(
", "
Expand All @@ -88,3 +85,25 @@ export function logEnvParseError(log: Logger, error: EnvParseError) {

// TODO: Suggest actions user might take in order to fix the problem.
}

/**
* Logs a {@link DetermineEditorVersionError} to a logger.
*/
export function logDetermineEditorError(
log: Logger,
error: DetermineEditorVersionError
) {
const reason =
error instanceof FileMissingError
? `the projects version file (ProjectVersion.txt) could not be found at "${error.path}"`
: error instanceof GenericIOError
? `a file-system interaction failed`
: error instanceof FileParseError
? `the project version file (ProjectVersion.txt) has an invalid structure`
: `the project versions file (ProjectVersion.txt) did not contain valid yaml`;

const errorMessage = `editor version could be determined because ${reason}.`;
log.error("", errorMessage);

// TODO: Suggest actions user might take in order to fix the problem.
}
6 changes: 4 additions & 2 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { makePackagesSearcher } from "../services/search-packages";
import { makeRemotePackumentResolver } from "../services/resolve-remote-packument";
import { makeLoginService } from "../services/login";
import { DebugLog } from "../logging";
import { makeEditorVersionDeterminer } from "../services/determine-editor-version";

// Composition root

Expand Down Expand Up @@ -80,9 +81,9 @@ const parseEnv = makeParseEnvService(
log,
getUpmConfigPath,
loadUpmConfig,
getCwd,
loadProjectVersion
getCwd
);
const determineEditorVersion = makeEditorVersionDeterminer(loadProjectVersion);
const authNpmrc = makeAuthNpmrcService(findNpmrcPath, loadNpmrc, saveNpmrc);
const npmLogin = makeNpmLoginService(regClient);
const resolveRemovePackumentVersion =
Expand Down Expand Up @@ -110,6 +111,7 @@ const addCmd = makeAddCmd(
resolveDependencies,
loadProjectManifest,
writeProjectManifest,
determineEditorVersion,
log,
debugLog
);
Expand Down
41 changes: 41 additions & 0 deletions src/services/determine-editor-version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { AsyncResult } from "ts-results-es";
import {
isRelease,
ReleaseVersion,
tryParseEditorVersion,
} from "../domain/editor-version";
import {
LoadProjectVersion,
ProjectVersionLoadError,
} from "../io/project-version-io";

/**
* Error which may occur when determining the editor-version.
*/
export type DetermineEditorVersionError = ProjectVersionLoadError;

/**
* Function for determining the editor-version for a Unity project.
* @param projectPath The path to the projects root directory.
* @returns The editor-version. Either a parsed version object or the raw
* version string if it could not be parsed.
*/
export type DetermineEditorVersion = (
projectPath: string
) => AsyncResult<ReleaseVersion | string, DetermineEditorVersionError>;

/**
* Makes a {@link DetermineEditorVersion} function.
*/
export function makeEditorVersionDeterminer(
loadProjectVersion: LoadProjectVersion
): DetermineEditorVersion {
return (projectPath) => {
return loadProjectVersion(projectPath).map((unparsedEditorVersion) => {
const parsedEditorVersion = tryParseEditorVersion(unparsedEditorVersion);
return parsedEditorVersion !== null && isRelease(parsedEditorVersion)
? parsedEditorVersion
: unparsedEditorVersion;
});
};
}
35 changes: 2 additions & 33 deletions src/services/parse-env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,8 @@ import path from "path";
import { coerceRegistryUrl, makeRegistryUrl } from "../domain/registry-url";
import { tryGetAuthForRegistry, UPMConfig } from "../domain/upm-config";
import { CmdOptions } from "../cli/options";
import { FileParseError } from "../common-errors";
import { Ok, Result } from "ts-results-es";
import {
LoadProjectVersion,
ProjectVersionLoadError,
} from "../io/project-version-io";
import { tryGetEnv } from "../utils/env-util";
import {
isRelease,
ReleaseVersion,
tryParseEditorVersion,
} from "../domain/editor-version";
import { Registry } from "../domain/registry";
import { Logger } from "npmlog";
import { GetCwd } from "../io/special-paths";
Expand All @@ -32,17 +22,9 @@ export type Env = Readonly<{
upstream: boolean;
upstreamRegistry: Registry;
registry: Registry;
/**
* The current project's editor version. Either a parsed {@link EditorVersion}
* object if parsing was successful or the unparsed string.
*/
editorVersion: ReleaseVersion | string;
}>;

export type EnvParseError =
| GetUpmConfigPathError
| UpmConfigLoadError
| ProjectVersionLoadError;
export type EnvParseError = GetUpmConfigPathError | UpmConfigLoadError;

/**
* Service function for parsing environment information and global
Expand All @@ -59,8 +41,7 @@ export function makeParseEnvService(
log: Logger,
getUpmConfigPath: GetUpmConfigPath,
loadUpmConfig: LoadUpmConfig,
getCwd: GetCwd,
loadProjectVersion: LoadProjectVersion
getCwd: GetCwd
): ParseEnvService {
function determineCwd(options: CmdOptions): string {
return options._global.chdir !== undefined
Expand Down Expand Up @@ -156,20 +137,8 @@ export function makeParseEnvService(
// cwd
const cwd = determineCwd(options);

// editor version
const projectVersionLoadResult = await loadProjectVersion(cwd).promise;
if (projectVersionLoadResult.isErr()) return projectVersionLoadResult;

const unparsedEditorVersion = projectVersionLoadResult.value;
const parsedEditorVersion = tryParseEditorVersion(unparsedEditorVersion);
const editorVersion =
parsedEditorVersion !== null && isRelease(parsedEditorVersion)
? parsedEditorVersion
: unparsedEditorVersion;

return Ok({
cwd,
editorVersion,
registry,
systemUser,
upstream,
Expand Down
28 changes: 23 additions & 5 deletions test/cli/cmd-add.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { makePackageReference } from "../../src/domain/package-reference";
import { VersionNotFoundError } from "../../src/domain/packument";
import { noopLogger } from "../../src/logging";
import { FileMissingError, GenericIOError } from "../../src/io/common-errors";
import { DetermineEditorVersion } from "../../src/services/determine-editor-version";

const somePackage = makeDomainName("com.some.package");
const otherPackage = makeDomainName("com.other.package");
Expand Down Expand Up @@ -59,7 +60,6 @@ const defaultEnv = {
upstream: true,
registry: { url: exampleRegistryUrl, auth: null },
upstreamRegistry: { url: unityRegistryUrl, auth: null },
editorVersion: makeEditorVersion(2022, 2, 1, "f", 2),
} as Env;

function makeDependencies() {
Expand Down Expand Up @@ -101,6 +101,11 @@ function makeDependencies() {
const writeProjectManifest = mockService<WriteProjectManifest>();
mockProjectManifestWriteResult(writeProjectManifest);

const determineEditorVersion = mockService<DetermineEditorVersion>();
determineEditorVersion.mockReturnValue(
Ok(makeEditorVersion(2022, 2, 1, "f", 2)).toAsyncResult()
);

const log = makeMockLogger();

const addCmd = makeAddCmd(
Expand All @@ -109,6 +114,7 @@ function makeDependencies() {
resolveDependencies,
loadProjectManifest,
writeProjectManifest,
determineEditorVersion,
log,
noopLogger
);
Expand All @@ -119,6 +125,7 @@ function makeDependencies() {
resolveDependencies,
loadProjectManifest,
writeProjectManifest,
determineEditorVersion,
log,
} as const;
}
Expand All @@ -134,6 +141,19 @@ describe("cmd-add", () => {
expect(result).toBeError((actual) => expect(actual).toEqual(expected));
});

it("should fail if editor-version could not be determined", async () => {
const { addCmd, determineEditorVersion } = makeDependencies();
determineEditorVersion.mockReturnValue(
Err(new GenericIOError()).toAsyncResult()
);

const result = await addCmd(somePackage, { _global: {} });

expect(result).toBeError((actual) =>
expect(actual).toBeInstanceOf(GenericIOError)
);
});

it("should fail if manifest could not be loaded", async () => {
const { addCmd, loadProjectManifest } = makeDependencies();
mockProjectManifest(loadProjectManifest, null);
Expand Down Expand Up @@ -203,10 +223,8 @@ describe("cmd-add", () => {
});

it("should notify if editor-version is unknown", async () => {
const { addCmd, parseEnv, log } = makeDependencies();
parseEnv.mockResolvedValue(
Ok({ ...defaultEnv, editorVersion: "bad version" })
);
const { addCmd, determineEditorVersion, log } = makeDependencies();
determineEditorVersion.mockReturnValue(Ok("bad version").toAsyncResult());

await addCmd(somePackage, {
_global: {},
Expand Down
2 changes: 0 additions & 2 deletions test/cli/cmd-login.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { LoginService } from "../../src/services/login";
import { makeMockLogger } from "./log.mock";
import { exampleRegistryUrl } from "../domain/data-registry";
import { unityRegistryUrl } from "../../src/domain/registry-url";
import { makeEditorVersion } from "../../src/domain/editor-version";
import { AuthenticationError } from "../../src/services/npm-login";
import { GenericIOError } from "../../src/io/common-errors";

Expand All @@ -19,7 +18,6 @@ const defaultEnv = {
upstream: true,
registry: { url: exampleRegistryUrl, auth: null },
upstreamRegistry: { url: unityRegistryUrl, auth: null },
editorVersion: makeEditorVersion(2022, 2, 1, "f", 2),
} as Env;
const exampleUser = "user";
const examplePassword = "pass";
Expand Down
Loading
Loading