@settlemint/sdk-utils
Version:
Shared utilities and helper functions for SettleMint SDK modules
246 lines (240 loc) • 8.07 kB
JavaScript
//#region rolldown:runtime
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
let node_path = require("node:path");
node_path = __toESM(node_path);
let find_up = require("find-up");
find_up = __toESM(find_up);
let node_fs_promises = require("node:fs/promises");
node_fs_promises = __toESM(node_fs_promises);
let glob = require("glob");
glob = __toESM(glob);
//#region src/filesystem/project-root.ts
/**
* Finds the root directory of the current project by locating the nearest package.json file
*
* @param fallbackToCwd - If true, will return the current working directory if no package.json is found
* @param cwd - The directory to start searching for the package.json file from (defaults to process.cwd())
* @returns Promise that resolves to the absolute path of the project root directory
* @throws Will throw an error if no package.json is found in the directory tree
* @example
* import { projectRoot } from "@settlemint/sdk-utils/filesystem";
*
* // Get project root path
* const rootDir = await projectRoot();
* console.log(`Project root is at: ${rootDir}`);
*/
async function projectRoot(fallbackToCwd = false, cwd) {
const packageJsonPath = await (0, find_up.findUp)("package.json", { cwd });
if (!packageJsonPath) {
if (fallbackToCwd) {
return process.cwd();
}
throw new Error("Unable to find project root (no package.json found)");
}
return (0, node_path.dirname)(packageJsonPath);
}
//#endregion
//#region src/filesystem/exists.ts
/**
* Checks if a file or directory exists at the given path
*
* @param path - The file system path to check for existence
* @returns Promise that resolves to true if the path exists, false otherwise
* @example
* import { exists } from "@settlemint/sdk-utils/filesystem";
*
* // Check if file exists before reading
* if (await exists('/path/to/file.txt')) {
* // File exists, safe to read
* }
*/
async function exists(path) {
try {
await (0, node_fs_promises.stat)(path);
return true;
} catch {
return false;
}
}
//#endregion
//#region src/json.ts
/**
* Attempts to parse a JSON string into a typed value, returning a default value if parsing fails.
*
* @param value - The JSON string to parse
* @param defaultValue - The value to return if parsing fails or results in null/undefined
* @returns The parsed JSON value as type T, or the default value if parsing fails
*
* @example
* import { tryParseJson } from "@settlemint/sdk-utils";
*
* const config = tryParseJson<{ port: number }>(
* '{"port": 3000}',
* { port: 8080 }
* );
* // Returns: { port: 3000 }
*
* const invalid = tryParseJson<string[]>(
* 'invalid json',
* []
* );
* // Returns: []
*/
function tryParseJson(value, defaultValue = null) {
try {
const parsed = JSON.parse(value);
if (parsed === undefined || parsed === null) {
return defaultValue;
}
return parsed;
} catch (_err) {
return defaultValue;
}
}
/**
* Extracts a JSON object from a string.
*
* @param value - The string to extract the JSON object from
* @returns The parsed JSON object, or null if no JSON object is found
* @throws {Error} If the input string is too long (longer than 5000 characters)
* @example
* import { extractJsonObject } from "@settlemint/sdk-utils";
*
* const json = extractJsonObject<{ port: number }>(
* 'port info: {"port": 3000}',
* );
* // Returns: { port: 3000 }
*/
function extractJsonObject(value) {
if (value.length > 5e3) {
throw new Error("Input too long");
}
const result = /\{([\s\S]*)\}/.exec(value);
if (!result) {
return null;
}
return tryParseJson(result[0]);
}
/**
* Converts a value to a JSON stringifiable format.
*
* @param value - The value to convert
* @returns The JSON stringifiable value
*
* @example
* import { makeJsonStringifiable } from "@settlemint/sdk-utils";
*
* const json = makeJsonStringifiable<{ amount: bigint }>({ amount: BigInt(1000) });
* // Returns: '{"amount":"1000"}'
*/
function makeJsonStringifiable(value) {
if (value === undefined || value === null) {
return value;
}
return tryParseJson(JSON.stringify(value, (_, value$1) => typeof value$1 === "bigint" ? value$1.toString() : value$1));
}
//#endregion
//#region src/filesystem/mono-repo.ts
/**
* Finds the root directory of a monorepo
*
* @param startDir - The directory to start searching from
* @returns The root directory of the monorepo or null if not found
* @example
* import { findMonoRepoRoot } from "@settlemint/sdk-utils/filesystem";
*
* const root = await findMonoRepoRoot("/path/to/your/project");
* console.log(root); // Output: /path/to/your/project/packages/core
*/
async function findMonoRepoRoot(startDir) {
const lockFilePath = await (0, find_up.findUp)([
"package-lock.json",
"yarn.lock",
"pnpm-lock.yaml",
"bun.lockb",
"bun.lock"
], { cwd: startDir });
if (lockFilePath) {
const packageJsonPath = (0, node_path.join)((0, node_path.dirname)(lockFilePath), "package.json");
const hasWorkSpaces = await packageJsonHasWorkspaces(packageJsonPath);
return hasWorkSpaces ? (0, node_path.dirname)(lockFilePath) : null;
}
let currentDir = startDir;
while (currentDir !== "/") {
const packageJsonPath = (0, node_path.join)(currentDir, "package.json");
if (await packageJsonHasWorkspaces(packageJsonPath)) {
return currentDir;
}
const parentDir = (0, node_path.dirname)(currentDir);
if (parentDir === currentDir) {
break;
}
currentDir = parentDir;
}
return null;
}
/**
* Finds all packages in a monorepo
*
* @param projectDir - The directory to start searching from
* @returns An array of package directories
* @example
* import { findMonoRepoPackages } from "@settlemint/sdk-utils/filesystem";
*
* const packages = await findMonoRepoPackages("/path/to/your/project");
* console.log(packages); // Output: ["/path/to/your/project/packages/core", "/path/to/your/project/packages/ui"]
*/
async function findMonoRepoPackages(projectDir) {
try {
const monoRepoRoot = await findMonoRepoRoot(projectDir);
if (!monoRepoRoot) {
return [projectDir];
}
const packageJsonPath = (0, node_path.join)(monoRepoRoot, "package.json");
const packageJson = tryParseJson(await (0, node_fs_promises.readFile)(packageJsonPath, "utf-8"));
const workspaces = packageJson?.workspaces ?? [];
const packagePaths = await Promise.all(workspaces.map(async (workspace) => {
const matches = await (0, glob.glob)((0, node_path.join)(monoRepoRoot, workspace, "package.json"));
return matches.map((match) => (0, node_path.join)(match, ".."));
}));
const allPaths = packagePaths.flat();
return allPaths.length === 0 ? [projectDir] : [monoRepoRoot, ...allPaths];
} catch (_error) {
return [projectDir];
}
}
async function packageJsonHasWorkspaces(packageJsonPath) {
if (await exists(packageJsonPath)) {
const packageJson = tryParseJson(await (0, node_fs_promises.readFile)(packageJsonPath, "utf-8"));
if (packageJson?.workspaces && Array.isArray(packageJson?.workspaces) && packageJson?.workspaces.length > 0) {
return true;
}
}
return false;
}
//#endregion
exports.exists = exists;
exports.findMonoRepoPackages = findMonoRepoPackages;
exports.findMonoRepoRoot = findMonoRepoRoot;
exports.projectRoot = projectRoot;
//# sourceMappingURL=filesystem.cjs.map