diff --git a/src/loaders/loader-metadata-reader.ts b/src/loaders/loader-metadata-reader.ts index 0fd968f..3226a02 100644 --- a/src/loaders/loader-metadata-reader.ts +++ b/src/loaders/loader-metadata-reader.ts @@ -5,6 +5,7 @@ import { ForgeMetadataReader } from "./forge/forge-metadata-reader"; import { LoaderMetadata } from "./loader-metadata"; import { LoaderType } from "./loader-type"; import { QuiltMetadataReader } from "./quilt/quilt-metadata-reader"; +import { NeoForgeMetadataReader } from "./neoforge/neoforge-metadata-reader"; /** * Defines a structure for reading metadata files. @@ -61,12 +62,14 @@ export function createLoaderMetadataReader(loader: LoaderType): LoaderMetadataRe return new FabricMetadataReader(); case LoaderType.FORGE: - case LoaderType.NEOFORGE: return new ForgeMetadataReader(); case LoaderType.QUILT: return new QuiltMetadataReader(); + case LoaderType.NEOFORGE: + return new NeoForgeMetadataReader(); + default: throw new Error(`Unknown mod loader '${LoaderType.format(loader)}'.`); } diff --git a/src/loaders/neoforge/neoforge-metadata-reader.ts b/src/loaders/neoforge/neoforge-metadata-reader.ts new file mode 100644 index 0000000..d3d8670 --- /dev/null +++ b/src/loaders/neoforge/neoforge-metadata-reader.ts @@ -0,0 +1,25 @@ +import { PathLike } from "node:fs"; +import { parse as parseToml } from "toml"; +import { readAllZippedText } from "@/utils/io/file-info"; +import { LoaderType } from "../loader-type"; +import { LoaderMetadataReader } from "../loader-metadata-reader"; +import { NeoForgeMetadata } from "./neoforge-metadata"; +import { MODS_TOML } from "./raw-neoforge-metadata"; + +/** + * A metadata reader that is able to read NeoForge mod metadata from a zipped file. + */ +export class NeoForgeMetadataReader implements LoaderMetadataReader { + /** + * @inheritdoc + */ + async readMetadataFile(path: PathLike): Promise { + const metadataText = await readAllZippedText(path, MODS_TOML); + const metadata = NeoForgeMetadata.from(parseToml(metadataText)); + if (!metadata.dependencies.some(x => x.id === LoaderType.NEOFORGE)) { + throw new Error("A NeoForge metadata file must contain a 'neoforge' dependency"); + } + + return metadata; + } +} diff --git a/tests/unit/loaders/neoforge/neoforge-metadata-reader.spec.ts b/tests/unit/loaders/neoforge/neoforge-metadata-reader.spec.ts new file mode 100644 index 0000000..fd9252b --- /dev/null +++ b/tests/unit/loaders/neoforge/neoforge-metadata-reader.spec.ts @@ -0,0 +1,37 @@ +import { zipFile } from "@/../tests/utils/zip-utils"; +import mockFs from "mock-fs"; +import { NeoForgeMetadata } from "@/loaders/neoforge/neoforge-metadata"; +import { NeoForgeMetadataReader } from "@/loaders/neoforge/neoforge-metadata-reader"; + +beforeEach(async () => { + mockFs({ + "neoforge.mod.jar": await zipFile([__dirname, "../../../content/neoforge/mods.toml"], "META-INF/mods.toml"), + "text.txt": "", + }); +}); + +afterEach(() => { + mockFs.restore(); +}); + +describe("NeoForgeMetadataReader", () => { + test("successfully reads mods.toml", async () => { + const reader = new NeoForgeMetadataReader(); + + const metadata = await reader.readMetadataFile("neoforge.mod.jar"); + + expect(metadata).toBeInstanceOf(NeoForgeMetadata); + }); + + test("throws if file is not a NeoForge mod", async () => { + const reader = new NeoForgeMetadataReader(); + + await expect(reader.readMetadataFile("text.txt")).rejects.toThrow(); + }); + + test("throws if file does not exist", async () => { + const reader = new NeoForgeMetadataReader(); + + await expect(reader.readMetadataFile("text.json")).rejects.toThrow(); + }); +});