Implement horizr init
This commit is contained in:
parent
1fbb3e2142
commit
2a9a16cb7f
14 changed files with 167 additions and 68 deletions
15
README.md
15
README.md
|
@ -1,15 +1,16 @@
|
|||
# Horizr CLI
|
||||
> A CLI tool for creating Minecraft modpacks, primarily using the Fabric and Quilt loaders.
|
||||
> A CLI tool for creating Minecraft modpacks using the Fabric loader.
|
||||
|
||||
🎉 Features:
|
||||
- Search for mods on [Modrinth](https://modrinth.com/)
|
||||
- Add mods from Modrinth
|
||||
- View available (compatible) versions of mods from Modrinth
|
||||
- View dependencies of specific mod versions
|
||||
- Access [Modrinth](https://modrinth.com/)
|
||||
- Search
|
||||
- Add
|
||||
- View available versions
|
||||
- View dependencies
|
||||
- Check for updates and view changelogs before applying them
|
||||
- Export the pack to the [Modrinth format (`.mrpack`)](https://docs.modrinth.com/docs/modpacks/format_definition/)
|
||||
- Export the pack to the [`packwiz`](https://packwiz.infra.link/) format
|
||||
- HTTP-serve the `packwiz` export for usage with [`packwiz-installer`](https://packwiz.infra.link/tutorials/installing/packwiz-installer/)
|
||||
- Export the pack to the [Modrinth format (`.mrpack`)](https://docs.modrinth.com/docs/modpacks/format_definition/)
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -24,6 +25,8 @@ $ npm i -g @horizr/cli
|
|||
|
||||
Run any command with the `-h` flag to see the available options.
|
||||
|
||||
A new pack can be initiated using `horizr init <path>`.
|
||||
|
||||
## Examples
|
||||
|
||||
- Activate the latest (compatible) version of [Charm](https://modrinth.com/mod/charm)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@horizr/cli",
|
||||
"version": "1.0.0",
|
||||
"main": "./dist/main.ts",
|
||||
"main": "./dist/main.js",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"author": "Moritz Ruth <dev@moritzruth.de>",
|
||||
|
@ -22,6 +22,7 @@
|
|||
"address": "^1.2.0",
|
||||
"commander": "^9.4.0",
|
||||
"dedent": "^0.7.0",
|
||||
"enquirer": "^2.3.6",
|
||||
"env-paths": "^3.0.0",
|
||||
"figures": "^5.0.0",
|
||||
"find-up": "^6.3.0",
|
||||
|
|
14
pnpm-lock.yaml
generated
14
pnpm-lock.yaml
generated
|
@ -14,6 +14,7 @@ specifiers:
|
|||
commander: ^9.4.0
|
||||
dedent: ^0.7.0
|
||||
del-cli: ^5.0.0
|
||||
enquirer: ^2.3.6
|
||||
env-paths: ^3.0.0
|
||||
figures: ^5.0.0
|
||||
find-up: ^6.3.0
|
||||
|
@ -44,6 +45,7 @@ dependencies:
|
|||
address: 1.2.0
|
||||
commander: 9.4.0
|
||||
dedent: 0.7.0
|
||||
enquirer: 2.3.6
|
||||
env-paths: 3.0.0
|
||||
figures: 5.0.0
|
||||
find-up: 6.3.0
|
||||
|
@ -263,6 +265,11 @@ packages:
|
|||
indent-string: 5.0.0
|
||||
dev: true
|
||||
|
||||
/ansi-colors/4.1.3:
|
||||
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/ansi-regex/6.0.1:
|
||||
resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
|
||||
engines: {node: '>=12'}
|
||||
|
@ -549,6 +556,13 @@ packages:
|
|||
once: 1.4.0
|
||||
dev: false
|
||||
|
||||
/enquirer/2.3.6:
|
||||
resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==}
|
||||
engines: {node: '>=8.6'}
|
||||
dependencies:
|
||||
ansi-colors: 4.1.3
|
||||
dev: false
|
||||
|
||||
/env-paths/3.0.0:
|
||||
resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
|
|
@ -20,11 +20,6 @@ import { addModrinthMod, findModForModrinthMod, getModFileDataForModrinthVersion
|
|||
|
||||
const modrinthCommand = new Command("modrinth")
|
||||
.alias("mr")
|
||||
.option("--clear-cache", "Clear the cache before doing the operation.")
|
||||
.on("option:clear-cache", () => {
|
||||
modrinthApi.clearCache()
|
||||
output.println(kleur.green("Cache was cleared.\n"))
|
||||
})
|
||||
|
||||
modrinthCommand.command("search <query...>")
|
||||
.description("Search for mods.")
|
||||
|
@ -33,7 +28,7 @@ modrinthCommand.command("search <query...>")
|
|||
.action(async (query, options) => {
|
||||
const pack = await usePack()
|
||||
const loader = output.startLoading(`Searching for ${kleur.yellow(query)}`)
|
||||
const { results } = await modrinthApi.searchMods(pack.horizrFile.loader, pack.horizrFile.versions.minecraft, query, options)
|
||||
const { results } = await modrinthApi.searchMods(pack.horizrFile.versions.minecraft, query, options)
|
||||
loader.stop()
|
||||
|
||||
output.println(
|
||||
|
@ -87,18 +82,14 @@ modrinthModCommand.command("versions <id>")
|
|||
const loader = output.startLoading("Fetching mod information")
|
||||
const modrinthMod = await modrinthApi.getMod(id)
|
||||
if (modrinthMod === null) return loader.failAndExit("not found")
|
||||
else loader.stop()
|
||||
|
||||
const existingMod = await findModForModrinthMod(modrinthMod)
|
||||
|
||||
loader.setText("Fetching versions")
|
||||
const modrinthVersions = await modrinthApi.listVersions(id, pack.horizrFile.loader, pack.horizrFile.versions.minecraft)
|
||||
loader.stop()
|
||||
const modrinthVersions = await output.withLoading(modrinthApi.listVersions(id, pack.horizrFile.versions.minecraft), "Fetching versions")
|
||||
|
||||
if (modrinthVersions.length === 0) {
|
||||
const message = dedent`
|
||||
There are no versions compatible with the pack (Loader: ${kleur.yellow(pack.horizrFile.loader)}, \
|
||||
Minecraft ${kleur.yellow(pack.horizrFile.versions.minecraft)}).
|
||||
`
|
||||
const message =
|
||||
`There are no versions compatible with the pack (Fabric ${kleur.yellow(pack.horizrFile.versions.fabric)}, Minecraft ${kleur.yellow(pack.horizrFile.versions.minecraft)}).`
|
||||
|
||||
output.println(kleur.red(message))
|
||||
} else {
|
||||
|
@ -138,11 +129,9 @@ modrinthModCommand.command("activate <id>")
|
|||
const loader = output.startLoading("Fetching mod information")
|
||||
const modrinthMod = await modrinthApi.getMod(id)
|
||||
if (modrinthMod === null) return loader.failAndExit("not found")
|
||||
else loader.stop()
|
||||
|
||||
loader.setText("Fetching versions")
|
||||
const modrinthVersions = await modrinthApi.listVersions(id, pack.horizrFile.loader, pack.horizrFile.versions.minecraft)
|
||||
loader.stop()
|
||||
|
||||
const modrinthVersions = await output.withLoading(modrinthApi.listVersions(id, pack.horizrFile.versions.minecraft), "Fetching versions")
|
||||
if (modrinthVersions.length === 0) return output.failAndExit("There is no compatible version of this mod.")
|
||||
|
||||
const sortedModrinthVersions = sortModrinthVersionsByPreference(modrinthVersions)
|
||||
|
@ -238,7 +227,7 @@ modrinthVersionCommand.command("info <id>")
|
|||
|
||||
Version name: ${kleur.yellow(modrinthVersion.name)} ${kleur.gray(ago(modrinthVersion.publicationDate))}
|
||||
Minecraft versions: ${modrinthVersion.supportedMinecraftVersions.map(version => version === pack.horizrFile.versions.minecraft ? kleur.green(version) : kleur.red(version)).join(", ")}
|
||||
Loaders: ${modrinthVersion.supportedLoaders.map(loader => loader === pack.horizrFile.loader ? kleur.green(loader) : kleur.red(loader)).join(", ")}
|
||||
Loaders: ${modrinthVersion.supportedLoaders.map(loader => loader === "fabric" ? kleur.green(loader) : kleur.red(loader)).join(", ")}
|
||||
|
||||
Related mods: ${relationsColorKey}
|
||||
${relationsList}
|
||||
|
@ -298,7 +287,7 @@ modrinthCommand.command("export")
|
|||
summary: pack.horizrFile.meta.description,
|
||||
dependencies: {
|
||||
minecraft: pack.horizrFile.versions.minecraft,
|
||||
[`${pack.horizrFile.loader}-loader`]: pack.horizrFile.versions.loader
|
||||
"fabric-loader": pack.horizrFile.versions.fabric
|
||||
},
|
||||
files: pack.mods.map(mod => ({
|
||||
path: `mods/${mod.modFile.file.name}`,
|
||||
|
|
|
@ -50,9 +50,6 @@ packwizCommand.command("export")
|
|||
async function runExport(forServer: boolean) {
|
||||
const pack = await usePack()
|
||||
|
||||
if (pack.horizrFile.loader !== "fabric")
|
||||
output.println(kleur.yellow(`packwiz does not yet support the ${kleur.reset(pack.horizrFile.loader)} loader. No loader will be specified.`))
|
||||
|
||||
const loader = output.startLoading("Generating")
|
||||
|
||||
const outputDirectoryPath = pack.paths.generated.resolve("packwiz")
|
||||
|
@ -172,8 +169,8 @@ async function writeIndexAndPackManifest(indexedFiles: IndexedFile[], outputDire
|
|||
pack-format = "packwiz:1.0.0"
|
||||
|
||||
[versions]
|
||||
minecraft = "${pack.horizrFile.versions.minecraft}"\
|
||||
${pack.horizrFile.loader === "fabric" ? "\n" + `fabric = ${JSON.stringify(pack.horizrFile.versions.loader)}` : ""}
|
||||
minecraft = ${JSON.stringify(pack.horizrFile.versions.minecraft)}
|
||||
fabric = ${JSON.stringify(pack.horizrFile.versions.fabric)}
|
||||
|
||||
[index]
|
||||
file = "index.toml"
|
||||
|
|
11
src/fabricApi.ts
Normal file
11
src/fabricApi.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { got } from "./utils.js"
|
||||
|
||||
export async function fetchFabricMinecraftVersions(): Promise<string[]> {
|
||||
const versions = await got("https://meta.fabricmc.net/v1/versions/game").json<any[]>()
|
||||
return versions.map(version => version.version as string)
|
||||
}
|
||||
|
||||
export async function fetchFabricVersions(minecraftVersion: string): Promise<string[]> {
|
||||
const versions = await got(`https://meta.fabricmc.net/v1/versions/loader/${minecraftVersion}`).json<any[]>()
|
||||
return versions.map(version => version.loader.version)
|
||||
}
|
|
@ -59,19 +59,19 @@ const horizrFileSchema = z.object({
|
|||
description: z.string().optional(),
|
||||
license: z.string()
|
||||
}),
|
||||
loader: z.enum(["fabric", "quilt"]),
|
||||
versions: z.object({
|
||||
minecraft: z.string(),
|
||||
loader: z.string()
|
||||
fabric: z.string()
|
||||
})
|
||||
})
|
||||
|
||||
export type HorizrFile = z.output<typeof horizrFileSchema>
|
||||
export const CURRENT_HORIZR_FILE_FORMAT_VERSION = 1
|
||||
|
||||
export async function readHorizrFile(packPath: Path) {
|
||||
const data = await readJsonFileInPack(packPath, Path.create("horizr.json"), horizrFileSchema)
|
||||
if (data === null) return output.failAndExit(`${kleur.yellow("horizr.json")} does not exist.`)
|
||||
if (data.formatVersion !== 1) return output.failAndExit(`${kleur.yellow("horizr.json")} has unsupported format version: ${kleur.yellow(data.formatVersion)}`)
|
||||
if (data.formatVersion !== CURRENT_HORIZR_FILE_FORMAT_VERSION) return output.failAndExit(`${kleur.yellow("horizr.json")} has unsupported format version: ${kleur.yellow(data.formatVersion)}`)
|
||||
|
||||
return data
|
||||
}
|
||||
|
|
85
src/main.ts
85
src/main.ts
|
@ -6,19 +6,101 @@ import { modrinthCommand } from "./commands/modrinth.js"
|
|||
import { packwizCommand } from "./commands/packwiz.js"
|
||||
import dedent from "dedent"
|
||||
import { default as wrapAnsi } from "wrap-ansi"
|
||||
import { removeModFile } from "./files.js"
|
||||
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"
|
||||
import enquirer from "enquirer"
|
||||
import { clearCache } from "./utils.js"
|
||||
import { fetchFabricMinecraftVersions, fetchFabricVersions } from "./fabricApi.js"
|
||||
|
||||
const program = new Command("horizr")
|
||||
.version(
|
||||
(await fs.readJson(Path.create(import.meta.url.slice(5)).getParent().resolve("../package.json").toString())).version,
|
||||
"-v, --version"
|
||||
)
|
||||
.option("--clear-cache", "Clear the HTTP cache before doing the operation.")
|
||||
.on("option:clear-cache", () => {
|
||||
clearCache()
|
||||
output.println(kleur.green("Cache was cleared.\n"))
|
||||
})
|
||||
|
||||
program.command("init <path>")
|
||||
.description("Initialize a new pack in the directory.")
|
||||
.action(async path => {
|
||||
const directoryPath = Path.create(path)
|
||||
const horizrFilePath = directoryPath.resolve("horizr.json")
|
||||
|
||||
if (await fs.pathExists(horizrFilePath.toString())) output.failAndExit(`${kleur.yellow("horizr.json")} already exists in the directory.`)
|
||||
|
||||
await fs.mkdirp(directoryPath.toString())
|
||||
const minecraftVersions = await output.withLoading(fetchFabricMinecraftVersions(), "Fetching Minecraft versions")
|
||||
|
||||
const answers: any = await enquirer.prompt([
|
||||
{
|
||||
name: "name",
|
||||
type: "input",
|
||||
message: "Name",
|
||||
validate: answer => answer.length === 0 ? "An answer is required." : true
|
||||
},
|
||||
{
|
||||
name: "authors",
|
||||
type: "input",
|
||||
message: "Authors (comma-separated)",
|
||||
validate: answer => answer.length === 0 ? "An answer is required." : true
|
||||
},
|
||||
{
|
||||
name: "description",
|
||||
type: "text",
|
||||
message: "Description"
|
||||
},
|
||||
{
|
||||
name: "license",
|
||||
type: "text",
|
||||
message: "License (SPDX-ID)",
|
||||
validate: answer => answer.length === 0 ? "An answer is required." : true
|
||||
},
|
||||
{
|
||||
name: "minecraftVersion",
|
||||
type: "autocomplete",
|
||||
message: "Minecraft version",
|
||||
choices: minecraftVersions.map(version => ({
|
||||
name: version,
|
||||
value: version
|
||||
})),
|
||||
// @ts-expect-error
|
||||
limit: 10,
|
||||
validate: answer => minecraftVersions.includes(answer) ? true : "Please select a version from the list."
|
||||
}
|
||||
])
|
||||
|
||||
const fabricVersion = (await output.withLoading(fetchFabricVersions(answers.minecraftVersion), "Fetching latest Fabric version"))[0]
|
||||
|
||||
const file: HorizrFile = {
|
||||
formatVersion: CURRENT_HORIZR_FILE_FORMAT_VERSION,
|
||||
meta: {
|
||||
name: answers.name,
|
||||
version: "1.0.0",
|
||||
description: answers.description === "" ? undefined : answers.description,
|
||||
authors: (answers.authors as string).split(", ").map(a => a.trim()),
|
||||
license: answers.license
|
||||
},
|
||||
versions: {
|
||||
minecraft: answers.minecraftVersion,
|
||||
fabric: fabricVersion
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeJson(horizrFilePath.toString(), file, { spaces: 2 })
|
||||
await fs.writeFile(directoryPath.resolve(".gitignore").toString(), "/generated/")
|
||||
|
||||
const relativePath = Path.create(process.cwd()).relative(directoryPath).toString()
|
||||
if (relativePath === "") output.println(kleur.green(`Successfully initialized pack.`))
|
||||
else output.println(kleur.green(`Successfully initialized pack in ${kleur.yellow(relativePath)}.`))
|
||||
})
|
||||
|
||||
program.command("info", { isDefault: true })
|
||||
.description("Print information about the pack.")
|
||||
|
@ -35,7 +117,6 @@ program.command("info", { isDefault: true })
|
|||
License: ${kleur.yellow(pack.horizrFile.meta.license.toUpperCase())}
|
||||
Mods: ${kleur.yellow(pack.mods.length.toString())}${disabledModsCount === 0 ? "" : ` (${disabledModsCount} disabled)`}
|
||||
|
||||
Loader: ${kleur.yellow(`${pack.horizrFile.loader} v${pack.horizrFile.versions.loader}`)}
|
||||
Minecraft version: ${kleur.yellow(pack.horizrFile.versions.minecraft)}
|
||||
`)
|
||||
})
|
||||
|
|
|
@ -1,19 +1,9 @@
|
|||
import got, { HTTPError, Response } from "got"
|
||||
import { HTTPError, Response } from "got"
|
||||
import kleur from "kleur"
|
||||
import { KeyvFile } from "keyv-file"
|
||||
import { delay } from "../utils.js"
|
||||
import { delay, got } from "../utils.js"
|
||||
import { output } from "../output.js"
|
||||
import { paths } from "../path.js"
|
||||
import { dependencyToRelatedVersionType } from "./utils.js"
|
||||
import { ModLoader, ReleaseChannel } from "../shared.js"
|
||||
|
||||
const keyvCache = new KeyvFile({
|
||||
filename: paths.cache.resolve("http.json").toString(),
|
||||
writeDelay: 50,
|
||||
expiredCheckDelay: 24 * 3600 * 1000,
|
||||
encode: JSON.stringify,
|
||||
decode: JSON.parse
|
||||
})
|
||||
import { ReleaseChannel } from "../shared.js"
|
||||
|
||||
async function getModrinthApiOptional(url: string): Promise<any | null> {
|
||||
let response: Response
|
||||
|
@ -21,11 +11,6 @@ async function getModrinthApiOptional(url: string): Promise<any | null> {
|
|||
while (true) {
|
||||
response = await got(url, {
|
||||
prefixUrl: "https://api.modrinth.com",
|
||||
headers: {
|
||||
"User-Agent": "moritzruth/horizr/1.0.0 (not yet public)"
|
||||
},
|
||||
cache: keyvCache,
|
||||
responseType: "json",
|
||||
throwHttpErrors: false,
|
||||
retry: {
|
||||
limit: 3,
|
||||
|
@ -159,14 +144,12 @@ export interface ModrinthVersionFile {
|
|||
}
|
||||
|
||||
export const modrinthApi = {
|
||||
clearCache: () => keyvCache.clear(),
|
||||
async searchMods(
|
||||
loader: ModLoader,
|
||||
minecraftVersion: string,
|
||||
query: string,
|
||||
pagination: PaginationOptions
|
||||
): Promise<{ total: number; results: ModrinthMod[] }> {
|
||||
const facets = `[["categories:${loader}"],["versions:${minecraftVersion}"],["project_type:mod"]]`
|
||||
const facets = `[["categories:fabric"],["versions:${minecraftVersion}"],["project_type:mod"]]`
|
||||
|
||||
const response = await getModrinthApi(`v2/search?query=${encodeURIComponent(query)}&limit=${pagination.limit}&offset=${pagination.skip}&facets=${facets}`)
|
||||
|
||||
|
@ -205,8 +188,8 @@ export const modrinthApi = {
|
|||
updateDate: new Date(response.updated)
|
||||
}
|
||||
},
|
||||
async listVersions(idOrSlug: string, loader: ModLoader, minecraftVersion: string): Promise<ModrinthVersion[]> {
|
||||
const response = await getModrinthApi(`v2/project/${idOrSlug}/version?loaders=["${loader}"]&game_versions=["${minecraftVersion}"]`)
|
||||
async listVersions(idOrSlug: string, minecraftVersion: string): Promise<ModrinthVersion[]> {
|
||||
const response = await getModrinthApi(`v2/project/${idOrSlug}/version?loaders=["fabric"]&game_versions=["${minecraftVersion}"]`)
|
||||
|
||||
return response.map(transformApiModVersion)
|
||||
},
|
||||
|
|
|
@ -29,7 +29,7 @@ export async function findModForModrinthMod(modrinthMod: ModrinthMod): Promise<(
|
|||
}
|
||||
|
||||
export const isModrinthVersionCompatible = (modrinthVersion: ModrinthVersion, pack: Pack) =>
|
||||
modrinthVersion.supportedMinecraftVersions.includes(pack.horizrFile.versions.minecraft) && modrinthVersion.supportedLoaders.includes(pack.horizrFile.loader)
|
||||
modrinthVersion.supportedMinecraftVersions.includes(pack.horizrFile.versions.minecraft) && modrinthVersion.supportedLoaders.includes("fabric")
|
||||
|
||||
export function getModFileDataForModrinthVersion(modrinthMod: ModrinthMod, modrinthModVersion: ModrinthVersion): ModFileData {
|
||||
const modrinthVersionFile = findCorrectModVersionFile(modrinthModVersion.files)
|
||||
|
|
|
@ -75,10 +75,12 @@ export async function usePack(): Promise<Pack> {
|
|||
if (mod.modFile.source.type === "modrinth") {
|
||||
const activeVersionString = mod.modFile.file.version
|
||||
const activeSemver = semver.parse(activeVersionString)
|
||||
if (activeSemver === null)
|
||||
output.warn(`${kleur.yellow(mod.modFile.name)} has no valid semantic version: ${kleur.yellow(mod.modFile.file.version)}. The publication date will instead be used.`)
|
||||
if (activeSemver === null) output.warn(
|
||||
`${kleur.yellow(mod.modFile.name)} has no valid semantic version: ${kleur.yellow(mod.modFile.file.version)}. ` +
|
||||
`The publication date will instead be used.`
|
||||
)
|
||||
|
||||
const versions = await modrinthApi.listVersions(mod.modFile.source.modId, pack.horizrFile.loader, pack.horizrFile.versions.minecraft)
|
||||
const versions = await modrinthApi.listVersions(mod.modFile.source.modId, pack.horizrFile.versions.minecraft)
|
||||
const allowedVersions = versions.filter(version => allowedReleaseChannels.includes(version.releaseChannel))
|
||||
|
||||
const newerVersions = activeSemver === null ? allowedVersions : allowedVersions.filter(version => {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
export type ModLoader = "fabric" | "quilt"
|
||||
export type ReleaseChannel = "alpha" | "beta" | "release"
|
||||
export const releaseChannelOrder: ReleaseChannel[] = ["alpha", "beta", "release"]
|
||||
|
||||
|
|
22
src/utils.ts
22
src/utils.ts
|
@ -1,6 +1,6 @@
|
|||
import { InvalidArgumentError } from "commander"
|
||||
import hash, { HashaInput } from "hasha"
|
||||
import { Path } from "./path.js"
|
||||
import { Path, paths } from "./path.js"
|
||||
import { ZipFile } from "yazl"
|
||||
import { walk } from "@root/walk"
|
||||
import fs from "fs-extra"
|
||||
|
@ -9,6 +9,26 @@ import serveHandler from "serve-handler"
|
|||
import * as http from "http"
|
||||
import addressWithCallback from "address"
|
||||
import { promisify } from "util"
|
||||
import { KeyvFile } from "keyv-file"
|
||||
import originalGot from "got"
|
||||
|
||||
const keyvCache = new KeyvFile({
|
||||
filename: paths.cache.resolve("http.json").toString(),
|
||||
writeDelay: 50,
|
||||
expiredCheckDelay: 24 * 3600 * 1000,
|
||||
encode: JSON.stringify,
|
||||
decode: JSON.parse
|
||||
})
|
||||
|
||||
export const clearCache = () => keyvCache.clear()
|
||||
|
||||
export const got = originalGot.extend({
|
||||
cache: keyvCache,
|
||||
responseType: "json",
|
||||
headers: {
|
||||
"User-Agent": "moritzruth/horizr/1.0.0 (not yet public)"
|
||||
}
|
||||
})
|
||||
|
||||
const address = promisify(addressWithCallback)
|
||||
export const getLANAddress = () => address().then(r => r.ip)
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
"description": "A test pack for testing the horizr CLI. It is not intended for playing.",
|
||||
"license": "MIT"
|
||||
},
|
||||
"loader": "fabric",
|
||||
"versions": {
|
||||
"loader": "0.14.7",
|
||||
"fabric": "0.14.7",
|
||||
"minecraft": "1.18.2"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue