oas
Version:
Comprehensive tooling for working with OpenAPI definitions
1,262 lines (1,216 loc) • 76.1 kB
JavaScript
"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