Skip to content
Warlock.js v4.2.11

Installation

One command installs the package, ejects config/notifications.ts, and scaffolds the in-app model + migration:

Terminal window
npx warlock add notifications

It also pulls in the mail feature (the package’s one required dependency), so a fresh app is wired end to end. @warlock.js/core and @warlock.js/cascade are already present in a Warlock app.

This ejects into your project — yours to edit:

  • src/config/notifications.ts — a declarative config wired to the scaffolded model (see below).
  • src/app/notifications/notification.model.ts — extends DatabaseNotification; declares its physical columns via columnMap.
  • src/app/notifications/migrations/…notification.migration.tsMigration.create(Notification, notificationColumns(Notification)).
  • src/app/notifications/routes.ts + controllers/notifications.controller.ts — the recipient-scoped read/dismiss endpoints (list / unread-count / mark-read / mark-all-read / clear / delete), gated by authMiddleware. Delete them if your app exposes notifications another way (sockets, GraphQL, …).

Prefer to wire it by hand? yarn add @warlock.js/notifications (npm / pnpm work too), then create the files yourself. The generator is the recommended path — it keeps them in sync and matches the conventions below.

The file is declarative: it exports a config object, and Warlock’s notifications connector reads that default export at boot and registers it. You never call setNotificationConfig yourself — the connector does, the same way the rest of src/config/*.ts is wired.

src/config/notifications.ts
import { type NotificationConfig, mailChannel, inApp } from "@warlock.js/notifications";
import { Notification } from "app/notifications/notification.model";
const config: NotificationConfig = {
channels: {
mail: mailChannel({ from: "no-reply@store.com" }),
database: inApp.configure({ model: Notification }),
},
// optional gates:
// preferences: userPreferences,
// rateLimit,
};
export default config;

inApp.configure({ model }) does double duty: it binds the in-app store and returns the database channel, so reads and writes share one repository.