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.
Files changed (2) hide show
  1. package/README.md +161 -4
  2. 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
- - **Configurable** — poll interval, page size, retention policy, UI accent colours, and merge rules
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** — daily cleanup at 3 AM, respects maxDays and maxPerUser limits
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, // delete notifications older than N days
51
- maxPerUser: 500, // cap notifications stored per user
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/`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-plugin-notifier",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "A highly configurable notification inbox plugin for the Strapi v5 admin panel",
5
5
  "keywords": [
6
6
  "strapi",