@tangelo/tangelo-configuration-toolkit 1.9.3 → 1.10.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangelo/tangelo-configuration-toolkit",
3
- "version": "1.9.3",
3
+ "version": "1.10.2",
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
@@ -72,6 +72,7 @@ module.exports = function cli () {
72
72
  init: {alias: 'i', desc: `Initialize editor (optionally pass version number or 'latest')`},
73
73
  schema: {alias: 's', desc: 'Compile schemas to json'},
74
74
  elements: {alias: 'e', desc: 'List schema elements not having a default configuration'},
75
+ attributes: {alias: 'a', desc: 'List schema attributes not having a default configuration'},
75
76
  localize: {alias: 'l', desc: 'Update localization file'},
76
77
  build: {alias: 'b', desc: 'Build the editor instance'},
77
78
  run: {alias: 'r', desc: 'Start editor instance on localhost and watch changes'}
@@ -91,7 +91,7 @@ module.exports = {
91
91
  let transferPattern = path.join(_paths.apply, filter).toFws();
92
92
 
93
93
  // test if 'cmscustom/tdi' would be included, then add specifically, because following symlinks doesnt work with glob stars
94
- const tdiIncRegex = /^(({\w*,?)?cmscustom(,?\w*})?\/|\*\/)?\*\*/;
94
+ const tdiIncRegex = /^(config\/)?(({\w*,?)?cmscustom(,?\w*})?\/|\*\/)?\*\*/;
95
95
  const tdiPattern = tdiIncRegex.test(transferPattern) ? transferPattern.replace(tdiIncRegex, `${this.deliveryPack ? 'config/' : ''}cmscustom/tdi/**`) : 'nomatch';
96
96
 
97
97
  if (!transferPattern)
@@ -171,7 +171,7 @@ const transfer = (paths, lrServer) => {
171
171
  .pipe(g_replace(c.replaceStrings))
172
172
  .pipe(through2.obj((file, enc, cb) => {
173
173
  file.originalRelativePath = file.relative; // original path needed for sftp.fastPut
174
- file.path = file.path.replace(/(fonto)[\\\/](dev|dist)/, '$1'); // change destination path for fonto build
174
+ file.path = file.path.replace(/(fonto).(?:dev|dist|packages.sx-shell-.+src)(.+)/, '$1$2'); // change destination path for fonto build files
175
175
  if (!file.relative.endsWith('.map')) files.push(file.relative); // collect all file paths in array for livereload
176
176
  cb(null, file);
177
177
  }))
@@ -49,15 +49,17 @@ module.exports = function deploy (argv) {
49
49
  const transfers = {
50
50
  queue: [],
51
51
  do () {
52
+ this.queue = this.queue.map(p => p.replace(/fonto(.)(?:dist|dev).assets.schemas(.sx-shell-.*?).json/, 'fonto$1packages$2$1src$1assets$1schemas$2.json')) // fonto schema changes can be detected in different paths at the same time, rewrite paths to original package-path because files in build folders can be removed before transfer starts
52
53
  this.queue = [...new Set(this.queue)]; // remove duplicates
53
54
  this.queue.forEach(v => s.addToCache(v));
54
55
  transfer(this.queue, lrServer);
55
56
  this.queue = [];
56
57
  },
57
58
  add (fp) {
59
+ const delay = !fp.match(/fonto/) ? 500 : 1500; // longer delay for fonto build files
58
60
  this.queue.push(fp);
59
61
  clearTimeout(this.delayedExec);
60
- this.delayedExec = setTimeout(()=>transfers.do(), 500);
62
+ this.delayedExec = setTimeout(()=>transfers.do(), delay);
61
63
  }
62
64
  };
63
65
 
@@ -67,12 +69,17 @@ module.exports = function deploy (argv) {
67
69
  sftp.connect(c.server.ftpConfig).then(() => sftp.end()).catch(err => _error(`Could not connect to server${err ? ': '+err.message : ''}`));
68
70
  }
69
71
 
70
- // for fonto, only watch dev/dist (for the build, does not detect "assets" most of the times btw)
71
- gulp.watch([...c.transferPatterns, `!**/fonto/!(${c.envDev?'dev|':''}dist)/**`])
72
+ gulp.watch(c.transferPatterns)
72
73
  .on('all', (event, filepath) => {
73
74
 
74
- if ((event=='add' || event=='change') &&
75
- (/fonto.(dev|dist)/.test(filepath) || !/fonto/.test(filepath)) // within fonto, only transfer build files
75
+ if ((event=='add' || event=='change') && (
76
+ // within fonto, transfer build files only, but also schema files, because
77
+ // the "dist" folder isn't watched properly: it does not detect "assets" anymore after building once
78
+ !/cmscustom.+fonto[\\\/]/.test(filepath) ||
79
+ /fonto[\\\/]dist/.test(filepath) ||
80
+ (/fonto[\\\/]dev/.test(filepath) && c.envDev) ||
81
+ /fonto[\\\/]packages[\\\/]sx-shell-.*?[\\\/]assets[\\\/]schemas[\\\/]/.test(filepath)
82
+ )
76
83
  ) {
77
84
  transfers.add(filepath);
78
85
  }
@@ -92,6 +92,7 @@ module.exports = {
92
92
 
93
93
  const {rootSchemas} = fs.readJsonSync('../schema/fonto.json');
94
94
  const fontoManifest = fs.readJsonSync('config/fonto-manifest.json');
95
+ let jsonPaths = [];
95
96
 
96
97
  // remove all schema packages (sx-shell-*) from fonto-manifest.json
97
98
  Object.keys(fontoManifest.dependencies).filter(k => k.includes('sx-shell-')).forEach(k => {
@@ -100,13 +101,14 @@ module.exports = {
100
101
 
101
102
  // add dependency for sx-module to each package fonto-manifest.json
102
103
  // add schema packages in fonto.json to config/fonto-manifest.json
103
- Object.entries(rootSchemas).forEach(([path, obj]) => {
104
+ Object.entries(rootSchemas).forEach(([xsdPath, obj]) => {
104
105
  const pckPath = 'packages/' + obj.packageName;
105
106
  const pckFontoManifest = fs.readJsonSync(pckPath + '/fonto-manifest.json', {throws: false}) || {dependencies: {}};
106
107
  pckFontoManifest.dependencies['sx-module'] = 'packages/sx-module';
107
108
  fs.outputJsonSync(pckPath + '/fonto-manifest.json', pckFontoManifest, {spaces: 2});
108
109
  _write(`${pckPath}/fonto-manifest.json`);
109
110
  fontoManifest.dependencies[obj.packageName] = pckPath;
111
+ jsonPaths.push(`${pckPath}/src/assets/schemas/${obj.packageName}.json`);
110
112
  });
111
113
 
112
114
  fs.outputJsonSync('config/fonto-manifest.json', fontoManifest, {spaces: 2});
@@ -119,6 +121,13 @@ module.exports = {
119
121
  _write('config/schemaExperienceResolver.js');
120
122
 
121
123
  _write();
124
+ _info('Copying schema json files to build folders:');
125
+ // deploy-watch copies schema's to server directly, so update local builds to keep integrity
126
+ jsonPaths.forEach(jsonPath => {
127
+ fs.copySync(jsonPath, 'dev/assets/schemas/' + jsonPath.match(/[^//]*$/)[0]);
128
+ fs.copySync(jsonPath, 'dist/assets/schemas/' + jsonPath.match(/[^//]*$/)[0]);
129
+ })
130
+ _write('Done.\n');
122
131
  })
123
132
  ;
124
133
  },
@@ -133,7 +142,7 @@ module.exports = {
133
142
  let ignoreElements = [];
134
143
  fs.readdirSync(tdiXsdPath).forEach(filename => {
135
144
  const file = fs.readFileSync(tdiXsdPath + filename, {encoding: 'UTF-8'});
136
- ignoreElements.push(...file.match(/(?<=xs:element name=")[^"]+(?=")/g));
145
+ ignoreElements.push(...(file.match(/(?<=xs:element name=")[^"]+(?=")/g)||[]));
137
146
  });
138
147
  ignoreElements = [...new Set(ignoreElements)]; // remove duplicates
139
148
 
@@ -169,6 +178,54 @@ module.exports = {
169
178
  );
170
179
  },
171
180
 
181
+ attributes () {
182
+ _info('Attributes requiring custom configuration:');
183
+
184
+ const findAttributes = ({rootSchemas, tdiXsdPath}) => { // cannot use variables from outside this function
185
+ const {execSync} = require('child_process'), fs = require('fs');
186
+
187
+ // get all attributes defined in default schema
188
+ let ignoreAttributes = [];
189
+ fs.readdirSync(tdiXsdPath).forEach(filename => {
190
+ const file = fs.readFileSync(tdiXsdPath + filename, {encoding: 'UTF-8'});
191
+ ignoreAttributes.push(...(file.match(/(?<=xs:attribute name=")[^"]+(?=")/g)||[]));
192
+ });
193
+ ignoreAttributes = [...new Set(ignoreAttributes)]; // remove duplicates
194
+
195
+ // execute "fdt attributes" for each schema package, ignore default attributes, and combine results
196
+ const schemasPerAttribute = {};
197
+ Object.entries(rootSchemas).forEach(([path, obj]) => {
198
+ const data = execSync(`fdt attributes --schema ${obj.packageName}`, {encoding: 'UTF-8'});
199
+ const attributes = data.replace(/^.*?Default value\s+|\s+Printed name\*.*$/gs, '').split(/\n\s+/).map(a => a.split(/\s+/)).map(a =>
200
+ a[0] + (a[2]=='required' ? ' (required)' : '') + (a[3]=='-' ? ' (no default)' : '')
201
+ );
202
+ const customAttributes = [...new Set(attributes)].filter(e => e && !ignoreAttributes.includes(e.replace(/ .*/, '')));
203
+
204
+ customAttributes.forEach(e => {
205
+ if (schemasPerAttribute[e]) schemasPerAttribute[e] = [...schemasPerAttribute[e], obj.packageName];
206
+ else schemasPerAttribute[e] = [obj.packageName];
207
+ });
208
+ });
209
+
210
+ const result = [];
211
+ Object.entries(schemasPerAttribute).forEach(([e, s]) => result.push([e, s])); // convert object to array
212
+ return result[0] ? result : 'No results.';
213
+ };
214
+
215
+ return wws(
216
+ 'searching',
217
+ findAttributes,
218
+ {
219
+ rootSchemas: fs.readJsonSync('../schema/fonto.json').rootSchemas,
220
+ tdiXsdPath: path.join(_paths.repo, _paths.tdi, 'src/config/cmscustom/[customer]/[project]/schema/xsd/')
221
+ },
222
+ result => {
223
+ if (Array.isArray(result)) result.forEach(([e, s]) => _write(e, s, '\n'));
224
+ else _write(result, '\n');
225
+ }
226
+ );
227
+ },
228
+
172
229
  localize () {
173
230
  const templateFile = 'messages-template-packages.json';
174
231
  const messagesFile = 'packages/localization/src/messages.nl.json';
@@ -31,6 +31,7 @@ module.exports = function fonto (argv) {
31
31
  .then(argv.init && (()=>commands.init(argv.init)))
32
32
  .then(argv.schema && commands.schema)
33
33
  .then(argv.elements && commands.elements)
34
+ .then(argv.attributes && commands.attributes)
34
35
  .then(argv.localize && commands.localize)
35
36
  .then(argv.build && commands.build)
36
37
  .then(argv.run && commands.run)
@@ -47,7 +47,7 @@ module.exports = function steps (step, dry, filter) {
47
47
  r.to = r.fromtoPairs.map(p => p[1]);
48
48
  }
49
49
 
50
- let filesModCount;
50
+ let filesModCount = 0;
51
51
  for (let i=0; i<20 && !dry && r.files[0]; i++) { // execute repeatedly for modified files only (with safety limit of 20)
52
52
  r.files = rif.sync(r).filter(f => f.hasChanged).map(f => f.file);
53
53
  if (i==0) filesModCount = r.files.length; // save count only after first run (after this only subsets are processed)