@speclynx/apidom-reference 2.8.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +208 -5
- package/dist/apidom-reference.browser.js +167 -77
- package/dist/apidom-reference.browser.min.js +1 -1
- package/package.json +25 -25
- package/src/dereference/strategies/arazzo-1/index.cjs +3 -2
- package/src/dereference/strategies/arazzo-1/index.mjs +3 -2
- package/src/dereference/strategies/arazzo-1/{source-description.cjs → source-descriptions.cjs} +98 -29
- package/src/dereference/strategies/arazzo-1/{source-description.mjs → source-descriptions.mjs} +99 -28
- package/src/parse/parsers/arazzo-json-1/source-descriptions.cjs +33 -15
- package/src/parse/parsers/arazzo-json-1/source-descriptions.mjs +33 -15
- package/types/dereference/strategies/arazzo-1/index.d.ts +1 -0
- package/types/dereference/strategies/arazzo-1/source-descriptions.d.ts +44 -0
- package/types/parse/parsers/arazzo-json-1/source-descriptions.d.ts +23 -8
- package/types/dereference/strategies/arazzo-1/source-description.d.ts +0 -8
|
@@ -816,6 +816,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
816
816
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
817
817
|
/* harmony export */ Arazzo1DereferenceVisitor: () => (/* reexport safe */ _visitor_ts__WEBPACK_IMPORTED_MODULE_9__["default"]),
|
|
818
818
|
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
|
|
819
|
+
/* harmony export */ dereferenceSourceDescriptions: () => (/* reexport safe */ _source_descriptions_ts__WEBPACK_IMPORTED_MODULE_10__.dereferenceSourceDescriptions),
|
|
819
820
|
/* harmony export */ maybeRefractToJSONSchemaElement: () => (/* reexport safe */ _util_ts__WEBPACK_IMPORTED_MODULE_11__.maybeRefractToJSONSchemaElement),
|
|
820
821
|
/* harmony export */ resolveSchema$idField: () => (/* reexport safe */ _util_ts__WEBPACK_IMPORTED_MODULE_12__.resolveSchema$idField),
|
|
821
822
|
/* harmony export */ resolveSchema$refField: () => (/* reexport safe */ _util_ts__WEBPACK_IMPORTED_MODULE_12__.resolveSchema$refField)
|
|
@@ -830,7 +831,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
830
831
|
/* harmony import */ var _Reference_ts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(98979);
|
|
831
832
|
/* harmony import */ var _ReferenceSet_ts__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(24131);
|
|
832
833
|
/* harmony import */ var _visitor_ts__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(31843);
|
|
833
|
-
/* harmony import */ var
|
|
834
|
+
/* harmony import */ var _source_descriptions_ts__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(12586);
|
|
834
835
|
/* harmony import */ var _util_ts__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(91005);
|
|
835
836
|
/* harmony import */ var _util_ts__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(60888);
|
|
836
837
|
|
|
@@ -908,7 +909,7 @@ class Arazzo1DereferenceStrategy extends _DereferenceStrategy_ts__WEBPACK_IMPORT
|
|
|
908
909
|
*/
|
|
909
910
|
const shouldDereferenceSourceDescriptions = options?.dereference?.strategyOpts?.[this.name]?.sourceDescriptions ?? options?.dereference?.strategyOpts?.sourceDescriptions;
|
|
910
911
|
if (shouldDereferenceSourceDescriptions) {
|
|
911
|
-
const sourceDescriptions = await (0,
|
|
912
|
+
const sourceDescriptions = await (0,_source_descriptions_ts__WEBPACK_IMPORTED_MODULE_10__.dereferenceSourceDescriptions)(dereferencedElement, reference.uri, options, this.name);
|
|
912
913
|
dereferencedElement.push(...sourceDescriptions);
|
|
913
914
|
}
|
|
914
915
|
|
|
@@ -935,11 +936,12 @@ class Arazzo1DereferenceStrategy extends _DereferenceStrategy_ts__WEBPACK_IMPORT
|
|
|
935
936
|
}
|
|
936
937
|
|
|
937
938
|
|
|
939
|
+
|
|
938
940
|
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Arazzo1DereferenceStrategy);
|
|
939
941
|
|
|
940
942
|
/***/ },
|
|
941
943
|
|
|
942
|
-
/***/
|
|
944
|
+
/***/ 12586
|
|
943
945
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
944
946
|
|
|
945
947
|
"use strict";
|
|
@@ -949,17 +951,17 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
949
951
|
/* harmony export */ });
|
|
950
952
|
/* harmony import */ var _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(25162);
|
|
951
953
|
/* harmony import */ var _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12111);
|
|
952
|
-
/* harmony import */ var _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(
|
|
953
|
-
/* harmony import */ var _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(
|
|
954
|
-
/* harmony import */ var
|
|
955
|
-
/* harmony import */ var
|
|
956
|
-
/* harmony import */ var
|
|
957
|
-
/* harmony import */ var
|
|
958
|
-
/* harmony import */ var
|
|
959
|
-
/* harmony import */ var
|
|
960
|
-
/* harmony import */ var
|
|
961
|
-
/* harmony import */ var
|
|
962
|
-
|
|
954
|
+
/* harmony import */ var _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(96911);
|
|
955
|
+
/* harmony import */ var _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(84660);
|
|
956
|
+
/* harmony import */ var _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4823);
|
|
957
|
+
/* harmony import */ var _speclynx_apidom_ns_arazzo_1__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(28839);
|
|
958
|
+
/* harmony import */ var _speclynx_apidom_ns_openapi_2__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(26365);
|
|
959
|
+
/* harmony import */ var _speclynx_apidom_ns_openapi_3_0__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(32131);
|
|
960
|
+
/* harmony import */ var _speclynx_apidom_ns_openapi_3_1__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(76332);
|
|
961
|
+
/* harmony import */ var _speclynx_apidom_core__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(44673);
|
|
962
|
+
/* harmony import */ var _util_url_ts__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(30658);
|
|
963
|
+
/* harmony import */ var _options_util_ts__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(86547);
|
|
964
|
+
/* harmony import */ var _index_ts__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(42037);
|
|
963
965
|
|
|
964
966
|
|
|
965
967
|
|
|
@@ -969,16 +971,14 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
969
971
|
|
|
970
972
|
|
|
971
973
|
|
|
972
|
-
// shared key for recursion state (works across JSON/YAML documents)
|
|
973
|
-
const ARAZZO_DEREFERENCE_RECURSION_KEY = 'arazzo-1';
|
|
974
974
|
/**
|
|
975
975
|
* Dereferences a single source description element.
|
|
976
976
|
* Returns ParseResultElement on success, or with annotation if skipped.
|
|
977
977
|
*/
|
|
978
978
|
async function dereferenceSourceDescription(sourceDescription, ctx) {
|
|
979
|
-
const parseResult = new
|
|
980
|
-
if (!(0,
|
|
981
|
-
const annotation = new
|
|
979
|
+
const parseResult = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_4__["default"]();
|
|
980
|
+
if (!(0,_speclynx_apidom_ns_arazzo_1__WEBPACK_IMPORTED_MODULE_5__.isSourceDescriptionElement)(sourceDescription)) {
|
|
981
|
+
const annotation = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__["default"]('Element is not a valid SourceDescriptionElement. Skipping');
|
|
982
982
|
annotation.classes.push('warning');
|
|
983
983
|
parseResult.push(annotation);
|
|
984
984
|
return parseResult;
|
|
@@ -988,37 +988,74 @@ async function dereferenceSourceDescription(sourceDescription, ctx) {
|
|
|
988
988
|
parseResult.classes.push('source-description');
|
|
989
989
|
if ((0,_speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_0__.isStringElement)(sourceDescription.name)) parseResult.setMetaProperty('name', (0,_speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_1__.cloneDeep)(sourceDescription.name));
|
|
990
990
|
if ((0,_speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_0__.isStringElement)(sourceDescription.type)) parseResult.setMetaProperty('type', (0,_speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_1__.cloneDeep)(sourceDescription.type));
|
|
991
|
-
const sourceDescriptionURI = (0,
|
|
991
|
+
const sourceDescriptionURI = (0,_speclynx_apidom_core__WEBPACK_IMPORTED_MODULE_9__["default"])(sourceDescription.url);
|
|
992
992
|
if (typeof sourceDescriptionURI !== 'string') {
|
|
993
|
-
const annotation = new
|
|
993
|
+
const annotation = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__["default"]('Source description URL is missing or not a string. Skipping');
|
|
994
994
|
annotation.classes.push('warning');
|
|
995
995
|
parseResult.push(annotation);
|
|
996
996
|
return parseResult;
|
|
997
997
|
}
|
|
998
|
-
|
|
998
|
+
|
|
999
|
+
// normalize URI for consistent cycle detection and refSet cache key matching
|
|
1000
|
+
const retrievalURI = _util_url_ts__WEBPACK_IMPORTED_MODULE_10__.sanitize(_util_url_ts__WEBPACK_IMPORTED_MODULE_10__.stripHash(_util_url_ts__WEBPACK_IMPORTED_MODULE_10__.resolve(ctx.baseURI, sourceDescriptionURI)));
|
|
1001
|
+
parseResult.setMetaProperty('retrievalURI', retrievalURI);
|
|
999
1002
|
|
|
1000
1003
|
// skip if already visited (cycle detection)
|
|
1001
1004
|
if (ctx.visitedUrls.has(retrievalURI)) {
|
|
1002
|
-
const annotation = new
|
|
1005
|
+
const annotation = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__["default"](`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle`);
|
|
1003
1006
|
annotation.classes.push('warning');
|
|
1004
1007
|
parseResult.push(annotation);
|
|
1005
1008
|
return parseResult;
|
|
1006
1009
|
}
|
|
1007
1010
|
ctx.visitedUrls.add(retrievalURI);
|
|
1011
|
+
|
|
1012
|
+
// check if source description was already parsed (e.g., during parse phase with sourceDescriptions: true)
|
|
1013
|
+
const existingParseResult = sourceDescription.meta.get('parseResult');
|
|
1008
1014
|
try {
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1015
|
+
let sourceDescriptionDereferenced;
|
|
1016
|
+
if ((0,_speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_2__.isParseResultElement)(existingParseResult)) {
|
|
1017
|
+
// use existing parsed result - just dereference it (no re-fetch/re-parse)
|
|
1018
|
+
sourceDescriptionDereferenced = await (0,_index_ts__WEBPACK_IMPORTED_MODULE_12__.dereferenceApiDOM)(existingParseResult, (0,_options_util_ts__WEBPACK_IMPORTED_MODULE_11__.merge)(ctx.options, {
|
|
1019
|
+
parse: {
|
|
1020
|
+
mediaType: 'text/plain' // allow dereference strategy detection via ApiDOM inspection
|
|
1021
|
+
},
|
|
1022
|
+
resolve: {
|
|
1023
|
+
baseURI: retrievalURI
|
|
1024
|
+
},
|
|
1025
|
+
dereference: {
|
|
1026
|
+
strategyOpts: {
|
|
1027
|
+
// nested documents should dereference all their source descriptions
|
|
1028
|
+
// (parent's name filter doesn't apply to nested documents)
|
|
1029
|
+
// set at strategy-specific level to override any inherited filters
|
|
1030
|
+
[ctx.strategyName]: {
|
|
1031
|
+
sourceDescriptions: true,
|
|
1032
|
+
sourceDescriptionsDepth: ctx.currentDepth + 1,
|
|
1033
|
+
sourceDescriptionsVisitedUrls: ctx.visitedUrls
|
|
1034
|
+
}
|
|
1018
1035
|
}
|
|
1019
1036
|
}
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1037
|
+
}));
|
|
1038
|
+
} else {
|
|
1039
|
+
// no existing parse result - fetch, parse, and dereference
|
|
1040
|
+
sourceDescriptionDereferenced = await (0,_index_ts__WEBPACK_IMPORTED_MODULE_12__["default"])(retrievalURI, (0,_options_util_ts__WEBPACK_IMPORTED_MODULE_11__.merge)(ctx.options, {
|
|
1041
|
+
parse: {
|
|
1042
|
+
mediaType: 'text/plain' // allow parser plugin detection
|
|
1043
|
+
},
|
|
1044
|
+
dereference: {
|
|
1045
|
+
strategyOpts: {
|
|
1046
|
+
// nested documents should dereference all their source descriptions
|
|
1047
|
+
// (parent's name filter doesn't apply to nested documents)
|
|
1048
|
+
// set at strategy-specific level to override any inherited filters
|
|
1049
|
+
[ctx.strategyName]: {
|
|
1050
|
+
sourceDescriptions: true,
|
|
1051
|
+
sourceDescriptionsDepth: ctx.currentDepth + 1,
|
|
1052
|
+
sourceDescriptionsVisitedUrls: ctx.visitedUrls
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}));
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1022
1059
|
// merge dereferenced result into our parse result
|
|
1023
1060
|
for (const item of sourceDescriptionDereferenced) {
|
|
1024
1061
|
parseResult.push(item);
|
|
@@ -1026,7 +1063,7 @@ async function dereferenceSourceDescription(sourceDescription, ctx) {
|
|
|
1026
1063
|
} catch (error) {
|
|
1027
1064
|
// create error annotation instead of failing entire dereference
|
|
1028
1065
|
const message = error instanceof Error ? error.message : String(error);
|
|
1029
|
-
const annotation = new
|
|
1066
|
+
const annotation = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__["default"](`Error dereferencing source description "${retrievalURI}": ${message}`);
|
|
1030
1067
|
annotation.classes.push('error');
|
|
1031
1068
|
parseResult.push(annotation);
|
|
1032
1069
|
return parseResult;
|
|
@@ -1036,24 +1073,24 @@ async function dereferenceSourceDescription(sourceDescription, ctx) {
|
|
|
1036
1073
|
const {
|
|
1037
1074
|
api: sourceDescriptionAPI
|
|
1038
1075
|
} = parseResult;
|
|
1039
|
-
const isOpenApi = (0,
|
|
1040
|
-
const isArazzo = (0,
|
|
1076
|
+
const isOpenApi = (0,_speclynx_apidom_ns_openapi_2__WEBPACK_IMPORTED_MODULE_6__.isSwaggerElement)(sourceDescriptionAPI) || (0,_speclynx_apidom_ns_openapi_3_0__WEBPACK_IMPORTED_MODULE_7__.isOpenApi3_0Element)(sourceDescriptionAPI) || (0,_speclynx_apidom_ns_openapi_3_1__WEBPACK_IMPORTED_MODULE_8__.isOpenApi3_1Element)(sourceDescriptionAPI);
|
|
1077
|
+
const isArazzo = (0,_speclynx_apidom_ns_arazzo_1__WEBPACK_IMPORTED_MODULE_5__.isArazzoSpecification1Element)(sourceDescriptionAPI);
|
|
1041
1078
|
if (!isOpenApi && !isArazzo) {
|
|
1042
|
-
const annotation = new
|
|
1079
|
+
const annotation = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__["default"](`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document`);
|
|
1043
1080
|
annotation.classes.push('warning');
|
|
1044
1081
|
parseResult.push(annotation);
|
|
1045
1082
|
return parseResult;
|
|
1046
1083
|
}
|
|
1047
1084
|
|
|
1048
1085
|
// validate declared type matches actual dereferenced type
|
|
1049
|
-
const declaredType = (0,
|
|
1086
|
+
const declaredType = (0,_speclynx_apidom_core__WEBPACK_IMPORTED_MODULE_9__["default"])(sourceDescription.type);
|
|
1050
1087
|
if (typeof declaredType === 'string') {
|
|
1051
1088
|
if (declaredType === 'openapi' && !isOpenApi) {
|
|
1052
|
-
const annotation = new
|
|
1089
|
+
const annotation = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__["default"](`Source description "${retrievalURI}" declared as "openapi" but dereferenced as Arazzo document`);
|
|
1053
1090
|
annotation.classes.push('warning');
|
|
1054
1091
|
parseResult.push(annotation);
|
|
1055
1092
|
} else if (declaredType === 'arazzo' && !isArazzo) {
|
|
1056
|
-
const annotation = new
|
|
1093
|
+
const annotation = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__["default"](`Source description "${retrievalURI}" declared as "arazzo" but dereferenced as OpenAPI document`);
|
|
1057
1094
|
annotation.classes.push('warning');
|
|
1058
1095
|
parseResult.push(annotation);
|
|
1059
1096
|
}
|
|
@@ -1063,11 +1100,48 @@ async function dereferenceSourceDescription(sourceDescription, ctx) {
|
|
|
1063
1100
|
|
|
1064
1101
|
/**
|
|
1065
1102
|
* Dereferences source descriptions from an Arazzo document.
|
|
1103
|
+
*
|
|
1104
|
+
* Each source description result is attached to its corresponding
|
|
1105
|
+
* SourceDescriptionElement's meta as 'parseResult' for easy access,
|
|
1106
|
+
* regardless of success or failure. On failure, the ParseResultElement
|
|
1107
|
+
* contains annotations explaining what went wrong.
|
|
1108
|
+
*
|
|
1109
|
+
* @param parseResult - ParseResult containing a parsed (optionally dereferenced) Arazzo specification
|
|
1110
|
+
* @param parseResultRetrievalURI - URI from which the parseResult was retrieved
|
|
1111
|
+
* @param options - Full ReferenceOptions. Pass `sourceDescriptions` as an array of names
|
|
1112
|
+
* in `dereference.strategyOpts` to filter which source descriptions to process.
|
|
1113
|
+
* @param strategyName - Strategy name for options lookup (defaults to 'arazzo-1')
|
|
1114
|
+
* @returns Array of ParseResultElements. Returns one ParseResultElement per source description
|
|
1115
|
+
* (each with class 'source-description' and metadata: name, type, retrievalURI).
|
|
1116
|
+
* May return early with a single-element array containing a warning annotation when:
|
|
1117
|
+
* - The API is not an Arazzo specification
|
|
1118
|
+
* - The sourceDescriptions field is missing or not an array
|
|
1119
|
+
* - Maximum dereference depth is exceeded (error annotation)
|
|
1120
|
+
* Returns an empty array when no source description names match the filter.
|
|
1121
|
+
*
|
|
1122
|
+
* @example
|
|
1123
|
+
* ```typescript
|
|
1124
|
+
* import { toValue } from '@speclynx/apidom-core';
|
|
1125
|
+
*
|
|
1126
|
+
* // Dereference all source descriptions
|
|
1127
|
+
* await dereferenceSourceDescriptions(parseResult, uri, options);
|
|
1128
|
+
*
|
|
1129
|
+
* // Filter by name
|
|
1130
|
+
* await dereferenceSourceDescriptions(parseResult, uri, mergeOptions(options, {
|
|
1131
|
+
* dereference: { strategyOpts: { sourceDescriptions: ['petStore'] } },
|
|
1132
|
+
* }));
|
|
1133
|
+
*
|
|
1134
|
+
* // Access dereferenced document from source description element
|
|
1135
|
+
* const sourceDesc = parseResult.api.sourceDescriptions.get(0);
|
|
1136
|
+
* const dereferencedDoc = sourceDesc.meta.get('parseResult');
|
|
1137
|
+
* const retrievalURI = toValue(dereferencedDoc.meta.get('retrievalURI'));
|
|
1138
|
+
* ```
|
|
1139
|
+
*
|
|
1066
1140
|
* @public
|
|
1067
1141
|
*/
|
|
1068
|
-
async function dereferenceSourceDescriptions(parseResult,
|
|
1142
|
+
async function dereferenceSourceDescriptions(parseResult, parseResultRetrievalURI, options, strategyName = 'arazzo-1') {
|
|
1143
|
+
const baseURI = _util_url_ts__WEBPACK_IMPORTED_MODULE_10__.sanitize(_util_url_ts__WEBPACK_IMPORTED_MODULE_10__.stripHash(parseResultRetrievalURI));
|
|
1069
1144
|
const results = [];
|
|
1070
|
-
const strategyName = 'arazzo-1';
|
|
1071
1145
|
|
|
1072
1146
|
// get API from dereferenced parse result
|
|
1073
1147
|
const {
|
|
@@ -1078,57 +1152,55 @@ async function dereferenceSourceDescriptions(parseResult, reference, options) {
|
|
|
1078
1152
|
* Validate prerequisites for dereferencing source descriptions.
|
|
1079
1153
|
* Return warning annotations if validation fails.
|
|
1080
1154
|
*/
|
|
1081
|
-
if (!(0,
|
|
1082
|
-
const annotation = new
|
|
1155
|
+
if (!(0,_speclynx_apidom_ns_arazzo_1__WEBPACK_IMPORTED_MODULE_5__.isArazzoSpecification1Element)(api)) {
|
|
1156
|
+
const annotation = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__["default"]('Cannot dereference source descriptions: API is not an Arazzo specification');
|
|
1083
1157
|
annotation.classes.push('warning');
|
|
1084
|
-
return [new
|
|
1158
|
+
return [new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_4__["default"]([annotation])];
|
|
1085
1159
|
}
|
|
1086
1160
|
if (!(0,_speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_0__.isArrayElement)(api.sourceDescriptions)) {
|
|
1087
|
-
const annotation = new
|
|
1161
|
+
const annotation = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__["default"]('Cannot dereference source descriptions: sourceDescriptions field is missing or not an array');
|
|
1088
1162
|
annotation.classes.push('warning');
|
|
1089
|
-
return [new
|
|
1163
|
+
return [new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_4__["default"]([annotation])];
|
|
1090
1164
|
}
|
|
1091
1165
|
|
|
1092
1166
|
// user config: strategy-specific options take precedence over global strategyOpts
|
|
1093
1167
|
const maxDepth = options?.dereference?.strategyOpts?.[strategyName]?.sourceDescriptionsMaxDepth ?? options?.dereference?.strategyOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
|
|
1094
1168
|
|
|
1095
|
-
// recursion state comes from
|
|
1096
|
-
const sharedOpts = options?.dereference?.strategyOpts?.[
|
|
1169
|
+
// recursion state comes from strategy-specific options
|
|
1170
|
+
const sharedOpts = options?.dereference?.strategyOpts?.[strategyName] ?? {};
|
|
1097
1171
|
const currentDepth = sharedOpts.sourceDescriptionsDepth ?? 0;
|
|
1098
1172
|
const visitedUrls = sharedOpts.sourceDescriptionsVisitedUrls ?? new Set();
|
|
1099
1173
|
|
|
1100
1174
|
// add current file to visited URLs to prevent cycles
|
|
1101
|
-
visitedUrls.add(
|
|
1175
|
+
visitedUrls.add(baseURI);
|
|
1102
1176
|
if (currentDepth >= maxDepth) {
|
|
1103
|
-
const annotation = new
|
|
1177
|
+
const annotation = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_3__["default"](`Maximum dereference depth of ${maxDepth} has been exceeded by file "${baseURI}"`);
|
|
1104
1178
|
annotation.classes.push('error');
|
|
1105
|
-
const parseResult = new
|
|
1179
|
+
const parseResult = new _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_4__["default"]([annotation]);
|
|
1106
1180
|
parseResult.classes.push('source-description');
|
|
1107
1181
|
return [parseResult];
|
|
1108
1182
|
}
|
|
1109
1183
|
const ctx = {
|
|
1110
|
-
baseURI
|
|
1184
|
+
baseURI,
|
|
1111
1185
|
options,
|
|
1186
|
+
strategyName,
|
|
1112
1187
|
currentDepth,
|
|
1113
1188
|
visitedUrls
|
|
1114
1189
|
};
|
|
1115
1190
|
|
|
1116
|
-
// determine which source descriptions to dereference
|
|
1191
|
+
// determine which source descriptions to dereference (array filters by name)
|
|
1117
1192
|
const sourceDescriptionsOption = options?.dereference?.strategyOpts?.[strategyName]?.sourceDescriptions ?? options?.dereference?.strategyOpts?.sourceDescriptions;
|
|
1118
|
-
|
|
1119
|
-
// handle false or other falsy values - no source descriptions should be dereferenced
|
|
1120
|
-
if (!sourceDescriptionsOption) {
|
|
1121
|
-
return results;
|
|
1122
|
-
}
|
|
1123
1193
|
const sourceDescriptions = Array.isArray(sourceDescriptionsOption) ? api.sourceDescriptions.filter(sd => {
|
|
1124
|
-
if (!(0,
|
|
1125
|
-
const name = (0,
|
|
1194
|
+
if (!(0,_speclynx_apidom_ns_arazzo_1__WEBPACK_IMPORTED_MODULE_5__.isSourceDescriptionElement)(sd)) return false;
|
|
1195
|
+
const name = (0,_speclynx_apidom_core__WEBPACK_IMPORTED_MODULE_9__["default"])(sd.name);
|
|
1126
1196
|
return typeof name === 'string' && sourceDescriptionsOption.includes(name);
|
|
1127
1197
|
}) : api.sourceDescriptions;
|
|
1128
1198
|
|
|
1129
1199
|
// process sequentially to ensure proper cycle detection with shared visitedUrls
|
|
1130
1200
|
for (const sourceDescription of sourceDescriptions) {
|
|
1131
1201
|
const sourceDescriptionDereferenceResult = await dereferenceSourceDescription(sourceDescription, ctx);
|
|
1202
|
+
// always attach result (even on failure - contains annotations)
|
|
1203
|
+
sourceDescription.meta.set('parseResult', sourceDescriptionDereferenceResult);
|
|
1132
1204
|
results.push(sourceDescriptionDereferenceResult);
|
|
1133
1205
|
}
|
|
1134
1206
|
return results;
|
|
@@ -5832,7 +5904,10 @@ async function parseSourceDescription(sourceDescription, ctx) {
|
|
|
5832
5904
|
parseResult.push(annotation);
|
|
5833
5905
|
return parseResult;
|
|
5834
5906
|
}
|
|
5835
|
-
|
|
5907
|
+
|
|
5908
|
+
// normalize URI for consistent cycle detection and cache key matching
|
|
5909
|
+
const retrievalURI = _util_url_ts__WEBPACK_IMPORTED_MODULE_10__.sanitize(_util_url_ts__WEBPACK_IMPORTED_MODULE_10__.stripHash(_util_url_ts__WEBPACK_IMPORTED_MODULE_10__.resolve(ctx.baseURI, sourceDescriptionURI)));
|
|
5910
|
+
parseResult.setMetaProperty('retrievalURI', retrievalURI);
|
|
5836
5911
|
|
|
5837
5912
|
// skip if already visited (cycle detection)
|
|
5838
5913
|
if (ctx.visitedUrls.has(retrievalURI)) {
|
|
@@ -5848,6 +5923,9 @@ async function parseSourceDescription(sourceDescription, ctx) {
|
|
|
5848
5923
|
mediaType: 'text/plain',
|
|
5849
5924
|
// allow parser plugin detection
|
|
5850
5925
|
parserOpts: {
|
|
5926
|
+
// nested documents should parse all their source descriptions
|
|
5927
|
+
// (parent's name filter doesn't apply to nested documents)
|
|
5928
|
+
sourceDescriptions: true,
|
|
5851
5929
|
[ARAZZO_RECURSION_KEY]: {
|
|
5852
5930
|
sourceDescriptionsDepth: ctx.currentDepth + 1,
|
|
5853
5931
|
sourceDescriptionsVisitedUrls: ctx.visitedUrls
|
|
@@ -5900,27 +5978,42 @@ async function parseSourceDescription(sourceDescription, ctx) {
|
|
|
5900
5978
|
/**
|
|
5901
5979
|
* Parses source descriptions from an Arazzo document's ParseResult.
|
|
5902
5980
|
*
|
|
5981
|
+
* Each source description result is attached to its corresponding
|
|
5982
|
+
* SourceDescriptionElement's meta as 'parseResult' for easy access,
|
|
5983
|
+
* regardless of success or failure. On failure, the ParseResultElement
|
|
5984
|
+
* contains annotations explaining what went wrong.
|
|
5985
|
+
*
|
|
5903
5986
|
* @param parseResult - ParseResult containing an Arazzo specification
|
|
5904
5987
|
* @param parseResultRetrievalURI - URI from which the parseResult was retrieved
|
|
5905
|
-
* @param options - Full ReferenceOptions
|
|
5988
|
+
* @param options - Full ReferenceOptions. Pass `sourceDescriptions` as an array of names
|
|
5989
|
+
* in `parse.parserOpts` to filter which source descriptions to process.
|
|
5906
5990
|
* @param parserName - Parser name for options lookup (defaults to 'arazzo-json-1')
|
|
5907
|
-
* @returns Array of ParseResultElements.
|
|
5908
|
-
*
|
|
5991
|
+
* @returns Array of ParseResultElements. Returns one ParseResultElement per source description
|
|
5992
|
+
* (each with class 'source-description' and metadata: name, type, retrievalURI).
|
|
5909
5993
|
* May return early with a single-element array containing a warning annotation when:
|
|
5910
5994
|
* - The API is not an Arazzo specification
|
|
5911
5995
|
* - The sourceDescriptions field is missing or not an array
|
|
5912
5996
|
* - Maximum parse depth is exceeded (error annotation)
|
|
5913
|
-
* Returns an empty array when
|
|
5997
|
+
* Returns an empty array when no source description names match the filter.
|
|
5914
5998
|
*
|
|
5915
5999
|
* @example
|
|
5916
6000
|
* ```typescript
|
|
6001
|
+
* import { toValue } from '@speclynx/apidom-core';
|
|
5917
6002
|
* import { options, mergeOptions } from '@speclynx/apidom-reference';
|
|
5918
6003
|
* import { parseSourceDescriptions } from '@speclynx/apidom-reference/parse/parsers/arazzo-json-1';
|
|
5919
6004
|
*
|
|
5920
|
-
*
|
|
5921
|
-
*
|
|
5922
|
-
*
|
|
5923
|
-
*
|
|
6005
|
+
* // Parse all source descriptions
|
|
6006
|
+
* const results = await parseSourceDescriptions(parseResult, uri, options);
|
|
6007
|
+
*
|
|
6008
|
+
* // Filter by name
|
|
6009
|
+
* const filtered = await parseSourceDescriptions(parseResult, uri, mergeOptions(options, {
|
|
6010
|
+
* parse: { parserOpts: { sourceDescriptions: ['petStore'] } }
|
|
6011
|
+
* }));
|
|
6012
|
+
*
|
|
6013
|
+
* // Access parsed document from source description element
|
|
6014
|
+
* const sourceDesc = parseResult.api.sourceDescriptions.get(0);
|
|
6015
|
+
* const parsedDoc = sourceDesc.meta.get('parseResult');
|
|
6016
|
+
* const retrievalURI = toValue(parsedDoc.meta.get('retrievalURI'));
|
|
5924
6017
|
* ```
|
|
5925
6018
|
*
|
|
5926
6019
|
* @public
|
|
@@ -5973,13 +6066,8 @@ async function parseSourceDescriptions(parseResult, parseResultRetrievalURI, opt
|
|
|
5973
6066
|
visitedUrls
|
|
5974
6067
|
};
|
|
5975
6068
|
|
|
5976
|
-
// determine which source descriptions to parse
|
|
6069
|
+
// determine which source descriptions to parse (array filters by name)
|
|
5977
6070
|
const sourceDescriptionsOption = options?.parse?.parserOpts?.[parserName]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
|
|
5978
|
-
|
|
5979
|
-
// handle false or other falsy values - no source descriptions should be parsed
|
|
5980
|
-
if (!sourceDescriptionsOption) {
|
|
5981
|
-
return results;
|
|
5982
|
-
}
|
|
5983
6071
|
const sourceDescriptions = Array.isArray(sourceDescriptionsOption) ? api.sourceDescriptions.filter(sd => {
|
|
5984
6072
|
if (!(0,_speclynx_apidom_ns_arazzo_1__WEBPACK_IMPORTED_MODULE_4__.isSourceDescriptionElement)(sd)) return false;
|
|
5985
6073
|
const name = (0,_speclynx_apidom_core__WEBPACK_IMPORTED_MODULE_8__["default"])(sd.name);
|
|
@@ -5989,6 +6077,8 @@ async function parseSourceDescriptions(parseResult, parseResultRetrievalURI, opt
|
|
|
5989
6077
|
// process sequentially to ensure proper cycle detection with shared visitedUrls
|
|
5990
6078
|
for (const sourceDescription of sourceDescriptions) {
|
|
5991
6079
|
const sourceDescriptionParseResult = await parseSourceDescription(sourceDescription, ctx);
|
|
6080
|
+
// always attach result (even on failure - contains annotations)
|
|
6081
|
+
sourceDescription.meta.set('parseResult', sourceDescriptionParseResult);
|
|
5992
6082
|
results.push(sourceDescriptionParseResult);
|
|
5993
6083
|
}
|
|
5994
6084
|
return results;
|