@ygracs/xobj-lib-js 0.2.0 → 0.2.1

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,1561 @@
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.099-20250128]
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
+ * @function insertXObjElementEx
324
+ * @param {object} obj - some object
325
+ * @param {string} name - some child element
326
+ * @param {OPT_inselops_L} [opt] - options
327
+ * @returns {RVAL_emodif}
328
+ * @throws {TypeError} if first param is not an object
329
+ * @throws {TypeError} if second param is empty string or not a string at all
330
+ * @since 0.2.0
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
+ const _opt = isPlainObject(opt) ? opt : {};
354
+ let { force, ripOldies, acceptIfList } = _opt;
355
+ if (typeof force !== 'boolean') force = false;
356
+ if (typeof ripOldies !== 'boolean') ripOldies = false;
357
+ if (typeof acceptIfList !== 'boolean') acceptIfList = false;
358
+ if (force && (ripOldies || !isObject(prop))) {
359
+ obj[key] = prop = item;
360
+ isSucceed = true;
361
+ } else {
362
+ isSucceed = isPlainObject(prop) || (isArray(prop) && acceptIfList);
363
+ };
364
+ };
365
+ return {
366
+ isSucceed,
367
+ item: isSucceed ? prop : null,
368
+ };
369
+ };
370
+
371
+ /**
372
+ * @function deleteXObjElement
373
+ * @param {object} obj - some object
374
+ * @param {string} name - some child element
375
+ * @returns {boolean}
376
+ * @throws {TypeError} if first param is not an object
377
+ * @description Deletes an element addressed by its key from a given object.
378
+ */
379
+ function deleteXObjElement(...args) {
380
+ let isSucceed = false;
381
+ try {
382
+ ({ isSucceed } = deleteXObjElementEx(...args));
383
+ } catch (err) {
384
+ switch (err.code) {
385
+ case XOBJ_TE_NSTR_ECODE :
386
+ case XOBJ_TE_KNES_ECODE : {
387
+ break;
388
+ }
389
+ default: {
390
+ throw err;
391
+ }
392
+ };
393
+ };
394
+ return isSucceed;
395
+ };
396
+
397
+ /**
398
+ * @function deleteXObjElementEx
399
+ * @param {object} obj - some object
400
+ * @param {string} name - some child element
401
+ * @returns {RVAL_emodif}
402
+ * @throws {TypeError} if first param is not an object
403
+ * @throws {TypeError} if second param is empty string or not a string at all
404
+ * @description Deletes an element addressed by its key from a given object.
405
+ */
406
+ function deleteXObjElementEx(obj, name) {
407
+ if (!isPlainObject(obj)) {
408
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
409
+ err.code = XOBJ_TE_NPOBJ_ECODE;
410
+ throw err;
411
+ };
412
+ let { isSucceed, value: key } = evalKeyName(name);
413
+ if (!isSucceed) {
414
+ const { code, msg } = key;
415
+ const err = new TypeError(msg);
416
+ err.code = code;
417
+ throw err;
418
+ };
419
+ let prop = obj[key];
420
+ isSucceed = false;
421
+ // // TODO: catch errors in strict mode
422
+ isSucceed = delete obj[key];
423
+ return {
424
+ isSucceed,
425
+ item: isSucceed && isObject(prop) ? prop : null,
426
+ };
427
+ };
428
+
429
+ /**
430
+ * @function renameXObjElement
431
+ * @param {object} obj - some object
432
+ * @param {string} name - some child element
433
+ * @param {string} value - new element ID
434
+ * @returns {boolean}
435
+ * @throws {TypeError} if first param is not an object
436
+ * @throws {TypeError} if second param is not a string
437
+ * @throws {TypeError} if third param is not a string
438
+ * @description Renames an element addressed by its key.
439
+ */
440
+ function renameXObjElement(obj, name = '', value = '') {
441
+ if (!isPlainObject(obj)) {
442
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
443
+ err.code = XOBJ_TE_NPOBJ_ECODE;
444
+ throw err;
445
+ };
446
+ const opt = false;
447
+ let { isSucceed: isAcceptON, value: oname } = evalKeyName(name, opt);
448
+ if (!isAcceptON) {
449
+ const { code, msg } = oname;
450
+ const err = new TypeError(msg);
451
+ err.code = code;
452
+ throw err;
453
+ };
454
+ let { isSucceed: isAcceptNN, value: nname } = evalKeyName(value, opt);
455
+ if (!isAcceptNN) {
456
+ const { code, msg } = nname;
457
+ const err = new TypeError(msg);
458
+ err.code = code;
459
+ throw err;
460
+ };
461
+ let isSucceed = false;
462
+ if (oname !== '' && oname in obj && nname !== '') {
463
+ isSucceed = true;
464
+ if (oname !== nname) {
465
+ const prop = obj[oname];
466
+ obj[nname] = prop;
467
+ isSucceed = delete obj[oname];
468
+ if (!isSucceed) {
469
+ // undo change if failed delete old element
470
+ delete obj[nname];
471
+ };
472
+ };
473
+ };
474
+ return isSucceed;
475
+ };
476
+
477
+ /**
478
+ * @function checkXObjAttribute
479
+ * @param {object} obj - some object
480
+ * @param {string} attr - some attribute ID
481
+ * @param {string} [key] - some key
482
+ * @returns {boolean}
483
+ * @throws {TypeError} if first param is not an object
484
+ * @description Checks whether an attribute is exists.
485
+ */
486
+ function checkXObjAttribute(obj, attr = '', key) {
487
+ let _obj = null;
488
+ try {
489
+ _obj = getXObjAttributes(obj, key);
490
+ } catch (err) {
491
+ throw err;
492
+ };
493
+ if (_obj === null) return false;
494
+ let { isSucceed, value: name } = evalKeyName(attr, false);
495
+ if (isSucceed) {
496
+ if (name === '') return false;
497
+ } else {
498
+ const { code, msg } = name;
499
+ const err = new TypeError(msg);
500
+ err.code = code;
501
+ throw err;
502
+ };
503
+ return _obj[name] !== undefined;
504
+ };
505
+
506
+ /**
507
+ * @function deleteXObjAttribute
508
+ * @param {object} obj - some object
509
+ * @param {string} attr - some attribute ID
510
+ * @param {string} [key] - some key
511
+ * @returns {boolean}
512
+ * @throws {TypeError} if first param is not an object
513
+ * @description Deletes an attribute addressed by a given name.
514
+ */
515
+ function deleteXObjAttribute(obj, attr = '', key) {
516
+ let _obj = null;
517
+ try {
518
+ _obj = getXObjAttributes(obj, key);
519
+ } catch (err) {
520
+ throw err;
521
+ };
522
+ if (_obj === null) return false;
523
+ let { isSucceed, value: name } = evalKeyName(attr, false);
524
+ if (!isSucceed) {
525
+ const { code, msg } = name;
526
+ const err = new TypeError(msg);
527
+ err.code = code;
528
+ throw err;
529
+ };
530
+ isSucceed = false;
531
+ if (name !== '') {
532
+ // // TODO: catch errors in strict mode
533
+ isSucceed = delete _obj[name];
534
+ };
535
+ return isSucceed;
536
+ };
537
+
538
+ /**
539
+ * @function renameXObjAttribute
540
+ * @param {object} obj - some object
541
+ * @param {string} attr - some attribute ID
542
+ * @param {string} value - new attribute ID
543
+ * @param {string} [key] - some key
544
+ * @returns {boolean}
545
+ * @throws {TypeError} if first param is not an object
546
+ * @throws {TypeError} if second param is not an object
547
+ * @throws {TypeError} if third param is not an object
548
+ * @since 0.2.0
549
+ * @description Renames an attribute addressed by a given name.
550
+ */
551
+ function renameXObjAttribute(obj, attr = '', value = '', key = XOBJ_DEF_ATTR_TNAME) {
552
+ if (!isPlainObject(obj)) {
553
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
554
+ err.code = XOBJ_TE_NPOBJ_ECODE;
555
+ throw err;
556
+ };
557
+ const opt = false;
558
+ let { isSucceed, value: _key } = evalKeyName(key, opt);
559
+ if (!isSucceed) {
560
+ const { code, msg } = _key;
561
+ const err = new TypeError(msg);
562
+ err.code = code;
563
+ throw err;
564
+ };
565
+ isSucceed = false;
566
+ if (_key !== '') {
567
+ let _obj = obj[_key];
568
+ if (isPlainObject(_obj)) {
569
+ let { isSucceed: isAcceptON, value: oname } = evalKeyName(attr, opt);
570
+ if (!isAcceptON) {
571
+ const { code, msg } = oname;
572
+ const err = new TypeError(msg);
573
+ err.code = code;
574
+ throw err;
575
+ };
576
+ let { isSucceed: isAcceptNN, value: nname } = evalKeyName(value, opt);
577
+ if (!isAcceptNN) {
578
+ const { code, msg } = nname;
579
+ const err = new TypeError(msg);
580
+ err.code = code;
581
+ throw err;
582
+ };
583
+ if (oname !== '' && oname in _obj && nname !== '') {
584
+ if (oname !== nname) {
585
+ _obj = Object.entries(_obj);
586
+ const index = _obj.findIndex((item) => item[0] === oname);
587
+ _obj[index][0] = nname;
588
+ obj[_key] = Object.fromEntries(_obj);
589
+ };
590
+ isSucceed = true;
591
+ };
592
+ };
593
+ };
594
+ return isSucceed;
595
+ };
596
+
597
+ /**
598
+ * @function readXObjParamRaw
599
+ * @param {object} obj - some object
600
+ * @param {string} [key=XOBJ_DEF_PARAM_TNAME] - some key
601
+ * @returns {any}
602
+ * @throws {TypeError} if first param is not an object
603
+ * @throws {TypeError} if third param is not a string
604
+ * @description Extracts a parameter 'AS IS' from a given object.
605
+ */
606
+ function readXObjParamRaw(obj, key = XOBJ_DEF_PARAM_TNAME) {
607
+ if (!isPlainObject(obj)) {
608
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
609
+ err.code = XOBJ_TE_NPOBJ_ECODE;
610
+ throw err;
611
+ };
612
+ let { isSucceed, value: _key } = evalKeyName(key, false);
613
+ if (!isSucceed) {
614
+ const { code, msg } = _key;
615
+ const err = new TypeError(msg);
616
+ err.code = code;
617
+ throw err;
618
+ };
619
+ return _key !== '' ? obj[_key] : undefined;
620
+ };
621
+
622
+ /**
623
+ * @function writeXObjParamRaw
624
+ * @param {object} obj - some object
625
+ * @param {any} value - some value
626
+ * @param {string} [key=XOBJ_DEF_PARAM_TNAME] - some key
627
+ * @returns {boolean}
628
+ * @throws {TypeError} if first param is not an object
629
+ * @throws {TypeError} if third param is not a string
630
+ * @description Writes a parameter 'AS IS' into a given object.
631
+ */
632
+ function writeXObjParamRaw(obj, value, key = XOBJ_DEF_PARAM_TNAME) {
633
+ if (!isPlainObject(obj)) {
634
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
635
+ err.code = XOBJ_TE_NPOBJ_ECODE;
636
+ throw err;
637
+ };
638
+ let { isSucceed, value: _key } = evalKeyName(key, false);
639
+ if (!isSucceed) {
640
+ const { code, msg } = _key;
641
+ const err = new TypeError(msg);
642
+ err.code = code;
643
+ throw err;
644
+ };
645
+ if (_key === '' || value === undefined) {
646
+ isSucceed = false;
647
+ } else {
648
+ obj[_key] = value;
649
+ };
650
+ return isSucceed;
651
+ };
652
+
653
+ /**
654
+ * @function readXObjAttrRaw
655
+ * @param {object} obj - some object
656
+ * @param {string} attr - some attribute
657
+ * @param {string} [key] - some key
658
+ * @returns {any}
659
+ * @throws {TypeError} if first param is not an object
660
+ * @throws {TypeError} if third param is not a string
661
+ * @description Extracts an attribute 'AS IS' from a given object.
662
+ */
663
+ function readXObjAttrRaw(obj, attr = '', key) {
664
+ let _obj = null;
665
+ try {
666
+ _obj = getXObjAttributes(obj, key);
667
+ } catch (err) {
668
+ throw err;
669
+ };
670
+ if (_obj !== null) {
671
+ let { isSucceed, value: name } = evalKeyName(attr, false);
672
+ if (!isSucceed) {
673
+ const { code, msg } = name;
674
+ const err = new TypeError(msg);
675
+ err.code = code;
676
+ throw err;
677
+ };
678
+ if (name !== '') return _obj[name];
679
+ };
680
+ };
681
+
682
+ /**
683
+ * @function writeXObjAttrRaw
684
+ * @param {object} obj - some object
685
+ * @param {string} attr - some attribute
686
+ * @param {any} value - some value
687
+ * @param {string} [key=XOBJ_DEF_ATTR_TNAME] - some key
688
+ * @returns {boolean}
689
+ * @throws {TypeError} if first param is not an object
690
+ * @throws {TypeError} if third param is not a string
691
+ * @description Writes a parameter into a given object.
692
+ */
693
+ function writeXObjAttrRaw(obj, attr = '', value, key = XOBJ_DEF_ATTR_TNAME) {
694
+ let { isSucceed, value: name } = evalKeyName(attr, false);
695
+ if (!isSucceed) {
696
+ const { code, msg } = name;
697
+ const err = new TypeError(msg);
698
+ err.code = code;
699
+ throw err;
700
+ };
701
+ isSucceed = false;
702
+ if (name !== '' && value !== undefined) {
703
+ let _obj = null;
704
+ try {
705
+ const opt = { force: true, acceptIfList: true };
706
+ _obj = insertXObjElement(obj, key, opt);
707
+ } catch (err) {
708
+ throw err;
709
+ };
710
+ if (isArray(_obj)) {
711
+ // force a replacement of the old element if it's array
712
+ try {
713
+ const opt = { force: true, ripOldies: true };
714
+ _obj = insertXObjElement(obj, key, opt);
715
+ } catch (err) {
716
+ throw err;
717
+ };
718
+ };
719
+ if (_obj !== null) {
720
+ _obj[name] = value;
721
+ isSucceed = true;
722
+ };
723
+ };
724
+ return isSucceed;
725
+ };
726
+
727
+ /**
728
+ * @function readXObjParam
729
+ * @param {object} obj - some object
730
+ * @param {string} [key] - some key
731
+ * @returns {string}
732
+ * @throws {TypeError} if first param is not an object
733
+ * @description Extracts a parameter from a given object
734
+ * and returns it as string.
735
+ */
736
+ function readXObjParam(obj, key) {
737
+ const opt = {
738
+ useTrim: false,
739
+ numberToString: true,
740
+ boolToString: true,
741
+ defValue: '',
742
+ };
743
+ let result = undefined;
744
+ try {
745
+ result = readXObjParamEx(obj, opt, key);
746
+ } catch (err) {
747
+ throw err;
748
+ };
749
+ return result;
750
+ };
751
+
752
+ /**
753
+ * @function readXObjParamAsBool
754
+ * @param {object} obj - some object
755
+ * @param {boolean} [defValue] - default value
756
+ * @param {string} [key] - some key
757
+ * @returns {boolean}
758
+ * @throws {TypeError} if first param is not an object
759
+ * @description Extracts a parameter from a given object
760
+ * and returns it as boolean.
761
+ */
762
+ function readXObjParamAsBool(obj, defValue, key) {
763
+ let result = undefined;
764
+ try {
765
+ result = readXObjParamRaw(obj, key);
766
+ } catch (err) {
767
+ switch (err.code) {
768
+ case XOBJ_TE_NSTR_ECODE : {
769
+ break;
770
+ }
771
+ default: {
772
+ throw err;
773
+ }
774
+ };
775
+ };
776
+ return readAsBoolEx(result, defValue);
777
+ };
778
+
779
+ /**
780
+ * @function readXObjParamAsNum
781
+ * @param {object} obj - some object
782
+ * @param {number} [defValue] - default value
783
+ * @param {string} [key] - some key
784
+ * @returns {number}
785
+ * @throws {TypeError} if first param is not an object
786
+ * @description Extracts a parameter from a given object
787
+ * and returns it as number.
788
+ */
789
+ function readXObjParamAsNum(obj, defValue, key) {
790
+ let result = undefined;
791
+ try {
792
+ result = readXObjParamRaw(obj, key);
793
+ } catch (err) {
794
+ switch (err.code) {
795
+ case XOBJ_TE_NSTR_ECODE : {
796
+ break;
797
+ }
798
+ default: {
799
+ throw err;
800
+ }
801
+ };
802
+ };
803
+ return readAsNumberEx(result, defValue);
804
+ };
805
+
806
+ /**
807
+ * @function readXObjParamEx
808
+ * @param {object} obj - some object
809
+ * @param {object} [opt] - options
810
+ * @param {string} [key] - some key
811
+ * @returns {string}
812
+ * @throws {TypeError} if first param is not an object
813
+ * @description Extracts a parameter from a given object
814
+ * and returns it as string.
815
+ * @todo [since `v0.2.1`] deprecate use of `opt` as `string`
816
+ */
817
+ function readXObjParamEx(obj, opt, key) {
818
+ let result = undefined;
819
+ try {
820
+ result = readXObjParamRaw(obj, key);
821
+ } catch (err) {
822
+ switch (err.code) {
823
+ case XOBJ_TE_NSTR_ECODE : {
824
+ break;
825
+ }
826
+ default: {
827
+ throw err;
828
+ }
829
+ };
830
+ };
831
+ let _opt = opt;
832
+ if (!isPlainObject(_opt)) {
833
+ _opt = {
834
+ useTrim: false,
835
+ numberToString: true,
836
+ boolToString: true,
837
+ defValue: _opt,
838
+ };
839
+ };
840
+ return readAsString(result, _opt);
841
+ };
842
+
843
+ /**
844
+ * @function readXObjParamAsIndex
845
+ * @param {object} obj - some object
846
+ * @param {string} [key] - some key
847
+ * @returns {number}
848
+ * @throws {TypeError} if first param is not an object
849
+ * @description Extracts a parameter from a given object
850
+ * and returns it as 'index' value.
851
+ */
852
+ function readXObjParamAsIndex(obj, key) {
853
+ let result = undefined;
854
+ try {
855
+ result = readXObjParamRaw(obj, key);
856
+ } catch (err) {
857
+ switch (err.code) {
858
+ case XOBJ_TE_NSTR_ECODE : {
859
+ break;
860
+ }
861
+ default: {
862
+ throw err;
863
+ }
864
+ };
865
+ };
866
+ return valueToIndex(result);
867
+ };
868
+
869
+ /**
870
+ * @function writeXObjParam
871
+ * @param {object} obj - some object
872
+ * @param {any} value - some value
873
+ * @param {string} [key] - some key
874
+ * @returns {boolean}
875
+ * @throws {TypeError} if first param is not an object
876
+ * @description Tries to convert a given value to a string
877
+ * and writes it as a parameter into a given object.
878
+ */
879
+ function writeXObjParam(obj, value, key) {
880
+ let isSucceed = false;
881
+ try {
882
+ const opt = {
883
+ useTrim: false,
884
+ numberToString: true,
885
+ boolToString: true,
886
+ defValue: '',
887
+ };
888
+ isSucceed = writeXObjParamEx(obj, value, opt, key);
889
+ } catch (err) {
890
+ throw err;
891
+ };
892
+ return isSucceed;
893
+ };
894
+
895
+ /**
896
+ * @function writeXObjParamAsBool
897
+ * @param {object} obj - some object
898
+ * @param {any} value - some value
899
+ * @param {boolean} [defValue] - default value
900
+ * @param {string} [key] - some key
901
+ * @returns {boolean}
902
+ * @throws {TypeError} if first param is not an object
903
+ * @description Tries to convert a given value to a boolean
904
+ * and writes it as a parameter into a given object.
905
+ */
906
+ function writeXObjParamAsBool(obj, value, defValue, key) {
907
+ let isSucceed = false;
908
+ if (value !== undefined || typeof defValue === 'boolean') {
909
+ const _value = readAsBoolEx(value, defValue).toString();
910
+ try {
911
+ isSucceed = writeXObjParamRaw(obj, _value, key);
912
+ } catch (err) {
913
+ switch (err.code) {
914
+ case XOBJ_TE_NSTR_ECODE : {
915
+ break;
916
+ }
917
+ default: {
918
+ throw err;
919
+ }
920
+ };
921
+ };
922
+ };
923
+ return isSucceed;
924
+ };
925
+
926
+ /**
927
+ * @function writeXObjParamAsNum
928
+ * @param {object} obj - some object
929
+ * @param {any} value - some value
930
+ * @param {number} [defValue] - default value
931
+ * @param {string} [key] - some key
932
+ * @returns {boolean}
933
+ * @throws {TypeError} if first param is not an object
934
+ * @description Tries to convert a given value to a number
935
+ * and writes it as a parameter into a given object.
936
+ */
937
+ function writeXObjParamAsNum(obj, value, defValue, key) {
938
+ let isSucceed = false;
939
+ if (value !== undefined || typeof defValue === 'number') {
940
+ const _value = readAsNumberEx(value, defValue).toString();
941
+ try {
942
+ isSucceed = writeXObjParamRaw(obj, _value, key);
943
+ } catch (err) {
944
+ switch (err.code) {
945
+ case XOBJ_TE_NSTR_ECODE : {
946
+ break;
947
+ }
948
+ default: {
949
+ throw err;
950
+ }
951
+ };
952
+ };
953
+ };
954
+ return isSucceed;
955
+ };
956
+
957
+ /**
958
+ * @function writeXObjParamAsIndex
959
+ * @param {object} obj - some object
960
+ * @param {any} value - some value
961
+ * @param {string} [key] - some key
962
+ * @returns {boolean}
963
+ * @throws {TypeError} if first param is not an object
964
+ * @description Tries to convert a given value into an 'index' value
965
+ * and writes it as a parameter into a given object.
966
+ */
967
+ function writeXObjParamAsIndex(obj, value, key) {
968
+ let isSucceed = false;
969
+ if (value !== undefined) {
970
+ const _value = valueToIndex(value).toString();
971
+ try {
972
+ isSucceed = writeXObjParamRaw(obj, _value, key);
973
+ } catch (err) {
974
+ switch (err.code) {
975
+ case XOBJ_TE_NSTR_ECODE : {
976
+ break;
977
+ }
978
+ default: {
979
+ throw err;
980
+ }
981
+ };
982
+ };
983
+ };
984
+ return isSucceed;
985
+ };
986
+
987
+ /**
988
+ * @function writeXObjParamEx
989
+ * @param {object} obj - some object
990
+ * @param {any} value - some value
991
+ * @param {object} [opt] - options
992
+ * @param {string} [key] - some key
993
+ * @returns {boolean}
994
+ * @throws {TypeError} if first param is not an object
995
+ * @description Tries to convert a given value to a string
996
+ * and writes it as a parameter into a given object.
997
+ * @todo [since `v0.2.1`] deprecate use of `opt` as `string`
998
+ */
999
+ function writeXObjParamEx(obj, value, opt, key) {
1000
+ let isSucceed = false;
1001
+ if (value !== undefined) {
1002
+ let _opt = opt;
1003
+ if (!isPlainObject(_opt)) {
1004
+ const defValue = readAsString(_opt, {
1005
+ useTrim: false,
1006
+ numberToString: true,
1007
+ boolToString: true,
1008
+ });
1009
+ _opt = {
1010
+ useTrim: false,
1011
+ numberToString: true,
1012
+ boolToString: true,
1013
+ defValue,
1014
+ };
1015
+ };
1016
+ const _value = readAsString(value, _opt);
1017
+ try {
1018
+ isSucceed = writeXObjParamRaw(obj, _value, key);
1019
+ } catch (err) {
1020
+ switch (err.code) {
1021
+ case XOBJ_TE_NSTR_ECODE : {
1022
+ break;
1023
+ }
1024
+ default: {
1025
+ throw err;
1026
+ }
1027
+ };
1028
+ };
1029
+ };
1030
+ return isSucceed;
1031
+ };
1032
+
1033
+ /**
1034
+ * @function readXObjAttr
1035
+ * @param {object} obj - some object
1036
+ * @param {string} attr - some attribute
1037
+ * @param {string} [key] - some key
1038
+ * @returns {string}
1039
+ * @throws {TypeError} if first param is not an object
1040
+ * @description Extracts an attribute from a given object
1041
+ * and returns it as string.
1042
+ */
1043
+ function readXObjAttr(obj, attr, key) {
1044
+ const opt = {
1045
+ useTrim: true,
1046
+ numberToString: true,
1047
+ boolToString: true,
1048
+ defValue: '',
1049
+ };
1050
+ let result = undefined;
1051
+ try {
1052
+ result = readXObjAttrEx(obj, attr, opt, key);
1053
+ } catch (err) {
1054
+ throw err;
1055
+ };
1056
+ return result;
1057
+ };
1058
+
1059
+ /**
1060
+ * @function readXObjAttrAsBool
1061
+ * @param {object} obj - some object
1062
+ * @param {string} attr - some attribute
1063
+ * @param {boolean} [defValue] - default value
1064
+ * @param {string} [key] - some key
1065
+ * @returns {boolean}
1066
+ * @throws {TypeError} if first param is not an object
1067
+ * @description Extracts an attribute from a given object
1068
+ * and returns it as boolean.
1069
+ */
1070
+ function readXObjAttrAsBool(obj, attr, defValue, key) {
1071
+ let result = undefined;
1072
+ try {
1073
+ result = readXObjAttrRaw(obj, attr, key);
1074
+ } catch (err) {
1075
+ switch (err.code) {
1076
+ case XOBJ_TE_NSTR_ECODE : {
1077
+ break;
1078
+ }
1079
+ default: {
1080
+ throw err;
1081
+ }
1082
+ };
1083
+ };
1084
+ return readAsBoolEx(result, defValue);
1085
+ };
1086
+
1087
+ /**
1088
+ * @function readXObjAttrAsNum
1089
+ * @param {object} obj - some object
1090
+ * @param {string} attr - some attribute
1091
+ * @param {number} [defValue] - default value
1092
+ * @param {string} [key] - some key
1093
+ * @returns {number}
1094
+ * @throws {TypeError} if first param is not an object
1095
+ * @description Extracts an attribute from a given object
1096
+ * and returns it as number.
1097
+ */
1098
+ function readXObjAttrAsNum(obj, attr, defValue, key) {
1099
+ let result = undefined;
1100
+ try {
1101
+ result = readXObjAttrRaw(obj, attr, key);
1102
+ } catch (err) {
1103
+ switch (err.code) {
1104
+ case XOBJ_TE_NSTR_ECODE : {
1105
+ break;
1106
+ }
1107
+ default: {
1108
+ throw err;
1109
+ }
1110
+ };
1111
+ };
1112
+ return readAsNumberEx(result, defValue);
1113
+ };
1114
+
1115
+ /**
1116
+ * @function readXObjAttrEx
1117
+ * @param {object} obj - some object
1118
+ * @param {string} attr - some attribute
1119
+ * @param {object} [opt] - options
1120
+ * @param {string} [key] - some key
1121
+ * @returns {string}
1122
+ * @throws {TypeError} if first param is not an object
1123
+ * @description Extracts an attribute from a given object
1124
+ * and returns it as string.
1125
+ * @todo [since `v0.2.1`] deprecate use of `opt` as `string`
1126
+ */
1127
+ function readXObjAttrEx(obj, attr, opt, key) {
1128
+ let result = undefined;
1129
+ try {
1130
+ result = readXObjAttrRaw(obj, attr, key);
1131
+ } catch (err) {
1132
+ switch (err.code) {
1133
+ case XOBJ_TE_NSTR_ECODE : {
1134
+ break;
1135
+ }
1136
+ default: {
1137
+ throw err;
1138
+ }
1139
+ };
1140
+ };
1141
+ let _opt = opt;
1142
+ if (!isPlainObject(_opt)) {
1143
+ _opt = {
1144
+ useTrim: true,
1145
+ numberToString: true,
1146
+ boolToString: true,
1147
+ defValue: _opt,
1148
+ };
1149
+ };
1150
+ return readAsString(result, _opt);
1151
+ };
1152
+
1153
+ /**
1154
+ * @function readXObjAttrAsIndex
1155
+ * @param {object} obj - some object
1156
+ * @param {string} attr - some attribute
1157
+ * @param {string} [key] - some key
1158
+ * @returns {number}
1159
+ * @throws {TypeError} if first param is not an object
1160
+ * @description Extracts an attribute from a given object
1161
+ * and returns it as 'index' value.
1162
+ */
1163
+ function readXObjAttrAsIndex(obj, attr, key) {
1164
+ let result = undefined;
1165
+ try {
1166
+ result = readXObjAttrRaw(obj, attr, key);
1167
+ } catch (err) {
1168
+ switch (err.code) {
1169
+ case XOBJ_TE_NSTR_ECODE : {
1170
+ break;
1171
+ }
1172
+ default: {
1173
+ throw err;
1174
+ }
1175
+ };
1176
+ };
1177
+ return valueToIndex(result);
1178
+ };
1179
+
1180
+ /**
1181
+ * @function writeXObjAttr
1182
+ * @param {object} obj - some object
1183
+ * @param {string} attr - some attribute
1184
+ * @param {any} value - some value
1185
+ * @param {string} [key] - some key
1186
+ * @returns {boolean}
1187
+ * @throws {TypeError} if first param is not an object
1188
+ * @description Tries to convert a given value to a string
1189
+ * and writes it as an attribute into a given object.
1190
+ */
1191
+ function writeXObjAttr(obj, attr, value, key) {
1192
+ let isSucceed = false;
1193
+ try {
1194
+ const opt = {
1195
+ useTrim: true,
1196
+ numberToString: true,
1197
+ boolToString: true,
1198
+ defValue: '',
1199
+ };
1200
+ isSucceed = writeXObjAttrEx(obj, attr, value, opt, key);
1201
+ } catch (err) {
1202
+ throw err;
1203
+ };
1204
+ return isSucceed;
1205
+ };
1206
+
1207
+ /**
1208
+ * @function writeXObjAttrAsBool
1209
+ * @param {object} obj - some object
1210
+ * @param {string} attr - some attribute
1211
+ * @param {any} value - some value
1212
+ * @param {boolean} [defValue] - default value
1213
+ * @param {string} [key] - some key
1214
+ * @returns {boolean}
1215
+ * @throws {TypeError} if first param is not an object
1216
+ * @description Tries to convert a given value to a boolean
1217
+ * and writes it as an attribute into a given object.
1218
+ */
1219
+ function writeXObjAttrAsBool(obj, attr, value, defValue, key) {
1220
+ let isSucceed = false;
1221
+ if (value !== undefined || typeof defValue === 'boolean') {
1222
+ const _value = readAsBoolEx(value, defValue).toString();
1223
+ try {
1224
+ isSucceed = writeXObjAttrRaw(obj, attr, _value, key);
1225
+ } catch (err) {
1226
+ switch (err.code) {
1227
+ case XOBJ_TE_NSTR_ECODE : {
1228
+ break;
1229
+ }
1230
+ default: {
1231
+ throw err;
1232
+ }
1233
+ };
1234
+ };
1235
+ };
1236
+ return isSucceed;
1237
+ };
1238
+
1239
+ /**
1240
+ * @function writeXObjAttrAsNum
1241
+ * @param {object} obj - some object
1242
+ * @param {string} attr - some attribute
1243
+ * @param {any} value - some value
1244
+ * @param {number} [defValue] - default value
1245
+ * @param {string} [key] - some key
1246
+ * @returns {boolean}
1247
+ * @throws {TypeError} if first param is not an object
1248
+ * @description Tries to convert a given value to a number
1249
+ * and writes it as an attribute into a given object.
1250
+ */
1251
+ function writeXObjAttrAsNum(obj, attr, value, defValue, key) {
1252
+ let isSucceed = false;
1253
+ if (value !== undefined || typeof defValue === 'number') {
1254
+ const _value = readAsNumberEx(value, defValue).toString();
1255
+ try {
1256
+ isSucceed = writeXObjAttrRaw(obj, attr, _value, key);
1257
+ } catch (err) {
1258
+ switch (err.code) {
1259
+ case XOBJ_TE_NSTR_ECODE : {
1260
+ break;
1261
+ }
1262
+ default: {
1263
+ throw err;
1264
+ }
1265
+ };
1266
+ };
1267
+ };
1268
+ return isSucceed;
1269
+ };
1270
+
1271
+ /**
1272
+ * @function writeXObjAttrAsIndex
1273
+ * @param {object} obj - some object
1274
+ * @param {string} attr - some attribute
1275
+ * @param {any} value - some value
1276
+ * @param {string} [key] - some key
1277
+ * @returns {boolean}
1278
+ * @throws {TypeError} if first param is not an object
1279
+ * @description Tries to convert a given value into an 'index' value
1280
+ * and writes it as an attribute into a given object.
1281
+ */
1282
+ function writeXObjAttrAsIndex(obj, attr, value, key) {
1283
+ let isSucceed = false;
1284
+ if (value !== undefined) {
1285
+ const _value = valueToIndex(value).toString();
1286
+ try {
1287
+ isSucceed = writeXObjAttrRaw(obj, attr, _value, key);
1288
+ } catch (err) {
1289
+ switch (err.code) {
1290
+ case XOBJ_TE_NSTR_ECODE : {
1291
+ break;
1292
+ }
1293
+ default: {
1294
+ throw err;
1295
+ }
1296
+ };
1297
+ };
1298
+ };
1299
+ return isSucceed;
1300
+ };
1301
+
1302
+ /**
1303
+ * @function writeXObjAttrEx
1304
+ * @param {object} obj - some object
1305
+ * @param {string} attr - some attribute
1306
+ * @param {any} value - some value
1307
+ * @param {object} [opt] - options
1308
+ * @param {string} [key] - some key
1309
+ * @returns {boolean}
1310
+ * @throws {TypeError} if first param is not an object
1311
+ * @description Tries to convert a given value to a string
1312
+ * and writes it as an attribute into a given object.
1313
+ * @todo [since `v0.2.1`] deprecate use of `opt` as `string`
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 {Object} OPT_inselops_S
1379
+ * @property {boolean} [force=false]
1380
+ * @property {boolean} [ripOldies=false]
1381
+ */
1382
+
1383
+ /**
1384
+ * @function insertXObjEList
1385
+ * @param {object} obj - some object
1386
+ * @param {string} name - some child element
1387
+ * @param {OPT_inselops_S} [opt] - options
1388
+ * @returns {?(object|object[])}
1389
+ * @throws {TypeError} if first param is not an object
1390
+ * @description Inserts a list elements into a given object.
1391
+ */
1392
+ function insertXObjEList(...args) {
1393
+ let item = null;
1394
+ try {
1395
+ ({ item } = insertXObjEListEx(...args));
1396
+ } catch (err) {
1397
+ switch (err.code) {
1398
+ case XOBJ_TE_NSTR_ECODE :
1399
+ case XOBJ_TE_KNES_ECODE : {
1400
+ break;
1401
+ }
1402
+ default: {
1403
+ throw err;
1404
+ }
1405
+ };
1406
+ };
1407
+ return item;
1408
+ };
1409
+
1410
+ /**
1411
+ * @function insertXObjEListEx
1412
+ * @param {object} obj - some object
1413
+ * @param {string} name - some child element
1414
+ * @param {OPT_inselops_S} [opt] - options
1415
+ * @returns {RVAL_emodif}
1416
+ * @throws {TypeError} if first param is not an object
1417
+ * @throws {TypeError} if second param is empty string or not a string at all
1418
+ * @since 0.2.0
1419
+ * @description Inserts a list elements into a given object.
1420
+ */
1421
+ function insertXObjEListEx(obj, name, opt) {
1422
+ if (!isPlainObject(obj)) {
1423
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
1424
+ err.code = XOBJ_TE_NPOBJ_ECODE;
1425
+ throw err;
1426
+ };
1427
+ let { isSucceed, value: key } = evalKeyName(name);
1428
+ if (!isSucceed) {
1429
+ const { code, msg } = key;
1430
+ const err = new TypeError(msg);
1431
+ err.code = code;
1432
+ throw err;
1433
+ };
1434
+ const _options = isPlainObject(opt) ? opt : {};
1435
+ let { force, ripOldies } = _options;
1436
+ if (typeof force !== 'boolean') force = false;
1437
+ if (typeof ripOldies !== 'boolean') ripOldies = false;
1438
+ let prop = obj[key];
1439
+ isSucceed = false;
1440
+ if (
1441
+ isNullOrUndef(prop)
1442
+ || (force && (ripOldies || !isObject(prop)))
1443
+ ) {
1444
+ obj[key] = prop = [];
1445
+ isSucceed = true;
1446
+ } else {
1447
+ if (isObject(prop)) {
1448
+ if (!isArray(prop)) prop = [ prop ];
1449
+ obj[key] = prop;
1450
+ isSucceed = true;
1451
+ };
1452
+ };
1453
+ return {
1454
+ isSucceed,
1455
+ item: isSucceed ? prop : null,
1456
+ };
1457
+ };
1458
+
1459
+ /**
1460
+ * @function insertXObjEChain
1461
+ * @param {object} obj - some object
1462
+ * @param {...string} name - some child element
1463
+ * @param {object} [opt] - options
1464
+ * @returns {?any}
1465
+ * @throws {TypeError} if first param is not an object
1466
+ * @description Inserts a chain of an elements into a given object.
1467
+ */
1468
+ function insertXObjEChain(obj, ...args) {
1469
+ if (!isPlainObject(obj)) {
1470
+ const err = new TypeError(XOBJ_TE_NPOBJ_EMSG);
1471
+ err.code = XOBJ_TE_NPOBJ_ECODE;
1472
+ throw err;
1473
+ };
1474
+ let result = null;
1475
+ let len = args.length;
1476
+ const opt = (
1477
+ len > 0 && isPlainObject(args[len - 1])
1478
+ ? (len--, args.pop())
1479
+ : {}
1480
+ );
1481
+ if (len > 0) {
1482
+ let parent = obj;
1483
+ let child = null;
1484
+ let isSucceed = false;
1485
+ for (let key of args) {
1486
+ child = insertXObjElement(parent, key, opt);
1487
+ isSucceed = isPlainObject(child);
1488
+ if (!isSucceed) break;
1489
+ parent = child;
1490
+ };
1491
+ result = isSucceed ? parent : null;
1492
+ };
1493
+ return result;
1494
+ };
1495
+
1496
+ /***
1497
+ * (* class definitions *)
1498
+ */
1499
+
1500
+ // === module exports block ===
1501
+
1502
+ module.exports.XOBJ_DEF_PARAM_TNAME = XOBJ_DEF_PARAM_TNAME;
1503
+ module.exports.XOBJ_DEF_ATTR_TNAME = XOBJ_DEF_ATTR_TNAME;
1504
+
1505
+ module.exports.readXObjParamRaw = readXObjParamRaw;
1506
+ module.exports.readXObjParam = readXObjParam;
1507
+ module.exports.readXObjParamAsBool = readXObjParamAsBool;
1508
+ module.exports.readXObjParamAsNum = readXObjParamAsNum;
1509
+ module.exports.readXObjParamEx = readXObjParamEx;
1510
+ module.exports.readXObjParamAsIndex = readXObjParamAsIndex;
1511
+ module.exports.writeXObjParamRaw = writeXObjParamRaw;
1512
+ module.exports.writeXObjParam = writeXObjParam;
1513
+ module.exports.writeXObjParamAsBool = writeXObjParamAsBool;
1514
+ module.exports.writeXObjParamAsNum = writeXObjParamAsNum;
1515
+ module.exports.writeXObjParamAsIndex = writeXObjParamAsIndex;
1516
+ module.exports.writeXObjParamEx = writeXObjParamEx;
1517
+
1518
+ module.exports.readXObjAttrRaw = readXObjAttrRaw;
1519
+ module.exports.readXObjAttr = readXObjAttr;
1520
+ module.exports.readXObjAttrAsBool = readXObjAttrAsBool;
1521
+ module.exports.readXObjAttrAsNum = readXObjAttrAsNum;
1522
+ module.exports.readXObjAttrEx = readXObjAttrEx;
1523
+ module.exports.readXObjAttrAsIndex = readXObjAttrAsIndex;
1524
+ module.exports.writeXObjAttrRaw = writeXObjAttrRaw;
1525
+ module.exports.writeXObjAttr = writeXObjAttr;
1526
+ module.exports.writeXObjAttrAsBool = writeXObjAttrAsBool;
1527
+ module.exports.writeXObjAttrAsNum = writeXObjAttrAsNum;
1528
+ module.exports.writeXObjAttrAsIndex = writeXObjAttrAsIndex;
1529
+ module.exports.writeXObjAttrEx = writeXObjAttrEx;
1530
+
1531
+ module.exports.getXObjAttributes = getXObjAttributes;
1532
+ module.exports.checkXObjAttribute = checkXObjAttribute;
1533
+ module.exports.deleteXObjAttribute = deleteXObjAttribute;
1534
+ module.exports.renameXObjAttribute = renameXObjAttribute;
1535
+
1536
+ module.exports.getXObjElement = getXObjElement;
1537
+ module.exports.addXObjElement = addXObjElement;
1538
+ module.exports.insertXObjElement = insertXObjElement;
1539
+ module.exports.insertXObjElementEx = insertXObjElementEx;
1540
+ module.exports.deleteXObjElement = deleteXObjElement;
1541
+ module.exports.deleteXObjElementEx = deleteXObjElementEx;
1542
+ module.exports.renameXObjElement = renameXObjElement;
1543
+
1544
+ module.exports.evalXObjEName = evalXObjEName;
1545
+ module.exports.insertXObjEList = insertXObjEList;
1546
+ module.exports.insertXObjEListEx = insertXObjEListEx;
1547
+
1548
+ /* inner */
1549
+ module.exports.evalKeyName = evalKeyName;
1550
+
1551
+ /* experimental */
1552
+ module.exports.genXObjENameDescr = genXObjENameDescr;
1553
+ /* experimental */
1554
+ module.exports.insertXObjElements = insertXObjElements;
1555
+ /* experimental */
1556
+ module.exports.insertXObjEChain = insertXObjEChain;
1557
+
1558
+ /** @deprecated */
1559
+ module.exports.readXObjParamAsStr = readXObjParamEx;
1560
+ /** @deprecated */
1561
+ module.exports.readXObjAttrAsStr = readXObjAttrEx;