UNPKG

@alova/wormhole

Version:

More modern openAPI generating solution for alova.js

196 lines (195 loc) 6.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.applyModifierSchema = applyModifierSchema; // Convert Schema (custom spec) -> OpenAPI SchemaObject function toSchemaObject(base, s) { const result = { ...base }; const cleanType = (schema) => { delete schema.type; delete schema.enum; delete schema.oneOf; delete schema.anyOf; delete schema.allOf; delete schema.items; delete schema.properties; delete schema.required; return schema; }; // Legacy union as array (treated as oneOf) if (Array.isArray(s)) { const baseOneOf = base.oneOf || []; cleanType(result); result.oneOf = s.map((item, idx) => toSchemaObject(baseOneOf[idx] || {}, item)); return result; } // Primitive types and no-op primitives if (typeof s === 'string') { result.type = s; return result; } // Handle union keywords: overwrite arrays but preserve unrelated fields if (s.oneOf) { const spec = s; const baseOneOf = base.oneOf || []; cleanType(result); result.oneOf = spec.oneOf.map((item, idx) => toSchemaObject(baseOneOf[idx] || {}, item)); } if (s.anyOf) { const spec = s; const baseAnyOf = base.anyOf || []; cleanType(result); result.anyOf = spec.anyOf.map((item, idx) => toSchemaObject(baseAnyOf[idx] || {}, item)); } if (s.allOf) { const spec = s; const baseAllOf = base.allOf || []; cleanType(result); result.allOf = spec.allOf.map((item, idx) => toSchemaObject(baseAllOf[idx] || {}, item)); } // Enum: set enum and optional type if (s.enum) { const spec = s; result.enum = spec.enum; if (spec.type) { result.type = spec.type; } } // Array: set/merge items if (s.type === 'array') { const spec = s; result.type = 'array'; const baseItems = result.items; if (Array.isArray(spec.items)) { // Tuple items: replace entire items with tuple const items = spec.items.map(item => toSchemaObject({}, item)); result.items = items; } else { // Single items: merge into existing items schema const patchItem = toSchemaObject(typeof baseItems === 'object' ? baseItems : {}, spec.items); result.items = patchItem; } return result; } // Object (reference-like map): merge properties and required const ref = s; if (ref && typeof ref === 'object') { result.type = 'object'; const properties = { ...result.properties }; const requiredSet = new Set(Array.isArray(result.required) ? result.required : []); for (const key in ref) { const val = ref[key]; if (!val) { continue; } const optional = key.endsWith('?'); const cleanKey = optional ? key.slice(0, -1) : key; const baseProp = properties[cleanKey]; properties[cleanKey] = toSchemaObject(baseProp || {}, val); if (optional) { requiredSet.delete(cleanKey); } else { requiredSet.add(cleanKey); } } result.properties = properties; result.required = Array.from(requiredSet); return result; } return result; } function schemaTypeToPrimitiveType(t) { if (t === null) { return 'null'; } if (t === undefined) { return 'undefined'; } if (!t) { return 'unknown'; } if (t === 'integer') { return 'number'; } return t; } // Convert existing OpenAPI SchemaObject -> Schema (best-effort, for handler input) function toSchemaSpec(obj) { if (!obj || typeof obj !== 'object') { return 'unknown'; } // Union keywords if (Array.isArray(obj.oneOf)) { const arr = obj.oneOf; return { oneOf: arr.map(item => toSchemaSpec(item)) }; } if (Array.isArray(obj.anyOf)) { const arr = obj.anyOf; return { anyOf: arr.map(item => toSchemaSpec(item)) }; } if (Array.isArray(obj.allOf)) { const arr = obj.allOf; return { allOf: arr.map(item => toSchemaSpec(item)) }; } // Enum if (Array.isArray(obj.enum) && obj.enum.length > 0) { const type = typeof obj.type === 'string' ? obj.type : undefined; return { enum: obj.enum, type }; } // Array if (obj.type === 'array' || obj.items) { const items = obj.items; if (Array.isArray(items)) { return { type: 'array', items: items.map((it) => toSchemaSpec(it)) }; } if (items) { return { type: 'array', items: toSchemaSpec(items) }; } return { type: 'array', items: 'unknown' }; } // Object if (obj.type === 'object' || obj.properties) { const properties = obj.properties || {}; const requiredSet = new Set(Array.isArray(obj.required) ? obj.required : []); const result = {}; for (const key of Object.keys(properties)) { const spec = toSchemaSpec(properties[key]); const finalKey = requiredSet.has(key) ? key : `${key}?`; result[finalKey] = spec; } return result; } // type union as array if (Array.isArray(obj.type)) { const typeArr = obj.type; const mapped = typeArr.map(schemaTypeToPrimitiveType); return { oneOf: mapped }; } return schemaTypeToPrimitiveType(obj.type); } // Replace whole schema based on handler result (used for params/pathParams) function applyModifierSchema(schema, config, { required }) { if (!schema || typeof schema !== 'object') { return schema; } const cloned = { ...schema }; const currentSpec = toSchemaSpec(cloned); const ret = config.handler(currentSpec); if (!ret) { return { required, value: null, }; } if (typeof ret === 'object' && 'required' in ret && 'value' in ret) { return { required: !!(ret.required ?? required), value: toSchemaObject(cloned, ret.value), }; } return { required, value: toSchemaObject(cloned, ret), }; }