cob-cli 2.39.8 → 2.40.0
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/customize.js +3 -3
- 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);
|
|
@@ -186,11 +186,11 @@ function copyAndMerge(customizationRepoName, source, substitutions = {}) {
|
|
|
186
186
|
{
|
|
187
187
|
clobber: true,
|
|
188
188
|
filter: (src) => src.match(excludedFiles) == null,
|
|
189
|
-
|
|
189
|
+
rename: function(target) {
|
|
190
190
|
// Don't rename __MERGE__ templates, they will be handled by the merge method
|
|
191
191
|
if (target.match(/__MERGE__/)) {
|
|
192
192
|
const newTmpName = target.replace(/__MERGE__/, customizationRepoName+"__MERGE__")
|
|
193
|
-
filesToMerge.push(newTmpName)
|
|
193
|
+
filesToMerge.push({name:newTmpName, block: customizationRepoName})
|
|
194
194
|
return newTmpName
|
|
195
195
|
};
|
|
196
196
|
|
|
@@ -226,7 +226,7 @@ function copyAndMerge(customizationRepoName, source, substitutions = {}) {
|
|
|
226
226
|
while(filesToMerge.length > 0) {
|
|
227
227
|
let file = filesToMerge.pop();
|
|
228
228
|
//Allow a little time for file to be written to disk
|
|
229
|
-
setTimeout( () => mergeFiles(
|
|
229
|
+
setTimeout( () => mergeFiles(file.block, file.name), 200)
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
232
|
}
|
|
@@ -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.label) {
|
|
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.0",
|
|
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",
|