hadron-document 8.6.2 → 8.6.4
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/dist/document.d.ts +152 -0
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +161 -0
- package/dist/document.js.map +1 -1
- package/dist/editor/date.d.ts +36 -0
- package/dist/editor/date.d.ts.map +1 -1
- package/dist/editor/date.js +38 -0
- package/dist/editor/date.js.map +1 -1
- package/dist/editor/decimal128.d.ts +18 -0
- package/dist/editor/decimal128.d.ts.map +1 -1
- package/dist/editor/decimal128.js +18 -0
- package/dist/editor/decimal128.js.map +1 -1
- package/dist/editor/double.d.ts +25 -0
- package/dist/editor/double.d.ts.map +1 -1
- package/dist/editor/double.js +30 -1
- package/dist/editor/double.js.map +1 -1
- package/dist/editor/int32.d.ts +15 -0
- package/dist/editor/int32.d.ts.map +1 -1
- package/dist/editor/int32.js +15 -0
- package/dist/editor/int32.js.map +1 -1
- package/dist/editor/int64.d.ts +18 -0
- package/dist/editor/int64.d.ts.map +1 -1
- package/dist/editor/int64.js +18 -0
- package/dist/editor/int64.js.map +1 -1
- package/dist/editor/null.d.ts +20 -0
- package/dist/editor/null.d.ts.map +1 -1
- package/dist/editor/null.js +23 -0
- package/dist/editor/null.js.map +1 -1
- package/dist/editor/objectid.d.ts +20 -0
- package/dist/editor/objectid.d.ts.map +1 -1
- package/dist/editor/objectid.js +20 -0
- package/dist/editor/objectid.js.map +1 -1
- package/dist/editor/standard.d.ts +32 -0
- package/dist/editor/standard.d.ts.map +1 -1
- package/dist/editor/standard.js +36 -0
- package/dist/editor/standard.js.map +1 -1
- package/dist/editor/string.d.ts +8 -0
- package/dist/editor/string.d.ts.map +1 -1
- package/dist/editor/string.js +8 -0
- package/dist/editor/string.js.map +1 -1
- package/dist/editor/undefined.d.ts +20 -0
- package/dist/editor/undefined.d.ts.map +1 -1
- package/dist/editor/undefined.js +23 -0
- package/dist/editor/undefined.js.map +1 -1
- package/dist/element-events.d.ts +3 -0
- package/dist/element-events.d.ts.map +1 -1
- package/dist/element-events.js +3 -0
- package/dist/element-events.js.map +1 -1
- package/dist/element.d.ts +321 -0
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +341 -0
- package/dist/element.js.map +1 -1
- package/dist/object-generator.d.ts +96 -0
- package/dist/object-generator.d.ts.map +1 -1
- package/dist/object-generator.js +129 -0
- package/dist/object-generator.js.map +1 -1
- package/dist/utils.d.ts +22 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +25 -0
- package/dist/utils.js.map +1 -1
- package/package.json +7 -7
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()) {
|