diff --git a/.husky/pre-commit b/.husky/pre-commit index 6697471..de886f7 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -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 diff --git a/lib/api.ts b/lib/api.ts index dd7408e..edd41b5 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -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'; @@ -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'); @@ -168,4 +176,4 @@ export class APIClient { } } -export { SendEmailRequest, SendPushRequest, SendSMSRequest } from './api/requests'; +export { SendEmailRequest, SendPushRequest, SendSMSRequest, SendInboxMessageRequest } from './api/requests'; diff --git a/lib/api/requests.ts b/lib/api/requests.ts index 104390d..fc04ee6 100644 --- a/lib/api/requests.ts +++ b/lib/api/requests.ts @@ -204,3 +204,37 @@ export class SendSMSRequest { }; } } + +export type InboxMessage = Partial; + +export type SendInboxMessageRequestRequiredOptions = { + identifiers: Identifiers; + transactional_message_id: string | number; +}; + +export type SendInboxMessageRequestOptionalOptions = Partial<{ + disable_message_retention: boolean; + queue_draft: boolean; + message_data: Record; + 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, + }; + } +} diff --git a/test/api.ts b/test/api.ts index 63bfde3..fc9a37a 100644 --- a/test/api.ts +++ b/test/api.ts @@ -7,6 +7,7 @@ import { SendEmailRequest, SendPushRequest, SendSMSRequest, + SendInboxMessageRequest, } from '../lib/api'; import { RegionUS, RegionEU } from '../lib/regions'; import { Filter, IdentifierType } from '../lib/types'; @@ -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), + ); +});