@stryke/fs
Version:
A package containing various file system utilities that expand the functionality of NodeJs's built-in `fs` module.
138 lines (136 loc) • 4.73 kB
JavaScript
import { getWorkspaceRoot } from "./get-workspace-root.mjs";
import { execSync } from "node:child_process";
import { detectPackageManager } from "@antfu/install-pkg";
import { parseArgs } from "node:util";
//#region src/registry.ts
const parseNodeArgs = (args) => {
const { values, tokens } = parseArgs({
args,
strict: false,
tokens: true
});
let orphan = null;
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i];
if (token.kind === "option-terminator") break;
if (token.kind === "option") {
orphan = typeof token.value === "undefined" ? token : null;
continue;
}
if (token.kind !== "positional") {
orphan = null;
continue;
}
if (!orphan) continue;
if (orphan.name in values && typeof values[orphan.name] === "string") values[orphan.name] += ` ${token.value}`;
else values[orphan.name] = token.value;
}
return values;
};
/**
* Tokenizes the arguments string into an array of strings, supporting quoted
* values and escaped characters.
* Converted from: https://github.com/nodejs/node/blob/c29d53c5cfc63c5a876084e788d70c9e87bed880/src/node_options.cc#L1401
*
* @param input - The arguments string to be tokenized.
* @returns An array of strings with the tokenized arguments.
*/
const tokenizeArgs = (input) => {
const args = [];
let isInString = false;
let willStartNewArg = true;
for (let i = 0; i < input.length; i++) {
let char = input[i];
if (char === "\\" && isInString) {
if (input.length === i + 1) throw new Error("Invalid escape character at the end.");
char = input[++i];
} else if (char === " " && !isInString) {
willStartNewArg = true;
continue;
} else if (char === "\"") {
isInString = !isInString;
continue;
}
if (willStartNewArg) {
args.push(char);
willStartNewArg = false;
} else args[args.length - 1] += char;
}
if (isInString) throw new Error("Unterminated string");
return args;
};
/**
* Get the node options from the environment variable `NODE_OPTIONS` and returns
* them as an array of strings.
*
* @returns An array of strings with the node options.
*/
const getNodeOptionsArgs = () => {
if (!process.env.NODE_OPTIONS) return [];
return tokenizeArgs(process.env.NODE_OPTIONS);
};
/**
* Stringify the arguments to be used in a command line. It will ignore any
* argument that has a value of `undefined`.
*
* @param args - The arguments to be stringified.
* @returns A string with the arguments.
*/
function formatNodeOptions(args) {
return Object.entries(args).map(([key, value]) => {
if (value === true) return `--${key}`;
if (value) return `--${key}=${value.includes(" ") && !value.startsWith("\"") ? JSON.stringify(value) : value}`;
return null;
}).filter((arg) => arg !== null).join(" ");
}
/**
* Get the node options from the `NODE_OPTIONS` environment variable and parse
* them into an object without the inspect options.
*
* @returns An object with the parsed node options.
*/
function getParsedNodeOptionsWithoutInspect() {
const args = getNodeOptionsArgs();
if (args.length === 0) return {};
const parsed = parseNodeArgs(args);
delete parsed.inspect;
delete parsed["inspect-brk"];
delete parsed.inspect_brk;
return parsed;
}
/**
* Get the node options from the `NODE_OPTIONS` environment variable and format
* them into a string without the inspect options.
*
* @returns A string with the formatted node options.
*/
function getFormattedNodeOptionsWithoutInspect() {
const args = getParsedNodeOptionsWithoutInspect();
if (Object.keys(args).length === 0) return "";
return formatNodeOptions(args);
}
/**
* Returns the package registry using the user's package manager. The URL will have a trailing slash.
*
* @param baseDir - The base directory to detect the package manager from.
* @returns The package registry URL with a trailing slash.
* @throws Will throw an error if the package manager cannot be detected or if the registry cannot be retrieved.
*/
async function getRegistry(baseDir) {
const pkgManager = await detectPackageManager(getWorkspaceRoot(baseDir));
const resolvedFlags = pkgManager === "npm" ? "--no-workspaces" : "";
let registry = `https://registry.npmjs.org/`;
try {
const output = execSync(`${pkgManager} config get registry ${resolvedFlags}`, { env: {
...process.env,
NODE_OPTIONS: getFormattedNodeOptionsWithoutInspect()
} }).toString().trim();
if (output.startsWith("http")) registry = output.endsWith("/") ? output : `${output}/`;
} catch (err) {
throw new Error(`Failed to get registry from "${pkgManager}".`, { cause: err });
}
return registry;
}
//#endregion
export { formatNodeOptions, getFormattedNodeOptionsWithoutInspect, getParsedNodeOptionsWithoutInspect, getRegistry, tokenizeArgs };
//# sourceMappingURL=registry.mjs.map