UNPKG

@alova/wormhole

Version:

More modern openAPI generating solution for alova.js

201 lines (200 loc) 6.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.rename = rename; function toCamelCase(str) { return str.replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : '')).replace(/^(.)/, c => c.toLowerCase()); } function toCase(str) { return str .replace(/([a-z\d])([A-Z])/g, '$1_$2') .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1_$2') .replace(/[-\s]+/g, '_') .toLowerCase(); } function toKebabCase(str) { return str .replace(/([a-z\d])([A-Z])/g, '$1-$2') .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1-$2') .replace(/[_\s]+/g, '-') .toLowerCase(); } function toPascalCase(str) { return str.replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : '')).replace(/^(.)/, c => c.toUpperCase()); } /** * Tests if value matches the specified rule */ function isMatch(value, match) { if (!match) return true; if (typeof match === 'string') { return value.includes(match); } if (match instanceof RegExp) { return match.test(value); } if (typeof match === 'function') { return match(value); } return false; } /** * Applies renaming rules to the specified value * @returns The renamed value, or original value if not matched */ function applyRenameRule(value, config, apiDescriptor) { if (!isMatch(value, config.match)) { return value; } if (config.transform) { value = config.transform(apiDescriptor); } if (!config.style) { return value; } switch (config.style) { case 'camelCase': return toCamelCase(value); case 'snakeCase': return toCase(value); case 'kebabCase': return toKebabCase(value); case 'pascalCase': return toPascalCase(value); default: throw new Error(`Invalid rename style: ${config.style}`); } } /** * renames URL path by processing each segment individually * while keeping path parameter placeholders */ function renameUrl(url, config, apiDescriptor) { const segments = url.split('/'); return segments .map((segment) => { // Skip parameter placeholders and empty segments if ((segment.startsWith('{') && segment.endsWith('}')) || !segment) { return segment; } return applyRenameRule(segment, config, apiDescriptor); }) .join('/') .replace(/^\/{2,}/g, '/'); } /** * Transforms object properties using the renaming rules */ function transformProperties(obj, config, apiDescriptor) { if (!obj || typeof obj !== 'object' || !('properties' in obj)) { return obj; } const properties = { ...obj.properties }; const newProperties = {}; for (const key in properties) { const newKey = applyRenameRule(key, config, apiDescriptor); newProperties[newKey] = properties[key]; } return { ...obj, properties: newProperties, }; } /** * Transforms parameters of specific type using the renaming rules */ function transformParameters(parameters, type, config, apiDescriptor) { if (!parameters || !Array.isArray(parameters)) { return parameters; } return parameters.map((param) => { if (param.in === type) { return { ...param, name: applyRenameRule(param.name, config, apiDescriptor), }; } return param; }); } /** * Processes API descriptor based on renaming configuration * * Each scope targets different parts of the API descriptor: * - url: Renames URL path segments * - params: Renames query parameters * - pathParams: Renames path parameters and their placeholders in URL * - data: Renames request body properties * - response: Renames response body properties */ function renameApiDescriptor(apiDescriptor, config) { if (!apiDescriptor) return apiDescriptor; const newDescriptor = { ...apiDescriptor }; const scope = config.scope || 'url'; switch (scope) { case 'params': if (newDescriptor.parameters) { newDescriptor.parameters = transformParameters(newDescriptor.parameters, 'query', config, apiDescriptor); } break; case 'pathParams': if (newDescriptor.parameters) { newDescriptor.parameters = transformParameters(newDescriptor.parameters, 'path', config, apiDescriptor); } if (newDescriptor.url) { newDescriptor.url = newDescriptor.url.replace(/\{([^}]+)\}/g, (match, paramName) => { const newName = applyRenameRule(paramName, config, apiDescriptor); return `{${newName}}`; }); } break; case 'data': if (newDescriptor.requestBody) { newDescriptor.requestBody = transformProperties(newDescriptor.requestBody, config, apiDescriptor); } break; case 'response': if (newDescriptor.responses) { newDescriptor.responses = transformProperties(newDescriptor.responses, config, apiDescriptor); } break; case 'url': if (newDescriptor.url) { newDescriptor.url = renameUrl(newDescriptor.url, config, apiDescriptor); } break; default: // No action needed, keep original descriptor break; } return newDescriptor; } /** * Creates a rename plugin that transforms API descriptors * according to specified naming rules */ function rename(config) { const configs = Array.isArray(config) ? config : [config]; for (const conf of configs) { if (!conf.style && !conf.transform) { throw new Error('at least one of `style` or `transform` is required'); } } return { name: 'rename', extends: { handleApi: (apiDescriptor) => { if (!apiDescriptor) return null; // Apply each configuration in sequence return configs.reduce((desc, conf) => { if (!desc) return null; return renameApiDescriptor(desc, conf); }, apiDescriptor); }, }, }; } exports.default = rename;