Skip to content

Commit 5001897

Browse files
feat: add email and phoneNumber formatters (#11050)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
1 parent 55ab46d commit 5001897

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

packages/formatters/__tests__/formatters.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import {
3030
underline,
3131
unorderedList,
3232
userMention,
33+
email,
34+
phoneNumber,
3335
} from '../src/index.js';
3436

3537
describe('Message formatters', () => {
@@ -348,6 +350,33 @@ describe('Message formatters', () => {
348350
});
349351
});
350352

353+
describe('email', () => {
354+
test('GIVEN an email THEN returns "<[email]>"', () => {
355+
expect<'<[email protected]>'>(email('[email protected]')).toEqual('<[email protected]>');
356+
});
357+
358+
test('GIVEN an email AND headers THEN returns "<[email]?[headers]>"', () => {
359+
expect<`<[email protected]?${string}>`>(email('[email protected]', { subject: 'Hello', body: 'World' })).toEqual(
360+
'<[email protected]?subject=Hello&body=World>',
361+
);
362+
});
363+
});
364+
365+
describe('phoneNumber', () => {
366+
test('GIVEN a phone number with + THEN returns "<[phoneNumber]>"', () => {
367+
expect<'<+1234567890>'>(phoneNumber('+1234567890')).toEqual('<+1234567890>');
368+
});
369+
370+
test('GIVEN a phone number without + THEN throws', () => {
371+
expect(() =>
372+
phoneNumber(
373+
// @ts-expect-error - Invalid input
374+
'1234567890',
375+
),
376+
).toThrowError();
377+
});
378+
});
379+
351380
describe('Faces', () => {
352381
test('GIVEN Faces.Shrug THEN returns "¯\\_(ツ)_/¯"', () => {
353382
expect<'¯\\_(ツ)_/¯'>(Faces.Shrug).toEqual('¯\\_(ツ)_/¯');

packages/formatters/src/formatters.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,60 @@ export function applicationDirectory<ApplicationId extends Snowflake, SKUId exte
658658
return skuId ? `${url}/${skuId}` : url;
659659
}
660660

661+
/**
662+
* Formats an email address into an email mention.
663+
*
664+
* @typeParam Email - This is inferred by the supplied email address
665+
* @param email - The email address to format
666+
*/
667+
export function email<Email extends string>(email: Email): `<${Email}>`;
668+
669+
/**
670+
* Formats an email address and headers into an email mention.
671+
*
672+
* @typeParam Email - This is inferred by the supplied email address
673+
* @param email - The email address to format
674+
* @param headers - Optional headers to include in the email mention
675+
*/
676+
export function email<Email extends string>(
677+
email: Email,
678+
headers: Record<string, string | readonly string[]> | undefined,
679+
): `<${Email}?${string}>`;
680+
681+
/**
682+
* Formats an email address into an email mention.
683+
*
684+
* @typeParam Email - This is inferred by the supplied email address
685+
* @param email - The email address to format
686+
* @param headers - Optional headers to include in the email mention
687+
*/
688+
export function email<Email extends string>(email: Email, headers?: Record<string, string | readonly string[]>) {
689+
if (headers) {
690+
// eslint-disable-next-line n/prefer-global/url-search-params
691+
const searchParams = new URLSearchParams(
692+
Object.fromEntries(Object.entries(headers).map(([key, value]) => [key.toLowerCase(), value])),
693+
);
694+
695+
return `<${email}?${searchParams.toString()}>` as const;
696+
}
697+
698+
return `<${email}>` as const;
699+
}
700+
701+
/**
702+
* Formats a phone number into a phone number mention.
703+
*
704+
* @typeParam PhoneNumber - This is inferred by the supplied phone number
705+
* @param phoneNumber - The phone number to format. Must start with a `+` sign.
706+
*/
707+
export function phoneNumber<PhoneNumber extends `+${string}`>(phoneNumber: PhoneNumber) {
708+
if (!phoneNumber.startsWith('+')) {
709+
throw new Error('Phone number must start with a "+" sign.');
710+
}
711+
712+
return `<${phoneNumber}>` as const;
713+
}
714+
661715
/**
662716
* The {@link https://discord.com/developers/docs/reference#message-formatting-timestamp-styles | message formatting timestamp styles}
663717
* supported by Discord.

0 commit comments

Comments
 (0)