@tangelo/tangelo-configuration-toolkit 1.17.1 → 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.
@@ -3,141 +3,136 @@ const objMerge = require('object-assign-deep');
3
3
  const path = require('path');
4
4
 
5
5
 
6
- module.exports = {
7
-
8
- getRemotePath (...arr) {
9
- const fp = path.join(this.server.remotedir, ...arr);
10
- return this.server.remotedir.match(/:/) ? fp : fp.toFws();
11
- },
12
-
13
- setServer (server) {
14
- if (!server) _error('No server was passed.');
15
-
16
- let serverConfigs = [];
17
-
18
- // find server in local config
19
- if (_appconfig.servers)
20
- serverConfigs = _appconfig.servers.filter(obj =>
21
- obj.name == server || (obj.domains && obj.domains.find(d => d.startsWith(server)))
22
- );
23
-
24
- // if nothing found, find server in shared config
25
- if (!serverConfigs[0] && _appconfig.shared.servers)
26
- serverConfigs = _appconfig.shared.servers.filter(obj =>
27
- obj.name == server || (obj.domains && obj.domains.find(d => d.startsWith(server)))
28
- );
29
-
30
- // complement configs with defaults and filter domains
31
- serverConfigs = serverConfigs.map(obj =>
32
- objMerge(
33
- {config: {}}, // make sure key is present
34
- _appconfig.shared.serverDefaults, // override with shared defaults
35
- _appconfig.serverDefaults, obj, // override with local defaults
36
- {domains: (obj.domains||[]).filter(d => obj.name == server || d.startsWith(server))} // make sure key is present and filter for domain (if not matched for name)
37
- )
38
- );
6
+ function getRemotePath (...arr) {
7
+ const fp = path.join(this.server.remotedir, ...arr);
8
+ return this.server.remotedir.includes(':') ? fp : fp.toFws;
9
+ }
10
+
11
+
12
+ function setServer (searchString) {
13
+ if (!searchString) _error('No server was passed.');
14
+
15
+ const stringsToArrays = stringOrArray => [stringOrArray].flat();
16
+ const filterDomains = domain => domain[0].startsWith(searchString) || domain.slice(1).includes(searchString);
17
+ const filterServerConfigs = (arr, cfg) => {
18
+ if (cfg.domains) cfg.domains = cfg.domains.map(stringsToArrays).filter(filterDomains);
19
+ if (cfg.name === searchString || cfg.domains?.[0]) arr.push(cfg);
20
+ return arr;
21
+ };
22
+
23
+ // find server in local config and filter domains
24
+ let serverConfigs = _appconfig.servers?.reduce(filterServerConfigs, []);
25
+ // if nothing found, find server in shared config and filter domains
26
+ if (!serverConfigs?.[0]) serverConfigs = _appconfig.shared.servers?.reduce(filterServerConfigs, []);
27
+
28
+ // abort if no config is found, or if multiple configs or domains are found for server
29
+ if (!serverConfigs?.[0]) _error(`No config found for "${searchString}".`);
30
+ if (serverConfigs.length > 1 || serverConfigs[0].domains?.length > 1) {
31
+ const matches = serverConfigs.map(obj => obj.name === searchString ? obj.name : obj.domains);
32
+ const matchesFlatten = matches.flat().map(stringsToArrays).map(m => m[0] + (m[1] ? ` [${m.slice(1).join(', ')}]` : '')).join(', ');
33
+ _error(`Passed server name "${searchString}" gives multiple results:\n${matchesFlatten}`);
34
+ }
39
35
 
40
- // abort if no config is found, or multiple configs, or multiple domains, are found for server
41
- if (!serverConfigs[0]) _error(`No config found for "${server}".`);
42
- if (serverConfigs.length > 1 || serverConfigs[0].domains.length > 1) {
43
- const matches = serverConfigs.map(obj => obj.name == server ? obj.name : obj.domains.filter(d => d.startsWith(server)));
44
- _error(`Passed server name "${server}" gives multiple results:\n${matches.flat().join(', ')}`);
45
- }
46
-
47
- // compose final server config in usable format
48
- const [serverConfig] = serverConfigs;
49
- this.server = {
50
- remotedir: serverConfig.config.remotedir,
51
- ftpConfig: {
52
- host: serverConfig.domains[0],
53
- port: serverConfig.config.port,
54
- parallel: serverConfig.config.parallel,
55
- username: serverConfig.config.username,
56
- agent: process.platform=='win32' ? 'pageant' : process.env.SSH_AUTH_SOCK,
57
- agentForward: process.platform!='win32',
58
- readyTimeout: 15000,
59
- retries: 1
60
- }
36
+ // complement serverconfig with defaults
37
+ const serverConfig = objMerge(
38
+ {config: {}, domains: [[]]}, // make sure keys are present
39
+ _appconfig.shared.serverDefaults, // override with shared defaults
40
+ _appconfig.serverDefaults, // override with local defaults
41
+ serverConfigs[0]
42
+ );
43
+
44
+ // compose final server config in usable format
45
+ const {config, domains: [[host]], mode} = serverConfig;
46
+
47
+ this.server = {remotedir: config.remotedir};
48
+
49
+ if (host) {
50
+ const {parallel, port, username} = config;
51
+ if (!(port && parallel && username)) _error('Config is incomplete!');
52
+ this.server.ftpConfig = {
53
+ host, port, parallel, username,
54
+ agent: process.platform === 'win32' ? 'pageant' : process.env.SSH_AUTH_SOCK,
55
+ agentForward: process.platform !== 'win32',
56
+ readyTimeout: 15000,
57
+ retries: 1
61
58
  };
59
+ }
60
+
61
+ if (mode === 'delivery-pack') {
62
+ const dateStr = new Date().toISOString().replace(/(.*)T(\d+):(\d+):(\d+).*/g, '$1_$2$3$4');
63
+ this.deliveryPackName = `tangelo-config-delivery-pack_${_paths.repo.split(/[\\/]/).pop()}_${dateStr}`;
64
+ this.server.remotedir += '/' + this.deliveryPackName; // output to temp folder
65
+ this.deliveryPack = true;
66
+ }
67
+
68
+ this.envDev = !host && !this.deliveryPack || /\.dev\.tangelo\.nl$/.test(host);
69
+ }
70
+
71
+
72
+ function prepareForCopy (filter) {
73
+ const {remotedir, ftpConfig} = this.server;
74
+ if (!path.isAbsolute(remotedir)) _error('"remotedir" must contain an absolute path!');
75
+
76
+ this.giPatterns = !fs.existsSync('.gitignore') ? [] :
77
+ fs.readFileSync('.gitignore').toString()
78
+ .trim()
79
+ .replace(/^#.+/gm, '') // remove comments
80
+ .split(/\s+/) // split on lines
81
+ .filter(p => !p.match(/(^database\/)|(\/tdi)|(\/fonto)/)) // filter paths that should be copied
82
+ .map(p => '!' + (p.match(/^config/) ? p : '**/' + p.split('**/').pop()) + (p.match(/\/$/) ? '**' : '')) // negate expressions, remove base dir, suffix folders with **
83
+ ;
84
+
85
+ let transferPattern = path.join(_paths.apply, filter).toFws;
86
+
87
+ // test if 'cmscustom/tdi' would be included, then add specifically, because following symlinks doesnt work with glob stars
88
+ const tdiIncRegex = /^(config\/)?((\{\w*,?)?cmscustom(,?\w*\})?\/|\*\/)?\*\*/;
89
+ const tdiPattern = tdiIncRegex.test(transferPattern) ? transferPattern.replace(tdiIncRegex, `${this.deliveryPack ? 'config/' : ''}cmscustom/tdi/**`) : 'nomatch';
90
+
91
+ if (!transferPattern)
92
+ _error('Invalid glob expression passed!');
93
+ else if (this.deliveryPack && transferPattern.startsWith('*'))
94
+ transferPattern = `{config,database,${_paths.tdi}/src/database/tdi}/${transferPattern}`;
95
+ else if (!this.deliveryPack) {
96
+ // for normal deployment to server, set config-dir so no other files in repo are unintentionally transferred
97
+ transferPattern = transferPattern.replace(/^config\/|^\//, '');
98
+ try { process.chdir('config'); }
99
+ catch(e) { _error('No config dir present!'); }
100
+ }
101
+
102
+ this.transferPatterns = [transferPattern, tdiPattern, ...this.giPatterns, '!**/*.crdownload']; // ignore patterns must come last
103
+
104
+ if (this.deliveryPack && transferPattern.includes(_paths.tdi)) this.transferPatterns.push(`${_paths.tdi}/src/database/create*.sql`); // create(_exists).sql is called by tdi install
105
+
106
+ // add time parameters to all xopus requests to overcome cache
107
+ const ts = new Date().toISOString().replace(/[-:]/g, '').substring(0, 15);
108
+ this.replaceStrings = [
109
+ [/((xsd|xsl|src|iconsrc)="[^"?]+)"/g, `$1?_=${ts}"`, '**/xopus/xml/*'],
110
+ [/(schemaLocation="[^"?]+)"/g, `$1?_=${ts}"`, '**/xopus/xsd/*'],
111
+ [/(href="[^"?]+.xsl)"/g, `$1?_=${ts}"`, '**/xopus/xsl/*']
112
+ ];
113
+ // depending on env, enable debug mode and change track functionality
114
+ if (this.envDev) {
115
+ this.transferPatterns.push('!ldap.xml');
116
+ this.replaceStrings.push(
117
+ ['debug.on=false', 'debug.on=true', '**/util.js'],
118
+ ['debugMode>false', 'debugMode>true', '**/xopus/xml/*'],
119
+ ['allowAccept>false', 'allowAccept>true', '**/xopus/xml/*'],
120
+ ['allowReject>false', 'allowReject>true', '**/xopus/xml/*'],
121
+ [/(id="generateSampleText" available=")false/, '$1true', '**/xopus/xml/*']
122
+ );
123
+ }
124
+ else this.replaceStrings.push(['debugMode>true', 'debugMode>false', '**/xopus/xml/*']);
125
+
126
+ _info(`Branch: ${_git.commitLocal().branch}`);
127
+ _info(`Source: ${path.join(process.cwd(), transferPattern)}`);
128
+ _info(`Server: ${ftpConfig ? `${ftpConfig.host}:${ftpConfig.port}` : 'local'}`);
129
+ _info(`Target: ${this.getRemotePath(transferPattern)}`);
130
+ _write();
62
131
 
63
- const {ftpConfig} = this.server;
64
-
65
- if (ftpConfig.host && !(ftpConfig.port && ftpConfig.parallel && ftpConfig.username)) _error('Config is incomplete!');
66
-
67
- this.localTransfer = !ftpConfig.host;
68
- this.deliveryPack = serverConfig.mode == 'delivery-pack';
69
- this.envDev = this.localTransfer && !this.deliveryPack || /\.dev\.tangelo\.nl$/.test(ftpConfig.host);
70
-
71
- if (this.deliveryPack) {
72
- const dateStr = new Date().toISOString().replace(/(.*)T(\d+):(\d+):(\d+).*/g, '$1_$2$3$4');
73
- this.deliveryPackName = `tangelo-config-delivery-pack_${_paths.repo.split(/[\\/]/).pop()}_${dateStr}`;
74
- this.server.remotedir += '/' + this.deliveryPackName; // output to temp folder
75
- }
76
- },
77
-
78
- prepareForCopy (filter) {
79
- const {remotedir, ftpConfig} = this.server;
80
- if (!path.isAbsolute(remotedir)) _error('"remotedir" must contain an absolute path!');
81
-
82
- this.giPatterns = !fs.existsSync('.gitignore') ? [] :
83
- fs.readFileSync('.gitignore').toString()
84
- .trim()
85
- .replace(/^#.+/gm, '') // remove comments
86
- .split(/\s+/) // split on lines
87
- .filter(p => !p.match(/(^database\/)|(\/tdi)|(\/fonto)/)) // filter paths that should be copied
88
- .map(p => '!' + (p.match(/^config/) ? p : '**/' + p.split('**/').pop()) + (p.match(/\/$/) ? '**' : '')) // negate expressions, remove base dir, suffix folders with **
89
- ;
90
-
91
- let transferPattern = path.join(_paths.apply, filter).toFws();
92
-
93
- // test if 'cmscustom/tdi' would be included, then add specifically, because following symlinks doesnt work with glob stars
94
- const tdiIncRegex = /^(config\/)?((\{\w*,?)?cmscustom(,?\w*\})?\/|\*\/)?\*\*/;
95
- const tdiPattern = tdiIncRegex.test(transferPattern) ? transferPattern.replace(tdiIncRegex, `${this.deliveryPack ? 'config/' : ''}cmscustom/tdi/**`) : 'nomatch';
96
-
97
- if (!transferPattern)
98
- _error('Invalid glob expression passed!');
99
- else if (this.deliveryPack && transferPattern.startsWith('*'))
100
- transferPattern = `{config,database,${_paths.tdi}/src/database/tdi}/${transferPattern}`;
101
- else if (!this.deliveryPack) {
102
- // for normal deployment to server, set config-dir so no other files in repo are unintentionally transferred
103
- transferPattern = transferPattern.replace(/^config\/|^\//, '');
104
- try { process.chdir('config'); }
105
- catch(e) { _error('No config dir present!'); }
106
- }
107
-
108
- this.transferPatterns = [transferPattern, tdiPattern, ...this.giPatterns, '!**/*.crdownload']; // ignore patterns must come last
109
-
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
-
112
- // add time parameters to all xopus requests to overcome cache
113
- const ts = new Date().toISOString().replace(/[-:]/g, '').substring(0, 15);
114
- this.replaceStrings = [
115
- [/((xsd|xsl|src|iconsrc)="[^"?]+)"/g, `$1?_=${ts}"`, '**/xopus/xml/*'],
116
- [/(schemaLocation="[^"?]+)"/g, `$1?_=${ts}"`, '**/xopus/xsd/*'],
117
- [/(href="[^"?]+.xsl)"/g, `$1?_=${ts}"`, '**/xopus/xsl/*']
118
- ];
119
- // depending on env, enable debug mode and change track functionality
120
- if (this.envDev) {
121
- this.transferPatterns.push('!ldap.xml');
122
- this.replaceStrings.push(
123
- ['debug.on=false', 'debug.on=true', '**/util.js'],
124
- ['debugMode>false', 'debugMode>true', '**/xopus/xml/*'],
125
- ['allowAccept>false', 'allowAccept>true', '**/xopus/xml/*'],
126
- ['allowReject>false', 'allowReject>true', '**/xopus/xml/*'],
127
- [/(id="generateSampleText" available=")false/, '$1true', '**/xopus/xml/*']
128
- );
129
- }
130
- else this.replaceStrings.push(['debugMode>true', 'debugMode>false', '**/xopus/xml/*']);
131
-
132
- _info(`Branch: ${_git.commitLocal().branch}`);
133
- _info(`Source: ${path.join(process.cwd(), transferPattern)}`);
134
- _info(`Server: ${ftpConfig.host ? `${ftpConfig.host}:${ftpConfig.port}` : 'local'}`);
135
- _info(`Target: ${this.getRemotePath(transferPattern)}`);
136
- _write();
137
-
138
- if (_git.commitLocal().date < _git.commitRemote().date) {
139
- _warn(`You're not deploying from the most recent git commit!\n`);
140
- }
132
+ if (_git.commitLocal().date < _git.commitRemote().date) {
133
+ _warn(`You're not deploying from the most recent git commit!\n`);
141
134
  }
135
+ }
136
+
142
137
 
143
- };
138
+ module.exports = {getRemotePath, setServer, prepareForCopy};
@@ -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 = [];
@@ -149,7 +150,7 @@ const transfer = (paths, lrServer) => {
149
150
  });
150
151
 
151
152
  // disable file logging for ftp (gulp-sftp does it already)
152
- g_print.setLogFunction((filepath) => c.localTransfer ? _write(filepath.nostyle) : null);
153
+ g_print.setLogFunction(filepath => c.server.ftpConfig ? null : _write(filepath.nostyle));
153
154
 
154
155
  _info('Start transferring', true);
155
156
 
@@ -181,7 +182,7 @@ const transfer = (paths, lrServer) => {
181
182
  cb(null, file);
182
183
  }))
183
184
  .pipe(g_print.default())
184
- .pipe(c.localTransfer ? gulp.dest(c.server.remotedir) : g_sftp(c.server.ftpConfig, c.server.remotedir))
185
+ .pipe(c.server.ftpConfig ? g_sftp(c.server.ftpConfig, c.server.remotedir) : gulp.dest(c.server.remotedir))
185
186
  .on('end', () => {
186
187
  _info('Finished transferring\n', true);
187
188
  if (fontoPaths.outdated[0]) _warn(`Fonto build files in the following folders were outdated and therefore skipped:\n ${fontoPaths.outdated.map(v => v.slice(0, -1)).join('\n ')}`);
@@ -16,8 +16,8 @@ module.exports = function deploy (argv) {
16
16
  c.setServer(argv.server);
17
17
  c.prepareForCopy(argv.filter);
18
18
 
19
- if (!c.localTransfer) {
20
- c.server.ftpConfig.eventPut = (file) => {
19
+ if (c.server.ftpConfig) {
20
+ c.server.ftpConfig.eventPut = file => {
21
21
  _write(file.destination.replace(c.server.remotedir, ''));
22
22
  if (path.extname(file.destination)=='.sh')
23
23
  remote.add('chmod 755 '+file.destination, 'Permissions set: '+file.destination);
@@ -64,7 +64,7 @@ module.exports = function deploy (argv) {
64
64
  };
65
65
 
66
66
  // check connection
67
- if (!c.localTransfer) {
67
+ if (c.server.ftpConfig) {
68
68
  const sftp = new sftpClient();
69
69
  sftp.connect(c.server.ftpConfig).then(() => sftp.end()).catch(err => _error(`Could not connect to server${err ? ': '+err.message : ''}`));
70
70
  }
@@ -90,8 +90,8 @@ module.exports = function deploy (argv) {
90
90
  if (!path.parse(filepath).base.match(/\.scss/)) {
91
91
  const rp = c.getRemotePath(filepath);
92
92
  const msg = 'Removed: ' + rp.replace(c.server.remotedir, '').white;
93
- if (c.localTransfer) del([rp], {force: true}).then(() => _info(msg, true));
94
- else remote.add(`rm -rf "${rp}"`, msg).process();
93
+ if (c.server.ftpConfig) remote.add(`rm -rf "${rp}"`, msg).process();
94
+ else del([rp], {force: true}).then(() => _info(msg, true));
95
95
  }
96
96
  }
97
97
  });
@@ -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
  };
@@ -279,7 +279,7 @@ module.exports = {
279
279
  });
280
280
  _write('Done.\n');
281
281
  })
282
- .then(() => cmdExec(`${fdt} editor run --write-to-disk`))
282
+ .then(() => cmdExec(`${fdt} editor run --port 8888 --write-to-disk`))
283
283
  ;
284
284
  }
285
285
 
@@ -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,10 +52,10 @@ 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
- _error(`Fonto version ${fontoVersionNew} is not compatible with the current TDI submodule commit!\nExecute: tct fonto --init latest`);
58
+ _error(`Fonto version ${fontoVersionNew} is not compatible with the current TDI submodule commit!\nExecute: ${'tct fonto --init latest'.cyan}`);
57
59
  }
58
60
 
59
61
  _write(fontoVersionNew+'\n');