Compare commits
2 commits
ac1afd3997
...
c76087fe17
Author | SHA1 | Date | |
---|---|---|---|
c76087fe17 | |||
c1d849b0e0 |
4 changed files with 95 additions and 41 deletions
14
bun.lock
14
bun.lock
|
@ -4,6 +4,8 @@
|
|||
"": {
|
||||
"name": "packwizjs",
|
||||
"dependencies": {
|
||||
"@types/semver": "^7.5.8",
|
||||
"semver": "^7.7.1",
|
||||
"toml": "^3.0.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -53,6 +55,8 @@
|
|||
|
||||
"@types/node": ["@types/node@22.13.1", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew=="],
|
||||
|
||||
"@types/semver": ["@types/semver@7.5.8", "", {}, "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ=="],
|
||||
|
||||
"@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
|
||||
|
||||
"acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
|
||||
|
@ -365,7 +369,7 @@
|
|||
|
||||
"safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
|
||||
|
||||
"semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
"semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="],
|
||||
|
||||
|
@ -443,18 +447,14 @@
|
|||
|
||||
"@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="],
|
||||
|
||||
"builtins/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"eslint-compat-utils/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||
|
||||
"eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||
|
||||
"eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||
|
||||
"eslint-plugin-n/globals": ["globals@13.24.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ=="],
|
||||
"eslint-plugin-import/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
|
||||
"eslint-plugin-n/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
"eslint-plugin-n/globals": ["globals@13.24.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ=="],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
"typescript": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/semver": "^7.5.8",
|
||||
"semver": "^7.7.1",
|
||||
"toml": "^3.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,6 @@ export function isValidHashFormat(hashFormat: string): HashFormat {
|
|||
if (hashFormat in HashFormat) {
|
||||
return HashFormat[hashFormat as keyof typeof HashFormat];
|
||||
} else {
|
||||
throw new Error("Invalid index file hash format!");
|
||||
throw new Error(`Invalid index file hash format: ${hashFormat}`);
|
||||
}
|
||||
}
|
||||
|
|
118
src/parser.ts
118
src/parser.ts
|
@ -8,6 +8,7 @@ import {
|
|||
} from "./provider";
|
||||
import { HashFormat, isValidHashFormat } from "./enums/hash-format";
|
||||
import { isValidSide, type Side } from "./enums/side";
|
||||
import * as semver from "semver";
|
||||
|
||||
export interface Metafile {
|
||||
name: string;
|
||||
|
@ -112,46 +113,97 @@ export class IndexFileEntry {
|
|||
*/
|
||||
export interface PackwizIndex {
|
||||
location: Resource;
|
||||
hash: string;
|
||||
hashFormat: HashFormat;
|
||||
files: IndexFileEntry[];
|
||||
}
|
||||
|
||||
// TODO: parse pack.toml too instead of just the index file
|
||||
// This is because pack.toml contains important information like modloader versions
|
||||
export interface PackwizVersions {
|
||||
minecraft: string;
|
||||
fabric?: string;
|
||||
forge?: string;
|
||||
neoforge?: string;
|
||||
quilt?: string;
|
||||
liteloader?: string;
|
||||
}
|
||||
|
||||
export class Packwiz {
|
||||
constructor(
|
||||
readonly location: Resource,
|
||||
readonly index: PackwizIndex,
|
||||
readonly name: string,
|
||||
readonly packFormat: string = "packwiz:1.0.0",
|
||||
readonly authors: Array<string>,
|
||||
readonly description: string,
|
||||
readonly version: string,
|
||||
readonly versions: PackwizVersions,
|
||||
) {
|
||||
const packwizJsMaxSupportedVersion = "1.1.0";
|
||||
const packFormatSemver = semver.clean(packFormat.split(":")[1]);
|
||||
if (!packFormat.startsWith("packwiz:")) {
|
||||
throw new Error("Invalid packwiz pack format!");
|
||||
} else if (!packFormatSemver) {
|
||||
throw new Error("Unable to parse pack format!");
|
||||
} else if (semver.gt(packFormatSemver, packwizJsMaxSupportedVersion)) {
|
||||
throw new Error(
|
||||
`Pack format of ${packFormat} is higher than what PackwizJS supports! Please report this upstream at https://www.coastalcommits.com/GalacticFactory/PackwizJS/issues`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a Packwiz index file and returns its contents.
|
||||
* Parses a packwiz.toml file and returns its contents.
|
||||
*
|
||||
* @param indexFilePath - The path of the TOML file.
|
||||
* @returns The parsed index as a structured object.
|
||||
* @returns The parsed file as a structured class.
|
||||
*/
|
||||
export async function parsePackwizIndex(
|
||||
indexFilePath: string,
|
||||
): Promise<PackwizIndex> {
|
||||
const indexFile = new Resource(indexFilePath);
|
||||
const parsed = toml.parse(await indexFile.fetchContents());
|
||||
const hashFormat = isValidHashFormat(parsed["hash-format"]);
|
||||
return {
|
||||
location: indexFile,
|
||||
hashFormat: hashFormat,
|
||||
files: parsed.files.map(
|
||||
(file: {
|
||||
file: string;
|
||||
hash: string;
|
||||
hashFormat: HashFormat;
|
||||
alias?: string;
|
||||
metafile?: boolean;
|
||||
preserve?: boolean;
|
||||
}) => {
|
||||
return new IndexFileEntry(
|
||||
indexFile.parent.join(file.file),
|
||||
file.hash,
|
||||
file.hashFormat || hashFormat,
|
||||
file.alias,
|
||||
file.metafile ?? false,
|
||||
file.preserve ?? false,
|
||||
);
|
||||
},
|
||||
),
|
||||
};
|
||||
export async function parsePackwiz(filePath: string): Promise<Packwiz> {
|
||||
const packwizFile = new Resource(filePath);
|
||||
const parsedPackwizFile = toml.parse(await packwizFile.fetchContents());
|
||||
|
||||
const indexFile = packwizFile.parent.join(parsedPackwizFile.index.file);
|
||||
const parsedIndexFile = toml.parse(await indexFile.fetchContents());
|
||||
const indexHashFormat = isValidHashFormat(parsedIndexFile["hash-format"]);
|
||||
|
||||
return new Packwiz(
|
||||
packwizFile,
|
||||
{
|
||||
location: indexFile,
|
||||
hash: parsedPackwizFile.index.hash,
|
||||
hashFormat: indexHashFormat,
|
||||
files: parsedIndexFile.files.map(
|
||||
(file: {
|
||||
file: string;
|
||||
hash: string;
|
||||
hashFormat: HashFormat;
|
||||
alias?: string;
|
||||
metafile?: boolean;
|
||||
preserve?: boolean;
|
||||
}) => {
|
||||
return new IndexFileEntry(
|
||||
packwizFile.parent.join(file.file),
|
||||
file.hash,
|
||||
file.hashFormat ?? indexHashFormat,
|
||||
file.alias,
|
||||
file.metafile ?? false,
|
||||
file.preserve ?? false,
|
||||
);
|
||||
},
|
||||
),
|
||||
},
|
||||
parsedPackwizFile.name,
|
||||
parsedPackwizFile["pack-format"],
|
||||
parsedPackwizFile.author?.split(",").map((s: string) => s.trim()),
|
||||
parsedPackwizFile.description,
|
||||
parsedPackwizFile.version,
|
||||
{
|
||||
minecraft: parsedPackwizFile.versions.minecraft,
|
||||
fabric: parsedPackwizFile.versions.fabric,
|
||||
forge: parsedPackwizFile.versions.forge,
|
||||
neoforge: parsedPackwizFile.versions.neoforge,
|
||||
quilt: parsedPackwizFile.versions.quilt,
|
||||
liteloader: parsedPackwizFile.versions.liteloader,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue