Skip to content

Commit

Permalink
feat(helper): add additonal types
Browse files Browse the repository at this point in the history
  • Loading branch information
tudormd committed Feb 2, 2022
1 parent fee007e commit b9c1b30
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 19 deletions.
3 changes: 2 additions & 1 deletion bin/prepublish.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { writeFileSync, copyFileSync } from 'fs';
import { EOL } from 'os';
import originPackage from '../package.json';

const distPackage: Record<string, any> = originPackage;
Expand All @@ -14,7 +15,7 @@ delete distPackage.files;
delete distPackage.directories;
delete distPackage['lint-staged'];

writeFileSync('./dist/package.json', JSON.stringify(distPackage, null, ' '));
writeFileSync('./dist/package.json', JSON.stringify(distPackage, null, 4) + EOL);

const copyFiles = ['README.md'];
for (const file of copyFiles) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@goparrot/square-connect-plus",
"description": "Extends the official Square Node.js SDK library with additional functionality",
"version": "0.5.0-dev-6619.1",
"version": "0.5.0-dev-6619.8",
"author": "Coroliov Oleg",
"license": "MIT",
"private": false,
Expand Down
26 changes: 15 additions & 11 deletions src/client/SquareClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import { exponentialDelay, mergeDeepProps, sleep } from '../utils';
import { CustomerClientApi } from './CustomerClientApi';

export class SquareClient {
private client: Client;
private readonly mergedConfig: ISquareClientMergedConfig;
private readonly defaultConfig: ISquareClientDefaultConfig = {
#client: Client;
readonly #mergedConfig: ISquareClientMergedConfig;
readonly #defaultConfig: ISquareClientDefaultConfig = {
retry: {
maxRetries: 6,
retryDelay: exponentialDelay,
Expand All @@ -38,8 +38,8 @@ export class SquareClient {
};

constructor(private readonly accessToken: string, config: ISquareClientConfig = {}) {
this.mergedConfig = mergeDeepProps(this.defaultConfig, config);
this.mergedConfig.logger = config.logger;
this.#mergedConfig = mergeDeepProps(this.#defaultConfig, config);
this.#mergedConfig.logger = config.logger;
}

/**
Expand All @@ -53,13 +53,13 @@ export class SquareClient {
}

getConfig(): ISquareClientMergedConfig {
return this.mergedConfig;
return this.#mergedConfig;
}

getOriginClient(): Client {
this.client = this.client ?? this.createOriginClient(this.accessToken, this.mergedConfig);
this.#client = this.#client ?? this.createOriginClient(this.accessToken, this.#mergedConfig);

return this.client;
return this.#client;
}

getApplePayApi(retryableMethods: string[] = []): ApplePayApi {
Expand Down Expand Up @@ -148,7 +148,7 @@ export class SquareClient {
}

private getLogger(): ILogger {
return this.mergedConfig.logger ?? (this.mergedConfig.logger = new NullLogger());
return this.#mergedConfig.logger ?? (this.#mergedConfig.logger = new NullLogger());
}

/**
Expand All @@ -162,7 +162,11 @@ export class SquareClient {
return async (...args: unknown[]): Promise<ApiResponse<T>> => {
const requestFn: (...arg: unknown[]) => Promise<ApiResponse<T>> = target[apiMethodName].bind(target, ...args);

this.getLogger().debug(`Square api request: ${JSON.stringify({ apiMethodName, args })}`);
this.getLogger().debug(
`Square api request: ${JSON.stringify({ apiMethodName, args }, (_, value) =>
typeof value === 'bigint' ? value.toString() + 'n' : value,
)}`,
);

try {
const response = await this.makeRetryable<ApiResponse<T>>(requestFn, apiMethodName, retryableMethods);
Expand All @@ -184,7 +188,7 @@ export class SquareClient {

private async makeRetryable<T>(promiseFn: (...arg: unknown[]) => Promise<T>, apiMethodName: string, retryableMethods: string[]): Promise<T> {
let retries: number = 0;
const { maxRetries, retryCondition = this.retryCondition } = this.mergedConfig.retry;
const { maxRetries, retryCondition = this.retryCondition } = this.#mergedConfig.retry;

async function retry(): Promise<T> {
try {
Expand Down
2 changes: 1 addition & 1 deletion src/exception/SquareApiException.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class SquareApiException extends Error implements ISquareApiException {
readonly url?: string;
readonly method?: string;

constructor(error: unknown, retries: number) {
constructor(error: unknown, retries: number = 0) {
super();
this.message = 'Square API error';
this.name = this.constructor.name;
Expand Down
12 changes: 11 additions & 1 deletion src/utils/SquareDataMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ import { recursiveBigIntToNumber, recursiveNumberToBigInt } from './helper';
export type IdempotencyFree<T> = Omit<T, 'idempotency_key' | 'idempotencyKey'>;

export class SquareDataMapper {
/**
*
* @param data
* @param recursiveReplaceBigInToNumber @default true
* @returns {T}
*/
static toOldFormat = <T extends ObjectLikeType>(data: ObjectLikeType, recursiveReplaceBigInToNumber: boolean = true): T => {
const object: T = SquareDataMapper.convert(data, snakeCase);

Expand All @@ -17,7 +23,11 @@ export class SquareDataMapper {
return object;
};

static toNewFormat = <T extends ObjectLikeType>(data: ObjectLikeType, recursiveReplaceNumberToBigInt: boolean = false): T => {
/**
* @param recursiveReplaceNumberToBigInt @default false
* @returns {T}
*/
static toNewFormat = <T extends ObjectLikeType>(data: ObjectLikeType, recursiveReplaceNumberToBigInt: boolean = true): T => {
const object: T = SquareDataMapper.convert(data, camelCase);

if (recursiveReplaceNumberToBigInt) {
Expand Down
4 changes: 2 additions & 2 deletions src/utils/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type ReturnRecursiveBigIntToNumberType<T> = T extends bigint
: T;

export function recursiveBigIntToNumber<T>(body: T): ReturnRecursiveBigIntToNumberType<T> {
if (!body || !['object', 'bigint'].includes(typeof body)) {
if (body === undefined || body === null || !['object', 'bigint'].includes(typeof body)) {
return body as ReturnRecursiveBigIntToNumberType<T>;
}

Expand Down Expand Up @@ -37,7 +37,7 @@ export type ReturnRecursiveNumberToBigIntType<T> = T extends number

/* global BigInt */
export function recursiveNumberToBigInt<T>(body: T): ReturnRecursiveNumberToBigIntType<T> {
if (!body || !['object', 'number'].includes(typeof body)) {
if (body === undefined || body === null || !['object', 'number'].includes(typeof body)) {
return body as ReturnRecursiveNumberToBigIntType<T>;
}

Expand Down
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './common.utils';
export * from './retry.utils';
export * from './SquareDataMapper';
export * from './helper';
export * from './isSquareApiException';
5 changes: 5 additions & 0 deletions src/utils/isSquareApiException.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SquareApiException } from '../exception';

export function isSquareApiException(error: Error | unknown): error is SquareApiException {
return error instanceof SquareApiException;
}
4 changes: 2 additions & 2 deletions test/unit/utils/SquareDataMapper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ describe('SquareDataMapper', () => {
],
};

SquareDataMapper.toNewFormat<SquareConnectOrder>(orderWithOldFormat).should.deep.equals({
SquareDataMapper.toNewFormat<SquareConnectOrder>(orderWithOldFormat, false).should.deep.equals({
...order,
lineItems: [{ ...order.lineItems![0], basePriceMoney: { ...order.lineItems![0].basePriceMoney, amount: 100 } }],
});
Expand All @@ -113,7 +113,7 @@ describe('SquareDataMapper', () => {
],
};

const { lineItems, locationId } = SquareDataMapper.toNewFormat<Order>(orderWithOldFormat, true);
const { lineItems, locationId } = SquareDataMapper.toNewFormat<Order>(orderWithOldFormat);
locationId.should.equal(orderWithOldFormat.location_id);
const { basePriceMoney, name, quantity }: OrderLineItem = lineItems![0];
name!.should.be.equal(orderWithOldFormat.line_items?.[0]?.name);
Expand Down
8 changes: 8 additions & 0 deletions test/unit/utils/helper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ describe('helper', () => {
};
recursiveBigIntToNumber(order).should.deep.equals(order);
});

it('should be ok 0 bigint', () => {
recursiveBigIntToNumber(0n).should.be.equal(0);
});
});

describe('#recursiveNumberToBigInt', () => {
Expand Down Expand Up @@ -105,6 +109,10 @@ describe('helper', () => {
expect(recursiveNumberToBigInt(null)).to.be.null;
});

it('should be ok with 0', () => {
assert.strictEqual(recursiveNumberToBigInt(0), 0n);
});

it('should be ok of object include null property', () => {
const order: ObjectLikeType = {
locationId: null,
Expand Down
47 changes: 47 additions & 0 deletions test/unit/utils/isSquareApiException.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { ApiError } from 'square';
import { isSquareApiException, SquareApiException } from '../../../src';

describe('isSquareApiException', () => {
it('should return true', () => {
const errors = [
{
category: 'RATE_LIMIT_ERROR',
code: 'RATE_LIMITED',
detail: 'fake 429 error',
},
];
const response = {
statusCode: 400,
headers: {
'user-agent': 'Square-TypeScript-SDK/17.0.0',
'Content-Type': 'application/json',
'Square-Version': '2021-12-15',
authorization: 'Bearer EAAAEDFfyeoo0XgXi-Dd7ofp_3W6eAcjHMClC3GlQR61xATqdVixe6v4kq21KgnL',
accept: 'application/json',
},
body: JSON.stringify({ errors }),
};

const apiError: ApiError = new ApiError(
{
response,
request: {
method: 'POST',
url: 'https://connect.squareupsandbox.com/v2/customers/search',
},
},
'',
);
isSquareApiException(new SquareApiException(apiError, 0)).should.equal(true);
});

it('should return false', () => {
// @ts-ignore
isSquareApiException(new ApiError({ request: {}, response: {} })).should.equal(false);
});

it('should return false (unknown)', () => {
const error: unknown = undefined;
isSquareApiException(error).should.equal(false);
});
});

0 comments on commit b9c1b30

Please sign in to comment.