UNPKG

@scalar/oas-utils

Version:

Open API spec and Yaml handling utilities

231 lines (230 loc) 9.74 kB
const MAX_LEVELS_DEEP = 5; const MAX_PROPERTIES = 10; const DEFAULT_ADDITIONAL_PROPERTIES_NAME = "propertyName*"; const genericExampleValues = { // 'date-time': '1970-01-01T00:00:00Z', "date-time": (/* @__PURE__ */ new Date()).toISOString(), // 'date': '1970-01-01', "date": (/* @__PURE__ */ new Date()).toISOString().split("T")[0], "email": "hello@example.com", "hostname": "example.com", // https://tools.ietf.org/html/rfc6531#section-3.3 "idn-email": "jane.doe@example.com", // https://tools.ietf.org/html/rfc5890#section-2.3.2.3 "idn-hostname": "example.com", "ipv4": "127.0.0.1", "ipv6": "51d4:7fab:bfbf:b7d7:b2cb:d4b4:3dad:d998", "iri-reference": "/entitiy/1", // https://tools.ietf.org/html/rfc3987 "iri": "https://example.com/entity/123", "json-pointer": "/nested/objects", "password": "super-secret", "regex": "/[a-z]/", // https://tools.ietf.org/html/draft-handrews-relative-json-pointer-01 "relative-json-pointer": "1/nested/objects", // full-time in https://tools.ietf.org/html/rfc3339#section-5.6 // 'time': '00:00:00Z', "time": (/* @__PURE__ */ new Date()).toISOString().split("T")[1].split(".")[0], // either a URI or relative-reference https://tools.ietf.org/html/rfc3986#section-4.1 "uri-reference": "../folder", "uri-template": "https://example.com/{id}", "uri": "https://example.com", "uuid": "123e4567-e89b-12d3-a456-426614174000", "object-id": "6592008029c8c3e4dc76256c" }; function guessFromFormat(schema, makeUpRandomData = false, fallback = "") { if (schema.format === "binary") { return new File([""], "filename"); } return makeUpRandomData ? genericExampleValues[schema.format] ?? fallback : ""; } const resultCache = /* @__PURE__ */ new WeakMap(); function cache(schema, result) { if (typeof result !== "object" || result === null) { return result; } resultCache.set(schema, result); return result; } const getExampleFromSchema = (schema, options, level = 0, parentSchema, name) => { if (resultCache.has(schema)) { return resultCache.get(schema); } if (level === MAX_LEVELS_DEEP + 1) { try { JSON.stringify(schema); } catch { return "[Circular Reference]"; } } const makeUpRandomData = !!options?.emptyString; if (schema.deprecated) { return void 0; } if (options?.mode === "write" && schema.readOnly || options?.mode === "read" && schema.writeOnly) { return void 0; } if (schema["x-variable"]) { const value = options?.variables?.[schema["x-variable"]]; if (value !== void 0) { if (schema.type === "number" || schema.type === "integer") { return Number.parseInt(value, 10); } return cache(schema, value); } } if (Array.isArray(schema.examples) && schema.examples.length > 0) { return cache(schema, schema.examples[0]); } if (schema.example !== void 0) { return cache(schema, schema.example); } if (schema.default !== void 0) { return cache(schema, schema.default); } if (Array.isArray(schema.enum) && schema.enum.length > 0) { return cache(schema, schema.enum[0]); } const isObjectOrArray = schema.type === "object" || schema.type === "array" || !!schema.allOf?.at?.(0) || !!schema.anyOf?.at?.(0) || !!schema.oneOf?.at?.(0); if (!isObjectOrArray && options?.omitEmptyAndOptionalProperties === true) { const isRequired = schema.required === true || parentSchema?.required === true || parentSchema?.required?.includes(name ?? schema.name); if (!isRequired) { return void 0; } } if (schema.type === "object" || schema.properties !== void 0) { const response = {}; let propertyCount = 0; if (schema.properties !== void 0) { for (const propertyName in schema.properties) { if (Object.prototype.hasOwnProperty.call(schema.properties, propertyName)) { if (level > 3 && propertyCount >= MAX_PROPERTIES) { response["..."] = "[Additional Properties Truncated]"; break; } const property = schema.properties[propertyName]; const propertyXmlTagName = options?.xml ? property.xml?.name : void 0; const value = getExampleFromSchema(property, options, level + 1, schema, propertyName); if (typeof value !== "undefined") { response[propertyXmlTagName ?? propertyName] = value; propertyCount++; } } } } if (schema.patternProperties !== void 0) { for (const pattern in schema.patternProperties) { if (Object.prototype.hasOwnProperty.call(schema.patternProperties, pattern)) { const property = schema.patternProperties[pattern]; const exampleKey = pattern; response[exampleKey] = getExampleFromSchema(property, options, level + 1, schema, exampleKey); } } } if (schema.additionalProperties !== void 0) { const anyTypeIsValid = ( // true schema.additionalProperties === true || // or an empty object {} typeof schema.additionalProperties === "object" && !Object.keys(schema.additionalProperties).length ); const additionalPropertiesName = typeof schema.additionalProperties === "object" && schema.additionalProperties["x-additionalPropertiesName"] && typeof schema.additionalProperties["x-additionalPropertiesName"] === "string" && schema.additionalProperties["x-additionalPropertiesName"].trim().length > 0 ? `${schema.additionalProperties["x-additionalPropertiesName"].trim()}*` : DEFAULT_ADDITIONAL_PROPERTIES_NAME; if (anyTypeIsValid) { response[additionalPropertiesName] = "anything"; } else if (schema.additionalProperties !== false) { response[additionalPropertiesName] = getExampleFromSchema(schema.additionalProperties, options, level + 1); } } if (schema.anyOf !== void 0) { Object.assign(response, getExampleFromSchema(schema.anyOf[0], options, level + 1)); } else if (schema.oneOf !== void 0) { Object.assign(response, getExampleFromSchema(schema.oneOf[0], options, level + 1)); } else if (schema.allOf !== void 0) { Object.assign( response, ...schema.allOf.map((item) => getExampleFromSchema(item, options, level + 1, schema)).filter((item) => item !== void 0) ); } return cache(schema, response); } if (schema.type === "array" || schema.items !== void 0) { const itemsXmlTagName = schema?.items?.xml?.name; const wrapItems = !!(options?.xml && schema.xml?.wrapped && itemsXmlTagName); if (schema.example !== void 0) { return cache(schema, wrapItems ? { [itemsXmlTagName]: schema.example } : schema.example); } if (schema.items) { if (schema.items.allOf) { if (schema.items.allOf[0].type === "object") { const mergedExample = getExampleFromSchema( { type: "object", allOf: schema.items.allOf }, options, level + 1, schema ); return cache(schema, wrapItems ? [{ [itemsXmlTagName]: mergedExample }] : [mergedExample]); } const examples = schema.items.allOf.map((item) => getExampleFromSchema(item, options, level + 1, schema)).filter((item) => item !== void 0); return cache(schema, wrapItems ? examples.map((example) => ({ [itemsXmlTagName]: example })) : examples); } const rules = ["anyOf", "oneOf"]; for (const rule of rules) { if (!schema.items[rule]) { continue; } const schemas = schema.items[rule].slice(0, 1); const exampleFromRule = schemas.map((item) => getExampleFromSchema(item, options, level + 1, schema)).filter((item) => item !== void 0); return cache(schema, wrapItems ? [{ [itemsXmlTagName]: exampleFromRule }] : exampleFromRule); } } const isObject = schema.items?.type === "object" || schema.items?.properties !== void 0; const isArray = schema.items?.type === "array" || schema.items?.items !== void 0; if (schema.items?.type || isObject || isArray) { const exampleFromSchema = getExampleFromSchema(schema.items, options, level + 1); return wrapItems ? [{ [itemsXmlTagName]: exampleFromSchema }] : [exampleFromSchema]; } return []; } const exampleValues = { string: guessFromFormat(schema, makeUpRandomData, options?.emptyString), boolean: true, integer: schema.min ?? 1, number: schema.min ?? 1, array: [] }; if (schema.type !== void 0 && exampleValues[schema.type] !== void 0) { return cache(schema, exampleValues[schema.type]); } const discriminateSchema = schema.oneOf || schema.anyOf; if (Array.isArray(discriminateSchema) && discriminateSchema.length > 0) { const firstNonNullItem = discriminateSchema.find((item) => item.type !== "null"); if (firstNonNullItem) { return getExampleFromSchema(firstNonNullItem, options, level + 1); } return null; } if (Array.isArray(schema.allOf)) { let example = null; schema.allOf.forEach((allOfItem) => { const newExample = getExampleFromSchema(allOfItem, options, level + 1); example = typeof newExample === "object" && typeof example === "object" ? { ...example ?? {}, ...newExample } : Array.isArray(newExample) && Array.isArray(example) ? [...example ?? {}, ...newExample] : newExample; }); return cache(schema, example); } if (Array.isArray(schema.type)) { if (schema.type.includes("null")) { return null; } const exampleValue = exampleValues[schema.type[0]]; if (exampleValue !== void 0) { return cache(schema, exampleValue); } } return null; }; export { getExampleFromSchema }; //# sourceMappingURL=get-example-from-schema.js.map