mirror of
https://github.com/Kir-Antipov/mc-publish.git
synced 2024-11-25 01:41:05 -05:00
Deleted obsolete files
This commit is contained in:
parent
c205e5d9c2
commit
e7368e858a
18 changed files with 0 additions and 794 deletions
|
@ -1,33 +0,0 @@
|
|||
enum DependencyKind {
|
||||
Depends = 1,
|
||||
Recommends,
|
||||
Includes,
|
||||
Suggests,
|
||||
Conflicts,
|
||||
Breaks,
|
||||
}
|
||||
|
||||
namespace DependencyKind {
|
||||
export function getValues(): DependencyKind[] {
|
||||
return <DependencyKind[]>Object.values(DependencyKind).filter(x => typeof x === "number");
|
||||
}
|
||||
|
||||
export function parse(kindName: string): DependencyKind | undefined {
|
||||
if (typeof DependencyKind[kindName] === "number") {
|
||||
return DependencyKind[kindName];
|
||||
}
|
||||
|
||||
for (const kind of Object.values(DependencyKind)) {
|
||||
if (typeof kind === "number" && kindName.localeCompare(DependencyKind[kind], undefined, { sensitivity: "accent" }) === 0) {
|
||||
return kind;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function toString(target: DependencyKind): string {
|
||||
return DependencyKind[target] ?? target.toString();
|
||||
}
|
||||
}
|
||||
|
||||
export default DependencyKind;
|
|
@ -1,25 +0,0 @@
|
|||
import PublisherTarget from "../publishing/publisher-target";
|
||||
import DependencyKind from "./dependency-kind";
|
||||
|
||||
interface Dependency {
|
||||
get id(): string;
|
||||
get version(): string;
|
||||
get kind(): DependencyKind;
|
||||
get ignore(): boolean;
|
||||
|
||||
getProjectSlug(project: PublisherTarget): string;
|
||||
}
|
||||
|
||||
namespace Dependency {
|
||||
export function create({ id, version = "*", kind = DependencyKind.Depends, ignore = false, aliases = null }: { id: string, version?: string, kind?: DependencyKind, ignore?: boolean, aliases?: Map<PublisherTarget, string> }): Dependency {
|
||||
return {
|
||||
id,
|
||||
version: version ?? "*",
|
||||
kind: kind ?? DependencyKind.Depends,
|
||||
ignore: ignore ?? false,
|
||||
getProjectSlug: target => aliases?.has(target) ? aliases.get(target) : id
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default Dependency;
|
|
@ -1,57 +0,0 @@
|
|||
import type DependencyKind from "../dependency-kind";
|
||||
|
||||
type Environment = "client" | "server" | "*";
|
||||
|
||||
type Person = string | { name: string; contact?: string; };
|
||||
|
||||
type Dependency = string | string[] | {
|
||||
version?: string | string[];
|
||||
versions?: string | string[];
|
||||
custom?: Record<string, any>;
|
||||
};
|
||||
|
||||
type DependencyContainer = {
|
||||
// Dependency resolution
|
||||
[Kind in keyof typeof DependencyKind as Lowercase<Kind>]?: Record<string, Dependency>;
|
||||
};
|
||||
|
||||
// https://fabricmc.net/wiki/documentation:fabric_mod_json
|
||||
type FabricModConfig = {
|
||||
// Mandatory fields
|
||||
schemaVersion: 1;
|
||||
id: string;
|
||||
version: string;
|
||||
|
||||
// Mod loading
|
||||
provides?: string;
|
||||
environment?: Environment;
|
||||
entrypoints?: Record<string, string[]>;
|
||||
jars?: { file: string }[];
|
||||
languageAdapters?: Record<string, string>;
|
||||
mixins?: (string | { config: string, environment: Environment })[];
|
||||
|
||||
// Metadata
|
||||
name?: string;
|
||||
description?: string;
|
||||
contact?: {
|
||||
email?: string;
|
||||
irc?: string;
|
||||
homepage?: string;
|
||||
issues?: string;
|
||||
sources?: string;
|
||||
[key: string]: string;
|
||||
};
|
||||
authors?: Person[];
|
||||
contributors?: Person[];
|
||||
license?: string | string[];
|
||||
icon?: string | Record<string, string>;
|
||||
|
||||
// Custom fields
|
||||
custom?: Record<string, any>;
|
||||
} & DependencyContainer;
|
||||
|
||||
namespace FabricModConfig {
|
||||
export const FILENAME = "fabric.mod.json";
|
||||
}
|
||||
|
||||
export default FabricModConfig;
|
|
@ -1,11 +0,0 @@
|
|||
import ZippedModTextMetadataReader from "../zipped-mod-text-metadata-reader";
|
||||
import FabricModConfig from "./fabric-mod-config";
|
||||
import FabricModMetadata from "./fabric-mod-metadata";
|
||||
|
||||
class FabricModMetadataReader extends ZippedModTextMetadataReader<FabricModConfig> {
|
||||
constructor() {
|
||||
super(FabricModConfig.FILENAME, x => new FabricModMetadata(x));
|
||||
}
|
||||
}
|
||||
|
||||
export default FabricModMetadataReader;
|
|
@ -1,158 +0,0 @@
|
|||
import action from "../../../package.json";
|
||||
import Dependency from "../dependency";
|
||||
import DependencyKind from "../dependency-kind";
|
||||
import PublisherTarget from "../../publishing/publisher-target";
|
||||
import FabricModConfig from "./fabric-mod-config";
|
||||
import ModMetadata from "../mod-metadata";
|
||||
|
||||
type Aliases = Map<PublisherTarget, string>;
|
||||
|
||||
type FabricDependency = FabricModConfig["depends"][string];
|
||||
|
||||
function getDependencies(config: FabricModConfig): Dependency[] {
|
||||
return DependencyKind.getValues().flatMap(x => getDependenciesByKind(config, x));
|
||||
}
|
||||
|
||||
function getDependenciesByKind(config: FabricModConfig, kind: DependencyKind): Dependency[] {
|
||||
const kindName = DependencyKind.toString(kind).toLowerCase() as Lowercase<keyof typeof DependencyKind>;
|
||||
const dependencies = new Array<Dependency>();
|
||||
for (const [id, value] of Object.entries(config[kindName] || {})) {
|
||||
const ignore = isDependencyIgnoredByDefault(id);
|
||||
const aliases = getDefaultDependencyAliases(id);
|
||||
const dependency = parseDependency(id, kind, value, ignore, aliases, config);
|
||||
|
||||
dependencies.push(dependency);
|
||||
}
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
function parseDependency(id: string, kind: DependencyKind, body: FabricDependency, ignore: boolean, aliases: Aliases, config: FabricModConfig): Dependency {
|
||||
if (typeof body === "string" || Array.isArray(body)) {
|
||||
return parseSimpleDependency(id, kind, body, ignore, aliases, config);
|
||||
}
|
||||
|
||||
let version = body.version || body.versions || "*";
|
||||
if (Array.isArray(version)) {
|
||||
version = version.join(" || ");
|
||||
}
|
||||
|
||||
kind = getDependencyKind(id, config) ?? kind;
|
||||
ignore = isDependencyIgnoredInConfig(id, config) ?? body.custom?.[action.name]?.ignore ?? ignore;
|
||||
aliases = new Map([ ...(aliases || []), ...(getDependencyAliases(id, config) || []) ]);
|
||||
for (const target of PublisherTarget.getValues()) {
|
||||
const targetName = PublisherTarget.toString(target).toLowerCase();
|
||||
const alias = body.custom?.[action.name]?.[targetName];
|
||||
if (alias) {
|
||||
aliases.set(target, String(alias));
|
||||
}
|
||||
}
|
||||
|
||||
return Dependency.create({ id, kind, version, ignore, aliases });
|
||||
}
|
||||
|
||||
function parseSimpleDependency(id: string, kind: DependencyKind, version: string | string[], ignore: boolean, aliases: Aliases, config: FabricModConfig): Dependency {
|
||||
if (Array.isArray(version)) {
|
||||
version = version.join(" || ");
|
||||
}
|
||||
|
||||
kind = getDependencyKind(id, config) ?? kind;
|
||||
ignore = isDependencyIgnoredInConfig(id, config) ?? ignore;
|
||||
aliases = new Map([ ...(aliases || []), ...(getDependencyAliases(id, config) || []) ]);
|
||||
return Dependency.create({ id, kind, version, ignore, aliases });
|
||||
}
|
||||
|
||||
const ignoredByDefault = [
|
||||
"minecraft",
|
||||
"java",
|
||||
"fabricloader",
|
||||
];
|
||||
function isDependencyIgnoredByDefault(id: string): boolean {
|
||||
return ignoredByDefault.includes(id);
|
||||
}
|
||||
|
||||
function isDependencyIgnoredInConfig(id: string, config: FabricModConfig): boolean | null {
|
||||
return config.custom?.[action.name]?.dependencies?.[id]?.ignore;
|
||||
}
|
||||
|
||||
const defaultAliases = new Map<string, string | Aliases>([
|
||||
["fabric", "fabric-api"],
|
||||
]);
|
||||
function getDefaultDependencyAliases(id: string): Aliases | null {
|
||||
if (!defaultAliases.has(id)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const aliases = defaultAliases.get(id);
|
||||
if (typeof aliases !== "string") {
|
||||
return new Map([...aliases]);
|
||||
}
|
||||
|
||||
return new Map(PublisherTarget.getValues().map(x => [x, aliases]));
|
||||
}
|
||||
|
||||
function getDependencyAliases(id: string, config: FabricModConfig): Aliases | null {
|
||||
const metadata = config.custom?.[action.name]?.dependencies?.[id];
|
||||
if (!metadata) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const aliases = new Map() as Aliases;
|
||||
for (const target of PublisherTarget.getValues()) {
|
||||
const targetName = PublisherTarget.toString(target).toLowerCase();
|
||||
const alias = metadata[targetName] ?? id;
|
||||
aliases.set(target, String(alias));
|
||||
}
|
||||
return aliases;
|
||||
}
|
||||
|
||||
function getDependencyKind(id: string, config: FabricModConfig): DependencyKind | null {
|
||||
const kind = config.custom?.[action.name]?.dependencies?.[id]?.kind;
|
||||
return kind ? DependencyKind.parse(kind) : null;
|
||||
}
|
||||
|
||||
function getLoaders(config: FabricModConfig): string[] {
|
||||
if (config.custom?.[action.name]?.quilt) {
|
||||
return ["fabric", "quilt"];
|
||||
}
|
||||
return ["fabric"];
|
||||
}
|
||||
|
||||
function getProjects(config: FabricModConfig): Map<PublisherTarget, string> {
|
||||
const projects = new Map();
|
||||
for (const target of PublisherTarget.getValues()) {
|
||||
const targetName = PublisherTarget.toString(target).toLowerCase();
|
||||
const projectId = config.custom?.[action.name]?.[targetName]
|
||||
?? config.custom?.modmanager?.[targetName]
|
||||
?? config.custom?.projects?.[targetName];
|
||||
|
||||
if (projectId) {
|
||||
projects.set(target, String(projectId));
|
||||
}
|
||||
}
|
||||
return projects;
|
||||
}
|
||||
|
||||
class FabricModMetadata implements ModMetadata {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly version: string;
|
||||
readonly loaders: string[];
|
||||
readonly dependencies: Dependency[];
|
||||
|
||||
private readonly _projects: Map<PublisherTarget, string>;
|
||||
|
||||
constructor(config: FabricModConfig) {
|
||||
this.id = String(config.id ?? "");
|
||||
this.name = String(config.name ?? this.id);
|
||||
this.version = String(config.version ?? "*");
|
||||
this.loaders = getLoaders(config);
|
||||
this.dependencies = getDependencies(config);
|
||||
this._projects = getProjects(config);
|
||||
}
|
||||
|
||||
getProjectId(project: PublisherTarget): string | undefined {
|
||||
return this._projects.get(project);
|
||||
}
|
||||
}
|
||||
|
||||
export default FabricModMetadata;
|
|
@ -1,44 +0,0 @@
|
|||
// https://forge.gemwire.uk/wiki/Mods.toml
|
||||
type ForgeModConfig = {
|
||||
// Non-Mod-Specific Properties
|
||||
modLoader: string;
|
||||
loaderVersion: string;
|
||||
license: string;
|
||||
showAsResourcePack?: boolean;
|
||||
properties?: Record<string, unknown>;
|
||||
issueTrackerURL?: string;
|
||||
|
||||
// Mod Properties
|
||||
mods: {
|
||||
modId: string;
|
||||
namespace?: string;
|
||||
version?: string;
|
||||
displayName?: string;
|
||||
description?: string;
|
||||
logoFile?: string;
|
||||
logoBlur?: boolean;
|
||||
updateJSONURL?: string;
|
||||
modproperties?: Record<string, unknown>;
|
||||
credits?: string;
|
||||
authors?: string;
|
||||
displayURL?: string;
|
||||
displayTest?: "MATCH_VERSION" | "IGNORE_SERVER_VERSION" | "IGNORE_ALL_VERSION" | "NONE";
|
||||
}[];
|
||||
|
||||
// Dependency Configurations
|
||||
dependencies?: Record<string, ({
|
||||
modId: string;
|
||||
mandatory: boolean;
|
||||
incompatible?: boolean;
|
||||
embedded?: boolean;
|
||||
versionRange?: string;
|
||||
ordering?: "BEFORE" | "AFTER" | "NONE";
|
||||
side?: "CLIENT" | "SERVER" | "BOTH";
|
||||
} & Record<string, any>)[]>;
|
||||
} & Record<string, any>;
|
||||
|
||||
namespace ForgeModConfig {
|
||||
export const FILENAME = "META-INF/mods.toml";
|
||||
}
|
||||
|
||||
export default ForgeModConfig;
|
|
@ -1,12 +0,0 @@
|
|||
import toml from "toml";
|
||||
import ZippedModTextMetadataReader from "../zipped-mod-text-metadata-reader";
|
||||
import ForgeModMetadata from "./forge-mod-metadata";
|
||||
import ForgeModConfig from "./forge-mod-config";
|
||||
|
||||
class ForgeModMetadataReader extends ZippedModTextMetadataReader<ForgeModConfig> {
|
||||
constructor() {
|
||||
super(ForgeModConfig.FILENAME, x => new ForgeModMetadata(x), toml.parse);
|
||||
}
|
||||
}
|
||||
|
||||
export default ForgeModMetadataReader;
|
|
@ -1,91 +0,0 @@
|
|||
import action from "../../../package.json";
|
||||
import Dependency from "../dependency";
|
||||
import DependencyKind from "../dependency-kind";
|
||||
import ForgeModConfig from "./forge-mod-config";
|
||||
import ModMetadata from "../mod-metadata";
|
||||
import PublisherTarget from "../../publishing/publisher-target";
|
||||
|
||||
type ForgeDependency = ForgeModConfig["dependencies"][string][number];
|
||||
|
||||
function getDependencies(config: ForgeModConfig): Dependency[] {
|
||||
return Object
|
||||
.values(config.dependencies || {})
|
||||
.filter(x => Array.isArray(x))
|
||||
.flatMap(x => x)
|
||||
.map(parseDependency)
|
||||
.filter((x, i, self) => self.findIndex(y => x.id === y.id && x.kind === y.kind) === i);
|
||||
}
|
||||
|
||||
function parseDependency(body: ForgeDependency): Dependency {
|
||||
const id = body.modId;
|
||||
const kind = body.incompatible && DependencyKind.Breaks || body.embedded && DependencyKind.Includes || body.mandatory && DependencyKind.Depends || DependencyKind.Recommends;
|
||||
const version = body.versionRange;
|
||||
const ignore = body[action.name]?.ignore ?? body.custom?.[action.name]?.ignore ?? body.ignore ?? isDependencyIgnoredByDefault(id);
|
||||
const aliases = new Map<PublisherTarget, string>();
|
||||
for (const target of PublisherTarget.getValues()) {
|
||||
const targetName = PublisherTarget.toString(target).toLowerCase();
|
||||
const alias = body[action.name]?.[targetName] ?? body.custom?.[action.name]?.[targetName];
|
||||
if (alias) {
|
||||
aliases.set(target, String(alias));
|
||||
}
|
||||
}
|
||||
|
||||
return Dependency.create({ id, kind, version, ignore, aliases });
|
||||
}
|
||||
|
||||
const ignoredByDefault = [
|
||||
"minecraft",
|
||||
"java",
|
||||
"forge",
|
||||
];
|
||||
function isDependencyIgnoredByDefault(id: string): boolean {
|
||||
return ignoredByDefault.includes(id);
|
||||
}
|
||||
|
||||
function getProjects(config: ForgeModConfig): Map<PublisherTarget, string> {
|
||||
const projects = new Map();
|
||||
for (const target of PublisherTarget.getValues()) {
|
||||
const targetName = PublisherTarget.toString(target).toLowerCase();
|
||||
const projectId = config[action.name]?.[targetName]
|
||||
?? config.custom?.[action.name]?.[targetName]
|
||||
?? config.projects?.[targetName]
|
||||
?? config.custom?.projects?.[targetName];
|
||||
|
||||
if (projectId) {
|
||||
projects.set(target, String(projectId));
|
||||
}
|
||||
}
|
||||
return projects;
|
||||
}
|
||||
|
||||
class ForgeModMetadata implements ModMetadata {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly version: string;
|
||||
readonly loaders: string[];
|
||||
readonly dependencies: Dependency[];
|
||||
|
||||
private readonly _projects: Map<PublisherTarget, string>;
|
||||
|
||||
constructor(config: ForgeModConfig) {
|
||||
const mods = Array.isArray(config.mods) && config.mods || [];
|
||||
const mod = mods[0];
|
||||
if (!mod) {
|
||||
throw new Error("At least one mod should be specified");
|
||||
}
|
||||
|
||||
this.id = mod.modId;
|
||||
this.name = mod.displayName || this.id;
|
||||
this.version = mod.version || "*";
|
||||
this.loaders = ["forge"];
|
||||
this.dependencies = getDependencies(config);
|
||||
|
||||
this._projects = getProjects(config);
|
||||
}
|
||||
|
||||
getProjectId(project: PublisherTarget): string | undefined {
|
||||
return this._projects.get(project);
|
||||
}
|
||||
}
|
||||
|
||||
export default ForgeModMetadata;
|
|
@ -1,17 +0,0 @@
|
|||
enum ModLoaderType {
|
||||
Fabric = 1,
|
||||
Forge,
|
||||
Quilt,
|
||||
}
|
||||
|
||||
namespace ModLoaderType {
|
||||
export function getValues(): ModLoaderType[] {
|
||||
return <ModLoaderType[]>Object.values(ModLoaderType).filter(x => typeof x === "number");
|
||||
}
|
||||
|
||||
export function toString(target: ModLoaderType): string {
|
||||
return ModLoaderType[target] ?? target.toString();
|
||||
}
|
||||
}
|
||||
|
||||
export default ModLoaderType;
|
|
@ -1,23 +0,0 @@
|
|||
import FabricModMetadataReader from "./fabric/fabric-mod-metadata-reader";
|
||||
import ForgeModMetadataReader from "./forge/forge-mod-metadata-reader";
|
||||
import QuiltModMetadataReader from "./quilt/quilt-mod-metadata-reader";
|
||||
import ModLoaderType from "./mod-loader-type";
|
||||
import ModMetadataReader from "./mod-metadata-reader";
|
||||
|
||||
export default class ModMetadataReaderFactory {
|
||||
public create(loaderType: ModLoaderType): ModMetadataReader {
|
||||
switch (loaderType) {
|
||||
case ModLoaderType.Fabric:
|
||||
return new FabricModMetadataReader();
|
||||
|
||||
case ModLoaderType.Forge:
|
||||
return new ForgeModMetadataReader();
|
||||
|
||||
case ModLoaderType.Quilt:
|
||||
return new QuiltModMetadataReader();
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown mod loader "${ModLoaderType.toString(loaderType)}"`);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
import ModLoaderType from "./mod-loader-type";
|
||||
import ModMetadata from "./mod-metadata";
|
||||
import ModMetadataReaderFactory from "./mod-metadata-reader-factory";
|
||||
|
||||
interface ModMetadataReader {
|
||||
readMetadata(modPath: string): Promise<ModMetadata | null>;
|
||||
}
|
||||
|
||||
namespace ModMetadataReader {
|
||||
export async function readMetadata(modPath: string): Promise<ModMetadata | null> {
|
||||
const factory = new ModMetadataReaderFactory();
|
||||
for (const loaderType of ModLoaderType.getValues()) {
|
||||
const metadata = await factory.create(loaderType).readMetadata(modPath).catch(_ => null);
|
||||
if (metadata) {
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default ModMetadataReader;
|
|
@ -1,12 +0,0 @@
|
|||
import PublisherTarget from "../publishing/publisher-target";
|
||||
import Dependency from "./dependency";
|
||||
|
||||
export default interface ModMetadata {
|
||||
get id(): string;
|
||||
get name(): string;
|
||||
get version(): string;
|
||||
get loaders(): string[];
|
||||
get dependencies(): Dependency[];
|
||||
|
||||
getProjectId(project: PublisherTarget): string | undefined;
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
type Plugin = string | { adapter?: string, value: string };
|
||||
|
||||
type Entrypoint = Plugin;
|
||||
|
||||
type License = string | {
|
||||
name: string;
|
||||
id: string;
|
||||
url: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
type Dependency = string | {
|
||||
id: string;
|
||||
version?: string;
|
||||
versions?: string | string[];
|
||||
reason?: string;
|
||||
optional?: boolean;
|
||||
unless?: Dependency | Dependency[];
|
||||
};
|
||||
|
||||
// https://github.com/QuiltMC/rfcs/blob/main/specification/0002-quilt.mod.json.md
|
||||
type QuiltModConfig = {
|
||||
schema_version: 1;
|
||||
|
||||
quilt_loader: {
|
||||
group: string;
|
||||
id: string;
|
||||
provides?: Dependency[];
|
||||
version: string;
|
||||
entrypoints?: Record<string, Entrypoint | Entrypoint[]>;
|
||||
plugins?: Plugin[];
|
||||
jars?: string[];
|
||||
language_adapters?: Record<string, string>;
|
||||
depends?: Dependency[];
|
||||
breaks?: Dependency[];
|
||||
load_type?: "always" | "if_possible" | "if_required";
|
||||
repositories?: string[];
|
||||
intermediate_mappings?: string;
|
||||
metadata?: Record<string, unknown>;
|
||||
name?: string;
|
||||
description?: string;
|
||||
contributors?: Record<string, string>;
|
||||
contact?: {
|
||||
email?: string;
|
||||
homepage?: string;
|
||||
issues?: string;
|
||||
sources?: string;
|
||||
[key: string]: string;
|
||||
};
|
||||
license?: License | License[];
|
||||
icon?: string | Record<string, string>;
|
||||
|
||||
};
|
||||
|
||||
mixin?: string | string[];
|
||||
access_widener?: string | string[];
|
||||
minecraft?: {
|
||||
environment?: "client" | "dedicated_server" | "*";
|
||||
};
|
||||
} & Record<string, any>;
|
||||
|
||||
namespace QuiltModConfig {
|
||||
export const FILENAME = "quilt.mod.json";
|
||||
}
|
||||
|
||||
export default QuiltModConfig;
|
|
@ -1,11 +0,0 @@
|
|||
import ZippedModTextMetadataReader from "../zipped-mod-text-metadata-reader";
|
||||
import QuiltModConfig from "./quilt-mod-config";
|
||||
import QuiltModMetadata from "./quilt-mod-metadata";
|
||||
|
||||
class QuiltModMetadataReader extends ZippedModTextMetadataReader<QuiltModConfig> {
|
||||
constructor() {
|
||||
super(QuiltModConfig.FILENAME, x => new QuiltModMetadata(x));
|
||||
}
|
||||
}
|
||||
|
||||
export default QuiltModMetadataReader;
|
|
@ -1,147 +0,0 @@
|
|||
import action from "../../../package.json";
|
||||
import Dependency from "../dependency";
|
||||
import DependencyKind from "../dependency-kind";
|
||||
import PublisherTarget from "../../publishing/publisher-target";
|
||||
import ModMetadata from "../mod-metadata";
|
||||
import QuiltModConfig from "./quilt-mod-config";
|
||||
|
||||
type Aliases = Map<PublisherTarget, string>;
|
||||
|
||||
type QuiltDependency = QuiltModConfig["quilt_loader"]["breaks"][number];
|
||||
|
||||
type ExtendedQuiltDependency = QuiltDependency & {
|
||||
embedded?: boolean;
|
||||
incompatible?: boolean;
|
||||
};
|
||||
|
||||
function getDependencies(config: QuiltModConfig): Dependency[] {
|
||||
const root = config.quilt_loader;
|
||||
return getExtendedDependencyEntries(root.depends)
|
||||
.concat(getExtendedDependencyEntries(root.provides, x => x.embedded = true))
|
||||
.concat(getExtendedDependencyEntries(root.breaks, x => x.incompatible = true))
|
||||
.map(parseDependency)
|
||||
.filter((x, i, self) => self.findIndex(y => x.id === y.id && x.kind === y.kind) === i);
|
||||
}
|
||||
|
||||
function parseId(id?: string): string | null {
|
||||
if (!id) {
|
||||
return id ?? null;
|
||||
}
|
||||
|
||||
const separatorIndex = id.indexOf(":");
|
||||
if (separatorIndex === -1) {
|
||||
return id;
|
||||
}
|
||||
return id.substring(separatorIndex + 1);
|
||||
}
|
||||
|
||||
function getExtendedDependencyEntries(container: QuiltDependency[], transformer?: (x: ExtendedQuiltDependency) => void): ExtendedQuiltDependency[] {
|
||||
if (!Array.isArray(container)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (transformer) {
|
||||
container = container.map(x => typeof x === "string" ? ({ id: x }) : ({ ...x }));
|
||||
container.forEach(transformer);
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
function parseDependency(body: ExtendedQuiltDependency): Dependency {
|
||||
const id = parseId(typeof body === "string" ? body : String(body.id ?? ""));
|
||||
const ignoredByDefault = isDependencyIgnoredByDefault(id);
|
||||
const defaultAliases = getDefaultDependencyAliases(id);
|
||||
|
||||
if (typeof body === "string") {
|
||||
return Dependency.create({ id, ignore: ignoredByDefault, aliases: defaultAliases });
|
||||
}
|
||||
|
||||
const version = body.version ?? (Array.isArray(body.versions) ? body.versions.join(" || ") : body.versions || "*");
|
||||
const kind = (
|
||||
body.incompatible && body.unless && DependencyKind.Conflicts ||
|
||||
body.incompatible && DependencyKind.Breaks ||
|
||||
body.embedded && DependencyKind.Includes ||
|
||||
body.optional && DependencyKind.Recommends ||
|
||||
DependencyKind.Depends
|
||||
);
|
||||
const ignore = body[action.name]?.ignore ?? ignoredByDefault;
|
||||
|
||||
const aliases = new Map([...(defaultAliases || [])]);
|
||||
for (const target of PublisherTarget.getValues()) {
|
||||
const targetName = PublisherTarget.toString(target).toLowerCase();
|
||||
const alias = body[action.name]?.[targetName];
|
||||
if (alias) {
|
||||
aliases.set(target, String(alias));
|
||||
}
|
||||
}
|
||||
|
||||
return Dependency.create({ id, version, kind, ignore, aliases });
|
||||
}
|
||||
|
||||
const ignoredByDefault = [
|
||||
"minecraft",
|
||||
"java",
|
||||
"quilt_loader",
|
||||
];
|
||||
function isDependencyIgnoredByDefault(id: string): boolean {
|
||||
return ignoredByDefault.includes(id);
|
||||
}
|
||||
|
||||
const defaultAliases = new Map<string, string | Aliases>([
|
||||
["fabric", "fabric-api"],
|
||||
["quilted_fabric_api", "qsl"],
|
||||
]);
|
||||
function getDefaultDependencyAliases(id: string): Aliases | null {
|
||||
if (id.startsWith("quilted_")) {
|
||||
id = "quilted_fabric_api";
|
||||
}
|
||||
|
||||
if (!defaultAliases.has(id)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const aliases = defaultAliases.get(id);
|
||||
if (typeof aliases !== "string") {
|
||||
return new Map([...aliases]);
|
||||
}
|
||||
|
||||
return new Map(PublisherTarget.getValues().map(x => [x, aliases]));
|
||||
}
|
||||
|
||||
function getProjects(config: QuiltModConfig): Map<PublisherTarget, string> {
|
||||
const projects = new Map();
|
||||
for (const target of PublisherTarget.getValues()) {
|
||||
const targetName = PublisherTarget.toString(target).toLowerCase();
|
||||
const projectId = config[action.name]?.[targetName] ?? config.projects?.[targetName];
|
||||
|
||||
if (projectId) {
|
||||
projects.set(target, String(projectId));
|
||||
}
|
||||
}
|
||||
return projects;
|
||||
}
|
||||
|
||||
class QuiltModMetadata implements ModMetadata {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly version: string;
|
||||
readonly loaders: string[];
|
||||
readonly dependencies: Dependency[];
|
||||
|
||||
private readonly _projects: Map<PublisherTarget, string>;
|
||||
|
||||
constructor(config: QuiltModConfig) {
|
||||
this.id = String(config.quilt_loader.id ?? "");
|
||||
this.name = String(config.quilt_loader.name ?? this.id);
|
||||
this.version = String(config.quilt_loader.version ?? "*");
|
||||
this.loaders = ["quilt"];
|
||||
this.dependencies = getDependencies(config);
|
||||
this._projects = getProjects(config);
|
||||
}
|
||||
|
||||
getProjectId(project: PublisherTarget): string | undefined {
|
||||
return this._projects.get(project);
|
||||
}
|
||||
}
|
||||
|
||||
export default QuiltModMetadata;
|
|
@ -1,30 +0,0 @@
|
|||
import ModMetadata from "./mod-metadata";
|
||||
import ModMetadataReader from "./mod-metadata-reader";
|
||||
import { StreamZipAsync, async as ZipArchive } from "node-stream-zip";
|
||||
|
||||
abstract class ZippedModMetadataReader<TConfig = Record<string, unknown>> implements ModMetadataReader {
|
||||
private _configEntryName: string;
|
||||
|
||||
protected constructor(configEntryName: string) {
|
||||
this._configEntryName = configEntryName;
|
||||
}
|
||||
|
||||
async readMetadata(modPath: string): Promise<ModMetadata | null> {
|
||||
let zip = null as StreamZipAsync;
|
||||
try {
|
||||
zip = new ZipArchive({ file: modPath });
|
||||
const buffer = await zip.entryData(this._configEntryName).catch(_ => null as Buffer);
|
||||
return buffer && this.createMetadataFromConfig(this.loadConfig(buffer));
|
||||
} catch {
|
||||
return null;
|
||||
} finally {
|
||||
await zip?.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract loadConfig(buffer: Buffer): TConfig;
|
||||
|
||||
protected abstract createMetadataFromConfig(config: TConfig): ModMetadata;
|
||||
}
|
||||
|
||||
export default ZippedModMetadataReader;
|
|
@ -1,27 +0,0 @@
|
|||
import ModMetadata from "./mod-metadata";
|
||||
import ZippedModMetadataReader from "./zipped-mod-metadata-reader";
|
||||
|
||||
type ModMetadataFactory<T> = (config: T) => ModMetadata;
|
||||
|
||||
type Parser<T> = (input: string) => T;
|
||||
|
||||
abstract class ZippedModTextMetadataReader<TConfig = Record<string, unknown>> extends ZippedModMetadataReader<TConfig> {
|
||||
private readonly _factory: ModMetadataFactory<TConfig>;
|
||||
private readonly _parser: Parser<TConfig>;
|
||||
|
||||
protected constructor(configEntryName: string, factory: ModMetadataFactory<TConfig>, parser?: Parser<any>) {
|
||||
super(configEntryName);
|
||||
this._factory = factory;
|
||||
this._parser = parser ?? JSON.parse;
|
||||
}
|
||||
|
||||
protected loadConfig(buffer: Buffer): TConfig {
|
||||
return this._parser(buffer.toString("utf8"));
|
||||
}
|
||||
|
||||
protected createMetadataFromConfig(config: TConfig): ModMetadata {
|
||||
return this._factory(config);
|
||||
}
|
||||
}
|
||||
|
||||
export default ZippedModTextMetadataReader;
|
|
@ -1,8 +0,0 @@
|
|||
export default class SoftError extends Error {
|
||||
readonly soft: boolean;
|
||||
|
||||
constructor(soft: boolean, message?: string) {
|
||||
super(message);
|
||||
this.soft = soft;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue