Rokot - [Rocketmakers](http://www.rocketmakers.com/) TypeScript NodeJs Platform
npm install rokot-notificationRokot - Rocketmakers TypeScript NodeJs Platform
The Rokot Notification library provides a framework to create (JSON) Notification Messages and send them to users via a notification channel (email, apns and gcm 'out-the-box')
These notification messages are generally transcoded into some form of textual content (HTML/text), but could also directly contain the content to be sent
#### INotification
The library is based around the core concept of a notification message (INotification)
This should represent the real life data behind the user notification
Each notification should have:
1. a unique type (this is the key to indicate which handler will process the notification)
1. a recipient to indicate the audience of the notification - which can be string values (for use in a single transport scenario), or transport keys {email:"developer@code.com", apns:["ABC", "XYYZ"], gcm:"xds") to support multiple transports and multiple tokens
``typescript
import {INotification} from "rokot-notification";
export interface ISampleTemplateNotification extends INotification {
fail?: boolean;
}
`
`typescript`
const notification: ISampleTemplateNotification = {
type: "sample-underscore-template-message",
recipient: {
email:"developers@rocketmakers.com"
},
fail: false
}
#### INotificationHandler
Each notification type requires a notification handler
The framework provides this handler with decorators to add functions to support:
1. validating notifications before the transport method is called
1. creating template content (html/text content via underscore templates)
1. to pre cache the templates at startup (loading template content from disk/db early)
1. to validate the template execution at startup with test case notifications you provide
A simple notification handler that just utilise the transport
`typescript
import {notifications, INotification} from "rokot-notification";
import {INodemailerNotificationHandler, INodemailerNotificationTransport} from "rokot-notification/lib/nodemailer";
/* Define the shape of the Notification /
export interface ISimpleNotification extends INotification {
html: string;
text: string;
}
/**
Register this handler for the notification type via @notification.handler("simple")
NOTE: You dont need to export the notification handler
*/
@notifications.handler("simple")
class SimpleHandler implements INodemailerNotificationHandler
/**
register the nodemailer transport function via @notifications.transport()
*/
@notifications.transport()
async nodemailer(notification: ISimpleNotification, transport: INodemailerNotificationTransport) {
return await transport.send(notification.recipient, m => {
m.from = transport.getFromAddress(notification)
m.subject = Simple Email`
m.text = notification.text
m.html = notification.html
})
}
}
Or a complete example showing usage of all the functions
`typescript
import {notifications, UnderscoreFileSystemTemplateProcessorFactory, INotification} from "rokot-notification";
import {INodemailerNotificationHandler, INodemailerNotificationTransport} from "rokot-notification/lib/nodemailer";
import {ISampleTemplateNotification} from "./sampleTemplateNotification";
import {emailTo} from "../../settings";
/* The example templates processor factory /
const exampleTemplatesFactory = new UnderscoreFileSystemTemplateProcessorFactory("./source/test/examples/templates")
export const notificationType = "sample-underscore-template-message"
/* You dont need to export the notification handler/
@notifications.handler(notificationType)
class TemplateHandler implements INodemailerNotificationHandler
/* Validate the notification before its passed to the transport method /
@notifications.validator()
validate(notification: ISampleTemplateNotification){
return Promise.resolve(notification);
}
/* Provides a sample notification that will be validated against any @notification.template() functions /
@notifications.testCase()
testMessage() : ISampleTemplateNotification{
return {type: notificationType, recipient: {nodemailer: emailTo}, fail: true}
}
/* You can provide as many test cases as you like (to exercise the template generation) /
@notifications.testCase()
testMessage1() : ISampleTemplateNotification{
return {type: notificationType, recipient: {nodemailer: emailTo}, fail: false}
}
/* You can also inspect which @notification.template() function is requesting the data /
@notifications.testCase()
testMessage2(template: string) : ISampleTemplateNotification{
if (template === "text") {
// dont use this for the 'text' template
return
}
return {type: notificationType, recipient: {nodemailer: emailTo}}
}
/**
Using Underscore templates loaded from a root folder
These template providing function are pre-cached at startup to reduce runtime IO
*/
@notifications.template()
html(){
return exampleTemplatesFactory.create)
}
/* Using Underscore templates loaded from a root folder /
@notifications.template()
text() {
return exampleTemplatesFactory.create)
}
/* the nodemailer transport function /
@notifications.transport()
async nodemailer(notification: ISampleTemplateNotification, transport: INodemailerNotificationTransport) {
return await transport.send(notification.recipient, m => {
m.from = transport.getFromAddress(notification)
m.subject = Template Email`
// using templates.transform provides access to the pre-cached @notification.template() decorated function results
m.text = notifications.transformTemplate(notification, this.text)
m.html = notifications.transformTemplate(notification, this.html)
})
}
}
Or a notification handler using multiple transports
`typescript
import {notifications, INotification} from "rokot-notification";
import {INodemailerNotificationHandler, INodemailerNotificationTransport} from "rokot-notification/lib/nodemailer";
import {IApnsNotificationHandler, IApnsNotificationTransport} from "rokot-notification/lib/apns";
export interface IMultipleNotification extends INotification {
type: "sample-multi-channel-message"
count: number;
}
@notifications.handler("sample-multi-channel-message")
class MultipleHandler implements IApnsNotificationHandler
/* the apns transport function /
@notifications.transport()
async apns(notification: IMultipleNotification, transport: IApnsNotificationTransport) : Promise
return await transport.send(notification.recipient, n => {
n.body = Count of ${notification.count}
n.topic = "
})
}
/* the nodemailer transport function /
@notifications.transport()
async nodemailer(notification: IMultipleNotification, transport: INodemailerNotificationTransport) {
return await transport.send(notification.recipient, m => {
m.from = transport.getFromAddress(notification)
m.subject = Test EmailCount of ${notification.count}
m.text = Test HTML email
m.html = `
})
}
}
NOTE: There are 3 core notification handlers avaiable 'out-the-box' IApnsNotificationHandler, IGcmNotificationHandler and INodemailerNotificationHandler
#### NotificationDispatcher
The framework provides a NotificationDispatcher to route notifications to their dispatch handler
You need to create your Application NotificationDispatcher and configuring which transports are used
`typescript
import {NotificationDispatcherFactory} from "rokot-notification";
import {apnsInitializer, IApnsProviderOptions} from "rokot-notification/lib/apns";
import {sendgridInitializer,INodemailerSendgridOptions} from "rokot-notification/lib/nodemailer";
import {gcmInitializer,IGcmProviderOptions} from "rokot-notification/lib/gcm";
import {ConsoleLogger, Logger} from "rokot-log";
async function createDispatcher(nodemailerOptions: INodemailerSendgridOptions, apnsOptions: IApnsProviderOptions, gcmOptions: IGcmProviderOptions) {
const logger = ConsoleLogger.create("test-multiple-message-dispatcher")
const dispatcherFactory = new NotificationDispatcherFactory(logger)
return await dispatcherFactory.createDispatcher(
sendgridInitializer(logger, nodemailerOptions),
gcmInitializer(logger, gcmOptions),
apnsInitializer(logger, apnsOptions));
}
// createDispatcher({username:"sendgrid username", password:"send grid password"}, {token:{key:"/path/to.p8",keyId:"KEY_ID",teamId:"TEAM_ID"},production:false}, {apiKey:"
`
NOTE: You can create your own MessageHandler for any kind of notification channel you like, or change the Nodemailer transport (from the 'out-the-box' sendgrid)
#### Notification Client Generation
You can create a typescript file in the root of your source and include the source below (modifying the paths to match your handler locations)
This code will inspect the source code and generate a Notifications client - exposing methods for each of the notification types
`typescript
import {ConsoleLogger} from "rokot-log";
import {generateClient, getInterfaceFunctionName, getFolderFiles} from "rokot-notification/lib/client/generator";
const logger = ConsoleLogger.create("create notification client",{level:"info"})
/* Get all notification handler source files (all in a single folder) /
const files = getFolderFiles("./source/test/examples/handlers");
/* Generate a notification client /
generateClient(logger, files, "./source/test/examples/notifications.ts", {
/* override the method naming function /
functionName: getInterfaceFunctionName
})
`
#### Templates
HTML Template
`html`
Hello There <%= model.recipient.nodemailer || model.recipient.email || model.recipient %> (<%= model.type %>)
Process <%= model.fail ? "Failed" : "Ok" %>
Install via yarn
``
yarn add rokot-notification
Check out the examples in /package/source/test/examples` to see various dispatcher configs and message handlers
The testing framework used within the Rokot Platform!