Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

ts-node ./check-version.ts
pretty-quick --staged
npx ts-node ./check-version.ts
npx pretty-quick --staged
12 changes: 10 additions & 2 deletions lib/api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { RequestOptions } from 'https';
import Request, { BearerAuth, RequestData } from './request';
import { Region, RegionUS } from './regions';
import { SendEmailRequest, SendPushRequest, SendSMSRequest } from './api/requests';
import { SendEmailRequest, SendPushRequest, SendSMSRequest, SendInboxMessageRequest } from './api/requests';
import { cleanEmail, isEmpty, isIdentifierType, MissingParamError } from './utils';
import { Filter, IdentifierType } from './types';

Expand Down Expand Up @@ -93,6 +93,14 @@ export class APIClient {
return this.request.post(`${this.apiRoot}/send/sms`, req.message);
}

sendInboxMessage(req: SendInboxMessageRequest) {
if (!(req instanceof SendInboxMessageRequest)) {
throw new Error('"request" must be an instance of SendInboxMessageRequest');
}

return this.request.post(`${this.apiRoot}/send/inbox_message`, req.message);
}

getCustomersByEmail(email: string) {
if (typeof email !== 'string' || isEmpty(email)) {
throw new Error('"email" must be a string');
Expand Down Expand Up @@ -168,4 +176,4 @@ export class APIClient {
}
}

export { SendEmailRequest, SendPushRequest, SendSMSRequest } from './api/requests';
export { SendEmailRequest, SendPushRequest, SendSMSRequest, SendInboxMessageRequest } from './api/requests';
34 changes: 34 additions & 0 deletions lib/api/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,37 @@ export class SendSMSRequest {
};
}
}

export type InboxMessage = Partial<SendInboxMessageRequestOptions>;

export type SendInboxMessageRequestRequiredOptions = {
identifiers: Identifiers;
transactional_message_id: string | number;
};

export type SendInboxMessageRequestOptionalOptions = Partial<{
disable_message_retention: boolean;
queue_draft: boolean;
message_data: Record<string, any>;
send_at: number;
language: string;
}>;

export type SendInboxMessageRequestOptions = SendInboxMessageRequestRequiredOptions &
SendInboxMessageRequestOptionalOptions & {};

export class SendInboxMessageRequest {
message: InboxMessage;

constructor(opts: SendInboxMessageRequestOptions) {
this.message = {
identifiers: opts.identifiers,
transactional_message_id: opts.transactional_message_id,
disable_message_retention: opts.disable_message_retention,
queue_draft: opts.queue_draft,
message_data: opts.message_data,
send_at: opts.send_at,
language: opts.language,
};
}
}
81 changes: 81 additions & 0 deletions test/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
SendEmailRequest,
SendPushRequest,
SendSMSRequest,
SendInboxMessageRequest,
} from '../lib/api';
import { RegionUS, RegionEU } from '../lib/regions';
import { Filter, IdentifierType } from '../lib/types';
Expand Down Expand Up @@ -565,3 +566,83 @@ test('#sendSMS: error', async (t) => {

t.truthy((t.context.client.request.post as SinonStub).calledWith(`${RegionUS.apiUrl}/send/sms`, req.message));
});

test('sendInboxMessage: passing in a plain object throws an error', (t) => {
sinon.stub(t.context.client.request, 'post');

let req = { identifiers: { id: '2' }, transactional_message_id: 1 };

t.throws(() => t.context.client.sendInboxMessage(req as any), {
message: /"request" must be an instance of SendInboxMessageRequest/,
});
t.falsy((t.context.client.request.post as SinonStub).calledWith(`${RegionUS.apiUrl}/send/inbox_message`));
});

test('#sendInboxMessage: with template: success', (t) => {
sinon.stub(t.context.client.request, 'post');
let req = new SendInboxMessageRequest({
identifiers: { id: '2' },
transactional_message_id: 1,
});
t.context.client.sendInboxMessage(req);
t.truthy(
(t.context.client.request.post as SinonStub).calledWith(`${RegionUS.apiUrl}/send/inbox_message`, req.message),
);
t.is(req.message.transactional_message_id, 1);
t.deepEqual(req.message.identifiers, { id: '2' });
});

test('#sendInboxMessage: with optional parameters: success', (t) => {
sinon.stub(t.context.client.request, 'post');
let req = new SendInboxMessageRequest({
identifiers: { id: '2' },
transactional_message_id: 1,
message_data: { key: 'value' },
disable_message_retention: true,
queue_draft: true,
send_at: 1234567890,
language: 'en',
});
t.context.client.sendInboxMessage(req);
t.truthy(
(t.context.client.request.post as SinonStub).calledWith(`${RegionUS.apiUrl}/send/inbox_message`, req.message),
);
t.is(req.message.transactional_message_id, 1);
t.deepEqual(req.message.identifiers, { id: '2' });
t.deepEqual(req.message.message_data, { key: 'value' });
t.true(req.message.disable_message_retention);
t.true(req.message.queue_draft);
t.is(req.message.send_at, 1234567890);
t.is(req.message.language, 'en');
});

test('#sendInboxMessage: with email identifier: success', (t) => {
sinon.stub(t.context.client.request, 'post');
let req = new SendInboxMessageRequest({
identifiers: { email: 'test@example.com' },
transactional_message_id: 1,
});
t.context.client.sendInboxMessage(req);
t.truthy(
(t.context.client.request.post as SinonStub).calledWith(`${RegionUS.apiUrl}/send/inbox_message`, req.message),
);
t.is(req.message.transactional_message_id, 1);
t.deepEqual(req.message.identifiers, { email: 'test@example.com' });
});

test('#sendInboxMessage: error', async (t) => {
sinon.stub(t.context.client.request, 'post').rejects({ message: 'sample error', statusCode: 400 });

let req = new SendInboxMessageRequest({
identifiers: { id: '2' },
transactional_message_id: 1,
});
t.context.client.sendInboxMessage(req).catch((err) => {
t.is(err.message, 'sample error');
t.is(err.statusCode, 400);
});

t.truthy(
(t.context.client.request.post as SinonStub).calledWith(`${RegionUS.apiUrl}/send/inbox_message`, req.message),
);
});