@speclynx/apidom-reference 4.0.2 → 4.0.3
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/CHANGELOG.md +6 -0
- package/package.json +26 -27
- package/src/File.cjs +50 -0
- package/src/File.mjs +44 -0
- package/src/File.ts +63 -0
- package/src/Reference.cjs +31 -0
- package/src/Reference.mjs +27 -0
- package/src/Reference.ts +38 -0
- package/src/ReferenceSet.cjs +60 -0
- package/src/ReferenceSet.mjs +57 -0
- package/src/ReferenceSet.ts +73 -0
- package/src/bundle/index.cjs +61 -0
- package/src/bundle/index.mjs +55 -0
- package/src/bundle/index.ts +57 -0
- package/src/bundle/strategies/BundleStrategy.cjs +20 -0
- package/src/bundle/strategies/BundleStrategy.mjs +16 -0
- package/src/bundle/strategies/BundleStrategy.ts +27 -0
- package/src/bundle/strategies/openapi-3-1/index.cjs +35 -0
- package/src/bundle/strategies/openapi-3-1/index.mjs +29 -0
- package/src/bundle/strategies/openapi-3-1/index.ts +57 -0
- package/src/configuration/empty.cjs +9 -0
- package/src/configuration/empty.mjs +1 -0
- package/src/configuration/empty.ts +1 -0
- package/src/configuration/saturated.cjs +88 -0
- package/src/configuration/saturated.mjs +80 -0
- package/src/configuration/saturated.ts +72 -0
- package/src/dereference/index.cjs +90 -0
- package/src/dereference/index.mjs +83 -0
- package/src/dereference/index.ts +96 -0
- package/src/dereference/strategies/DereferenceStrategy.cjs +20 -0
- package/src/dereference/strategies/DereferenceStrategy.mjs +16 -0
- package/src/dereference/strategies/DereferenceStrategy.ts +27 -0
- package/src/dereference/strategies/apidom/index.cjs +89 -0
- package/src/dereference/strategies/apidom/index.mjs +83 -0
- package/src/dereference/strategies/apidom/index.ts +128 -0
- package/src/dereference/strategies/apidom/selectors/element-id.cjs +47 -0
- package/src/dereference/strategies/apidom/selectors/element-id.mjs +41 -0
- package/src/dereference/strategies/apidom/selectors/element-id.ts +48 -0
- package/src/dereference/strategies/apidom/visitor.cjs +266 -0
- package/src/dereference/strategies/apidom/visitor.mjs +259 -0
- package/src/dereference/strategies/apidom/visitor.ts +316 -0
- package/src/dereference/strategies/arazzo-1/index.cjs +109 -0
- package/src/dereference/strategies/arazzo-1/index.mjs +100 -0
- package/src/dereference/strategies/arazzo-1/index.ts +158 -0
- package/src/dereference/strategies/arazzo-1/selectors/$anchor.cjs +12 -0
- package/src/dereference/strategies/arazzo-1/selectors/$anchor.mjs +1 -0
- package/src/dereference/strategies/arazzo-1/selectors/$anchor.ts +9 -0
- package/src/dereference/strategies/arazzo-1/selectors/uri.cjs +8 -0
- package/src/dereference/strategies/arazzo-1/selectors/uri.mjs +1 -0
- package/src/dereference/strategies/arazzo-1/selectors/uri.ts +5 -0
- package/src/dereference/strategies/arazzo-1/source-descriptions.cjs +248 -0
- package/src/dereference/strategies/arazzo-1/source-descriptions.mjs +243 -0
- package/src/dereference/strategies/arazzo-1/source-descriptions.ts +317 -0
- package/src/dereference/strategies/arazzo-1/util.cjs +37 -0
- package/src/dereference/strategies/arazzo-1/util.mjs +29 -0
- package/src/dereference/strategies/arazzo-1/util.ts +33 -0
- package/src/dereference/strategies/arazzo-1/visitor.cjs +507 -0
- package/src/dereference/strategies/arazzo-1/visitor.mjs +500 -0
- package/src/dereference/strategies/arazzo-1/visitor.ts +574 -0
- package/src/dereference/strategies/asyncapi-2/index.cjs +94 -0
- package/src/dereference/strategies/asyncapi-2/index.mjs +88 -0
- package/src/dereference/strategies/asyncapi-2/index.ts +133 -0
- package/src/dereference/strategies/asyncapi-2/visitor.cjs +501 -0
- package/src/dereference/strategies/asyncapi-2/visitor.mjs +494 -0
- package/src/dereference/strategies/asyncapi-2/visitor.ts +589 -0
- package/src/dereference/strategies/openapi-2/index.cjs +96 -0
- package/src/dereference/strategies/openapi-2/index.mjs +90 -0
- package/src/dereference/strategies/openapi-2/index.ts +136 -0
- package/src/dereference/strategies/openapi-2/visitor.cjs +629 -0
- package/src/dereference/strategies/openapi-2/visitor.mjs +622 -0
- package/src/dereference/strategies/openapi-2/visitor.ts +745 -0
- package/src/dereference/strategies/openapi-3-0/index.cjs +96 -0
- package/src/dereference/strategies/openapi-3-0/index.mjs +90 -0
- package/src/dereference/strategies/openapi-3-0/index.ts +134 -0
- package/src/dereference/strategies/openapi-3-0/visitor.cjs +622 -0
- package/src/dereference/strategies/openapi-3-0/visitor.mjs +615 -0
- package/src/dereference/strategies/openapi-3-0/visitor.ts +760 -0
- package/src/dereference/strategies/openapi-3-1/index.cjs +99 -0
- package/src/dereference/strategies/openapi-3-1/index.mjs +90 -0
- package/src/dereference/strategies/openapi-3-1/index.ts +141 -0
- package/src/dereference/strategies/openapi-3-1/selectors/$anchor.cjs +65 -0
- package/src/dereference/strategies/openapi-3-1/selectors/$anchor.mjs +54 -0
- package/src/dereference/strategies/openapi-3-1/selectors/$anchor.ts +64 -0
- package/src/dereference/strategies/openapi-3-1/selectors/uri.cjs +50 -0
- package/src/dereference/strategies/openapi-3-1/selectors/uri.mjs +42 -0
- package/src/dereference/strategies/openapi-3-1/selectors/uri.ts +54 -0
- package/src/dereference/strategies/openapi-3-1/util.cjs +68 -0
- package/src/dereference/strategies/openapi-3-1/util.mjs +59 -0
- package/src/dereference/strategies/openapi-3-1/util.ts +83 -0
- package/src/dereference/strategies/openapi-3-1/visitor.cjs +874 -0
- package/src/dereference/strategies/openapi-3-1/visitor.mjs +867 -0
- package/src/dereference/strategies/openapi-3-1/visitor.ts +1053 -0
- package/src/dereference/util.cjs +31 -0
- package/src/dereference/util.mjs +27 -0
- package/src/dereference/util.ts +29 -0
- package/src/errors/BundleError.cjs +10 -0
- package/src/errors/BundleError.mjs +7 -0
- package/src/errors/BundleError.ts +8 -0
- package/src/errors/DereferenceError.cjs +10 -0
- package/src/errors/DereferenceError.mjs +7 -0
- package/src/errors/DereferenceError.ts +8 -0
- package/src/errors/EvaluationElementIdError.cjs +10 -0
- package/src/errors/EvaluationElementIdError.mjs +7 -0
- package/src/errors/EvaluationElementIdError.ts +8 -0
- package/src/errors/EvaluationJsonSchema$anchorError.cjs +11 -0
- package/src/errors/EvaluationJsonSchema$anchorError.mjs +6 -0
- package/src/errors/EvaluationJsonSchema$anchorError.ts +8 -0
- package/src/errors/EvaluationJsonSchemaUriError.cjs +11 -0
- package/src/errors/EvaluationJsonSchemaUriError.mjs +6 -0
- package/src/errors/EvaluationJsonSchemaUriError.ts +8 -0
- package/src/errors/InvalidJsonSchema$anchorError.cjs +15 -0
- package/src/errors/InvalidJsonSchema$anchorError.mjs +10 -0
- package/src/errors/InvalidJsonSchema$anchorError.ts +12 -0
- package/src/errors/JsonSchema$anchorError.cjs +10 -0
- package/src/errors/JsonSchema$anchorError.mjs +7 -0
- package/src/errors/JsonSchema$anchorError.ts +8 -0
- package/src/errors/JsonSchemaUriError.cjs +10 -0
- package/src/errors/JsonSchemaUriError.mjs +7 -0
- package/src/errors/JsonSchemaUriError.ts +8 -0
- package/src/errors/MaximumBundleDepthError.cjs +11 -0
- package/src/errors/MaximumBundleDepthError.mjs +6 -0
- package/src/errors/MaximumBundleDepthError.ts +8 -0
- package/src/errors/MaximumDereferenceDepthError.cjs +11 -0
- package/src/errors/MaximumDereferenceDepthError.mjs +6 -0
- package/src/errors/MaximumDereferenceDepthError.ts +8 -0
- package/src/errors/MaximumResolveDepthError.cjs +11 -0
- package/src/errors/MaximumResolveDepthError.mjs +6 -0
- package/src/errors/MaximumResolveDepthError.ts +8 -0
- package/src/errors/ParseError.cjs +10 -0
- package/src/errors/ParseError.mjs +7 -0
- package/src/errors/ParseError.ts +8 -0
- package/src/errors/ParserError.cjs +11 -0
- package/src/errors/ParserError.mjs +6 -0
- package/src/errors/ParserError.ts +8 -0
- package/src/errors/PluginError.cjs +18 -0
- package/src/errors/PluginError.mjs +15 -0
- package/src/errors/PluginError.ts +15 -0
- package/src/errors/ResolveError.cjs +10 -0
- package/src/errors/ResolveError.mjs +7 -0
- package/src/errors/ResolveError.ts +8 -0
- package/src/errors/ResolverError.cjs +11 -0
- package/src/errors/ResolverError.mjs +6 -0
- package/src/errors/ResolverError.ts +8 -0
- package/src/errors/UnmatchedBundleStrategyError.cjs +11 -0
- package/src/errors/UnmatchedBundleStrategyError.mjs +6 -0
- package/src/errors/UnmatchedBundleStrategyError.ts +8 -0
- package/src/errors/UnmatchedDereferenceStrategyError.cjs +11 -0
- package/src/errors/UnmatchedDereferenceStrategyError.mjs +6 -0
- package/src/errors/UnmatchedDereferenceStrategyError.ts +8 -0
- package/src/errors/UnmatchedParserError.cjs +11 -0
- package/src/errors/UnmatchedParserError.mjs +6 -0
- package/src/errors/UnmatchedParserError.ts +8 -0
- package/src/errors/UnmatchedResolveStrategyError.cjs +11 -0
- package/src/errors/UnmatchedResolveStrategyError.mjs +6 -0
- package/src/errors/UnmatchedResolveStrategyError.ts +8 -0
- package/src/errors/UnmatchedResolverError.cjs +11 -0
- package/src/errors/UnmatchedResolverError.mjs +6 -0
- package/src/errors/UnmatchedResolverError.ts +8 -0
- package/src/errors/UnresolvableReferenceError.cjs +11 -0
- package/src/errors/UnresolvableReferenceError.mjs +6 -0
- package/src/errors/UnresolvableReferenceError.ts +8 -0
- package/src/index.cjs +146 -0
- package/src/index.mjs +103 -0
- package/src/index.ts +135 -0
- package/src/options/index.cjs +194 -0
- package/src/options/index.mjs +191 -0
- package/src/options/index.ts +239 -0
- package/src/options/util.cjs +24 -0
- package/src/options/util.mjs +19 -0
- package/src/options/util.ts +22 -0
- package/src/parse/index.cjs +69 -0
- package/src/parse/index.mjs +63 -0
- package/src/parse/index.ts +67 -0
- package/src/parse/parsers/Parser.cjs +62 -0
- package/src/parse/parsers/Parser.mjs +58 -0
- package/src/parse/parsers/Parser.ts +80 -0
- package/src/parse/parsers/apidom-json/index.cjs +70 -0
- package/src/parse/parsers/apidom-json/index.mjs +64 -0
- package/src/parse/parsers/apidom-json/index.ts +78 -0
- package/src/parse/parsers/arazzo-json-1/index.cjs +62 -0
- package/src/parse/parsers/arazzo-json-1/index.mjs +56 -0
- package/src/parse/parsers/arazzo-json-1/index.ts +76 -0
- package/src/parse/parsers/arazzo-json-1/source-descriptions.cjs +221 -0
- package/src/parse/parsers/arazzo-json-1/source-descriptions.mjs +214 -0
- package/src/parse/parsers/arazzo-json-1/source-descriptions.ts +280 -0
- package/src/parse/parsers/arazzo-yaml-1/index.cjs +62 -0
- package/src/parse/parsers/arazzo-yaml-1/index.mjs +56 -0
- package/src/parse/parsers/arazzo-yaml-1/index.ts +77 -0
- package/src/parse/parsers/arazzo-yaml-1/source-descriptions.cjs +12 -0
- package/src/parse/parsers/arazzo-yaml-1/source-descriptions.mjs +7 -0
- package/src/parse/parsers/arazzo-yaml-1/source-descriptions.ts +16 -0
- package/src/parse/parsers/asyncapi-json-2/index.cjs +54 -0
- package/src/parse/parsers/asyncapi-json-2/index.mjs +48 -0
- package/src/parse/parsers/asyncapi-json-2/index.ts +58 -0
- package/src/parse/parsers/asyncapi-yaml-2/index.cjs +54 -0
- package/src/parse/parsers/asyncapi-yaml-2/index.mjs +48 -0
- package/src/parse/parsers/asyncapi-yaml-2/index.ts +58 -0
- package/src/parse/parsers/binary/index-browser.cjs +56 -0
- package/src/parse/parsers/binary/index-browser.mjs +50 -0
- package/src/parse/parsers/binary/index-browser.ts +60 -0
- package/src/parse/parsers/binary/index-node.cjs +51 -0
- package/src/parse/parsers/binary/index-node.mjs +45 -0
- package/src/parse/parsers/binary/index-node.ts +57 -0
- package/src/parse/parsers/json/index.cjs +53 -0
- package/src/parse/parsers/json/index.mjs +47 -0
- package/src/parse/parsers/json/index.ts +52 -0
- package/src/parse/parsers/openapi-json-2/index.cjs +54 -0
- package/src/parse/parsers/openapi-json-2/index.mjs +48 -0
- package/src/parse/parsers/openapi-json-2/index.ts +58 -0
- package/src/parse/parsers/openapi-json-3-0/index.cjs +54 -0
- package/src/parse/parsers/openapi-json-3-0/index.mjs +48 -0
- package/src/parse/parsers/openapi-json-3-0/index.ts +59 -0
- package/src/parse/parsers/openapi-json-3-1/index.cjs +54 -0
- package/src/parse/parsers/openapi-json-3-1/index.mjs +48 -0
- package/src/parse/parsers/openapi-json-3-1/index.ts +59 -0
- package/src/parse/parsers/openapi-yaml-2/index.cjs +54 -0
- package/src/parse/parsers/openapi-yaml-2/index.mjs +48 -0
- package/src/parse/parsers/openapi-yaml-2/index.ts +58 -0
- package/src/parse/parsers/openapi-yaml-3-0/index.cjs +54 -0
- package/src/parse/parsers/openapi-yaml-3-0/index.mjs +48 -0
- package/src/parse/parsers/openapi-yaml-3-0/index.ts +59 -0
- package/src/parse/parsers/openapi-yaml-3-1/index.cjs +54 -0
- package/src/parse/parsers/openapi-yaml-3-1/index.mjs +48 -0
- package/src/parse/parsers/openapi-yaml-3-1/index.ts +59 -0
- package/src/parse/parsers/yaml-1-2/index.cjs +56 -0
- package/src/parse/parsers/yaml-1-2/index.mjs +50 -0
- package/src/parse/parsers/yaml-1-2/index.ts +60 -0
- package/src/resolve/index.cjs +67 -0
- package/src/resolve/index.mjs +60 -0
- package/src/resolve/index.ts +75 -0
- package/src/resolve/resolvers/HTTPResolver.cjs +45 -0
- package/src/resolve/resolvers/HTTPResolver.mjs +37 -0
- package/src/resolve/resolvers/HTTPResolver.ts +58 -0
- package/src/resolve/resolvers/Resolver.cjs +20 -0
- package/src/resolve/resolvers/Resolver.mjs +16 -0
- package/src/resolve/resolvers/Resolver.ts +25 -0
- package/src/resolve/resolvers/file/index-browser.cjs +24 -0
- package/src/resolve/resolvers/file/index-browser.mjs +19 -0
- package/src/resolve/resolvers/file/index-browser.ts +24 -0
- package/src/resolve/resolvers/file/index-node.cjs +49 -0
- package/src/resolve/resolvers/file/index-node.mjs +42 -0
- package/src/resolve/resolvers/file/index-node.ts +55 -0
- package/src/resolve/resolvers/http-axios/cache/MemoryCache.cjs +41 -0
- package/src/resolve/resolvers/http-axios/cache/MemoryCache.mjs +37 -0
- package/src/resolve/resolvers/http-axios/cache/MemoryCache.ts +46 -0
- package/src/resolve/resolvers/http-axios/index.cjs +113 -0
- package/src/resolve/resolvers/http-axios/index.mjs +105 -0
- package/src/resolve/resolvers/http-axios/index.ts +130 -0
- package/src/resolve/strategies/ResolveStrategy.cjs +20 -0
- package/src/resolve/strategies/ResolveStrategy.mjs +16 -0
- package/src/resolve/strategies/ResolveStrategy.ts +26 -0
- package/src/resolve/strategies/apidom/index.cjs +49 -0
- package/src/resolve/strategies/apidom/index.mjs +43 -0
- package/src/resolve/strategies/apidom/index.ts +78 -0
- package/src/resolve/strategies/asyncapi-2/index.cjs +49 -0
- package/src/resolve/strategies/asyncapi-2/index.mjs +43 -0
- package/src/resolve/strategies/asyncapi-2/index.ts +78 -0
- package/src/resolve/strategies/openapi-2/index.cjs +49 -0
- package/src/resolve/strategies/openapi-2/index.mjs +43 -0
- package/src/resolve/strategies/openapi-2/index.ts +78 -0
- package/src/resolve/strategies/openapi-3-0/index.cjs +49 -0
- package/src/resolve/strategies/openapi-3-0/index.mjs +43 -0
- package/src/resolve/strategies/openapi-3-0/index.ts +78 -0
- package/src/resolve/strategies/openapi-3-1/index.cjs +49 -0
- package/src/resolve/strategies/openapi-3-1/index.mjs +43 -0
- package/src/resolve/strategies/openapi-3-1/index.ts +78 -0
- package/src/resolve/util.cjs +37 -0
- package/src/resolve/util.mjs +30 -0
- package/src/resolve/util.ts +39 -0
- package/src/util/plugins.cjs +39 -0
- package/src/util/plugins.mjs +34 -0
- package/src/util/plugins.ts +37 -0
- package/src/util/url.cjs +288 -0
- package/src/util/url.mjs +274 -0
- package/src/util/url.ts +285 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { isEmpty, propEq } from 'ramda';
|
|
2
|
+
import { isParseResultElement, ParseResultElement, cloneShallow } from '@speclynx/apidom-datamodel';
|
|
3
|
+
import File from "../File.mjs";
|
|
4
|
+
import * as plugins from "../util/plugins.mjs";
|
|
5
|
+
import UnmatchedDereferenceStrategyError from "../errors/UnmatchedDereferenceStrategyError.mjs";
|
|
6
|
+
import DereferenceError from "../errors/DereferenceError.mjs";
|
|
7
|
+
import UnresolvableReferenceError from "../errors/UnresolvableReferenceError.mjs";
|
|
8
|
+
import parse from "../parse/index.mjs";
|
|
9
|
+
import { merge as mergeOptions } from "../options/util.mjs";
|
|
10
|
+
import * as url from "../util/url.mjs";
|
|
11
|
+
/**
|
|
12
|
+
* Dereferences ApiDOM with all its external references.
|
|
13
|
+
*/
|
|
14
|
+
export const dereferenceApiDOM = async (element, options) => {
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
let parseResult = element;
|
|
17
|
+
let surrogateWrapping = false;
|
|
18
|
+
|
|
19
|
+
// wrap element into parse result
|
|
20
|
+
if (!isParseResultElement(element)) {
|
|
21
|
+
const elementClone = cloneShallow(element);
|
|
22
|
+
elementClone.classes.push('result');
|
|
23
|
+
parseResult = new ParseResultElement([elementClone]);
|
|
24
|
+
surrogateWrapping = true;
|
|
25
|
+
}
|
|
26
|
+
const file = new File({
|
|
27
|
+
uri: options.resolve.baseURI,
|
|
28
|
+
parseResult,
|
|
29
|
+
mediaType: options.parse.mediaType
|
|
30
|
+
});
|
|
31
|
+
const dereferenceStrategies = await plugins.filter('canDereference', [file, options], options.dereference.strategies);
|
|
32
|
+
|
|
33
|
+
// we couldn't find any dereference strategy for this File
|
|
34
|
+
if (isEmpty(dereferenceStrategies)) {
|
|
35
|
+
throw new UnmatchedDereferenceStrategyError(`Could not find a dereference strategy that can dereference the file "${file.uri}"`);
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const {
|
|
39
|
+
result
|
|
40
|
+
} = await plugins.run('dereference', [file, options], dereferenceStrategies);
|
|
41
|
+
// unwrap the element from ParseResult assuming first element is the actual result
|
|
42
|
+
return surrogateWrapping ? result.get(0) : result;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (error instanceof UnresolvableReferenceError) {
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
throw new DereferenceError(`Error while dereferencing file "${file.uri}"`, {
|
|
48
|
+
cause: error
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Dereferences a file with all its external references.
|
|
55
|
+
*/
|
|
56
|
+
const dereference = async (uri, options) => {
|
|
57
|
+
const {
|
|
58
|
+
refSet
|
|
59
|
+
} = options.dereference;
|
|
60
|
+
const sanitizedURI = url.sanitize(uri);
|
|
61
|
+
let parseResult;
|
|
62
|
+
|
|
63
|
+
// if refSet was provided, use it to avoid unnecessary parsing
|
|
64
|
+
if (refSet !== null && refSet.has(sanitizedURI)) {
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
({
|
|
67
|
+
value: parseResult
|
|
68
|
+
} = refSet.find(propEq(sanitizedURI, 'uri')));
|
|
69
|
+
} else {
|
|
70
|
+
parseResult = await parse(uri, options);
|
|
71
|
+
}
|
|
72
|
+
const mergedOptions = mergeOptions(options, {
|
|
73
|
+
resolve: {
|
|
74
|
+
baseURI: sanitizedURI
|
|
75
|
+
},
|
|
76
|
+
dereference: {
|
|
77
|
+
// if refSet was not provided, then we can work in mutable mode
|
|
78
|
+
immutable: options.dereference.immutable && refSet !== null
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return dereferenceApiDOM(parseResult, mergedOptions);
|
|
82
|
+
};
|
|
83
|
+
export default dereference;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { isEmpty, propEq } from 'ramda';
|
|
2
|
+
import {
|
|
3
|
+
Element,
|
|
4
|
+
isParseResultElement,
|
|
5
|
+
ParseResultElement,
|
|
6
|
+
cloneShallow,
|
|
7
|
+
} from '@speclynx/apidom-datamodel';
|
|
8
|
+
|
|
9
|
+
import File from '../File.ts';
|
|
10
|
+
import * as plugins from '../util/plugins.ts';
|
|
11
|
+
import UnmatchedDereferenceStrategyError from '../errors/UnmatchedDereferenceStrategyError.ts';
|
|
12
|
+
import DereferenceError from '../errors/DereferenceError.ts';
|
|
13
|
+
import UnresolvableReferenceError from '../errors/UnresolvableReferenceError.ts';
|
|
14
|
+
import parse from '../parse/index.ts';
|
|
15
|
+
import { merge as mergeOptions } from '../options/util.ts';
|
|
16
|
+
import * as url from '../util/url.ts';
|
|
17
|
+
import type { ReferenceOptions } from '../options/index.ts';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Dereferences ApiDOM with all its external references.
|
|
21
|
+
*/
|
|
22
|
+
export const dereferenceApiDOM = async <T extends Element>(
|
|
23
|
+
element: T,
|
|
24
|
+
options: ReferenceOptions,
|
|
25
|
+
): Promise<T> => {
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
let parseResult: ParseResultElement = element;
|
|
28
|
+
let surrogateWrapping = false;
|
|
29
|
+
|
|
30
|
+
// wrap element into parse result
|
|
31
|
+
if (!isParseResultElement(element)) {
|
|
32
|
+
const elementClone = cloneShallow(element);
|
|
33
|
+
elementClone.classes.push('result');
|
|
34
|
+
parseResult = new ParseResultElement([elementClone]);
|
|
35
|
+
surrogateWrapping = true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const file = new File({
|
|
39
|
+
uri: options.resolve.baseURI,
|
|
40
|
+
parseResult,
|
|
41
|
+
mediaType: options.parse.mediaType,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const dereferenceStrategies = await plugins.filter(
|
|
45
|
+
'canDereference',
|
|
46
|
+
[file, options],
|
|
47
|
+
options.dereference.strategies,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// we couldn't find any dereference strategy for this File
|
|
51
|
+
if (isEmpty(dereferenceStrategies)) {
|
|
52
|
+
throw new UnmatchedDereferenceStrategyError(
|
|
53
|
+
`Could not find a dereference strategy that can dereference the file "${file.uri}"`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
const { result } = await plugins.run('dereference', [file, options], dereferenceStrategies);
|
|
59
|
+
// unwrap the element from ParseResult assuming first element is the actual result
|
|
60
|
+
return surrogateWrapping ? result.get(0) : result;
|
|
61
|
+
} catch (error: any) {
|
|
62
|
+
if (error instanceof UnresolvableReferenceError) {
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
throw new DereferenceError(`Error while dereferencing file "${file.uri}"`, { cause: error });
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Dereferences a file with all its external references.
|
|
71
|
+
*/
|
|
72
|
+
const dereference = async (uri: string, options: ReferenceOptions): Promise<ParseResultElement> => {
|
|
73
|
+
const { refSet } = options.dereference;
|
|
74
|
+
const sanitizedURI = url.sanitize(uri);
|
|
75
|
+
let parseResult;
|
|
76
|
+
|
|
77
|
+
// if refSet was provided, use it to avoid unnecessary parsing
|
|
78
|
+
if (refSet !== null && refSet.has(sanitizedURI)) {
|
|
79
|
+
// @ts-ignore
|
|
80
|
+
({ value: parseResult } = refSet.find(propEq(sanitizedURI, 'uri')));
|
|
81
|
+
} else {
|
|
82
|
+
parseResult = await parse(uri, options);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const mergedOptions = mergeOptions(options, {
|
|
86
|
+
resolve: { baseURI: sanitizedURI },
|
|
87
|
+
dereference: {
|
|
88
|
+
// if refSet was not provided, then we can work in mutable mode
|
|
89
|
+
immutable: options.dereference.immutable && refSet !== null,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return dereferenceApiDOM(parseResult, mergedOptions);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export default dereference;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
class DereferenceStrategy {
|
|
13
|
+
name;
|
|
14
|
+
constructor({
|
|
15
|
+
name
|
|
16
|
+
}) {
|
|
17
|
+
this.name = name;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
var _default = exports.default = DereferenceStrategy;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Element } from '@speclynx/apidom-datamodel';
|
|
2
|
+
|
|
3
|
+
import File from '../../File.ts';
|
|
4
|
+
import type { ReferenceOptions } from '../../options/index.ts';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export interface DereferenceStrategyOptions {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
abstract class DereferenceStrategy {
|
|
17
|
+
public readonly name: string;
|
|
18
|
+
|
|
19
|
+
constructor({ name }: DereferenceStrategyOptions) {
|
|
20
|
+
this.name = name;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
abstract canDereference(file: File, options: ReferenceOptions): boolean;
|
|
24
|
+
abstract dereference(file: File, options: ReferenceOptions): Promise<Element>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default DereferenceStrategy;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
|
|
4
|
+
exports.__esModule = true;
|
|
5
|
+
exports.default = void 0;
|
|
6
|
+
var _apidomDatamodel = require("@speclynx/apidom-datamodel");
|
|
7
|
+
var _apidomTraverse = require("@speclynx/apidom-traverse");
|
|
8
|
+
var _DereferenceStrategy = _interopRequireDefault(require("../DereferenceStrategy.cjs"));
|
|
9
|
+
var _Reference = _interopRequireDefault(require("../../../Reference.cjs"));
|
|
10
|
+
var _ReferenceSet = _interopRequireDefault(require("../../../ReferenceSet.cjs"));
|
|
11
|
+
var _visitor = _interopRequireDefault(require("./visitor.cjs"));
|
|
12
|
+
exports.ApiDOMDereferenceVisitor = _visitor.default;
|
|
13
|
+
/**
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
class ApiDOMDereferenceStrategy extends _DereferenceStrategy.default {
|
|
21
|
+
constructor(options) {
|
|
22
|
+
super({
|
|
23
|
+
...(options ?? {}),
|
|
24
|
+
name: 'apidom'
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
canDereference(file) {
|
|
28
|
+
return file.mediaType.startsWith('application/vnd.apidom') && (0, _apidomDatamodel.isElement)(file.parseResult?.result);
|
|
29
|
+
}
|
|
30
|
+
async dereference(file, options) {
|
|
31
|
+
const immutableRefSet = options.dereference.refSet ?? new _ReferenceSet.default();
|
|
32
|
+
const mutableRefSet = new _ReferenceSet.default();
|
|
33
|
+
let refSet = immutableRefSet;
|
|
34
|
+
let reference;
|
|
35
|
+
|
|
36
|
+
// determine the initial reference
|
|
37
|
+
if (!immutableRefSet.has(file.uri)) {
|
|
38
|
+
reference = new _Reference.default({
|
|
39
|
+
uri: file.uri,
|
|
40
|
+
value: file.parseResult
|
|
41
|
+
});
|
|
42
|
+
immutableRefSet.add(reference);
|
|
43
|
+
} else {
|
|
44
|
+
// pre-computed refSet was provided as configuration option
|
|
45
|
+
reference = immutableRefSet.find(ref => ref.uri === file.uri);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Clone refSet due the dereferencing process being mutable.
|
|
50
|
+
* We don't want to mutate the original refSet and the references.
|
|
51
|
+
*/
|
|
52
|
+
if (options.dereference.immutable) {
|
|
53
|
+
immutableRefSet.refs.map(ref => new _Reference.default({
|
|
54
|
+
...ref,
|
|
55
|
+
value: (0, _apidomDatamodel.cloneDeep)(ref.value)
|
|
56
|
+
})).forEach(ref => mutableRefSet.add(ref));
|
|
57
|
+
reference = mutableRefSet.find(ref => ref.uri === file.uri);
|
|
58
|
+
refSet = mutableRefSet;
|
|
59
|
+
}
|
|
60
|
+
const visitor = new _visitor.default({
|
|
61
|
+
reference: reference,
|
|
62
|
+
options
|
|
63
|
+
});
|
|
64
|
+
const dereferencedElement = await (0, _apidomTraverse.traverseAsync)(refSet.rootRef.value, visitor, {
|
|
65
|
+
mutable: true
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* If immutable option is set, replay refs from the refSet.
|
|
70
|
+
*/
|
|
71
|
+
if (options.dereference.immutable) {
|
|
72
|
+
mutableRefSet.refs.filter(ref => ref.uri.startsWith('immutable://')).map(ref => new _Reference.default({
|
|
73
|
+
...ref,
|
|
74
|
+
uri: ref.uri.replace(/^immutable:\/\//, '')
|
|
75
|
+
})).forEach(ref => immutableRefSet.add(ref));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Release all memory if this refSet was not provided as a configuration option.
|
|
80
|
+
* If provided as configuration option, then provider is responsible for cleanup.
|
|
81
|
+
*/
|
|
82
|
+
if (options.dereference.refSet === null) {
|
|
83
|
+
immutableRefSet.clean();
|
|
84
|
+
}
|
|
85
|
+
mutableRefSet.clean();
|
|
86
|
+
return dereferencedElement;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
var _default = exports.default = ApiDOMDereferenceStrategy;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { isElement, cloneDeep } from '@speclynx/apidom-datamodel';
|
|
2
|
+
import { traverseAsync } from '@speclynx/apidom-traverse';
|
|
3
|
+
import DereferenceStrategy from "../DereferenceStrategy.mjs";
|
|
4
|
+
import Reference from "../../../Reference.mjs";
|
|
5
|
+
import ReferenceSet from "../../../ReferenceSet.mjs";
|
|
6
|
+
import ApiDOMDereferenceVisitor from "./visitor.mjs";
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
class ApiDOMDereferenceStrategy extends DereferenceStrategy {
|
|
14
|
+
constructor(options) {
|
|
15
|
+
super({
|
|
16
|
+
...(options ?? {}),
|
|
17
|
+
name: 'apidom'
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
canDereference(file) {
|
|
21
|
+
return file.mediaType.startsWith('application/vnd.apidom') && isElement(file.parseResult?.result);
|
|
22
|
+
}
|
|
23
|
+
async dereference(file, options) {
|
|
24
|
+
const immutableRefSet = options.dereference.refSet ?? new ReferenceSet();
|
|
25
|
+
const mutableRefSet = new ReferenceSet();
|
|
26
|
+
let refSet = immutableRefSet;
|
|
27
|
+
let reference;
|
|
28
|
+
|
|
29
|
+
// determine the initial reference
|
|
30
|
+
if (!immutableRefSet.has(file.uri)) {
|
|
31
|
+
reference = new Reference({
|
|
32
|
+
uri: file.uri,
|
|
33
|
+
value: file.parseResult
|
|
34
|
+
});
|
|
35
|
+
immutableRefSet.add(reference);
|
|
36
|
+
} else {
|
|
37
|
+
// pre-computed refSet was provided as configuration option
|
|
38
|
+
reference = immutableRefSet.find(ref => ref.uri === file.uri);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Clone refSet due the dereferencing process being mutable.
|
|
43
|
+
* We don't want to mutate the original refSet and the references.
|
|
44
|
+
*/
|
|
45
|
+
if (options.dereference.immutable) {
|
|
46
|
+
immutableRefSet.refs.map(ref => new Reference({
|
|
47
|
+
...ref,
|
|
48
|
+
value: cloneDeep(ref.value)
|
|
49
|
+
})).forEach(ref => mutableRefSet.add(ref));
|
|
50
|
+
reference = mutableRefSet.find(ref => ref.uri === file.uri);
|
|
51
|
+
refSet = mutableRefSet;
|
|
52
|
+
}
|
|
53
|
+
const visitor = new ApiDOMDereferenceVisitor({
|
|
54
|
+
reference: reference,
|
|
55
|
+
options
|
|
56
|
+
});
|
|
57
|
+
const dereferencedElement = await traverseAsync(refSet.rootRef.value, visitor, {
|
|
58
|
+
mutable: true
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* If immutable option is set, replay refs from the refSet.
|
|
63
|
+
*/
|
|
64
|
+
if (options.dereference.immutable) {
|
|
65
|
+
mutableRefSet.refs.filter(ref => ref.uri.startsWith('immutable://')).map(ref => new Reference({
|
|
66
|
+
...ref,
|
|
67
|
+
uri: ref.uri.replace(/^immutable:\/\//, '')
|
|
68
|
+
})).forEach(ref => immutableRefSet.add(ref));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Release all memory if this refSet was not provided as a configuration option.
|
|
73
|
+
* If provided as configuration option, then provider is responsible for cleanup.
|
|
74
|
+
*/
|
|
75
|
+
if (options.dereference.refSet === null) {
|
|
76
|
+
immutableRefSet.clean();
|
|
77
|
+
}
|
|
78
|
+
mutableRefSet.clean();
|
|
79
|
+
return dereferencedElement;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export { ApiDOMDereferenceVisitor };
|
|
83
|
+
export default ApiDOMDereferenceStrategy;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Element, isElement, cloneDeep } from '@speclynx/apidom-datamodel';
|
|
2
|
+
import { traverseAsync } from '@speclynx/apidom-traverse';
|
|
3
|
+
|
|
4
|
+
import DereferenceStrategy, { DereferenceStrategyOptions } from '../DereferenceStrategy.ts';
|
|
5
|
+
import File from '../../../File.ts';
|
|
6
|
+
import Reference from '../../../Reference.ts';
|
|
7
|
+
import ReferenceSet from '../../../ReferenceSet.ts';
|
|
8
|
+
import ApiDOMDereferenceVisitor from './visitor.ts';
|
|
9
|
+
import type { ReferenceOptions } from '../../../options/index.ts';
|
|
10
|
+
|
|
11
|
+
export type {
|
|
12
|
+
default as DereferenceStrategy,
|
|
13
|
+
DereferenceStrategyOptions,
|
|
14
|
+
} from '../DereferenceStrategy.ts';
|
|
15
|
+
export type { default as File, FileOptions } from '../../../File.ts';
|
|
16
|
+
export type { default as Reference, ReferenceOptions } from '../../../Reference.ts';
|
|
17
|
+
export type { default as ReferenceSet, ReferenceSetOptions } from '../../../ReferenceSet.ts';
|
|
18
|
+
export type { ApiDOMDereferenceVisitorOptions } from './visitor.ts';
|
|
19
|
+
export type {
|
|
20
|
+
ReferenceOptions as ApiDOMReferenceOptions,
|
|
21
|
+
ReferenceBundleOptions as ApiDOMReferenceBundleOptions,
|
|
22
|
+
ReferenceDereferenceOptions as ApiDOMReferenceDereferenceOptions,
|
|
23
|
+
ReferenceParseOptions as ApiDOMReferenceParseOptions,
|
|
24
|
+
ReferenceResolveOptions as ApiDOMReferenceResolveOptions,
|
|
25
|
+
} from '../../../options/index.ts';
|
|
26
|
+
export type { default as Parser, ParserOptions } from '../../../parse/parsers/Parser.ts';
|
|
27
|
+
export type { default as Resolver, ResolverOptions } from '../../../resolve/resolvers/Resolver.ts';
|
|
28
|
+
export type {
|
|
29
|
+
default as ResolveStrategy,
|
|
30
|
+
ResolveStrategyOptions,
|
|
31
|
+
} from '../../../resolve/strategies/ResolveStrategy.ts';
|
|
32
|
+
export type {
|
|
33
|
+
default as BundleStrategy,
|
|
34
|
+
BundleStrategyOptions,
|
|
35
|
+
} from '../../../bundle/strategies/BundleStrategy.ts';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export interface ApiDOMDereferenceStrategyOptions extends Omit<
|
|
41
|
+
DereferenceStrategyOptions,
|
|
42
|
+
'name'
|
|
43
|
+
> {}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
48
|
+
class ApiDOMDereferenceStrategy extends DereferenceStrategy {
|
|
49
|
+
constructor(options?: ApiDOMDereferenceStrategyOptions) {
|
|
50
|
+
super({ ...(options ?? {}), name: 'apidom' });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
canDereference(file: File) {
|
|
54
|
+
return (
|
|
55
|
+
file.mediaType.startsWith('application/vnd.apidom') && isElement(file.parseResult?.result)
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async dereference(file: File, options: ReferenceOptions): Promise<Element> {
|
|
60
|
+
const immutableRefSet = options.dereference.refSet ?? new ReferenceSet();
|
|
61
|
+
const mutableRefSet = new ReferenceSet();
|
|
62
|
+
let refSet = immutableRefSet;
|
|
63
|
+
let reference;
|
|
64
|
+
|
|
65
|
+
// determine the initial reference
|
|
66
|
+
if (!immutableRefSet.has(file.uri)) {
|
|
67
|
+
reference = new Reference({ uri: file.uri, value: file.parseResult! });
|
|
68
|
+
immutableRefSet.add(reference);
|
|
69
|
+
} else {
|
|
70
|
+
// pre-computed refSet was provided as configuration option
|
|
71
|
+
reference = immutableRefSet.find((ref) => ref.uri === file.uri);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Clone refSet due the dereferencing process being mutable.
|
|
76
|
+
* We don't want to mutate the original refSet and the references.
|
|
77
|
+
*/
|
|
78
|
+
if (options.dereference.immutable) {
|
|
79
|
+
immutableRefSet.refs
|
|
80
|
+
.map(
|
|
81
|
+
(ref) =>
|
|
82
|
+
new Reference({
|
|
83
|
+
...ref,
|
|
84
|
+
value: cloneDeep(ref.value),
|
|
85
|
+
}),
|
|
86
|
+
)
|
|
87
|
+
.forEach((ref) => mutableRefSet.add(ref));
|
|
88
|
+
reference = mutableRefSet.find((ref) => ref.uri === file.uri);
|
|
89
|
+
refSet = mutableRefSet;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const visitor = new ApiDOMDereferenceVisitor({ reference: reference!, options });
|
|
93
|
+
const dereferencedElement = await traverseAsync(refSet.rootRef!.value, visitor, {
|
|
94
|
+
mutable: true,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* If immutable option is set, replay refs from the refSet.
|
|
99
|
+
*/
|
|
100
|
+
if (options.dereference.immutable) {
|
|
101
|
+
mutableRefSet.refs
|
|
102
|
+
.filter((ref) => ref.uri.startsWith('immutable://'))
|
|
103
|
+
.map(
|
|
104
|
+
(ref) =>
|
|
105
|
+
new Reference({
|
|
106
|
+
...ref,
|
|
107
|
+
uri: ref.uri.replace(/^immutable:\/\//, ''),
|
|
108
|
+
}),
|
|
109
|
+
)
|
|
110
|
+
.forEach((ref) => immutableRefSet.add(ref));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Release all memory if this refSet was not provided as a configuration option.
|
|
115
|
+
* If provided as configuration option, then provider is responsible for cleanup.
|
|
116
|
+
*/
|
|
117
|
+
if (options.dereference.refSet === null) {
|
|
118
|
+
immutableRefSet.clean();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
mutableRefSet.clean();
|
|
122
|
+
|
|
123
|
+
return dereferencedElement;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export { ApiDOMDereferenceVisitor };
|
|
128
|
+
export default ApiDOMDereferenceStrategy;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
|
|
4
|
+
exports.__esModule = true;
|
|
5
|
+
exports.evaluate = void 0;
|
|
6
|
+
var _ramdaAdjunct = require("ramda-adjunct");
|
|
7
|
+
var _apidomDatamodel = require("@speclynx/apidom-datamodel");
|
|
8
|
+
var _apidomCore = require("@speclynx/apidom-core");
|
|
9
|
+
var _apidomTraverse = require("@speclynx/apidom-traverse");
|
|
10
|
+
var _EvaluationElementIdError = _interopRequireDefault(require("../../../../errors/EvaluationElementIdError.cjs"));
|
|
11
|
+
exports.EvaluationElementIdError = _EvaluationElementIdError.default;
|
|
12
|
+
const getElementID = element => {
|
|
13
|
+
const id = element.meta.get('id');
|
|
14
|
+
// handle both raw string (new format) and StringElement (legacy Refract without __meta_raw__)
|
|
15
|
+
return (0, _apidomDatamodel.isElement)(id) ? (0, _apidomCore.toValue)(id) : id;
|
|
16
|
+
};
|
|
17
|
+
const hasElementID = path => {
|
|
18
|
+
if (!path.node.hasMetaProperty('id')) return false;
|
|
19
|
+
const id = getElementID(path.node);
|
|
20
|
+
return typeof id === 'string' && id !== '';
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Evaluates element ID against ApiDOM fragment.
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
const evaluate = (elementID, element) => {
|
|
28
|
+
const {
|
|
29
|
+
cache
|
|
30
|
+
} = evaluate;
|
|
31
|
+
// warm the cache
|
|
32
|
+
if (!cache.has(element)) {
|
|
33
|
+
const pathsWithID = (0, _apidomTraverse.filter)(element, hasElementID);
|
|
34
|
+
cache.set(element, pathsWithID.map(path => path.node));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// search for the matching element
|
|
38
|
+
const result = cache.get(element).find(e => {
|
|
39
|
+
return getElementID(e) === elementID;
|
|
40
|
+
});
|
|
41
|
+
if ((0, _ramdaAdjunct.isUndefined)(result)) {
|
|
42
|
+
throw new _EvaluationElementIdError.default(`Evaluation failed on element ID: "${elementID}"`);
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
exports.evaluate = evaluate;
|
|
47
|
+
evaluate.cache = new WeakMap();
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { isUndefined } from 'ramda-adjunct';
|
|
2
|
+
import { isElement } from '@speclynx/apidom-datamodel';
|
|
3
|
+
import { toValue } from '@speclynx/apidom-core';
|
|
4
|
+
import { filter } from '@speclynx/apidom-traverse';
|
|
5
|
+
import EvaluationElementIdError from "../../../../errors/EvaluationElementIdError.mjs";
|
|
6
|
+
const getElementID = element => {
|
|
7
|
+
const id = element.meta.get('id');
|
|
8
|
+
// handle both raw string (new format) and StringElement (legacy Refract without __meta_raw__)
|
|
9
|
+
return isElement(id) ? toValue(id) : id;
|
|
10
|
+
};
|
|
11
|
+
const hasElementID = path => {
|
|
12
|
+
if (!path.node.hasMetaProperty('id')) return false;
|
|
13
|
+
const id = getElementID(path.node);
|
|
14
|
+
return typeof id === 'string' && id !== '';
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Evaluates element ID against ApiDOM fragment.
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
export const evaluate = (elementID, element) => {
|
|
22
|
+
const {
|
|
23
|
+
cache
|
|
24
|
+
} = evaluate;
|
|
25
|
+
// warm the cache
|
|
26
|
+
if (!cache.has(element)) {
|
|
27
|
+
const pathsWithID = filter(element, hasElementID);
|
|
28
|
+
cache.set(element, pathsWithID.map(path => path.node));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// search for the matching element
|
|
32
|
+
const result = cache.get(element).find(e => {
|
|
33
|
+
return getElementID(e) === elementID;
|
|
34
|
+
});
|
|
35
|
+
if (isUndefined(result)) {
|
|
36
|
+
throw new EvaluationElementIdError(`Evaluation failed on element ID: "${elementID}"`);
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
evaluate.cache = new WeakMap();
|
|
41
|
+
export { EvaluationElementIdError };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { isUndefined } from 'ramda-adjunct';
|
|
2
|
+
import { Element, isElement } from '@speclynx/apidom-datamodel';
|
|
3
|
+
import { toValue } from '@speclynx/apidom-core';
|
|
4
|
+
import { filter, type Path } from '@speclynx/apidom-traverse';
|
|
5
|
+
|
|
6
|
+
import EvaluationElementIdError from '../../../../errors/EvaluationElementIdError.ts';
|
|
7
|
+
|
|
8
|
+
const getElementID = (element: Element): string => {
|
|
9
|
+
const id = element.meta.get('id');
|
|
10
|
+
// handle both raw string (new format) and StringElement (legacy Refract without __meta_raw__)
|
|
11
|
+
return isElement(id) ? (toValue(id) as string) : (id as string);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const hasElementID = (path: Path<Element>): boolean => {
|
|
15
|
+
if (!path.node.hasMetaProperty('id')) return false;
|
|
16
|
+
const id = getElementID(path.node);
|
|
17
|
+
return typeof id === 'string' && id !== '';
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Evaluates element ID against ApiDOM fragment.
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export const evaluate = <T extends Element>(elementID: string, element: T): Element | undefined => {
|
|
25
|
+
const { cache } = evaluate;
|
|
26
|
+
// warm the cache
|
|
27
|
+
if (!cache.has(element)) {
|
|
28
|
+
const pathsWithID = filter(element, hasElementID);
|
|
29
|
+
cache.set(
|
|
30
|
+
element,
|
|
31
|
+
pathsWithID.map((path) => path.node),
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// search for the matching element
|
|
36
|
+
const result = cache.get(element).find((e: Element) => {
|
|
37
|
+
return getElementID(e) === elementID;
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (isUndefined(result)) {
|
|
41
|
+
throw new EvaluationElementIdError(`Evaluation failed on element ID: "${elementID}"`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
evaluate.cache = new WeakMap();
|
|
47
|
+
|
|
48
|
+
export { EvaluationElementIdError };
|