grunt-generate-view-model

Global task for generation view model

Usage no npm install needed!

<script type="module">
  import gruntGenerateViewModel from 'https://cdn.skypack.dev/grunt-generate-view-model';
</script>

README

Grunt plugin for code generation view models by models description

Build Status

This repository provides a grunt plugin for code generation view models by models description.

Установка

npm install grunt-generate-view-model

Как начать использовать

  • Создайте gencofig.json в корневом каталоге
{
    "check":
        {
            "folders":[
                "./models"
            ]
        }
}

Свойство "folders" показывает для каких папок(и их внутренних папок) нужны модели отображений.

  • Установите декораторы на нужные модели
import { InnerClass } from "./innerClass";
import {GenerateView, ViewModelType} from "grunt-generate-view-model";
import {InnerClassView } from "../generated/viewmodels/innerClassView";
import {fromModelToView, fromViewtoModel} from '../function/transformFunction';

@GenerateView({
    'model':'ClassView',
    'filePath':'./generated/viewmodels',
    'mapperPath':'./generated/mappers'})
export class Class {
    public property1: number;

    public property2: Object;

    public property3: string[];
    @ViewModelType({'type': InnerClassView,
    'transformer':{
        "toView":{'function':fromModelToView, "isAsync":true},
        "fromView":{'function': fromViewtoModel}}})
    public property4: InnerClass;

    @ViewModelType({'type': InnerClassView})
    public property5: InnerClass;

    public property6: InnerClass[];
    
    @IgnoreViewModel()
    public property7: number[]

}
  • В package.json добавьте инициализирующую команду в свойство "scripts":
  "scripts": {
    "generation": "generateView"
  }

где "generateView" - строка для запуска плагина

  • npm run generation

  • после завершения работы плагина по пути, указанному в декораторе GenerateView, появятся файлы с расширением ".ts" :

view model

import { InnerClassView } from './innerClassView';
import { InnerClass } from '../../models/innerClass';

  export class ClassView {

  public property1: number;

  public property2: Object;

  public property3: string [];

  public property4: InnerClassView;

  public property5: InnerClassView;

  public property6: InnerClass [];
}

mapper

  import { ClassView } from '../viewmodels/classView';
import { Class } from '../../models/class';
import { fromModelToView,fromViewtoModel } from '../../function/transformFunction';
import { InnerClassViewMapper } from './InnerClassViewMapper';

export class ClassViewMapper {
      public static async toClassView(model: Class): Promise<ClassView> {
            let result = new ClassView();
            result.property1 = model.property1;
            if (model.property2) {
                  result.property2 = JSON.parse(JSON.stringify(model.property2));
            }
            if (model.property3) {
                  result.property3 =  model.property3.map(function(item: any ) { return JSON.parse(JSON.stringify(item)); });
            }
            result.property4  = await fromModelToView(model);
            if (model.property5) {
                  result.property5 =  await InnerClassViewMapper.toInnerClassView(model.property5);
            }
            if (model.property6) {
                  result.property6 =  model.property6.map(function(item: any ) { return JSON.parse(JSON.stringify(item)); });
            }
            return result;
      }
      public static async fromClassView(viewModel: ClassView): Promise<Class> {
            let result = new Class();
            result.property1 = viewModel.property1;
            if (viewModel.property2) {
                  result.property2 = JSON.parse(JSON.stringify(viewModel.property2));
            }
            if (viewModel.property3) {
                  result.property3 =  viewModel.property3.map(function(item: any ) { return JSON.parse(JSON.stringify( item )); });
            }
            result.property4  =  fromViewtoModel(viewModel);
            if (viewModel.property5) {
                  result.property5 =  await InnerClassViewMapper.fromInnerClassView(viewModel.property5);
            }
            if (viewModel.property6) {
                  result.property6 =  viewModel.property6.map(function(item: any ) { return JSON.parse(JSON.stringify( item )); });
            }
            return result;
      }
}

Декораторы

В этом плагине используются 4 декоратора: 1 для классов и 3 для свойств

Декораторы для классов

GenerateView

Основной декоратор для создания моделей отображения

+-------------+--------------+-------------------------------------------------------+
|                        @GenerateView                                               |
+------------------------------------------------------------------------------------+
|   Property  |  Mandatory   |                      Definition                       |
+-------------+--------------+-------------------------------------------------------+
| model       | true         | name of view model                                    |
| filePath    | true         | path to view model relative to the root of the folder |
| mapperpath  | false        | path to mapper                                        |
+-------------+--------------+-------------------------------------------------------+

Можно создавать несколько моделей отображения от одной базовой модели.

@GenerateView({
    'model':'ClassView',
    'filePath':'./generated/viewmodels',
    'mapperPath':'./generated/mappers'})

Декораторы для свойств

ViewModelName

Декоратор, который используется для переименования свойства у модели отображения.

+------------------------------------------------------------------------------------+
|                        @ViewModelName                                              |
+------------------------------------------------------------------------------------+
|   Property             |  Mandatory   |              Definition                    |
+------------------------+--------------+--------------------------------------------+
| 1st param(name)        | true         | name of field in view model                |
| 2nd param(using models)| false        | view model using this name of field        |
+------------------------+--------------+--------------------------------------------+
  • Если 2 параметр - null : свойство будет переименовано во всех создаваемых моделях отображения от базовой модели.
@ViewModelName("information")

@ViewModelName("information", "HeroViewModel")
public data: string;

IgnoreViewModel

Декоратор, который используется для удаления свойства из модели отображения.

+--------------------------------------------------------------------------------------------------+
|                              @IgnoreViewModel                                                    |
+--------------------------------------------------------------------------------------------------+
|   Property                   |   Mandatory  |               Definition                           |
+-------------+----------------+--------------+----------------------------------------------------+
| 1st param(name of view model)|     false    |name of view model ,which ignore ths field          |
+------------------------------+--------------+----------------------------------------------------+
  • Если параметр не определен - это свойство игнорируется во всех создаваемых моделях.
  • Если необходимо игнорировать несколько моделей - необходимо написать декоратор для каждой создаваемой модели отбражения.
@IgnoreViewModel()

@IgnoreViewModel("HeroViewModel")

ViewModelType

Декоратор, который используется для смены типа свойства в модели отображения.

+-------------------------------------------------------------------------------------------+
|                        @ViewModelType                                                     |
+-------------------------------------------------------------------------------------------+
|   Property  |  Mandatory   |                      Definition                              | 
+-------------+--------------+--------------------------------------------------------------+
| type        | true         | property type in view model                                  |
| transformer | false        | function used to transform to view model and back im mappers | - complex object
| modelName   | false        | name of view model which will be have property               |
+-------------+--------------+--------------------------------------------------------------+

+-------------------------------------------------------------------------------------------+
|                        transforner Type                                                   |
+-------------------------------------------------------------------------------------------+
|   Property  |  Mandatory   |                      Definition                              | 
+-------------+--------------+--------------------------------------------------------------+
| toView      | true         | transform object which used to transform base model to view  | - complex object
| fromView    | true         | transform object which used to transform view model to base  | - complex object
+-------------+--------------+--------------------------------------------------------------+


+-------------------------------------------------------------------------------------------+
|                        toView/fromView objects                                            |
+-------------------------------------------------------------------------------------------+
|   Property  |  Mandatory   |                      Definition                              | 
+-------------+--------------+--------------------------------------------------------------+
| function    | true         | function which transformate model                            | 
| isAsync     | false        | is function async                                            | 
+-------------+--------------+--------------------------------------------------------------+
  • Если свойство "transformer" отсутствует:
    • Если тип свойства - составной, но не сгенерирован или сгенерирован без маппера - глубокое копирование.
    • Если тип скодогенерирован с маппером - используется маппер.
  • Если свойство "modelName" отсутствует, тип используется для всех моделей отображения для данной базовой модели.
    @ViewModelType({
    "modelName": "HeroViewModel",
    "transformer": { "toView" : { "function": toViewModelFunction , "isAsync": true},
                    "fromView": { "function": FromViewModelFunction }},
    "type": HeroDetail})