swaxios
Version:
Swagger API client generator based on axios and TypeScript.
162 lines • 7.74 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InterfaceGenerator = exports.TypeScriptType = exports.SwaggerType = void 0;
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const util_1 = require("util");
const TemplateGenerator_1 = require("./TemplateGenerator");
var SwaggerType;
(function (SwaggerType) {
SwaggerType["ARRAY"] = "array";
SwaggerType["BOOLEAN"] = "boolean";
SwaggerType["INTEGER"] = "integer";
SwaggerType["NUMBER"] = "number";
SwaggerType["OBJECT"] = "object";
SwaggerType["STRING"] = "string";
})(SwaggerType || (exports.SwaggerType = SwaggerType = {}));
var TypeScriptType;
(function (TypeScriptType) {
TypeScriptType["ANY"] = "any";
TypeScriptType["ARRAY"] = "Array";
TypeScriptType["BOOLEAN"] = "boolean";
TypeScriptType["EMPTY_OBJECT"] = "{}";
TypeScriptType["NUMBER"] = "number";
TypeScriptType["STRING"] = "string";
TypeScriptType["INTERFACE"] = "interface";
TypeScriptType["TYPE"] = "type";
})(TypeScriptType || (exports.TypeScriptType = TypeScriptType = {}));
class InterfaceGenerator extends TemplateGenerator_1.TemplateGenerator {
name;
templateFile;
spec;
definition;
outputDirectory;
constructor(definitionName, definition, spec, outputDirectory) {
super();
this.name = definitionName;
this.templateFile = 'Interface.hbs';
this.spec = spec;
this.definition = definition;
this.outputDirectory = outputDirectory;
fs_extra_1.default.ensureDirSync(this.outputDirectory);
}
static buildInterface(spec, schema, schemaName, imports = [], basicType = TypeScriptType.TYPE) {
const reference = schema.$ref;
if (reference && reference.startsWith('#/definitions')) {
if (!spec.definitions) {
console.info('Spec has no definitions.');
return { type: TypeScriptType.EMPTY_OBJECT, imports };
}
const definition = reference.replace('#/definitions/', '').replace(/[^\w\/-]/gm, '_');
if (!imports.includes(definition)) {
imports.push(definition);
}
return { type: definition, imports };
}
const schemaObject = schema;
const { allOf: multipleSchemas, required: requiredProperties, properties } = schemaObject;
if (multipleSchemas) {
const multipleTypes = multipleSchemas.map(itemSchema => InterfaceGenerator.buildInterface(spec, itemSchema, schemaName, imports, basicType));
const schemas = multipleTypes.map(item => item.type).join('&');
for (const itemType of multipleTypes) {
for (const itemImport of itemType.imports) {
if (!imports.includes(itemImport)) {
imports.push(itemImport);
}
}
}
return { basicType, type: schemas, imports };
}
let schemaType = schemaObject.type || SwaggerType.OBJECT;
if (Array.isArray(schemaType) && schemaType[0]) {
schemaType = schemaType[0];
}
switch (schemaType.toLowerCase()) {
case SwaggerType.BOOLEAN: {
return { basicType, type: TypeScriptType.BOOLEAN, imports };
}
case SwaggerType.STRING: {
return { basicType, type: TypeScriptType.STRING, imports };
}
case SwaggerType.NUMBER:
case SwaggerType.INTEGER: {
return { basicType, type: TypeScriptType.NUMBER, imports };
}
case SwaggerType.OBJECT: {
if (!properties) {
console.info(`Schema type for "${schemaName}" is "object" but has no properties.`);
return { basicType: TypeScriptType.INTERFACE, type: TypeScriptType.EMPTY_OBJECT, imports };
}
const schema = {};
for (const [property, propertyOptions] of Object.entries(properties)) {
const isRequired = requiredProperties && requiredProperties.includes(property);
const safeProperty = property.replace(/\W/gm, '_');
const isReadOnly = !!propertyOptions.readOnly;
const propertyName = `${isReadOnly ? 'readonly ' : ''}${safeProperty}${isRequired ? '' : '?'}`;
const { type: propertyType, imports: propertyImports } = InterfaceGenerator.buildInterface(spec, propertyOptions, safeProperty, imports);
schema[propertyName] = propertyType;
for (const propertyImport of propertyImports) {
if (!imports.includes(propertyImport)) {
imports.push(propertyImport);
}
}
}
const type = (0, util_1.inspect)(schema, { breakLength: Infinity, depth: Infinity })
.replace(/'/gm, '')
.replace(',', ';')
.replace(new RegExp('\\n', 'g'), '');
return { basicType: TypeScriptType.INTERFACE, type, imports };
}
case SwaggerType.ARRAY: {
if (!schemaObject.items) {
console.info(`Schema type for "${schemaName}" is "array" but has no items.`);
return { basicType, type: `${TypeScriptType.ARRAY}<${TypeScriptType.ANY}>`, imports };
}
if (!(schemaObject.items instanceof Array)) {
const { imports: itemImports, type: itemType } = InterfaceGenerator.buildInterface(spec, schemaObject.items, schemaName, imports);
for (const itemImport of itemImports) {
if (!imports.includes(itemImport)) {
imports.push(itemImport);
}
}
return { basicType, type: `${TypeScriptType.ARRAY}<${itemType}>`, imports };
}
const itemTypes = schemaObject.items.map(itemSchema => InterfaceGenerator.buildInterface(spec, itemSchema, schemaName, imports, basicType));
const schemas = itemTypes.map(item => item.type).join('|');
for (const itemType of itemTypes) {
for (const itemImport of itemType.imports) {
if (!imports.includes(itemImport)) {
imports.push(itemImport);
}
}
}
return { basicType, type: `${TypeScriptType.ARRAY}<${schemas}>`, imports };
}
default: {
return { basicType, type: TypeScriptType.EMPTY_OBJECT, imports };
}
}
}
generateInterface() {
return InterfaceGenerator.buildInterface(this.spec, this.definition, this.name);
}
async write() {
const renderedIndex = await this.toString();
const outputFile = path_1.default.join(this.outputDirectory, this.filePath);
return fs_extra_1.default.outputFile(outputFile, renderedIndex, 'utf-8');
}
async getContext() {
const { basicType, imports, type: typeData } = this.generateInterface();
return {
basicType: basicType || '',
imports,
name: this.name,
typeData,
};
}
}
exports.InterfaceGenerator = InterfaceGenerator;
//# sourceMappingURL=InterfaceGenerator.js.map