diff --git a/.gitignore b/.gitignore index 67ccce4..8b70917 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -node_modules/ -.idea/ -dist/ +/node_modules/ +/.idea/ +/dist/ +/schemas/ diff --git a/package.json b/package.json index 2712e6f..e7bed30 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,8 @@ "toml": "^3.0.0", "wrap-ansi": "^8.0.1", "yazl": "^2.5.1", - "zod": "^3.18.0" + "zod": "^3.18.0", + "zod-to-json-schema": "^3.17.1" }, "devDependencies": { "@types/dedent": "^0.7.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19fa08e..ea89324 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,6 +42,7 @@ specifiers: wrap-ansi: ^8.0.1 yazl: ^2.5.1 zod: ^3.18.0 + zod-to-json-schema: ^3.17.1 dependencies: '@root/walk': 1.1.0 @@ -73,6 +74,7 @@ dependencies: wrap-ansi: 8.0.1 yazl: 2.5.1 zod: 3.18.0 + zod-to-json-schema: 3.17.1_zod@3.18.0 devDependencies: '@types/dedent': 0.7.0 @@ -1777,6 +1779,14 @@ packages: engines: {node: '>=12.20'} dev: false + /zod-to-json-schema/3.17.1_zod@3.18.0: + resolution: {integrity: sha512-h1WLfvkdwM6lcRt5q09ytNh2OKcU13vY9D0FetN/7Erdd7lVraIiMkEnObg3KELm5EQlMqvi0r5nzMa0EA+8qw==} + peerDependencies: + zod: ^3.17.10 + dependencies: + zod: 3.18.0 + dev: false + /zod/3.18.0: resolution: {integrity: sha512-gwTm8RfUCe8l9rDwN5r2A17DkAa8Ez4Yl4yXqc5VqeGaXaJahzYYXbTwvhroZi0SNBqTwh/bKm2N0mpCzuw4bA==} dev: false diff --git a/src/commands/exportJsonSchemas.ts b/src/commands/exportJsonSchemas.ts new file mode 100644 index 0000000..2e19ecf --- /dev/null +++ b/src/commands/exportJsonSchemas.ts @@ -0,0 +1,22 @@ +import { Command } from "commander" +import fs from "fs-extra" +import { zodToJsonSchema } from "zod-to-json-schema" +import { metaFileContentSchema, packManifestFileSchema } from "../files.js" + +export const exportJsonSchemasCommand = new Command("export-json-schemas") + .argument("") + .description("Exports the pack manifest and meta-file JSON schemas.") + .action(async path => { + await fs.mkdirp(path) + await fs.writeJson(path + "/manifest.schema.json", { + title: "Horizr pack manifest", + $id: "https://horizr.moritzruth.de/schemas/pack/manifest.schema.json", + ...zodToJsonSchema(packManifestFileSchema) + }, { spaces: 2 }) + + await fs.writeJson(path + "/meta-file.schema.json", { + title: "Horizr pack meta-file", + $id: "https://horizr.moritzruth.de/schemas/pack/meta-file.schema.json", + ...zodToJsonSchema(metaFileContentSchema) + }, { spaces: 2 }) + }) diff --git a/src/commands/init.ts b/src/commands/init.ts index b920948..aaaa6f8 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -5,7 +5,7 @@ import { output } from "../utils/output.js" import kleur from "kleur" import { fetchFabricMinecraftVersions, fetchFabricVersions } from "../fabricApi.js" import enquirer from "enquirer" -import { PACK_MANIFEST_FILE_NAME, PACK_MANIFEST_FORMAT_VERSION, PackManifest } from "../files.js" +import { PACK_MANIFEST_FILE_NAME, FORMAT_VERSION, PackManifest } from "../files.js" import pathModule from "path" import { EXPORTS_DIRECTORY_NAME } from "../pack.js" import slugify from "@sindresorhus/slugify" @@ -63,7 +63,7 @@ export const initCommand = new Command("init") const fabricVersion = (await output.withLoading(fetchFabricVersions(answers.minecraftVersion), "Fetching latest Fabric version"))[0] const file: PackManifest = { - formatVersion: PACK_MANIFEST_FORMAT_VERSION, + formatVersion: FORMAT_VERSION, slug: slugify(answers.name), meta: { name: answers.name, diff --git a/src/commands/modrinth/activate.ts b/src/commands/modrinth/activate.ts index cf65c64..cd1374a 100644 --- a/src/commands/modrinth/activate.ts +++ b/src/commands/modrinth/activate.ts @@ -12,7 +12,7 @@ import { output } from "../../utils/output.js" import { modrinthApi } from "../../modrinth/api.js" import { Side, usePack } from "../../pack.js" import kleur from "kleur" -import { META_FILE_EXTENSION, metaFileContentSchema, writeJsonFile } from "../../files.js" +import { FORMAT_VERSION, META_FILE_EXTENSION, metaFileContentSchema, writeJsonFile } from "../../files.js" import fs from "fs-extra" import enquirer from "enquirer" import { orEmptyString } from "../../utils/strings.js" @@ -67,6 +67,7 @@ export const activateCommand = new Command("activate") await fs.mkdirp(absolutePath.parent().toString()) await writeJsonFile(absolutePath, metaFileContentSchema, { + formatVersion: FORMAT_VERSION, enabled: true, version: getMetaFileContentVersionForModrinth(modrinthVersion), source: { diff --git a/src/files.ts b/src/files.ts index 19c3681..82d6445 100644 --- a/src/files.ts +++ b/src/files.ts @@ -44,11 +44,11 @@ export async function readJsonFile>(rootPath: return result.data } -export const PACK_MANIFEST_FORMAT_VERSION = 1 +export const FORMAT_VERSION = 1 export const PACK_MANIFEST_FILE_NAME = "horizr.json" -export const horizrFileSchema = z.object({ - formatVersion: z.literal(PACK_MANIFEST_FORMAT_VERSION), +export const packManifestFileSchema = z.object({ + formatVersion: z.literal(FORMAT_VERSION), slug: z.string(), meta: z.object({ name: z.string(), @@ -63,7 +63,7 @@ export const horizrFileSchema = z.object({ }) }) -export type PackManifest = z.output +export type PackManifest = z.output export const META_FILE_EXTENSION = "hm.json" @@ -89,6 +89,7 @@ const metaFileContentVersionSchema = z.object({ export type MetaFileContentVersion = z.output export const metaFileContentSchema = z.object({ + formatVersion: z.literal(FORMAT_VERSION), displayName: z.string().optional(), enabled: z.boolean().default(true), comment: z.string().optional(), diff --git a/src/main.ts b/src/main.ts index 47c47b4..01c505d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,6 +10,7 @@ import { infoCommand } from "./commands/info.js" import { updateCommand } from "./commands/update.js" import { packwizCommand } from "./commands/packwiz/index.js" import { modrinthCommand } from "./commands/modrinth/index.js" +import { exportJsonSchemasCommand } from "./commands/exportJsonSchemas.js" const program = new Command("horizr") .version( @@ -23,6 +24,7 @@ const program = new Command("horizr") }) .addCommand(modrinthCommand) .addCommand(packwizCommand) + .addCommand(exportJsonSchemasCommand, { hidden: true }) .addCommand(infoCommand) .addCommand(initCommand) .addCommand(updateCommand) diff --git a/src/pack.ts b/src/pack.ts index f540a2e..2b6082d 100644 --- a/src/pack.ts +++ b/src/pack.ts @@ -2,7 +2,7 @@ import { AbsolutePath, envPaths, RelativePath } from "./utils/path.js" import { findPackDirectoryPath, PackManifest, - horizrFileSchema, + packManifestFileSchema, MetaFileContent, PACK_MANIFEST_FILE_NAME, metaFileContentSchema, @@ -82,7 +82,7 @@ export async function usePack(): Promise { const sourceDirectoryPath = rootDirectoryPath.resolve("src") const readSourceJsonFile: Pack["readSourceJsonFile"] = async (path, schema) => readJsonFile(sourceDirectoryPath, path, schema) - const manifest = (await readJsonFile(rootDirectoryPath, RelativePath.create(PACK_MANIFEST_FILE_NAME), horizrFileSchema))! + const manifest = (await readJsonFile(rootDirectoryPath, RelativePath.create(PACK_MANIFEST_FILE_NAME), packManifestFileSchema))! const metaFiles: MetaFile[] = [] const staticSourceFiles: StaticSourceFile[] = []