Просмотр исходного кода

fix: embedded objects conversion

e22m4u 1 год назад
Родитель
Сommit
13108089ce

+ 27 - 4
dist/cjs/index.cjs

@@ -2348,8 +2348,19 @@ var init_model_definition_utils = __esm({
         propNames.forEach((propName) => {
           if (!(propName in convertedData)) return;
           const colName = this.getColumnNameByPropertyName(modelName, propName);
-          if (propName === colName) return;
-          const propValue = convertedData[propName];
+          let propValue = convertedData[propName];
+          const propDef = propDefs[propName];
+          if (propValue !== null && typeof propValue === "object" && !Array.isArray(propValue) && propDef !== null && typeof propDef === "object" && propDef.type === DataType.OBJECT && propDef.model) {
+            propValue = this.convertPropertyNamesToColumnNames(
+              propDef.model,
+              propValue
+            );
+          }
+          if (Array.isArray(propValue) && propDef !== null && typeof propDef === "object" && propDef.type === DataType.ARRAY && propDef.itemModel) {
+            propValue = propValue.map((el) => {
+              return el !== null && typeof el === "object" && !Array.isArray(el) ? this.convertPropertyNamesToColumnNames(propDef.itemModel, el) : el;
+            });
+          }
           delete convertedData[propName];
           convertedData[colName] = propValue;
         });
@@ -2368,8 +2379,20 @@ var init_model_definition_utils = __esm({
         const convertedData = cloneDeep(tableData);
         propNames.forEach((propName) => {
           const colName = this.getColumnNameByPropertyName(modelName, propName);
-          if (!(colName in convertedData) || colName === propName) return;
-          const colValue = convertedData[colName];
+          if (!(colName in convertedData)) return;
+          let colValue = convertedData[colName];
+          const propDef = propDefs[propName];
+          if (colValue !== null && typeof colValue === "object" && !Array.isArray(colValue) && propDef !== null && typeof propDef === "object" && propDef.type === DataType.OBJECT && propDef.model) {
+            colValue = this.convertColumnNamesToPropertyNames(
+              propDef.model,
+              colValue
+            );
+          }
+          if (Array.isArray(colValue) && propDef !== null && typeof propDef === "object" && propDef.type === DataType.ARRAY && propDef.itemModel) {
+            colValue = colValue.map((el) => {
+              return el !== null && typeof el === "object" && !Array.isArray(el) ? this.convertColumnNamesToPropertyNames(propDef.itemModel, el) : el;
+            });
+          }
           delete convertedData[colName];
           convertedData[propName] = colValue;
         });

+ 75 - 4
src/definition/model/model-definition-utils.js

@@ -179,8 +179,43 @@ export class ModelDefinitionUtils extends Service {
     propNames.forEach(propName => {
       if (!(propName in convertedData)) return;
       const colName = this.getColumnNameByPropertyName(modelName, propName);
-      if (propName === colName) return;
-      const propValue = convertedData[propName];
+      let propValue = convertedData[propName];
+      // если значением является объект, то проверяем
+      // тип свойства и наличие модели для замены
+      // полей данного объекта
+      const propDef = propDefs[propName];
+      if (
+        propValue !== null &&
+        typeof propValue === 'object' &&
+        !Array.isArray(propValue) &&
+        propDef !== null &&
+        typeof propDef === 'object' &&
+        propDef.type === DataType.OBJECT &&
+        propDef.model
+      ) {
+        propValue = this.convertPropertyNamesToColumnNames(
+          propDef.model,
+          propValue,
+        );
+      }
+      // если значением является массив, то проверяем
+      // тип свойства и наличие модели элементов массива
+      // для замены полей каждого объекта
+      if (
+        Array.isArray(propValue) &&
+        propDef !== null &&
+        typeof propDef === 'object' &&
+        propDef.type === DataType.ARRAY &&
+        propDef.itemModel
+      ) {
+        propValue = propValue.map(el => {
+          // если элементом массива является объект,
+          // то конвертируем поля согласно модели
+          return el !== null && typeof el === 'object' && !Array.isArray(el)
+            ? this.convertPropertyNamesToColumnNames(propDef.itemModel, el)
+            : el;
+        });
+      }
       delete convertedData[propName];
       convertedData[colName] = propValue;
     });
@@ -201,8 +236,44 @@ export class ModelDefinitionUtils extends Service {
     const convertedData = cloneDeep(tableData);
     propNames.forEach(propName => {
       const colName = this.getColumnNameByPropertyName(modelName, propName);
-      if (!(colName in convertedData) || colName === propName) return;
-      const colValue = convertedData[colName];
+      if (!(colName in convertedData)) return;
+      let colValue = convertedData[colName];
+      // если значением является объект, то проверяем
+      // тип свойства и наличие модели для замены
+      // полей данного объекта
+      const propDef = propDefs[propName];
+      if (
+        colValue !== null &&
+        typeof colValue === 'object' &&
+        !Array.isArray(colValue) &&
+        propDef !== null &&
+        typeof propDef === 'object' &&
+        propDef.type === DataType.OBJECT &&
+        propDef.model
+      ) {
+        colValue = this.convertColumnNamesToPropertyNames(
+          propDef.model,
+          colValue,
+        );
+      }
+      // если значением является массив, то проверяем
+      // тип свойства и наличие модели элементов массива
+      // для замены полей каждого объекта
+      if (
+        Array.isArray(colValue) &&
+        propDef !== null &&
+        typeof propDef === 'object' &&
+        propDef.type === DataType.ARRAY &&
+        propDef.itemModel
+      ) {
+        colValue = colValue.map(el => {
+          // если элементом массива является объект,
+          // то конвертируем поля согласно модели
+          return el !== null && typeof el === 'object' && !Array.isArray(el)
+            ? this.convertColumnNamesToPropertyNames(propDef.itemModel, el)
+            : el;
+        });
+      }
       delete convertedData[colName];
       convertedData[propName] = colValue;
     });

+ 368 - 0
src/definition/model/model-definition-utils.spec.js

@@ -690,6 +690,191 @@ describe('ModelDefinitionUtils', function () {
         .convertPropertyNamesToColumnNames('modelB', {foo: 'string'});
       expect(result).to.be.eql({fooColumn: 'string'});
     });
+
+    describe('embedded object with model', function () {
+      it('does nothing if no property definitions', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.OBJECT,
+              model: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertPropertyNamesToColumnNames('modelA', {
+            embedded: {foo: 'string'},
+          });
+        expect(result).to.be.eql({embedded: {foo: 'string'}});
+      });
+
+      it('does nothing if no column name specified', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.OBJECT,
+              model: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+          properties: {
+            foo: DataType.STRING,
+            bar: DataType.NUMBER,
+          },
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertPropertyNamesToColumnNames('modelA', {
+            embedded: {foo: 'string', bar: 10},
+          });
+        expect(result).to.be.eql({embedded: {foo: 'string', bar: 10}});
+      });
+
+      it('replaces property names by column names', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.OBJECT,
+              model: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+          properties: {
+            foo: {
+              type: DataType.STRING,
+              columnName: 'fooColumn',
+            },
+            bar: {
+              type: DataType.NUMBER,
+              columnName: 'barColumn',
+            },
+          },
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertPropertyNamesToColumnNames('modelA', {
+            embedded: {foo: 'string', bar: 10},
+          });
+        expect(result).to.be.eql({
+          embedded: {fooColumn: 'string', barColumn: 10},
+        });
+      });
+    });
+
+    describe('embedded array with items model', function () {
+      it('does nothing if no property definitions', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.ARRAY,
+              itemType: DataType.OBJECT,
+              itemModel: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertPropertyNamesToColumnNames('modelA', {
+            embedded: [{foo: 'val'}, {bar: 10}],
+          });
+        expect(result).to.be.eql({embedded: [{foo: 'val'}, {bar: 10}]});
+      });
+
+      it('does nothing if no column name specified', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.ARRAY,
+              itemType: DataType.OBJECT,
+              itemModel: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+          properties: {
+            foo: DataType.STRING,
+            bar: DataType.NUMBER,
+          },
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertPropertyNamesToColumnNames('modelA', {
+            embedded: [
+              {foo: 'val1', bar: 10},
+              {foo: 'val2', bar: 20},
+            ],
+          });
+        expect(result).to.be.eql({
+          embedded: [
+            {foo: 'val1', bar: 10},
+            {foo: 'val2', bar: 20},
+          ],
+        });
+      });
+
+      it('replaces property names by column names', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.ARRAY,
+              itemType: DataType.OBJECT,
+              itemModel: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+          properties: {
+            foo: {
+              type: DataType.STRING,
+              columnName: 'fooColumn',
+            },
+            bar: {
+              type: DataType.NUMBER,
+              columnName: 'barColumn',
+            },
+          },
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertPropertyNamesToColumnNames('modelA', {
+            embedded: [
+              {foo: 'val1', bar: 10},
+              {foo: 'val2', bar: 20},
+            ],
+          });
+        expect(result).to.be.eql({
+          embedded: [
+            {fooColumn: 'val1', barColumn: 10},
+            {fooColumn: 'val2', barColumn: 20},
+          ],
+        });
+      });
+    });
   });
 
   describe('convertColumnNamesToPropertyNames', function () {
@@ -764,6 +949,189 @@ describe('ModelDefinitionUtils', function () {
         .convertColumnNamesToPropertyNames('modelA', {fooColumn: 'string'});
       expect(result).to.be.eql({foo: 'string'});
     });
+
+    describe('embedded object with model', function () {
+      it('does nothing if no property definitions', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.OBJECT,
+              model: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertColumnNamesToPropertyNames('modelA', {
+            embedded: {foo: 'string'},
+          });
+        expect(result).to.be.eql({embedded: {foo: 'string'}});
+      });
+
+      it('does nothing if no column name specified', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.OBJECT,
+              model: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+          properties: {
+            foo: DataType.STRING,
+            bar: DataType.NUMBER,
+          },
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertColumnNamesToPropertyNames('modelA', {
+            embedded: {foo: 'string', bar: 10},
+          });
+        expect(result).to.be.eql({embedded: {foo: 'string', bar: 10}});
+      });
+
+      it('replaces property names by column names', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.OBJECT,
+              model: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+          properties: {
+            foo: {
+              type: DataType.STRING,
+              columnName: 'fooColumn',
+            },
+            bar: {
+              type: DataType.NUMBER,
+              columnName: 'barColumn',
+            },
+          },
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertColumnNamesToPropertyNames('modelA', {
+            embedded: {fooColumn: 'string', barColumn: 10},
+          });
+        expect(result).to.be.eql({embedded: {foo: 'string', bar: 10}});
+      });
+    });
+
+    describe('embedded array with items model', function () {
+      it('does nothing if no property definitions', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.ARRAY,
+              itemType: DataType.OBJECT,
+              itemModel: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertColumnNamesToPropertyNames('modelA', {
+            embedded: [{foo: 'val'}, {bar: 10}],
+          });
+        expect(result).to.be.eql({embedded: [{foo: 'val'}, {bar: 10}]});
+      });
+
+      it('does nothing if no column name specified', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.ARRAY,
+              itemType: DataType.OBJECT,
+              itemModel: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+          properties: {
+            foo: DataType.STRING,
+            bar: DataType.NUMBER,
+          },
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertColumnNamesToPropertyNames('modelA', {
+            embedded: [
+              {foo: 'val1', bar: 10},
+              {foo: 'val2', bar: 20},
+            ],
+          });
+        expect(result).to.be.eql({
+          embedded: [
+            {foo: 'val1', bar: 10},
+            {foo: 'val2', bar: 20},
+          ],
+        });
+      });
+
+      it('replaces property names by column names', function () {
+        const schema = new Schema();
+        schema.defineModel({
+          name: 'modelA',
+          properties: {
+            embedded: {
+              type: DataType.ARRAY,
+              itemType: DataType.OBJECT,
+              itemModel: 'modelB',
+            },
+          },
+        });
+        schema.defineModel({
+          name: 'modelB',
+          properties: {
+            foo: {
+              type: DataType.STRING,
+              columnName: 'fooColumn',
+            },
+            bar: {
+              type: DataType.NUMBER,
+              columnName: 'barColumn',
+            },
+          },
+        });
+        const result = schema
+          .getService(ModelDefinitionUtils)
+          .convertColumnNamesToPropertyNames('modelA', {
+            embedded: [
+              {fooColumn: 'val1', barColumn: 10},
+              {fooColumn: 'val2', barColumn: 20},
+            ],
+          });
+        expect(result).to.be.eql({
+          embedded: [
+            {foo: 'val1', bar: 10},
+            {foo: 'val2', bar: 20},
+          ],
+        });
+      });
+    });
   });
 
   describe('getDataTypeByPropertyName', function () {