diff --git a/src/publishing/mod-publisher.ts b/src/publishing/mod-publisher.ts index 1369ab2..2aab47e 100644 --- a/src/publishing/mod-publisher.ts +++ b/src/publishing/mod-publisher.ts @@ -1,10 +1,15 @@ import { context } from "@actions/github"; +import { parseVersionName, parseVersionNameFromFileVersion } from "../utils/minecraft-utils"; import { File } from "../utils/file"; import { getFiles } from "../utils/file-utils"; import Publisher from "./publisher"; import PublisherTarget from "./publisher-target"; import MinecraftVersionResolver from "../utils/minecraft-version-resolver"; +import ModMetadataReader from "../metadata/mod-metadata-reader"; +import Dependency from "../metadata/dependency"; import { parseVersionFromName, parseVersionTypeFromName } from "../utils/version-utils"; +import DependencyKind from "../metadata/dependency-kind"; +import path from "path"; interface ModPublisherOptions { id: string; @@ -17,11 +22,10 @@ interface ModPublisherOptions { versionResolver?: string; gameVersions?: string | string[]; java?: string | string[]; + dependencies?: string | string[]; files?: string | { primary?: string, secondary?: string }; } -const defaultLoaders = ["fabric"]; - function processMultilineInput(input: string | string[], splitter?: RegExp): string[] { if (!input) { return []; @@ -29,12 +33,20 @@ function processMultilineInput(input: string | string[], splitter?: RegExp): str return (typeof input === "string" ? input.split(splitter || /(\r?\n)+/) : input).map(x => x.trim()).filter(x => x); } -async function readChangelog(changelog: string | { file?: string }): Promise { - if (typeof changelog === "string") { - return changelog; - } +function processDependenciesInput(input: string | string[], inputSplitter?: RegExp, entrySplitter?: RegExp): Dependency[] { + return processMultilineInput(input, inputSplitter).map(x => { + const parts = x.split(entrySplitter || /\|/); + const id = parts[0].trim(); + return Dependency.create({ + id, + kind: parts[1] && DependencyKind.parse(parts[1].trim()) || DependencyKind.Depends, + version: parts[2]?.trim() || "*" + }); + }); +} - const file = (await getFiles(changelog.file || ""))[0]; +async function readChangelog(changelogPath: string): Promise { + const file = (await getFiles(changelogPath))[0]; if (!file) { throw new Error("Changelog file was not found"); } @@ -46,9 +58,8 @@ export default abstract class ModPublisher extends Publishercontext.payload.release; - const id = options.id; - if (!id) { - throw new Error(`Project id is required to publish your assets to ${PublisherTarget.toString(this.target)}`); + if (!Array.isArray(files) || !files.length) { + throw new Error("No upload files were specified"); } const token = options.token; @@ -56,19 +67,39 @@ export default abstract class ModPublisher extends PublisherreleaseInfo?.tag_name || parseVersionFromFilename(files[0].name); - const versionType = options.versionType?.toLowerCase() || parseVersionTypeFromFilename(files[0].name); + const metadata = await ModMetadataReader.readMetadata(files[0].path); + + const id = options.id || metadata?.getProjectId(this.target); + if (!id) { + throw new Error(`Project id is required to publish your assets to ${PublisherTarget.toString(this.target)}`); + } + + const filename = path.parse(files[0].path).name; + const version = (typeof options.version === "string" && options.version) || releaseInfo?.tag_name || metadata?.version || parseVersionFromName(filename); + const versionType = options.versionType?.toLowerCase() || parseVersionTypeFromName(metadata?.version || filename); const name = typeof options.name === "string" ? options.name : (releaseInfo?.name || version); - const changelog = ((typeof options.changelog === "string" || options.changelog?.file) ? (await readChangelog(options.changelog)) : releaseInfo?.body) || ""; + const changelog = typeof options.changelog === "string" + ? options.changelog + : typeof options.changelog?.file === "string" + ? await readChangelog(options.changelog.file) + : releaseInfo?.body || ""; const loaders = processMultilineInput(options.loaders, /\s+/); if (!loaders.length) { - loaders.push(...defaultLoaders); + if (metadata) { + loaders.push(...metadata.loaders); + } + if (!loaders.length) { + throw new Error("At least one mod loader should be specified"); + } } const gameVersions = processMultilineInput(options.gameVersions); if (!gameVersions.length) { - const minecraftVersion = parseVersionNameFromFileVersion(version); + const minecraftVersion = + metadata?.dependencies.filter(x => x.id === "minecraft").map(x => parseVersionName(x.version))[0] || + parseVersionNameFromFileVersion(version); + if (minecraftVersion) { const resolver = options.versionResolver && MinecraftVersionResolver.byName(options.versionResolver) || MinecraftVersionResolver.releasesIfAny; gameVersions.push(...(await resolver.resolve(minecraftVersion)).map(x => x.id)); @@ -79,9 +110,13 @@ export default abstract class ModPublisher extends Publisher !x.ignore && self.findIndex(y => y.id === x.id && y.kind === x.kind) === i); - await this.publishMod(id, token, name, version, versionType, loaders, gameVersions, java, changelog, files); + await this.publishMod(id, token, name, version, versionType, loaders, gameVersions, java, changelog, files, uniqueDependencies); } - protected abstract publishMod(id: string, token: string, name: string, version: string, versionType: string, loaders: string[], gameVersions: string[], java: string[], changelog: string, files: File[]): Promise; + protected abstract publishMod(id: string, token: string, name: string, version: string, versionType: string, loaders: string[], gameVersions: string[], java: string[], changelog: string, files: File[], dependencies: Dependency[]): Promise; } \ No newline at end of file