@pnpm/directory-fetcher
Version:
A fetcher for local directory packages
125 lines • 5.26 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createDirectoryFetcher = createDirectoryFetcher;
exports.fetchFromDir = fetchFromDir;
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
const util_1 = __importDefault(require("util"));
const exec_pkg_requires_build_1 = require("@pnpm/exec.pkg-requires-build");
const logger_1 = require("@pnpm/logger");
const fs_packlist_1 = require("@pnpm/fs.packlist");
const read_project_manifest_1 = require("@pnpm/read-project-manifest");
const directoryFetcherLogger = (0, logger_1.logger)('directory-fetcher');
function createDirectoryFetcher(opts) {
const readFileStat = opts?.resolveSymlinks === true ? realFileStat : fileStat;
const fetchFromDir = opts?.includeOnlyPackageFiles ? fetchPackageFilesFromDir : fetchAllFilesFromDir.bind(null, readFileStat);
const directoryFetcher = (cafs, resolution, opts) => {
const dir = path_1.default.join(opts.lockfileDir, resolution.directory);
return fetchFromDir(dir);
};
return {
directory: directoryFetcher,
};
}
async function fetchFromDir(dir, opts) {
if (opts.includeOnlyPackageFiles) {
return fetchPackageFilesFromDir(dir);
}
const readFileStat = opts?.resolveSymlinks === true ? realFileStat : fileStat;
return fetchAllFilesFromDir(readFileStat, dir);
}
async function fetchAllFilesFromDir(readFileStat, dir) {
const { filesIndex, filesStats } = await _fetchAllFilesFromDir(readFileStat, dir);
// In a regular pnpm workspace it will probably never happen that a dependency has no package.json file.
// Safe read was added to support the Bit workspace in which the components have no package.json files.
// Related PR in Bit: https://github.com/teambit/bit/pull/5251
const manifest = await (0, read_project_manifest_1.safeReadProjectManifestOnly)(dir) ?? undefined;
const requiresBuild = (0, exec_pkg_requires_build_1.pkgRequiresBuild)(manifest, filesIndex);
return {
local: true,
filesIndex,
filesStats,
packageImportMethod: 'hardlink',
manifest,
requiresBuild,
};
}
async function _fetchAllFilesFromDir(readFileStat, dir, relativeDir = '') {
const filesIndex = {};
const filesStats = {};
const files = await fs_1.promises.readdir(dir);
await Promise.all(files
.filter((file) => file !== 'node_modules')
.map(async (file) => {
const fileStatResult = await readFileStat(path_1.default.join(dir, file));
if (!fileStatResult)
return;
const { filePath, stat } = fileStatResult;
const relativeSubdir = `${relativeDir}${relativeDir ? '/' : ''}${file}`;
if (stat.isDirectory()) {
const subFetchResult = await _fetchAllFilesFromDir(readFileStat, filePath, relativeSubdir);
Object.assign(filesIndex, subFetchResult.filesIndex);
Object.assign(filesStats, subFetchResult.filesStats);
}
else {
filesIndex[relativeSubdir] = filePath;
filesStats[relativeSubdir] = fileStatResult.stat;
}
}));
return { filesIndex, filesStats };
}
async function realFileStat(filePath) {
let stat = await fs_1.promises.lstat(filePath);
if (!stat.isSymbolicLink()) {
return { filePath, stat };
}
try {
filePath = await fs_1.promises.realpath(filePath);
stat = await fs_1.promises.stat(filePath);
return { filePath, stat };
}
catch (err) {
// Broken symlinks are skipped
if (util_1.default.types.isNativeError(err) && 'code' in err && err.code === 'ENOENT') {
directoryFetcherLogger.debug({ brokenSymlink: filePath });
return null;
}
throw err;
}
}
async function fileStat(filePath) {
try {
return {
filePath,
stat: await fs_1.promises.stat(filePath),
};
}
catch (err) {
// Broken symlinks are skipped
if (util_1.default.types.isNativeError(err) && 'code' in err && err.code === 'ENOENT') {
directoryFetcherLogger.debug({ brokenSymlink: filePath });
return null;
}
throw err;
}
}
async function fetchPackageFilesFromDir(dir) {
const files = await (0, fs_packlist_1.packlist)(dir);
const filesIndex = Object.fromEntries(files.map((file) => [file, path_1.default.join(dir, file)]));
// In a regular pnpm workspace it will probably never happen that a dependency has no package.json file.
// Safe read was added to support the Bit workspace in which the components have no package.json files.
// Related PR in Bit: https://github.com/teambit/bit/pull/5251
const manifest = await (0, read_project_manifest_1.safeReadProjectManifestOnly)(dir) ?? undefined;
const requiresBuild = (0, exec_pkg_requires_build_1.pkgRequiresBuild)(manifest, filesIndex);
return {
local: true,
filesIndex,
packageImportMethod: 'hardlink',
manifest,
requiresBuild,
};
}
//# sourceMappingURL=index.js.map