strapi-plugin-notifier 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +161 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,9 +10,10 @@ A first-class notification system for Strapi v5 admin panels. Adds a live bell i
|
|
|
10
10
|
- **Batch sending** — send multiple notifications in one call, settings fetched once
|
|
11
11
|
- **Merge** — collapse repeated notifications into one item with a count badge (fully configurable)
|
|
12
12
|
- **User opt-out** — each admin user can mute individual notification types or opt out entirely
|
|
13
|
-
- **
|
|
13
|
+
- **Declarative rules** — trigger notifications from lifecycle hooks, eventHub events, or cron schedules — no code required beyond `config/plugins.ts`
|
|
14
|
+
- **Configurable** — poll interval, page size, retention policy, UI accent colours, merge rules, and cleanup schedule
|
|
14
15
|
- **Settings panel** — runtime configuration via Settings → Notifier (persisted in Strapi plugin store)
|
|
15
|
-
- **Retention cron** —
|
|
16
|
+
- **Retention cron** — configurable cleanup schedule (default: 3 AM daily), respects maxDays and maxPerUser limits
|
|
16
17
|
- **Strapi v5 only**
|
|
17
18
|
|
|
18
19
|
## Installation
|
|
@@ -47,8 +48,9 @@ export default {
|
|
|
47
48
|
enabled: true,
|
|
48
49
|
config: {
|
|
49
50
|
retention: {
|
|
50
|
-
maxDays: 90,
|
|
51
|
-
maxPerUser: 500,
|
|
51
|
+
maxDays: 90, // delete notifications older than N days
|
|
52
|
+
maxPerUser: 500, // cap notifications stored per user
|
|
53
|
+
cleanupCron: '0 3 * * *', // cron schedule for cleanup job (default: 3 AM daily)
|
|
52
54
|
},
|
|
53
55
|
delivery: {
|
|
54
56
|
pollIntervalMs: 30_000, // how often the Bell polls (ms)
|
|
@@ -214,6 +216,161 @@ Content-Type: application/json
|
|
|
214
216
|
| `globalOptOut` | `boolean` | `false` | Suppress all notifications for this user |
|
|
215
217
|
| `mutedTypes` | `NotificationType[]` | `[]` | Suppress only these notification types |
|
|
216
218
|
|
|
219
|
+
## Declarative rules
|
|
220
|
+
|
|
221
|
+
Instead of calling the notifier service in code, you can declare rules in `config/plugins.ts`. The plugin wires up the listeners at bootstrap — notifications fire automatically with no further code changes needed.
|
|
222
|
+
|
|
223
|
+
Three trigger types are supported: `lifecycle`, `event`, and `cron`.
|
|
224
|
+
|
|
225
|
+
### `on: 'lifecycle'` — content-type create/update/delete
|
|
226
|
+
|
|
227
|
+
Fires when Strapi's DB lifecycle executes for a given content-type and action.
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
// config/plugins.ts
|
|
231
|
+
notifier: {
|
|
232
|
+
enabled: true,
|
|
233
|
+
config: {
|
|
234
|
+
rules: [
|
|
235
|
+
{
|
|
236
|
+
on: 'lifecycle',
|
|
237
|
+
model: 'api::article.article',
|
|
238
|
+
action: 'afterCreate', // afterCreate | afterUpdate | afterDelete | afterPublish | afterUnpublish
|
|
239
|
+
notification: {
|
|
240
|
+
title: 'New article: {{entry.title}}',
|
|
241
|
+
message: 'Created by {{entry.createdBy.firstname}}',
|
|
242
|
+
type: 'info',
|
|
243
|
+
to: { role: 'strapi-editor' },
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
`entry` in templates is the DB record produced by the lifecycle action (`result` for after-hooks, `params.data` for before-hooks).
|
|
252
|
+
|
|
253
|
+
### `on: 'event'` — strapi.eventHub subscription
|
|
254
|
+
|
|
255
|
+
Fires on any named event published to Strapi's internal event hub (lifecycle events, media events, plugin events, or your own custom events emitted with `strapi.eventHub.emit()`).
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
{
|
|
259
|
+
on: 'event',
|
|
260
|
+
event: 'media.upload', // any strapi.eventHub event name
|
|
261
|
+
filter: { uid: 'api::article.article' }, // optional shallow key=value filter on payload
|
|
262
|
+
notification: {
|
|
263
|
+
title: 'File uploaded: {{media.name}}',
|
|
264
|
+
type: 'info',
|
|
265
|
+
to: 'broadcast',
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Custom events from your own services:**
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
// In your service
|
|
274
|
+
strapi.eventHub.emit('order.placed', { order });
|
|
275
|
+
|
|
276
|
+
// In config/plugins.ts
|
|
277
|
+
{
|
|
278
|
+
on: 'event',
|
|
279
|
+
event: 'order.placed',
|
|
280
|
+
notification: {
|
|
281
|
+
title: 'New order: #{{order.id}}',
|
|
282
|
+
message: '{{order.customerName}} — €{{order.total}}',
|
|
283
|
+
type: 'success',
|
|
284
|
+
to: { role: 'strapi-super-admin' },
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### `on: 'cron'` — time-based notifications
|
|
290
|
+
|
|
291
|
+
Fires on a cron schedule. Standard 5-field cron expressions.
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
{
|
|
295
|
+
on: 'cron',
|
|
296
|
+
schedule: '0 9 * * 1', // Every Monday at 9 AM
|
|
297
|
+
notification: {
|
|
298
|
+
title: 'Weekly reminder: review pending content',
|
|
299
|
+
type: 'warning',
|
|
300
|
+
to: { role: 'strapi-editor' },
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Notification templates
|
|
306
|
+
|
|
307
|
+
Every field in `notification` accepts either a **static value** or a **function** for dynamic content.
|
|
308
|
+
|
|
309
|
+
**String interpolation** — use `{{path.to.field}}` dot-notation to resolve values from the event context:
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
notification: {
|
|
313
|
+
title: 'New order from {{entry.customer.name}}',
|
|
314
|
+
message: 'Total: {{entry.total}} — shipped to {{entry.address.city}}',
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**Function templates** — for logic that can't be expressed as a template string:
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
notification: {
|
|
322
|
+
title: (ctx) => `${ctx.entry.priority === 'high' ? '🔴' : ''} Order #${ctx.entry.id}`,
|
|
323
|
+
type: (ctx) => ctx.entry.priority === 'high' ? 'error' : 'info',
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Targeting in rules
|
|
328
|
+
|
|
329
|
+
The `to` field supports the same options as the programmatic API, plus a `userIdFrom` path resolver:
|
|
330
|
+
|
|
331
|
+
| Value | Behaviour |
|
|
332
|
+
|-----------------------------|---------------------------------------------------------|
|
|
333
|
+
| `'broadcast'` (or omitted) | Send to all admin users |
|
|
334
|
+
| `{ role: 'strapi-editor' }` | Send to all users with this role code |
|
|
335
|
+
| `{ userId: 42 }` | Send to a specific admin user |
|
|
336
|
+
| `{ userIdFrom: 'entry.createdBy.id' }` | Resolve user ID via dot-path into the event context — useful for "notify the author" patterns |
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
// Notify the author when their content is rejected
|
|
340
|
+
{
|
|
341
|
+
on: 'lifecycle',
|
|
342
|
+
model: 'api::article.article',
|
|
343
|
+
action: 'afterUpdate',
|
|
344
|
+
when: (ctx) => ctx.entry.status === 'rejected',
|
|
345
|
+
notification: {
|
|
346
|
+
title: 'Your article was rejected',
|
|
347
|
+
to: { userIdFrom: 'entry.createdBy.id' },
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### `when` guard
|
|
353
|
+
|
|
354
|
+
Add a `when` function to conditionally skip the notification. Return `false` to suppress it.
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
{
|
|
358
|
+
on: 'lifecycle',
|
|
359
|
+
model: 'api::article.article',
|
|
360
|
+
action: 'afterUpdate',
|
|
361
|
+
when: (ctx) => ctx.entry.publishedAt != null, // only fire when published
|
|
362
|
+
notification: {
|
|
363
|
+
title: 'Article published: {{entry.title}}',
|
|
364
|
+
type: 'success',
|
|
365
|
+
to: 'broadcast',
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
`when` is not available on `cron` rules (there is no event context to filter on).
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
217
374
|
## API routes
|
|
218
375
|
|
|
219
376
|
All routes require `admin::isAuthenticatedAdmin`. The plugin mounts under `/notifier/`.
|