@ygracs/xobj-lib-js 0.2.0 → 0.2.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/lib/xObj-lib.js CHANGED
@@ -1,1562 +1,1568 @@
1
- // [v0.2.091-20240915]
2
-
3
- // === module init block ===
4
-
5
- const {
6
- valueToIndex, valueToIDString,
7
- readAsString, readAsBoolEx, readAsNumberEx,
8
- isNullOrUndef,
9
- isInteger,
10
- isArray, isObject, isPlainObject,
11
- readAsListS,
12
- } = require('@ygracs/bsfoc-lib-js');
13
-
14
- // === module extra block (helper functions) ===
15
-
16
- /**
17
- * @typedef RVAL_reason
18
- * @type {object}
19
- * @property {string} code - message ID
20
- * @property {string} msg - message text
21
- * @description A result of a value check ops.
22
- */
23
-
24
- /**
25
- * @typedef VCOR_evalkname
26
- * @type {object}
27
- * @property {boolean} isSucceed - ops flag
28
- * @property {(string|RVAL_reason)} value - result value or reson if failed
29
- * @description A result of a value check ops.
30
- */
31
-
32
- /**
33
- * @function evalKeyName
34
- * @param {any} value
35
- * @param {boolean} [opt=true]
36
- * @returns {VCOR_evalkname}
37
- * @inner
38
- * @description Tries to convert a value into an ID.
39
- */
40
- function evalKeyName(value, opt = true) {
41
- if (typeof value !== 'string') {
42
- return {
43
- isSucceed: false,
44
- value: {
45
- code: XOBJ_TE_NSTR_ECODE,
46
- msg: XOBJ_TE_NSTR_EMSG,
47
- },
48
- };
49
- };
50
- const key = value.trim();
51
- if (opt && key === '') {
52
- return {
53
- isSucceed: false,
54
- value: {
55
- code: XOBJ_TE_KNES_ECODE,
56
- msg: XOBJ_TE_KNES_EMSG,
57
- },
58
- };
59
- };
60
- return {
61
- isSucceed: true,
62
- value: key,
63
- };
64
- };
65
-
66
- // === module main block ===
67
-
68
- /***
69
- * (* constant definitions *)
70
- */
71
-
72
- const XOBJ_DEF_PARAM_TNAME = '__text';
73
- const XOBJ_DEF_ATTR_TNAME = '__attr';
74
-
75
- const XOBJ_TE_INVARG_EMSG = 'invalid argument';
76
- const XOBJ_TE_NOBJ_EMSG = `${XOBJ_TE_INVARG_EMSG} (an object expected)`;
77
- const XOBJ_TE_NOBJ_ECODE = 'ERR_XOBJ_NOBJ';
78
- const XOBJ_TE_NARR_EMSG = `${XOBJ_TE_INVARG_EMSG} (an array expected)`;
79
- const XOBJ_TE_NARR_ECODE = 'ERR_XOBJ_NARR';
80
- const XOBJ_TE_NSTR_EMSG = `${XOBJ_TE_INVARG_EMSG} (a string expected)`;
81
- const XOBJ_TE_NSTR_ECODE = 'ERR_XOBJ_NSTR';
82
- const XOBJ_TE_NPOBJ_EMSG = `${XOBJ_TE_INVARG_EMSG} (a plain object expected)`;
83
- const XOBJ_TE_NPOBJ_ECODE = 'ERR_XOBJ_NPOBJ';
84
- const XOBJ_TE_ANES_EMSG = '<attr_name> must be a non-empty string';
85
- const XOBJ_TE_ANES_ECODE = 'ERR_XOBJ_INVARG_ATTR';
86
- const XOBJ_TE_KNES_EMSG = '<key_name> must be a non-empty string';
87
- const XOBJ_TE_KNES_ECODE = 'ERR_XOBJ_INVARG_KEY';
88
-
89
- /***
90
- * (* function definitions *)
91
- */
92
-
93
- /**
94
- * @function evalXObjEName
95
- * @param {any}
96
- * @returns {(null|number|string)}
97
- * @description Tries to convert a value into an ID.
98
- */
99
- function evalXObjEName(value) {
100
- //return valueToIDString(value); // // TODO: [?]
101
- let name = value;
102
- switch (typeof name) {
103
- case 'number' : {
104
- if (valueToIndex(name) === -1) name = null;
105
- break;
106
- }
107
- case 'string' : {
108
- name = name.trim();
109
- if (name !== '') {
110
- let value = Number(name);
111
- if (!Number.isNaN(value)) {
112
- name = (
113
- value < 0 || !isInteger(value)
114
- ? null
115
- : value
116
- );
117
- };
118
- } else {
119
- name = null;
120
- };
121
- break;
122
- }
123
- default: {
124
- name = null;
125
- }
126
- };
127
- return name;
128
- };
129
-
130
- /**
131
- * @function genXObjENameDescr
132
- * @param {any}
133
- * @returns {object}
134
- * @description Tries to convert a value into an element name description.
135
- */
136
- function genXObjENameDescr(value) {
137
- let result = null;
138
- let name = null;
139
- let conditions = null;
140
- let isERR = false;
141
- let tail = null;
142
- if (typeof value === 'string') {
143
- const re = /^\s*([^\[\]\s]+)?(\s*)(\[.*])?\s*$/;
144
- tail = value.match(re);
145
- //console.log('CHECK: '+JSON.stringify(tail, null, 2));
146
- if (tail) {
147
- if (tail[1]) {
148
- name = tail[1];
149
- if (name) {
150
- if (tail[2] === '') {
151
- if (tail[3]) {
152
- const re = /\[(@{0,1})(?:([^\[=]*?)(?:(?=[=])(=)((?![\"\'])[^\]]*|(?=([\"\']))\5(.*)\5))?)](\s*.*)/;
153
- tail = tail[3].match(re);
154
- //console.log('CHECK: '+JSON.stringify(tail, null, 2));
155
- if (tail) {
156
- let name = evalXObjEName(tail[2]);
157
- let type = tail[1] === '@' ? 'attribute' : 'child';
158
- let value = undefined;
159
- if (tail[3] === '=') value = tail[5] ? tail[6] : tail[4];
160
- if (tail[7]) isERR = true;
161
- conditions = {
162
- name,
163
- type,
164
- value,
165
- };
166
- };
167
- };
168
- } else if (tail[3]) {
169
- name = null;
170
- };
171
- };
172
- };
173
- };
174
- } else {
175
- name = value;
176
- };
177
- name = evalXObjEName(name);
178
- if (name === null) isERR = true;
179
- result = {
180
- name,
181
- conditions,
182
- isERR,
183
- };
184
- return result;
185
- };
186
-
187
- /**
188
- * @function getXObjElement
189
- * @param {object} obj
190
- * @param {string} name
191
- * @returns {?any}
192
- * @throws {TypeError} if first param is not an object
193
- * @throws {TypeError} if second param is empty string or not a string at all
194
- * @description Extracts an element from a given object by its key.
195
- */
196
- function getXObjElement(obj, name) {
197
- if (!isPlainObject(obj)) {
198
- const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
199
- err.code = XOBJ_TE_NPOBJ_ECODE;
200
- throw err;
201
- };
202
- let { isSucceed, value: key } = evalKeyName(name);
203
- if (!isSucceed) {
204
- const { code, msg } = key;
205
- const err = new TypeError(msg);
206
- err.code = code;
207
- throw err;
208
- };
209
- // TODO: [?] check type of obj[key_name]
210
- return obj[key] !== undefined ? obj[key] : null;
211
- };
212
-
213
- /**
214
- * @function getXObjAttributes
215
- * @param {object} obj
216
- * @param {string} [key=XOBJ_DEF_ATTR_TNAME]
217
- * @returns {?object}
218
- * @throws {TypeError} if first param is not an object
219
- * @description Extracts an attributes from a given object by its key.
220
- */
221
- function getXObjAttributes(obj, key = XOBJ_DEF_ATTR_TNAME) {
222
- let result = null;
223
- try {
224
- result = getXObjElement(obj, key);
225
- } catch (err) {
226
- switch (err.code) {
227
- case XOBJ_TE_NSTR_ECODE :
228
- case XOBJ_TE_KNES_ECODE : {
229
- break;
230
- }
231
- default: {
232
- throw err;
233
- }
234
- };
235
- };
236
- return isPlainObject(result) ? result : null;
237
- };
238
-
239
- /**
240
- * @typedef RVAL_emodif
241
- * @type {object}
242
- * @property {boolean} isSucceed - ops flag
243
- * @property {?object} item
244
- * @description A result of an xObj modification ops
245
- */
246
-
247
- /**
248
- * @function addXObjElement
249
- * @param {object} obj
250
- * @param {string} name
251
- * @returns {RVAL_emodif}
252
- * @throws {TypeError} if first param is not an object
253
- * @throws {TypeError} if second param is empty string or not a string at all
254
- * @description Adds an element addressed by its key to a given object.
255
- */
256
- function addXObjElement(obj, name) {
257
- if (!isPlainObject(obj)) {
258
- const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
259
- err.code = XOBJ_TE_NPOBJ_ECODE;
260
- throw err;
261
- };
262
- let { isSucceed, value: key } = evalKeyName(name);
263
- if (!isSucceed) {
264
- const { code, msg } = key;
265
- const err = new TypeError(msg);
266
- err.code = code;
267
- throw err;
268
- };
269
- const item = {};
270
- let prop = obj[key];
271
- isSucceed = false;
272
- // // TODO: [?] consider wheter or not do ops if new_key exists
273
- if (isNullOrUndef(prop)) {
274
- obj[key] = prop = item;
275
- isSucceed = true;
276
- } else if (isObject(prop)) {
277
- if (isArray(prop)) {
278
- prop.push(item);
279
- } else {
280
- obj[key] = [ prop, item ];
281
- };
282
- prop = item;
283
- isSucceed = true;
284
- };
285
- return {
286
- isSucceed,
287
- item: isSucceed ? prop : null,
288
- };
289
- };
290
-
291
- /**
292
- * typedef OPT_inselops_L
293
- * type {object}
294
- * @property {boolean} [force=false]
295
- * @property {boolean} [ripOldies=false]
296
- * @property {boolean} [acceptIfList=false]
297
- */
298
-
299
- /**
300
- * @function insertXObjElement
301
- * @param {object} obj
302
- * @param {string} name
303
- * @param {OPT_inselops_L} [opt]
304
- * @returns {?object}
305
- * @throws {TypeError} if first param is not an object
306
- * @description Inserts an element addressed by its key into a given object.
307
- */
308
- function insertXObjElement(...args) {
309
- let item = null;
310
- try {
311
- ({ item } = insertXObjElementEx(...args));
312
- } catch (err) {
313
- switch (err.code) {
314
- case XOBJ_TE_NSTR_ECODE :
315
- case XOBJ_TE_KNES_ECODE : {
316
- break;
317
- }
318
- default: {
319
- throw err;
320
- }
321
- };
322
- };
323
- return item;
324
- };
325
-
326
- /**
327
- * @function insertXObjElementEx
328
- * @param {object} obj
329
- * @param {string} name
330
- * @param {OPT_inselops_L} [opt]
331
- * @returns {RVAL_emodif}
332
- * @throws {TypeError} if first param is not an object
333
- * @throws {TypeError} if second param is empty string or not a string at all
334
- * @since 0.2.0
335
- * @description Inserts an element addressed by its key into a given object.
336
- */
337
- function insertXObjElementEx(obj, name, opt) {
338
- if (!isPlainObject(obj)) {
339
- const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
340
- err.code = XOBJ_TE_NPOBJ_ECODE;
341
- throw err;
342
- };
343
- let { isSucceed, value: key } = evalKeyName(name);
344
- if (!isSucceed) {
345
- const { code, msg } = key;
346
- const err = new TypeError(msg);
347
- err.code = code;
348
- throw err;
349
- };
350
- const item = {};
351
- let prop = obj[key];
352
- isSucceed = false;
353
- if (isNullOrUndef(prop)) {
354
- obj[key] = prop = item;
355
- isSucceed = true;
356
- } else {
357
- const _opt = isPlainObject(opt) ? opt : {};
358
- let { force, ripOldies, acceptIfList } = _opt;
359
- if (typeof force !== 'boolean') force = false;
360
- if (typeof ripOldies !== 'boolean') ripOldies = false;
361
- if (typeof acceptIfList !== 'boolean') acceptIfList = false;
362
- if (force && (ripOldies || !isObject(prop))) {
363
- obj[key] = prop = item;
364
- isSucceed = true;
365
- } else {
366
- isSucceed = isPlainObject(prop) || (isArray(prop) && acceptIfList);
367
- };
368
- };
369
- return {
370
- isSucceed,
371
- item: isSucceed ? prop : null,
372
- };
373
- };
374
-
375
- /**
376
- * @function deleteXObjElement
377
- * @param {object} obj
378
- * @param {string} name
379
- * @returns {boolean}
380
- * @throws {TypeError} if first param is not an object
381
- * @description Deletes an element addressed by its key from a given object.
382
- */
383
- function deleteXObjElement(...args) {
384
- let isSucceed = false;
385
- try {
386
- ({ isSucceed } = deleteXObjElementEx(...args));
387
- } catch (err) {
388
- switch (err.code) {
389
- case XOBJ_TE_NSTR_ECODE :
390
- case XOBJ_TE_KNES_ECODE : {
391
- break;
392
- }
393
- default: {
394
- throw err;
395
- }
396
- };
397
- };
398
- return isSucceed;
399
- };
400
-
401
- /**
402
- * @function deleteXObjElementEx
403
- * @param {object} obj
404
- * @param {string} name
405
- * @returns {RVAL_emodif}
406
- * @throws {TypeError} if first param is not an object
407
- * @throws {TypeError} if second param is empty string or not a string at all
408
- * @description Deletes an element addressed by its key from a given object.
409
- */
410
- function deleteXObjElementEx(obj, name) {
411
- if (!isPlainObject(obj)) {
412
- const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
413
- err.code = XOBJ_TE_NPOBJ_ECODE;
414
- throw err;
415
- };
416
- let { isSucceed, value: key } = evalKeyName(name);
417
- if (!isSucceed) {
418
- const { code, msg } = key;
419
- const err = new TypeError(msg);
420
- err.code = code;
421
- throw err;
422
- };
423
- let prop = obj[key];
424
- isSucceed = false;
425
- // // TODO: catch errors in strict mode
426
- isSucceed = delete obj[key];
427
- return {
428
- isSucceed,
429
- item: isSucceed && isObject(prop) ? prop : null,
430
- };
431
- };
432
-
433
- /**
434
- * @function renameXObjElement
435
- * @param {object} obj
436
- * @param {string} name - old key
437
- * @param {string} newName - new key
438
- * @returns {boolean}
439
- * @throws {TypeError} if first param is not an object
440
- * @throws {TypeError} if second param is not a string
441
- * @throws {TypeError} if third param is not a string
442
- * @description Renames an element addressed by its key.
443
- */
444
- function renameXObjElement(obj, name = '', newName = '') {
445
- if (!isPlainObject(obj)) {
446
- const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
447
- err.code = XOBJ_TE_NPOBJ_ECODE;
448
- throw err;
449
- };
450
- const opt = false;
451
- let { isSucceed: isAcceptON, value: oname } = evalKeyName(name, opt);
452
- if (!isAcceptON) {
453
- const { code, msg } = oname;
454
- const err = new TypeError(msg);
455
- err.code = code;
456
- throw err;
457
- };
458
- let { isSucceed: isAcceptNN, value: nname } = evalKeyName(newName, opt);
459
- if (!isAcceptNN) {
460
- const { code, msg } = nname;
461
- const err = new TypeError(msg);
462
- err.code = code;
463
- throw err;
464
- };
465
- let isSucceed = false;
466
- if (oname !== '' && oname in obj && nname !== '') {
467
- isSucceed = true;
468
- if (oname !== nname) {
469
- const prop = obj[oname];
470
- obj[newName] = prop;
471
- isSucceed = delete obj[oname];
472
- if (!isSucceed) {
473
- // undo change if failed delete old element
474
- delete obj[nname];
475
- };
476
- };
477
- };
478
- return isSucceed;
479
- };
480
-
481
- /**
482
- * @function checkXObjAttribute
483
- * @param {object} obj
484
- * @param {string} attr
485
- * @param {string} [key]
486
- * @returns {boolean}
487
- * @throws {TypeError} if first param is not an object
488
- * @description Checks wheter an attribute is exists.
489
- */
490
- function checkXObjAttribute(obj, attr = '', key) {
491
- let _obj = null;
492
- try {
493
- _obj = getXObjAttributes(obj, key);
494
- } catch (err) {
495
- throw err;
496
- };
497
- if (_obj === null) return false;
498
- let { isSucceed, value: name } = evalKeyName(attr, false);
499
- if (isSucceed) {
500
- if (name === '') return false;
501
- } else {
502
- const { code, msg } = name;
503
- const err = new TypeError(msg);
504
- err.code = code;
505
- throw err;
506
- };
507
- return _obj[name] !== undefined;
508
- };
509
-
510
- /**
511
- * @function deleteXObjAttribute
512
- * @param {object} obj
513
- * @param {string} attr
514
- * @param {string} [key]
515
- * @returns {boolean}
516
- * @throws {TypeError} if first param is not an object
517
- * @description Deletes an attribute addressed by a given name.
518
- */
519
- function deleteXObjAttribute(obj, attr = '', key) {
520
- let _obj = null;
521
- try {
522
- _obj = getXObjAttributes(obj, key);
523
- } catch (err) {
524
- throw err;
525
- };
526
- if (_obj === null) return false;
527
- let { isSucceed, value: name } = evalKeyName(attr, false);
528
- if (!isSucceed) {
529
- const { code, msg } = name;
530
- const err = new TypeError(msg);
531
- err.code = code;
532
- throw err;
533
- };
534
- isSucceed = false;
535
- if (name !== '') {
536
- // // TODO: catch errors in strict mode
537
- isSucceed = delete _obj[name];
538
- };
539
- return isSucceed;
540
- };
541
-
542
- /**
543
- * @function renameXObjAttribute
544
- * @param {object} obj
545
- * @param {string} attr
546
- * @param {string} newName
547
- * @param {string} [key]
548
- * @returns {boolean}
549
- * @throws {TypeError} if first param is not an object
550
- * @throws {TypeError} if second param is not an object
551
- * @throws {TypeError} if third param is not an object
552
- * @since 0.2.0
553
- * @description Renames an attribute addressed by a given name.
554
- */
555
- function renameXObjAttribute(obj, attr = '', newName = '', key = XOBJ_DEF_ATTR_TNAME) {
556
- if (!isPlainObject(obj)) {
557
- const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
558
- err.code = XOBJ_TE_NPOBJ_ECODE;
559
- throw err;
560
- };
561
- const opt = false;
562
- let { isSucceed, value: _key } = evalKeyName(key, opt);
563
- if (!isSucceed) {
564
- const { code, msg } = _key;
565
- const err = new TypeError(msg);
566
- err.code = code;
567
- throw err;
568
- };
569
- isSucceed = false;
570
- if (_key !== '') {
571
- let _obj = obj[_key];
572
- if (isPlainObject(_obj)) {
573
- let { isSucceed: isAcceptON, value: oname } = evalKeyName(attr, opt);
574
- if (!isAcceptON) {
575
- const { code, msg } = oname;
576
- const err = new TypeError(msg);
577
- err.code = code;
578
- throw err;
579
- };
580
- let { isSucceed: isAcceptNN, value: nname } = evalKeyName(newName, opt);
581
- if (!isAcceptNN) {
582
- const { code, msg } = nname;
583
- const err = new TypeError(msg);
584
- err.code = code;
585
- throw err;
586
- };
587
- if (oname !== '' && oname in _obj && nname !== '') {
588
- if (oname !== nname) {
589
- _obj = Object.entries(_obj);
590
- const index = _obj.findIndex((item) => item[0] === oname);
591
- _obj[index][0] = nname;
592
- obj[_key] = Object.fromEntries(_obj);
593
- };
594
- isSucceed = true;
595
- };
596
- };
597
- };
598
- return isSucceed;
599
- };
600
-
601
- /**
602
- * @function readXObjParamRaw
603
- * @param {object} obj
604
- * @param {string} [key=XOBJ_DEF_PARAM_TNAME]
605
- * @returns {any}
606
- * @throws {TypeError} if first param is not an object
607
- * @throws {TypeError} if third param is not a string
608
- * @description Extracts a parameter 'AS IS' from a given object.
609
- */
610
- function readXObjParamRaw(obj, key = XOBJ_DEF_PARAM_TNAME) {
611
- if (!isPlainObject(obj)) {
612
- const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
613
- err.code = XOBJ_TE_NPOBJ_ECODE;
614
- throw err;
615
- };
616
- let { isSucceed, value: _key } = evalKeyName(key, false);
617
- if (!isSucceed) {
618
- const { code, msg } = _key;
619
- const err = new TypeError(msg);
620
- err.code = code;
621
- throw err;
622
- };
623
- return _key !== '' ? obj[_key] : undefined;
624
- };
625
-
626
- /**
627
- * @function writeXObjParamRaw
628
- * @param {object} obj
629
- * @param {any} value
630
- * @param {string} [key=XOBJ_DEF_PARAM_TNAME]
631
- * @returns {boolean}
632
- * @throws {TypeError} if first param is not an object
633
- * @throws {TypeError} if third param is not a string
634
- * @description Writes a parameter 'AS IS' into a given object.
635
- */
636
- function writeXObjParamRaw(obj, value, key = XOBJ_DEF_PARAM_TNAME) {
637
- if (!isPlainObject(obj)) {
638
- const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
639
- err.code = XOBJ_TE_NPOBJ_ECODE;
640
- throw err;
641
- };
642
- let { isSucceed, value: _key } = evalKeyName(key, false);
643
- if (!isSucceed) {
644
- const { code, msg } = _key;
645
- const err = new TypeError(msg);
646
- err.code = code;
647
- throw err;
648
- };
649
- if (_key === '' || value === undefined) {
650
- isSucceed = false;
651
- } else {
652
- obj[_key] = value;
653
- };
654
- return isSucceed;
655
- };
656
-
657
- /**
658
- * @function readXObjAttrRaw
659
- * @param {object} obj
660
- * @param {string} attr
661
- * @param {string} [key]
662
- * @returns {any}
663
- * @throws {TypeError} if first param is not an object
664
- * @throws {TypeError} if third param is not a string
665
- * @description Extracts an attribute 'AS IS' from a given object.
666
- */
667
- function readXObjAttrRaw(obj, attr = '', key) {
668
- let _obj = null;
669
- try {
670
- _obj = getXObjAttributes(obj, key);
671
- } catch (err) {
672
- throw err;
673
- };
674
- if (_obj !== null) {
675
- let { isSucceed, value: name } = evalKeyName(attr, false);
676
- if (!isSucceed) {
677
- const { code, msg } = name;
678
- const err = new TypeError(msg);
679
- err.code = code;
680
- throw err;
681
- };
682
- if (name !== '') return _obj[name];
683
- };
684
- };
685
-
686
- /**
687
- * @function writeXObjAttrRaw
688
- * @param {object} obj
689
- * @param {string} attr
690
- * @param {any} value
691
- * @param {string} [key]
692
- * @returns {boolean}
693
- * @throws {TypeError} if first param is not an object
694
- * @throws {TypeError} if third param is not a string
695
- * @description Writes a parameter into a given object.
696
- */
697
- function writeXObjAttrRaw(obj, attr = '', value, key = XOBJ_DEF_ATTR_TNAME) {
698
- let { isSucceed, value: name } = evalKeyName(attr, false);
699
- if (!isSucceed) {
700
- const { code, msg } = name;
701
- const err = new TypeError(msg);
702
- err.code = code;
703
- throw err;
704
- };
705
- isSucceed = false;
706
- if (name !== '' && value !== undefined) {
707
- let _obj = null;
708
- try {
709
- const opt = { force: true, acceptIfList: true };
710
- _obj = insertXObjElement(obj, key, opt);
711
- } catch (err) {
712
- throw err;
713
- };
714
- if (isArray(_obj)) {
715
- // force a replacement of the old element if it's array
716
- try {
717
- const opt = { force: true, ripOldies: true };
718
- _obj = insertXObjElement(obj, key, opt);
719
- } catch (err) {
720
- throw err;
721
- };
722
- };
723
- if (_obj !== null) {
724
- _obj[name] = value;
725
- isSucceed = true;
726
- };
727
- };
728
- return isSucceed;
729
- };
730
-
731
- /**
732
- * @function readXObjParam
733
- * @param {object} obj
734
- * @param {string} [key]
735
- * @returns {string}
736
- * @throws {TypeError} if first param is not an object
737
- * @description Extracts a parameter from a given object
738
- * and returns it as string.
739
- */
740
- function readXObjParam(obj, key) {
741
- const opt = {
742
- useTrim: false,
743
- numberToString: true,
744
- boolToString: true,
745
- defValue: '',
746
- };
747
- let result = undefined;
748
- try {
749
- result = readXObjParamEx(obj, opt, key);
750
- } catch (err) {
751
- throw err;
752
- };
753
- return result;
754
- };
755
-
756
- /**
757
- * @function readXObjParamAsBool
758
- * @param {object} obj
759
- * @param {boolean} [defValue]
760
- * @param {string} [key]
761
- * @returns {boolean}
762
- * @throws {TypeError} if first param is not an object
763
- * @description Extracts a parameter from a given object
764
- * and returns it as boolean.
765
- */
766
- function readXObjParamAsBool(obj, defValue, key) {
767
- let result = undefined;
768
- try {
769
- result = readXObjParamRaw(obj, key);
770
- } catch (err) {
771
- switch (err.code) {
772
- case XOBJ_TE_NSTR_ECODE : {
773
- break;
774
- }
775
- default: {
776
- throw err;
777
- }
778
- };
779
- };
780
- return readAsBoolEx(result, defValue);
781
- };
782
-
783
- /**
784
- * @function readXObjParamAsNum
785
- * @param {object} obj
786
- * @param {number} [defValue]
787
- * @param {string} [key]
788
- * @returns {number}
789
- * @throws {TypeError} if first param is not an object
790
- * @description Extracts a parameter from a given object
791
- * and returns it as number.
792
- */
793
- function readXObjParamAsNum(obj, defValue, key) {
794
- let result = undefined;
795
- try {
796
- result = readXObjParamRaw(obj, key);
797
- } catch (err) {
798
- switch (err.code) {
799
- case XOBJ_TE_NSTR_ECODE : {
800
- break;
801
- }
802
- default: {
803
- throw err;
804
- }
805
- };
806
- };
807
- return readAsNumberEx(result, defValue);
808
- };
809
-
810
- /**
811
- * @function readXObjParamEx
812
- * @param {object} obj
813
- * @param {any} [opt]
814
- * @param {string} [key]
815
- * @returns {string}
816
- * @throws {TypeError} if first param is not an object
817
- * @description Extracts a parameter from a given object
818
- * and returns it as string.
819
- */
820
- function readXObjParamEx(obj, opt, key) {
821
- let result = undefined;
822
- try {
823
- result = readXObjParamRaw(obj, key);
824
- } catch (err) {
825
- switch (err.code) {
826
- case XOBJ_TE_NSTR_ECODE : {
827
- break;
828
- }
829
- default: {
830
- throw err;
831
- }
832
- };
833
- };
834
- let _opt = opt;
835
- if (!isPlainObject(_opt)) {
836
- _opt = {
837
- useTrim: false,
838
- numberToString: true,
839
- boolToString: true,
840
- defValue: _opt,
841
- };
842
- };
843
- return readAsString(result, _opt);
844
- };
845
-
846
- /**
847
- * @function readXObjParamAsIndex
848
- * @param {object} obj
849
- * @param {string} [key]
850
- * @returns {number}
851
- * @throws {TypeError} if first param is not an object
852
- * @description Extracts a parameter from a given object
853
- * and returns it as 'index' value.
854
- */
855
- function readXObjParamAsIndex(obj, key) {
856
- let result = undefined;
857
- try {
858
- result = readXObjParamRaw(obj, key);
859
- } catch (err) {
860
- switch (err.code) {
861
- case XOBJ_TE_NSTR_ECODE : {
862
- break;
863
- }
864
- default: {
865
- throw err;
866
- }
867
- };
868
- };
869
- return valueToIndex(result);
870
- };
871
-
872
- /**
873
- * @function writeXObjParam
874
- * @param {object} obj
875
- * @param {any} value
876
- * @param {string} [key]
877
- * @returns {boolean}
878
- * @throws {TypeError} if first param is not an object
879
- * @description Tries to convert a given value to a string
880
- * and writes it as a parameter into a given object.
881
- */
882
- function writeXObjParam(obj, value, key) {
883
- let isSucceed = false;
884
- try {
885
- const opt = {
886
- useTrim: false,
887
- numberToString: true,
888
- boolToString: true,
889
- defValue: '',
890
- };
891
- isSucceed = writeXObjParamEx(obj, value, opt, key);
892
- } catch (err) {
893
- throw err;
894
- };
895
- return isSucceed;
896
- };
897
-
898
- /**
899
- * @function writeXObjParamAsBool
900
- * @param {object} obj
901
- * @param {any} value
902
- * @param {boolean} [defValue]
903
- * @param {string} [key]
904
- * @returns {boolean}
905
- * @throws {TypeError} if first param is not an object
906
- * @description Tries to convert a given value to a boolean
907
- * and writes it as a parameter into a given object.
908
- */
909
- function writeXObjParamAsBool(obj, value, defValue, key) {
910
- let isSucceed = false;
911
- if (value !== undefined || typeof defValue === 'boolean') {
912
- const _value = readAsBoolEx(value, defValue).toString();
913
- try {
914
- isSucceed = writeXObjParamRaw(obj, _value, key);
915
- } catch (err) {
916
- switch (err.code) {
917
- case XOBJ_TE_NSTR_ECODE : {
918
- break;
919
- }
920
- default: {
921
- throw err;
922
- }
923
- };
924
- };
925
- };
926
- return isSucceed;
927
- };
928
-
929
- /**
930
- * @function writeXObjParamAsNum
931
- * @param {object} obj
932
- * @param {any} value
933
- * @param {number} [defValue]
934
- * @param {string} [key]
935
- * @returns {boolean}
936
- * @throws {TypeError} if first param is not an object
937
- * @description Tries to convert a given value to a number
938
- * and writes it as a parameter into a given object.
939
- */
940
- function writeXObjParamAsNum(obj, value, defValue, key) {
941
- let isSucceed = false;
942
- if (value !== undefined || typeof defValue === 'number') {
943
- const _value = readAsNumberEx(value, defValue).toString();
944
- try {
945
- isSucceed = writeXObjParamRaw(obj, _value, key);
946
- } catch (err) {
947
- switch (err.code) {
948
- case XOBJ_TE_NSTR_ECODE : {
949
- break;
950
- }
951
- default: {
952
- throw err;
953
- }
954
- };
955
- };
956
- };
957
- return isSucceed;
958
- };
959
-
960
- /**
961
- * @function writeXObjParamAsIndex
962
- * @param {object} obj
963
- * @param {any} value
964
- * @param {string} [key]
965
- * @returns {boolean}
966
- * @throws {TypeError} if first param is not an object
967
- * @description Tries to convert a given value into an 'index' value
968
- * and writes it as a parameter into a given object.
969
- */
970
- function writeXObjParamAsIndex(obj, value, key) {
971
- let isSucceed = false;
972
- if (value !== undefined) {
973
- const _value = valueToIndex(value).toString();
974
- try {
975
- isSucceed = writeXObjParamRaw(obj, _value, key);
976
- } catch (err) {
977
- switch (err.code) {
978
- case XOBJ_TE_NSTR_ECODE : {
979
- break;
980
- }
981
- default: {
982
- throw err;
983
- }
984
- };
985
- };
986
- };
987
- return isSucceed;
988
- };
989
-
990
- /**
991
- * @function writeXObjParamEx
992
- * @param {object} obj
993
- * @param {any} value
994
- * @param {any} [opt]
995
- * @param {string} [key]
996
- * @returns {boolean}
997
- * @throws {TypeError} if first param is not an object
998
- * @description Tries to convert a given value to a string
999
- * and writes it as a parameter into a given object.
1000
- */
1001
- function writeXObjParamEx(obj, value, opt, key) {
1002
- let isSucceed = false;
1003
- if (value !== undefined) {
1004
- let _opt = opt;
1005
- if (!isPlainObject(_opt)) {
1006
- const defValue = readAsString(_opt, {
1007
- useTrim: false,
1008
- numberToString: true,
1009
- boolToString: true,
1010
- });
1011
- _opt = {
1012
- useTrim: false,
1013
- numberToString: true,
1014
- boolToString: true,
1015
- defValue,
1016
- };
1017
- };
1018
- const _value = readAsString(value, _opt);
1019
- try {
1020
- isSucceed = writeXObjParamRaw(obj, _value, key);
1021
- } catch (err) {
1022
- switch (err.code) {
1023
- case XOBJ_TE_NSTR_ECODE : {
1024
- break;
1025
- }
1026
- default: {
1027
- throw err;
1028
- }
1029
- };
1030
- };
1031
- };
1032
- return isSucceed;
1033
- };
1034
-
1035
- /**
1036
- * @function readXObjAttr
1037
- * @param {object} obj
1038
- * @param {string} attr
1039
- * @param {string} [key]
1040
- * @returns {string}
1041
- * @throws {TypeError} if first param is not an object
1042
- * @description Extracts an attribute from a given object
1043
- * and returns it as string.
1044
- */
1045
- function readXObjAttr(obj, attr, key) {
1046
- const opt = {
1047
- useTrim: true,
1048
- numberToString: true,
1049
- boolToString: true,
1050
- defValue: '',
1051
- };
1052
- let result = undefined;
1053
- try {
1054
- result = readXObjAttrEx(obj, attr, opt, key);
1055
- } catch (err) {
1056
- throw err;
1057
- };
1058
- return result;
1059
- };
1060
-
1061
- /**
1062
- * @function readXObjAttrAsBool
1063
- * @param {object} obj
1064
- * @param {string} attr
1065
- * @param {boolean} [defValue]
1066
- * @param {string} [key]
1067
- * @returns {boolean}
1068
- * @throws {TypeError} if first param is not an object
1069
- * @description Extracts an attribute from a given object
1070
- * and returns it as boolean.
1071
- */
1072
- function readXObjAttrAsBool(obj, attr, defValue, key) {
1073
- let result = undefined;
1074
- try {
1075
- result = readXObjAttrRaw(obj, attr, key);
1076
- } catch (err) {
1077
- switch (err.code) {
1078
- case XOBJ_TE_NSTR_ECODE : {
1079
- break;
1080
- }
1081
- default: {
1082
- throw err;
1083
- }
1084
- };
1085
- };
1086
- return readAsBoolEx(result, defValue);
1087
- };
1088
-
1089
- /**
1090
- * @function readXObjAttrAsNum
1091
- * @param {object} obj
1092
- * @param {string} attr
1093
- * @param {number} [defValue]
1094
- * @param {string} [key]
1095
- * @returns {number}
1096
- * @throws {TypeError} if first param is not an object
1097
- * @description Extracts an attribute from a given object
1098
- * and returns it as number.
1099
- */
1100
- function readXObjAttrAsNum(obj, attr, defValue, key) {
1101
- let result = undefined;
1102
- try {
1103
- result = readXObjAttrRaw(obj, attr, key);
1104
- } catch (err) {
1105
- switch (err.code) {
1106
- case XOBJ_TE_NSTR_ECODE : {
1107
- break;
1108
- }
1109
- default: {
1110
- throw err;
1111
- }
1112
- };
1113
- };
1114
- return readAsNumberEx(result, defValue);
1115
- };
1116
-
1117
- /**
1118
- * @function readXObjAttrEx
1119
- * @param {object} obj
1120
- * @param {string} attr
1121
- * @param {any} [opt]
1122
- * @param {string} [key]
1123
- * @returns {string}
1124
- * @throws {TypeError} if first param is not an object
1125
- * @description Extracts an attribute from a given object
1126
- * and returns it as string.
1127
- */
1128
- function readXObjAttrEx(obj, attr, opt, key) {
1129
- let result = undefined;
1130
- try {
1131
- result = readXObjAttrRaw(obj, attr, key);
1132
- } catch (err) {
1133
- switch (err.code) {
1134
- case XOBJ_TE_NSTR_ECODE : {
1135
- break;
1136
- }
1137
- default: {
1138
- throw err;
1139
- }
1140
- };
1141
- };
1142
- let _opt = opt;
1143
- if (!isPlainObject(_opt)) {
1144
- _opt = {
1145
- useTrim: true,
1146
- numberToString: true,
1147
- boolToString: true,
1148
- defValue: _opt,
1149
- };
1150
- };
1151
- return readAsString(result, _opt);
1152
- };
1153
-
1154
- /**
1155
- * @function readXObjAttrAsIndex
1156
- * @param {object} obj
1157
- * @param {string} attr
1158
- * @param {string} [key]
1159
- * @returns {number}
1160
- * @throws {TypeError} if first param is not an object
1161
- * @description Extracts an attribute from a given object
1162
- * and returns it as 'index' value.
1163
- */
1164
- function readXObjAttrAsIndex(obj, attr, key) {
1165
- let result = undefined;
1166
- try {
1167
- result = readXObjAttrRaw(obj, attr, key);
1168
- } catch (err) {
1169
- switch (err.code) {
1170
- case XOBJ_TE_NSTR_ECODE : {
1171
- break;
1172
- }
1173
- default: {
1174
- throw err;
1175
- }
1176
- };
1177
- };
1178
- return valueToIndex(result);
1179
- };
1180
-
1181
- /**
1182
- * @function writeXObjAttr
1183
- * @param {object} obj
1184
- * @param {string} attr
1185
- * @param {any} value
1186
- * @param {string} [key]
1187
- * @returns {boolean}
1188
- * @throws {TypeError} if first param is not an object
1189
- * @description Tries to convert a given value to a string
1190
- * and writes it as an attribute into a given object.
1191
- */
1192
- function writeXObjAttr(obj, attr, value, key) {
1193
- let isSucceed = false;
1194
- try {
1195
- const opt = {
1196
- useTrim: true,
1197
- numberToString: true,
1198
- boolToString: true,
1199
- defValue: '',
1200
- };
1201
- isSucceed = writeXObjAttrEx(obj, attr, value, opt, key);
1202
- } catch (err) {
1203
- throw err;
1204
- };
1205
- return isSucceed;
1206
- };
1207
-
1208
- /**
1209
- * @function writeXObjAttrAsBool
1210
- * @param {object} obj
1211
- * @param {string} attr
1212
- * @param {any} value
1213
- * @param {boolean} [defValue]
1214
- * @param {string} [key]
1215
- * @returns {boolean}
1216
- * @throws {TypeError} if first param is not an object
1217
- * @description Tries to convert a given value to a boolean
1218
- * and writes it as an attribute into a given object.
1219
- */
1220
- function writeXObjAttrAsBool(obj, attr, value, defValue, key) {
1221
- let isSucceed = false;
1222
- if (value !== undefined || typeof defValue === 'boolean') {
1223
- const _value = readAsBoolEx(value, defValue).toString();
1224
- try {
1225
- isSucceed = writeXObjAttrRaw(obj, attr, _value, key);
1226
- } catch (err) {
1227
- switch (err.code) {
1228
- case XOBJ_TE_NSTR_ECODE : {
1229
- break;
1230
- }
1231
- default: {
1232
- throw err;
1233
- }
1234
- };
1235
- };
1236
- };
1237
- return isSucceed;
1238
- };
1239
-
1240
- /**
1241
- * @function writeXObjAttrAsNum
1242
- * @param {object} obj
1243
- * @param {string} attr
1244
- * @param {any} value
1245
- * @param {number} [defValue]
1246
- * @param {string} [key]
1247
- * @returns {boolean}
1248
- * @throws {TypeError} if first param is not an object
1249
- * @description Tries to convert a given value to a number
1250
- * and writes it as an attribute into a given object.
1251
- */
1252
- function writeXObjAttrAsNum(obj, attr, value, defValue, key) {
1253
- let isSucceed = false;
1254
- if (value !== undefined || typeof defValue === 'number') {
1255
- const _value = readAsNumberEx(value, defValue).toString();
1256
- try {
1257
- isSucceed = writeXObjAttrRaw(obj, attr, _value, key);
1258
- } catch (err) {
1259
- switch (err.code) {
1260
- case XOBJ_TE_NSTR_ECODE : {
1261
- break;
1262
- }
1263
- default: {
1264
- throw err;
1265
- }
1266
- };
1267
- };
1268
- };
1269
- return isSucceed;
1270
- };
1271
-
1272
- /**
1273
- * @function writeXObjAttrAsIndex
1274
- * @param {object} obj
1275
- * @param {string} attr
1276
- * @param {any} value
1277
- * @param {string} [key]
1278
- * @returns {boolean}
1279
- * @throws {TypeError} if first param is not an object
1280
- * @description Tries to convert a given value into an 'index' value
1281
- * and writes it as an attribute into a given object.
1282
- */
1283
- function writeXObjAttrAsIndex(obj, attr, value, key) {
1284
- let isSucceed = false;
1285
- if (value !== undefined) {
1286
- const _value = valueToIndex(value).toString();
1287
- try {
1288
- isSucceed = writeXObjAttrRaw(obj, attr, _value, key);
1289
- } catch (err) {
1290
- switch (err.code) {
1291
- case XOBJ_TE_NSTR_ECODE : {
1292
- break;
1293
- }
1294
- default: {
1295
- throw err;
1296
- }
1297
- };
1298
- };
1299
- };
1300
- return isSucceed;
1301
- };
1302
-
1303
- /**
1304
- * @function writeXObjAttrEx
1305
- * @param {object} obj
1306
- * @param {string} attr
1307
- * @param {any} value
1308
- * @param {any} [opt]
1309
- * @param {string} [key]
1310
- * @returns {boolean}
1311
- * @throws {TypeError} if first param is not an object
1312
- * @description Tries to convert a given value to a string
1313
- * and writes it as an attribute into a given object.
1314
- */
1315
- function writeXObjAttrEx(obj, attr, value, opt, key) {
1316
- let isSucceed = false;
1317
- if (value !== undefined) {
1318
- let _opt = opt;
1319
- if (!isPlainObject(_opt)) {
1320
- const defValue = readAsString(_opt, {
1321
- useTrim: true,
1322
- numberToString: true,
1323
- boolToString: true,
1324
- });
1325
- _opt = {
1326
- useTrim: true,
1327
- numberToString: true,
1328
- boolToString: true,
1329
- defValue,
1330
- };
1331
- };
1332
- const _value = readAsString(value, _opt);
1333
- try {
1334
- isSucceed = writeXObjAttrRaw(obj, attr, _value, key);
1335
- } catch (err) {
1336
- switch (err.code) {
1337
- case XOBJ_TE_NSTR_ECODE : {
1338
- break;
1339
- }
1340
- default: {
1341
- throw err;
1342
- }
1343
- };
1344
- };
1345
- };
1346
- return isSucceed;
1347
- };
1348
-
1349
- /**
1350
- * @function insertXObjElements
1351
- * @param {object} obj
1352
- * @param {...string} name
1353
- * @param {OPT_inselops_L} [opt]
1354
- * @returns {number}
1355
- * @throws {TypeError} if first param is not an object
1356
- * @description Inserts an elements into a given object.
1357
- */
1358
- function insertXObjElements(obj, ...args) {
1359
- if (!isPlainObject(obj)) {
1360
- const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
1361
- err.code = XOBJ_TE_NPOBJ_ECODE;
1362
- throw err;
1363
- };
1364
- let count = 0;
1365
- let len = args.length;
1366
- const opt = (
1367
- len > 0 && isPlainObject(args[len - 1])
1368
- ? (len--, args.pop())
1369
- : {}
1370
- );
1371
- for (let key of args) {
1372
- if (insertXObjElement(obj, key, opt) !== null) count++;
1373
- };
1374
- return count;
1375
- };
1376
-
1377
- /**
1378
- * typedef OPT_inselops_S
1379
- * type {object}
1380
- * @property {boolean} [force=false]
1381
- * @property {boolean} [ripOldies=false]
1382
- */
1383
-
1384
- /**
1385
- * @function insertXObjEList
1386
- * @param {object} obj
1387
- * @param {string} name
1388
- * @param {OPT_inselops_S} [opt]
1389
- * @returns {?any}
1390
- * @throws {TypeError} if first param is not an object
1391
- * @description Inserts a list elements into a given object.
1392
- */
1393
- function insertXObjEList(...args) {
1394
- let item = null;
1395
- try {
1396
- ({ item } = insertXObjEListEx(...args));
1397
- } catch (err) {
1398
- switch (err.code) {
1399
- case XOBJ_TE_NSTR_ECODE :
1400
- case XOBJ_TE_KNES_ECODE : {
1401
- break;
1402
- }
1403
- default: {
1404
- throw err;
1405
- }
1406
- };
1407
- };
1408
- return item;
1409
- };
1410
-
1411
- /**
1412
- * @function insertXObjEListEx
1413
- * @param {object} obj
1414
- * @param {string} name
1415
- * @param {OPT_inselops_S} [opt]
1416
- * @returns {RVAL_emodif}
1417
- * @throws {TypeError} if first param is not an object
1418
- * @throws {TypeError} if second param is empty string or not a string at all
1419
- * @since 0.2.0
1420
- * @description Inserts a list elements into a given object.
1421
- */
1422
- function insertXObjEListEx(obj, name, opt) {
1423
- if (!isPlainObject(obj)) {
1424
- const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
1425
- err.code = XOBJ_TE_NPOBJ_ECODE;
1426
- throw err;
1427
- };
1428
- let { isSucceed, value: key } = evalKeyName(name);
1429
- if (!isSucceed) {
1430
- const { code, msg } = key;
1431
- const err = new TypeError(msg);
1432
- err.code = code;
1433
- throw err;
1434
- };
1435
- const _options = isPlainObject(opt) ? opt : {};
1436
- let { force, ripOldies } = _options;
1437
- if (typeof force !== 'boolean') force = false;
1438
- if (typeof ripOldies !== 'boolean') ripOldies = false;
1439
- let prop = obj[key];
1440
- isSucceed = false;
1441
- if (
1442
- isNullOrUndef(prop)
1443
- || (force && (ripOldies || !isObject(prop)))
1444
- ) {
1445
- obj[key] = prop = [];
1446
- isSucceed = true;
1447
- } else {
1448
- if (isObject(prop)) {
1449
- if (!isArray(prop)) prop = [ prop ];
1450
- obj[key] = prop;
1451
- isSucceed = true;
1452
- };
1453
- };
1454
- return {
1455
- isSucceed,
1456
- item: isSucceed ? prop : null,
1457
- };
1458
- };
1459
-
1460
- /**
1461
- * @function insertXObjEChain
1462
- * @param {object} obj
1463
- * @param {...string} name
1464
- * @param {object} [opt]
1465
- * @returns {?any}
1466
- * @throws {TypeError} if first param is not an object
1467
- * @description Inserts a chain of an elements into a given object.
1468
- */
1469
- function insertXObjEChain(obj, ...args){
1470
- if (!isPlainObject(obj)) {
1471
- const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
1472
- err.code = XOBJ_TE_NPOBJ_ECODE;
1473
- throw err;
1474
- };
1475
- let result = null;
1476
- let len = args.length;
1477
- const opt = (
1478
- len > 0 && isPlainObject(args[len - 1])
1479
- ? (len--, args.pop())
1480
- : {}
1481
- );
1482
- if (len > 0) {
1483
- let parent = obj;
1484
- let child = null;
1485
- let isSucceed = false;
1486
- for (let key of args) {
1487
- child = insertXObjElement(parent, key, opt);
1488
- isSucceed = isPlainObject(child);
1489
- if (!isSucceed) break;
1490
- parent = child;
1491
- };
1492
- result = isSucceed ? parent : null;
1493
- };
1494
- return result;
1495
- };
1496
-
1497
- /***
1498
- * (* class definitions *)
1499
- */
1500
-
1501
- // === module exports block ===
1502
-
1503
- module.exports.XOBJ_DEF_PARAM_TNAME = XOBJ_DEF_PARAM_TNAME;
1504
- module.exports.XOBJ_DEF_ATTR_TNAME = XOBJ_DEF_ATTR_TNAME;
1505
-
1506
- module.exports.readXObjParamRaw = readXObjParamRaw;
1507
- module.exports.readXObjParam = readXObjParam;
1508
- module.exports.readXObjParamAsBool = readXObjParamAsBool;
1509
- module.exports.readXObjParamAsNum = readXObjParamAsNum;
1510
- module.exports.readXObjParamEx = readXObjParamEx;
1511
- module.exports.readXObjParamAsIndex = readXObjParamAsIndex;
1512
- module.exports.writeXObjParamRaw = writeXObjParamRaw;
1513
- module.exports.writeXObjParam = writeXObjParam;
1514
- module.exports.writeXObjParamAsBool = writeXObjParamAsBool;
1515
- module.exports.writeXObjParamAsNum = writeXObjParamAsNum;
1516
- module.exports.writeXObjParamAsIndex = writeXObjParamAsIndex;
1517
- module.exports.writeXObjParamEx = writeXObjParamEx;
1518
-
1519
- module.exports.readXObjAttrRaw = readXObjAttrRaw;
1520
- module.exports.readXObjAttr = readXObjAttr;
1521
- module.exports.readXObjAttrAsBool = readXObjAttrAsBool;
1522
- module.exports.readXObjAttrAsNum = readXObjAttrAsNum;
1523
- module.exports.readXObjAttrEx = readXObjAttrEx;
1524
- module.exports.readXObjAttrAsIndex = readXObjAttrAsIndex;
1525
- module.exports.writeXObjAttrRaw = writeXObjAttrRaw;
1526
- module.exports.writeXObjAttr = writeXObjAttr;
1527
- module.exports.writeXObjAttrAsBool = writeXObjAttrAsBool;
1528
- module.exports.writeXObjAttrAsNum = writeXObjAttrAsNum;
1529
- module.exports.writeXObjAttrAsIndex = writeXObjAttrAsIndex;
1530
- module.exports.writeXObjAttrEx = writeXObjAttrEx;
1531
-
1532
- module.exports.getXObjAttributes = getXObjAttributes;
1533
- module.exports.checkXObjAttribute = checkXObjAttribute;
1534
- module.exports.deleteXObjAttribute = deleteXObjAttribute;
1535
- module.exports.renameXObjAttribute = renameXObjAttribute;
1536
-
1537
- module.exports.getXObjElement = getXObjElement;
1538
- module.exports.addXObjElement = addXObjElement;
1539
- module.exports.insertXObjElement = insertXObjElement;
1540
- module.exports.insertXObjElementEx = insertXObjElementEx;
1541
- module.exports.deleteXObjElement = deleteXObjElement;
1542
- module.exports.deleteXObjElementEx = deleteXObjElementEx;
1543
- module.exports.renameXObjElement = renameXObjElement;
1544
-
1545
- module.exports.evalXObjEName = evalXObjEName;
1546
- module.exports.insertXObjEList = insertXObjEList;
1547
- module.exports.insertXObjEListEx = insertXObjEListEx;
1548
-
1549
- /* inner */
1550
- module.exports.evalKeyName = evalKeyName;
1551
-
1552
- /* experimental */
1553
- module.exports.genXObjENameDescr = genXObjENameDescr;
1554
- /* experimental */
1555
- module.exports.insertXObjElements = insertXObjElements;
1556
- /* experimental */
1557
- module.exports.insertXObjEChain = insertXObjEChain;
1558
-
1559
- /** @deprecated */
1560
- module.exports.readXObjParamAsStr = readXObjParamEx;
1561
- /** @deprecated */
1562
- module.exports.readXObjAttrAsStr = readXObjAttrEx;
1
+ // [v0.2.101-20250401]
2
+
3
+ // === module init block ===
4
+
5
+ const {
6
+ valueToIndex, valueToIDString,
7
+ readAsString, readAsBoolEx, readAsNumberEx,
8
+ isNullOrUndef,
9
+ isInteger,
10
+ isArray, isObject, isPlainObject,
11
+ readAsListS,
12
+ } = require('@ygracs/bsfoc-lib-js');
13
+
14
+ // === module extra block (helper functions) ===
15
+
16
+ /**
17
+ * @typedef {Object} RVAL_reason
18
+ * @property {string} code - message ID
19
+ * @property {string} msg - message text
20
+ * @description A result of a value check ops.
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} VCOR_evalkname
25
+ * @property {boolean} isSucceed - ops flag
26
+ * @property {(string|RVAL_reason)} value - result value or reson if failed
27
+ * @description A result of a value check ops.
28
+ */
29
+
30
+ /**
31
+ * @function evalKeyName
32
+ * @param {any} value - key to validate
33
+ * @param {boolean} [opt=true]
34
+ * @returns {VCOR_evalkname}
35
+ * @inner
36
+ * @description Tries to convert a value into an ID.
37
+ */
38
+ function evalKeyName(value, opt = true) {
39
+ if (typeof value !== 'string') {
40
+ return {
41
+ isSucceed: false,
42
+ value: {
43
+ code: XOBJ_TE_NSTR_ECODE,
44
+ msg: XOBJ_TE_NSTR_EMSG,
45
+ },
46
+ };
47
+ };
48
+ const key = value.trim();
49
+ if (opt && key === '') {
50
+ return {
51
+ isSucceed: false,
52
+ value: {
53
+ code: XOBJ_TE_KNES_ECODE,
54
+ msg: XOBJ_TE_KNES_EMSG,
55
+ },
56
+ };
57
+ };
58
+ return {
59
+ isSucceed: true,
60
+ value: key,
61
+ };
62
+ };
63
+
64
+ // === module main block ===
65
+
66
+ /***
67
+ * (* constant definitions *)
68
+ */
69
+
70
+ const XOBJ_DEF_PARAM_TNAME = '__text';
71
+ const XOBJ_DEF_ATTR_TNAME = '__attr';
72
+
73
+ const XOBJ_TE_INVARG_EMSG = 'invalid argument';
74
+ const XOBJ_TE_NOBJ_EMSG = `${XOBJ_TE_INVARG_EMSG} (an object expected)`;
75
+ const XOBJ_TE_NOBJ_ECODE = 'ERR_XOBJ_NOBJ';
76
+ const XOBJ_TE_NARR_EMSG = `${XOBJ_TE_INVARG_EMSG} (an array expected)`;
77
+ const XOBJ_TE_NARR_ECODE = 'ERR_XOBJ_NARR';
78
+ const XOBJ_TE_NSTR_EMSG = `${XOBJ_TE_INVARG_EMSG} (a string expected)`;
79
+ const XOBJ_TE_NSTR_ECODE = 'ERR_XOBJ_NSTR';
80
+ const XOBJ_TE_NPOBJ_EMSG = `${XOBJ_TE_INVARG_EMSG} (a plain object expected)`;
81
+ const XOBJ_TE_NPOBJ_ECODE = 'ERR_XOBJ_NPOBJ';
82
+ const XOBJ_TE_ANES_EMSG = '<attr_name> must be a non-empty string';
83
+ const XOBJ_TE_ANES_ECODE = 'ERR_XOBJ_INVARG_ATTR';
84
+ const XOBJ_TE_KNES_EMSG = '<key_name> must be a non-empty string';
85
+ const XOBJ_TE_KNES_ECODE = 'ERR_XOBJ_INVARG_KEY';
86
+
87
+ /***
88
+ * (* function definitions *)
89
+ */
90
+
91
+ /**
92
+ * @function evalXObjEName
93
+ * @param {any} value - some value to evaluate
94
+ * @returns {(null|number|string)}
95
+ * @description Tries to convert a value into an ID.
96
+ */
97
+ function evalXObjEName(value) {
98
+ //return valueToIDString(value); // // TODO: [?]
99
+ let name = value;
100
+ switch (typeof name) {
101
+ case 'number' : {
102
+ if (valueToIndex(name) === -1) name = null;
103
+ break;
104
+ }
105
+ case 'string' : {
106
+ name = name.trim();
107
+ if (name !== '') {
108
+ let value = Number(name);
109
+ if (!Number.isNaN(value)) {
110
+ name = (
111
+ value < 0 || !isInteger(value)
112
+ ? null
113
+ : value
114
+ );
115
+ };
116
+ } else {
117
+ name = null;
118
+ };
119
+ break;
120
+ }
121
+ default: {
122
+ name = null;
123
+ }
124
+ };
125
+ return name;
126
+ };
127
+
128
+ /**
129
+ * @function genXObjENameDescr
130
+ * @param {any} value
131
+ * @returns {object}
132
+ * @description Tries to convert a value into an element name description.
133
+ */
134
+ function genXObjENameDescr(value) {
135
+ let result = null;
136
+ let name = null;
137
+ let conditions = null;
138
+ let isERR = false;
139
+ let tail = null;
140
+ if (typeof value === 'string') {
141
+ const re = /^\s*([^\[\]\s]+)?(\s*)(\[.*])?\s*$/;
142
+ tail = value.match(re);
143
+ //console.log('CHECK: '+JSON.stringify(tail, null, 2));
144
+ if (tail) {
145
+ if (tail[1]) {
146
+ name = tail[1];
147
+ if (name) {
148
+ if (tail[2] === '') {
149
+ if (tail[3]) {
150
+ const re = /\[(@{0,1})(?:([^\[=]*?)(?:(?=[=])(=)((?![\"\'])[^\]]*|(?=([\"\']))\5(.*)\5))?)](\s*.*)/;
151
+ tail = tail[3].match(re);
152
+ //console.log('CHECK: '+JSON.stringify(tail, null, 2));
153
+ if (tail) {
154
+ let name = evalXObjEName(tail[2]);
155
+ let type = tail[1] === '@' ? 'attribute' : 'child';
156
+ let value = undefined;
157
+ if (tail[3] === '=') value = tail[5] ? tail[6] : tail[4];
158
+ if (tail[7]) isERR = true;
159
+ conditions = {
160
+ name,
161
+ type,
162
+ value,
163
+ };
164
+ };
165
+ };
166
+ } else if (tail[3]) {
167
+ name = null;
168
+ };
169
+ };
170
+ };
171
+ };
172
+ } else {
173
+ name = value;
174
+ };
175
+ name = evalXObjEName(name);
176
+ if (name === null) isERR = true;
177
+ result = {
178
+ name,
179
+ conditions,
180
+ isERR,
181
+ };
182
+ return result;
183
+ };
184
+
185
+ /**
186
+ * @function getXObjElement
187
+ * @param {object} obj - some object
188
+ * @param {string} name - some child element
189
+ * @returns {?any}
190
+ * @throws {TypeError} if first param is not an object
191
+ * @throws {TypeError} if second param is empty string or not a string at all
192
+ * @description Extracts an element from a given object by its key.
193
+ */
194
+ function getXObjElement(obj, name) {
195
+ if (!isPlainObject(obj)) {
196
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
197
+ err.code = XOBJ_TE_NPOBJ_ECODE;
198
+ throw err;
199
+ };
200
+ let { isSucceed, value: key } = evalKeyName(name);
201
+ if (!isSucceed) {
202
+ const { code, msg } = key;
203
+ const err = new TypeError(msg);
204
+ err.code = code;
205
+ throw err;
206
+ };
207
+ // TODO: [?] check type of obj[key_name]
208
+ return obj[key] !== undefined ? obj[key] : null;
209
+ };
210
+
211
+ /**
212
+ * @function getXObjAttributes
213
+ * @param {object} obj - some object
214
+ * @param {string} [key=XOBJ_DEF_ATTR_TNAME] - some key
215
+ * @returns {?object}
216
+ * @throws {TypeError} if first param is not an object
217
+ * @description Extracts an attributes from a given object by its key.
218
+ */
219
+ function getXObjAttributes(obj, key = XOBJ_DEF_ATTR_TNAME) {
220
+ let result = null;
221
+ try {
222
+ result = getXObjElement(obj, key);
223
+ } catch (err) {
224
+ switch (err.code) {
225
+ case XOBJ_TE_NSTR_ECODE :
226
+ case XOBJ_TE_KNES_ECODE : {
227
+ break;
228
+ }
229
+ default: {
230
+ throw err;
231
+ }
232
+ };
233
+ };
234
+ return isPlainObject(result) ? result : null;
235
+ };
236
+
237
+ /**
238
+ * @typedef {Object} RVAL_emodif
239
+ * @property {boolean} isSucceed - flag that indicates whether an ops is succeed or not
240
+ * @property {?(object|object[])} item - some element as a result
241
+ * @description A result of an xObj modification ops
242
+ */
243
+
244
+ /**
245
+ * @function addXObjElement
246
+ * @param {object} obj - some object
247
+ * @param {string} name - some child element
248
+ * @returns {RVAL_emodif}
249
+ * @throws {TypeError} if first param is not an object
250
+ * @throws {TypeError} if second param is empty string or not a string at all
251
+ * @description Adds an element addressed by its key to a given object.
252
+ */
253
+ function addXObjElement(obj, name) {
254
+ if (!isPlainObject(obj)) {
255
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
256
+ err.code = XOBJ_TE_NPOBJ_ECODE;
257
+ throw err;
258
+ };
259
+ let { isSucceed, value: key } = evalKeyName(name);
260
+ if (!isSucceed) {
261
+ const { code, msg } = key;
262
+ const err = new TypeError(msg);
263
+ err.code = code;
264
+ throw err;
265
+ };
266
+ const item = {};
267
+ let prop = obj[key];
268
+ isSucceed = false;
269
+ // // TODO: [?] consider whether or not do ops if new_key exists
270
+ if (isNullOrUndef(prop)) {
271
+ obj[key] = prop = item;
272
+ isSucceed = true;
273
+ } else if (isObject(prop)) {
274
+ if (isArray(prop)) {
275
+ prop.push(item);
276
+ } else {
277
+ obj[key] = [ prop, item ];
278
+ };
279
+ prop = item;
280
+ isSucceed = true;
281
+ };
282
+ return {
283
+ isSucceed,
284
+ item: isSucceed ? prop : null,
285
+ };
286
+ };
287
+
288
+ /**
289
+ * @typedef {Object} OPT_inselops_L
290
+ * @property {boolean} [force=false]
291
+ * @property {boolean} [ripOldies=false]
292
+ * @property {boolean} [acceptIfList=false]
293
+ */
294
+
295
+ /**
296
+ * @function insertXObjElement
297
+ * @param {object} obj - some object
298
+ * @param {string} name - some child element
299
+ * @param {OPT_inselops_L} [opt] - options
300
+ * @returns {?object}
301
+ * @throws {TypeError} if first param is not an object
302
+ * @description Inserts an element addressed by its key into a given object.
303
+ */
304
+ function insertXObjElement(...args) {
305
+ let item = null;
306
+ try {
307
+ ({ item } = insertXObjElementEx(...args));
308
+ } catch (err) {
309
+ switch (err.code) {
310
+ case XOBJ_TE_NSTR_ECODE :
311
+ case XOBJ_TE_KNES_ECODE : {
312
+ break;
313
+ }
314
+ default: {
315
+ throw err;
316
+ }
317
+ };
318
+ };
319
+ return item;
320
+ };
321
+
322
+ /**
323
+ * @since 0.2.0
324
+ * @function insertXObjElementEx
325
+ * @param {object} obj - some object
326
+ * @param {string} name - some child element
327
+ * @param {OPT_inselops_L} [opt] - options
328
+ * @returns {RVAL_emodif}
329
+ * @throws {TypeError} if first param is not an object
330
+ * @throws {TypeError} if second param is empty string or not a string at all
331
+ * @description Inserts an element addressed by its key into a given object.
332
+ */
333
+ function insertXObjElementEx(obj, name, opt) {
334
+ if (!isPlainObject(obj)) {
335
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
336
+ err.code = XOBJ_TE_NPOBJ_ECODE;
337
+ throw err;
338
+ };
339
+ let { isSucceed, value: key } = evalKeyName(name);
340
+ if (!isSucceed) {
341
+ const { code, msg } = key;
342
+ const err = new TypeError(msg);
343
+ err.code = code;
344
+ throw err;
345
+ };
346
+ const item = {};
347
+ let prop = obj[key];
348
+ isSucceed = false;
349
+ if (isNullOrUndef(prop)) {
350
+ obj[key] = prop = item;
351
+ isSucceed = true;
352
+ } else {
353
+ /** @type {OPT_inselops_L} */
354
+ let {
355
+ force,
356
+ ripOldies,
357
+ acceptIfList,
358
+ } = isPlainObject(opt) ? opt : {};
359
+ if (typeof force !== 'boolean') force = false;
360
+ if (typeof ripOldies !== 'boolean') ripOldies = false;
361
+ if (typeof acceptIfList !== 'boolean') acceptIfList = false;
362
+ if (force && (ripOldies || !isObject(prop))) {
363
+ obj[key] = prop = item;
364
+ isSucceed = true;
365
+ } else {
366
+ isSucceed = isPlainObject(prop) || (isArray(prop) && acceptIfList);
367
+ };
368
+ };
369
+ return {
370
+ isSucceed,
371
+ item: isSucceed ? prop : null,
372
+ };
373
+ };
374
+
375
+ /**
376
+ * @function deleteXObjElement
377
+ * @param {object} obj - some object
378
+ * @param {string} name - some child element
379
+ * @returns {boolean}
380
+ * @throws {TypeError} if first param is not an object
381
+ * @description Deletes an element addressed by its key from a given object.
382
+ */
383
+ function deleteXObjElement(...args) {
384
+ let isSucceed = false;
385
+ try {
386
+ ({ isSucceed } = deleteXObjElementEx(...args));
387
+ } catch (err) {
388
+ switch (err.code) {
389
+ case XOBJ_TE_NSTR_ECODE :
390
+ case XOBJ_TE_KNES_ECODE : {
391
+ break;
392
+ }
393
+ default: {
394
+ throw err;
395
+ }
396
+ };
397
+ };
398
+ return isSucceed;
399
+ };
400
+
401
+ /**
402
+ * @function deleteXObjElementEx
403
+ * @param {object} obj - some object
404
+ * @param {string} name - some child element
405
+ * @returns {RVAL_emodif}
406
+ * @throws {TypeError} if first param is not an object
407
+ * @throws {TypeError} if second param is empty string or not a string at all
408
+ * @description Deletes an element addressed by its key from a given object.
409
+ */
410
+ function deleteXObjElementEx(obj, name) {
411
+ if (!isPlainObject(obj)) {
412
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
413
+ err.code = XOBJ_TE_NPOBJ_ECODE;
414
+ throw err;
415
+ };
416
+ let { isSucceed, value: key } = evalKeyName(name);
417
+ if (!isSucceed) {
418
+ const { code, msg } = key;
419
+ const err = new TypeError(msg);
420
+ err.code = code;
421
+ throw err;
422
+ };
423
+ let prop = obj[key];
424
+ isSucceed = false;
425
+ // // TODO: catch errors in strict mode
426
+ isSucceed = delete obj[key];
427
+ return {
428
+ isSucceed,
429
+ item: isSucceed && isObject(prop) ? prop : null,
430
+ };
431
+ };
432
+
433
+ /**
434
+ * @function renameXObjElement
435
+ * @param {object} obj - some object
436
+ * @param {string} name - some child element
437
+ * @param {string} value - new element ID
438
+ * @returns {boolean}
439
+ * @throws {TypeError} if first param is not an object
440
+ * @throws {TypeError} if second param is not a string
441
+ * @throws {TypeError} if third param is not a string
442
+ * @description Renames an element addressed by its key.
443
+ */
444
+ function renameXObjElement(obj, name = '', value = '') {
445
+ if (!isPlainObject(obj)) {
446
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
447
+ err.code = XOBJ_TE_NPOBJ_ECODE;
448
+ throw err;
449
+ };
450
+ const opt = false;
451
+ let { isSucceed: isAcceptON, value: oname } = evalKeyName(name, opt);
452
+ if (!isAcceptON) {
453
+ const { code, msg } = oname;
454
+ const err = new TypeError(msg);
455
+ err.code = code;
456
+ throw err;
457
+ };
458
+ let { isSucceed: isAcceptNN, value: nname } = evalKeyName(value, opt);
459
+ if (!isAcceptNN) {
460
+ const { code, msg } = nname;
461
+ const err = new TypeError(msg);
462
+ err.code = code;
463
+ throw err;
464
+ };
465
+ let isSucceed = false;
466
+ if (oname !== '' && oname in obj && nname !== '') {
467
+ isSucceed = true;
468
+ if (oname !== nname) {
469
+ const prop = obj[oname];
470
+ obj[nname] = prop;
471
+ isSucceed = delete obj[oname];
472
+ if (!isSucceed) {
473
+ // undo change if failed delete old element
474
+ delete obj[nname];
475
+ };
476
+ };
477
+ };
478
+ return isSucceed;
479
+ };
480
+
481
+ /**
482
+ * @function checkXObjAttribute
483
+ * @param {object} obj - some object
484
+ * @param {string} attr - some attribute ID
485
+ * @param {string} [key] - some key
486
+ * @returns {boolean}
487
+ * @throws {TypeError} if first param is not an object
488
+ * @description Checks whether an attribute is exists.
489
+ */
490
+ function checkXObjAttribute(obj, attr = '', key) {
491
+ let _obj = null;
492
+ try {
493
+ _obj = getXObjAttributes(obj, key);
494
+ } catch (err) {
495
+ throw err;
496
+ };
497
+ if (_obj === null) return false;
498
+ let { isSucceed, value: name } = evalKeyName(attr, false);
499
+ if (isSucceed) {
500
+ if (name === '') return false;
501
+ } else {
502
+ const { code, msg } = name;
503
+ const err = new TypeError(msg);
504
+ err.code = code;
505
+ throw err;
506
+ };
507
+ return _obj[name] !== undefined;
508
+ };
509
+
510
+ /**
511
+ * @function deleteXObjAttribute
512
+ * @param {object} obj - some object
513
+ * @param {string} attr - some attribute ID
514
+ * @param {string} [key] - some key
515
+ * @returns {boolean}
516
+ * @throws {TypeError} if first param is not an object
517
+ * @description Deletes an attribute addressed by a given name.
518
+ */
519
+ function deleteXObjAttribute(obj, attr = '', key) {
520
+ let _obj = null;
521
+ try {
522
+ _obj = getXObjAttributes(obj, key);
523
+ } catch (err) {
524
+ throw err;
525
+ };
526
+ if (_obj === null) return false;
527
+ let { isSucceed, value: name } = evalKeyName(attr, false);
528
+ if (!isSucceed) {
529
+ const { code, msg } = name;
530
+ const err = new TypeError(msg);
531
+ err.code = code;
532
+ throw err;
533
+ };
534
+ isSucceed = false;
535
+ if (name !== '') {
536
+ // // TODO: catch errors in strict mode
537
+ isSucceed = delete _obj[name];
538
+ };
539
+ return isSucceed;
540
+ };
541
+
542
+ /**
543
+ * @since 0.2.0
544
+ * @function renameXObjAttribute
545
+ * @param {object} obj - some object
546
+ * @param {string} attr - some attribute ID
547
+ * @param {string} value - new attribute ID
548
+ * @param {string} [key] - some key
549
+ * @returns {boolean}
550
+ * @throws {TypeError} if first param is not an object
551
+ * @throws {TypeError} if second param is not an object
552
+ * @throws {TypeError} if third param is not an object
553
+ * @description Renames an attribute addressed by a given name.
554
+ */
555
+ function renameXObjAttribute(obj, attr = '', value = '', key = XOBJ_DEF_ATTR_TNAME) {
556
+ if (!isPlainObject(obj)) {
557
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
558
+ err.code = XOBJ_TE_NPOBJ_ECODE;
559
+ throw err;
560
+ };
561
+ const opt = false;
562
+ let { isSucceed, value: _key } = evalKeyName(key, opt);
563
+ if (!isSucceed) {
564
+ const { code, msg } = _key;
565
+ const err = new TypeError(msg);
566
+ err.code = code;
567
+ throw err;
568
+ };
569
+ isSucceed = false;
570
+ if (_key !== '') {
571
+ let _obj = obj[_key];
572
+ if (isPlainObject(_obj)) {
573
+ let { isSucceed: isAcceptON, value: oname } = evalKeyName(attr, opt);
574
+ if (!isAcceptON) {
575
+ const { code, msg } = oname;
576
+ const err = new TypeError(msg);
577
+ err.code = code;
578
+ throw err;
579
+ };
580
+ let { isSucceed: isAcceptNN, value: nname } = evalKeyName(value, opt);
581
+ if (!isAcceptNN) {
582
+ const { code, msg } = nname;
583
+ const err = new TypeError(msg);
584
+ err.code = code;
585
+ throw err;
586
+ };
587
+ if (oname !== '' && oname in _obj && nname !== '') {
588
+ if (oname !== nname) {
589
+ _obj = Object.entries(_obj);
590
+ const index = _obj.findIndex((item) => item[0] === oname);
591
+ _obj[index][0] = nname;
592
+ obj[_key] = Object.fromEntries(_obj);
593
+ };
594
+ isSucceed = true;
595
+ };
596
+ };
597
+ };
598
+ return isSucceed;
599
+ };
600
+
601
+ /**
602
+ * @function readXObjParamRaw
603
+ * @param {object} obj - some object
604
+ * @param {string} [key=XOBJ_DEF_PARAM_TNAME] - some key
605
+ * @returns {any}
606
+ * @throws {TypeError} if first param is not an object
607
+ * @throws {TypeError} if third param is not a string
608
+ * @description Extracts a parameter 'AS IS' from a given object.
609
+ */
610
+ function readXObjParamRaw(obj, key = XOBJ_DEF_PARAM_TNAME) {
611
+ if (!isPlainObject(obj)) {
612
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
613
+ err.code = XOBJ_TE_NPOBJ_ECODE;
614
+ throw err;
615
+ };
616
+ let { isSucceed, value: _key } = evalKeyName(key, false);
617
+ if (!isSucceed) {
618
+ const { code, msg } = _key;
619
+ const err = new TypeError(msg);
620
+ err.code = code;
621
+ throw err;
622
+ };
623
+ return _key !== '' ? obj[_key] : undefined;
624
+ };
625
+
626
+ /**
627
+ * @function writeXObjParamRaw
628
+ * @param {object} obj - some object
629
+ * @param {any} value - some value
630
+ * @param {string} [key=XOBJ_DEF_PARAM_TNAME] - some key
631
+ * @returns {boolean}
632
+ * @throws {TypeError} if first param is not an object
633
+ * @throws {TypeError} if third param is not a string
634
+ * @description Writes a parameter 'AS IS' into a given object.
635
+ */
636
+ function writeXObjParamRaw(obj, value, key = XOBJ_DEF_PARAM_TNAME) {
637
+ if (!isPlainObject(obj)) {
638
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
639
+ err.code = XOBJ_TE_NPOBJ_ECODE;
640
+ throw err;
641
+ };
642
+ let { isSucceed, value: _key } = evalKeyName(key, false);
643
+ if (!isSucceed) {
644
+ const { code, msg } = _key;
645
+ const err = new TypeError(msg);
646
+ err.code = code;
647
+ throw err;
648
+ };
649
+ if (_key === '' || value === undefined) {
650
+ isSucceed = false;
651
+ } else {
652
+ obj[_key] = value;
653
+ };
654
+ return isSucceed;
655
+ };
656
+
657
+ /**
658
+ * @function readXObjAttrRaw
659
+ * @param {object} obj - some object
660
+ * @param {string} attr - some attribute
661
+ * @param {string} [key] - some key
662
+ * @returns {any}
663
+ * @throws {TypeError} if first param is not an object
664
+ * @throws {TypeError} if third param is not a string
665
+ * @description Extracts an attribute 'AS IS' from a given object.
666
+ */
667
+ function readXObjAttrRaw(obj, attr = '', key) {
668
+ let _obj = null;
669
+ try {
670
+ _obj = getXObjAttributes(obj, key);
671
+ } catch (err) {
672
+ throw err;
673
+ };
674
+ if (_obj !== null) {
675
+ let { isSucceed, value: name } = evalKeyName(attr, false);
676
+ if (!isSucceed) {
677
+ const { code, msg } = name;
678
+ const err = new TypeError(msg);
679
+ err.code = code;
680
+ throw err;
681
+ };
682
+ if (name !== '') return _obj[name];
683
+ };
684
+ };
685
+
686
+ /**
687
+ * @function writeXObjAttrRaw
688
+ * @param {object} obj - some object
689
+ * @param {string} attr - some attribute
690
+ * @param {any} value - some value
691
+ * @param {string} [key=XOBJ_DEF_ATTR_TNAME] - some key
692
+ * @returns {boolean}
693
+ * @throws {TypeError} if first param is not an object
694
+ * @throws {TypeError} if third param is not a string
695
+ * @description Writes a parameter into a given object.
696
+ */
697
+ function writeXObjAttrRaw(obj, attr = '', value, key = XOBJ_DEF_ATTR_TNAME) {
698
+ let { isSucceed, value: name } = evalKeyName(attr, false);
699
+ if (!isSucceed) {
700
+ const { code, msg } = name;
701
+ const err = new TypeError(msg);
702
+ err.code = code;
703
+ throw err;
704
+ };
705
+ isSucceed = false;
706
+ if (name !== '' && value !== undefined) {
707
+ let _obj = null;
708
+ try {
709
+ const opt = { force: true, acceptIfList: true };
710
+ _obj = insertXObjElement(obj, key, opt);
711
+ } catch (err) {
712
+ throw err;
713
+ };
714
+ if (isArray(_obj)) {
715
+ // force a replacement of the old element if it's array
716
+ try {
717
+ const opt = { force: true, ripOldies: true };
718
+ _obj = insertXObjElement(obj, key, opt);
719
+ } catch (err) {
720
+ throw err;
721
+ };
722
+ };
723
+ if (_obj !== null) {
724
+ _obj[name] = value;
725
+ isSucceed = true;
726
+ };
727
+ };
728
+ return isSucceed;
729
+ };
730
+
731
+ /**
732
+ * @function readXObjParam
733
+ * @param {object} obj - some object
734
+ * @param {string} [key] - some key
735
+ * @returns {string}
736
+ * @throws {TypeError} if first param is not an object
737
+ * @description Extracts a parameter from a given object
738
+ * and returns it as string.
739
+ */
740
+ function readXObjParam(obj, key) {
741
+ const opt = {
742
+ useTrim: false,
743
+ numberToString: true,
744
+ boolToString: true,
745
+ defValue: '',
746
+ };
747
+ let result = undefined;
748
+ try {
749
+ result = readXObjParamEx(obj, opt, key);
750
+ } catch (err) {
751
+ throw err;
752
+ };
753
+ return result;
754
+ };
755
+
756
+ /**
757
+ * @function readXObjParamAsBool
758
+ * @param {object} obj - some object
759
+ * @param {boolean} [defValue] - default value
760
+ * @param {string} [key] - some key
761
+ * @returns {boolean}
762
+ * @throws {TypeError} if first param is not an object
763
+ * @description Extracts a parameter from a given object
764
+ * and returns it as boolean.
765
+ */
766
+ function readXObjParamAsBool(obj, defValue, key) {
767
+ let result = undefined;
768
+ try {
769
+ result = readXObjParamRaw(obj, key);
770
+ } catch (err) {
771
+ switch (err.code) {
772
+ case XOBJ_TE_NSTR_ECODE : {
773
+ break;
774
+ }
775
+ default: {
776
+ throw err;
777
+ }
778
+ };
779
+ };
780
+ return readAsBoolEx(result, defValue);
781
+ };
782
+
783
+ /**
784
+ * @function readXObjParamAsNum
785
+ * @param {object} obj - some object
786
+ * @param {number} [defValue] - default value
787
+ * @param {string} [key] - some key
788
+ * @returns {number}
789
+ * @throws {TypeError} if first param is not an object
790
+ * @description Extracts a parameter from a given object
791
+ * and returns it as number.
792
+ */
793
+ function readXObjParamAsNum(obj, defValue, key) {
794
+ let result = undefined;
795
+ try {
796
+ result = readXObjParamRaw(obj, key);
797
+ } catch (err) {
798
+ switch (err.code) {
799
+ case XOBJ_TE_NSTR_ECODE : {
800
+ break;
801
+ }
802
+ default: {
803
+ throw err;
804
+ }
805
+ };
806
+ };
807
+ return readAsNumberEx(result, defValue);
808
+ };
809
+
810
+ /**
811
+ * @function readXObjParamEx
812
+ * @param {object} obj - some object
813
+ * @param {object} [opt] - options
814
+ * @param {string} [key] - some key
815
+ * @returns {string}
816
+ * @throws {TypeError} if first param is not an object
817
+ * @description Extracts a parameter from a given object
818
+ * and returns it as string.
819
+ * @todo [since `v0.2.1`] deprecate use of `opt` as `string`
820
+ */
821
+ function readXObjParamEx(obj, opt, key) {
822
+ let result = undefined;
823
+ try {
824
+ result = readXObjParamRaw(obj, key);
825
+ } catch (err) {
826
+ switch (err.code) {
827
+ case XOBJ_TE_NSTR_ECODE : {
828
+ break;
829
+ }
830
+ default: {
831
+ throw err;
832
+ }
833
+ };
834
+ };
835
+ let _opt = opt;
836
+ if (!isPlainObject(_opt)) {
837
+ _opt = {
838
+ useTrim: false,
839
+ numberToString: true,
840
+ boolToString: true,
841
+ defValue: _opt,
842
+ };
843
+ };
844
+ return readAsString(result, _opt);
845
+ };
846
+
847
+ /**
848
+ * @function readXObjParamAsIndex
849
+ * @param {object} obj - some object
850
+ * @param {string} [key] - some key
851
+ * @returns {number}
852
+ * @throws {TypeError} if first param is not an object
853
+ * @description Extracts a parameter from a given object
854
+ * and returns it as 'index' value.
855
+ */
856
+ function readXObjParamAsIndex(obj, key) {
857
+ let result = undefined;
858
+ try {
859
+ result = readXObjParamRaw(obj, key);
860
+ } catch (err) {
861
+ switch (err.code) {
862
+ case XOBJ_TE_NSTR_ECODE : {
863
+ break;
864
+ }
865
+ default: {
866
+ throw err;
867
+ }
868
+ };
869
+ };
870
+ return valueToIndex(result);
871
+ };
872
+
873
+ /**
874
+ * @function writeXObjParam
875
+ * @param {object} obj - some object
876
+ * @param {any} value - some value
877
+ * @param {string} [key] - some key
878
+ * @returns {boolean}
879
+ * @throws {TypeError} if first param is not an object
880
+ * @description Tries to convert a given value to a string
881
+ * and writes it as a parameter into a given object.
882
+ */
883
+ function writeXObjParam(obj, value, key) {
884
+ let isSucceed = false;
885
+ try {
886
+ const opt = {
887
+ useTrim: false,
888
+ numberToString: true,
889
+ boolToString: true,
890
+ defValue: '',
891
+ };
892
+ isSucceed = writeXObjParamEx(obj, value, opt, key);
893
+ } catch (err) {
894
+ throw err;
895
+ };
896
+ return isSucceed;
897
+ };
898
+
899
+ /**
900
+ * @function writeXObjParamAsBool
901
+ * @param {object} obj - some object
902
+ * @param {any} value - some value
903
+ * @param {boolean} [defValue] - default value
904
+ * @param {string} [key] - some key
905
+ * @returns {boolean}
906
+ * @throws {TypeError} if first param is not an object
907
+ * @description Tries to convert a given value to a boolean
908
+ * and writes it as a parameter into a given object.
909
+ */
910
+ function writeXObjParamAsBool(obj, value, defValue, key) {
911
+ let isSucceed = false;
912
+ if (value !== undefined || typeof defValue === 'boolean') {
913
+ const _value = readAsBoolEx(value, defValue).toString();
914
+ try {
915
+ isSucceed = writeXObjParamRaw(obj, _value, key);
916
+ } catch (err) {
917
+ switch (err.code) {
918
+ case XOBJ_TE_NSTR_ECODE : {
919
+ break;
920
+ }
921
+ default: {
922
+ throw err;
923
+ }
924
+ };
925
+ };
926
+ };
927
+ return isSucceed;
928
+ };
929
+
930
+ /**
931
+ * @function writeXObjParamAsNum
932
+ * @param {object} obj - some object
933
+ * @param {any} value - some value
934
+ * @param {number} [defValue] - default value
935
+ * @param {string} [key] - some key
936
+ * @returns {boolean}
937
+ * @throws {TypeError} if first param is not an object
938
+ * @description Tries to convert a given value to a number
939
+ * and writes it as a parameter into a given object.
940
+ */
941
+ function writeXObjParamAsNum(obj, value, defValue, key) {
942
+ let isSucceed = false;
943
+ if (value !== undefined || typeof defValue === 'number') {
944
+ const _value = readAsNumberEx(value, defValue).toString();
945
+ try {
946
+ isSucceed = writeXObjParamRaw(obj, _value, key);
947
+ } catch (err) {
948
+ switch (err.code) {
949
+ case XOBJ_TE_NSTR_ECODE : {
950
+ break;
951
+ }
952
+ default: {
953
+ throw err;
954
+ }
955
+ };
956
+ };
957
+ };
958
+ return isSucceed;
959
+ };
960
+
961
+ /**
962
+ * @function writeXObjParamAsIndex
963
+ * @param {object} obj - some object
964
+ * @param {any} value - some value
965
+ * @param {string} [key] - some key
966
+ * @returns {boolean}
967
+ * @throws {TypeError} if first param is not an object
968
+ * @description Tries to convert a given value into an 'index' value
969
+ * and writes it as a parameter into a given object.
970
+ */
971
+ function writeXObjParamAsIndex(obj, value, key) {
972
+ let isSucceed = false;
973
+ if (value !== undefined) {
974
+ const _value = valueToIndex(value).toString();
975
+ try {
976
+ isSucceed = writeXObjParamRaw(obj, _value, key);
977
+ } catch (err) {
978
+ switch (err.code) {
979
+ case XOBJ_TE_NSTR_ECODE : {
980
+ break;
981
+ }
982
+ default: {
983
+ throw err;
984
+ }
985
+ };
986
+ };
987
+ };
988
+ return isSucceed;
989
+ };
990
+
991
+ /**
992
+ * @function writeXObjParamEx
993
+ * @param {object} obj - some object
994
+ * @param {any} value - some value
995
+ * @param {object} [opt] - options
996
+ * @param {string} [key] - some key
997
+ * @returns {boolean}
998
+ * @throws {TypeError} if first param is not an object
999
+ * @description Tries to convert a given value to a string
1000
+ * and writes it as a parameter into a given object.
1001
+ * @todo [since `v0.2.1`] deprecate use of `opt` as `string`
1002
+ */
1003
+ function writeXObjParamEx(obj, value, opt, key) {
1004
+ let isSucceed = false;
1005
+ if (value !== undefined) {
1006
+ let _opt = opt;
1007
+ if (!isPlainObject(_opt)) {
1008
+ const defValue = readAsString(_opt, {
1009
+ useTrim: false,
1010
+ numberToString: true,
1011
+ boolToString: true,
1012
+ });
1013
+ _opt = {
1014
+ useTrim: false,
1015
+ numberToString: true,
1016
+ boolToString: true,
1017
+ defValue,
1018
+ };
1019
+ };
1020
+ const _value = readAsString(value, _opt);
1021
+ try {
1022
+ isSucceed = writeXObjParamRaw(obj, _value, key);
1023
+ } catch (err) {
1024
+ switch (err.code) {
1025
+ case XOBJ_TE_NSTR_ECODE : {
1026
+ break;
1027
+ }
1028
+ default: {
1029
+ throw err;
1030
+ }
1031
+ };
1032
+ };
1033
+ };
1034
+ return isSucceed;
1035
+ };
1036
+
1037
+ /**
1038
+ * @function readXObjAttr
1039
+ * @param {object} obj - some object
1040
+ * @param {string} attr - some attribute
1041
+ * @param {string} [key] - some key
1042
+ * @returns {string}
1043
+ * @throws {TypeError} if first param is not an object
1044
+ * @description Extracts an attribute from a given object
1045
+ * and returns it as string.
1046
+ */
1047
+ function readXObjAttr(obj, attr, key) {
1048
+ const opt = {
1049
+ useTrim: true,
1050
+ numberToString: true,
1051
+ boolToString: true,
1052
+ defValue: '',
1053
+ };
1054
+ let result = undefined;
1055
+ try {
1056
+ result = readXObjAttrEx(obj, attr, opt, key);
1057
+ } catch (err) {
1058
+ throw err;
1059
+ };
1060
+ return result;
1061
+ };
1062
+
1063
+ /**
1064
+ * @function readXObjAttrAsBool
1065
+ * @param {object} obj - some object
1066
+ * @param {string} attr - some attribute
1067
+ * @param {boolean} [defValue] - default value
1068
+ * @param {string} [key] - some key
1069
+ * @returns {boolean}
1070
+ * @throws {TypeError} if first param is not an object
1071
+ * @description Extracts an attribute from a given object
1072
+ * and returns it as boolean.
1073
+ */
1074
+ function readXObjAttrAsBool(obj, attr, defValue, key) {
1075
+ let result = undefined;
1076
+ try {
1077
+ result = readXObjAttrRaw(obj, attr, key);
1078
+ } catch (err) {
1079
+ switch (err.code) {
1080
+ case XOBJ_TE_NSTR_ECODE : {
1081
+ break;
1082
+ }
1083
+ default: {
1084
+ throw err;
1085
+ }
1086
+ };
1087
+ };
1088
+ return readAsBoolEx(result, defValue);
1089
+ };
1090
+
1091
+ /**
1092
+ * @function readXObjAttrAsNum
1093
+ * @param {object} obj - some object
1094
+ * @param {string} attr - some attribute
1095
+ * @param {number} [defValue] - default value
1096
+ * @param {string} [key] - some key
1097
+ * @returns {number}
1098
+ * @throws {TypeError} if first param is not an object
1099
+ * @description Extracts an attribute from a given object
1100
+ * and returns it as number.
1101
+ */
1102
+ function readXObjAttrAsNum(obj, attr, defValue, key) {
1103
+ let result = undefined;
1104
+ try {
1105
+ result = readXObjAttrRaw(obj, attr, key);
1106
+ } catch (err) {
1107
+ switch (err.code) {
1108
+ case XOBJ_TE_NSTR_ECODE : {
1109
+ break;
1110
+ }
1111
+ default: {
1112
+ throw err;
1113
+ }
1114
+ };
1115
+ };
1116
+ return readAsNumberEx(result, defValue);
1117
+ };
1118
+
1119
+ /**
1120
+ * @function readXObjAttrEx
1121
+ * @param {object} obj - some object
1122
+ * @param {string} attr - some attribute
1123
+ * @param {object} [opt] - options
1124
+ * @param {string} [key] - some key
1125
+ * @returns {string}
1126
+ * @throws {TypeError} if first param is not an object
1127
+ * @description Extracts an attribute from a given object
1128
+ * and returns it as string.
1129
+ * @todo [since `v0.2.1`] deprecate use of `opt` as `string`
1130
+ */
1131
+ function readXObjAttrEx(obj, attr, opt, key) {
1132
+ let result = undefined;
1133
+ try {
1134
+ result = readXObjAttrRaw(obj, attr, key);
1135
+ } catch (err) {
1136
+ switch (err.code) {
1137
+ case XOBJ_TE_NSTR_ECODE : {
1138
+ break;
1139
+ }
1140
+ default: {
1141
+ throw err;
1142
+ }
1143
+ };
1144
+ };
1145
+ let _opt = opt;
1146
+ if (!isPlainObject(_opt)) {
1147
+ _opt = {
1148
+ useTrim: true,
1149
+ numberToString: true,
1150
+ boolToString: true,
1151
+ defValue: _opt,
1152
+ };
1153
+ };
1154
+ return readAsString(result, _opt);
1155
+ };
1156
+
1157
+ /**
1158
+ * @function readXObjAttrAsIndex
1159
+ * @param {object} obj - some object
1160
+ * @param {string} attr - some attribute
1161
+ * @param {string} [key] - some key
1162
+ * @returns {number}
1163
+ * @throws {TypeError} if first param is not an object
1164
+ * @description Extracts an attribute from a given object
1165
+ * and returns it as 'index' value.
1166
+ */
1167
+ function readXObjAttrAsIndex(obj, attr, key) {
1168
+ let result = undefined;
1169
+ try {
1170
+ result = readXObjAttrRaw(obj, attr, key);
1171
+ } catch (err) {
1172
+ switch (err.code) {
1173
+ case XOBJ_TE_NSTR_ECODE : {
1174
+ break;
1175
+ }
1176
+ default: {
1177
+ throw err;
1178
+ }
1179
+ };
1180
+ };
1181
+ return valueToIndex(result);
1182
+ };
1183
+
1184
+ /**
1185
+ * @function writeXObjAttr
1186
+ * @param {object} obj - some object
1187
+ * @param {string} attr - some attribute
1188
+ * @param {any} value - some value
1189
+ * @param {string} [key] - some key
1190
+ * @returns {boolean}
1191
+ * @throws {TypeError} if first param is not an object
1192
+ * @description Tries to convert a given value to a string
1193
+ * and writes it as an attribute into a given object.
1194
+ */
1195
+ function writeXObjAttr(obj, attr, value, key) {
1196
+ let isSucceed = false;
1197
+ try {
1198
+ const opt = {
1199
+ useTrim: true,
1200
+ numberToString: true,
1201
+ boolToString: true,
1202
+ defValue: '',
1203
+ };
1204
+ isSucceed = writeXObjAttrEx(obj, attr, value, opt, key);
1205
+ } catch (err) {
1206
+ throw err;
1207
+ };
1208
+ return isSucceed;
1209
+ };
1210
+
1211
+ /**
1212
+ * @function writeXObjAttrAsBool
1213
+ * @param {object} obj - some object
1214
+ * @param {string} attr - some attribute
1215
+ * @param {any} value - some value
1216
+ * @param {boolean} [defValue] - default value
1217
+ * @param {string} [key] - some key
1218
+ * @returns {boolean}
1219
+ * @throws {TypeError} if first param is not an object
1220
+ * @description Tries to convert a given value to a boolean
1221
+ * and writes it as an attribute into a given object.
1222
+ */
1223
+ function writeXObjAttrAsBool(obj, attr, value, defValue, key) {
1224
+ let isSucceed = false;
1225
+ if (value !== undefined || typeof defValue === 'boolean') {
1226
+ const _value = readAsBoolEx(value, defValue).toString();
1227
+ try {
1228
+ isSucceed = writeXObjAttrRaw(obj, attr, _value, key);
1229
+ } catch (err) {
1230
+ switch (err.code) {
1231
+ case XOBJ_TE_NSTR_ECODE : {
1232
+ break;
1233
+ }
1234
+ default: {
1235
+ throw err;
1236
+ }
1237
+ };
1238
+ };
1239
+ };
1240
+ return isSucceed;
1241
+ };
1242
+
1243
+ /**
1244
+ * @function writeXObjAttrAsNum
1245
+ * @param {object} obj - some object
1246
+ * @param {string} attr - some attribute
1247
+ * @param {any} value - some value
1248
+ * @param {number} [defValue] - default value
1249
+ * @param {string} [key] - some key
1250
+ * @returns {boolean}
1251
+ * @throws {TypeError} if first param is not an object
1252
+ * @description Tries to convert a given value to a number
1253
+ * and writes it as an attribute into a given object.
1254
+ */
1255
+ function writeXObjAttrAsNum(obj, attr, value, defValue, key) {
1256
+ let isSucceed = false;
1257
+ if (value !== undefined || typeof defValue === 'number') {
1258
+ const _value = readAsNumberEx(value, defValue).toString();
1259
+ try {
1260
+ isSucceed = writeXObjAttrRaw(obj, attr, _value, key);
1261
+ } catch (err) {
1262
+ switch (err.code) {
1263
+ case XOBJ_TE_NSTR_ECODE : {
1264
+ break;
1265
+ }
1266
+ default: {
1267
+ throw err;
1268
+ }
1269
+ };
1270
+ };
1271
+ };
1272
+ return isSucceed;
1273
+ };
1274
+
1275
+ /**
1276
+ * @function writeXObjAttrAsIndex
1277
+ * @param {object} obj - some object
1278
+ * @param {string} attr - some attribute
1279
+ * @param {any} value - some value
1280
+ * @param {string} [key] - some key
1281
+ * @returns {boolean}
1282
+ * @throws {TypeError} if first param is not an object
1283
+ * @description Tries to convert a given value into an 'index' value
1284
+ * and writes it as an attribute into a given object.
1285
+ */
1286
+ function writeXObjAttrAsIndex(obj, attr, value, key) {
1287
+ let isSucceed = false;
1288
+ if (value !== undefined) {
1289
+ const _value = valueToIndex(value).toString();
1290
+ try {
1291
+ isSucceed = writeXObjAttrRaw(obj, attr, _value, key);
1292
+ } catch (err) {
1293
+ switch (err.code) {
1294
+ case XOBJ_TE_NSTR_ECODE : {
1295
+ break;
1296
+ }
1297
+ default: {
1298
+ throw err;
1299
+ }
1300
+ };
1301
+ };
1302
+ };
1303
+ return isSucceed;
1304
+ };
1305
+
1306
+ /**
1307
+ * @function writeXObjAttrEx
1308
+ * @param {object} obj - some object
1309
+ * @param {string} attr - some attribute
1310
+ * @param {any} value - some value
1311
+ * @param {object} [opt] - options
1312
+ * @param {string} [key] - some key
1313
+ * @returns {boolean}
1314
+ * @throws {TypeError} if first param is not an object
1315
+ * @description Tries to convert a given value to a string
1316
+ * and writes it as an attribute into a given object.
1317
+ * @todo [since `v0.2.1`] deprecate use of `opt` as `string`
1318
+ */
1319
+ function writeXObjAttrEx(obj, attr, value, opt, key) {
1320
+ let isSucceed = false;
1321
+ if (value !== undefined) {
1322
+ let _opt = opt;
1323
+ if (!isPlainObject(_opt)) {
1324
+ const defValue = readAsString(_opt, {
1325
+ useTrim: true,
1326
+ numberToString: true,
1327
+ boolToString: true,
1328
+ });
1329
+ _opt = {
1330
+ useTrim: true,
1331
+ numberToString: true,
1332
+ boolToString: true,
1333
+ defValue,
1334
+ };
1335
+ };
1336
+ const _value = readAsString(value, _opt);
1337
+ try {
1338
+ isSucceed = writeXObjAttrRaw(obj, attr, _value, key);
1339
+ } catch (err) {
1340
+ switch (err.code) {
1341
+ case XOBJ_TE_NSTR_ECODE : {
1342
+ break;
1343
+ }
1344
+ default: {
1345
+ throw err;
1346
+ }
1347
+ };
1348
+ };
1349
+ };
1350
+ return isSucceed;
1351
+ };
1352
+
1353
+ /**
1354
+ * @function insertXObjElements
1355
+ * @param {object} obj
1356
+ * @param {...string} name
1357
+ * @param {OPT_inselops_L} [opt]
1358
+ * @returns {number}
1359
+ * @throws {TypeError} if first param is not an object
1360
+ * @description Inserts an elements into a given object.
1361
+ */
1362
+ function insertXObjElements(obj, ...args) {
1363
+ if (!isPlainObject(obj)) {
1364
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
1365
+ err.code = XOBJ_TE_NPOBJ_ECODE;
1366
+ throw err;
1367
+ };
1368
+ let count = 0;
1369
+ let len = args.length;
1370
+ const opt = (
1371
+ len > 0 && isPlainObject(args[len - 1])
1372
+ ? (len--, args.pop())
1373
+ : {}
1374
+ );
1375
+ for (let key of args) {
1376
+ if (insertXObjElement(obj, key, opt) !== null) count++;
1377
+ };
1378
+ return count;
1379
+ };
1380
+
1381
+ /**
1382
+ * @typedef {Object} OPT_inselops_S
1383
+ * @property {boolean} [force=false]
1384
+ * @property {boolean} [ripOldies=false]
1385
+ */
1386
+
1387
+ /**
1388
+ * @function insertXObjEList
1389
+ * @param {object} obj - some object
1390
+ * @param {string} name - some child element
1391
+ * @param {OPT_inselops_S} [opt] - options
1392
+ * @returns {?(object|object[])}
1393
+ * @throws {TypeError} if first param is not an object
1394
+ * @description Inserts a list elements into a given object.
1395
+ */
1396
+ function insertXObjEList(...args) {
1397
+ let item = null;
1398
+ try {
1399
+ ({ item } = insertXObjEListEx(...args));
1400
+ } catch (err) {
1401
+ switch (err.code) {
1402
+ case XOBJ_TE_NSTR_ECODE :
1403
+ case XOBJ_TE_KNES_ECODE : {
1404
+ break;
1405
+ }
1406
+ default: {
1407
+ throw err;
1408
+ }
1409
+ };
1410
+ };
1411
+ return item;
1412
+ };
1413
+
1414
+ /**
1415
+ * @since 0.2.0
1416
+ * @function insertXObjEListEx
1417
+ * @param {object} obj - some object
1418
+ * @param {string} name - some child element
1419
+ * @param {OPT_inselops_S} [opt] - options
1420
+ * @returns {RVAL_emodif}
1421
+ * @throws {TypeError} if first param is not an object
1422
+ * @throws {TypeError} if second param is empty string or not a string at all
1423
+ * @description Inserts a list elements into a given object.
1424
+ */
1425
+ function insertXObjEListEx(obj, name, opt) {
1426
+ if (!isPlainObject(obj)) {
1427
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
1428
+ err.code = XOBJ_TE_NPOBJ_ECODE;
1429
+ throw err;
1430
+ };
1431
+ let { isSucceed, value: key } = evalKeyName(name);
1432
+ if (!isSucceed) {
1433
+ const { code, msg } = key;
1434
+ const err = new TypeError(msg);
1435
+ err.code = code;
1436
+ throw err;
1437
+ };
1438
+ /** @type {OPT_inselops_S} */
1439
+ let {
1440
+ force,
1441
+ ripOldies,
1442
+ } = isPlainObject(opt) ? opt : {};
1443
+ if (typeof force !== 'boolean') force = false;
1444
+ if (typeof ripOldies !== 'boolean') ripOldies = false;
1445
+ let prop = obj[key];
1446
+ isSucceed = false;
1447
+ if (
1448
+ isNullOrUndef(prop)
1449
+ || (force && (ripOldies || !isObject(prop)))
1450
+ ) {
1451
+ obj[key] = prop = [];
1452
+ isSucceed = true;
1453
+ } else {
1454
+ if (isObject(prop)) {
1455
+ if (!isArray(prop)) prop = [ prop ];
1456
+ obj[key] = prop;
1457
+ isSucceed = true;
1458
+ };
1459
+ };
1460
+ return {
1461
+ isSucceed,
1462
+ item: isSucceed ? prop : null,
1463
+ };
1464
+ };
1465
+
1466
+ /**
1467
+ * @function insertXObjEChain
1468
+ * @param {object} obj - some object
1469
+ * @param {...string} name - some child element
1470
+ * @param {object} [opt] - options
1471
+ * @returns {?any}
1472
+ * @throws {TypeError} if first param is not an object
1473
+ * @description Inserts a chain of an elements into a given object.
1474
+ */
1475
+ function insertXObjEChain(obj, ...args) {
1476
+ if (!isPlainObject(obj)) {
1477
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
1478
+ err.code = XOBJ_TE_NPOBJ_ECODE;
1479
+ throw err;
1480
+ };
1481
+ let result = null;
1482
+ let len = args.length;
1483
+ const opt = (
1484
+ len > 0 && isPlainObject(args[len - 1])
1485
+ ? (len--, args.pop())
1486
+ : {}
1487
+ );
1488
+ if (len > 0) {
1489
+ let parent = obj;
1490
+ let child = null;
1491
+ let isSucceed = false;
1492
+ for (let key of args) {
1493
+ child = insertXObjElement(parent, key, opt);
1494
+ isSucceed = isPlainObject(child);
1495
+ if (!isSucceed) break;
1496
+ parent = child;
1497
+ };
1498
+ result = isSucceed ? parent : null;
1499
+ };
1500
+ return result;
1501
+ };
1502
+
1503
+ /***
1504
+ * (* class definitions *)
1505
+ */
1506
+
1507
+ // === module exports block ===
1508
+
1509
+ module.exports.XOBJ_DEF_PARAM_TNAME = XOBJ_DEF_PARAM_TNAME;
1510
+ module.exports.XOBJ_DEF_ATTR_TNAME = XOBJ_DEF_ATTR_TNAME;
1511
+
1512
+ module.exports.readXObjParamRaw = readXObjParamRaw;
1513
+ module.exports.readXObjParam = readXObjParam;
1514
+ module.exports.readXObjParamAsBool = readXObjParamAsBool;
1515
+ module.exports.readXObjParamAsNum = readXObjParamAsNum;
1516
+ module.exports.readXObjParamEx = readXObjParamEx;
1517
+ module.exports.readXObjParamAsIndex = readXObjParamAsIndex;
1518
+ module.exports.writeXObjParamRaw = writeXObjParamRaw;
1519
+ module.exports.writeXObjParam = writeXObjParam;
1520
+ module.exports.writeXObjParamAsBool = writeXObjParamAsBool;
1521
+ module.exports.writeXObjParamAsNum = writeXObjParamAsNum;
1522
+ module.exports.writeXObjParamAsIndex = writeXObjParamAsIndex;
1523
+ module.exports.writeXObjParamEx = writeXObjParamEx;
1524
+
1525
+ module.exports.readXObjAttrRaw = readXObjAttrRaw;
1526
+ module.exports.readXObjAttr = readXObjAttr;
1527
+ module.exports.readXObjAttrAsBool = readXObjAttrAsBool;
1528
+ module.exports.readXObjAttrAsNum = readXObjAttrAsNum;
1529
+ module.exports.readXObjAttrEx = readXObjAttrEx;
1530
+ module.exports.readXObjAttrAsIndex = readXObjAttrAsIndex;
1531
+ module.exports.writeXObjAttrRaw = writeXObjAttrRaw;
1532
+ module.exports.writeXObjAttr = writeXObjAttr;
1533
+ module.exports.writeXObjAttrAsBool = writeXObjAttrAsBool;
1534
+ module.exports.writeXObjAttrAsNum = writeXObjAttrAsNum;
1535
+ module.exports.writeXObjAttrAsIndex = writeXObjAttrAsIndex;
1536
+ module.exports.writeXObjAttrEx = writeXObjAttrEx;
1537
+
1538
+ module.exports.getXObjAttributes = getXObjAttributes;
1539
+ module.exports.checkXObjAttribute = checkXObjAttribute;
1540
+ module.exports.deleteXObjAttribute = deleteXObjAttribute;
1541
+ module.exports.renameXObjAttribute = renameXObjAttribute;
1542
+
1543
+ module.exports.getXObjElement = getXObjElement;
1544
+ module.exports.addXObjElement = addXObjElement;
1545
+ module.exports.insertXObjElement = insertXObjElement;
1546
+ module.exports.insertXObjElementEx = insertXObjElementEx;
1547
+ module.exports.deleteXObjElement = deleteXObjElement;
1548
+ module.exports.deleteXObjElementEx = deleteXObjElementEx;
1549
+ module.exports.renameXObjElement = renameXObjElement;
1550
+
1551
+ module.exports.evalXObjEName = evalXObjEName;
1552
+ module.exports.insertXObjEList = insertXObjEList;
1553
+ module.exports.insertXObjEListEx = insertXObjEListEx;
1554
+
1555
+ /* inner */
1556
+ module.exports.evalKeyName = evalKeyName;
1557
+
1558
+ /* experimental */
1559
+ module.exports.genXObjENameDescr = genXObjENameDescr;
1560
+ /* experimental */
1561
+ module.exports.insertXObjElements = insertXObjElements;
1562
+ /* experimental */
1563
+ module.exports.insertXObjEChain = insertXObjEChain;
1564
+
1565
+ /** @deprecated */
1566
+ module.exports.readXObjParamAsStr = readXObjParamEx;
1567
+ /** @deprecated */
1568
+ module.exports.readXObjAttrAsStr = readXObjAttrEx;