airhorn
Table of Contents
- Cloud Native Notifications
- Table of Contents
- Getting Started
- Airhorn Options
- Using Send Helper Methods
- Airhorn Send Response
- Send Strategies
- Airhorn API
- Using Webhooks
- Statistics
- Emitting Events
- Load Template Helper
- Core Supported Providers
- Third Party Providers
- Creating a Provider
- How to Contribute
- Licensing and Copyright
Cloud Native Notifications
Airhorn
simplifies the process of notifications by using templates to send messages across various providers with a common easy to use interface.
- Supports multiple notification types: SMS, Email, Mobile Push, Webhooks
- A unified API for all notification types using the
send()
method. - Hooks and Emitting built in by default for extendability and observability.
- Send Strategy (Round Robin, Fail Over, All) Choose the best delivery method for each notification.
- Built in Webhook support for sending notifications to external services.
- Built in support for retries and error handling on sends.
- Advanced caching on template compilation and execution.
- Load a template from a file for easy GitOps based workflows.
- Many supported providers such as Twilio (with Sendgrid), AWS, and Google Cloud.
- Robust (6+ template formats) templating via ecto
- Easily build your own provider with minimal effort via
AirhornProvider
interface. - Statistics tracking for send successes, failures, and execution times (instance only).
- ESM and Typescript based supporting Nodejs 20+
- Maintained on a regular basis with updates and improvements.
Table of Contents
- Getting Started
- Airhorn Options
- Using Send Helper Methods
- Airhorn Send Response
- Send Strategies
- Airhorn API
- Using Webhooks
- Statistics
- Emitting Events
- Load Template Helper
- Core Supported Providers
- Third Party Providers
- Creating a Provider
- How to Contribute
- Licensing and Copyright
Getting Started
To get started with Airhorn, you can install it via npm:
npm install airhorn
Once installed, this gives you the main send functionality and built in webhook support. You can use it in your project like so:
import { Airhorn, AirhornProviderType } from "airhorn";
const airhorn = new Airhorn();
const template = {
from: "https://mywebhookdomain.com",
content: "Hey <%= name %> this is a test message from Airhorn",
templateEngine: "ejs",
}
const data = { name: "John" };
await airhorn.send("https://mockhttp.org/post", template, data, AirhornProviderType.WEBHOOK);
Now lets configure the Airhorn instance with your preferred providers such as Twilio
for SMS and SendGrid
for Email.
npm install airhorn @airhorn/twilio
import { Airhorn, AirhornProviderType } from "airhorn";
import { AirhornTwilio } from "@airhorn/twilio";
const providers = [
new AirhornTwilio({
accountSid: "your_account_sid",
authToken: "your_auth_token"
}),
];
const airhorn = new Airhorn({
providers
});
// this will give you twilio and webhook (built in) support. Now lets create a template and send it!
const template = {
from: "+12223334444",
content: "Hey <%= name %> this is a test message from Airhorn",
templateEngine: "ejs",
}
const data = { name: "John" };
await airhorn.send("+1234567890", template, data, AirhornProviderType.SMS);
To learn about the available providers and their capabilities, check the Providers section.
Airhorn Options
Airhorn provides a variety of options to customize its behavior. You can configure these options when creating an instance of the Airhorn
class:
import { Airhorn, AirhornSendStrategy } from "airhorn";
const airhorn = new Airhorn({
sendStrategy: AirhornSendStrategy.RoundRobin
});
Here is the AirhornOptions
type:
export type AirhornOptions = {
/**
* Whether to enable caching.
* @default true
*/
cache?: boolean | Cacheable | CacheableOptions;
/**
* Whether to collect statistics.
* @default false
*/
statistics?: boolean;
/**
* The providers to add to the Airhorn instance. AirhornWebhook is added by default unless `useWebhookProvider` is set to false.
*/
providers?: Array<AirhornProvider>;
/**
* Whether to use the built-in webhook provider.
* @default true
*/
useWebhookProvider?: boolean;
/**
* The retry strategy to use when sending messages.
* @default 0
*/
retryStrategy?: AirhornRetryStrategy;
/**
* The timeout to use when sending messages.
* @default 100
*/
timeout?: number;
/**
* The send strategy to use when sending messages.
* @default AirhornSendStrategy.RoundRobin
*/
sendStrategy?: AirhornSendStrategy;
/**
* Whether to throw an error if sending fails. By default we use emitting for errors
* @default false
*/
throwOnErrors?: boolean;
};
Using Send Helper Methods
Airhorn provides helper methods for common tasks. For example, you can use the sendSMS
method to send SMS messages easily:
import { Airhorn } from "airhorn";
import { AirhornTwilio } from "@airhorn/twilio";
const providers = [
new AirhornTwilio({
accountSid: "your_account_sid",
authToken: "your_auth_token"
}),
];
const airhorn = new Airhorn({
providers
});
const template = {
from: "+12223334444",
content: "Hey <%= name %> this is a test message from Airhorn",
templateEngine: "ejs",
}
const data = { name: "John" };
await airhorn.sendSMS("+1234567890", template, data);
Here are the following helper methods available:
sendSMS
: Sends an SMS message.sendEmail
: Sends an email message.sendMobilePush
: Sends a mobile push notification.sendWebhook
: Sends a webhook notification.
Airhorn Send Response
The send
method returns an AirhornSendResult
object that contains information about the send operation. Here is the structure of the AirhornSendResult
type:
export type AirhornSendResult = {
/**
* The providers that were used to send the message.
*/
providers: Array<AirhornProvider>;
/**
* The message that was sent.
*/
message?: AirhornProviderMessage;
/**
* Whether the message was sent successfully.
*/
success: boolean;
/**
* The response from the provider.
*/
// biome-ignore lint/suspicious/noExplicitAny: expected
response: any;
/**
* The number of times the message was retried.
*/
retries: number;
/**
* The errors that occurred while sending the message.
*/
errors: Array<Error>;
/**
* The time taken to execute the send operation.
*/
executionTime: number;
};
Send Strategies
Airhorn supports multiple send strategies to control how notifications are delivered. You can choose from the following strategies:
- Round Robin: Distributes notifications evenly across all available providers.
- Fail Over: Tries each provider in order until one succeeds.
- All: Sends the notification to all providers simultaneously.
You can configure the send strategy when creating the Airhorn instance:
import { Airhorn, AirhornSendStrategy } from "airhorn";
const airhorn = new Airhorn({
sendStrategy: AirhornSendStrategy.RoundRobin
});
Airhorn API
Here are all the properties and methods available and a brief description of each:
.cache
: Gets the cache instance which is based oncacheable
..retryStrategy
: Gets the retry strategy..timeout
: Gets the timeout for sending messages..sendStrategy
: Gets the send strategy..throwOnErrors
: Gets the throw on errors flag..statistics
: Access the statistics instance. go to Statistics to learn more..providers
: Gets the list of configured providers.send()
: Sends a message using the configured providers.sendSMS()
: Sends an SMS message.sendEmail()
: Sends an email message.sendMobilePush()
: Sends a mobile push notification.sendWebhook()
: Sends a webhook notification.loadTemplate()
: Helper method that loads a template from the file system. Go to Load Template Helper to learn more.getProvidersByType()
: Gets the list of providers by type. (Used Internally)setCache()
: Sets the cache instance. (Used Internally)addProviders()
: Adds new providers to the Airhorn instance. (Used Internally)generateMessage()
: Generates a message from a template and data. (Used Internally)
Using Webhooks
Webhooks is built into Airhorn as a default provider and can be used to send notifications to external services. To use the built in webhooks just create an instance of the Airhorn
class and call the send
or sendWebhook
method.
An example using the send
method (recommended):
import { Airhorn, AirhornProviderType } from "airhorn";
const template = {
from: "+12223334444",
to: "+1234567890",
content: "Hey <%= name %> this is a test message from Airhorn",
templateEngine: "ejs",
}
const data = { name: "John" };
await airhorn.send("https://mockhttp.org/post", template, data, AirhornProviderType.WEBHOOK);
To send using the helper function sendWebhook
:
import { Airhorn } from "airhorn";
const airhorn = new Airhorn();
const template = {
from: "+12223334444",
to: "+1234567890",
content: "Hey <%= name %> this is a test message from Airhorn",
templateEngine: "ejs",
}
const data = { name: "John" };
await airhorn.sendWebhook("https://mockhttp.org/post", template, data);
Statistics
Airhorn provides built-in statistics to help you monitor the performance of your notifications. You can access the statistics instance through the .statistics
property:
import { Airhorn } from "airhorn";
const airhorn = new Airhorn({ statistics: true });
// Now you can use the stats object to get information about sent notifications
console.log(`Total Sends: ${airhorn.statistics.totalSends}`);
console.log(`Total Successful Sends: ${airhorn.statistics.totalSendSuccesses}`);
console.log(`Total Failed Sends: ${airhorn.statistics.totalSendFailures}`);
// execution time statistics
console.log(`Total Execution Time: ${airhorn.statistics.totalExecutionTime} ms`);
console.log(`Average Execution Time: ${airhorn.statistics.averageExecutionTime} ms`);
console.log(`Minimum Execution Time: ${airhorn.statistics.minimumExecutionTime} ms`);
console.log(`Maximum Execution Time: ${airhorn.statistics.maxExecutionTime} ms`);
// execution time data Array
console.log(`All Execution Times: ${airhorn.statistics.executionTimes}`);
console.log(`Slowest Execution Times: ${airhorn.statistics.slowestExecutionTimes}`);
console.log(`Fastest Execution Times: ${airhorn.statistics.fastestExecutionTimes}`);
By default, Airhorn statistics are disabled. You can enable them by setting the statistics
option to true
when creating the Airhorn instance. If you want to enable it after the Airhorn instance is created do the following:
import { Airhorn } from "airhorn";
const airhorn = new Airhorn();
airhorn.statistics.enable();
To reset the statistics, you can call the reset
method:
import { Airhorn } from "airhorn";
const airhorn = new Airhorn();
airhorn.statistics.reset();
Emitting Events
Airhorn provides event emitting by default with the following events:
error
: Emitted when there is an error.send.success
: Emitted when a notification is successfully sent.send.failure
: Emitted when a notification fails to send.
You can listen for these events using the on
method:
import { Airhorn, AirhornEvent, type AirhornSendResult } from "airhorn";
const airhorn = new Airhorn();
airhorn.on(AirhornEvent.SendSuccess, (data: AirhornSendResult) => {
console.log(`Notification sent successfully: ${data}`);
});
airhorn.on(AirhornEvent.SendFailure, (data: AirhornSendResult) => {
console.error(`Failed to send notification: ${data}`);
});
Load Template Helper
In previous versions of Airhon
we used the file system to load all the templates into a store that was used by the instance. Now, we offer an easy method to just load it from a markdown file if you want from anywhere on the file system.
Here is an example of how to use the loadTemplate
helper method:
import { Airhorn } from "airhorn";
const airhorn = new Airhorn();
const template = await airhorn.loadTemplate("path/to/template.md");
// now you can send with that template
await airhorn.send("https://mockhttp.org/post", template, data, AirhornProviderType.WEBHOOK);
An example of the markdown
format is located at ./packages/airhorn/test/fixtures
.
Core Supported Providers
We currently support twilio
, aws
, and azure
with thier offerings. Here is a chart showing what functionality is in each:
Provider | SMS | Push | Webhook | |
---|---|---|---|---|
(built in airhorn ) |
❌ | ❌ | ❌ | ✅ |
@airhorn/twilio |
✅ | ✅ | ❌ | ❌ |
@airhorn/aws |
✅ | ✅ | ✅ | ❌ |
@airhorn/azure |
✅ | ✅ | ✅ | ❌ |
Note: We used to support firebase because of mobile push but it made more sense to focus on aws
and azure
because it is more comprehensive.
Third Party Providers
If you have built a provider library let us know! We are more than happy to list it here!
Creating a Provider
To create a provider you can extend the AirhornProvider
interface and implement the required methods for your specific provider.
import { AirhornProvider } from "airhorn";
class MyCustomProvider implements AirhornProvider {
// Implement required methods
}
Once implemented, you can use your custom provider just like any other provider in Airhorn.
import { Airhorn, AirhornProvider } from "airhorn";
class MyCustomProvider implements AirhornProvider {
// Implement required methods
}
const airhorn = new Airhorn({
providers: [new MyCustomProvider()]
});
Use one of the built in providers as a reference such as @airhorn/twilio
.
How to Contribute
Now that you've set up your workspace, you're ready to contribute changes to the airhorn
repository you can refer to the CONTRIBUTING guide. If you have any questions please feel free to ask by creating an issue and label it question
.
Licensing and Copyright
This project is MIT License © Jared Wray