@checkstack/notification-discord-backend 0.1.21 → 0.1.23

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/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @checkstack/notification-discord-backend
2
2
 
3
+ ## 0.1.23
4
+
5
+ ### Patch Changes
6
+
7
+ - 32d52c6: Bulk notifications affecting multiple systems and collapse lifecycle events into a single card.
8
+
9
+ Notifications now carry an optional `subjects` array (the entities they affect) and an optional `collapseKey` (so related notifications collapse into one row per recipient). Incidents, maintenances, anomalies, healthchecks, and dependency-impact events route through these new fields, so an incident affecting three systems produces one in-app notification + one external send per subscriber instead of three. Lifecycle updates for the same entity (created → updated → resolved) also collapse, with an expandable "+N updates" timeline.
10
+
11
+ Subject kinds are namespaced as `<pluginId>.<localKind>` and built via type-safe helpers exported from each domain's common package (`createSystemSubject`, `incidentCollapseKey`, etc.). The frontend kind registry (`registerSubjectKind`) lets plugins bind icon + label for their kinds; unknown kinds fall back to a generic chip.
12
+
13
+ All notification strategies (SMTP, Slack, Discord, Teams, Telegram, Pushover, Gotify, Webex, Backstage) render the affected subjects natively in their format (HTML cards, Slack blocks, Discord embed fields, adaptive cards, markdown lists, etc.).
14
+
15
+ - Updated dependencies [32d52c6]
16
+ - Updated dependencies [32d52c6]
17
+ - Updated dependencies [32d52c6]
18
+ - Updated dependencies [32d52c6]
19
+ - @checkstack/notification-backend@1.0.0
20
+ - @checkstack/backend-api@0.14.0
21
+
22
+ ## 0.1.22
23
+
24
+ ### Patch Changes
25
+
26
+ - @checkstack/backend-api@0.13.1
27
+ - @checkstack/notification-backend@0.2.1
28
+
3
29
  ## 0.1.21
4
30
 
5
31
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/notification-discord-backend",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "checkstack": {
@@ -16,9 +16,9 @@
16
16
  "test": "bun test"
17
17
  },
18
18
  "dependencies": {
19
- "@checkstack/backend-api": "0.12.0",
20
- "@checkstack/common": "0.6.5",
21
- "@checkstack/notification-backend": "0.1.23",
19
+ "@checkstack/backend-api": "0.13.1",
20
+ "@checkstack/common": "0.7.0",
21
+ "@checkstack/notification-backend": "0.2.1",
22
22
  "zod": "^4.2.1"
23
23
  },
24
24
  "devDependencies": {
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ import {
6
6
  type NotificationStrategy,
7
7
  type NotificationSendContext,
8
8
  type NotificationDeliveryResult,
9
+ type NotificationSubject,
9
10
  markdownToPlainText,
10
11
  } from "@checkstack/backend-api";
11
12
  import { notificationStrategyExtensionPoint } from "@checkstack/notification-backend";
@@ -67,6 +68,7 @@ interface DiscordEmbedOptions {
67
68
  body?: string;
68
69
  importance: "info" | "warning" | "critical";
69
70
  action?: { label: string; url: string };
71
+ subjects?: NotificationSubject[];
70
72
  }
71
73
 
72
74
  interface DiscordEmbed {
@@ -77,8 +79,15 @@ interface DiscordEmbed {
77
79
  timestamp?: string;
78
80
  }
79
81
 
82
+ const SUBJECT_STATUS_EMOJI = {
83
+ healthy: "🟢",
84
+ degraded: "🟡",
85
+ unhealthy: "🔴",
86
+ unknown: "⚪",
87
+ } as const;
88
+
80
89
  function buildDiscordEmbed(options: DiscordEmbedOptions): DiscordEmbed {
81
- const { title, body, importance, action } = options;
90
+ const { title, body, importance, action, subjects } = options;
82
91
 
83
92
  // Discord colors are decimal values
84
93
  const importanceColors: Record<string, number> = {
@@ -104,14 +113,38 @@ function buildDiscordEmbed(options: DiscordEmbedOptions): DiscordEmbed {
104
113
  embed.description = markdownToPlainText(body);
105
114
  }
106
115
 
116
+ const fields: NonNullable<DiscordEmbed["fields"]> = [];
117
+
118
+ if (subjects && subjects.length > 0) {
119
+ // One field summarizing every affected subject as a markdown bullet
120
+ // list. Discord renders [name](url) in field values, and prefixes
121
+ // status with a colored circle when present.
122
+ fields.push({
123
+ name: "Affected",
124
+ value: subjects
125
+ .map((subject) => {
126
+ const prefix = subject.status
127
+ ? `${SUBJECT_STATUS_EMOJI[subject.status]} `
128
+ : "• ";
129
+ return subject.url
130
+ ? `${prefix}[${subject.name}](${subject.url})`
131
+ : `${prefix}${subject.name}`;
132
+ })
133
+ .join("\n"),
134
+ inline: false,
135
+ });
136
+ }
137
+
107
138
  if (action?.url) {
108
- embed.fields = [
109
- {
110
- name: action.label,
111
- value: `[Click here](${action.url})`,
112
- inline: false,
113
- },
114
- ];
139
+ fields.push({
140
+ name: action.label,
141
+ value: `[Click here](${action.url})`,
142
+ inline: false,
143
+ });
144
+ }
145
+
146
+ if (fields.length > 0) {
147
+ embed.fields = fields;
115
148
  }
116
149
 
117
150
  return embed;
@@ -166,6 +199,7 @@ const discordStrategy: NotificationStrategy<DiscordConfig, DiscordUserConfig> =
166
199
  body: notification.body,
167
200
  importance: notification.importance,
168
201
  action: notification.action,
202
+ subjects: notification.subjects,
169
203
  });
170
204
 
171
205
  // Send to Discord webhook