airship-server
Version:
Airship is a framework for Node.JS & TypeScript that helps you to write big, scalable and maintainable API servers.
215 lines • 9.39 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const SourceCode_1 = require("../domain/SourceCode");
const StringType_1 = require("../domain/types/StringType");
const NumberType_1 = require("../domain/types/NumberType");
const AnyType_1 = require("../domain/types/AnyType");
const BooleanType_1 = require("../domain/types/BooleanType");
const CustomType_1 = require("../domain/types/CustomType");
const VectorType_1 = require("../domain/types/VectorType");
const Utils_1 = require("./Utils");
const IntBoolType_1 = require("../domain/types/IntBoolType");
class TypescriptCodeGenerator {
generateClass(scheme) {
let code = new SourceCode_1.default();
let constructor = this.generateClassConstructor(scheme);
let deserializeMethod = this.generateDeserializeMethod(scheme);
let serializeMethod = this.generateSerializeMethod(scheme);
code.add(`export class ${scheme.name} {`);
code.append(constructor, 1);
code.add('');
code.append(deserializeMethod, 1);
code.add('');
code.append(serializeMethod, 1);
code.add('}');
return code;
}
generateApiMethod(scheme) {
let code = new SourceCode_1.default();
let methodName = Utils_1.toCamelCase(scheme.name, false, '.');
let propsName = `MethodsProps.${Utils_1.toCamelCase(scheme.name, true, '.')}Params`;
let responseName = this.renderType(scheme.responseType, true);
/**
* Returns detailed information on users.
*
*
* @param {{
* subview:string,
* el:(number|Element)
* }} params
*/
code.add(`/**`);
code.add(` * ${scheme.description}`);
code.add(' *');
code.add(' * @param {{');
scheme.params.forEach((param, index) => {
let coma = this.genComa(scheme.params, index);
code.add(` * ${Utils_1.toCamelCase(param.name)}: (${this.renderType(param.type, true)}${param.required ? '' : '|undefined'})${coma}`);
});
code.add(' * }} params');
code.add(' *');
code.add(` * @returns {Promise<${responseName}>}`);
code.add(` */`);
code.add(`public async ${methodName}(params: ${propsName}): Promise<Responses.${responseName}> {`);
code.add('return this.call(', 1);
code.add(`'${scheme.name}',`, 2);
code.add(`{`, 2);
scheme.params.forEach((param, index) => {
let coma = this.genComa(scheme.params, index);
let fieldVar = `${param.name}: params.${param.name}`;
if (param.type instanceof VectorType_1.default)
code.add(`${param.name}: ${this.renderVectorSerialize(`params.${param.name}`, param.type) + coma}`, 3);
else if (param.type instanceof CustomType_1.default)
code.add(`${fieldVar} ? params.${param.name}.serialize() : undefined${coma}`, 3);
else
code.add(fieldVar + coma, 3);
//code.add(`${param.name}: params.${toCamelCase(param.name)}${coma}`, 3)
});
code.add(`},`, 2);
code.add(`Responses.${responseName}`, 2);
code.add(')', 1);
code.add('}');
return code;
}
generateApiMethodParamsInterface(scheme) {
let code = new SourceCode_1.default();
code.add(`export interface ${Utils_1.toCamelCase(scheme.name, true, '.')}Params {`);
scheme.params.forEach((prop, index) => {
let coma = this.genComa(scheme.params, index);
let isCustom = this.isCustomType(prop.type);
// code.add(`/**`, 1)
// code.add(` * ${prop.description}`, 1)
// code.add(` */`, 1)
code.add(`${Utils_1.toCamelCase(prop.name)}${prop.required ? '' : '?'}: ${isCustom ? 'Models.' : ''}${this.renderType(prop.type, true)}${coma}`, 1);
});
code.add('}');
return code;
}
generateClassConstructor(scheme) {
let code = new SourceCode_1.default();
let jsdoc = this.generateClassConstructorJSDoc(scheme);
code.append(jsdoc);
code.add('constructor (');
scheme.fields.forEach((field, index) => {
let coma = this.genComa(scheme.fields, index);
code.add(`readonly ${Utils_1.toCamelCase(field.name)}: ${this.renderType(field.type)}${coma}`, 1);
});
code.add(') {');
code.add('');
code.add('}');
return code;
}
generateClassConstructorJSDoc(scheme) {
let code = new SourceCode_1.default();
code.add('/**');
code.add(' * @class');
scheme.fields.forEach(field => {
let type = this.removeNamespaceFromCustomType(field.type);
code.add(` * @property {${this.renderType(type)}} ${Utils_1.toCamelCase(field.name)} ${field.description}`);
});
code.add(' */');
return code;
}
generateDeserializeMethod(scheme) {
let code = new SourceCode_1.default();
code.add('/**');
code.add(' * @param {Object} raw');
code.add(` * @returns {${scheme.name}}`);
code.add(' */');
code.add(`static deserialize(raw: any): ${scheme.name} {`);
code.add(`return new ${scheme.name} (`, 1);
scheme.fields.forEach((field, index) => {
let coma = this.genComa(scheme.fields, index);
let fieldVar = `raw['${field.name}']`;
if (field.type instanceof VectorType_1.default)
code.add(this.renderVectorDeserialize(fieldVar, field.type) + coma, 2);
else if (field.type instanceof CustomType_1.default)
code.add(`${fieldVar} ? ${field.type.name}.deserialize(${fieldVar}) : undefined${coma}`, 2);
else if (field.type instanceof IntBoolType_1.default)
code.add(`!!${fieldVar}${coma}`, 2);
else
code.add(fieldVar + coma, 2);
});
code.add(`)`, 1);
code.add('}');
return code;
}
generateSerializeMethod(scheme) {
let code = new SourceCode_1.default();
code.add('/**');
code.add(` * @returns {Object}`);
code.add(' */');
code.add(`public serialize(): Object {`);
code.add(`return {`, 1);
scheme.fields.forEach((field, index) => {
let coma = this.genComa(scheme.fields, index);
let fieldVar = `${field.name}: this.${field.name}`;
if (field.type instanceof VectorType_1.default)
code.add(`${field.name}: ${this.renderVectorSerialize(`this.${field.name}`, field.type) + coma}`, 2);
else if (field.type instanceof CustomType_1.default)
code.add(`${fieldVar} ? this.${field.name}.serialize() : undefined${coma}`, 2);
else
code.add(fieldVar + coma, 2);
});
code.add('}', 1);
code.add('}');
return code;
}
renderType(type, withoutUndefined = false) {
if (type instanceof StringType_1.default)
return 'string';
if (type instanceof NumberType_1.default)
return 'number';
if (type instanceof AnyType_1.default)
return 'any';
if (type instanceof BooleanType_1.default)
return 'boolean';
if (type instanceof IntBoolType_1.default)
return 'boolean';
if (type instanceof CustomType_1.default)
return type.name + `${!withoutUndefined ? '|undefined' : ''}`;
if (type instanceof VectorType_1.default) {
return this.renderType(type.item, true) + `[]${!withoutUndefined ? '|undefined' : ''}`;
}
throw new Error('UNSUPPORTED TYPE' + JSON.stringify(type));
}
genComa(list, index) {
return (index == list.length - 1) ? '' : ',';
}
renderVectorDeserialize(value, type) {
let code = '';
if (type instanceof VectorType_1.default)
code += `${value} ? ${value}.map((v: any) => ${this.renderVectorDeserialize('v', type.item)}) : undefined`;
else if (type instanceof CustomType_1.default)
code += `${value} ? ${type.name}.deserialize(${value}) : undefined`;
else
code += value;
return code;
}
renderVectorSerialize(value, type) {
let code = '';
if (type instanceof VectorType_1.default)
code += `${value} ? ${value}.map((v: any) => ${this.renderVectorSerialize('v', type.item)}) : undefined`;
else if (type instanceof CustomType_1.default)
code += `${value} ? ${value}.serialize() : undefined`;
else
code += value;
return code;
}
isCustomType(type) {
if (type instanceof CustomType_1.default)
return true;
if (type instanceof VectorType_1.default)
return this.isCustomType(type.item);
return false;
}
removeNamespaceFromCustomType(type) {
if (type instanceof CustomType_1.default)
return new CustomType_1.default(type.name.replace('Models.', ''));
if (type instanceof VectorType_1.default)
return new VectorType_1.default(this.removeNamespaceFromCustomType(type.item));
return type;
}
}
exports.default = TypescriptCodeGenerator;
//# sourceMappingURL=TypescriptCodeGenerator.js.map