mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-12-14 05:45:20 +01:00
[Dev] Break up test:create script; add help message, file name CLI argument support (#6793)
* [Dev] Broke up `test:create` script, added CLI args file name suppoert * Moved `HELP_FLAGS` constant; fixed help msg indentation * ran biome * Fix floting promise err * Added REUSE info * Typo fix * comment out reward boilerplate * Removed redundant comments --------- Co-authored-by: fabske0 <192151969+fabske0@users.noreply.github.com>
This commit is contained in:
parent
4522e9e593
commit
3478e09923
10
biome.jsonc
10
biome.jsonc
@ -251,6 +251,16 @@
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"includes": ["**/scripts/**/*.js"],
|
||||
"linter": {
|
||||
"rules": {
|
||||
"nursery": {
|
||||
"noFloatingPromises": "error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"includes": ["**/test/**/*.test.ts"],
|
||||
"linter": {
|
||||
|
||||
80
scripts/create-test/cli.js
Normal file
80
scripts/create-test/cli.js
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Pagefault Games
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import chalk from "chalk";
|
||||
import { cliAliases, validTestTypes } from "./constants.js";
|
||||
import { promptFileName, promptTestType } from "./interactive.js";
|
||||
|
||||
/**
|
||||
* @import {testType} from "./constants.js"
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parse `process.argv` to retrieve the test type if it exists, otherwise prompting input from the user.
|
||||
* @param {string | undefined} arg - The argument from `process.argv`
|
||||
* @returns {Promise<testType | undefined>}
|
||||
* A Promise that resolves with the type of test to be created, or `undefined` if the user interactively selects "Exit".
|
||||
* Will set `process.exitCode` to a non-zero integer if args are invalid.
|
||||
*/
|
||||
export async function getTestType(arg) {
|
||||
if (arg == null) {
|
||||
return await promptTestType();
|
||||
}
|
||||
|
||||
const testType = getCliTestType(arg);
|
||||
if (testType) {
|
||||
console.log(chalk.blue(`Using ${testType} as test type from CLI...`));
|
||||
return testType;
|
||||
}
|
||||
console.error(
|
||||
chalk.red.bold(
|
||||
`✗ Invalid type of test file specified: ${arg}!\nValid types: ${chalk.blue(validTestTypes.join(", "))}`,
|
||||
),
|
||||
);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a test type from command-line args.
|
||||
* @param {string} arg
|
||||
* @returns {testType | undefined} The resulting test type.
|
||||
* Will return `undefined` if no valid match was found.
|
||||
*/
|
||||
function getCliTestType(arg) {
|
||||
// Check for a direct match, falling back to alias checking if none work
|
||||
const testTypeName = validTestTypes.find(c => c.toLowerCase() === arg.toLowerCase());
|
||||
if (testTypeName) {
|
||||
return testTypeName;
|
||||
}
|
||||
|
||||
const alias = /** @type {(keyof typeof cliAliases)[]} */ (Object.keys(cliAliases)).find(aliasKey =>
|
||||
cliAliases[aliasKey].some(alias => alias.toLowerCase() === arg.toLowerCase()),
|
||||
);
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the file name for a given file
|
||||
* @param {testType} testType - The chosen test type
|
||||
* @param {string | undefined} arg - The contents of `process.argv[3]`, if it exists
|
||||
* @returns {Promise<string | undefined>} A promise that resolves with the name of the file to create.
|
||||
*/
|
||||
export async function getFileName(testType, arg) {
|
||||
if (arg == null) {
|
||||
return await promptFileName(testType);
|
||||
}
|
||||
|
||||
const nameTrimmed = arg.trim().replace(".test.ts", "");
|
||||
if (nameTrimmed.length === 0) {
|
||||
console.error(chalk.red.bold("✗ Cannot use an empty string as a file name!"));
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(chalk.blue(`Using ${nameTrimmed} as file name from CLI...`));
|
||||
return nameTrimmed;
|
||||
}
|
||||
47
scripts/create-test/constants.js
Normal file
47
scripts/create-test/constants.js
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Pagefault Games
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
/**
|
||||
* Array containing all valid options for the type of test file to create.
|
||||
* @package
|
||||
*/
|
||||
export const validTestTypes = /** @type {const} */ ([
|
||||
"Move",
|
||||
"Ability",
|
||||
"Item",
|
||||
"Reward",
|
||||
"Mystery Encounter",
|
||||
"Utils",
|
||||
"UI",
|
||||
]);
|
||||
|
||||
/**
|
||||
* @typedef {typeof validTestTypes[number]}
|
||||
* testType
|
||||
* Union type representing a single valid choice of test type.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Const object mapping each test type to any additional names they can be used with from CLI.
|
||||
* @satisfies {Partial<Record<testType, readonly string[]>>}
|
||||
*/
|
||||
export const cliAliases = /** @type {const} */ ({
|
||||
"Mystery Encounter": ["ME"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Const object matching all test types to the directories in which their tests reside.
|
||||
* @satisfies {Record<testType, string>}
|
||||
*/
|
||||
export const testTypesToDirs = /** @type {const} */ ({
|
||||
Move: "moves",
|
||||
Ability: "abilities",
|
||||
Item: "items",
|
||||
Reward: "rewards",
|
||||
"Mystery Encounter": "mystery-encounter/encounters",
|
||||
Utils: "utils",
|
||||
UI: "ui",
|
||||
});
|
||||
@ -11,146 +11,25 @@
|
||||
*/
|
||||
|
||||
import fs from "node:fs";
|
||||
import path, { join } from "node:path";
|
||||
import { join } from "node:path";
|
||||
import chalk from "chalk";
|
||||
import inquirer from "inquirer";
|
||||
import { writeFileSafe } from "../helpers/file.js";
|
||||
import { toKebabCase, toTitleCase } from "../helpers/strings.js";
|
||||
import { getFileName, getTestType } from "./cli.js";
|
||||
import { getBoilerplatePath, getTestFileFullPath } from "./dirs.js";
|
||||
import { HELP_FLAGS, showHelpText } from "./help-message.js";
|
||||
|
||||
/**
|
||||
* @import {testType} from "./constants.js"
|
||||
*/
|
||||
|
||||
//#region Constants
|
||||
|
||||
const version = "2.0.2";
|
||||
// Get the directory name of the current module file
|
||||
const version = "2.1.0";
|
||||
const __dirname = import.meta.dirname;
|
||||
const projectRoot = path.join(__dirname, "..", "..");
|
||||
|
||||
const choices = /** @type {const} */ (["Move", "Ability", "Item", "Reward", "Mystery Encounter", "Utils", "UI"]);
|
||||
/** @typedef {typeof choices[number]} choiceType */
|
||||
/**
|
||||
* Object mapping choice types to extra names they can be used with from CLI.
|
||||
* @satisfies {Partial<Record<choiceType, readonly string[]>>}
|
||||
*/
|
||||
const cliAliases = {
|
||||
"Mystery Encounter": ["ME"],
|
||||
};
|
||||
|
||||
/** @satisfies {{[k in choiceType]: string}} */
|
||||
const choicesToDirs = /** @type {const} */ ({
|
||||
Move: "moves",
|
||||
Ability: "abilities",
|
||||
Item: "items",
|
||||
Reward: "rewards",
|
||||
"Mystery Encounter": "mystery-encounter/encounters",
|
||||
Utils: "utils",
|
||||
UI: "ui",
|
||||
});
|
||||
|
||||
const projectRoot = join(__dirname, "..", "..");
|
||||
//#endregion
|
||||
//#region Functions
|
||||
|
||||
/**
|
||||
* Get the path to a given folder in the test directory
|
||||
* @param {...string} folders the subfolders to append to the base path
|
||||
* @returns {string} the path to the requested folder
|
||||
*/
|
||||
function getTestFolderPath(...folders) {
|
||||
return path.join(projectRoot, "test", ...folders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to select a type via list.
|
||||
* @returns {Promise<choiceType>} the selected type
|
||||
*/
|
||||
async function promptTestType() {
|
||||
/** @type {choiceType | "EXIT"} */
|
||||
const choice = (
|
||||
await inquirer.prompt([
|
||||
{
|
||||
type: "list",
|
||||
name: "selectedOption",
|
||||
message: "What type of test would you like to create?",
|
||||
choices: [...choices, "EXIT"],
|
||||
},
|
||||
])
|
||||
).selectedOption;
|
||||
|
||||
if (choice === "EXIT") {
|
||||
console.log("Exiting...");
|
||||
return process.exit(0);
|
||||
}
|
||||
|
||||
return choice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to provide a file name.
|
||||
* @param {choiceType} selectedType The chosen string (used to display console logs)
|
||||
* @returns {Promise<string>} the selected file name
|
||||
*/
|
||||
async function promptFileName(selectedType) {
|
||||
/** @type {string} */
|
||||
const fileNameAnswer = (
|
||||
await inquirer.prompt([
|
||||
{
|
||||
type: "input",
|
||||
name: "userInput",
|
||||
message: `Please provide the name of the ${selectedType}.`,
|
||||
},
|
||||
])
|
||||
).userInput;
|
||||
|
||||
if (fileNameAnswer.trim().length === 0) {
|
||||
console.error("Please provide a valid file name!");
|
||||
return await promptFileName(selectedType);
|
||||
}
|
||||
|
||||
return fileNameAnswer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the path to the boilerplate file based on the current option.
|
||||
* @param {choiceType} choiceType The choice selected
|
||||
* @returns {string} The path to the boilerplate file
|
||||
*/
|
||||
function getBoilerplatePath(choiceType) {
|
||||
switch (choiceType) {
|
||||
// case "Reward":
|
||||
// return path.join(__dirname, "boilerplates/reward.boilerplate.ts");
|
||||
default:
|
||||
return path.join(__dirname, "boilerplates/default.boilerplate.ts");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse `process.argv` and get the test type if it exists.
|
||||
* @returns {choiceType | undefined}
|
||||
* The type of choice the CLI args corresponds to, or `undefined` if none were specified.
|
||||
* Will set `process.exitCode` to a non-zero integer if args are invalid.
|
||||
*/
|
||||
function convertArgsToTestType() {
|
||||
// If the first argument is a test name, use that as the test name
|
||||
const args = process.argv.slice(2);
|
||||
if (args[0] == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for a direct match, falling back to alias checking.
|
||||
const choiceName = choices.find(c => c.toLowerCase() === args[0].toLowerCase());
|
||||
if (choiceName) {
|
||||
return choiceName;
|
||||
}
|
||||
|
||||
const alias = /** @type {(keyof cliAliases)[]} */ (Object.keys(cliAliases)).find(k =>
|
||||
cliAliases[k].some(a => a.toLowerCase() === args[0].toLowerCase()),
|
||||
);
|
||||
if (alias) {
|
||||
return alias;
|
||||
}
|
||||
console.error(
|
||||
chalk.red.bold(`✗ Invalid type of test file specified: ${args[0]}!
|
||||
Valid types: ${chalk.blue(choices.join(", "))}`),
|
||||
);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
//#region Main
|
||||
|
||||
/**
|
||||
* Run the interactive `test:create` CLI.
|
||||
@ -159,65 +38,49 @@ Valid types: ${chalk.blue(choices.join(", "))}`),
|
||||
async function runInteractive() {
|
||||
console.group(chalk.grey(`🧪 Create Test - v${version}\n`));
|
||||
|
||||
const cliTestType = convertArgsToTestType();
|
||||
if (process.exitCode) {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
if (HELP_FLAGS.some(h => args.includes(h))) {
|
||||
return showHelpText();
|
||||
}
|
||||
|
||||
const testType = await getTestType(args[0]);
|
||||
if (process.exitCode || !testType) {
|
||||
return;
|
||||
}
|
||||
// TODO: Add a help command
|
||||
|
||||
const fileNameAnswer = await getFileName(testType, args[1]);
|
||||
if (process.exitCode || !fileNameAnswer) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let choice;
|
||||
if (cliTestType) {
|
||||
console.log(chalk.blue(`Using ${cliTestType} as test type from CLI...`));
|
||||
choice = cliTestType;
|
||||
} else {
|
||||
choice = await promptTestType();
|
||||
}
|
||||
const fileNameAnswer = await promptFileName(choice);
|
||||
|
||||
// Convert fileName from snake_case or camelCase to kebab-case
|
||||
const fileName = fileNameAnswer
|
||||
.replace(/_+/g, "-") // Convert snake_case (underscore) to kebab-case (dashes)
|
||||
.replace(/([a-z])([A-Z])/g, "$1-$2") // Convert camelCase to kebab-case
|
||||
.replace(/\s+/g, "-") // Replace spaces with dashes
|
||||
.toLowerCase(); // Ensure all lowercase
|
||||
|
||||
// Format the description for the test case in Title Case
|
||||
const formattedName = fileName.replace(/-/g, " ").replace(/\b\w/g, char => char.toUpperCase());
|
||||
const description = `${choice} - ${formattedName}`;
|
||||
|
||||
// Determine the directory based on the type
|
||||
const localDir = choicesToDirs[choice];
|
||||
const absoluteDir = getTestFolderPath(localDir);
|
||||
|
||||
// Define the content template
|
||||
const content = fs.readFileSync(getBoilerplatePath(choice), "utf8").replace("{{description}}", description);
|
||||
|
||||
// Ensure the directory exists
|
||||
if (!fs.existsSync(absoluteDir)) {
|
||||
fs.mkdirSync(absoluteDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Create the file with the given name
|
||||
const filePath = path.join(absoluteDir, `${fileName}.test.ts`);
|
||||
|
||||
if (fs.existsSync(filePath)) {
|
||||
console.error(chalk.red.bold(`✗ File "${fileName}.test.ts" already exists!\n`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Write the template content to the file
|
||||
fs.writeFileSync(filePath, content, "utf8");
|
||||
|
||||
console.log(chalk.green.bold(`✔ File created at: ${join("test", localDir, fileName)}.test.ts\n`));
|
||||
console.groupEnd();
|
||||
doCreateFile(testType, fileNameAnswer);
|
||||
} catch (err) {
|
||||
console.error(chalk.red("✗ Error: ", err));
|
||||
}
|
||||
console.groupEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create the test file.
|
||||
* @param {testType} testType - The type of test to create
|
||||
* @param {string} fileNameAnswer - The name of the file to create
|
||||
* @returns {void}
|
||||
*/
|
||||
function doCreateFile(testType, fileNameAnswer) {
|
||||
// Convert file name to kebab-case, formatting the description in Title Case
|
||||
const fileName = toKebabCase(fileNameAnswer);
|
||||
const formattedName = toTitleCase(fileNameAnswer);
|
||||
const description = `${testType} - ${formattedName}`;
|
||||
|
||||
const content = fs.readFileSync(getBoilerplatePath(testType), "utf8").replace("{{description}}", description);
|
||||
const filePath = getTestFileFullPath(testType, fileName);
|
||||
writeFileSafe(filePath, content, "utf8");
|
||||
|
||||
console.log(chalk.green.bold(`✔ File created at: ${filePath.replace(`${projectRoot}/`, "")}\n`));
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region Run
|
||||
|
||||
runInteractive();
|
||||
|
||||
//#endregion
|
||||
await runInteractive();
|
||||
|
||||
56
scripts/create-test/dirs.js
Normal file
56
scripts/create-test/dirs.js
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Pagefault Games
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { join } from "path";
|
||||
import { testTypesToDirs } from "./constants.js";
|
||||
|
||||
/**
|
||||
* @import { testType } from "./constants.js";
|
||||
*/
|
||||
|
||||
// Get the directory name of the current module file
|
||||
const __dirname = import.meta.dirname;
|
||||
const projectRoot = join(__dirname, "..", "..");
|
||||
|
||||
/**
|
||||
* Const object matching all {@linkcode testType}s to any custom boilerplate files
|
||||
* they may be associated with.
|
||||
* @type {Readonly<Partial<Record<testType, string>>>}
|
||||
*/
|
||||
const customBoilerplates = {
|
||||
// Reward: "boilerplates/reward.boilerplate.ts", // Todo: Boilerplate is added in the modifier rework
|
||||
};
|
||||
|
||||
const DEFAULT_BOILERPLATE_PATH = "boilerplates/default.boilerplate.ts";
|
||||
|
||||
/**
|
||||
* Retrieve the path to the boilerplate file used for the given test type.
|
||||
* @param {testType} testType - The type of test file to create
|
||||
* @returns {string} The path to the boilerplate file.
|
||||
*/
|
||||
export function getBoilerplatePath(testType) {
|
||||
return join(import.meta.dirname, customBoilerplates[testType] ?? DEFAULT_BOILERPLATE_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to a given folder in the test directory
|
||||
* @param {...string} folders the subfolders to append to the base path
|
||||
* @returns {string} the path to the requested folder
|
||||
*/
|
||||
function getTestFolderPath(...folders) {
|
||||
return join(projectRoot, "test", ...folders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to convert the test file name into an absolute path.
|
||||
* @param {testType} testType - The type of test being created (used to look up folder)
|
||||
* @param {string} fileName - The name of the test file (without suffix)
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getTestFileFullPath(testType, fileName) {
|
||||
const absoluteDir = getTestFolderPath(testTypesToDirs[testType]);
|
||||
return join(absoluteDir, `${fileName}.test.ts`);
|
||||
}
|
||||
32
scripts/create-test/help-message.js
Normal file
32
scripts/create-test/help-message.js
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Pagefault Games
|
||||
* SPDX-FileContributor: Bertie690
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import chalk from "chalk";
|
||||
|
||||
/**
|
||||
* Array containing all valid ways of showing the help message.
|
||||
*/
|
||||
export const HELP_FLAGS = /** @type {const} */ (["-h", "-help", "--help"]);
|
||||
|
||||
/**
|
||||
* Show help/usage text for the `test:create` CLI.
|
||||
* @package
|
||||
*/
|
||||
export function showHelpText() {
|
||||
console.log(`
|
||||
Usage: ${chalk.cyan("pnpm test:create [options] [testType] [fileName]")}
|
||||
If either ${chalk.hex("#7fff00")("testType")} or ${chalk.hex("#7fff00")("fileName")} are omitted,
|
||||
they will be selected interactively.
|
||||
|
||||
${chalk.hex("#8a2be2")("Arguments:")}
|
||||
${chalk.hex("#7fff00")("testType")} The type/category of test file to create.
|
||||
${chalk.hex("#7fff00")("fileName")} The name of the test file to create.
|
||||
|
||||
${chalk.hex("#ffa500")("Options:")}
|
||||
${chalk.blue("-h, -help, --help")} Show this help message.
|
||||
`);
|
||||
}
|
||||
66
scripts/create-test/interactive.js
Normal file
66
scripts/create-test/interactive.js
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Pagefault Games
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import chalk from "chalk";
|
||||
import inquirer from "inquirer";
|
||||
import { validTestTypes } from "./constants.js";
|
||||
|
||||
/**
|
||||
* @import {testType} from "./constants.js"
|
||||
*/
|
||||
/**
|
||||
* Prompt the user to select a test type via list.
|
||||
* @returns {Promise<testType | undefined>} The selected type, or `undefined` if "Exit" was pressed.
|
||||
*/
|
||||
export async function promptTestType() {
|
||||
/** @type {testType | "EXIT"} */
|
||||
const choice = (
|
||||
await inquirer.prompt([
|
||||
{
|
||||
type: "list",
|
||||
name: "selectedOption",
|
||||
message: "What type of test would you like to create?",
|
||||
choices: [...validTestTypes, "EXIT"],
|
||||
},
|
||||
])
|
||||
).selectedOption;
|
||||
|
||||
if (choice === "EXIT") {
|
||||
console.log("Exiting...");
|
||||
process.exitCode = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
return choice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt the user to provide a file name.
|
||||
* @param {testType} selectedType - The chosen string (used for logging & validation)
|
||||
* @returns {Promise<string>} The selected file name
|
||||
*/
|
||||
export async function promptFileName(selectedType) {
|
||||
/** @type {string} */
|
||||
const fileNameAnswer = (
|
||||
await inquirer.prompt([
|
||||
{
|
||||
type: "input",
|
||||
name: "userInput",
|
||||
message: `Please provide the name of the ${selectedType}.`,
|
||||
validate: name => {
|
||||
const nameProcessed = name.trim().replace(".test.ts", "");
|
||||
if (nameProcessed.length === 0) {
|
||||
return chalk.red.bold("✗ Cannot use an empty string as a file name!");
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
])
|
||||
).userInput;
|
||||
|
||||
// Trim whitespace and any extension suffixes
|
||||
return fileNameAnswer.trim().replace(".test.ts", "");
|
||||
}
|
||||
36
scripts/helpers/file.js
Normal file
36
scripts/helpers/file.js
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Pagefault Games
|
||||
* SPDX-FileContributor: Bertie690
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
||||
import { dirname } from "node:path";
|
||||
|
||||
/**
|
||||
* @import {PathOrFileDescriptor, WriteFileOptions} from "node:fs"
|
||||
*/
|
||||
|
||||
/**
|
||||
* "Safely" write to a file, creating any parent directories as required.
|
||||
* @param {PathOrFileDescriptor} file - The filename or file descriptor to open
|
||||
* @param {string | NodeJS.ArrayBufferView<ArrayBufferLike>} content - The content which will be written
|
||||
* @param {WriteFileOptions} [options]
|
||||
* @returns {void}
|
||||
* @remarks
|
||||
* If `file` is a file descriptor, this method will simply return the result of
|
||||
* {@linkcode writeFileSync} verbatim.
|
||||
*/
|
||||
export function writeFileSafe(file, content, options) {
|
||||
if (typeof file === "number") {
|
||||
return writeFileSync(file, content, options);
|
||||
}
|
||||
|
||||
const parentDir = dirname(file.toString("utf-8"));
|
||||
if (!existsSync(parentDir)) {
|
||||
mkdirSync(parentDir, { recursive: true });
|
||||
}
|
||||
|
||||
writeFileSync(file, content, options);
|
||||
}
|
||||
@ -170,4 +170,4 @@ function badArgs() {
|
||||
process.exitCode = 1;
|
||||
}
|
||||
|
||||
start();
|
||||
await start();
|
||||
|
||||
@ -297,4 +297,4 @@ async function promptExisting(outFile) {
|
||||
).continue;
|
||||
}
|
||||
|
||||
main();
|
||||
await main();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user