npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

notifme-sdk

v1.16.20

Published

Unified notification SDK (emails, SMS, pushes, webpushes...) for Node.js

Downloads

14,335

Readme

Features

  • Easy channel integration — Want to start sending emails | SMS | pushes | webpushes | slack? Do so in no time!

  • Unique documentation — Don't look everywhere for the parameters you need to pass, just do it once. Switching provider becomes a no-brainer.

  • Multiple providers strategies — Want to use more than one provider? Use fallback and round-robin strategies out of the box.

  • Tools for local testing — Run a catcher locally to intercept all your notifications and display them in a web interface.

  • MIT license — Use it like you want.

Getting Started

$ yarn add notifme-sdk
import NotifmeSdk from 'notifme-sdk'

const notifmeSdk = new NotifmeSdk({}) // empty config = all providers are set to console.log
notifmeSdk
  .send({sms: {from: '+15000000000', to: '+15000000001', text: 'Hello, how are you?'}})
  .then(console.log)

:sparkles: Congratulations, you should see the following lines in your console:

Getting started SMS log

[Recommended] Setup Notification Catcher for your local tests

Notification Catcher is a web interface for viewing and testing notifications during development.

$ yarn add --dev notification-catcher
$ yarn run notification-catcher
import NotifmeSdk from 'notifme-sdk'

const notifmeSdk = new NotifmeSdk({
  useNotificationCatcher: true // <= this sends all your notifications to the catcher running on port 1025
})
notifmeSdk
  .send({sms: {from: '+15000000000', to: '+15000000001', text: 'Hello, how are you?'}})
  .then(console.log)

:heart_eyes_cat: Open http://localhost:1080 on your favorite browser, you should see the notification:

Getting started SMS catcher

Custom connection settings

If you have the Notification Catcher running on a custom port, domain, or you need to change any other connection setting, set the environment variable NOTIFME_CATCHER_OPTIONS with your custom connection smtp url.

$ # Example
$ NOTIFME_CATCHER_OPTIONS=smtp://127.0.0.1:3025?ignoreTLS=true node your-script-using-notifme.js

How to use

1. General options

new NotifmeSdk({
  channels: ..., // Object
  useNotificationCatcher: ... // boolean
})

| Option name | Required | Type | Description | | --- | --- | --- | --- | | channels | false | Object | Define providers (Array) and multiProviderStrategy (string) for each channel (email, sms, push, webpush, slack).See all details below: 2. Providers. | | useNotificationCatcher | false | boolean | If true, all your notifications are sent to the catcher running on localhost:1025 (channels option will be completely ignored!) |

Complete examples

// Env: development
new NotifmeSdk({
  useNotificationCatcher: true
})

// Env: production
new NotifmeSdk({
  channels: {
    email: {
      // If "Provider1" fails, use "Provider2"
      multiProviderStrategy: 'fallback',
      providers: [{
        type: 'Provider1',
        // ...credentials
      }, {
        type: 'Provider2',
        // ...credentials
      }]
    },
    sms: {
      // Use "Provider1" and "Provider2" in turns (and fallback if error)
      multiProviderStrategy: 'roundrobin',
      providers: [{
        type: 'Provider1',
        // ...credentials
      }, {
        type: 'Provider2',
        // ...credentials
      }]
    }
  }
})

HTTP proxy option

If you want to use a HTTP proxy, set an environment variable NOTIFME_HTTP_PROXY.

$ # Example
$ NOTIFME_HTTP_PROXY=http://127.0.0.1:8580 node your-script-using-notifme.js

2. Providers

Email providers

new NotifmeSdk({
  channels: {
    email: {
      providers: [{
        type: 'logger'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    email: {
      providers: [{
        type: 'smtp',
        host: 'smtp.example.com',
        port: 465,
        secure: true,
        auth: {
          user: 'xxxxx',
          pass: 'xxxxx'
        }
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    email: {
      providers: [{
        type: 'sendmail',
        sendmail: true,
        newline: 'unix',
        path: '/usr/sbin/sendmail'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    email: {
      providers: [{
        type: 'mailgun',
        apiKey: 'xxxxx',
        domainName: 'example.com'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    email: {
      providers: [{
        type: 'mandrill',
        apiKey: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    email: {
      providers: [{
        type: 'sendgrid',
        apiKey: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    email: {
      providers: [{
        type: 'ses',
        region: 'xxxxx',
        accessKeyId: 'xxxxx',
        secretAccessKey: 'xxxxx',
        sessionToken: 'xxxxx' // optional
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    email: {
      providers: [{
        type: 'sparkpost',
        apiKey: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    email: {
      providers: [{
        type: 'custom',
        id: 'my-custom-email-provider...',
        send: async (request) => {
          // Send email
          return 'id...'
        }
      }]
    }
  }
})

request being of the following type.

See all options: Email provider options

SMS providers

new NotifmeSdk({
  channels: {
    sms: {
      providers: [{
        type: 'logger'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    sms: {
      providers: [{
        type: '46elks',
        apiUsername: 'xxxxx',
        apiPassword: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    sms: {
      providers: [{
        type: 'callr',
        login: 'xxxxx',
        password: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    sms: {
      providers: [{
        type: 'clickatell',
        apiKey: 'xxxxx' // One-way integration API key
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    sms: {
      providers: [{
        type: 'infobip',
        username: 'xxxxx',
        password: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    sms: {
      providers: [{
        type: 'nexmo',
        apiKey: 'xxxxx',
        apiSecret: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    sms: {
      providers: [{
        type: 'ovh',
        appKey: 'xxxxx',
        appSecret: 'xxxxx',
        consumerKey: 'xxxxx',
        account: 'xxxxx',
        host: 'xxxxx' // https://github.com/ovh/node-ovh/blob/master/lib/endpoints.js
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    sms: {
      providers: [{
        type: 'plivo',
        authId: 'xxxxx',
        authToken: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    sms: {
      providers: [{
        type: 'twilio',
        accountSid: 'xxxxx',
        authToken: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    sms: {
      providers: [{
        type: 'seven',
        apiKey: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    sms: {
      providers: [{
        type: 'custom',
        id: 'my-custom-sms-provider...',
        send: async (request) => {
          // Send SMS
          return 'id...'
        }
      }]
    }
  }
})

request being of the following type.

See all options: SMS provider options

Voice providers

new NotifmeSdk({
  channels: {
    voice: {
      providers: [{
        type: 'logger'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    voice: {
      providers: [{
        type: 'twilio',
        accountSid: 'xxxxx',
        authToken: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    voice: {
      providers: [{
        type: 'custom',
        id: 'my-custom-voice-provider...',
        send: async (request) => {
          // Send Voice
          return 'id...'
        }
      }]
    }
  }
})

request being of the following type.

See all options: Voice provider options

Push providers

new NotifmeSdk({
  channels: {
    push: {
      providers: [{
        type: 'logger'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    push: {
      providers: [{
        type: 'apn',
        token: {
          key: './certs/key.p8',
          keyId: 'xxxxx',
          teamId: 'xxxxx'
        }
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    push: {
      providers: [{
        type: 'fcm',
        id: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    push: {
      providers: [{
        type: 'wns',
        clientId: 'xxxxx',
        clientSecret: 'xxxxx',
        notificationMethod: 'sendTileSquareBlock'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    push: {
      providers: [{
        type: 'adm',
        clientId: 'xxxxx',
        clientSecret: 'xxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    push: {
      providers: [{
        type: 'custom',
        id: 'my-custom-push-provider...',
        send: async (request) => {
          // Send push
          return 'id...'
        }
      }]
    }
  }
})

request being of the following type.

See all options: Push provider options

Webpush providers

new NotifmeSdk({
  channels: {
    webpush: {
      providers: [{
        type: 'logger'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    webpush: {
      providers: [{
        type: 'gcm',
        gcmAPIKey: 'xxxxx',
        vapidDetails: {
          subject: 'mailto: [email protected]',
          publicKey: 'xxxxx',
          privateKey: 'xxxxx'
        }
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    webpush: {
      providers: [{
        type: 'custom',
        id: 'my-custom-webpush-provider...',
        send: async (request) => {
          // Send webpush
          return 'id...'
        }
      }]
    }
  }
})

request being of the following type.

See all options: Webpush provider options

Slack providers

new NotifmeSdk({
  channels: {
    slack: {
      providers: [{
        type: 'logger'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    slack: {
      providers: [{
        type: 'webhook',
        webhookUrl: 'https://hooks.slack.com/services/Txxxxxxxx/Bxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxx'
      }]
    }
  }
})
new NotifmeSdk({
  channels: {
    slack: {
      providers: [{
        type: 'custom',
        id: 'my-custom-slack-provider...',
        send: async (request) => {
          // Send slack
          return 'id...'
        }
      }]
    }
  }
})

request being of the following type.

See all options: Slack provider options

Multi-provider strategies

A multi-provider strategy allows you to customize the send process on a channel.

Predefined strategies

| Strategy name | Description | | --- | --- | | fallback | If the used provider returns an error, try the next in the list. | | roundrobin | Use every provider in turns. If one of them returns an error, fallback to the next. | | no-fallback | Deactivates fallback strategy. |

Custom

You can also provide your own strategy. You have to pass a function implementing:

(Provider[]) => Sender
// See examples below for more details

Examples:

/*
 * `providers` is an array containing all the instances that were
 * created from your configuration.
 */
const randomStrategy = (providers) => async (request) => {
  // Choose one provider at random
  const provider = providers[Math.floor(Math.random() * providers.length)];

  try {
    const id = await provider.send(request)
    return {id, providerId: provider.id}
  } catch (error) {
    error.providerId = provider.id
    throw error
  }
}

new NotifmeSdk({
  channels: {
    email: { // Example for email channel
      providers: [...],
      multiProviderStrategy: randomStrategy
    }
  }
})
import strategyFallback from 'notifme-sdk/lib/strategies/fallback'

function getCountryFromNumber(number) {
  // extract the country from a phone number (+33670707070) -> 'fr'
}
function orderProvidersByPrice(country, providers) {
  // giving a country return an array of ordered providers by price
}

const smsCheapStrategy = (providers) => async (request) => {
  const country = getCountryFromNumber(request.from)
  const providersOrdered = orderProvidersByPrice(country, providers)

  return strategyFallback(providersOrdered)(request)
}

Adding a provider or a channel

If you would like to see another provider or channel, please upvote the corresponding issue (or create one if it does not exist yet).

3. Custom channels

If you want to have custom channels (and providers) you can add them.

Example:

new NotifmeSdk({
  channels: {
    socket: {
      multiProviderStrategy: 'fallback',
      providers: [
        {
          type: 'custom',
          id: 'my-socket-sender',
          send: async () => {
            return 'custom-socket-id'
          }
        }
      ]
    }
  }
})

4. Send a notification

Parameters

New: you can check notifme-template to help you define your templates.

notifmeSdk.send({
  email: {
    from: '[email protected]',
    to: '[email protected]',
    subject: 'Hi John',
    html: '<b>Hello John! How are you?</b>'
  }
})

See all parameters.

notifmeSdk.send({
  sms: {
    from: '+15000000000',
    to: '+15000000001',
    text: 'Hello John! How are you?'
  }
})

See all parameters.

notifmeSdk.send({
  voice: {
    from: '+15000000000',
    to: '+15000000001',
    url: 'http://demo.twilio.com/docs/voice.xml'
  }
})

See all parameters.

notifmeSdk.send({
  push: {
    registrationToken: 'xxxxx',
    title: 'Hi John',
    body: 'Hello John! How are you?',
    icon: 'https://notifme.github.io/notifme-sdk/img/icon.png'
  }
})

See all parameters.

notifmeSdk.send({
  webpush: {
    subscription: {
      keys: {
        auth: 'xxxxx',
        p256dh: 'xxxxx'
      },
      endpoint: 'xxxxx'
    },
    title: 'Hi John',
    body: 'Hello John! How are you?',
    icon: 'https://notifme.github.io/notifme-sdk/img/icon.png'
  }
})

See all parameters.

notifmeSdk.send({
  slack: {
    text: 'Slack webhook text'
  }
})

See all parameters.

notifmeSdk.send({
  email: {
    from: '[email protected]',
    to: '[email protected]',
    subject: 'Hi John',
    html: '<b>Hello John! How are you?</b>'
  },
  sms: {
    from: '+15000000000',
    to: '+15000000001',
    text: 'Hello John! How are you?'
  },
  push: {
    registrationToken: 'xxxxx',
    title: 'Hi John',
    body: 'Hello John! How are you?',
    icon: 'https://notifme.github.io/notifme-sdk/img/icon.png'
  },
  webpush: {
    subscription: {
      keys: {
        auth: 'xxxxx',
        p256dh: 'xxxxx'
      },
      endpoint: 'xxxxx'
    },
    title: 'Hi John',
    body: 'Hello John! How are you?',
    icon: 'https://notifme.github.io/notifme-sdk/img/icon.png'
  },
  slack: {
    text: 'Slack webhook text'
  }
})

See all parameters.

Returned type

send returns a Promise resolving with an Object of the following type:

type NotificationStatusType = {
  status: 'success' | 'error',
  channels?: {[channel: ChannelType]: {
    id: string,
    providerId: ?string
  }},
  errors?: {[channel: ChannelType]: Error}
}

Examples:

| Case | Returned JSON | | --- | --- | | Success(when Promise resolves) | {status: 'success', channels: {sms: {id: 'id-116561976', providerId: 'sms-default-provider'}}} | | Error(here Notification Catcher is not running) | {status: 'error', channels: {sms: {id: undefined, providerId: 'sms-notificationcatcher-provider'}}, errors: {sms: 'connect ECONNREFUSED 127.0.0.1:1025'}} |

5. In production

Recommended options

| Option name | Usage in production | Comment | | --- | --- | --- | | useNotificationCatcher | false | Don't forget to deactivate notification catcher (it overrides channels configuration). |

Logger

This project uses winston as logging library. You can add or remove loggers as you wish.

import NotifmeSdk from 'notifme-sdk'
import winston from 'winston'

const notifmeSdk = new NotifmeSdk({})

// To deactivate all loggers
notifmeSdk.logger.mute()

// Or set the loggers you want
notifmeSdk.logger.configure([
  new (winston.transports.File)({filename: 'somefile.log'})
])

See winston's documentation for more details.

Use a request queue

Send us a message

So that we can make a list of people using this library ;)

Contributing

test framework js-standard-style flow-typed Greenkeeper badge

Contributions are very welcome!

To get started: fork this repository to your own GitHub account and then clone it to your local device.

$ git clone [email protected]:[YOUR_USERNAME]/notifme-sdk.git && cd notifme-sdk
$ yarn install

Before making a pull request, check that the code passes all the unit tests, respects the Standard JS rules, and the Flow type checker.

Tests will also run automatically with GitHub Actions when you open a PR.

$ yarn run test

Next for this project

  • Implement other providers for each channel (ask or vote for a provider)
  • Add other types of notifications based on what people ask (slack, messenger, skype, telegram, kik, spark...)
  • A plugin system (for queues, retry system on error, templating, strategies...)

Need Help? Found a bug?

Submit an issue to the project Github if you need any help. And, of course, feel free to submit pull requests with bug fixes or changes.

Related Projects