@krizaka/notifications
La cloche, les canaux et les préférences : un notify écrit l'élément et un message d'outbox par canal activé ; les plafonds de rafale tiennent en concurrence ; l'admin règle les défauts.
Installer
npm install @krizaka/notificationsAussi publié en sous-chemins : @krizaka/notifications/settings, @krizaka/notifications/testkit.
Le README ci-dessous est celui du paquet sur npm, en anglais.
The bell, the channels and the preferences for every Krizaka product. One notify writes the in-app item and appends one outbox message per enabled channel, respecting the account's matrix and a burst cap per category. No push or realtime import (the workers that deliver a channel are the product's), no database client, no wall clock.
- Channels.
app(the bell and the live event of the open pages, one switch),push(one message per registered device) andemail. The outbox topics arenotifications.live,notifications.pushandnotifications.email; the event isevt.notification.requested.v1, the name and the shape of Java'skrizaka-notifications-apirequest (channel,recipient,template,locale,variables, plus the ids;channelisEMAIL, andPUSH/LIVEfor the web). A product delivers e-mail with its own worker (@krizaka/emailto render,@krizaka/mailto queue) or lets the Java service consume it. - The product declares its categories and their defaults (
notificationSettings(declared)is the registry fragment); the admin tunes the default channels and the caps without a redeploy. Alockedcategory (security, the account) cannot be switched off by anyone. - Burst caps. After
burstMaxnotifications of one category to one account withinburstWindowSeconds, the next ones are bell-only: the item is kept, no channel is used. The count and the insert run under a transaction-level advisory lock per account and category, so the cap holds under concurrency whennotifygets the caller'stx. - Idempotent.
dedupeKeymakes one fact one notification; the outbox message ids derive from the item, so a retried append is a no-op. - The bell.
list(newest first, cursor),unreadCount,markRead(the account's own items; the firstread_atstays). An item whoseappchannel was off is kept for the history and the cap, never shown. - Preferences.
preferences(every category by channel with its source: default, account, locked),setPreference,setMatrix(a preset applied). - Devices.
registerDevice(a token belongs to one account; registering it again moves it),revokeDevicewhen the push service refuses it. - Privacy. The module holds no address (the product passes
emailper call);erase(accountId)removes the items, choices and devices;purgeapplies the retention.
import { createOutbox } from "@krizaka/outbox";
import { createNotifications, dbNotificationStore } from "@krizaka/notifications";
import { notificationSettings, readNotificationConfig } from "@krizaka/notifications/settings";
const declared = {
messages: { defaults: { app: true, push: true, email: true }, burst: { max: 5, windowSeconds: 3600 } },
follows: { defaults: { app: true, push: false, email: false } },
account: { locked: true, defaults: { app: true, push: true, email: true } },
};
// settingsRegistry = { ...otherSettings, ...notificationSettings(declared) }
const notifications = createNotifications({
clock,
outbox: createOutbox({ clock, settings: outboxSettings }),
config: () => readNotificationConfig(declared, (key) => settings.get(key)),
});
// in the use case's transaction
await notifications.notify(tx, { accountId, category: "messages", template: "new-message", variables: { name }, locale: "fr", email, dedupeKey: `message:${messageId}` });Tables (schema notifications, notificationsSchema): item, preference, device. notificationStoreContract (@krizaka/notifications/testkit) is the contract every store runs.
Apache-2.0.
Exports
Les 38 noms que le paquet exporte, lus dans ses types.
| Nom | Nature | Ce que c’est |
|---|---|---|
CategoryDefaults | type | A category as the product declares it. |
categoryOf | fonction | |
Channel | type | |
CHANNEL | constante | The channels an account switches. |
CHANNELS | constante | |
checkConfig | fonction | |
checkInput | fonction | |
Clock | type | |
createNotifications | fonction | The notifications of a product. |
dbNotificationStore | fonction | The PostgreSQL store of « notifications » over a Query, in schema notifications (or the one the product renamed it to). |
Delivery | type | |
DELIVERY | constante | What the outbox carries: the channel of Java's evt.notification.requested.v1 (EMAIL) and two more for the web (PUSH, LIVE). |
Device | type | |
Item | type | One line of the bell. |
memoryNotificationStore | fonction | An in-memory store, for unit tests and demos: the behaviour of the database's (the contract kit runs on both). |
NOTIFICATION_BOUNDS | constante | |
NOTIFICATION_CODE | constante | |
NOTIFICATION_DEFAULTS | constante | |
NOTIFICATION_EVENT | constante | The event the outbox carries, the name Java's krizaka-notifications-api gives its request. |
NOTIFICATION_TOPIC | constante | One topic per delivery, so a worker claims only what it delivers (notifications.email, notifications.push, notifications.live). |
NotificationCode | type | |
NotificationConfig | type | The categories (declared by the product, tuned by the admin) and the retention. |
NotificationDeps | type | |
NotificationError | classe | |
NotificationOutbox | type | What the module needs of @krizaka/outbox (its Outbox satisfies it): append in the caller's transaction. |
NotificationRequest | type | The request one delivery worker receives: Java's NotificationRequest (channel, recipient, template, locale, variables) plus the ids. |
Notifications | type | |
notificationsSchema | constante | The tables of « notifications », in their own Postgres schema: item (the bell, and the history the burst caps count), preference (the account's explicit… |
NotificationStore | type | Where the state lives. |
Notified | type | |
NotifyInput | type | |
Platform | type | |
PLATFORM | constante | |
PreferenceView | type | What an account sees in its settings: every category, every channel, and why. |
Query | type | |
resolveChannels | fonction | The channels on for an account: the category's defaults, overridden by the account's choices, unless the category is locked. |
uuidOf | fonction | A stable UUID (version 5 shaped) from a seed: the same fact appended twice is one outbox message. |
viewOf | fonction |
@krizaka/notifications/settings
| Nom | Nature | Ce que c’est |
|---|---|---|
CategoryDeclaration | type | What a product declares for a category; the admin tunes the values (except locked, which is code). |
Declared | type | |
notificationSettings | fonction | The settings of « notifications » for the categories a product declares, a fragment it adds to its registry (@krizaka/notifications/settings): for each cat… |
readNotificationConfig | fonction | The module's configuration as createNotifications takes it, from the product's accessor ((key) => service.get(key, ctx)). |
@krizaka/notifications/testkit
| Nom | Nature | Ce que c’est |
|---|---|---|
at | fonction | |
itemOf | fonction | An item for tests; the account ids are UUIDs because the database's are. |
notificationStoreContract | fonction | What every NotificationStore adapter must do: the same behaviour behind the same port. |
T0 | constante |
Paquet
| Version sur npm | 0.2.2 (npm) |
| Licence | Apache-2.0 |
| Node.js | >=22 |
| Dépendances | @krizaka/db workspace:^, @krizaka/settings workspace:^, @krizaka/time workspace:^ |
| Dépendances à fournir | vitest >=4, zod >=3.23 |
| Code source | notifications |
Journal des versions
0.2.2
Patch changes
- The READMEs, comments and published declarations no longer name the products that left the organisation (krizaka/.github#413, rule
no-departed-published). The sources were cleaned in #262 with an empty changeset, so the published tarballs still carried the old text; this release replaces them. No behaviour change. - Updated dependencies [2a7898c]
- Updated dependencies [2272b57]
- @krizaka/[email protected]
- @krizaka/[email protected]
0.2.1
Patch changes
- Updated dependencies [0d19b64]
- @krizaka/[email protected]
- @krizaka/[email protected]
0.2.0
Minor changes
- New package (#60):
@krizaka/notifications.createNotifications(notifywriting the bell item and one outbox message per enabled channel: live, e-mail, push per device, asevt.notification.requested.v1in the shape of Java's request;list,unreadCount,markRead,preferences,setPreference,setMatrix,registerDevice,revokeDevice,purge,erase), per-category burst caps that hold under concurrency (advisory lock per account and category), locked categories,dedupeKey,notificationsSchema(notifications.item,notifications.preference,notifications.device),dbNotificationStore,memoryNotificationStore,@krizaka/notifications/settings(notificationSettings(declared),readNotificationConfig) andnotificationStoreContract.
Patch changes
- Updated dependencies [8210a9a]
- @krizaka/[email protected]
@krizaka/storage
Fichiers derrière un seul port : noms hachés par le contenu, liens signés et publics ; une zone HTTP, tout bucket compatible S3 ou un dossier, au choix de l'admin ; octets vérifiés par nombre magique.
@krizaka/mail
Courriel en file : envoyé après le commit, une fois par clé, jamais à une adresse supprimée ; le fournisseur est le choix de l'admin ; rebonds et plaintes suppriment.