api-client-generator
Version:
Angular REST API client generator from Swagger YAML or JSON file with camel case settings
422 lines • 20.4 kB
JavaScript
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
;