UNPKG

@manypkg/tools

Version:
161 lines (147 loc) 4.11 kB
import * as path from "node:path"; import * as fs from "node:fs"; import * as fsp from "node:fs/promises"; import { F_OK } from "node:constants"; import { type Tool, type PackageJSON, type Packages, InvalidMonorepoError, } from "./Tool.ts"; import { expandPackageGlobs, expandPackageGlobsSync, } from "./expandPackageGlobs.ts"; import { readJson, readJsonSync } from "./utils.ts"; interface BunPackageJSON extends PackageJSON { workspaces?: | string[] | { packages: string[]; catalog?: Record<string, string> }; } async function hasBunLockFile(directory: string): Promise<boolean> { try { await Promise.any([ fsp.access(path.join(directory, "bun.lockb"), F_OK), fsp.access(path.join(directory, "bun.lock"), F_OK), ]); return true; } catch (err) { return false; } } function hasBunLockFileSync(directory: string): boolean { try { fs.accessSync(path.join(directory, "bun.lockb"), F_OK); return true; } catch (err) { try { fs.accessSync(path.join(directory, "bun.lock"), F_OK); return true; } catch (err) { return false; } } } export const BunTool: Tool = { type: "bun", async isMonorepoRoot(directory: string): Promise<boolean> { try { const [pkgJson, hasLockFile] = await Promise.all([ readJson(directory, "package.json") as Promise<BunPackageJSON>, hasBunLockFile(directory), ]); if (pkgJson.workspaces && hasLockFile) { if ( Array.isArray(pkgJson.workspaces) || Array.isArray(pkgJson.workspaces.packages) ) { return true; } } } catch (err) { if (err && (err as { code: string }).code === "ENOENT") { return false; } throw err; } return false; }, isMonorepoRootSync(directory: string): boolean { try { const hasLockFile = hasBunLockFileSync(directory); if (!hasLockFile) { return false; } const pkgJson = readJsonSync(directory, "package.json") as BunPackageJSON; if (pkgJson.workspaces) { if ( Array.isArray(pkgJson.workspaces) || Array.isArray(pkgJson.workspaces.packages) ) { return true; } } } catch (err) { if (err && (err as { code: string }).code === "ENOENT") { return false; } throw err; } return false; }, async getPackages(directory: string): Promise<Packages> { const rootDir = path.resolve(directory); try { const pkgJson = (await readJson( rootDir, "package.json" )) as BunPackageJSON; const packageGlobs: string[] = Array.isArray(pkgJson.workspaces) ? pkgJson.workspaces : pkgJson.workspaces?.packages || []; return { tool: BunTool, packages: await expandPackageGlobs(packageGlobs, rootDir), rootPackage: { dir: rootDir, relativeDir: ".", packageJson: pkgJson, }, rootDir, }; } catch (err) { if (err && (err as { code: string }).code === "ENOENT") { throw new InvalidMonorepoError( `Directory ${rootDir} is not a valid ${BunTool.type} monorepo root` ); } throw err; } }, getPackagesSync(directory: string): Packages { const rootDir = path.resolve(directory); try { const pkgJson = readJsonSync(rootDir, "package.json") as BunPackageJSON; const packageGlobs: string[] = Array.isArray(pkgJson.workspaces) ? pkgJson.workspaces : pkgJson.workspaces?.packages || []; return { tool: BunTool, packages: expandPackageGlobsSync(packageGlobs, rootDir), rootPackage: { dir: rootDir, relativeDir: ".", packageJson: pkgJson, }, rootDir, }; } catch (err) { if (err && (err as { code: string }).code === "ENOENT") { throw new InvalidMonorepoError( `Directory ${rootDir} is not a valid ${BunTool.type} monorepo root` ); } throw err; } }, };