UNPKG

13.1 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.isAngularSecondaryEntrypoint = exports.groupImports = exports.isTerminalRun = exports.mapProjectGraphFiles = exports.hasBuildExecutor = exports.isDirectDependency = exports.hasBannedDependencies = exports.findTransitiveExternalDependencies = exports.hasBannedImport = exports.getSourceFilePath = exports.onlyLoadChildren = exports.findConstraintsFor = exports.findProjectUsingImport = exports.isAbsoluteImportIntoAnotherProject = exports.findTargetProject = exports.findSourceProject = exports.findProjectUsingFile = exports.getTargetProjectBasedOnRelativeImport = exports.isRelative = exports.matchImportWithWildcard = exports.removeExt = exports.findDependenciesWithTags = exports.hasNoneOfTheseTags = exports.stringifyTags = void 0;
4const path = require("path");
5const devkit_1 = require("@nrwl/devkit");
6const path_1 = require("path");
7const app_root_1 = require("./app-root");
8const graph_utils_1 = require("./graph-utils");
9const fs_1 = require("fs");
10const file_utils_1 = require("nx/src/project-graph/file-utils");
11function stringifyTags(tags) {
12 return tags.map((t) => `"${t}"`).join(', ');
13}
14exports.stringifyTags = stringifyTags;
15function hasNoneOfTheseTags(proj, tags) {
16 return tags.filter((tag) => hasTag(proj, tag)).length === 0;
17}
18exports.hasNoneOfTheseTags = hasNoneOfTheseTags;
19/**
20 * Check if any of the given tags is included in the project
21 * @param proj ProjectGraphProjectNode
22 * @param tags
23 * @returns
24 */
25function findDependenciesWithTags(targetProject, tags, graph) {
26 // find all reachable projects that have one of the tags and
27 // are reacheable from the targetProject (including self)
28 const allReachableProjects = Object.keys(graph.nodes).filter((projectName) => (0, graph_utils_1.pathExists)(graph, targetProject.name, projectName) &&
29 tags.some((tag) => hasTag(graph.nodes[projectName], tag)));
30 // return path from targetProject to reachable project
31 return allReachableProjects.map((project) => targetProject.name === project
32 ? [targetProject]
33 : (0, graph_utils_1.getPath)(graph, targetProject.name, project));
34}
35exports.findDependenciesWithTags = findDependenciesWithTags;
36function hasTag(proj, tag) {
37 return tag === '*' || (proj.data.tags || []).indexOf(tag) > -1;
38}
39function removeExt(file) {
40 return file.replace(/(?<!(^|\/))\.[^/.]+$/, '');
41}
42exports.removeExt = removeExt;
43function matchImportWithWildcard(
44// This may or may not contain wildcards ("*")
45allowableImport, extractedImport) {
46 if (allowableImport.endsWith('/**')) {
47 const prefix = allowableImport.substring(0, allowableImport.length - 2);
48 return extractedImport.startsWith(prefix);
49 }
50 else if (allowableImport.endsWith('/*')) {
51 const prefix = allowableImport.substring(0, allowableImport.length - 1);
52 if (!extractedImport.startsWith(prefix))
53 return false;
54 return extractedImport.substring(prefix.length).indexOf('/') === -1;
55 }
56 else if (allowableImport.indexOf('/**/') > -1) {
57 const [prefix, suffix] = allowableImport.split('/**/');
58 return (extractedImport.startsWith(prefix) && extractedImport.endsWith(suffix));
59 }
60 else {
61 return new RegExp(allowableImport).test(extractedImport);
62 }
63}
64exports.matchImportWithWildcard = matchImportWithWildcard;
65function isRelative(s) {
66 return s.startsWith('.');
67}
68exports.isRelative = isRelative;
69function getTargetProjectBasedOnRelativeImport(imp, projectPath, projectGraph, sourceFilePath) {
70 if (!isRelative(imp)) {
71 return undefined;
72 }
73 const sourceDir = path.join(projectPath, path.dirname(sourceFilePath));
74 const targetFile = (0, devkit_1.normalizePath)(path.resolve(sourceDir, imp)).substring(projectPath.length + 1);
75 return findTargetProject(projectGraph, targetFile);
76}
77exports.getTargetProjectBasedOnRelativeImport = getTargetProjectBasedOnRelativeImport;
78function findProjectUsingFile(projectGraph, file) {
79 return projectGraph.nodes[projectGraph.allFiles[file]];
80}
81exports.findProjectUsingFile = findProjectUsingFile;
82function findSourceProject(projectGraph, sourceFilePath) {
83 const targetFile = removeExt(sourceFilePath);
84 return findProjectUsingFile(projectGraph, targetFile);
85}
86exports.findSourceProject = findSourceProject;
87function findTargetProject(projectGraph, targetFile) {
88 let targetProject = findProjectUsingFile(projectGraph, targetFile);
89 if (!targetProject) {
90 targetProject = findProjectUsingFile(projectGraph, (0, devkit_1.normalizePath)(path.join(targetFile, 'index')));
91 }
92 if (!targetProject) {
93 targetProject = findProjectUsingFile(projectGraph, (0, devkit_1.normalizePath)(path.join(targetFile, 'src', 'index')));
94 }
95 return targetProject;
96}
97exports.findTargetProject = findTargetProject;
98function isAbsoluteImportIntoAnotherProject(imp, workspaceLayout = { libsDir: 'libs', appsDir: 'apps' }) {
99 return (imp.startsWith(`${workspaceLayout.libsDir}/`) ||
100 imp.startsWith(`/${workspaceLayout.libsDir}/`) ||
101 imp.startsWith(`${workspaceLayout.appsDir}/`) ||
102 imp.startsWith(`/${workspaceLayout.appsDir}/`));
103}
104exports.isAbsoluteImportIntoAnotherProject = isAbsoluteImportIntoAnotherProject;
105function findProjectUsingImport(projectGraph, targetProjectLocator, filePath, imp) {
106 var _a;
107 const target = targetProjectLocator.findProjectWithImport(imp, filePath);
108 return projectGraph.nodes[target] || ((_a = projectGraph.externalNodes) === null || _a === void 0 ? void 0 : _a[target]);
109}
110exports.findProjectUsingImport = findProjectUsingImport;
111function findConstraintsFor(depConstraints, sourceProject) {
112 return depConstraints.filter((f) => hasTag(sourceProject, f.sourceTag));
113}
114exports.findConstraintsFor = findConstraintsFor;
115function onlyLoadChildren(graph, sourceProjectName, targetProjectName, visited) {
116 if (visited.indexOf(sourceProjectName) > -1)
117 return false;
118 return ((graph.dependencies[sourceProjectName] || []).filter((d) => {
119 if (d.type !== devkit_1.DependencyType.dynamic)
120 return false;
121 if (d.target === targetProjectName)
122 return true;
123 return onlyLoadChildren(graph, d.target, targetProjectName, [
124 ...visited,
125 sourceProjectName,
126 ]);
127 }).length > 0);
128}
129exports.onlyLoadChildren = onlyLoadChildren;
130function getSourceFilePath(sourceFileName, projectPath) {
131 const relativePath = sourceFileName.slice(projectPath.length + 1);
132 return (0, devkit_1.normalizePath)(relativePath);
133}
134exports.getSourceFilePath = getSourceFilePath;
135/**
136 * Find constraint (if any) that explicitly banns the given target npm project
137 * @param externalProject
138 * @param depConstraints
139 * @returns
140 */
141function isConstraintBanningProject(externalProject, constraint) {
142 return constraint.bannedExternalImports.some((importDefinition) => parseImportWildcards(importDefinition).test(externalProject.data.packageName));
143}
144function hasBannedImport(source, target, depConstraints) {
145 // return those constraints that match source project and have `bannedExternalImports` defined
146 depConstraints = depConstraints.filter((c) => (source.data.tags || []).includes(c.sourceTag) &&
147 c.bannedExternalImports &&
148 c.bannedExternalImports.length);
149 return depConstraints.find((constraint) => isConstraintBanningProject(target, constraint));
150}
151exports.hasBannedImport = hasBannedImport;
152/**
153 * Find all unique (transitive) external dependencies of given project
154 * @param graph
155 * @param source
156 * @returns
157 */
158function findTransitiveExternalDependencies(graph, source) {
159 if (!graph.externalNodes) {
160 return [];
161 }
162 const allReachableProjects = [];
163 const allProjects = Object.keys(graph.nodes);
164 for (let i = 0; i < allProjects.length; i++) {
165 if ((0, graph_utils_1.pathExists)(graph, source.name, allProjects[i])) {
166 allReachableProjects.push(allProjects[i]);
167 }
168 }
169 const externalDependencies = [];
170 for (let i = 0; i < allReachableProjects.length; i++) {
171 const dependencies = graph.dependencies[allReachableProjects[i]];
172 if (dependencies) {
173 for (let d = 0; d < dependencies.length; d++) {
174 const dependency = dependencies[d];
175 if (graph.externalNodes[dependency.target]) {
176 externalDependencies.push(dependency);
177 }
178 }
179 }
180 }
181 return externalDependencies;
182}
183exports.findTransitiveExternalDependencies = findTransitiveExternalDependencies;
184/**
185 * Check if
186 * @param externalDependencies
187 * @param graph
188 * @param depConstraint
189 * @returns
190 */
191function hasBannedDependencies(externalDependencies, graph, depConstraint) {
192 return externalDependencies
193 .filter((dependency) => isConstraintBanningProject(graph.externalNodes[dependency.target], depConstraint))
194 .map((dep) => [
195 graph.externalNodes[dep.target],
196 graph.nodes[dep.source],
197 depConstraint,
198 ]);
199}
200exports.hasBannedDependencies = hasBannedDependencies;
201function isDirectDependency(target) {
202 const fileName = 'package.json';
203 const content = (0, file_utils_1.readFileIfExisting)((0, path_1.join)(app_root_1.workspaceRoot, fileName));
204 if (content) {
205 const { dependencies, devDependencies, peerDependencies } = (0, devkit_1.parseJson)(content);
206 if (dependencies && dependencies[target.data.packageName]) {
207 return true;
208 }
209 if (peerDependencies && peerDependencies[target.data.packageName]) {
210 return true;
211 }
212 if (devDependencies && devDependencies[target.data.packageName]) {
213 return true;
214 }
215 return false;
216 }
217 return true;
218}
219exports.isDirectDependency = isDirectDependency;
220/**
221 * Maps import with wildcards to regex pattern
222 * @param importDefinition
223 * @returns
224 */
225function parseImportWildcards(importDefinition) {
226 const mappedWildcards = importDefinition.split('*').join('.*');
227 return new RegExp(`^${new RegExp(mappedWildcards).source}$`);
228}
229/**
230 * Verifies whether the given node has an architect builder attached
231 * @param projectGraph the node to verify
232 */
233function hasBuildExecutor(projectGraph) {
234 return (
235 // can the architect not be defined? real use case?
236 projectGraph.data.targets &&
237 projectGraph.data.targets.build &&
238 projectGraph.data.targets.build.executor !== '');
239}
240exports.hasBuildExecutor = hasBuildExecutor;
241function mapProjectGraphFiles(projectGraph) {
242 if (!projectGraph) {
243 return null;
244 }
245 const allFiles = {};
246 Object.entries(projectGraph.nodes).forEach(([name, node]) => {
247 node.data.files.forEach(({ file }) => {
248 const fileName = removeExt(file);
249 allFiles[fileName] = name;
250 });
251 });
252 return Object.assign(Object.assign({}, projectGraph), { allFiles });
253}
254exports.mapProjectGraphFiles = mapProjectGraphFiles;
255const ESLINT_REGEX = /node_modules.*[\/\\]eslint$/;
256const NRWL_CLI_REGEX = /nx[\/\\]bin[\/\\]run-executor\.js$/;
257function isTerminalRun() {
258 return (process.argv.length > 1 &&
259 (!!process.argv[1].match(NRWL_CLI_REGEX) ||
260 !!process.argv[1].match(ESLINT_REGEX)));
261}
262exports.isTerminalRun = isTerminalRun;
263/**
264 * Takes an array of imports and tries to group them, so rather than having
265 * `import { A } from './some-location'` and `import { B } from './some-location'` you get
266 * `import { A, B } from './some-location'`
267 * @param importsToRemap
268 * @returns
269 */
270function groupImports(importsToRemap) {
271 const importsToRemapGrouped = importsToRemap.reduce((acc, curr) => {
272 const existing = acc.find((i) => i.importPath === curr.importPath && i.member !== curr.member);
273 if (existing) {
274 if (existing.member) {
275 existing.member += `, ${curr.member}`;
276 }
277 }
278 else {
279 acc.push({
280 importPath: curr.importPath,
281 member: curr.member,
282 });
283 }
284 return acc;
285 }, []);
286 return importsToRemapGrouped
287 .map((entry) => `import { ${entry.member} } from '${entry.importPath}';`)
288 .join('\n');
289}
290exports.groupImports = groupImports;
291/**
292 * Checks if import points to a secondary entry point in Angular project
293 * @param targetProjectLocator
294 * @param importExpr
295 * @returns
296 */
297function isAngularSecondaryEntrypoint(targetProjectLocator, importExpr) {
298 const targetFiles = targetProjectLocator.findPaths(importExpr);
299 return (targetFiles &&
300 targetFiles.some((file) =>
301 // The `ng-packagr` defaults to the `src/public_api.ts` entry file to
302 // the public API if the `lib.entryFile` is not specified explicitly.
303 (file.endsWith('src/public_api.ts') || file.endsWith('src/index.ts')) &&
304 (0, fs_1.existsSync)((0, devkit_1.joinPathFragments)(file, '../../', 'ng-package.json'))));
305}
306exports.isAngularSecondaryEntrypoint = isAngularSecondaryEntrypoint;
307//# sourceMappingURL=runtime-lint-utils.js.map
\No newline at end of file