rokot-notification
Rokot - Rocketmakers TypeScript NodeJs Platform
Introduction
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
Core Components
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:
a unique type
(this is the key to indicate which handler will process the notification)
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
import { INotification } from " rokot-notification " ;
export interface ISampleTemplateNotification extends INotification {
fail ? : boolean ;
}
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:
validating notifications before the transport method is called
creating template content (html/text content via underscore templates)
to pre cache the templates at startup (loading template content from disk/db early)
to validate the template execution at startup with test case notifications you provide
A simple notification handler that just utilise the transport
import { notifications , INotification } from " rokot-notification " ;
import { INodemailerNotificationHandler , INodemailerNotificationTransport } from " rokot-notification/lib/nodemailer " ;
export interface ISimpleNotification extends INotification {
html : string ;
text : string ;
}
@ notifications . handler ( " simple " )
class SimpleHandler implements INodemailerNotificationHandler < ISimpleNotification > {
@ 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
import { notifications , UnderscoreFileSystemTemplateProcessorFactory , INotification } from " rokot-notification " ;
import { INodemailerNotificationHandler , INodemailerNotificationTransport } from " rokot-notification/lib/nodemailer " ;
import { ISampleTemplateNotification } from " ./sampleTemplateNotification " ;
import { emailTo } from " ../../settings " ;
const exampleTemplatesFactory = new UnderscoreFileSystemTemplateProcessorFactory ( " ./source/test/examples/templates " )
export const notificationType = " sample-underscore-template-message "
@ notifications . handler ( notificationType )
class TemplateHandler implements INodemailerNotificationHandler < ISampleTemplateNotification > {
@ notifications . validator ( )
validate ( notification : ISampleTemplateNotification ) {
return Promise . resolve ( notification ) ;
}
@ notifications . testCase ( )
testMessage ( ) : ISampleTemplateNotification {
return { type : notificationType , recipient : { nodemailer : emailTo } , fail : true }
}
@ notifications . testCase ( )
testMessage1 ( ) : ISampleTemplateNotification {
return { type : notificationType , recipient : { nodemailer : emailTo } , fail : false }
}
@ notifications . testCase ( )
testMessage2 ( template : string ) : ISampleTemplateNotification {
if ( template === " text " ) {
return
}
return { type : notificationType , recipient : { nodemailer : emailTo } }
}
@ notifications . template ( )
html ( ) {
return exampleTemplatesFactory . create < ISampleTemplateNotification > ( ` ${ notificationType } .html ` )
}
@ notifications . template ( )
text ( ) {
return exampleTemplatesFactory . create < ISampleTemplateNotification > ( ` ${ notificationType } .txt ` )
}
@ notifications . transport ( )
async nodemailer ( notification : ISampleTemplateNotification , transport : INodemailerNotificationTransport ) {
return await transport . send ( notification . recipient , m => {
m . from = transport . getFromAddress ( notification )
m . subject = ` Template Email `
m . text = notifications . transformTemplate ( notification , this . text )
m . html = notifications . transformTemplate ( notification , this . html )
} )
}
}
Or a notification handler using multiple transports
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 < IMultipleNotification > , INodemailerNotificationHandler < IMultipleNotification > {
@ notifications . transport ( )
async apns ( notification : IMultipleNotification , transport : IApnsNotificationTransport ) : Promise < any > {
return await transport . send ( notification . recipient , n => {
n . body = ` Count of ${ notification . count } `
n . topic = " <app package id> "
} )
}
@ notifications . transport ( )
async nodemailer ( notification : IMultipleNotification , transport : INodemailerNotificationTransport ) {
return await transport . send ( notification . recipient , m => {
m . from = transport . getFromAddress ( notification )
m . subject = ` Test Email `
m . text = ` Count of ${ notification . count } `
m . html = ` Test HTML email `
} )
}
}
NOTE: There are 3 core notification handlers avaiable 'out-the-box' IApnsNotificationHandler<TNotification>
, IGcmNotificationHandler<TNotification>
and INodemailerNotificationHandler<TNotification>
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
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 ) ) ;
}
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
import { ConsoleLogger } from " rokot-log " ;
import { generateClient , getInterfaceFunctionName , getFolderFiles } from " rokot-notification/lib/client/generator " ;
const logger = ConsoleLogger . create ( " create notification client " , { level : " info " } )
const files = getFolderFiles ( " ./source/test/examples/handlers " ) ;
generateClient ( logger , files , " ./source/test/examples/notifications.ts " , {
functionName : getInterfaceFunctionName
} )
Templates
HTML Template
< div >
Hello There <%= model.recipient.nodemailer || model.recipient.email || model.recipient %> (<%= model.type %>)
Process <%= model.fail ? "Failed" : "Ok" %>
</ div >
Getting Started
Installation
Install via yarn
yarn add rokot-notification
Further Examples
Check out the examples in /package/source/test/examples
to see various dispatcher configs and message handlers
Consumed Libraries
Android Push Notifications
Apple Push Notifications
Email Notifications
Email via sendgrid transport
The testing framework used within the Rokot Platform!