nx
Version:
166 lines (165 loc) • 7.67 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createDependencies = exports.createNodesV2 = exports.name = void 0;
const fs_1 = require("fs");
const path_1 = require("path");
const perf_hooks_1 = require("perf_hooks");
const file_hasher_1 = require("../../hasher/file-hasher");
const plugins_1 = require("../../project-graph/plugins");
const cache_directory_1 = require("../../utils/cache-directory");
const globs_1 = require("../../utils/globs");
const package_manager_1 = require("../../utils/package-manager");
const versions_1 = require("../../utils/versions");
const workspace_root_1 = require("../../utils/workspace-root");
const bun_parser_1 = require("./lock-file/bun-parser");
const lock_file_1 = require("./lock-file/lock-file");
const build_dependencies_1 = require("./project-graph/build-dependencies/build-dependencies");
const config_1 = require("./utils/config");
exports.name = 'nx/js/dependencies-and-lockfile';
// Separate in-memory caches
let cachedExternalNodes;
let cachedKeyMap;
exports.createNodesV2 = [
(0, globs_1.combineGlobPatterns)(lock_file_1.LOCKFILES),
(files, _, context) => {
return (0, plugins_1.createNodesFromFiles)(internalCreateNodes, files, _, context);
},
];
function internalCreateNodes(lockFile, _, context) {
const pluginConfig = (0, config_1.jsPluginConfig)(context.nxJsonConfiguration);
if (!pluginConfig.analyzeLockfile) {
return {};
}
const packageManager = (0, package_manager_1.detectPackageManager)(workspace_root_1.workspaceRoot);
// Only process the correct lockfile
if (lockFile !== (0, lock_file_1.getLockFileName)(packageManager)) {
return {};
}
const lockFilePath = (0, path_1.join)(workspace_root_1.workspaceRoot, lockFile);
const lockFileContents = packageManager !== 'bun'
? (0, fs_1.readFileSync)(lockFilePath, 'utf-8')
: (0, bun_parser_1.readBunLockFile)(lockFilePath);
const lockFileHash = getLockFileHash(lockFileContents);
if (!lockFileNeedsReprocessing(lockFileHash, externalNodesHashFile)) {
const { nodes, keyMap } = readCachedExternalNodes();
cachedExternalNodes = nodes;
cachedKeyMap = keyMap;
return {
externalNodes: nodes,
};
}
const { nodes: externalNodes, keyMap } = (0, lock_file_1.getLockFileNodes)(packageManager, lockFileContents, lockFileHash, context);
cachedExternalNodes = externalNodes;
cachedKeyMap = keyMap;
writeExternalNodesCache(lockFileHash, externalNodes, keyMap);
return {
externalNodes,
};
}
const createDependencies = (_, ctx) => {
const pluginConfig = (0, config_1.jsPluginConfig)(ctx.nxJsonConfiguration);
const packageManager = (0, package_manager_1.detectPackageManager)(workspace_root_1.workspaceRoot);
let lockfileDependencies = [];
// lockfile may not exist yet
if (pluginConfig.analyzeLockfile &&
(0, lock_file_1.lockFileExists)(packageManager) &&
cachedExternalNodes) {
const lockFilePath = (0, path_1.join)(workspace_root_1.workspaceRoot, (0, lock_file_1.getLockFileName)(packageManager));
const lockFileContents = packageManager !== 'bun'
? (0, fs_1.readFileSync)(lockFilePath, 'utf-8')
: (0, bun_parser_1.readBunLockFile)(lockFilePath);
const lockFileHash = getLockFileHash(lockFileContents);
if (!lockFileNeedsReprocessing(lockFileHash, dependenciesHashFile)) {
lockfileDependencies = readCachedDependencies();
}
else {
lockfileDependencies = (0, lock_file_1.getLockFileDependencies)(packageManager, lockFileContents, lockFileHash, ctx, cachedKeyMap);
writeDependenciesCache(lockFileHash, lockfileDependencies);
}
}
perf_hooks_1.performance.mark('build typescript dependencies - start');
const explicitProjectDependencies = (0, build_dependencies_1.buildExplicitDependencies)(pluginConfig, ctx);
perf_hooks_1.performance.mark('build typescript dependencies - end');
perf_hooks_1.performance.measure('build typescript dependencies', 'build typescript dependencies - start', 'build typescript dependencies - end');
return lockfileDependencies.concat(explicitProjectDependencies);
};
exports.createDependencies = createDependencies;
function getLockFileHash(lockFileContents) {
return (0, file_hasher_1.hashArray)([versions_1.nxVersion, lockFileContents]);
}
// Serialize keyMap to JSON-friendly format
function serializeKeyMap(keyMap) {
const serialized = {};
for (const [key, value] of keyMap.entries()) {
if (value instanceof Set) {
// pnpm: Map<string, Set<ProjectGraphExternalNode>>
serialized[key] = Array.from(value).map((node) => node.name);
}
else if (value && typeof value === 'object' && 'name' in value) {
// npm/yarn: Map<string, ProjectGraphExternalNode>
serialized[key] = value.name;
}
else {
serialized[key] = value;
}
}
return serialized;
}
// Deserialize keyMap from JSON format using ctx.externalNodes
function deserializeKeyMap(serialized, externalNodes) {
const keyMap = new Map();
for (const [key, value] of Object.entries(serialized)) {
if (Array.isArray(value)) {
// pnpm: reconstruct Set<ProjectGraphExternalNode>
const nodes = value
.map((nodeName) => externalNodes[nodeName])
.filter(Boolean);
keyMap.set(key, new Set(nodes));
}
else if (typeof value === 'string') {
// npm/yarn: reconstruct ProjectGraphExternalNode
const node = externalNodes[value];
if (node) {
keyMap.set(key, node);
}
}
else {
keyMap.set(key, value);
}
}
return keyMap;
}
function lockFileNeedsReprocessing(lockHash, hashFilePath) {
try {
return (0, fs_1.readFileSync)(hashFilePath).toString() !== lockHash;
}
catch {
return true;
}
}
// External nodes cache functions
function writeExternalNodesCache(hash, nodes, keyMap) {
(0, fs_1.mkdirSync)((0, path_1.dirname)(externalNodesHashFile), { recursive: true });
const serializedKeyMap = serializeKeyMap(keyMap);
const cacheData = { nodes, keyMap: serializedKeyMap };
(0, fs_1.writeFileSync)(externalNodesCache, JSON.stringify(cacheData, null, 2));
(0, fs_1.writeFileSync)(externalNodesHashFile, hash);
}
function readCachedExternalNodes() {
const { nodes, keyMap } = JSON.parse((0, fs_1.readFileSync)(externalNodesCache, 'utf-8'));
return { nodes, keyMap: deserializeKeyMap(keyMap, nodes) };
}
// Dependencies cache functions
function writeDependenciesCache(hash, dependencies) {
(0, fs_1.mkdirSync)((0, path_1.dirname)(dependenciesHashFile), { recursive: true });
(0, fs_1.writeFileSync)(dependenciesCache, JSON.stringify(dependencies, null, 2));
(0, fs_1.writeFileSync)(dependenciesHashFile, hash);
}
function readCachedDependencies() {
return JSON.parse((0, fs_1.readFileSync)(dependenciesCache).toString());
}
// Cache file paths
const externalNodesHashFile = (0, path_1.join)(cache_directory_1.workspaceDataDirectory, 'lockfile-nodes.hash');
const dependenciesHashFile = (0, path_1.join)(cache_directory_1.workspaceDataDirectory, 'lockfile-dependencies.hash');
const externalNodesCache = (0, path_1.join)(cache_directory_1.workspaceDataDirectory, 'parsed-lock-file.nodes.json');
const dependenciesCache = (0, path_1.join)(cache_directory_1.workspaceDataDirectory, 'parsed-lock-file.dependencies.json');