neo.mjs 4.0.51 → 4.0.52
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.
|
@@ -1,24 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { Command } from 'commander/esm.mjs';
|
|
5
|
+
import envinfo from 'envinfo';
|
|
6
|
+
import fs from 'fs-extra';
|
|
7
|
+
import inquirer from 'inquirer';
|
|
8
|
+
import os from 'os';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import {fileURLToPath} from 'url';
|
|
11
|
+
|
|
12
|
+
const
|
|
13
|
+
__dirname = fileURLToPath(new URL('../', import.meta.url)),
|
|
10
14
|
cwd = process.cwd(),
|
|
11
15
|
requireJson = path => JSON.parse(fs.readFileSync((path))),
|
|
12
16
|
packageJson = requireJson(path.join(__dirname, 'package.json')),
|
|
13
17
|
insideNeo = packageJson.name === 'neo.mjs',
|
|
14
18
|
program = new Command(),
|
|
15
19
|
programName = `${packageJson.name} create-class`,
|
|
16
|
-
questions = []
|
|
20
|
+
questions = [],
|
|
21
|
+
/**
|
|
22
|
+
* Maintain a list of dir-names recognized as source root directories.
|
|
23
|
+
* When not using dot notation with a class-name, the program assumes
|
|
24
|
+
* that we want to create the class inside the cwd. The proper namespace
|
|
25
|
+
* is then looked up by traversing the directory path up to the first
|
|
26
|
+
* folder that matches an entry in "sourceRootDirs". The owning
|
|
27
|
+
* folder (parent of cwd, child of sourceRootDirs[n]) will then be used as the
|
|
28
|
+
* namespace for this created class.
|
|
29
|
+
* Can be overwritten with the -s option.
|
|
30
|
+
* @type {string[]}
|
|
31
|
+
*/
|
|
32
|
+
sourceRootDirs = ['apps'];
|
|
17
33
|
|
|
18
34
|
program
|
|
19
35
|
.name(programName)
|
|
20
36
|
.version(packageJson.version)
|
|
21
37
|
.option('-i, --info', 'print environment debug info')
|
|
38
|
+
.option('-d, --drop', 'drops class in the currently selected folder')
|
|
39
|
+
.option('-s, --source <value>', `name of the folder containing the project. Defaults to any of ${sourceRootDirs.join(',')}`)
|
|
22
40
|
.option('-b, --baseClass <value>')
|
|
23
41
|
.option('-c, --className <value>')
|
|
24
42
|
.allowUnknownOption()
|
|
@@ -33,7 +51,7 @@ const programOpts = program.opts();
|
|
|
33
51
|
if (programOpts.info) {
|
|
34
52
|
console.log(chalk.bold('\nEnvironment Info:'));
|
|
35
53
|
console.log(`\n current version of ${packageJson.name}: ${packageJson.version}`);
|
|
36
|
-
console.log(` running from ${
|
|
54
|
+
console.log(` running from ${cwd}`);
|
|
37
55
|
|
|
38
56
|
envinfo
|
|
39
57
|
.run({
|
|
@@ -49,6 +67,28 @@ if (programOpts.info) {
|
|
|
49
67
|
} else {
|
|
50
68
|
console.log(chalk.green(programName));
|
|
51
69
|
|
|
70
|
+
if (programOpts.drop) {
|
|
71
|
+
// change source folder if the user wants to
|
|
72
|
+
if (programOpts.source) {
|
|
73
|
+
while (sourceRootDirs.length) {
|
|
74
|
+
sourceRootDirs.pop();
|
|
75
|
+
}
|
|
76
|
+
sourceRootDirs.push(programOpts.source);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!programOpts.className || !programOpts.baseClass) {
|
|
80
|
+
console.error(chalk.red('-d is non interactive. Please provide name base class, and optionally the source parent for the class to create'));
|
|
81
|
+
console.info(chalk.bgCyan('Usage: createClass -d -c <className> -b <baseClass> [-s sourceParent]'));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (programOpts.className.indexOf('.') !== -1) {
|
|
86
|
+
console.error(chalk.red('No .dot-notation avcailable when -d option is selected.'));
|
|
87
|
+
console.info(chalk.bgCyan('Usage: createClass -d -c <className> -b <baseClass> [-s sourceParent]'));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
52
92
|
if (!programOpts.className) {
|
|
53
93
|
questions.push({
|
|
54
94
|
type : 'input',
|
|
@@ -71,6 +111,7 @@ if (programOpts.info) {
|
|
|
71
111
|
inquirer.prompt(questions).then(answers => {
|
|
72
112
|
let baseClass = programOpts.baseClass || answers.baseClass,
|
|
73
113
|
className = programOpts.className || answers.className,
|
|
114
|
+
isDrop = programOpts.drop,
|
|
74
115
|
startDate = new Date(),
|
|
75
116
|
classFolder, file, folderDelta, index, ns, root, rootLowerCase, viewFile;
|
|
76
117
|
|
|
@@ -78,36 +119,97 @@ if (programOpts.info) {
|
|
|
78
119
|
className = className.slice(0, -4);
|
|
79
120
|
}
|
|
80
121
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
122
|
+
if (!isDrop) {
|
|
123
|
+
ns = className.split('.');
|
|
124
|
+
file = ns.pop();
|
|
125
|
+
root = ns.shift();
|
|
126
|
+
rootLowerCase = root.toLowerCase();
|
|
127
|
+
}
|
|
85
128
|
|
|
86
129
|
if (root === 'Neo') {
|
|
87
130
|
console.log('todo: create the file inside the src folder');
|
|
88
131
|
} else {
|
|
89
|
-
if (
|
|
90
|
-
|
|
132
|
+
if (isDrop === true) {
|
|
133
|
+
ns = [];
|
|
134
|
+
|
|
135
|
+
let pathInfo = path.parse(cwd),
|
|
136
|
+
sep = path.sep,
|
|
137
|
+
baseName, loc = baseName = '',
|
|
138
|
+
tmpNs;
|
|
139
|
+
|
|
140
|
+
sourceRootDirs.some(dir => {
|
|
141
|
+
loc = cwd;
|
|
142
|
+
tmpNs = [];
|
|
143
|
+
|
|
144
|
+
while (pathInfo.root !== loc) {
|
|
145
|
+
baseName = path.resolve(loc, './').split(sep).pop();
|
|
146
|
+
|
|
147
|
+
if (baseName === dir) {
|
|
148
|
+
ns = tmpNs.reverse();
|
|
149
|
+
classFolder = path.resolve(loc, ns.join(sep));
|
|
150
|
+
file = className;
|
|
151
|
+
className = ns.concat(className).join('.');
|
|
152
|
+
loc = path.resolve(loc, ns.join(sep));
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
tmpNs.push(baseName);
|
|
157
|
+
loc = path.resolve(loc, '../');
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
if (!ns.length) {
|
|
162
|
+
console.error(chalk.red(
|
|
163
|
+
'Could not determine namespace for application. Did you provide the ' +
|
|
164
|
+
`correct source parent with -s? (was: ${sourceRootDirs.join(',')}`));
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
console.info(
|
|
169
|
+
chalk.yellow(`Creating ${chalk.bgGreen(className)} extending ${chalk.bgGreen(baseClass)} in ${loc}${sep}${file}.mjs`)
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
let delta_l = path.normalize(__dirname),
|
|
173
|
+
delta_r = path.normalize(loc);
|
|
174
|
+
|
|
175
|
+
if (delta_r.indexOf(delta_l) !== 0) {
|
|
176
|
+
console.error(chalk.red(`Could not determine ${loc} being a child of ${__dirname}`));
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
let delta = delta_r.replace(delta_l, ''),
|
|
181
|
+
parts = delta.split(sep);
|
|
182
|
+
|
|
183
|
+
folderDelta = parts.length;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (isDrop !== true) {
|
|
187
|
+
if (fs.existsSync(path.resolve(__dirname, 'apps', rootLowerCase))) {
|
|
188
|
+
classFolder = path.resolve(__dirname, 'apps', rootLowerCase, ns.join('/'));
|
|
189
|
+
} else {
|
|
190
|
+
console.log('\nNon existing neo app name:', chalk.red(root));
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (folderDelta === undefined) {
|
|
91
196
|
folderDelta = ns.length + 2;
|
|
197
|
+
}
|
|
92
198
|
|
|
93
|
-
|
|
199
|
+
fs.mkdirpSync(classFolder);
|
|
94
200
|
|
|
95
|
-
|
|
201
|
+
fs.writeFileSync(path.join(classFolder, file + '.mjs'), createContent({baseClass, className, file, folderDelta, ns, root}));
|
|
96
202
|
|
|
97
|
-
|
|
98
|
-
|
|
203
|
+
if (baseClass === 'controller.Component') {
|
|
204
|
+
index = file.indexOf('Controller');
|
|
99
205
|
|
|
100
|
-
|
|
101
|
-
|
|
206
|
+
if (index > 0) {
|
|
207
|
+
viewFile = path.join(classFolder, file.substr(0, index) + '.mjs');
|
|
102
208
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
209
|
+
if (fs.existsSync(viewFile)) {
|
|
210
|
+
adjustView({file, viewFile});
|
|
106
211
|
}
|
|
107
212
|
}
|
|
108
|
-
} else {
|
|
109
|
-
console.log('\nNon existing neo app name:', chalk.red(root));
|
|
110
|
-
process.exit(1);
|
|
111
213
|
}
|
|
112
214
|
}
|
|
113
215
|
|
|
@@ -97,6 +97,22 @@ class MainContainer extends ConfigurationViewport {
|
|
|
97
97
|
minValue : 50,
|
|
98
98
|
stepSize : 5,
|
|
99
99
|
value : me.exampleComponent.labelWidth
|
|
100
|
+
}, {
|
|
101
|
+
module : NumberField,
|
|
102
|
+
labelText: 'maxLength',
|
|
103
|
+
listeners: {change: me.onConfigChange.bind(me, 'maxLength')},
|
|
104
|
+
maxValue : 50,
|
|
105
|
+
minValue : 1,
|
|
106
|
+
stepSize : 1,
|
|
107
|
+
value : me.exampleComponent.maxLength
|
|
108
|
+
}, {
|
|
109
|
+
module : NumberField,
|
|
110
|
+
labelText: 'minLength',
|
|
111
|
+
listeners: {change: me.onConfigChange.bind(me, 'minLength')},
|
|
112
|
+
maxValue : 50,
|
|
113
|
+
minValue : 1,
|
|
114
|
+
stepSize : 1,
|
|
115
|
+
value : me.exampleComponent.minLength
|
|
100
116
|
}, {
|
|
101
117
|
module : TextField,
|
|
102
118
|
clearable: true,
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neo.mjs",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.52",
|
|
4
4
|
"description": "The webworkers driven UI framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/neomjs/neo.git"
|
|
9
9
|
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"neo-cc": "./buildScripts/createClass.mjs"
|
|
12
|
+
},
|
|
10
13
|
"scripts": {
|
|
11
14
|
"build-all": "node ./buildScripts/buildAll.mjs -f -n",
|
|
12
15
|
"build-all-questions": "node ./buildScripts/buildAll.mjs -f",
|
|
@@ -51,7 +54,7 @@
|
|
|
51
54
|
"neo-jsdoc": "^1.0.1",
|
|
52
55
|
"neo-jsdoc-x": "^1.0.4",
|
|
53
56
|
"postcss": "^8.4.14",
|
|
54
|
-
"sass": "^1.
|
|
57
|
+
"sass": "^1.53.0",
|
|
55
58
|
"webpack": "^5.73.0",
|
|
56
59
|
"webpack-cli": "^4.10.0",
|
|
57
60
|
"webpack-dev-server": "4.9.2",
|
|
@@ -59,7 +62,8 @@
|
|
|
59
62
|
"webpack-node-externals": "^3.0.0"
|
|
60
63
|
},
|
|
61
64
|
"devDependencies": {
|
|
62
|
-
"siesta-lite": "^5.5.2"
|
|
65
|
+
"siesta-lite": "^5.5.2",
|
|
66
|
+
"url": "^0.11.0"
|
|
63
67
|
},
|
|
64
68
|
"funding": {
|
|
65
69
|
"type": "GitHub Sponsors",
|
|
@@ -28,9 +28,9 @@ class RecordFactory extends Base {
|
|
|
28
28
|
*/
|
|
29
29
|
ovPrefix: 'ov_',
|
|
30
30
|
/**
|
|
31
|
-
* @member {String} recordNamespace='Neo.data.record
|
|
31
|
+
* @member {String} recordNamespace='Neo.data.record'
|
|
32
32
|
*/
|
|
33
|
-
recordNamespace: 'Neo.data.record
|
|
33
|
+
recordNamespace: 'Neo.data.record'
|
|
34
34
|
}}
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -39,7 +39,7 @@ class RecordFactory extends Base {
|
|
|
39
39
|
* @returns {Object}
|
|
40
40
|
*/
|
|
41
41
|
createRecord(model, config) {
|
|
42
|
-
let recordClass = Neo.ns(this.recordNamespace
|
|
42
|
+
let recordClass = Neo.ns(`${this.recordNamespace}.${model.className}.${model.id}`);
|
|
43
43
|
|
|
44
44
|
if (!recordClass) {
|
|
45
45
|
recordClass = this.createRecordClass(model);
|
|
@@ -54,7 +54,7 @@ class RecordFactory extends Base {
|
|
|
54
54
|
*/
|
|
55
55
|
createRecordClass(model) {
|
|
56
56
|
if (model instanceof Model) {
|
|
57
|
-
let className = this.recordNamespace
|
|
57
|
+
let className = `${this.recordNamespace}.${model.className}.${model.id}`,
|
|
58
58
|
ns = Neo.ns(className),
|
|
59
59
|
key, nsArray;
|
|
60
60
|
|
|
@@ -76,7 +76,7 @@ class RecordFactory extends Base {
|
|
|
76
76
|
|
|
77
77
|
if (Array.isArray(model.fields)) {
|
|
78
78
|
model.fields.forEach(field => {
|
|
79
|
-
let parsedValue = instance.parseRecordValue(field, config[field.name], config),
|
|
79
|
+
let parsedValue = instance.parseRecordValue(me, field, config[field.name], config),
|
|
80
80
|
symbol = Symbol.for(field.name);
|
|
81
81
|
|
|
82
82
|
properties = {
|
|
@@ -97,9 +97,9 @@ class RecordFactory extends Base {
|
|
|
97
97
|
let me = this,
|
|
98
98
|
oldValue = me[symbol];
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
value = instance.parseRecordValue(field, value, null);
|
|
100
|
+
value = instance.parseRecordValue(me, field, value);
|
|
102
101
|
|
|
102
|
+
if (!Neo.isEqual(value, oldValue)) {
|
|
103
103
|
me[symbol] = value;
|
|
104
104
|
|
|
105
105
|
me._isModified = true;
|
|
@@ -221,14 +221,18 @@ class RecordFactory extends Base {
|
|
|
221
221
|
|
|
222
222
|
/**
|
|
223
223
|
* todo: parse value for more field types
|
|
224
|
+
* @param {Object} record
|
|
224
225
|
* @param {Object} field
|
|
225
226
|
* @param {*} value
|
|
226
|
-
* @param {Object} recordConfig
|
|
227
|
+
* @param {Object} recordConfig=null
|
|
227
228
|
* @returns {*}
|
|
228
229
|
*/
|
|
229
|
-
parseRecordValue(field, value, recordConfig) {
|
|
230
|
-
let mapping
|
|
231
|
-
|
|
230
|
+
parseRecordValue(record, field, value, recordConfig=null) {
|
|
231
|
+
let mapping = field.mapping,
|
|
232
|
+
maxLength = field.maxLength,
|
|
233
|
+
minLength = field.minLength,
|
|
234
|
+
oldValue = recordConfig?.[field.name] || record[field.name],
|
|
235
|
+
type = field.type?.toLowerCase();
|
|
232
236
|
|
|
233
237
|
// only trigger mappings for initial values
|
|
234
238
|
// dynamic changes of a field will not pass the recordConfig
|
|
@@ -240,7 +244,21 @@ class RecordFactory extends Base {
|
|
|
240
244
|
value = ns[key];
|
|
241
245
|
}
|
|
242
246
|
|
|
243
|
-
if (
|
|
247
|
+
if (Object.hasOwn(field, maxLength)) {
|
|
248
|
+
if (value?.toString() > maxLength) {
|
|
249
|
+
console.warn(`Setting record field: ${field} value: ${value} conflicts with the maxLength: ${maxLength}`);
|
|
250
|
+
return oldValue;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (Object.hasOwn(field, minLength)) {
|
|
255
|
+
if (value?.toString() < minLength) {
|
|
256
|
+
console.warn(`Setting record field: ${field} value: ${value} conflicts with the minLength: ${minLength}`);
|
|
257
|
+
return oldValue;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (type === 'date' && Neo.typeOf(value) !== 'Date') {
|
|
244
262
|
return new Date(value);
|
|
245
263
|
}
|
|
246
264
|
|
|
@@ -259,6 +277,7 @@ class RecordFactory extends Base {
|
|
|
259
277
|
|
|
260
278
|
Object.entries(fields).forEach(([key, value]) => {
|
|
261
279
|
oldValue = record[key];
|
|
280
|
+
value = instance.parseRecordValue(record, model.getField(key), value);
|
|
262
281
|
|
|
263
282
|
if (!Neo.isEqual(oldValue, value)) {
|
|
264
283
|
record[Symbol.for(key)] = value; // silent update
|
|
@@ -237,12 +237,13 @@ class Number extends Text {
|
|
|
237
237
|
*/
|
|
238
238
|
onSpinButtonDownClick() {
|
|
239
239
|
let me = this,
|
|
240
|
-
|
|
241
|
-
|
|
240
|
+
stepSize = me.stepSize,
|
|
241
|
+
oldValue = Neo.isNumber(me.value) ? me.value : me.minValue,
|
|
242
|
+
value = (oldValue - stepSize) < me.minValue ? me.maxValue : (oldValue - stepSize);
|
|
242
243
|
|
|
243
244
|
if (me.excludedValues) {
|
|
244
245
|
while(me.excludedValues.includes(value)) {
|
|
245
|
-
value = Math.max(me.minValue, value -
|
|
246
|
+
value = Math.max(me.minValue, value - stepSize);
|
|
246
247
|
}
|
|
247
248
|
}
|
|
248
249
|
|
|
@@ -256,12 +257,13 @@ class Number extends Text {
|
|
|
256
257
|
*/
|
|
257
258
|
onSpinButtonUpClick() {
|
|
258
259
|
let me = this,
|
|
259
|
-
|
|
260
|
-
|
|
260
|
+
stepSize = me.stepSize,
|
|
261
|
+
oldValue = Neo.isNumber(me.value) ? me.value : me.maxValue,
|
|
262
|
+
value = (oldValue + stepSize) > me.maxValue ? me.minValue : (oldValue + stepSize);
|
|
261
263
|
|
|
262
264
|
if (me.excludedValues) {
|
|
263
265
|
while(me.excludedValues.includes(value)) {
|
|
264
|
-
value = Math.min(me.maxValue, value +
|
|
266
|
+
value = Math.min(me.maxValue, value + stepSize);
|
|
265
267
|
}
|
|
266
268
|
}
|
|
267
269
|
|
|
@@ -186,11 +186,15 @@ class DeltaUpdates extends Base {
|
|
|
186
186
|
}
|
|
187
187
|
} else if (key === 'id') {
|
|
188
188
|
node[Neo.config.useDomIds ? 'id' : 'data-neo-id'] = val;
|
|
189
|
-
}else if (key === 'spellcheck' && val === 'false') {
|
|
189
|
+
} else if (key === 'spellcheck' && val === 'false') {
|
|
190
190
|
// see https://github.com/neomjs/neo/issues/1922
|
|
191
191
|
node[key] = false;
|
|
192
192
|
} else {
|
|
193
|
-
|
|
193
|
+
if (key === 'value') {
|
|
194
|
+
node[key] = val;
|
|
195
|
+
} else {
|
|
196
|
+
node.setAttribute(key, val);
|
|
197
|
+
}
|
|
194
198
|
}
|
|
195
199
|
});
|
|
196
200
|
break;
|
package/src/table/Container.mjs
CHANGED
|
@@ -247,9 +247,9 @@ class Container extends BaseContainer {
|
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
if (value) {
|
|
250
|
-
let me = this
|
|
250
|
+
let me = this,
|
|
251
251
|
|
|
252
|
-
|
|
252
|
+
listeners = {
|
|
253
253
|
filter : me.onStoreFilter,
|
|
254
254
|
load : me.onStoreLoad,
|
|
255
255
|
recordChange: me.onStoreRecordChange,
|
|
@@ -258,13 +258,10 @@ class Container extends BaseContainer {
|
|
|
258
258
|
|
|
259
259
|
if (value instanceof Store) {
|
|
260
260
|
value.on(listeners);
|
|
261
|
-
|
|
262
|
-
if (value.getCount() > 0) {
|
|
263
|
-
me.onStoreLoad(value.items);
|
|
264
|
-
}
|
|
261
|
+
value.getCount() > 0 && me.onStoreLoad(value.items);
|
|
265
262
|
} else {
|
|
266
263
|
value = ClassSystemUtil.beforeSetInstance(value, Store, {
|
|
267
|
-
listeners
|
|
264
|
+
listeners
|
|
268
265
|
});
|
|
269
266
|
}
|
|
270
267
|
|