diff --git a/package.json b/package.json index 437bf0f..135eddd 100644 --- a/package.json +++ b/package.json @@ -40,9 +40,9 @@ "s-ago": "^2.2.0", "semver": "^7.3.7", "serve-handler": "^6.1.3", + "toml": "^3.0.0", "wrap-ansi": "^8.0.1", "yazl": "^2.5.1", - "yesno": "^0.4.0", "zod": "^3.18.0" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 96e313e..3e745c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,12 +32,12 @@ specifiers: s-ago: ^2.2.0 semver: ^7.3.7 serve-handler: ^6.1.3 + toml: ^3.0.0 tsx: ^3.8.2 type-fest: ^2.18.0 typescript: ^4.7.4 wrap-ansi: ^8.0.1 yazl: ^2.5.1 - yesno: ^0.4.0 zod: ^3.18.0 dependencies: @@ -63,9 +63,9 @@ dependencies: s-ago: 2.2.0 semver: 7.3.7 serve-handler: 6.1.3 + toml: 3.0.0 wrap-ansi: 8.0.1 yazl: 2.5.1 - yesno: 0.4.0 zod: 3.18.0 devDependencies: @@ -1634,6 +1634,10 @@ packages: is-number: 7.0.0 dev: true + /toml/3.0.0: + resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} + dev: false + /trim-newlines/4.0.2: resolution: {integrity: sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==} engines: {node: '>=12'} @@ -1728,10 +1732,6 @@ packages: buffer-crc32: 0.2.13 dev: false - /yesno/0.4.0: - resolution: {integrity: sha512-tdBxmHvbXPBKYIg81bMCB7bVeDmHkRzk5rVJyYYXurwKkHq/MCd8rz4HSJUP7hW0H2NlXiq8IFiWvYKEHhlotA==} - dev: false - /yocto-queue/0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} diff --git a/src/commands/packwiz.ts b/src/commands/packwiz.ts index 9af2c31..cf571e6 100644 --- a/src/commands/packwiz.ts +++ b/src/commands/packwiz.ts @@ -7,15 +7,43 @@ import { getLANAddress, getSha512HexHash, httpServeDirectory, optionParsePositiv import { output } from "../output.js" import { Visitor, walk } from "@root/walk" import { Path } from "../path.js" +import toml from "toml" +import { addModrinthMod } from "../modrinth/utils.js" +import { modrinthApi } from "../modrinth/api.js" const packwizCommand = new Command("packwiz") .alias("pw") -packwizCommand.command("import") - .description("Import a packwiz pack.") - .action(async () => { - output.failAndExit("Not implemented.") - // TODO: Import packwiz pack +packwizCommand.command("import ") + .description("Import the mods of a packwiz pack. Overrides are ignored.") + .addHelpText("after", kleur.red("This command should only be used in newly created packs. Otherwise, the behaviour is undefined.")) + .action(async path => { + const packDirectoryPath = Path.create(path) + const modsDirectoryPath = packDirectoryPath.resolve("mods") + if (!await fs.pathExists(modsDirectoryPath.toString())) output.failAndExit(`The pack does not contain a ${kleur.yellow("mods")} directory.`) + + const modFileNames = (await fs.readdir(modsDirectoryPath.toString(), { withFileTypes: true })) + .filter(dirent => dirent.isFile() && dirent.name.endsWith(".toml")) + .map(dirent => dirent.name) + + let index = 0 + for (const modFileName of modFileNames) { + const content = toml.parse(await fs.readFile(modsDirectoryPath.resolve(modFileName).toString(), "utf-8")) + const modrinthVersionId = content.update?.modrinth?.version + + if (modrinthVersionId === undefined) output.warn(`${kleur.yellow(modFileName)} has no Modrinth version ID associated. It will not be imported.`) + else { + const modrinthVersion = (await output.withLoading(modrinthApi.getVersion(modrinthVersionId), "Fetching version information"))! + const modrinthMod = (await output.withLoading(modrinthApi.getMod(modrinthVersion.projectId), "Fetching mod information"))! + + await addModrinthMod(modrinthMod, modrinthVersion, content.side?.replace("both", "client-server")) + } + + output.println(`${kleur.yellow(modFileName)} ${kleur.green("was imported.")} ${kleur.gray(`(${index}/${modFileNames.length})`)}`) + index++ + } + + output.println(`${kleur.yellow(modFileNames.length)} ${kleur.green("mods were imported.")}`) }) packwizCommand.command("serve") diff --git a/src/main.ts b/src/main.ts index c763cfd..3b31164 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,7 +9,6 @@ import { default as wrapAnsi } from "wrap-ansi" import { CURRENT_HORIZR_FILE_FORMAT_VERSION, HorizrFile, removeModFile } from "./files.js" import { output } from "./output.js" import figures from "figures" -import yesno from "yesno" import { releaseChannelOrder } from "./shared.js" import fs from "fs-extra" import { Path } from "./path.js" @@ -168,11 +167,11 @@ program.command("update [code]") output.println("") - const confirmed = options.yes || await yesno({ - question: "Apply the update? [Y/n]", - defaultValue: true, - invalid: () => {} - }) + const confirmed = options.yes || (await enquirer.prompt({ + type: "confirm", + name: "confirmed", + message: "Apply the update?" + }) as any).confirmed if (confirmed) { await output.withLoading(update.apply(), "Updating") diff --git a/src/modrinth/utils.ts b/src/modrinth/utils.ts index 71cf859..67e201b 100644 --- a/src/modrinth/utils.ts +++ b/src/modrinth/utils.ts @@ -7,7 +7,7 @@ import { nanoid } from "nanoid/non-secure" import { output } from "../output.js" import kleur from "kleur" import { ModrinthMod, ModrinthVersion, ModrinthVersionFile } from "./api.js" -import { releaseChannelOrder } from "../shared.js" +import { releaseChannelOrder, Side } from "../shared.js" export const dependencyToRelatedVersionType: Record["type"]> = { required: "hard_dependency", @@ -46,7 +46,7 @@ export function getModFileDataForModrinthVersion(modrinthMod: ModrinthMod, modri } } -export async function addModrinthMod(modrinthMod: ModrinthMod, modrinthVersion: ModrinthVersion) { +export async function addModrinthMod(modrinthMod: ModrinthMod, modrinthVersion: ModrinthVersion, side?: Side) { const pack = await usePack() let id = modrinthMod.slug @@ -60,14 +60,18 @@ export async function addModrinthMod(modrinthMod: ModrinthMod, modrinthVersion: ) } - const isClientSupported = modrinthMod.clientSide !== "unsupported" - const isServerSupported = modrinthMod.serverSide !== "unsupported" + if (side === undefined) { + const isClientSupported = modrinthMod.clientSide !== "unsupported" + const isServerSupported = modrinthMod.serverSide !== "unsupported" + + side = isClientSupported && isServerSupported ? "client-server" : isClientSupported ? "client" : "server" + } await pack.addMod(id, { name: modrinthMod.title, enabled: true, ignoreUpdates: false, - side: isClientSupported && isServerSupported ? "client-server" : isClientSupported ? "client" : "server", + side, file: getModFileDataForModrinthVersion(modrinthMod, modrinthVersion), source: { type: "modrinth",