UNPKG

oas

Version:

Comprehensive tooling for working with OpenAPI definitions

1,262 lines (1,216 loc) 76.1 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _chunk2X4PY2BScjs = require('./chunk-2X4PY2BS.cjs'); var _chunkAYA3UT4Lcjs = require('./chunk-AYA3UT4L.cjs'); var _chunk3MTU2ESPcjs = require('./chunk-3MTU2ESP.cjs'); // src/operation/index.ts var _jsonschemarefparser = require('@apidevtools/json-schema-ref-parser'); // src/operation/lib/dedupe-common-parameters.ts function dedupeCommonParameters(parameters, commonParameters) { return commonParameters.filter((param) => { return !parameters.find((param2) => { if (param.name && param2.name) { return param.name === param2.name && param.in === param2.in; } else if (_chunk3MTU2ESPcjs.isRef.call(void 0, param) && _chunk3MTU2ESPcjs.isRef.call(void 0, param2)) { return param.$ref === param2.$ref; } return false; }); }); } // src/samples/index.ts var _jsonschemamergeallof = require('json-schema-merge-allof'); var _jsonschemamergeallof2 = _interopRequireDefault(_jsonschemamergeallof); var _memoizee = require('memoizee'); var _memoizee2 = _interopRequireDefault(_memoizee); // src/samples/utils.ts function usesPolymorphism(schema) { if (schema.oneOf) { return "oneOf"; } else if (schema.anyOf) { return "anyOf"; } else if (schema.allOf) { return "allOf"; } return false; } function objectify(thing) { if (!_chunk2X4PY2BScjs.isObject.call(void 0, thing)) { return {}; } return thing; } function normalizeArray(arr) { if (Array.isArray(arr)) { return arr; } return [arr]; } function isFunc(thing) { return typeof thing === "function"; } function deeplyStripKey(input, keyToStrip, predicate) { if (typeof input !== "object" || Array.isArray(input) || input === null || !keyToStrip) { return input; } const obj = { ...input }; Object.keys(obj).forEach((k) => { if (k === keyToStrip && _optionalChain([predicate, 'optionalCall', _2 => _2(obj[k], k)])) { delete obj[k]; return; } obj[k] = deeplyStripKey(obj[k], keyToStrip, predicate); }); return obj; } // src/samples/index.ts var sampleDefaults = (genericSample) => { return (schema) => typeof schema.default === typeof genericSample ? schema.default : genericSample; }; var primitives = { string: sampleDefaults("string"), string_email: sampleDefaults("user@example.com"), "string_date-time": sampleDefaults((/* @__PURE__ */ new Date()).toISOString()), string_date: sampleDefaults((/* @__PURE__ */ new Date()).toISOString().substring(0, 10)), "string_YYYY-MM-DD": sampleDefaults((/* @__PURE__ */ new Date()).toISOString().substring(0, 10)), string_uuid: sampleDefaults("3fa85f64-5717-4562-b3fc-2c963f66afa6"), string_hostname: sampleDefaults("example.com"), string_ipv4: sampleDefaults("198.51.100.42"), string_ipv6: sampleDefaults("2001:0db8:5b96:0000:0000:426f:8e17:642a"), number: sampleDefaults(0), number_float: sampleDefaults(0), integer: sampleDefaults(0), boolean: sampleDefaults(true) }; var primitive = (schema) => { const objectifiedSchema = objectify(schema); const { format } = objectifiedSchema; let { type } = objectifiedSchema; if (type === "null") { return null; } else if (Array.isArray(type)) { if (type.length === 1) { type = type[0]; } else { if (type.includes("null")) { type = type.filter((t) => t !== "null"); } type = type.shift(); } } const fn = primitives[`${type}_${format}`] || primitives[type]; if (isFunc(fn)) { return fn(objectifiedSchema); } return `Unknown Type: ${objectifiedSchema.type}`; }; function sampleFromSchema(schema, opts = {}) { const seenRefs = opts.seenRefs || /* @__PURE__ */ new Set(); let objectifySchema = objectify(schema); let refToRelease; if (opts.definition && _chunk3MTU2ESPcjs.isRef.call(void 0, objectifySchema)) { refToRelease = objectifySchema.$ref; if (seenRefs.has(refToRelease)) { return void 0; } objectifySchema = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, objectifySchema, opts.definition, seenRefs); if (!objectifySchema || _chunk3MTU2ESPcjs.isRef.call(void 0, objectifySchema)) { return void 0; } } try { return sampleFromResolvedSchema(objectifySchema, opts, seenRefs); } finally { if (refToRelease) { seenRefs.delete(refToRelease); } } } function sampleFromResolvedSchema(schema, opts, seenRefs) { let { type } = schema; const hasPolymorphism = usesPolymorphism(schema); if (hasPolymorphism === "allOf") { try { const definition = opts.definition; const resolvedAllOf = schema.allOf.map((subSchema) => { let sub = objectify(subSchema); if (definition && _chunk3MTU2ESPcjs.isRef.call(void 0, sub)) { const resolved = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, sub, definition, /* @__PURE__ */ new Set()); if (resolved && !_chunk3MTU2ESPcjs.isRef.call(void 0, resolved)) { sub = resolved; } } return sub; }); return sampleFromSchema( _jsonschemamergeallof2.default.call(void 0, { ...schema, allOf: resolvedAllOf }, { resolvers: { // Ignore any unrecognized OAS-specific keywords that might be present on the schema // (like `xml`). defaultResolver: _jsonschemamergeallof2.default.options.resolvers.title } } ), { ...opts, seenRefs } ); } catch (e) { return; } } else if (hasPolymorphism) { const samples = schema[hasPolymorphism].map((s) => { return sampleFromSchema(s, { ...opts, seenRefs }); }); if (samples.length === 1) { return samples[0]; } else if (samples.some((s) => s === null)) { return samples.find((s) => s !== null); } return samples[0]; } const { example, additionalProperties, properties, items } = schema; const { includeReadOnly, includeWriteOnly } = opts; if (example !== void 0) { const cleanedExample = deeplyStripKey(example, "$$ref", (val) => { return typeof val === "string" && val.indexOf("#") > -1; }); return _chunk2X4PY2BScjs.dereferenceRefDeep.call(void 0, cleanedExample, opts.definition, seenRefs); } if (!type) { if (properties || additionalProperties) { type = "object"; } else if (items) { type = "array"; } else { return; } } if (type === "object" || Array.isArray(type) && type.includes("object")) { const props = objectify(properties); const obj = {}; for (const name in props) { if (_optionalChain([props, 'optionalAccess', _3 => _3[name], 'access', _4 => _4.deprecated])) { continue; } if (_optionalChain([props, 'optionalAccess', _5 => _5[name], 'access', _6 => _6.readOnly]) && !includeReadOnly) { continue; } if (_optionalChain([props, 'optionalAccess', _7 => _7[name], 'access', _8 => _8.writeOnly]) && !includeWriteOnly) { continue; } if (_optionalChain([props, 'access', _9 => _9[name], 'access', _10 => _10.examples, 'optionalAccess', _11 => _11.length])) { obj[name] = props[name].examples[0]; continue; } obj[name] = sampleFromSchema(props[name], { ...opts, seenRefs }); } if (additionalProperties === true) { obj.additionalProp = {}; } else if (additionalProperties) { const additionalProps = objectify(additionalProperties); const additionalPropVal = sampleFromSchema(additionalProps, { ...opts, seenRefs }); obj.additionalProp = additionalPropVal; } return obj; } if (type === "array" || Array.isArray(type) && type.includes("array")) { if (typeof items === "undefined") { return []; } if (Array.isArray(items.anyOf)) { return items.anyOf.map( (i) => sampleFromSchema(i, { ...opts, seenRefs }) ); } if (Array.isArray(items.oneOf)) { return items.oneOf.map( (i) => sampleFromSchema(i, { ...opts, seenRefs }) ); } return [sampleFromSchema(items, { ...opts, seenRefs })]; } if (schema.enum) { if (schema.default) { return schema.default; } return normalizeArray(schema.enum)[0]; } if (type === "file") { return; } return primitive(schema); } var memo = _memoizee2.default.call(void 0, sampleFromSchema); var samples_default = memo; // src/operation/lib/get-mediatype-examples.ts function getMediaTypeExamples(mediaType, mediaTypeObject, definition, opts = {}) { if (mediaTypeObject.example) { mediaTypeObject.example = _chunk2X4PY2BScjs.dereferenceRefDeep.call(void 0, mediaTypeObject.example, definition); if (mediaTypeObject.example === void 0 || _chunk2X4PY2BScjs.collectRefsInSchema.call(void 0, mediaTypeObject.example).size > 0) { return []; } return [ { value: mediaTypeObject.example } ]; } else if (mediaTypeObject.examples) { const { examples } = mediaTypeObject; const multipleExamples = Object.keys(examples).map((key) => { let summary = key; let description; let example = examples[key]; if (example !== null && typeof example === "object") { if (_chunk3MTU2ESPcjs.isRef.call(void 0, example)) { example = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, example, definition); if (!example || _chunk3MTU2ESPcjs.isRef.call(void 0, example)) { return false; } } if ("summary" in example) { summary = example.summary; } if ("description" in example) { description = example.description; } if ("value" in example) { example.value = _chunk2X4PY2BScjs.dereferenceRefDeep.call(void 0, example.value, definition); if (example.value === void 0 || _chunk2X4PY2BScjs.collectRefsInSchema.call(void 0, example.value).size > 0) { return false; } example = example.value; } } const ret = { summary, title: key, value: example }; if (description) { ret.description = description; } return ret; }).filter((item) => item !== false); if (multipleExamples.length) { return multipleExamples; } } if (mediaTypeObject.schema) { if (!_chunk2X4PY2BScjs.matches_mimetype_default.xml(mediaType)) { return [ { value: samples_default(structuredClone(mediaTypeObject.schema), { ...opts, definition }) } ]; } } return []; } // src/operation/lib/get-response-examples.ts function getResponseExamples(operation, definition) { return Object.keys(operation.responses || {}).map((status) => { let response = _optionalChain([operation, 'access', _12 => _12.responses, 'optionalAccess', _13 => _13[status]]); let onlyHeaders = false; if (!response) return false; if (_chunk3MTU2ESPcjs.isRef.call(void 0, response)) { response = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, response, definition); if (!response || _chunk3MTU2ESPcjs.isRef.call(void 0, response)) return false; } const mediaTypes = {}; (_optionalChain([response, 'optionalAccess', _14 => _14.content]) ? Object.keys(response.content) : []).forEach((mediaType) => { if (!mediaType) return; const mediaTypeObject = _optionalChain([response, 'access', _15 => _15.content, 'optionalAccess', _16 => _16[mediaType]]); if (!mediaTypeObject) return; const examples = getMediaTypeExamples(mediaType, mediaTypeObject, definition, { includeReadOnly: true, includeWriteOnly: false }); if (examples) { mediaTypes[mediaType] = examples; } }); if (response.headers && Object.keys(response.headers).length && !Object.keys(mediaTypes).length) { mediaTypes["*/*"] = []; onlyHeaders = true; } if (!Object.keys(mediaTypes).length) { return false; } return { status, mediaTypes, ...onlyHeaders ? { onlyHeaders } : {} }; }).filter((item) => item !== false); } // src/operation/lib/get-callback-examples.ts function getCallbackExamples(operation, definition) { if (!operation.callbacks) { return []; } const examples = Object.keys(operation.callbacks).map((identifier) => { let callback = _optionalChain([operation, 'access', _17 => _17.callbacks, 'optionalAccess', _18 => _18[identifier]]); if (!callback) return []; if (_chunk3MTU2ESPcjs.isRef.call(void 0, callback)) { callback = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, callback, definition); if (!callback || _chunk3MTU2ESPcjs.isRef.call(void 0, callback)) return []; } const items = Object.keys(callback).map((expression) => { let callbackPath = callback[expression]; if (!callbackPath) return []; if (_chunk3MTU2ESPcjs.isRef.call(void 0, callbackPath)) { callbackPath = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, callbackPath, definition); if (!callbackPath || _chunk3MTU2ESPcjs.isRef.call(void 0, callbackPath)) return []; } return Object.keys(callbackPath).map((method) => { if (["servers", "parameters", "summary", "description"].includes(method)) { return false; } const pathItem = callbackPath; const example = getResponseExamples(pathItem[method], definition); if (!example.length) return false; return { identifier, expression, method, example }; }); }); return items.flat().filter((item) => item !== false); }); return examples.flat(); } // src/operation/lib/get-example-groups.ts var noCorrespondingResponseKey = "NoCorrespondingResponseForCustomCodeSample"; function addMatchingResponseExamples(groups, operation) { operation.getResponseExamples().forEach((example) => { Object.entries(example.mediaTypes || {}).forEach(([mediaType, mediaTypeExamples]) => { mediaTypeExamples.forEach((mediaTypeExample) => { if (mediaTypeExample.title && Object.keys(groups).includes(mediaTypeExample.title)) { groups[mediaTypeExample.title].response = { mediaType, mediaTypeExample, status: example.status }; if (!groups[mediaTypeExample.title].name) { groups[mediaTypeExample.title].name = mediaTypeExample.summary || mediaTypeExample.title; } } }); }); }); } function getDefaultName(sample, count) { return sample.name && sample.name.length > 0 ? sample.name : `Default${count[sample.language] > 1 ? ` #${count[sample.language]}` : ""}`; } function getExampleGroups(operation) { const namelessCodeSampleCounts = {}; const groups = {}; const codeSamples = _chunkAYA3UT4Lcjs.getExtension.call(void 0, "code-samples", operation.api, operation); _optionalChain([codeSamples, 'optionalAccess', _19 => _19.forEach, 'call', _20 => _20((sample, i) => { if (namelessCodeSampleCounts[sample.language]) { namelessCodeSampleCounts[sample.language] += 1; } else { namelessCodeSampleCounts[sample.language] = 1; } const name = getDefaultName(sample, namelessCodeSampleCounts); if (sample.correspondingExample) { if (_optionalChain([groups, 'access', _21 => _21[sample.correspondingExample], 'optionalAccess', _22 => _22.customCodeSamples, 'optionalAccess', _23 => _23.length])) { groups[sample.correspondingExample].customCodeSamples.push({ ...sample, name, originalIndex: i }); } else if (sample.correspondingExample) { groups[sample.correspondingExample] = { name, customCodeSamples: [{ ...sample, name, originalIndex: i }] }; } } else if (_optionalChain([groups, 'access', _24 => _24[noCorrespondingResponseKey], 'optionalAccess', _25 => _25.customCodeSamples, 'optionalAccess', _26 => _26.length])) { groups[noCorrespondingResponseKey].customCodeSamples.push({ ...sample, name, originalIndex: i }); } else { groups[noCorrespondingResponseKey] = { name, customCodeSamples: [{ ...sample, name, originalIndex: i }] }; } })]); if (Object.keys(groups).length) { addMatchingResponseExamples(groups, operation); return groups; } operation.getParameters().forEach((param) => { Object.entries(param.examples || {}).forEach(([exampleKey, paramExample]) => { let example = paramExample; if (_chunk3MTU2ESPcjs.isRef.call(void 0, example)) { example = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, example, operation.api); if (!example || _chunk3MTU2ESPcjs.isRef.call(void 0, example)) return; } groups[exampleKey] = { ...groups[exampleKey], name: _optionalChain([groups, 'access', _27 => _27[exampleKey], 'optionalAccess', _28 => _28.name]) || example.summary || exampleKey, request: { ..._optionalChain([groups, 'access', _29 => _29[exampleKey], 'optionalAccess', _30 => _30.request]), [param.in]: { ..._optionalChain([groups, 'access', _31 => _31[exampleKey], 'optionalAccess', _32 => _32.request, 'optionalAccess', _33 => _33[param.in]]), [param.name]: example.value } } }; }); }); operation.getRequestBodyExamples().forEach((requestExample) => { requestExample.examples.forEach((mediaTypeExample) => { if (mediaTypeExample.title) { const mediaType = requestExample.mediaType === "application/x-www-form-urlencoded" ? "formData" : "body"; groups[mediaTypeExample.title] = { ...groups[mediaTypeExample.title], name: _optionalChain([groups, 'access', _34 => _34[mediaTypeExample.title], 'optionalAccess', _35 => _35.name]) || mediaTypeExample.summary || mediaTypeExample.title, request: { ..._optionalChain([groups, 'access', _36 => _36[mediaTypeExample.title], 'optionalAccess', _37 => _37.request]), [mediaType]: mediaTypeExample.value } }; } }); }); if (Object.keys(groups).length) { addMatchingResponseExamples(groups, operation); } Object.entries(groups).forEach(([groupId, group]) => { if (group.request && !group.response) { delete groups[groupId]; } }); return groups; } // src/operation/lib/get-requestbody-examples.ts function getRequestBodyExamples(operation, definition) { let requestBody = operation.requestBody; if (!requestBody) { return []; } else if (_chunk3MTU2ESPcjs.isRef.call(void 0, requestBody)) { requestBody = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, requestBody, definition); } if (!requestBody || _chunk3MTU2ESPcjs.isRef.call(void 0, requestBody) || !requestBody.content) { return []; } return Object.keys(requestBody.content || {}).map((mediaType) => { const mediaTypeObject = requestBody.content[mediaType]; const examples = getMediaTypeExamples(mediaType, mediaTypeObject, definition, { includeReadOnly: false, includeWriteOnly: true }); if (!examples.length) { return false; } return { mediaType, examples }; }).filter((item) => item !== false); } // src/operation/lib/operationId.ts function hasOperationId(operation) { return Boolean("operationId" in operation && _optionalChain([operation, 'access', _38 => _38.operationId, 'optionalAccess', _39 => _39.length])); } function getOperationId(path, method, operation, opts = {}) { function sanitize(id) { return id.replace(_optionalChain([opts, 'optionalAccess', _40 => _40.camelCase]) || _optionalChain([opts, 'optionalAccess', _41 => _41.friendlyCase]) ? /[^a-zA-Z0-9_]/g : /[^a-zA-Z0-9]/g, "-").replace(/--+/g, "-").replace(/^-|-$/g, ""); } const operationIdExists = hasOperationId(operation); let operationId; if (operationIdExists) { operationId = operation.operationId; } else { operationId = sanitize(path).toLowerCase(); } const currMethod = method.toLowerCase(); if (_optionalChain([opts, 'optionalAccess', _42 => _42.camelCase]) || _optionalChain([opts, 'optionalAccess', _43 => _43.friendlyCase])) { if (_optionalChain([opts, 'optionalAccess', _44 => _44.friendlyCase])) { operationId = operationId.replaceAll("_", " "); if (!operationIdExists) { operationId = operationId.replace(/[^a-zA-Z0-9_]+(.)/g, (_, chr) => ` ${chr}`).split(" ").filter((word, i, arr) => word !== arr[i - 1]).join(" "); } } operationId = operationId.replace(/[^a-zA-Z0-9_]+(.)/g, (_, chr) => chr.toUpperCase()); if (operationIdExists) { operationId = sanitize(operationId); } operationId = operationId.replace(/^[0-9]/g, (match) => `_${match}`); operationId = operationId.charAt(0).toLowerCase() + operationId.slice(1); if (operationId.startsWith(currMethod)) { return operationId; } if (operationIdExists) { return operationId; } operationId = operationId.charAt(0).toUpperCase() + operationId.slice(1); return `${currMethod}${operationId}`; } else if (operationIdExists) { return operationId; } return `${currMethod}_${operationId}`; } // src/operation/transformers/get-response-as-json-schema.ts var isJSON = _chunk2X4PY2BScjs.matches_mimetype_default.json; function buildHeadersSchema(response, schemaOptions) { const headersSchema = { type: "object", properties: {} }; const api = schemaOptions.definition; const seenRefs = _nullishCoalesce(schemaOptions.seenRefs, () => ( /* @__PURE__ */ new Set())); if (response.headers) { Object.keys(response.headers).forEach((key) => { let headerEntry = _optionalChain([response, 'access', _45 => _45.headers, 'optionalAccess', _46 => _46[key]]); if (!headerEntry) return; if (_chunk3MTU2ESPcjs.isRef.call(void 0, headerEntry)) { headerEntry = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, headerEntry, api, seenRefs); if (!headerEntry || _chunk3MTU2ESPcjs.isRef.call(void 0, headerEntry)) return; } if (headerEntry.schema) { const header = headerEntry; let headerSchema = header.schema; if (!headerSchema) return; if (_chunk3MTU2ESPcjs.isRef.call(void 0, headerSchema)) { headerSchema = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, headerSchema, api, seenRefs); if (!headerSchema || _chunk3MTU2ESPcjs.isRef.call(void 0, headerSchema)) return; } headersSchema.properties[key] = _chunk2X4PY2BScjs.toJSONSchema.call(void 0, _chunk2X4PY2BScjs.cloneObject.call(void 0, headerSchema), { addEnumsToDescriptions: true, ...schemaOptions }); if (header.description) { headersSchema.properties[key].description = header.description; } } }); } const headersWrapper = { schema: headersSchema, type: "object", label: "Headers" }; if (response.description && headersWrapper.schema) { headersWrapper.description = response.description; } return headersWrapper; } function getResponseAsJSONSchema(operation, api, statusCode, opts) { const response = operation.getResponseByStatusCode(statusCode); const jsonSchema = []; if (!response) { return null; } const usedSchemas = /* @__PURE__ */ new Map(); const seenRefs = /* @__PURE__ */ new Set(); const refsByGroup = /* @__PURE__ */ new Map(); function refLoggerForSchemaGroup(group) { let set = refsByGroup.get(group); if (!set) { set = /* @__PURE__ */ new Set(); refsByGroup.set(group, set); } return set; } const baseSchemaOptions = { addEnumsToDescriptions: true, definition: api, seenRefs, usedSchemas, refLogger: (ref) => refLoggerForSchemaGroup("body").add(ref) }; function getPreferredSchema(content, preferredContentType) { if (!content) { return null; } const contentTypes = Object.keys(content); if (!contentTypes.length) { return null; } if (preferredContentType) { if (contentTypes.includes(preferredContentType)) { const schema2 = _chunk2X4PY2BScjs.cloneObject.call(void 0, content[preferredContentType].schema); if (!schema2) { return null; } return _chunk2X4PY2BScjs.toJSONSchema.call(void 0, schema2, baseSchemaOptions); } return null; } for (let i = 0; i < contentTypes.length; i++) { if (isJSON(contentTypes[i])) { const schema2 = _chunk2X4PY2BScjs.cloneObject.call(void 0, content[contentTypes[i]].schema); if (!schema2) { return {}; } return _chunk2X4PY2BScjs.toJSONSchema.call(void 0, schema2, baseSchemaOptions); } } const contentType = contentTypes.shift(); if (!contentType) { return {}; } const schema = _chunk2X4PY2BScjs.cloneObject.call(void 0, content[contentType].schema); if (!schema) { return {}; } return _chunk2X4PY2BScjs.toJSONSchema.call(void 0, schema, baseSchemaOptions); } const foundSchema = getPreferredSchema(response.content, _optionalChain([opts, 'optionalAccess', _47 => _47.contentType])); if (_optionalChain([opts, 'optionalAccess', _48 => _48.contentType]) && !foundSchema) { return null; } if (foundSchema) { const schema = structuredClone(foundSchema); let schemaType = foundSchema.type; if (schemaType === void 0 && _chunk3MTU2ESPcjs.isRef.call(void 0, foundSchema) && usedSchemas.size > 0) { const resolvedSchema = usedSchemas.get(foundSchema.$ref); const resolvedType = resolvedSchema && typeof resolvedSchema === "object" && "type" in resolvedSchema ? resolvedSchema.type : void 0; schemaType = Array.isArray(resolvedType) ? resolvedType[0] : resolvedType; } const schemaWrapper = { // If there's no `type` then the root schema is a circular `$ref` that we likely won't be // able to render so instead of generating a JSON Schema with an `undefined` type we should // default to `string` so there's at least *something* the end-user can interact with. type: _nullishCoalesce(schemaType, () => ( "string")), schema: _chunk2X4PY2BScjs.isPrimitive.call(void 0, schema) ? schema : { ...schema, $schema: _chunk2X4PY2BScjs.getSchemaVersionString.call(void 0, schema, api) }, label: "Response body" }; if (response.description && schemaWrapper.schema) { schemaWrapper.description = response.description; } _chunk2X4PY2BScjs.applyDiscriminatorOneOfToUsedSchemas.call(void 0, api, usedSchemas, (ref) => { if (usedSchemas.has(ref)) { return usedSchemas.get(ref); } try { const resolved = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, { $ref: ref }, api, seenRefs); if (_chunk3MTU2ESPcjs.isRef.call(void 0, resolved)) return; const converted = _chunk2X4PY2BScjs.toJSONSchema.call(void 0, structuredClone(resolved), { ...baseSchemaOptions, seenRefs }); usedSchemas.set(ref, converted); return converted; } catch (e2) { } }); if (schemaWrapper.schema && usedSchemas.size > 0) { const refsInOutput = _chunk2X4PY2BScjs.collectRefsInSchema.call(void 0, schemaWrapper.schema); const refsInGroup = _nullishCoalesce(refsByGroup.get("body"), () => ( /* @__PURE__ */ new Set())); const referencedSchemas = _chunk2X4PY2BScjs.filterRequiredRefsToReferenced.call(void 0, /* @__PURE__ */ new Set([...refsInGroup, ...refsInOutput]), usedSchemas); if (referencedSchemas.size > 0) { _chunk2X4PY2BScjs.mergeReferencedSchemasIntoRoot.call(void 0, schemaWrapper.schema, referencedSchemas); } } jsonSchema.push(schemaWrapper); } if (response.headers) { const headersWrapper = buildHeadersSchema(response, { ...baseSchemaOptions, refLogger: (ref) => refLoggerForSchemaGroup("headers").add(ref) }); if (headersWrapper.schema && usedSchemas.size > 0) { const refsInGroup = _nullishCoalesce(refsByGroup.get("headers"), () => ( /* @__PURE__ */ new Set())); const refsInOutput = _chunk2X4PY2BScjs.collectRefsInSchema.call(void 0, headersWrapper.schema); const referencedSchemas = _chunk2X4PY2BScjs.filterRequiredRefsToReferenced.call(void 0, /* @__PURE__ */ new Set([...refsInGroup, ...refsInOutput]), usedSchemas); if (referencedSchemas.size > 0) { _chunk2X4PY2BScjs.mergeReferencedSchemasIntoRoot.call(void 0, headersWrapper.schema, referencedSchemas); } } jsonSchema.push(headersWrapper); } return jsonSchema.length ? jsonSchema : null; } // src/operation/index.ts var Operation = (_class = class { /** * The `Oas` instance that this operation belongs to. */ /** * Schema of the operation from the API Definition. */ /** * OpenAPI API Definition that this operation originated from. */ /** * Path that this operation is targeted towards. */ /** * HTTP Method that this operation is targeted towards. */ /** * The primary Content Type that this operation accepts. */ /** * An object with groups of all example definitions (body/header/query/path/response/etc.) */ /** * Request body examples for this operation. */ /** * Response examples for this operation. */ /** * Callback examples for this operation (if it has callbacks). */ /** * Flattened out arrays of both request and response headers that are utilized on this operation. */ /** * Internal storage array that the library utilizes to keep track of the times the * {@see Operation.dereference} has been called so that if you initiate multiple promises they'll * all end up returning the same data set once the initial dereference call completed. */ /** * Internal storage array that the library utilizes to keep track of its `dereferencing` state so * it doesn't initiate multiple dereferencing processes. */ /** * Have the component schemas within this API definition been decorated with our * `x-readme-ref-name` extension? * * @see {@link decorateComponentSchemas} */ __init() {this.schemasDecorated = false} constructor(oas, path, method, operation) {;_class.prototype.__init.call(this); this.oas = oas; this.schema = operation; this.api = oas.api; this.path = path; this.method = method; this.contentType = void 0; this.requestBodyExamples = void 0; this.responseExamples = void 0; this.callbackExamples = void 0; this.exampleGroups = void 0; this.headers = { request: [], response: [] }; this.promises = []; this.dereferencing = { processing: false, complete: false, circularRefs: [] }; } /** * Retrieve the `summary` for this operation. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-operationsummary} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-operation-summary} */ getSummary() { if (_optionalChain([this, 'access', _49 => _49.schema, 'optionalAccess', _50 => _50.summary]) && typeof this.schema.summary === "string") { return this.schema.summary; } const pathItem = _optionalChain([this, 'access', _51 => _51.api, 'access', _52 => _52.paths, 'optionalAccess', _53 => _53[this.path]]); if (_optionalChain([pathItem, 'optionalAccess', _54 => _54.summary]) && typeof pathItem.summary === "string") { return pathItem.summary; } return void 0; } /** * Retrieve the `description` for this operation. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-operationdescription} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-operation-description} */ getDescription() { if (_optionalChain([this, 'access', _55 => _55.schema, 'optionalAccess', _56 => _56.description]) && typeof this.schema.description === "string") { return this.schema.description; } const pathItem = _optionalChain([this, 'access', _57 => _57.api, 'access', _58 => _58.paths, 'optionalAccess', _59 => _59[this.path]]); if (_optionalChain([pathItem, 'optionalAccess', _60 => _60.description]) && typeof pathItem.description === "string") { return pathItem.description; } return void 0; } /** * Retrieve the primary content type for this operation. If multiple exist, the first JSON-like * type will be returned. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-requestbodycontent} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-request-body-content} */ getContentType() { if (this.contentType) { return this.contentType; } let types = []; if (this.schema.requestBody) { if (_chunk3MTU2ESPcjs.isRef.call(void 0, this.schema.requestBody)) { this.schema.requestBody = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, this.schema.requestBody, this.api); } if (this.schema.requestBody && "content" in this.schema.requestBody) { types = Object.keys(this.schema.requestBody.content); } } this.contentType = "application/json"; if (_optionalChain([types, 'optionalAccess', _61 => _61.length])) { this.contentType = types[0]; } types.forEach((t) => { if (_chunk2X4PY2BScjs.matches_mimetype_default.json(t)) { this.contentType = t; } }); return this.contentType; } /** * Checks if the current operation has a `x-www-form-urlencoded` content type payload. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-requestbodycontent} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-request-body-content} */ isFormUrlEncoded() { return _chunk2X4PY2BScjs.matches_mimetype_default.formUrlEncoded(this.getContentType()); } /** * Checks if the current operation has a mutipart content type payload. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-requestbodycontent} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-request-body-content} */ isMultipart() { return _chunk2X4PY2BScjs.matches_mimetype_default.multipart(this.getContentType()); } /** * Checks if the current operation has a JSON-like content type payload. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-requestbodycontent} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-request-body-content} */ isJson() { return _chunk2X4PY2BScjs.matches_mimetype_default.json(this.getContentType()); } /** * Checks if the current operation has an XML content type payload. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-requestbodycontent} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-request-body-content} */ isXml() { return _chunk2X4PY2BScjs.matches_mimetype_default.xml(this.getContentType()); } /** * Checks if the current operation is a webhook or not. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#oas-webhooks} */ isWebhook() { return this instanceof Webhook; } /** * Returns an array of all security requirements associated wtih this operation. If none are * defined at the operation level, the securities for the entire API definition are returned * (with an empty array as a final fallback). * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#security-requirement-object} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#security-requirement-object} */ getSecurity() { if (!_optionalChain([this, 'access', _62 => _62.api, 'optionalAccess', _63 => _63.components, 'optionalAccess', _64 => _64.securitySchemes]) || !Object.keys(this.api.components.securitySchemes).length) { return []; } return this.schema.security || this.api.security || []; } /** * Retrieve a collection of grouped security schemes. The inner array determines AND-grouped * security schemes, the outer array determines OR-groups. * * @see {@link https://swagger.io/docs/specification/authentication/#multiple} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#security-requirement-object} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#security-requirement-object} * @param filterInvalid Optional flag that, when set to `true`, filters out invalid/nonexistent * security schemes, rather than returning `false`. */ getSecurityWithTypes(filterInvalid = false) { return this.getSecurity().map((requirement) => { let keys; try { keys = Object.keys(requirement); } catch (e3) { return false; } const keysWithTypes = keys.map((key) => { let security; try { security = _optionalChain([this, 'access', _65 => _65.api, 'optionalAccess', _66 => _66.components, 'optionalAccess', _67 => _67.securitySchemes, 'optionalAccess', _68 => _68[key]]); if (!security) return false; if (_chunk3MTU2ESPcjs.isRef.call(void 0, security)) { security = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, security, this.api); if (!security || _chunk3MTU2ESPcjs.isRef.call(void 0, security)) return false; } } catch (e4) { return false; } if (!security || _chunk3MTU2ESPcjs.isRef.call(void 0, security)) return false; let type = null; if (security.type === "http") { if (security.scheme === "basic") type = "Basic"; else if (security.scheme === "bearer") type = "Bearer"; else type = security.type; } else if (security.type === "oauth2") { type = "OAuth2"; } else if (security.type === "apiKey") { if (security.in === "query") type = "Query"; else if (security.in === "header") type = "Header"; else if (security.in === "cookie") type = "Cookie"; else type = security.type; } else { return false; } return { type, security: { ...security, _key: key, _requirements: requirement[key] } }; }); if (filterInvalid) return keysWithTypes.filter((key) => key !== false); return keysWithTypes; }); } /** * Retrieve an object where the keys are unique scheme types, and the values are arrays * containing each security scheme of that type. * */ prepareSecurity() { return this.getSecurityWithTypes().reduce( (prev, securities) => { if (!securities) return prev; securities.forEach((security) => { if (!security) return; if (!prev[security.type]) prev[security.type] = []; const exists = prev[security.type].some((sec) => sec._key === security.security._key); if (!exists) { if (_optionalChain([security, 'access', _69 => _69.security, 'optionalAccess', _70 => _70._requirements])) delete security.security._requirements; prev[security.type].push(security.security); } }); return prev; }, {} ); } /** * Retrieve all of the headers, request and response, that are associated with this operation. * */ getHeaders() { const security = this.prepareSecurity(); if (security.Header) { this.headers.request = security.Header.map((h) => { if (!("name" in h)) return false; return h.name; }).filter((item) => item !== false); } if (security.Bearer || security.Basic || security.OAuth2) { this.headers.request.push("Authorization"); } if (security.Cookie) { this.headers.request.push("Cookie"); } if (this.schema.parameters) { this.headers.request = this.headers.request.concat( this.schema.parameters.map((p) => { let param = p; if (_chunk3MTU2ESPcjs.isRef.call(void 0, param)) { param = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, param, this.api); if (!param || _chunk3MTU2ESPcjs.isRef.call(void 0, param)) return; } if (param.in && param.in === "header") return param.name; return; }).filter((item) => item !== void 0) ); } if (this.schema.responses) { this.headers.response = Object.keys(this.schema.responses).map((r) => { let response = this.schema.responses[r]; if (!response) return []; if (_chunk3MTU2ESPcjs.isRef.call(void 0, response)) { this.schema.responses[r] = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, response, this.api); response = this.schema.responses[r]; if (!response || _chunk3MTU2ESPcjs.isRef.call(void 0, response)) { return []; } } return _optionalChain([response, 'optionalAccess', _71 => _71.headers]) ? Object.keys(response.headers) : []; }).reduce((a, b) => a.concat(b), []); } if (!this.headers.request.includes("Content-Type") && this.schema.requestBody) { let requestBody = this.schema.requestBody; if (requestBody) { if (_chunk3MTU2ESPcjs.isRef.call(void 0, requestBody)) { this.schema.requestBody = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, requestBody, this.api); requestBody = this.schema.requestBody; } if (requestBody && !_chunk3MTU2ESPcjs.isRef.call(void 0, requestBody) && "content" in requestBody && Object.keys(requestBody.content)) { this.headers.request.push("Content-Type"); } } } if (this.schema.responses) { const hasResponseContent = Object.keys(this.schema.responses).some((r) => { let response = _optionalChain([this, 'access', _72 => _72.schema, 'access', _73 => _73.responses, 'optionalAccess', _74 => _74[r]]); if (!response) return false; if (_chunk3MTU2ESPcjs.isRef.call(void 0, response)) { this.schema.responses[r] = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, response, this.api); response = this.schema.responses[r]; if (!response || _chunk3MTU2ESPcjs.isRef.call(void 0, response)) { return false; } } return response.content && Object.keys(response.content).length > 0; }); if (hasResponseContent) { if (!this.headers.request.includes("Accept")) this.headers.request.push("Accept"); if (!this.headers.response.includes("Content-Type")) this.headers.response.push("Content-Type"); } } return this.headers; } /** * Determine if this operation has an `operationId` present in its schema. Note that if one is * present in the schema but is an empty string then this will return `false`. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-operationid} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-operation-id} */ hasOperationId() { return hasOperationId(this.schema); } /** * Determine if an operation has an `operationId` present in its schema. Note that if one is * present in the schema but is an empty string then this will return `false`. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-operationid} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-operation-id} */ static hasOperationId(schema) { return hasOperationId(schema); } /** * Get an `operationId` for this operation. If one is not present (it's not required by the spec!) * a hash of the path and method will be returned instead. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-operationid} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-operation-id} */ getOperationId(opts = {}) { return getOperationId(this.path, this.method, this.schema, opts); } /** * Get an `operationId` for an operation. If one is not present (it's not required by the spec!) * a hash of the path and method will be returned instead. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-operationid} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-operation-id} */ static getOperationId(path, method, schema, opts = {}) { return getOperationId(path, method, schema, opts); } /** * Return an array of all tags, and their metadata, that exist on this operation. * */ getTags() { if (!("tags" in this.schema)) { return []; } const oasTagMap = /* @__PURE__ */ new Map(); if (Array.isArray(_optionalChain([this, 'access', _75 => _75.api, 'optionalAccess', _76 => _76.tags]))) { this.api.tags.forEach((tag) => { oasTagMap.set(tag.name, tag); }); } const oasTags = Object.fromEntries(oasTagMap); const tags = []; if (Array.isArray(this.schema.tags)) { this.schema.tags.forEach((tag) => { if (tag in oasTags) { tags.push(oasTags[tag]); } else { tags.push({ name: tag }); } }); } return tags; } /** * Return is the operation is flagged as `deprecated` or not. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-operationdeprecated} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-operation-deprecated} */ isDeprecated() { return Boolean("deprecated" in this.schema ? this.schema.deprecated : false); } /** * Determine if the operation has any (non-request body) parameters. * */ hasParameters() { return !!this.getParameters().length; } /** * Return the parameters (non-request body) on the operation. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-operationparameters} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-operation-parameters} */ getParameters() { let parameters = (_optionalChain([this, 'access', _77 => _77.schema, 'optionalAccess', _78 => _78.parameters]) || []).map((p) => { let param = p; if (_chunk3MTU2ESPcjs.isRef.call(void 0, param)) { param = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, param, this.api); if (!param || _chunk3MTU2ESPcjs.isRef.call(void 0, param)) return; } return param; }).filter((param) => param !== void 0); const commonParams = (_optionalChain([this, 'access', _79 => _79.api, 'optionalAccess', _80 => _80.paths, 'optionalAccess', _81 => _81[this.path], 'optionalAccess', _82 => _82.parameters]) || []).map((p) => { let param = p; if (_chunk3MTU2ESPcjs.isRef.call(void 0, param)) { param = _chunk2X4PY2BScjs.dereferenceRef.call(void 0, param, this.api); if (!param || _chunk3MTU2ESPcjs.isRef.call(void 0, param)) return; } return param; }).filter((param) => param !== void 0); if (commonParams.length) { parameters = parameters.concat(dedupeCommonParameters(parameters, commonParams) || []); } return parameters; } /** * Determine if this operation has any required parameters. * * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#user-content-operationparameters} * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.2.md#user-content-operation-parameters} */ hasRequiredParameters() { return this.getParameters().some((param) => "required" in param && param.required); } /** * Convert the operation into an array of JSON Schema schemas for each available type of * parameter available on the operation. * * Note that this method is not compatible with an operation or OpenAPI definition that has been * processed with `.dereference()`. This method can only be called with the _original_ API * definition that was used to initialize the `Operation` and `Oas` instance. If a dereferenced * schema is present when this is