mirror of
https://github.com/Kir-Antipov/mc-publish.git
synced 2024-11-25 09:51:01 -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