@tangelo/tangelo-configuration-toolkit 1.18.0 → 1.19.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 CHANGED
@@ -1,10 +1,7 @@
1
1
  global._appStartTime = new Date();
2
2
 
3
- require('./src/lib/style-string-getters');
4
-
5
- String.prototype.toFws = function(){
6
- return this.replace(/\\/g, '/');
7
- };
3
+ require('./src/lib/set-string-getters.js');
4
+ require('./src/lib/set-global-functions.js');
8
5
 
9
6
 
10
7
  const {execSync} = require('child_process');
@@ -17,51 +14,12 @@ const execGitCommand = require('./src/lib/exec-git-command');
17
14
  const memoize = require('./src/lib/memoize');
18
15
 
19
16
 
20
- const appname = 'tangelo-configuration-toolkit';
21
-
22
-
23
- global._write = (...msg) => {
24
- msg = msg.map(m => typeof m == 'object' ? JSON.stringify(m, null, 2).cyan : m);
25
- console.log(msg.join(' ').replace(/^/gm, ' ')); // indent each line
26
- };
27
-
28
- global._info = (msg, time = false) => {
29
- if (time) {
30
- const tzDiff = new Date().getTimezoneOffset() * 60000;
31
- const time = new Date(Date.now() - tzDiff).toISOString().match(/\d\d:\d\d:\d\d/)[0];
32
- msg = `[${time}] ${msg}`;
33
- }
34
- console.log(msg.lgreen);
35
- };
36
-
37
- global._warn = msg => {
38
- console.log(msg.lyellow);
39
- };
40
-
41
- global._error = msg => {
42
- console.log(msg.red, '\n');
43
- process.exit();
44
- };
45
-
46
- global._perf = t1 => {
47
- const t2 = new Date();
48
- console.log(`\nExecution time: ${t2 - t1}ms`.blue);
49
- };
50
-
51
- global._formatDate = date =>
52
- date?.toLocaleDateString('en-gb', {day: 'numeric', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit'})
53
- ;
17
+ global._package = require('./package.json');
54
18
 
55
19
 
56
20
  global._devmode = !__dirname.includes('node_modules');
57
21
 
58
22
 
59
- global._packages = {
60
- TCT: {name: '@tangelo/tangelo-configuration-toolkit', version: require('./package.json')?.version},
61
- FDT: {name: '@fontoxml/fontoxml-development-tools'}
62
- };
63
-
64
-
65
23
  global._paths = {
66
24
  app: __dirname,
67
25
  apphome: path.join(homedir, '.tct'),
@@ -71,8 +29,7 @@ global._paths = {
71
29
  };
72
30
  _paths.appdata = path.join(_paths.apphome, 'appdata.json');
73
31
  _paths.appconfig = path.join(_paths.apphome, 'appconfig.json');
74
- _paths.repoconfig = path.join(_paths.repo, appname+'-repoconfig.json');
75
- _paths.apply = process.cwd().replace(_paths.repo, '').substr(1);
32
+ _paths.apply = process.cwd().replace(_paths.repo, '').slice(1);
76
33
 
77
34
 
78
35
  global._appdata = fs.readJsonSync(_paths.appdata, {throws: false}) || {};
@@ -105,7 +62,8 @@ catch({code, message}) {
105
62
  global._repoconfig = require('./src/lib/get-repoconfig')(_paths.repo);
106
63
 
107
64
 
108
- _appconfig.sharedConfigPath = path.resolve(_paths.appconfig, '..', _appconfig.sharedConfigPath || '', appname+'-appconfig.json');
65
+ const filenameSC = _package.name.split('/').pop() + '-appconfig.json';
66
+ _appconfig.sharedConfigPath = path.resolve(_paths.appconfig, '..', _appconfig.sharedConfigPath || '', filenameSC);
109
67
  _appconfig.shared = fs.readJsonSync(_appconfig.sharedConfigPath, {throws: false}) || {};
110
68
 
111
69
 
@@ -145,18 +103,21 @@ global._modulesTdi = {
145
103
  }
146
104
  this.depsUpToDate = true;
147
105
  },
148
- require(module) {
106
+ require(module, {throws = true, message = true} = {}) {
149
107
  if (path.extname(module) !== '.json') this.ensureDepsUpToDate();
150
- _info(`Loading ${path.join(_paths.tdi, 'tct', module)}\n`);
108
+ if (message) _info(`Loading ${path.join(_paths.tdi, 'tct', module)}\n`);
151
109
  try {
152
110
  return require(path.join(this.absolutePathTdi, 'tct', module));
153
111
  }
154
112
  catch (e) {
155
- _error('Module could not be loaded');
113
+ if (throws) _error('Module could not be loaded: ' + module);
114
+ else return undefined;
156
115
  }
157
116
  }
158
117
  };
159
118
 
119
+ global._settingsTdi = memoize(() => Object.assign(_package.settingsTdiDefault, _modulesTdi.require('settings.json', {throws: false, message: false}) ?? {}));
120
+
160
121
 
161
122
  process.on('beforeExit', () => {
162
123
  _write(); // print empty line before and after update check
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangelo/tangelo-configuration-toolkit",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "engines": {
5
5
  "node": ">=14.0.0"
6
6
  },
@@ -56,5 +56,9 @@
56
56
  "type": "git",
57
57
  "url": "git+ssh://git@bitbucket.org/tangelosoftware/tangelo-configuration-toolkit.git"
58
58
  },
59
- "homepage": "https://bitbucket.org/tangelosoftware/tangelo-configuration-toolkit#readme"
59
+ "homepage": "https://bitbucket.org/tangelosoftware/tangelo-configuration-toolkit#readme",
60
+ "settingsTdiDefault": {
61
+ "#": "Defaults for tangelo-default-implementation/tct/settings.json",
62
+ "transpileToES5": true
63
+ }
60
64
  }
package/src/cli.js CHANGED
@@ -6,7 +6,7 @@ module.exports = function cli () {
6
6
  _write();
7
7
 
8
8
  const txtTitle = 'Tangelo Configuration Toolkit'.bold.underline.cyan;
9
- const txtVersion = `v${_packages.TCT.version}`.lblack;
9
+ const txtVersion = `v${_package.version}`.lblack;
10
10
 
11
11
  yargs
12
12
  .scriptName('tct')
@@ -77,7 +77,7 @@ module.exports = function cli () {
77
77
  clone: {alias: 'c', desc: 'Clone a client repository and do basic setup', conflicts: ['i', 'r', 'u']},
78
78
  'update-repo': {alias: 'ur', desc: 'Update repository', conflicts: ['i', 'r', 'c']},
79
79
  'update-submodule': {alias: 'us', desc: 'Update TDI submodule, optionally pass release branch (without "release/")', conflicts: ['i', 'r', 'c']},
80
- dates: {alias: 'd', desc: '[hidden] Use i.c.w. update-submodule, pass 2 dates in format dd-mm-yyyy', conflicts: ['i', 'r', 'c'], implies: 'update-submodule', requiresArg: true, array: true, hidden: !_devmode}
80
+ dates: {alias: 'd', desc: '[hidden] Use i.c.w. update-submodule, pass 2 dates in format yyyy-mm-dd', conflicts: ['i', 'r', 'c'], implies: 'update-submodule', requiresArg: true, array: true, hidden: !_devmode}
81
81
  },
82
82
  handler: require('./modules/git')
83
83
  })
@@ -16,7 +16,7 @@ module.exports = function(ftpConfig, remotedir) {
16
16
  if (file.isStream()) return cb(new Error('Streaming not supported.'));
17
17
  if (file.stat.isDirectory()) return cb();
18
18
 
19
- file.destination = path.join(remotedir, file.relative).toFws();
19
+ file.destination = path.join(remotedir, file.relative).toFws;
20
20
  files.push(file); // collect all files in array
21
21
  return cb();
22
22
  },
@@ -2,12 +2,14 @@ const {compare} = require('compare-versions');
2
2
  const exec = require('util').promisify(require('child_process').exec);
3
3
 
4
4
 
5
+ const packages = {TCT: _package};
6
+
5
7
  const doUpdateCheck = (pkg) => (
6
- exec(`npm view -g ${_packages[pkg].name} version`)
8
+ exec(`npm view -g ${packages[pkg].name} version`)
7
9
  .then(r => {
8
10
  const versionAvailable = r.stdout.match(/([\d/.]+)/)[1];
9
- if (!_packages[pkg].version) _warn(`${pkg} is not installed! Run ` + `npm i -g ${_packages[pkg].name}`.white);
10
- else if (compare(_packages[pkg].version, versionAvailable, '<')) {
11
+ if (!packages[pkg].version) _warn(`${pkg} is not installed! Run ` + `npm i -g ${packages[pkg].name}`.white);
12
+ else if (compare(packages[pkg].version, versionAvailable, '<')) {
11
13
  _appdata._update({[`updateCheck${pkg}`]: {executed: new Date(), versionAvailable}});
12
14
  return versionAvailable;
13
15
  }
@@ -25,14 +27,14 @@ module.exports = function packageUpdateCheck () {
25
27
  checkUpdatesDone = true;
26
28
 
27
29
  ['TCT'].forEach(pkg => {
28
- const updateMsg = (va) => `| Update ${pkg} to ${va} | ` + `npm i -g ${_packages[pkg].name}`.white;
30
+ const updateMsg = (va) => `| Update ${pkg} to ${va} | ` + `npm i -g ${packages[pkg].name}`.white;
29
31
  const {versionAvailable} = _appdata[`updateCheck${pkg}`] || {};
30
32
 
31
33
  if (new Date() - new Date(_appdata[`updateCheck${pkg}`]?.executed || 0) > 1000*3600*24*1) { // check every day
32
34
  doUpdateCheck(pkg).then(r => r && _warn(updateMsg(r)));
33
35
  }
34
36
  else if (versionAvailable) {
35
- if (compare(_packages[pkg].version, versionAvailable, '<')) _warn(updateMsg(versionAvailable));
37
+ if (compare(packages[pkg].version, versionAvailable, '<')) _warn(updateMsg(versionAvailable));
36
38
  else _appdata._update({[`updateCheck${pkg}`]: {executed: new Date()}});
37
39
  }
38
40
  });
@@ -0,0 +1,24 @@
1
+ global._write = (...msg) => {
2
+ msg = msg.map(m => typeof m == 'object' ? JSON.stringify(m, null, 2).cyan : m);
3
+ console.log(msg.join(' ').replace(/^/gm, ' ')); // indent each line
4
+ };
5
+ global._info = (msg, time = false) => {
6
+ if (time) {
7
+ const tzDiff = new Date().getTimezoneOffset() * 60000;
8
+ const time = new Date(Date.now() - tzDiff).toISOString().match(/\d\d:\d\d:\d\d/)[0];
9
+ msg = `[${time}] ${msg}`;
10
+ }
11
+ console.log(msg.lgreen);
12
+ };
13
+ global._warn = msg => {
14
+ console.log(msg.lyellow);
15
+ };
16
+ global._error = msg => {
17
+ console.log(msg.red, '\n');
18
+ process.exit();
19
+ };
20
+ global._perf = t1 => {
21
+ const t2 = new Date();
22
+ console.log(`\nExecution time: ${t2 - t1}ms`.blue);
23
+ };
24
+ global._formatDate = date => date?.toLocaleDateString('en-gb', {day: 'numeric', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit'});
@@ -15,4 +15,10 @@ Object.defineProperty(String.prototype, 'nostyle', {
15
15
  get () {
16
16
  return this.replace(/[\u001b\u009b][[()#;?]*(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');
17
17
  }
18
+ });
19
+
20
+ Object.defineProperty(String.prototype, 'toFws', {
21
+ get () {
22
+ return this.replace(/\\/g, '/');
23
+ }
18
24
  });
@@ -5,7 +5,7 @@ const path = require('path');
5
5
 
6
6
  function getRemotePath (...arr) {
7
7
  const fp = path.join(this.server.remotedir, ...arr);
8
- return this.server.remotedir.includes(':') ? fp : fp.toFws();
8
+ return this.server.remotedir.includes(':') ? fp : fp.toFws;
9
9
  }
10
10
 
11
11
 
@@ -82,7 +82,7 @@ function prepareForCopy (filter) {
82
82
  .map(p => '!' + (p.match(/^config/) ? p : '**/' + p.split('**/').pop()) + (p.match(/\/$/) ? '**' : '')) // negate expressions, remove base dir, suffix folders with **
83
83
  ;
84
84
 
85
- let transferPattern = path.join(_paths.apply, filter).toFws();
85
+ let transferPattern = path.join(_paths.apply, filter).toFws;
86
86
 
87
87
  // test if 'cmscustom/tdi' would be included, then add specifically, because following symlinks doesnt work with glob stars
88
88
  const tdiIncRegex = /^(config\/)?((\{\w*,?)?cmscustom(,?\w*\})?\/|\*\/)?\*\*/;
@@ -120,9 +120,10 @@ const createDeliveryPack = () => { // create install scripts if necessary, zip o
120
120
 
121
121
 
122
122
  const transfer = (paths, lrServer) => {
123
+ const jsFGlob = _settingsTdi().transpileToES5 ? ['**/*.js', '!**/hce/**/template_*', '!**/fonto/**', '!**/vendor/**', '!**/*.min.js'] : [];
124
+ const jsF = g_filter(jsFGlob, {restore: true});
123
125
  const xpsF = g_filter(['**/xopus/**/*.x*'], {restore: true});
124
126
  const sassF = g_filter(['**/*.scss'], {restore: true});
125
- const jsF = g_filter(['**/*.js', '!**/hce/**/template_*', '!**/fonto/**', '!**/vendor/**', '!**/*.min.js'], {restore: true});
126
127
  const shF = g_filter(['**/*.sh'], {restore: true});
127
128
  const srcset = s.create(paths);
128
129
  const files = [];
@@ -77,7 +77,7 @@ module.exports = function deploy (argv) {
77
77
  // the "dist" folder isn't watched properly: it does not detect "assets" anymore after building once
78
78
  !/cmscustom.+fonto[\\/]/.test(filepath) ||
79
79
  /fonto[\\/]dist[\\/]/.test(filepath) ||
80
- (/fonto[\\/]dev[\\/]/.test(filepath)) ||
80
+ (/fonto[\\/]dev[\\/]/.test(filepath) && c.envDev) ||
81
81
  /fonto[\\/]packages[\\/]sx-shell-.*?[\\/]assets[\\/]schemas[\\/]/.test(filepath)
82
82
  )
83
83
  ) {
@@ -3,7 +3,7 @@ const globby = require('globby');
3
3
  const path = require('path');
4
4
 
5
5
 
6
- const relPath = (d, p) => path.relative(d, p).toFws();
6
+ const relPath = (d, p) => path.relative(d, p).toFws;
7
7
  const resolveBind = (d, p) => p.replace('#{cmscustompath}', 'cmscustom/').replace('{$rsrcPath}', (d.replace('stylesheets', 'resources')+'/'));
8
8
 
9
9
 
@@ -98,11 +98,11 @@ module.exports = {
98
98
  },
99
99
 
100
100
  addToCache (filepath) {
101
- if (this.potentialBaseFilesCache) this.potentialBaseFilesCache.push(filepath.toFws());
101
+ if (this.potentialBaseFilesCache) this.potentialBaseFilesCache.push(filepath.toFws);
102
102
  },
103
103
 
104
104
  removeFromCache (filepath) {
105
- if (this.potentialBaseFilesCache) this.potentialBaseFilesCache = this.potentialBaseFilesCache.filter(fp => fp != filepath.toFws());
105
+ if (this.potentialBaseFilesCache) this.potentialBaseFilesCache = this.potentialBaseFilesCache.filter(fp => fp != filepath.toFws);
106
106
  }
107
107
 
108
108
  };
@@ -5,23 +5,25 @@ 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\.[012]\.).*/, '3.12.0')}`;
8
+ const fdtPackage = '@fontoxml/fontoxml-development-tools';
9
+ const fdtCommand = fv => `npx -y ${fdtPackage}@${fv.replace(/^(7\.|8\.[012]\.).*/, '3.12.0')}`;
9
10
 
10
11
  module.exports = function fonto (argv) {
11
12
 
12
13
  const allowedFontoVersionRegex = (() => {
13
- const cvRegex = _modulesTdi.require('fonto/compatibleVersions.json')?.regex;
14
+ const cvRegex = _settingsTdi().compatibleFontoVersions ?? _modulesTdi.require('fonto/compatibleVersions.json', {throws: false})?.regex;
14
15
  if (cvRegex) return RegExp(cvRegex);
15
16
 
16
17
  // old way: a regex for each basecommit is stored in global._git.commitTdi
18
+ _info('Fallback to list of commits for determining compatible Fonto versions\n');
17
19
  for (const fv of _git.commitTdi.fontoVersions) {
18
20
  if (_git.commitTdi.after(fv.commitHash)) return fv.regex;
19
21
  }
20
22
  })();
21
23
 
22
24
  // check if FDT is not installed globally, because then it won't be possible to use specific versions with npx
23
- if (fs.pathExistsSync(path.join(_appdata.npmPath, 'node_modules', _packages.FDT.name))) {
24
- _error(`A global installation of FDT has been found! Remove it first.\nExecute: npm r -g ${_packages.FDT.name}`);
25
+ if (fs.pathExistsSync(path.join(_appdata.npmPath, 'node_modules', fdtPackage))) {
26
+ _error(`A global installation of FDT has been found! Remove it first.\nExecute: npm r -g ${fdtPackage}`);
25
27
  }
26
28
 
27
29
  process.chdir(_paths.apply || '.');
@@ -50,7 +52,7 @@ module.exports = function fonto (argv) {
50
52
 
51
53
  if (fontoVersionNew === 'latest') {
52
54
  const data = execSync(`${fdtCommand(fontoVersionCurrent)} editor versions`, {encoding: 'UTF-8'});
53
- fontoVersionNew = data.match(/\d+\.\d+\.\d+/g).filter(v => allowedFontoVersionRegex.test(v))[0];
55
+ fontoVersionNew = data.match(/\d+\.\d+\.\d+/g).find(v => allowedFontoVersionRegex.test(v));
54
56
  }
55
57
  else if (!allowedFontoVersionRegex.test(fontoVersionNew)) {
56
58
  _error(`Fonto version ${fontoVersionNew} is not compatible with the current TDI submodule commit!\nExecute: ${'tct fonto --init latest'.cyan}`);
@@ -123,6 +123,7 @@ function updateRepo () {
123
123
  const fontoLocations = globby.sync('*/*/fonto/manifest.json', {cwd: path.join(_paths.repo, 'config/cmscustom')});
124
124
  const fontoVersions = {};
125
125
  fontoLocations.forEach(p => {fontoVersions[p] = readFontoVersionFromFile(p);});
126
+ const tdiLogBeforeUpdate = _git.commitTdi.local();
126
127
 
127
128
  _info(`Fetch all`);
128
129
  const cmdFetch = execGitCommand('fetch -pf --all', _paths.repo);
@@ -138,11 +139,24 @@ function updateRepo () {
138
139
 
139
140
  if (fontoLocations.find(p => fontoVersions[p] !== readFontoVersionFromFile(p))) _warn(`\nChanges in Fonto instance versions have been pulled. Therefore you must execute ${'tct fonto --init'.cyan} before building and deploying Fonto.`);
140
141
 
141
- _info(`\nRetrieve submodules that belong to this repo-commit`); // update submodule recursively (set to version that belongs to repo)
142
- _write(execGitCommand(`submodule update --recursive`, _paths.repo));
143
- _info(`Submodule checked out at commit:`);
142
+ // update submodule recursively (set to version that belongs to repo)
143
+ execGitCommand(`submodule update --recursive`, _paths.repo);
144
+
145
+ // clear memoize cache; which is filled with the old TDI data due to tdiLogBeforeUpdate
146
+ _git.commitTdi.local.clear();
144
147
  const tdiLog = _git.commitTdi.local();
145
- _write([_formatDate(tdiLog.date), tdiLog.tags, tdiLog.hash].filter(v=>v).join(' - '));
148
+
149
+ _info(`\nTDI submodule:`);
150
+ _write(`Submodule in repo-commit: ${[_formatDate(tdiLog.date), tdiLog.tags, tdiLog.hash].filter(v=>v).join(' - ')}`);
151
+
152
+ if (tdiLog.date < tdiLogBeforeUpdate.date) {
153
+ _write(`Restore TDI submodule because it was newer before the repository update:`);
154
+ execGitCommand(`checkout ${tdiLogBeforeUpdate.hash}`, path.join(_paths.repo, _paths.tdi));
155
+ _write(`Submodule checked out: ${[_formatDate(tdiLogBeforeUpdate.date), tdiLogBeforeUpdate.tags, tdiLogBeforeUpdate.hash].filter(v=>v).join(' - ')}\n`);
156
+ }
157
+ else {
158
+ _write(`Submodule in repo-commit is checked out\n`);
159
+ }
146
160
 
147
161
  const tdiBranch = getTdiBranch();
148
162
  _info(`\nTDI branch ${tdiBranch.name} is ${tdiBranch.commitsBehind} commits behind.\nUpdate TDI submodule to latest version with ${'tct git --update-submodule'.cyan}`);
@@ -51,7 +51,7 @@ module.exports = function migrate (argv) {
51
51
  a.script = cmdlScript.value;
52
52
  }
53
53
 
54
- let filter = path.join(_paths.apply, argv.filter??'**').toFws(); // Default set filter with filter added to the command argument -f
54
+ let filter = path.join(_paths.apply, argv.filter??'**').toFws; // Default set filter with filter added to the command argument -f
55
55
 
56
56
  if (a.filter === 'projects' && _repoconfig.length > a.projects.length) {
57
57
  // push paths of chosen active documents to projectFolders (only if not all projects are chosen)
@@ -61,10 +61,7 @@ module.exports = function sql (argv) {
61
61
  .prompt([
62
62
  {
63
63
  message: 'Choose projects: ', name: 'projects', type: 'checkbox', validate: v => !!v[0],
64
- choices:
65
- _repoconfig.projects
66
- ? _repoconfig.projects.map(p => ({name: p.name, value: p})) // when using repoconfig file (old)
67
- : _repoconfig.map(p => ({name: `${p.customer_name} ${p.project_name}`, value: p}))
64
+ choices: _repoconfig.map(p => ({name: `${p.customer_name} ${p.project_name}`, value: p}))
68
65
  },
69
66
  {message: 'Database TNS name: ', name: 'db', default: _appconfig.defaultDatabase},
70
67
  {message: 'TANCMS password: ', name: 'pw', default: 'tancms'}