diff --git a/package.json b/package.json index 0f97da8..8442b5d 100644 --- a/package.json +++ b/package.json @@ -1,88 +1,79 @@ { - "name": "@pssbletrngle/data-modifier", - "version": "0.0.0-dev", - "description": "Data Modifier", - "main": "dist/index.js", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "./parser": { - "types": "./dist/parser/index.d.ts", - "default": "./dist/parser/index.js" - }, - "./parser/create": { - "types": "./dist/parser/create.d.ts", - "default": "./dist/parser/create.js" - }, - "./parser/thermal": { - "types": "./dist/parser/thermal.d.ts", - "default": "./dist/parser/thermal.js" - }, - "./parser/farmersdelight": { - "types": "./dist/parser/farmersdelight.d.ts", - "default": "./dist/parser/farmersdelight.js" - }, - "./parser/adAstra": { - "types": "./dist/parser/adAstra.d.ts", - "default": "./dist/parser/adAstra.js" - }, - "./parser/roots": { - "types": "./dist/parser/roots.d.ts", - "default": "./dist/parser/roots.js" - } - }, - "types": "./dist/index.d.ts", - "files": [ - "dist" - ], - "type": "module", - "packageManager": "pnpm@8.6.12", - "scripts": { - "build": "tsc", - "lint": "eslint \"{src,test}/**/*.ts\"", - "test": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --no-warnings\" jest", - "test:ci": "pnpm run lint && pnpm run test --coverage" - }, - "repository": { - "type": "git", - "url": "https://github.com/PssbleTrngle/DataModifier.git" - }, - "publishConfig": { - "registry": "https://npm.pkg.github.com" - }, - "license": "ISC", - "bugs": { - "url": "https://github.com/PssbleTrngle/DataModifier/issues" - }, - "homepage": "https://github.com/PssbleTrngle/DataModifier#readme", - "devDependencies": { - "@types/jest": "^29.5.5", - "@types/lodash-es": "^4.17.9", - "@types/node": "^17.0.45", - "@typescript-eslint/eslint-plugin": "^6.7.4", - "@typescript-eslint/parser": "^6.7.4", - "cross-env": "^7.0.3", - "eslint": "^8.23.0", - "eslint-plugin-jest": "^27.4.2", - "eslint-plugin-require-extensions": "^0.1.3", - "jest": "^29.7.0", - "ts-jest": "^29.1.1" - }, - "dependencies": { - "@pssbletrngle/pack-resolver": "1.2.2", - "@pssbletrngle/resource-merger": "1.2.4", - "@types/minimatch": "^3.0.5", - "@types/prettier": "^2.7.0", - "chalk": "^5.0.1", - "json5": "^2.2.3", - "lodash-es": "^4.17.21", - "minimatch": "^5.1.0", - "node-stream-zip": "^1.15.0", - "prettier": "^2.7.1", - "prismarine-nbt": "^2.2.1", - "typescript": "^4.8.2", - "zod": "^3.22.4" - } + "name": "@pssbletrngle/data-modifier", + "version": "0.0.0-dev", + "description": "Data Modifier", + "main": "dist/index.js", + "exports": { + ".": "./dist/index.js", + "./parser": "./dist/parser/index.js", + "./parser/botania": "./dist/parser/botania.js", + "./parser/create": "./dist/parser/create.js", + "./parser/thermal": "./dist/parser/thermal.js", + "./parser/farmersdelight": "./dist/parser/farmersdelight.js", + "./parser/adAstra": "./dist/parser/adAstra.js", + "./parser/roots": "./dist/parser/roots.js" + }, + "typesVersions": { + "*": { + "parser": ["./dist/parser/index.d.ts"], + "parser/botania": ["./dist/parser/botania.d.ts"], + "parser/create": ["./dist/parser/create.d.ts"], + "parser/thermal": ["./dist/parser/thermal.d.ts"], + "parser/farmersdelight": ["./dist/parser/farmersdelight.d.ts"], + "parser/adAstra": ["./dist/parser/adAstra.d.ts"], + "parser/roots": ["./dist/parser/roots.d.ts"] + } + }, + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "type": "module", + "packageManager": "pnpm@8.6.12", + "scripts": { + "build": "tsc", + "lint": "eslint \"{src,test}/**/*.ts\"", + "test": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --no-warnings\" jest", + "test:ci": "pnpm run lint && pnpm run test --coverage" + }, + "repository": { + "type": "git", + "url": "https://github.com/PssbleTrngle/DataModifier.git" + }, + "publishConfig": { + "registry": "https://npm.pkg.github.com" + }, + "license": "ISC", + "bugs": { + "url": "https://github.com/PssbleTrngle/DataModifier/issues" + }, + "homepage": "https://github.com/PssbleTrngle/DataModifier#readme", + "devDependencies": { + "@types/jest": "^29.5.5", + "@types/lodash-es": "^4.17.9", + "@types/node": "^17.0.45", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "cross-env": "^7.0.3", + "eslint": "^8.23.0", + "eslint-plugin-jest": "^27.4.2", + "eslint-plugin-require-extensions": "^0.1.3", + "jest": "^29.7.0", + "ts-jest": "^29.1.1" + }, + "dependencies": { + "@pssbletrngle/pack-resolver": "1.2.2", + "@pssbletrngle/resource-merger": "1.2.4", + "@types/minimatch": "^3.0.5", + "@types/prettier": "^2.7.0", + "chalk": "^5.0.1", + "json5": "^2.2.3", + "lodash-es": "^4.17.21", + "minimatch": "^5.1.0", + "node-stream-zip": "^1.15.0", + "prettier": "^2.7.1", + "prismarine-nbt": "^2.2.1", + "typescript": "^4.8.2", + "zod": "^3.22.4" + } } diff --git a/src/emit/ruled.ts b/src/emit/ruled.ts index 852dff6..5a77f8a 100644 --- a/src/emit/ruled.ts +++ b/src/emit/ruled.ts @@ -36,7 +36,7 @@ export default class RuledEmitter> { const path = this.pathProvider(id) - const rules = this.rules.filter(it => it.matches(id, recipe, this.logger)) + const rules = this.rules.filter(it => it.matches(id, recipe, this.logger.group(path))) if (rules.length === 0) return const modified = rules.reduce((previous, rule) => previous && rule.modify(previous), recipe) diff --git a/src/error.ts b/src/error.ts index 19c4a60..2a4e98a 100644 --- a/src/error.ts +++ b/src/error.ts @@ -3,7 +3,7 @@ import { ZodError } from 'zod' export class IllegalShapeError extends Error { constructor(message: string, readonly input?: unknown) { - super(input ? `${message}: ${JSON.stringify(input)}` : message) + super(message) } } @@ -12,12 +12,19 @@ export function tryCatching(logger: Logger | undefined, run: () => T): T | nu return run() } catch (error) { if (error instanceof IllegalShapeError) { - logger?.warn((error as Error).message) + if (error.input) logger?.warn(error.message, error.input) + else logger?.warn(error.message) return null } if (error instanceof ZodError) { - logger?.warn(`unknown shape`, error) + const message = error.errors + .map(it => { + if (it.path) return `${it.path.join('.')}: ${it.message}` + else return it.message + }) + .join(', ') + logger?.warn(`unknown shape: ${message}`) return null } diff --git a/src/loader/index.ts b/src/loader/index.ts index 412841d..3899349 100644 --- a/src/loader/index.ts +++ b/src/loader/index.ts @@ -26,7 +26,7 @@ export abstract class JsonLoader implements RegistryProvider { return fromJson(content) } catch (error) { if (error instanceof SyntaxError) { - logger.warn(`unable to parse json: ${error.message}`, content) + logger.warn(`unable to parse json: ${error.message}`) return null } throw error @@ -40,10 +40,12 @@ export abstract class JsonLoader implements RegistryProvider { const { namespace, rest } = match.groups const id: Id = { namespace, path: rest } - const json = this.tryParseJson(logger.group(path), content.toString()) + const grouped = logger.group(path) + + const json = this.tryParseJson(grouped, content.toString()) if (!json) return false - const parsed = tryCatching(logger, () => this.parse(logger, json, id)) + const parsed = tryCatching(grouped, () => this.parse(grouped, json, id)) if (!parsed) return false this.registry.set(id, parsed) diff --git a/src/loader/lang.ts b/src/loader/lang.ts index b0f94a1..8d7a0b0 100644 --- a/src/loader/lang.ts +++ b/src/loader/lang.ts @@ -1,16 +1,13 @@ import { Id } from '../common/id.js' -import { tryCatching } from '../error.js' import { JsonLoader } from './index.js' import { Logger } from '../logger.js' import { LangDefinition, LangSchema } from '../schema/lang.js' export default class LangLoader extends JsonLoader { - protected parse(logger: Logger, json: unknown, id: Id): LangDefinition | null { - return tryCatching(logger.group(`unable to parse lang file ${id.path}`), () => { - const parsed = LangSchema.parse(json) - const existing = this.registry.get(id) - if (!existing) return parsed - return { ...existing, ...parsed } - }) + protected parse(_: Logger, json: unknown, id: Id): LangDefinition | null { + const parsed = LangSchema.parse(json) + const existing = this.registry.get(id) + if (!existing) return parsed + return { ...existing, ...parsed } } } diff --git a/src/loader/recipe.ts b/src/loader/recipe.ts index 95ee584..707d4cf 100644 --- a/src/loader/recipe.ts +++ b/src/loader/recipe.ts @@ -36,6 +36,7 @@ import RootRitualRecipeParser from '../parser/recipe/roots/ritual.js' import { ShapelessRecipeParser } from '../parser/index.js' import { Logger } from '../logger.js' import { IllegalShapeError } from '../error.js' +import IgnoredRecipe from '../parser/recipe/ignored.js' export interface RecipeLoaderAccessor { unknownRecipeTypes(): RecipeDefinition[] @@ -219,15 +220,11 @@ export default class RecipeLoader extends JsonLoader implements RecipeLo return null } - try { - return parser.create(definition, it => { - const parsed = this.parse(logger, it) - if (parsed) return parsed - throw new IllegalShapeError('unable to parse sub-recipe', it) - }) as TRecipe - } catch (error) { - throw new IllegalShapeError(`Failed to parse recipe with type '${definition.type}'`, error) - } + return parser.create(definition, it => { + const parsed = this.parse(logger, it) + if (parsed) return parsed + return new IgnoredRecipe(it) + }) as TRecipe } registerParser(recipeType: string, parser: RecipeParser) { diff --git a/src/logger.ts b/src/logger.ts index e3b4e71..5e031a5 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -18,7 +18,7 @@ export function wrapLogMethods(logMethods: LogMethods): Logger { } function grouped(prefix: string | undefined, message: Logable) { - if (prefix) return `${prefix}: ${message}` + if (prefix) return `${prefix} -> ${message}` return ` ${message}` } diff --git a/src/parser/botania.ts b/src/parser/botania.ts index 1f9aa67..b9f333d 100644 --- a/src/parser/botania.ts +++ b/src/parser/botania.ts @@ -24,7 +24,17 @@ export { NbtWrapperRecipe, default as NbtWrapperRecipeParser, } from './recipe/botania/nbtWrapper.js' -export { OrechidRecipeDefinition, OrechidRecipe, default as OrechidRecipeParser } from './recipe/botania/orechid.js' +export { + OrechidRecipeDefinition, + OrechidRecipe, + default as OrechidRecipeParser, + createBlockInput, + createBlockOutput, + fromBlockInput, + fromBlockOutput, + BlockInput, + BlockOutput, +} from './recipe/botania/orechid.js' export { PureDaisyRecipeDefinition, PureDaisyRecipe, diff --git a/src/parser/recipe/ignored.ts b/src/parser/recipe/ignored.ts new file mode 100644 index 0000000..70cada9 --- /dev/null +++ b/src/parser/recipe/ignored.ts @@ -0,0 +1,22 @@ +import { Recipe } from './index.js' +import { IngredientInput } from '../../common/ingredient.js' +import { ResultInput } from '../../common/result.js' +import { RecipeDefinition } from '../../schema/recipe.js' + +export default class IgnoredRecipe extends Recipe { + getIngredients(): IngredientInput[] { + return [] + } + + getResults(): ResultInput[] { + return [] + } + + replaceIngredient(): Recipe { + return new IgnoredRecipe(this.definition) + } + + replaceResult(): Recipe { + return new IgnoredRecipe(this.definition) + } +} diff --git a/src/rule/lootTable.ts b/src/rule/lootTable.ts index 71d4cb4..724d9cf 100644 --- a/src/rule/lootTable.ts +++ b/src/rule/lootTable.ts @@ -1,6 +1,6 @@ import Rule, { Modifier } from './index.js' import { extendLootEntry, LootEntryBase, LootTable } from '../schema/loot.js' -import { encodeId, Id } from '../common/id.js' +import { Id } from '../common/id.js' import { Logger } from '../logger.js' import { IngredientInput, Predicate } from '../common/ingredient.js' @@ -36,7 +36,7 @@ export default class LootTableRule extends Rule { } matches(id: Id, table: LootTable, logger: Logger): boolean { - const prefixed = logger.group(encodeId(id)) + const prefixed = logger return this.idTests.every(test => test(id, prefixed)) && this.outputTests.every(test => hasOutput(test, table)) } } diff --git a/src/rule/recipe.ts b/src/rule/recipe.ts index 66b2422..1d8737d 100644 --- a/src/rule/recipe.ts +++ b/src/rule/recipe.ts @@ -1,6 +1,6 @@ import { IngredientInput, Predicate } from '../common/ingredient.js' import { Recipe } from '../parser/recipe/index.js' -import { createId, encodeId, Id } from '../common/id.js' +import { createId, Id } from '../common/id.js' import { Logger } from '../logger.js' import Rule, { Modifier } from './index.js' @@ -16,13 +16,12 @@ export default class RecipeRule extends Rule { } matches(id: Id, recipe: Recipe, logger: Logger): boolean { - const prefixed = logger.group(encodeId(id)) const type = createId(recipe.toJSON().type) return ( - this.idsTests.every(test => test(id, prefixed)) && - this.typeTests.every(test => test(type, prefixed)) && - this.ingredientTests.every(test => recipe.getIngredients().some(it => test(it, prefixed))) && - this.resultTests.every(test => recipe.getResults().some(it => test(it, prefixed))) + this.idsTests.every(test => test(id, logger)) && + this.typeTests.every(test => test(type, logger)) && + this.ingredientTests.every(test => recipe.getIngredients().some(it => test(it, logger))) && + this.resultTests.every(test => recipe.getResults().some(it => test(it, logger))) ) } } diff --git a/src/textHelper.ts b/src/textHelper.ts index 66847f5..91fdbae 100644 --- a/src/textHelper.ts +++ b/src/textHelper.ts @@ -2,7 +2,14 @@ import { format } from 'prettier' import json from 'json5' export function fromJson(input: string) { - return json.parse(input.replaceAll('\r\n', '')) + try { + return json.parse(input) + } catch (e) { + if (e instanceof SyntaxError) { + return json.parse(input.replaceAll('\r\n', '')) + } + throw e + } } export function toJson(input: unknown) { diff --git a/test/logger.test.ts b/test/logger.test.ts index e278204..e3047f1 100644 --- a/test/logger.test.ts +++ b/test/logger.test.ts @@ -52,9 +52,9 @@ describe('tests regarding the logger', () => { logger.warn('Some Warning') logger.error('An Error Occured', error) - expect(console.log).toHaveBeenCalledWith(chalk.green('prefix: Info Test')) - expect(console.warn).toHaveBeenCalledWith(chalk.yellow('prefix: Some Warning')) - expect(console.error).toHaveBeenCalledWith(chalk.red('prefix: An Error Occured'), error) + expect(console.log).toHaveBeenCalledWith(chalk.green('prefix -> Info Test')) + expect(console.warn).toHaveBeenCalledWith(chalk.yellow('prefix -> Some Warning')) + expect(console.error).toHaveBeenCalledWith(chalk.red('prefix -> An Error Occured'), error) }) })