UNPKG

18.3 kBPlain TextView Raw
1import * as _ from 'lodash';
2
3import { MiscellaneousData } from '../interfaces/miscellaneous-data.interface';
4import { ParsedData } from '../interfaces/parsed-data.interface';
5import { RouteInterface } from '../interfaces/routes.interface';
6
7import AngularApiUtil from '../../utils/angular-api.util';
8import { IApiSourceResult } from '../../utils/api-source-result.interface';
9import { getNamesCompareFn } from '../../utils/utils';
10
11import {
12 IEnumDecDep,
13 IFunctionDecDep,
14 IGuardDep,
15 IInjectableDep,
16 IInterceptorDep,
17 IInterfaceDep,
18 IPipeDep,
19 ITypeAliasDecDep
20} from '../compiler/angular/dependencies.interfaces';
21
22import { IComponentDep } from '../compiler/angular/deps/component-dep.factory';
23import { IControllerDep } from '../compiler/angular/deps/controller-dep.factory';
24import { IDirectiveDep } from '../compiler/angular/deps/directive-dep.factory';
25import { IModuleDep } from '../compiler/angular/deps/module-dep.factory';
26
27const traverse = require('traverse');
28
29export 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 // Prevent wrong matching like MultiSelectOptionDirective with SelectOptionDirective, or QueryParamGroupService with QueryParamGroup
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 // First element is the reference for duplicates
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 * Miscellaneous update
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 // group each subgoup by file
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
470export default DependenciesEngine.getInstance();