123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- import Mustache from 'mustache';
- import { Field, ObjectType } from '../model';
- import * as path from 'path';
- import { kebabCase, camelCase } from 'lodash';
- import { getTypesForArray, names, pascalCase, camelPlural } from './utils';
- import Debug from "debug";
- import { GeneratorContext } from './SourcesGenerator';
- const debug = Debug('qnode-cli:model-renderer');
- const TYPE_FIELDS: { [key: string]: { [key: string]: string } } = {
- bool: {
- decorator: 'BooleanField',
- tsType: 'boolean'
- },
- date: {
- decorator: 'DateField',
- tsType: 'Date'
- },
- int: {
- decorator: 'IntField',
- tsType: 'number'
- },
- float: {
- decorator: 'FloatField',
- tsType: 'number'
- },
- json: {
- decorator: 'JSONField',
- tsType: 'JsonObject'
- },
- otm: {
- decorator: 'OneToMany',
- tsType: '---'
- },
- string: {
- decorator: 'StringField',
- tsType: 'string'
- },
- numeric: {
- decorator: 'NumericField',
- tsType: 'string'
- },
- decimal: {
- decorator: 'NumericField',
- tsType: 'string'
- },
- oto: {
- decorator: 'OneToOne',
- tsType: '---'
- },
- array: {
- decorator: 'ArrayField',
- tsType: '' // will be updated with the correct type
- },
- bytes: {
- decorator: 'BytesField',
- tsType: 'Buffer'
- }
- };
- type FunctionProp = () => string;
- type MustacheProp = string | FunctionProp;
- export interface MustacheObjectType {
- generatedFolderRelPath: string,
- className: string
- fields: MustacheField[],
- has: Props // hasBooleanField, hasIntField, ...
- }
- export interface MustacheField {
- camelName: MustacheProp,
- tsType: MustacheProp,
- decorator: MustacheProp,
- relClassName?: string,
- relCamelName?: string,
- relPathForModel?: string,
- apiType?: string,
- dbType?: string,
- required: boolean,
- is: Props // isOtm, isMto, isScalar ...
- }
- interface Props {
- [key: string]: boolean | string
- }
- export class ModelRenderer {
- private context: GeneratorContext = {};
- constructor(context: GeneratorContext = {}) {
- this.context = context;
- }
- transformField(f: Field, entity: ObjectType): MustacheField {
- let ret = {};
- const isProps: Props = {};
- isProps['array'] = f.isArray();
- isProps['scalar'] = f.isScalar();
- ['mto', 'oto', 'otm'].map((s) => isProps[s] = (f.type === s));
- isProps['refType'] = isProps['mto'] || isProps['oto'] || isProps['otm'];
- const fieldType = f.columnType();
-
- ret = {
- is: isProps,
- required: !f.nullable,
- ...TYPE_FIELDS[fieldType]
- };
- if (isProps['array']) {
- ret = {
- ...ret,
- ...getTypesForArray(fieldType),
- decorator: 'ArrayField',
- }
- }
- const names = this.interpolateNames(f, entity);
- ret = {
- ...ret,
- ...this.interpolateNames(f, entity),
- relPathForModel: this.relativePathForModel(names['relClassName'])
- }
- debug(`Mustache Field: ${JSON.stringify(ret, null, 2)}`);
- return ret as MustacheField;
- }
- interpolateNames(f: Field, entity: ObjectType): { [key: string]: string } {
- const single = (f.type === 'otm') ? f.name.slice(0, -1) : f.name; // strip s at the end if otm
- return {
- ...names(single),
- relClassName: pascalCase(single),
- relCamelName: camelCase(single),
- relFieldName: camelCase(entity.name),
- relFieldNamePlural: camelPlural(entity.name)
- }
-
- }
- transform(objType: ObjectType): MustacheObjectType {
- const fields: MustacheField[] = [];
-
- objType.fields.map((f) => fields.push(this.transformField(f, objType)));
-
- const has: Props = {};
- for (const key in TYPE_FIELDS) {
- const _key: string = (key === 'numeric') ? 'numeric' || 'decimal' : key;
- has[key] = objType.fields.some((f) => f.columnType() === _key);
- }
- has['array'] = objType.fields.some((f) => f.isArray());
- debug(`ObjectType has: ${JSON.stringify(has, null, 2)}`);
- return { fields,
- generatedFolderRelPath: this.context["generatedFolderRelPath"] as string, //this.getGeneratedFolderRelativePath(objType.name),
- has,
- ...names(objType.name) } as MustacheObjectType;
- }
- generate(mustacheTeplate: string, objType: ObjectType):string {
- const mustacheQuery = this.transform(objType);
- return Mustache.render(mustacheTeplate, mustacheQuery);
- }
-
- relativePathForModel(referenced: string): string {
- return path.join(
- '..',
- kebabCase(referenced),
- `${kebabCase(referenced)}.model`
- );
- }
- }
|