neo.mjs 4.0.62 → 4.0.65

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/README.md CHANGED
@@ -236,12 +236,12 @@ More infos: <a href="./BACKERS.md">Sponsors & Backers</a>
236
236
  </br></br>
237
237
  <h2 id="jobs">14. Jobs</h2>
238
238
  Accenture is hiring multiple neo.mjs developers for the new Cloud Technology Studio in Kaiserslauern (Germany):</br>
239
- <a href="https://www.accenture.com/de-de/careers/jobdetails?id=R00057924_de">Senior neo.mjs Frontend Developer /Architect (all genders)</a></br></br>
240
-
239
+ </br>
241
240
  These full-time roles are based on German contracts, so they require living in (or relocating to) Germany.
241
+ Ping us on LinkedIn or Slack for details.
242
242
 
243
243
  </br></br>
244
- Logo contributed by <a href="https://www.linkedin.com/in/dinkheller/">Torsten Dinkheller</a>.
244
+ Logo contributed by <a href="https://www.linkedin.com/in/torsten-dinkheller-614516231/">Torsten Dinkheller</a>.
245
245
 
246
246
  </br></br>
247
247
  Build with :heart: in Germany.
@@ -14,7 +14,7 @@ const
14
14
  cwd = process.cwd(),
15
15
  requireJson = path => JSON.parse(fs.readFileSync((path))),
16
16
  packageJson = requireJson(path.join(__dirname, 'package.json')),
17
- insideNeo = packageJson.name === 'neo.mjs',
17
+ insideNeo = process.env.npm_package_name === 'neo.mjs',
18
18
  program = new Command(),
19
19
  programName = `${packageJson.name} create-class`,
20
20
  questions = [],
@@ -27,7 +27,7 @@ const
27
27
  * folder (parent of cwd, child of sourceRootDirs[n]) will then be used as the
28
28
  * namespace for this created class.
29
29
  * Can be overwritten with the -s option.
30
- * @type {string[]}
30
+ * @type {String[]}
31
31
  */
32
32
  sourceRootDirs = ['apps'];
33
33
 
@@ -94,7 +94,7 @@ if (programOpts.info) {
94
94
  type : 'input',
95
95
  name : 'className',
96
96
  message: 'Please choose the namespace for your class:',
97
- default: 'Covid.view.HeaderContainerController'
97
+ default: 'Covid.view.MyContainer'
98
98
  });
99
99
  }
100
100
 
@@ -103,8 +103,17 @@ if (programOpts.info) {
103
103
  type : 'list',
104
104
  name : 'baseClass',
105
105
  message: 'Please pick the base class, which you want to extend:',
106
- choices: ['component.Base', 'container.Base', 'controller.Component', 'core.Base'],
107
- default: 'container.Base'
106
+ default: 'container.Base',
107
+
108
+ choices: [
109
+ 'component.Base',
110
+ 'container.Base',
111
+ 'controller.Component',
112
+ 'core.Base',
113
+ 'data.Model',
114
+ 'data.Store',
115
+ 'model.Component'
116
+ ]
108
117
  });
109
118
  }
110
119
 
@@ -113,7 +122,7 @@ if (programOpts.info) {
113
122
  className = programOpts.className || answers.className,
114
123
  isDrop = programOpts.drop,
115
124
  startDate = new Date(),
116
- classFolder, file, folderDelta, index, ns, root, rootLowerCase, viewFile;
125
+ baseFileName, baseType, classFolder, configName, file, folderDelta, importName, importPath, index, ns, root, rootLowerCase, viewFile;
117
126
 
118
127
  if (className.endsWith('.mjs')) {
119
128
  className = className.slice(0, -4);
@@ -184,8 +193,8 @@ if (programOpts.info) {
184
193
  }
185
194
 
186
195
  if (isDrop !== true) {
187
- if (fs.existsSync(path.resolve(__dirname, 'apps', rootLowerCase))) {
188
- classFolder = path.resolve(__dirname, 'apps', rootLowerCase, ns.join('/'));
196
+ if (fs.existsSync(path.resolve(cwd, 'apps', rootLowerCase))) {
197
+ classFolder = path.resolve(cwd, 'apps', rootLowerCase, ns.join('/'));
189
198
  } else {
190
199
  console.log('\nNon existing neo app name:', chalk.red(root));
191
200
  process.exit(1);
@@ -198,17 +207,87 @@ if (programOpts.info) {
198
207
 
199
208
  fs.mkdirpSync(classFolder);
200
209
 
201
- fs.writeFileSync(path.join(classFolder, file + '.mjs'), createContent({baseClass, className, file, folderDelta, ns, root}));
210
+ baseFileName = baseClass.split('.').pop();
202
211
 
203
- if (baseClass === 'controller.Component') {
204
- index = file.indexOf('Controller');
212
+ if (baseFileName === file) {
213
+ baseFileName = baseClass.split('.');
214
+ baseFileName = baseFileName.map(e => capitalize(e)).join('');
215
+ }
216
+
217
+ console.log(baseFileName, baseClass);
218
+
219
+ fs.writeFileSync(path.join(classFolder, file + '.mjs'), createContent({
220
+ baseClass,
221
+ baseFileName,
222
+ className,
223
+ file,
224
+ folderDelta,
225
+ ns,
226
+ root
227
+ }));
228
+
229
+ switch(baseClass) {
230
+ case 'controller.Component': {
231
+ baseType = 'Neo.controller.Component';
232
+ configName = 'controller';
233
+ importName = file;
234
+ importPath = `./${importName}.mjs`;
235
+ index = file.indexOf('Controller');
236
+
237
+ if (index > 0) {
238
+ viewFile = path.join(classFolder, file.substr(0, index) + '.mjs');
239
+
240
+ if (fs.existsSync(viewFile)) {
241
+ adjustView({baseType, configName, importName, importPath, viewFile});
242
+ }
243
+ }
244
+ break;
245
+ }
246
+
247
+ case 'data.Store': {
248
+ baseType = 'Neo.data.Model';
249
+ configName = 'model';
250
+ importName = className.replace('.store.', '.model.');
251
+
252
+ if (importName.endsWith('ies')) {
253
+ importName.replace(new RegExp('ies$'), 'y')
254
+ } else {
255
+ importName = importName.slice(0, -1);
256
+ }
257
+
258
+ viewFile = importName.split('.');
259
+ viewFile.shift();
205
260
 
206
- if (index > 0) {
207
- viewFile = path.join(classFolder, file.substr(0, index) + '.mjs');
261
+ importPath = `../${viewFile.join('/')}.mjs`;
262
+ viewFile = path.join(classFolder, importPath);
208
263
 
264
+ // checking for the data.Model file
209
265
  if (fs.existsSync(viewFile)) {
210
- adjustView({file, viewFile});
266
+ // adjusting the data.Store file
267
+ viewFile = path.join(classFolder, file + '.mjs');
268
+ importName = importName.split('.');
269
+ importName = importName.pop();
270
+
271
+ adjustView({baseType, configName, importName, importPath, viewFile});
272
+ }
273
+ break;
274
+ }
275
+
276
+ case 'model.Component': {
277
+ baseType = 'Neo.model.Component';
278
+ configName = 'model';
279
+ importName = file;
280
+ importPath = `./${importName}.mjs`;
281
+ index = file.indexOf('Model');
282
+
283
+ if (index > 0) {
284
+ viewFile = path.join(classFolder, file.substr(0, index) + '.mjs');
285
+
286
+ if (fs.existsSync(viewFile)) {
287
+ adjustView({baseType, configName, importName, importPath, viewFile});
288
+ }
211
289
  }
290
+ break;
212
291
  }
213
292
  }
214
293
  }
@@ -222,27 +301,58 @@ if (programOpts.info) {
222
301
  /**
223
302
  * Adds a comma to the last element of the contentArray
224
303
  * @param {String[]} contentArray
304
+ * @param {Number} index=contentArray.length - 1
225
305
  * @returns {String[]}
226
306
  */
227
- function addComma(contentArray) {
228
- contentArray[contentArray.length - 1] += ',';
307
+ function addComma(contentArray, index=contentArray.length - 1) {
308
+ contentArray[index] += ',';
229
309
  return contentArray;
230
310
  }
231
311
 
312
+ /**
313
+ * Adds a config to the given index of the contentArray
314
+ * @param {Object} opts
315
+ * @param {String} opts.baseType
316
+ * @param {String} opts.className
317
+ * @param {String} opts.configName
318
+ * @param {String[]} opts.contentArray
319
+ * @param {Boolean} opts.isLastConfig
320
+ * @param {Number} opts.index
321
+ * @returns {String[]}
322
+ */
323
+ function addConfig(opts) {
324
+ const config = [
325
+ ' /**',
326
+ ` * @member {${opts.baseType}} ${opts.configName}=${opts.className}`,
327
+ ' */',
328
+ ` ${opts.configName}: ${opts.className}`
329
+ ];
330
+
331
+ !opts.isLastConfig && addComma(config);
332
+
333
+ opts.contentArray.splice(opts.index, 0, config.join(os.EOL));
334
+ return opts.contentArray;
335
+ }
336
+
232
337
  /**
233
338
  * Adjusts the views related to controller.Component or model.Component
234
339
  * @param {Object} opts
235
- * @param {String} opts.file
340
+ * @param {String} opts.baseType
341
+ * @param {String} opts.configName
342
+ * @param {String} opts.importName
343
+ * @param {String} opts.importPath
236
344
  * @param {String} opts.viewFile
237
345
  */
238
346
  function adjustView(opts) {
239
- let file = opts.file,
347
+ let baseType = opts.baseType,
348
+ configName = opts.configName,
349
+ importName = opts.importName,
240
350
  viewFile = opts.viewFile,
241
351
  content = fs.readFileSync(viewFile).toString().split(os.EOL),
242
352
  fromMaxPosition = 0,
243
353
  i = 0,
244
354
  len = content.length,
245
- adjustSpaces, codeLine, fromPosition, importLength, importName, j, spaces;
355
+ adjustSpaces, className, codeLine, existingImportName, fromPosition, importLength, j, nextLine, spaces;
246
356
 
247
357
  // find the index where we want to insert our import statement
248
358
  for (; i < len; i++) {
@@ -252,16 +362,16 @@ if (programOpts.info) {
252
362
  break;
253
363
  }
254
364
 
255
- importName = codeLine.substr(7);
256
- importName = importName.substr(0, importName.indexOf(' '));
257
- importLength = importName.length;
365
+ existingImportName = codeLine.substr(7);
366
+ existingImportName = existingImportName.substr(0, existingImportName.indexOf(' '));
367
+ importLength = existingImportName.length;
258
368
 
259
- if (importName > file) {
369
+ if (existingImportName > importName) {
260
370
  break;
261
371
  }
262
372
  }
263
373
 
264
- content.splice(i, 0, `import ${file} from './${file}.mjs';`);
374
+ content.splice(i, 0, `import ${importName} from '${opts.importPath}';`);
265
375
 
266
376
  // find the longest import module name
267
377
  for (i=0; i < len; i++) {
@@ -296,16 +406,76 @@ if (programOpts.info) {
296
406
  }
297
407
  }
298
408
 
409
+ i = 0;
410
+ len = content.length;
411
+
412
+ // find the starting point
413
+ for (; i < len; i++) {
414
+ if (content[i].includes('static getConfig')) {
415
+ break;
416
+ }
417
+ }
418
+
419
+ for (; i < len; i++) {
420
+ codeLine = content[i];
421
+
422
+ if (codeLine.includes('}}')) {
423
+ addComma(content, i - 1);
424
+ addConfig({
425
+ baseType,
426
+ className : importName,
427
+ configName,
428
+ contentArray: content,
429
+ index : i,
430
+ isLastConfig: true
431
+ });
432
+ break;
433
+ }
434
+
435
+ if (codeLine.includes('*/')) {
436
+ nextLine = content[i + 1]
437
+ className = nextLine.substring(0, nextLine.indexOf(':')).trim();
438
+
439
+ if (className === 'className' || className === 'ntype') {
440
+ continue;
441
+ }
442
+
443
+ if (className > configName) {
444
+ for (j=i; j > 0; j--) {
445
+ if (content[j].includes('/**')) {
446
+ addConfig({
447
+ baseType,
448
+ className : importName,
449
+ configName,
450
+ contentArray: content,
451
+ index : j,
452
+ isLastConfig: false
453
+ });
454
+ break;
455
+ }
456
+ }
457
+ break;
458
+ }
459
+ }
460
+ }
461
+
299
462
  fs.writeFileSync(viewFile, content.join(os.EOL));
463
+ }
300
464
 
301
- console.log(i, opts.file);
302
- console.log(content);
465
+ /**
466
+ * Makes the first character of a string uppercase
467
+ * @param {String} value
468
+ * @returns {Boolean|String} Returns false for non string inputs
469
+ */
470
+ function capitalize(value) {
471
+ return typeof value === 'string' && value[0].toUpperCase() + value.slice(1);
303
472
  }
304
473
 
305
474
  /**
306
475
  * Creates the content of the neo-class .mjs file
307
476
  * @param {Object} opts
308
477
  * @param {String} opts.baseClass
478
+ * @param {String} opts.baseFileName
309
479
  * @param {String} opts.className
310
480
  * @param {String} opts.file
311
481
  * @param {String} opts.folderDelta
@@ -314,20 +484,20 @@ if (programOpts.info) {
314
484
  * @returns {String}
315
485
  */
316
486
  function createContent(opts) {
317
- let baseClass = opts.baseClass,
318
- baseClassNs = baseClass.split('.'),
319
- baseFileName = baseClassNs.pop(),
320
- className = opts.className,
321
- file = opts.file,
322
- i = 0,
323
- importDelta = '';
487
+ let baseClass = opts.baseClass,
488
+ baseFileName = opts.baseFileName,
489
+ baseClassPath = baseClass.split('.').join('/'),
490
+ className = opts.className,
491
+ file = opts.file,
492
+ i = 0,
493
+ importDelta = '';
324
494
 
325
495
  for (; i < opts.folderDelta; i++) {
326
496
  importDelta += '../';
327
497
  }
328
498
 
329
499
  let classContent = [
330
- `import ${baseFileName} from '${importDelta}${(insideNeo ? '' : 'node_modules/neo.mjs/')}src/${baseClassNs.join('/')}/${baseFileName}.mjs';`,
500
+ `import ${baseFileName} from '${importDelta}${(insideNeo ? '' : 'node_modules/neo.mjs/')}src/${baseClassPath}.mjs';`,
331
501
  "",
332
502
  "/**",
333
503
  ` * @class ${className}`,
@@ -342,6 +512,16 @@ if (programOpts.info) {
342
512
  ` className: '${className}'`
343
513
  ];
344
514
 
515
+ baseClass === 'data.Model' && addComma(classContent).push(
516
+ " /*",
517
+ " * @member {Object[]} fields",
518
+ " */",
519
+ " fields: [{",
520
+ " name: 'id',",
521
+ " type: 'String'",
522
+ " }]"
523
+ );
524
+
345
525
  baseClass === 'container.Base' && addComma(classContent).push(
346
526
  " /*",
347
527
  " * @member {Object[]} items",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "4.0.62",
3
+ "version": "4.0.65",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
package/src/core/Util.mjs CHANGED
@@ -40,11 +40,11 @@ class Util extends Base {
40
40
 
41
41
  /**
42
42
  * Makes the first character of a string uppercase
43
- * @param {String} string
43
+ * @param {String} value
44
44
  * @returns {Boolean|String} Returns false for non string inputs
45
45
  */
46
- static capitalize(string) {
47
- return Util.isString(string) && string[0].toUpperCase() + string.slice(1);
46
+ static capitalize(value) {
47
+ return Util.isString(value) && value[0].toUpperCase() + value.slice(1);
48
48
  }
49
49
 
50
50
  /**
@@ -100,7 +100,7 @@ class Util extends Base {
100
100
  }
101
101
 
102
102
  /**
103
- * Transforms all uppercase characters of a string into lowercase.
103
+ * Transforms all uppercase characters of a string into -lowercase.
104
104
  * Does not touch special characters.
105
105
  * @param {String} value The input containing uppercase characters
106
106
  * @returns {String} The lowercase output