[d24f17c] | 1 | # @swagger-api/apidom-reference
|
---|
| 2 |
|
---|
| 3 | `@swagger-api/apidom-reference` package contains advanced algorithms for semantic ApiDOM manipulations.
|
---|
| 4 | This package is divided into three (3) main components:
|
---|
| 5 |
|
---|
| 6 | - **[Parse component](#parse-component)**
|
---|
| 7 | - **[Resolve component](#resolve-component)**
|
---|
| 8 | - **[Dereference component](#dereference-component)**
|
---|
| 9 | - **[Bundle component](#bundle-component)**
|
---|
| 10 |
|
---|
| 11 | ## Installation
|
---|
| 12 |
|
---|
| 13 | After [prerequisites](https://github.com/swagger-api/apidom/blob/main/README.md#prerequisites) for installing this package are satisfied, you can install it
|
---|
| 14 | via [npm CLI](https://docs.npmjs.com/cli) by running the following command:
|
---|
| 15 |
|
---|
| 16 | ```sh
|
---|
| 17 | $ npm install @swagger-api/apidom-reference
|
---|
| 18 | ```
|
---|
| 19 |
|
---|
| 20 | ## Configurations
|
---|
| 21 |
|
---|
| 22 | This package has two main exports suitable for different use-cases. **Empty** configuration and **saturated** configuration.
|
---|
| 23 |
|
---|
| 24 | ### Empty configuration
|
---|
| 25 |
|
---|
| 26 | ```js
|
---|
| 27 | import { parse } from '@swagger-api/apidom-reference/configuration/empty';
|
---|
| 28 | import OpenApiJson3_1Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-json-3-1';
|
---|
| 29 |
|
---|
| 30 | await parse('/home/user/oas.json', {
|
---|
| 31 | parse: {
|
---|
| 32 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 33 | parsers: [OpenApiJson3_0Parser({ allowEmpty: true, sourceMap: false })]
|
---|
| 34 | }
|
---|
| 35 | });
|
---|
| 36 | ```
|
---|
| 37 |
|
---|
| 38 | When using this approach, `options` object is not configured with parsers, resolvers or strategies.
|
---|
| 39 | This is suitable for creating **web bundles** and gives you total control of the contents of your bundles.
|
---|
| 40 |
|
---|
| 41 | ### Saturated configuration
|
---|
| 42 |
|
---|
| 43 | ```js
|
---|
| 44 | import { parse } from '@swagger-api/apidom-reference';
|
---|
| 45 | ```
|
---|
| 46 | or
|
---|
| 47 | ```js
|
---|
| 48 | import { parse } from '@swagger-api/apidom-reference/configuration/saturaged';
|
---|
| 49 | ```
|
---|
| 50 |
|
---|
| 51 | Both of above imports are equivalent. This approach is suitable for **Node.js** environments.
|
---|
| 52 | `options` object is pre-configured with all the parsers, resolvers and strategies.
|
---|
| 53 |
|
---|
| 54 | ## Parse component
|
---|
| 55 |
|
---|
| 56 | Parse component consists of implementation of default [parser plugins](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers).
|
---|
| 57 | Defaults parser plugin is a specialized wrapper that wraps one of the ApiDOM parser adapter into specialized API.
|
---|
| 58 | Standard ApiDOM parser adapter can only parse strings. Parser plugins are capable of parsing local filesystem URIs and network URLs.
|
---|
| 59 |
|
---|
| 60 | **Parsing a file localed on local filesystem:**
|
---|
| 61 |
|
---|
| 62 | ```js
|
---|
| 63 | import { parse } from '@swagger-api/apidom-reference';
|
---|
| 64 |
|
---|
| 65 | await parse('/home/user/oas.json', {
|
---|
| 66 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }
|
---|
| 67 | });
|
---|
| 68 | ```
|
---|
| 69 |
|
---|
| 70 | **Parsing an HTTP(S) URL located on internet:**
|
---|
| 71 |
|
---|
| 72 | ```js
|
---|
| 73 | import { parse } from '@swagger-api/apidom-reference';
|
---|
| 74 |
|
---|
| 75 | await parse('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.1/webhook-example.json', {
|
---|
| 76 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }
|
---|
| 77 | })
|
---|
| 78 | ```
|
---|
| 79 |
|
---|
| 80 | Notice how we explicitly pass a `mediaType` parse option. This option is actually **not required**,
|
---|
| 81 | but if not provided, the Parse component will try to identify appropriate parser plugin by file contents, and it's extension (`.json`).
|
---|
| 82 |
|
---|
| 83 | What actually happens if you don't provide `mediaType` parse option?
|
---|
| 84 |
|
---|
| 85 | ```js
|
---|
| 86 | import { parse } from '@swagger-api/apidom-reference';
|
---|
| 87 |
|
---|
| 88 | await parse('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.1/webhook-example.json');
|
---|
| 89 | ```
|
---|
| 90 |
|
---|
| 91 | The result of this operation is going to be generic ApiDOM structure. By analyzing the name of the file
|
---|
| 92 | we can identify the extension of the file as `.json`. At this point we only know
|
---|
| 93 | that this file is probably going to contain JSON string, though we have no idea what data (AsyncApi/OpenApi)
|
---|
| 94 | is encoded within that JSON string.
|
---|
| 95 |
|
---|
| 96 | In the future, we will introduce smart algorithms for looking in the contents of a file and detecting the
|
---|
| 97 | `mediaType` automatically. Of course not explicitly providing `mediaType` has performance implications (running detection)
|
---|
| 98 | so providing it is always a better option.
|
---|
| 99 |
|
---|
| 100 | ### Parser plugins
|
---|
| 101 |
|
---|
| 102 | Parse component comes with number of default parser plugins.
|
---|
| 103 |
|
---|
| 104 | #### [openapi-json-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/openapi-json-2)
|
---|
| 105 |
|
---|
| 106 | Wraps [@swagger-api/apidom-parser-adapter-openapi-json-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-openapi-json-2) package
|
---|
| 107 | and is uniquely identified by `openapi-json-2` name.
|
---|
| 108 |
|
---|
| 109 | Supported media types are:
|
---|
| 110 |
|
---|
| 111 | ```js
|
---|
| 112 | [
|
---|
| 113 | 'application/vnd.oai.openapi;version=2.0',
|
---|
| 114 | 'application/vnd.oai.openapi+json;version=2.0',
|
---|
| 115 | ]
|
---|
| 116 | ```
|
---|
| 117 |
|
---|
| 118 | #### [openapi-json-3-0](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/openapi-json-3-0)
|
---|
| 119 |
|
---|
| 120 | Wraps [@swagger-api/apidom-parser-adapter-openapi-json-3-0](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-openapi-json-3-0) package
|
---|
| 121 | and is uniquely identified by `openapi-json-3-1` name.
|
---|
| 122 |
|
---|
| 123 | Supported media types are:
|
---|
| 124 |
|
---|
| 125 | ```js
|
---|
| 126 | [
|
---|
| 127 | 'application/vnd.oai.openapi;version=3.0.0',
|
---|
| 128 | 'application/vnd.oai.openapi+json;version=3.0.0',
|
---|
| 129 | 'application/vnd.oai.openapi;version=3.0.1',
|
---|
| 130 | 'application/vnd.oai.openapi+json;version=3.0.1',
|
---|
| 131 | 'application/vnd.oai.openapi;version=3.0.2',
|
---|
| 132 | 'application/vnd.oai.openapi+json;version=3.0.2',
|
---|
| 133 | 'application/vnd.oai.openapi;version=3.0.3',
|
---|
| 134 | 'application/vnd.oai.openapi+json;version=3.0.3',
|
---|
| 135 | ]
|
---|
| 136 | ```
|
---|
| 137 |
|
---|
| 138 | #### [openapi-yaml-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/openapi-yaml-2)
|
---|
| 139 |
|
---|
| 140 | Wraps [@swagger-api/apidom-parser-adapter-openapi-yaml-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-openapi-yaml-2) package
|
---|
| 141 | and is uniquely identified by `openapi-yaml-2` name.
|
---|
| 142 |
|
---|
| 143 | Supported media types are:
|
---|
| 144 |
|
---|
| 145 | ```js
|
---|
| 146 | [
|
---|
| 147 | 'application/vnd.oai.openapi;version=2.0',
|
---|
| 148 | 'application/vnd.oai.openapi+yaml;version=2.0',
|
---|
| 149 | ]
|
---|
| 150 | ```
|
---|
| 151 |
|
---|
| 152 | #### [openapi-yaml-3-0](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/openapi-yaml-3-0)
|
---|
| 153 |
|
---|
| 154 | Wraps [@swagger-api/apidom-parser-adapter-openapi-yaml-3-0](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-openapi-yaml-3-0) package
|
---|
| 155 | and is uniquely identified by `openapi-yaml-3-1` name.
|
---|
| 156 |
|
---|
| 157 | Supported media types are:
|
---|
| 158 |
|
---|
| 159 | ```js
|
---|
| 160 | [
|
---|
| 161 | 'application/vnd.oai.openapi;version=3.0.0',
|
---|
| 162 | 'application/vnd.oai.openapi+yaml;version=3.0.0',
|
---|
| 163 | 'application/vnd.oai.openapi;version=3.0.1',
|
---|
| 164 | 'application/vnd.oai.openapi+yaml;version=3.0.1',
|
---|
| 165 | 'application/vnd.oai.openapi;version=3.0.2',
|
---|
| 166 | 'application/vnd.oai.openapi+yaml;version=3.0.2',
|
---|
| 167 | 'application/vnd.oai.openapi;version=3.0.3',
|
---|
| 168 | 'application/vnd.oai.openapi+yaml;version=3.0.3',
|
---|
| 169 | ]
|
---|
| 170 | ```
|
---|
| 171 |
|
---|
| 172 | #### [openapi-json-3-1](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/openapi-json-3-1)
|
---|
| 173 |
|
---|
| 174 | Wraps [@swagger-api/apidom-parser-adapter-openapi-json-3-1](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-openapi-json-3-1) package
|
---|
| 175 | and is uniquely identified by `openapi-json-3-1` name.
|
---|
| 176 |
|
---|
| 177 | Supported media types are:
|
---|
| 178 |
|
---|
| 179 | ```js
|
---|
| 180 | [
|
---|
| 181 | 'application/vnd.oai.openapi;version=3.1.0',
|
---|
| 182 | 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 183 | ]
|
---|
| 184 | ```
|
---|
| 185 |
|
---|
| 186 | #### [openapi-yaml-3-1](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/openapi-yaml-3-1)
|
---|
| 187 |
|
---|
| 188 | Wraps [@swagger-api/apidom-parser-adapter-openapi-yaml-3-1](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-openapi-yaml-3-1) package
|
---|
| 189 | and is uniquely identified by `openapi-yaml-3-1` name.
|
---|
| 190 |
|
---|
| 191 | Supported media types are:
|
---|
| 192 |
|
---|
| 193 | ```js
|
---|
| 194 | [
|
---|
| 195 | 'application/vnd.oai.openapi;version=3.1.0',
|
---|
| 196 | 'application/vnd.oai.openapi+yaml;version=3.1.0',
|
---|
| 197 | ]
|
---|
| 198 | ```
|
---|
| 199 |
|
---|
| 200 | #### [asyncapi-json-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/asyncapi-json-2)
|
---|
| 201 |
|
---|
| 202 | Wraps [@swagger-api/apidom-parser-adapter-asyncapi-json-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-asyncapi-json-2) package
|
---|
| 203 | and is uniquely identified by `asyncapi-json-2` name.
|
---|
| 204 |
|
---|
| 205 | Supported media types are:
|
---|
| 206 |
|
---|
| 207 | ```js
|
---|
| 208 | [
|
---|
| 209 | 'application/vnd.aai.asyncapi;version=2.0.0',
|
---|
| 210 | 'application/vnd.aai.asyncapi;version=2.1.0',
|
---|
| 211 | 'application/vnd.aai.asyncapi;version=2.2.0',
|
---|
| 212 | 'application/vnd.aai.asyncapi;version=2.3.0',
|
---|
| 213 | 'application/vnd.aai.asyncapi;version=2.4.0',
|
---|
| 214 | 'application/vnd.aai.asyncapi;version=2.5.0',
|
---|
| 215 | 'application/vnd.aai.asyncapi;version=2.6.0',
|
---|
| 216 | 'application/vnd.aai.asyncapi+json;version=2.0.0',
|
---|
| 217 | 'application/vnd.aai.asyncapi+json;version=2.1.0',
|
---|
| 218 | 'application/vnd.aai.asyncapi+json;version=2.2.0',
|
---|
| 219 | 'application/vnd.aai.asyncapi+json;version=2.3.0',
|
---|
| 220 | 'application/vnd.aai.asyncapi+json;version=2.4.0',
|
---|
| 221 | 'application/vnd.aai.asyncapi+json;version=2.5.0',
|
---|
| 222 | 'application/vnd.aai.asyncapi+json;version=2.6.0',
|
---|
| 223 | ]
|
---|
| 224 | ```
|
---|
| 225 |
|
---|
| 226 | #### [asyncapi-yaml-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/asyncapi-yaml-2)
|
---|
| 227 |
|
---|
| 228 | Wraps [@swagger-api/apidom-parser-adapter-asyncapi-yaml-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-asyncapi-yaml-2) package
|
---|
| 229 | and is uniquely identified by `asyncapi-yaml-2` name.
|
---|
| 230 |
|
---|
| 231 |
|
---|
| 232 | Supported media types are:
|
---|
| 233 |
|
---|
| 234 | ```js
|
---|
| 235 | [
|
---|
| 236 | 'application/vnd.aai.asyncapi;version=2.0.0',
|
---|
| 237 | 'application/vnd.aai.asyncapi;version=2.1.0',
|
---|
| 238 | 'application/vnd.aai.asyncapi;version=2.2.0',
|
---|
| 239 | 'application/vnd.aai.asyncapi;version=2.3.0',
|
---|
| 240 | 'application/vnd.aai.asyncapi;version=2.3.0',
|
---|
| 241 | 'application/vnd.aai.asyncapi;version=2.4.0',
|
---|
| 242 | 'application/vnd.aai.asyncapi;version=2.5.0',
|
---|
| 243 | 'application/vnd.aai.asyncapi;version=2.6.0',
|
---|
| 244 | 'application/vnd.aai.asyncapi+yaml;version=2.0.0',
|
---|
| 245 | 'application/vnd.aai.asyncapi+yaml;version=2.1.0',
|
---|
| 246 | 'application/vnd.aai.asyncapi+yaml;version=2.2.0',
|
---|
| 247 | 'application/vnd.aai.asyncapi+yaml;version=2.3.0',
|
---|
| 248 | 'application/vnd.aai.asyncapi+yaml;version=2.4.0',
|
---|
| 249 | 'application/vnd.aai.asyncapi+yaml;version=2.5.0',
|
---|
| 250 | 'application/vnd.aai.asyncapi+yaml;version=2.6.0',
|
---|
| 251 | ]
|
---|
| 252 | ```
|
---|
| 253 |
|
---|
| 254 | #### [workflows-json-1](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/workflows-json-1)
|
---|
| 255 |
|
---|
| 256 | Wraps [@swagger-api/apidom-parser-adapter-workflows-json-1](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-workflows-json-1) package
|
---|
| 257 | and is uniquely identified by `workflows-json-1` name.
|
---|
| 258 |
|
---|
| 259 | Supported media types are:
|
---|
| 260 |
|
---|
| 261 | ```js
|
---|
| 262 | [
|
---|
| 263 | 'application/vnd.oai.workflows;version=1.0.0',
|
---|
| 264 | 'application/vnd.oai.workflows+json;version=1.0.0',
|
---|
| 265 | ]
|
---|
| 266 | ```
|
---|
| 267 |
|
---|
| 268 | #### [workflows-yaml-1](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/workflows-yaml-1)
|
---|
| 269 |
|
---|
| 270 | Wraps [@swagger-api/apidom-parser-adapter-workflows-yaml-1](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-workflows-yaml-1) package
|
---|
| 271 | and is uniquely identified by `workflows-yaml-1` name.
|
---|
| 272 |
|
---|
| 273 | Supported media types are:
|
---|
| 274 |
|
---|
| 275 | ```js
|
---|
| 276 | [
|
---|
| 277 | 'application/vnd.oai.workflows;version=1.0.0',
|
---|
| 278 | 'application/vnd.oai.workflows+yaml;version=1.0.0',
|
---|
| 279 | ]
|
---|
| 280 | ```
|
---|
| 281 |
|
---|
| 282 | #### [api-design-systems-json](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/api-design-systems-json)
|
---|
| 283 |
|
---|
| 284 | Wraps [@swagger-api/apidom-parser-adapter-api-design-systsems-json](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-api-design-systems-json) package
|
---|
| 285 | and is uniquely identified by `api-design-systems-json` name.
|
---|
| 286 |
|
---|
| 287 | Supported media types are:
|
---|
| 288 |
|
---|
| 289 | ```js
|
---|
| 290 | [
|
---|
| 291 | 'application/vnd.aai.apidesignsystems;version=2021-05-07',
|
---|
| 292 | 'application/vnd.aai.apidesignsystems+json;version=2021-05-07'
|
---|
| 293 | ]
|
---|
| 294 | ```
|
---|
| 295 |
|
---|
| 296 | #### [api-design-systems-yaml](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/api-design-systems-yaml)
|
---|
| 297 |
|
---|
| 298 | Wraps [@swagger-api/apidom-parser-adapter-api-design-systems-yaml](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-api-design-systems-yaml) package
|
---|
| 299 | and is uniquely identified by `api-design-systems-yaml` name.
|
---|
| 300 |
|
---|
| 301 |
|
---|
| 302 | Supported media types are:
|
---|
| 303 |
|
---|
| 304 | ```js
|
---|
| 305 | [
|
---|
| 306 | 'application/vnd.aai.apidesignsystems;version=2021-05-07',
|
---|
| 307 | 'application/vnd.aai.apidesignsystems+yaml;version=2021-05-07'
|
---|
| 308 | ]
|
---|
| 309 | ```
|
---|
| 310 |
|
---|
| 311 | #### [json](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/json)
|
---|
| 312 |
|
---|
| 313 | Wraps [@swagger-api/apidom-parser-adapter-json](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-json) package
|
---|
| 314 | and is uniquely identified by `json` name.
|
---|
| 315 |
|
---|
| 316 |
|
---|
| 317 | Supported media types are:
|
---|
| 318 |
|
---|
| 319 | ```js
|
---|
| 320 | [
|
---|
| 321 | 'application/json'
|
---|
| 322 | ]
|
---|
| 323 | ```
|
---|
| 324 |
|
---|
| 325 | #### [yaml-1-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/yaml-1-2)
|
---|
| 326 |
|
---|
| 327 | Wraps [@swagger-api/apidom-parser-adapter-yaml-1-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-yaml-1-2) package
|
---|
| 328 | and is uniquely identified by `yaml-1-2` name.
|
---|
| 329 |
|
---|
| 330 |
|
---|
| 331 | Supported media types are:
|
---|
| 332 |
|
---|
| 333 | ```js
|
---|
| 334 | [
|
---|
| 335 | 'text/yaml',
|
---|
| 336 | 'application/yaml'
|
---|
| 337 | ]
|
---|
| 338 | ```
|
---|
| 339 |
|
---|
| 340 | #### [binary](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/parse/parsers/binary)
|
---|
| 341 |
|
---|
| 342 | Can parse any binary or non-binary file and return it's content as `base64` encoded string.
|
---|
| 343 | This parser is uniquely identified by `binary` name.
|
---|
| 344 |
|
---|
| 345 |
|
---|
| 346 | **All** media types are supported.
|
---|
| 347 |
|
---|
| 348 | #### Parser plugins execution order
|
---|
| 349 |
|
---|
| 350 | It's important to understand that default parser plugins are run in specific order. The order is determined
|
---|
| 351 | by the [options.parse.parsers](https://github.com/swagger-api/apidom/blob/ba888d711a4292e8ed0b72e343c4902a4bf0d45a/packages/apidom-reference/src/configuration/saturated.ts#L22) option.
|
---|
| 352 | Every plugin is pulled from `options.parse.parsers` option, and it's `canParse` method is called to determine
|
---|
| 353 | whether the plugin can parse the URI. If `canParse` returns `true`, `parse` method of plugin is called
|
---|
| 354 | and result from parsing is returned. No subsequent parser plugins are run. If `canParse` returns
|
---|
| 355 | `false`, next parser plugin is pulled and this process is repeated until one of the parser plugins `canParse` method
|
---|
| 356 | returns `true` or until entire list of parser plugins is exhausted (throws error).
|
---|
| 357 |
|
---|
| 358 | ```js
|
---|
| 359 | [
|
---|
| 360 | OpenApiJson2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 361 | OpenApiYaml2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 362 | OpenApiJson3_0Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 363 | OpenApiYaml3_0Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 364 | OpenApiYaml3_1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 365 | OpenApiJson3_1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 366 | OpenApiYaml3_1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 367 | AsyncApiJson2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 368 | AsyncApiYaml2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 369 | WorkflowsJson1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 370 | WorkflowsYaml1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 371 | ApiDesignSystemsJsonParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 372 | ApiDesignSystemsYamlParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 373 | JsonParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 374 | YamlParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 375 | BinaryParser({ allowEmpty: true }),
|
---|
| 376 | ]
|
---|
| 377 | ```
|
---|
| 378 | Most specific parser plugins are listed first, most generic are listed last.
|
---|
| 379 |
|
---|
| 380 | It's possible to **change** the parser plugins **order globally** by mutating global `parse` options:
|
---|
| 381 |
|
---|
| 382 | ```js
|
---|
| 383 | import { options } from '@swagger-api/apidom-reference';
|
---|
| 384 | import OpenApiJson2Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-json-2';
|
---|
| 385 | import OpenApiYaml2Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-yaml-2';
|
---|
| 386 | import OpenApiJson3_0Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-json-3-0';
|
---|
| 387 | import OpenApiYaml3_0Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-yaml-3-0'
|
---|
| 388 | import OpenApiJson3_1Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-json-3-1';
|
---|
| 389 | import OpenApiYaml3_1Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-yaml-3-1'
|
---|
| 390 | import AsyncApiJson2Parser from '@swagger-api/apidom-reference/parse/parsers/asyncapi-json-2';
|
---|
| 391 | import AsyncApiYaml2Parser from '@swagger-api/apidom-reference/parse/parsers/asyncapi-yaml-2';
|
---|
| 392 | import WorkflowsJson1Parser from '@swagger-api/apidom-reference/parse/parsers/workflows-json-1';
|
---|
| 393 | import WorkflowsYaml1Parser from '@swagger-api/apidom-reference/parse/parsers/workflows-yaml-1';
|
---|
| 394 | import ApiDesignSystemsJsonParser from '@swagger-api/apidom-reference/parse/parsers/api-design-systems-json';
|
---|
| 395 | import ApiDesignSystemsYamlParser from '@swagger-api/apidom-reference/parse/parsers/api-design-systems-json';
|
---|
| 396 | import JsonParser from '@swagger-api/apidom-reference/parse/parsers/json';
|
---|
| 397 | import YamlParser from '@swagger-api/apidom-reference/parse/parsers/yaml';
|
---|
| 398 | import BinaryParser from '@swagger-api/apidom-reference/parse/parsers/binary';
|
---|
| 399 |
|
---|
| 400 |
|
---|
| 401 | options.parse.parsers = [
|
---|
| 402 | OpenApiJson2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 403 | OpenApiYaml2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 404 | OpenApiJson3_0Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 405 | OpenApiYaml3_0Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 406 | OpenApiJson3_1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 407 | OpenApiYaml3_1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 408 | AsyncApiJson2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 409 | AsyncApiYaml2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 410 | WorkflowsJson1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 411 | WorkflowsYaml1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 412 | ApiDesignSystemsJsonParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 413 | ApiDesignSystemsYamlParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 414 | YamlParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 415 | JsonParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 416 | BinaryParser({ allowEmpty: true }),
|
---|
| 417 | ]
|
---|
| 418 | ```
|
---|
| 419 |
|
---|
| 420 | To **change** the parser plugins **order** on ad-hoc basis:
|
---|
| 421 |
|
---|
| 422 | ```js
|
---|
| 423 | import { parse } from '@swagger-api/apidom-reference';
|
---|
| 424 | import OpenApiJson2Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-json-2';
|
---|
| 425 | import OpenApiYaml2Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-yaml-2';
|
---|
| 426 | import OpenApiJson3_0Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-json-3-0';
|
---|
| 427 | import OpenApiYaml3_0Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-yaml-3-0'
|
---|
| 428 | import OpenApiJson3_1Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-json-3-1';
|
---|
| 429 | import OpenApiYaml3_1Parser from '@swagger-api/apidom-reference/parse/parsers/openapi-yaml-3-1'
|
---|
| 430 | import AsyncApiJson2Parser from '@swagger-api/apidom-reference/parse/parsers/asyncapi-json-2';
|
---|
| 431 | import AsyncApiYaml2Parser from '@swagger-api/apidom-reference/parse/parsers/asyncapi-yaml-2';
|
---|
| 432 | import WorkflowsJson1Parser from '@swagger-api/apidom-reference/parse/parsers/workflows-json-1';
|
---|
| 433 | import WorkflowsYaml1Parser from '@swagger-api/apidom-reference/parse/parsers/workflows-yaml-1';
|
---|
| 434 | import ApiDesignSystemsJsonParser from '@swagger-api/apidom-reference/parse/parsers/api-design-systems-json';
|
---|
| 435 | import ApiDesignSystemsYamlParser from '@swagger-api/apidom-reference/parse/parsers/api-design-systems-json';
|
---|
| 436 | import JsonParser from '@swagger-api/apidom-reference/parse/parsers/json';
|
---|
| 437 | import YamlParser from '@swagger-api/apidom-reference/parse/parsers/yaml';
|
---|
| 438 | import BinaryParser from '@swagger-api/apidom-reference/parse/parsers/binary';
|
---|
| 439 |
|
---|
| 440 | await parse('/home/user/oas.json', {
|
---|
| 441 | parse: {
|
---|
| 442 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 443 | parsers: [
|
---|
| 444 | OpenApiJson2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 445 | OpenApiYaml2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 446 | OpenApiJson3_1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 447 | OpenApiYaml3_1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 448 | OpenApiJson3_0Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 449 | OpenApiYaml3_0Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 450 | AsyncApiJson2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 451 | AsyncApiYaml2Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 452 | WorkflowsJson1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 453 | WorkflowsYaml1Parser({ allowEmpty: true, sourceMap: false }),
|
---|
| 454 | ApiDesignSystemsJsonParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 455 | ApiDesignSystemsYamlParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 456 | YamlParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 457 | JsonParser({ allowEmpty: true, sourceMap: false }),
|
---|
| 458 | BinaryParser({ allowEmpty: true }),
|
---|
| 459 | ],
|
---|
| 460 | },
|
---|
| 461 | });
|
---|
| 462 | ```
|
---|
| 463 |
|
---|
| 464 | #### Parser plugin options
|
---|
| 465 |
|
---|
| 466 | Parser plugins accept additional options like `allowEmpty` or `sourceMap`. It's possible to **change** parser plugin
|
---|
| 467 | **options globally** by mutating global `parse` options:
|
---|
| 468 |
|
---|
| 469 | ```js
|
---|
| 470 | import { options, parse } from '@swagger-api/apidom-reference';
|
---|
| 471 |
|
---|
| 472 | options.parser.parserOpts = {
|
---|
| 473 | allowEmpty: false,
|
---|
| 474 | sourceMap: true,
|
---|
| 475 | };
|
---|
| 476 |
|
---|
| 477 | await parse('/home/user/oas.json', {
|
---|
| 478 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }
|
---|
| 479 | });
|
---|
| 480 | ```
|
---|
| 481 |
|
---|
| 482 | To **change** the parser plugins **options** on ad-hoc basis:
|
---|
| 483 |
|
---|
| 484 | ```js
|
---|
| 485 | import { parse } from '@swagger-api/apidom-reference';
|
---|
| 486 |
|
---|
| 487 | await parse('/home/user/oas.json', {
|
---|
| 488 | parse: {
|
---|
| 489 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 490 | parserOpts: { allowEmpty: false, sourceMap: true },
|
---|
| 491 | },
|
---|
| 492 | });
|
---|
| 493 | ```
|
---|
| 494 |
|
---|
| 495 | ### Creating new parser plugin
|
---|
| 496 |
|
---|
| 497 | Parse component can be extended by additional parser plugins. Every parser plugin is an object that
|
---|
| 498 | must conform to the following interface/shape:
|
---|
| 499 |
|
---|
| 500 | ```typescript
|
---|
| 501 | {
|
---|
| 502 | // uniquely identifies this parser plugin
|
---|
| 503 | name: string,
|
---|
| 504 |
|
---|
| 505 | // this method is called to determine whether the parser plugin can parse the file
|
---|
| 506 | async canParse(file: IFile): Promise<boolean> {
|
---|
| 507 | // ...implementation...
|
---|
| 508 | },
|
---|
| 509 |
|
---|
| 510 | // this method actually parses the file
|
---|
| 511 | async parse(file: IFile): Promise<ParseResultElement> {
|
---|
| 512 | // ...implementation...
|
---|
| 513 | }
|
---|
| 514 | }
|
---|
| 515 | ```
|
---|
| 516 |
|
---|
| 517 | New parser plugin is then provided as an option to a `parse` function:
|
---|
| 518 |
|
---|
| 519 | ```js
|
---|
| 520 | import { parse, options } from '@swagger-api/apidom-reference';
|
---|
| 521 |
|
---|
| 522 | const myCustomParserPlugin = {
|
---|
| 523 | name: 'myCustomParserPlugin',
|
---|
| 524 | async canParse(file) {
|
---|
| 525 | return true;
|
---|
| 526 | },
|
---|
| 527 | async parse(file) {
|
---|
| 528 | // implementation of parsing
|
---|
| 529 | }
|
---|
| 530 | };
|
---|
| 531 |
|
---|
| 532 | await parse('/home/user/oas.json', {
|
---|
| 533 | parse: {
|
---|
| 534 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 535 | parsers: [...options.parse.parsers, myCustomParserPlugin],
|
---|
| 536 | }
|
---|
| 537 | });
|
---|
| 538 | ```
|
---|
| 539 |
|
---|
| 540 | In this particular example we're adding our custom parser plugin as the last plugin
|
---|
| 541 | to the available default parser plugin list, so there's a good chance that one of the
|
---|
| 542 | default parser plugins detects that it can parse the `/home/user/oas.json` file,
|
---|
| 543 | parses it and returns.
|
---|
| 544 |
|
---|
| 545 | If you want to force execution of your custom plugin, add it as a first parser plugin:
|
---|
| 546 |
|
---|
| 547 | ```js
|
---|
| 548 | import { parse, options } from '@swagger-api/apidom-reference';
|
---|
| 549 |
|
---|
| 550 | const myCustomParserPlugin = {
|
---|
| 551 | name: 'myCustomParserPlugin',
|
---|
| 552 | async canParse(file) {
|
---|
| 553 | return true;
|
---|
| 554 | },
|
---|
| 555 | async parse(file) {
|
---|
| 556 | // implementation of parsing
|
---|
| 557 | }
|
---|
| 558 | };
|
---|
| 559 |
|
---|
| 560 | await parse('/home/user/oas.json', {
|
---|
| 561 | parse: {
|
---|
| 562 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 563 | parsers: [myCustomParserPlugin, ...options.parse.parsers],
|
---|
| 564 | }
|
---|
| 565 | });
|
---|
| 566 | ```
|
---|
| 567 |
|
---|
| 568 | To override the default parser plugins entirely, set `myCustomParserPlugin` plugin to be the only one available:
|
---|
| 569 |
|
---|
| 570 | ```js
|
---|
| 571 | import { parse } from '@swagger-api/apidom-reference';
|
---|
| 572 |
|
---|
| 573 | const myCustomParserPlugin = {
|
---|
| 574 | name: 'myCustomParserPlugin',
|
---|
| 575 | async canParse(file) {
|
---|
| 576 | return true;
|
---|
| 577 | },
|
---|
| 578 | async parse(file) {
|
---|
| 579 | // implementation of parsing
|
---|
| 580 | }
|
---|
| 581 | };
|
---|
| 582 |
|
---|
| 583 | await parse('/home/user/oas.json', {
|
---|
| 584 | parse: {
|
---|
| 585 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 586 | parsers: [myCustomParserPlugin],
|
---|
| 587 | }
|
---|
| 588 | });
|
---|
| 589 | ```
|
---|
| 590 |
|
---|
| 591 | ### Manipulating parser plugins
|
---|
| 592 |
|
---|
| 593 | Parser plugins can be added, removed, replaced or reordered.
|
---|
| 594 |
|
---|
| 595 | Here are two examples of removing one of the parser plugins called `asyncapi-json-2`.
|
---|
| 596 | We're using the fact that every parser plugin is uniquely identifiable by its name.
|
---|
| 597 |
|
---|
| 598 | **Removing** parser plugin **globally** for all subsequence `parse` calls is achieved by mutating global options:
|
---|
| 599 |
|
---|
| 600 | ```js
|
---|
| 601 | import { parse, options, mergeOptions } from '@swagger-api/apidom-reference';
|
---|
| 602 |
|
---|
| 603 | options.parse.parsers = options.parse.parsers.filter(parserPlugin => parserPlugin !== 'asyncapi-json-2')
|
---|
| 604 |
|
---|
| 605 | // here you can be sure `asyncapi-json-2` plugin was disabled
|
---|
| 606 | await parse('/home/user/oas.json', {
|
---|
| 607 | parse: {
|
---|
| 608 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 609 | }
|
---|
| 610 | });
|
---|
| 611 | ```
|
---|
| 612 |
|
---|
| 613 | **Removing** default parser plugin on **ad-hoc** basis:
|
---|
| 614 |
|
---|
| 615 | ```js
|
---|
| 616 | import { parse, options } from '@swagger-api/apidom-reference';
|
---|
| 617 |
|
---|
| 618 | await parse('/home/user/oas.json', {
|
---|
| 619 | parse: {
|
---|
| 620 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 621 | parsers: options.parse.parsers.filter(parserPlugin => parserPlugin.name !== 'asyncapi-json-2'),
|
---|
| 622 | }
|
---|
| 623 | });
|
---|
| 624 | ```
|
---|
| 625 | As you can see, these are all primitive JavaScript Array manipulation techniques.
|
---|
| 626 | These techniques can be applied to replacing (use [Array.prototype.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)) or reordering parser plugins as well.
|
---|
| 627 |
|
---|
| 628 |
|
---|
| 629 | ## Resolve component
|
---|
| 630 |
|
---|
| 631 | `Resolve component` consists of two (2) sub-components: **File resolution** and **External Resolution**.
|
---|
| 632 | `Resolve component` is used by [Parse component](#parse-component) under the hood. `Resolve component` provides a resolved
|
---|
| 633 | file contents for a Parse component to parse.
|
---|
| 634 |
|
---|
| 635 | ### File resolution
|
---|
| 636 |
|
---|
| 637 | Contains implementation of default [resolver plugins](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/resolve/resolvers).
|
---|
| 638 | Defaults resolver plugin is an object which knows how to obtain contents of a file represented by URI or URL.
|
---|
| 639 |
|
---|
| 640 | #### Resolver plugins
|
---|
| 641 |
|
---|
| 642 | File resolution comes with two (2) default resolver plugins.
|
---|
| 643 |
|
---|
| 644 | ##### [FileResolver](https://github.com/swagger-api/apidom/blob/main/packages/apidom-reference/src/resolve/resolvers/file)
|
---|
| 645 |
|
---|
| 646 | This resolver plugin is responsible for resolving a local file.
|
---|
| 647 | It detects if the provided URI represents a filesystem path and if so,
|
---|
| 648 | reads the file and provides its content.
|
---|
| 649 |
|
---|
| 650 | **WARNING**: use this plugin with caution, as it can read files from a local file system.
|
---|
| 651 | By default, this plugin will reject to read any files from the local file system, unless
|
---|
| 652 | explicitly provided by **fileAllowList** option.
|
---|
| 653 |
|
---|
| 654 | ###### Providing file allow list
|
---|
| 655 |
|
---|
| 656 | File allow list can be provided **globally** as an option to `FileResolver` in form
|
---|
| 657 | of array of *glob patterns* or *regular expressions*.
|
---|
| 658 |
|
---|
| 659 | ```js
|
---|
| 660 | import { options } from '@swagger-api/apidom-reference';
|
---|
| 661 | import { FileResolver } from '@swagger-api/apidom-reference/resolve/resolvers/file';
|
---|
| 662 | import { HttpResolverAxios } from '@swagger-api/apidom-reference/resolve/resolvers/http-axios';
|
---|
| 663 |
|
---|
| 664 | options.resolve.resolvers = [
|
---|
| 665 | FileResolver({
|
---|
| 666 | fileAllowList: [
|
---|
| 667 | '*.json',
|
---|
| 668 | /\.json$/,
|
---|
| 669 | ]
|
---|
| 670 | }),
|
---|
| 671 | HttpResolverAxios({ timeout: 5000, redirects: 5, withCredentials: false }),
|
---|
| 672 | ]
|
---|
| 673 | ```
|
---|
| 674 |
|
---|
| 675 | File allow list can also be provided on ad-hoc basis:
|
---|
| 676 |
|
---|
| 677 | ```js
|
---|
| 678 | import { resolve } from '@swagger-api/apidom-reference';
|
---|
| 679 |
|
---|
| 680 | await resolve('/home/user/oas.json', {
|
---|
| 681 | resolve: {
|
---|
| 682 | resolverOpts: {
|
---|
| 683 | fileAllowList: [
|
---|
| 684 | '*.json',
|
---|
| 685 | /\.json$/,
|
---|
| 686 | ]
|
---|
| 687 | },
|
---|
| 688 | },
|
---|
| 689 | });
|
---|
| 690 | ```
|
---|
| 691 |
|
---|
| 692 | ##### [HttpResolverAxios](https://github.com/swagger-api/apidom/blob/main/packages/apidom-reference/src/resolve/resolvers/http-axios)
|
---|
| 693 |
|
---|
| 694 | This resolver plugin is responsible for resolving a remote file represented by HTTP(s) URL.
|
---|
| 695 | It detects if the provided URI represents an HTTP(s) URL and if so,
|
---|
| 696 | fetches the file and provides its content.
|
---|
| 697 |
|
---|
| 698 | ###### [Axios Request Config](https://axios-http.com/docs/req_config) support
|
---|
| 699 |
|
---|
| 700 | HttpResolverAxios plugin supports all the options available in [Axios Request Config](https://axios-http.com/docs/req_config).
|
---|
| 701 | Config options can be provided in following way:
|
---|
| 702 |
|
---|
| 703 | ```js
|
---|
| 704 | import { resolve } from '@swagger-api/apidom-reference';
|
---|
| 705 |
|
---|
| 706 | await resolve('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.1/webhook-example.json', {
|
---|
| 707 | resolve: {
|
---|
| 708 | resolverOpts: {
|
---|
| 709 | axiosConfig: {
|
---|
| 710 | timeout: 10000,
|
---|
| 711 | withCredentials: false,
|
---|
| 712 | responseType: 'json',
|
---|
| 713 | },
|
---|
| 714 | },
|
---|
| 715 | },
|
---|
| 716 | });
|
---|
| 717 | ```
|
---|
| 718 |
|
---|
| 719 | ###### [Axios Interceptors](https://axios-http.com/docs/interceptors) support
|
---|
| 720 |
|
---|
| 721 | HttpResolverAxios plugin supports [Axios Interceptors](https://axios-http.com/docs/interceptors).
|
---|
| 722 | Interceptors can be provided in following way:
|
---|
| 723 |
|
---|
| 724 | ```js
|
---|
| 725 | import { resolve } from '@swagger-api/apidom-reference';
|
---|
| 726 |
|
---|
| 727 | const requestInterceptor = (config) => config;
|
---|
| 728 | const responseInterceptor = (response) => response;
|
---|
| 729 |
|
---|
| 730 | await resolve('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.1/webhook-example.json', {
|
---|
| 731 | resolve: {
|
---|
| 732 | resolverOpts: {
|
---|
| 733 | axiosConfig: {
|
---|
| 734 | interceptors: {
|
---|
| 735 | request: requestInterceptor,
|
---|
| 736 | response: responseInterceptor,
|
---|
| 737 | },
|
---|
| 738 | },
|
---|
| 739 | },
|
---|
| 740 | },
|
---|
| 741 | });
|
---|
| 742 | ```
|
---|
| 743 |
|
---|
| 744 | Multiple request and response interceptors can be provided in following way:
|
---|
| 745 |
|
---|
| 746 | ```js
|
---|
| 747 | import { resolve } from '@swagger-api/apidom-reference';
|
---|
| 748 |
|
---|
| 749 | const requestInterceptor1 = (config) => config;
|
---|
| 750 | const requestInterceptor2 = (config) => config;
|
---|
| 751 | const responseInterceptor1 = (response) => response;
|
---|
| 752 | const responseInterceptor2 = async (error) => Promise.reject(error);
|
---|
| 753 |
|
---|
| 754 | await resolve('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.1/webhook-example.json', {
|
---|
| 755 | resolve: {
|
---|
| 756 | resolverOpts: {
|
---|
| 757 | axiosConfig: {
|
---|
| 758 | interceptors: {
|
---|
| 759 | request: [requestInterceptor1, requestInterceptor2],
|
---|
| 760 | response: [responseInterceptor1, responseInterceptor2],
|
---|
| 761 | },
|
---|
| 762 | },
|
---|
| 763 | },
|
---|
| 764 | },
|
---|
| 765 | });
|
---|
| 766 | ```
|
---|
| 767 |
|
---|
| 768 | **File resolution on local filesystem path**:
|
---|
| 769 |
|
---|
| 770 | ```js
|
---|
| 771 | import { readFile } from '@swagger-api/apidom-reference';
|
---|
| 772 |
|
---|
| 773 | await readFile('/home/user/oas.json'); // Promise<Buffer>
|
---|
| 774 | ```
|
---|
| 775 |
|
---|
| 776 | **File resolution on HTTP(s) URL:**
|
---|
| 777 |
|
---|
| 778 | ```js
|
---|
| 779 | import { readFile } from '@swagger-api/apidom-reference';
|
---|
| 780 |
|
---|
| 781 | await readFile('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.1/webhook-example.json'); // Promise<Buffer>
|
---|
| 782 | ```
|
---|
| 783 | File resolution always returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) containing a [Buffer](https://nodejs.org/api/buffer.html).
|
---|
| 784 | It is responsibility of the API consumer to transform `Buffer` into `String` or any other type.
|
---|
| 785 |
|
---|
| 786 | ```js
|
---|
| 787 | import { readFile } from '@swagger-api/apidom-reference';
|
---|
| 788 |
|
---|
| 789 | const buffer = await readFile('/home/user/oas.json');
|
---|
| 790 | const string = buffer.toString('utf-8');
|
---|
| 791 | ```
|
---|
| 792 |
|
---|
| 793 | ##### Resolver plugins execution order
|
---|
| 794 |
|
---|
| 795 | It's important to understand that default resolver plugins are run in specific order. The order is determined
|
---|
| 796 | by the [options.resolve.resolvers]https://github.com/swagger-api/apidom/blob/ba888d711a4292e8ed0b72e343c4902a4bf0d45a/packages/apidom-reference/src/configuration/saturated.ts#L36) option.
|
---|
| 797 | Every plugin is pulled from `options.resolve.resolvers` option, and it's `canRead` method is called to determine
|
---|
| 798 | whether the plugin can resolve the URI. If `canRead` returns `true`, `read` method of plugin is called
|
---|
| 799 | and result from reading the file is returned. No subsequent resolver plugins are run.
|
---|
| 800 | If `canRead` returns `false`, next resolver plugin is pulled and this process is repeated until one
|
---|
| 801 | of the resolver plugins `canRead` method returns `true` or until entire list of resolver plugins is exhausted (throws error).
|
---|
| 802 |
|
---|
| 803 | ```js
|
---|
| 804 | [
|
---|
| 805 | FileResolver(),
|
---|
| 806 | HttpResolverAxios({ timeout: 5000, redirects: 5, withCredentials: false }),
|
---|
| 807 | ]
|
---|
| 808 | ```
|
---|
| 809 |
|
---|
| 810 | It's possible to **change** resolver plugins **order globally** by mutating global `resolve` option:
|
---|
| 811 |
|
---|
| 812 | ```js
|
---|
| 813 | import { options } from '@swagger-api/apidom-reference';
|
---|
| 814 | import { FileResolver } from '@swagger-api/apidom-reference/resolve/resolvers/file';
|
---|
| 815 | import { HttpResolverAxios } from '@swagger-api/apidom-reference/resolve/resolvers/http-axios';
|
---|
| 816 |
|
---|
| 817 | options.resolve.resolvers = [
|
---|
| 818 | HttpResolverAxios({ timeout: 5000, redirects: 5, withCredentials: false }),
|
---|
| 819 | FileResolver(),
|
---|
| 820 | ]
|
---|
| 821 | ```
|
---|
| 822 |
|
---|
| 823 | To **change** resolver plugins **order** on ad-hoc basis:
|
---|
| 824 |
|
---|
| 825 | ```js
|
---|
| 826 | import { readFile } from '@swagger-api/apidom-reference';
|
---|
| 827 | import { FileResolver } from '@swagger-api/apidom-reference/resolve/resolvers/file';
|
---|
| 828 | import { HttpResolverAxios } from '@swagger-api/apidom-reference/resolve/resolvers/http-axios';
|
---|
| 829 |
|
---|
| 830 | await readFile('/home/user/oas.json', {
|
---|
| 831 | resolve: {
|
---|
| 832 | resolvers: [
|
---|
| 833 | HttpResolverAxios({ timeout: 5000, redirects: 5, withCredentials: false }),
|
---|
| 834 | FileResolver(),
|
---|
| 835 | ],
|
---|
| 836 | },
|
---|
| 837 | });
|
---|
| 838 | ```
|
---|
| 839 |
|
---|
| 840 | ##### Resolver plugin options
|
---|
| 841 |
|
---|
| 842 | Some resolver plugins accept additional options. It's possible to **change** resolver plugin
|
---|
| 843 | **options globally** by mutating global `resolve` options:
|
---|
| 844 |
|
---|
| 845 | ```js
|
---|
| 846 | import { options, readFile } from '@swagger-api/apidom-reference';
|
---|
| 847 |
|
---|
| 848 | options.resolve.resolverOpts = {
|
---|
| 849 | axiosConfig: {
|
---|
| 850 | timeout: 10000,
|
---|
| 851 | },
|
---|
| 852 | };
|
---|
| 853 |
|
---|
| 854 | await readFile('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.1/webhook-example.json');
|
---|
| 855 | ```
|
---|
| 856 |
|
---|
| 857 | To **change** the resolver plugins **options** on ad-hoc basis:
|
---|
| 858 |
|
---|
| 859 | ```js
|
---|
| 860 | import { readFile } from '@swagger-api/apidom-reference';
|
---|
| 861 |
|
---|
| 862 | await readFile('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.1/webhook-example.json', {
|
---|
| 863 | resolve: {
|
---|
| 864 | resolverOpts: {
|
---|
| 865 | axiosConfig: {
|
---|
| 866 | timeout: 10000,
|
---|
| 867 | },
|
---|
| 868 | },
|
---|
| 869 | },
|
---|
| 870 | });
|
---|
| 871 | ```
|
---|
| 872 |
|
---|
| 873 | Both of above examples will be using [HttpResolverAxios](https://github.com/swagger-api/apidom/blob/main/packages/apidom-reference/src/resolve/resolvers/http-axios) plugin
|
---|
| 874 | (as we're trying to resolve HTTP(s) URL) and the `timeout` of resolution will increase from **default 3 seconds**
|
---|
| 875 | to 10 seconds.
|
---|
| 876 |
|
---|
| 877 | ##### Creating new resolver plugin
|
---|
| 878 |
|
---|
| 879 | Resolve component can be extended by additional resolver plugins. Every resolver plugin is an object that
|
---|
| 880 | must conform to the following interface/shape:
|
---|
| 881 |
|
---|
| 882 | ```typescript
|
---|
| 883 | {
|
---|
| 884 | // uniquely identifies this plugin
|
---|
| 885 | name: string,
|
---|
| 886 |
|
---|
| 887 | // this method is called to determine whether the resolver plugin can resolve the file
|
---|
| 888 | canRead(file: IFile): boolean {
|
---|
| 889 | // ...implementation...
|
---|
| 890 | },
|
---|
| 891 |
|
---|
| 892 | // this method actually resolves the file
|
---|
| 893 | async read(file: IFile): Promise<Buffer> {
|
---|
| 894 | // ...implementation...
|
---|
| 895 | }
|
---|
| 896 | }
|
---|
| 897 | ```
|
---|
| 898 |
|
---|
| 899 | New resolver plugin is then provided as an option to a `readFile` function:
|
---|
| 900 |
|
---|
| 901 | ```js
|
---|
| 902 | import { readFile, options } from '@swagger-api/apidom-reference';
|
---|
| 903 |
|
---|
| 904 | const myCustomResolverPlugin = {
|
---|
| 905 | name: 'myCustomResolverPlugin',
|
---|
| 906 | canRead(file) {
|
---|
| 907 | return true;
|
---|
| 908 | },
|
---|
| 909 | async read(file) {
|
---|
| 910 | // implementation of file resolution
|
---|
| 911 | }
|
---|
| 912 | };
|
---|
| 913 |
|
---|
| 914 | await readFile('/home/user/oas.json', {
|
---|
| 915 | resolve: {
|
---|
| 916 | resolvers: [...options.resolve.resolvers, myCustomResolverPlugin],
|
---|
| 917 | }
|
---|
| 918 | });
|
---|
| 919 | ```
|
---|
| 920 |
|
---|
| 921 | In this particular example we're adding our custom resolver plugin as the last plugin
|
---|
| 922 | to the available default resolver plugin list, so there's a good chance that one of the
|
---|
| 923 | default resolver plugins detects that it can resolve the `/home/user/oas.json` file,
|
---|
| 924 | resolves it and returns its content.
|
---|
| 925 |
|
---|
| 926 | If you want to force execution of your custom plugin, add it as a first resolver plugin:
|
---|
| 927 |
|
---|
| 928 | ```js
|
---|
| 929 | import { readFile, options } from '@swagger-api/apidom-reference';
|
---|
| 930 |
|
---|
| 931 | const myCustomResolverPlugin = {
|
---|
| 932 | name: 'myCustomResolverPlugin',
|
---|
| 933 | canRead(file) {
|
---|
| 934 | return true;
|
---|
| 935 | },
|
---|
| 936 | async read(file) {
|
---|
| 937 | // implementation of file resolution
|
---|
| 938 | }
|
---|
| 939 | };
|
---|
| 940 |
|
---|
| 941 | await readFile('/home/user/oas.json', {
|
---|
| 942 | resolve: {
|
---|
| 943 | resolvers: [myCustomResolverPlugin, ...options.resolve.resolvers],
|
---|
| 944 | }
|
---|
| 945 | });
|
---|
| 946 | ```
|
---|
| 947 |
|
---|
| 948 | To override the default resolver plugins entirely, set `myCustomResolverPlugin` plugin to be the only one available:
|
---|
| 949 |
|
---|
| 950 | ```js
|
---|
| 951 | import { readFile } from '@swagger-api/apidom-reference';
|
---|
| 952 |
|
---|
| 953 | const myCustomResolverPlugin = {
|
---|
| 954 | name: 'myCustomResolverPlugin',
|
---|
| 955 | canRead(file) {
|
---|
| 956 | return true;
|
---|
| 957 | },
|
---|
| 958 | async read(file) {
|
---|
| 959 | // implementation of file resolution
|
---|
| 960 | }
|
---|
| 961 | };
|
---|
| 962 |
|
---|
| 963 | await readFile('/home/user/oas.json', {
|
---|
| 964 | resolve: {
|
---|
| 965 | resolvers: [myCustomResolverPlugin],
|
---|
| 966 | }
|
---|
| 967 | });
|
---|
| 968 | ```
|
---|
| 969 | New resolver plugins can be based on two predefined stamps: [Resolver](https://github.com/swagger-api/apidom/blob/main/packages/apidom-reference/src/resolve/resolvers/Resolver.ts) and [HttpResolver](https://github.com/swagger-api/apidom/blob/main/packages/apidom-reference/src/resolve/resolvers/HttpResolver.ts).
|
---|
| 970 |
|
---|
| 971 | ##### Manipulating resolver plugins
|
---|
| 972 |
|
---|
| 973 | Resolver plugins can be added, removed, replaced or reordered. We've already covered these techniques in [Manipulating parser plugins section](#manipulating-parser-plugins).
|
---|
| 974 |
|
---|
| 975 | ### External resolution
|
---|
| 976 |
|
---|
| 977 | External resolution is a process of resolving all external dependencies of a particular
|
---|
| 978 | document using a specific [external resolution strategy](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/resolve/strategies). External resolution strategy is determined by
|
---|
| 979 | asserting on `mediaType` option. [File Resolution](#file-resolution) (file content is read/fetched)
|
---|
| 980 | and [Parse component](#parse-component) (file content is parsed) are used under the hood.
|
---|
| 981 |
|
---|
| 982 | **Externally resolving a file localed on a local filesystem:**
|
---|
| 983 |
|
---|
| 984 | ```js
|
---|
| 985 | import { resolve } from '@swagger-api/apidom-reference';
|
---|
| 986 |
|
---|
| 987 | await resolve('/home/user/oas.json', {
|
---|
| 988 | parse: { mediType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 989 | }); // Promise<ReferenceSet>
|
---|
| 990 | ```
|
---|
| 991 |
|
---|
| 992 | **Externally resolving an HTTP(S) URL located on an internet:**
|
---|
| 993 |
|
---|
| 994 | ```js
|
---|
| 995 | import { resolve } from '@swagger-api/apidom-reference';
|
---|
| 996 |
|
---|
| 997 | await resolve('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.1/webhook-example.json', {
|
---|
| 998 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 999 | resolve: {
|
---|
| 1000 | resolverOpts: {
|
---|
| 1001 | axiosConfig: {
|
---|
| 1002 | timeout: 10
|
---|
| 1003 | },
|
---|
| 1004 | },
|
---|
| 1005 | },
|
---|
| 1006 | }); // Promise<ReferenceSet>
|
---|
| 1007 | ```
|
---|
| 1008 |
|
---|
| 1009 | **Externally resolving an ApiDOM fragment:**
|
---|
| 1010 |
|
---|
| 1011 | When externally resolving an ApiDOM fragment, [baseURI](https://github.com/swagger-api/apidom/blob/91763fa4ad876375a413e7049c28c2031c7bbe83/apidom/packages/apidom-reference/src/options/index.ts#L47)
|
---|
| 1012 | resolve option needs to be provided to have a starting point for external dependency resolution.
|
---|
| 1013 | `mediaType` parse option is unnecessary as we can directly assert the type of ApiDOM fragment.
|
---|
| 1014 |
|
---|
| 1015 | ```js
|
---|
| 1016 | import { OpenApi3_1Element } from '@swagger-api/apidom-ns-openapi-3-1';
|
---|
| 1017 | import { resolveApiDOM } from '@swagger-api/apidom-reference';
|
---|
| 1018 |
|
---|
| 1019 | const apidom = OpenApi3_1Element.refract({
|
---|
| 1020 | openapi: '3.1.0',
|
---|
| 1021 | components: {
|
---|
| 1022 | parameters: {
|
---|
| 1023 | externalRef: {
|
---|
| 1024 | $ref: './ex.json#/externalParameter', // file is located at /home/user/ex.json
|
---|
| 1025 | }
|
---|
| 1026 | }
|
---|
| 1027 | }
|
---|
| 1028 | });
|
---|
| 1029 |
|
---|
| 1030 | const refSet = await resolveApiDOM(apidom, {
|
---|
| 1031 | resolve: { baseURI: '/home/user/' },
|
---|
| 1032 | });
|
---|
| 1033 |
|
---|
| 1034 | for (const ref of refSet) {
|
---|
| 1035 | console.log(ref.uri);
|
---|
| 1036 | }
|
---|
| 1037 | // /home/user
|
---|
| 1038 | // /home/user/ex.json
|
---|
| 1039 | ```
|
---|
| 1040 |
|
---|
| 1041 | [ReferenceSet](https://github.com/swagger-api/apidom/blob/main/packages/apidom-reference/src/ReferenceSet.ts) is a [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)
|
---|
| 1042 | like structure containing list of [Reference](https://github.com/swagger-api/apidom/blob/main/packages/apidom-reference/src/Reference.ts) objects.
|
---|
| 1043 | Every Reference object represents single external dependency.
|
---|
| 1044 |
|
---|
| 1045 | #### [External resolution strategies](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/resolve/strategies)
|
---|
| 1046 |
|
---|
| 1047 | External resolution strategy determines how a document is externally resolved. Depending on document `mediaType`
|
---|
| 1048 | every strategy differs significantly. Resolve component comes with two (2) default external resolution strategies.
|
---|
| 1049 |
|
---|
| 1050 | ##### [asyncapi-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/resolve/strategies/asyncapi-2)
|
---|
| 1051 |
|
---|
| 1052 | External resolution strategy for understanding and resolving external dependencies of [AsyncApi 2.x.y](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md) definitions.
|
---|
| 1053 |
|
---|
| 1054 | Supported media types:
|
---|
| 1055 |
|
---|
| 1056 | ```js
|
---|
| 1057 | [
|
---|
| 1058 | 'application/vnd.aai.asyncapi;version=2.0.0',
|
---|
| 1059 | 'application/vnd.aai.asyncapi+json;version=2.0.0',
|
---|
| 1060 | 'application/vnd.aai.asyncapi+yaml;version=2.0.0',
|
---|
| 1061 | 'application/vnd.aai.asyncapi;version=2.1.0',
|
---|
| 1062 | 'application/vnd.aai.asyncapi+json;version=2.1.0',
|
---|
| 1063 | 'application/vnd.aai.asyncapi+yaml;version=2.1.0',
|
---|
| 1064 | 'application/vnd.aai.asyncapi;version=2.2.0',
|
---|
| 1065 | 'application/vnd.aai.asyncapi+json;version=2.2.0',
|
---|
| 1066 | 'application/vnd.aai.asyncapi+yaml;version=2.2.0',
|
---|
| 1067 | 'application/vnd.aai.asyncapi;version=2.3.0',
|
---|
| 1068 | 'application/vnd.aai.asyncapi+json;version=2.3.0',
|
---|
| 1069 | 'application/vnd.aai.asyncapi+yaml;version=2.3.0',
|
---|
| 1070 | 'application/vnd.aai.asyncapi;version=2.4.0',
|
---|
| 1071 | 'application/vnd.aai.asyncapi+json;version=2.4.0',
|
---|
| 1072 | 'application/vnd.aai.asyncapi+yaml;version=2.4.0',
|
---|
| 1073 | 'application/vnd.aai.asyncapi;version=2.5.0',
|
---|
| 1074 | 'application/vnd.aai.asyncapi+json;version=2.5.0',
|
---|
| 1075 | 'application/vnd.aai.asyncapi+yaml;version=2.5.0',
|
---|
| 1076 | 'application/vnd.aai.asyncapi;version=2.6.0',
|
---|
| 1077 | 'application/vnd.aai.asyncapi+json;version=2.6.0',
|
---|
| 1078 | 'application/vnd.aai.asyncapi+yaml;version=2.6.0',
|
---|
| 1079 | ]
|
---|
| 1080 | ```
|
---|
| 1081 |
|
---|
| 1082 | ##### [openapi-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/resolve/strategies/openapi-2)
|
---|
| 1083 |
|
---|
| 1084 | External resolution strategy for understanding and resolving external dependencies of [OpenApi 2.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md) definitions.
|
---|
| 1085 |
|
---|
| 1086 | Supported media types:
|
---|
| 1087 |
|
---|
| 1088 | ```js
|
---|
| 1089 | [
|
---|
| 1090 | 'application/vnd.oai.openapi;version=2.0',
|
---|
| 1091 | 'application/vnd.oai.openapi+json;version=2.0',
|
---|
| 1092 | 'application/vnd.oai.openapi+yaml;version=2.0',
|
---|
| 1093 | ]
|
---|
| 1094 | ```
|
---|
| 1095 |
|
---|
| 1096 | ##### [openapi-3-0](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/resolve/strategies/openapi-3-0)
|
---|
| 1097 |
|
---|
| 1098 | External resolution strategy for understanding and resolving external dependencies of [OpenApi 3.0.x](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md) definitions.
|
---|
| 1099 |
|
---|
| 1100 | Supported media types:
|
---|
| 1101 |
|
---|
| 1102 | ```js
|
---|
| 1103 | [
|
---|
| 1104 | 'application/vnd.oai.openapi;version=3.0.0',
|
---|
| 1105 | 'application/vnd.oai.openapi+json;version=3.0.0',
|
---|
| 1106 | 'application/vnd.oai.openapi+yaml;version=3.0.0',
|
---|
| 1107 | 'application/vnd.oai.openapi;version=3.0.1',
|
---|
| 1108 | 'application/vnd.oai.openapi+json;version=3.0.1',
|
---|
| 1109 | 'application/vnd.oai.openapi+yaml;version=3.0.1',
|
---|
| 1110 | 'application/vnd.oai.openapi;version=3.0.2',
|
---|
| 1111 | 'application/vnd.oai.openapi+json;version=3.0.2',
|
---|
| 1112 | 'application/vnd.oai.openapi+yaml;version=3.0.2',
|
---|
| 1113 | 'application/vnd.oai.openapi;version=3.0.3',
|
---|
| 1114 | 'application/vnd.oai.openapi+json;version=3.0.3',
|
---|
| 1115 | 'application/vnd.oai.openapi+yaml;version=3.0.3',
|
---|
| 1116 | ]
|
---|
| 1117 | ```
|
---|
| 1118 |
|
---|
| 1119 | ##### [openapi-3-1](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/resolve/strategies/openapi-3-1)
|
---|
| 1120 |
|
---|
| 1121 | External resolution strategy for understanding and resolving external dependencies of [OpenApi 3.1.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md) definitions.
|
---|
| 1122 |
|
---|
| 1123 | Supported media types:
|
---|
| 1124 |
|
---|
| 1125 | ```js
|
---|
| 1126 | [
|
---|
| 1127 | 'application/vnd.oai.openapi;version=3.1.0',
|
---|
| 1128 | 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 1129 | 'application/vnd.oai.openapi+yaml;version=3.1.0'
|
---|
| 1130 | ]
|
---|
| 1131 | ```
|
---|
| 1132 |
|
---|
| 1133 | ##### External resolution strategies execution order
|
---|
| 1134 |
|
---|
| 1135 | It's important to understand that default external resolution strategies are run in specific order. The order is determined
|
---|
| 1136 | by the [options.resolve.strategies](https://github.com/swagger-api/apidom/blob/ba888d711a4292e8ed0b72e343c4902a4bf0d45a/packages/apidom-reference/src/configuration/saturated.ts#L41) option.
|
---|
| 1137 | Every strategy is pulled from `options.resolve.strategies` option and its `canResolve` method is called to determine
|
---|
| 1138 | whether the strategy can externally resolve the URI. If `canResolve` returns `true`, `resolve` method of strategy is called
|
---|
| 1139 | and result from external resolution is returned. No subsequent strategies are run. If `canResolve` returns
|
---|
| 1140 | `false`, next strategy is pulled and this process is repeated until one of the strategy's `canResolve` method
|
---|
| 1141 | returns `true` or until entire list of strategies is exhausted (throws error).
|
---|
| 1142 |
|
---|
| 1143 | ```js
|
---|
| 1144 | [
|
---|
| 1145 | OpenApi2ResolveStrategy(),
|
---|
| 1146 | OpenApi3_0ResolveStrategy(),
|
---|
| 1147 | OpenApi3_1ResolveStrategy(),
|
---|
| 1148 | AsyncApi2ResolveStrategy(),
|
---|
| 1149 | ]
|
---|
| 1150 | ```
|
---|
| 1151 | Most specific strategies are listed first, most generic are listed last.
|
---|
| 1152 |
|
---|
| 1153 | It's possible to **change** strategies **order globally** by mutating global `resolve` option:
|
---|
| 1154 |
|
---|
| 1155 | ```js
|
---|
| 1156 | import { options } from '@swagger-api/apidom-reference';
|
---|
| 1157 | import AsyncApi2ResolveStrategy from '@swagger-api/apidom-reference/resolve/strategies/asyncapi-2';
|
---|
| 1158 | import OpenApi2ResolveStrategy from '@swagger-api/apidom-reference/resolve/strategies/openapi-2';
|
---|
| 1159 | import OpenApi3_0ResolveStrategy from '@swagger-api/apidom-reference/resolve/strategies/openapi-3-0';
|
---|
| 1160 | import OpenApi3_1ResolveStrategy from '@swagger-api/apidom-reference/resolve/strategies/openapi-3-1';
|
---|
| 1161 |
|
---|
| 1162 | options.resolve.strategies = [
|
---|
| 1163 | OpenApi2ResolveStrategy(),
|
---|
| 1164 | OpenApi3_0ResolveStrategy(),
|
---|
| 1165 | OpenApi3_1ResolveStrategy(),
|
---|
| 1166 | AsyncApi2ResolveStrategy(),
|
---|
| 1167 | ];
|
---|
| 1168 | ```
|
---|
| 1169 |
|
---|
| 1170 | To **change** the strategies **order** on ad-hoc basis:
|
---|
| 1171 |
|
---|
| 1172 | ```js
|
---|
| 1173 | import { resolve } from '@swagger-api/apidom-reference';
|
---|
| 1174 | import AsyncApi2ResolveStrategy from '@swagger-api/apidom-reference/resolve/strategies/asyncapi-2';
|
---|
| 1175 | import OpenApi2ResolveStrategy from '@swagger-api/apidom-reference/resolve/strategies/openapi-2';
|
---|
| 1176 | import OpenApi3_0ResolveStrategy from '@swagger-api/apidom-reference/resolve/strategies/openapi-3-0';
|
---|
| 1177 | import OpenApi3_1ResolveStrategy from '@swagger-api/apidom-reference/resolve/strategies/openapi-3-1';
|
---|
| 1178 |
|
---|
| 1179 |
|
---|
| 1180 | await resolve('/home/user/oas.json', {
|
---|
| 1181 | parse: {
|
---|
| 1182 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 1183 | },
|
---|
| 1184 | resolve: {
|
---|
| 1185 | strategies: [
|
---|
| 1186 | AsyncApi2ResolveStrategy(),
|
---|
| 1187 | OpenApi2ResolveStrategy(),
|
---|
| 1188 | OpenApi3_0ResolveStrategy(),
|
---|
| 1189 | OpenApi3_1ResolveStrategy(),
|
---|
| 1190 | ]
|
---|
| 1191 | }
|
---|
| 1192 | });
|
---|
| 1193 | ```
|
---|
| 1194 | ##### Creating new external resolution strategy
|
---|
| 1195 |
|
---|
| 1196 | Resolve component can be extended by additional strategies. Every strategy is an object that
|
---|
| 1197 | must conform to the following interface/shape:
|
---|
| 1198 |
|
---|
| 1199 | ```typescript
|
---|
| 1200 | {
|
---|
| 1201 | // uniquely identifies this plugin
|
---|
| 1202 | name: string,
|
---|
| 1203 |
|
---|
| 1204 | // this method is called to determine whether the strategy can externally resolve the file
|
---|
| 1205 | canResolve(file: IFile): boolean {
|
---|
| 1206 | // ...implementation...
|
---|
| 1207 | },
|
---|
| 1208 |
|
---|
| 1209 | // this method actually externally resolves the file
|
---|
| 1210 | async resolve(file: IFile): Promise<ReferenceSet> {
|
---|
| 1211 | // ...implementation...
|
---|
| 1212 | }
|
---|
| 1213 | }
|
---|
| 1214 | ```
|
---|
| 1215 |
|
---|
| 1216 | New strategy is then provided as an option to a `resolve` function:
|
---|
| 1217 |
|
---|
| 1218 | ```js
|
---|
| 1219 | import { resolve, options } from '@swagger-api/apidom-reference';
|
---|
| 1220 |
|
---|
| 1221 | const myCustomResolverStrategy = {
|
---|
| 1222 | name: 'myCustomResolverStrategy',
|
---|
| 1223 | canResolve(file) {
|
---|
| 1224 | return true;
|
---|
| 1225 | },
|
---|
| 1226 | async resolve(file) {
|
---|
| 1227 | // implementation of external resolution
|
---|
| 1228 | }
|
---|
| 1229 | };
|
---|
| 1230 |
|
---|
| 1231 | await resolve('/home/user/oas.json', {
|
---|
| 1232 | parse: {
|
---|
| 1233 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 1234 | },
|
---|
| 1235 | resolve: {
|
---|
| 1236 | strategies: [...options.resolve.strategies, myCustomResolverStrategy],
|
---|
| 1237 | }
|
---|
| 1238 | });
|
---|
| 1239 | ```
|
---|
| 1240 |
|
---|
| 1241 | In this particular example we're adding our custom strategy as the last strategy
|
---|
| 1242 | to the available default external resolution strategy list, so there's a good chance that one of the
|
---|
| 1243 | default strategies detects that it can externally resolve the `/home/user/oas.json` file,
|
---|
| 1244 | resolves it and returns `ReferenceSet` object.
|
---|
| 1245 |
|
---|
| 1246 | If you want to force execution of your strategy, add it as a first one:
|
---|
| 1247 |
|
---|
| 1248 | ```js
|
---|
| 1249 | import { resolve, options } from '@swagger-api/apidom-reference';
|
---|
| 1250 |
|
---|
| 1251 |
|
---|
| 1252 | const myCustomResolverStrategy = {
|
---|
| 1253 | name: 'myCustomResolverStrategy',
|
---|
| 1254 | canResolve(file) {
|
---|
| 1255 | return true;
|
---|
| 1256 | },
|
---|
| 1257 | async resolve(file) {
|
---|
| 1258 | // implementation of external resolution
|
---|
| 1259 | }
|
---|
| 1260 | };
|
---|
| 1261 |
|
---|
| 1262 | await resolve('/home/user/oas.json', {
|
---|
| 1263 | parse: {
|
---|
| 1264 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 1265 | },
|
---|
| 1266 | resolve: {
|
---|
| 1267 | strategies: [myCustomResolverStrategy, ...options.resolve.strategies],
|
---|
| 1268 | }
|
---|
| 1269 | });
|
---|
| 1270 | ```
|
---|
| 1271 |
|
---|
| 1272 | To override the default strategies entirely, set `myCustomResolverStrategy` strategy to be the only one available:
|
---|
| 1273 |
|
---|
| 1274 | ```js
|
---|
| 1275 | import { resolve } from '@swagger-api/apidom-reference';
|
---|
| 1276 |
|
---|
| 1277 | const myCustomResolverStrategy = {
|
---|
| 1278 | name: 'myCustomResolverStrategy',
|
---|
| 1279 | canResolve(file) {
|
---|
| 1280 | return true;
|
---|
| 1281 | },
|
---|
| 1282 | async resolve(file) {
|
---|
| 1283 | // implementation of external resolution
|
---|
| 1284 | }
|
---|
| 1285 | };
|
---|
| 1286 |
|
---|
| 1287 | await resolve('/home/user/oas.json', {
|
---|
| 1288 | parse: {
|
---|
| 1289 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 1290 | },
|
---|
| 1291 | resolve: {
|
---|
| 1292 | strategies: [myCustomResolverPlugin],
|
---|
| 1293 | }
|
---|
| 1294 | });
|
---|
| 1295 | ```
|
---|
| 1296 | New strategies can be based on a predefined stamp called [ResolveStrategy](https://github.com/swagger-api/apidom/blob/main/packages/apidom-reference/src/resolve/strategies/ResolveStrategy.ts).
|
---|
| 1297 |
|
---|
| 1298 | ##### Manipulating external resolution strategies
|
---|
| 1299 |
|
---|
| 1300 | External resolution strategies can be added, removed, replaced or reordered. We've already covered these techniques in [Manipulating parser plugins section](#manipulating-parser-plugins).
|
---|
| 1301 |
|
---|
| 1302 | ## Dereference component
|
---|
| 1303 |
|
---|
| 1304 | Dereferencing is a process of transcluding referencing element (internal or external) with a referenced element
|
---|
| 1305 | using a specific [dereference strategy](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/dereference/strategies). Simply put, dereferencing is a process of reference removal.
|
---|
| 1306 | Dereferencing strategy is determined by asserting on `mediaType` option. [File Resolution](#file-resolution) (file content is read/fetched)
|
---|
| 1307 | and [Parse component](#parse-component) (file content is parsed) are used under the hood.
|
---|
| 1308 |
|
---|
| 1309 | **Dereferencing a file localed on a local filesystem:**
|
---|
| 1310 |
|
---|
| 1311 | ```js
|
---|
| 1312 | import { dereference } from '@swagger-api/apidom-reference';
|
---|
| 1313 |
|
---|
| 1314 | await dereference('/home/user/oas.json', {
|
---|
| 1315 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1316 | }); // Promise<ParseResultElement>
|
---|
| 1317 | ```
|
---|
| 1318 |
|
---|
| 1319 | **Dereferencing an HTTP(S) URL located on an internet:**
|
---|
| 1320 |
|
---|
| 1321 | ```js
|
---|
| 1322 | import { dereference } from '@swagger-api/apidom-reference';
|
---|
| 1323 |
|
---|
| 1324 | await dereference('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.1/webhook-example.json', {
|
---|
| 1325 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1326 | resolve: {
|
---|
| 1327 | resolverOpts: {
|
---|
| 1328 | axiosConfig: {
|
---|
| 1329 | timeout: 10
|
---|
| 1330 | },
|
---|
| 1331 | },
|
---|
| 1332 | },
|
---|
| 1333 | }); // Promise<ParseResultElement>
|
---|
| 1334 | ```
|
---|
| 1335 |
|
---|
| 1336 | **Dereferencing an ApiDOM fragment:**
|
---|
| 1337 |
|
---|
| 1338 | When dereferencing an ApiDOM fragment, [baseURI](https://github.com/swagger-api/apidom/blob/91763fa4ad876375a413e7049c28c2031c7bbe83/apidom/packages/apidom-reference/src/options/index.ts#L47)
|
---|
| 1339 | resolve option needs to be provided to have a starting point for external dependency resolution.
|
---|
| 1340 | `mediaType` parse option is unnecessary as we can directly assert the type of ApiDOM fragment.
|
---|
| 1341 |
|
---|
| 1342 | **ex.json**
|
---|
| 1343 |
|
---|
| 1344 | ```json
|
---|
| 1345 | {
|
---|
| 1346 | "externalParameter": {
|
---|
| 1347 | "name": "param1",
|
---|
| 1348 | "in": "query"
|
---|
| 1349 | }
|
---|
| 1350 | }
|
---|
| 1351 | ```
|
---|
| 1352 |
|
---|
| 1353 | ```js
|
---|
| 1354 | import { OpenApi3_1Element } from '@swagger-api/apidom-ns-openapi-3-1';
|
---|
| 1355 | import { dereferenceApiDOM } from '@swagger-api/apidom-reference';
|
---|
| 1356 |
|
---|
| 1357 | const apidom = OpenApi3_1Element.refract({
|
---|
| 1358 | openapi: '3.1.0',
|
---|
| 1359 | components: {
|
---|
| 1360 | parameters: {
|
---|
| 1361 | externalRef: {
|
---|
| 1362 | $ref: './ex.json#/externalParameter', // file is located at /home/user/ex.json
|
---|
| 1363 | }
|
---|
| 1364 | }
|
---|
| 1365 | }
|
---|
| 1366 | });
|
---|
| 1367 |
|
---|
| 1368 | const dereferenced = await dereferenceApiDOM(apidom, {
|
---|
| 1369 | resolve: { baseURI: '/home/user/' },
|
---|
| 1370 | });
|
---|
| 1371 | /**
|
---|
| 1372 | * OpenApi3_1Element {
|
---|
| 1373 | * openapi: '3.1.0',
|
---|
| 1374 | * components: {
|
---|
| 1375 | * parameters: {
|
---|
| 1376 | * externalRef: {
|
---|
| 1377 | * name: param1,
|
---|
| 1378 | * in: query
|
---|
| 1379 | * }
|
---|
| 1380 | * }
|
---|
| 1381 | * }
|
---|
| 1382 | * }
|
---|
| 1383 | */
|
---|
| 1384 | ```
|
---|
| 1385 |
|
---|
| 1386 | #### [Dereference strategies](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/dereference/strategies)
|
---|
| 1387 |
|
---|
| 1388 | Dereference strategy determines how a document is internally or externally dereferenced. Depending on document `mediaType` option,
|
---|
| 1389 | every strategy differs significantly. `Dereference component` comes with four (4) default dereference strategies.
|
---|
| 1390 |
|
---|
| 1391 | ##### [asyncapi-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/dereference/strategies/asyncapi-2)
|
---|
| 1392 |
|
---|
| 1393 | Dereference strategy for dereferencing [AsyncApi 2.x.y](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md) definitions.
|
---|
| 1394 |
|
---|
| 1395 | Supported media types:
|
---|
| 1396 |
|
---|
| 1397 | ```js
|
---|
| 1398 | [
|
---|
| 1399 | 'application/vnd.aai.asyncapi;version=2.0.0',
|
---|
| 1400 | 'application/vnd.aai.asyncapi+json;version=2.0.0',
|
---|
| 1401 | 'application/vnd.aai.asyncapi+yaml;version=2.0.0',
|
---|
| 1402 | 'application/vnd.aai.asyncapi;version=2.1.0',
|
---|
| 1403 | 'application/vnd.aai.asyncapi+json;version=2.1.0',
|
---|
| 1404 | 'application/vnd.aai.asyncapi+yaml;version=2.1.0',
|
---|
| 1405 | 'application/vnd.aai.asyncapi;version=2.2.0',
|
---|
| 1406 | 'application/vnd.aai.asyncapi+json;version=2.2.0',
|
---|
| 1407 | 'application/vnd.aai.asyncapi+yaml;version=2.2.0',
|
---|
| 1408 | 'application/vnd.aai.asyncapi;version=2.3.0',
|
---|
| 1409 | 'application/vnd.aai.asyncapi+json;version=2.3.0',
|
---|
| 1410 | 'application/vnd.aai.asyncapi+yaml;version=2.3.0',
|
---|
| 1411 | 'application/vnd.aai.asyncapi;version=2.4.0',
|
---|
| 1412 | 'application/vnd.aai.asyncapi+json;version=2.4.0',
|
---|
| 1413 | 'application/vnd.aai.asyncapi+yaml;version=2.4.0',
|
---|
| 1414 | 'application/vnd.aai.asyncapi;version=2.5.0',
|
---|
| 1415 | 'application/vnd.aai.asyncapi+json;version=2.5.0',
|
---|
| 1416 | 'application/vnd.aai.asyncapi+yaml;version=2.5.0',
|
---|
| 1417 | 'application/vnd.aai.asyncapi;version=2.6.0',
|
---|
| 1418 | 'application/vnd.aai.asyncapi+json;version=2.6.0',
|
---|
| 1419 | 'application/vnd.aai.asyncapi+yaml;version=2.6.0',
|
---|
| 1420 | ]
|
---|
| 1421 | ```
|
---|
| 1422 |
|
---|
| 1423 | ##### [openapi-2](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/dereference/strategies/openapi-2)
|
---|
| 1424 |
|
---|
| 1425 | Dereference strategy for dereferencing [OpenApi 2.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md) definitions.
|
---|
| 1426 |
|
---|
| 1427 | Supported media types:
|
---|
| 1428 |
|
---|
| 1429 | ```js
|
---|
| 1430 | [
|
---|
| 1431 | 'application/vnd.oai.openapi;version=2.0',
|
---|
| 1432 | 'application/vnd.oai.openapi+json;version=2.0',
|
---|
| 1433 | 'application/vnd.oai.openapi+yaml;version=2.0',
|
---|
| 1434 | ]
|
---|
| 1435 | ```
|
---|
| 1436 |
|
---|
| 1437 | ##### [openapi-3-0](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/dereference/strategies/openapi-3-0)
|
---|
| 1438 |
|
---|
| 1439 | Dereference strategy for dereferencing [OpenApi 3.0.x](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md) definitions.
|
---|
| 1440 |
|
---|
| 1441 | Supported media types:
|
---|
| 1442 |
|
---|
| 1443 | ```js
|
---|
| 1444 | [
|
---|
| 1445 | 'application/vnd.oai.openapi;version=3.0.0',
|
---|
| 1446 | 'application/vnd.oai.openapi+json;version=3.0.0',
|
---|
| 1447 | 'application/vnd.oai.openapi+yaml;version=3.0.0',
|
---|
| 1448 | 'application/vnd.oai.openapi;version=3.0.1',
|
---|
| 1449 | 'application/vnd.oai.openapi+json;version=3.0.1',
|
---|
| 1450 | 'application/vnd.oai.openapi+yaml;version=3.0.1',
|
---|
| 1451 | 'application/vnd.oai.openapi;version=3.0.2',
|
---|
| 1452 | 'application/vnd.oai.openapi+json;version=3.0.2',
|
---|
| 1453 | 'application/vnd.oai.openapi+yaml;version=3.0.2',
|
---|
| 1454 | 'application/vnd.oai.openapi;version=3.0.3',
|
---|
| 1455 | 'application/vnd.oai.openapi+json;version=3.0.3',
|
---|
| 1456 | 'application/vnd.oai.openapi+yaml;version=3.0.3',
|
---|
| 1457 | ]
|
---|
| 1458 | ```
|
---|
| 1459 |
|
---|
| 1460 | ##### [openapi-3-1](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/dereference/strategies/openapi-3-1)
|
---|
| 1461 |
|
---|
| 1462 | Dereference strategy for dereferencing [OpenApi 3.1.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md) definitions.
|
---|
| 1463 |
|
---|
| 1464 | Supported media types:
|
---|
| 1465 |
|
---|
| 1466 | ```js
|
---|
| 1467 | [
|
---|
| 1468 | 'application/vnd.oai.openapi;version=3.1.0',
|
---|
| 1469 | 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 1470 | 'application/vnd.oai.openapi+yaml;version=3.1.0'
|
---|
| 1471 | ]
|
---|
| 1472 | ```
|
---|
| 1473 |
|
---|
| 1474 | ##### Dereference strategies execution order
|
---|
| 1475 |
|
---|
| 1476 | It's important to understand that default dereference strategies are run in specific order. The order is determined
|
---|
| 1477 | by the [options.dereference.strategies](https://github.com/swagger-api/apidom/blob/b3a391481360004d3d4a56c1467cece557442ec8/apidom/packages/apidom-reference/src/options/index.ts#L88) option.
|
---|
| 1478 | Every strategy is pulled from `options.dereference.strategies` option and it's `canDereference` method is called to determine
|
---|
| 1479 | whether the strategy can dereference the URI. If `canDereference` returns `true`, `dereference` method of strategy is called
|
---|
| 1480 | and result from dereferencing is returned. No subsequent strategies are run. If `canDereference` returns
|
---|
| 1481 | `false`, next strategy is pulled and this process is repeated until one of the strategy's `canDereference` method
|
---|
| 1482 | returns `true` or until entire list of strategies is exhausted (throws error).
|
---|
| 1483 |
|
---|
| 1484 | ```js
|
---|
| 1485 | [
|
---|
| 1486 | OpenApi2DereferenceStrategy(),
|
---|
| 1487 | OpenApi3_0DereferenceStrategy(),
|
---|
| 1488 | OpenApi3_1DereferenceStrategy(),
|
---|
| 1489 | AsyncApi2DereferenceStrategy(),
|
---|
| 1490 | ]
|
---|
| 1491 | ```
|
---|
| 1492 | Most specific strategies are listed first, most generic are listed last.
|
---|
| 1493 |
|
---|
| 1494 | It's possible to **change** strategies **order globally** by mutating global `dereference` option:
|
---|
| 1495 |
|
---|
| 1496 | ```js
|
---|
| 1497 | import { options } from '@swagger-api/apidom-reference';
|
---|
| 1498 | import AsyncApi2DereferenceStrategy from '@swagger-api/apidom-reference/dereference/strategies/asyncapi-2'
|
---|
| 1499 | import OpenApi2DereferenceStrategy from '@swagger-api/apidom-reference/dereference/strategies/openapi-2'
|
---|
| 1500 | import OpenApi3_0DereferenceStrategy from '@swagger-api/apidom-reference/dereference/strategies/openapi-3-0'
|
---|
| 1501 | import OpenApi3_1DereferenceStrategy from '@swagger-api/apidom-reference/dereference/strategies/openapi-3-1'
|
---|
| 1502 |
|
---|
| 1503 | options.dereference.strategies = [
|
---|
| 1504 | OpenApi2DereferenceStrategy(),
|
---|
| 1505 | OpenApi3_0DereferenceStrategy(),
|
---|
| 1506 | OpenApi3_1DereferenceStrategy(),
|
---|
| 1507 | AsyncApi2DereferenceStrategy(),
|
---|
| 1508 | ];
|
---|
| 1509 | ```
|
---|
| 1510 |
|
---|
| 1511 | To **change** the strategies **order** on ad-hoc basis:
|
---|
| 1512 |
|
---|
| 1513 | ```js
|
---|
| 1514 | import { dereference } from '@swagger-api/apidom-reference';
|
---|
| 1515 | import AsyncApi2DereferenceStrategy from '@swagger-api/apidom-reference/dereference/strategies/asyncapi-2'
|
---|
| 1516 | import OpenApi2DereferenceStrategy from '@swagger-api/apidom-reference/dereference/strategies/openapi-2'
|
---|
| 1517 | import OpenApi3_0DereferenceStrategy from '@swagger-api/apidom-reference/dereference/strategies/openapi-3-0'
|
---|
| 1518 | import OpenApi3_1DereferenceStrategy from '@swagger-api/apidom-reference/dereference/strategies/openapi-3-1'
|
---|
| 1519 |
|
---|
| 1520 | await dereference('/home/user/oas.json', {
|
---|
| 1521 | parse: {
|
---|
| 1522 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 1523 | },
|
---|
| 1524 | dereference: {
|
---|
| 1525 | strategies: [
|
---|
| 1526 | AsyncApi2DereferenceStrategy(),
|
---|
| 1527 | OpenApi2DereferenceStrategy(),
|
---|
| 1528 | OpenApi3_0DereferenceStrategy(),
|
---|
| 1529 | OpenApi3_1DereferenceStrategy(),
|
---|
| 1530 | ]
|
---|
| 1531 | }
|
---|
| 1532 | });
|
---|
| 1533 | ```
|
---|
| 1534 | ##### Creating new dereference strategy
|
---|
| 1535 |
|
---|
| 1536 | Dereference component can be extended by additional strategies. Every strategy is an object that
|
---|
| 1537 | must conform to the following interface/shape:
|
---|
| 1538 |
|
---|
| 1539 | ```typescript
|
---|
| 1540 | {
|
---|
| 1541 | // uniquely identifies this plugin
|
---|
| 1542 | name: string,
|
---|
| 1543 |
|
---|
| 1544 | // this method is called to determine whether the strategy can dereference the file
|
---|
| 1545 | canDereference(file: IFile): boolean {
|
---|
| 1546 | // ...implementation...
|
---|
| 1547 | },
|
---|
| 1548 |
|
---|
| 1549 | // this method actually dereferences the file
|
---|
| 1550 | async dereference(file: IFile, options: IReferenceOptions): Promise<ParseResultElement> {
|
---|
| 1551 | // ...implementation...
|
---|
| 1552 | }
|
---|
| 1553 | }
|
---|
| 1554 | ```
|
---|
| 1555 |
|
---|
| 1556 | New strategy is then provided as an option to the `dereference` function:
|
---|
| 1557 |
|
---|
| 1558 | ```js
|
---|
| 1559 | import { dereference, options } from '@swagger-api/apidom-reference';
|
---|
| 1560 |
|
---|
| 1561 | const myCustomDereferenceStrategy = {
|
---|
| 1562 | name: 'myCustomDereferenceStrategy',
|
---|
| 1563 | canDereference(file) {
|
---|
| 1564 | return true;
|
---|
| 1565 | },
|
---|
| 1566 | async dereference(file, options: IReferenceOptions) {
|
---|
| 1567 | // implementation of dereferenceing
|
---|
| 1568 | }
|
---|
| 1569 | };
|
---|
| 1570 |
|
---|
| 1571 | await dereference('/home/user/oas.json', {
|
---|
| 1572 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1573 | dereference: {
|
---|
| 1574 | strategies: [...options.dereference.strategies, myCustomDereferenceStrategy],
|
---|
| 1575 | }
|
---|
| 1576 | });
|
---|
| 1577 | ```
|
---|
| 1578 |
|
---|
| 1579 | In this particular example we're adding our custom strategy as the last strategy
|
---|
| 1580 | to the available default dereference strategy list, so there's a good chance that one of the
|
---|
| 1581 | default strategies detects that it can dereference the `/home/user/oas.json` file,
|
---|
| 1582 | dereferences it and returns a dereferenced element.
|
---|
| 1583 |
|
---|
| 1584 | If you want to force execution of your strategy, add it as a first one:
|
---|
| 1585 |
|
---|
| 1586 | ```js
|
---|
| 1587 | import { dereference, options } from '@swagger-api/apidom-reference';
|
---|
| 1588 |
|
---|
| 1589 | const myCustomDereferenceStrategy = {
|
---|
| 1590 | name: 'myCustomDereferenceStrategy',
|
---|
| 1591 | canDereference(file) {
|
---|
| 1592 | return true;
|
---|
| 1593 | },
|
---|
| 1594 | async dereference(file, options: IReferenceOptions) {
|
---|
| 1595 | // implementation of dereferenceing
|
---|
| 1596 | }
|
---|
| 1597 | };
|
---|
| 1598 |
|
---|
| 1599 | await dereference('/home/user/oas.json', {
|
---|
| 1600 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1601 | dereference: {
|
---|
| 1602 | strategies: [myCustomDereferenceStrategy, ...options.dereference.strategies],
|
---|
| 1603 | }
|
---|
| 1604 | });
|
---|
| 1605 | ```
|
---|
| 1606 |
|
---|
| 1607 | To override the default strategies entirely, set `myCustomDereferenceStrategy` strategy to be the only one available:
|
---|
| 1608 |
|
---|
| 1609 | ```js
|
---|
| 1610 | import { dereference } from '@swagger-api/apidom-reference';
|
---|
| 1611 |
|
---|
| 1612 | const myCustomDereferenceStrategy = {
|
---|
| 1613 | name: 'myCustomDereferenceStrategy',
|
---|
| 1614 | canDereference(file) {
|
---|
| 1615 | return true;
|
---|
| 1616 | },
|
---|
| 1617 | async dereference(file, options: IReferenceOptions) {
|
---|
| 1618 | // implementation of dereferenceing
|
---|
| 1619 | }
|
---|
| 1620 | };
|
---|
| 1621 |
|
---|
| 1622 | await dereference('/home/user/oas.json', {
|
---|
| 1623 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1624 | dereference: {
|
---|
| 1625 | strategies: [myCustomDereferenceStrategy],
|
---|
| 1626 | }
|
---|
| 1627 | });
|
---|
| 1628 | ```
|
---|
| 1629 |
|
---|
| 1630 | New strategies can be based on a predefined stamp called [DereferenceStrategy](https://github.com/swagger-api/apidom/blob/main/packages/apidom-reference/src/dereference/strategies/DereferenceStrategy.ts).
|
---|
| 1631 |
|
---|
| 1632 | ##### Manipulating dereference strategies
|
---|
| 1633 |
|
---|
| 1634 | Dereference strategies can be added, removed, replaced or reordered. We've already covered these techniques in [Manipulating parser plugins section](#manipulating-parser-plugins).
|
---|
| 1635 |
|
---|
| 1636 | ##### Increasing speed of dereference
|
---|
| 1637 |
|
---|
| 1638 | Our default dereference strategies are built on asynchronous sequential traversing of ApiDOM.
|
---|
| 1639 | The total time of dereferencing is the sum of `traversing` + sum of `external resolution per referencing element`.
|
---|
| 1640 | By having a huge number of external dependencies in your definition file, dereferencing can get quite slow.
|
---|
| 1641 | Fortunately there is solution for this by running an `external resolution` first,
|
---|
| 1642 | and passing its result to dereferencing via an option. External resolution is built on asynchronous parallel traversal (on single file),
|
---|
| 1643 | so it's theoretically always faster on huge amount of external dependencies than the dereferencing.
|
---|
| 1644 |
|
---|
| 1645 | ```js
|
---|
| 1646 | import { resolve, dereference } from '@swagger-api/apidom-reference';
|
---|
| 1647 |
|
---|
| 1648 | const refSet = await resolve('/home/user/oas.json', {
|
---|
| 1649 | parse: { mediType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1650 | });
|
---|
| 1651 |
|
---|
| 1652 | const dereferenced = await dereference('/home/user/oas.json', {
|
---|
| 1653 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1654 | dereference: { refSet },
|
---|
| 1655 | });
|
---|
| 1656 | ```
|
---|
| 1657 |
|
---|
| 1658 | Total time of dereferencing is now the sum of `external resolution traversing` + `dereference traversing` + sum of `max external resolution per file`.
|
---|
| 1659 |
|
---|
| 1660 |
|
---|
| 1661 | ## Bundle component
|
---|
| 1662 |
|
---|
| 1663 | Bundling is a convenient way to package up resources spread across multiple files in a single file
|
---|
| 1664 | (**Compound Document**) using a specific [bundle strategy](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/bundle/strategies).
|
---|
| 1665 |
|
---|
| 1666 | The bundling process for creating a Compound Document is defined as taking references (such as "$ref")
|
---|
| 1667 | to an external Resource and embedding the referenced Resources within the referring document.
|
---|
| 1668 | Bundling SHOULD be done in such a way that all URIs (used for referencing) in the base document
|
---|
| 1669 | and any referenced/embedded documents do not require altering.
|
---|
| 1670 |
|
---|
| 1671 | Bundling strategy is determined by asserting on `mediaType` option. [File Resolution](#file-resolution) (file content is read/fetched)
|
---|
| 1672 | and [Parse component](#parse-component) (file content is parsed) are used under the hood.
|
---|
| 1673 |
|
---|
| 1674 | **Bundling a file localed on a local filesystem:**
|
---|
| 1675 |
|
---|
| 1676 | ```js
|
---|
| 1677 | import { bundle } from '@swagger-api/apidom-reference';
|
---|
| 1678 |
|
---|
| 1679 | await bundle('/home/user/oas.json', {
|
---|
| 1680 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1681 | }); // Promise<ParseResultElement>
|
---|
| 1682 | ```
|
---|
| 1683 |
|
---|
| 1684 | **Bundling an HTTP(S) URL located on an internet:**
|
---|
| 1685 |
|
---|
| 1686 | ```js
|
---|
| 1687 | import { bundle } from '@swagger-api/apidom-reference';
|
---|
| 1688 |
|
---|
| 1689 | await bundle('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.1/webhook-example.json', {
|
---|
| 1690 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1691 | resolve: {
|
---|
| 1692 | resolverOpts: {
|
---|
| 1693 | axiosConfig: {
|
---|
| 1694 | timeout: 10
|
---|
| 1695 | },
|
---|
| 1696 | },
|
---|
| 1697 | },
|
---|
| 1698 | }); // Promise<ParseResultElement>
|
---|
| 1699 | ```
|
---|
| 1700 |
|
---|
| 1701 | #### [Bundle strategies](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/bundle/strategies)
|
---|
| 1702 |
|
---|
| 1703 | Bundle strategy determines how a document is bundled into a Compound Document. Depending on document `mediaType` option,
|
---|
| 1704 | every strategy differs significantly. `Bundle component` comes with single (1) default bundle strategy.
|
---|
| 1705 |
|
---|
| 1706 | ##### [openapi-3-1](https://github.com/swagger-api/apidom/tree/main/packages/apidom-reference/src/bundle/strategies/openapi-3-1)
|
---|
| 1707 |
|
---|
| 1708 | Bundle strategy for bundling [OpenApi 3.1.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md) definitions.
|
---|
| 1709 |
|
---|
| 1710 | Supported media types:
|
---|
| 1711 |
|
---|
| 1712 | ```js
|
---|
| 1713 | [
|
---|
| 1714 | 'application/vnd.oai.openapi;version=3.1.0',
|
---|
| 1715 | 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 1716 | 'application/vnd.oai.openapi+yaml;version=3.1.0'
|
---|
| 1717 | ]
|
---|
| 1718 | ```
|
---|
| 1719 |
|
---|
| 1720 | ##### Bundle strategies execution order
|
---|
| 1721 |
|
---|
| 1722 | It's important to understand that default bundle strategies are run in specific order. The order is determined
|
---|
| 1723 | by the `options.bundle.strategies` option.
|
---|
| 1724 | Every strategy is pulled from `options.bundle.strategies` option, and it's `canBundle` method is called to determine
|
---|
| 1725 | whether the strategy can bundle the URI. If `canBundle` returns `true`, `bundle` method of strategy is called
|
---|
| 1726 | and result from bundling is returned. No subsequent strategies are run. If `canBundle` returns
|
---|
| 1727 | `false`, next strategy is pulled and this process is repeated until one of the strategy's `canBundle` method
|
---|
| 1728 | returns `true` or until entire list of strategies is exhausted (throws error).
|
---|
| 1729 |
|
---|
| 1730 | ```js
|
---|
| 1731 | [
|
---|
| 1732 | OpenApi3_1BundleStrategy(),
|
---|
| 1733 | ]
|
---|
| 1734 | ```
|
---|
| 1735 | Most specific strategies are listed first, most generic are listed last.
|
---|
| 1736 |
|
---|
| 1737 | It's possible to **change** strategies **order globally** by mutating global `bundle` option:
|
---|
| 1738 |
|
---|
| 1739 | ```js
|
---|
| 1740 | import { options } from '@swagger-api/apidom-reference';
|
---|
| 1741 | import OpenApi3_1BundleStrategy from '@swagger-api/apidom-reference/bundle/strategies/openapi-3-1'
|
---|
| 1742 |
|
---|
| 1743 | options.dereference.strategies = [
|
---|
| 1744 | OpenApi3_1DereferenceStrategy(),
|
---|
| 1745 | ];
|
---|
| 1746 | ```
|
---|
| 1747 |
|
---|
| 1748 | To **change** the strategies **order** on ad-hoc basis:
|
---|
| 1749 |
|
---|
| 1750 | ```js
|
---|
| 1751 | import { bundle } from '@swagger-api/apidom-reference';
|
---|
| 1752 | import OpenApi3_1BundleStrategy from '@swagger-api/apidom-reference/bundle/strategies/openapi-3-1'
|
---|
| 1753 |
|
---|
| 1754 | await bundle('/home/user/oas.json', {
|
---|
| 1755 | parse: {
|
---|
| 1756 | mediaType: 'application/vnd.oai.openapi+json;version=3.1.0',
|
---|
| 1757 | },
|
---|
| 1758 | bundle: {
|
---|
| 1759 | strategies: [
|
---|
| 1760 | OpenApi3_1BundleStrategy(),
|
---|
| 1761 | ]
|
---|
| 1762 | }
|
---|
| 1763 | });
|
---|
| 1764 | ```
|
---|
| 1765 | ##### Creating new bundle strategy
|
---|
| 1766 |
|
---|
| 1767 | Bundle component can be extended by additional strategies. Every strategy is an object that
|
---|
| 1768 | must conform to the following interface/shape:
|
---|
| 1769 |
|
---|
| 1770 | ```typescript
|
---|
| 1771 | {
|
---|
| 1772 | // uniquely identifies this plugin
|
---|
| 1773 | name: string,
|
---|
| 1774 |
|
---|
| 1775 | // this method is called to determine whether the strategy can bundle the file
|
---|
| 1776 | canBundle(file: IFile): boolean {
|
---|
| 1777 | // ...implementation...
|
---|
| 1778 | },
|
---|
| 1779 |
|
---|
| 1780 | // this method actually bundles the file
|
---|
| 1781 | async bundle(file: IFile, options: IReferenceOptions): Promise<ParseResultElement> {
|
---|
| 1782 | // ...implementation...
|
---|
| 1783 | }
|
---|
| 1784 | }
|
---|
| 1785 | ```
|
---|
| 1786 |
|
---|
| 1787 | New strategy is then provided as an option to the `bundle` function:
|
---|
| 1788 |
|
---|
| 1789 | ```js
|
---|
| 1790 | import { bundle, options } from '@swagger-api/apidom-reference';
|
---|
| 1791 |
|
---|
| 1792 | const myCustomBundleStrategy = {
|
---|
| 1793 | name: 'myCustomByndleStrategy',
|
---|
| 1794 | canBundle(file) {
|
---|
| 1795 | return true;
|
---|
| 1796 | },
|
---|
| 1797 | async bundle(file, options: IReferenceOptions) {
|
---|
| 1798 | // implementation of bundling
|
---|
| 1799 | }
|
---|
| 1800 | };
|
---|
| 1801 |
|
---|
| 1802 | await bundle('/home/user/oas.json', {
|
---|
| 1803 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1804 | bundle: {
|
---|
| 1805 | strategies: [...options.bundle.strategies, myCustomBundleStrategy],
|
---|
| 1806 | }
|
---|
| 1807 | });
|
---|
| 1808 | ```
|
---|
| 1809 |
|
---|
| 1810 | In this particular example we're adding our custom strategy as the last strategy
|
---|
| 1811 | to the available default bundle strategy list, so there's a good chance that one of the
|
---|
| 1812 | default strategies detects that it can bundle the `/home/user/oas.json` file,
|
---|
| 1813 | bundles it and returns a bundled element.
|
---|
| 1814 |
|
---|
| 1815 | If you want to force execution of your strategy, add it as a first one:
|
---|
| 1816 |
|
---|
| 1817 | ```js
|
---|
| 1818 | import { bundle, options } from '@swagger-api/apidom-reference';
|
---|
| 1819 |
|
---|
| 1820 | const myCustomBundleStrategy = {
|
---|
| 1821 | name: 'myCustomBundleStrategy',
|
---|
| 1822 | canBundle(file) {
|
---|
| 1823 | return true;
|
---|
| 1824 | },
|
---|
| 1825 | async bundle(file, options: IReferenceOptions) {
|
---|
| 1826 | // implementation of bundling
|
---|
| 1827 | }
|
---|
| 1828 | };
|
---|
| 1829 |
|
---|
| 1830 |
|
---|
| 1831 | await bundle('/home/user/oas.json', {
|
---|
| 1832 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1833 | bundle: {
|
---|
| 1834 | strategies: [myCustomBundleStrategy, ...options.bundle.strategies],
|
---|
| 1835 | }
|
---|
| 1836 | });
|
---|
| 1837 | ```
|
---|
| 1838 |
|
---|
| 1839 | To override the default strategies entirely, set `myCustomBundleStrategy` strategy to be the only one available:
|
---|
| 1840 |
|
---|
| 1841 | ```js
|
---|
| 1842 | import { bundle } from '@swagger-api/apidom-reference';
|
---|
| 1843 |
|
---|
| 1844 | const myCustomBundleStrategy = {
|
---|
| 1845 | name: 'myCustomBundleStrategy',
|
---|
| 1846 | canBundle(file) {
|
---|
| 1847 | return true;
|
---|
| 1848 | },
|
---|
| 1849 | async bundle(file, options: IReferenceOptions) {
|
---|
| 1850 | // implementation of bundling
|
---|
| 1851 | }
|
---|
| 1852 | };
|
---|
| 1853 |
|
---|
| 1854 | await bundle('/home/user/oas.json', {
|
---|
| 1855 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1856 | bundle: {
|
---|
| 1857 | strategies: [myCustomBundleStrategy],
|
---|
| 1858 | }
|
---|
| 1859 | });
|
---|
| 1860 | ```
|
---|
| 1861 |
|
---|
| 1862 | New strategies can be based on a predefined stamp called [BundleStrategy](https://github.com/swagger-api/apidom/blob/main/packages/apidom-reference/src/bundle/strategies/BundleStrategy.ts).
|
---|
| 1863 |
|
---|
| 1864 | ##### Manipulating bundle strategies
|
---|
| 1865 |
|
---|
| 1866 | Bundle strategies can be added, removed, replaced or reordered. We've already covered these techniques in [Manipulating parser plugins section](#manipulating-parser-plugins).
|
---|
| 1867 |
|
---|
| 1868 | ##### Increasing speed of bundling
|
---|
| 1869 |
|
---|
| 1870 | Our default bundling strategies are built on asynchronous sequential traversing of ApiDOM.
|
---|
| 1871 | The total time of bundling is the sum of `traversing` + sum of `external resolution per referencing element`.
|
---|
| 1872 | By having a huge number of external dependencies in your definition file, bundling can get quite slow.
|
---|
| 1873 | Fortunately there is solution for this by running an `external resolution` first,
|
---|
| 1874 | and passing its result to bundling via an option. External resolution is built on asynchronous parallel traversal (on single file),
|
---|
| 1875 | so it's theoretically always faster on huge amount of external dependencies than the bundling.
|
---|
| 1876 |
|
---|
| 1877 | ```js
|
---|
| 1878 | import { resolve, bundle } from '@swagger-api/apidom-reference';
|
---|
| 1879 |
|
---|
| 1880 | const refSet = await resolve('/home/user/oas.json', {
|
---|
| 1881 | parse: { mediType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1882 | });
|
---|
| 1883 |
|
---|
| 1884 | const bundled = await bundle('/home/user/oas.json', {
|
---|
| 1885 | parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
|
---|
| 1886 | bundle: { refSet },
|
---|
| 1887 | });
|
---|
| 1888 | ```
|
---|
| 1889 |
|
---|
| 1890 | Total time of bundling is now the sum of `external resolution traversing` + `bundle traversing` + sum of `max external resolution per file`.
|
---|