UNPKG

waka-pm

Version:

a pnpm supplement for enforcing consistent versions across all workspaces

321 lines 13.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseWorkspaceDir = exports.mapNPMPackageDetails = exports.getDetailKey = exports.getNPMPackageDetails = exports.getWakaPackageDocuments = exports.getWakaPackages = exports.getWakaPackageDocument = exports.getWakaPackage = exports.getRawWakaPackageYamlData = exports.getWakaRootDocument = exports.getWakaRoot = exports.getRootNPMPackageFile = exports.getNPMPackageJsonContents = exports.getNPMPackageFiles = exports.getWakaPackageFiles = exports.getWakaRootFile = exports.getNPMPackageFile = exports.getWakaPackageFile = exports.getAllPackageDirectories = exports.getNPMPackageDir = exports.getWorkspaceDirectoryByPackage = exports.getWorkspaceDirectories = exports.getNPMPackageName = void 0; const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const glob_1 = require("glob"); const yaml_1 = __importDefault(require("yaml")); const schema_1 = require("../schema"); const file_1 = require("../file"); const packageDirToNameCache = new Map(); const packageNameToDirCache = new Map(); let workspaceDirCache; function toDirectoryOnly(p) { if (fs_1.default.existsSync(p) === false) { throw new Error(`Path ${p} does not exist.`); } if (fs_1.default.lstatSync(p).isDirectory()) { return p; } return path_1.default.dirname(p); } function getNPMPackageName(packageJsonFile) { const fullPath = path_1.default.resolve(packageJsonFile); const dir = toDirectoryOnly(fullPath); if (packageDirToNameCache.has(dir)) { return packageDirToNameCache.get(dir); } const rawData = fs_1.default.readFileSync(fullPath, 'utf8'); // eslint-disable-next-line @typescript-eslint/no-explicit-any const pkgJsonData = JSON.parse(rawData); const pkgName = pkgJsonData.name; packageDirToNameCache.set(dir, pkgName); packageNameToDirCache.set(pkgName, dir); return pkgName; } exports.getNPMPackageName = getNPMPackageName; async function getWorkspaceDirectories(repoRootDir) { if (workspaceDirCache && Object.keys(workspaceDirCache).length > 0) { return workspaceDirCache; } const pnpmWorkspaceYaml = path_1.default.join(repoRootDir, 'pnpm-workspace.yaml'); const rootPackageJson = path_1.default.join(repoRootDir, 'package.json'); let workspaceDirs = []; if (fs_1.default.existsSync(pnpmWorkspaceYaml)) { const rawData = fs_1.default.readFileSync(pnpmWorkspaceYaml, 'utf8'); workspaceDirs = yaml_1.default.parse(rawData).packages; } else if (fs_1.default.existsSync(rootPackageJson)) { const rawData = fs_1.default.readFileSync(rootPackageJson, 'utf8'); workspaceDirs = JSON.parse(rawData) .workspaces.packages; } else { throw new Error('No pnpm-workspace.yaml or root package.json found'); } const workspacePackageJsons = workspaceDirs.map((dir) => `${dir}/package.json`); const foundJsons = (await (0, glob_1.glob)(workspacePackageJsons, { ignore: ['**/node_modules/**'], cwd: repoRootDir, })).map((p) => path_1.default.join(repoRootDir, p)); const foundDirs = foundJsons .map((json) => { const dir = path_1.default.relative(repoRootDir, path_1.default.dirname(json)); const pkgName = getNPMPackageName(json); return { [pkgName]: dir }; }) .reduce((acc, p) => { return { ...acc, ...p }; }); workspaceDirCache = foundDirs; const rootName = getNPMPackageName(rootPackageJson); workspaceDirCache[rootName] = ''; return foundDirs; } exports.getWorkspaceDirectories = getWorkspaceDirectories; async function getWorkspaceDirectoryByPackage(repoRootDir, packageName) { const workspaces = await getWorkspaceDirectories(repoRootDir); const workspace = workspaces[packageName]; if (!workspace) { throw new Error(`Package ${packageName} does not exist.`); } return workspace; } exports.getWorkspaceDirectoryByPackage = getWorkspaceDirectoryByPackage; async function getNPMPackageDir(packageName, repoRootDir) { if (packageNameToDirCache.has(packageName)) { return packageNameToDirCache.get(packageName); } const packageDirRelative = await getWorkspaceDirectoryByPackage(repoRootDir, packageName); const dir = toDirectoryOnly(path_1.default.join(repoRootDir, packageDirRelative)); const packageDir = path_1.default.resolve(dir); packageNameToDirCache.set(packageName, packageDir); packageDirToNameCache.set(packageDir, packageName); return packageDir; } exports.getNPMPackageDir = getNPMPackageDir; async function getAllPackageDirectories(repoRootDir, opts) { const packageDirs = Object.values(await getWorkspaceDirectories(repoRootDir)); if (opts?.includeRoot === false) { return packageDirs.filter((p) => p !== '' && p !== '.' && p !== './'); } return packageDirs; } exports.getAllPackageDirectories = getAllPackageDirectories; async function getPackageFile(filename, packageDir, opts) { const f = path_1.default.join(packageDir, filename); if (opts?.ensureExists && !fs_1.default.existsSync(f)) { throw new Error(`File ${f} does not exist.`); } return Promise.resolve(f); } async function getWakaPackageFile(packageDir, opts) { packageDir = toDirectoryOnly(packageDir); return getPackageFile('waka-package.yaml', packageDir, opts); } exports.getWakaPackageFile = getWakaPackageFile; async function getNPMPackageFile(packageDir, opts) { packageDir = toDirectoryOnly(packageDir); return getPackageFile('package.json', packageDir, opts); } exports.getNPMPackageFile = getNPMPackageFile; function getWakaRootFile(repoRootDir, opts) { const rootFile = path_1.default.join(repoRootDir, 'waka-root.yaml'); if (opts?.ensureExists && !fs_1.default.existsSync(rootFile)) { throw new Error(`File ${rootFile} does not exist.`); } return Promise.resolve(rootFile); } exports.getWakaRootFile = getWakaRootFile; async function getWakaPackageFiles(repoRootDir, opts) { const packageDirs = await getAllPackageDirectories(repoRootDir, { includeRoot: false, }); const pkgFilePromises = packageDirs.map(async (p) => { const f = await getWakaPackageFile(path_1.default.join(repoRootDir, p), opts); return f; }); const allPackageFiles = await Promise.all(pkgFilePromises); if (opts?.includeRoot) { const rootFile = await getWakaRootFile(repoRootDir, { ensureExists: opts?.ensureExists, }); allPackageFiles.push(rootFile); } return allPackageFiles.filter((f) => !!f); } exports.getWakaPackageFiles = getWakaPackageFiles; async function getNPMPackageFiles(repoRootDir, opts) { const packageDirs = await getAllPackageDirectories(repoRootDir, { includeRoot: opts?.includeRoot ?? false, }); const pkgFilePromises = packageDirs.map(async (p) => { const f = await getNPMPackageFile(path_1.default.join(repoRootDir, p), opts); return f; }); return (await Promise.all(pkgFilePromises)).filter((f) => !!f); } exports.getNPMPackageFiles = getNPMPackageFiles; async function getNPMPackageJsonContents(packageDir) { packageDir = toDirectoryOnly(packageDir); const fullPath = await getNPMPackageFile(packageDir, { ensureExists: true }); const rawData = fs_1.default.readFileSync(fullPath, 'utf8'); const pkgJsonData = JSON.parse(rawData); return pkgJsonData; } exports.getNPMPackageJsonContents = getNPMPackageJsonContents; function getRootNPMPackageFile(repoRootDir, opts) { const rootFile = path_1.default.join(repoRootDir, 'package.json'); if (opts?.ensureExists && !fs_1.default.existsSync(rootFile)) { throw new Error(`File ${rootFile} does not exist.`); } return Promise.resolve(rootFile); } exports.getRootNPMPackageFile = getRootNPMPackageFile; async function getRawWakaRootYamlData(repoRootDir) { const rootFile = await getWakaRootFile(repoRootDir, { ensureExists: true }); const rawData = fs_1.default.readFileSync(rootFile, 'utf8'); return rawData; } async function getWakaRoot(repoRootDir) { const rawData = await getRawWakaRootYamlData(repoRootDir); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const root = yaml_1.default.parse(rawData); const rootParsed = schema_1.rootSchema.parse(root); return rootParsed; } exports.getWakaRoot = getWakaRoot; async function getWakaRootDocument(repoRootDir) { const rawData = await getRawWakaRootYamlData(repoRootDir); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const root = yaml_1.default.parse(rawData); // still parse for validation purposes schema_1.rootSchema.parse(root); const doc = yaml_1.default.parseDocument(rawData); const rootParsed = schema_1.RootDocument.instanceFromDocument(doc); return rootParsed; } exports.getWakaRootDocument = getWakaRootDocument; async function getRawWakaPackageYamlData(packageDirectory) { const packageDir = toDirectoryOnly(packageDirectory); const wakaPackageFile = await getWakaPackageFile(packageDir, { ensureExists: true, }); const rawData = fs_1.default.readFileSync(wakaPackageFile, 'utf8'); return rawData; } exports.getRawWakaPackageYamlData = getRawWakaPackageYamlData; async function getWakaPackage(packageDirectory) { const rawData = await getRawWakaPackageYamlData(packageDirectory); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const pkg = yaml_1.default.parse(rawData); const pkgParsed = schema_1.packageSchema.parse(pkg); return pkgParsed; } exports.getWakaPackage = getWakaPackage; async function getWakaPackageDocument(packageDirectory) { const rawData = await getRawWakaPackageYamlData(packageDirectory); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const pkg = yaml_1.default.parse(rawData); // still parse for validation purposes schema_1.packageSchema.parse(pkg); const doc = yaml_1.default.parseDocument(rawData); return schema_1.PackageDocument.instanceFromDocument(doc); } exports.getWakaPackageDocument = getWakaPackageDocument; async function getWakaPackagesInFormat(repoRootDir, format) { const packageFiles = await getWakaPackageFiles(repoRootDir, { ensureExists: true, }); return (await Promise.all(packageFiles.map(async (p) => { const packageDir = path_1.default.dirname(p); const packageJsonFile = await getNPMPackageFile(packageDir, { ensureExists: true, }); const packageName = getNPMPackageName(packageJsonFile); const pkgParsed = await format(p); return { [packageName]: pkgParsed }; }))).reduce((acc, p) => { return { ...acc, ...p }; }, {}); } async function getWakaPackages(repoRootDir) { return getWakaPackagesInFormat(repoRootDir, getWakaPackage); } exports.getWakaPackages = getWakaPackages; async function getWakaPackageDocuments(repoRootDir) { return getWakaPackagesInFormat(repoRootDir, getWakaPackageDocument); } exports.getWakaPackageDocuments = getWakaPackageDocuments; async function getNPMPackageDetails(repoRootDir, opts) { let pkgJsons = await getNPMPackageFiles(repoRootDir, { ensureExists: true, includeRoot: false, }); if (opts?.includeRoot) { const rootPkgJson = await getRootNPMPackageFile(repoRootDir, { ensureExists: true, }); pkgJsons = [...pkgJsons, rootPkgJson]; } const details = []; for (const p of pkgJsons) { const pkgJsonData = await getNPMPackageJsonContents(p); schema_1.npmDepTypes.forEach((depType) => { const deps = pkgJsonData[depType]; if (deps) { Object.keys(deps).forEach((depName) => { details.push({ name: depName, version: deps[depName], type: depType, packagePath: p, packageName: getNPMPackageName(p), }); }); } }); } return details; } exports.getNPMPackageDetails = getNPMPackageDetails; function getDetailKey(detail, mapBy = ['name']) { return mapBy.map((mapByKey) => detail[mapByKey]).join('|'); } exports.getDetailKey = getDetailKey; function mapNPMPackageDetails(details, mapBy = ['name']) { const m = details.reduce((acc, pkgDetail) => { const fullKey = getDetailKey(pkgDetail, mapBy); if (!acc[fullKey]) { acc[fullKey] = []; } acc[fullKey].push(pkgDetail); return acc; }, {}); return m; } exports.mapNPMPackageDetails = mapNPMPackageDetails; async function parseWorkspaceDir(repoRootDir, currentDir, packageNameOrRelativePath) { const isSub = (0, file_1.isSubDirOfMonoRepo)(currentDir); const isRoot = (0, file_1.isMonoRepoRoot)(currentDir); if ((packageNameOrRelativePath ?? '') === '') { if (isSub && !isRoot) { return currentDir; } return repoRootDir; } const fullPath = path_1.default.resolve(path_1.default.join(repoRootDir, packageNameOrRelativePath)); if (fs_1.default.existsSync(fullPath)) { return fullPath; } if (packageNameOrRelativePath ?? '' !== '') { const dir = await getNPMPackageDir(packageNameOrRelativePath, repoRootDir); return dir; } throw new Error(`Could not determine package directory for ${packageNameOrRelativePath} or ${currentDir}`); } exports.parseWorkspaceDir = parseWorkspaceDir; //# sourceMappingURL=read.js.map