1 | import * as _ from 'lodash';
|
2 |
|
3 | import { MiscellaneousData } from '../interfaces/miscellaneous-data.interface';
|
4 | import { ParsedData } from '../interfaces/parsed-data.interface';
|
5 | import { RouteInterface } from '../interfaces/routes.interface';
|
6 |
|
7 | import AngularApiUtil from '../../utils/angular-api.util';
|
8 | import { IApiSourceResult } from '../../utils/api-source-result.interface';
|
9 | import { getNamesCompareFn } from '../../utils/utils';
|
10 |
|
11 | import {
|
12 | IEnumDecDep,
|
13 | IFunctionDecDep,
|
14 | IGuardDep,
|
15 | IInjectableDep,
|
16 | IInterceptorDep,
|
17 | IInterfaceDep,
|
18 | IPipeDep,
|
19 | ITypeAliasDecDep
|
20 | } from '../compiler/angular/dependencies.interfaces';
|
21 |
|
22 | import { IComponentDep } from '../compiler/angular/deps/component-dep.factory';
|
23 | import { IControllerDep } from '../compiler/angular/deps/controller-dep.factory';
|
24 | import { IDirectiveDep } from '../compiler/angular/deps/directive-dep.factory';
|
25 | import { IModuleDep } from '../compiler/angular/deps/module-dep.factory';
|
26 |
|
27 | const traverse = require('traverse');
|
28 |
|
29 | export class DependenciesEngine {
|
30 | public rawData: ParsedData;
|
31 | public modules: Object[];
|
32 | public rawModules: Object[];
|
33 | public rawModulesForOverview: Object[];
|
34 | public components: Object[];
|
35 | public controllers: Object[];
|
36 | public entities: Object[];
|
37 | public directives: Object[];
|
38 | public injectables: Object[];
|
39 | public interceptors: Object[];
|
40 | public guards: Object[];
|
41 | public interfaces: Object[];
|
42 | public routes: RouteInterface;
|
43 | public pipes: Object[];
|
44 | public classes: Object[];
|
45 | public miscellaneous: MiscellaneousData = {
|
46 | variables: [],
|
47 | functions: [],
|
48 | typealiases: [],
|
49 | enumerations: [],
|
50 | groupedVariables: [],
|
51 | groupedFunctions: [],
|
52 | groupedEnumerations: [],
|
53 | groupedTypeAliases: []
|
54 | };
|
55 |
|
56 | private static instance: DependenciesEngine;
|
57 | private constructor() {}
|
58 | public static getInstance() {
|
59 | if (!DependenciesEngine.instance) {
|
60 | DependenciesEngine.instance = new DependenciesEngine();
|
61 | }
|
62 | return DependenciesEngine.instance;
|
63 | }
|
64 |
|
65 | private updateModulesDeclarationsExportsTypes() {
|
66 | let mergeTypes = entry => {
|
67 | let directive = this.findInCompodocDependencies(
|
68 | entry.name,
|
69 | this.directives,
|
70 | entry.file
|
71 | );
|
72 | if (typeof directive.data !== 'undefined') {
|
73 | entry.type = 'directive';
|
74 | entry.id = directive.data.id;
|
75 | }
|
76 |
|
77 | let component = this.findInCompodocDependencies(
|
78 | entry.name,
|
79 | this.components,
|
80 | entry.file
|
81 | );
|
82 | if (typeof component.data !== 'undefined') {
|
83 | entry.type = 'component';
|
84 | entry.id = component.data.id;
|
85 | }
|
86 |
|
87 | let pipe = this.findInCompodocDependencies(entry.name, this.pipes, entry.file);
|
88 | if (typeof pipe.data !== 'undefined') {
|
89 | entry.type = 'pipe';
|
90 | entry.id = pipe.data.id;
|
91 | }
|
92 | };
|
93 |
|
94 | this.modules.forEach(module => {
|
95 | module.declarations.forEach(declaration => {
|
96 | mergeTypes(declaration);
|
97 | });
|
98 | module.exports.forEach(expt => {
|
99 | mergeTypes(expt);
|
100 | });
|
101 | module.entryComponents.forEach(ent => {
|
102 | mergeTypes(ent);
|
103 | });
|
104 | });
|
105 | }
|
106 |
|
107 | public init(data: ParsedData) {
|
108 | traverse(data).forEach(function (node) {
|
109 | if (node) {
|
110 | if (node.parent) {
|
111 | delete node.parent;
|
112 | }
|
113 | if (node.initializer) {
|
114 | delete node.initializer;
|
115 | }
|
116 | }
|
117 | });
|
118 | this.rawData = data;
|
119 | this.modules = _.sortBy(this.rawData.modules, [el => el.name.toLowerCase()]);
|
120 | this.rawModulesForOverview = _.sortBy(data.modulesForGraph, [el => el.name.toLowerCase()]);
|
121 | this.rawModules = _.sortBy(data.modulesForGraph, [el => el.name.toLowerCase()]);
|
122 | this.components = _.sortBy(this.rawData.components, [el => el.name.toLowerCase()]);
|
123 | this.controllers = _.sortBy(this.rawData.controllers, [el => el.name.toLowerCase()]);
|
124 | this.entities = _.sortBy(this.rawData.entities, [el => el.name.toLowerCase()]);
|
125 | this.directives = _.sortBy(this.rawData.directives, [el => el.name.toLowerCase()]);
|
126 | this.injectables = _.sortBy(this.rawData.injectables, [el => el.name.toLowerCase()]);
|
127 | this.interceptors = _.sortBy(this.rawData.interceptors, [el => el.name.toLowerCase()]);
|
128 | this.guards = _.sortBy(this.rawData.guards, [el => el.name.toLowerCase()]);
|
129 | this.interfaces = _.sortBy(this.rawData.interfaces, [el => el.name.toLowerCase()]);
|
130 | this.pipes = _.sortBy(this.rawData.pipes, [el => el.name.toLowerCase()]);
|
131 | this.classes = _.sortBy(this.rawData.classes, [el => el.name.toLowerCase()]);
|
132 | this.miscellaneous = this.rawData.miscellaneous;
|
133 | this.prepareMiscellaneous();
|
134 | this.updateModulesDeclarationsExportsTypes();
|
135 | this.routes = this.rawData.routesTree;
|
136 | this.manageDuplicatesName();
|
137 | this.cleanRawModulesNames();
|
138 | }
|
139 |
|
140 | private cleanRawModulesNames() {
|
141 | this.rawModulesForOverview = this.rawModulesForOverview.map(module => {
|
142 | module.name = module.name.replace('$', '');
|
143 | return module;
|
144 | });
|
145 | }
|
146 |
|
147 | private findInCompodocDependencies(name, data, file?): IApiSourceResult<any> {
|
148 | let _result = {
|
149 | source: 'internal',
|
150 | data: undefined
|
151 | };
|
152 | let nameFoundCounter = 0;
|
153 | if (data && data.length > 0) {
|
154 | for (let i = 0; i < data.length; i++) {
|
155 | if (typeof name !== 'undefined') {
|
156 | if (typeof file !== 'undefined') {
|
157 | if (
|
158 | name.indexOf(data[i].name) !== -1 &&
|
159 | file.replace(/\\/g, '/').indexOf(data[i].file) !== -1
|
160 | ) {
|
161 | nameFoundCounter += 1;
|
162 | _result.data = data[i];
|
163 | }
|
164 | } else {
|
165 | if (name.indexOf(data[i].name) !== -1) {
|
166 | nameFoundCounter += 1;
|
167 | _result.data = data[i];
|
168 | }
|
169 | }
|
170 | }
|
171 | }
|
172 |
|
173 |
|
174 | if (nameFoundCounter > 1) {
|
175 | let found = false;
|
176 | for (let i = 0; i < data.length; i++) {
|
177 | if (typeof name !== 'undefined') {
|
178 | if (typeof file !== 'undefined') {
|
179 | if (
|
180 | name === data[i].name &&
|
181 | file.replace(/\\/g, '/').indexOf(data[i].file) !== -1
|
182 | ) {
|
183 | found = true;
|
184 | _result.data = data[i];
|
185 | }
|
186 | } else {
|
187 | if (name === data[i].name) {
|
188 | found = true;
|
189 | _result.data = data[i];
|
190 | }
|
191 | }
|
192 | }
|
193 | }
|
194 | if (!found) {
|
195 | _result = {
|
196 | source: 'internal',
|
197 | data: undefined
|
198 | };
|
199 | }
|
200 | }
|
201 | }
|
202 | return _result;
|
203 | }
|
204 |
|
205 | private manageDuplicatesName() {
|
206 | let processDuplicates = (element, index, array) => {
|
207 | let elementsWithSameName = _.filter(array, { name: element.name });
|
208 | if (elementsWithSameName.length > 1) {
|
209 |
|
210 | for (let i = 1; i < elementsWithSameName.length; i++) {
|
211 | let elementToEdit = elementsWithSameName[i];
|
212 | if (typeof elementToEdit.isDuplicate === 'undefined') {
|
213 | elementToEdit.isDuplicate = true;
|
214 | elementToEdit.duplicateId = i;
|
215 | elementToEdit.duplicateName =
|
216 | elementToEdit.name + '-' + elementToEdit.duplicateId;
|
217 | elementToEdit.id = elementToEdit.id + '-' + elementToEdit.duplicateId;
|
218 | }
|
219 | }
|
220 | }
|
221 | return element;
|
222 | };
|
223 | this.classes = this.classes.map(processDuplicates);
|
224 | this.interfaces = this.interfaces.map(processDuplicates);
|
225 | this.injectables = this.injectables.map(processDuplicates);
|
226 | this.pipes = this.pipes.map(processDuplicates);
|
227 | this.interceptors = this.interceptors.map(processDuplicates);
|
228 | this.guards = this.guards.map(processDuplicates);
|
229 | this.modules = this.modules.map(processDuplicates);
|
230 | this.components = this.components.map(processDuplicates);
|
231 | this.controllers = this.controllers.map(processDuplicates);
|
232 | this.entities = this.entities.map(processDuplicates);
|
233 | this.directives = this.directives.map(processDuplicates);
|
234 | }
|
235 |
|
236 | public find(name: string): IApiSourceResult<any> | undefined {
|
237 | const searchFunctions: Array<() => IApiSourceResult<any>> = [
|
238 | () => this.findInCompodocDependencies(name, this.injectables),
|
239 | () => this.findInCompodocDependencies(name, this.interceptors),
|
240 | () => this.findInCompodocDependencies(name, this.guards),
|
241 | () => this.findInCompodocDependencies(name, this.interfaces),
|
242 | () => this.findInCompodocDependencies(name, this.classes),
|
243 | () => this.findInCompodocDependencies(name, this.components),
|
244 | () => this.findInCompodocDependencies(name, this.controllers),
|
245 | () => this.findInCompodocDependencies(name, this.entities),
|
246 | () => this.findInCompodocDependencies(name, this.directives),
|
247 | () => this.findInCompodocDependencies(name, this.miscellaneous.variables),
|
248 | () => this.findInCompodocDependencies(name, this.miscellaneous.functions),
|
249 | () => this.findInCompodocDependencies(name, this.miscellaneous.typealiases),
|
250 | () => this.findInCompodocDependencies(name, this.miscellaneous.enumerations),
|
251 | () => AngularApiUtil.findApi(name)
|
252 | ];
|
253 |
|
254 | for (let searchFunction of searchFunctions) {
|
255 | let result = searchFunction();
|
256 |
|
257 | if (result.data) {
|
258 | return result;
|
259 | }
|
260 | }
|
261 |
|
262 | return undefined;
|
263 | }
|
264 |
|
265 | public update(updatedData): void {
|
266 | if (updatedData.modules.length > 0) {
|
267 | _.forEach(updatedData.modules, (module: IModuleDep) => {
|
268 | const _index = _.findIndex(this.modules, { name: module.name });
|
269 | this.modules[_index] = module;
|
270 | });
|
271 | }
|
272 | if (updatedData.components.length > 0) {
|
273 | _.forEach(updatedData.components, (component: IComponentDep) => {
|
274 | const _index = _.findIndex(this.components, { name: component.name });
|
275 | this.components[_index] = component;
|
276 | });
|
277 | }
|
278 | if (updatedData.controllers.length > 0) {
|
279 | _.forEach(updatedData.controllers, (controller: IControllerDep) => {
|
280 | const _index = _.findIndex(this.controllers, { name: controller.name });
|
281 | this.controllers[_index] = controller;
|
282 | });
|
283 | }
|
284 | if (updatedData.entities.length > 0) {
|
285 | _.forEach(updatedData.entities, (entity: IControllerDep) => {
|
286 | const _index = _.findIndex(this.entities, { name: entity.name });
|
287 | this.entities[_index] = entity;
|
288 | });
|
289 | }
|
290 | if (updatedData.directives.length > 0) {
|
291 | _.forEach(updatedData.directives, (directive: IDirectiveDep) => {
|
292 | const _index = _.findIndex(this.directives, { name: directive.name });
|
293 | this.directives[_index] = directive;
|
294 | });
|
295 | }
|
296 | if (updatedData.injectables.length > 0) {
|
297 | _.forEach(updatedData.injectables, (injectable: IInjectableDep) => {
|
298 | const _index = _.findIndex(this.injectables, { name: injectable.name });
|
299 | this.injectables[_index] = injectable;
|
300 | });
|
301 | }
|
302 | if (updatedData.interceptors.length > 0) {
|
303 | _.forEach(updatedData.interceptors, (interceptor: IInterceptorDep) => {
|
304 | const _index = _.findIndex(this.interceptors, { name: interceptor.name });
|
305 | this.interceptors[_index] = interceptor;
|
306 | });
|
307 | }
|
308 | if (updatedData.guards.length > 0) {
|
309 | _.forEach(updatedData.guards, (guard: IGuardDep) => {
|
310 | const _index = _.findIndex(this.guards, { name: guard.name });
|
311 | this.guards[_index] = guard;
|
312 | });
|
313 | }
|
314 | if (updatedData.interfaces.length > 0) {
|
315 | _.forEach(updatedData.interfaces, (int: IInterfaceDep) => {
|
316 | const _index = _.findIndex(this.interfaces, { name: int.name });
|
317 | this.interfaces[_index] = int;
|
318 | });
|
319 | }
|
320 | if (updatedData.pipes.length > 0) {
|
321 | _.forEach(updatedData.pipes, (pipe: IPipeDep) => {
|
322 | const _index = _.findIndex(this.pipes, { name: pipe.name });
|
323 | this.pipes[_index] = pipe;
|
324 | });
|
325 | }
|
326 | if (updatedData.classes.length > 0) {
|
327 | _.forEach(updatedData.classes, (classe: any) => {
|
328 | const _index = _.findIndex(this.classes, { name: classe.name });
|
329 | this.classes[_index] = classe;
|
330 | });
|
331 | }
|
332 | |
333 |
|
334 |
|
335 | if (updatedData.miscellaneous.variables.length > 0) {
|
336 | _.forEach(updatedData.miscellaneous.variables, (variable: any) => {
|
337 | const _index = _.findIndex(this.miscellaneous.variables, {
|
338 | name: variable.name,
|
339 | file: variable.file
|
340 | });
|
341 | this.miscellaneous.variables[_index] = variable;
|
342 | });
|
343 | }
|
344 | if (updatedData.miscellaneous.functions.length > 0) {
|
345 | _.forEach(updatedData.miscellaneous.functions, (func: IFunctionDecDep) => {
|
346 | const _index = _.findIndex(this.miscellaneous.functions, {
|
347 | name: func.name,
|
348 | file: func.file
|
349 | });
|
350 | this.miscellaneous.functions[_index] = func;
|
351 | });
|
352 | }
|
353 | if (updatedData.miscellaneous.typealiases.length > 0) {
|
354 | _.forEach(updatedData.miscellaneous.typealiases, (typealias: ITypeAliasDecDep) => {
|
355 | const _index = _.findIndex(this.miscellaneous.typealiases, {
|
356 | name: typealias.name,
|
357 | file: typealias.file
|
358 | });
|
359 | this.miscellaneous.typealiases[_index] = typealias;
|
360 | });
|
361 | }
|
362 | if (updatedData.miscellaneous.enumerations.length > 0) {
|
363 | _.forEach(updatedData.miscellaneous.enumerations, (enumeration: IEnumDecDep) => {
|
364 | const _index = _.findIndex(this.miscellaneous.enumerations, {
|
365 | name: enumeration.name,
|
366 | file: enumeration.file
|
367 | });
|
368 | this.miscellaneous.enumerations[_index] = enumeration;
|
369 | });
|
370 | }
|
371 | this.prepareMiscellaneous();
|
372 | }
|
373 |
|
374 | public findInCompodoc(name: string) {
|
375 | let mergedData = _.concat(
|
376 | [],
|
377 | this.modules,
|
378 | this.components,
|
379 | this.controllers,
|
380 | this.entities,
|
381 | this.directives,
|
382 | this.injectables,
|
383 | this.interceptors,
|
384 | this.guards,
|
385 | this.interfaces,
|
386 | this.pipes,
|
387 | this.classes,
|
388 | this.miscellaneous.enumerations,
|
389 | this.miscellaneous.typealiases,
|
390 | this.miscellaneous.variables,
|
391 | this.miscellaneous.functions
|
392 | );
|
393 | let result = _.find(mergedData, { name: name } as any);
|
394 | return result || false;
|
395 | }
|
396 |
|
397 | private prepareMiscellaneous() {
|
398 | this.miscellaneous.variables.sort(getNamesCompareFn());
|
399 | this.miscellaneous.functions.sort(getNamesCompareFn());
|
400 | this.miscellaneous.enumerations.sort(getNamesCompareFn());
|
401 | this.miscellaneous.typealiases.sort(getNamesCompareFn());
|
402 |
|
403 | this.miscellaneous.groupedVariables = _.groupBy(this.miscellaneous.variables, 'file');
|
404 | this.miscellaneous.groupedFunctions = _.groupBy(this.miscellaneous.functions, 'file');
|
405 | this.miscellaneous.groupedEnumerations = _.groupBy(this.miscellaneous.enumerations, 'file');
|
406 | this.miscellaneous.groupedTypeAliases = _.groupBy(this.miscellaneous.typealiases, 'file');
|
407 | }
|
408 |
|
409 | public getModule(name: string) {
|
410 | return _.find(this.modules, ['name', name]);
|
411 | }
|
412 |
|
413 | public getRawModule(name: string): any {
|
414 | return _.find(this.rawModules, ['name', name]);
|
415 | }
|
416 |
|
417 | public getModules() {
|
418 | return this.modules;
|
419 | }
|
420 |
|
421 | public getComponents() {
|
422 | return this.components;
|
423 | }
|
424 |
|
425 | public getControllers() {
|
426 | return this.controllers;
|
427 | }
|
428 |
|
429 | public getEntities() {
|
430 | return this.entities;
|
431 | }
|
432 |
|
433 | public getDirectives() {
|
434 | return this.directives;
|
435 | }
|
436 |
|
437 | public getInjectables() {
|
438 | return this.injectables;
|
439 | }
|
440 |
|
441 | public getInterceptors() {
|
442 | return this.interceptors;
|
443 | }
|
444 |
|
445 | public getGuards() {
|
446 | return this.guards;
|
447 | }
|
448 |
|
449 | public getInterfaces() {
|
450 | return this.interfaces;
|
451 | }
|
452 |
|
453 | public getRoutes() {
|
454 | return this.routes;
|
455 | }
|
456 |
|
457 | public getPipes() {
|
458 | return this.pipes;
|
459 | }
|
460 |
|
461 | public getClasses() {
|
462 | return this.classes;
|
463 | }
|
464 |
|
465 | public getMiscellaneous() {
|
466 | return this.miscellaneous;
|
467 | }
|
468 | }
|
469 |
|
470 | export default DependenciesEngine.getInstance();
|