@tangelo/tangelo-configuration-toolkit 1.12.0 → 1.13.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/index.js +9 -11
- package/package.json +1 -1
- package/src/cli.js +9 -7
- package/src/modules/build/index.js +2 -3
- package/src/modules/build/oxygen.js +3 -1
- package/src/modules/deploy/config.js +2 -2
- package/src/modules/fonto/commands.js +2 -2
- package/src/modules/fonto/index.js +2 -2
- package/src/modules/{version → info}/index.js +72 -35
- package/src/modules/migrate/steps.js +2 -1
package/index.js
CHANGED
|
@@ -72,7 +72,7 @@ try { global._appconfig = _paths.appconfig && fs.readJsonSync(_paths.appconfig)
|
|
|
72
72
|
catch({message}) { _error('Error in '+message); }
|
|
73
73
|
|
|
74
74
|
_appconfig.sharedConfigPath = path.resolve(_paths.appconfig || '', '..', _appconfig.sharedConfigPath || '', appname+'-appconfig.json');
|
|
75
|
-
_appconfig.shared
|
|
75
|
+
_appconfig.shared = fs.readJsonSync(_appconfig.sharedConfigPath, {throws: false}) || {};
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
global._git = {
|
|
@@ -81,22 +81,21 @@ global._git = {
|
|
|
81
81
|
return _appdata.gitUser;
|
|
82
82
|
},
|
|
83
83
|
commitLocal () {
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
this.cache ??= execGitCommand(`log -1 --format=%D;%H;%cd --date=iso-strict`, _paths.repo, ['branch', 'hash', 'date']);
|
|
85
|
+
return this.cache;
|
|
86
86
|
},
|
|
87
87
|
commitRemote () {
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
this.cache ??= execGitCommand('log -1 --format=%cd --date=iso-strict origin/'+_git.commitLocal().branch, _paths.repo, ['date']);
|
|
89
|
+
return this.cache;
|
|
90
90
|
},
|
|
91
91
|
commitTdi: {
|
|
92
92
|
local () {
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
this.cache ??= execGitCommand(`log -1 --format=%D;%H;%cd --date=iso-strict`, path.join(_paths.repo, _paths.tdi), ['tags', 'hash', 'date']);
|
|
94
|
+
return this.cache;
|
|
95
95
|
},
|
|
96
96
|
after (commitHash) {
|
|
97
|
-
|
|
98
|
-
return this['cache-'+commitHash]
|
|
99
|
-
execGitCommand(`merge-base --is-ancestor ${commitHash} ${_git.commitTdi.local().hash}`, path.join(_paths.repo, _paths.tdi), null, 0);
|
|
97
|
+
this['cache-'+commitHash] ??= execGitCommand(`merge-base --is-ancestor ${commitHash} ${_git.commitTdi.local().hash}`, path.join(_paths.repo, _paths.tdi), null, 0);
|
|
98
|
+
return this['cache-'+commitHash];
|
|
100
99
|
},
|
|
101
100
|
fontoVersions: [ // latest commits first
|
|
102
101
|
{commitHash: 'e599766', regex: /^7\.1[45]\./},
|
|
@@ -127,7 +126,6 @@ global._isPre42 = fs.existsSync(path.join(_paths.repo, _paths.tdi, 'create_new_p
|
|
|
127
126
|
global._isPre51 = !fs.existsSync(path.join(_paths.repo, _paths.tdi, 'src')); // folder changed in 5.1 (check new folder because old one could still exist after branch switch)
|
|
128
127
|
|
|
129
128
|
|
|
130
|
-
|
|
131
129
|
process.on('beforeExit', () => {
|
|
132
130
|
_write(); // print empty line before and after update check
|
|
133
131
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangelo/tangelo-configuration-toolkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "Tangelo Configuration Toolkit is a command-line toolkit which offers support for developing a Tangelo configuration.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"tct": "bin/index.js",
|
package/src/cli.js
CHANGED
|
@@ -25,7 +25,7 @@ module.exports = function cli () {
|
|
|
25
25
|
init: {alias: 'i', desc: 'Create repository content structure', conflicts: ['p', 's', 'c']},
|
|
26
26
|
project: {alias: 'p', desc: 'Create project configuration', conflicts: ['i', 's', 'c']},
|
|
27
27
|
symlinks: {alias: 's', desc: 'Recreate symlinks to TDI', conflicts: ['p', 'i', 'c']},
|
|
28
|
-
config: {alias: 'c', desc: 'Create repo-config file', conflicts: ['p', 'i', 's'], hidden:
|
|
28
|
+
config: {alias: 'c', desc: 'Create repo-config file', conflicts: ['p', 'i', 's'], hidden: true},
|
|
29
29
|
oxygen: {alias: 'x', desc: 'Create or update oXygen project file (.xpr)', conflicts: ['p', 'i', 'c']}
|
|
30
30
|
},
|
|
31
31
|
handler: require('./modules/build')
|
|
@@ -92,15 +92,17 @@ module.exports = function cli () {
|
|
|
92
92
|
remove: {alias: 'r', desc: 'Remove project configuration', conflicts: ['i', 'c', 'g']}
|
|
93
93
|
},
|
|
94
94
|
handler: require('./modules/sql')
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
})
|
|
96
|
+
.command({
|
|
97
|
+
command: 'info',
|
|
98
|
+
aliases: ['i'],
|
|
99
|
+
desc: 'Show project information',
|
|
99
100
|
builder: {
|
|
100
|
-
|
|
101
|
+
doctypes: {alias: 'd', desc: `List document-types information`},
|
|
102
|
+
versions: {alias: 'v', desc: `Find all version information, sorted by project or type`, choices: ['project', 'type'], conflicts: ['d']},
|
|
101
103
|
server: {alias: 's', desc: 'Pass server name (set in config file)', default: _appconfig.defaultServer}
|
|
102
104
|
},
|
|
103
|
-
handler: require('./modules/
|
|
105
|
+
handler: require('./modules/info')
|
|
104
106
|
})
|
|
105
107
|
.recommendCommands()
|
|
106
108
|
.option('config', {alias: 'c', desc: 'Show loaded appconfig', global: false})
|
|
@@ -18,11 +18,11 @@ const createSymlink = (t, p) => {
|
|
|
18
18
|
const createSymlinks = () => {
|
|
19
19
|
_info('Creating symlinks:');
|
|
20
20
|
const src = _isPre51 ? 'sources' : 'src';
|
|
21
|
-
createSymlink(src + '/config/cmscustom/tdi', 'config/cmscustom/tdi'
|
|
21
|
+
createSymlink(src + '/config/cmscustom/tdi', 'config/cmscustom/tdi');
|
|
22
22
|
globby
|
|
23
23
|
.sync('config/cmscustom/!(tdi)/**/fonto')
|
|
24
24
|
.forEach(p => {
|
|
25
|
-
createSymlink(src + '/config/cmscustom/tdi/fonto/packages-shared', p + '/packages-shared'
|
|
25
|
+
createSymlink(src + '/config/cmscustom/tdi/fonto/packages-shared', p + '/packages-shared');
|
|
26
26
|
});
|
|
27
27
|
};
|
|
28
28
|
|
|
@@ -109,7 +109,6 @@ module.exports = function build (argv) {
|
|
|
109
109
|
_repoconfig.update({customer, projects, applink: 'None'});
|
|
110
110
|
|
|
111
111
|
_write(`\nFile '${_paths.repoconfig}' has been created.`);
|
|
112
|
-
_repoconfig.projects;
|
|
113
112
|
});
|
|
114
113
|
}
|
|
115
114
|
|
|
@@ -11,6 +11,8 @@ const siteStylesheetsPath = 'config/txp/site-stylesheets/';
|
|
|
11
11
|
const masterFiles = new Set;
|
|
12
12
|
const transformationScenarios = [];
|
|
13
13
|
|
|
14
|
+
const convertToValidFilename = (string) => string.replace(/[\/|\\:*?"<>]/g, " ");
|
|
15
|
+
|
|
14
16
|
const createProjectFile = (config) => {
|
|
15
17
|
_info('Initializing xpr file(s):');
|
|
16
18
|
const xprFiles = globby.sync(`*.xpr`);
|
|
@@ -20,7 +22,7 @@ const createProjectFile = (config) => {
|
|
|
20
22
|
else {
|
|
21
23
|
const customers = new Set;
|
|
22
24
|
_repoconfig.forEach(p => customers.add(p.customer_name));
|
|
23
|
-
xprFiles.push([...customers].join(' - ') + '.xpr');
|
|
25
|
+
xprFiles.push(convertToValidFilename([...customers].join(' - ')) + '.xpr');
|
|
24
26
|
fs.copySync(path.join(_paths.repo, 'tangelo-default-implementation/src/[customer].xpr'), path.join(_paths.repo, xprFiles[0]));
|
|
25
27
|
_write(`Created: '${xprFiles[0]}'`);
|
|
26
28
|
}
|
|
@@ -84,7 +84,7 @@ module.exports = {
|
|
|
84
84
|
.trim()
|
|
85
85
|
.replace(/^#.+/gm, '') // remove comments
|
|
86
86
|
.split(/\s+/) // split on lines
|
|
87
|
-
.filter(p => !p.match(
|
|
87
|
+
.filter(p => !p.match(/(^database\/)|(\/tdi)|(\/fonto)/)) // filter paths that should be copied
|
|
88
88
|
.map(p => '!' + (p.match(/^config/) ? p : '**/' + p.split('**/').pop()) + (p.match(/\/$/) ? '**' : '')) // negate expressions, remove base dir, suffix folders with **
|
|
89
89
|
;
|
|
90
90
|
|
|
@@ -110,7 +110,7 @@ module.exports = {
|
|
|
110
110
|
if (this.deliveryPack && transferPattern.includes(_paths.tdi)) this.transferPatterns.push(`${_paths.tdi}/src/database/create*.sql`); // create(_exists).sql is called by tdi install
|
|
111
111
|
|
|
112
112
|
// add time parameters to all xopus requests to overcome cache
|
|
113
|
-
const ts = new Date().toISOString().replace(
|
|
113
|
+
const ts = new Date().toISOString().replace(/[-:]/g, '').substring(0, 15);
|
|
114
114
|
this.replaceStrings = [
|
|
115
115
|
[/((xsd|xsl|src|iconsrc)="[^"?]+)"/g, `$1?_=${ts}"`, '**/xopus/xml/*'],
|
|
116
116
|
[/(schemaLocation="[^"?]+)"/g, `$1?_=${ts}"`, '**/xopus/xsd/*'],
|
|
@@ -127,7 +127,7 @@ module.exports = {
|
|
|
127
127
|
const schemasPerElement = {};
|
|
128
128
|
Object.entries(rootSchemas).forEach(([path, obj]) => {
|
|
129
129
|
const data = execSync(`${fdt} elements --schema packages/${obj.packageName}/src/assets/schemas/${obj.packageName}.json -C name`, {encoding: 'UTF-8'});
|
|
130
|
-
const elements = data.replace(
|
|
130
|
+
const elements = data.replace(/(^.*?Name\*)|(Printed name\*.*$)/gs, '').split(/\s+/);
|
|
131
131
|
const customElements = [...new Set(elements)].filter(e => e && !ignoreElements.includes(e));
|
|
132
132
|
|
|
133
133
|
customElements.forEach(e => {
|
|
@@ -176,7 +176,7 @@ module.exports = {
|
|
|
176
176
|
const schemasPerAttribute = {};
|
|
177
177
|
Object.entries(rootSchemas).forEach(([path, obj]) => {
|
|
178
178
|
const data = execSync(`${fdt} attributes --schema packages/${obj.packageName}/src/assets/schemas/${obj.packageName}.json`, {encoding: 'UTF-8'});
|
|
179
|
-
const attributes = data.replace(
|
|
179
|
+
const attributes = data.replace(/(^.*?Default value\s+)|(\s+Printed name\*.*$)/gs, '').split(/\n\s+/).map(a => a.split(/\s+/)).map(a =>
|
|
180
180
|
a[0] + (a[2]=='required' ? ' (required)' : '') + (a[3]=='-' ? ' (no default)' : '')
|
|
181
181
|
);
|
|
182
182
|
const customAttributes = [...new Set(attributes)].filter(e => e && !ignoreAttributes.includes(e.replace(/ .*/, '')));
|
|
@@ -5,7 +5,7 @@ const globby = require('globby');
|
|
|
5
5
|
const path = require('path');
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
const fdtCommand = (fv) => `npx -y ${_packages.FDT.name}@${fv.replace(/^(7\.|8\.[
|
|
8
|
+
const fdtCommand = (fv) => `npx -y ${_packages.FDT.name}@${fv.replace(/^(7\.|8\.[012]\.).*/, '3.12.0')}`;
|
|
9
9
|
|
|
10
10
|
module.exports = function fonto (argv) {
|
|
11
11
|
|
|
@@ -29,7 +29,7 @@ module.exports = function fonto (argv) {
|
|
|
29
29
|
process.chdir(_paths.apply || '.');
|
|
30
30
|
|
|
31
31
|
// find fonto instances by searching for fonto/manifest.json files
|
|
32
|
-
const fontoPaths = globby.sync(['**/fonto/manifest.json', `!${_paths.tdi}/**`])
|
|
32
|
+
const fontoPaths = globby.sync(['**/fonto/manifest.json', 'manifest.json', `!${_paths.tdi}/**`])
|
|
33
33
|
.map(p => ([p.replace('manifest.json', ''), fs.readJsonSync(p).sdkVersion.replace(/Nightlies.*/, 'nightly')])
|
|
34
34
|
);
|
|
35
35
|
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
const fs
|
|
2
|
-
const globby
|
|
3
|
-
const path
|
|
4
|
-
const {Table}
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const globby = require('globby');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const {Table} = require('console-table-printer');
|
|
5
|
+
|
|
6
|
+
const execGitCommand = require('../../lib/exec-git-command');
|
|
7
|
+
const c = require('../deploy/config');
|
|
8
|
+
const {remote} = require('../deploy/execute');
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
const getGitInfo = () => {
|
|
10
12
|
// Version info TDI submodule
|
|
11
|
-
const branchInfo = [];
|
|
12
13
|
const gitSubmoduleInfo = new Table({
|
|
13
14
|
columns: [
|
|
14
15
|
{name: 'property', title: 'TDI - submodule', alignment: 'left'},
|
|
@@ -21,18 +22,12 @@ const getGitInfo = () => {
|
|
|
21
22
|
|
|
22
23
|
// Get branches containing TDI HEAD commit
|
|
23
24
|
const releaseBranches = execGitCommand(`branch --all --contains ${_git.commitTdi.local().hash}`, path.join(_paths.repo, _paths.tdi)).match(/release\/[^\s]+/gsm);
|
|
24
|
-
if (releaseBranches)
|
|
25
|
-
releaseBranches.forEach(b => {
|
|
26
|
-
// Get number of commits behind
|
|
27
|
-
const count = execGitCommand(`rev-list HEAD...origin/${b} --count`, path.join(_paths.repo, _paths.tdi));
|
|
28
|
-
// _info(`debug: [${b}]:${count}`);
|
|
29
|
-
// Push number of commits behind to branchInfo
|
|
30
|
-
branchInfo.push({name: b, commitsBehind: count});
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
25
|
+
if (!releaseBranches) _error('Could not retrieve TDI release branches');
|
|
34
26
|
// Get the first possible branch; prefer release/5.1 over release/5.2:
|
|
35
|
-
|
|
27
|
+
releaseBranches.sort((a, b) => a.name > b.name ? 1 : -1);
|
|
28
|
+
const firstBranch = {name: releaseBranches[0]};
|
|
29
|
+
// Get number of commits behind
|
|
30
|
+
firstBranch.commitsBehind = execGitCommand(`rev-list HEAD...origin/${firstBranch.name} --count`, path.join(_paths.repo, _paths.tdi));
|
|
36
31
|
|
|
37
32
|
// Create table rows for TDI submodule info
|
|
38
33
|
gitSubmoduleInfo.addRow({
|
|
@@ -59,9 +54,8 @@ const getGitInfo = () => {
|
|
|
59
54
|
gitSubmoduleInfo.printTable();
|
|
60
55
|
};
|
|
61
56
|
|
|
62
|
-
const getFileExtractInfo = (
|
|
57
|
+
const getFileExtractInfo = (sorting) => {
|
|
63
58
|
// version info miscellaneous
|
|
64
|
-
const sorting = argv.find.toString().includes('sort-type') ? 'type' : 'project';
|
|
65
59
|
const projects = new Set;
|
|
66
60
|
const types = new Set;
|
|
67
61
|
const versionInfoConfigPath = path.join(_paths.repo, _paths.tdi, 'tct/version/versionInfo.js');
|
|
@@ -86,8 +80,8 @@ const getFileExtractInfo = (argv) => {
|
|
|
86
80
|
.sync(location)
|
|
87
81
|
.forEach(f => {
|
|
88
82
|
const filePathExtract = f.match(/.*(?<path>(cmscustom|site-stylesheets)\/(?<customer>[^/]*)\/(?<project>[^/]*)\/.*)/);
|
|
89
|
-
const path = filePathExtract.groups.path
|
|
90
|
-
const project = filePathExtract.groups.project
|
|
83
|
+
const path = filePathExtract.groups.path || '';
|
|
84
|
+
const project = filePathExtract.groups.project || '';
|
|
91
85
|
|
|
92
86
|
const fileContent = fs.readFileSync(f).toString();
|
|
93
87
|
v.extracts.forEach(e => {
|
|
@@ -124,8 +118,8 @@ const getFileExtractInfo = (argv) => {
|
|
|
124
118
|
color: 'yellow'
|
|
125
119
|
});
|
|
126
120
|
});
|
|
127
|
-
}
|
|
128
|
-
if (sorting=='type') {
|
|
121
|
+
}
|
|
122
|
+
else if (sorting=='type') {
|
|
129
123
|
types.forEach(t => {
|
|
130
124
|
versionInfo.addRow({ // Add empty row after type
|
|
131
125
|
path: '',
|
|
@@ -136,30 +130,73 @@ const getFileExtractInfo = (argv) => {
|
|
|
136
130
|
});
|
|
137
131
|
}
|
|
138
132
|
versionInfo.printTable();
|
|
139
|
-
}
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
140
135
|
_warn('Version info of miscellaneous items cannot be extracted:\nCannot find required files in TDI submodule. Try updating TDI submodule.');
|
|
141
136
|
}
|
|
142
137
|
};
|
|
143
138
|
|
|
144
|
-
const getServerInfo = (
|
|
139
|
+
const getServerInfo = (server) => {
|
|
145
140
|
// Remote server info
|
|
146
141
|
// common setup
|
|
147
142
|
_write();
|
|
148
|
-
c.setServer(
|
|
143
|
+
c.setServer(server);
|
|
149
144
|
|
|
150
145
|
if (!c.envDev) {
|
|
151
146
|
_info(`Remote version info for '${c.server.ftpConfig.host}':\n`);
|
|
152
147
|
remote.add('sudo ~root/scripts/version.sh', '').process();
|
|
153
|
-
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
154
150
|
_info('For development environments no server version information is available. Check rancher / database for this information.\nAdd the --server option with a non-dev environment to see version information for that server.');
|
|
155
151
|
}
|
|
156
152
|
};
|
|
157
153
|
|
|
158
|
-
module.exports = function version (argv) {
|
|
159
|
-
_info('Version information of this git repository\n');
|
|
160
154
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
155
|
+
module.exports = function info (argv) {
|
|
156
|
+
|
|
157
|
+
if (argv.doctypes) {
|
|
158
|
+
_info('Document type information for this git repository\n');
|
|
159
|
+
|
|
160
|
+
const doctypesInfo = new Table({
|
|
161
|
+
columns: [
|
|
162
|
+
{name: 'id', alignment: 'right'},
|
|
163
|
+
{name: 'name', alignment: 'left'},
|
|
164
|
+
{name: 'paths', alignment: 'left'}
|
|
165
|
+
],
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
globby
|
|
169
|
+
.sync(_paths.repo + '/database/config/**/txd_document_types.sql')
|
|
170
|
+
.forEach((p, i, a) => {
|
|
171
|
+
fs.readFileSync(p).toString().match(/select([\s\S]+?)from\s+dual/gmi)
|
|
172
|
+
.forEach((dtRow, i, a) => {
|
|
173
|
+
const ntSqlInsert = fs.readFileSync(p.replace('txd_document_types', 'txd_node_types')).toString().match(/select(.*?)from\s+dual/s)[1];
|
|
174
|
+
const id = dtRow.match(/(\d+) id/)?.[1];
|
|
175
|
+
const name = dtRow.match(/'([^']+)' display_name/)?.[1];
|
|
176
|
+
const dbPath = p.match(/(database\/config\/(:?.*)\/)txd_document_types.sql/i)?.[1];
|
|
177
|
+
const prPath = ntSqlInsert.match(/'([^']+)' xsl_prep_inc/)[1].replace('prepare_xincludes.xsl','');
|
|
178
|
+
|
|
179
|
+
doctypesInfo.addRows([
|
|
180
|
+
{id, name, paths: 'config/cmscustom/'+ prPath},
|
|
181
|
+
{paths: dbPath}
|
|
182
|
+
]);
|
|
183
|
+
|
|
184
|
+
if (i!==a.length-1) doctypesInfo.addRow({});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
if (i!==a.length-1) doctypesInfo.addRow({});
|
|
188
|
+
});
|
|
189
|
+
|
|
164
190
|
|
|
165
|
-
|
|
191
|
+
doctypesInfo.printTable();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (argv.versions) {
|
|
195
|
+
_info('Version information for this git repository\n');
|
|
196
|
+
|
|
197
|
+
getGitInfo();
|
|
198
|
+
getFileExtractInfo(argv.versions);
|
|
199
|
+
getServerInfo(argv.server);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
};
|
|
@@ -52,9 +52,10 @@ module.exports = function steps (step, dry, filter) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
let filesModCount = 0;
|
|
55
|
-
for (let i=0; i<20 &&
|
|
55
|
+
for (let i=0; i<20 && r.files[0]; i++) { // execute repeatedly for modified files only (with safety limit of 20)
|
|
56
56
|
r.files = rif.sync(r).filter(f => f.hasChanged).map(f => f.file);
|
|
57
57
|
if (i==0) filesModCount = r.files.length; // save count only after first run (after this only subsets are processed)
|
|
58
|
+
if (dry) break;
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
_write('Files modified:', filesModCount);
|