Skip to content

Commit

Permalink
refactor: improve data validation
Browse files Browse the repository at this point in the history
  • Loading branch information
schoero committed Sep 20, 2023
1 parent b5ba92c commit b3140d9
Show file tree
Hide file tree
Showing 15 changed files with 1,303 additions and 219 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
},
"sideEffects": false,
"exports": {
"./errors": {
"import": "./lib/esm/shared/errors.js",
"require": "./lib/cjs/shared/errors.js"
},
"./pdf": {
"import": "./lib/esm/pdf/swissqrbill.js",
"require": "./lib/cjs/pdf/swissqrbill.js"
Expand Down
2 changes: 1 addition & 1 deletion src/pdf/swissqrbill.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";

import { utils } from "swissqrbill:node/index.js";
import { mm2pt } from "swissqrbill:shared/utils.js";
import { minimalRequired } from "swissqrbill:tests:data/data.js";
import { minimalRequired } from "swissqrbill:tests:data/valid-data.js";
import { TestDocument } from "swissqrbill:tests:utils/pdf.js";

import { SwissQRBill } from "./swissqrbill.js";
Expand Down
4 changes: 3 additions & 1 deletion src/pdf/swissqrbill.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { validateData } from "swissqrbill:shared/validator.js";

import { generateQRData, renderQRCode } from "../shared/qr-code.js";
import { cleanData, validateData } from "../shared/shared.js";
import { cleanData } from "../shared/cleaner.js";
import translations from "../shared/translations.js";
import * as utils from "../shared/utils.js";

Expand Down
Empty file added src/shared/cleaner.test.ts
Empty file.
45 changes: 45 additions & 0 deletions src/shared/cleaner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { Creditor, Data, Debtor } from "./types.js";


export function cleanData(data: Data): Data {

const _cleanObject = <ObjectType extends Creditor | Data | Debtor>(object: ObjectType): ObjectType => {

return Object.fromEntries(
Object.entries(object).map(([key, value]) => {

if(typeof value === "object"){
return [key, _cleanObject(value)];
}

if(typeof value === "string"){
if(key === "account"){
return [key, removeLineBreaks(removeSpaces(value))];
}
if(key === "reference"){
return [key, removeLineBreaks(removeSpaces(value))];
}
if(key === "country"){
return [key, removeLineBreaks(removeSpaces(value).toUpperCase())];
}
return [key, removeLineBreaks(value)];
}

return [key, value];
})
) as ObjectType;
};

return _cleanObject(data);

}

export function removeSpaces(text: string): string {
return text.replace(/ /g, "");
}

export function removeLineBreaks(text: string): string {
return text
.replace(/\n/g, "")
.replace(/\r/g, "");
}
80 changes: 80 additions & 0 deletions src/shared/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
export class ValidationError extends Error {
constructor(message: string, params?: { [name: string]: string; }) {

const messageWithParams = params
? resolveMessageParams(message, params)
: message;

super(messageWithParams);
this.name = "ValidationError";
}
}

export function resolveMessageParams(message: string, params: { [name: string]: string; }): string {
return Object.entries(params).reduce((message, [key, value]) => {
return message.replace(`{${key}}`, value);
}, message);
}

export enum ValidationErrors {
ACCOUNT_IS_QR_IBAN_BUT_REFERENCE_IS_MISSING = "If there is no reference, a conventional IBAN must be used.",
ACCOUNT_IS_QR_IBAN_BUT_REFERENCE_IS_REGULAR = "QR-IBAN requires the use of a QR-Reference.",
ACCOUNT_IS_REGULAR_IBAN_BUT_REFERENCE_IS_QR = "QR-Reference requires the use of a QR-IBAN.",
ACCOUNT_LENGTH_IS_INVALID = "The provided IBAN number '{iban}' is either too long or too short.",
ADDITIONAL_INFORMATION_LENGTH_IS_INVALID = "Additional information must be a maximum of 140 characters.",
ADDITIONAL_INFORMATION_TYPE_IS_INVALID = "Additional information must be a string.",
ALTERNATIVE_SCHEME_LENGTH_IS_INVALID = "{scheme} must be a maximum of 100 characters.",
ALTERNATIVE_SCHEME_TYPE_IS_INVALID = "{scheme} must be a string.",
AMOUNT_LENGTH_IS_INVALID = "Amount must be a maximum of 12 digits.",
AMOUNT_TYPE_IS_INVALID = "Amount must be a number.",
CREDITOR_ACCOUNT_COUNTRY_IS_INVALID = "Only CH and LI IBAN numbers are allowed.",
CREDITOR_ACCOUNT_IS_INVALID = "The provided IBAN number '{iban}' is not valid.",
CREDITOR_ACCOUNT_IS_UNDEFINED = "Creditor account cannot be undefined.",
CREDITOR_ADDRESS_IS_UNDEFINED = "Creditor address cannot be undefined.",
CREDITOR_ADDRESS_LENGTH_IS_INVALID = "Creditor address must be a maximum of 70 characters.",
CREDITOR_ADDRESS_TYPE_IS_INVALID = "Creditor address TYPE must be a string.",
CREDITOR_BUILDING_NUMBER_LENGTH_IS_INVALID = "Creditor buildingNumber must be a maximum of 16 characters.",
CREDITOR_BUILDING_NUMBER_TYPE_IS_INVALID = "Creditor buildingNumber must be either a string or a number.",
CREDITOR_CITY_IS_UNDEFINED = "Creditor city cannot be undefined.",
CREDITOR_CITY_LENGTH_IS_INVALID = "Creditor city must be a maximum of 35 characters.",
CREDITOR_CITY_TYPE_IS_INVALID = "Creditor city must be a string.",
CREDITOR_COUNTRY_IS_UNDEFINED = "Creditor country cannot be undefined.",
CREDITOR_COUNTRY_LENGTH_IS_INVALID = "Creditor country must be 2 characters.",
CREDITOR_COUNTRY_TYPE_IS_INVALID = "Creditor country must be a string.",
CREDITOR_IS_UNDEFINED = "Creditor cannot be undefined.",
CREDITOR_NAME_IS_UNDEFINED = "Creditor name cannot be undefined.",
CREDITOR_NAME_LENGTH_IS_INVALID = "Creditor name must be a maximum of 70 characters.",
CREDITOR_NAME_TYPE_IS_INVALID = "Creditor name must be a string.",
CREDITOR_ZIP_IS_UNDEFINED = "Creditor zip cannot be undefined.",
CREDITOR_ZIP_LENGTH_IS_INVALID = "Creditor zip must be a maximum of 16 characters.",
CREDITOR_ZIP_TYPE_IS_INVALID = "Creditor zip must be either a string or a number.",
CURRENCY_IS_UNDEFINED = "Currency cannot be undefined.",
CURRENCY_LENGTH_IS_INVALID = "Currency must be a length of 3 characters.",
CURRENCY_STRING_IS_INVALID = "Currency must be either 'CHF' or 'EUR'",
CURRENCY_TYPE_IS_INVALID = "Currency must be a string.",
DEBTOR_ADDRESS_IS_UNDEFINED = "Debtor address cannot be undefined.",
DEBTOR_ADDRESS_LENGTH_IS_INVALID = "Debtor address must be a maximum of 70 characters.",
DEBTOR_ADDRESS_TYPE_IS_INVALID = "Debtor address TYPE must be a string.",
DEBTOR_BUILDING_NUMBER_LENGTH_IS_INVALID = "Debtor buildingNumber must be a maximum of 16 characters.",
DEBTOR_BUILDING_NUMBER_TYPE_IS_INVALID = "Debtor buildingNumber must be either a string or a number.",
DEBTOR_CITY_IS_UNDEFINED = "Debtor city cannot be undefined.",
DEBTOR_CITY_LENGTH_IS_INVALID = "Debtor city must be a maximum of 35 characters.",
DEBTOR_CITY_TYPE_IS_INVALID = "Debtor city must be a string.",
DEBTOR_COUNTRY_IS_UNDEFINED = "Debtor country cannot be undefined.",
DEBTOR_COUNTRY_LENGTH_IS_INVALID = "Debtor country must be 2 characters.",
DEBTOR_COUNTRY_TYPE_IS_INVALID = "Debtor country must be a string.",
DEBTOR_IS_UNDEFINED = "Debtor cannot be undefined.",
DEBTOR_NAME_IS_UNDEFINED = "Debtor name cannot be undefined.",
DEBTOR_NAME_LENGTH_IS_INVALID = "Debtor name must be a maximum of 70 characters.",
DEBTOR_NAME_TYPE_IS_INVALID = "Debtor name must be a string.",
DEBTOR_ZIP_IS_UNDEFINED = "Debtor zip cannot be undefined.",
DEBTOR_ZIP_LENGTH_IS_INVALID = "Debtor zip must be a maximum of 16 characters.",
DEBTOR_ZIP_TYPE_IS_INVALID = "Debtor zip must be either a string or a number.",
MESSAGE_AND_ADDITIONAL_INFORMATION_LENGTH_IS_INVALID = "Message and additionalInformation combined must be a maximum of 140 characters.",
MESSAGE_LENGTH_IS_INVALID = "Message must be a maximum of 140 characters.",
MESSAGE_TYPE_IS_INVALID = "Message must be a string.",
QR_REFERENCE_IS_INVALID = "The provided QR-Reference '{reference}' is not valid.",
QR_REFERENCE_LENGTH_IS_INVALID = "QR-Reference must be a must be exactly 27 characters.",
REFERENCE_TYPE_IS_INVALID = "Reference must be a string.",
REGULAR_REFERENCE_LENGTH_IS_INVALID = "Creditor reference must be a maximum of 25 characters."
}
2 changes: 1 addition & 1 deletion src/shared/qr-code.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
minimalRequiredWithEuro,
minimalRequiredWithMaxedOutMessage,
minimalRequiredWithMessage
} from "swissqrbill:tests:data/data.js";
} from "swissqrbill:tests:data/valid-data.js";


describe("generateQRData", () => {
Expand Down
212 changes: 0 additions & 212 deletions src/shared/shared.ts

This file was deleted.

Loading

0 comments on commit b3140d9

Please sign in to comment.