@speclynx/apidom-datamodel 1.12.2 → 2.0.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +2 -2
  4. package/README.md +151 -19
  5. package/dist/apidom-datamodel.browser.js +1141 -167
  6. package/dist/apidom-datamodel.browser.min.js +1 -1
  7. package/package.json +6 -3
  8. package/src/KeyValuePair.cjs +0 -7
  9. package/src/KeyValuePair.mjs +0 -7
  10. package/src/Namespace.cjs +1 -1
  11. package/src/Namespace.mjs +1 -1
  12. package/src/ObjectSlice.cjs +0 -7
  13. package/src/ObjectSlice.mjs +0 -7
  14. package/src/clone/errors/CloneError.cjs +22 -0
  15. package/src/clone/errors/CloneError.mjs +19 -0
  16. package/src/clone/errors/DeepCloneError.cjs +11 -0
  17. package/src/clone/errors/DeepCloneError.mjs +6 -0
  18. package/src/clone/errors/ShallowCloneError.cjs +11 -0
  19. package/src/clone/errors/ShallowCloneError.mjs +6 -0
  20. package/src/clone/index.cjs +184 -0
  21. package/src/clone/index.mjs +174 -0
  22. package/src/elements/Annotation.cjs +35 -0
  23. package/src/elements/Annotation.mjs +30 -0
  24. package/src/elements/Comment.cjs +18 -0
  25. package/src/elements/Comment.mjs +13 -0
  26. package/src/elements/LinkElement.cjs +8 -2
  27. package/src/elements/LinkElement.mjs +8 -2
  28. package/src/elements/ParseResult.cjs +91 -0
  29. package/src/elements/ParseResult.mjs +86 -0
  30. package/src/elements/RefElement.cjs +4 -1
  31. package/src/elements/RefElement.mjs +4 -1
  32. package/src/elements/SourceMap.cjs +140 -0
  33. package/src/elements/SourceMap.mjs +134 -0
  34. package/src/index.cjs +31 -2
  35. package/src/index.mjs +7 -3
  36. package/src/predicates/elements.cjs +46 -0
  37. package/src/predicates/elements.mjs +35 -0
  38. package/src/predicates/index.cjs +68 -0
  39. package/src/predicates/index.mjs +48 -0
  40. package/src/predicates/primitives.cjs +69 -0
  41. package/src/predicates/primitives.mjs +56 -0
  42. package/src/primitives/ArrayElement.cjs +0 -21
  43. package/src/primitives/ArrayElement.mjs +0 -21
  44. package/src/primitives/CollectionElement.cjs +5 -19
  45. package/src/primitives/CollectionElement.mjs +5 -19
  46. package/src/primitives/Element.cjs +110 -60
  47. package/src/primitives/Element.mjs +110 -60
  48. package/src/primitives/MemberElement.cjs +6 -2
  49. package/src/primitives/MemberElement.mjs +6 -2
  50. package/src/primitives/ObjectElement.cjs +0 -2
  51. package/src/primitives/ObjectElement.mjs +0 -2
  52. package/src/registration.cjs +8 -0
  53. package/src/registration.mjs +5 -1
  54. package/src/serialisers/JSONSerialiser.cjs +35 -4
  55. package/src/serialisers/JSONSerialiser.mjs +34 -8
  56. package/types/apidom-datamodel.d.ts +347 -51
@@ -23,6 +23,60 @@ var _ObjectSlice = _interopRequireDefault(require("../ObjectSlice.cjs"));
23
23
  * @public
24
24
  */
25
25
  class Element {
26
+ // ============================================================
27
+ // Public Properties
28
+ // ============================================================
29
+
30
+ /**
31
+ * Parent element reference (set when tree is frozen).
32
+ */
33
+ parent;
34
+
35
+ // ============================================================================
36
+ // Source Position (LSP-compatible, TextDocument-compatible, UTF-16 code units)
37
+ // web-tree-sitter automatically provides position data in UTF-16 code units.
38
+ // ============================================================================
39
+
40
+ /**
41
+ * Starting line number (0-based).
42
+ * Compatible with LSP Position.line.
43
+ */
44
+ startLine;
45
+
46
+ /**
47
+ * Starting character offset within the line (0-based, UTF-16 code units).
48
+ * Compatible with LSP Position.character.
49
+ */
50
+ startCharacter;
51
+
52
+ /**
53
+ * Starting offset from beginning of document (UTF-16 code units).
54
+ * Can be used directly as JavaScript string index.
55
+ */
56
+ startOffset;
57
+
58
+ /**
59
+ * Ending line number (0-based).
60
+ * Compatible with LSP Position.line.
61
+ */
62
+ endLine;
63
+
64
+ /**
65
+ * Ending character offset within the line (0-based, UTF-16 code units).
66
+ * Compatible with LSP Position.character.
67
+ */
68
+ endCharacter;
69
+
70
+ /**
71
+ * Ending offset from beginning of document (UTF-16 code units).
72
+ * Can be used directly as JavaScript string index.
73
+ */
74
+ endOffset;
75
+
76
+ // ============================================================
77
+ // Protected Properties
78
+ // ============================================================
79
+
26
80
  /**
27
81
  * The element type identifier.
28
82
  * @internal
@@ -47,11 +101,6 @@ class Element {
47
101
  */
48
102
  _attributes;
49
103
 
50
- /**
51
- * Parent element reference (set when tree is frozen).
52
- */
53
- parent;
54
-
55
104
  // ============================================================
56
105
  // Prototype-assigned properties (set in elements.ts)
57
106
  // Using 'declare' allows TypeScript to know about these
@@ -205,22 +254,6 @@ class Element {
205
254
  this.setMetaProperty('classes', value);
206
255
  }
207
256
 
208
- /** Human-readable title. */
209
- get title() {
210
- return this.getMetaProperty('title', '');
211
- }
212
- set title(value) {
213
- this.setMetaProperty('title', value);
214
- }
215
-
216
- /** Human-readable description. */
217
- get description() {
218
- return this.getMetaProperty('description', '');
219
- }
220
- set description(value) {
221
- this.setMetaProperty('description', value);
222
- }
223
-
224
257
  /** Hyperlinks associated with this element. */
225
258
  get links() {
226
259
  return this.getMetaProperty('links', []);
@@ -292,41 +325,6 @@ class Element {
292
325
  Object.freeze(this);
293
326
  }
294
327
 
295
- // ============================================================
296
- // Cloneable Implementation
297
- // ============================================================
298
-
299
- /**
300
- * Creates a deep clone of this element.
301
- */
302
- clone() {
303
- const Ctor = this.constructor;
304
- const copy = new Ctor();
305
- copy.element = this.element;
306
- if (this._meta) {
307
- copy._meta = this._meta.clone();
308
- }
309
- if (this._attributes) {
310
- copy._attributes = this._attributes.clone();
311
- }
312
-
313
- // Clone content based on its type
314
- const {
315
- _content
316
- } = this;
317
- if (_content instanceof Element) {
318
- copy._content = _content.clone();
319
- } else if (_content instanceof _KeyValuePair.default) {
320
- copy._content = _content.clone();
321
- } else if (Array.isArray(_content)) {
322
- copy._content = _content.map(el => el.clone());
323
- } else {
324
- // Primitives are immutable, assign as-is
325
- copy._content = _content;
326
- }
327
- return copy;
328
- }
329
-
330
328
  // ============================================================
331
329
  // ToValue Implementation
332
330
  // ============================================================
@@ -407,10 +405,6 @@ class Element {
407
405
  return ref;
408
406
  }
409
407
 
410
- // ============================================================
411
- // Protected Helpers
412
- // ============================================================
413
-
414
408
  /**
415
409
  * Gets a meta property, creating it with default value if not present.
416
410
  */
@@ -432,6 +426,62 @@ class Element {
432
426
  setMetaProperty(name, value) {
433
427
  this.meta.set(name, value);
434
428
  }
429
+
430
+ /**
431
+ * Has meta property.
432
+ */
433
+ hasMetaProperty(name) {
434
+ if (!this.isMetaEmpty) {
435
+ return this.meta.hasKey(name);
436
+ }
437
+ return false;
438
+ }
439
+
440
+ /**
441
+ * Checks if meta is empty.
442
+ */
443
+ get isMetaEmpty() {
444
+ return this._meta === undefined || this.meta.isEmpty;
445
+ }
446
+
447
+ /**
448
+ * Gets an attribute property, creating it with default value if not present.
449
+ */
450
+ getAttributesProperty(name, defaultValue) {
451
+ if (!this.hasAttributesProperty(name)) {
452
+ if (this.isFrozen) {
453
+ const element = this.refract(defaultValue);
454
+ element.freeze();
455
+ return element;
456
+ }
457
+ this.attributes.set(name, defaultValue);
458
+ }
459
+ return this.attributes.get(name);
460
+ }
461
+
462
+ /**
463
+ * Sets an attributes property.
464
+ */
465
+ setAttributesProperty(name, value) {
466
+ this.attributes.set(name, value);
467
+ }
468
+
469
+ /**
470
+ * Has attributes property.
471
+ */
472
+ hasAttributesProperty(name) {
473
+ if (!this.isAttributesEmpty) {
474
+ return this.attributes.hasKey(name);
475
+ }
476
+ return false;
477
+ }
478
+
479
+ /**
480
+ * Checks if attributes is empty.
481
+ */
482
+ get isAttributesEmpty() {
483
+ return this._attributes === undefined || this.attributes.isEmpty;
484
+ }
435
485
  }
436
486
 
437
487
  // Re-export types for convenience
@@ -17,6 +17,60 @@ import ObjectSlice from "../ObjectSlice.mjs";
17
17
  * @public
18
18
  */
19
19
  class Element {
20
+ // ============================================================
21
+ // Public Properties
22
+ // ============================================================
23
+
24
+ /**
25
+ * Parent element reference (set when tree is frozen).
26
+ */
27
+ parent;
28
+
29
+ // ============================================================================
30
+ // Source Position (LSP-compatible, TextDocument-compatible, UTF-16 code units)
31
+ // web-tree-sitter automatically provides position data in UTF-16 code units.
32
+ // ============================================================================
33
+
34
+ /**
35
+ * Starting line number (0-based).
36
+ * Compatible with LSP Position.line.
37
+ */
38
+ startLine;
39
+
40
+ /**
41
+ * Starting character offset within the line (0-based, UTF-16 code units).
42
+ * Compatible with LSP Position.character.
43
+ */
44
+ startCharacter;
45
+
46
+ /**
47
+ * Starting offset from beginning of document (UTF-16 code units).
48
+ * Can be used directly as JavaScript string index.
49
+ */
50
+ startOffset;
51
+
52
+ /**
53
+ * Ending line number (0-based).
54
+ * Compatible with LSP Position.line.
55
+ */
56
+ endLine;
57
+
58
+ /**
59
+ * Ending character offset within the line (0-based, UTF-16 code units).
60
+ * Compatible with LSP Position.character.
61
+ */
62
+ endCharacter;
63
+
64
+ /**
65
+ * Ending offset from beginning of document (UTF-16 code units).
66
+ * Can be used directly as JavaScript string index.
67
+ */
68
+ endOffset;
69
+
70
+ // ============================================================
71
+ // Protected Properties
72
+ // ============================================================
73
+
20
74
  /**
21
75
  * The element type identifier.
22
76
  * @internal
@@ -41,11 +95,6 @@ class Element {
41
95
  */
42
96
  _attributes;
43
97
 
44
- /**
45
- * Parent element reference (set when tree is frozen).
46
- */
47
- parent;
48
-
49
98
  // ============================================================
50
99
  // Prototype-assigned properties (set in elements.ts)
51
100
  // Using 'declare' allows TypeScript to know about these
@@ -199,22 +248,6 @@ class Element {
199
248
  this.setMetaProperty('classes', value);
200
249
  }
201
250
 
202
- /** Human-readable title. */
203
- get title() {
204
- return this.getMetaProperty('title', '');
205
- }
206
- set title(value) {
207
- this.setMetaProperty('title', value);
208
- }
209
-
210
- /** Human-readable description. */
211
- get description() {
212
- return this.getMetaProperty('description', '');
213
- }
214
- set description(value) {
215
- this.setMetaProperty('description', value);
216
- }
217
-
218
251
  /** Hyperlinks associated with this element. */
219
252
  get links() {
220
253
  return this.getMetaProperty('links', []);
@@ -286,41 +319,6 @@ class Element {
286
319
  Object.freeze(this);
287
320
  }
288
321
 
289
- // ============================================================
290
- // Cloneable Implementation
291
- // ============================================================
292
-
293
- /**
294
- * Creates a deep clone of this element.
295
- */
296
- clone() {
297
- const Ctor = this.constructor;
298
- const copy = new Ctor();
299
- copy.element = this.element;
300
- if (this._meta) {
301
- copy._meta = this._meta.clone();
302
- }
303
- if (this._attributes) {
304
- copy._attributes = this._attributes.clone();
305
- }
306
-
307
- // Clone content based on its type
308
- const {
309
- _content
310
- } = this;
311
- if (_content instanceof Element) {
312
- copy._content = _content.clone();
313
- } else if (_content instanceof KeyValuePair) {
314
- copy._content = _content.clone();
315
- } else if (Array.isArray(_content)) {
316
- copy._content = _content.map(el => el.clone());
317
- } else {
318
- // Primitives are immutable, assign as-is
319
- copy._content = _content;
320
- }
321
- return copy;
322
- }
323
-
324
322
  // ============================================================
325
323
  // ToValue Implementation
326
324
  // ============================================================
@@ -401,10 +399,6 @@ class Element {
401
399
  return ref;
402
400
  }
403
401
 
404
- // ============================================================
405
- // Protected Helpers
406
- // ============================================================
407
-
408
402
  /**
409
403
  * Gets a meta property, creating it with default value if not present.
410
404
  */
@@ -426,6 +420,62 @@ class Element {
426
420
  setMetaProperty(name, value) {
427
421
  this.meta.set(name, value);
428
422
  }
423
+
424
+ /**
425
+ * Has meta property.
426
+ */
427
+ hasMetaProperty(name) {
428
+ if (!this.isMetaEmpty) {
429
+ return this.meta.hasKey(name);
430
+ }
431
+ return false;
432
+ }
433
+
434
+ /**
435
+ * Checks if meta is empty.
436
+ */
437
+ get isMetaEmpty() {
438
+ return this._meta === undefined || this.meta.isEmpty;
439
+ }
440
+
441
+ /**
442
+ * Gets an attribute property, creating it with default value if not present.
443
+ */
444
+ getAttributesProperty(name, defaultValue) {
445
+ if (!this.hasAttributesProperty(name)) {
446
+ if (this.isFrozen) {
447
+ const element = this.refract(defaultValue);
448
+ element.freeze();
449
+ return element;
450
+ }
451
+ this.attributes.set(name, defaultValue);
452
+ }
453
+ return this.attributes.get(name);
454
+ }
455
+
456
+ /**
457
+ * Sets an attributes property.
458
+ */
459
+ setAttributesProperty(name, value) {
460
+ this.attributes.set(name, value);
461
+ }
462
+
463
+ /**
464
+ * Has attributes property.
465
+ */
466
+ hasAttributesProperty(name) {
467
+ if (!this.isAttributesEmpty) {
468
+ return this.attributes.hasKey(name);
469
+ }
470
+ return false;
471
+ }
472
+
473
+ /**
474
+ * Checks if attributes is empty.
475
+ */
476
+ get isAttributesEmpty() {
477
+ return this._attributes === undefined || this.attributes.isEmpty;
478
+ }
429
479
  }
430
480
 
431
481
  // Re-export types for convenience
@@ -23,7 +23,11 @@ class MemberElement extends _Element.default {
23
23
  if (key !== undefined) {
24
24
  this.key = key;
25
25
  }
26
- if (value !== undefined) {
26
+
27
+ // Note: We check arguments.length to distinguish between:
28
+ // - new MemberElement('key') - value not provided, don't set
29
+ // - new MemberElement('key', undefined) - value explicitly undefined, set it
30
+ if (arguments.length >= 2) {
27
31
  this.value = value;
28
32
  }
29
33
  }
@@ -48,7 +52,7 @@ class MemberElement extends _Element.default {
48
52
  return this._content.value;
49
53
  }
50
54
  set value(value) {
51
- this._content.value = this.refract(value);
55
+ this._content.value = value === undefined ? undefined : this.refract(value);
52
56
  }
53
57
  }
54
58
  var _default = exports.default = MemberElement;
@@ -18,7 +18,11 @@ class MemberElement extends Element {
18
18
  if (key !== undefined) {
19
19
  this.key = key;
20
20
  }
21
- if (value !== undefined) {
21
+
22
+ // Note: We check arguments.length to distinguish between:
23
+ // - new MemberElement('key') - value not provided, don't set
24
+ // - new MemberElement('key', undefined) - value explicitly undefined, set it
25
+ if (arguments.length >= 2) {
22
26
  this.value = value;
23
27
  }
24
28
  }
@@ -43,7 +47,7 @@ class MemberElement extends Element {
43
47
  return this._content.value;
44
48
  }
45
49
  set value(value) {
46
- this._content.value = this.refract(value);
50
+ this._content.value = value === undefined ? undefined : this.refract(value);
47
51
  }
48
52
  }
49
53
  export default MemberElement;
@@ -210,8 +210,6 @@ class ObjectElement extends _CollectionElement.default {
210
210
  return memo;
211
211
  }
212
212
 
213
- // Fantasy Land
214
-
215
213
  /**
216
214
  * Returns an empty object element.
217
215
  */
@@ -204,8 +204,6 @@ class ObjectElement extends CollectionElement {
204
204
  return memo;
205
205
  }
206
206
 
207
- // Fantasy Land
208
-
209
207
  /**
210
208
  * Returns an empty object element.
211
209
  */
@@ -25,6 +25,14 @@ var _LinkElement = _interopRequireDefault(require("./elements/LinkElement.cjs"))
25
25
  exports.LinkElement = _LinkElement.default;
26
26
  var _RefElement = _interopRequireDefault(require("./elements/RefElement.cjs"));
27
27
  exports.RefElement = _RefElement.default;
28
+ var _Annotation = _interopRequireDefault(require("./elements/Annotation.cjs"));
29
+ exports.AnnotationElement = _Annotation.default;
30
+ var _Comment = _interopRequireDefault(require("./elements/Comment.cjs"));
31
+ exports.CommentElement = _Comment.default;
32
+ var _ParseResult = _interopRequireDefault(require("./elements/ParseResult.cjs"));
33
+ exports.ParseResultElement = _ParseResult.default;
34
+ var _SourceMap = _interopRequireDefault(require("./elements/SourceMap.cjs"));
35
+ exports.SourceMapElement = _SourceMap.default;
28
36
  var _ObjectSlice = _interopRequireDefault(require("./ObjectSlice.cjs"));
29
37
  exports.ObjectSlice = _ObjectSlice.default;
30
38
  var _KeyValuePair = _interopRequireDefault(require("./KeyValuePair.cjs"));
@@ -9,6 +9,10 @@ import MemberElement from "./primitives/MemberElement.mjs";
9
9
  import ObjectElement from "./primitives/ObjectElement.mjs";
10
10
  import LinkElement from "./elements/LinkElement.mjs";
11
11
  import RefElement from "./elements/RefElement.mjs";
12
+ import AnnotationElement from "./elements/Annotation.mjs";
13
+ import CommentElement from "./elements/Comment.mjs";
14
+ import ParseResultElement from "./elements/ParseResult.mjs";
15
+ import SourceMapElement from "./elements/SourceMap.mjs";
12
16
  import ObjectSlice from "./ObjectSlice.mjs";
13
17
  import KeyValuePair from "./KeyValuePair.mjs";
14
18
  /**
@@ -65,6 +69,6 @@ Element.prototype.refract = refract;
65
69
  * Contains all of the element classes, and related structures and methods
66
70
  * for handling with element instances.
67
71
  */
68
- export { Element, CollectionElement, NullElement, StringElement, NumberElement, BooleanElement, ArrayElement, MemberElement, ObjectElement, LinkElement, RefElement, refract, ObjectSlice, KeyValuePair };
72
+ export { Element, CollectionElement, NullElement, StringElement, NumberElement, BooleanElement, ArrayElement, MemberElement, ObjectElement, LinkElement, RefElement, AnnotationElement, CommentElement, ParseResultElement, SourceMapElement, refract, ObjectSlice, KeyValuePair };
69
73
 
70
74
  // Re-export types from element classes
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
3
4
  exports.__esModule = true;
4
5
  exports.default = void 0;
6
+ var _SourceMap = _interopRequireDefault(require("../elements/SourceMap.cjs"));
5
7
  /**
6
8
  * Serialized representation of an Element in JSON Refract format.
7
9
  * @public
@@ -46,12 +48,23 @@ class JSONSerialiser {
46
48
  const payload = {
47
49
  element: element.element
48
50
  };
49
- if (element._meta && element._meta.length > 0) {
51
+ if (!element.isMetaEmpty) {
50
52
  payload.meta = this.serialiseObject(element.meta);
51
53
  }
52
- if (element._attributes && element._attributes.length > 0) {
54
+ if (!element.isAttributesEmpty) {
53
55
  payload.attributes = this.serialiseObject(element.attributes);
54
56
  }
57
+
58
+ // Serialize source position as __mappings__ in meta (skip for SourceMapElement itself)
59
+ if (!(element instanceof _SourceMap.default)) {
60
+ const sourceMap = _SourceMap.default.from(element);
61
+ if (sourceMap) {
62
+ if (!payload.meta) {
63
+ payload.meta = {};
64
+ }
65
+ payload.meta.__mappings__ = this.serialise(sourceMap);
66
+ }
67
+ }
55
68
  const content = this.serialiseContent(element.content);
56
69
  if (content !== undefined) {
57
70
  payload.content = content;
@@ -71,8 +84,26 @@ class JSONSerialiser {
71
84
  if (element.element !== value.element) {
72
85
  element.element = value.element;
73
86
  }
74
- if (value.meta) {
75
- this.deserialiseObject(value.meta, element.meta);
87
+
88
+ // Extract __mappings__ without mutating input, filter remaining meta
89
+ let mappingsDoc;
90
+ let metaToDeserialize = value.meta;
91
+ if (value.meta?.__mappings__) {
92
+ const {
93
+ __mappings__,
94
+ ...rest
95
+ } = value.meta;
96
+ mappingsDoc = __mappings__;
97
+ metaToDeserialize = Object.keys(rest).length > 0 ? rest : undefined;
98
+ }
99
+ if (metaToDeserialize) {
100
+ this.deserialiseObject(metaToDeserialize, element.meta);
101
+ }
102
+
103
+ // Restore source position from __mappings__
104
+ if (mappingsDoc) {
105
+ const sourceMap = this.deserialise(mappingsDoc);
106
+ sourceMap.applyTo(element);
76
107
  }
77
108
  if (value.attributes) {
78
109
  this.deserialiseObject(value.attributes, element.attributes);
@@ -1,23 +1,20 @@
1
+ import SourceMapElement from "../elements/SourceMap.mjs";
1
2
  /**
2
3
  * Serialized representation of an Element in JSON Refract format.
3
4
  * @public
4
5
  */
5
-
6
6
  /**
7
7
  * Serialized representation of a KeyValuePair in JSON Refract format.
8
8
  * @public
9
9
  */
10
-
11
10
  /**
12
11
  * Possible content types in a serialized element.
13
12
  * @public
14
13
  */
15
-
16
14
  /**
17
15
  * Input document format for deserialization.
18
16
  * @public
19
17
  */
20
-
21
18
  /**
22
19
  * JSONSerialiser handles serialization and deserialization of ApiDOM elements
23
20
  * to and from JSON Refract format.
@@ -42,12 +39,23 @@ class JSONSerialiser {
42
39
  const payload = {
43
40
  element: element.element
44
41
  };
45
- if (element._meta && element._meta.length > 0) {
42
+ if (!element.isMetaEmpty) {
46
43
  payload.meta = this.serialiseObject(element.meta);
47
44
  }
48
- if (element._attributes && element._attributes.length > 0) {
45
+ if (!element.isAttributesEmpty) {
49
46
  payload.attributes = this.serialiseObject(element.attributes);
50
47
  }
48
+
49
+ // Serialize source position as __mappings__ in meta (skip for SourceMapElement itself)
50
+ if (!(element instanceof SourceMapElement)) {
51
+ const sourceMap = SourceMapElement.from(element);
52
+ if (sourceMap) {
53
+ if (!payload.meta) {
54
+ payload.meta = {};
55
+ }
56
+ payload.meta.__mappings__ = this.serialise(sourceMap);
57
+ }
58
+ }
51
59
  const content = this.serialiseContent(element.content);
52
60
  if (content !== undefined) {
53
61
  payload.content = content;
@@ -67,8 +75,26 @@ class JSONSerialiser {
67
75
  if (element.element !== value.element) {
68
76
  element.element = value.element;
69
77
  }
70
- if (value.meta) {
71
- this.deserialiseObject(value.meta, element.meta);
78
+
79
+ // Extract __mappings__ without mutating input, filter remaining meta
80
+ let mappingsDoc;
81
+ let metaToDeserialize = value.meta;
82
+ if (value.meta?.__mappings__) {
83
+ const {
84
+ __mappings__,
85
+ ...rest
86
+ } = value.meta;
87
+ mappingsDoc = __mappings__;
88
+ metaToDeserialize = Object.keys(rest).length > 0 ? rest : undefined;
89
+ }
90
+ if (metaToDeserialize) {
91
+ this.deserialiseObject(metaToDeserialize, element.meta);
92
+ }
93
+
94
+ // Restore source position from __mappings__
95
+ if (mappingsDoc) {
96
+ const sourceMap = this.deserialise(mappingsDoc);
97
+ sourceMap.applyTo(element);
72
98
  }
73
99
  if (value.attributes) {
74
100
  this.deserialiseObject(value.attributes, element.attributes);