cob-cli 2.39.9 → 2.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cob-cli.js +12 -1
- package/lib/commands/generateMermaid.js +168 -0
- package/package.json +4 -3
package/bin/cob-cli.js
CHANGED
|
@@ -12,6 +12,7 @@ const test = require("../lib/commands/test");
|
|
|
12
12
|
const deploy = require("../lib/commands/deploy");
|
|
13
13
|
const updateFromServer = require("../lib/commands/updateFromServer");
|
|
14
14
|
const getDefs = require("../lib/commands/getDefs");
|
|
15
|
+
const generateMermaid = require("../lib/commands/generateMermaid");
|
|
15
16
|
const { upgradeRepo } = require("../lib/commands/upgradeRepo");
|
|
16
17
|
|
|
17
18
|
/*******************************************/
|
|
@@ -85,4 +86,14 @@ program
|
|
|
85
86
|
.description('Updates local copy with definitions on server')
|
|
86
87
|
.action( getDefs );
|
|
87
88
|
|
|
88
|
-
program
|
|
89
|
+
program
|
|
90
|
+
.command('generateMermaid')
|
|
91
|
+
.option('-e --environment <name>', 'environment to use')
|
|
92
|
+
.option('-s --server <name>', 'server to use (ignores -e)')
|
|
93
|
+
.option('-f --filter <regexp>', 'regexp used to filter against names & descriptions')
|
|
94
|
+
.option('-l --labels <lang>', 'add labels in the given language. Available options are "en", "pt" or "es"')
|
|
95
|
+
.option('-d --debug', 'send debug info to stderr')
|
|
96
|
+
.description('Generates mermaid diagram from Definitions')
|
|
97
|
+
.action( generateMermaid );
|
|
98
|
+
|
|
99
|
+
program.parse(process.argv);
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
const { getCurrentCommandEnviroment } = require("../task_lists/common_enviromentHandler");
|
|
2
|
+
const { checkRepoVersion } = require("../commands/upgradeRepo");
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const fg = require('fast-glob');
|
|
5
|
+
const path = require('path')
|
|
6
|
+
const axios = require('axios');
|
|
7
|
+
const FileCookieStore = require('file-cookie-store');
|
|
8
|
+
|
|
9
|
+
async function generateMermaid(args) {
|
|
10
|
+
try {
|
|
11
|
+
checkRepoVersion()
|
|
12
|
+
const cmdEnv = await getCurrentCommandEnviroment(args)
|
|
13
|
+
|
|
14
|
+
if(args.debug) console.error(`Generating mermaid` );
|
|
15
|
+
const defs = args.server
|
|
16
|
+
? await readDefsFromServer(args.server, args.filter, args.debug)
|
|
17
|
+
: await readDefsFromDisk(`recordm/definitions/${cmdEnv.name}`, args.filter, args.debug);
|
|
18
|
+
|
|
19
|
+
console.log('erDiagram');
|
|
20
|
+
let refs = [];
|
|
21
|
+
let references = [];
|
|
22
|
+
for(const def of defs){
|
|
23
|
+
refs.push(...getRefs(def.name, def.fieldDefinitions, args.debug));
|
|
24
|
+
references.push(...getReferences(def.name, def.fieldDefinitions, args.debug));
|
|
25
|
+
}
|
|
26
|
+
refs = uniqBy(refs, r => r.one + ":" + r.many)
|
|
27
|
+
references = uniqBy(references, r => r.one + ":" + r.many)
|
|
28
|
+
if(args.debug) console.error(
|
|
29
|
+
'refs: ', refs,
|
|
30
|
+
'references: ', references
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
const tables = new Set();
|
|
34
|
+
for(const ref of refs){
|
|
35
|
+
tables.add(ref.one);
|
|
36
|
+
tables.add(ref.many);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Output table defs
|
|
40
|
+
for(const table of tables){
|
|
41
|
+
const id = toMermaidId(table)
|
|
42
|
+
if (id != table) { console.debug(`\t${id}["${table}"]{}`) }
|
|
43
|
+
}
|
|
44
|
+
console.debug("")
|
|
45
|
+
// Output relations
|
|
46
|
+
for (const ref of refs) {
|
|
47
|
+
const one = toMermaidId(ref.one);
|
|
48
|
+
const many = toMermaidId(ref.many);
|
|
49
|
+
const left = '|o';
|
|
50
|
+
const right = (ref.required ? '|' : 'o') + '{';
|
|
51
|
+
const msgType = references.some(r => r.one === ref.one && r.many === ref.many) ? "hasMany" : "isOf"
|
|
52
|
+
let msg = "";
|
|
53
|
+
switch (args.labels) {
|
|
54
|
+
case "en":
|
|
55
|
+
msg = msgType == "hasMany" ? `${ref.one} have many ${ref.many}` : `_${ref.fieldName}_ is one of ${ref.one}`;
|
|
56
|
+
break;
|
|
57
|
+
case "pt":
|
|
58
|
+
msg = msgType == "hasMany" ? `${ref.one} têm ${ref.many}` : `_${ref.fieldName}_ refere um registo de ${ref.one}`;
|
|
59
|
+
break;
|
|
60
|
+
case "es":
|
|
61
|
+
msg = msgType == "hasMany" ? `${ref.one} tienen ${ref.many}` : `_${ref.fieldName}_ se refiere a un registro de ${ref.one}`;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.debug(`\t${one} ${left}..${right} ${many}: " ${msg}"`)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
} catch(err) {
|
|
69
|
+
console.error("\n",err.message);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
module.exports = generateMermaid;
|
|
73
|
+
|
|
74
|
+
async function readDefsFromDisk(dir, filter, debug) {
|
|
75
|
+
if(debug) console.error(`Reading Definitions from ${dir}`);
|
|
76
|
+
const defFiles = await fg([`${dir}/*.json`]);
|
|
77
|
+
return defFiles
|
|
78
|
+
.map((f) => JSON.parse(fs.readFileSync(f)))
|
|
79
|
+
.filter(def => {
|
|
80
|
+
return !filter || def.name.match(filter) || def.description?.match(filter)
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function readDefsFromServer(server, filter, debug) {
|
|
85
|
+
if(debug) console.error(`Reading Definitions from server ${server}`);
|
|
86
|
+
|
|
87
|
+
const p = path.resolve(require('os').homedir(), '.cob-cookie');
|
|
88
|
+
const cookieFile = new FileCookieStore(p, {auto_sync: false});
|
|
89
|
+
const cobtoken = await readCobtoken(cookieFile, server);
|
|
90
|
+
|
|
91
|
+
// get Defs
|
|
92
|
+
let defs = (await axios.get(`https://${server}/recordm/recordm/definitions`,{
|
|
93
|
+
headers: {
|
|
94
|
+
Accept: "application/json",
|
|
95
|
+
Cookie: cobtoken
|
|
96
|
+
}
|
|
97
|
+
})).data
|
|
98
|
+
if(debug) console.error('found a total of ', defs.length, 'Defs');
|
|
99
|
+
// filter
|
|
100
|
+
if(filter) defs = defs.filter(def => {
|
|
101
|
+
return def.name.match(filter) || def.description?.match(filter)
|
|
102
|
+
})
|
|
103
|
+
if(debug) console.error('filtered to ', defs.length, 'Defs');
|
|
104
|
+
return await Promise.all(defs.map(async (def) => {
|
|
105
|
+
return (await axios.get(`https://${server}/recordm/recordm/definitions/${def.id}`,{
|
|
106
|
+
headers: {
|
|
107
|
+
Accept: "application/json",
|
|
108
|
+
Cookie: cobtoken
|
|
109
|
+
}
|
|
110
|
+
})).data
|
|
111
|
+
}))
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function readCobtoken(cookies, server){
|
|
115
|
+
return new Promise((resolve, reject) => {
|
|
116
|
+
cookies.findCookie(server, '/', 'cobtoken', (err, result) => {
|
|
117
|
+
if(err != null) reject(err);
|
|
118
|
+
else resolve(result);
|
|
119
|
+
} )
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function getRefs(defName, fieldDefs, debug) {
|
|
124
|
+
return fieldDefs.reduce((acc, fd) => {
|
|
125
|
+
if (fd.configuration.keys.Reference && !fd.configuration.keys.AutoRefField) {
|
|
126
|
+
// if(debug) console.error('using fieldDefinition', fd)
|
|
127
|
+
acc.push({
|
|
128
|
+
one: fd.configuration.keys.Reference.args.definition,
|
|
129
|
+
many: defName,
|
|
130
|
+
fieldName: fd.name,
|
|
131
|
+
required: !!fd.required,
|
|
132
|
+
duplicable: !!fd.duplicable
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (fd.fields) acc.push(...getRefs(defName, fd.fields));
|
|
136
|
+
return acc;
|
|
137
|
+
}, [])
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function getReferences(defName, fieldDefs, debug) {
|
|
141
|
+
return fieldDefs.reduce((acc, fd) => {
|
|
142
|
+
if (fd.configuration.keys.References) {
|
|
143
|
+
// if(debug) console.error('using fieldDefinition', fd.name, fd.configuration.keys.References)
|
|
144
|
+
acc.push({
|
|
145
|
+
one: defName,
|
|
146
|
+
many: fd.configuration.keys.References.args.definition,
|
|
147
|
+
duplicable: true
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
if (fd.fields) acc.push(...getReferences(defName, fd.fields));
|
|
151
|
+
return acc;
|
|
152
|
+
}, [])
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function toMermaidId(name) {
|
|
156
|
+
return name.normalize("NFD")
|
|
157
|
+
.replace(/\p{Diacritic}/gu, "")
|
|
158
|
+
.replace(/\./g, "_")
|
|
159
|
+
.replace(/ /g, "_");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function uniqBy(a, key) {
|
|
163
|
+
const seen = new Set();
|
|
164
|
+
return a.filter(item => {
|
|
165
|
+
const k = key(item);
|
|
166
|
+
return seen.has(k) ? false : seen.add(k);
|
|
167
|
+
});
|
|
168
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cob-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.40.1",
|
|
4
4
|
"description": "A command line utility to help Cult of Bits partners develop with higher speed and reusing common code and best practices.",
|
|
5
5
|
"preferGlobal": true,
|
|
6
6
|
"repository": {
|
|
@@ -18,12 +18,14 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@webpack-cli/serve": "^2.0.1",
|
|
20
20
|
"axios": "^0.21.1",
|
|
21
|
+
"chokidar": "^3.5.3",
|
|
21
22
|
"cmd-line-importer": "^1.0.0",
|
|
22
23
|
"colors": "^1.4.0",
|
|
23
24
|
"commander": "^5.1.0",
|
|
24
25
|
"concurrently": "^5.3.0",
|
|
25
26
|
"execa": "^4.0.3",
|
|
26
27
|
"fast-glob": "^3.2.5",
|
|
28
|
+
"file-cookie-store": "^0.2.1",
|
|
27
29
|
"fs-extra": "^9.0.1",
|
|
28
30
|
"inquirer": "^7.3.3",
|
|
29
31
|
"listr": "^0.14.3",
|
|
@@ -34,8 +36,7 @@
|
|
|
34
36
|
"webpack": "^5.75.0",
|
|
35
37
|
"webpack-cli": "^5.0.1",
|
|
36
38
|
"webpack-dev-server": "^4.11.1",
|
|
37
|
-
"xdg-basedir": "^5.1.0"
|
|
38
|
-
"chokidar": "^3.5.3"
|
|
39
|
+
"xdg-basedir": "^5.1.0"
|
|
39
40
|
},
|
|
40
41
|
"keywords": [],
|
|
41
42
|
"author": "mimes70",
|