hadron-document 8.6.1 → 8.6.3

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.
Files changed (61) hide show
  1. package/dist/document.d.ts +152 -0
  2. package/dist/document.d.ts.map +1 -1
  3. package/dist/document.js +161 -0
  4. package/dist/document.js.map +1 -1
  5. package/dist/editor/date.d.ts +36 -0
  6. package/dist/editor/date.d.ts.map +1 -1
  7. package/dist/editor/date.js +38 -0
  8. package/dist/editor/date.js.map +1 -1
  9. package/dist/editor/decimal128.d.ts +18 -0
  10. package/dist/editor/decimal128.d.ts.map +1 -1
  11. package/dist/editor/decimal128.js +18 -0
  12. package/dist/editor/decimal128.js.map +1 -1
  13. package/dist/editor/double.d.ts +25 -0
  14. package/dist/editor/double.d.ts.map +1 -1
  15. package/dist/editor/double.js +30 -1
  16. package/dist/editor/double.js.map +1 -1
  17. package/dist/editor/int32.d.ts +15 -0
  18. package/dist/editor/int32.d.ts.map +1 -1
  19. package/dist/editor/int32.js +15 -0
  20. package/dist/editor/int32.js.map +1 -1
  21. package/dist/editor/int64.d.ts +18 -0
  22. package/dist/editor/int64.d.ts.map +1 -1
  23. package/dist/editor/int64.js +18 -0
  24. package/dist/editor/int64.js.map +1 -1
  25. package/dist/editor/null.d.ts +20 -0
  26. package/dist/editor/null.d.ts.map +1 -1
  27. package/dist/editor/null.js +23 -0
  28. package/dist/editor/null.js.map +1 -1
  29. package/dist/editor/objectid.d.ts +20 -0
  30. package/dist/editor/objectid.d.ts.map +1 -1
  31. package/dist/editor/objectid.js +20 -0
  32. package/dist/editor/objectid.js.map +1 -1
  33. package/dist/editor/standard.d.ts +32 -0
  34. package/dist/editor/standard.d.ts.map +1 -1
  35. package/dist/editor/standard.js +36 -0
  36. package/dist/editor/standard.js.map +1 -1
  37. package/dist/editor/string.d.ts +8 -0
  38. package/dist/editor/string.d.ts.map +1 -1
  39. package/dist/editor/string.js +8 -0
  40. package/dist/editor/string.js.map +1 -1
  41. package/dist/editor/undefined.d.ts +20 -0
  42. package/dist/editor/undefined.d.ts.map +1 -1
  43. package/dist/editor/undefined.js +23 -0
  44. package/dist/editor/undefined.js.map +1 -1
  45. package/dist/element-events.d.ts +3 -0
  46. package/dist/element-events.d.ts.map +1 -1
  47. package/dist/element-events.js +3 -0
  48. package/dist/element-events.js.map +1 -1
  49. package/dist/element.d.ts +321 -0
  50. package/dist/element.d.ts.map +1 -1
  51. package/dist/element.js +341 -0
  52. package/dist/element.js.map +1 -1
  53. package/dist/object-generator.d.ts +96 -0
  54. package/dist/object-generator.d.ts.map +1 -1
  55. package/dist/object-generator.js +129 -0
  56. package/dist/object-generator.js.map +1 -1
  57. package/dist/utils.d.ts +22 -0
  58. package/dist/utils.d.ts.map +1 -1
  59. package/dist/utils.js +25 -0
  60. package/dist/utils.js.map +1 -1
  61. package/package.json +5 -5
package/dist/element.js CHANGED
@@ -15,11 +15,21 @@ exports.Events = element_events_1.default;
15
15
  const utils_1 = require("./utils");
16
16
  const _1 = require(".");
17
17
  exports.DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS';
18
+ /**
19
+ * Id field constant.
20
+ */
18
21
  const ID = '_id';
22
+ /**
23
+ * Is this the path to a field that is used internally by the
24
+ * MongoDB driver or server and not for user consumption?
25
+ */
19
26
  function isInternalFieldPath(path) {
20
27
  return typeof path === 'string' && /^__safeContent__($|\.)/.test(path);
21
28
  }
22
29
  exports.isInternalFieldPath = isInternalFieldPath;
30
+ /**
31
+ * Types that are not editable.
32
+ */
23
33
  const UNEDITABLE_TYPES = [
24
34
  'Binary',
25
35
  'Code',
@@ -36,9 +46,17 @@ function isValueExpandable(value) {
36
46
  return (0, lodash_1.isPlainObject)(value) || (0, lodash_1.isArray)(value);
37
47
  }
38
48
  exports.isValueExpandable = isValueExpandable;
49
+ /**
50
+ * Represents an element in a document.
51
+ */
39
52
  class Element extends eventemitter3_1.default {
53
+ /**
54
+ * Cancel any modifications to the element.
55
+ */
40
56
  cancel() {
41
57
  if (this.elements) {
58
+ // Cancel will remove elements from iterator, clone it before iterating
59
+ // otherwise we will skip items
42
60
  for (const element of Array.from(this.elements)) {
43
61
  element.cancel();
44
62
  }
@@ -47,6 +65,14 @@ class Element extends eventemitter3_1.default {
47
65
  this.revert();
48
66
  }
49
67
  }
68
+ /**
69
+ * Create the element.
70
+ *
71
+ * @param key - The key.
72
+ * @param value - The value.
73
+ * @param parent - The parent element.
74
+ * @param added - Is the element a new 'addition'?
75
+ */
50
76
  constructor(key, value, parent = null, added = false) {
51
77
  super();
52
78
  this.expanded = false;
@@ -61,10 +87,14 @@ class Element extends eventemitter3_1.default {
61
87
  this.currentType = this.type;
62
88
  this.level = this._getLevel();
63
89
  this.setValid();
90
+ // Make sure that all values that element will hold onto will be explicit
91
+ // bson types: convert JavaScript numbers to either Int32 or Double
64
92
  if (typeof value === 'number') {
65
93
  value = hadron_type_checker_1.default.cast(value, hadron_type_checker_1.default.type(value));
66
94
  }
67
95
  if (isValueExpandable(value)) {
96
+ // NB: Important to set `originalExpandableValue` first as element
97
+ // generation will depend on it
68
98
  this.originalExpandableValue = value;
69
99
  this.elements = this._generateElements(value);
70
100
  }
@@ -72,6 +102,9 @@ class Element extends eventemitter3_1.default {
72
102
  this.value = value;
73
103
  this.currentValue = value;
74
104
  }
105
+ // The AutoEncrypter marks decrypted entries in a document
106
+ // for us with a special symbol. We opt into this behavior
107
+ // in the devtools-connect package.
75
108
  let parentValue;
76
109
  if (this.parent) {
77
110
  parentValue = this.parent.isRoot()
@@ -98,6 +131,11 @@ class Element extends eventemitter3_1.default {
98
131
  }
99
132
  return level;
100
133
  }
134
+ /**
135
+ * Edit the element.
136
+ *
137
+ * @param value - The new value.
138
+ */
101
139
  edit(value) {
102
140
  this.currentType = hadron_type_checker_1.default.type(value);
103
141
  if (isValueExpandable(value) && !isValueExpandable(this.currentValue)) {
@@ -144,16 +182,40 @@ class Element extends eventemitter3_1.default {
144
182
  }
145
183
  return parent;
146
184
  }
185
+ /**
186
+ * Get an element by its key.
187
+ *
188
+ * @param key - The key name.
189
+ *
190
+ * @returns The element.
191
+ */
147
192
  get(key) {
148
193
  return this.elements?.get(key);
149
194
  }
195
+ /**
196
+ * Get an element by its index.
197
+ *
198
+ * @param i - The index.
199
+ *
200
+ * @returns The element.
201
+ */
150
202
  at(i) {
151
203
  return this.elements?.at(i);
152
204
  }
205
+ /**
206
+ * Rename the element. Update the parent's mapping if available.
207
+ *
208
+ * @param key - The new key.
209
+ */
153
210
  rename(key) {
154
211
  this.currentKey = key;
155
212
  this._bubbleUp(element_events_1.default.Edited, this);
156
213
  }
214
+ /**
215
+ * Generate the javascript object for this element.
216
+ *
217
+ * @returns The javascript object.
218
+ */
157
219
  generateObject(options) {
158
220
  if (this.currentType === 'Array') {
159
221
  return object_generator_1.default.generateArray(this.elements, options);
@@ -163,6 +225,12 @@ class Element extends eventemitter3_1.default {
163
225
  }
164
226
  return this.currentValue;
165
227
  }
228
+ /**
229
+ * Generate the javascript object representing the original values
230
+ * for this element (pre-element removal, renaming, editing).
231
+ *
232
+ * @returns The javascript object.
233
+ */
166
234
  generateOriginalObject(options) {
167
235
  if (this.type === 'Array') {
168
236
  const originalElements = this._generateElements(this.originalExpandableValue);
@@ -174,6 +242,17 @@ class Element extends eventemitter3_1.default {
174
242
  }
175
243
  return this.value;
176
244
  }
245
+ /**
246
+ * Insert an element after the provided element. If this element is an array,
247
+ * then ignore the key specified by the caller and use the correct index.
248
+ * Update the keys of the rest of the elements in the LinkedList.
249
+ *
250
+ * @param element - The element to insert after.
251
+ * @param key - The key.
252
+ * @param value - The value.
253
+ *
254
+ * @returns The new element.
255
+ */
177
256
  insertAfter(element, key, value) {
178
257
  if (!this.elements) {
179
258
  throw new Error('Cannot insert values on non-array/non-object elements');
@@ -183,6 +262,14 @@ class Element extends eventemitter3_1.default {
183
262
  this.emitVisibleElementsChanged();
184
263
  return newElement;
185
264
  }
265
+ /**
266
+ * Add a new element to this element.
267
+ *
268
+ * @param| Number} key - The element key.
269
+ * @param value - The value.
270
+ *
271
+ * @returns The new element.
272
+ */
186
273
  insertEnd(key, value) {
187
274
  if (!this.elements) {
188
275
  throw new Error('Cannot insert values on non-array/non-object elements');
@@ -192,32 +279,67 @@ class Element extends eventemitter3_1.default {
192
279
  this.emitVisibleElementsChanged();
193
280
  return newElement;
194
281
  }
282
+ /**
283
+ * Insert a placeholder element at the end of the element.
284
+ *
285
+ * @returns The placeholder element.
286
+ */
195
287
  insertPlaceholder() {
288
+ // When adding a placeholder value to an array we default to the type
289
+ // of the last value currently in the array. Otherwise empty string.
196
290
  const placeholderValue = this.currentType === 'Array' && this.elements?.lastElement
197
291
  ? (0, utils_1.getDefaultValueForType)(this.elements?.lastElement.currentType)
198
292
  : '';
199
293
  return this.insertEnd('', placeholderValue);
200
294
  }
201
295
  insertSiblingPlaceholder() {
296
+ // When adding a sibling placeholder value to an array we default the
297
+ // new values' type to the preceding element's type to hopefully make
298
+ // it so folks don't have to change the type later. Otherwise empty string.
202
299
  const placeholderValue = this.parent?.currentType === 'Array'
203
300
  ? (0, utils_1.getDefaultValueForType)(this.currentType)
204
301
  : '';
205
302
  return this.parent.insertAfter(this, '', placeholderValue);
206
303
  }
304
+ /**
305
+ * Is the element a newly added element
306
+ *
307
+ * @returns If the element is newly added.
308
+ */
207
309
  isAdded() {
208
310
  return this.added || !!this.parent?.isAdded();
209
311
  }
312
+ /**
313
+ * Is the element blank?
314
+ *
315
+ * @returns If the element is blank.
316
+ */
210
317
  isBlank() {
211
318
  return this.currentKey === '' && this.currentValue === '';
212
319
  }
320
+ /**
321
+ * Does the element have a valid value for the current type?
322
+ *
323
+ * @returns If the value is valid.
324
+ */
213
325
  isCurrentTypeValid() {
214
326
  return !!this.currentTypeValid;
215
327
  }
328
+ /**
329
+ * Set the element as valid.
330
+ */
216
331
  setValid() {
217
332
  this.currentTypeValid = true;
218
333
  this.invalidTypeMessage = undefined;
219
334
  this._bubbleUp(element_events_1.default.Valid, this);
220
335
  }
336
+ /**
337
+ * Set the element as invalid.
338
+ *
339
+ * @param value - The value.
340
+ * @param newType - The new type.
341
+ * @param message - The error message.
342
+ */
221
343
  setInvalid(value, newType, message) {
222
344
  this.currentValue = value;
223
345
  this.currentType = newType;
@@ -225,6 +347,13 @@ class Element extends eventemitter3_1.default {
225
347
  this.invalidTypeMessage = message;
226
348
  this._bubbleUp(element_events_1.default.Invalid, this);
227
349
  }
350
+ /**
351
+ * Determine if the key is a duplicate.
352
+ *
353
+ * @param value - The value to check.
354
+ *
355
+ * @returns If the key is a duplicate.
356
+ */
228
357
  isDuplicateKey(value) {
229
358
  if (value === '') {
230
359
  return false;
@@ -236,12 +365,24 @@ class Element extends eventemitter3_1.default {
236
365
  }
237
366
  return false;
238
367
  }
368
+ /**
369
+ * Determine if the element is edited - returns true if
370
+ * the key or value changed. Does not count array values whose keys have
371
+ * changed as edited.
372
+ *
373
+ * @returns If the element is edited.
374
+ */
239
375
  isEdited() {
240
376
  return ((this.isRenamed() ||
241
377
  !this._valuesEqual() ||
242
378
  this.type !== this.currentType) &&
243
379
  !this.isAdded());
244
380
  }
381
+ /**
382
+ * Check for value equality.
383
+
384
+ * @returns If the value is equal.
385
+ */
245
386
  _valuesEqual() {
246
387
  if (this.currentType === 'Date' && (0, lodash_1.isString)(this.currentValue)) {
247
388
  return (0, lodash_1.isEqual)(this.value, new Date(this.currentValue));
@@ -262,9 +403,19 @@ class Element extends eventemitter3_1.default {
262
403
  _isExpandable() {
263
404
  return this.currentType === 'Array' || this.currentType === 'Object';
264
405
  }
406
+ /**
407
+ * Is the element the last in the elements.
408
+ *
409
+ * @returns If the element is last.
410
+ */
265
411
  isLast() {
266
412
  return this.parent?.elements?.lastElement === this;
267
413
  }
414
+ /**
415
+ * Determine if the element was explicitly renamed by the user.
416
+ *
417
+ * @returns If the element was explicitly renamed by the user.
418
+ */
268
419
  isRenamed() {
269
420
  if (!this.parent ||
270
421
  this.parent.isRoot() ||
@@ -273,22 +424,77 @@ class Element extends eventemitter3_1.default {
273
424
  }
274
425
  return false;
275
426
  }
427
+ /**
428
+ * Determine if the element was renamed, potentially as part
429
+ * of moving array elements.
430
+ *
431
+ * @returns If the element was renamed, explicitly or implicitly.
432
+ */
276
433
  hasChangedKey() {
277
434
  return this.key !== this.currentKey;
278
435
  }
436
+ /**
437
+ * Can changes to the element be reverted?
438
+ *
439
+ * @returns If the element can be reverted.
440
+ */
279
441
  isRevertable() {
280
442
  return this.isEdited() || this.isRemoved();
281
443
  }
444
+ /**
445
+ * Can the element be removed?
446
+ *
447
+ * @returns If the element can be removed.
448
+ */
282
449
  isRemovable() {
283
450
  return !this.parent.isRemoved();
284
451
  }
452
+ /**
453
+ * Can no action be taken on the element
454
+ *
455
+ * @returns If no action can be taken.
456
+ */
285
457
  isNotActionable() {
286
458
  return (((this.key === ID || this.isInternalField()) && !this.isAdded()) ||
287
459
  !this.isRemovable());
288
460
  }
461
+ /**
462
+ * Determine if the value has been decrypted via CSFLE.
463
+ *
464
+ * Warning: This does *not* apply to the children of decrypted elements!
465
+ * This only returns true for the exact field that was decrypted.
466
+ *
467
+ * a: Object
468
+ * \-- b: Object <- decrypted
469
+ * \-- c: number
470
+ *
471
+ * a.isValueDecrypted() === false
472
+ * a.get('b')?.isValueDecrypted() === true
473
+ * a.get('b')?.get('c')?.isValueDecrypted() === true
474
+ *
475
+ * @returns If the value was encrypted on the server and is now decrypted.
476
+ */
289
477
  isValueDecrypted() {
290
478
  return this.decrypted;
291
479
  }
480
+ /**
481
+ * Detemine if this value or any of its children were marked
482
+ * as having been decrypted with CSFLE.
483
+ *
484
+ * Warning: This does *not* apply to the children of decrypted elements!
485
+ * This only returns true for the exact field that was decrypted
486
+ * and its parents.
487
+ *
488
+ * a: Object
489
+ * \-- b: Object <- decrypted
490
+ * \-- c: number
491
+ *
492
+ * a.containsDecryptedChildren() === true
493
+ * a.get('b')?.containsDecryptedChildren() === true
494
+ * a.get('b')?.get('c')?.containsDecryptedChildren() === false
495
+ *
496
+ * @returns If any child of this element has been decrypted directly.
497
+ */
292
498
  containsDecryptedChildren() {
293
499
  if (this.isValueDecrypted()) {
294
500
  return true;
@@ -300,10 +506,20 @@ class Element extends eventemitter3_1.default {
300
506
  }
301
507
  return false;
302
508
  }
509
+ /**
510
+ * Determine if the value is editable.
511
+ *
512
+ * @returns If the value is editable.
513
+ */
303
514
  isValueEditable() {
304
515
  return (this._isKeyLegallyEditable() &&
305
516
  !UNEDITABLE_TYPES.includes(this.currentType));
306
517
  }
518
+ /**
519
+ * Determine if the key of the parent element is editable.
520
+ *
521
+ * @returns If the parent's key is editable.
522
+ */
307
523
  isParentEditable() {
308
524
  if (this.parent && !this.parent.isRoot()) {
309
525
  return this.parent._isKeyLegallyEditable();
@@ -316,9 +532,20 @@ class Element extends eventemitter3_1.default {
316
532
  ((this.currentKey !== ID || !this.parent?.isRoot()) &&
317
533
  !this.isInternalField())));
318
534
  }
535
+ /**
536
+ * Determine if the key is editable.
537
+ *
538
+ * @returns If the key is editable.
539
+ */
319
540
  isKeyEditable() {
320
541
  return this._isKeyLegallyEditable() && !this.containsDecryptedChildren();
321
542
  }
543
+ /**
544
+ * Is this a field that is used internally by the MongoDB driver or server
545
+ * and not for user consumption?
546
+ *
547
+ * @returns
548
+ */
322
549
  isInternalField() {
323
550
  if (!this.parent) {
324
551
  return false;
@@ -331,6 +558,11 @@ class Element extends eventemitter3_1.default {
331
558
  }
332
559
  return false;
333
560
  }
561
+ /**
562
+ * Determine if the element is modified at all.
563
+ *
564
+ * @returns If the element is modified.
565
+ */
334
566
  isModified() {
335
567
  if (this.elements) {
336
568
  for (const element of this.elements) {
@@ -341,9 +573,19 @@ class Element extends eventemitter3_1.default {
341
573
  }
342
574
  return this.isAdded() || this.isEdited() || this.isRemoved();
343
575
  }
576
+ /**
577
+ * Is the element flagged for removal?
578
+ *
579
+ * @returns If the element is flagged for removal.
580
+ */
344
581
  isRemoved() {
345
582
  return this.removed;
346
583
  }
584
+ /**
585
+ * Are any immediate children of this element flagged for removal?
586
+ *
587
+ * @returns If any immediate children of this element are flagged for removal.
588
+ */
347
589
  hasAnyRemovedChild() {
348
590
  if (this.elements) {
349
591
  for (const element of this.elements) {
@@ -354,9 +596,17 @@ class Element extends eventemitter3_1.default {
354
596
  }
355
597
  return false;
356
598
  }
599
+ /**
600
+ * Elements themselves are not the root.
601
+ *
602
+ * @returns Always false.
603
+ */
357
604
  isRoot() {
358
605
  return false;
359
606
  }
607
+ /**
608
+ * Flag the element for removal.
609
+ */
360
610
  remove() {
361
611
  this.revert();
362
612
  this.removed = true;
@@ -365,6 +615,9 @@ class Element extends eventemitter3_1.default {
365
615
  this.emitVisibleElementsChanged(this.parent);
366
616
  }
367
617
  }
618
+ /**
619
+ * Revert the changes to the element.
620
+ */
368
621
  revert() {
369
622
  if (this.isAdded()) {
370
623
  this.parent?.elements?.remove(this);
@@ -395,6 +648,11 @@ class Element extends eventemitter3_1.default {
395
648
  this.setValid();
396
649
  this._bubbleUp(element_events_1.default.Reverted, this);
397
650
  }
651
+ /**
652
+ * Expands the target element and optionally its children as well.
653
+ * Document.expand is when we would want to expand the children otherwise we
654
+ * will most expand the element itself.
655
+ */
398
656
  expand(expandChildren = false) {
399
657
  if (!this._isExpandable()) {
400
658
  return;
@@ -408,6 +666,9 @@ class Element extends eventemitter3_1.default {
408
666
  this.emit(_1.ElementEvents.Expanded, this);
409
667
  this.emitVisibleElementsChanged();
410
668
  }
669
+ /**
670
+ * Collapses only the target element
671
+ */
411
672
  collapse() {
412
673
  if (!this._isExpandable()) {
413
674
  return;
@@ -421,6 +682,12 @@ class Element extends eventemitter3_1.default {
421
682
  this.emit(_1.ElementEvents.Collapsed, this);
422
683
  this.emitVisibleElementsChanged();
423
684
  }
685
+ /**
686
+ * Fire and bubble up the event.
687
+ *
688
+ * @param evt - The event.
689
+ * @paramdata - Optional.
690
+ */
424
691
  _bubbleUp(evt, ...data) {
425
692
  this.emit(evt, ...data);
426
693
  const element = this.parent;
@@ -433,20 +700,43 @@ class Element extends eventemitter3_1.default {
433
700
  }
434
701
  }
435
702
  }
703
+ /**
704
+ * Convert this element to an empty object.
705
+ */
436
706
  _convertToEmptyObject() {
437
707
  this.edit({});
438
708
  this.insertPlaceholder();
439
709
  }
710
+ /**
711
+ * Convert to an empty array.
712
+ */
440
713
  _convertToEmptyArray() {
441
714
  this.edit([]);
442
715
  this.insertPlaceholder();
443
716
  }
717
+ /**
718
+ * Is the element empty?
719
+ *
720
+ * @param element - The element to check.
721
+ *
722
+ * @returns If the element is empty.
723
+ */
444
724
  _isElementEmpty(element) {
445
725
  return !!element && element.isAdded() && element.isBlank();
446
726
  }
727
+ /**
728
+ * Generates a sequence of child elements.
729
+ *
730
+ * @param object - The object to generate from.
731
+ *
732
+ * @returns The elements.
733
+ */
447
734
  _generateElements(object) {
448
735
  return new ElementList(this, object);
449
736
  }
737
+ /**
738
+ * Removes the added elements from the element.
739
+ */
450
740
  _removeAddedElements() {
451
741
  if (this.elements) {
452
742
  for (const element of this.elements) {
@@ -485,11 +775,17 @@ class Element extends eventemitter3_1.default {
485
775
  targetElement._bubbleUp(element_events_1.default.VisibleElementsChanged, targetElement, targetElement.getRoot());
486
776
  }
487
777
  }
778
+ /**
779
+ * @deprecated Use ElementEvents import instead
780
+ */
488
781
  static get Events() {
489
782
  return _1.ElementEvents;
490
783
  }
491
784
  }
492
785
  exports.Element = Element;
786
+ /**
787
+ * Represents a doubly linked list.
788
+ */
493
789
  class ElementList {
494
790
  constructor(parent, originalDoc) {
495
791
  this.parent = parent;
@@ -523,6 +819,16 @@ class ElementList {
523
819
  get lastElement() {
524
820
  return this.elements[this.elements.length - 1];
525
821
  }
822
+ /**
823
+ * Insert data after the provided element.
824
+ *
825
+ * @param afterElement - The element to insert after.
826
+ * @param key - The element key.
827
+ * @param value - The element value.
828
+ * @param added - If the element is new.
829
+ *
830
+ * @returns The inserted element.
831
+ */
526
832
  insertAfter(afterElement, key, value, added = true) {
527
833
  let newElement;
528
834
  let newElementIdx = -1;
@@ -541,6 +847,16 @@ class ElementList {
541
847
  }
542
848
  return newElement;
543
849
  }
850
+ /**
851
+ * Insert data before the provided element.
852
+ *
853
+ * @param beforeElement - The element to insert before.
854
+ * @param key - The element key.
855
+ * @param value - The element value.
856
+ * @param added - If the element is new.
857
+ *
858
+ * @returns The inserted element.
859
+ */
544
860
  insertBefore(beforeElement, key, value, added = true) {
545
861
  let newElement;
546
862
  let newElementIdx = -1;
@@ -558,6 +874,15 @@ class ElementList {
558
874
  }
559
875
  return newElement;
560
876
  }
877
+ /**
878
+ * Insert data at the beginning of the list.
879
+ *
880
+ * @param key - The element key.
881
+ * @param value - The element value.
882
+ * @param added - If the element is new.
883
+ *
884
+ * @returns The data element.
885
+ */
561
886
  insertBeginning(key, value, added = true) {
562
887
  const newElement = new Element(this.isArray() ? 0 : key, value, this.parent, added);
563
888
  if (this.isArray()) {
@@ -568,11 +893,27 @@ class ElementList {
568
893
  this.elements.unshift(newElement);
569
894
  return newElement;
570
895
  }
896
+ /**
897
+ * Insert data at the end of the list.
898
+ *
899
+ * @param key - The element key.
900
+ * @param value - The element value.
901
+ * @param added - If the element is new.
902
+ *
903
+ * @returns The data element.
904
+ */
571
905
  insertEnd(key, value, added = true) {
572
906
  const newElement = new Element(this.isArray() ? this.elements.length : key, value, this.parent, added);
573
907
  this.elements.push(newElement);
574
908
  return newElement;
575
909
  }
910
+ /**
911
+ * Remove the element from the list.
912
+ *
913
+ * @param removeElement - The element to remove.
914
+ *
915
+ * @returns The list with the element removed.
916
+ */
576
917
  remove(removeElement) {
577
918
  let removeIdx = -1;
578
919
  for (const [idx, el] of this.elements.entries()) {