feat: made http service header reusable

This commit is contained in:
Brian Pooe 2023-06-17 12:38:13 +02:00
parent 7bfa7ed030
commit 56735efc13
11 changed files with 129 additions and 57 deletions

3
.env.sample Normal file
View file

@ -0,0 +1,3 @@
HTTP_TIMEOUT=
BASE_URL=
PAYSTACK_SECRET_KEY=

View file

@ -8,11 +8,9 @@ import { TransactionController } from './transactions/controllers/transaction.co
@Module({
imports: [
NsPaystackModule.registerAsync({
useFactory: (configService: ConfigService) => {
return {
secretKey: configService.get('PAYSTACK_SECRET_KEY')
};
},
useFactory: (configService: ConfigService) => ({
secretKey: configService.get('PAYSTACK_SECRET_KEY')
}),
inject: [ConfigService]
})
],

View file

@ -3,19 +3,11 @@ import { PsTransactionsService } from './services';
import { HttpModule } from '@nestjs/axios';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { ConfigurableModuleClass } from './helpers';
import { CustomHttpService } from './services/custom-http/custom-http.service';
@Module({
imports: [
HttpModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
timeout: configService.get('HTTP_TIMEOUT'),
baseURL: configService.get('BASE_URL')
}),
inject: [ConfigService]
})
],
providers: [PsTransactionsService, ConfigService],
imports: [HttpModule, ConfigModule],
providers: [PsTransactionsService, ConfigService, CustomHttpService],
exports: [PsTransactionsService]
})
export class NsPaystackModule extends ConfigurableModuleClass {}

View file

@ -0,0 +1,22 @@
import { CustomHttpService } from './custom-http.service';
import { TestBed } from '@automock/jest';
import { ConfigService } from '@nestjs/config';
describe('CustomHttpService', () => {
let service: CustomHttpService;
beforeAll(() => {
const { unit, unitRef } = TestBed.create(CustomHttpService)
.mock(ConfigService)
.using({
get: jest.fn()
})
.compile();
service = unit;
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View file

@ -0,0 +1,47 @@
import { Inject, Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { MODULE_OPTIONS_TOKEN, PsConfigModel } from '../../models';
import { AxiosRequestConfig, AxiosResponse } from 'axios';
import { Observable } from 'rxjs';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class CustomHttpService extends HttpService {
axiosRequestConfig: AxiosRequestConfig = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.appConfigService.secretKey}`
}
};
constructor(
@Inject(MODULE_OPTIONS_TOKEN)
private readonly appConfigService: PsConfigModel,
private readonly configService: ConfigService
) {
super();
this.axiosRef.defaults.timeout = configService.get('HTTP_TIMEOUT');
this.axiosRef.defaults.baseURL = configService.get('BASE_URL');
}
override get<T>(
url: string,
config?: AxiosRequestConfig
): Observable<AxiosResponse<T>> {
return super.get<T>(url, {
...config,
headers: this.axiosRequestConfig.headers
});
}
override post<T>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Observable<AxiosResponse<T>> {
return super.post<T>(url, data, {
...config,
headers: this.axiosRequestConfig.headers
});
}
}

View file

@ -1 +1,2 @@
export * from './transactions/ps-transactions.service';
export * from './transaction-split/transaction-split.service';

View file

@ -0,0 +1,26 @@
import { TransactionSplitService } from './transaction-split.service';
import { CustomHttpService } from '../custom-http/custom-http.service';
import { TestBed } from '@automock/jest';
describe(TransactionSplitService.name, () => {
let service: TransactionSplitService;
let httpService: jest.Mocked<CustomHttpService>;
beforeAll(() => {
const { unit, unitRef } = TestBed.create(TransactionSplitService)
.mock(CustomHttpService)
.using({
post: jest.fn(),
get: jest.fn()
})
.compile();
service = unit;
httpService = unitRef.get(CustomHttpService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View file

@ -0,0 +1,9 @@
import { Injectable } from '@nestjs/common';
import { CustomHttpService } from '../custom-http/custom-http.service';
@Injectable()
export class TransactionSplitService {
constructor(private readonly httpService: CustomHttpService) {}
// createSplit() {}
}

View file

@ -1,5 +1,4 @@
import { PsTransactionsService } from './ps-transactions.service';
import { HttpService } from '@nestjs/axios';
import { AxiosResponse } from 'axios';
import {
PsChargeTransactionRequestModel,
@ -22,14 +21,15 @@ import { fromExact, fromPartial } from '@total-typescript/shoehorn';
import { of } from 'rxjs';
import { TestBed } from '@automock/jest';
import { subscribeSpyTo } from '@hirez_io/observer-spy';
import { CustomHttpService } from '../custom-http/custom-http.service';
describe(PsTransactionsService.name, () => {
let service: PsTransactionsService;
let httpService: jest.Mocked<HttpService>;
let httpService: jest.Mocked<CustomHttpService>;
beforeAll(() => {
const { unit, unitRef } = TestBed.create(PsTransactionsService)
.mock(HttpService)
.mock(CustomHttpService)
.using({
post: jest.fn(),
get: jest.fn()
@ -38,7 +38,7 @@ describe(PsTransactionsService.name, () => {
service = unit;
httpService = unitRef.get(HttpService);
httpService = unitRef.get(CustomHttpService);
});
describe('initializeTransaction', () => {

View file

@ -1,8 +1,7 @@
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { BadRequestException, Injectable } from '@nestjs/common';
import {
PsChargeTransactionRequestModel,
PsChargeTransactionResponseModel,
PsConfigModel,
PsExportTransactionRequestModel,
PsExportTransactionResponseModel,
PsFetchTransactionResponseModel,
@ -17,25 +16,13 @@ import {
PsVerifyTransactionResponseModel,
PsViewTransactionTimeLineResponseModel
} from '../../models';
import { HttpService } from '@nestjs/axios';
import { Observable } from 'rxjs';
import { AxiosRequestConfig } from 'axios';
import { handleResponseAndError, MODULE_OPTIONS_TOKEN } from '../../helpers';
import { handleResponseAndError } from '../../helpers';
import { CustomHttpService } from '../custom-http/custom-http.service';
@Injectable()
export class PsTransactionsService {
axiosRequestConfig: AxiosRequestConfig = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.appConfig.secretKey}`
}
};
constructor(
@Inject(MODULE_OPTIONS_TOKEN)
private readonly appConfig: PsConfigModel,
private readonly httpService: HttpService
) {}
constructor(private readonly httpService: CustomHttpService) {}
/**
* Initialize a transaction
@ -50,8 +37,7 @@ export class PsTransactionsService {
return this.httpService
.post<PsInitializeTransactionResponseModel>(
'transaction/initialize',
payload,
this.axiosRequestConfig
payload
)
.pipe(handleResponseAndError());
}
@ -64,10 +50,7 @@ export class PsTransactionsService {
reference: string
): Observable<PsVerifyTransactionResponseModel> {
return this.httpService
.get<PsVerifyTransactionResponseModel>(
`transaction/verify/${reference}`,
this.axiosRequestConfig
)
.get<PsVerifyTransactionResponseModel>(`transaction/verify/${reference}`)
.pipe(handleResponseAndError());
}
@ -80,7 +63,6 @@ export class PsTransactionsService {
): Observable<PsListTransactionsResponseModel> {
return this.httpService
.get<PsListTransactionsResponseModel>('transaction', {
...this.axiosRequestConfig,
params: queryParamsPayload
})
.pipe(handleResponseAndError());
@ -94,10 +76,7 @@ export class PsTransactionsService {
transactionId: number
): Observable<PsFetchTransactionResponseModel> {
return this.httpService
.get<PsFetchTransactionResponseModel>(
`transaction/${transactionId}`,
this.axiosRequestConfig
)
.get<PsFetchTransactionResponseModel>(`transaction/${transactionId}`)
.pipe(handleResponseAndError());
}
@ -111,8 +90,7 @@ export class PsTransactionsService {
return this.httpService
.post<PsInitializeTransactionResponseModel>(
'transaction/charge_authorization',
payload,
this.axiosRequestConfig
payload
)
.pipe(handleResponseAndError());
}
@ -126,8 +104,7 @@ export class PsTransactionsService {
): Observable<PsViewTransactionTimeLineResponseModel> {
return this.httpService
.get<PsViewTransactionTimeLineResponseModel>(
`transaction/timeline/${idOrReference}`,
this.axiosRequestConfig
`transaction/timeline/${idOrReference}`
)
.pipe(handleResponseAndError());
}
@ -141,7 +118,6 @@ export class PsTransactionsService {
): Observable<PsTransactionTotalsResponseModel> {
return this.httpService
.get<PsTransactionTotalsResponseModel>(`transaction/totals`, {
...this.axiosRequestConfig,
params: queryParamsPayload
})
.pipe(handleResponseAndError());
@ -156,7 +132,6 @@ export class PsTransactionsService {
): Observable<PsExportTransactionResponseModel> {
return this.httpService
.get<PsTransactionTotalsResponseModel>(`transaction/export`, {
...this.axiosRequestConfig,
params: queryParamsPayload
})
.pipe(handleResponseAndError());
@ -172,8 +147,7 @@ export class PsTransactionsService {
return this.httpService
.post<PsInitializeTransactionResponseModel>(
'transaction/partial_debit',
payload,
this.axiosRequestConfig
payload
)
.pipe(handleResponseAndError());
}

View file

@ -1,5 +1,5 @@
module.exports = {
'{libs,apps, tools, .github}/**/*.{ts,js,json,md,html,css,scss,yml,yaml}': [
'{libs,apps,tools,.github}/**/*.{ts,js,json,md,html,css,scss,yml,yaml}': [
'nx affected --target typecheck --uncommitted',
'nx affected --target lint --uncommitted --fix true',
'nx affected --target test --uncommitted',