@speclynx/apidom-ns-openapi-3-0 4.1.0 → 4.3.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.
@@ -0,0 +1,143 @@
1
+ import { isArrayElement } from '@speclynx/apidom-datamodel';
2
+ import ServersElement from "../../elements/nces/Servers.mjs";
3
+ import PathItemServersElement from "../../elements/nces/PathItemServers.mjs";
4
+ import OperationServersElement from "../../elements/nces/OperationServers.mjs";
5
+ import NormalizeStorage from "./normalize-storage/index.mjs";
6
+ import { refractServer } from "../index.mjs";
7
+ /**
8
+ * Override of Server Objects.
9
+ *
10
+ * List of Server Objects can be defined in OpenAPI 3.0 on multiple levels:
11
+ *
12
+ * - OpenAPI.servers
13
+ * - PathItem.servers
14
+ * - Operation.servers
15
+ *
16
+ * If a servers array is specified at the OpenAPI Object level, it will be overridden by `PathItem`.servers.
17
+ * If a servers array is specified at the Path Item Object or OpenAPI Object level, it will be overridden by Operation.servers.
18
+ * @public
19
+ */
20
+ /**
21
+ * Ensures the OpenAPI document has at least one server defined.
22
+ * If `servers` is missing or empty, adds a default server with `url: "/"`.
23
+ * @public
24
+ */
25
+ const ensureDefaultServer = openapiElement => {
26
+ const isServersUndefined = typeof openapiElement.servers === 'undefined';
27
+ const isServersArray = isArrayElement(openapiElement.servers);
28
+ const isServersEmpty = isServersArray && openapiElement.servers.length === 0;
29
+ const defaultServer = refractServer({
30
+ url: '/'
31
+ });
32
+ if (isServersUndefined || !isServersArray) {
33
+ openapiElement.servers = new ServersElement([defaultServer]);
34
+ } else if (isServersArray && isServersEmpty) {
35
+ openapiElement.servers.push(defaultServer);
36
+ }
37
+ };
38
+
39
+ /**
40
+ * Inherits servers from the OpenAPI root into a PathItem element.
41
+ * If PathItem.servers is missing or empty, copies from OpenAPI.servers.
42
+ * @public
43
+ */
44
+ const inheritServersToPathItem = (pathItemElement, openapiElement) => {
45
+ const isServersUndefined = typeof pathItemElement.servers === 'undefined';
46
+ const isServersArray = isArrayElement(pathItemElement.servers);
47
+ const isServersEmpty = isServersArray && pathItemElement.servers.length === 0;
48
+ const openapiServers = [...(openapiElement.servers ?? [])];
49
+ if (isServersUndefined || !isServersArray) {
50
+ pathItemElement.servers = new PathItemServersElement(openapiServers);
51
+ } else if (isServersArray && isServersEmpty) {
52
+ openapiServers.forEach(server => {
53
+ pathItemElement.servers.push(server);
54
+ });
55
+ }
56
+ };
57
+
58
+ /**
59
+ * Inherits servers from a PathItem into an Operation element.
60
+ * If Operation.servers is missing or empty, copies from PathItem.servers.
61
+ * @public
62
+ */
63
+ const inheritServersToOperation = (operationElement, pathItemElement) => {
64
+ const isServersUndefined = typeof operationElement.servers === 'undefined';
65
+ const isServersArray = isArrayElement(operationElement.servers);
66
+ const isServersEmpty = isServersArray && operationElement.servers.length === 0;
67
+ const pathItemServers = [...(pathItemElement.servers ?? [])];
68
+ if (isServersUndefined || !isServersArray) {
69
+ operationElement.servers = new OperationServersElement(pathItemServers);
70
+ } else if (isServersArray && isServersEmpty) {
71
+ pathItemServers.forEach(server => {
72
+ operationElement.servers.push(server);
73
+ });
74
+ }
75
+ };
76
+
77
+ /**
78
+ * @public
79
+ */
80
+ const plugin = ({
81
+ storageField = 'x-normalized'
82
+ } = {}) => toolbox => {
83
+ const {
84
+ predicates
85
+ } = toolbox;
86
+ let storage;
87
+ return {
88
+ visitor: {
89
+ OpenApi3_0Element: {
90
+ enter(path) {
91
+ const openapiElement = path.node;
92
+ ensureDefaultServer(openapiElement);
93
+ storage = new NormalizeStorage(openapiElement, storageField, 'servers');
94
+ },
95
+ leave() {
96
+ storage = undefined;
97
+ }
98
+ },
99
+ PathItemElement(path) {
100
+ const pathItemElement = path.node;
101
+ const ancestors = path.getAncestorNodes(); // parent to root order
102
+
103
+ // skip visiting this Path Item
104
+ if (ancestors.some(predicates.isComponentsElement)) return;
105
+ if (!ancestors.some(predicates.isOpenApi3_0Element)) return;
106
+ const pathItemJSONPointer = path.formatPath();
107
+
108
+ // skip visiting this Path Item Object if it's already normalized
109
+ if (storage.includes(pathItemJSONPointer)) {
110
+ return;
111
+ }
112
+ const parentOpenapiElement = ancestors.find(predicates.isOpenApi3_0Element);
113
+ if (predicates.isOpenApi3_0Element(parentOpenapiElement)) {
114
+ inheritServersToPathItem(pathItemElement, parentOpenapiElement);
115
+ storage.append(pathItemJSONPointer);
116
+ }
117
+ },
118
+ OperationElement(path) {
119
+ const operationElement = path.node;
120
+ const ancestors = path.getAncestorNodes(); // parent to root order
121
+
122
+ // skip visiting this Operation
123
+ if (ancestors.some(predicates.isComponentsElement)) return;
124
+ if (!ancestors.some(predicates.isOpenApi3_0Element)) return;
125
+ const operationJSONPointer = path.formatPath();
126
+
127
+ // skip visiting this Operation Object if it's already normalized
128
+ if (storage.includes(operationJSONPointer)) {
129
+ return;
130
+ }
131
+ const parentPathItemElement = ancestors.find(predicates.isPathItemElement);
132
+ if (predicates.isPathItemElement(parentPathItemElement)) {
133
+ inheritServersToOperation(operationElement, parentPathItemElement);
134
+ storage.append(operationJSONPointer);
135
+ }
136
+ }
137
+ }
138
+ };
139
+ };
140
+ plugin.ensureDefaultServer = ensureDefaultServer;
141
+ plugin.inheritServersToPathItem = inheritServersToPathItem;
142
+ plugin.inheritServersToOperation = inheritServersToOperation;
143
+ export default plugin;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _apidomDatamodel = require("@speclynx/apidom-datamodel");
6
+ class NormalizeStorage {
7
+ internalStore;
8
+ constructor(storageElement, storageField, storageSubField) {
9
+ this.storageElement = storageElement;
10
+ this.storageField = storageField;
11
+ this.storageSubField = storageSubField;
12
+ }
13
+ get store() {
14
+ if (this.internalStore === undefined) {
15
+ let rootStore = this.storageElement.get(this.storageField);
16
+ if (!(0, _apidomDatamodel.isObjectElement)(rootStore)) {
17
+ rootStore = new _apidomDatamodel.ObjectElement();
18
+ this.storageElement.set(this.storageField, rootStore);
19
+ }
20
+ let store = rootStore.get(this.storageSubField);
21
+ if (!(0, _apidomDatamodel.isArrayElement)(store)) {
22
+ store = new _apidomDatamodel.ArrayElement();
23
+ rootStore.set(this.storageSubField, store);
24
+ }
25
+ this.internalStore = store;
26
+ }
27
+ return this.internalStore;
28
+ }
29
+ append(pointer) {
30
+ if (!this.includes(pointer)) {
31
+ this.store.push(pointer);
32
+ }
33
+ }
34
+ includes(pointer) {
35
+ return this.store.includes(pointer);
36
+ }
37
+ }
38
+ var _default = exports.default = NormalizeStorage;
@@ -0,0 +1,34 @@
1
+ import { ArrayElement, ObjectElement, isObjectElement, isArrayElement } from '@speclynx/apidom-datamodel';
2
+ class NormalizeStorage {
3
+ internalStore;
4
+ constructor(storageElement, storageField, storageSubField) {
5
+ this.storageElement = storageElement;
6
+ this.storageField = storageField;
7
+ this.storageSubField = storageSubField;
8
+ }
9
+ get store() {
10
+ if (this.internalStore === undefined) {
11
+ let rootStore = this.storageElement.get(this.storageField);
12
+ if (!isObjectElement(rootStore)) {
13
+ rootStore = new ObjectElement();
14
+ this.storageElement.set(this.storageField, rootStore);
15
+ }
16
+ let store = rootStore.get(this.storageSubField);
17
+ if (!isArrayElement(store)) {
18
+ store = new ArrayElement();
19
+ rootStore.set(this.storageSubField, store);
20
+ }
21
+ this.internalStore = store;
22
+ }
23
+ return this.internalStore;
24
+ }
25
+ append(pointer) {
26
+ if (!this.includes(pointer)) {
27
+ this.store.push(pointer);
28
+ }
29
+ }
30
+ includes(pointer) {
31
+ return this.store.includes(pointer);
32
+ }
33
+ }
34
+ export default NormalizeStorage;
@@ -12,12 +12,17 @@ var _namespace = _interopRequireDefault(require("../namespace.cjs"));
12
12
  * @public
13
13
  */
14
14
 
15
+ /**
16
+ * @public
17
+ */
15
18
  const createToolbox = () => {
16
19
  const namespace = new _apidomDatamodel.Namespace();
17
20
  const predicates = {
18
21
  ...refractorPredicates,
19
22
  ...openApi3_0Predicates,
20
- isStringElement: _apidomDatamodel.isStringElement
23
+ isStringElement: _apidomDatamodel.isStringElement,
24
+ isArrayElement: _apidomDatamodel.isArrayElement,
25
+ isObjectElement: _apidomDatamodel.isObjectElement
21
26
  };
22
27
  namespace.use(_namespace.default);
23
28
  return {
@@ -1,7 +1,10 @@
1
- import { isStringElement, Namespace } from '@speclynx/apidom-datamodel';
1
+ import { isStringElement, isArrayElement, isObjectElement, Namespace } from '@speclynx/apidom-datamodel';
2
2
  import * as openApi3_0Predicates from "../predicates.mjs";
3
3
  import * as refractorPredicates from "./predicates.mjs";
4
4
  import openApi3_0Namespace from "../namespace.mjs";
5
+ /**
6
+ * @public
7
+ */
5
8
  /**
6
9
  * @public
7
10
  */
@@ -10,7 +13,9 @@ const createToolbox = () => {
10
13
  const predicates = {
11
14
  ...refractorPredicates,
12
15
  ...openApi3_0Predicates,
13
- isStringElement
16
+ isStringElement,
17
+ isArrayElement,
18
+ isObjectElement
14
19
  };
15
20
  namespace.use(openApi3_0Namespace);
16
21
  return {
@@ -488,6 +488,11 @@ export declare class ContentVisitor extends BaseMapVisitor {
488
488
  constructor(options: BaseMapVisitorOptions);
489
489
  }
490
490
 
491
+ /**
492
+ * @public
493
+ */
494
+ export declare const createToolbox: () => Toolbox;
495
+
491
496
  /**
492
497
  * @public
493
498
  */
@@ -1815,6 +1820,111 @@ export declare type RefractorPlugin = (toolbox: Toolbox) => {
1815
1820
  post?: () => void;
1816
1821
  };
1817
1822
 
1823
+ /**
1824
+ * @public
1825
+ */
1826
+ export declare const refractorPluginNormalizeParameters: {
1827
+ ({ storageField }?: RefractorPluginNormalizeParametersOptions): (toolbox: Toolbox) => {
1828
+ visitor: {
1829
+ OpenApi3_0Element: {
1830
+ enter(path: Path<OpenApi3_0Element>): void;
1831
+ leave(): void;
1832
+ };
1833
+ OperationElement: {
1834
+ leave(path: Path<OperationElement>): void;
1835
+ };
1836
+ };
1837
+ };
1838
+ inheritParametersToOperation: (operationElement: OperationElement, pathItemElement: PathItemElement) => void;
1839
+ };
1840
+
1841
+ /**
1842
+ * Inheritance of Parameter Objects.
1843
+ *
1844
+ * OpenAPI 3.0 specification excerpt that defines the inheritance behavior:
1845
+ *
1846
+ * A list of parameters that are applicable for this operation. If a parameter is already defined at the Path Item,
1847
+ * the new definition will override it but can never remove it. The list MUST NOT include duplicated parameters.
1848
+ * A unique parameter is defined by a combination of a name and location.
1849
+ *
1850
+ * NOTE: this plugin is idempotent
1851
+ * @public
1852
+ */
1853
+ export declare interface RefractorPluginNormalizeParametersOptions {
1854
+ storageField?: string;
1855
+ }
1856
+
1857
+ /**
1858
+ * @public
1859
+ */
1860
+ export declare const refractorPluginNormalizeSecurityRequirements: {
1861
+ ({ storageField }?: RefractorPluginNormalizeSecurityRequirementsOptions): (toolbox: Toolbox) => {
1862
+ visitor: {
1863
+ OpenApi3_0Element: {
1864
+ enter(path: Path<OpenApi3_0Element>): void;
1865
+ leave(): void;
1866
+ };
1867
+ OperationElement: {
1868
+ leave(path: Path<OperationElement>): void;
1869
+ };
1870
+ };
1871
+ };
1872
+ inheritSecurityToOperation: (operationElement: OperationElement, openapiElement: OpenApi3_0Element) => void;
1873
+ };
1874
+
1875
+ /**
1876
+ * Override of Security Requirement Objects.
1877
+ *
1878
+ * OpenAPI 3.0 specification excerpt that defines the override behavior:
1879
+ *
1880
+ * Operation.security definition overrides any declared top-level security.
1881
+ * To remove a top-level security declaration, an empty array can be used.
1882
+ * When a list of Security Requirement Objects is defined on the OpenAPI Object or Operation Object,
1883
+ * only one of the Security Requirement Objects in the list needs to be satisfied to authorize the request.
1884
+ *
1885
+ * NOTE: this plugin is idempotent
1886
+ * @public
1887
+ */
1888
+ export declare interface RefractorPluginNormalizeSecurityRequirementsOptions {
1889
+ storageField?: string;
1890
+ }
1891
+
1892
+ /**
1893
+ * @public
1894
+ */
1895
+ export declare const refractorPluginNormalizeServers: {
1896
+ ({ storageField }?: RefractorPluginNormalizeServersOptions): (toolbox: Toolbox) => {
1897
+ visitor: {
1898
+ OpenApi3_0Element: {
1899
+ enter(path: Path<OpenApi3_0Element>): void;
1900
+ leave(): void;
1901
+ };
1902
+ PathItemElement(path: Path<PathItemElement>): void;
1903
+ OperationElement(path: Path<OperationElement>): void;
1904
+ };
1905
+ };
1906
+ ensureDefaultServer: (openapiElement: OpenApi3_0Element) => void;
1907
+ inheritServersToPathItem: (pathItemElement: PathItemElement, openapiElement: OpenApi3_0Element) => void;
1908
+ inheritServersToOperation: (operationElement: OperationElement, pathItemElement: PathItemElement) => void;
1909
+ };
1910
+
1911
+ /**
1912
+ * Override of Server Objects.
1913
+ *
1914
+ * List of Server Objects can be defined in OpenAPI 3.0 on multiple levels:
1915
+ *
1916
+ * - OpenAPI.servers
1917
+ * - PathItem.servers
1918
+ * - Operation.servers
1919
+ *
1920
+ * If a servers array is specified at the OpenAPI Object level, it will be overridden by `PathItem`.servers.
1921
+ * If a servers array is specified at the Path Item Object or OpenAPI Object level, it will be overridden by Operation.servers.
1922
+ * @public
1923
+ */
1924
+ export declare interface RefractorPluginNormalizeServersOptions {
1925
+ storageField?: string;
1926
+ }
1927
+
1818
1928
  /**
1819
1929
  * @public
1820
1930
  */