UNPKG

5.45 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const fs = require("fs");
4const ts = require("typescript");
5const glob = require("glob");
6const path = require("path");
7const denodeify = require("denodeify");
8const readFile = denodeify(fs.readFile);
9const globSearch = denodeify(glob);
10/**
11 * Create a SourceFile as defined by Typescript Compiler API.
12 * Generate a AST structure from a source file.
13 *
14 * @param fileName source file for which AST is to be extracted
15 */
16function createTsSourceFile(fileName) {
17 return readFile(fileName, 'utf8')
18 .then((contents) => {
19 return ts.createSourceFile(fileName, contents, ts.ScriptTarget.Latest, true);
20 });
21}
22exports.createTsSourceFile = createTsSourceFile;
23/**
24 * Traverses through AST of a given file of kind 'ts.SourceFile', filters out child
25 * nodes of the kind 'ts.SyntaxKind.ImportDeclaration' and returns import clauses as
26 * ModuleImport[]
27 *
28 * @param {ts.SourceFile} node: Typescript Node of whose AST is being traversed
29 *
30 * @return {ModuleImport[]} traverses through ts.Node and returns an array of moduleSpecifiers.
31 */
32function getImportClauses(node) {
33 return node.statements
34 .filter(node => node.kind === ts.SyntaxKind.ImportDeclaration) // Only Imports.
35 .map((node) => {
36 let moduleSpecifier = node.moduleSpecifier;
37 return {
38 specifierText: moduleSpecifier.getText().slice(1, -1),
39 pos: moduleSpecifier.pos,
40 end: moduleSpecifier.end
41 };
42 });
43}
44exports.getImportClauses = getImportClauses;
45/**
46 * Find the file, 'index.ts' given the directory name and return boolean value
47 * based on its findings.
48 *
49 * @param dirPath
50 *
51 * @return a boolean value after it searches for a barrel (index.ts by convention) in a given path
52 */
53function hasIndexFile(dirPath) {
54 return globSearch(path.join(dirPath, 'index.ts'), { nodir: true })
55 .then((indexFile) => {
56 return indexFile.length > 0;
57 });
58}
59exports.hasIndexFile = hasIndexFile;
60/**
61 * Function to get all the templates, stylesheets, and spec files of a given component unit
62 * Assumption: When any component/service/pipe unit is generated, Angular CLI has a blueprint for
63 * creating associated files with the name of the generated unit. So, there are two
64 * assumptions made:
65 * a. the function only returns associated files that have names matching to the given unit.
66 * b. the function only looks for the associated files in the directory where the given unit
67 * exists.
68 *
69 * @todo read the metadata to look for the associated files of a given file.
70 *
71 * @param fileName
72 *
73 * @return absolute paths of '.html/.css/.sass/.spec.ts' files associated with the given file.
74 *
75 */
76function getAllAssociatedFiles(fileName) {
77 let fileDirName = path.dirname(fileName);
78 let componentName = path.basename(fileName, '.ts');
79 return globSearch(path.join(fileDirName, `${componentName}.*`), { nodir: true })
80 .then((files) => {
81 return files.filter((file) => {
82 return (path.basename(file) !== 'index.ts');
83 });
84 });
85}
86exports.getAllAssociatedFiles = getAllAssociatedFiles;
87/**
88 * Returns a map of all dependent file/s' path with their moduleSpecifier object
89 * (specifierText, pos, end).
90 *
91 * @param fileName file upon which other files depend
92 * @param rootPath root of the project
93 *
94 * @return {Promise<ModuleMap>} ModuleMap of all dependent file/s (specifierText, pos, end)
95 *
96 */
97function getDependentFiles(fileName, rootPath) {
98 return globSearch(path.join(rootPath, '**/*.ts'), { nodir: true })
99 .then((files) => Promise.all(files.map(file => createTsSourceFile(file)))
100 .then((tsFiles) => tsFiles.map(file => getImportClauses(file)))
101 .then((moduleSpecifiers) => {
102 let allFiles = {};
103 files.forEach((file, index) => {
104 let sourcePath = path.normalize(file);
105 allFiles[sourcePath] = moduleSpecifiers[index];
106 });
107 return allFiles;
108 })
109 .then((allFiles) => {
110 let relevantFiles = {};
111 Object.keys(allFiles).forEach(filePath => {
112 const tempModuleSpecifiers = allFiles[filePath]
113 .filter(importClause => {
114 // Filter only relative imports
115 let singleSlash = importClause.specifierText.charAt(0) === '/';
116 let currentDirSyntax = importClause.specifierText.slice(0, 2) === './';
117 let parentDirSyntax = importClause.specifierText.slice(0, 3) === '../';
118 return singleSlash || currentDirSyntax || parentDirSyntax;
119 })
120 .filter(importClause => {
121 let modulePath = path.resolve(path.dirname(filePath), importClause.specifierText);
122 let resolvedFileName = path.resolve(fileName);
123 let fileBaseName = path.basename(resolvedFileName, '.ts');
124 let parsedFilePath = path.join(path.dirname(resolvedFileName), fileBaseName);
125 return (parsedFilePath === modulePath) || (resolvedFileName === modulePath);
126 });
127 if (tempModuleSpecifiers.length > 0) {
128 relevantFiles[filePath] = tempModuleSpecifiers;
129 }
130 ;
131 });
132 return relevantFiles;
133 }));
134}
135exports.getDependentFiles = getDependentFiles;
136//# sourceMappingURL=/users/hans/sources/angular-cli/utilities/get-dependent-files.js.map
\No newline at end of file