forked from yantrashala/loopback-component-visualizer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
142 lines (117 loc) · 4.58 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
'use strict';
module.exports = visualize;
var _defaults = require('lodash').defaults;
function visualize(loopbackApp, options) {
options = _defaults({}, options, {
mountPath: '/visualize',
});
loopbackApp.use(options.mountPath, createDiagram(loopbackApp, options));
}
function createDiagram(app, options) {
var finalObj = prepareJson(app);
return respond(finalObj, app);
}
function prepareJson(app) {
var models = (app && app.models && app.models()) || {};
var remotes = (app && app.remoteObjects && app.remoteObjects()) || {};
var level = 0;
var x = 0;
var propArr = [];
var edgeArr = [];
var idx = 0;
var modIdxObj = {};
var finalObj = {};
for (var i in models) {
modIdxObj[models[i].modelName] = i;
}
models.length && models.forEach(function (Model) {
var remotes = [];
Model.sharedClass.methods().forEach(function (method) {
remotes.push(method.name);
});
var modelDefinition = app.models[Model.modelName].definition;
if (modelDefinition && modelDefinition.properties) {
var propObj = {};
propObj.id = idx;
propObj.label = Model.modelName;
propObj.props = '<ul><li>' + Object.keys(modelDefinition.properties).toString().split(',').join('<li>\n').replace('"', '') + '</ul>';
propObj.level = level;
propObj.remotes = remotes && '<ul><li>' + remotes.toString().split(',').join('<li>\n').replace('"', '') + '</ul>';
propArr.push(propObj);
x++;
if (x == 5) {
x = 0;
level++;
}
}
//edges
if (Model.settings.relations) {
var relArr = Object.keys(Model.settings.relations);
for (var rel in relArr) {
var relObj = Model.settings.relations[relArr[rel]];
if (relObj.model) {
var edgeObj = {};
edgeObj.from = modIdxObj[Model.modelName];
edgeObj.to = modIdxObj[relObj.model];
edgeObj.label = relArr[rel];
edgeObj.model = relObj.model;
edgeObj.type = relObj.type;
edgeObj.foreignKey = relObj.foreignKey;
edgeObj.options = relObj.options;
edgeObj.through = relObj.through;
edgeObj.title = Model.modelName + " " + relObj.type + " " + relObj.model;
if (relObj.through) edgeObj.title += " (through " + edgeObj.through + ")";
//default length and arrow direction
edgeObj.length = 100;
edgeObj.arrows = 'to';
//show middle circle if relation has a through object
if (relObj.through) {
//extend through relation edge lenght so it embraces the middle node
edgeObj.length = 300;
edgeObj.arrows = {
'middle': {
'enabled': true,
'type': 'circle'
},
'to': {
'enabled': true,
'type': 'arrow'
}
};
}
if (relObj.type == "belongsTo") {
//represent a belongsTo relation with a dashed line
edgeObj.dashes = true;
}
if (relObj.type == "hasAndBelongsToMany") {
//draw a many to many relation with double arrows
edgeObj.arrows = {
'from': {
'enabled': true,
'type': 'arrow'
},
'to': {
'enabled': true,
'type': 'arrow'
}
};
}
edgeArr.push(edgeObj);
}
}
}
idx++;
});
finalObj.nodes = propArr;
finalObj.edges = edgeArr;
return finalObj;
}
function respond(finalObj, app) {
return function (req, res, next) {
var data = finalObj || {};
var render = app.loopback.template(__dirname + '/template.ejs');
var html = render(data);
res.send(200, html);
};
}
module.exports.prepareJson = prepareJson;