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

@alis-kit/mailer

v0.1.0

Published

Email delivery abstraction with template engine and TC39 native decorators

Readme

Mailer Kit

Email delivery abstraction with a template engine and TC39 native decorators (Stage 3).

Features

  • TC39 Native Decorators — Uses stage 3 decorators with Symbol.metadata, no reflect-metadata needed
  • Template Engine — Dynamic ${variable} and ${nested.variable} interpolation
  • Provider Agnostic — Switch between Nodemailer, Resend, or custom providers
  • Async Queues — Send emails synchronously or queue them for background delivery
  • Type Safe — Full TypeScript support with strict mode

Requirements

  • Node.js >= 18.0.0
  • TypeScript >= 5.5.0

Installation

npm install @alis-kit/mailer

Quick Start

1. Setup

import { MailerKit } from "@alis-kit/mailer"

MailerKit.setup({
  provider: "nodemailer",
  config: {
    host: "smtp.gmail.com",
    port: 587,
    auth: {
      user: process.env.SMTP_USER,
      pass: process.env.SMTP_PASS
    }
  },
  from: "[email protected]"
})

2. Define a Template

import { EmailTemplate } from "@alis-kit/mailer"

/**
 * Welcome email sent to new users after registration.
 *
 * @example
 * ```ts
 * await MailerKit.send(WelcomeEmail, {
 *   to: "[email protected]",
 *   name: "John"
 * })
 * ```
 */
@EmailTemplate("welcome", {
  template: "./templates/welcome.html",
  subject: "Welcome to Our Platform!"
})
export class WelcomeEmail {
  to!: string
  name!: string
}

3. Create the HTML Template

<!-- templates/welcome.html -->
<h1>Welcome, ${name}!</h1>
<p>We're excited to have you on board.</p>

4. Send

await MailerKit.send(WelcomeEmail, {
  to: "[email protected]",
  name: "John"
})

API Reference

MailerKit.setup(config)

Initialize the mailer service. Must be called before sending.

MailerKit.setup({
  provider: "nodemailer",
  config: {
    host: "smtp.example.com",
    port: 587,
    auth: { user: "...", pass: "..." }
  },
  from: "[email protected]",
  queue: {
    engine: "memory"          // or "bullmq"
  }
})

| Option | Type | Required | Description | |--------|------|----------|-------------| | provider | "nodemailer" | Yes | Email provider to use | | config | object | Yes | Provider-specific configuration | | from | string | Yes | Default sender email address | | queue.engine | "memory" \| "bullmq" | No | Queue engine for async delivery |


@EmailTemplate(name, options)

Class decorator that links a class to an HTML template file. Uses TC39 stage 3 native decorators.

@EmailTemplate("notification", {
  template: "./templates/notification.html",
  subject: "You have a new notification"
})
export class NotificationEmail {
  to!: string
  title!: string
  message!: string
}

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | name | string | Yes | Unique identifier for the template | | options.template | string | Yes | Path to the HTML template file | | options.subject | string | No | Default subject line |


MailerKit.send(TemplateClass, data)

Send an email immediately.

await MailerKit.send(NotificationEmail, {
  to: "[email protected]",
  title: "New Message",
  message: "You have a new notification!"
})

| Parameter | Type | Description | |-----------|------|-------------| | TemplateClass | Class | A class decorated with @EmailTemplate | | data | object | Email data including to, template variables, and optional overrides |

Data properties:

| Property | Type | Description | |----------|------|-------------| | to | string \| string[] | Recipient(s) — required | | subject | string | Override default subject | | cc | string \| string[] | CC recipients | | bcc | string \| string[] | BCC recipients | | replyTo | string | Reply-to address | | attachments | Attachment[] | File attachments (pdf, doc, docx, xls, xlsx, jpg, jpeg, png, zip) |


MailerKit.queue(TemplateClass, data, options?)

Queue an email for asynchronous delivery.

await MailerKit.queue(WelcomeEmail, {
  to: "[email protected]",
  name: "John"
}, { delay: "5s" })

| Option | Type | Description | |--------|------|-------------| | delay | string | Delay before sending (e.g., "5s", "2m", "1h") | | priority | number | Priority level (for BullMQ) |


TemplateEngine.render(templatePath, variables)

Render an HTML template with variable interpolation.

import { TemplateEngine } from "@alis-kit/mailer"

const html = await TemplateEngine.render("./template.html", {
  name: "John",
  user: { email: "[email protected]" }
})

Supported syntax:

| Syntax | Example | Description | |--------|---------|-------------| | ${var} | ${name} | Simple variable | | ${nested} | ${user.email} | Dot-notation for nested objects | | ${array} | ${items} | Arrays are JSON-stringified |


MailerKit.getTemplateMetadata(TemplateClass)

Retrieve the metadata attached to a decorated class.

const metadata = MailerKit.getTemplateMetadata(WelcomeEmail)
// { name: "welcome", template: "./templates/welcome.html", subject: "Welcome!" }

Template Variables

Properties defined in your decorated class act as template variables:

@EmailTemplate("invoice", {
  template: "./templates/invoice.html",
  subject: "Your Invoice"
})
export class InvoiceEmail {
  to!: string
  invoiceNumber!: string
  total!: number
  items!: Array<{ name: string; price: number }>
}
<!-- templates/invoice.html -->
<h1>Invoice #${invoiceNumber}</h1>
<p>Total: $${total}</p>
<ul>
  ${items}
</ul>

Error Handling

| Error | Cause | |-------|-------| | MailerKit not initialized. Call setup() first. | send() or queue() called before setup() | | Unsupported mail provider: <name> | Invalid provider in setup() config | | Class <Name> is not a valid @EmailTemplate | Class not decorated with @EmailTemplate | | Class <Name> is already decorated with @EmailTemplate | Duplicate @EmailTemplate on same class | | Unsupported attachment type: .<ext> | Attachment file extension not in allowed list | | Template file not found at: <path> | HTML template file does not exist | | Queue not configured | queue() called without queue in config | | BullMQ integration not implemented | Using "bullmq" engine (not yet supported) |

Testing

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

Architecture

This project follows the Functional Core + Decorator Sugar pattern:

  • core/ — Pure functions and classes with all business logic
  • decorators/ — Thin wrappers that store metadata via Symbol.metadata
  • providers/ — Email provider adapters (Nodemailer, Resend, etc.)
  • template/ — Template engine and path resolution

Decorators never contain business logic — they only attach metadata that core/ reads.

License

ISC