Skip to content

Commit

Permalink
feat: throw if error fn (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
thalesog authored Aug 28, 2022
1 parent f4284ec commit 5de222b
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 32 deletions.
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@
"build:module": "tsc -p tsconfig.module.json",
"lint": "eslint --ignore-path .gitignore \"src/**/*.ts\"",
"format": "prettier --ignore-path .gitignore \"src/**/*.ts\" --write",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest --coverage",
"test": "vitest",
"coverage": "vitest --coverage",
"reset-hard": "git clean -dfx && git reset --hard && yarn install",
"prepare-release": "run-s reset-hard test",
"prepare": "husky install",
Expand Down
26 changes: 21 additions & 5 deletions src/create.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { generatePixObject } from './assembler';
import {
DynamicPixEmvElements,
PixDynamicObject,
PixElementType,
PixObject,
PixStaticObject,
StaticPixEmvElements,
} from './types/pixElements';
import { PixError } from './types/pixError';
Expand Down Expand Up @@ -41,23 +42,32 @@ const defaultStaticFields = {

export function createStaticPix(
params: CreateStaticPixParams
): PixObject | PixError {
): PixStaticObject | PixError {
if (params.merchantName.length > 25)
return {
error: true,
message: 'merchantName character limit exceeded (> 25)',
throwIfError: () => {
throw new Error('merchantName character limit exceeded (> 25)');
},
};

if (params.merchantCity.length > 15)
return {
error: true,
message: 'merchantCity character limit exceeded (> 15)',
throwIfError: () => {
throw new Error('merchantCity character limit exceeded (> 15)');
},
};

if (params.txid.length > 25)
return {
error: true,
message: 'txid character limit exceeded (> 25)',
throwIfError: () => {
throw new Error('txid character limit exceeded (> 25)');
},
};

const elements = {
Expand All @@ -66,22 +76,28 @@ export function createStaticPix(
...params,
} as StaticPixEmvElements;

return generatePixObject(elements);
return generatePixObject(elements) as PixStaticObject;
}

export function createDynamicPix(
params: CreateDynamicPixParams
): PixObject | PixError {
): PixDynamicObject | PixError {
if (params.merchantName.length > 25)
return {
error: true,
message: 'merchantName character limit exceeded (> 25)',
throwIfError: () => {
throw new Error('merchantName character limit exceeded (> 25)');
},
};

if (params.merchantCity.length > 15)
return {
error: true,
message: 'merchantCity character limit exceeded (> 15)',
throwIfError: () => {
throw new Error('merchantCity character limit exceeded (> 15)');
},
};

const elements = {
Expand All @@ -91,5 +107,5 @@ export function createDynamicPix(
merchantCity: params.merchantCity.substr(0, 15).toUpperCase(),
} as DynamicPixEmvElements;

return generatePixObject(elements);
return generatePixObject(elements) as PixDynamicObject;
}
10 changes: 4 additions & 6 deletions src/dynamicPayload.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Buffer } from 'buffer';

import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';

import { Buffer } from 'buffer';
import { PIXPayload } from './types/pixDynamicPayload';
import { PixError } from './types/pixError';
import { generateErrorObject } from './utils/generateErrorObject';
import zeroPad from './utils/zeroPad';

export type PIXFetchResults = {
Expand Down Expand Up @@ -37,7 +36,7 @@ export default async function fetchPayload({
return axios
.get('https://' + url, axiosOptions)
.then(({ data, status }: AxiosResponse) => {
if (status !== 200) return { error: true, message: 'Status != 200' };
if (status !== 200) return generateErrorObject('Status != 200');
return data;
})
.then((jws: string) => {
Expand All @@ -55,7 +54,6 @@ export default async function fetchPayload({
return pixFetch;
})
.catch((error) => {
console.error(error);
return { error: true, message: error.message };
return generateErrorObject(error.message);
});
}
12 changes: 6 additions & 6 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@ import {
ValidTags,
} from './types/pixEmvSchema';
import { PixError } from './types/pixError';
import { generateErrorObject } from './utils/generateErrorObject';
import { hasElementError, isPix } from './validate';

export function parsePix(brCode: string): PixObject | PixError {
// Parse EMV Code
const emvElements = parseEmv({ emvCode: brCode });
if (!emvElements.isValid) return { error: true, message: 'invalid emv code' };
if (!emvElements.isValid) return generateErrorObject('invalid emv code');

// Validate CRC16
const crc = computeCRC(brCode);
if (crc !== emvElements.getTag(EmvSchema.TAG_CRC))
return { error: true, message: 'invalid crc' };
return generateErrorObject('invalid crc');

// Extract Elements
const elements = extractElements(emvElements);

if (hasElementError(elements))
return { error: true, message: 'invalid emv code' };
if (hasElementError(elements)) return generateErrorObject(elements.message);

return generatePixObject(elements);
}
Expand Down Expand Up @@ -80,7 +80,7 @@ export function extractElements(
};
}
if (!isPix(emvElements, 'pix') || !isPix(emvElements, 'valid'))
return { error: true, message: 'invalid pix' };
return generateErrorObject('invalid pix');

return { error: true, message: 'error' };
return generateErrorObject('error');
}
1 change: 1 addition & 0 deletions src/types/pixError.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export type PixError = {
readonly error: boolean;
readonly message: string;
readonly throwIfError: () => never;
};
28 changes: 16 additions & 12 deletions src/types/pixFunctions.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { PIXFetchResults } from '../dynamicPayload';

import { PixDynamicObject, PixStaticObject } from './pixElements';
import { PixError } from './pixError';

export type PixFnDefault = {
export interface PixFnDefault {
readonly toBRCode: () => string;
readonly toImage: () => Promise<string>;
};
}

export type PixStaticFn = PixFnDefault;
export interface PixStaticFn extends PixFnDefault {
readonly throwIfError: () => PixStaticObject;
}

export type PixDynamicFn = PixFnDefault & {
readonly fetchPayload: ({
DPP,
codMun,
}: {
readonly DPP: string;
readonly codMun: number;
}) => Promise<PIXFetchResults | PixError>;
type FetchPayloadParams = {
DPP: string;
codMun: number;
};

export interface PixDynamicFn extends PixFnDefault {
readonly fetchPayload: (
params: FetchPayloadParams
) => Promise<PIXFetchResults | PixError>;
readonly throwIfError: () => PixDynamicObject;
}
11 changes: 11 additions & 0 deletions src/utils/generateErrorObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { PixError } from '../types/pixError';

export function generateErrorObject(message: string): PixError {
return {
error: true,
message,
throwIfError: () => {
throw new Error(message);
},
};
}
49 changes: 49 additions & 0 deletions tests/throwIfError.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { describe, expect, it } from 'vitest';
import { createStaticPix } from '../src';

describe('throwIfError', () => {
it('should throw if merchant city is longer than 15 characters', () => {
const staticPixFn = createStaticPix({
merchantName: 'Thales Ogliari',
merchantCity: 'SAO MIGUEL DO OESTE',
pixKey: '[email protected]',
infoAdicional: 'Pedido 123',
txid: '',
transactionAmount: 10,
});

expect(staticPixFn.throwIfError).toThrow(
'merchantCity character limit exceeded (> 15)'
);
});

it('should throw if merchant name is longer than 25 characters', () => {
const staticPixFn = createStaticPix({
merchantName: 'Thales Ogliari Thales Ogliari Thales Ogliari',
merchantCity: 'SAO MIGUEL',
pixKey: '[email protected]',
infoAdicional: 'Pedido 123',
txid: '',
transactionAmount: 10,
});

expect(staticPixFn.throwIfError).toThrow(
'merchantName character limit exceeded (> 25)'
);
});

it('should throw if txid is longer than 25 characters', () => {
const staticPixFn = createStaticPix({
merchantName: 'Thales Ogliari',
merchantCity: 'SAO MIGUEL',
pixKey: '[email protected]',
infoAdicional: 'Pedido 123',
txid: 'F2B8073B0A52461997F53FB2A85FE7E8',
transactionAmount: 10,
});

expect(staticPixFn.throwIfError).toThrow(
'txid character limit exceeded (> 25)'
);
});
});

0 comments on commit 5de222b

Please sign in to comment.