UNPKG

@nx/js

Version:

The JS plugin for Nx contains executors and generators that provide the best experience for developing JavaScript and TypeScript projects.

164 lines (163 loc) • 8.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.findNpmDependencies = findNpmDependencies; const path_1 = require("path"); const configuration_1 = require("nx/src/config/configuration"); const devkit_1 = require("@nx/devkit"); const fileutils_1 = require("nx/src/utils/fileutils"); const project_graph_1 = require("nx/src/config/project-graph"); const ts_config_1 = require("./typescript/ts-config"); const task_hasher_1 = require("nx/src/hasher/task-hasher"); /** * Finds all npm dependencies and their expected versions for a given project. */ function findNpmDependencies(workspaceRoot, sourceProject, projectGraph, projectFileMap, buildTarget, options = {}) { let seen = null; if (options.includeTransitiveDependencies) { seen = new Set(); } const results = {}; function collectAll(currentProject, collectedDeps) { if (seen?.has(currentProject.name)) return; seen?.add(currentProject.name); collectDependenciesFromFileMap(workspaceRoot, currentProject, projectGraph, projectFileMap, buildTarget, options.ignoredFiles, options.useLocalPathsForWorkspaceDependencies, collectedDeps); collectHelperDependencies(workspaceRoot, currentProject, projectGraph, buildTarget, options.runtimeHelpers, collectedDeps); if (options.includeTransitiveDependencies) { const projectDeps = projectGraph.dependencies[currentProject.name]; for (const dep of projectDeps) { const projectDep = projectGraph.nodes[dep.target]; if (projectDep) collectAll(projectDep, collectedDeps); } } } collectAll(sourceProject, results); return results; } // Keep track of workspace libs we already read package.json for so we don't read from disk again. const seenWorkspaceDeps = {}; function collectDependenciesFromFileMap(workspaceRoot, sourceProject, projectGraph, projectFileMap, buildTarget, ignoredFiles, useLocalPathsForWorkspaceDependencies, npmDeps) { const rawFiles = projectFileMap[sourceProject.name]; if (!rawFiles) return; // If build target does not exist in project, use all files as input. // This is needed for transitive dependencies for apps -- where libs may not be buildable. const inputs = sourceProject.data.targets[buildTarget] ? (0, task_hasher_1.getTargetInputs)((0, configuration_1.readNxJson)(), sourceProject, buildTarget).selfInputs : ['{projectRoot}/**/*']; if (ignoredFiles) { for (const pattern of ignoredFiles) { inputs.push(`!${pattern}`); } } const files = (0, task_hasher_1.filterUsingGlobPatterns)(sourceProject.data.root, projectFileMap[sourceProject.name] || [], inputs); for (const fileData of files) { if (!fileData.deps || fileData.file === (0, devkit_1.joinPathFragments)(sourceProject.data.root, 'package.json')) { continue; } for (const dep of fileData.deps) { const target = (0, project_graph_1.fileDataDepTarget)(dep); // If the node is external, then read package info from `data`. const externalDep = projectGraph.externalNodes[target]; if (externalDep?.type === 'npm') { npmDeps[externalDep.data.packageName] = externalDep.data.version; continue; } // If node is internal, then try reading package info from `package.json` (which must exist for this to work). const workspaceDep = projectGraph.nodes[target]; if (!workspaceDep) continue; const cached = seenWorkspaceDeps[workspaceDep.name]; if (cached) { npmDeps[cached.name] = cached.version; } else { const packageJson = readPackageJson(workspaceDep, workspaceRoot); if ( // Check that this is a buildable project, otherwise it cannot be a dependency in package.json. workspaceDep.data.targets[buildTarget] && // Make sure package.json exists and has a valid name. packageJson?.name) { let version; if (useLocalPathsForWorkspaceDependencies) { // Find the relative `file:...` path and use that as the version value. // This is useful for monorepos like Nx where the release will handle setting the correct version in dist. const depRoot = (0, path_1.join)(workspaceRoot, workspaceDep.data.root); const ownRoot = (0, path_1.join)(workspaceRoot, sourceProject.data.root); const relativePath = (0, path_1.relative)(ownRoot, depRoot); const filePath = (0, devkit_1.normalizePath)(relativePath); // normalize slashes for windows version = `file:${filePath}`; } else { // Otherwise, read the version from the dependencies `package.json` file. // This is useful for monorepos that commit release versions. // Users can also set version as "*" in source `package.json` files, which will be the value set here. // This is useful if they use custom scripts to update them in dist. version = packageJson.version ?? '*'; // fallback in case version is missing } npmDeps[packageJson.name] = version; seenWorkspaceDeps[workspaceDep.name] = { name: packageJson.name, version, }; } } } } } function readPackageJson(project, workspaceRoot) { const packageJsonPath = (0, path_1.join)(workspaceRoot, project.data.root, 'package.json'); if ((0, fileutils_1.fileExists)(packageJsonPath)) return (0, devkit_1.readJsonFile)(packageJsonPath); return null; } function collectHelperDependencies(workspaceRoot, sourceProject, projectGraph, buildTarget, runtimeHelpers, npmDeps) { if (runtimeHelpers?.length > 0) { for (const helper of runtimeHelpers) { if (!npmDeps[helper] && projectGraph.externalNodes[`npm:${helper}`]?.type === 'npm') { npmDeps[helper] = projectGraph.externalNodes[`npm:${helper}`].data.version; } } return; } const target = sourceProject.data.targets[buildTarget]; if (!target) return; if (target.executor === '@nx/js:tsc' && target.options?.tsConfig) { const tsConfig = (0, ts_config_1.readTsConfig)((0, path_1.join)(workspaceRoot, target.options.tsConfig)); if (tsConfig?.options['importHelpers'] && projectGraph.externalNodes['npm:tslib']?.type === 'npm') { npmDeps['tslib'] = projectGraph.externalNodes['npm:tslib'].data.version; } } if (target.executor === '@nx/js:swc') { const swcConfigPath = target.options.swcrc ? (0, path_1.join)(workspaceRoot, target.options.swcrc) : (0, path_1.join)(workspaceRoot, sourceProject.data.root, '.swcrc'); const swcConfig = (0, fileutils_1.fileExists)(swcConfigPath) ? (0, devkit_1.readJsonFile)(swcConfigPath) : {}; if (swcConfig?.jsc?.externalHelpers && projectGraph.externalNodes['npm:@swc/helpers']?.type === 'npm') { npmDeps['@swc/helpers'] = projectGraph.externalNodes['npm:@swc/helpers'].data.version; } } // For inferred targets or manually added run-commands, check if user is using `tsc` in build target. if (target.executor === 'nx:run-commands' && /\btsc\b/.test(target.options.command)) { const tsConfigFileName = (0, ts_config_1.getRootTsConfigFileName)(); if (tsConfigFileName) { const tsConfig = (0, ts_config_1.readTsConfig)((0, path_1.join)(workspaceRoot, tsConfigFileName)); if (tsConfig?.options['importHelpers'] && projectGraph.externalNodes['npm:tslib']?.type === 'npm') { npmDeps['tslib'] = projectGraph.externalNodes['npm:tslib'].data.version; } } } }