mirror of
https://github.com/Kir-Antipov/mc-publish.git
synced 2024-11-22 08:20:58 -05:00
Refactoring
This commit is contained in:
parent
03cc643a6e
commit
f8343090b1
43 changed files with 302 additions and 276 deletions
|
@ -32,6 +32,7 @@
|
||||||
"@typescript-eslint/no-empty-function": ["error", { "allow": ["arrowFunctions"] }],
|
"@typescript-eslint/no-empty-function": ["error", { "allow": ["arrowFunctions"] }],
|
||||||
"@typescript-eslint/no-namespace": "off",
|
"@typescript-eslint/no-namespace": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "off",
|
||||||
"@typescript-eslint/no-unused-vars": ["error", {
|
"@typescript-eslint/no-unused-vars": ["error", {
|
||||||
"varsIgnorePattern": "^_",
|
"varsIgnorePattern": "^_",
|
||||||
"argsIgnorePattern": "^_"
|
"argsIgnorePattern": "^_"
|
||||||
|
|
14
src/index.ts
14
src/index.ts
|
@ -1,10 +1,10 @@
|
||||||
import { getRequiredFiles, gradleOutputSelector } from "./utils/file-utils";
|
import File, { gradleOutputSelector } from "./utils/io/file";
|
||||||
import PublisherFactory from "./publishing/publisher-factory";
|
import PublisherFactory from "./publishing/publisher-factory";
|
||||||
import PublisherTarget from "./publishing/publisher-target";
|
import PublisherTarget from "./publishing/publisher-target";
|
||||||
import { getInputAsObject, mapEnumInput, mapNumberInput } from "./utils/input-utils";
|
import { getInputAsObject, mapEnumInput, mapNumberInput } from "./utils/actions/input";
|
||||||
import { getDefaultLogger } from "./utils/logger-utils";
|
import { getDefaultLogger } from "./utils/logging/logger";
|
||||||
import { retry } from "./utils/function-utils";
|
import retry from "./utils/retry";
|
||||||
import LoggingStopwatch from "./utils/logging-stopwatch";
|
import LoggingStopwatch from "./utils/logging/logging-stopwatch";
|
||||||
import AggregateError from "aggregate-error";
|
import AggregateError from "aggregate-error";
|
||||||
|
|
||||||
enum FailMode {
|
enum FailMode {
|
||||||
|
@ -28,8 +28,8 @@ async function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = { ...commonOptions, ...publisherOptions };
|
const options = { ...commonOptions, ...publisherOptions };
|
||||||
const fileSelector = typeof options.filesPrimary === "string" ? { primary: options.filesPrimary, secondary: typeof options.filesSecondary === "string" ? options.filesSecondary : gradleOutputSelector["secondary"] } : typeof options.files === "string" ? options.files : gradleOutputSelector;
|
const fileSelector = typeof options.filesPrimary === "string" ? { primary: options.filesPrimary, secondary: typeof options.filesSecondary === "string" ? options.filesSecondary : gradleOutputSelector.secondary } : typeof options.files === "string" ? options.files : gradleOutputSelector;
|
||||||
const files = await getRequiredFiles(fileSelector);
|
const files = await File.getRequiredFiles(fileSelector);
|
||||||
const retryAttempts = mapNumberInput(options.retryAttempts);
|
const retryAttempts = mapNumberInput(options.retryAttempts);
|
||||||
const retryDelay = mapNumberInput(options.retryDelay);
|
const retryDelay = mapNumberInput(options.retryDelay);
|
||||||
const failMode = mapEnumInput(options.failMode, FailMode, FailMode.Fail as FailMode);
|
const failMode = mapEnumInput(options.failMode, FailMode, FailMode.Fail as FailMode);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { File } from "../../utils/file";
|
import File from "../../utils/io/file";
|
||||||
import ModPublisher from "../mod-publisher";
|
import ModPublisher from "../mod-publisher";
|
||||||
import PublisherTarget from "../publisher-target";
|
import PublisherTarget from "../publisher-target";
|
||||||
import { convertToCurseForgeVersions, uploadFile } from "../../utils/curseforge-utils";
|
import { convertToCurseForgeVersions, uploadFile } from "../../utils/curseforge";
|
||||||
import Dependency from "../../metadata/dependency";
|
import Dependency from "../../metadata/dependency";
|
||||||
import DependencyKind from "../../metadata/dependency-kind";
|
import DependencyKind from "../../metadata/dependency-kind";
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import PublisherTarget from "../publisher-target";
|
import PublisherTarget from "../publisher-target";
|
||||||
import * as github from "@actions/github";
|
import * as github from "@actions/github";
|
||||||
import { File } from "../../utils/file";
|
import File from "../../utils/io/file";
|
||||||
import ModPublisher from "../../publishing/mod-publisher";
|
import ModPublisher from "../../publishing/mod-publisher";
|
||||||
import Dependency from "../../metadata/dependency";
|
import Dependency from "../../metadata/dependency";
|
||||||
import { mapStringInput, mapBooleanInput } from "../../utils/input-utils";
|
import { mapStringInput, mapBooleanInput } from "../../utils/actions/input";
|
||||||
import { VersionType } from "../../utils/version-utils";
|
import VersionType from "../../utils/versioning/version-type";
|
||||||
import { env } from "process";
|
import { env } from "process";
|
||||||
|
|
||||||
function getEnvironmentTag(): string | undefined {
|
function getEnvironmentTag(): string | undefined {
|
||||||
|
@ -49,7 +49,7 @@ export default class GitHubPublisher extends ModPublisher {
|
||||||
}
|
}
|
||||||
|
|
||||||
const generated = !releaseId;
|
const generated = !releaseId;
|
||||||
if (generated && (tag ??= environmentTag ?? version)) {
|
if (!releaseId && (tag ??= environmentTag ?? version)) {
|
||||||
const generateChangelog = mapBooleanInput(options.generateChangelog, !changelog);
|
const generateChangelog = mapBooleanInput(options.generateChangelog, !changelog);
|
||||||
const draft = mapBooleanInput(options.draft, false);
|
const draft = mapBooleanInput(options.draft, false);
|
||||||
const prerelease = mapBooleanInput(options.prerelease, channel !== VersionType.Release);
|
const prerelease = mapBooleanInput(options.prerelease, channel !== VersionType.Release);
|
||||||
|
@ -58,7 +58,7 @@ export default class GitHubPublisher extends ModPublisher {
|
||||||
releaseId = await this.createRelease(tag, name, changelog, generateChangelog, draft, prerelease, commitish, discussion, token);
|
releaseId = await this.createRelease(tag, name, changelog, generateChangelog, draft, prerelease, commitish, discussion, token);
|
||||||
}
|
}
|
||||||
if (!releaseId) {
|
if (!releaseId) {
|
||||||
throw new Error(`Cannot find or create release ${tag || `#${releaseId}`}`);
|
throw new Error(`Cannot find or create release ${tag}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingAssets = generated ? [] : (await octokit.rest.repos.listReleaseAssets({ ...repo, release_id: releaseId })).data;
|
const existingAssets = generated ? [] : (await octokit.rest.repos.listReleaseAssets({ ...repo, release_id: releaseId })).data;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { context } from "@actions/github";
|
import { context } from "@actions/github";
|
||||||
import { parseVersionName, parseVersionNameFromFileVersion } from "../utils/minecraft-utils";
|
import { parseVersionName, parseVersionNameFromFileVersion } from "../utils/minecraft";
|
||||||
import { File } from "../utils/file";
|
import File from "../utils/io/file";
|
||||||
import { getFiles } from "../utils/file-utils";
|
|
||||||
import Publisher from "./publisher";
|
import Publisher from "./publisher";
|
||||||
import PublisherTarget from "./publisher-target";
|
import PublisherTarget from "./publisher-target";
|
||||||
import MinecraftVersionResolver from "../utils/minecraft-version-resolver";
|
import MinecraftVersionResolver from "../utils/minecraft/minecraft-version-resolver";
|
||||||
import ModMetadataReader from "../metadata/mod-metadata-reader";
|
import ModMetadataReader from "../metadata/mod-metadata-reader";
|
||||||
import Dependency from "../metadata/dependency";
|
import Dependency from "../metadata/dependency";
|
||||||
import { parseVersionFromName, parseVersionTypeFromName } from "../utils/version-utils";
|
import Version from "../utils/versioning/version";
|
||||||
|
import VersionType from "../utils/versioning/version-type";
|
||||||
import DependencyKind from "../metadata/dependency-kind";
|
import DependencyKind from "../metadata/dependency-kind";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ function processDependenciesInput(input: string | string[], inputSplitter?: RegE
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readChangelog(changelogPath: string): Promise<string | never> {
|
async function readChangelog(changelogPath: string): Promise<string | never> {
|
||||||
const file = (await getFiles(changelogPath))[0];
|
const file = (await File.getFiles(changelogPath))[0];
|
||||||
if (!file) {
|
if (!file) {
|
||||||
throw new Error("Changelog file was not found");
|
throw new Error("Changelog file was not found");
|
||||||
}
|
}
|
||||||
|
@ -87,8 +87,8 @@ export default abstract class ModPublisher extends Publisher<ModPublisherOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
const filename = path.parse(files[0].path).name;
|
const filename = path.parse(files[0].path).name;
|
||||||
const version = (typeof options.version === "string" && options.version) || <string>releaseInfo?.tag_name || metadata?.version || parseVersionFromName(filename);
|
const version = (typeof options.version === "string" && options.version) || <string>releaseInfo?.tag_name || metadata?.version || Version.fromName(filename);
|
||||||
const versionType = options.versionType?.toLowerCase() || parseVersionTypeFromName(metadata?.version || filename);
|
const versionType = options.versionType?.toLowerCase() || VersionType.fromName(metadata?.version || filename);
|
||||||
const name = typeof options.name === "string" ? options.name : (<string>releaseInfo?.name || version);
|
const name = typeof options.name === "string" ? options.name : (<string>releaseInfo?.name || version);
|
||||||
const changelog = typeof options.changelog === "string"
|
const changelog = typeof options.changelog === "string"
|
||||||
? options.changelog
|
? options.changelog
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { createVersion, getProject, getVersions, modifyVersion } from "../../utils/modrinth-utils";
|
import { createVersion, getProject, getVersions, modifyVersion } from "../../utils/modrinth";
|
||||||
import { File } from "../../utils/file";
|
import File from "../../utils/io/file";
|
||||||
import ModPublisher from "../mod-publisher";
|
import ModPublisher from "../mod-publisher";
|
||||||
import PublisherTarget from "../publisher-target";
|
import PublisherTarget from "../publisher-target";
|
||||||
import Dependency from "../../metadata/dependency";
|
import Dependency from "../../metadata/dependency";
|
||||||
import DependencyKind from "../../metadata/dependency-kind";
|
import DependencyKind from "../../metadata/dependency-kind";
|
||||||
import { mapBooleanInput, mapEnumInput } from "../../utils/input-utils";
|
import { mapBooleanInput, mapEnumInput } from "../../utils/actions/input";
|
||||||
import LoggingStopwatch from "../../utils/logging-stopwatch";
|
import LoggingStopwatch from "../../utils/logging/logging-stopwatch";
|
||||||
|
|
||||||
enum UnfeatureMode {
|
enum UnfeatureMode {
|
||||||
None = 0,
|
None = 0,
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PublisherTarget from "./publisher-target";
|
||||||
import GitHubPublisher from "./github/github-publisher";
|
import GitHubPublisher from "./github/github-publisher";
|
||||||
import ModrinthPublisher from "./modrinth/modrinth-publisher";
|
import ModrinthPublisher from "./modrinth/modrinth-publisher";
|
||||||
import CurseForgePublisher from "./curseforge/curseforge-publisher";
|
import CurseForgePublisher from "./curseforge/curseforge-publisher";
|
||||||
import Logger from "../utils/logger";
|
import Logger from "../utils/logging/logger";
|
||||||
|
|
||||||
export default class PublisherFactory {
|
export default class PublisherFactory {
|
||||||
public create(target: PublisherTarget, logger?: Logger): Publisher<unknown> {
|
public create(target: PublisherTarget, logger?: Logger): Publisher<unknown> {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { File } from "../utils/file";
|
import File from "../utils/io/file";
|
||||||
import Logger from "../utils/logger";
|
import Logger from "../utils/logging/logger";
|
||||||
import { getEmptyLogger } from "../utils/logger-utils";
|
import { getEmptyLogger } from "../utils/logging/logger";
|
||||||
import PublisherTarget from "./publisher-target";
|
import PublisherTarget from "./publisher-target";
|
||||||
|
|
||||||
export default abstract class Publisher<TOptions> {
|
export default abstract class Publisher<TOptions> {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import FormData from "form-data";
|
import FormData from "form-data";
|
||||||
import { File } from "./file";
|
import File from "../io/file";
|
||||||
import { findVersionByName } from "./minecraft-utils";
|
import { findVersionByName } from "../minecraft";
|
||||||
import SoftError from "./soft-error";
|
import SoftError from "../soft-error";
|
||||||
|
|
||||||
const baseUrl = "https://minecraft.curseforge.com/api";
|
const baseUrl = "https://minecraft.curseforge.com/api";
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ class CurseForgeUploadError extends SoftError {
|
||||||
async function fetchJsonArray<T>(url: string): Promise<T[] | never> {
|
async function fetchJsonArray<T>(url: string): Promise<T[] | never> {
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const isServerError = response.status >= 500;
|
const isSoft = response.status === 429 || response.status >= 500;
|
||||||
throw new SoftError(isServerError, `${response.status} (${response.statusText})`);
|
throw new SoftError(isSoft, `${response.status} (${response.statusText})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let array: T[];
|
let array: T[];
|
||||||
|
@ -145,8 +145,8 @@ export async function uploadFile(id: string, data: Record<string, any>, file: Fi
|
||||||
info = <CurseForgeUploadErrorInfo>await response.json();
|
info = <CurseForgeUploadErrorInfo>await response.json();
|
||||||
errorText += `, ${JSON.stringify(info)}`;
|
errorText += `, ${JSON.stringify(info)}`;
|
||||||
} catch { }
|
} catch { }
|
||||||
const isServerError = response.status >= 500;
|
const isSoftError = response.status === 429 || response.status >= 500;
|
||||||
throw new CurseForgeUploadError(isServerError, `Failed to upload file: ${response.status} (${errorText})`, info);
|
throw new CurseForgeUploadError(isSoftError, `Failed to upload file: ${response.status} (${errorText})`, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<{ id: number }>await response.json()).id;
|
return (<{ id: number }>await response.json()).id;
|
|
@ -1,36 +0,0 @@
|
||||||
import glob from "fast-glob";
|
|
||||||
import { File } from "./file";
|
|
||||||
|
|
||||||
export type FileSelector = string | { primary?: string, secondary?: string };
|
|
||||||
|
|
||||||
export const gradleOutputSelector: FileSelector = {
|
|
||||||
primary: "build/libs/!(*-@(dev|sources)).jar",
|
|
||||||
secondary: "build/libs/*-@(dev|sources).jar"
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function getRequiredFiles(files: FileSelector): Promise<File[] | never> {
|
|
||||||
const foundFiles = await getFiles(files);
|
|
||||||
if (foundFiles && foundFiles.length) {
|
|
||||||
return foundFiles;
|
|
||||||
}
|
|
||||||
throw new Error(`Specified files ('${typeof files === "string" ? files : [files.primary, files.secondary].filter(x => x).join(", ")}') were not found`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getFiles(files: FileSelector): Promise<File[]> {
|
|
||||||
if (!files || typeof files !== "string" && !files.primary && !files.secondary) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof files === "string") {
|
|
||||||
return (await glob(files)).map(x => new File(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
let results = [];
|
|
||||||
if (files.primary) {
|
|
||||||
results = (await glob(files.primary)).map(x => new File(x));
|
|
||||||
}
|
|
||||||
if (files.secondary) {
|
|
||||||
results = results.concat((await glob(files.secondary)).map(x => new File(x)));
|
|
||||||
}
|
|
||||||
return results.filter((x, i, self) => self.findIndex(y => x.equals(y)) === i);
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
import fs from "fs";
|
|
||||||
import path from "path";
|
|
||||||
|
|
||||||
export class File {
|
|
||||||
public name: string;
|
|
||||||
public path: string;
|
|
||||||
|
|
||||||
public constructor(filePath: string) {
|
|
||||||
this.name = path.basename(filePath);
|
|
||||||
this.path = filePath;
|
|
||||||
Object.freeze(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getStream(): fs.ReadStream {
|
|
||||||
return fs.createReadStream(this.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getBuffer(): Promise<Buffer> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
fs.readFile(this.path, (error, data) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
} else {
|
|
||||||
resolve(data);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public equals(file: unknown): boolean {
|
|
||||||
return file instanceof File && file.path === this.path;
|
|
||||||
}
|
|
||||||
}
|
|
68
src/utils/io/file.ts
Normal file
68
src/utils/io/file.ts
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
import glob from "fast-glob";
|
||||||
|
|
||||||
|
export type FileSelector = string | { primary?: string, secondary?: string };
|
||||||
|
|
||||||
|
export const gradleOutputSelector = {
|
||||||
|
primary: "build/libs/!(*-@(dev|sources)).jar",
|
||||||
|
secondary: "build/libs/*-@(dev|sources).jar"
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class File {
|
||||||
|
public name: string;
|
||||||
|
public path: string;
|
||||||
|
|
||||||
|
public constructor(filePath: string) {
|
||||||
|
this.name = path.basename(filePath);
|
||||||
|
this.path = filePath;
|
||||||
|
Object.freeze(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getStream(): fs.ReadStream {
|
||||||
|
return fs.createReadStream(this.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getBuffer(): Promise<Buffer> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
fs.readFile(this.path, (error, data) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve(data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public equals(file: unknown): boolean {
|
||||||
|
return file instanceof File && file.path === this.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async getFiles(files: FileSelector): Promise<File[]> {
|
||||||
|
if (!files || typeof files !== "string" && !files.primary && !files.secondary) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof files === "string") {
|
||||||
|
return (await glob(files)).map(x => new File(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
let results = [];
|
||||||
|
if (files.primary) {
|
||||||
|
results = (await glob(files.primary)).map(x => new File(x));
|
||||||
|
}
|
||||||
|
if (files.secondary) {
|
||||||
|
results = results.concat((await glob(files.secondary)).map(x => new File(x)));
|
||||||
|
}
|
||||||
|
return results.filter((x, i, self) => self.findIndex(y => x.equals(y)) === i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async getRequiredFiles(files: FileSelector): Promise<File[] | never> {
|
||||||
|
const foundFiles = await File.getFiles(files);
|
||||||
|
if (foundFiles && foundFiles.length) {
|
||||||
|
return foundFiles;
|
||||||
|
}
|
||||||
|
throw new Error(`Specified files ('${typeof files === "string" ? files : [files.primary, files.secondary].filter(x => x).join(", ")}') were not found`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
export default interface Logger {
|
|
||||||
fatal(message: string | Error): void;
|
|
||||||
error(message: string | Error): void;
|
|
||||||
warn(message: string | Error): void;
|
|
||||||
info(message: string | Error): void;
|
|
||||||
debug(message: string | Error): void;
|
|
||||||
}
|
|
|
@ -1,6 +1,13 @@
|
||||||
import * as actions from "@actions/core";
|
import * as actions from "@actions/core";
|
||||||
import * as console from "console";
|
import * as console from "console";
|
||||||
import Logger from "./logger";
|
|
||||||
|
export default interface Logger {
|
||||||
|
fatal(message: string | Error): void;
|
||||||
|
error(message: string | Error): void;
|
||||||
|
warn(message: string | Error): void;
|
||||||
|
info(message: string | Error): void;
|
||||||
|
debug(message: string | Error): void;
|
||||||
|
}
|
||||||
|
|
||||||
export function getDefaultLogger(): Logger {
|
export function getDefaultLogger(): Logger {
|
||||||
return {
|
return {
|
|
@ -1,5 +1,5 @@
|
||||||
import Logger from "./logger";
|
import Logger from "./logger";
|
||||||
import Stopwatch from "./stopwatch";
|
import Stopwatch from "../diagnostics/stopwatch";
|
||||||
|
|
||||||
interface StartCallback {
|
interface StartCallback {
|
||||||
(currentDate: Date, stopwatch: Stopwatch): string;
|
(currentDate: Date, stopwatch: Stopwatch): string;
|
|
@ -1,5 +1,5 @@
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import Version from "./version";
|
import Version from "../versioning/version";
|
||||||
|
|
||||||
export enum MinecraftVersionType {
|
export enum MinecraftVersionType {
|
||||||
Release = "release",
|
Release = "release",
|
|
@ -1,6 +1,6 @@
|
||||||
import GameVersionResolver from "./game-version-resolver";
|
import GameVersionResolver from "../versioning/game-version-resolver";
|
||||||
import { getCompatibleBuilds, MinecraftVersion } from "./minecraft-utils";
|
import { getCompatibleBuilds, MinecraftVersion } from ".";
|
||||||
import Version from "./version";
|
import Version from "../versioning/version";
|
||||||
|
|
||||||
export default class MinecraftVersionResolver extends GameVersionResolver<MinecraftVersion> {
|
export default class MinecraftVersionResolver extends GameVersionResolver<MinecraftVersion> {
|
||||||
public static readonly exact = new MinecraftVersionResolver((n, v) => [v.find(x => x.version.equals(n))].filter(x => x));
|
public static readonly exact = new MinecraftVersionResolver((n, v) => [v.find(x => x.version.equals(n))].filter(x => x));
|
|
@ -1,8 +1,8 @@
|
||||||
import FormData from "form-data";
|
import FormData from "form-data";
|
||||||
import fetch, { Response } from "node-fetch";
|
import fetch, { Response } from "node-fetch";
|
||||||
import { URLSearchParams } from "url";
|
import { URLSearchParams } from "url";
|
||||||
import { File } from "./file";
|
import File from "../io/file";
|
||||||
import SoftError from "./soft-error";
|
import SoftError from "../soft-error";
|
||||||
|
|
||||||
const baseUrl = "https://api.modrinth.com/v2";
|
const baseUrl = "https://api.modrinth.com/v2";
|
||||||
|
|
||||||
|
@ -100,10 +100,10 @@ async function processResponse<T>(response: Response | Promise<Response>, mapper
|
||||||
errorText += `, ${await response.text()}`;
|
errorText += `, ${await response.text()}`;
|
||||||
} catch { }
|
} catch { }
|
||||||
errorText = `${response.status} (${errorText})`;
|
errorText = `${response.status} (${errorText})`;
|
||||||
const isServerError = response.status >= 500;
|
const isSoftError = response.status === 429 || response.status >= 500;
|
||||||
if (errorFactory) {
|
if (errorFactory) {
|
||||||
throw errorFactory(isServerError, errorText, response);
|
throw errorFactory(isSoftError, errorText, response);
|
||||||
} else {
|
} else {
|
||||||
throw new SoftError(isServerError, errorText);
|
throw new SoftError(isSoftError, errorText);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import sleep from "./sleep";
|
import sleep from "./sleep";
|
||||||
|
|
||||||
export async function retry<T>({ func, delay = 0, maxAttempts = -1, softErrorPredicate, errorCallback }: { func: () => T | Promise<T>, delay?: number, maxAttempts?: number, softErrorPredicate?: (error: unknown) => boolean, errorCallback?: (error: unknown) => void }): Promise<T> {
|
export default async function retry<T>({ func, delay = 0, maxAttempts = -1, softErrorPredicate, errorCallback }: { func: () => T | Promise<T>, delay?: number, maxAttempts?: number, softErrorPredicate?: (error: unknown) => boolean, errorCallback?: (error: unknown) => void }): Promise<T> {
|
||||||
let attempts = 0;
|
let attempts = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
|
@ -1,20 +0,0 @@
|
||||||
export enum VersionType {
|
|
||||||
Alpha = "alpha",
|
|
||||||
Beta = "beta",
|
|
||||||
Release = "release",
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseVersionFromName(name: string): string {
|
|
||||||
const match = name.match(/[a-z]{0,2}\d+\.\d+.*/i);
|
|
||||||
return match ? match[0] : name;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseVersionTypeFromName(name: string): VersionType {
|
|
||||||
if (name.match(/[+-_]alpha/i)) {
|
|
||||||
return VersionType.Alpha;
|
|
||||||
} else if (name.match(/[+-_]beta/i)) {
|
|
||||||
return VersionType.Beta;
|
|
||||||
} else {
|
|
||||||
return VersionType.Release;
|
|
||||||
}
|
|
||||||
}
|
|
19
src/utils/versioning/version-type.ts
Normal file
19
src/utils/versioning/version-type.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
enum VersionType {
|
||||||
|
Alpha = "alpha",
|
||||||
|
Beta = "beta",
|
||||||
|
Release = "release"
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace VersionType {
|
||||||
|
export function fromName(name: string): VersionType {
|
||||||
|
if (name.match(/[+-_]alpha/i)) {
|
||||||
|
return VersionType.Alpha;
|
||||||
|
} else if (name.match(/[+-_]beta/i)) {
|
||||||
|
return VersionType.Beta;
|
||||||
|
} else {
|
||||||
|
return VersionType.Release;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VersionType;
|
|
@ -23,4 +23,9 @@ export default class Version {
|
||||||
}
|
}
|
||||||
return typeof version === "string" && this.equals(new Version(version));
|
return typeof version === "string" && this.equals(new Version(version));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static fromName(name: string): string {
|
||||||
|
const match = name.match(/[a-z]{0,2}\d+\.\d+.*/i);
|
||||||
|
return match ? match[0] : name;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,28 +0,0 @@
|
||||||
import { describe, test, expect } from "@jest/globals";
|
|
||||||
import { getFiles, getRequiredFiles } from "../src/utils/file-utils";
|
|
||||||
|
|
||||||
describe("getFiles", () => {
|
|
||||||
test("all files matching the given pattern are returned", async () => {
|
|
||||||
expect(await getFiles("(README|LICENSE|FOO).md")).toHaveLength(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("files matching the primary pattern are returned first", async () => {
|
|
||||||
const files = await getFiles({ primary: "README.md", secondary: "(README|LICENSE|FOO).md" });
|
|
||||||
expect(files).toHaveLength(2);
|
|
||||||
expect(files[0]).toHaveProperty("name", "README.md");
|
|
||||||
|
|
||||||
const inversedFiles = await getFiles({ primary: "LICENSE.md", secondary: "(README|LICENSE|FOO).md" });
|
|
||||||
expect(inversedFiles).toHaveLength(2);
|
|
||||||
expect(inversedFiles[0]).toHaveProperty("name", "LICENSE.md");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("getRequiredFiles", () => {
|
|
||||||
test("all files matching the given pattern are returned", async () => {
|
|
||||||
expect(await getRequiredFiles("(README|LICENSE|FOO).md")).toHaveLength(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("an error is thrown if no files are found", async () => {
|
|
||||||
await expect(getRequiredFiles("FOO.md")).rejects.toBeInstanceOf(Error);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { describe, test, expect } from "@jest/globals";
|
import { describe, test, expect } from "@jest/globals";
|
||||||
import DependencyKind from "../src/metadata/dependency-kind";
|
import DependencyKind from "../../../src/metadata/dependency-kind";
|
||||||
|
|
||||||
describe("DependencyKind.getValues", () => {
|
describe("DependencyKind.getValues", () => {
|
||||||
test("all DependencyKind values are returned", () => {
|
test("all DependencyKind values are returned", () => {
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, test, expect } from "@jest/globals";
|
import { describe, test, expect } from "@jest/globals";
|
||||||
import ModLoaderType from "../src/metadata/mod-loader-type";
|
import ModLoaderType from "../../../src/metadata/mod-loader-type";
|
||||||
import ModMetadataReaderFactory from "../src/metadata/mod-metadata-reader-factory";
|
import ModMetadataReaderFactory from "../../../src/metadata/mod-metadata-reader-factory";
|
||||||
|
|
||||||
describe("ModMetadataReaderFactory.create", () => {
|
describe("ModMetadataReaderFactory.create", () => {
|
||||||
test("factory can create metadata reader for every ModLoaderType value", () => {
|
test("factory can create metadata reader for every ModLoaderType value", () => {
|
|
@ -1,8 +1,8 @@
|
||||||
import { describe, test, expect, beforeAll, afterAll } from "@jest/globals";
|
import { describe, test, expect, beforeAll, afterAll } from "@jest/globals";
|
||||||
import Dependency from "../src/metadata/dependency";
|
import Dependency from "../../../src/metadata/dependency";
|
||||||
import DependencyKind from "../src/metadata/dependency-kind";
|
import DependencyKind from "../../../src/metadata/dependency-kind";
|
||||||
import ModMetadataReader from "../src/metadata/mod-metadata-reader";
|
import ModMetadataReader from "../../../src/metadata/mod-metadata-reader";
|
||||||
import PublisherTarget from "../src/publishing/publisher-target";
|
import PublisherTarget from "../../../src/publishing/publisher-target";
|
||||||
import { ZipFile } from "yazl";
|
import { ZipFile } from "yazl";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
|
||||||
|
@ -23,22 +23,22 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("mod info can be read", async () => {
|
test("mod info can be read", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.fabric.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!;
|
||||||
expect(metadata.id).toBe("example-mod");
|
expect(metadata.id).toBe("example-mod");
|
||||||
expect(metadata.name).toBe("Example Mod");
|
expect(metadata.name).toBe("Example Mod");
|
||||||
expect(metadata.version).toBe("0.1.0");
|
expect(metadata.version).toBe("0.1.0");
|
||||||
expect(metadata.loaders).toMatchObject(["fabric"]);
|
expect(metadata.loaders).toMatchObject(["fabric"] as any);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("project ids can be specified in the config file", async () => {
|
test("project ids can be specified in the config file", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.fabric.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!;
|
||||||
expect(metadata.getProjectId(PublisherTarget.Modrinth)).toBe("AANobbMI");
|
expect(metadata.getProjectId(PublisherTarget.Modrinth)).toBe("AANobbMI");
|
||||||
expect(metadata.getProjectId(PublisherTarget.CurseForge)).toBe("394468");
|
expect(metadata.getProjectId(PublisherTarget.CurseForge)).toBe("394468");
|
||||||
expect(metadata.getProjectId(PublisherTarget.GitHub)).toBe("mc1.18-0.4.0-alpha5");
|
expect(metadata.getProjectId(PublisherTarget.GitHub)).toBe("mc1.18-0.4.0-alpha5");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("all dependencies are read", async () => {
|
test("all dependencies are read", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.fabric.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!;
|
||||||
expect(metadata.dependencies).toHaveLength(9);
|
expect(metadata.dependencies).toHaveLength(9);
|
||||||
const dependencies = metadata.dependencies.reduce((agg, x) => { agg[x.id] = x; return agg; }, <Record<string, Dependency>>{});
|
const dependencies = metadata.dependencies.reduce((agg, x) => { agg[x.id] = x; return agg; }, <Record<string, Dependency>>{});
|
||||||
expect(dependencies["fabricloader"]?.kind).toBe(DependencyKind.Depends);
|
expect(dependencies["fabricloader"]?.kind).toBe(DependencyKind.Depends);
|
||||||
|
@ -53,8 +53,8 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("dependency info can be read", async () => {
|
test("dependency info can be read", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.fabric.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!;
|
||||||
const conflicting = metadata.dependencies.find(x => x.id === "conflicting-mod");
|
const conflicting = metadata.dependencies.find(x => x.id === "conflicting-mod")!;
|
||||||
expect(conflicting).toBeTruthy();
|
expect(conflicting).toBeTruthy();
|
||||||
expect(conflicting.id).toBe("conflicting-mod");
|
expect(conflicting.id).toBe("conflicting-mod");
|
||||||
expect(conflicting.kind).toBe(DependencyKind.Conflicts);
|
expect(conflicting.kind).toBe(DependencyKind.Conflicts);
|
||||||
|
@ -66,8 +66,8 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("custom metadata can be attached to dependency entry", async () => {
|
test("custom metadata can be attached to dependency entry", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.fabric.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!;
|
||||||
const recommended = metadata.dependencies.find(x => x.id === "recommended-mod");
|
const recommended = metadata.dependencies.find(x => x.id === "recommended-mod")!;
|
||||||
expect(recommended).toBeTruthy();
|
expect(recommended).toBeTruthy();
|
||||||
expect(recommended.id).toBe("recommended-mod");
|
expect(recommended.id).toBe("recommended-mod");
|
||||||
expect(recommended.kind).toBe(DependencyKind.Recommends);
|
expect(recommended.kind).toBe(DependencyKind.Recommends);
|
||||||
|
@ -79,15 +79,15 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("special case dependencies (minecraft, java and fabricloader) are ignored by default", async () => {
|
test("special case dependencies (minecraft, java and fabricloader) are ignored by default", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.fabric.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!;
|
||||||
expect(metadata.dependencies.find(x => x.id === "minecraft").ignore).toBe(true);
|
expect(metadata.dependencies.find(x => x.id === "minecraft")!.ignore).toBe(true);
|
||||||
expect(metadata.dependencies.find(x => x.id === "java").ignore).toBe(true);
|
expect(metadata.dependencies.find(x => x.id === "java")!.ignore).toBe(true);
|
||||||
expect(metadata.dependencies.find(x => x.id === "fabricloader").ignore).toBe(true);
|
expect(metadata.dependencies.find(x => x.id === "fabricloader")!.ignore).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("special case dependencies (fabric) are replaced with their aliases", async() => {
|
test("special case dependencies (fabric) are replaced with their aliases", async() => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.fabric.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!;
|
||||||
const fabric = metadata.dependencies.find(x => x.id === "fabric");
|
const fabric = metadata.dependencies.find(x => x.id === "fabric")!;
|
||||||
for (const target of PublisherTarget.getValues()) {
|
for (const target of PublisherTarget.getValues()) {
|
||||||
expect(fabric.getProjectSlug(target) === "fabric-api");
|
expect(fabric.getProjectSlug(target) === "fabric-api");
|
||||||
}
|
}
|
||||||
|
@ -110,22 +110,22 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("mod info can be read", async () => {
|
test("mod info can be read", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.forge.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!;
|
||||||
expect(metadata.id).toBe("example-mod");
|
expect(metadata.id).toBe("example-mod");
|
||||||
expect(metadata.name).toBe("Example Mod");
|
expect(metadata.name).toBe("Example Mod");
|
||||||
expect(metadata.version).toBe("0.1.0");
|
expect(metadata.version).toBe("0.1.0");
|
||||||
expect(metadata.loaders).toMatchObject(["forge"]);
|
expect(metadata.loaders).toMatchObject(["forge"] as any);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("project ids can be specified in the config file", async () => {
|
test("project ids can be specified in the config file", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.forge.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!;
|
||||||
expect(metadata.getProjectId(PublisherTarget.Modrinth)).toBe("AANobbMI");
|
expect(metadata.getProjectId(PublisherTarget.Modrinth)).toBe("AANobbMI");
|
||||||
expect(metadata.getProjectId(PublisherTarget.CurseForge)).toBe("394468");
|
expect(metadata.getProjectId(PublisherTarget.CurseForge)).toBe("394468");
|
||||||
expect(metadata.getProjectId(PublisherTarget.GitHub)).toBe("mc1.18-0.4.0-alpha5");
|
expect(metadata.getProjectId(PublisherTarget.GitHub)).toBe("mc1.18-0.4.0-alpha5");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("all dependencies are read", async () => {
|
test("all dependencies are read", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.forge.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!;
|
||||||
expect(metadata.dependencies).toHaveLength(6);
|
expect(metadata.dependencies).toHaveLength(6);
|
||||||
const dependencies = metadata.dependencies.reduce((agg, x) => { agg[x.id] = x; return agg; }, <Record<string, Dependency>>{});
|
const dependencies = metadata.dependencies.reduce((agg, x) => { agg[x.id] = x; return agg; }, <Record<string, Dependency>>{});
|
||||||
expect(dependencies["forge"]?.kind).toBe(DependencyKind.Depends);
|
expect(dependencies["forge"]?.kind).toBe(DependencyKind.Depends);
|
||||||
|
@ -137,8 +137,8 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("dependency info can be read", async () => {
|
test("dependency info can be read", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.forge.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!;
|
||||||
const included = metadata.dependencies.find(x => x.id === "included-mod");
|
const included = metadata.dependencies.find(x => x.id === "included-mod")!;
|
||||||
expect(included).toBeTruthy();
|
expect(included).toBeTruthy();
|
||||||
expect(included.id).toBe("included-mod");
|
expect(included.id).toBe("included-mod");
|
||||||
expect(included.kind).toBe(DependencyKind.Includes);
|
expect(included.kind).toBe(DependencyKind.Includes);
|
||||||
|
@ -150,8 +150,8 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("custom metadata can be attached to dependency entry", async () => {
|
test("custom metadata can be attached to dependency entry", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.forge.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!;
|
||||||
const recommended = metadata.dependencies.find(x => x.id === "recommended-mod");
|
const recommended = metadata.dependencies.find(x => x.id === "recommended-mod")!;
|
||||||
expect(recommended).toBeTruthy();
|
expect(recommended).toBeTruthy();
|
||||||
expect(recommended.id).toBe("recommended-mod");
|
expect(recommended.id).toBe("recommended-mod");
|
||||||
expect(recommended.kind).toBe(DependencyKind.Recommends);
|
expect(recommended.kind).toBe(DependencyKind.Recommends);
|
||||||
|
@ -163,10 +163,10 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("special case dependencies (minecraft, java and forge) are ignored by default", async () => {
|
test("special case dependencies (minecraft, java and forge) are ignored by default", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.forge.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!;
|
||||||
expect(metadata.dependencies.find(x => x.id === "minecraft").ignore).toBe(true);
|
expect(metadata.dependencies.find(x => x.id === "minecraft")!.ignore).toBe(true);
|
||||||
expect(metadata.dependencies.find(x => x.id === "java").ignore).toBe(true);
|
expect(metadata.dependencies.find(x => x.id === "java")!.ignore).toBe(true);
|
||||||
expect(metadata.dependencies.find(x => x.id === "forge").ignore).toBe(true);
|
expect(metadata.dependencies.find(x => x.id === "forge")!.ignore).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -186,22 +186,22 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("mod info can be read", async () => {
|
test("mod info can be read", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.quilt.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!;
|
||||||
expect(metadata.id).toBe("example-mod");
|
expect(metadata.id).toBe("example-mod");
|
||||||
expect(metadata.name).toBe("Example Mod");
|
expect(metadata.name).toBe("Example Mod");
|
||||||
expect(metadata.version).toBe("0.1.0");
|
expect(metadata.version).toBe("0.1.0");
|
||||||
expect(metadata.loaders).toMatchObject(["quilt"]);
|
expect(metadata.loaders).toMatchObject(["quilt"] as any);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("project ids can be specified in the config file", async () => {
|
test("project ids can be specified in the config file", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.quilt.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!;
|
||||||
expect(metadata.getProjectId(PublisherTarget.Modrinth)).toBe("AANobbMI");
|
expect(metadata.getProjectId(PublisherTarget.Modrinth)).toBe("AANobbMI");
|
||||||
expect(metadata.getProjectId(PublisherTarget.CurseForge)).toBe("394468");
|
expect(metadata.getProjectId(PublisherTarget.CurseForge)).toBe("394468");
|
||||||
expect(metadata.getProjectId(PublisherTarget.GitHub)).toBe("mc1.18-0.4.0-alpha5");
|
expect(metadata.getProjectId(PublisherTarget.GitHub)).toBe("mc1.18-0.4.0-alpha5");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("all dependencies are read", async () => {
|
test("all dependencies are read", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.quilt.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!;
|
||||||
expect(metadata.dependencies).toHaveLength(8);
|
expect(metadata.dependencies).toHaveLength(8);
|
||||||
const dependencies = metadata.dependencies.reduce((agg, x) => { agg[x.id] = x; return agg; }, <Record<string, Dependency>>{});
|
const dependencies = metadata.dependencies.reduce((agg, x) => { agg[x.id] = x; return agg; }, <Record<string, Dependency>>{});
|
||||||
expect(dependencies["quilt_loader"]?.kind).toBe(DependencyKind.Depends);
|
expect(dependencies["quilt_loader"]?.kind).toBe(DependencyKind.Depends);
|
||||||
|
@ -215,8 +215,8 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("dependency info can be read", async () => {
|
test("dependency info can be read", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.quilt.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!;
|
||||||
const conflicting = metadata.dependencies.find(x => x.id === "conflicting-mod");
|
const conflicting = metadata.dependencies.find(x => x.id === "conflicting-mod")!;
|
||||||
expect(conflicting).toBeTruthy();
|
expect(conflicting).toBeTruthy();
|
||||||
expect(conflicting.id).toBe("conflicting-mod");
|
expect(conflicting.id).toBe("conflicting-mod");
|
||||||
expect(conflicting.kind).toBe(DependencyKind.Conflicts);
|
expect(conflicting.kind).toBe(DependencyKind.Conflicts);
|
||||||
|
@ -228,8 +228,8 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("custom metadata can be attached to dependency entry", async () => {
|
test("custom metadata can be attached to dependency entry", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.quilt.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!;
|
||||||
const recommended = metadata.dependencies.find(x => x.id === "recommended-mod");
|
const recommended = metadata.dependencies.find(x => x.id === "recommended-mod")!;
|
||||||
expect(recommended).toBeTruthy();
|
expect(recommended).toBeTruthy();
|
||||||
expect(recommended.id).toBe("recommended-mod");
|
expect(recommended.id).toBe("recommended-mod");
|
||||||
expect(recommended.kind).toBe(DependencyKind.Recommends);
|
expect(recommended.kind).toBe(DependencyKind.Recommends);
|
||||||
|
@ -241,15 +241,15 @@ describe("ModMetadataReader.readMetadata", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("special case dependencies (minecraft, java and quilt_loader) are ignored by default", async () => {
|
test("special case dependencies (minecraft, java and quilt_loader) are ignored by default", async () => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.quilt.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!;
|
||||||
expect(metadata.dependencies.find(x => x.id === "minecraft").ignore).toBe(true);
|
expect(metadata.dependencies.find(x => x.id === "minecraft")!.ignore).toBe(true);
|
||||||
expect(metadata.dependencies.find(x => x.id === "java").ignore).toBe(true);
|
expect(metadata.dependencies.find(x => x.id === "java")!.ignore).toBe(true);
|
||||||
expect(metadata.dependencies.find(x => x.id === "quilt_loader").ignore).toBe(true);
|
expect(metadata.dependencies.find(x => x.id === "quilt_loader")!.ignore).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("special case dependencies (quilted_quilt_api) are replaced with their aliases", async() => {
|
test("special case dependencies (quilted_quilt_api) are replaced with their aliases", async() => {
|
||||||
const metadata = await ModMetadataReader.readMetadata("example-mod.quilt.jar");
|
const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!;
|
||||||
const quilt = metadata.dependencies.find(x => x.id === "quilt_base");
|
const quilt = metadata.dependencies.find(x => x.id === "quilt_base")!;
|
||||||
for (const target of PublisherTarget.getValues()) {
|
for (const target of PublisherTarget.getValues()) {
|
||||||
expect(quilt.getProjectSlug(target) === "qsl");
|
expect(quilt.getProjectSlug(target) === "qsl");
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import { describe, test, expect } from "@jest/globals";
|
import { describe, test, expect } from "@jest/globals";
|
||||||
import PublisherFactory from "../src/publishing/publisher-factory";
|
import PublisherFactory from "../../../src/publishing/publisher-factory";
|
||||||
import PublisherTarget from "../src/publishing/publisher-target";
|
import PublisherTarget from "../../../src/publishing/publisher-target";
|
||||||
import { getConsoleLogger } from "../src/utils/logger-utils";
|
import { getConsoleLogger } from "../../../src/utils/logging/logger";
|
||||||
|
|
||||||
describe("PublisherFactory.create", () => {
|
describe("PublisherFactory.create", () => {
|
||||||
test("factory can create publisher for every PublisherTarget value", () => {
|
test("factory can create publisher for every PublisherTarget value", () => {
|
||||||
|
@ -10,7 +10,7 @@ describe("PublisherFactory.create", () => {
|
||||||
const logger = getConsoleLogger();
|
const logger = getConsoleLogger();
|
||||||
const publisher = factory.create(target, logger);
|
const publisher = factory.create(target, logger);
|
||||||
expect(publisher.target).toStrictEqual(target);
|
expect(publisher.target).toStrictEqual(target);
|
||||||
expect((<any>publisher).logger).toStrictEqual(logger);
|
expect((publisher as any).logger).toStrictEqual(logger);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ describe("PublisherFactory.create", () => {
|
||||||
for (const target of PublisherTarget.getValues()) {
|
for (const target of PublisherTarget.getValues()) {
|
||||||
const publisher = factory.create(target);
|
const publisher = factory.create(target);
|
||||||
expect(publisher.target).toStrictEqual(target);
|
expect(publisher.target).toStrictEqual(target);
|
||||||
expect((<any>publisher).logger).toBeTruthy();
|
expect((publisher as any).logger).toBeTruthy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, test, expect, beforeAll, afterAll } from "@jest/globals";
|
import { describe, test, expect, beforeAll, afterAll } from "@jest/globals";
|
||||||
import { setupInput, unsetInput } from "./utils/input-utils";
|
import { setupInput, unsetInput } from "../../../utils/input-utils";
|
||||||
import { getInputAsObject, mapStringInput, mapObjectInput, mapNumberInput, mapBooleanInput, mapEnumInput } from "../src/utils/input-utils";
|
import { getInputAsObject, mapStringInput, mapObjectInput, mapNumberInput, mapBooleanInput, mapEnumInput } from "../../../../src/utils/actions/input";
|
||||||
|
|
||||||
const defaultInput = {
|
const defaultInput = {
|
||||||
"boolean": true,
|
"boolean": true,
|
||||||
|
@ -101,10 +101,10 @@ describe("mapObjectInput", () => {
|
||||||
const input = getInputAsObject();
|
const input = getInputAsObject();
|
||||||
|
|
||||||
expect(input["boolean"]).not.toBeUndefined();
|
expect(input["boolean"]).not.toBeUndefined();
|
||||||
expect(mapObjectInput(input["boolean"], null)).toBeNull();
|
expect(mapObjectInput(input["boolean"], null!)).toBeNull();
|
||||||
|
|
||||||
expect(input["number"]).not.toBeUndefined();
|
expect(input["number"]).not.toBeUndefined();
|
||||||
expect(mapObjectInput(input["number"], null)).toBeNull()
|
expect(mapObjectInput(input["number"], null!)).toBeNull()
|
||||||
|
|
||||||
expect(input["array"]).not.toBeUndefined();
|
expect(input["array"]).not.toBeUndefined();
|
||||||
expect(mapObjectInput(input["array"])).toBeNull()
|
expect(mapObjectInput(input["array"])).toBeNull()
|
||||||
|
@ -115,7 +115,7 @@ describe("mapObjectInput", () => {
|
||||||
|
|
||||||
test("maps object values to object", () => {
|
test("maps object values to object", () => {
|
||||||
const input = getInputAsObject();
|
const input = getInputAsObject();
|
||||||
expect(mapObjectInput(input["modrinth"], null)).toStrictEqual({ id: "42", token: "1234", filesPrimary: "primaryPath", filesSecondary: "secondaryPath", files: { primary: "primaryPath", secondary: "secondaryPath" } });
|
expect(mapObjectInput(input["modrinth"], null!)).toStrictEqual({ id: "42", token: "1234", filesPrimary: "primaryPath", filesSecondary: "secondaryPath", files: { primary: "primaryPath", secondary: "secondaryPath" } });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import process from "process";
|
import process from "process";
|
||||||
import { describe, test, expect } from "@jest/globals";
|
import { describe, test, expect } from "@jest/globals";
|
||||||
import { unifyGameVersion, unifyJava, convertToCurseForgeVersions } from "../src/utils/curseforge-utils";
|
import { unifyGameVersion, unifyJava, convertToCurseForgeVersions } from "../../../../src/utils/curseforge";
|
||||||
|
|
||||||
describe("unifyGameVersion", () => {
|
describe("unifyGameVersion", () => {
|
||||||
test("versions in the unified format are not changed", async () => {
|
test("versions in the unified format are not changed", async () => {
|
||||||
|
@ -94,7 +94,7 @@ describe("convertToCurseForgeVersions", () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const curseForgeVersions = await convertToCurseForgeVersions(Object.keys(versions.gameVersions), Object.keys(versions.loaders), Object.keys(versions.java), process.env.CURSEFORGE_TOKEN);
|
const curseForgeVersions = await convertToCurseForgeVersions(Object.keys(versions.gameVersions), Object.keys(versions.loaders), Object.keys(versions.java), process.env.CURSEFORGE_TOKEN as string);
|
||||||
const expectedIds = new Set([...Object.values<number>(versions.gameVersions), ...Object.values(versions.loaders), ...Object.values(versions.java)]);
|
const expectedIds = new Set([...Object.values<number>(versions.gameVersions), ...Object.values(versions.loaders), ...Object.values(versions.java)]);
|
||||||
|
|
||||||
expect(curseForgeVersions).toHaveLength(expectedIds.size);
|
expect(curseForgeVersions).toHaveLength(expectedIds.size);
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, test, expect } from "@jest/globals";
|
import { describe, test, expect } from "@jest/globals";
|
||||||
import sleep from "../src/utils/sleep";
|
import sleep from "../../../../src/utils/sleep";
|
||||||
import Stopwatch from "../src/utils/stopwatch";
|
import Stopwatch from "../../../../src/utils/diagnostics/stopwatch";
|
||||||
|
|
||||||
describe("Stopwatch", () => {
|
describe("Stopwatch", () => {
|
||||||
test("base functionality of Stopwatch works", async () => {
|
test("base functionality of Stopwatch works", async () => {
|
30
test/unit-tests/utils/io/file.test.ts
Normal file
30
test/unit-tests/utils/io/file.test.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { describe, test, expect } from "@jest/globals";
|
||||||
|
import File from "../../../../src/utils/io/file";
|
||||||
|
|
||||||
|
describe("File", () => {
|
||||||
|
describe("getFiles", () => {
|
||||||
|
test("all files matching the given pattern are returned", async () => {
|
||||||
|
expect(await File.getFiles("(README|LICENSE|FOO).md")).toHaveLength(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("files matching the primary pattern are returned first", async () => {
|
||||||
|
const files = await File.getFiles({ primary: "README.md", secondary: "(README|LICENSE|FOO).md" });
|
||||||
|
expect(files).toHaveLength(2);
|
||||||
|
expect(files[0]).toHaveProperty("name", "README.md");
|
||||||
|
|
||||||
|
const inversedFiles = await File.getFiles({ primary: "LICENSE.md", secondary: "(README|LICENSE|FOO).md" });
|
||||||
|
expect(inversedFiles).toHaveLength(2);
|
||||||
|
expect(inversedFiles[0]).toHaveProperty("name", "LICENSE.md");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getRequiredFiles", () => {
|
||||||
|
test("all files matching the given pattern are returned", async () => {
|
||||||
|
expect(await File.getRequiredFiles("(README|LICENSE|FOO).md")).toHaveLength(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("an error is thrown if no files are found", async () => {
|
||||||
|
await expect(File.getRequiredFiles("FOO.md")).rejects.toBeInstanceOf(Error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,7 +1,7 @@
|
||||||
import { describe, test, expect } from "@jest/globals";
|
import { describe, test, expect } from "@jest/globals";
|
||||||
import sleep from "../src/utils/sleep";
|
import sleep from "../../../../src/utils/sleep";
|
||||||
import Logger from "../src/utils/logger";
|
import Logger from "../../../../src/utils/logging/logger";
|
||||||
import LogginStopwatch from "../src/utils/logging-stopwatch";
|
import LogginStopwatch from "../../../../src/utils/logging/logging-stopwatch";
|
||||||
|
|
||||||
function createLogger(info?: (msg: string) => void): Logger {
|
function createLogger(info?: (msg: string) => void): Logger {
|
||||||
const notImplementedLogger = () => {
|
const notImplementedLogger = () => {
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, test, expect } from "@jest/globals";
|
import { describe, test, expect } from "@jest/globals";
|
||||||
import { getVersionById, findVersionByName, isSnapshot, parseVersionName, parseVersionNameFromFileVersion, getVersions, getLatestRelease, getCompatibleBuilds } from "../src/utils/minecraft-utils";
|
import { getVersionById, findVersionByName, isSnapshot, parseVersionName, parseVersionNameFromFileVersion, getVersions, getLatestRelease, getCompatibleBuilds } from "../../../../src/utils/minecraft";
|
||||||
import Version from "../src/utils/version";
|
import Version from "../../../../src/utils/versioning/version";
|
||||||
|
|
||||||
describe("getVersionById", () => {
|
describe("getVersionById", () => {
|
||||||
test("returned versions have the same id as the given one", async () => {
|
test("returned versions have the same id as the given one", async () => {
|
|
@ -1,5 +1,5 @@
|
||||||
import { describe, test, expect } from "@jest/globals";
|
import { describe, test, expect } from "@jest/globals";
|
||||||
import MinecraftVersionResolver from "../src/utils/minecraft-version-resolver";
|
import MinecraftVersionResolver from "../../../../src/utils/minecraft/minecraft-version-resolver";
|
||||||
|
|
||||||
describe("MinecraftVersionResolver.byName", () => {
|
describe("MinecraftVersionResolver.byName", () => {
|
||||||
test("every predefined MinecraftVersionResolver can be resolved", () => {
|
test("every predefined MinecraftVersionResolver can be resolved", () => {
|
|
@ -1,5 +1,5 @@
|
||||||
import { describe, test, expect } from "@jest/globals";
|
import { describe, test, expect } from "@jest/globals";
|
||||||
import { getProject, getVersions } from "../src/utils/modrinth-utils";
|
import { getProject, getVersions } from "../../../../src/utils/modrinth";
|
||||||
|
|
||||||
const timeout = 15000;
|
const timeout = 15000;
|
||||||
|
|
||||||
|
@ -48,12 +48,12 @@ describe("getVersions", () => {
|
||||||
}, timeout);
|
}, timeout);
|
||||||
|
|
||||||
test("returns only featured versions with featured === true", async () => {
|
test("returns only featured versions with featured === true", async () => {
|
||||||
const versions = await getVersions("terra", null, null, true);
|
const versions = await getVersions("terra", null!, null!, true);
|
||||||
expect(versions.every(x => x.featured)).toBe(true);
|
expect(versions.every(x => x.featured)).toBe(true);
|
||||||
}, timeout);
|
}, timeout);
|
||||||
|
|
||||||
test("returns only unfeatured versions with featured === false", async () => {
|
test("returns only unfeatured versions with featured === false", async () => {
|
||||||
const versions = await getVersions("terra", null, null, false);
|
const versions = await getVersions("terra", null!, null!, false);
|
||||||
expect(versions.every(x => !x.featured)).toBe(true);
|
expect(versions.every(x => !x.featured)).toBe(true);
|
||||||
}, timeout);
|
}, timeout);
|
||||||
|
|
||||||
|
@ -66,10 +66,10 @@ describe("getVersions", () => {
|
||||||
}, timeout);
|
}, timeout);
|
||||||
|
|
||||||
test("returns only versions that support given mc versions", async () => {
|
test("returns only versions that support given mc versions", async () => {
|
||||||
const versions_1_18_2 = await getVersions("terra", null, ["1.18.2"]);
|
const versions_1_18_2 = await getVersions("terra", null!, ["1.18.2"]);
|
||||||
expect(versions_1_18_2.every(x => x.game_versions.includes("1.18.2"))).toBe(true);
|
expect(versions_1_18_2.every(x => x.game_versions.includes("1.18.2"))).toBe(true);
|
||||||
|
|
||||||
const versions_1_16_5 = await getVersions("terra", null, ["1.16.5"]);
|
const versions_1_16_5 = await getVersions("terra", null!, ["1.16.5"]);
|
||||||
expect(versions_1_16_5.every(x => x.game_versions.includes("1.16.5"))).toBe(true);
|
expect(versions_1_16_5.every(x => x.game_versions.includes("1.16.5"))).toBe(true);
|
||||||
}, timeout);
|
}, timeout);
|
||||||
});
|
});
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, test, expect } from "@jest/globals";
|
import { describe, test, expect } from "@jest/globals";
|
||||||
import { retry } from "../src/utils/function-utils";
|
import retry from "../../../src/utils/retry";
|
||||||
import SoftError from "../src/utils/soft-error";
|
import SoftError from "../../../src/utils/soft-error";
|
||||||
|
|
||||||
function createThrowingFunc(attempts: number): () => true {
|
function createThrowingFunc(attempts: number): () => true {
|
||||||
let counter = 0;
|
let counter = 0;
|
14
test/unit-tests/utils/sleep.test.ts
Normal file
14
test/unit-tests/utils/sleep.test.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { describe, test, expect } from "@jest/globals";
|
||||||
|
import sleep from "../../../src/utils/sleep";
|
||||||
|
|
||||||
|
describe("sleep", () => {
|
||||||
|
test("execution continues after the specified delay", async () => {
|
||||||
|
const start = new Date();
|
||||||
|
await sleep(100);
|
||||||
|
const end = new Date();
|
||||||
|
const duration = end.getTime() - start.getTime();
|
||||||
|
expect(duration).toBeGreaterThan(50);
|
||||||
|
expect(duration).toBeLessThan(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
18
test/unit-tests/utils/versioning/version-type.test.ts
Normal file
18
test/unit-tests/utils/versioning/version-type.test.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { describe, test, expect } from "@jest/globals";
|
||||||
|
import VersionType from "../../../../src/utils/versioning/version-type";
|
||||||
|
|
||||||
|
describe("VersionType", () => {
|
||||||
|
describe("fromName", () => {
|
||||||
|
test("version type is correctly extracted from the filename", () => {
|
||||||
|
expect(VersionType.fromName("sodium-fabric-mc1.17.1-0.3.2+build.7")).toStrictEqual("release");
|
||||||
|
expect(VersionType.fromName("fabric-api-0.40.1+1.18_experimental")).toStrictEqual("release");
|
||||||
|
expect(VersionType.fromName("TechReborn-5.0.8-beta+build.111")).toStrictEqual("beta");
|
||||||
|
expect(VersionType.fromName("TechReborn-1.17-5.0.1-beta+build.29")).toStrictEqual("beta");
|
||||||
|
expect(VersionType.fromName("Terra-forge-5.3.3-BETA+ec3b0e5d")).toStrictEqual("beta");
|
||||||
|
expect(VersionType.fromName("Terra-forge-5.3.3-alpha+ec3b0e5d")).toStrictEqual("alpha");
|
||||||
|
expect(VersionType.fromName("modmenu-2.0.12")).toStrictEqual("release");
|
||||||
|
expect(VersionType.fromName("enhancedblockentities-0.5+1.17")).toStrictEqual("release");
|
||||||
|
expect(VersionType.fromName("sync-mc1.17.x-1.2")).toStrictEqual("release");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
17
test/unit-tests/utils/versioning/version.test.ts
Normal file
17
test/unit-tests/utils/versioning/version.test.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { describe, test, expect } from "@jest/globals";
|
||||||
|
import Version from "../../../../src/utils/versioning/version";
|
||||||
|
|
||||||
|
describe("Version", () => {
|
||||||
|
describe("fromName", () => {
|
||||||
|
test("file version is correctly extracted from the filename", () => {
|
||||||
|
expect(Version.fromName("sodium-fabric-mc1.17.1-0.3.2+build.7")).toStrictEqual("mc1.17.1-0.3.2+build.7");
|
||||||
|
expect(Version.fromName("fabric-api-0.40.1+1.18_experimental")).toStrictEqual("0.40.1+1.18_experimental");
|
||||||
|
expect(Version.fromName("TechReborn-5.0.8-beta+build.111")).toStrictEqual("5.0.8-beta+build.111");
|
||||||
|
expect(Version.fromName("TechReborn-1.17-5.0.1-beta+build.29")).toStrictEqual("1.17-5.0.1-beta+build.29");
|
||||||
|
expect(Version.fromName("Terra-forge-5.3.3-BETA+ec3b0e5d")).toStrictEqual("5.3.3-BETA+ec3b0e5d");
|
||||||
|
expect(Version.fromName("modmenu-2.0.12")).toStrictEqual("2.0.12");
|
||||||
|
expect(Version.fromName("enhancedblockentities-0.5+1.17")).toStrictEqual("0.5+1.17");
|
||||||
|
expect(Version.fromName("sync-mc1.17.x-1.2")).toStrictEqual("mc1.17.x-1.2");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,29 +0,0 @@
|
||||||
import { describe, test, expect } from "@jest/globals";
|
|
||||||
import { parseVersionFromName, parseVersionTypeFromName } from "../src/utils/version-utils";
|
|
||||||
|
|
||||||
describe("parseVersionFromName", () => {
|
|
||||||
test("file version is correctly extracted from the filename", () => {
|
|
||||||
expect(parseVersionFromName("sodium-fabric-mc1.17.1-0.3.2+build.7")).toStrictEqual("mc1.17.1-0.3.2+build.7");
|
|
||||||
expect(parseVersionFromName("fabric-api-0.40.1+1.18_experimental")).toStrictEqual("0.40.1+1.18_experimental");
|
|
||||||
expect(parseVersionFromName("TechReborn-5.0.8-beta+build.111")).toStrictEqual("5.0.8-beta+build.111");
|
|
||||||
expect(parseVersionFromName("TechReborn-1.17-5.0.1-beta+build.29")).toStrictEqual("1.17-5.0.1-beta+build.29");
|
|
||||||
expect(parseVersionFromName("Terra-forge-5.3.3-BETA+ec3b0e5d")).toStrictEqual("5.3.3-BETA+ec3b0e5d");
|
|
||||||
expect(parseVersionFromName("modmenu-2.0.12")).toStrictEqual("2.0.12");
|
|
||||||
expect(parseVersionFromName("enhancedblockentities-0.5+1.17")).toStrictEqual("0.5+1.17");
|
|
||||||
expect(parseVersionFromName("sync-mc1.17.x-1.2")).toStrictEqual("mc1.17.x-1.2");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("parseVersionTypeFromName", () => {
|
|
||||||
test("version type is correctly extracted from the filename", () => {
|
|
||||||
expect(parseVersionTypeFromName("sodium-fabric-mc1.17.1-0.3.2+build.7")).toStrictEqual("release");
|
|
||||||
expect(parseVersionTypeFromName("fabric-api-0.40.1+1.18_experimental")).toStrictEqual("release");
|
|
||||||
expect(parseVersionTypeFromName("TechReborn-5.0.8-beta+build.111")).toStrictEqual("beta");
|
|
||||||
expect(parseVersionTypeFromName("TechReborn-1.17-5.0.1-beta+build.29")).toStrictEqual("beta");
|
|
||||||
expect(parseVersionTypeFromName("Terra-forge-5.3.3-BETA+ec3b0e5d")).toStrictEqual("beta");
|
|
||||||
expect(parseVersionTypeFromName("Terra-forge-5.3.3-alpha+ec3b0e5d")).toStrictEqual("alpha");
|
|
||||||
expect(parseVersionTypeFromName("modmenu-2.0.12")).toStrictEqual("release");
|
|
||||||
expect(parseVersionTypeFromName("enhancedblockentities-0.5+1.17")).toStrictEqual("release");
|
|
||||||
expect(parseVersionTypeFromName("sync-mc1.17.x-1.2")).toStrictEqual("release");
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in a new issue