react-native-test-app
Version:
react-native-test-app provides a test app for all supported platforms as a package
165 lines (148 loc) • 4.32 kB
JavaScript
// @ts-check
;
const nodefs = require("node:fs");
const path = require("node:path");
const { fileURLToPath } = require("node:url");
/**
* Finds the specified file using Node module resolution.
* @param {string} file
* @param {string=} startDir
* @returns {string | undefined}
*/
function findFile(file, startDir = process.cwd(), fs = nodefs) {
let currentDir = startDir;
let candidate = path.join(currentDir, file);
while (!fs.existsSync(candidate)) {
const nextDir = path.dirname(currentDir);
if (nextDir === currentDir) {
return undefined;
}
currentDir = nextDir;
candidate = path.join(currentDir, file);
}
return candidate;
}
/**
* Finds nearest relative path to a file or directory from current path.
* @param {string} fileOrDirName Path to the file or directory to find.
* @param {string=} currentDir The current working directory. Mostly used for unit tests.
* @returns {string | null} Nearest path to given file or directory; null if not found
*/
function findNearest(
fileOrDirName,
currentDir = path.resolve(""),
fs = nodefs
) {
const result = findFile(fileOrDirName, currentDir, fs);
return result ? path.relative("", result) : null;
}
/**
* Returns whether the current module is main.
* @param {string | import("node:url").URL} url
* @param {string} script
* @returns {boolean}
*/
function isMain(url, script = process.argv[1]) {
return Boolean(
url && script && fileURLToPath(url) === require.resolve(script)
);
}
/**
* @template T
* @param {(...args: any[]) => T} fn
* @returns {(...args: any[]) => T}
*/
function memo(fn) {
/** @type {T} */
let result;
return (...args) => {
if (result === undefined) {
result = fn(...args);
}
return result;
};
}
/**
* Reads text file at specified path.
* @param {import("node:fs").PathLike} path
* @returns {string}
*/
function readTextFile(path, fs = nodefs) {
return fs.readFileSync(path, { encoding: "utf-8" });
}
/**
* Reads and parses JSON file at specified path.
* @template [T = Record<string, unknown>]
* @param {import("node:fs").PathLike} path
* @returns {T}
*/
function readJSONFile(path, fs = nodefs) {
return JSON.parse(readTextFile(path, fs));
}
/**
* @template T
* @param {string[]} dependencyChain
* @param {string=} startDir
* @returns {T}
*/
function requireTransitive(dependencyChain, startDir = process.cwd()) {
const p = dependencyChain.reduce((curr, next) => {
const p = require.resolve(next + "/package.json", { paths: [curr] });
return path.dirname(p);
}, startDir);
return require(p);
}
/**
* Returns the numerical value equivalent of the specified version string.
* @param {string} version
* @returns {number}
*/
function toVersionNumber(version) {
const [major, minor = 0, patch = 0] = version.split("-")[0].split(".");
return v(Number(major), Number(minor), Number(patch));
}
/**
* Returns the numerical value of the individual version identifiers combined.
* @param {number} major
* @param {number} minor
* @param {number} patch
* @returns {number}
*/
function v(major, minor, patch) {
return major * 1000000 + minor * 1000 + patch;
}
/**
* Writes data to specified file path.
* @param {string} file
* @param {string} data
* @returns {Promise<void>}
*/
function writeTextFile(file, data, fs = nodefs.promises) {
return fs.writeFile(file, data, { encoding: "utf-8", mode: 0o644 });
}
/**
* Returns version string of specified module.
* @param {string} module
* @returns {string}
*/
function getPackageVersion(module, startDir = process.cwd(), fs = nodefs) {
const options = { paths: [startDir] };
const manifestPath = require.resolve(`${module}/package.json`, options);
const mod = readJSONFile(manifestPath, fs);
const version = mod["version"];
if (typeof version !== "string") {
throw new Error(`Invalid version number: ${module}@${version}`);
}
return version;
}
exports.findFile = findFile;
exports.findNearest = findNearest;
exports.getPackageVersion = getPackageVersion;
exports.isMain = isMain;
exports.memo = memo;
exports.readJSONFile = readJSONFile;
exports.readTextFile = readTextFile;
exports.requireTransitive = requireTransitive;
exports.toVersionNumber = toVersionNumber;
exports.v = v;
exports.writeTextFile = writeTextFile;