@speclynx/apidom-datamodel 1.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSES/AFL-3.0.txt +182 -0
  2. package/LICENSES/Apache-2.0.txt +202 -0
  3. package/LICENSES/BSD-3-Clause.txt +26 -0
  4. package/LICENSES/MIT.txt +9 -0
  5. package/NOTICE +74 -0
  6. package/README.md +479 -0
  7. package/dist/apidom-datamodel.browser.js +2717 -0
  8. package/dist/apidom-datamodel.browser.min.js +1 -0
  9. package/package.json +53 -0
  10. package/src/KeyValuePair.cjs +38 -0
  11. package/src/KeyValuePair.mjs +34 -0
  12. package/src/Namespace.cjs +212 -0
  13. package/src/Namespace.mjs +206 -0
  14. package/src/ObjectSlice.cjs +206 -0
  15. package/src/ObjectSlice.mjs +202 -0
  16. package/src/elements/LinkElement.cjs +44 -0
  17. package/src/elements/LinkElement.mjs +39 -0
  18. package/src/elements/RefElement.cjs +31 -0
  19. package/src/elements/RefElement.mjs +26 -0
  20. package/src/index.cjs +25 -0
  21. package/src/index.mjs +6 -0
  22. package/src/primitives/ArrayElement.cjs +176 -0
  23. package/src/primitives/ArrayElement.mjs +169 -0
  24. package/src/primitives/BooleanElement.cjs +20 -0
  25. package/src/primitives/BooleanElement.mjs +15 -0
  26. package/src/primitives/CollectionElement.cjs +194 -0
  27. package/src/primitives/CollectionElement.mjs +187 -0
  28. package/src/primitives/Element.cjs +438 -0
  29. package/src/primitives/Element.mjs +433 -0
  30. package/src/primitives/MemberElement.cjs +54 -0
  31. package/src/primitives/MemberElement.mjs +49 -0
  32. package/src/primitives/NullElement.cjs +28 -0
  33. package/src/primitives/NullElement.mjs +23 -0
  34. package/src/primitives/NumberElement.cjs +20 -0
  35. package/src/primitives/NumberElement.mjs +15 -0
  36. package/src/primitives/ObjectElement.cjs +222 -0
  37. package/src/primitives/ObjectElement.mjs +216 -0
  38. package/src/primitives/StringElement.cjs +27 -0
  39. package/src/primitives/StringElement.mjs +22 -0
  40. package/src/registration.cjs +87 -0
  41. package/src/registration.mjs +70 -0
  42. package/src/serialisers/JSONSerialiser.cjs +144 -0
  43. package/src/serialisers/JSONSerialiser.mjs +140 -0
  44. package/src/types.cjs +3 -0
  45. package/src/types.mjs +1 -0
  46. package/types/apidom-datamodel.d.ts +887 -0
@@ -0,0 +1,433 @@
1
+ import { equals } from 'ramda';
2
+ import KeyValuePair from "../KeyValuePair.mjs";
3
+ import ObjectSlice from "../ObjectSlice.mjs";
4
+ /**
5
+ * Valid content types for an Element.
6
+ * @public
7
+ */
8
+ /**
9
+ * Base Element class that all ApiDOM elements extend.
10
+ *
11
+ * Elements are the core building blocks of ApiDOM. Each element has:
12
+ * - An `element` property identifying its type
13
+ * - Optional `content` holding the element's value
14
+ * - Optional `meta` for metadata (id, classes, title, description, links)
15
+ * - Optional `attributes` for element-specific properties
16
+ *
17
+ * @public
18
+ */
19
+ class Element {
20
+ /**
21
+ * The element type identifier.
22
+ * @internal
23
+ */
24
+ _storedElement = 'element';
25
+
26
+ /**
27
+ * The element's content/value.
28
+ * @internal
29
+ */
30
+ _content;
31
+
32
+ /**
33
+ * Metadata about this element.
34
+ * @internal
35
+ */
36
+ _meta;
37
+
38
+ /**
39
+ * Element-specific attributes.
40
+ * @internal
41
+ */
42
+ _attributes;
43
+
44
+ /**
45
+ * Parent element reference (set when tree is frozen).
46
+ */
47
+ parent;
48
+
49
+ // ============================================================
50
+ // Prototype-assigned properties (set in elements.ts)
51
+ // Using 'declare' allows TypeScript to know about these
52
+ // without generating runtime code.
53
+ // ============================================================
54
+
55
+ /** @internal ObjectElement constructor for creating meta/attributes */
56
+
57
+ /** @internal ArrayElement constructor for creating arrays */
58
+
59
+ /** @internal MemberElement constructor for creating object members */
60
+
61
+ /** @internal RefElement constructor for creating references */
62
+
63
+ /** @internal Function to convert values to elements */
64
+
65
+ constructor(content, meta, attributes) {
66
+ if (meta !== undefined) {
67
+ this.meta = meta;
68
+ }
69
+ if (attributes !== undefined) {
70
+ this.attributes = attributes;
71
+ }
72
+ if (content !== undefined) {
73
+ this.content = content;
74
+ }
75
+ }
76
+
77
+ // ============================================================
78
+ // Core Properties
79
+ // ============================================================
80
+
81
+ /**
82
+ * The element type identifier (e.g., 'string', 'object', 'array').
83
+ */
84
+ get element() {
85
+ return this._storedElement;
86
+ }
87
+ set element(value) {
88
+ this._storedElement = value;
89
+ }
90
+
91
+ /**
92
+ * The element's content/value.
93
+ */
94
+ get content() {
95
+ return this._content;
96
+ }
97
+ set content(value) {
98
+ // Already an element
99
+ if (value instanceof Element) {
100
+ this._content = value;
101
+ return;
102
+ }
103
+
104
+ // Primitives (inlined for performance - avoids 8 function calls)
105
+ if (value === null || value === undefined || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint' || typeof value === 'symbol') {
106
+ this._content = value;
107
+ return;
108
+ }
109
+
110
+ // KeyValuePair
111
+ if (value instanceof KeyValuePair) {
112
+ this._content = value;
113
+ return;
114
+ }
115
+
116
+ // ObjectSlice - extract elements array
117
+ if (value instanceof ObjectSlice) {
118
+ this._content = value.elements;
119
+ return;
120
+ }
121
+
122
+ // Array - refract each item
123
+ if (Array.isArray(value)) {
124
+ this._content = value.map(item => this.refract(item));
125
+ return;
126
+ }
127
+
128
+ // Plain object - convert to MemberElements
129
+ if (typeof value === 'object') {
130
+ this._content = Object.entries(value).map(([key, val]) => new this.MemberElement(key, val));
131
+ return;
132
+ }
133
+ throw new Error(`Cannot set content to value of type ${typeof value}`);
134
+ }
135
+
136
+ /**
137
+ * Metadata about this element (id, classes, title, description, links).
138
+ * Lazily creates an ObjectElement if not set.
139
+ */
140
+ get meta() {
141
+ if (!this._meta) {
142
+ if (this.isFrozen) {
143
+ const meta = new this.ObjectElement();
144
+ meta.freeze();
145
+ return meta;
146
+ }
147
+ this._meta = new this.ObjectElement();
148
+ }
149
+ return this._meta;
150
+ }
151
+ set meta(value) {
152
+ if (value instanceof Element) {
153
+ this._meta = value;
154
+ } else {
155
+ this.meta.set(value ?? {});
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Element-specific attributes.
161
+ * Lazily creates an ObjectElement if not set.
162
+ */
163
+ get attributes() {
164
+ if (!this._attributes) {
165
+ if (this.isFrozen) {
166
+ const attributes = new this.ObjectElement();
167
+ attributes.freeze();
168
+ return attributes;
169
+ }
170
+ this._attributes = new this.ObjectElement();
171
+ }
172
+ return this._attributes;
173
+ }
174
+ set attributes(value) {
175
+ if (value instanceof Element) {
176
+ this._attributes = value;
177
+ } else {
178
+ this.attributes.set(value ?? {});
179
+ }
180
+ }
181
+
182
+ // ============================================================
183
+ // Meta Property Shortcuts
184
+ // ============================================================
185
+
186
+ /** Unique identifier for this element. */
187
+ get id() {
188
+ return this.getMetaProperty('id', '');
189
+ }
190
+ set id(value) {
191
+ this.setMetaProperty('id', value);
192
+ }
193
+
194
+ /** CSS-like class names. */
195
+ get classes() {
196
+ return this.getMetaProperty('classes', []);
197
+ }
198
+ set classes(value) {
199
+ this.setMetaProperty('classes', value);
200
+ }
201
+
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
+ /** Hyperlinks associated with this element. */
219
+ get links() {
220
+ return this.getMetaProperty('links', []);
221
+ }
222
+ set links(value) {
223
+ this.setMetaProperty('links', value);
224
+ }
225
+
226
+ // ============================================================
227
+ // Tree Navigation
228
+ // ============================================================
229
+
230
+ /** Returns direct children of this element. */
231
+ get children() {
232
+ const {
233
+ _content: content
234
+ } = this;
235
+ if (Array.isArray(content)) {
236
+ return content;
237
+ }
238
+ if (content instanceof KeyValuePair) {
239
+ const children = [];
240
+ if (content.key) children.push(content.key);
241
+ if (content.value) children.push(content.value);
242
+ return children;
243
+ }
244
+ if (content instanceof Element) {
245
+ return [content];
246
+ }
247
+ return [];
248
+ }
249
+
250
+ // ============================================================
251
+ // Freezable Implementation
252
+ // ============================================================
253
+
254
+ /** Whether this element is frozen (immutable). */
255
+ get isFrozen() {
256
+ return Object.isFrozen(this);
257
+ }
258
+
259
+ /**
260
+ * Freezes the element tree, making it immutable.
261
+ * Sets up parent references for tree traversal.
262
+ */
263
+ freeze() {
264
+ if (this.isFrozen) return;
265
+
266
+ // Freeze meta and attributes
267
+ if (this._meta) {
268
+ this._meta.parent = this;
269
+ this._meta.freeze();
270
+ }
271
+ if (this._attributes) {
272
+ this._attributes.parent = this;
273
+ this._attributes.freeze();
274
+ }
275
+
276
+ // Freeze children
277
+ for (const child of this.children) {
278
+ child.parent = this;
279
+ child.freeze();
280
+ }
281
+
282
+ // Freeze content array if applicable
283
+ if (Array.isArray(this._content)) {
284
+ Object.freeze(this._content);
285
+ }
286
+ Object.freeze(this);
287
+ }
288
+
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
+ // ============================================================
325
+ // ToValue Implementation
326
+ // ============================================================
327
+
328
+ /**
329
+ * Converts the element to its JavaScript value representation.
330
+ */
331
+ toValue() {
332
+ const {
333
+ _content
334
+ } = this;
335
+ if (_content instanceof Element) {
336
+ return _content.toValue();
337
+ }
338
+ if (_content instanceof KeyValuePair) {
339
+ return _content.toValue();
340
+ }
341
+ if (Array.isArray(_content)) {
342
+ return _content.map(el => el.toValue());
343
+ }
344
+ return _content;
345
+ }
346
+
347
+ // ============================================================
348
+ // Equatable Implementation
349
+ // ============================================================
350
+
351
+ /**
352
+ * Checks deep equality with another value.
353
+ */
354
+ equals(value) {
355
+ return equals(this.toValue(), value);
356
+ }
357
+
358
+ // ============================================================
359
+ // Element Type
360
+ // ============================================================
361
+
362
+ /**
363
+ * Returns the primitive type name for this element.
364
+ * Override in subclasses (e.g., 'string', 'number', 'array').
365
+ */
366
+ primitive() {
367
+ return undefined;
368
+ }
369
+
370
+ // ============================================================
371
+ // Content Operations
372
+ // ============================================================
373
+
374
+ /**
375
+ * Sets the content of this element.
376
+ * @returns this for chaining
377
+ */
378
+ set(content) {
379
+ this.content = content;
380
+ return this;
381
+ }
382
+
383
+ // ============================================================
384
+ // Reference Creation
385
+ // ============================================================
386
+
387
+ /**
388
+ * Creates a RefElement pointing to this element.
389
+ * @param path - Optional path within the referenced element
390
+ * @throws Error if this element has no ID
391
+ */
392
+ toRef(path) {
393
+ const idValue = this.id.toValue();
394
+ if (idValue === '') {
395
+ throw new Error('Cannot create reference to an element without an ID');
396
+ }
397
+ const ref = new this.RefElement(idValue);
398
+ if (typeof path === 'string') {
399
+ ref.path = this.refract(path);
400
+ }
401
+ return ref;
402
+ }
403
+
404
+ // ============================================================
405
+ // Protected Helpers
406
+ // ============================================================
407
+
408
+ /**
409
+ * Gets a meta property, creating it with default value if not present.
410
+ */
411
+ getMetaProperty(name, defaultValue) {
412
+ if (!this.meta.hasKey(name)) {
413
+ if (this.isFrozen) {
414
+ const element = this.refract(defaultValue);
415
+ element.freeze();
416
+ return element;
417
+ }
418
+ this.meta.set(name, defaultValue);
419
+ }
420
+ return this.meta.get(name);
421
+ }
422
+
423
+ /**
424
+ * Sets a meta property.
425
+ */
426
+ setMetaProperty(name, value) {
427
+ this.meta.set(name, value);
428
+ }
429
+ }
430
+
431
+ // Re-export types for convenience
432
+
433
+ export default Element;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
+ exports.__esModule = true;
5
+ exports.default = void 0;
6
+ var _KeyValuePair = _interopRequireDefault(require("../KeyValuePair.cjs"));
7
+ var _Element = _interopRequireDefault(require("./Element.cjs"));
8
+ /**
9
+ * MemberElement represents a key-value pair member in an ObjectElement.
10
+ *
11
+ * The member's content is always a KeyValuePair containing:
12
+ * - `key`: The key element (typically a StringElement)
13
+ * - `value`: The value element (any Element type)
14
+ *
15
+ * @typeParam K - The key element type, defaults to Element
16
+ * @typeParam V - The value element type, defaults to Element
17
+ * @public
18
+ */
19
+ class MemberElement extends _Element.default {
20
+ constructor(key, value, meta, attributes) {
21
+ super(new _KeyValuePair.default(), meta, attributes);
22
+ this.element = 'member';
23
+ if (key !== undefined) {
24
+ this.key = key;
25
+ }
26
+ if (value !== undefined) {
27
+ this.value = value;
28
+ }
29
+ }
30
+ primitive() {
31
+ return 'member';
32
+ }
33
+
34
+ /**
35
+ * The key element of this member.
36
+ */
37
+ get key() {
38
+ return this._content.key;
39
+ }
40
+ set key(value) {
41
+ this._content.key = this.refract(value);
42
+ }
43
+
44
+ /**
45
+ * The value element of this member.
46
+ */
47
+ get value() {
48
+ return this._content.value;
49
+ }
50
+ set value(value) {
51
+ this._content.value = this.refract(value);
52
+ }
53
+ }
54
+ var _default = exports.default = MemberElement;
@@ -0,0 +1,49 @@
1
+ import KeyValuePair from "../KeyValuePair.mjs";
2
+ import Element from "./Element.mjs";
3
+ /**
4
+ * MemberElement represents a key-value pair member in an ObjectElement.
5
+ *
6
+ * The member's content is always a KeyValuePair containing:
7
+ * - `key`: The key element (typically a StringElement)
8
+ * - `value`: The value element (any Element type)
9
+ *
10
+ * @typeParam K - The key element type, defaults to Element
11
+ * @typeParam V - The value element type, defaults to Element
12
+ * @public
13
+ */
14
+ class MemberElement extends Element {
15
+ constructor(key, value, meta, attributes) {
16
+ super(new KeyValuePair(), meta, attributes);
17
+ this.element = 'member';
18
+ if (key !== undefined) {
19
+ this.key = key;
20
+ }
21
+ if (value !== undefined) {
22
+ this.value = value;
23
+ }
24
+ }
25
+ primitive() {
26
+ return 'member';
27
+ }
28
+
29
+ /**
30
+ * The key element of this member.
31
+ */
32
+ get key() {
33
+ return this._content.key;
34
+ }
35
+ set key(value) {
36
+ this._content.key = this.refract(value);
37
+ }
38
+
39
+ /**
40
+ * The value element of this member.
41
+ */
42
+ get value() {
43
+ return this._content.value;
44
+ }
45
+ set value(value) {
46
+ this._content.value = this.refract(value);
47
+ }
48
+ }
49
+ export default MemberElement;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
+ exports.__esModule = true;
5
+ exports.default = void 0;
6
+ var _Element = _interopRequireDefault(require("./Element.cjs"));
7
+ /**
8
+ * NullElement represents a null value in ApiDOM.
9
+ * @public
10
+ */
11
+ class NullElement extends _Element.default {
12
+ constructor(content, meta, attributes) {
13
+ super(content ?? null, meta, attributes);
14
+ this.element = 'null';
15
+ }
16
+ primitive() {
17
+ return 'null';
18
+ }
19
+
20
+ /**
21
+ * NullElement cannot have its value changed.
22
+ * @throws Error - NullElement value cannot be modified
23
+ */
24
+ set(_content) {
25
+ throw new Error('Cannot set the value of null');
26
+ }
27
+ }
28
+ var _default = exports.default = NullElement;
@@ -0,0 +1,23 @@
1
+ import Element from "./Element.mjs";
2
+ /**
3
+ * NullElement represents a null value in ApiDOM.
4
+ * @public
5
+ */
6
+ class NullElement extends Element {
7
+ constructor(content, meta, attributes) {
8
+ super(content ?? null, meta, attributes);
9
+ this.element = 'null';
10
+ }
11
+ primitive() {
12
+ return 'null';
13
+ }
14
+
15
+ /**
16
+ * NullElement cannot have its value changed.
17
+ * @throws Error - NullElement value cannot be modified
18
+ */
19
+ set(_content) {
20
+ throw new Error('Cannot set the value of null');
21
+ }
22
+ }
23
+ export default NullElement;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
+ exports.__esModule = true;
5
+ exports.default = void 0;
6
+ var _Element = _interopRequireDefault(require("./Element.cjs"));
7
+ /**
8
+ * NumberElement represents a numeric value in ApiDOM.
9
+ * @public
10
+ */
11
+ class NumberElement extends _Element.default {
12
+ constructor(content, meta, attributes) {
13
+ super(content, meta, attributes);
14
+ this.element = 'number';
15
+ }
16
+ primitive() {
17
+ return 'number';
18
+ }
19
+ }
20
+ var _default = exports.default = NumberElement;
@@ -0,0 +1,15 @@
1
+ import Element from "./Element.mjs";
2
+ /**
3
+ * NumberElement represents a numeric value in ApiDOM.
4
+ * @public
5
+ */
6
+ class NumberElement extends Element {
7
+ constructor(content, meta, attributes) {
8
+ super(content, meta, attributes);
9
+ this.element = 'number';
10
+ }
11
+ primitive() {
12
+ return 'number';
13
+ }
14
+ }
15
+ export default NumberElement;