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

davepi-plugin-slack

v0.1.0

Published

Slack notifications for dAvePi. Subscribes to the in-process record event bus and posts a message to a Slack incoming webhook for every CRUD event whose type matches a configured pattern. Also exposes `postMessage` for ad-hoc use from schema lifecycle hoo

Readme

davepi-plugin-slack

Slack incoming-webhook notifications for dAvePi. Subscribes to the in-process record event bus and posts a message to your Slack channel for every CRUD event whose type matches a configured pattern. Also exposes postMessage so a schema lifecycle hook can fire a custom Slack message inline.

Install

npm install davepi-plugin-slack

Add it to your project's package.json under davepi.plugins:

{
  "davepi": {
    "plugins": ["davepi-plugin-slack"]
  }
}

Configure

All config is env-driven:

| Variable | Required | Default | Description | |----------|----------|---------|-------------| | SLACK_WEBHOOK_URL | yes (otherwise dormant) | — | The full incoming-webhook URL Slack handed you when you created the integration. Must be https://. | | SLACK_EVENTS | no | (empty — no auto-forward) | Comma-separated event patterns. Supports order.created, order.*, and *. | | SLACK_APP_NAME | no | dAvePi's APP_NAME env var, then "dAvePi" | The prefix the default formatter uses in every message. | | SLACK_USERNAME | no | — | Optional sender name override. | | SLACK_ICON_EMOJI | no | — | Optional sender icon (e.g. :robot_face:). |

A missing SLACK_WEBHOOK_URL is intentional: the plugin logs a warning and stays dormant. postMessage will throw if called in that state. This lets you ship the plugin in a project that hasn't wired Slack yet without crashing boot.

Event patterns

| Pattern | Matches | |---------|---------| | order.created | Exact event type. | | order.* | Every order.<verb> event (created, updated, deleted, transitioned). | | * | Every event the framework emits. |

The patterns are identical to dAvePi's built-in outbound webhooks, so the same SLACK_EVENTS value you'd put in a webhook subscription works here too.

What gets posted

For a single-record event:

my-apporder.created66e8b3...

For a bulk event (bulk PUT / GraphQL updateMany):

my-apporder.updated — 42 record(s) affected

For a state-machine transition:

my-apporder.transitioned66e8b3... — status: draft → approved

Want a richer payload (block-kit cards, mentions, channel routing)? Override the default formatter — see "Advanced" below.

Calling Slack from a hook

// plugins/postmark.js  (your other plugin)
// ... runs setup, exports sendEmail ...
// schema/versions/v1/user.js
const slack = require('davepi-plugin-slack');
const postmark = require('#plugins/postmark');

module.exports = {
  path: 'user',
  collection: 'user',
  fields: [/* ... */],
  hooks: {
    afterCreate: async ({ record, req }) => {
      try {
        await postmark.sendEmail({ to: record.email, subject: 'Welcome', body: '...' });
        await slack.postMessage(`:tada: signup — ${record.email}`);
      } catch (err) {
        (req?.log || console).error({ err }, 'afterCreate side-effects failed');
      }
    },
  },
};

The try/catch is the convention for after* hooks — they're best-effort, and dAvePi swallows throws to keep responses fast. Wrap locally so a Slack outage doesn't lose its diagnostic trail. See Hooks › Calling a plugin from a hook.

Advanced

require('davepi-plugin-slack') returns a default instance reading config from process.env. Use the createPlugin factory if you want to inject a custom formatter, fetch implementation, or env source:

const { createPlugin } = require('davepi-plugin-slack');

module.exports = createPlugin({
  // Slack accepts richer payloads — return blocks instead of text.
  formatter: (event, { appName }) => `:warning: [${appName}] ${event.type}`,
  // Pin a request timeout (default 10s).
  timeoutMs: 5000,
});

Then in package.json:

{
  "davepi": {
    "plugins": ["./plugins/my-slack.js"]
  }
}

Failure handling

  • Bus subscriber: every post is wrapped in try/catch. A Slack outage logs an error row via the framework's pino instance and is otherwise silent — the request loop is never blocked.
  • postMessage (ad-hoc): errors propagate to the caller. The convention is to call it from an after* hook and wrap in try/catch so the hook doesn't surface an unhandledRejection.
  • Boot: a missing / malformed SLACK_WEBHOOK_URL logs once and leaves the plugin dormant. Boot does not fail — that would be a footgun in CI / staging where Slack is intentionally unset.

Why not outbound webhooks for this?

The framework's webhook dispatcher delivers a per-tenant subscription to an arbitrary URL with HMAC signing and exponential-backoff retries — exactly the right tool for "tenant X wants their own webhook." It isn't the right tool for "operator wants Slack to ping when anything mutates," which is what this plugin is for:

  • One Slack channel for the whole app, not one per tenant.
  • Operator-controlled via env, not per-user subscriptions managed in Mongo.
  • No HMAC, no per-tenant secret rotation — Slack incoming webhooks are their own URL-as-secret.
  • No retry queue — Slack outages are visible in operator logs, and the next event will go through.

If you also want per-tenant Slack alerts (e.g. "tenant Y subscribes to their own order.created events"), use the in-tree webhook dispatcher instead — it's purpose-built for that.

License

ISC