@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.
Files changed (91) hide show
  1. package/dist/index.d.ts +31 -7
  2. package/dist/index.js +56 -2
  3. package/dist/index.js.map +2 -2
  4. package/dist/services/accounts/admin-tools.service.d.ts +27 -0
  5. package/dist/services/accounts/admin-tools.service.js +70 -0
  6. package/dist/services/accounts/admin-tools.service.js.map +7 -0
  7. package/dist/services/accounts/connections.service.d.ts +85 -0
  8. package/dist/services/accounts/connections.service.js +150 -0
  9. package/dist/services/accounts/connections.service.js.map +2 -2
  10. package/dist/services/accounts/early-access-features.service.d.ts +59 -0
  11. package/dist/services/accounts/early-access-features.service.js +142 -0
  12. package/dist/services/accounts/early-access-features.service.js.map +2 -2
  13. package/dist/services/accounts/invites.service.d.ts +28 -0
  14. package/dist/services/accounts/invites.service.js +53 -0
  15. package/dist/services/accounts/invites.service.js.map +7 -0
  16. package/dist/services/accounts/orgs.service.d.ts +42 -0
  17. package/dist/services/accounts/orgs.service.js +123 -0
  18. package/dist/services/accounts/orgs.service.js.map +2 -2
  19. package/dist/services/accounts/orgs.v2.service.d.ts +6 -0
  20. package/dist/services/accounts/orgs.v2.service.js +34 -0
  21. package/dist/services/accounts/orgs.v2.service.js.map +2 -2
  22. package/dist/services/accounts/pdf-watermark.service.d.ts +93 -0
  23. package/dist/services/accounts/pdf-watermark.service.js +147 -0
  24. package/dist/services/accounts/pdf-watermark.service.js.map +7 -0
  25. package/dist/services/accounts/release-train.service.d.ts +25 -0
  26. package/dist/services/accounts/release-train.service.js +46 -0
  27. package/dist/services/accounts/release-train.service.js.map +7 -0
  28. package/dist/services/accounts/salesplan.service.d.ts +45 -0
  29. package/dist/services/accounts/salesplan.service.js +185 -0
  30. package/dist/services/accounts/salesplan.service.js.map +2 -2
  31. package/dist/services/accounts/token-issuer.service.d.ts +31 -0
  32. package/dist/services/accounts/token-issuer.service.js +63 -0
  33. package/dist/services/accounts/token-issuer.service.js.map +7 -0
  34. package/dist/services/accounts/users.service.d.ts +59 -0
  35. package/dist/services/accounts/users.service.js +296 -4
  36. package/dist/services/accounts/users.service.js.map +2 -2
  37. package/dist/services/console/console.admin.service.d.ts +21 -1
  38. package/dist/services/console/console.admin.service.js +75 -0
  39. package/dist/services/console/console.admin.service.js.map +2 -2
  40. package/dist/services/console/console.channel.service.d.ts +49 -0
  41. package/dist/services/console/console.channel.service.js +123 -0
  42. package/dist/services/console/console.channel.service.js.map +7 -0
  43. package/dist/services/console/console.cluster.service.d.ts +23 -11
  44. package/dist/services/console/console.cluster.service.js +36 -1
  45. package/dist/services/console/console.cluster.service.js.map +2 -2
  46. package/dist/services/console/console.cluster.v2.service.d.ts +18 -1
  47. package/dist/services/console/console.cluster.v2.service.js +95 -0
  48. package/dist/services/console/console.cluster.v2.service.js.map +2 -2
  49. package/dist/services/console/console.clusterplan.service.d.ts +21 -0
  50. package/dist/services/console/console.clusterplan.service.js +92 -0
  51. package/dist/services/console/console.clusterplan.service.js.map +2 -2
  52. package/dist/services/console/console.clusterplantype.service.d.ts +54 -0
  53. package/dist/services/console/console.clusterplantype.service.js +152 -0
  54. package/dist/services/console/console.clusterplantype.service.js.map +7 -0
  55. package/dist/services/console/console.k8scontext.service.d.ts +10 -0
  56. package/dist/services/console/console.k8scontext.service.js +41 -0
  57. package/dist/services/console/console.k8scontext.service.js.map +7 -0
  58. package/dist/services/console/console.storybook-config.service.d.ts +10 -0
  59. package/dist/services/console/console.storybook-config.service.js +40 -0
  60. package/dist/services/console/console.storybook-config.service.js.map +7 -0
  61. package/dist/services/console/generation.service.d.ts +45 -0
  62. package/dist/services/console/generation.service.js +143 -0
  63. package/dist/services/console/generation.service.js.map +2 -2
  64. package/dist/services/external/external.accounts.service.d.ts +27 -0
  65. package/dist/services/external/external.accounts.service.js +80 -0
  66. package/dist/services/external/external.accounts.service.js.map +7 -0
  67. package/dist/services/external/external.console.service.d.ts +37 -0
  68. package/dist/services/external/external.console.service.js +81 -0
  69. package/dist/services/external/external.console.service.js.map +7 -0
  70. package/dist/services/external/external.notifications.service.d.ts +78 -0
  71. package/dist/services/external/external.notifications.service.js +220 -0
  72. package/dist/services/external/external.notifications.service.js.map +7 -0
  73. package/dist/services/external/external.services.spec.d.ts +1 -0
  74. package/dist/services/notifications/notifications.service.d.ts +45 -1
  75. package/dist/services/notifications/notifications.service.js +168 -1
  76. package/dist/services/notifications/notifications.service.js.map +2 -2
  77. package/dist/types/general.types.d.ts +9 -1
  78. package/dist/utils/api.d.ts +14 -1
  79. package/dist/utils/api.js +71 -6
  80. package/dist/utils/api.js.map +2 -2
  81. package/dist/utils/api.request-headers.spec.d.ts +1 -0
  82. package/dist/utils/api.transient-retry.spec.d.ts +1 -0
  83. package/dist/utils/sse.d.ts +51 -0
  84. package/dist/utils/sse.js +254 -0
  85. package/dist/utils/sse.js.map +7 -0
  86. package/dist/utils/sse.spec.d.ts +1 -0
  87. package/dist/utils/traceparent.d.ts +30 -0
  88. package/dist/utils/traceparent.js +46 -0
  89. package/dist/utils/traceparent.js.map +7 -0
  90. package/dist/utils/traceparent.spec.d.ts +1 -0
  91. 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 { NotificationOptions } 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 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 })\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": "AAWA,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAEnB,MAAM,qBAAqB;AAAA,EAChC,aAAoB,iBAClB,QACA;AACA,UAAM,iBAA4C;AAAA,MAChD,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,KAAK,iBAAiB,OAAO,aAAa,IAAI;AAAA,QAC9C,eAAe;AAAA,QACf,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO,OAAO,SAAS,UAAU;AAAA,MACzC,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,QAAQ;AAAA,MAC7B,QAAQ,OAAO;AAAA,MACf,MAAM,EAAE,IAAI,gBAAgB;AAAA,MAC5B,KAAK,eAAe,OAAO;AAAA,MAC3B,QAAQ,eAAe,OAAO;AAAA,MAC9B,gBAAgB;AAAA,MAChB,MAAM,EAAE,cAAc,OAAO,aAAa;AAAA,IAC5C,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,GAAG,eAAe,OAAO,IAAI,KAAK,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QACxE,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACF;",
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;
@@ -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
  }