Skip to content

Commit

Permalink
refactor(providers): migrate from sparkpost sdk to axios (#4785)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaldziuba03 authored Nov 9, 2023
1 parent 4bf6b44 commit 99056ef
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 37 deletions.
43 changes: 22 additions & 21 deletions pnpm-lock.yaml

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

3 changes: 3 additions & 0 deletions providers/sparkpost/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
moduleNameMapper: {
axios: 'axios/dist/node/axios.cjs',
},
};
2 changes: 1 addition & 1 deletion providers/sparkpost/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
},
"dependencies": {
"@novu/stateless": "^0.21.0",
"sparkpost": "^2.1.4"
"axios": "^1.6.0"
},
"devDependencies": {
"@istanbuljs/nyc-config-typescript": "^1.0.1",
Expand Down
16 changes: 16 additions & 0 deletions providers/sparkpost/src/lib/sparkpost.error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export interface ISparkPostErrorResponse {
errors: Array<{
description: string;
code: string;
message: string;
}>;
}

export class SparkPostError extends Error implements ISparkPostErrorResponse {
readonly errors: ISparkPostErrorResponse['errors'];

constructor(response: ISparkPostErrorResponse, readonly statusCode: number) {
super();
this.errors = response.errors;
}
}
63 changes: 48 additions & 15 deletions providers/sparkpost/src/lib/sparkpost.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,22 @@ import {
ICheckIntegrationResponse,
CheckIntegrationResponseEnum,
} from '@novu/stateless';
import axios, { AxiosError } from 'axios';
import { randomUUID } from 'crypto';
import SparkPost from 'sparkpost';
import { ISparkPostErrorResponse, SparkPostError } from './sparkpost.error';

interface ISparkPostResponse {
results: {
total_rejected_recipients: number;
total_accepted_recipients: number;
id: string;
};
}

export class SparkPostEmailProvider implements IEmailProvider {
readonly id = 'sparkpost';
readonly channelType = ChannelTypeEnum.EMAIL as ChannelTypeEnum.EMAIL;
private readonly client: SparkPost;
readonly channelType = ChannelTypeEnum.EMAIL;
private readonly endpoint: string;

constructor(
private config: {
Expand All @@ -22,10 +31,7 @@ export class SparkPostEmailProvider implements IEmailProvider {
senderName: string;
}
) {
const endpoint = this.getEndpoint(config.region);
this.client = new SparkPost(config.apiKey, {
endpoint,
});
this.endpoint = this.getEndpoint(config.region);
}

async sendMessage({
Expand All @@ -50,7 +56,7 @@ export class SparkPostEmailProvider implements IEmailProvider {
});
});

const sent = await this.client.transmissions.send({
const data = {
recipients,
content: {
from: from || this.config.from,
Expand All @@ -59,12 +65,29 @@ export class SparkPostEmailProvider implements IEmailProvider {
html,
attachments: files,
},
});

return {
id: sent.results.id,
date: new Date().toISOString(),
};

try {
const sent = await axios.post<ISparkPostResponse>(
'/transmissions',
data,
{
headers: {
'Content-Type': 'application/json',
Authorization: this.config.apiKey,
},
baseURL: this.endpoint,
}
);

return {
id: sent.data.results.id,
date: new Date().toISOString(),
};
} catch (err) {
this.createSparkPostError(err);
throw err;
}
}

async checkIntegration(
Expand Down Expand Up @@ -93,6 +116,16 @@ export class SparkPostEmailProvider implements IEmailProvider {
}
}

private createSparkPostError(err: unknown) {
if (axios.isAxiosError(err)) {
const response = (err as AxiosError<ISparkPostErrorResponse>).response;

if (response && response.data && response.data.errors) {
throw new SparkPostError(response.data, response.status);
}
}
}

private transformLegacyRegion(region: string | boolean) {
if (region === 'true' || region === true) return 'eu';

Expand All @@ -104,9 +137,9 @@ export class SparkPostEmailProvider implements IEmailProvider {

switch (region) {
case 'eu':
return 'https://api.eu.sparkpost.com:443';
return 'https://api.eu.sparkpost.com/api/v1';
default:
return;
return 'https://api.sparkpost.com/api/v1';
}
}
}

0 comments on commit 99056ef

Please sign in to comment.