From 7f7b756778975c9c0a1f45c10efc76ce56cdc365 Mon Sep 17 00:00:00 2001 From: Etienne Noel Date: Sun, 29 Oct 2023 14:12:42 -0700 Subject: [PATCH] - Added useful updates. --- package-lock.json | 24 +++++++-- package.json | 2 +- .../interfaces/data-normalizer.interface.ts | 2 +- .../src/normalizers/lowercase.normalizer.ts | 4 +- .../data-transformer.property.spec.ts | 2 +- .../transformers/data-transformer.property.ts | 2 +- .../src/transformers/data.transformer.spec.ts | 47 +++++++++++++--- .../src/transformers/data.transformer.ts | 54 ++++++++++++------- 8 files changed, 100 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index 85aaa2f85..31888312d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@pristine-ts/common": "file:packages/common", "@pristine-ts/configuration": "file:packages/configuration", "@pristine-ts/core": "file:packages/core", - "@pristine-ts/data-transformer": "file:tests/data-transformer", + "@pristine-ts/data-transformer": "file:packages/data-transformer", "@pristine-ts/e2e": "file:tests/e2e", "@pristine-ts/express": "file:packages/express", "@pristine-ts/file": "file:packages/file", @@ -5824,7 +5824,7 @@ "link": true }, "node_modules/@pristine-ts/data-transformer": { - "resolved": "tests/data-transformer", + "resolved": "packages/data-transformer", "link": true }, "node_modules/@pristine-ts/e2e": { @@ -17706,6 +17706,15 @@ "@types/uuid": "^8.3.4" } }, + "packages/data-transformer": { + "version": "0.0.239", + "license": "ISC", + "dependencies": { + "@camaro/redis": "^2.2.5", + "@pristine-ts/common": "file:../common", + "@pristine-ts/logging": "file:../logging" + } + }, "packages/express": { "name": "@pristine-ts/express", "version": "0.0.256", @@ -17867,7 +17876,9 @@ "version": "0.5.1", "license": "MIT" }, - "tests/data-transformer": {}, + "tests/data-transformer": { + "extraneous": true + }, "tests/e2e": { "name": "@pristine-ts/e2e", "version": "1.0.0", @@ -22339,7 +22350,12 @@ } }, "@pristine-ts/data-transformer": { - "version": "file:tests/data-transformer" + "version": "file:packages/data-transformer", + "requires": { + "@camaro/redis": "^2.2.5", + "@pristine-ts/common": "file:../common", + "@pristine-ts/logging": "file:../logging" + } }, "@pristine-ts/e2e": { "version": "file:tests/e2e", diff --git a/package.json b/package.json index f88a74784..a7650c1d7 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "@pristine-ts/common": "file:packages/common", "@pristine-ts/configuration": "file:packages/configuration", "@pristine-ts/core": "file:packages/core", - "@pristine-ts/data-transformer": "file:tests/data-transformer", + "@pristine-ts/data-transformer": "file:packages/data-transformer", "@pristine-ts/e2e": "file:tests/e2e", "@pristine-ts/express": "file:packages/express", "@pristine-ts/file": "file:packages/file", diff --git a/packages/data-transformer/src/interfaces/data-normalizer.interface.ts b/packages/data-transformer/src/interfaces/data-normalizer.interface.ts index 55b6fb8ea..e983e9947 100644 --- a/packages/data-transformer/src/interfaces/data-normalizer.interface.ts +++ b/packages/data-transformer/src/interfaces/data-normalizer.interface.ts @@ -13,5 +13,5 @@ export interface DataNormalizer { * @param source * @param options */ - normalize(source: any, options: R): T; + normalize(source: any, options?: R): T; } diff --git a/packages/data-transformer/src/normalizers/lowercase.normalizer.ts b/packages/data-transformer/src/normalizers/lowercase.normalizer.ts index a6bf82f43..e250cf044 100644 --- a/packages/data-transformer/src/normalizers/lowercase.normalizer.ts +++ b/packages/data-transformer/src/normalizers/lowercase.normalizer.ts @@ -8,9 +8,9 @@ export class LowercaseNormalizer implements DataNormalizer { "optionA": true, }; - dataTransformerProperty.addExcludedNormalizer("normalizer"); + dataTransformerProperty.excludeNormalizer("normalizer"); expect(dataTransformerProperty.excludedNormalizers.size).toBe(1); expect(dataTransformerProperty.excludedNormalizers.has("normalizer")).toBeTruthy() diff --git a/packages/data-transformer/src/transformers/data-transformer.property.ts b/packages/data-transformer/src/transformers/data-transformer.property.ts index 24095af21..12d96bbed 100644 --- a/packages/data-transformer/src/transformers/data-transformer.property.ts +++ b/packages/data-transformer/src/transformers/data-transformer.property.ts @@ -42,7 +42,7 @@ export class DataTransformerProperty { return this.normalizers.find(element => element.key === normalizerUniqueKey) !== undefined; } - public addExcludedNormalizer(normalizerUniqueKey: DataNormalizerUniqueKey): DataTransformerProperty { + public excludeNormalizer(normalizerUniqueKey: DataNormalizerUniqueKey): DataTransformerProperty { if(this.excludedNormalizers.has(normalizerUniqueKey)) { throw new DataNormalizerAlreadyAdded("The EXCLUDED data normalizer '" + normalizerUniqueKey + "' has already been added to this source property: '" + this.sourceProperty + "'.", normalizerUniqueKey) } diff --git a/packages/data-transformer/src/transformers/data.transformer.spec.ts b/packages/data-transformer/src/transformers/data.transformer.spec.ts index 87a2f0e75..c14c23ff6 100644 --- a/packages/data-transformer/src/transformers/data.transformer.spec.ts +++ b/packages/data-transformer/src/transformers/data.transformer.spec.ts @@ -7,11 +7,11 @@ describe('Data Transformer', () => { it("should properly transform", () => { const dataTransformer = new DataTransformer([new LowercaseNormalizer()]); - const source = { + const source = [{ NAME: "Etienne Noel", province: "QUEBEC", TOTAL: 10, - } + }]; const dataTransformerBuilder = new DataTransformerBuilder(); dataTransformerBuilder @@ -27,14 +27,47 @@ describe('Data Transformer', () => { .add() .setSourceProperty("TOTAL") .setDestinationProperty("total") + .end(); + + const destination = dataTransformer.transform(dataTransformerBuilder, source); + + expect(destination.length).toBe(1) + + expect(destination[0].name).toBeDefined() + expect(destination[0].name).toBe("Etienne Noel"); + expect(destination[0].province).toBe("quebec"); + expect(destination[0].total).toBe(10); + }) + it("should properly transform an array with numerical indices", () => { + const dataTransformer = new DataTransformer([new LowercaseNormalizer()]); + + const source = [ + ["Etienne Noel", "QUEBEC", 10], + ]; + + const dataTransformerBuilder = new DataTransformerBuilder(); + dataTransformerBuilder + .add() + .setSourceProperty("0") + .setDestinationProperty("name") + .end() + .add() + .setSourceProperty("1") + .addNormalizer(LowercaseNormalizer.name) + .setDestinationProperty("province") .end() + .add() + .setSourceProperty("2") + .setDestinationProperty("total") + .end(); + const destination = dataTransformer.transform(dataTransformerBuilder, source); - const destination = dataTransformer.transform(dataTransformerBuilder, source, {}); + expect(destination.length).toBe(1) - expect(destination.name).toBeDefined() - expect(destination.name).toBe("Etienne Noel"); - expect(destination.province).toBe("quebec"); - expect(destination.total).toBe(10); + expect(destination[0].name).toBeDefined() + expect(destination[0].name).toBe("Etienne Noel"); + expect(destination[0].province).toBe("quebec"); + expect(destination[0].total).toBe(10); }) }); \ No newline at end of file diff --git a/packages/data-transformer/src/transformers/data.transformer.ts b/packages/data-transformer/src/transformers/data.transformer.ts index 144414867..19e5a0b2c 100644 --- a/packages/data-transformer/src/transformers/data.transformer.ts +++ b/packages/data-transformer/src/transformers/data.transformer.ts @@ -1,5 +1,5 @@ import {injectable, injectAll} from "tsyringe"; -import {tag} from "@pristine-ts/common"; +import {moduleScoped, tag} from "@pristine-ts/common"; import {DataTransformerModuleKeyname} from "../data-transformer.module.keyname"; import {DataNormalizer} from "../interfaces/data-normalizer.interface"; import {DataTransformerBuilder} from "./data-transformer.builder"; @@ -7,7 +7,7 @@ import {DataTransformerProperty} from "./data-transformer.property"; import {DataTransformerSourcePropertyNotFoundError} from "../errors/data-transformer-source-property-not-found.error"; import {DataNormalizerUniqueKey} from "../types/data-normalizer-unique-key.type"; -@tag(DataTransformerModuleKeyname) +@moduleScoped(DataTransformerModuleKeyname) @injectable() export class DataTransformer { private readonly dataNormalizersMap: { [key in DataNormalizerUniqueKey]: DataNormalizer} = {} @@ -18,36 +18,50 @@ export class DataTransformer { }) } - public transform(builder: DataTransformerBuilder, source: any, destination: any) { + public transform(builder: DataTransformerBuilder, source: ({[key in string]: any} | any)[]): {[key in string]: any}[] { const globalNormalizers = builder.normalizers; - // Loop over the properties defined in the builder - for (let key in builder.properties) { - if(builder.properties.hasOwnProperty(key) === false) { + const destination: {[key in string]: any}[] = []; + + const row: any = {}; + for(const key in source) { + if(source.hasOwnProperty(key) === false) { continue; } - const property: DataTransformerProperty = builder.properties[key]; - if(source.hasOwnProperty(property.sourceProperty) === false) { - if(property.isOptional) { + const inputRow = source[key]; + + // Loop over the properties defined in the builder + for (const key in builder.properties) { + if(builder.properties.hasOwnProperty(key) === false) { continue; } - throw new DataTransformerSourcePropertyNotFoundError("The property '" + key + "' isn't found in the Source object and isn't marked as Optional. If you want to ignore this property, use the 'setIsOptional(true)' method in the builder.", key) - } + const property: DataTransformerProperty = builder.properties[key]; + if(inputRow.hasOwnProperty(property.sourceProperty) === false) { + if(property.isOptional) { + continue; + } - let value = source[property.sourceProperty]; + throw new DataTransformerSourcePropertyNotFoundError("The property '" + key + "' isn't found in the Source object and isn't marked as Optional. If you want to ignore this property, use the 'setIsOptional(true)' method in the builder.", key) + } - const normalizers = globalNormalizers.filter(element => property.excludedNormalizers.has(element.key) === false); - normalizers.push(...property.normalizers); + let value = inputRow[property.sourceProperty]; - normalizers.forEach(element => { - const dataNormalizer = this.dataNormalizersMap[element.key]; - value = dataNormalizer.normalize(value, element.options); - }) + // Remove the normalizers part of the excludedNormalizers + const normalizers = globalNormalizers.filter(element => property.excludedNormalizers.has(element.key) === false); + normalizers.push(...property.normalizers); + + normalizers.forEach(element => { + const dataNormalizer = this.dataNormalizersMap[element.key]; + value = dataNormalizer.normalize(value, element.options); + }) + + // Assign the resulting value in the destination + row[property.destinationProperty] = value; + } - // Assign the resulting value in the destination - destination[property.destinationProperty] = value; + destination.push(row); } return destination;