From 402f4620dd3ae4e196100823353f1c5432fe9302 Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Fri, 18 Jul 2025 20:23:23 -0400 Subject: [PATCH 01/19] Added egg move parse utility script --- biome.jsonc | 7 +- package.json | 1 + scripts/parse-egg-moves/egg-move-template.ts | 10 ++ scripts/parse-egg-moves/help-message.js | 16 ++ scripts/parse-egg-moves/interactive.js | 104 ++++++++++++ scripts/parse-egg-moves/main.js | 163 +++++++++++++++++++ scripts/parse-egg-moves/parse.js | 60 +++++++ src/data/balance/egg-moves.ts | 62 +------ src/loading-scene.ts | 2 - test/testUtils/testFileInitialization.ts | 2 - 10 files changed, 365 insertions(+), 62 deletions(-) create mode 100644 scripts/parse-egg-moves/egg-move-template.ts create mode 100644 scripts/parse-egg-moves/help-message.js create mode 100644 scripts/parse-egg-moves/interactive.js create mode 100644 scripts/parse-egg-moves/main.js create mode 100644 scripts/parse-egg-moves/parse.js diff --git a/biome.jsonc b/biome.jsonc index ed5db201824..ecabdbfb940 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -177,9 +177,10 @@ } }, - // Overrides to prevent unused import removal inside `overrides.ts` and enums files (for TSDoc linkcodes) + // Overrides to prevent unused import removal inside `overrides.ts` and enums files (for TSDoc linkcodes), + // as well as in all TS files in `scripts/` (which are assumed to be boilerplate templates). { - "includes": ["**/src/overrides.ts", "**/src/enums/**/*"], + "includes": ["**/src/overrides.ts", "**/src/enums/**/*", "**/scripts/**/*.ts"], "linter": { "rules": { "correctness": { @@ -189,7 +190,7 @@ } }, { - "includes": ["**/src/overrides.ts"], + "includes": ["**/src/overrides.ts", "**/scripts/**/*.ts"], "linter": { "rules": { "style": { diff --git a/package.json b/package.json index 64f2f9786db..b559fcbca29 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "test:watch": "vitest watch --coverage --no-isolate", "test:silent": "vitest run --silent --no-isolate", "test:create": "node scripts/create-test/create-test.js", + "eggMove:parse": "node scripts/parse-egg-moves/main.js", "typecheck": "tsc --noEmit", "eslint": "eslint --fix .", "eslint-ci": "eslint .", diff --git a/scripts/parse-egg-moves/egg-move-template.ts b/scripts/parse-egg-moves/egg-move-template.ts new file mode 100644 index 00000000000..bfac05f4bde --- /dev/null +++ b/scripts/parse-egg-moves/egg-move-template.ts @@ -0,0 +1,10 @@ +//! DO NOT EDIT THIS FILE - CREATED BY THE `eggMoves:parse` script automatically +import { MoveId } from "#enums/move-id"; +import { SpeciesId } from "#enums/species-id"; + +/** + * An object mapping all base form {@linkcode SpeciesId}s to an array of {@linkcode MoveId}s corresponding + * to their current egg moves. + * Generated by the `eggMoves:parse` script using a CSV sourced from the current Balance Team spreadsheet. + */ +export const speciesEggMoves = "{{table}}"; diff --git a/scripts/parse-egg-moves/help-message.js b/scripts/parse-egg-moves/help-message.js new file mode 100644 index 00000000000..57d28c36132 --- /dev/null +++ b/scripts/parse-egg-moves/help-message.js @@ -0,0 +1,16 @@ +import chalk from "chalk"; + +export function showHelpText() { + console.log(` +Usage: ${chalk.cyan("pnpm eggMove:parse [options]")} +If given no options, assumes ${chalk.blue("\`--interactive\`")}. +If given only a file path, assumes ${chalk.blue("\`--file\`")}. + +${chalk.hex("#ffa500")("Options:")} + ${chalk.blue("-h, --help")} Show this help message. + ${chalk.blue("-f, --file[=PATH]")} Specify a path to a CSV file to read, or provide one from stdin. + ${chalk.blue("-t, --text[=TEXT]")} + ${chalk.blue("-c, --console[=TEXT]")} Specify CSV text to read, or provide it from stdin. + ${chalk.blue("-i, --interactive")} Run in interactive mode (default) +`); +} diff --git a/scripts/parse-egg-moves/interactive.js b/scripts/parse-egg-moves/interactive.js new file mode 100644 index 00000000000..46150137f74 --- /dev/null +++ b/scripts/parse-egg-moves/interactive.js @@ -0,0 +1,104 @@ +import fs from "fs"; +import chalk from "chalk"; +import inquirer from "inquirer"; +import { showHelpText } from "./help-message.js"; + +/** + * Prompt the user to interactively select an option (console/file) to retrieve the egg move CSV. + * @returns {Promise<{type: "Console" | "File", value: string} | {type: "Exit"}>} The selected option with value + */ +export async function runInteractive() { + /** @type {"Console" | "File" | "HELP MEEEEE" | "Exit"} */ + const answer = await inquirer + .prompt([ + { + type: "list", + name: "type", + message: "Select the method to obtain egg moves.", + choices: ["Console", "File", "HELP MEEEEE", "Exit"], + }, + ]) + .then(a => a.type); + + if (answer === "Exit") { + console.log("Exiting..."); + process.exitCode = 1; + return { type: "Exit" }; + } + + if (answer === "HELP MEEEEE") { + showHelpText(); + return { type: "Exit" }; + } + + if (!["Console", "File"].includes(answer)) { + console.error(chalk.red("Please provide a valid type!")); + return await runInteractive(); + } + + return { type: answer, value: await promptForValue(answer) }; +} + +/** + * Prompt the user to give a value (either the direct CSV or the file path). + * @param {"Console" | "File"} type - The input method + * @returns {Promise} A Promise resolving with the CSV/file path. + */ +function promptForValue(type) { + switch (type) { + case "Console": + return doPromptConsole(); + case "File": + return getFilePath(); + } +} + +/** + * Prompt the user to enter a file path from the console. + * @returns {Promise} The file path inputted by the user. + */ +async function getFilePath() { + return await inquirer + .prompt([ + { + type: "input", + name: "path", + message: "Please enter the path to the egg move CSV file.", + validate: input => { + if (input.trim() === "") { + return "File path cannot be empty!"; + } + if (!fs.existsSync(input)) { + return "File does not exist!"; + } + return true; + }, + }, + ]) + .then(answer => answer.path); +} + +/** + * Prompt the user for CSV input from the console. + * @returns {Promise} The CSV input from the user. + */ +async function doPromptConsole() { + return await inquirer + .prompt([ + { + type: "input", + name: "csv", + message: "Please enter the egg move CSV text.", + validate: input => { + if (input.trim() === "") { + return "CSV text cannot be empty!"; + } + if (!input.match(/^[^,]+(,[^,]+){4}$/gm)) { + return "CSV text malformed - should contain 5 consecutive comma-separated values per line!"; + } + return true; + }, + }, + ]) + .then(answer => answer.csv); +} diff --git a/scripts/parse-egg-moves/main.js b/scripts/parse-egg-moves/main.js new file mode 100644 index 00000000000..1d0009a6fe9 --- /dev/null +++ b/scripts/parse-egg-moves/main.js @@ -0,0 +1,163 @@ +/* + * This script accepts a CSV value or file path as input, parses the egg moves, + * and writes the output to a TypeScript file. + * It can be run interactively or with command line arguments. + * Usage: `pnpm eggMove:parse` + */ + +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import chalk from "chalk"; +import { showHelpText } from "./help-message.js"; +import { runInteractive } from "./interactive.js"; +import { parseEggMoves } from "./parse.js"; + +const version = "0.0.0"; // Replace with actual version if needed + +// Get the directory name of the current module file +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const projectRoot = path.join(__dirname, "..", ".."); +const templatePath = path.join(__dirname, "egg-move-template.ts"); +// TODO: Do we want this to be configurable? +const eggMoveTargetPath = path.join(projectRoot, "src/data/balance/egg-moves.ts"); + +/** + * Runs the interactive eggMove:parse CLI. + * @returns {Promise} + */ +async function start() { + console.log(chalk.yellow(`🄚 Egg Move Parser - v${version}`)); + + if (process.argv.length > 4) { + console.error( + chalk.redBright.bold( + `āœ— Error: Too many arguments provided!\nArgs: ${chalk.hex("#7310fdff")(process.argv.slice(2).join(" "))}`, + ), + ); + showHelpText(); + process.exitCode = 1; + return; + } + + /** @type {string} */ + let csv = ""; + const inputType = await parseArguments(); + if (process.exitCode) { + // If exit code is non-zero, return to allow it to propagate up the chain. + return; + } + switch (inputType.type) { + case "Console": + csv = inputType.value; + break; + case "File": + csv = await fs.promises.readFile(inputType.value, "utf-8"); + break; + case "Exit": + // Help screen triggered; break out + return; + } + + await writeToFile(parseEggMoves(csv)); +} + +/** + * Handle the arguments passed to the script and obtain the CSV input type. + * @returns {Promise<{type: "Console" | "File", value: string} | {type: "Exit"}>} The input method selected by the user + */ +async function parseArguments() { + const args = process.argv.slice(2); // first 2 args are node and script name (irrelevant) + + /** @type {string | undefined} */ + const arg = args[0].split("=")[0]; // Yoink everything up to the first "=" to get the raw command + switch (arg) { + case "-f": + case "--file": + return { type: "File", value: getArgValue() }; + case "-t": + case "--text": + case "-c": + case "--console": + return { type: "Console", value: getArgValue() }; + case "-h": + case "--help": + showHelpText(); + process.exitCode = 0; + return { type: "Exit" }; + case "--interactive": + case "-i": + case undefined: + return await runInteractive(); + default: + // If no arguments are found, check if it's a file path + if (fs.existsSync(arg)) { + console.log(chalk.green(`Using file path: ${chalk.blue(arg)}`)); + return { type: "File", value: arg }; + } + badArgs(); + return { type: "Exit" }; + } +} + +/** + * Get the value of the argument provided. + * @returns {string} The CSV or file path from the arguments + * @throws {Error} If arguments are malformed + */ +function getArgValue() { + // If the user provided a value as argument 2, take that as the argument. + // Otherwise, check the 1st argument to see if it contains an `=` and extract everything afterwards. + /** @type {string | undefined} */ + let filePath = process.argv[3]; + const equalsIndex = process.argv[2].indexOf("="); + if (equalsIndex > -1) { + // If arg 3 was aleady existing and someone used `=` notation to assign a property, throw an error. + filePath = filePath ? undefined : process.argv[2].slice(equalsIndex + 1); + } + + if (!filePath?.trim()) { + badArgs(); + return ""; + } + // NB: It doesn't really matter that this can be `undefined` - we'll always break out by lieu of setting the exit code + return filePath; +} + +/** + * Write out the parsed CSV to a file. + * @param {string} moves - The parsed CSV + * @returns {Promise} + */ +export async function writeToFile(moves) { + try { + // Read the template file, replacing the placeholder with the move table. + const content = fs.readFileSync(templatePath, "utf8").replace(`"{{table}}"`, moves); + + if (fs.existsSync(eggMoveTargetPath)) { + console.warn(chalk.hex("#ffa500")("\nEgg moves file already exists, overwriting...\n")); + } + + // Write the template content to the file + fs.writeFileSync(eggMoveTargetPath, content, "utf8"); + + console.log(chalk.green.bold(`\nāœ” Egg Moves written to ${eggMoveTargetPath}`)); + console.groupEnd(); + } catch (err) { + console.error(chalk.red("āœ— Error while writing egg moves!", err.message)); + process.exitCode = 1; + } +} + +/** + * Do logging for incorrect or malformed CLI arguments. + * @returns {void} + */ +function badArgs() { + chalk.red.bold(`āœ— Error: Malformed arguments!\nArgs: ${chalk.hex("#7310fdff")(process.argv.slice(2).join(" "))}`); + showHelpText(); + process.exitCode = 1; +} + +start(); diff --git a/scripts/parse-egg-moves/parse.js b/scripts/parse-egg-moves/parse.js new file mode 100644 index 00000000000..b6d41965bdc --- /dev/null +++ b/scripts/parse-egg-moves/parse.js @@ -0,0 +1,60 @@ +import chalk from "chalk"; + +/** + * Given a CSV string, parse it and return a structured table ready to be inputted into code. + * @param {string} csv - The formatted CSV string. + * @returns {string} The fully formatted table. + */ +export function parseEggMoves(csv) { + console.log(chalk.grey("āš™ļø Parsing egg moves...")); + let output = "{\n"; + + const lines = csv.split(/\n/g); + + for (const line of lines) { + /** + * The individual CSV column for this species. + */ + const cols = + /** @type {[speciesName: string, move1: string, move2: string, move3: string, move4: string]} */ + (line.split(",").slice(0, 5)); + const speciesName = toUpperSnakeCase(cols[0]); + + /** @type {string[]} */ + const eggMoves = []; + + for (let m = 1; m < 5; m++) { + const moveName = cols[m].trim(); + if (moveName === "N/A") { + console.warn(`Species ${speciesName} missing ${m}th egg move!`); + eggMoves.push("MoveId.NONE"); + continue; + } + + // Remove (N) and (P) from the ends of move names before UPPER_SNAKE_CASE-ing them + const moveNameTitle = toUpperSnakeCase(moveName.replace(/ \([A-Z]\)$/, "")); + eggMoves.push("MoveId." + moveNameTitle); + } + + if (eggMoves.every(move => move === "MoveId.NONE")) { + console.warn(`Species ${speciesName} could not be parsed, excluding from output...`); + output += ` // [SpeciesId.${speciesName}]: [ MoveId.NONE, MoveId.NONE, MoveId.NONE, MoveId.NONE ],\n`; + } else { + output += ` [SpeciesId.${speciesName}]: [ ${eggMoves.join(", ")} ],\n`; + } + } + + return output + "} satisfies Partial>;"; +} + +/** + * Helper method to convert a string into `UPPER_SNAKE_CASE`. + * @param {string} str - The string being converted + * @returns {string} The result of converting `str` into upper snake case. + */ +function toUpperSnakeCase(str) { + return str + .split(/[_ -]+/g) + .map(word => word.toUpperCase()) + .join("_"); +} diff --git a/src/data/balance/egg-moves.ts b/src/data/balance/egg-moves.ts index f5026abe2ef..08ee74098fb 100644 --- a/src/data/balance/egg-moves.ts +++ b/src/data/balance/egg-moves.ts @@ -1,9 +1,12 @@ -import { allMoves } from "#data/data-lists"; +//! DO NOT EDIT THIS FILE - CREATED BY THE `eggMoves:parse` script automatically import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; -import { toReadableString } from "#utils/common"; -import { getEnumKeys, getEnumValues } from "#utils/enums"; +/** + * An object mapping all base form {@linkcode SpeciesId}s to an array of {@linkcode MoveId}s corresponding + * to their current egg moves. + * Generated by the `eggMoves:parse` script using a CSV sourced from the current Balance Team spreadsheet. + */ export const speciesEggMoves = { [SpeciesId.BULBASAUR]: [ MoveId.SAPPY_SEED, MoveId.MALIGNANT_CHAIN, MoveId.EARTH_POWER, MoveId.MATCHA_GOTCHA ], [SpeciesId.CHARMANDER]: [ MoveId.DRAGON_DANCE, MoveId.BITTER_BLADE, MoveId.EARTH_POWER, MoveId.OBLIVION_WING ], @@ -582,55 +585,4 @@ export const speciesEggMoves = { [SpeciesId.PALDEA_TAUROS]: [ MoveId.NO_RETREAT, MoveId.BLAZING_TORQUE, MoveId.AQUA_STEP, MoveId.THUNDEROUS_KICK ], [SpeciesId.PALDEA_WOOPER]: [ MoveId.STONE_AXE, MoveId.RECOVER, MoveId.BANEFUL_BUNKER, MoveId.BARB_BARRAGE ], [SpeciesId.BLOODMOON_URSALUNA]: [ MoveId.NASTY_PLOT, MoveId.ROCK_POLISH, MoveId.SANDSEAR_STORM, MoveId.BOOMBURST ] -}; - -/** - * Parse a CSV-separated list of Egg Moves (such as one sourced from a Google Sheets) - * into code able to form the `speciesEggMoves` const object as above. - * @param content - The CSV-formatted string to convert into code. - */ -// TODO: Move this into the scripts folder and stop running it on initialization -function parseEggMoves(content: string): void { - let output = ""; - - const speciesNames = getEnumKeys(SpeciesId); - const speciesValues = getEnumValues(SpeciesId); - const moveNames = allMoves.map(m => m.name.replace(/ \([A-Z]\)$/, "").toLowerCase()); - const lines = content.split(/\n/g); - - for (const line of lines) { - const cols = line.split(",").slice(0, 5); - const enumSpeciesName = cols[0].toUpperCase().replace(/[ -]/g, "_") as keyof typeof SpeciesId; - // TODO: This should use reverse mapping instead of `indexOf` - const species = speciesValues[speciesNames.indexOf(enumSpeciesName)]; - - const eggMoves: MoveId[] = []; - - for (let m = 0; m < 4; m++) { - const moveName = cols[m + 1].trim(); - const moveIndex = moveName !== "N/A" ? moveNames.indexOf(moveName.toLowerCase()) : -1; - if (moveIndex === -1) { - console.warn(moveName, "could not be parsed"); - } - - eggMoves.push(moveIndex > -1 ? moveIndex as MoveId : MoveId.NONE); - } - - if (eggMoves.every(m => m === MoveId.NONE)) { - console.warn(`Species ${toReadableString(SpeciesId[species])} could not be parsed, excluding from output...`) - } else { - output += `[SpeciesId.${SpeciesId[species]}]: [ ${eggMoves.map(m => `MoveId.${MoveId[m]}`).join(", ")} ],\n`; - } - } - - console.log(output); -} - -export function initEggMoves() { - const eggMovesStr = ""; - if (eggMovesStr) { - setTimeout(() => { - parseEggMoves(eggMovesStr); - }, 1000); - } -} +} satisfies Partial>; \ No newline at end of file diff --git a/src/loading-scene.ts b/src/loading-scene.ts index eb6883e0c68..686958aa0de 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -3,7 +3,6 @@ import { timedEventManager } from "#app/global-event-manager"; import { SceneBase } from "#app/scene-base"; import { isMobile } from "#app/touch-controls"; import { initBiomes } from "#balance/biomes"; -import { initEggMoves } from "#balance/egg-moves"; import { initPokemonPrevolutions, initPokemonStarters } from "#balance/pokemon-evolutions"; import { initChallenges } from "#data/challenge"; import { initTrainerTypeDialogue } from "#data/dialogue"; @@ -375,7 +374,6 @@ export class LoadingScene extends SceneBase { initPokemonPrevolutions(); initPokemonStarters(); initBiomes(); - initEggMoves(); initPokemonForms(); initTrainerTypeDialogue(); initSpecies(); diff --git a/test/testUtils/testFileInitialization.ts b/test/testUtils/testFileInitialization.ts index 98b49159d98..c1b7bb4fe37 100644 --- a/test/testUtils/testFileInitialization.ts +++ b/test/testUtils/testFileInitialization.ts @@ -2,7 +2,6 @@ import { initAbilities } from "#abilities/ability"; import { initLoggedInUser } from "#app/account"; import { SESSION_ID_COOKIE_NAME } from "#app/constants"; import { initBiomes } from "#balance/biomes"; -import { initEggMoves } from "#balance/egg-moves"; import { initPokemonPrevolutions, initPokemonStarters } from "#balance/pokemon-evolutions"; import { initPokemonForms } from "#data/pokemon-forms"; import { initSpecies } from "#data/pokemon-species"; @@ -97,7 +96,6 @@ export function initTestFile() { initStatsKeys(); initPokemonPrevolutions(); initBiomes(); - initEggMoves(); initPokemonForms(); initSpecies(); initMoves(); From 61d268ac82185342de77eeded3d77e16d0763703 Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Mon, 21 Jul 2025 12:21:37 -0400 Subject: [PATCH 02/19] Update interactive.js Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- scripts/parse-egg-moves/interactive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/parse-egg-moves/interactive.js b/scripts/parse-egg-moves/interactive.js index 46150137f74..380f0273e32 100644 --- a/scripts/parse-egg-moves/interactive.js +++ b/scripts/parse-egg-moves/interactive.js @@ -8,7 +8,7 @@ import { showHelpText } from "./help-message.js"; * @returns {Promise<{type: "Console" | "File", value: string} | {type: "Exit"}>} The selected option with value */ export async function runInteractive() { - /** @type {"Console" | "File" | "HELP MEEEEE" | "Exit"} */ + /** @type {"Console" | "File" | "Help" | "Exit"} */ const answer = await inquirer .prompt([ { From 4ed50b15c36fc2a3ad264a6a337a3ab2ac6581b8 Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Mon, 21 Jul 2025 12:21:42 -0400 Subject: [PATCH 03/19] Update interactive.js Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- scripts/parse-egg-moves/interactive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/parse-egg-moves/interactive.js b/scripts/parse-egg-moves/interactive.js index 380f0273e32..3f21b3e71d4 100644 --- a/scripts/parse-egg-moves/interactive.js +++ b/scripts/parse-egg-moves/interactive.js @@ -15,7 +15,7 @@ export async function runInteractive() { type: "list", name: "type", message: "Select the method to obtain egg moves.", - choices: ["Console", "File", "HELP MEEEEE", "Exit"], + choices: ["Console", "File", "Help", "Exit"], }, ]) .then(a => a.type); From 44b0b8dcd0a55738a3b094113102b04c597cd4a1 Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Mon, 21 Jul 2025 12:21:50 -0400 Subject: [PATCH 04/19] Update interactive.js Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- scripts/parse-egg-moves/interactive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/parse-egg-moves/interactive.js b/scripts/parse-egg-moves/interactive.js index 3f21b3e71d4..814957dc09a 100644 --- a/scripts/parse-egg-moves/interactive.js +++ b/scripts/parse-egg-moves/interactive.js @@ -26,7 +26,7 @@ export async function runInteractive() { return { type: "Exit" }; } - if (answer === "HELP MEEEEE") { + if (answer === "Help") { showHelpText(); return { type: "Exit" }; } From 8ea5121b72829872212adbb1c3d42c21a57fadbd Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Mon, 21 Jul 2025 13:37:12 -0400 Subject: [PATCH 05/19] Applied kev's reviews --- package.json | 2 +- scripts/parse-egg-moves/help-message.js | 2 +- scripts/parse-egg-moves/main.js | 9 ++++----- scripts/parse-egg-moves/parse.js | 3 ++- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index b559fcbca29..a586879d578 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "test:watch": "vitest watch --coverage --no-isolate", "test:silent": "vitest run --silent --no-isolate", "test:create": "node scripts/create-test/create-test.js", - "eggMove:parse": "node scripts/parse-egg-moves/main.js", + "eggMoves:parse": "node scripts/parse-egg-moves/main.js", "typecheck": "tsc --noEmit", "eslint": "eslint --fix .", "eslint-ci": "eslint .", diff --git a/scripts/parse-egg-moves/help-message.js b/scripts/parse-egg-moves/help-message.js index 57d28c36132..6b5f1965a2b 100644 --- a/scripts/parse-egg-moves/help-message.js +++ b/scripts/parse-egg-moves/help-message.js @@ -2,7 +2,7 @@ import chalk from "chalk"; export function showHelpText() { console.log(` -Usage: ${chalk.cyan("pnpm eggMove:parse [options]")} +Usage: ${chalk.cyan("pnpm eggMoves:parse [options]")} If given no options, assumes ${chalk.blue("\`--interactive\`")}. If given only a file path, assumes ${chalk.blue("\`--file\`")}. diff --git a/scripts/parse-egg-moves/main.js b/scripts/parse-egg-moves/main.js index 1d0009a6fe9..1ab0e30bda0 100644 --- a/scripts/parse-egg-moves/main.js +++ b/scripts/parse-egg-moves/main.js @@ -2,7 +2,7 @@ * This script accepts a CSV value or file path as input, parses the egg moves, * and writes the output to a TypeScript file. * It can be run interactively or with command line arguments. - * Usage: `pnpm eggMove:parse` + * Usage: `pnpm eggMoves:parse` */ import fs from "node:fs"; @@ -13,7 +13,7 @@ import { showHelpText } from "./help-message.js"; import { runInteractive } from "./interactive.js"; import { parseEggMoves } from "./parse.js"; -const version = "0.0.0"; // Replace with actual version if needed +const version = "1.0.0"; // Get the directory name of the current module file const __filename = fileURLToPath(import.meta.url); @@ -24,7 +24,7 @@ const templatePath = path.join(__dirname, "egg-move-template.ts"); const eggMoveTargetPath = path.join(projectRoot, "src/data/balance/egg-moves.ts"); /** - * Runs the interactive eggMove:parse CLI. + * Runs the interactive eggMoves:parse CLI. * @returns {Promise} */ async function start() { @@ -41,7 +41,6 @@ async function start() { return; } - /** @type {string} */ let csv = ""; const inputType = await parseArguments(); if (process.exitCode) { @@ -93,7 +92,7 @@ async function parseArguments() { default: // If no arguments are found, check if it's a file path if (fs.existsSync(arg)) { - console.log(chalk.green(`Using file path: ${chalk.blue(arg)}`)); + console.log(chalk.green(`Using file path from stdin: ${chalk.blue(arg)}`)); return { type: "File", value: arg }; } badArgs(); diff --git a/scripts/parse-egg-moves/parse.js b/scripts/parse-egg-moves/parse.js index b6d41965bdc..209a350df42 100644 --- a/scripts/parse-egg-moves/parse.js +++ b/scripts/parse-egg-moves/parse.js @@ -44,7 +44,8 @@ export function parseEggMoves(csv) { } } - return output + "} satisfies Partial>;"; + // NB: We omit the semicolon as it is contained in the template string itself + return output + "} satisfies Partial>"; } /** From 5f97a97ffff5a6f46ff9d29dd13978b6af482010 Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Mon, 11 Aug 2025 17:01:33 -0400 Subject: [PATCH 06/19] Removed `basePath` from tsconfig the docs literally recommend against using it so yeah --- tsconfig.json | 74 +++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index dcbf7456df8..9b6a912bac7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,43 +21,43 @@ "checkJs": true, "strict": false, // TODO: Enable this eventually "rootDir": ".", - "baseUrl": "./src", - "paths": { - "#abilities/*": ["./data/abilities/*.ts"], - "#api/*": ["./plugins/api/*.ts"], - "#balance/*": ["./data/balance/*.ts"], - "#enums/*": ["./enums/*.ts"], - "#events/*": ["./events/*.ts"], - "#field/*": ["./field/*.ts"], - "#inputs/*": ["./configs/inputs/*.ts"], - "#modifiers/*": ["./modifier/*.ts"], - "#moves/*": ["./data/moves/*.ts"], - "#mystery-encounters/*": [ - "./data/mystery-encounters/utils/*.ts", - "./data/mystery-encounters/encounters/*.ts", - "./data/mystery-encounters/requirements/*.ts", - "./data/mystery-encounters/*.ts" - ], - "#package.json": ["../package.json"], - "#phases/*": ["./phases/*.ts"], - "#plugins/*": ["./plugins/vite/*.ts", "./plugins/*.ts"], - "#sprites/*": ["./sprites/*.ts"], - "#system/*": [ - "./system/settings/*.ts", - "./system/version-migration/versions/*.ts", - "./system/version-migration/*.ts", - "./system/*.ts" - ], - "#trainers/*": ["./data/trainers/*.ts"], - "#types/*": ["./@types/helpers/*.ts", "./@types/*.ts", "./typings/phaser/*.ts"], - "#ui/*": ["./ui/battle-info/*.ts", "./ui/settings/*.ts", "./ui/*.ts"], - "#utils/*": ["./utils/*.ts"], - "#data/*": ["./data/pokemon-forms/*.ts", "./data/pokemon/*.ts", "./data/*.ts"], - "#test/*": ["../test/*.ts"], - "#app/*": ["*.ts"] - }, "outDir": "./build", - "noEmit": true + "noEmit": true, + "paths": { + "#abilities/*": ["./src/data/abilities/*.ts"], + "#api/*": ["./src/plugins/api/*.ts"], + "#balance/*": ["./src/data/balance/*.ts"], + "#enums/*": ["./src/enums/*.ts"], + "#events/*": ["./src/events/*.ts"], + "#field/*": ["./src/field/*.ts"], + "#inputs/*": ["./src/configs/inputs/*.ts"], + "#modifiers/*": ["./src/modifier/*.ts"], + "#moves/*": ["./src/data/moves/*.ts"], + "#mystery-encounters/*": [ + "./src/data/mystery-encounters/utils/*.ts", + "./src/data/mystery-encounters/encounters/*.ts", + "./src/data/mystery-encounters/requirements/*.ts", + "./src/data/mystery-encounters/*.ts" + ], + "#package.json": ["./package.json"], + "#phases/*": ["./src/phases/*.ts"], + "#plugins/*": ["./src/plugins/vite/*.ts", "./src/plugins/*.ts"], + "#sprites/*": ["./src/sprites/*.ts"], + "#system/*": [ + "./src/system/settings/*.ts", + "./src/system/version-migration/versions/*.ts", + "./src/system/version-migration/*.ts", + "./src/system/*.ts" + ], + "#trainers/*": ["./src/data/trainers/*.ts"], + "#types/*": ["./src/@types/helpers/*.ts", "./src/@types/*.ts", "./src/typings/phaser/*.ts"], + "#ui/*": ["./src/ui/battle-info/*.ts", "./src/ui/settings/*.ts", "./src/ui/*.ts"], + "#utils/*": ["./src/utils/*.ts"], + "#data/*": ["./src/data/pokemon-forms/*.ts", "./src/data/pokemon/*.ts", "./src/data/*.ts"], + "#test/*": ["./test/*.ts"], + "#app/*": ["./src/*.ts"], + "#scripts/*": ["./scripts/*.ts"] + } }, - "exclude": ["node_modules", "dist", "vite.config.ts", "vitest.config.ts", "vitest.workspace.ts"] + "exclude": ["scripts", "node_modules", "dist", "vite.config.ts", "vitest.config.ts", "vitest.workspace.ts"] } From 0c3782172b1ad364cff09635a6de636e00cc012d Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Tue, 12 Aug 2025 10:26:11 -0400 Subject: [PATCH 07/19] Fixed up configs so that script folder has its own file --- biome.jsonc | 8 ++++---- scripts/biome.jsonc | 38 ++++++++++++++++++++++++++++++++++++++ scripts/jsconfig.json | 12 ++++++++++++ tsconfig.json | 7 +++---- 4 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 scripts/biome.jsonc create mode 100644 scripts/jsconfig.json diff --git a/biome.jsonc b/biome.jsonc index 35a458d2933..d4cb67d33a6 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -19,6 +19,7 @@ // and having to verify whether each individual file is ignored "includes": [ "**", + "!**/*.d.ts", "!**/dist/**/*", "!**/build/**/*", "!**/coverage/**/*", @@ -176,10 +177,9 @@ } }, - // Overrides to prevent unused import removal inside `overrides.ts` and enums files (for TSDoc linkcodes), - // as well as in all boilerplate files + // Overrides to prevent unused import removal inside `overrides.ts` and enums files (for TSDoc linkcodes) { - "includes": ["**/src/overrides.ts", "**/src/enums/**/*", "**/*.boilerplate.ts", "**/*.d.ts"], + "includes": ["**/src/overrides.ts", "**/src/enums/**/*"], "linter": { "rules": { "correctness": { @@ -189,7 +189,7 @@ } }, { - "includes": ["**/src/overrides.ts", "**/scripts/**/*.ts"], + "includes": ["**/src/overrides.ts"], "linter": { "rules": { "style": { diff --git a/scripts/biome.jsonc b/scripts/biome.jsonc new file mode 100644 index 00000000000..848e2a87184 --- /dev/null +++ b/scripts/biome.jsonc @@ -0,0 +1,38 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.0.0/schema.json", + // extend from base config in root dir + "extends": "//", + "files": { + "includes": ["**/*.{js,ts,jsx,tsx}"] + }, + "linter": { + "rules": { + "style": { + // Unfortunately, TS does not support multiple configs, so we need to have Biome pull the slack + // and effectively enforce `noErasableSyntax` + "noEnum": "error", + "noNamespace": "error", + "noNonNullAssertion": "error", // TODO: Remove once added to main config + "useForOf": "error" // TODO: Move to main config + }, + "suspicious": { + "noImplicitAnyLet": "error" + } + } + }, + "overrides": [ + // Prevent unused import removal inside boilerplate files. + // These are unused in the file themselves, but will become used once copied and converted to actual TS files. + // (If not, the generated files will themselves produce errors.) + { + "includes": ["**/*.boilerplate.ts", "**/boilerplates/*.ts"], // TODO: Rename existing boilerplates in the folder and remove this 2nd alias + "linter": { + "rules": { + "correctness": { + "noUnusedImports": "off" + } + } + } + } + ] +} diff --git a/scripts/jsconfig.json b/scripts/jsconfig.json new file mode 100644 index 00000000000..34a18a515e7 --- /dev/null +++ b/scripts/jsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../tsconfig", + "include": ["**/*.{js,jsx}"], + "compilerOptions": { + "checkJs": true, + "target": "esnext", + "module": "nodenext", + "moduleResolution": "nodenext", + "erasableSyntaxOnly": true, + "strict": true + } +} diff --git a/tsconfig.json b/tsconfig.json index 9b6a912bac7..0338c306d49 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,7 +18,6 @@ "esModuleInterop": true, "strictNullChecks": true, "sourceMap": false, - "checkJs": true, "strict": false, // TODO: Enable this eventually "rootDir": ".", "outDir": "./build", @@ -55,9 +54,9 @@ "#utils/*": ["./src/utils/*.ts"], "#data/*": ["./src/data/pokemon-forms/*.ts", "./src/data/pokemon/*.ts", "./src/data/*.ts"], "#test/*": ["./test/*.ts"], - "#app/*": ["./src/*.ts"], - "#scripts/*": ["./scripts/*.ts"] + "#app/*": ["./src/*.ts"] } }, - "exclude": ["scripts", "node_modules", "dist", "vite.config.ts", "vitest.config.ts", "vitest.workspace.ts"] + "include": ["**/*.{ts,tsx}"], + "exclude": ["node_modules", "dist", "vite.config.ts", "vitest.config.ts", "vitest.workspace.ts"] } From e2218613930979e08252655a0385d45734f327c6 Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Tue, 12 Aug 2025 10:42:28 -0400 Subject: [PATCH 08/19] Reverted changes to egg move contents --- src/data/balance/egg-moves.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/data/balance/egg-moves.ts b/src/data/balance/egg-moves.ts index 6831f035515..c5d2397ca1b 100644 --- a/src/data/balance/egg-moves.ts +++ b/src/data/balance/egg-moves.ts @@ -18,7 +18,7 @@ export const speciesEggMoves = { [SpeciesId.SPEAROW]: [ MoveId.FLOATY_FALL, MoveId.EXTREME_SPEED, MoveId.KNOCK_OFF, MoveId.TRIPLE_ARROWS ], [SpeciesId.EKANS]: [ MoveId.NOXIOUS_TORQUE, MoveId.DRAGON_DANCE, MoveId.SLACK_OFF, MoveId.SHED_TAIL ], [SpeciesId.SANDSHREW]: [ MoveId.HIGH_HORSEPOWER, MoveId.DIRE_CLAW, MoveId.SHORE_UP, MoveId.MIGHTY_CLEAVE ], - [SpeciesId.NIDORAN_F]: [ MoveId.BANEFUL_BUNKER, MoveId.MOONLIGHT, MoveId.BARB_BARRAGE, MoveId.THOUSAND_WAVES ], + [SpeciesId.NIDORAN_F]: [ MoveId.CALM_MIND, MoveId.MOONLIGHT, MoveId.MALIGNANT_CHAIN, MoveId.SANDSEAR_STORM ], [SpeciesId.NIDORAN_M]: [ MoveId.DRAGON_DANCE, MoveId.MOUNTAIN_GALE, MoveId.NOXIOUS_TORQUE, MoveId.PRECIPICE_BLADES ], [SpeciesId.VULPIX]: [ MoveId.MOONBLAST, MoveId.INFERNAL_PARADE, MoveId.MORNING_SUN, MoveId.TAIL_GLOW ], [SpeciesId.ZUBAT]: [ MoveId.FLOATY_FALL, MoveId.DIRE_CLAW, MoveId.SWORDS_DANCE, MoveId.COLLISION_COURSE ], @@ -296,7 +296,7 @@ export const speciesEggMoves = { [SpeciesId.ARCHEN]: [ MoveId.ROOST, MoveId.EARTHQUAKE, MoveId.FLOATY_FALL, MoveId.MIGHTY_CLEAVE ], [SpeciesId.TRUBBISH]: [ MoveId.COIL, MoveId.RECOVER, MoveId.DIRE_CLAW, MoveId.GIGATON_HAMMER ], [SpeciesId.ZORUA]: [ MoveId.MALIGNANT_CHAIN, MoveId.MOONBLAST, MoveId.SECRET_SWORD, MoveId.FIERY_WRATH ], - [SpeciesId.MINCCINO]: [ MoveId.ICICLE_SPEAR, MoveId.TIDY_UP, MoveId.LOW_KICK, MoveId.POPULATION_BOMB ], + [SpeciesId.MINCCINO]: [ MoveId.ICICLE_SPEAR, MoveId.TIDY_UP, MoveId.KNOCK_OFF, MoveId.POPULATION_BOMB ], [SpeciesId.GOTHITA]: [ MoveId.RECOVER, MoveId.MOONBLAST, MoveId.AURA_SPHERE, MoveId.LUMINA_CRASH ], [SpeciesId.SOLOSIS]: [ MoveId.MIST_BALL, MoveId.SPEED_SWAP, MoveId.FLAMETHROWER, MoveId.LIGHT_OF_RUIN ], [SpeciesId.DUCKLETT]: [ MoveId.SPLISHY_SPLASH, MoveId.SANDSEAR_STORM, MoveId.WILDBOLT_STORM, MoveId.QUIVER_DANCE ], @@ -313,7 +313,7 @@ export const speciesEggMoves = { [SpeciesId.TYNAMO]: [ MoveId.SCALD, MoveId.STRENGTH_SAP, MoveId.FIRE_LASH, MoveId.AURA_WHEEL ], [SpeciesId.ELGYEM]: [ MoveId.THUNDERCLAP, MoveId.BADDY_BAD, MoveId.AURA_SPHERE, MoveId.PHOTON_GEYSER ], [SpeciesId.LITWICK]: [ MoveId.GIGA_DRAIN, MoveId.EARTH_POWER, MoveId.MOONBLAST, MoveId.TORCH_SONG ], - [SpeciesId.AXEW]: [ MoveId.STONE_AXE, MoveId.DIRE_CLAW, MoveId.RAGING_FURY, MoveId.BITTER_BLADE ], + [SpeciesId.AXEW]: [ MoveId.STONE_AXE, MoveId.DIRE_CLAW, MoveId.BITTER_BLADE, MoveId.GLAIVE_RUSH ], [SpeciesId.CUBCHOO]: [ MoveId.MOUNTAIN_GALE, MoveId.AQUA_STEP, MoveId.ICE_SHARD, MoveId.COLLISION_COURSE ], [SpeciesId.CRYOGONAL]: [ MoveId.FREEZING_GLARE, MoveId.AURORA_VEIL, MoveId.NASTY_PLOT, MoveId.ORIGIN_PULSE ], [SpeciesId.SHELMET]: [ MoveId.POWER_GEM, MoveId.NASTY_PLOT, MoveId.EARTH_POWER, MoveId.STEAM_ERUPTION ], @@ -451,7 +451,7 @@ export const speciesEggMoves = { [SpeciesId.ROOKIDEE]: [ MoveId.ROOST, MoveId.BODY_PRESS, MoveId.KINGS_SHIELD, MoveId.BEHEMOTH_BASH ], [SpeciesId.BLIPBUG]: [ MoveId.HEAL_ORDER, MoveId.LUSTER_PURGE, MoveId.SLEEP_POWDER, MoveId.TAIL_GLOW ], [SpeciesId.NICKIT]: [ MoveId.BADDY_BAD, MoveId.MYSTICAL_FIRE, MoveId.SPARKLY_SWIRL, MoveId.MAKE_IT_RAIN ], - [SpeciesId.GOSSIFLEUR]: [ MoveId.BATON_PASS, MoveId.TAILWIND, MoveId.SAPPY_SEED, MoveId.SPORE ], + [SpeciesId.GOSSIFLEUR]: [ MoveId.PARTING_SHOT, MoveId.STRENGTH_SAP, MoveId.SAPPY_SEED, MoveId.SEED_FLARE ], [SpeciesId.WOOLOO]: [ MoveId.NUZZLE, MoveId.MILK_DRINK, MoveId.BODY_PRESS, MoveId.MULTI_ATTACK ], [SpeciesId.CHEWTLE]: [ MoveId.ICE_FANG, MoveId.PSYCHIC_FANGS, MoveId.SHELL_SMASH, MoveId.MIGHTY_CLEAVE ], [SpeciesId.YAMPER]: [ MoveId.ICE_FANG, MoveId.SWORDS_DANCE, MoveId.THUNDER_FANG, MoveId.BOLT_STRIKE ], @@ -517,7 +517,7 @@ export const speciesEggMoves = { [SpeciesId.TAROUNTULA]: [ MoveId.STONE_AXE, MoveId.LEECH_LIFE, MoveId.FAKE_OUT, MoveId.SPORE ], [SpeciesId.NYMBLE]: [ MoveId.KNOCK_OFF, MoveId.FELL_STINGER, MoveId.ATTACK_ORDER, MoveId.WICKED_BLOW ], [SpeciesId.PAWMI]: [ MoveId.DRAIN_PUNCH, MoveId.METEOR_MASH, MoveId.JET_PUNCH, MoveId.PLASMA_FISTS ], - [SpeciesId.TANDEMAUS]: [ MoveId.BATON_PASS, MoveId.FAKE_OUT, MoveId.POWER_UP_PUNCH, MoveId.REVIVAL_BLESSING ], + [SpeciesId.TANDEMAUS]: [ MoveId.BATON_PASS, MoveId.COVET, MoveId.SIZZLY_SLIDE, MoveId.REVIVAL_BLESSING ], [SpeciesId.FIDOUGH]: [ MoveId.SOFT_BOILED, MoveId.HIGH_HORSEPOWER, MoveId.SIZZLY_SLIDE, MoveId.TIDY_UP ], [SpeciesId.SMOLIV]: [ MoveId.STRENGTH_SAP, MoveId.EARTH_POWER, MoveId.CALM_MIND, MoveId.BOOMBURST ], [SpeciesId.SQUAWKABILLY]: [ MoveId.PARTING_SHOT, MoveId.EARTHQUAKE, MoveId.FLARE_BLITZ, MoveId.EXTREME_SPEED ], From bba141b6ec17a0ede990b3e9e59b916343564fc1 Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Tue, 12 Aug 2025 10:49:03 -0400 Subject: [PATCH 09/19] renamed boilerplate so biome doesn't lint it --- .../{egg-move-template.ts => egg-move-template.boilerplate.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/parse-egg-moves/{egg-move-template.ts => egg-move-template.boilerplate.ts} (100%) diff --git a/scripts/parse-egg-moves/egg-move-template.ts b/scripts/parse-egg-moves/egg-move-template.boilerplate.ts similarity index 100% rename from scripts/parse-egg-moves/egg-move-template.ts rename to scripts/parse-egg-moves/egg-move-template.boilerplate.ts From ca2c080994edbee60119a4f456ae4a196a40456f Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Tue, 12 Aug 2025 16:02:20 -0400 Subject: [PATCH 10/19] Fix `jsconfig.json` so that it doesn't typecheck all of `node_modules` See https://github.com/microsoft/TypeScript/issues/50862#issuecomment-1565175938 for more info --- .github/workflows/github-pages.yml | 7 ++++ biome.jsonc | 6 ++- package.json | 2 + pnpm-lock.yaml | 8 ++++ scripts/biome.jsonc | 38 ------------------- scripts/create-test/create-test.js | 2 +- scripts/decrypt-save.js | 18 +++++++-- scripts/jsconfig.json | 11 ++++-- scripts/parse-egg-moves/help-message.js | 1 + scripts/parse-egg-moves/main.js | 8 +++- scripts/parse-egg-moves/parse.js | 26 +++++++++++-- .../helpers/challenge-mode-helper.ts | 2 +- tsconfig.json | 3 +- 13 files changed, 78 insertions(+), 54 deletions(-) delete mode 100644 scripts/biome.jsonc diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml index 1588a15afeb..1aa04d67007 100644 --- a/.github/workflows/github-pages.yml +++ b/.github/workflows/github-pages.yml @@ -62,8 +62,15 @@ jobs: working-directory: ${{env.api-dir}} run: | cd pokerogue_docs + pnpm typedoc pnpm exec typedoc --out /tmp/docs --githubPages false --entryPoints ./src/ + - name: Typecheck Node.js Scripts + working-directory: ${{env.api-dir}} + run: | + cd pokerogue_docs + pnpm typecheck:scripts + - name: Commit & Push docs if: github.event_name == 'push' run: | diff --git a/biome.jsonc b/biome.jsonc index d4cb67d33a6..86b508e6a3c 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -177,9 +177,11 @@ } }, - // Overrides to prevent unused import removal inside `overrides.ts` and enums files (for TSDoc linkcodes) + // Overrides to prevent unused import removal inside `overrides.ts` and enums files (for TSDoc linkcodes), + // as well as inside script boilerplate files. { - "includes": ["**/src/overrides.ts", "**/src/enums/**/*"], + // TODO: Rename existing boilerplates in the folder and remove this last alias + "includes": ["**/src/overrides.ts", "**/src/enums/**/*", "scripts/**/*.boilerplate.ts", "**/boilerplates/*.ts"], "linter": { "rules": { "correctness": { diff --git a/package.json b/package.json index 87ba8309c97..135270d58fa 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "test:create": "node scripts/create-test/create-test.js", "eggMoves:parse": "node scripts/parse-egg-moves/main.js", "typecheck": "tsc --noEmit", + "typecheck:scripts": "tsc -p scripts/jsconfig.json", "eslint": "eslint --fix .", "eslint-ci": "eslint .", "biome": "biome check --write --changed --no-errors-on-unmatched --diagnostic-level=error", @@ -30,6 +31,7 @@ "devDependencies": { "@biomejs/biome": "2.0.0", "@ls-lint/ls-lint": "2.3.1", + "@types/crypto-js": "^4.2.2", "@types/jsdom": "^21.1.7", "@types/node": "^22.16.5", "@vitest/coverage-istanbul": "^3.2.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 900be6fd76e..4611e3bdbf1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,6 +48,9 @@ importers: '@ls-lint/ls-lint': specifier: 2.3.1 version: 2.3.1 + '@types/crypto-js': + specifier: ^4.2.2 + version: 4.2.2 '@types/jsdom': specifier: ^21.1.7 version: 21.1.7 @@ -718,6 +721,9 @@ packages: '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/crypto-js@4.2.2': + resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} + '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} @@ -2525,6 +2531,8 @@ snapshots: '@types/cookie@0.6.0': {} + '@types/crypto-js@4.2.2': {} + '@types/deep-eql@4.0.2': {} '@types/estree@1.0.8': {} diff --git a/scripts/biome.jsonc b/scripts/biome.jsonc deleted file mode 100644 index 848e2a87184..00000000000 --- a/scripts/biome.jsonc +++ /dev/null @@ -1,38 +0,0 @@ -{ - "$schema": "https://biomejs.dev/schemas/2.0.0/schema.json", - // extend from base config in root dir - "extends": "//", - "files": { - "includes": ["**/*.{js,ts,jsx,tsx}"] - }, - "linter": { - "rules": { - "style": { - // Unfortunately, TS does not support multiple configs, so we need to have Biome pull the slack - // and effectively enforce `noErasableSyntax` - "noEnum": "error", - "noNamespace": "error", - "noNonNullAssertion": "error", // TODO: Remove once added to main config - "useForOf": "error" // TODO: Move to main config - }, - "suspicious": { - "noImplicitAnyLet": "error" - } - } - }, - "overrides": [ - // Prevent unused import removal inside boilerplate files. - // These are unused in the file themselves, but will become used once copied and converted to actual TS files. - // (If not, the generated files will themselves produce errors.) - { - "includes": ["**/*.boilerplate.ts", "**/boilerplates/*.ts"], // TODO: Rename existing boilerplates in the folder and remove this 2nd alias - "linter": { - "rules": { - "correctness": { - "noUnusedImports": "off" - } - } - } - } - ] -} diff --git a/scripts/create-test/create-test.js b/scripts/create-test/create-test.js index 765993959d1..5e395783da7 100644 --- a/scripts/create-test/create-test.js +++ b/scripts/create-test/create-test.js @@ -156,7 +156,7 @@ async function runInteractive() { console.log(chalk.green.bold(`āœ” File created at: test/${localDir}/${fileName}.test.ts\n`)); console.groupEnd(); } catch (err) { - console.error(chalk.red("āœ— Error: ", err.message)); + console.error(chalk.red("āœ— Error: ", err)); } } diff --git a/scripts/decrypt-save.js b/scripts/decrypt-save.js index e50f152f159..bb08c58e2b7 100644 --- a/scripts/decrypt-save.js +++ b/scripts/decrypt-save.js @@ -1,7 +1,6 @@ // Usage: node decrypt-save.js [save-file] -// biome-ignore lint/performance/noNamespaceImport: This is how you import fs from node -import * as fs from "node:fs"; +import fs from "node:fs"; import crypto_js from "crypto-js"; const { AES, enc } = crypto_js; @@ -60,6 +59,11 @@ function decryptSave(path) { try { fileData = fs.readFileSync(path, "utf8"); } catch (e) { + if (!(e instanceof Error)) { + console.error(`Unrecognized error: ${e}`); + process.exit(1); + } + // @ts-expect-error: TODO fix switch (e.code) { case "ENOENT": console.error(`File not found: ${path}`); @@ -104,6 +108,13 @@ function writeToFile(filePath, data) { try { fs.writeFileSync(filePath, data); } catch (e) { + if (!(e instanceof Error)) { + console.error("Unknown error detected: ", e); + process.exitCode = 1; + return; + } + + // @ts-expect-error - e is usually a SystemError (all of which have codes) switch (e.code) { case "EACCES": console.error(`Could not open ${filePath}: Permission denied`); @@ -114,7 +125,8 @@ function writeToFile(filePath, data) { default: console.error(`Error writing file: ${e.message}`); } - process.exit(1); + process.exitCode = 1; + return; } } diff --git a/scripts/jsconfig.json b/scripts/jsconfig.json index 34a18a515e7..aed71f4f576 100644 --- a/scripts/jsconfig.json +++ b/scripts/jsconfig.json @@ -1,12 +1,17 @@ { - "extends": "../tsconfig", - "include": ["**/*.{js,jsx}"], + "include": ["**/*.js"], "compilerOptions": { + "allowJs": true, "checkJs": true, + "rootDir": ".", "target": "esnext", "module": "nodenext", "moduleResolution": "nodenext", "erasableSyntaxOnly": true, - "strict": true + "strict": true, + "noEmit": true, + // Forcibly disable `node_modules` recursion to prevent TSC from typechecking random JS files. + // This is disabled by default in `tsconfig.json`, but needs to be explicitly disabled from the default of `2` + "maxNodeModuleJsDepth": 0 } } diff --git a/scripts/parse-egg-moves/help-message.js b/scripts/parse-egg-moves/help-message.js index 6b5f1965a2b..397a28e5011 100644 --- a/scripts/parse-egg-moves/help-message.js +++ b/scripts/parse-egg-moves/help-message.js @@ -1,5 +1,6 @@ import chalk from "chalk"; +/** Show help/usage text for the `eggMoves:parse` CLI. */ export function showHelpText() { console.log(` Usage: ${chalk.cyan("pnpm eggMoves:parse [options]")} diff --git a/scripts/parse-egg-moves/main.js b/scripts/parse-egg-moves/main.js index 1ab0e30bda0..a009c81a041 100644 --- a/scripts/parse-egg-moves/main.js +++ b/scripts/parse-egg-moves/main.js @@ -23,6 +23,12 @@ const templatePath = path.join(__dirname, "egg-move-template.ts"); // TODO: Do we want this to be configurable? const eggMoveTargetPath = path.join(projectRoot, "src/data/balance/egg-moves.ts"); +/** + * @typedef {{type: "Console" | "File", value: string} | {type: "Exit"}} + * Option + * An option selected by the user. + */ + /** * Runs the interactive eggMoves:parse CLI. * @returns {Promise} @@ -144,7 +150,7 @@ export async function writeToFile(moves) { console.log(chalk.green.bold(`\nāœ” Egg Moves written to ${eggMoveTargetPath}`)); console.groupEnd(); } catch (err) { - console.error(chalk.red("āœ— Error while writing egg moves!", err.message)); + console.error(chalk.red(`āœ— Error while writing egg moves: ${err}`)); process.exitCode = 1; } } diff --git a/scripts/parse-egg-moves/parse.js b/scripts/parse-egg-moves/parse.js index 209a350df42..fe7511f8b08 100644 --- a/scripts/parse-egg-moves/parse.js +++ b/scripts/parse-egg-moves/parse.js @@ -1,5 +1,16 @@ import chalk from "chalk"; +/** + * A single line of the inputted CSV. + * @typedef {[speciesName: string, move1: string, move2: string, move3: string, move4: string]} + * CSVLine + */ + +/** + * Regex to determine if a string follows the required CSV format. + */ +const csvRegex = /^((?:[^,]+?,){4}(?:\w|\s)+?,?\n?)+$/g; + /** * Given a CSV string, parse it and return a structured table ready to be inputted into code. * @param {string} csv - The formatted CSV string. @@ -7,6 +18,12 @@ import chalk from "chalk"; */ export function parseEggMoves(csv) { console.log(chalk.grey("āš™ļø Parsing egg moves...")); + if (!csvRegex.test(csv)) { + console.error(chalk.redBright("! Input was not proper CSV!")); + process.exitCode = 1; + return ""; + } + let output = "{\n"; const lines = csv.split(/\n/g); @@ -16,16 +33,17 @@ export function parseEggMoves(csv) { * The individual CSV column for this species. */ const cols = - /** @type {[speciesName: string, move1: string, move2: string, move3: string, move4: string]} */ + /** @type {CSVLine} */ (line.split(",").slice(0, 5)); const speciesName = toUpperSnakeCase(cols[0]); - /** @type {string[]} */ - const eggMoves = []; + const eggMoves = + /** @type {string[]} */ + ([]); for (let m = 1; m < 5; m++) { const moveName = cols[m].trim(); - if (moveName === "N/A") { + if (!moveName || moveName === "N/A") { console.warn(`Species ${speciesName} missing ${m}th egg move!`); eggMoves.push("MoveId.NONE"); continue; diff --git a/test/test-utils/helpers/challenge-mode-helper.ts b/test/test-utils/helpers/challenge-mode-helper.ts index 3952685a560..561d9e4a875 100644 --- a/test/test-utils/helpers/challenge-mode-helper.ts +++ b/test/test-utils/helpers/challenge-mode-helper.ts @@ -1,5 +1,6 @@ import overrides from "#app/overrides"; import type { Challenge } from "#data/challenge"; +import { copyChallenge } from "#data/challenge"; import { BattleStyle } from "#enums/battle-style"; import type { Challenges } from "#enums/challenges"; import type { SpeciesId } from "#enums/species-id"; @@ -10,7 +11,6 @@ import { SelectStarterPhase } from "#phases/select-starter-phase"; import { TurnInitPhase } from "#phases/turn-init-phase"; import { generateStarter } from "#test/test-utils/game-manager-utils"; import { GameManagerHelper } from "#test/test-utils/helpers/game-manager-helper"; -import { copyChallenge } from "data/challenge"; /** * Helper to handle Challenge mode specifics diff --git a/tsconfig.json b/tsconfig.json index 0338c306d49..0015212eac0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -57,6 +57,7 @@ "#app/*": ["./src/*.ts"] } }, - "include": ["**/*.{ts,tsx}"], + // Exclude checking for script JS files as those are covered by the folder's `jsconfig/json` + "include": ["**/*.ts", "**/*.d.ts"], "exclude": ["node_modules", "dist", "vite.config.ts", "vitest.config.ts", "vitest.workspace.ts"] } From 65e8e4062613e420dafd358973490719a3c78093 Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Sat, 16 Aug 2025 18:13:35 -0400 Subject: [PATCH 11/19] Update tsconfig.json Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 0015212eac0..1b212c49bcf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -57,7 +57,7 @@ "#app/*": ["./src/*.ts"] } }, - // Exclude checking for script JS files as those are covered by the folder's `jsconfig/json` + // Exclude checking for script JS files as those are covered by the folder's `jsconfig.json` "include": ["**/*.ts", "**/*.d.ts"], "exclude": ["node_modules", "dist", "vite.config.ts", "vitest.config.ts", "vitest.workspace.ts"] } From 7ea48b0fa2d899eb89d60289d2be55d0bedc8b3b Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Sat, 16 Aug 2025 18:56:34 -0400 Subject: [PATCH 12/19] Updated workflows and fixed issues --- .github/test-filters.yml | 2 + .github/workflows/github-pages.yml | 7 --- .github/workflows/linting.yml | 84 ++++++++++++++++++++++++++---- src/data/balance/egg-moves.ts | 10 ++-- 4 files changed, 80 insertions(+), 23 deletions(-) diff --git a/.github/test-filters.yml b/.github/test-filters.yml index fc52e85082c..796432679e1 100644 --- a/.github/test-filters.yml +++ b/.github/test-filters.yml @@ -3,6 +3,7 @@ all: - "src/**/!(*.{md,py,sh,gitkeep,gitignore})" - "test/**/!(*.{md,py,sh,gitkeep,gitignore})" - "public/**/!(*.{md,py,sh,gitkeep,gitignore})" + - "scripts/**/!(*.{md,py,sh,gitkeep,gitignore})" # Workflows that can impact tests - ".github/workflows/test*.yml" - ".github/test-filters.yml" @@ -11,5 +12,6 @@ all: - ".nvrmc" # Updates to node version can break tests - "vite*" # vite.config.ts, vite.vitest.config.ts, vitest.workspace.ts - "tsconfig*.json" # tsconfig.json tweaking can impact compilation + - "jsconfig*.json" # jsconfig.json tweaking can impact compilation - "global.d.ts" - ".env*" \ No newline at end of file diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml index 1aa04d67007..1588a15afeb 100644 --- a/.github/workflows/github-pages.yml +++ b/.github/workflows/github-pages.yml @@ -62,15 +62,8 @@ jobs: working-directory: ${{env.api-dir}} run: | cd pokerogue_docs - pnpm typedoc pnpm exec typedoc --out /tmp/docs --githubPages false --entryPoints ./src/ - - name: Typecheck Node.js Scripts - working-directory: ${{env.api-dir}} - run: | - cd pokerogue_docs - pnpm typecheck:scripts - - name: Commit & Push docs if: github.event_name == 'push' run: | diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 82f5abd23a1..87859879710 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -14,34 +14,96 @@ on: jobs: run-linters: - name: Run linters + name: Run all linters runs-on: ubuntu-latest steps: - name: Check out Git repository uses: actions/checkout@v4 with: - submodules: 'recursive' + submodules: "recursive" - name: Install pnpm uses: pnpm/action-setup@v4 with: version: 10 - - name: Set up Node.js + - name: Set up Node uses: actions/setup-node@v4 with: - node-version-file: '.nvmrc' - cache: 'pnpm' + node-version-file: ".nvmrc" + cache: "pnpm" - - name: Install Node.js dependencies + - name: Install Node modules run: pnpm i - - name: Lint with Biome + # Lint files with Biome-Lint - https://biomejs.dev/linter/ + - name: Run Biome-Lint run: pnpm biome-ci + id: biome_lint + continue-on-error: true - - name: Check dependencies with depcruise + # Validate dependencies with dependency-cruiser - https://github.com/sverweij/dependency-cruiser + - name: Run Dependency-Cruise run: pnpm depcruise - - - name: Lint with ls-lint - run: pnpm ls-lint \ No newline at end of file + id: depcruise + continue-on-error: true + + # Validate types with tsc - https://www.typescriptlang.org/docs/handbook/compiler-options.html#using-the-cli + - name: Run Typecheck + run: pnpm typecheck + id: typecheck + continue-on-error: true + + # The exact same thing + - name: Run Typecheck (scripts) + run: pnpm typecheck:scripts + id: typecheck-scripts + continue-on-error: true + + - name: Evaluate for Errors + env: + BIOME_LINT_OUTCOME: ${{ steps.biome_lint.outcome }} + ESLINT_OUTCOME: ${{ steps.eslint.outcome }} + DEPCRUISE_OUTCOME: ${{ steps.depcruise.outcome }} + TYPECHECK_OUTCOME: ${{ steps.typecheck.outcome }} + TYPECHECK_SCRIPTS_OUTCOME: ${{ steps.typecheck-scripts.outcome }} + run: | + # Check for Errors + + # Make text red. + red () { + printf "\e[31m%s\e[0m" "$1" + } + + # Make text green. + green () { + printf "\e[32m%s\e[0m" "$1" + } + + print_result() { + local name=$1 + local outcome=$2 + if [ "$outcome" == "success" ]; then + printf "$(green "āœ… $name: $outcome")\n" + else + printf "$(red "āŒ $name: $outcome")\n" + fi + } + + print_result "Biome" "$BIOME_LINT_OUTCOME" + print_result "ESLint" "$ESLINT_OUTCOME" + print_result "Depcruise" "$DEPCRUISE_OUTCOME" + print_result "Typecheck" "$TYPECHECK_OUTCOME" + print_result "Typecheck scripts" "$TYPECHECK_SCRIPTS_OUTCOME" + + if [[ "$BIOME_LINT_OUTCOME" != "success" || \ + "$ESLINT_OUTCOME" != "success" || \ + "$DEPCRUISE_OUTCOME" != "success" || \ + "$TYPECHECK_OUTCOME" != "success" || \ + "$TYPECHECK_SCRIPTS_OUTCOME" != "success" ]]; then + printf "$(red "āŒ One or more checks failed!")\n" >&2 + exit 1 + fi + + printf "$(green "āœ… All checks passed!")\n" \ No newline at end of file diff --git a/src/data/balance/egg-moves.ts b/src/data/balance/egg-moves.ts index c5d2397ca1b..6831f035515 100644 --- a/src/data/balance/egg-moves.ts +++ b/src/data/balance/egg-moves.ts @@ -18,7 +18,7 @@ export const speciesEggMoves = { [SpeciesId.SPEAROW]: [ MoveId.FLOATY_FALL, MoveId.EXTREME_SPEED, MoveId.KNOCK_OFF, MoveId.TRIPLE_ARROWS ], [SpeciesId.EKANS]: [ MoveId.NOXIOUS_TORQUE, MoveId.DRAGON_DANCE, MoveId.SLACK_OFF, MoveId.SHED_TAIL ], [SpeciesId.SANDSHREW]: [ MoveId.HIGH_HORSEPOWER, MoveId.DIRE_CLAW, MoveId.SHORE_UP, MoveId.MIGHTY_CLEAVE ], - [SpeciesId.NIDORAN_F]: [ MoveId.CALM_MIND, MoveId.MOONLIGHT, MoveId.MALIGNANT_CHAIN, MoveId.SANDSEAR_STORM ], + [SpeciesId.NIDORAN_F]: [ MoveId.BANEFUL_BUNKER, MoveId.MOONLIGHT, MoveId.BARB_BARRAGE, MoveId.THOUSAND_WAVES ], [SpeciesId.NIDORAN_M]: [ MoveId.DRAGON_DANCE, MoveId.MOUNTAIN_GALE, MoveId.NOXIOUS_TORQUE, MoveId.PRECIPICE_BLADES ], [SpeciesId.VULPIX]: [ MoveId.MOONBLAST, MoveId.INFERNAL_PARADE, MoveId.MORNING_SUN, MoveId.TAIL_GLOW ], [SpeciesId.ZUBAT]: [ MoveId.FLOATY_FALL, MoveId.DIRE_CLAW, MoveId.SWORDS_DANCE, MoveId.COLLISION_COURSE ], @@ -296,7 +296,7 @@ export const speciesEggMoves = { [SpeciesId.ARCHEN]: [ MoveId.ROOST, MoveId.EARTHQUAKE, MoveId.FLOATY_FALL, MoveId.MIGHTY_CLEAVE ], [SpeciesId.TRUBBISH]: [ MoveId.COIL, MoveId.RECOVER, MoveId.DIRE_CLAW, MoveId.GIGATON_HAMMER ], [SpeciesId.ZORUA]: [ MoveId.MALIGNANT_CHAIN, MoveId.MOONBLAST, MoveId.SECRET_SWORD, MoveId.FIERY_WRATH ], - [SpeciesId.MINCCINO]: [ MoveId.ICICLE_SPEAR, MoveId.TIDY_UP, MoveId.KNOCK_OFF, MoveId.POPULATION_BOMB ], + [SpeciesId.MINCCINO]: [ MoveId.ICICLE_SPEAR, MoveId.TIDY_UP, MoveId.LOW_KICK, MoveId.POPULATION_BOMB ], [SpeciesId.GOTHITA]: [ MoveId.RECOVER, MoveId.MOONBLAST, MoveId.AURA_SPHERE, MoveId.LUMINA_CRASH ], [SpeciesId.SOLOSIS]: [ MoveId.MIST_BALL, MoveId.SPEED_SWAP, MoveId.FLAMETHROWER, MoveId.LIGHT_OF_RUIN ], [SpeciesId.DUCKLETT]: [ MoveId.SPLISHY_SPLASH, MoveId.SANDSEAR_STORM, MoveId.WILDBOLT_STORM, MoveId.QUIVER_DANCE ], @@ -313,7 +313,7 @@ export const speciesEggMoves = { [SpeciesId.TYNAMO]: [ MoveId.SCALD, MoveId.STRENGTH_SAP, MoveId.FIRE_LASH, MoveId.AURA_WHEEL ], [SpeciesId.ELGYEM]: [ MoveId.THUNDERCLAP, MoveId.BADDY_BAD, MoveId.AURA_SPHERE, MoveId.PHOTON_GEYSER ], [SpeciesId.LITWICK]: [ MoveId.GIGA_DRAIN, MoveId.EARTH_POWER, MoveId.MOONBLAST, MoveId.TORCH_SONG ], - [SpeciesId.AXEW]: [ MoveId.STONE_AXE, MoveId.DIRE_CLAW, MoveId.BITTER_BLADE, MoveId.GLAIVE_RUSH ], + [SpeciesId.AXEW]: [ MoveId.STONE_AXE, MoveId.DIRE_CLAW, MoveId.RAGING_FURY, MoveId.BITTER_BLADE ], [SpeciesId.CUBCHOO]: [ MoveId.MOUNTAIN_GALE, MoveId.AQUA_STEP, MoveId.ICE_SHARD, MoveId.COLLISION_COURSE ], [SpeciesId.CRYOGONAL]: [ MoveId.FREEZING_GLARE, MoveId.AURORA_VEIL, MoveId.NASTY_PLOT, MoveId.ORIGIN_PULSE ], [SpeciesId.SHELMET]: [ MoveId.POWER_GEM, MoveId.NASTY_PLOT, MoveId.EARTH_POWER, MoveId.STEAM_ERUPTION ], @@ -451,7 +451,7 @@ export const speciesEggMoves = { [SpeciesId.ROOKIDEE]: [ MoveId.ROOST, MoveId.BODY_PRESS, MoveId.KINGS_SHIELD, MoveId.BEHEMOTH_BASH ], [SpeciesId.BLIPBUG]: [ MoveId.HEAL_ORDER, MoveId.LUSTER_PURGE, MoveId.SLEEP_POWDER, MoveId.TAIL_GLOW ], [SpeciesId.NICKIT]: [ MoveId.BADDY_BAD, MoveId.MYSTICAL_FIRE, MoveId.SPARKLY_SWIRL, MoveId.MAKE_IT_RAIN ], - [SpeciesId.GOSSIFLEUR]: [ MoveId.PARTING_SHOT, MoveId.STRENGTH_SAP, MoveId.SAPPY_SEED, MoveId.SEED_FLARE ], + [SpeciesId.GOSSIFLEUR]: [ MoveId.BATON_PASS, MoveId.TAILWIND, MoveId.SAPPY_SEED, MoveId.SPORE ], [SpeciesId.WOOLOO]: [ MoveId.NUZZLE, MoveId.MILK_DRINK, MoveId.BODY_PRESS, MoveId.MULTI_ATTACK ], [SpeciesId.CHEWTLE]: [ MoveId.ICE_FANG, MoveId.PSYCHIC_FANGS, MoveId.SHELL_SMASH, MoveId.MIGHTY_CLEAVE ], [SpeciesId.YAMPER]: [ MoveId.ICE_FANG, MoveId.SWORDS_DANCE, MoveId.THUNDER_FANG, MoveId.BOLT_STRIKE ], @@ -517,7 +517,7 @@ export const speciesEggMoves = { [SpeciesId.TAROUNTULA]: [ MoveId.STONE_AXE, MoveId.LEECH_LIFE, MoveId.FAKE_OUT, MoveId.SPORE ], [SpeciesId.NYMBLE]: [ MoveId.KNOCK_OFF, MoveId.FELL_STINGER, MoveId.ATTACK_ORDER, MoveId.WICKED_BLOW ], [SpeciesId.PAWMI]: [ MoveId.DRAIN_PUNCH, MoveId.METEOR_MASH, MoveId.JET_PUNCH, MoveId.PLASMA_FISTS ], - [SpeciesId.TANDEMAUS]: [ MoveId.BATON_PASS, MoveId.COVET, MoveId.SIZZLY_SLIDE, MoveId.REVIVAL_BLESSING ], + [SpeciesId.TANDEMAUS]: [ MoveId.BATON_PASS, MoveId.FAKE_OUT, MoveId.POWER_UP_PUNCH, MoveId.REVIVAL_BLESSING ], [SpeciesId.FIDOUGH]: [ MoveId.SOFT_BOILED, MoveId.HIGH_HORSEPOWER, MoveId.SIZZLY_SLIDE, MoveId.TIDY_UP ], [SpeciesId.SMOLIV]: [ MoveId.STRENGTH_SAP, MoveId.EARTH_POWER, MoveId.CALM_MIND, MoveId.BOOMBURST ], [SpeciesId.SQUAWKABILLY]: [ MoveId.PARTING_SHOT, MoveId.EARTHQUAKE, MoveId.FLARE_BLITZ, MoveId.EXTREME_SPEED ], From b8fc7c4377c3db1c45ecc91e6bc6c025332aad3e Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Sun, 17 Aug 2025 22:43:13 -0400 Subject: [PATCH 13/19] Removed eslint from linting workflow --- .github/workflows/linting.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 87859879710..b6d47fd2020 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -64,7 +64,6 @@ jobs: - name: Evaluate for Errors env: BIOME_LINT_OUTCOME: ${{ steps.biome_lint.outcome }} - ESLINT_OUTCOME: ${{ steps.eslint.outcome }} DEPCRUISE_OUTCOME: ${{ steps.depcruise.outcome }} TYPECHECK_OUTCOME: ${{ steps.typecheck.outcome }} TYPECHECK_SCRIPTS_OUTCOME: ${{ steps.typecheck-scripts.outcome }} @@ -92,13 +91,11 @@ jobs: } print_result "Biome" "$BIOME_LINT_OUTCOME" - print_result "ESLint" "$ESLINT_OUTCOME" print_result "Depcruise" "$DEPCRUISE_OUTCOME" print_result "Typecheck" "$TYPECHECK_OUTCOME" print_result "Typecheck scripts" "$TYPECHECK_SCRIPTS_OUTCOME" if [[ "$BIOME_LINT_OUTCOME" != "success" || \ - "$ESLINT_OUTCOME" != "success" || \ "$DEPCRUISE_OUTCOME" != "success" || \ "$TYPECHECK_OUTCOME" != "success" || \ "$TYPECHECK_SCRIPTS_OUTCOME" != "success" ]]; then @@ -106,4 +103,4 @@ jobs: exit 1 fi - printf "$(green "āœ… All checks passed!")\n" \ No newline at end of file + printf "$(green "āœ… All checks passed!")\n" From e9b758414ce7dd0257085d236bc45fa41279e7ff Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Sun, 17 Aug 2025 22:50:43 -0400 Subject: [PATCH 14/19] Fixed type error in d.ts file to shut up linters --- test/@types/vitest.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/@types/vitest.d.ts b/test/@types/vitest.d.ts index 21cf76ed352..06cc0ecac0d 100644 --- a/test/@types/vitest.d.ts +++ b/test/@types/vitest.d.ts @@ -22,7 +22,7 @@ import type { expectedStatusType } from "#test/test-utils/matchers/to-have-statu import type { toHaveTypesOptions } from "#test/test-utils/matchers/to-have-types"; import type { TurnMove } from "#types/turn-move"; import type { AtLeastOne } from "#types/type-helpers"; -import type { toDmgValue } from "utils/common"; +import type { toDmgValue } from "#utils/common"; import type { expect } from "vitest"; declare module "vitest" { From 92f10275e3aedeb2be4ce67eee00a93b5cab845d Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Mon, 18 Aug 2025 09:23:42 -0400 Subject: [PATCH 15/19] Reverted test-filters.yml --- .github/test-filters.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/test-filters.yml b/.github/test-filters.yml index 796432679e1..fc52e85082c 100644 --- a/.github/test-filters.yml +++ b/.github/test-filters.yml @@ -3,7 +3,6 @@ all: - "src/**/!(*.{md,py,sh,gitkeep,gitignore})" - "test/**/!(*.{md,py,sh,gitkeep,gitignore})" - "public/**/!(*.{md,py,sh,gitkeep,gitignore})" - - "scripts/**/!(*.{md,py,sh,gitkeep,gitignore})" # Workflows that can impact tests - ".github/workflows/test*.yml" - ".github/test-filters.yml" @@ -12,6 +11,5 @@ all: - ".nvrmc" # Updates to node version can break tests - "vite*" # vite.config.ts, vite.vitest.config.ts, vitest.workspace.ts - "tsconfig*.json" # tsconfig.json tweaking can impact compilation - - "jsconfig*.json" # jsconfig.json tweaking can impact compilation - "global.d.ts" - ".env*" \ No newline at end of file From 73ba4de3fbc18eb2205c4f26c500db0b3caa8bea Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Mon, 18 Aug 2025 09:24:28 -0400 Subject: [PATCH 16/19] Update biome.jsonc --- biome.jsonc | 1 - 1 file changed, 1 deletion(-) diff --git a/biome.jsonc b/biome.jsonc index 900f772ef6f..5a6de48bd0a 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -19,7 +19,6 @@ // and having to verify whether each individual file is ignored "includes": [ "**", - "!**/*.d.ts", "!**/dist/**/*", "!**/build/**/*", "!**/coverage/**/*", From dea9bda49204e71df94650e3ab9a789db6aa98b5 Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Mon, 18 Aug 2025 09:25:39 -0400 Subject: [PATCH 17/19] Update decrypt-save.js comment --- scripts/decrypt-save.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/decrypt-save.js b/scripts/decrypt-save.js index bb08c58e2b7..26b0a311378 100644 --- a/scripts/decrypt-save.js +++ b/scripts/decrypt-save.js @@ -63,7 +63,7 @@ function decryptSave(path) { console.error(`Unrecognized error: ${e}`); process.exit(1); } - // @ts-expect-error: TODO fix + // @ts-expect-error - e is usually a SystemError (all of which have codes) switch (e.code) { case "ENOENT": console.error(`File not found: ${path}`); From fe20b3061e8159a3e27302043c65bf7b5e9d4a3b Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Mon, 18 Aug 2025 09:27:39 -0400 Subject: [PATCH 18/19] Update interactive.js --- scripts/parse-egg-moves/interactive.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/parse-egg-moves/interactive.js b/scripts/parse-egg-moves/interactive.js index 814957dc09a..bf88e70e7cf 100644 --- a/scripts/parse-egg-moves/interactive.js +++ b/scripts/parse-egg-moves/interactive.js @@ -3,9 +3,13 @@ import chalk from "chalk"; import inquirer from "inquirer"; import { showHelpText } from "./help-message.js"; +/** + * @import { Option } from "./main.js" + */ + /** * Prompt the user to interactively select an option (console/file) to retrieve the egg move CSV. - * @returns {Promise<{type: "Console" | "File", value: string} | {type: "Exit"}>} The selected option with value + * @returns {Promise