Skip to content

Commit

Permalink
- Added useful updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
etiennenoel committed Oct 29, 2023
1 parent eca426b commit 7f7b756
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 37 deletions.
24 changes: 20 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ export interface DataNormalizer<T, R> {
* @param source
* @param options
*/
normalize(source: any, options: R): T;
normalize(source: any, options?: R): T;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ export class LowercaseNormalizer implements DataNormalizer<string, LowercaseNorm
return LowercaseNormalizer.name;
}

normalize(source: any, options: LowercaseNormalizerOptions): string {
normalize(source: any, options?: LowercaseNormalizerOptions): string {
if(typeof source !== "string") {
if(options.shouldThrowIfTypeIsNotString) {
if(options && options.shouldThrowIfTypeIsNotString) {
throw new NormalizerInvalidSourceTypeError("The 'LowercaseNormalizer' expects the source value to be of type 'string'. Type '" + typeof source+ "' was received.", this.getUniqueKey(), options, source, typeof source)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('Data Transformer Property', () => {
"optionA": true,
};

dataTransformerProperty.addExcludedNormalizer("normalizer");
dataTransformerProperty.excludeNormalizer("normalizer");

expect(dataTransformerProperty.excludedNormalizers.size).toBe(1);
expect(dataTransformerProperty.excludedNormalizers.has("normalizer")).toBeTruthy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
})
});
54 changes: 34 additions & 20 deletions packages/data-transformer/src/transformers/data.transformer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
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";
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<any, any>} = {}
Expand All @@ -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;
Expand Down

0 comments on commit 7f7b756

Please sign in to comment.