Skip to content

Commit

Permalink
refactor: extract pure logic
Browse files Browse the repository at this point in the history
Extract pure function for parsing manifest
  • Loading branch information
ComradeVanti committed Aug 25, 2024
1 parent 897ff87 commit 92e250b
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 31 deletions.
22 changes: 13 additions & 9 deletions src/io/project-manifest-io.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { AnyJson } from "@iarna/toml";
import path from "path";
import { CustomError } from "ts-custom-error";
import { z } from "zod";
import { UnityProjectManifest } from "../domain/project-manifest";
import { DebugLog, npmDebugLog } from "../logging";
import { assertIsError } from "../utils/error-type-guards";
import { isZod } from "../utils/zod-utils";
import {
readTextFile,
ReadTextFile,
Expand Down Expand Up @@ -40,7 +38,18 @@ export type LoadProjectManifest = (
) => Promise<UnityProjectManifest>;

// TODO: Add a better schema
const projectManifestSchema = z.object({});
const projectManifestSchema = z.object({}).passthrough();

/**
* Parses the content of a `manifest.json` file to a {@link UnityProjectManifest}.
* @param content The files content.
* @returns The parsed file.
* @throws {Error} If parsing failed.
*/
export function parseProjectManifest(content: string): UnityProjectManifest {
const json = JSON.parse(content);
return projectManifestSchema.parse(json) as UnityProjectManifest;
}

/**
* Makes a {@link LoadProjectManifest} function which reads the content
Expand All @@ -56,18 +65,13 @@ export function ReadProjectManifestFile(
const content = await readFile(manifestPath, true);
if (content === null) throw new ManifestMissingError(manifestPath);

let json: AnyJson;
try {
json = await JSON.parse(content);
return parseProjectManifest(content);
} catch (error) {
assertIsError(error);
debugLog("Manifest parse failed because of invalid json content.", error);
throw new ManifestMalformedError();
}

if (!isZod(json, projectManifestSchema)) throw new ManifestMalformedError();

return json as unknown as UnityProjectManifest;
};
}

Expand Down
56 changes: 34 additions & 22 deletions test/io/project-manifest-io.test.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,47 @@
import path from "path";
import { UnityProjectManifest } from "../../src/domain/project-manifest";
import {
ReadProjectManifestFile,
WriteProjectManifestFile,
ManifestMalformedError,
ManifestMissingError,
manifestPathFor,
parseProjectManifest,
ReadProjectManifestFile,
serializeProjectManifest,
} from "../../src/io/project-manifest-io";
import {
mapScopedRegistry,
UnityProjectManifest,
} from "../../src/domain/project-manifest";
import path from "path";
import { ReadTextFile, WriteTextFile } from "../../src/io/text-file-io";
import { buildProjectManifest } from "../domain/data-project-manifest";
import { DomainName } from "../../src/domain/domain-name";
import { removeScope } from "../../src/domain/scoped-registry";
import { ReadTextFile } from "../../src/io/text-file-io";
import { noopLogger } from "../../src/logging";
import { exampleRegistryUrl } from "../domain/data-registry";
import { mockService } from "../services/service.mock";
import { noopLogger } from "../../src/logging";

const exampleProjectPath = "/some/path";
describe("project-manifest io", () => {
describe("parse", () => {
it("should parse valid manifest", () => {
const content = `{ "dependencies": { "com.package.a": "1.0.0"} }`;

const parsed = parseProjectManifest(content);

expect(parsed).toEqual({
dependencies: {
"com.package.a": "1.0.0",
},
});
});

it("should fail for bad json", () => {
const content = "not : valid // json";

expect(() => parseProjectManifest(content)).toThrow(Error);
});

it("should fail incorrect json shape", () => {
// Valid json but not what we want
const content = `123`;

expect(() => parseProjectManifest(content)).toThrow(Error);
});
});

describe("path", () => {
it("should determine correct manifest path", () => {
const manifestPath = manifestPathFor("test-openupm-cli");
Expand Down Expand Up @@ -53,7 +74,7 @@ describe("project-manifest io", () => {
).rejects.toBeInstanceOf(ManifestMissingError);
});

it("should fail if manifest contains invalid json", async () => {
it("should fail if manifest could not be parsed", async () => {
const { readProjectManifestFile, readFile } = makeDependencies();
readFile.mockResolvedValue("not {} valid : json");

Expand All @@ -62,15 +83,6 @@ describe("project-manifest io", () => {
).rejects.toBeInstanceOf(ManifestMalformedError);
});

it("should fail if manifest contains invalid content", async () => {
const { readProjectManifestFile, readFile } = makeDependencies();
readFile.mockResolvedValue(`123`);

await expect(
readProjectManifestFile(exampleProjectPath)
).rejects.toBeInstanceOf(ManifestMalformedError);
});

it("should load valid manifest", async () => {
const { readProjectManifestFile, readFile } = makeDependencies();
readFile.mockResolvedValue(
Expand Down

0 comments on commit 92e250b

Please sign in to comment.