@speclynx/apidom-core 1.12.1 → 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 (92) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/NOTICE +16 -7
  3. package/README.md +102 -330
  4. package/dist/apidom-core.browser.js +7529 -11588
  5. package/dist/apidom-core.browser.min.js +1 -1
  6. package/package.json +7 -12
  7. package/src/identity/index.cjs +8 -6
  8. package/src/identity/index.mjs +6 -4
  9. package/src/index.cjs +13 -79
  10. package/src/index.mjs +3 -13
  11. package/src/merge/deepmerge.cjs +22 -20
  12. package/src/merge/deepmerge.mjs +9 -7
  13. package/src/merge/merge-right.cjs +2 -2
  14. package/src/merge/merge-right.mjs +1 -1
  15. package/src/namespace.cjs +4 -36
  16. package/src/namespace.mjs +2 -30
  17. package/src/refractor/plugins/dispatcher/index.cjs +5 -12
  18. package/src/refractor/plugins/dispatcher/index.mjs +5 -12
  19. package/src/refractor/plugins/element-identity.cjs +2 -2
  20. package/src/refractor/plugins/element-identity.mjs +2 -2
  21. package/src/refractor/plugins/semantic-element-identity.cjs +5 -10
  22. package/src/refractor/plugins/semantic-element-identity.mjs +5 -9
  23. package/src/refractor/toolbox.cjs +22 -5
  24. package/src/refractor/toolbox.mjs +25 -6
  25. package/src/specification.cjs +51 -0
  26. package/src/specification.mjs +47 -0
  27. package/src/transcluder/Transcluder.cjs +8 -8
  28. package/src/transcluder/Transcluder.mjs +1 -1
  29. package/src/transformers/from.mjs +2 -2
  30. package/src/transformers/serializers/json.cjs +2 -2
  31. package/src/transformers/serializers/json.mjs +1 -1
  32. package/src/transformers/serializers/value.cjs +50 -0
  33. package/src/transformers/serializers/value.mjs +47 -0
  34. package/src/transformers/serializers/yaml-1-2.cjs +22 -18
  35. package/src/transformers/serializers/yaml-1-2.mjs +22 -18
  36. package/src/transformers/sexprs.cjs +20 -23
  37. package/src/transformers/sexprs.mjs +20 -22
  38. package/src/transformers/to-string.mjs +2 -2
  39. package/types/apidom-core.d.ts +67 -519
  40. package/src/clone/errors/CloneError.cjs +0 -22
  41. package/src/clone/errors/CloneError.mjs +0 -19
  42. package/src/clone/errors/DeepCloneError.cjs +0 -11
  43. package/src/clone/errors/DeepCloneError.mjs +0 -6
  44. package/src/clone/errors/ShallowCloneError.cjs +0 -11
  45. package/src/clone/errors/ShallowCloneError.mjs +0 -6
  46. package/src/clone/index.cjs +0 -155
  47. package/src/clone/index.mjs +0 -146
  48. package/src/elements/Annotation.cjs +0 -23
  49. package/src/elements/Annotation.mjs +0 -20
  50. package/src/elements/Comment.cjs +0 -15
  51. package/src/elements/Comment.mjs +0 -12
  52. package/src/elements/ParseResult.cjs +0 -53
  53. package/src/elements/ParseResult.mjs +0 -50
  54. package/src/elements/SourceMap.cjs +0 -39
  55. package/src/elements/SourceMap.mjs +0 -36
  56. package/src/predicates/helpers.cjs +0 -85
  57. package/src/predicates/helpers.mjs +0 -77
  58. package/src/predicates/index.cjs +0 -208
  59. package/src/predicates/index.mjs +0 -198
  60. package/src/refractor/index.cjs +0 -46
  61. package/src/refractor/index.mjs +0 -40
  62. package/src/refractor/registration.cjs +0 -34
  63. package/src/refractor/registration.mjs +0 -19
  64. package/src/transformers/serializers/value/ast/ephemeral-array.cjs +0 -21
  65. package/src/transformers/serializers/value/ast/ephemeral-array.mjs +0 -17
  66. package/src/transformers/serializers/value/ast/ephemeral-object.cjs +0 -20
  67. package/src/transformers/serializers/value/ast/ephemeral-object.mjs +0 -16
  68. package/src/transformers/serializers/value/index.cjs +0 -85
  69. package/src/transformers/serializers/value/index.mjs +0 -80
  70. package/src/transformers/serializers/value/visitor.cjs +0 -52
  71. package/src/transformers/serializers/value/visitor.mjs +0 -47
  72. package/src/traversal/filter.cjs +0 -18
  73. package/src/traversal/filter.mjs +0 -14
  74. package/src/traversal/find.cjs +0 -19
  75. package/src/traversal/find.mjs +0 -15
  76. package/src/traversal/findAtOffset.cjs +0 -65
  77. package/src/traversal/findAtOffset.mjs +0 -60
  78. package/src/traversal/index.cjs +0 -19
  79. package/src/traversal/index.mjs +0 -7
  80. package/src/traversal/parents.cjs +0 -38
  81. package/src/traversal/parents.mjs +0 -34
  82. package/src/traversal/reject.cjs +0 -15
  83. package/src/traversal/reject.mjs +0 -10
  84. package/src/traversal/some.cjs +0 -15
  85. package/src/traversal/some.mjs +0 -10
  86. package/src/traversal/traverse.cjs +0 -60
  87. package/src/traversal/traverse.mjs +0 -53
  88. package/src/traversal/visitor.cjs +0 -123
  89. package/src/traversal/visitor.mjs +0 -115
  90. package/src/util.cjs +0 -28
  91. package/src/util.mjs +0 -24
  92. package/types/minim.d.ts +0 -236
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # @speclynx/apidom-core
2
2
 
3
3
  `apidom-core` is a package that contains tools for manipulating the ApiDOM structures.
4
+ It provides utilities for transformation, merging, cloning, and refraction of ApiDOM elements.
4
5
 
5
6
  ## Installation
6
7
 
@@ -12,63 +13,26 @@ You can install this package via [npm CLI](https://docs.npmjs.com/cli) by runnin
12
13
 
13
14
  ---
14
15
 
15
- ## Base namespace
16
+ ## Relationship with other packages
16
17
 
17
- Base namespace consists of [four higher order elements](https://github.com/speclynx/apidom/tree/main/packages/apidom-core/src/elements) implemented on top
18
- of [primitive ones](https://github.com/refractproject/minim/tree/master/lib/primitives).
18
+ This package works together with:
19
19
 
20
- ```js
21
- import { createNamespace } from '@speclynx/apidom-core';
22
-
23
- const namespace = createNamespace();
24
-
25
- const objectElement = new namespace.elements.Object();
26
- const commentElement = new namespace.elements.Comment();
27
- ```
28
-
29
- It's possible to create namespace instances using another namespaces.
20
+ - **@speclynx/apidom-datamodel** - Contains the core element primitives (`ObjectElement`, `ArrayElement`, `StringElement`, etc.), predicates, and the `Namespace` class
21
+ - **@speclynx/apidom-traverse** - Contains traversal utilities (`traverse`, `filter`, `find`, `forEach`, etc.)
22
+ - **@speclynx/apidom-core** - Contains utilities for working with elements: transformers, merging, cloning, and refractor plugins
30
23
 
31
24
  ```js
32
- import { createNamespace } from '@speclynx/apidom-core';
33
- import openApi3_1Namespace from '@speclynx/apidom-ns-openapi-3-1';
34
-
35
- const namespace = createNamespace(openApi3_1Namespace);
36
-
37
- const objectElement = new namespace.elements.Object();
38
- const openApiElement = new namespace.elements.OpenApi3_1();
39
- ```
40
-
41
- When namespace instance is created in this way, it will extend the base namespace
42
- with the namespace provided as an argument.
25
+ // Elements and predicates come from datamodel
26
+ import { ObjectElement, StringElement, isObjectElement } from '@speclynx/apidom-datamodel';
43
27
 
44
- ---
45
-
46
- ## Predicates
47
-
48
- This package exposes [predicates](https://github.com/speclynx/apidom/blob/main/packages/apidom-core/src/predicates/index.ts)
49
- for all primitive elements and all higher order elements that are part of the base namespace.
50
-
51
- ```js
52
- import { CommentElement, isCommentElement } from '@speclynx/apidom-core';
28
+ // Traversal utilities come from traverse
29
+ import { traverse, filter, find } from '@speclynx/apidom-traverse';
53
30
 
54
- const commentElement = new CommentElement();
31
+ // Other utilities come from core
32
+ import { toValue, deepmerge, from } from '@speclynx/apidom-core';
55
33
 
56
- isCommentElement(commentElement); // => true
57
- ```
58
-
59
- [Predicate helpers](https://github.com/speclynx/apidom/blob/main/packages/apidom-core/src/predicates/helpers.ts)
60
- helps in building predicates for this and other packages.
61
-
62
- ```js
63
- import { createPredicate } from '@speclynx/apidom-core';
64
-
65
- const isMyElement = createPredicate(
66
- ({ hasBasicElementProps, isElementType, primitiveEq }) => {
67
- return (element) =>
68
- element instanceof MyElement ||
69
- (hasBasicElementProps(element) && isElementType('myElement', element) && primitiveEq('object', element));
70
- },
71
- );
34
+ const obj = new ObjectElement({ a: 'b' });
35
+ toValue(obj); // => { a: 'b' }
72
36
  ```
73
37
 
74
38
  ---
@@ -79,7 +43,8 @@ Transclusion is the inclusion of one ApiDOM fragment into another ApiDOM fragmen
79
43
  Our [transcluder](https://github.com/speclynx/apidom/tree/main/packages/apidom-core/src/transcluder) does exactly that and is based on mutating algorithm.
80
44
 
81
45
  ```js
82
- import { transclude, ArrayElement, NumberElement } from '@speclynx/apidom-core';
46
+ import { ArrayElement, NumberElement } from '@speclynx/apidom-datamodel';
47
+ import { transclude } from '@speclynx/apidom-core';
83
48
 
84
49
  const element = new ArrayElement([1, 2, 3]);
85
50
  const search = element.get(1);
@@ -92,7 +57,8 @@ When multiple transclusions are going to be performed use [Transcluder stamp](ht
92
57
  for optimal performance.
93
58
 
94
59
  ```js
95
- import { Transcluder, ArrayElement, NumberElement } from '@speclynx/apidom-core';
60
+ import { ArrayElement, NumberElement } from '@speclynx/apidom-datamodel';
61
+ import { Transcluder } from '@speclynx/apidom-core';
96
62
 
97
63
  const element = new ArrayElement([1, 2, 3]);
98
64
  const search = element.get(1);
@@ -119,7 +85,8 @@ the value from source will appear in the result. Merging creates a new ApiDOM el
119
85
  so that neither target nor source is modified (operation is immutable).
120
86
 
121
87
  ```js
122
- import { mergeRight, ObjectElement } from '@speclynx/apidom-core';
88
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
89
+ import { mergeRight } from '@speclynx/apidom-core';
123
90
 
124
91
  const x = new ObjectElement({
125
92
  foo: { bar: 3 },
@@ -145,7 +112,8 @@ const output = mergeRight(x, y);
145
112
  Merges shallowly any number of ApiDOM elements into a single ApiDOM element.
146
113
 
147
114
  ```js
148
- import { mergeRight, ObjectElement } from '@speclynx/apidom-core';
115
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
116
+ import { mergeRight } from '@speclynx/apidom-core';
149
117
 
150
118
  const foobar = new ObjectElement({ foo: { bar: 3 } });
151
119
  const foobaz = new ObjectElement({ foo: { baz: 4 } });
@@ -163,7 +131,8 @@ the value from source will appear in the result. Merging creates a new ApiDOM el
163
131
  so that neither target nor source is modified (operation is immutable).
164
132
 
165
133
  ```js
166
- import { mergeLeft, ObjectElement } from '@speclynx/apidom-core';
134
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
135
+ import { mergeLeft } from '@speclynx/apidom-core';
167
136
 
168
137
  const x = new ObjectElement({
169
138
  foo: { bar: 3 },
@@ -189,7 +158,8 @@ const output = mergeLeft(x, y);
189
158
  Merges shallowly any number of ApiDOM elements into a single ApiDOM element.
190
159
 
191
160
  ```js
192
- import { mergeLeft, ObjectElement } from '@speclynx/apidom-core';
161
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
162
+ import { mergeLeft } from '@speclynx/apidom-core';
193
163
 
194
164
  const foobar = new ObjectElement({ foo: { bar: 3 } });
195
165
  const foobaz = new ObjectElement({ foo: { baz: 4 } });
@@ -220,7 +190,8 @@ the value from source will appear in the result. Merging creates a new ApiDOM el
220
190
  so that neither target nor source is modified (operation is immutable).
221
191
 
222
192
  ```js
223
- import { deepmerge, ObjectElement } from '@speclynx/apidom-core';
193
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
194
+ import { deepmerge } from '@speclynx/apidom-core';
224
195
 
225
196
  const x = new ObjectElement({
226
197
  foo: { bar: 3 },
@@ -275,7 +246,8 @@ const output = deepmerge(x, y);
275
246
  Merges deeply any number of ApiDOM elements into a single ApiDOM element.
276
247
 
277
248
  ```js
278
- import { deepmerge, ObjectElement } from '@speclynx/apidom-core';
249
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
250
+ import { deepmerge } from '@speclynx/apidom-core';
279
251
 
280
252
  const foobar = new ObjectElement({ foo: { bar: 3 } });
281
253
  const foobaz = new ObjectElement({ foo: { baz: 4 } });
@@ -295,7 +267,8 @@ Your `arrayElementMerge` function will be called with three arguments: a `target
295
267
  and an `options` object.
296
268
 
297
269
  ```js
298
- import { deepmerge, ArrayElement } from '@speclynx/apidom-core';
270
+ import { ArrayElement } from '@speclynx/apidom-datamodel';
271
+ import { deepmerge } from '@speclynx/apidom-core';
299
272
 
300
273
  const arrayElementMerge = (destination, source, options) => source;
301
274
 
@@ -313,7 +286,8 @@ Your `objectElementMerge` function will be called with three arguments: a `targe
313
286
  and an `options` object.
314
287
 
315
288
  ```js
316
- import { deepmerge, ObjectElement } from '@speclynx/apidom-core';
289
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
290
+ import { deepmerge } from '@speclynx/apidom-core';
317
291
 
318
292
  const objectElementMerge = (destination, source, options) => source;
319
293
 
@@ -332,10 +306,14 @@ and you want to copy the whole ObjectElement instead of just copying its member.
332
306
  You can accomplish this by passing in a function for the `isMergeableElement` option.
333
307
 
334
308
  ```js
335
- import { deepmerge, ObjectElement, isObjectElement } from '@speclynx/apidom-core';
309
+ import { ObjectElement, Element, isObjectElement } from '@speclynx/apidom-datamodel';
310
+ import { deepmerge } from '@speclynx/apidom-core';
336
311
 
337
312
  class CustomObjectElement extends ObjectElement {
338
- element = 'custom';
313
+ constructor(...args) {
314
+ super(...args);
315
+ this.element = 'custom';
316
+ }
339
317
  }
340
318
  const instantiatedCustomObjectElement = new CustomObjectElement({ special: 'oh yeah' });
341
319
 
@@ -365,7 +343,8 @@ be used to merge the values for that member.
365
343
  It may also return undefined, in which case the default merge behaviour will be used.
366
344
 
367
345
  ```js
368
- import { deepmerge, ObjectElement } from '@speclynx/apidom-core';
346
+ import { ObjectElement, StringElement, Element } from '@speclynx/apidom-datamodel';
347
+ import { deepmerge, toValue } from '@speclynx/apidom-core';
369
348
 
370
349
  const alex = new ObjectElement({
371
350
  name: {
@@ -387,7 +366,7 @@ const mergeNames = (nameA: ObjectElement, nameB: ObjectElement) =>
387
366
  const customMerge = (key: Element) => (toValue(key) === 'name' ? mergeNames : undefined);
388
367
 
389
368
  const output = deepmerge(alex, tony, { customMerge });
390
- // output.get('name'); // => StrignElement('Alex and Tony')
369
+ // output.get('name'); // => StringElement('Alex and Tony')
391
370
  // output.get('pets'); // => ArrayElement(['Cat', 'Parrot', 'Dog'])
392
371
  ```
393
372
 
@@ -398,7 +377,8 @@ The `customMetaMerge` function will be passed target and source metadata. If not
398
377
  the default behavior is to deep copy metadata from target to new merged element.
399
378
 
400
379
  ```js
401
- import { deepmerge, ObjectElement } from '@speclynx/apidom-core';
380
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
381
+ import { deepmerge } from '@speclynx/apidom-core';
402
382
 
403
383
  const alex = new ObjectElement({ name: { first: 'Alex' } }, { metaKey: true });
404
384
  const tony = new ObjectElement({ name: { first: 'Tony' } }, { metaKey: false });
@@ -416,7 +396,8 @@ The `customAttributesMerge` function will be passed target and source attributes
416
396
  the default behavior is to deep copy attributes from target to new merged element.
417
397
 
418
398
  ```js
419
- import { deepmerge, ObjectElement } from '@speclynx/apidom-core';
399
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
400
+ import { deepmerge } from '@speclynx/apidom-core';
420
401
 
421
402
  const alex = new ObjectElement({ name: { first: 'Alex' } }, undefined, { attributeKey: true });
422
403
  const tony = new ObjectElement({ name: { first: 'Tony' } }, undefined, { attributeKey: false });
@@ -424,7 +405,7 @@ const tony = new ObjectElement({ name: { first: 'Tony' } }, undefined, { attribu
424
405
  const customAttributesMerge = (targetMeta, sourceMeta) => deepmerge(targetMeta, sourceMeta);
425
406
 
426
407
  const output = deepmerge(alex, tony, { customAttributesMerge });
427
- // output.attributs.get('attributeKey') // => BooleanElement(false)
408
+ // output.attributes.get('attributeKey') // => BooleanElement(false)
428
409
  ```
429
410
 
430
411
  #### clone
@@ -435,41 +416,17 @@ If `clone` is false then child elements will be copied directly instead of being
435
416
 
436
417
  ---
437
418
 
438
- ## Refractors
439
-
440
- Refractor is a special layer inside the base namespace that can transform JavaScript structures
441
- into generic ApiDOM structures built from elements of this base namespace.
419
+ ## Refractor plugins
442
420
 
443
- **Refracting JavaScript structures**:
421
+ Refractor plugins allow you to transform ApiDOM structures during traversal.
422
+ Use `dispatchRefractorPlugins` to apply plugins to an element tree.
444
423
 
445
424
  ```js
446
- import { ObjectElement } from '@speclynx/apidom-core';
447
-
448
- const object = {
449
- title: 'my title',
450
- description: 'my description',
451
- version: '0.1.0',
452
- };
453
-
454
- ObjectElement.refract(object); // => ObjectElement({ title, description, version })
455
- ```
456
-
457
- ```js
458
- import { CommentElement } from '@speclynx/apidom-core';
459
-
460
- const comment = 'this is comment';
461
-
462
- CommentElement.refract(comment); // => CommentElement('this is comment')
463
- ```
464
-
465
- ### Refractor plugins
466
-
467
- Refractors can accept plugins as a second argument of refract static method.
468
-
469
- ```js
470
- import { ObjectElement, StringElement } from '@speclynx/apidom-core';
425
+ import { ObjectElement, StringElement } from '@speclynx/apidom-datamodel';
426
+ import { dispatchRefractorPlugins, from } from '@speclynx/apidom-core';
471
427
 
472
428
  const object = { a: 'b' };
429
+ const objectElement = from(object);
473
430
 
474
431
  const plugin = ({ predicates, namespace }) => ({
475
432
  name: 'plugin',
@@ -486,24 +443,22 @@ const plugin = ({ predicates, namespace }) => ({
486
443
  },
487
444
  });
488
445
 
489
- ObjectElement.refract(object, { plugins: [plugin] }); // => ObjectElement({ a = 'c' })
446
+ dispatchRefractorPlugins(objectElement, [plugin]); // => ObjectElement({ a = 'c' })
490
447
  ```
491
- You can define as many plugins as needed to enhance the resulting namespaced ApiDOM structure.
448
+ You can define as many plugins as needed to enhance the resulting ApiDOM structure.
492
449
  If multiple plugins with the same visitor method are defined, they run in parallel (just like in Babel).
493
450
 
494
- #### Element identity plugin
451
+ ### Element identity plugin
495
452
 
496
- `apidom` package comes with `refractorPluginElementIdentity`. When used, this plugin will
453
+ `apidom-core` package comes with `refractorPluginElementIdentity`. When used, this plugin will
497
454
  assign unique ID to all elements in ApiDOM tree.
498
455
 
499
456
  ```js
500
- import { refractorPluginElementIdentity, ObjectElement } from '@speclynx/apidom-core';
457
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
458
+ import { refractorPluginElementIdentity, dispatchRefractorPlugins, from } from '@speclynx/apidom-core';
501
459
 
502
- const objectElement = ObjectElement.refract({ a: 'b' }, {
503
- plugins: [
504
- refractorPluginElementIdentity(),
505
- ]
506
- });
460
+ const objectElement = from({ a: 'b' });
461
+ dispatchRefractorPlugins(objectElement, [refractorPluginElementIdentity()]);
507
462
 
508
463
  objectElement.id; // 8RaWF9
509
464
  objectElement.getMember('a').key.id; // NdHHV7
@@ -513,217 +468,55 @@ objectElement.getMember('a').value.id; // rFGVFP
513
468
  You can configure the plugin to generate unique IDs in the specific length:
514
469
 
515
470
  ```js
516
- import { refractorPluginElementIdentity, ObjectElement } from '@speclynx/apidom-core';
471
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
472
+ import { refractorPluginElementIdentity, dispatchRefractorPlugins, from } from '@speclynx/apidom-core';
517
473
 
518
- const objectElement = ObjectElement.refract({ a: 'b' }, {
519
- plugins: [
520
- refractorPluginElementIdentity({ length: 36}),
521
- ]
522
- });
474
+ const objectElement = from({ a: 'b' });
475
+ dispatchRefractorPlugins(objectElement, [refractorPluginElementIdentity({ length: 36 })]);
523
476
 
524
477
  objectElement.id; // OnReGGrO7fMd9ztacvGfwGbOdGKuOFLiQQ1W
525
478
  objectElement.getMember('a').key.id; // BN6rHsmqI56SMQ1elshtbgRVECtEWNYS9lmd
526
479
  objectElement.getMember('a').value.id; // Ki4tWmf9xw9Lwb8MxkXJq1uONmJrmhXifmsI
527
480
  ```
528
481
 
529
- #### Semantic element identity plugin
482
+ ### Semantic element identity plugin
530
483
 
531
- `apidom` package comes with `refractorPluginSemanticElementIdentity`. When used, this plugin will
484
+ `apidom-core` package comes with `refractorPluginSemanticElementIdentity`. When used, this plugin will
532
485
  assign unique ID to all non-primitive elements in ApiDOM tree. Primitive elements include
533
- `ObjectElement`, `ArrayElement`, `StringElement`, `BooleanElement`, `NullElement` and `NumberElement`.
486
+ `ObjectElement`, `ArrayElement`, `StringElement`, `BooleanElement`, `NullElement`, `NumberElement`, and `MemberElement`.
534
487
 
535
488
  ```js
536
- import { refractorPluginSemanticElementIdentity, ObjectElement } from '@speclynx/apidom-core';
537
- import { InfoElement } from '@speclynx/apidom-ns-openapi-3-1';
538
-
539
- const infoElement = InfoElement.refract({ title: 'title' });
540
- const objectElement = ObjectElement.refract({ a: 'b', info: infoElement }, {
541
- plugins: [
542
- refractorPluginSemanticElementIdentity(),
543
- ]
544
- });
489
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
490
+ import { refractorPluginSemanticElementIdentity, dispatchRefractorPlugins, from } from '@speclynx/apidom-core';
545
491
 
546
- objectElement.id; // ''
547
- objectElement.getMember('a').key.id; // ''
548
- objectElement.getMember('a').value.id; // ''
549
- objectElement.getMember('info').key.id; // ''
550
- objectElement.getMember('info').value.id; // '8RaWF9'
551
- ```
552
-
553
- You can configure the plugin to generate unique IDs in the specific length:
492
+ // Create a semantic element (element with non-primitive name)
493
+ class InfoElement extends ObjectElement {
494
+ constructor(...args) {
495
+ super(...args);
496
+ this.element = 'info';
497
+ }
498
+ }
554
499
 
555
- ```js
556
- import { refractorPluginSemanticElementIdentity, ObjectElement } from '@speclynx/apidom-core';
557
- import { InfoElement } from '@speclynx/apidom-ns-openapi-3-1';
558
-
559
- const infoElement = InfoElement.refract({ title: 'title' });
560
- const objectElement = ObjectElement.refract({ a: 'b', info: infoElement }, {
561
- plugins: [
562
- refractorPluginSemanticElementIdentity({ length: 36 }),
563
- ]
564
- });
500
+ const infoElement = new InfoElement({ title: 'title' });
501
+ const objectElement = from({ a: 'b', info: infoElement });
502
+ dispatchRefractorPlugins(objectElement, [refractorPluginSemanticElementIdentity()]);
565
503
 
566
504
  objectElement.id; // ''
567
505
  objectElement.getMember('a').key.id; // ''
568
506
  objectElement.getMember('a').value.id; // ''
569
507
  objectElement.getMember('info').key.id; // ''
570
- objectElement.getMember('info').value.id; // 'OnReGGrO7fMd9ztacvGfwGbOdGKuOFLiQQ1W'
571
- ```
572
-
573
- ---
574
-
575
- ## Traversal
576
-
577
- `apidom` comes with its own traversal algorithm along with couple of convenient abstractions on top of it.
578
-
579
- ### visit
580
-
581
- [visit](https://github.com/speclynx/apidom/blob/main/packages/apidom-core/src/traversal/visitor.ts#L104-L103) will walk through an AST using a depth first traversal, calling
582
- the visitor's enter function at each node in the traversal, and calling the
583
- leave function after visiting that node and all of its child nodes.
584
-
585
- By returning different values from the enter and leave functions, the
586
- behavior of the visitor can be altered, including skipping over a sub-tree of
587
- the ApiDOM (by returning false), editing the ApiDOM by returning a value or null
588
- to remove the value, or to stop the whole traversal by returning [BREAK](https://github.com/speclynx/apidom/blob/main/packages/apidom-core/src/index.ts#L52).
589
-
590
- When using `visit` to edit an ApiDOM, the original ApiDOM will not be modified, and
591
- a new version of the ApiDOM with the changes applied will be returned from the
592
- visit function.
593
-
594
- ```js
595
- import { visit, ObjectElement, NumberElement } from '@speclynx/apidom-core';
596
-
597
- const visitor = {
598
- NumberElement(numberElement) {
599
- return new NumberElement(2);
600
- },
601
- };
602
- const element = new ObjectElement({ a: 1 });
603
-
604
- const newElement = visit(element, visitor); // => ObjectElement<{a: 2}>
605
- ```
606
-
607
- This function originally comes from [@speclynx/apidom-ast package](https://github.com/speclynx/apidom/blob/main/packages/apidom-ast/src/visitor.ts)
608
- and is originally designed to work with [CST](https://en.wikipedia.org/wiki/Parse_tree). `apidom` package
609
- imports it, specializes it to work with ApiDOM and re-export it.
610
-
611
- All following algorithms are based on `visit` function.
612
-
613
- ### filter
614
-
615
- Finds all elements matching the predicate.
616
-
617
- ```js
618
- import { ObjectElement, filter, isNumberElement } from '@speclynx/apidom-core'
619
-
620
- const objElement = new ObjectElement({ a: 'b', c: 2 });
621
-
622
- filter(isNumberElement, objElement); // => ArraySlice<[NumberElement<2>]>
623
- ```
624
-
625
- ### find
626
-
627
- Find first element that satisfies the provided predicate.
628
-
629
- ```js
630
- import { ObjectElement, find, isMemberElement } from '@speclynx/apidom-core'
631
-
632
- const objElement = new ObjectElement({ a: 'b', c: 2 });
633
-
634
- find(isNumberElement, objElement); // => NumberElement<2>
635
- ```
636
-
637
- ### findAtOffset
638
-
639
- ApiDOM nodes can be associated with source maps. This function finds the most inner node at the given offset.
640
- If includeRightBound is set, also finds nodes that end at the given offset.
641
-
642
- ```js
643
- import { findAtOffset } from '@speclynx/apidom-core'
644
-
645
- findAtOffset(3, elementWithSourceMaps); // => returns most inner node at offset 3
646
- ```
647
-
648
- ### reject
649
-
650
- Complement of [filter](#filter).
651
-
652
- ```js
653
- import { ArrayElement, reject, isNumberElement } from '@speclynx/apidom-core'
654
-
655
- const arrayElement = new ArrayElement([1, 'a']);
656
-
657
- reject(isNumberElement, arrayElement); // => ArraySlice<[StringElement<'a'>]>
658
- ```
659
-
660
- ### some
661
-
662
- Tests whether at least one element passes the predicate.
663
-
664
- ```js
665
- import { ArrayElement, some, isNumberElement } from '@speclynx/apidom-core'
666
-
667
- const arrayElement = new ArrayElement([1, 'a']);
668
-
669
- some(isNumberElement, arrayElement); // => true
670
- ```
671
-
672
- ### traverse
673
-
674
- Executes the callback on this element and all descendants.
675
-
676
- ```js
677
- import { ArrayElement, traverse } from '@speclynx/apidom-core'
678
-
679
- const arrayElement = new ArrayElement([1, 'a']);
680
-
681
- traverse(console.dir, arrayElement); // => prints ArrayElement, NumberElement, StringElement in this order
682
- ```
683
-
684
- The execution of the callback can be controlled further by providing a predicate.
685
-
686
- ```js
687
- import { ArrayElement, traverse, isNumberElement } from '@speclynx/apidom-core'
688
-
689
- const arrayElement = new ArrayElement([1, 'a']);
690
-
691
- traverse({ callback: console.dir, predicate: isNumberElement }, arrayElement); // => prints NumberElement<1>
692
- ```
693
-
694
- ### parents
695
-
696
- Computes upwards edges from every child to its parent.
697
-
698
- #### ObjectElement example
699
-
700
- ```js
701
- import { parents, ObjectElement } from '@speclynx/apidom-core';
702
-
703
- const objectElement = new ObjectElement({ key: 'value' });
704
- const memberElement = objectElement.getMember('key');
705
- const { key: keyElement, value: valueElement } = memberElement;
706
-
707
- const parentEdges = parents(objectElement); // => WeakMap<ChildElement, ParentElement>
708
-
709
- parentEdges.get(memberElement) === objectElement; // => true
710
- parentEdges.get(keyElement) === memberElement; // => true
711
- parentEdges.get(valueElement) === memberElement; // => true
508
+ objectElement.getMember('info').value.id; // '8RaWF9'
712
509
  ```
713
510
 
714
- #### ArrayElement example
511
+ You can configure the plugin to generate unique IDs in the specific length:
715
512
 
716
513
  ```js
717
- import { parents, ArrayElement, StringElement } from '@speclynx/apidom-core';
718
-
719
- const itemElement1 = new StringElement('item1');
720
- const itemElement2 = new StringElement('item2');
721
- const arrayElement = new ArrayElement([itemElement1, itemElement2]);
514
+ import { refractorPluginSemanticElementIdentity, dispatchRefractorPlugins, from } from '@speclynx/apidom-core';
722
515
 
723
- const parentEdges = parents(arrayElement); // => WeakMap<ChildElement, ParentElement>
516
+ const objectElement = from({ a: 'b', info: infoElement });
517
+ dispatchRefractorPlugins(objectElement, [refractorPluginSemanticElementIdentity({ length: 36 })]);
724
518
 
725
- parentEdges.get(itemElement1) === arrayElement; // => true
726
- parentEdges.get(itemElement2) === arrayElement; // => true
519
+ objectElement.getMember('info').value.id; // 'OnReGGrO7fMd9ztacvGfwGbOdGKuOFLiQQ1W'
727
520
  ```
728
521
 
729
522
  ---
@@ -773,7 +566,8 @@ Transforms the ApiDOM into JavaScript POJO. This POJO would be the result of int
773
566
  into JavaScript structure. This function can handle cycles in ApiDOM structure.
774
567
 
775
568
  ```js
776
- import { toValue, ObjectElement } from '@speclynx/apidom-core';
569
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
570
+ import { toValue } from '@speclynx/apidom-core';
777
571
 
778
572
  const objElement = new ObjectElement({ a: 'b' });
779
573
 
@@ -785,7 +579,8 @@ toValue(objElement); // => { a: 'b' }
785
579
  Transforms the ApiDOM into JSON string.
786
580
 
787
581
  ```js
788
- import { toJSON, ObjectElement } from '@speclynx/apidom-core';
582
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
583
+ import { toJSON } from '@speclynx/apidom-core';
789
584
 
790
585
  const objElement = new ObjectElement({ a: 'b' });
791
586
 
@@ -794,10 +589,11 @@ toJSON(objElement); // => '{"a":"b"}'
794
589
 
795
590
  ### toYAML
796
591
 
797
- Transforms the ApiDOM into JSON string.
592
+ Transforms the ApiDOM into YAML string.
798
593
 
799
594
  ```js
800
- import { toYAML, ObjectElement } from '@speclynx/apidom-core';
595
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
596
+ import { toYAML } from '@speclynx/apidom-core';
801
597
 
802
598
  const objElement = new ObjectElement({ a: 'b' });
803
599
 
@@ -812,14 +608,15 @@ toYAML(objElement);
812
608
 
813
609
  ### dehydrate
814
610
 
815
- Creates a [refract representation](https://github.com/refractproject/refract-spec) of the an Element.
611
+ Creates a [refract representation](https://github.com/refractproject/refract-spec) of an Element.
816
612
 
817
613
  ```js
818
- import { dehyrate, NumberElement } from '@speclynx/apidom-core';
614
+ import { NumberElement } from '@speclynx/apidom-datamodel';
615
+ import { dehydrate } from '@speclynx/apidom-core';
819
616
 
820
617
  const numberElement = new NumberElement(1);
821
618
 
822
- dehyrate(numberElement); // => { element: 'number', content: 1 }
619
+ dehydrate(numberElement); // => { element: 'number', content: 1 }
823
620
  ```
824
621
 
825
622
  ### S-Expression
@@ -827,7 +624,8 @@ dehyrate(numberElement); // => { element: 'number', content: 1 }
827
624
  Transforms ApiDOM into [symbolic expression](https://en.wikipedia.org/wiki/S-expression).
828
625
 
829
626
  ```js
830
- import { sexprs, ObjectElement } from '@speclynx/apidom-core';
627
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
628
+ import { sexprs } from '@speclynx/apidom-core';
831
629
 
832
630
  const objectElement = new ObjectElement({ a: 1 });
833
631
 
@@ -846,36 +644,10 @@ sexprs(objectElement);
846
644
  Create a [refracted string](https://github.com/refractproject/refract-spec) representation of an Element.
847
645
 
848
646
  ```js
849
- import { toString, NumberElement } from '@speclynx/apidom-core';
647
+ import { NumberElement } from '@speclynx/apidom-datamodel';
648
+ import { toString } from '@speclynx/apidom-core';
850
649
 
851
650
  const numberElement = new NumberElement(1);
852
651
 
853
652
  toString(numberElement); // => '{"element":"number","content":1}'
854
653
  ```
855
-
856
- ## Cloning
857
-
858
- Following functions provide mechanism for creating shallow and deep copies of ApiDOM elements.
859
-
860
- ### Shallow cloning
861
-
862
- Creates shallow clone of ApiDOM element.
863
-
864
- ```js
865
- import { cloneShallow, ObjectElement } from '@speclynx/apidom-core';
866
-
867
- const objectElement = new ObjectElement({ a: 'b' });
868
- const objectElementShallowClone = cloneShallow(objectElement);
869
- ```
870
-
871
- ### Deep cloning
872
-
873
- Creates deep clone of ApiDOM Element.
874
-
875
- ```js
876
- import { cloneDeep, ObjectElement } from '@speclynx/apidom-core';
877
-
878
- const objectElement = new ObjectElement({ a: 'b' });
879
- const objectElementDeepClone = cloneDeep(objectElement);
880
- ```
881
-