@neoimpulse/cap-js-notifications 1.0.6 → 1.0.8

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.
@@ -3,305 +3,324 @@ const { buildHeadersForDestination } = require("@sap-cloud-sdk/connectivity");
3
3
  const { getNotificationDestination, getPrefix, getNotificationTypesKeyWithPrefix } = require("./utils");
4
4
  const NOTIFICATION_TYPES_API_ENDPOINT = "v2/NotificationType.svc";
5
5
  const cds = require("@sap/cds");
6
- const LOG = cds.log('notifications');
6
+ const LOG = cds.log("notifications");
7
7
 
8
8
  const defaultTemplate = {
9
- NotificationTypeKey: "Default",
10
- NotificationTypeVersion: "1",
11
- Templates: [
12
- {
13
- Language: "en",
14
- Description: "Other Notifications",
15
- TemplatePublic: "{{title}}",
16
- TemplateSensitive: "{{title}}",
17
- TemplateGrouped: "Other Notifications",
18
- TemplateLanguage: "mustache",
19
- Subtitle: "{{description}}"
20
- }
21
- ]
9
+ NotificationTypeKey: "Default",
10
+ NotificationTypeVersion: "1",
11
+ Templates: [
12
+ {
13
+ Language: "en",
14
+ Description: "Other Notifications",
15
+ TemplatePublic: "{{title}}",
16
+ TemplateSensitive: "{{title}}",
17
+ TemplateGrouped: "Other Notifications",
18
+ TemplateLanguage: "mustache",
19
+ Subtitle: "{{description}}"
20
+ }
21
+ ]
22
22
  };
23
23
 
24
24
  function fromOdataArrayFormat(objectInArray) {
25
- if (objectInArray === undefined || objectInArray === null || Array.isArray(objectInArray)) {
26
- return (objectInArray === undefined || objectInArray === null) ? [] : objectInArray;
27
- } else {
28
- return (objectInArray.results === undefined || objectInArray.results === null) ? [] : objectInArray.results;
29
- }
25
+ if (objectInArray === undefined || objectInArray === null || Array.isArray(objectInArray)) {
26
+ return objectInArray === undefined || objectInArray === null ? [] : objectInArray;
27
+ } else {
28
+ return objectInArray.results === undefined || objectInArray.results === null ? [] : objectInArray.results;
29
+ }
30
30
  }
31
31
 
32
32
  function createNotificationTypesMap(notificationTypesJSON, isLocal = false) {
33
- const types = {};
33
+ const types = {};
34
34
 
35
- if (isLocal) {
36
- types["Default"] = { "1": defaultTemplate };
37
- }
38
-
39
- // add user provided templates
40
- notificationTypesJSON.forEach((notificationType) => {
41
- // set default NotificationTypeVersion if required
42
- if (notificationType.NotificationTypeVersion === undefined) {
43
- notificationType.NotificationTypeVersion = "1";
35
+ if (isLocal) {
36
+ types["Default"] = { 1: defaultTemplate };
44
37
  }
45
38
 
46
- const notificationTypeKeyWithPrefix = getNotificationTypesKeyWithPrefix(notificationType.NotificationTypeKey);
39
+ // add user provided templates
40
+ notificationTypesJSON.forEach((notificationType) => {
41
+ // set default NotificationTypeVersion if required
42
+ if (notificationType.NotificationTypeVersion === undefined) {
43
+ notificationType.NotificationTypeVersion = "1";
44
+ }
47
45
 
48
- // update the notification type key with prefix
49
- notificationType.NotificationTypeKey = notificationTypeKeyWithPrefix;
46
+ const notificationTypeKeyWithPrefix = getNotificationTypesKeyWithPrefix(notificationType.NotificationTypeKey);
50
47
 
51
- if (!(notificationTypeKeyWithPrefix in types)) {
52
- types[notificationTypeKeyWithPrefix] = {};
53
- }
48
+ // update the notification type key with prefix
49
+ notificationType.NotificationTypeKey = notificationTypeKeyWithPrefix;
50
+
51
+ if (!(notificationTypeKeyWithPrefix in types)) {
52
+ types[notificationTypeKeyWithPrefix] = {};
53
+ }
54
54
 
55
- types[notificationTypeKeyWithPrefix][notificationType.NotificationTypeVersion] = notificationType;
56
- });
55
+ types[notificationTypeKeyWithPrefix][notificationType.NotificationTypeVersion] = notificationType;
56
+ });
57
57
 
58
- return types;
58
+ return types;
59
59
  }
60
60
 
61
61
  async function getNotificationTypes() {
62
- const notificationDestination = await getNotificationDestination();
63
- const response = await executeHttpRequest(notificationDestination, {
64
- url: `${NOTIFICATION_TYPES_API_ENDPOINT}/NotificationTypes?$format=json&$expand=Templates,Actions,DeliveryChannels`,
65
- method: "get"
66
- });
67
- return response.data.d.results;
62
+ const notificationDestination = await getNotificationDestination();
63
+ const response = await executeHttpRequest(notificationDestination, {
64
+ url: `${NOTIFICATION_TYPES_API_ENDPOINT}/NotificationTypes?$format=json&$expand=Templates,Actions,DeliveryChannels`,
65
+ method: "get"
66
+ });
67
+ return response.data.d.results;
68
68
  }
69
69
 
70
70
  async function createNotificationType(notificationType) {
71
- const notificationDestination = await getNotificationDestination();
72
- const csrfHeaders = await buildHeadersForDestination(notificationDestination, {
73
- url: NOTIFICATION_TYPES_API_ENDPOINT
74
- });
75
-
76
- LOG._warn && LOG.warn(
77
- `Notification Type of key ${notificationType.NotificationTypeKey} and version ${notificationType.NotificationTypeVersion} was not found. Creating it...`
78
- );
79
-
80
- const response = await executeHttpRequest(notificationDestination, {
81
- url: `${NOTIFICATION_TYPES_API_ENDPOINT}/NotificationTypes`,
82
- method: "post",
83
- data: notificationType,
84
- headers: csrfHeaders
85
- });
86
- return response.data?.d ?? response;
71
+ const notificationDestination = await getNotificationDestination();
72
+ const csrfHeaders = await buildHeadersForDestination(notificationDestination, {
73
+ url: NOTIFICATION_TYPES_API_ENDPOINT
74
+ });
75
+
76
+ LOG._warn &&
77
+ LOG.warn(
78
+ `Notification Type of key ${notificationType.NotificationTypeKey} and version ${notificationType.NotificationTypeVersion} was not found. Creating it...`
79
+ );
80
+
81
+ const response = await executeHttpRequest(notificationDestination, {
82
+ url: `${NOTIFICATION_TYPES_API_ENDPOINT}/NotificationTypes`,
83
+ method: "post",
84
+ data: notificationType,
85
+ headers: csrfHeaders
86
+ });
87
+ return response.data?.d ?? response;
87
88
  }
88
89
 
89
90
  async function updateNotificationType(id, notificationType) {
90
- const notificationDestination = await getNotificationDestination();
91
- const csrfHeaders = await buildHeadersForDestination(notificationDestination, {
92
- url: NOTIFICATION_TYPES_API_ENDPOINT
93
- });
94
-
95
- LOG._info && LOG.info(
96
- `Detected change in notification type of key ${notificationType.NotificationTypeKey} and version ${notificationType.NotificationTypeVersion}. Updating it...`
97
- );
98
-
99
- const response = await executeHttpRequest(notificationDestination, {
100
- url: `${NOTIFICATION_TYPES_API_ENDPOINT}/NotificationTypes(guid'${id}')`,
101
- method: "patch",
102
- data: notificationType,
103
- headers: csrfHeaders
104
- });
105
- return response.status;
91
+ const notificationDestination = await getNotificationDestination();
92
+ const csrfHeaders = await buildHeadersForDestination(notificationDestination, {
93
+ url: NOTIFICATION_TYPES_API_ENDPOINT
94
+ });
95
+
96
+ LOG._info &&
97
+ LOG.info(
98
+ `Detected change in notification type of key ${notificationType.NotificationTypeKey} and version ${notificationType.NotificationTypeVersion}. Updating it...`
99
+ );
100
+
101
+ const response = await executeHttpRequest(notificationDestination, {
102
+ url: `${NOTIFICATION_TYPES_API_ENDPOINT}/NotificationTypes(guid'${id}')`,
103
+ method: "patch",
104
+ data: notificationType,
105
+ headers: csrfHeaders
106
+ });
107
+ return response.status;
106
108
  }
107
109
 
108
110
  async function deleteNotificationType(notificationType) {
109
- const notificationDestination = await getNotificationDestination();
110
- const csrfHeaders = await buildHeadersForDestination(notificationDestination, {
111
- url: NOTIFICATION_TYPES_API_ENDPOINT
112
- });
113
-
114
- LOG._info && LOG.info(
115
- `Notification Type of key ${notificationType.NotificationTypeKey} and version ${notificationType.NotificationTypeVersion} not present in the types file. Deleting it...`
116
- );
117
-
118
- const response = await executeHttpRequest(notificationDestination, {
119
- url: `${NOTIFICATION_TYPES_API_ENDPOINT}/NotificationTypes(guid'${notificationType.NotificationTypeId}')`,
120
- method: "delete",
121
- headers: csrfHeaders
122
- });
123
- return response.status;
111
+ const notificationDestination = await getNotificationDestination();
112
+ const csrfHeaders = await buildHeadersForDestination(notificationDestination, {
113
+ url: NOTIFICATION_TYPES_API_ENDPOINT
114
+ });
115
+
116
+ LOG._info &&
117
+ LOG.info(
118
+ `Notification Type of key ${notificationType.NotificationTypeKey} and version ${notificationType.NotificationTypeVersion} not present in the types file. Deleting it...`
119
+ );
120
+
121
+ const response = await executeHttpRequest(notificationDestination, {
122
+ url: `${NOTIFICATION_TYPES_API_ENDPOINT}/NotificationTypes(guid'${notificationType.NotificationTypeId}')`,
123
+ method: "delete",
124
+ headers: csrfHeaders
125
+ });
126
+ return response.status;
124
127
  }
125
128
 
126
129
  function _createChannelsMap(channels) {
127
- const channelMap = {};
130
+ const channelMap = {};
128
131
 
129
- channels.forEach((channel) => {
130
- channelMap[channel.Type] = channel;
131
- });
132
+ channels.forEach((channel) => {
133
+ channelMap[channel.Type] = channel;
134
+ });
132
135
 
133
- return channelMap;
136
+ return channelMap;
134
137
  }
135
138
 
136
139
  function areDeliveryChannelsEqual(oldChannels, newChannels) {
137
- if (oldChannels.length !== newChannels.length) {
138
- return false;
139
- }
140
+ if (oldChannels.length !== newChannels.length) {
141
+ return false;
142
+ }
140
143
 
141
- const oldChannelsMap = _createChannelsMap(oldChannels);
142
- const newChannelsMap = _createChannelsMap(newChannels);
144
+ const oldChannelsMap = _createChannelsMap(oldChannels);
145
+ const newChannelsMap = _createChannelsMap(newChannels);
143
146
 
144
- for (let type of Object.keys(oldChannelsMap)) {
145
- if (!(type in newChannelsMap)) return false;
147
+ for (let type of Object.keys(oldChannelsMap)) {
148
+ if (!(type in newChannelsMap)) return false;
146
149
 
147
- const oldChannel = oldChannelsMap[type];
148
- const newChannel = newChannelsMap[type];
150
+ const oldChannel = oldChannelsMap[type];
151
+ const newChannel = newChannelsMap[type];
149
152
 
150
- // TODO: Check if language is not there
151
- const equal =
152
- oldChannel.Type == newChannel.Type.toUpperCase() &&
153
- oldChannel.Enabled == newChannel.Enabled &&
154
- oldChannel.DefaultPreference == newChannel.DefaultPreference &&
155
- oldChannel.EditablePreference == newChannel.EditablePreference;
153
+ // TODO: Check if language is not there
154
+ const equal =
155
+ oldChannel.Type == newChannel.Type.toUpperCase() &&
156
+ oldChannel.Enabled == newChannel.Enabled &&
157
+ oldChannel.DefaultPreference == newChannel.DefaultPreference &&
158
+ oldChannel.EditablePreference == newChannel.EditablePreference;
156
159
 
157
- if (!equal) return false;
158
- delete newChannelsMap[type];
159
- }
160
+ if (!equal) return false;
161
+ delete newChannelsMap[type];
162
+ }
160
163
 
161
- return Object.keys(newChannelsMap).length == 0;
164
+ return Object.keys(newChannelsMap).length == 0;
162
165
  }
163
166
 
164
167
  function isActionEqual(oldAction, newAction) {
165
- return (
166
- oldAction.Language == newAction.Language.toUpperCase() &&
167
- oldAction.ActionId == newAction.ActionId &&
168
- oldAction.ActionText == newAction.ActionText &&
169
- oldAction.GroupActionText == newAction.GroupActionText &&
170
- oldAction.Nature == newAction.Nature
171
- );
168
+ return (
169
+ oldAction.Language == newAction.Language.toUpperCase() &&
170
+ oldAction.ActionId == newAction.ActionId &&
171
+ oldAction.ActionText == newAction.ActionText &&
172
+ oldAction.GroupActionText == newAction.GroupActionText &&
173
+ oldAction.Nature == newAction.Nature
174
+ );
172
175
  }
173
176
 
174
177
  function areActionsEqual(oldActions, newActions) {
175
- if (oldActions.length !== newActions.length) {
176
- return false;
177
- }
178
-
179
- let matchFound = false;
180
- for (const oldAction of oldActions) {
181
- for (const newAction of newActions) {
182
- if (isActionEqual(oldAction, newAction)) {
183
- matchFound = true;
184
- break;
185
- }
178
+ if (oldActions.length !== newActions.length) {
179
+ return false;
186
180
  }
187
- if (!matchFound) {
188
- return false;
181
+
182
+ let matchFound = false;
183
+ for (const oldAction of oldActions) {
184
+ for (const newAction of newActions) {
185
+ if (isActionEqual(oldAction, newAction)) {
186
+ matchFound = true;
187
+ break;
188
+ }
189
+ }
190
+ if (!matchFound) {
191
+ return false;
192
+ }
189
193
  }
190
- }
191
194
 
192
- return true;
195
+ return true;
193
196
  }
194
197
 
195
198
  function isTemplateEqual(oldTemplate, newTemplate) {
196
- return (
197
- oldTemplate.Language == newTemplate.Language.toUpperCase() &&
198
- oldTemplate.TemplatePublic == newTemplate.TemplatePublic &&
199
- oldTemplate.TemplateSensitive == newTemplate.TemplateSensitive &&
200
- oldTemplate.TemplateGrouped == newTemplate.TemplateGrouped &&
201
- oldTemplate.Description == newTemplate.Description &&
202
- oldTemplate.TemplateLanguage == newTemplate.TemplateLanguage.toUpperCase() &&
203
- oldTemplate.Subtitle == newTemplate.Subtitle &&
204
- oldTemplate.EmailSubject == newTemplate.EmailSubject &&
205
- oldTemplate.EmailText == newTemplate.EmailText &&
206
- oldTemplate.EmailHtml == newTemplate.EmailHtml
207
- );
199
+ return (
200
+ oldTemplate.Language == newTemplate.Language.toUpperCase() &&
201
+ oldTemplate.TemplatePublic == newTemplate.TemplatePublic &&
202
+ oldTemplate.TemplateSensitive == newTemplate.TemplateSensitive &&
203
+ oldTemplate.TemplateGrouped == newTemplate.TemplateGrouped &&
204
+ oldTemplate.Description == newTemplate.Description &&
205
+ oldTemplate.TemplateLanguage == newTemplate.TemplateLanguage.toUpperCase() &&
206
+ oldTemplate.Subtitle == newTemplate.Subtitle &&
207
+ oldTemplate.EmailSubject == newTemplate.EmailSubject &&
208
+ oldTemplate.EmailText == newTemplate.EmailText &&
209
+ oldTemplate.EmailHtml == newTemplate.EmailHtml
210
+ );
208
211
  }
209
212
 
210
213
  function areTemplatesEqual(oldTemplates, newTemplates) {
211
- if (oldTemplates.length !== newTemplates.length) {
212
- return false;
213
- }
214
-
215
- let matchFound = false;
216
- for (const oldTemplate of oldTemplates) {
217
- for (const newTemplate of newTemplates) {
218
- if (isTemplateEqual(oldTemplate, newTemplate)) {
219
- matchFound = true;
220
- break;
221
- }
214
+ if (oldTemplates.length !== newTemplates.length) {
215
+ return false;
222
216
  }
223
- if (!matchFound) {
224
- return false;
217
+
218
+ let matchFound = false;
219
+ for (const oldTemplate of oldTemplates) {
220
+ for (const newTemplate of newTemplates) {
221
+ if (isTemplateEqual(oldTemplate, newTemplate)) {
222
+ matchFound = true;
223
+ break;
224
+ }
225
+ }
226
+ if (!matchFound) {
227
+ return false;
228
+ }
225
229
  }
226
- }
227
230
 
228
- return true;
231
+ return true;
229
232
  }
230
233
 
231
234
  function isNotificationTypeEqual(oldNotificationType, newNotificationType) {
232
- if (newNotificationType.IsGroupable === undefined) {
233
- newNotificationType.IsGroupable = true;
234
- }
235
-
236
- return (
237
- oldNotificationType.IsGroupable == newNotificationType.IsGroupable &&
238
- areTemplatesEqual(fromOdataArrayFormat(oldNotificationType.Templates), fromOdataArrayFormat(newNotificationType.Templates)) &&
239
- areActionsEqual(fromOdataArrayFormat(oldNotificationType.Actions), fromOdataArrayFormat(newNotificationType.Actions)) &&
240
- areDeliveryChannelsEqual(fromOdataArrayFormat(oldNotificationType.DeliveryChannels), fromOdataArrayFormat(newNotificationType.DeliveryChannels))
241
- );
242
- }
243
-
244
- async function processNotificationTypes(notificationTypesJSON) {
245
- const notificationTypes = createNotificationTypesMap(notificationTypesJSON);
246
- const prefix = getPrefix();
247
- let defaultTemplateExists = false;
248
-
249
- // get notficationTypes
250
- const existingTypes = await getNotificationTypes();
251
-
252
- // iterate through notification types
253
- for (const existingType of existingTypes) {
254
- if (existingType.NotificationTypeKey == "Default") {
255
- defaultTemplateExists = true;
256
- continue;
257
- }
258
-
259
- if (!existingType.NotificationTypeKey.startsWith(`${prefix}/`)) {
260
- LOG._info && LOG.info(`Skipping Notification Type of other application: ${existingType.NotificationTypeKey}.`);
261
- continue;
235
+ if (newNotificationType.IsGroupable === undefined) {
236
+ newNotificationType.IsGroupable = true;
262
237
  }
263
238
 
264
- // if the type isn't present in the JSON file, delete it
265
- if (
266
- notificationTypes[existingType.NotificationTypeKey] === undefined ||
267
- notificationTypes[existingType.NotificationTypeKey][existingType.NotificationTypeVersion] === undefined
268
- ) {
269
- await deleteNotificationType(existingType);
270
- continue;
271
- }
272
-
273
- const newType = JSON.parse(JSON.stringify(notificationTypes[existingType.NotificationTypeKey][existingType.NotificationTypeVersion]));
239
+ return (
240
+ oldNotificationType.IsGroupable == newNotificationType.IsGroupable &&
241
+ areTemplatesEqual(
242
+ fromOdataArrayFormat(oldNotificationType.Templates),
243
+ fromOdataArrayFormat(newNotificationType.Templates)
244
+ ) &&
245
+ areActionsEqual(
246
+ fromOdataArrayFormat(oldNotificationType.Actions),
247
+ fromOdataArrayFormat(newNotificationType.Actions)
248
+ ) &&
249
+ areDeliveryChannelsEqual(
250
+ fromOdataArrayFormat(oldNotificationType.DeliveryChannels),
251
+ fromOdataArrayFormat(newNotificationType.DeliveryChannels)
252
+ )
253
+ );
254
+ }
274
255
 
275
- // if the type is there then verify if everything is same or not
276
- if (!isNotificationTypeEqual(existingType, newType)) {
277
- await updateNotificationType(existingType.NotificationTypeId, notificationTypes[existingType.NotificationTypeKey][existingType.NotificationTypeVersion]);
278
- } else {
279
- LOG._info && LOG.info(
280
- `Notification Type of key ${existingType.NotificationTypeKey} and version ${existingType.NotificationTypeVersion} unchanged.`
281
- );
256
+ async function processNotificationTypes(notificationTypesJSON) {
257
+ const notificationTypes = createNotificationTypesMap(notificationTypesJSON);
258
+ const prefix = getPrefix();
259
+ let defaultTemplateExists = false;
260
+
261
+ // get notficationTypes
262
+ const existingTypes = await getNotificationTypes();
263
+
264
+ // iterate through notification types
265
+ for (const existingType of existingTypes) {
266
+ if (existingType.NotificationTypeKey == "Default") {
267
+ defaultTemplateExists = true;
268
+ continue;
269
+ }
270
+
271
+ if (!existingType.NotificationTypeKey.startsWith(`${prefix}/`)) {
272
+ LOG._info &&
273
+ LOG.info(`Skipping Notification Type of other application: ${existingType.NotificationTypeKey}.`);
274
+ continue;
275
+ }
276
+
277
+ // if the type isn't present in the JSON file, delete it
278
+ if (
279
+ notificationTypes[existingType.NotificationTypeKey] === undefined ||
280
+ notificationTypes[existingType.NotificationTypeKey][existingType.NotificationTypeVersion] === undefined
281
+ ) {
282
+ await deleteNotificationType(existingType);
283
+ continue;
284
+ }
285
+
286
+ const newType = JSON.parse(
287
+ JSON.stringify(notificationTypes[existingType.NotificationTypeKey][existingType.NotificationTypeVersion])
288
+ );
289
+
290
+ // if the type is there then verify if everything is same or not
291
+ if (!isNotificationTypeEqual(existingType, newType)) {
292
+ await updateNotificationType(
293
+ existingType.NotificationTypeId,
294
+ notificationTypes[existingType.NotificationTypeKey][existingType.NotificationTypeVersion]
295
+ );
296
+ } else {
297
+ LOG._info &&
298
+ LOG.info(
299
+ `Notification Type of key ${existingType.NotificationTypeKey} and version ${existingType.NotificationTypeVersion} unchanged.`
300
+ );
301
+ }
302
+
303
+ delete notificationTypes[existingType.NotificationTypeKey][existingType.NotificationTypeVersion];
304
+
305
+ if (Object.keys(notificationTypes[existingType.NotificationTypeKey]).length == 0) {
306
+ delete notificationTypes[existingType.NotificationTypeKey];
307
+ }
282
308
  }
283
309
 
284
- delete notificationTypes[existingType.NotificationTypeKey][existingType.NotificationTypeVersion];
285
-
286
- if (Object.keys(notificationTypes[existingType.NotificationTypeKey]).length == 0) {
287
- delete notificationTypes[existingType.NotificationTypeKey];
310
+ // create default template if required
311
+ if (!defaultTemplateExists) {
312
+ await createNotificationType(defaultTemplate);
288
313
  }
289
- }
290
314
 
291
- // create default template if required
292
- if (!defaultTemplateExists) {
293
- await createNotificationType(defaultTemplate);
294
- }
295
-
296
- // create notification types that aren't there
297
- for (const notificationTypeKey in notificationTypes) {
298
- for (const notificationTypeVersion in notificationTypes[notificationTypeKey]) {
299
- await createNotificationType(notificationTypes[notificationTypeKey][notificationTypeVersion]);
315
+ // create notification types that aren't there
316
+ for (const notificationTypeKey in notificationTypes) {
317
+ for (const notificationTypeVersion in notificationTypes[notificationTypeKey]) {
318
+ await createNotificationType(notificationTypes[notificationTypeKey][notificationTypeVersion]);
319
+ }
300
320
  }
301
- }
302
321
  }
303
322
 
304
323
  module.exports = {
305
- createNotificationTypesMap,
306
- processNotificationTypes
307
- }
324
+ createNotificationTypesMap,
325
+ processNotificationTypes
326
+ };