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

cliam

v3.0.3

Published

Agnostic transactional email sending in Node.js environment

Readme

Cliam

Node Bun TypeScript

Github action workflow status GitHub Release GPL Licence

Maintainability Code Coverage

Transactional emails with a kick

Agnostic transactional email sending in Node.js environment

> Why ?

To improve and facilitate the implementation, the flexibility and the maintenance of transactional emailing tasks.

> Features

  • Agnostic transactional email sending using web API or SMTP server. One input, one output.
  • Multiple simultaneous transporters.
  • Configuration based, not implementation based : easy switch between different modes.
  • Normalized transactions events.
  • Securized payloads.
  • Customisable default templates.

> Table of contents

  • Node.js >= 18.19.0
  • NPM >= 10.2.3

Install

> npm i cliam --save

Configure

Cliam must be configured once at application startup, before any call to mail(). Two approaches are available.

Option A - Pass a configuration object directly:

import { Cliam } from 'cliam';
import type { IClientConfiguration } from 'cliam';

const config: IClientConfiguration = {
  sandbox: true,
  variables: {
    domain: 'https://www.my-website.com',
    addresses: {
      from: { name: 'My App', email: '[email protected]' },
      replyTo: { name: 'My App', email: '[email protected]' }
    }
  },
  transporters: [
    {
      id: 'smtp-main',
      auth: {
        username: process.env.SMTP_USERNAME,
        password: process.env.SMTP_PASSWORD
      },
      options: {
        host: process.env.SMTP_HOST,
        port: 587,
        secure: false
      }
    },
    {
      id: 'sendgrid-api',
      provider: 'sendgrid',
      auth: {
        apiKey: process.env.SENDGRID_API_KEY
      },
      templates: {
        'user.welcome': 'd-321bb40f548e4db8a628b4d6464ebacc'
      }
    }
  ]
};

Cliam.configure(config);

Option B - Load from a .cliamrc.js file:

import { Cliam } from 'cliam';

// Loads .cliamrc.js from process.cwd() by default
Cliam.configureFromFile();

// Or pass an explicit path
Cliam.configureFromFile('/path/to/my-cliam-config.js');

The .cliamrc.js file should export the same configuration object as above:

require('dotenv').config();

module.exports = {
  sandbox: true,
  variables: {
    domain: 'https://www.my-website.com',
    addresses: {
      from: { name: 'My App', email: '[email protected]' },
      replyTo: { name: 'My App', email: '[email protected]' }
    }
  },
  transporters: [ ... ]
};

Use environment variables for sensitive values such as API keys. Cliam does not load .env automatically.

See cliamrc configuration wiki section for the full list of available options.

Selective imports

The default entry point registers all supported providers at import time:

import { Cliam } from 'cliam'; // all providers loaded

If you use a bundler and want to reduce your bundle size, import the core and load only the providers you actually use:

import { Cliam } from 'cliam/core';
import 'cliam/providers/sendgrid';
// import 'cliam/providers/smtp'; // add others as needed

Types and enums are available separately:

import type { IPayload, IClientConfiguration } from 'cliam/types';
import { EVENT, PROVIDER } from 'cliam/types';

Available sub-paths:

| Sub-path | Exports | |---|---| | cliam | Cliam, SendingResponse, SendingError, all types — registers all providers | | cliam/core | Cliam, SendingResponse, SendingError — no providers registered | | cliam/types | All interfaces, enums and types — no runtime code | | cliam/providers/brevo | Side-effect: registers the Brevo transporter | | cliam/providers/mailersend | Side-effect: registers the Mailersend transporter | | cliam/providers/mailgun | Side-effect: registers the Mailgun transporter | | cliam/providers/mailjet | Side-effect: registers the Mailjet transporter | | cliam/providers/mandrill | Side-effect: registers the Mandrill transporter | | cliam/providers/postmark | Side-effect: registers the Postmark transporter | | cliam/providers/resend | Side-effect: registers the Resend transporter | | cliam/providers/sendgrid | Side-effect: registers the Sendgrid transporter | | cliam/providers/ses | Side-effect: registers the Amazon SES transporter | | cliam/providers/sparkpost | Side-effect: registers the Sparkpost transporter | | cliam/providers/smtp | Side-effect: registers the SMTP transporter |

If a transporter is configured but its provider was never imported, Cliam throws at send time with a clear message.

Implement

import { Cliam } from 'cliam';
import type { IPayload } from 'cliam';

const payload: IPayload = {
  meta: {
    from: { email: '[email protected]', name: 'John Doe' },
    to: [{ email: '[email protected]' }],
    replyTo: { email: '[email protected]', name: 'John Doe' },
    subject: 'Welcome John'
  },
  content: [
    {
      type: 'text/html',
      value: '<h1>Hello Yoda</h1><p>I use Cliam to send my emails !</p>'
    }
  ]
};

Cliam.mail('user.welcome', payload)
  .then(res => {
    console.log('Email delivered: ', res);
  })
  .catch(err => {
    console.log('Error: ', err);
  });

The render engine is inferred automatically:

  • content provided → uses your HTML directly
  • No content, template ID configured for the event → delegates to the provider's template engine
  • No content, no template → uses Cliam's built-in default templates

By default, Cliam uses the first transporter in the configuration. Pass transporterId in the payload to target a specific one.

See email payload wiki section for the full payload reference.

:white_check_mark: I have many projects which uses differents providers, it's a hell of a thing to maintain.

This is to be forgotten with Cliam. No more worries about polymorphics inputs / outputs. Whether you are working with an A, B, C, D provider or a smtp server, your input / output will always be the same regardless of your delivery method or service provider.

:white_check_mark: I'm just using many providers into a same project, it's convoluted to securize and maintain.

Same purpose. Whether you are working with a provider or a SMTP server - or boths, with Cliam, you don't get anymore n libraries into your node_modules folder: we only embed the bare metal minimum, and not some old deprecated SDK's.

:white_check_mark: I wish change from supplier, but I'm in panic about the implementation ?

Your implementation does not move, you just have to adapt a configuration file, remove your legacy code and implement some lines of code.

:white_check_mark: I don't have a subscription to a supplier, and no templates

No problem, we have all been poor once. Start with a simple SMTP server and use default templates. When your business is up, you can use a paid web api.

:white_check_mark: I did not have time to prepare the template for an important email that should be send today !

No more, you can fallback easily with a one shot default template.

:white_check_mark: I have a big problem with a provider, and my emails stay blocked in the pipe !

The same: fallback on a SMTP server. In two minutes you're ready and your mailing is back in operation.

AGPL-3.0 License