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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@b2y/email-service

v1.2.3

Published

A flexible, channel-agnostic notification delivery library. Ships a shared, versioned NotificationTemplate model, NotificationType/MediaType/TemplateCategory enums, and a Handlebars template engine that any notification channel (email, sms, whatsapp, push

Readme

@b2y/email-service

A reusable, channel-agnostic notification library. It is split into two layers:

  1. Shared, channel-agnostic layer - usable by any notification channel (email, sms, whatsapp, push): the versioned NotificationTemplate model, the NotificationType / MediaType / TemplateCategory enums, and the Handlebars-based TemplateEngine.
  2. Concrete EMAIL delivery layer - EmailService plus five email providers (Nodemailer, SendGrid, Postmark, Amazon SES, Mailgun).

Sibling packages such as @b2y/sms-service and @b2y/whatsapp-service are expected to implement their own channel-specific delivery service (their own SmsService/WhatsappService + their own carrier providers), but should import layer 1 from this package via its subpath exports instead of redefining their own template model/enums - see "Building another channel" below. This keeps exactly one source of truth for the template schema, versioning rules, and rendering logic across every channel.

Features

  • Channel-agnostic NotificationTemplate model with real versioning (Version + IsActive, enforced at the DB level with a partial unique index so exactly one version is active per template/tenant/language/channel)
  • NotificationType (EMAIL, SMS, PUSH, WHATSAPP), MediaType, and TemplateCategory enums, shared by every consumer instead of being redefined per-service
  • Handlebars-based template rendering with placeholder substitution and a language-fallback lookup, independent of which channel is sending
  • A concrete EMAIL implementation on top of that shared layer, with a common interface across five providers - switch providers via config, not code
  • Zero process.env reads anywhere in the library - every value the library needs (provider selection, credentials, from-address, etc.) is passed in explicitly by the consuming application

Architecture note: no database connection, no environment binding

This package does not open a database connection and does not read environment variables. Both concerns belong to the consuming application:

  • Database connection & template CRUD/tenant logic: the application owns its own sequelize instance, instantiates the shared model against it, and is responsible for creating/versioning templates (see NotificationTemplateModel below). This library only ever reads active templates.
  • Environment / secrets: the application reads its own .env (however it already does that) and builds a plain config object, which it passes into createEmailService / getEmailService / createEmailProvider. See .env.example for the exact shape each provider expects on that object.

Installation

npm install @b2y/email-service

sequelize is a peer dependency (see package.json) rather than a bundled dependency - install whichever version your application already uses, so there is only ever one sequelize instance in the dependency tree. It is marked optional because a consumer that only needs the enums or the email providers (no DB-backed templates) doesn't need it; importing the package's root entrypoint (require('@b2y/email-service')), however, does load model/NotificationTemplate.js, so sequelize must be present whenever the root entrypoint is used.

Usage

const { getEmailService, NotificationTemplateModel } = require('@b2y/email-service');
const { sequelize } = require('./ConnectionDB/Connect'); // the app's own connection

// The application owns the model instance.
const NotificationTemplate = NotificationTemplateModel(sequelize);

// The application owns config - built from its own env, however it likes.
const config = {
  emailProvider: process.env.EMAIL_PROVIDER,   // nodemailer | sendgrid | postmark | amazonses | mailgun
  fromEmail: process.env.FROM_EMAIL,
  fromName: process.env.FROM_NAME,
  defaultLanguage: process.env.DEFAULT_LANGUAGE,   // optional - used when sendEmail gets no langCode (falls back to 'en')
  // ...provider-specific fields, see .env.example
};

const emailService = await getEmailService({
  dbClient: { NotificationTemplate },
  config
});

await emailService.sendEmail({
  tenantId: 1,
  // langCode: 'en',   // optional - defaults to config.defaultLanguage
  templateName: 'WELCOME_EMAIL',
  placeholders: { userName: 'Aarvi' },
  recipients: { to: '[email protected]' }
});

getEmailService memoizes a singleton on first call - dbClient/config only need to be supplied once per process. Use createEmailService directly if you need more than one independently-configured instance.

Building another channel (SMS / WhatsApp / Push)

A sibling service does not need its own copy of the template model or enums. Import just the shared layer via this package's subpath exports, which avoids pulling in any email provider SDK:

const NotificationTemplateModel = require('@b2y/email-service/model/NotificationTemplate');
const TemplateEngine = require('@b2y/email-service/utils/templateEngine');
const { NotificationType } = require('@b2y/email-service/enum/NotificationType');
const { MediaType } = require('@b2y/email-service/enum/MediaType');
const { TemplateCategory } = require('@b2y/email-service/enum/TemplateCategory');

const NotificationTemplate = NotificationTemplateModel(sequelize);
const templateEngine = new TemplateEngine({ NotificationTemplate }, config);

const { subject, body } = await templateEngine.compileTemplate(
  'ORDER_SHIPPED',
  { orderId: '123' },
  tenantId,
  'en',
  NotificationType.WHATSAPP // any NotificationType value works - the engine is channel-agnostic
);

The new service then implements its own delivery layer (e.g. WhatsappService

  • a BaseProvider-style contract for its own carrier(s)), following the same config-injection pattern used here: no process.env reads inside the library, the host application passes in a config object.

Breaking changes from 1.x

  • The library no longer reads process.env or its own .env file (the old Config.js is removed). Every provider/service constructor now takes an explicit config object - see "Usage" above and .env.example for the field mapping.
  • EmailTemplate is replaced by the shared, versioned NotificationTemplate model (adds NotificationType, MediaType, TemplateCategory, IsActive, Version; removes Styles). See the consuming application's migration scripts for the corresponding schema changes.
  • sequelize moved from a bundled dependency to a peer dependency - run npm install sequelize in the consuming application if it doesn't already have it.

License

ISC