@speclynx/apidom-reference 4.11.1 → 4.12.0

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 (123) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +215 -3
  3. package/dist/apidom-reference.browser.js +1339 -153
  4. package/dist/apidom-reference.browser.min.js +1 -1
  5. package/package.json +35 -30
  6. package/src/File.cjs +3 -1
  7. package/src/Reference.cjs +3 -1
  8. package/src/ReferenceSet.cjs +3 -1
  9. package/src/bundle/index.cjs +9 -1
  10. package/src/bundle/index.mjs +6 -0
  11. package/src/bundle/strategies/BundleStrategy.cjs +3 -1
  12. package/src/bundle/strategies/openapi-3-0/index.cjs +94 -0
  13. package/src/bundle/strategies/openapi-3-0/index.mjs +81 -0
  14. package/src/bundle/strategies/openapi-3-0/visitor.cjs +650 -0
  15. package/src/bundle/strategies/openapi-3-0/visitor.mjs +642 -0
  16. package/src/bundle/strategies/openapi-3-1/index.cjs +3 -1
  17. package/src/bundle/util.cjs +42 -0
  18. package/src/bundle/util.mjs +33 -0
  19. package/src/configuration/empty.cjs +9 -2
  20. package/src/configuration/saturated.cjs +19 -11
  21. package/src/configuration/saturated.mjs +2 -1
  22. package/src/dereference/index.cjs +3 -1
  23. package/src/dereference/strategies/DereferenceStrategy.cjs +3 -1
  24. package/src/dereference/strategies/apidom/index.cjs +9 -2
  25. package/src/dereference/strategies/apidom/selectors/element-id.cjs +9 -2
  26. package/src/dereference/strategies/apidom/visitor.cjs +3 -1
  27. package/src/dereference/strategies/arazzo-1/index.cjs +34 -7
  28. package/src/dereference/strategies/arazzo-1/selectors/$anchor.cjs +46 -10
  29. package/src/dereference/strategies/arazzo-1/selectors/uri.cjs +22 -6
  30. package/src/dereference/strategies/arazzo-1/source-descriptions.cjs +3 -1
  31. package/src/dereference/strategies/arazzo-1/util.cjs +16 -4
  32. package/src/dereference/strategies/arazzo-1/visitor.cjs +3 -1
  33. package/src/dereference/strategies/asyncapi-2/index.cjs +9 -2
  34. package/src/dereference/strategies/asyncapi-2/visitor.cjs +3 -1
  35. package/src/dereference/strategies/openapi-2/index.cjs +9 -2
  36. package/src/dereference/strategies/openapi-2/visitor.cjs +3 -1
  37. package/src/dereference/strategies/openapi-3-0/index.cjs +9 -2
  38. package/src/dereference/strategies/openapi-3-0/visitor.cjs +3 -1
  39. package/src/dereference/strategies/openapi-3-1/index.cjs +28 -6
  40. package/src/dereference/strategies/openapi-3-1/selectors/$anchor.cjs +22 -5
  41. package/src/dereference/strategies/openapi-3-1/selectors/uri.cjs +16 -4
  42. package/src/dereference/strategies/openapi-3-1/util.cjs +3 -1
  43. package/src/dereference/strategies/openapi-3-1/visitor.cjs +3 -1
  44. package/src/dereference/strategies/overlay-1/extends.cjs +3 -1
  45. package/src/dereference/strategies/overlay-1/index.cjs +9 -2
  46. package/src/dereference/util.cjs +3 -1
  47. package/src/errors/BundleError.cjs +4 -2
  48. package/src/errors/BundleError.mjs +2 -2
  49. package/src/errors/DereferenceError.cjs +3 -1
  50. package/src/errors/EvaluationElementIdError.cjs +3 -1
  51. package/src/errors/EvaluationJsonSchema$anchorError.cjs +3 -1
  52. package/src/errors/EvaluationJsonSchemaUriError.cjs +3 -1
  53. package/src/errors/InvalidJsonSchema$anchorError.cjs +3 -1
  54. package/src/errors/JsonSchema$anchorError.cjs +3 -1
  55. package/src/errors/JsonSchemaUriError.cjs +3 -1
  56. package/src/errors/MaximumBundleDepthError.cjs +3 -1
  57. package/src/errors/MaximumDereferenceDepthError.cjs +3 -1
  58. package/src/errors/MaximumResolveDepthError.cjs +3 -1
  59. package/src/errors/ParseError.cjs +3 -1
  60. package/src/errors/ParserError.cjs +3 -1
  61. package/src/errors/PluginError.cjs +3 -1
  62. package/src/errors/ResolveError.cjs +3 -1
  63. package/src/errors/ResolverError.cjs +3 -1
  64. package/src/errors/UnmatchedBundleStrategyError.cjs +3 -1
  65. package/src/errors/UnmatchedDereferenceStrategyError.cjs +3 -1
  66. package/src/errors/UnmatchedParserError.cjs +3 -1
  67. package/src/errors/UnmatchedResolveStrategyError.cjs +3 -1
  68. package/src/errors/UnmatchedResolverError.cjs +3 -1
  69. package/src/errors/UnresolvableReferenceError.cjs +8 -3
  70. package/src/errors/UnresolvableReferenceError.mjs +5 -2
  71. package/src/index.cjs +209 -36
  72. package/src/options/index.cjs +71 -2
  73. package/src/options/index.mjs +68 -1
  74. package/src/options/util.cjs +3 -1
  75. package/src/parse/index.cjs +3 -1
  76. package/src/parse/parsers/Parser.cjs +3 -1
  77. package/src/parse/parsers/apidom-json/index.cjs +3 -1
  78. package/src/parse/parsers/arazzo-json-1/index.cjs +9 -2
  79. package/src/parse/parsers/arazzo-json-1/source-descriptions.cjs +3 -1
  80. package/src/parse/parsers/arazzo-yaml-1/index.cjs +9 -2
  81. package/src/parse/parsers/arazzo-yaml-1/source-descriptions.cjs +3 -1
  82. package/src/parse/parsers/asyncapi-json-2/index.cjs +3 -1
  83. package/src/parse/parsers/asyncapi-yaml-2/index.cjs +3 -1
  84. package/src/parse/parsers/binary/index-browser.cjs +3 -1
  85. package/src/parse/parsers/binary/index-node.cjs +3 -1
  86. package/src/parse/parsers/json/index.cjs +3 -1
  87. package/src/parse/parsers/openapi-json-2/index.cjs +3 -1
  88. package/src/parse/parsers/openapi-json-3-0/index.cjs +3 -1
  89. package/src/parse/parsers/openapi-json-3-1/index.cjs +3 -1
  90. package/src/parse/parsers/openapi-yaml-2/index.cjs +3 -1
  91. package/src/parse/parsers/openapi-yaml-3-0/index.cjs +3 -1
  92. package/src/parse/parsers/openapi-yaml-3-1/index.cjs +3 -1
  93. package/src/parse/parsers/overlay-json-1/extends.cjs +3 -1
  94. package/src/parse/parsers/overlay-json-1/index.cjs +9 -2
  95. package/src/parse/parsers/overlay-yaml-1/extends.cjs +10 -4
  96. package/src/parse/parsers/overlay-yaml-1/index.cjs +9 -2
  97. package/src/parse/parsers/yaml-1-2/index.cjs +3 -1
  98. package/src/resolve/index.cjs +3 -1
  99. package/src/resolve/resolvers/HTTPResolver.cjs +3 -1
  100. package/src/resolve/resolvers/Resolver.cjs +3 -1
  101. package/src/resolve/resolvers/file/index-browser.cjs +3 -1
  102. package/src/resolve/resolvers/file/index-node.cjs +3 -1
  103. package/src/resolve/resolvers/http-axios/cache/MemoryCache.cjs +3 -1
  104. package/src/resolve/resolvers/http-axios/index.cjs +3 -1
  105. package/src/resolve/strategies/ResolveStrategy.cjs +3 -1
  106. package/src/resolve/strategies/apidom/index.cjs +3 -1
  107. package/src/resolve/strategies/arazzo-1/index.cjs +3 -1
  108. package/src/resolve/strategies/asyncapi-2/index.cjs +3 -1
  109. package/src/resolve/strategies/openapi-2/index.cjs +3 -1
  110. package/src/resolve/strategies/openapi-3-0/index.cjs +3 -1
  111. package/src/resolve/strategies/openapi-3-1/index.cjs +3 -1
  112. package/src/resolve/strategies/overlay-1/index.cjs +3 -1
  113. package/src/resolve/util.cjs +3 -1
  114. package/src/util/plugins.cjs +3 -1
  115. package/src/util/url.cjs +3 -1
  116. package/types/apidom-reference.d.ts +41 -2
  117. package/types/bundle/strategies/openapi-3-0/index.d.ts +31 -0
  118. package/types/bundle/strategies/openapi-3-0/visitor.d.ts +131 -0
  119. package/types/bundle/util.d.ts +22 -0
  120. package/types/errors/BundleError.d.ts +2 -2
  121. package/types/errors/UnresolvableReferenceError.d.ts +5 -2
  122. package/types/index.d.ts +1 -0
  123. package/types/options/index.d.ts +33 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [4.12.0](https://github.com/speclynx/apidom/compare/v4.11.1...v4.12.0) (2026-06-23)
7
+
8
+ ### Features
9
+
10
+ - **reference:** add OpenAPI 3.0 bundle strategy ([#352](https://github.com/speclynx/apidom/issues/352)) ([982860e](https://github.com/speclynx/apidom/commit/982860e6db5c6a122e69b34bfdd02f5f99cbbb9a))
11
+
6
12
  ## [4.11.1](https://github.com/speclynx/apidom/compare/v4.11.0...v4.11.1) (2026-06-10)
7
13
 
8
14
  **Note:** Version bump only for package @speclynx/apidom-reference
package/README.md CHANGED
@@ -2707,12 +2707,114 @@ await bundle('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/e
2707
2707
  #### [Bundle strategies](https://github.com/speclynx/apidom/tree/main/packages/apidom-reference/src/bundle/strategies)
2708
2708
 
2709
2709
  Bundle strategy determines how a document is bundled into a Compound Document. Depending on document `mediaType` option,
2710
- every strategy differs significantly. `Bundle component` comes with single (1) default bundle strategy.
2710
+ every strategy differs significantly. `Bundle component` comes with two (2) default bundle strategies.
2711
+
2712
+ ##### [openapi-3-0](https://github.com/speclynx/apidom/tree/main/packages/apidom-reference/src/bundle/strategies/openapi-3-0)
2713
+
2714
+ Bundle strategy for bundling [OpenApi 3.0.x](https://spec.openapis.org/oas/v3.0.4.html) definitions.
2715
+
2716
+ It produces a self-contained, transferable Compound Document: every external reference is resolved and lifted
2717
+ into the appropriate `components` field, and the referencing `$ref` is rewritten to an internal JSON Pointer.
2718
+ External references that have no Components Object field in OpenAPI 3.0 are handled differently — external
2719
+ Path Item Objects and Example Object `externalValue` content are inlined in place, and an external Link Object
2720
+ `operationRef` is rewritten to an absolute URI so the link stays resolvable. Multiple references to the
2721
+ **same** external target (same document URI and JSON Pointer) are collapsed into a single component; distinct
2722
+ targets each get their own component, even when their content happens to be identical. Internal references are
2723
+ preserved untouched; only a self-file reference (e.g. `./root.json#/components/schemas/Pet`) is normalized to a
2724
+ bare fragment (`#/components/schemas/Pet`) so the bundled document remains transferable.
2725
+
2726
+ Supported media types:
2727
+
2728
+ ```js
2729
+ [
2730
+ 'application/openapi;version=3.0.0',
2731
+ 'application/openapi+json;version=3.0.0',
2732
+ 'application/openapi+yaml;version=3.0.0',
2733
+ 'application/openapi;version=3.0.1',
2734
+ 'application/openapi+json;version=3.0.1',
2735
+ 'application/openapi+yaml;version=3.0.1',
2736
+ 'application/openapi;version=3.0.2',
2737
+ 'application/openapi+json;version=3.0.2',
2738
+ 'application/openapi+yaml;version=3.0.2',
2739
+ 'application/openapi;version=3.0.3',
2740
+ 'application/openapi+json;version=3.0.3',
2741
+ 'application/openapi+yaml;version=3.0.3',
2742
+ 'application/openapi;version=3.0.4',
2743
+ 'application/openapi+json;version=3.0.4',
2744
+ 'application/openapi+yaml;version=3.0.4'
2745
+ ]
2746
+ ```
2747
+
2748
+ This strategy accepts the following options:
2749
+
2750
+ This strategy's behavior is controlled by the following `bundle` options:
2751
+
2752
+ ```js
2753
+ import { bundle } from '@speclynx/apidom-reference';
2754
+
2755
+ await bundle('/home/user/oas.json', {
2756
+ parse: {
2757
+ mediaType: 'application/openapi+json;version=3.0.4',
2758
+ },
2759
+ bundle: {
2760
+ // how hoisted components are named
2761
+ componentNamesStrategy: 'basename',
2762
+ // how a collision-forced rename is reported
2763
+ onComponentNameCollision: 'warn',
2764
+ },
2765
+ });
2766
+ ```
2767
+
2768
+ `componentNamesStrategy` determines how hoisted components are named:
2769
+
2770
+ - `'basename'` (default) — derive the name from the referenced JSON Pointer (its last token),
2771
+ falling back to the referenced file's basename.
2772
+ - `'title'` — derive Schema Object names from their `title` field (PascalCased and sanitized),
2773
+ falling back to `'basename'` when no usable title is present.
2774
+ - a resolver function `({ element, field, jsonPointer, baseURI }) => string` — returns the base name;
2775
+ collision suffixing is still applied on top of the returned value.
2776
+
2777
+ `onComponentNameCollision` determines how a rename forced by two distinct targets resolving to the same
2778
+ component name is reported:
2779
+
2780
+ - `'warn'` (default) — append a `warning` annotation to the returned `ParseResultElement`.
2781
+ - `'off'` — rename silently.
2782
+ - `'error'` — throw a `BundleError` instead of renaming.
2783
+
2784
+ Both options are top-level `bundle` fields that apply to every bundle strategy. To override them for a
2785
+ specific strategy only, use `bundle.strategyOpts` keyed by strategy name (strategy specific options take
2786
+ precedence over the top-level ones):
2787
+
2788
+ ```js
2789
+ await bundle('/home/user/oas.json', {
2790
+ parse: {
2791
+ mediaType: 'application/openapi+json;version=3.0.4',
2792
+ },
2793
+ bundle: {
2794
+ strategyOpts: {
2795
+ 'openapi-3-0': {
2796
+ onComponentNameCollision: 'error',
2797
+ },
2798
+ },
2799
+ },
2800
+ });
2801
+ ```
2802
+
2803
+ Hoisted components are annotated with a `ref-origin` meta field pointing at their source document.
2804
+
2805
+ The bundling process is **immutable** by default (`bundle.immutable: true`) — the original ApiDOM and any
2806
+ pre-computed `bundle.refSet` are deep cloned before bundling, so they are never mutated. Set
2807
+ `bundle.immutable` to `false` to bundle in place (faster, no deep cloning) when you don't need to retain
2808
+ the original.
2711
2809
 
2712
2810
  ##### [openapi-3-1](https://github.com/speclynx/apidom/tree/main/packages/apidom-reference/src/bundle/strategies/openapi-3-1)
2713
2811
 
2714
2812
  Bundle strategy for bundling [OpenApi 3.1.x](https://spec.openapis.org/oas/v3.1.2.html) definitions.
2715
2813
 
2814
+ > **Note:** this strategy is **not implemented yet**. It matches OpenAPI 3.1.x
2815
+ > documents but currently returns the parse result unchanged (no references are
2816
+ > resolved or hoisted). For real bundling, use OpenAPI 3.0.x for now.
2817
+
2716
2818
  Supported media types:
2717
2819
 
2718
2820
  ```js
@@ -2741,6 +2843,7 @@ returns `true` or until entire list of strategies is exhausted (throws error).
2741
2843
 
2742
2844
  ```js
2743
2845
  [
2846
+ new OpenAPI3_0BundleStrategy(),
2744
2847
  new OpenAPI3_1BundleStrategy(),
2745
2848
  ]
2746
2849
  ```
@@ -2750,10 +2853,12 @@ It's possible to **change** strategies **order globally** by mutating global `bu
2750
2853
 
2751
2854
  ```js
2752
2855
  import { options } from '@speclynx/apidom-reference';
2856
+ import OpenAPI3_0BundleStrategy from '@speclynx/apidom-reference/bundle/strategies/openapi-3-0'
2753
2857
  import OpenAPI3_1BundleStrategy from '@speclynx/apidom-reference/bundle/strategies/openapi-3-1'
2754
2858
 
2755
- options.dereference.strategies = [
2756
- new OpenAPI3_1DereferenceStrategy(),
2859
+ options.bundle.strategies = [
2860
+ new OpenAPI3_1BundleStrategy(),
2861
+ new OpenAPI3_0BundleStrategy(),
2757
2862
  ];
2758
2863
  ```
2759
2864
 
@@ -2761,6 +2866,7 @@ To **change** the strategies **order** on ad-hoc basis:
2761
2866
 
2762
2867
  ```js
2763
2868
  import { bundle } from '@speclynx/apidom-reference';
2869
+ import OpenAPI3_0BundleStrategy from '@speclynx/apidom-reference/bundle/strategies/openapi-3-0'
2764
2870
  import OpenAPI3_1BundleStrategy from '@speclynx/apidom-reference/bundle/strategies/openapi-3-1'
2765
2871
 
2766
2872
  await bundle('/home/user/oas.json', {
@@ -2770,10 +2876,116 @@ await bundle('/home/user/oas.json', {
2770
2876
  bundle: {
2771
2877
  strategies: [
2772
2878
  new OpenAPI3_1BundleStrategy(),
2879
+ new OpenAPI3_0BundleStrategy(),
2773
2880
  ]
2774
2881
  }
2775
2882
  });
2776
2883
  ```
2884
+
2885
+ ##### Bundle strategy plugin options
2886
+
2887
+ Some bundle strategy plugins accept additional options. These can be set globally as top-level
2888
+ `bundle` options (applying to every strategy), or per-strategy via `bundle.strategyOpts` keyed by
2889
+ strategy name (strategy specific options take precedence over the top-level ones).
2890
+
2891
+ To **change** strategy plugin **options globally** by mutating global `bundle` options:
2892
+
2893
+ ```js
2894
+ import { options } from '@speclynx/apidom-reference';
2895
+
2896
+ options.bundle.componentNamesStrategy = 'title';
2897
+ options.bundle.onComponentNameCollision = 'error';
2898
+ ```
2899
+
2900
+ To **change** the bundle strategy plugin **options** on ad-hoc basis:
2901
+
2902
+ ```js
2903
+ import { bundle } from '@speclynx/apidom-reference';
2904
+
2905
+ await bundle('/home/user/oas.json', {
2906
+ parse: { mediaType: 'application/openapi+json;version=3.0.4' },
2907
+ bundle: {
2908
+ componentNamesStrategy: 'title',
2909
+ onComponentNameCollision: 'error',
2910
+ },
2911
+ });
2912
+ ```
2913
+
2914
+ To **override** options for a **single strategy** via `strategyOpts`:
2915
+
2916
+ ```js
2917
+ import { bundle } from '@speclynx/apidom-reference';
2918
+
2919
+ await bundle('/home/user/oas.json', {
2920
+ parse: { mediaType: 'application/openapi+json;version=3.0.4' },
2921
+ bundle: {
2922
+ strategyOpts: {
2923
+ 'openapi-3-0': {
2924
+ componentNamesStrategy: 'title',
2925
+ onComponentNameCollision: 'error',
2926
+ },
2927
+ },
2928
+ },
2929
+ });
2930
+ ```
2931
+
2932
+ ##### Increasing speed of bundle
2933
+
2934
+ Just like dereference, bundling time is the sum of `traversing` + sum of `external resolution per file`.
2935
+ By having a huge number of external dependencies in your definition file, bundling can get quite slow.
2936
+ The same optimization applies: run an `external resolution` first and pass its result to bundling via the
2937
+ `refSet` option. External resolution ignores internal references, so it's theoretically always faster than
2938
+ the bundling.
2939
+
2940
+ ```js
2941
+ import { resolve, bundle } from '@speclynx/apidom-reference';
2942
+
2943
+ const refSet = await resolve('/home/user/oas.json', {
2944
+ parse: { mediaType: 'application/openapi+json;version=3.0.4' },
2945
+ });
2946
+
2947
+ const bundled = await bundle('/home/user/oas.json', {
2948
+ parse: { mediaType: 'application/openapi+json;version=3.0.4' },
2949
+ bundle: { refSet },
2950
+ });
2951
+ ```
2952
+
2953
+ ##### Continue on error
2954
+
2955
+ By default, bundling fails fast on the first unresolvable reference. The `continueOnError` option
2956
+ allows bundling to continue past broken references, collecting errors instead of throwing.
2957
+
2958
+ **Type:** `false | true | ((error: Error) => void)`
2959
+
2960
+ **Default:** `false`
2961
+
2962
+ | Value | Behavior |
2963
+ |---|---|
2964
+ | `false` | Fail fast — throws `UnresolvableReferenceError` on first broken reference |
2965
+ | `true` | Skip unresolvable references silently |
2966
+ | callback | Called for each unresolvable reference with structured error context |
2967
+
2968
+ Unlike dereferencing, a skipped reference is **left in place** — so the bundled document may still
2969
+ contain unresolved external references when `continueOnError` is not `false`. Bundling cannot inline or
2970
+ hoist a reference it could not resolve, so the resulting document is not guaranteed to be self-contained.
2971
+
2972
+ ```js
2973
+ import { bundle, UnresolvableReferenceError } from '@speclynx/apidom-reference';
2974
+
2975
+ const errors = [];
2976
+
2977
+ await bundle('/home/user/oas.json', {
2978
+ parse: { mediaType: 'application/openapi+json;version=3.0.4' },
2979
+ bundle: {
2980
+ continueOnError: (error) => {
2981
+ errors.push(error);
2982
+ },
2983
+ },
2984
+ });
2985
+
2986
+ // errors is an array of UnresolvableReferenceError instances
2987
+ ```
2988
+
2777
2989
  ##### Creating new bundle strategy
2778
2990
 
2779
2991
  Bundle component can be extended by additional strategies. Every strategy is an object that