UNPKG

@stryke/fs

Version:

A package containing various file system utilities that expand the functionality of NodeJs's built-in `fs` module.

228 lines (226 loc) 7.93 kB
import { existsSync } from "./exists.mjs"; import { getWorkspaceRoot } from "./get-workspace-root.mjs"; import { appendExtension } from "@stryke/path"; import { joinPaths as joinPaths$1 } from "@stryke/path/join-paths"; import { correctPath, toAbsolutePath } from "@stryke/path/correct-path"; import { findFileName, findFilePath as findFilePath$1, findFolderName as findFolderName$1, hasFileExtension } from "@stryke/path/file-path-fns"; import { interopDefault, resolvePath, resolvePathSync } from "mlly"; import { cwd } from "@stryke/path/cwd"; import { getUnique } from "@stryke/helpers/get-unique"; import { isAbsolutePath, isNpmScopedPackage } from "@stryke/path/is-type"; //#region src/resolve.ts const DEFAULT_EXTENSIONS = [ "js", "jsx", "mjs", "cjs", "ts", "tsx", "mts", "cts", "json", "jsonc", "json5", "node" ]; /** * Get the resolution paths based on the provided paths, current working directory, and workspace root. * * @param paths - An array of paths to include in the resolution. * @returns An array of unique, corrected resolution paths. */ function getResolutionPaths(paths = []) { let resolutionPaths = paths; if (!resolutionPaths.includes(cwd())) resolutionPaths.push(cwd()); const workspaceRoot = getWorkspaceRoot(); if (!resolutionPaths.includes(workspaceRoot)) resolutionPaths.push(workspaceRoot); resolutionPaths = getUnique(resolutionPaths.filter(Boolean).map((path) => correctPath(path)).reduce((ret, path, _, arr) => { ret.push(path); if (!isAbsolutePath(path)) { ret.push(toAbsolutePath(path, cwd())); ret.push(toAbsolutePath(path, workspaceRoot)); arr.forEach((existing) => { ret.push(toAbsolutePath(path, existing)); }); } return ret; }, [])); return resolutionPaths; } /** * Get the node_modules resolution paths based on the provided paths. * * @param paths - An array of paths to include in the resolution. * @returns An array of unique, corrected node_modules resolution paths. */ function getNodeModulesPaths(paths = []) { return getUnique(paths.reduce((ret, path) => { if (findFolderName$1(path) === "node_modules") ret.push(correctPath(path)); if (existsSync(joinPaths$1(path, "node_modules"))) ret.push(correctPath(joinPaths$1(path, "node_modules"))); return ret; }, [])); } /** * Get all combinations of resolution paths for a given path and options. * * @param path - The base path to combine with resolution paths. * @param options - The options containing resolution paths. * @returns An array of unique, corrected resolution paths. */ function getResolutionCombinations(path, options = {}) { let paths = options.useAdditionalPaths ? getResolutionPaths(options.paths) : options.paths ?? []; if (isNpmScopedPackage(path)) paths = getNodeModulesPaths(paths); else paths.push(...getNodeModulesPaths(paths)); let combinations = paths.map((base) => joinPaths$1(base, path)); if (findFileName(path, { withExtension: false }) !== "index") combinations = combinations.reduce((ret, combination) => { ret.push(combination); ret.push(joinPaths$1(combination, "index")); return ret; }, []); if (!hasFileExtension(path)) { const extensions = options.extensions ?? DEFAULT_EXTENSIONS; combinations = combinations.reduce((ret, combination) => { ret.push(combination); extensions.forEach((ext) => { ret.push(appendExtension(combination, ext)); }); return ret; }, []); combinations.push(...extensions.map((ext) => getResolutionCombinations(appendExtension(path, ext), options)).flat()); } paths.map((p) => { if (hasFileExtension(p)) combinations.push(...getResolutionCombinations(path, { ...options, useAdditionalPaths: false, paths: [findFilePath$1(p)] })); }); return getUnique(combinations.filter(Boolean)).map((p) => correctPath(p)); } /** * Resolve the path to a specified module * * @param path - The path to the module * @param options - The options to use when resolving the module * @returns A promise for the path to the module */ async function resolve(path, options = {}) { let paths = getResolutionPaths(options.paths); if (isNpmScopedPackage(path)) paths = getNodeModulesPaths(paths); else paths.push(...getNodeModulesPaths(paths)); let result; let error; try { result = await resolvePath(path, { url: paths, extensions: options.extensions ?? DEFAULT_EXTENSIONS, conditions: options.conditions }); } catch (err) { error = err; } if (!result) throw new Error(`Unable to resolve module "${path}". The following import paths were tried: \n${paths.join("\n")}`, { cause: error }); return correctPath(result); } /** * Resolve the path to a specified module * * @param path - The path to the module * @param options - The options to use when resolving the module * @returns The path to the module or undefined */ function resolveSync(path, options = {}) { let paths = getResolutionPaths(options.paths); if (isNpmScopedPackage(path)) paths = getNodeModulesPaths(paths); else paths.push(...getNodeModulesPaths(paths)); let result; let error; try { result = resolvePathSync(path, { url: paths, extensions: options.extensions ?? DEFAULT_EXTENSIONS, conditions: options.conditions }); } catch (err) { error = err; } if (!result) throw new Error(`Unable to resolve module "${path}". The following import paths were tried: \n${paths.join("\n")}`, { cause: error }); return correctPath(result); } /** * Resolve the path to a specified module with error handling * * @param name - The name of the module * @param options - The options to use when resolving the module * @returns A promise for the path to the module */ async function resolveSafe(name, options = {}) { try { return await resolve(name, options); } catch { return; } } /** * Resolve the path to a specified module with error handling * * @param name - The name of the module * @param options - The options to use when resolving the module * @returns The path to the module or undefined */ function resolveSafeSync(name, options = {}) { try { return resolveSync(name, options); } catch { return; } } /** * Import a module from a specified path * * @param path - The path to the module * @returns The module */ async function importModule(path) { const i = await import(path); if (i) return interopDefault(i); return i; } /** * Resolve the path to a specified package asynchronously * * @remarks * This path points to the root of the package, which is usually the directory containing the `package.json` file. Please note: this path does not include the `package.json` file itself. * * @param name - The name of the module * @returns A promise for the module or undefined */ async function resolvePackage(name, options = {}) { let result = await resolveSafe(joinPaths$1(name, "package.json"), options); if (!result) { result = await resolveSafe(joinPaths$1(name, "index.js"), options); if (!result) result = await resolveSafe(name, options); } return result ? findFilePath$1(result) : void 0; } /** * Resolve the path to a specified package synchronously * * @remarks * This path points to the root of the package, which is usually the directory containing the `package.json` file. Please note: this path does not include the `package.json` file itself. * * @param name - The name of the module * @param options - The options to use when resolving the module * @returns The module or undefined */ function resolvePackageSync(name, options = {}) { let result = resolveSafeSync(joinPaths$1(name, "package.json"), options); if (!result) { result = resolveSafeSync(joinPaths$1(name, "index.js"), options); if (!result) result = resolveSafeSync(name, options); } return result ? findFilePath$1(result) : void 0; } //#endregion export { DEFAULT_EXTENSIONS, getNodeModulesPaths, getResolutionCombinations, getResolutionPaths, importModule, resolve, resolvePackage, resolvePackageSync, resolveSafe, resolveSafeSync, resolveSync }; //# sourceMappingURL=resolve.mjs.map