@usearazzo/resolver 1.0.1-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +20 -0
- package/README.md +99 -0
- package/dist/arazzo-resolver.browser.js +93083 -0
- package/dist/arazzo-resolver.browser.min.js +1 -0
- package/package.json +78 -0
- package/src/bundle/arazzo.cjs +92 -0
- package/src/bundle/arazzo.mjs +83 -0
- package/src/bundle/openapi.cjs +101 -0
- package/src/bundle/openapi.mjs +92 -0
- package/src/dereference/arazzo.cjs +246 -0
- package/src/dereference/arazzo.mjs +236 -0
- package/src/dereference/openapi.cjs +239 -0
- package/src/dereference/openapi.mjs +229 -0
- package/src/errors/BundleError.cjs +17 -0
- package/src/errors/BundleError.mjs +12 -0
- package/src/errors/DereferenceError.cjs +17 -0
- package/src/errors/DereferenceError.mjs +12 -0
- package/src/errors/ResolveError.cjs +17 -0
- package/src/errors/ResolveError.mjs +12 -0
- package/src/index.cjs +129 -0
- package/src/index.mjs +9 -0
- package/src/resolve/arazzo.cjs +208 -0
- package/src/resolve/arazzo.mjs +198 -0
- package/src/resolve/openapi.cjs +234 -0
- package/src/resolve/openapi.mjs +224 -0
- package/types/resolver.d.ts +529 -0
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@usearazzo/resolver",
|
|
3
|
+
"version": "1.0.1-alpha.2",
|
|
4
|
+
"description": "Resolver for Arazzo Documents.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"arazzo",
|
|
7
|
+
"arazzo-specification",
|
|
8
|
+
"resolver",
|
|
9
|
+
"resolve",
|
|
10
|
+
"dereference",
|
|
11
|
+
"workflow",
|
|
12
|
+
"workflows"
|
|
13
|
+
],
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public",
|
|
16
|
+
"registry": "https://registry.npmjs.org",
|
|
17
|
+
"provenance": false,
|
|
18
|
+
"tag": "latest"
|
|
19
|
+
},
|
|
20
|
+
"type": "module",
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=20.10.0"
|
|
24
|
+
},
|
|
25
|
+
"unpkg": "./dist/arazzo-resolver.browser.min.js",
|
|
26
|
+
"main": "./src/index.cjs",
|
|
27
|
+
"exports": {
|
|
28
|
+
"types": "./types/resolver.d.ts",
|
|
29
|
+
"import": "./src/index.mjs",
|
|
30
|
+
"require": "./src/index.cjs"
|
|
31
|
+
},
|
|
32
|
+
"types": "./types/resolver.d.ts",
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "npm run clean && run-p --max-parallel ${CPU_CORES:-2} typescript:declaration build:es build:cjs build:umd:browser",
|
|
35
|
+
"build:es": "cross-env BABEL_ENV=es babel src --out-dir src --extensions '.ts' --out-file-extension '.mjs' --root-mode 'upward'",
|
|
36
|
+
"build:cjs": "cross-env BABEL_ENV=cjs babel src --out-dir src --extensions '.ts' --out-file-extension '.cjs' --root-mode 'upward'",
|
|
37
|
+
"build:umd:browser": "cross-env BABEL_ENV=browser webpack --config config/webpack/browser.config.js --progress",
|
|
38
|
+
"lint": "eslint ./",
|
|
39
|
+
"lint:fix": "eslint ./ --fix",
|
|
40
|
+
"clean": "rimraf --glob 'src/**/*.mjs' 'src/**/*.cjs' 'test/**/*.mjs' ./dist ./types",
|
|
41
|
+
"typescript:check-types": "tsc --noEmit",
|
|
42
|
+
"typescript:declaration": "tsc -p tsconfig.declaration.json && api-extractor run -l -c ./config/api-extractor/api-extractor.json",
|
|
43
|
+
"test": "npm run build:es && cross-env BABEL_ENV=es babel test --out-dir test --extensions '.ts' --out-file-extension '.mjs' --root-mode 'upward' && cross-env NODE_ENV=test mocha",
|
|
44
|
+
"prepack": "copyfiles -u 2 ../../LICENSE . && copyfiles -u 2 ../../NOTICE .",
|
|
45
|
+
"postpack": "rimraf NOTICE LICENSE"
|
|
46
|
+
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/usearazzo/arazzo-toolkit.git"
|
|
50
|
+
},
|
|
51
|
+
"author": "Vladimir Gorej <vladimir.gorej@gmail.com>",
|
|
52
|
+
"license": "Apache-2.0",
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@babel/runtime-corejs3": "^8.0.5",
|
|
55
|
+
"@speclynx/apidom-datamodel": "^5.2.5",
|
|
56
|
+
"@speclynx/apidom-error": "^5.2.5",
|
|
57
|
+
"@speclynx/apidom-ns-arazzo-1": "^5.2.5",
|
|
58
|
+
"@speclynx/apidom-ns-openapi-2": "^5.2.5",
|
|
59
|
+
"@speclynx/apidom-ns-openapi-3-0": "^5.2.5",
|
|
60
|
+
"@speclynx/apidom-ns-openapi-3-1": "^5.2.5",
|
|
61
|
+
"@speclynx/apidom-reference": "^5.2.5",
|
|
62
|
+
"@usearazzo/parser": "1.0.1-alpha.2",
|
|
63
|
+
"type-fest": "^5.4.4"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@speclynx/apidom-core": "^5.2.5"
|
|
67
|
+
},
|
|
68
|
+
"files": [
|
|
69
|
+
"src/**/*.mjs",
|
|
70
|
+
"src/**/*.cjs",
|
|
71
|
+
"dist/",
|
|
72
|
+
"types/resolver.d.ts",
|
|
73
|
+
"LICENSE",
|
|
74
|
+
"NOTICE",
|
|
75
|
+
"README.md",
|
|
76
|
+
"CHANGELOG.md"
|
|
77
|
+
]
|
|
78
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.bundle = bundle;
|
|
8
|
+
exports.defaultOptions = void 0;
|
|
9
|
+
var _empty = require("@speclynx/apidom-reference/configuration/empty");
|
|
10
|
+
var _arazzo = _interopRequireDefault(require("@speclynx/apidom-reference/bundle/strategies/arazzo-1"));
|
|
11
|
+
var _openapi = _interopRequireDefault(require("@speclynx/apidom-reference/bundle/strategies/openapi-2"));
|
|
12
|
+
var _openapi2 = _interopRequireDefault(require("@speclynx/apidom-reference/bundle/strategies/openapi-3-0"));
|
|
13
|
+
var _openapi3 = _interopRequireDefault(require("@speclynx/apidom-reference/bundle/strategies/openapi-3-1"));
|
|
14
|
+
var _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
|
|
15
|
+
var _arazzo2 = require("../dereference/arazzo.cjs");
|
|
16
|
+
var _BundleError = _interopRequireDefault(require("../errors/BundleError.cjs"));
|
|
17
|
+
/**
|
|
18
|
+
* Options for bundling Arazzo Documents.
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Default reference options for bundling Arazzo Documents.
|
|
24
|
+
*
|
|
25
|
+
* Bundling reads only the bundle strategies plus the resolvers and parsers that fetch
|
|
26
|
+
* external documents, so no resolve or dereference strategies are configured.
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
const defaultOptions = exports.defaultOptions = {
|
|
30
|
+
resolve: {
|
|
31
|
+
resolvers: [..._arazzo2.defaultOptions.resolve.resolvers]
|
|
32
|
+
},
|
|
33
|
+
parse: {
|
|
34
|
+
parsers: [..._arazzo2.defaultOptions.parse.parsers],
|
|
35
|
+
parserOpts: {
|
|
36
|
+
..._arazzo2.defaultOptions.parse.parserOpts
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
bundle: {
|
|
40
|
+
strategies: [new _arazzo.default(), new _openapi.default(), new _openapi2.default(), new _openapi3.default()]
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Bundles an Arazzo Document from a file system path or HTTP(S) URL.
|
|
46
|
+
*
|
|
47
|
+
* This function embeds every external JSON Schema resource reached through
|
|
48
|
+
* JSON References ($ref) into the Components Object of the Arazzo Document,
|
|
49
|
+
* producing a single compound document.
|
|
50
|
+
*
|
|
51
|
+
* @param uri - A file system path or HTTP(S) URL to the Arazzo Document
|
|
52
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
53
|
+
* @returns A promise that resolves to the bundled Arazzo Document as ApiDOM element
|
|
54
|
+
* @throws BundleError - When bundling fails or document is not an Arazzo specification. The original error is available via the `cause` property.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* // Bundle from file
|
|
58
|
+
* const result = await bundleArazzo('/path/to/arazzo.json');
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* // Bundle from URL
|
|
62
|
+
* const result = await bundleArazzo('https://example.com/arazzo.yaml');
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* // Bundle with custom options
|
|
66
|
+
* const result = await bundleArazzo('/path/to/arazzo.json', customReferenceOptions);
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
async function bundle(uri, options = {}) {
|
|
70
|
+
const mergedOptions = (0, _empty.mergeOptions)(defaultOptions, options);
|
|
71
|
+
|
|
72
|
+
// a relative file system path resolves against the current working directory; the string
|
|
73
|
+
// doubles as the base URI for relative references, where a relative base resolves against
|
|
74
|
+
// the filesystem root instead of the document. A leading slash or backslash (UNC,
|
|
75
|
+
// drive-rooted) is already rooted and passes through untouched. `uri` itself is left as
|
|
76
|
+
// is so error messages below quote what the caller passed in.
|
|
77
|
+
const retrievalURI = !_empty.url.isHttpUrl(uri) && _empty.url.getProtocol(uri) !== 'file' && !/^[\\/]/.test(uri) ? _empty.url.resolve(_empty.url.fromFileSystemPath(_empty.url.cwd()), uri) : uri;
|
|
78
|
+
try {
|
|
79
|
+
const parseResult = await (0, _empty.bundle)(retrievalURI, mergedOptions);
|
|
80
|
+
|
|
81
|
+
// validate that the bundled document is an Arazzo specification
|
|
82
|
+
if (!(0, _apidomNsArazzo.isArazzoSpecification1Element)(parseResult.api)) {
|
|
83
|
+
throw new _empty.UnmatchedBundleStrategyError(`Could not find a bundle strategy that can bundle "${uri}" as an Arazzo specification`);
|
|
84
|
+
}
|
|
85
|
+
parseResult.meta.set('retrievalURI', retrievalURI);
|
|
86
|
+
return parseResult;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
throw new _BundleError.default(`Failed to bundle Arazzo Document at "${uri}"`, {
|
|
89
|
+
cause: error
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { url, bundle as bundleURI, mergeOptions, UnmatchedBundleStrategyError } from '@speclynx/apidom-reference/configuration/empty';
|
|
2
|
+
import Arazzo1BundleStrategy from '@speclynx/apidom-reference/bundle/strategies/arazzo-1';
|
|
3
|
+
import OpenAPI2BundleStrategy from '@speclynx/apidom-reference/bundle/strategies/openapi-2';
|
|
4
|
+
import OpenAPI30BundleStrategy from '@speclynx/apidom-reference/bundle/strategies/openapi-3-0';
|
|
5
|
+
import OpenAPI31BundleStrategy from '@speclynx/apidom-reference/bundle/strategies/openapi-3-1';
|
|
6
|
+
import { isArazzoSpecification1Element } from '@speclynx/apidom-ns-arazzo-1';
|
|
7
|
+
import { defaultOptions as dereferenceDefaultOptions } from "../dereference/arazzo.mjs";
|
|
8
|
+
import BundleError from "../errors/BundleError.mjs";
|
|
9
|
+
/**
|
|
10
|
+
* Options for bundling Arazzo Documents.
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Default reference options for bundling Arazzo Documents.
|
|
15
|
+
*
|
|
16
|
+
* Bundling reads only the bundle strategies plus the resolvers and parsers that fetch
|
|
17
|
+
* external documents, so no resolve or dereference strategies are configured.
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export const defaultOptions = {
|
|
21
|
+
resolve: {
|
|
22
|
+
resolvers: [...dereferenceDefaultOptions.resolve.resolvers]
|
|
23
|
+
},
|
|
24
|
+
parse: {
|
|
25
|
+
parsers: [...dereferenceDefaultOptions.parse.parsers],
|
|
26
|
+
parserOpts: {
|
|
27
|
+
...dereferenceDefaultOptions.parse.parserOpts
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
bundle: {
|
|
31
|
+
strategies: [new Arazzo1BundleStrategy(), new OpenAPI2BundleStrategy(), new OpenAPI30BundleStrategy(), new OpenAPI31BundleStrategy()]
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Bundles an Arazzo Document from a file system path or HTTP(S) URL.
|
|
37
|
+
*
|
|
38
|
+
* This function embeds every external JSON Schema resource reached through
|
|
39
|
+
* JSON References ($ref) into the Components Object of the Arazzo Document,
|
|
40
|
+
* producing a single compound document.
|
|
41
|
+
*
|
|
42
|
+
* @param uri - A file system path or HTTP(S) URL to the Arazzo Document
|
|
43
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
44
|
+
* @returns A promise that resolves to the bundled Arazzo Document as ApiDOM element
|
|
45
|
+
* @throws BundleError - When bundling fails or document is not an Arazzo specification. The original error is available via the `cause` property.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* // Bundle from file
|
|
49
|
+
* const result = await bundleArazzo('/path/to/arazzo.json');
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* // Bundle from URL
|
|
53
|
+
* const result = await bundleArazzo('https://example.com/arazzo.yaml');
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // Bundle with custom options
|
|
57
|
+
* const result = await bundleArazzo('/path/to/arazzo.json', customReferenceOptions);
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
export async function bundle(uri, options = {}) {
|
|
61
|
+
const mergedOptions = mergeOptions(defaultOptions, options);
|
|
62
|
+
|
|
63
|
+
// a relative file system path resolves against the current working directory; the string
|
|
64
|
+
// doubles as the base URI for relative references, where a relative base resolves against
|
|
65
|
+
// the filesystem root instead of the document. A leading slash or backslash (UNC,
|
|
66
|
+
// drive-rooted) is already rooted and passes through untouched. `uri` itself is left as
|
|
67
|
+
// is so error messages below quote what the caller passed in.
|
|
68
|
+
const retrievalURI = !url.isHttpUrl(uri) && url.getProtocol(uri) !== 'file' && !/^[\\/]/.test(uri) ? url.resolve(url.fromFileSystemPath(url.cwd()), uri) : uri;
|
|
69
|
+
try {
|
|
70
|
+
const parseResult = await bundleURI(retrievalURI, mergedOptions);
|
|
71
|
+
|
|
72
|
+
// validate that the bundled document is an Arazzo specification
|
|
73
|
+
if (!isArazzoSpecification1Element(parseResult.api)) {
|
|
74
|
+
throw new UnmatchedBundleStrategyError(`Could not find a bundle strategy that can bundle "${uri}" as an Arazzo specification`);
|
|
75
|
+
}
|
|
76
|
+
parseResult.meta.set('retrievalURI', retrievalURI);
|
|
77
|
+
return parseResult;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
throw new BundleError(`Failed to bundle Arazzo Document at "${uri}"`, {
|
|
80
|
+
cause: error
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.bundle = bundle;
|
|
8
|
+
exports.defaultOptions = void 0;
|
|
9
|
+
var _empty = require("@speclynx/apidom-reference/configuration/empty");
|
|
10
|
+
var _openapi = _interopRequireDefault(require("@speclynx/apidom-reference/bundle/strategies/openapi-2"));
|
|
11
|
+
var _openapi2 = _interopRequireDefault(require("@speclynx/apidom-reference/bundle/strategies/openapi-3-0"));
|
|
12
|
+
var _openapi3 = _interopRequireDefault(require("@speclynx/apidom-reference/bundle/strategies/openapi-3-1"));
|
|
13
|
+
var _apidomNsOpenapi = require("@speclynx/apidom-ns-openapi-2");
|
|
14
|
+
var _apidomNsOpenapi2 = require("@speclynx/apidom-ns-openapi-3-0");
|
|
15
|
+
var _apidomNsOpenapi3 = require("@speclynx/apidom-ns-openapi-3-1");
|
|
16
|
+
var _openapi4 = require("../dereference/openapi.cjs");
|
|
17
|
+
var _BundleError = _interopRequireDefault(require("../errors/BundleError.cjs"));
|
|
18
|
+
/**
|
|
19
|
+
* Options for bundling OpenAPI Documents.
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Default reference options for bundling OpenAPI Documents.
|
|
25
|
+
*
|
|
26
|
+
* Bundling reads only the bundle strategies plus the resolvers and parsers that fetch
|
|
27
|
+
* external documents, so no resolve or dereference strategies are configured.
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
const defaultOptions = exports.defaultOptions = {
|
|
31
|
+
resolve: {
|
|
32
|
+
resolvers: [..._openapi4.defaultOptions.resolve.resolvers]
|
|
33
|
+
},
|
|
34
|
+
parse: {
|
|
35
|
+
parsers: [..._openapi4.defaultOptions.parse.parsers],
|
|
36
|
+
parserOpts: {
|
|
37
|
+
..._openapi4.defaultOptions.parse.parserOpts
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
bundle: {
|
|
41
|
+
strategies: [new _openapi.default(), new _openapi2.default(), new _openapi3.default()]
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Bundles an OpenAPI Document from a file system path or HTTP(S) URL.
|
|
47
|
+
*
|
|
48
|
+
* This function hoists every external document reached through JSON References ($ref)
|
|
49
|
+
* into the components of the OpenAPI Document, producing a single compound document.
|
|
50
|
+
*
|
|
51
|
+
* Supports OpenAPI 2.0 (Swagger), OpenAPI 3.0.x, and OpenAPI 3.1.x.
|
|
52
|
+
*
|
|
53
|
+
* @param uri - A file system path or HTTP(S) URL to the OpenAPI Document
|
|
54
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
55
|
+
* @returns A promise that resolves to the bundled OpenAPI Document as ApiDOM element
|
|
56
|
+
* @throws BundleError - When bundling fails or document is not an OpenAPI specification. The original error is available via the `cause` property.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // Bundle from file
|
|
60
|
+
* const result = await bundleOpenAPI('/path/to/openapi.json');
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* // Bundle from URL
|
|
64
|
+
* const result = await bundleOpenAPI('https://example.com/openapi.yaml');
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* // Bundle with custom options
|
|
68
|
+
* const result = await bundleOpenAPI('/path/to/openapi.json', customReferenceOptions);
|
|
69
|
+
* @public
|
|
70
|
+
*/
|
|
71
|
+
async function bundle(uri, options = {}) {
|
|
72
|
+
const mergedOptions = (0, _empty.mergeOptions)(defaultOptions, options);
|
|
73
|
+
|
|
74
|
+
// a relative file system path resolves against the current working directory; the string
|
|
75
|
+
// doubles as the base URI for relative references, where a relative base resolves against
|
|
76
|
+
// the filesystem root instead of the document. A leading slash or backslash (UNC,
|
|
77
|
+
// drive-rooted) is already rooted and passes through untouched. `uri` itself is left as
|
|
78
|
+
// is so error messages below quote what the caller passed in.
|
|
79
|
+
const retrievalURI = !_empty.url.isHttpUrl(uri) && _empty.url.getProtocol(uri) !== 'file' && !/^[\\/]/.test(uri) ? _empty.url.resolve(_empty.url.fromFileSystemPath(_empty.url.cwd()), uri) : uri;
|
|
80
|
+
try {
|
|
81
|
+
const parseResult = await (0, _empty.bundle)(retrievalURI, mergedOptions);
|
|
82
|
+
|
|
83
|
+
// validate that the bundled document is an OpenAPI specification
|
|
84
|
+
if (!isOpenApiElement(parseResult.api)) {
|
|
85
|
+
throw new _empty.UnmatchedBundleStrategyError(`Could not find a bundle strategy that can bundle "${uri}" as an OpenAPI specification`);
|
|
86
|
+
}
|
|
87
|
+
parseResult.meta.set('retrievalURI', retrievalURI);
|
|
88
|
+
return parseResult;
|
|
89
|
+
} catch (error) {
|
|
90
|
+
throw new _BundleError.default(`Failed to bundle OpenAPI Document at "${uri}"`, {
|
|
91
|
+
cause: error
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Checks if the element is a valid OpenAPI specification element.
|
|
98
|
+
*/
|
|
99
|
+
function isOpenApiElement(element) {
|
|
100
|
+
return (0, _apidomNsOpenapi.isSwaggerElement)(element) || (0, _apidomNsOpenapi2.isOpenApi3_0Element)(element) || (0, _apidomNsOpenapi3.isOpenApi3_1Element)(element);
|
|
101
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { url, bundle as bundleURI, mergeOptions, UnmatchedBundleStrategyError } from '@speclynx/apidom-reference/configuration/empty';
|
|
2
|
+
import OpenAPI2BundleStrategy from '@speclynx/apidom-reference/bundle/strategies/openapi-2';
|
|
3
|
+
import OpenAPI3_0BundleStrategy from '@speclynx/apidom-reference/bundle/strategies/openapi-3-0';
|
|
4
|
+
import OpenAPI3_1BundleStrategy from '@speclynx/apidom-reference/bundle/strategies/openapi-3-1';
|
|
5
|
+
import { isSwaggerElement } from '@speclynx/apidom-ns-openapi-2';
|
|
6
|
+
import { isOpenApi3_0Element } from '@speclynx/apidom-ns-openapi-3-0';
|
|
7
|
+
import { isOpenApi3_1Element } from '@speclynx/apidom-ns-openapi-3-1';
|
|
8
|
+
import { defaultOptions as dereferenceDefaultOptions } from "../dereference/openapi.mjs";
|
|
9
|
+
import BundleError from "../errors/BundleError.mjs";
|
|
10
|
+
/**
|
|
11
|
+
* Options for bundling OpenAPI Documents.
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Default reference options for bundling OpenAPI Documents.
|
|
16
|
+
*
|
|
17
|
+
* Bundling reads only the bundle strategies plus the resolvers and parsers that fetch
|
|
18
|
+
* external documents, so no resolve or dereference strategies are configured.
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
export const defaultOptions = {
|
|
22
|
+
resolve: {
|
|
23
|
+
resolvers: [...dereferenceDefaultOptions.resolve.resolvers]
|
|
24
|
+
},
|
|
25
|
+
parse: {
|
|
26
|
+
parsers: [...dereferenceDefaultOptions.parse.parsers],
|
|
27
|
+
parserOpts: {
|
|
28
|
+
...dereferenceDefaultOptions.parse.parserOpts
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
bundle: {
|
|
32
|
+
strategies: [new OpenAPI2BundleStrategy(), new OpenAPI3_0BundleStrategy(), new OpenAPI3_1BundleStrategy()]
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Bundles an OpenAPI Document from a file system path or HTTP(S) URL.
|
|
38
|
+
*
|
|
39
|
+
* This function hoists every external document reached through JSON References ($ref)
|
|
40
|
+
* into the components of the OpenAPI Document, producing a single compound document.
|
|
41
|
+
*
|
|
42
|
+
* Supports OpenAPI 2.0 (Swagger), OpenAPI 3.0.x, and OpenAPI 3.1.x.
|
|
43
|
+
*
|
|
44
|
+
* @param uri - A file system path or HTTP(S) URL to the OpenAPI Document
|
|
45
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
46
|
+
* @returns A promise that resolves to the bundled OpenAPI Document as ApiDOM element
|
|
47
|
+
* @throws BundleError - When bundling fails or document is not an OpenAPI specification. The original error is available via the `cause` property.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // Bundle from file
|
|
51
|
+
* const result = await bundleOpenAPI('/path/to/openapi.json');
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* // Bundle from URL
|
|
55
|
+
* const result = await bundleOpenAPI('https://example.com/openapi.yaml');
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // Bundle with custom options
|
|
59
|
+
* const result = await bundleOpenAPI('/path/to/openapi.json', customReferenceOptions);
|
|
60
|
+
* @public
|
|
61
|
+
*/
|
|
62
|
+
export async function bundle(uri, options = {}) {
|
|
63
|
+
const mergedOptions = mergeOptions(defaultOptions, options);
|
|
64
|
+
|
|
65
|
+
// a relative file system path resolves against the current working directory; the string
|
|
66
|
+
// doubles as the base URI for relative references, where a relative base resolves against
|
|
67
|
+
// the filesystem root instead of the document. A leading slash or backslash (UNC,
|
|
68
|
+
// drive-rooted) is already rooted and passes through untouched. `uri` itself is left as
|
|
69
|
+
// is so error messages below quote what the caller passed in.
|
|
70
|
+
const retrievalURI = !url.isHttpUrl(uri) && url.getProtocol(uri) !== 'file' && !/^[\\/]/.test(uri) ? url.resolve(url.fromFileSystemPath(url.cwd()), uri) : uri;
|
|
71
|
+
try {
|
|
72
|
+
const parseResult = await bundleURI(retrievalURI, mergedOptions);
|
|
73
|
+
|
|
74
|
+
// validate that the bundled document is an OpenAPI specification
|
|
75
|
+
if (!isOpenApiElement(parseResult.api)) {
|
|
76
|
+
throw new UnmatchedBundleStrategyError(`Could not find a bundle strategy that can bundle "${uri}" as an OpenAPI specification`);
|
|
77
|
+
}
|
|
78
|
+
parseResult.meta.set('retrievalURI', retrievalURI);
|
|
79
|
+
return parseResult;
|
|
80
|
+
} catch (error) {
|
|
81
|
+
throw new BundleError(`Failed to bundle OpenAPI Document at "${uri}"`, {
|
|
82
|
+
cause: error
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Checks if the element is a valid OpenAPI specification element.
|
|
89
|
+
*/
|
|
90
|
+
function isOpenApiElement(element) {
|
|
91
|
+
return isSwaggerElement(element) || isOpenApi3_0Element(element) || isOpenApi3_1Element(element);
|
|
92
|
+
}
|