@camunda/ccma-api 0.1.0 → 0.4.0
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/dist/index.d.ts +31 -7
- package/dist/index.js +56 -2
- package/dist/index.js.map +2 -2
- package/dist/services/accounts/admin-tools.service.d.ts +27 -0
- package/dist/services/accounts/admin-tools.service.js +70 -0
- package/dist/services/accounts/admin-tools.service.js.map +7 -0
- package/dist/services/accounts/connections.service.d.ts +85 -0
- package/dist/services/accounts/connections.service.js +150 -0
- package/dist/services/accounts/connections.service.js.map +2 -2
- package/dist/services/accounts/early-access-features.service.d.ts +59 -0
- package/dist/services/accounts/early-access-features.service.js +142 -0
- package/dist/services/accounts/early-access-features.service.js.map +2 -2
- package/dist/services/accounts/invites.service.d.ts +28 -0
- package/dist/services/accounts/invites.service.js +53 -0
- package/dist/services/accounts/invites.service.js.map +7 -0
- package/dist/services/accounts/orgs.service.d.ts +42 -0
- package/dist/services/accounts/orgs.service.js +123 -0
- package/dist/services/accounts/orgs.service.js.map +2 -2
- package/dist/services/accounts/orgs.v2.service.d.ts +6 -0
- package/dist/services/accounts/orgs.v2.service.js +34 -0
- package/dist/services/accounts/orgs.v2.service.js.map +2 -2
- package/dist/services/accounts/pdf-watermark.service.d.ts +93 -0
- package/dist/services/accounts/pdf-watermark.service.js +147 -0
- package/dist/services/accounts/pdf-watermark.service.js.map +7 -0
- package/dist/services/accounts/release-train.service.d.ts +25 -0
- package/dist/services/accounts/release-train.service.js +46 -0
- package/dist/services/accounts/release-train.service.js.map +7 -0
- package/dist/services/accounts/salesplan.service.d.ts +45 -0
- package/dist/services/accounts/salesplan.service.js +185 -0
- package/dist/services/accounts/salesplan.service.js.map +2 -2
- package/dist/services/accounts/token-issuer.service.d.ts +31 -0
- package/dist/services/accounts/token-issuer.service.js +63 -0
- package/dist/services/accounts/token-issuer.service.js.map +7 -0
- package/dist/services/accounts/users.service.d.ts +59 -0
- package/dist/services/accounts/users.service.js +296 -4
- package/dist/services/accounts/users.service.js.map +2 -2
- package/dist/services/console/console.admin.service.d.ts +21 -1
- package/dist/services/console/console.admin.service.js +75 -0
- package/dist/services/console/console.admin.service.js.map +2 -2
- package/dist/services/console/console.channel.service.d.ts +49 -0
- package/dist/services/console/console.channel.service.js +123 -0
- package/dist/services/console/console.channel.service.js.map +7 -0
- package/dist/services/console/console.cluster.service.d.ts +23 -11
- package/dist/services/console/console.cluster.service.js +36 -1
- package/dist/services/console/console.cluster.service.js.map +2 -2
- package/dist/services/console/console.cluster.v2.service.d.ts +18 -1
- package/dist/services/console/console.cluster.v2.service.js +95 -0
- package/dist/services/console/console.cluster.v2.service.js.map +2 -2
- package/dist/services/console/console.clusterplan.service.d.ts +21 -0
- package/dist/services/console/console.clusterplan.service.js +92 -0
- package/dist/services/console/console.clusterplan.service.js.map +2 -2
- package/dist/services/console/console.clusterplantype.service.d.ts +54 -0
- package/dist/services/console/console.clusterplantype.service.js +152 -0
- package/dist/services/console/console.clusterplantype.service.js.map +7 -0
- package/dist/services/console/console.k8scontext.service.d.ts +10 -0
- package/dist/services/console/console.k8scontext.service.js +41 -0
- package/dist/services/console/console.k8scontext.service.js.map +7 -0
- package/dist/services/console/console.storybook-config.service.d.ts +10 -0
- package/dist/services/console/console.storybook-config.service.js +40 -0
- package/dist/services/console/console.storybook-config.service.js.map +7 -0
- package/dist/services/console/generation.service.d.ts +45 -0
- package/dist/services/console/generation.service.js +143 -0
- package/dist/services/console/generation.service.js.map +2 -2
- package/dist/services/external/external.accounts.service.d.ts +27 -0
- package/dist/services/external/external.accounts.service.js +80 -0
- package/dist/services/external/external.accounts.service.js.map +7 -0
- package/dist/services/external/external.console.service.d.ts +37 -0
- package/dist/services/external/external.console.service.js +81 -0
- package/dist/services/external/external.console.service.js.map +7 -0
- package/dist/services/external/external.notifications.service.d.ts +78 -0
- package/dist/services/external/external.notifications.service.js +220 -0
- package/dist/services/external/external.notifications.service.js.map +7 -0
- package/dist/services/external/external.services.spec.d.ts +1 -0
- package/dist/services/notifications/notifications.service.d.ts +45 -1
- package/dist/services/notifications/notifications.service.js +168 -1
- package/dist/services/notifications/notifications.service.js.map +2 -2
- package/dist/types/general.types.d.ts +9 -1
- package/dist/utils/api.d.ts +14 -1
- package/dist/utils/api.js +71 -6
- package/dist/utils/api.js.map +2 -2
- package/dist/utils/api.request-headers.spec.d.ts +1 -0
- package/dist/utils/api.transient-retry.spec.d.ts +1 -0
- package/dist/utils/sse.d.ts +51 -0
- package/dist/utils/sse.js +254 -0
- package/dist/utils/sse.js.map +7 -0
- package/dist/utils/sse.spec.d.ts +1 -0
- package/dist/utils/traceparent.d.ts +30 -0
- package/dist/utils/traceparent.js +46 -0
- package/dist/utils/traceparent.js.map +7 -0
- package/dist/utils/traceparent.spec.d.ts +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { request } from "../../utils/api.js";
|
|
2
|
+
import { getEnvParam } from "../../utils/environments.js";
|
|
3
|
+
import { HttpError } from "../../utils/errors.js";
|
|
4
|
+
import {
|
|
5
|
+
connectSse
|
|
6
|
+
} from "../../utils/sse.js";
|
|
7
|
+
class ExternalNotificationsService {
|
|
8
|
+
/** The user's notifications for an org (`GET notifications/orgs/:orgId`). */
|
|
9
|
+
static async getUserNotifications(params) {
|
|
10
|
+
const serviceContext = {
|
|
11
|
+
method: {
|
|
12
|
+
name: "ExternalNotificationsService.getUserNotifications",
|
|
13
|
+
url: `notifications/orgs/${params.params.orgId}`,
|
|
14
|
+
normalizedUrl: "notifications/orgs/:orgId",
|
|
15
|
+
type: "get"
|
|
16
|
+
},
|
|
17
|
+
source: params.config.metrics?.source || "unset",
|
|
18
|
+
target: {
|
|
19
|
+
name: "notifications",
|
|
20
|
+
type: "internal"
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const response = await request({
|
|
24
|
+
...params,
|
|
25
|
+
base: { id: "notifications" },
|
|
26
|
+
url: serviceContext.method.url,
|
|
27
|
+
method: serviceContext.method.type,
|
|
28
|
+
metricsDetails: serviceContext,
|
|
29
|
+
responseType: "json"
|
|
30
|
+
});
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new HttpError(
|
|
33
|
+
`${serviceContext.method.name}: ${response.status} ${response.statusText}`,
|
|
34
|
+
response.status,
|
|
35
|
+
response.statusText
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return response.body ?? [];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Mark a single notification read or dismissed
|
|
42
|
+
* (`PATCH notifications/:uuid/:state`).
|
|
43
|
+
*/
|
|
44
|
+
static async setNotificationState(params) {
|
|
45
|
+
const serviceContext = {
|
|
46
|
+
method: {
|
|
47
|
+
name: "ExternalNotificationsService.setNotificationState",
|
|
48
|
+
url: `notifications/${params.params.uuid}/${params.params.state}`,
|
|
49
|
+
normalizedUrl: "notifications/:uuid/:state",
|
|
50
|
+
type: "patch"
|
|
51
|
+
},
|
|
52
|
+
source: params.config.metrics?.source || "unset",
|
|
53
|
+
target: {
|
|
54
|
+
name: "notifications",
|
|
55
|
+
type: "internal"
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const response = await request({
|
|
59
|
+
config: params.config,
|
|
60
|
+
base: { id: "notifications" },
|
|
61
|
+
url: serviceContext.method.url,
|
|
62
|
+
method: serviceContext.method.type,
|
|
63
|
+
metricsDetails: serviceContext,
|
|
64
|
+
responseType: "none"
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
throw new HttpError(
|
|
68
|
+
`${serviceContext.method.name}: ${response.status} ${response.statusText}`,
|
|
69
|
+
response.status,
|
|
70
|
+
response.statusText
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Mark many notifications read in one call
|
|
76
|
+
* (`PATCH notifications/batch/state/read`, body `{ uuids }`). No-op for an
|
|
77
|
+
* empty list.
|
|
78
|
+
*/
|
|
79
|
+
static async markManyAsRead(params) {
|
|
80
|
+
if (params.params.uuids.length === 0) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const serviceContext = {
|
|
84
|
+
method: {
|
|
85
|
+
name: "ExternalNotificationsService.markManyAsRead",
|
|
86
|
+
url: "notifications/batch/state/read",
|
|
87
|
+
normalizedUrl: "notifications/batch/state/read",
|
|
88
|
+
type: "patch"
|
|
89
|
+
},
|
|
90
|
+
source: params.config.metrics?.source || "unset",
|
|
91
|
+
target: {
|
|
92
|
+
name: "notifications",
|
|
93
|
+
type: "internal"
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const response = await request({
|
|
97
|
+
config: params.config,
|
|
98
|
+
base: { id: "notifications" },
|
|
99
|
+
url: serviceContext.method.url,
|
|
100
|
+
method: serviceContext.method.type,
|
|
101
|
+
metricsDetails: serviceContext,
|
|
102
|
+
body: { uuids: params.params.uuids },
|
|
103
|
+
responseType: "none"
|
|
104
|
+
});
|
|
105
|
+
if (!response.ok) {
|
|
106
|
+
throw new HttpError(
|
|
107
|
+
`${serviceContext.method.name}: ${response.status} ${response.statusText}`,
|
|
108
|
+
response.status,
|
|
109
|
+
response.statusText
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Dismiss every notification for an org
|
|
115
|
+
* (`PATCH notifications/dismissAll?orgId=:orgId`).
|
|
116
|
+
*/
|
|
117
|
+
static async dismissAll(params) {
|
|
118
|
+
const serviceContext = {
|
|
119
|
+
method: {
|
|
120
|
+
name: "ExternalNotificationsService.dismissAll",
|
|
121
|
+
url: `notifications/dismissAll?orgId=${encodeURIComponent(params.params.orgId)}`,
|
|
122
|
+
normalizedUrl: "notifications/dismissAll",
|
|
123
|
+
type: "patch"
|
|
124
|
+
},
|
|
125
|
+
source: params.config.metrics?.source || "unset",
|
|
126
|
+
target: {
|
|
127
|
+
name: "notifications",
|
|
128
|
+
type: "internal"
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const response = await request({
|
|
132
|
+
config: params.config,
|
|
133
|
+
base: { id: "notifications" },
|
|
134
|
+
url: serviceContext.method.url,
|
|
135
|
+
method: serviceContext.method.type,
|
|
136
|
+
metricsDetails: serviceContext,
|
|
137
|
+
responseType: "none"
|
|
138
|
+
});
|
|
139
|
+
if (!response.ok) {
|
|
140
|
+
throw new HttpError(
|
|
141
|
+
`${serviceContext.method.name}: ${response.status} ${response.statusText}`,
|
|
142
|
+
response.status,
|
|
143
|
+
response.statusText
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Fire-and-forget analytics event
|
|
149
|
+
* (`POST analytics/:orgId/:event`, body `{ id }`). Errors are logged and
|
|
150
|
+
* swallowed — analytics must never break the UI.
|
|
151
|
+
*/
|
|
152
|
+
static async trackEvent(params) {
|
|
153
|
+
const serviceContext = {
|
|
154
|
+
method: {
|
|
155
|
+
name: "ExternalNotificationsService.trackEvent",
|
|
156
|
+
url: `analytics/${encodeURIComponent(params.params.orgId)}/${params.params.event}`,
|
|
157
|
+
normalizedUrl: "analytics/:orgId/:event",
|
|
158
|
+
type: "post"
|
|
159
|
+
},
|
|
160
|
+
source: params.config.metrics?.source || "unset",
|
|
161
|
+
target: {
|
|
162
|
+
name: "notifications",
|
|
163
|
+
type: "internal"
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
try {
|
|
167
|
+
await request({
|
|
168
|
+
config: params.config,
|
|
169
|
+
base: { id: "notifications" },
|
|
170
|
+
url: serviceContext.method.url,
|
|
171
|
+
method: serviceContext.method.type,
|
|
172
|
+
metricsDetails: serviceContext,
|
|
173
|
+
body: { id: params.params.id },
|
|
174
|
+
responseType: "text"
|
|
175
|
+
});
|
|
176
|
+
} catch (error) {
|
|
177
|
+
params.config.logger?.debug(
|
|
178
|
+
"ExternalNotificationsService.trackEvent failed (ignored)",
|
|
179
|
+
{ error }
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Subscribe to the user's live notification stream
|
|
185
|
+
* (`GET notifications/events`, `text/event-stream`). `keepAlive` frames are
|
|
186
|
+
* skipped. Auto-reconnects with a fresh token; heartbeat window is 1h to
|
|
187
|
+
* match the backend's keep-alive cadence. Call `.close()` to stop.
|
|
188
|
+
*/
|
|
189
|
+
static streamUserNotifications(params) {
|
|
190
|
+
const base = getEnvParam("notifications", params.config);
|
|
191
|
+
const url = `${base}/notifications/events`;
|
|
192
|
+
return connectSse({
|
|
193
|
+
url,
|
|
194
|
+
config: params.config,
|
|
195
|
+
heartbeatTimeoutMs: 60 * 60 * 1e3,
|
|
196
|
+
onStateChange: params.onStateChange,
|
|
197
|
+
onMessage: (message) => {
|
|
198
|
+
if (!message.data) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const parsed = JSON.parse(message.data);
|
|
203
|
+
if (parsed.keepAlive) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
params.onEvent(parsed);
|
|
207
|
+
} catch (error) {
|
|
208
|
+
params.config.logger?.debug(
|
|
209
|
+
"ExternalNotificationsService.streamUserNotifications: failed to parse event",
|
|
210
|
+
{ error }
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
export {
|
|
218
|
+
ExternalNotificationsService
|
|
219
|
+
};
|
|
220
|
+
//# sourceMappingURL=external.notifications.service.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/services/external/external.notifications.service.ts"],
|
|
4
|
+
"sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type { NotificationDto } from '@camunda/ccma-shared-types'\nimport type {\n RequestBaseParams,\n RequestBaseParamsConfig,\n RequestBaseServiceContext,\n} from '../../types/general.types.js'\nimport { request } from '../../utils/api.js'\nimport { getEnvParam } from '../../utils/environments.js'\nimport { HttpError } from '../../utils/errors.js'\nimport {\n connectSse,\n type SseConnection,\n type SseConnectionState,\n} from '../../utils/sse.js'\n\nexport type UserNotificationAnalyticsEvent =\n | 'notification-panel-opened'\n | 'notification-clicked-cta'\n\nexport interface GetUserNotificationsParams extends RequestBaseParams {\n params: {\n orgId: string\n }\n}\n\nexport interface SetNotificationStateParams extends RequestBaseParams {\n params: {\n uuid: string\n state: 'read' | 'dismiss'\n }\n}\n\nexport interface MarkManyNotificationsReadParams extends RequestBaseParams {\n params: {\n uuids: string[]\n }\n}\n\nexport interface DismissAllNotificationsParams extends RequestBaseParams {\n params: {\n orgId: string\n }\n}\n\nexport interface TrackNotificationEventParams extends RequestBaseParams {\n params: {\n orgId: string\n event: UserNotificationAnalyticsEvent\n id?: string\n }\n}\n\nexport interface StreamUserNotificationsParams {\n config: RequestBaseParamsConfig\n /** Called for each parsed user notification. `keepAlive` frames are skipped. */\n onEvent: (notification: NotificationDto) => void\n onStateChange?: (state: SseConnectionState) => void\n}\n\n/**\n * Per-user notification **feed** on the notifications backend \u2014 the bell-icon\n * inbox (list, mark read/dismiss, live updates), distinct from\n * `NotificationsService`, which is the admin/authoring surface\n * (`notifications/global` CRUD). Use this from webapp navigation; use\n * `NotificationsService` from internal admin tooling.\n */\nexport class ExternalNotificationsService {\n /** The user's notifications for an org (`GET notifications/orgs/:orgId`). */\n public static async getUserNotifications(\n params: GetUserNotificationsParams,\n ): Promise<NotificationDto[]> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalNotificationsService.getUserNotifications',\n url: `notifications/orgs/${params.params.orgId}`,\n normalizedUrl: 'notifications/orgs/:orgId',\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'notifications',\n type: 'internal',\n },\n }\n\n const response = await request<NotificationDto[]>({\n ...params,\n base: { id: 'notifications' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n responseType: 'json',\n })\n\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n\n return response.body ?? []\n }\n\n /**\n * Mark a single notification read or dismissed\n * (`PATCH notifications/:uuid/:state`).\n */\n public static async setNotificationState(\n params: SetNotificationStateParams,\n ): Promise<void> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalNotificationsService.setNotificationState',\n url: `notifications/${params.params.uuid}/${params.params.state}`,\n normalizedUrl: 'notifications/:uuid/:state',\n type: 'patch',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'notifications',\n type: 'internal',\n },\n }\n\n const response = await request({\n config: params.config,\n base: { id: 'notifications' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n responseType: 'none',\n })\n\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n }\n\n /**\n * Mark many notifications read in one call\n * (`PATCH notifications/batch/state/read`, body `{ uuids }`). No-op for an\n * empty list.\n */\n public static async markManyAsRead(\n params: MarkManyNotificationsReadParams,\n ): Promise<void> {\n if (params.params.uuids.length === 0) {\n return\n }\n\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalNotificationsService.markManyAsRead',\n url: 'notifications/batch/state/read',\n normalizedUrl: 'notifications/batch/state/read',\n type: 'patch',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'notifications',\n type: 'internal',\n },\n }\n\n const response = await request({\n config: params.config,\n base: { id: 'notifications' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n body: { uuids: params.params.uuids },\n responseType: 'none',\n })\n\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n }\n\n /**\n * Dismiss every notification for an org\n * (`PATCH notifications/dismissAll?orgId=:orgId`).\n */\n public static async dismissAll(\n params: DismissAllNotificationsParams,\n ): Promise<void> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalNotificationsService.dismissAll',\n url: `notifications/dismissAll?orgId=${encodeURIComponent(params.params.orgId)}`,\n normalizedUrl: 'notifications/dismissAll',\n type: 'patch',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'notifications',\n type: 'internal',\n },\n }\n\n const response = await request({\n config: params.config,\n base: { id: 'notifications' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n responseType: 'none',\n })\n\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n }\n\n /**\n * Fire-and-forget analytics event\n * (`POST analytics/:orgId/:event`, body `{ id }`). Errors are logged and\n * swallowed \u2014 analytics must never break the UI.\n */\n public static async trackEvent(\n params: TrackNotificationEventParams,\n ): Promise<void> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalNotificationsService.trackEvent',\n url: `analytics/${encodeURIComponent(params.params.orgId)}/${params.params.event}`,\n normalizedUrl: 'analytics/:orgId/:event',\n type: 'post',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'notifications',\n type: 'internal',\n },\n }\n\n try {\n await request({\n config: params.config,\n base: { id: 'notifications' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n body: { id: params.params.id },\n responseType: 'text',\n })\n } catch (error) {\n params.config.logger?.debug(\n 'ExternalNotificationsService.trackEvent failed (ignored)',\n { error },\n )\n }\n }\n\n /**\n * Subscribe to the user's live notification stream\n * (`GET notifications/events`, `text/event-stream`). `keepAlive` frames are\n * skipped. Auto-reconnects with a fresh token; heartbeat window is 1h to\n * match the backend's keep-alive cadence. Call `.close()` to stop.\n */\n public static streamUserNotifications(\n params: StreamUserNotificationsParams,\n ): SseConnection {\n const base = getEnvParam('notifications', params.config)\n const url = `${base}/notifications/events`\n\n return connectSse({\n url,\n config: params.config,\n heartbeatTimeoutMs: 60 * 60 * 1000,\n onStateChange: params.onStateChange,\n onMessage: (message) => {\n if (!message.data) {\n return\n }\n try {\n const parsed = JSON.parse(message.data) as NotificationDto & {\n keepAlive?: boolean\n }\n if (parsed.keepAlive) {\n return\n }\n params.onEvent(parsed)\n } catch (error) {\n params.config.logger?.debug(\n 'ExternalNotificationsService.streamUserNotifications: failed to parse event',\n { error },\n )\n }\n },\n })\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,51 @@
|
|
|
1
|
-
import type { NotificationOptions } from '@camunda/ccma-shared-types';
|
|
1
|
+
import type { NotificationDto, NotificationOptions } from '@camunda/ccma-shared-types';
|
|
2
2
|
import type { RequestBaseParams } from '../../types/general.types.js';
|
|
3
|
+
export interface CreateGlobalNotificationParams extends RequestBaseParams {
|
|
4
|
+
body: {
|
|
5
|
+
/** Scheduling rides on `meta.scheduleTs` (epoch ms). */
|
|
6
|
+
notification: NotificationOptions;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export interface CreateNotificationBySalesPlanParams extends RequestBaseParams {
|
|
10
|
+
params: {
|
|
11
|
+
salesPlanType: string;
|
|
12
|
+
};
|
|
13
|
+
body: {
|
|
14
|
+
notification: NotificationOptions;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface UpdateNotificationParams extends RequestBaseParams {
|
|
18
|
+
params: {
|
|
19
|
+
uuid: string;
|
|
20
|
+
};
|
|
21
|
+
body: {
|
|
22
|
+
/** Only draft/scheduled notifications are editable (backend-enforced). */
|
|
23
|
+
notification: Partial<NotificationOptions>;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface DeleteGlobalNotificationParams extends RequestBaseParams {
|
|
27
|
+
params: {
|
|
28
|
+
notificationId: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
3
31
|
export declare class NotificationsService {
|
|
4
32
|
static sendNotification(params: {
|
|
5
33
|
notification: NotificationOptions;
|
|
6
34
|
} & RequestBaseParams): Promise<void>;
|
|
35
|
+
/** All global notifications (sent, draft, scheduled) for the admin list. */
|
|
36
|
+
static getGlobalNotifications(params: RequestBaseParams): Promise<NotificationDto[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Create a global notification (visible to every user). Scheduling rides on
|
|
39
|
+
* `meta.scheduleTs`; an `initState` of `draft` keeps it unsent.
|
|
40
|
+
*/
|
|
41
|
+
static createGlobalNotification(params: CreateGlobalNotificationParams): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Create a notification for every member of the orgs on a sales-plan type
|
|
44
|
+
* (fans out via the accounts backend, `POST api/notifications/:salesPlanType`).
|
|
45
|
+
*/
|
|
46
|
+
static createNotificationBySalesPlan(params: CreateNotificationBySalesPlanParams): Promise<void>;
|
|
47
|
+
/** Update a draft/scheduled notification (`PATCH notifications/:uuid`). */
|
|
48
|
+
static updateNotification(params: UpdateNotificationParams): Promise<void>;
|
|
49
|
+
/** Delete a global notification (`DELETE notifications/global/:id`). */
|
|
50
|
+
static deleteGlobalNotification(params: DeleteGlobalNotificationParams): Promise<void>;
|
|
7
51
|
}
|
|
@@ -21,7 +21,174 @@ class NotificationsService {
|
|
|
21
21
|
url: serviceContext.method.url,
|
|
22
22
|
method: serviceContext.method.type,
|
|
23
23
|
metricsDetails: serviceContext,
|
|
24
|
-
body: { notification: params.notification }
|
|
24
|
+
body: { notification: params.notification },
|
|
25
|
+
// Transient envoy resets (connection termination during a pod restart)
|
|
26
|
+
// otherwise drop the notification and trip the internal error-rate alert.
|
|
27
|
+
// Safe to retry: a duplicate notification is harmless (deduped by
|
|
28
|
+
// meta.identifier / low-impact toast).
|
|
29
|
+
retryTransientErrors: true
|
|
30
|
+
});
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new HttpError(
|
|
33
|
+
`${serviceContext.method.name}: ${response.status} ${response.statusText}`,
|
|
34
|
+
response.status,
|
|
35
|
+
response.statusText
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** All global notifications (sent, draft, scheduled) for the admin list. */
|
|
40
|
+
static async getGlobalNotifications(params) {
|
|
41
|
+
const serviceContext = {
|
|
42
|
+
method: {
|
|
43
|
+
name: `NotificationsService.getGlobalNotifications`,
|
|
44
|
+
url: `notifications/global`,
|
|
45
|
+
normalizedUrl: `notifications/global`,
|
|
46
|
+
type: "get"
|
|
47
|
+
},
|
|
48
|
+
source: params.config.metrics?.source || "unset",
|
|
49
|
+
target: {
|
|
50
|
+
name: "notifications",
|
|
51
|
+
type: "internal"
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const response = await request({
|
|
55
|
+
...params,
|
|
56
|
+
base: { id: "notifications" },
|
|
57
|
+
url: serviceContext.method.url,
|
|
58
|
+
method: serviceContext.method.type,
|
|
59
|
+
metricsDetails: serviceContext,
|
|
60
|
+
responseType: "json"
|
|
61
|
+
});
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
throw new HttpError(
|
|
64
|
+
`${serviceContext.method.name}: ${response.status} ${response.statusText}`,
|
|
65
|
+
response.status,
|
|
66
|
+
response.statusText
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return response.body ?? [];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a global notification (visible to every user). Scheduling rides on
|
|
73
|
+
* `meta.scheduleTs`; an `initState` of `draft` keeps it unsent.
|
|
74
|
+
*/
|
|
75
|
+
static async createGlobalNotification(params) {
|
|
76
|
+
const serviceContext = {
|
|
77
|
+
method: {
|
|
78
|
+
name: `NotificationsService.createGlobalNotification`,
|
|
79
|
+
url: `notifications/global`,
|
|
80
|
+
normalizedUrl: `notifications/global`,
|
|
81
|
+
type: "post"
|
|
82
|
+
},
|
|
83
|
+
source: params.config.metrics?.source || "unset",
|
|
84
|
+
target: {
|
|
85
|
+
name: "notifications",
|
|
86
|
+
type: "internal"
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const response = await request({
|
|
90
|
+
config: params.config,
|
|
91
|
+
base: { id: "notifications" },
|
|
92
|
+
url: serviceContext.method.url,
|
|
93
|
+
method: serviceContext.method.type,
|
|
94
|
+
metricsDetails: serviceContext,
|
|
95
|
+
body: params.body
|
|
96
|
+
});
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
throw new HttpError(
|
|
99
|
+
`${serviceContext.method.name}: ${response.status} ${response.statusText}`,
|
|
100
|
+
response.status,
|
|
101
|
+
response.statusText
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Create a notification for every member of the orgs on a sales-plan type
|
|
107
|
+
* (fans out via the accounts backend, `POST api/notifications/:salesPlanType`).
|
|
108
|
+
*/
|
|
109
|
+
static async createNotificationBySalesPlan(params) {
|
|
110
|
+
const serviceContext = {
|
|
111
|
+
method: {
|
|
112
|
+
name: `NotificationsService.createNotificationBySalesPlan`,
|
|
113
|
+
url: `api/notifications/${encodeURIComponent(params.params.salesPlanType)}`,
|
|
114
|
+
normalizedUrl: `api/notifications/:salesPlanType`,
|
|
115
|
+
type: "post"
|
|
116
|
+
},
|
|
117
|
+
source: params.config.metrics?.source || "unset",
|
|
118
|
+
target: {
|
|
119
|
+
name: "accounts",
|
|
120
|
+
type: "internal"
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const response = await request({
|
|
124
|
+
config: params.config,
|
|
125
|
+
base: { id: "accounts" },
|
|
126
|
+
url: serviceContext.method.url,
|
|
127
|
+
method: serviceContext.method.type,
|
|
128
|
+
metricsDetails: serviceContext,
|
|
129
|
+
body: params.body
|
|
130
|
+
});
|
|
131
|
+
if (!response.ok) {
|
|
132
|
+
throw new HttpError(
|
|
133
|
+
`${serviceContext.method.name}: ${response.status} ${response.statusText}`,
|
|
134
|
+
response.status,
|
|
135
|
+
response.statusText
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/** Update a draft/scheduled notification (`PATCH notifications/:uuid`). */
|
|
140
|
+
static async updateNotification(params) {
|
|
141
|
+
const serviceContext = {
|
|
142
|
+
method: {
|
|
143
|
+
name: `NotificationsService.updateNotification`,
|
|
144
|
+
url: `notifications/${params.params.uuid}`,
|
|
145
|
+
normalizedUrl: `notifications/:uuid`,
|
|
146
|
+
type: "patch"
|
|
147
|
+
},
|
|
148
|
+
source: params.config.metrics?.source || "unset",
|
|
149
|
+
target: {
|
|
150
|
+
name: "notifications",
|
|
151
|
+
type: "internal"
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
const response = await request({
|
|
155
|
+
config: params.config,
|
|
156
|
+
base: { id: "notifications" },
|
|
157
|
+
url: serviceContext.method.url,
|
|
158
|
+
method: serviceContext.method.type,
|
|
159
|
+
metricsDetails: serviceContext,
|
|
160
|
+
body: params.body
|
|
161
|
+
});
|
|
162
|
+
if (!response.ok) {
|
|
163
|
+
throw new HttpError(
|
|
164
|
+
`${serviceContext.method.name}: ${response.status} ${response.statusText}`,
|
|
165
|
+
response.status,
|
|
166
|
+
response.statusText
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/** Delete a global notification (`DELETE notifications/global/:id`). */
|
|
171
|
+
static async deleteGlobalNotification(params) {
|
|
172
|
+
const serviceContext = {
|
|
173
|
+
method: {
|
|
174
|
+
name: `NotificationsService.deleteGlobalNotification`,
|
|
175
|
+
url: `notifications/global/${params.params.notificationId}`,
|
|
176
|
+
normalizedUrl: `notifications/global/:notificationId`,
|
|
177
|
+
type: "delete"
|
|
178
|
+
},
|
|
179
|
+
source: params.config.metrics?.source || "unset",
|
|
180
|
+
target: {
|
|
181
|
+
name: "notifications",
|
|
182
|
+
type: "internal"
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
const response = await request({
|
|
186
|
+
config: params.config,
|
|
187
|
+
base: { id: "notifications" },
|
|
188
|
+
url: serviceContext.method.url,
|
|
189
|
+
method: serviceContext.method.type,
|
|
190
|
+
metricsDetails: serviceContext,
|
|
191
|
+
responseType: "none"
|
|
25
192
|
});
|
|
26
193
|
if (!response.ok) {
|
|
27
194
|
throw new HttpError(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/services/notifications/notifications.service.ts"],
|
|
4
|
-
"sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type {
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type {\n NotificationDto,\n NotificationOptions,\n} from '@camunda/ccma-shared-types'\nimport type {\n RequestBaseParams,\n RequestBaseServiceContext,\n} from '../../types/general.types.js'\nimport { request } from '../../utils/api.js'\nimport { HttpError } from '../../utils/errors.js'\n\nexport interface CreateGlobalNotificationParams extends RequestBaseParams {\n body: {\n /** Scheduling rides on `meta.scheduleTs` (epoch ms). */\n notification: NotificationOptions\n }\n}\n\nexport interface CreateNotificationBySalesPlanParams extends RequestBaseParams {\n params: {\n salesPlanType: string\n }\n body: {\n notification: NotificationOptions\n }\n}\n\nexport interface UpdateNotificationParams extends RequestBaseParams {\n params: {\n uuid: string\n }\n body: {\n /** Only draft/scheduled notifications are editable (backend-enforced). */\n notification: Partial<NotificationOptions>\n }\n}\n\nexport interface DeleteGlobalNotificationParams extends RequestBaseParams {\n params: {\n notificationId: string\n }\n}\n\nexport class NotificationsService {\n public static async sendNotification(\n params: { notification: NotificationOptions } & RequestBaseParams,\n ) {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `NotificationsService.sendNotification`,\n url: `notifications/${params.notification.type}`,\n normalizedUrl: `notifications/:type`,\n type: 'post',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'notifications',\n type: 'internal',\n },\n }\n\n const response = await request({\n config: params.config,\n base: { id: 'notifications' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n body: { notification: params.notification },\n // Transient envoy resets (connection termination during a pod restart)\n // otherwise drop the notification and trip the internal error-rate alert.\n // Safe to retry: a duplicate notification is harmless (deduped by\n // meta.identifier / low-impact toast).\n retryTransientErrors: true,\n })\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n }\n\n /** All global notifications (sent, draft, scheduled) for the admin list. */\n public static async getGlobalNotifications(\n params: RequestBaseParams,\n ): Promise<NotificationDto[]> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `NotificationsService.getGlobalNotifications`,\n url: `notifications/global`,\n normalizedUrl: `notifications/global`,\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'notifications',\n type: 'internal',\n },\n }\n\n const response = await request<NotificationDto[]>({\n ...params,\n base: { id: 'notifications' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n responseType: 'json',\n })\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n return response.body ?? []\n }\n\n /**\n * Create a global notification (visible to every user). Scheduling rides on\n * `meta.scheduleTs`; an `initState` of `draft` keeps it unsent.\n */\n public static async createGlobalNotification(\n params: CreateGlobalNotificationParams,\n ): Promise<void> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `NotificationsService.createGlobalNotification`,\n url: `notifications/global`,\n normalizedUrl: `notifications/global`,\n type: 'post',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'notifications',\n type: 'internal',\n },\n }\n\n const response = await request({\n config: params.config,\n base: { id: 'notifications' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n body: params.body,\n })\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n }\n\n /**\n * Create a notification for every member of the orgs on a sales-plan type\n * (fans out via the accounts backend, `POST api/notifications/:salesPlanType`).\n */\n public static async createNotificationBySalesPlan(\n params: CreateNotificationBySalesPlanParams,\n ): Promise<void> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `NotificationsService.createNotificationBySalesPlan`,\n url: `api/notifications/${encodeURIComponent(params.params.salesPlanType)}`,\n normalizedUrl: `api/notifications/:salesPlanType`,\n type: 'post',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'accounts',\n type: 'internal',\n },\n }\n\n const response = await request({\n config: params.config,\n base: { id: 'accounts' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n body: params.body,\n })\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n }\n\n /** Update a draft/scheduled notification (`PATCH notifications/:uuid`). */\n public static async updateNotification(\n params: UpdateNotificationParams,\n ): Promise<void> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `NotificationsService.updateNotification`,\n url: `notifications/${params.params.uuid}`,\n normalizedUrl: `notifications/:uuid`,\n type: 'patch',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'notifications',\n type: 'internal',\n },\n }\n\n const response = await request({\n config: params.config,\n base: { id: 'notifications' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n body: params.body,\n })\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n }\n\n /** Delete a global notification (`DELETE notifications/global/:id`). */\n public static async deleteGlobalNotification(\n params: DeleteGlobalNotificationParams,\n ): Promise<void> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `NotificationsService.deleteGlobalNotification`,\n url: `notifications/global/${params.params.notificationId}`,\n normalizedUrl: `notifications/global/:notificationId`,\n type: 'delete',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'notifications',\n type: 'internal',\n },\n }\n\n const response = await request({\n config: params.config,\n base: { id: 'notifications' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n responseType: 'none',\n })\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -7,7 +7,7 @@ export interface RequestBaseParamsLogger {
|
|
|
7
7
|
info: (message: string, data?: any) => void;
|
|
8
8
|
error: (message: string, data?: any) => void;
|
|
9
9
|
}
|
|
10
|
-
export type RequestBaseCustomMetricsDetailsType = 'request' | 'success' | 'error' | 'rate-limit-retry';
|
|
10
|
+
export type RequestBaseCustomMetricsDetailsType = 'request' | 'success' | 'error' | 'rate-limit-retry' | 'transient-retry';
|
|
11
11
|
export interface RequestBaseServiceContext {
|
|
12
12
|
source: string;
|
|
13
13
|
target: {
|
|
@@ -41,6 +41,14 @@ export interface RequestBaseParamsConfig {
|
|
|
41
41
|
metrics?: RequestBaseCustomMetrics;
|
|
42
42
|
timeout?: number;
|
|
43
43
|
proxyAgent?: any;
|
|
44
|
+
/**
|
|
45
|
+
* Returns extra headers to add to every outgoing request, evaluated per call.
|
|
46
|
+
* Used to propagate correlation headers (traceparent, x-cc-session-id) from
|
|
47
|
+
* the ambient request context. Only wire this for trusted internal services —
|
|
48
|
+
* not third-party APIs. Explicit per-request headers and auth/content-type
|
|
49
|
+
* headers take precedence over these. Errors thrown here are ignored.
|
|
50
|
+
*/
|
|
51
|
+
getDynamicHeaders?: () => Record<string, string>;
|
|
44
52
|
frontendCaching?: {
|
|
45
53
|
enabled: boolean;
|
|
46
54
|
dbName: string;
|
package/dist/utils/api.d.ts
CHANGED
|
@@ -10,11 +10,24 @@ export interface RequestPayload extends RequestBaseParams {
|
|
|
10
10
|
[key: string]: string;
|
|
11
11
|
};
|
|
12
12
|
type?: 'json' | 'text' | 'form' | 'none';
|
|
13
|
-
responseType?: 'json' | 'text' | 'none';
|
|
13
|
+
responseType?: 'json' | 'text' | 'blob' | 'none';
|
|
14
14
|
retry?: {
|
|
15
15
|
attempts: number;
|
|
16
16
|
remaining: number;
|
|
17
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* Opt-in: retry transient gateway failures (502/503/504 and network/fetch
|
|
20
|
+
* errors) with backoff, mirroring the 429 retry. Retried attempts emit a
|
|
21
|
+
* `transient-retry` metric instead of `error`, so a healed blip (e.g. an
|
|
22
|
+
* envoy connection reset during a pod restart) doesn't count toward the
|
|
23
|
+
* internal error-rate alert. Only enable for idempotent-safe calls — a
|
|
24
|
+
* retried POST may execute twice.
|
|
25
|
+
*/
|
|
26
|
+
retryTransientErrors?: boolean;
|
|
27
|
+
transientRetry?: {
|
|
28
|
+
attempts: number;
|
|
29
|
+
remaining: number;
|
|
30
|
+
};
|
|
18
31
|
body?: any;
|
|
19
32
|
metricsDetails: RequestBaseServiceContext;
|
|
20
33
|
}
|