UNPKG

api-client-generator

Version:

Angular REST API client generator from Swagger YAML or JSON file with camel case settings

422 lines 20.4 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.determineDomain = exports.createMustacheViewModel = void 0; var helper_1 = require("./helper"); function createMustacheViewModel(swagger, swaggerTag) { var methods = parseMethods(swagger, swaggerTag); var camelSwaggerTag = helper_1.toCamelCase(swaggerTag, false); return { isSecure: !!swagger.securityDefinitions, swagger: swagger, swaggerTag: swaggerTag, domain: determineDomain(swagger), methods: methods, definitions: parseDefinitions(swagger.definitions, swagger.parameters, swaggerTag ? methods : undefined), serviceName: camelSwaggerTag ? camelSwaggerTag + "APIClient" : 'APIClient', serviceFileName: helper_1.fileName(camelSwaggerTag ? camelSwaggerTag + "APIClient" : 'api-client', 'service'), interfaceName: camelSwaggerTag ? camelSwaggerTag + "APIClientInterface" : 'APIClientInterface', interfaceFileName: helper_1.fileName(camelSwaggerTag ? camelSwaggerTag + "APIClient" : 'api-client', 'interface'), }; } exports.createMustacheViewModel = createMustacheViewModel; function determineDomain(_a) { var schemes = _a.schemes, host = _a.host, basePath = _a.basePath; var protocol = host && schemes && schemes.length > 0 ? schemes[0] + "://" : '//'; var domain = host ? host : "${window.location.hostname}${window.location.port ? ':'+window.location.port : ''}"; var base = '/' === basePath || !basePath ? '' : basePath; return "" + protocol + domain + base; } exports.determineDomain = determineDomain; function parseMethods(_a, swaggerTag) { var _b; var paths = _a.paths, security = _a.security, parameters = _a.parameters, _c = _a.responses, responses = _c === void 0 ? {} : _c; var supportedMethods = [ 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT', ]; return (_b = []).concat.apply(_b, Object.entries(paths).map(function (_a) { var pathName = _a[0], pathDef = _a[1]; return Object.entries(pathDef) .filter(function (_a) { var methodType = _a[0], operation = _a[1]; var op = operation; return (supportedMethods.indexOf(methodType.toUpperCase()) !== -1 && (!swaggerTag || (op.tags && op.tags.includes(swaggerTag)))); }) .map(function (_a) { var methodType = _a[0], operation = _a[1]; var successResponseCode = Object.keys(operation.responses) .slice() .sort() .filter(function (code) { return code.startsWith('2'); })[0] || 'missing'; var okResponse = operation.responses[successResponseCode]; var responseType = determineResponseType(okResponse && helper_1.isReference(okResponse) ? responses[helper_1.dereferenceType(okResponse.$ref)] : okResponse); var transformedParams = transformParameters(__spreadArrays((pathDef.parameters || []), (operation.parameters || [])), parameters || {}); var responseTypeName = helper_1.typeName(responseType.name); return __assign({ hasJsonResponse: true, isSecure: security !== undefined || operation.security !== undefined, methodName: helper_1.toCamelCase(operation.operationId ? !swaggerTag ? operation.operationId : operation.operationId.replace(swaggerTag + "_", '') : methodType + "_" + pathName.replace(/[{}]/g, '')), methodType: methodType.toUpperCase(), parameters: transformedParams, formData: transformedParams .filter(function (_a) { var name = _a.name, isFormParameter = _a.isFormParameter; return name && isFormParameter; }) .map(function (_a) { var name = _a.name, camelCaseName = _a.camelCaseName; return ({ name: name, camelCaseName: camelCaseName || name, }); }), path: pathName.replace(/{(.*?)}/g, function (_) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } return "${args." + helper_1.toCamelCase(args[0]) + "}"; }), responseTypeName: responseTypeName, responseGuard: helper_1.BASIC_TS_TYPE_REGEX.test(responseTypeName) ? "typeof res === '" + responseTypeName + "'" : "guards.is" + responseTypeName + "(res)", isVoid: responseType.name === 'void', response: helper_1.prefixImportedModels(responseType.type), description: "" + helper_1.replaceNewLines(operation.description, '$1 * ') + (operation.description ? '\n * ' : '') + "Response generated for [ " + successResponseCode + " ] HTTP response code." }, (/^(File|Blob)\b/i.test(responseType.name) && { requestResponseType: 'blob', })); }); })); } function parseDefinitions(definitions, parameters, methods) { if (definitions === void 0) { definitions = {}; } if (parameters === void 0) { parameters = {}; } var allDefs = __spreadArrays(Object.entries(definitions).map(function (_a) { var key = _a[0], definition = _a[1]; return defineEnumOrInterface(key, definition); }), Object.entries(parameters) .filter(function (_a) { var definition = _a[1]; return (definition.enum && definition.enum.length !== 0) || definition.schema; }) .map(function (_a) { var key = _a[0], definition = _a[1]; return defineEnumOrInterface(key, definition); })); if (methods) { var filterByName_1 = function (defName, parentDefs) { if (parentDefs === void 0) { parentDefs = []; } var namedDefs = allDefs.filter(function (_a) { var definitionName = _a.definitionName; return definitionName === defName; }); return namedDefs.reduce(function (acc, def) { return __spreadArrays(acc, def.properties .filter(function (prop) { return prop.typescriptType && prop.isRef; }) .reduce(function (a, prop) { return parentDefs.some(function (_a) { var definitionName = _a.definitionName; return definitionName === prop.typescriptType; }) ? a : __spreadArrays(a, filterByName_1(prop.typescriptType, __spreadArrays(parentDefs, namedDefs))); }, [])); }, namedDefs); }; return methods.reduce(function (acc, method) { return __spreadArrays(acc, method.parameters.reduce(function (a, param) { return __spreadArrays(a, filterByName_1(helper_1.toCamelCase(param.typescriptType, false))); }, filterByName_1(helper_1.toCamelCase(method.responseTypeName, false)))); }, []); } return allDefs; } function defineEnumOrInterface(key, definition) { return definition.enum && definition.enum.length !== 0 ? defineEnum(definition.enum, key, definition.type === 'integer', definition.description, definition['x-enumNames']) : defineInterface(('schema' in definition ? definition.schema : definition) || {}, key); } function defineEnum(enumSchema, definitionKey, isNumeric, enumDesc, xEnumNames) { if (enumSchema === void 0) { enumSchema = []; } if (isNumeric === void 0) { isNumeric = false; } if (enumDesc === void 0) { enumDesc = ''; } if (xEnumNames === void 0) { xEnumNames = []; } var splitDesc = enumDesc.split('\n'); var descKeys = splitDesc.length > 1 ? splitDesc.reduce(function (acc, cur) { var _a; var captured = /(\d) (\w+)/.exec(cur); return captured ? __assign(__assign({}, acc), (_a = {}, _a[captured[1]] = captured[2], _a)) : acc; }, {}) : null; return { definitionName: helper_1.typeName(definitionKey), properties: enumSchema && enumSchema.map(function (val, index) { return ({ name: (isNumeric ? xEnumNames.length === 0 && descKeys ? descKeys[val.toString()] || '' : xEnumNames[index] || "" + val : val.toString()).replace(/[\W\s]+/, '_'), value: val.toString(), }); }), description: helper_1.replaceNewLines(enumDesc, '$1 * '), isEnum: true, isNumeric: isNumeric, imports: [], renderFileName: function () { return function (text, render) { return helper_1.fileName(render(text), 'enum'); }; }, }; } function parseInterfaceProperties(properties, requiredProps) { if (properties === void 0) { properties = {}; } if (requiredProps === void 0) { requiredProps = []; } return Object.entries(properties) .map(function (_a) { var propName = _a[0], propSchema = _a[1]; var isArray = propSchema.type === 'array'; var ref = propSchema.additionalProperties && typeof propSchema.additionalProperties !== 'boolean' ? propSchema.additionalProperties.$ref : propSchema.$ref; var typescriptType = 'enum' in propSchema ? (propSchema.type === 'number' ? propSchema.enum || [] : (propSchema.enum || []).map(function (str) { return "'" + str + "'"; })).join(' | ') : propSchema.properties ? 'object' : helper_1.toTypescriptType(isArray ? determineArrayType(propSchema) : ref ? helper_1.dereferenceType(ref) : propSchema.additionalProperties && typeof propSchema.additionalProperties !== 'boolean' ? propSchema.additionalProperties.type : propSchema.type); var isRef = !!parseReference(propSchema); var propertyAllOf = propSchema.allOf && propSchema.allOf.length ? parseInterfaceProperties(propSchema.allOf.reduce(function (acc, prop, i) { var _a; return (__assign(__assign({}, acc), (_a = {}, _a[i] = prop, _a))); }, {})) : []; var allOfParsed = propertyAllOf.map(function (prop) { return "" + prop.typescriptType + (prop.isArray ? '[]' : ''); }); var allOfImports = propertyAllOf.map(function (prop) { return "" + prop.typescriptType; }); var type = typescriptType.replace('[]', ''); var name = /^[A-Za-z_$][\w$]*$/.test(propName) || propName === helper_1.ADDITIONAL_PROPERTIES_KEY ? propName : "'" + propName + "'"; var property = { isArray: isArray, isDictionary: !!propSchema.additionalProperties, isRef: isRef, isPrimitiveType: helper_1.BASIC_TS_TYPE_REGEX.test(type), isRequired: requiredProps.includes(propName), name: name, description: helper_1.replaceNewLines(propSchema.description), type: type, typescriptType: allOfParsed.length ? allOfParsed.join(' & ') : typescriptType, imports: isRef ? __spreadArrays([type], allOfImports) : allOfImports, }; var guard = "(" + helper_1.guardFn(function () { return propertyAllOf.length ? "(" + propertyAllOf .map(function (prop) { return helper_1.guardFn(function () { return "is" + prop.typescriptType + "(" + helper_1.accessProp(name) + ")"; }, __assign(__assign({}, prop), { name: name, isRequired: true })); }) .join(' && ') + ")" : 'enum' in propSchema ? "[" + (typescriptType || '').replace(/ \| /g, ', ') + "].includes(" + helper_1.accessProp(name) + ")" : "is" + typescriptType + "(" + helper_1.accessProp(name) + ")"; }, property).replace(/\s+/g, ' ') + ") &&"; return __assign(__assign({}, property), { guard: guard }); }) .sort(helper_1.compareStringByKey('name')); } function parseReference(schema) { if ('$ref' in schema && schema.$ref) { return schema.$ref; } else if (schema.type === 'array' && schema.items) { if ('$ref' in schema.items && schema.items.$ref) { return schema.items.$ref; } else if (!Array.isArray(schema.items) && schema.items.items && '$ref' in schema.items.items && schema.items.items.$ref) { return schema.items.items.$ref; } } else if (schema.additionalProperties && typeof schema.additionalProperties !== 'boolean' && schema.additionalProperties.$ref) { return schema.additionalProperties.$ref; } return ''; } function determineArrayType(property) { if (property === void 0) { property = {}; } if (Array.isArray(property.items)) { helper_1.logWarn('Arrays with type diversity are currently not supported'); return 'any'; } if (property.items && property.items.$ref) { return helper_1.typeName(helper_1.dereferenceType(property.items.$ref)); } else if (property.items && property.items.type) { if (/^(array)$/i.test(property.items.type || '')) { return determineArrayType(property.items) + "[]"; } return helper_1.typeName(property.items.type); } return helper_1.typeName(property.type); } function defineInterface(schema, definitionKey) { var _a; var name = helper_1.typeName(definitionKey); var extendInterface = schema.allOf ? helper_1.toCamelCase(helper_1.dereferenceType((schema.allOf.find(function (allOfSchema) { return !!allOfSchema.$ref; }) || {}).$ref), false) : undefined; var allOfProps = schema.allOf ? schema.allOf.reduce(function (props, allOfSchema) { return (__assign(__assign({}, props), allOfSchema.properties)); }, {}) : {}; var properties = parseInterfaceProperties(__assign(__assign({}, (schema.additionalProperties ? (_a = {}, _a[helper_1.ADDITIONAL_PROPERTIES_KEY] = schema.additionalProperties, _a) : schema.properties)), (!schema.additionalProperties && allOfProps)), __spreadArrays((schema.required || []), [helper_1.ADDITIONAL_PROPERTIES_KEY])); var modelImports = properties .reduce(function (acc, _a) { var _b = _a.imports, imports = _b === void 0 ? [] : _b; return __spreadArrays(acc, imports); }, extendInterface ? [extendInterface] : []) .filter(function (type) { return type !== name; }) .sort() .filter(function (el, i, a) { return (i === a.indexOf(el) ? 1 : 0); }); return { definitionName: name, description: helper_1.replaceNewLines(schema.description, '$1 * '), properties: properties, imports: modelImports, isEnum: false, extend: extendInterface, renderFileName: function () { return function (text, render) { return helper_1.fileName(render(text), 'model'); }; }, }; } function determineResponseType(response) { if (response == null) { return { name: 'void', type: 'void' }; } var schema = response.schema; if (schema == null) { return { name: 'void', type: 'void' }; } var nullable = schema['x-nullable'] || false; if (schema.type === 'array') { var items = schema.items; if (items == null) { helper_1.logWarn('`items` field not present; `any[]` will be used'); return { name: 'any', type: 'any[]' }; } if (Array.isArray(items)) { helper_1.logWarn('Arrays with type diversity are currently not supported; `any[]` will be used'); return { name: 'any', type: 'any[]' }; } var name_1 = items.$ref ? helper_1.dereferenceType(items.$ref) : items.type; var type = nullable ? helper_1.typeName(name_1, true) + " | null" : helper_1.typeName(name_1, true); return { name: name_1 || 'any', type: type }; } if (schema.$ref != null) { var name_2 = helper_1.dereferenceType(schema.$ref); var type = nullable ? helper_1.typeName(name_2) + " | null" : helper_1.typeName(name_2); return { name: name_2, type: type }; } if (schema.type != null) { var type = nullable ? helper_1.typeName(schema.type) + " | null" : helper_1.typeName(schema.type); return { name: type, type: type }; } if (schema.properties) { var type = nullable ? 'object | null' : 'object'; return { name: type, type: type }; } return { name: 'any', type: 'any' }; } function transformParameters(parameters, allParams) { return parameters.map(function (param) { var ref = param.$ref || ('schema' in param && param.schema && param.schema.$ref) || ''; var derefName = ref ? helper_1.dereferenceType(ref) : undefined; var paramRef = derefName ? allParams[derefName] || {} : {}; var name = 'name' in paramRef ? paramRef.name || '' : param.name; var type = ('type' in param && param.type) || (paramRef && 'type' in paramRef && paramRef.type) || ''; var isArray = /^(array)$/i.test(type); var typescriptType = 'enum' in param ? (param.type === 'number' ? param.enum || [] : (param.enum || []).map(function (str) { return "'" + str + "'"; })).join(' | ') : 'schema' in param && param.schema && param.schema.properties ? 'object' : helper_1.toTypescriptType(isArray ? determineArrayType(param) : !ref || (paramRef && 'type' in paramRef && !paramRef.enum && paramRef.type && helper_1.BASIC_TS_TYPE_REGEX.test(paramRef.type)) ? type : derefName); return __assign(__assign(__assign({}, param), determineParamType('in' in paramRef ? paramRef.in : param.in)), { description: helper_1.replaceNewLines(param.description || paramRef.description, ' '), camelCaseName: helper_1.toCamelCase(name), importType: 'enum' in param ? typescriptType : helper_1.prefixImportedModels(typescriptType), isArray: isArray, isRequired: param.isRequired || param.required || paramRef.required, name: name, typescriptType: typescriptType }); }); } function determineParamType(paramType) { if (!paramType) { return {}; } switch (paramType) { case 'body': return { isBodyParameter: true }; case 'formData': return { isFormParameter: true }; case 'header': return { isHeaderParameter: true }; case 'path': return { isPathParameter: true }; case 'query' || 'modelbinding': return { isQueryParameter: true }; default: helper_1.logWarn("Unsupported parameter type [ " + paramType + " ]"); return {}; } } //# sourceMappingURL=parser.js.map