@aws-amplify/notifications 1.0.25 → 1.0.26-unstable.1116fef.4

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 (208) hide show
  1. package/lib/InAppMessaging/InAppMessaging.d.ts +10 -8
  2. package/lib/InAppMessaging/InAppMessaging.js +9 -11
  3. package/lib/InAppMessaging/InAppMessaging.js.map +1 -1
  4. package/lib/InAppMessaging/Providers/AWSPinpointProvider/index.d.ts +5 -25
  5. package/lib/InAppMessaging/Providers/AWSPinpointProvider/index.js +37 -252
  6. package/lib/InAppMessaging/Providers/AWSPinpointProvider/index.js.map +1 -1
  7. package/lib/InAppMessaging/Providers/AWSPinpointProvider/types.d.ts +0 -9
  8. package/lib/InAppMessaging/Providers/AWSPinpointProvider/types.js.map +1 -1
  9. package/lib/InAppMessaging/Providers/AWSPinpointProvider/utils.js +3 -9
  10. package/lib/InAppMessaging/Providers/AWSPinpointProvider/utils.js.map +1 -1
  11. package/lib/InAppMessaging/index.d.ts +1 -3
  12. package/lib/InAppMessaging/index.js +0 -2
  13. package/lib/InAppMessaging/index.js.map +1 -1
  14. package/lib/InAppMessaging/types.d.ts +30 -42
  15. package/lib/InAppMessaging/types.js +2 -0
  16. package/lib/InAppMessaging/types.js.map +1 -1
  17. package/lib/Notifications.d.ts +6 -2
  18. package/lib/Notifications.js +45 -0
  19. package/lib/Notifications.js.map +1 -1
  20. package/lib/PushNotification/NotEnabledError.d.ts +3 -0
  21. package/lib/PushNotification/NotEnabledError.js +16 -0
  22. package/lib/PushNotification/NotEnabledError.js.map +1 -0
  23. package/lib/PushNotification/Platform/index.d.ts +2 -0
  24. package/lib/PushNotification/Platform/index.js +26 -0
  25. package/lib/PushNotification/Platform/index.js.map +1 -0
  26. package/lib/PushNotification/Platform/index.native.d.ts +2 -0
  27. package/lib/PushNotification/Platform/index.native.js +8 -0
  28. package/lib/PushNotification/Platform/index.native.js.map +1 -0
  29. package/lib/PushNotification/Platform/types.d.ts +5 -0
  30. package/lib/PushNotification/Platform/types.js +5 -0
  31. package/lib/PushNotification/Platform/types.js.map +1 -0
  32. package/lib/PushNotification/PlatformNotSupportedError.d.ts +3 -0
  33. package/lib/PushNotification/PlatformNotSupportedError.js +16 -0
  34. package/lib/PushNotification/PlatformNotSupportedError.js.map +1 -0
  35. package/lib/PushNotification/Providers/AWSPinpointProvider/index.d.ts +15 -0
  36. package/lib/PushNotification/Providers/AWSPinpointProvider/index.js +115 -0
  37. package/lib/PushNotification/Providers/AWSPinpointProvider/index.js.map +1 -0
  38. package/lib/PushNotification/Providers/AWSPinpointProvider/types.d.ts +9 -0
  39. package/lib/PushNotification/Providers/AWSPinpointProvider/types.js +16 -0
  40. package/lib/PushNotification/Providers/AWSPinpointProvider/types.js.map +1 -0
  41. package/lib/PushNotification/Providers/AWSPinpointProvider/utils.d.ts +7 -0
  42. package/lib/PushNotification/Providers/AWSPinpointProvider/utils.js +58 -0
  43. package/lib/PushNotification/Providers/AWSPinpointProvider/utils.js.map +1 -0
  44. package/lib/PushNotification/Providers/index.d.ts +1 -0
  45. package/lib/PushNotification/Providers/index.js +7 -0
  46. package/lib/PushNotification/Providers/index.js.map +1 -0
  47. package/lib/PushNotification/PushNotification.d.ts +39 -0
  48. package/lib/PushNotification/PushNotification.js +91 -0
  49. package/lib/PushNotification/PushNotification.js.map +1 -0
  50. package/lib/PushNotification/PushNotification.native.d.ts +63 -0
  51. package/lib/PushNotification/PushNotification.native.js +327 -0
  52. package/lib/PushNotification/PushNotification.native.js.map +1 -0
  53. package/lib/PushNotification/index.d.ts +2 -0
  54. package/lib/PushNotification/index.js +9 -0
  55. package/lib/PushNotification/index.js.map +1 -0
  56. package/lib/PushNotification/types.d.ts +77 -0
  57. package/lib/PushNotification/types.js +12 -0
  58. package/lib/PushNotification/types.js.map +1 -0
  59. package/lib/PushNotification/utils.d.ts +3 -0
  60. package/lib/PushNotification/utils.js +81 -0
  61. package/lib/PushNotification/utils.js.map +1 -0
  62. package/lib/common/AWSPinpointProviderCommon/index.d.ts +34 -0
  63. package/lib/common/AWSPinpointProviderCommon/index.js +281 -0
  64. package/lib/common/AWSPinpointProviderCommon/index.js.map +1 -0
  65. package/lib/common/AWSPinpointProviderCommon/types.d.ts +9 -0
  66. package/lib/common/AWSPinpointProviderCommon/types.js +5 -0
  67. package/lib/common/AWSPinpointProviderCommon/types.js.map +1 -0
  68. package/lib/common/constants.d.ts +1 -0
  69. package/lib/common/constants.js +6 -0
  70. package/lib/common/constants.js.map +1 -0
  71. package/lib/common/eventListeners/index.d.ts +4 -0
  72. package/lib/common/eventListeners/index.js +55 -0
  73. package/lib/common/eventListeners/index.js.map +1 -0
  74. package/lib/common/eventListeners/types.d.ts +7 -0
  75. package/lib/common/eventListeners/types.js +5 -0
  76. package/lib/common/eventListeners/types.js.map +1 -0
  77. package/lib/common/index.d.ts +4 -0
  78. package/lib/common/index.js +13 -0
  79. package/lib/common/index.js.map +1 -0
  80. package/lib/index.d.ts +5 -2
  81. package/lib/index.js +4 -0
  82. package/lib/index.js.map +1 -1
  83. package/lib/types.d.ts +34 -2
  84. package/lib/types.js +2 -0
  85. package/lib/types.js.map +1 -1
  86. package/lib-esm/InAppMessaging/InAppMessaging.d.ts +10 -8
  87. package/lib-esm/InAppMessaging/InAppMessaging.js +9 -11
  88. package/lib-esm/InAppMessaging/InAppMessaging.js.map +1 -1
  89. package/lib-esm/InAppMessaging/Providers/AWSPinpointProvider/index.d.ts +5 -25
  90. package/lib-esm/InAppMessaging/Providers/AWSPinpointProvider/index.js +39 -254
  91. package/lib-esm/InAppMessaging/Providers/AWSPinpointProvider/index.js.map +1 -1
  92. package/lib-esm/InAppMessaging/Providers/AWSPinpointProvider/types.d.ts +0 -9
  93. package/lib-esm/InAppMessaging/Providers/AWSPinpointProvider/types.js.map +1 -1
  94. package/lib-esm/InAppMessaging/Providers/AWSPinpointProvider/utils.js +2 -8
  95. package/lib-esm/InAppMessaging/Providers/AWSPinpointProvider/utils.js.map +1 -1
  96. package/lib-esm/InAppMessaging/index.d.ts +1 -3
  97. package/lib-esm/InAppMessaging/index.js +0 -1
  98. package/lib-esm/InAppMessaging/index.js.map +1 -1
  99. package/lib-esm/InAppMessaging/types.d.ts +30 -42
  100. package/lib-esm/InAppMessaging/types.js +2 -0
  101. package/lib-esm/InAppMessaging/types.js.map +1 -1
  102. package/lib-esm/Notifications.d.ts +6 -2
  103. package/lib-esm/Notifications.js +48 -3
  104. package/lib-esm/Notifications.js.map +1 -1
  105. package/lib-esm/PushNotification/NotEnabledError.d.ts +3 -0
  106. package/lib-esm/PushNotification/NotEnabledError.js +14 -0
  107. package/lib-esm/PushNotification/NotEnabledError.js.map +1 -0
  108. package/lib-esm/PushNotification/Platform/index.d.ts +2 -0
  109. package/lib-esm/PushNotification/Platform/index.js +24 -0
  110. package/lib-esm/PushNotification/Platform/index.js.map +1 -0
  111. package/lib-esm/PushNotification/Platform/index.native.d.ts +2 -0
  112. package/lib-esm/PushNotification/Platform/index.native.js +6 -0
  113. package/lib-esm/PushNotification/Platform/index.native.js.map +1 -0
  114. package/lib-esm/PushNotification/Platform/types.d.ts +5 -0
  115. package/lib-esm/PushNotification/Platform/types.js +3 -0
  116. package/lib-esm/PushNotification/Platform/types.js.map +1 -0
  117. package/lib-esm/PushNotification/PlatformNotSupportedError.d.ts +3 -0
  118. package/lib-esm/PushNotification/PlatformNotSupportedError.js +14 -0
  119. package/lib-esm/PushNotification/PlatformNotSupportedError.js.map +1 -0
  120. package/lib-esm/PushNotification/Providers/AWSPinpointProvider/index.d.ts +15 -0
  121. package/lib-esm/PushNotification/Providers/AWSPinpointProvider/index.js +113 -0
  122. package/lib-esm/PushNotification/Providers/AWSPinpointProvider/index.js.map +1 -0
  123. package/lib-esm/PushNotification/Providers/AWSPinpointProvider/types.d.ts +9 -0
  124. package/lib-esm/PushNotification/Providers/AWSPinpointProvider/types.js +14 -0
  125. package/lib-esm/PushNotification/Providers/AWSPinpointProvider/types.js.map +1 -0
  126. package/lib-esm/PushNotification/Providers/AWSPinpointProvider/utils.d.ts +7 -0
  127. package/lib-esm/PushNotification/Providers/AWSPinpointProvider/utils.js +56 -0
  128. package/lib-esm/PushNotification/Providers/AWSPinpointProvider/utils.js.map +1 -0
  129. package/lib-esm/PushNotification/Providers/index.d.ts +1 -0
  130. package/lib-esm/PushNotification/Providers/index.js +4 -0
  131. package/lib-esm/PushNotification/Providers/index.js.map +1 -0
  132. package/lib-esm/PushNotification/PushNotification.d.ts +39 -0
  133. package/lib-esm/PushNotification/PushNotification.js +89 -0
  134. package/lib-esm/PushNotification/PushNotification.js.map +1 -0
  135. package/lib-esm/PushNotification/PushNotification.native.d.ts +63 -0
  136. package/lib-esm/PushNotification/PushNotification.native.js +325 -0
  137. package/lib-esm/PushNotification/PushNotification.native.js.map +1 -0
  138. package/lib-esm/PushNotification/index.d.ts +2 -0
  139. package/lib-esm/PushNotification/index.js +5 -0
  140. package/lib-esm/PushNotification/index.js.map +1 -0
  141. package/lib-esm/PushNotification/types.d.ts +77 -0
  142. package/lib-esm/PushNotification/types.js +10 -0
  143. package/lib-esm/PushNotification/types.js.map +1 -0
  144. package/lib-esm/PushNotification/utils.d.ts +3 -0
  145. package/lib-esm/PushNotification/utils.js +79 -0
  146. package/lib-esm/PushNotification/utils.js.map +1 -0
  147. package/lib-esm/common/AWSPinpointProviderCommon/index.d.ts +34 -0
  148. package/lib-esm/common/AWSPinpointProviderCommon/index.js +279 -0
  149. package/lib-esm/common/AWSPinpointProviderCommon/index.js.map +1 -0
  150. package/lib-esm/common/AWSPinpointProviderCommon/types.d.ts +9 -0
  151. package/lib-esm/common/AWSPinpointProviderCommon/types.js +3 -0
  152. package/lib-esm/common/AWSPinpointProviderCommon/types.js.map +1 -0
  153. package/lib-esm/common/constants.d.ts +1 -0
  154. package/lib-esm/common/constants.js +4 -0
  155. package/lib-esm/common/constants.js.map +1 -0
  156. package/lib-esm/common/eventListeners/index.d.ts +4 -0
  157. package/lib-esm/common/eventListeners/index.js +53 -0
  158. package/lib-esm/common/eventListeners/index.js.map +1 -0
  159. package/lib-esm/common/eventListeners/types.d.ts +7 -0
  160. package/lib-esm/common/eventListeners/types.js +3 -0
  161. package/lib-esm/common/eventListeners/types.js.map +1 -0
  162. package/lib-esm/common/index.d.ts +4 -0
  163. package/lib-esm/common/index.js +6 -0
  164. package/lib-esm/common/index.js.map +1 -0
  165. package/lib-esm/index.d.ts +5 -2
  166. package/lib-esm/index.js +2 -0
  167. package/lib-esm/index.js.map +1 -1
  168. package/lib-esm/types.d.ts +34 -2
  169. package/lib-esm/types.js +2 -0
  170. package/lib-esm/types.js.map +1 -1
  171. package/package.json +11 -50
  172. package/src/InAppMessaging/InAppMessaging.ts +27 -36
  173. package/src/InAppMessaging/Providers/AWSPinpointProvider/index.ts +45 -245
  174. package/src/InAppMessaging/Providers/AWSPinpointProvider/types.ts +0 -12
  175. package/src/InAppMessaging/Providers/AWSPinpointProvider/utils.ts +3 -12
  176. package/src/InAppMessaging/index.ts +0 -3
  177. package/src/InAppMessaging/types.ts +52 -56
  178. package/src/Notifications.ts +42 -4
  179. package/src/PushNotification/NotEnabledError.ts +11 -0
  180. package/src/PushNotification/Platform/index.native.ts +9 -0
  181. package/src/PushNotification/Platform/index.ts +22 -0
  182. package/src/PushNotification/Platform/types.ts +15 -0
  183. package/src/PushNotification/PlatformNotSupportedError.ts +9 -0
  184. package/src/PushNotification/Providers/AWSPinpointProvider/index.ts +137 -0
  185. package/src/PushNotification/Providers/AWSPinpointProvider/types.ts +13 -0
  186. package/src/PushNotification/Providers/AWSPinpointProvider/utils.ts +79 -0
  187. package/src/PushNotification/Providers/index.ts +4 -0
  188. package/src/PushNotification/PushNotification.native.ts +381 -0
  189. package/src/PushNotification/PushNotification.ts +107 -0
  190. package/src/PushNotification/index.ts +9 -0
  191. package/src/PushNotification/types.ts +114 -0
  192. package/src/PushNotification/utils.ts +112 -0
  193. package/src/common/AWSPinpointProviderCommon/index.ts +295 -0
  194. package/src/common/AWSPinpointProviderCommon/types.ts +14 -0
  195. package/src/common/constants.ts +5 -0
  196. package/src/common/eventListeners/index.ts +44 -0
  197. package/src/common/eventListeners/types.ts +12 -0
  198. package/src/common/index.ts +11 -0
  199. package/src/index.ts +9 -3
  200. package/src/types.ts +47 -2
  201. package/CHANGELOG.md +0 -215
  202. package/lib/InAppMessaging/eventListeners.d.ts +0 -3
  203. package/lib/InAppMessaging/eventListeners.js +0 -28
  204. package/lib/InAppMessaging/eventListeners.js.map +0 -1
  205. package/lib-esm/InAppMessaging/eventListeners.d.ts +0 -3
  206. package/lib-esm/InAppMessaging/eventListeners.js +0 -26
  207. package/lib-esm/InAppMessaging/eventListeners.js.map +0 -1
  208. package/src/InAppMessaging/eventListeners.ts +0 -42
@@ -0,0 +1,112 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { isEmpty } from 'lodash';
5
+
6
+ import {
7
+ NormalizedValues,
8
+ PushNotificationMessage,
9
+ PushNotificationPermissionStatus,
10
+ } from './types';
11
+
12
+ const DEEP_LINK_ACTION = 'deeplink';
13
+ const URL_ACTION = 'url';
14
+
15
+ export const normalizeNativePermissionStatus = (
16
+ nativeStatus?
17
+ ): PushNotificationPermissionStatus => {
18
+ switch (nativeStatus) {
19
+ case 'ShouldRequest':
20
+ return PushNotificationPermissionStatus.SHOULD_REQUEST;
21
+ case 'NotDetermined':
22
+ case 'ShouldExplainThenRequest':
23
+ return PushNotificationPermissionStatus.SHOULD_EXPLAIN_THEN_REQUEST;
24
+ case 'Authorized':
25
+ case 'Granted':
26
+ return PushNotificationPermissionStatus.GRANTED;
27
+ case 'Denied':
28
+ return PushNotificationPermissionStatus.DENIED;
29
+ }
30
+ };
31
+
32
+ export const normalizeNativeMessage = (
33
+ nativeMessage?
34
+ ): PushNotificationMessage | null => {
35
+ let normalized: NormalizedValues;
36
+ if (nativeMessage?.aps) {
37
+ normalized = normalizeApnsMessage(nativeMessage);
38
+ }
39
+ if (nativeMessage?.rawData) {
40
+ normalized = normalizeFcmMessage(nativeMessage);
41
+ }
42
+ if (!normalized) {
43
+ return null;
44
+ }
45
+ const { body, imageUrl, title, action, options, data } = normalized;
46
+ return {
47
+ ...(body && { body }),
48
+ ...(imageUrl && { imageUrl }),
49
+ ...(title && { title }),
50
+ ...action,
51
+ ...options,
52
+ ...(!isEmpty(data) && { data }),
53
+ };
54
+ };
55
+
56
+ const normalizeApnsMessage = (apnsMessage): NormalizedValues => {
57
+ const { aps, data = {} } = apnsMessage;
58
+ const { body, title } = aps.alert ?? {};
59
+ const action = getApnsAction(data.pinpoint) ?? {};
60
+ const imageUrl = data['media-url'];
61
+ const options = getApnsOptions(apnsMessage);
62
+ return { body, imageUrl, title, action, options, data };
63
+ };
64
+
65
+ const normalizeFcmMessage = (fcmMessage): NormalizedValues => {
66
+ const { body, imageUrl, rawData: data, title } = fcmMessage;
67
+ const action = getFcmAction(fcmMessage.action) ?? {};
68
+ const options = getFcmOptions(fcmMessage);
69
+ return { body, imageUrl, title, action, options, data };
70
+ };
71
+
72
+ const getApnsAction = (
73
+ action = {}
74
+ ): Pick<PushNotificationMessage, 'deeplinkUrl'> => {
75
+ if (action[DEEP_LINK_ACTION]) {
76
+ return { deeplinkUrl: action[DEEP_LINK_ACTION] };
77
+ }
78
+ };
79
+
80
+ const getFcmAction = (
81
+ action = {}
82
+ ): Pick<PushNotificationMessage, 'goToUrl' | 'deeplinkUrl'> => {
83
+ if (action[URL_ACTION]) {
84
+ return { goToUrl: action[URL_ACTION] };
85
+ }
86
+ if (action[DEEP_LINK_ACTION]) {
87
+ return { deeplinkUrl: action[DEEP_LINK_ACTION] };
88
+ }
89
+ };
90
+
91
+ const getApnsOptions = ({
92
+ aps,
93
+ }): Pick<PushNotificationMessage, 'apnsOptions'> => {
94
+ const { subtitle } = aps.alert ?? {};
95
+ const apnsOptions = { ...(subtitle && { subtitle }) };
96
+ return { ...(!isEmpty(apnsOptions) && { apnsOptions }) };
97
+ };
98
+
99
+ const getFcmOptions = ({
100
+ channelId,
101
+ messageId,
102
+ senderId,
103
+ sendTime,
104
+ }): Pick<PushNotificationMessage, 'fcmOptions'> => {
105
+ const fcmOptions = {
106
+ ...(channelId && { channelId }),
107
+ ...(messageId && { messageId }),
108
+ ...(senderId && { senderId }),
109
+ ...(sendTime && { sendTime: new Date(sendTime) }),
110
+ };
111
+ return { ...(!isEmpty(fcmOptions) && { fcmOptions }) };
112
+ };
@@ -0,0 +1,295 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import {
5
+ ClientDevice,
6
+ ConsoleLogger,
7
+ Credentials,
8
+ getAmplifyUserAgent,
9
+ StorageHelper,
10
+ transferKeyToUpperCase,
11
+ } from '@aws-amplify/core';
12
+ import { Cache } from '@aws-amplify/cache';
13
+ import {
14
+ Event as AWSPinpointAnalyticsEvent,
15
+ UpdateEndpointCommand,
16
+ UpdateEndpointCommandInput,
17
+ PinpointClient,
18
+ PutEventsCommand,
19
+ PutEventsCommandInput,
20
+ } from '@aws-sdk/client-pinpoint';
21
+ import { v4 as uuid } from 'uuid';
22
+
23
+ import {
24
+ NotificationsCategory,
25
+ NotificationsSubCategory,
26
+ NotificationsProvider,
27
+ UserInfo,
28
+ } from '../../types';
29
+ import { AWSPinpointUserInfo } from './types';
30
+
31
+ export default abstract class AWSPinpointProviderCommon
32
+ implements NotificationsProvider
33
+ {
34
+ static category: NotificationsCategory = 'Notifications';
35
+ static providerName = 'AWSPinpoint';
36
+
37
+ protected clientInfo;
38
+ protected config: Record<string, any> = {};
39
+ protected endpointInitialized = false;
40
+ protected initialized = false;
41
+ protected logger: ConsoleLogger;
42
+
43
+ constructor(logger) {
44
+ this.config = { storage: new StorageHelper().getStorage() };
45
+ this.clientInfo = ClientDevice.clientInfo() ?? {};
46
+ this.logger = logger;
47
+ }
48
+
49
+ /**
50
+ * get the category of the plugin
51
+ */
52
+ getCategory() {
53
+ return AWSPinpointProviderCommon.category;
54
+ }
55
+
56
+ /**
57
+ * get the sub-category of the plugin
58
+ */
59
+ abstract getSubCategory(): NotificationsSubCategory;
60
+
61
+ /**
62
+ * get provider name of the plugin
63
+ */
64
+ getProviderName(): string {
65
+ return AWSPinpointProviderCommon.providerName;
66
+ }
67
+
68
+ configure(config = {}): Record<string, any> {
69
+ this.config = { ...this.config, ...config };
70
+ this.logger.debug(
71
+ `configure ${this.getProviderName()}${this.getSubCategory()}Provider`,
72
+ this.config
73
+ );
74
+ return this.config;
75
+ }
76
+
77
+ identifyUser = async (userId: string, userInfo: UserInfo): Promise<void> => {
78
+ if (!this.initialized) {
79
+ await this.init();
80
+ }
81
+ try {
82
+ await this.updateEndpoint(userId, userInfo);
83
+ } catch (err) {
84
+ this.logger.error('Error identifying user', err);
85
+ throw err;
86
+ }
87
+ };
88
+
89
+ protected init = async (): Promise<void> => {
90
+ const { endpointId, storage } = this.config;
91
+ const providerName = this.getProviderName();
92
+ try {
93
+ // Only run sync() if it's available (i.e. React Native)
94
+ if (typeof storage.sync === 'function') {
95
+ await storage.sync();
96
+ }
97
+ // If an endpoint was not provided via configuration, try to get it from cache
98
+ if (!endpointId) {
99
+ this.config.endpointId = await this.getEndpointId();
100
+ }
101
+ this.initialized = true;
102
+ } catch (err) {
103
+ this.logger.error(`Failed to initialize ${providerName}`, err);
104
+ }
105
+ };
106
+
107
+ protected recordAnalyticsEvent = async (
108
+ event: AWSPinpointAnalyticsEvent
109
+ ): Promise<void> => {
110
+ const { appId, credentials, endpointId, pinpointClient } = this.config;
111
+ const currentCredentials = await this.getCredentials();
112
+ // Shallow compare to determine if credentials stored here are outdated
113
+ const credentialsUpdated =
114
+ !credentials ||
115
+ Object.keys(currentCredentials).some(
116
+ key => currentCredentials[key] !== credentials[key]
117
+ );
118
+ // Update credentials
119
+ this.config.credentials = currentCredentials;
120
+ try {
121
+ // Initialize a new pinpoint client if one isn't already configured or if credentials changed
122
+ if (!pinpointClient || credentialsUpdated) {
123
+ await this.initPinpointClient();
124
+ }
125
+ // Create the PutEvents input
126
+ const input: PutEventsCommandInput = {
127
+ ApplicationId: appId,
128
+ EventsRequest: {
129
+ BatchItem: {
130
+ [endpointId]: {
131
+ Endpoint: {},
132
+ Events: {
133
+ [uuid()]: event,
134
+ },
135
+ },
136
+ },
137
+ },
138
+ };
139
+ const command: PutEventsCommand = new PutEventsCommand(input);
140
+ this.logger.debug('recording analytics event');
141
+ await this.config.pinpointClient.send(command);
142
+ } catch (err) {
143
+ this.logger.error('Error recording analytics event', err);
144
+ throw err;
145
+ }
146
+ };
147
+
148
+ protected updateEndpoint = async (
149
+ userId: string = null,
150
+ userInfo: AWSPinpointUserInfo = null
151
+ ): Promise<void> => {
152
+ const {
153
+ appId,
154
+ credentials,
155
+ endpointId,
156
+ endpointInfo = {},
157
+ pinpointClient,
158
+ } = this.config;
159
+ const currentCredentials = await this.getCredentials();
160
+ // Shallow compare to determine if credentials stored here are outdated
161
+ const credentialsUpdated =
162
+ !credentials ||
163
+ Object.keys(currentCredentials).some(
164
+ key => currentCredentials[key] !== credentials[key]
165
+ );
166
+ // If endpoint is already initialized, and nothing else is changing, just early return
167
+ if (
168
+ this.endpointInitialized &&
169
+ !credentialsUpdated &&
170
+ !userId &&
171
+ !userInfo
172
+ ) {
173
+ return;
174
+ }
175
+ // Update credentials
176
+ this.config.credentials = currentCredentials;
177
+ try {
178
+ // Initialize a new pinpoint client if one isn't already configured or if credentials changed
179
+ if (!pinpointClient || credentialsUpdated) {
180
+ this.initPinpointClient();
181
+ }
182
+ const { address, attributes, demographic, location, metrics, optOut } =
183
+ userInfo ?? {};
184
+ const { appVersion, make, model, platform, version } = this.clientInfo;
185
+ // Create the UpdateEndpoint input, prioritizing passed in user info and falling back to
186
+ // defaults (if any) obtained from the config
187
+ const input: UpdateEndpointCommandInput = {
188
+ ApplicationId: appId,
189
+ EndpointId: endpointId,
190
+ EndpointRequest: {
191
+ RequestId: uuid(),
192
+ EffectiveDate: new Date().toISOString(),
193
+ ChannelType: endpointInfo.channelType,
194
+ Address: address ?? endpointInfo.address,
195
+ Attributes: {
196
+ ...endpointInfo.attributes,
197
+ ...attributes,
198
+ },
199
+ Demographic: {
200
+ AppVersion: appVersion,
201
+ Make: make,
202
+ Model: model,
203
+ ModelVersion: version,
204
+ Platform: platform,
205
+ ...transferKeyToUpperCase({
206
+ ...endpointInfo.demographic,
207
+ ...demographic,
208
+ }),
209
+ },
210
+ Location: transferKeyToUpperCase({
211
+ ...endpointInfo.location,
212
+ ...location,
213
+ }),
214
+ Metrics: {
215
+ ...endpointInfo.metrics,
216
+ ...metrics,
217
+ },
218
+ OptOut: optOut ?? endpointInfo.optOut,
219
+ User: {
220
+ UserId:
221
+ userId ?? endpointInfo.userId ?? currentCredentials.identityId,
222
+ UserAttributes: attributes ?? endpointInfo.userAttributes,
223
+ },
224
+ },
225
+ };
226
+ const command: UpdateEndpointCommand = new UpdateEndpointCommand(input);
227
+ this.logger.debug('updating endpoint');
228
+ await this.config.pinpointClient.send(command);
229
+ this.endpointInitialized = true;
230
+ } catch (err) {
231
+ throw err;
232
+ }
233
+ };
234
+
235
+ private initPinpointClient = (): void => {
236
+ const { appId, credentials, pinpointClient, region } = this.config;
237
+
238
+ if (!appId || !credentials || !region) {
239
+ throw new Error(
240
+ 'One or more of credentials, appId or region is not configured'
241
+ );
242
+ }
243
+
244
+ if (pinpointClient) {
245
+ pinpointClient.destroy();
246
+ }
247
+
248
+ this.config.pinpointClient = new PinpointClient({
249
+ region,
250
+ credentials,
251
+ customUserAgent: getAmplifyUserAgent(`/${this.getSubCategory()}`),
252
+ });
253
+ };
254
+
255
+ private getEndpointId = async (): Promise<string> => {
256
+ const { appId } = this.config;
257
+ // Each Pinpoint channel requires its own Endpoint ID
258
+ // However, Push will share the Analytics endpoint for now so as to not break existing customers
259
+ const cacheKey =
260
+ this.getSubCategory() === 'PushNotification'
261
+ ? `${this.getProviderName()}_${appId}`
262
+ : `${this.getSubCategory()}:${this.getProviderName()}:${appId}`;
263
+ // First attempt to retrieve the ID from cache
264
+ const cachedEndpointId = await Cache.getItem(cacheKey);
265
+ // Found in cache, just return it
266
+ if (cachedEndpointId) {
267
+ return cachedEndpointId;
268
+ }
269
+ // Otherwise, generate a new ID and store it in long-lived cache before returning it
270
+ const endpointId = uuid();
271
+ // Set a longer TTL to avoid endpoint id being deleted after the default TTL (3 days)
272
+ // Also set its priority to the highest to reduce its chance of being deleted when cache is full
273
+ const ttl = 1000 * 60 * 60 * 24 * 365 * 100; // 100 years
274
+ const expiration = new Date().getTime() + ttl;
275
+ Cache.setItem(cacheKey, endpointId, {
276
+ expires: expiration,
277
+ priority: 1,
278
+ });
279
+ return endpointId;
280
+ };
281
+
282
+ private getCredentials = async () => {
283
+ try {
284
+ const credentials = await Credentials.get();
285
+ if (!credentials) {
286
+ this.logger.debug('no credentials found');
287
+ return null;
288
+ }
289
+ return Credentials.shear(credentials);
290
+ } catch (err) {
291
+ this.logger.error('Error getting credentials:', err);
292
+ return null;
293
+ }
294
+ };
295
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { UserInfo } from '../../types';
5
+
6
+ export interface AWSPinpointProviderConfig {
7
+ appId: string;
8
+ region: string;
9
+ }
10
+
11
+ export interface AWSPinpointUserInfo extends UserInfo {
12
+ address?: string;
13
+ optOut?: 'ALL' | 'NONE';
14
+ }
@@ -0,0 +1,5 @@
1
+ export const AMPLIFY_SYMBOL = (
2
+ typeof Symbol !== 'undefined' && typeof Symbol.for === 'function'
3
+ ? Symbol.for('amplify_default')
4
+ : '@@amplify_default'
5
+ ) as Symbol;
@@ -0,0 +1,44 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { EventListener, EventType } from './types';
5
+
6
+ const eventListeners: Record<string, Set<EventListener<Function>>> = {};
7
+
8
+ export const notifyEventListeners = (type: EventType, ...args: any[]): void => {
9
+ eventListeners[type]?.forEach(listener => {
10
+ listener.handleEvent(...args);
11
+ });
12
+ };
13
+
14
+ export const notifyEventListenersAndAwaitHandlers = (
15
+ type: EventType,
16
+ ...args: any[]
17
+ ): Promise<void[]> =>
18
+ Promise.all<void>(
19
+ Array.from(eventListeners[type] ?? []).map(async listener => {
20
+ try {
21
+ await listener.handleEvent(...args);
22
+ } catch (err) {
23
+ throw err;
24
+ }
25
+ })
26
+ );
27
+
28
+ export const addEventListener = <EventHandler extends Function>(
29
+ type: EventType,
30
+ handler: EventHandler
31
+ ): EventListener<EventHandler> => {
32
+ // If there is no listener set for the event type, just create it
33
+ if (!eventListeners[type]) {
34
+ eventListeners[type] = new Set<EventListener<EventHandler>>();
35
+ }
36
+ const listener = {
37
+ handleEvent: handler,
38
+ remove: () => {
39
+ eventListeners[type].delete(listener);
40
+ },
41
+ };
42
+ eventListeners[type].add(listener);
43
+ return listener;
44
+ };
@@ -0,0 +1,12 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { InAppMessageInteractionEvent } from '../../InAppMessaging/types';
5
+ import { PushNotificationEvent } from '../../PushNotification/types';
6
+
7
+ export interface EventListener<EventHandler extends Function> {
8
+ handleEvent: EventHandler;
9
+ remove: () => void;
10
+ }
11
+
12
+ export type EventType = InAppMessageInteractionEvent | PushNotificationEvent;
@@ -0,0 +1,11 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export { default as AWSPinpointProviderCommon } from './AWSPinpointProviderCommon';
5
+ export { AMPLIFY_SYMBOL } from './constants';
6
+ export {
7
+ addEventListener,
8
+ notifyEventListeners,
9
+ notifyEventListenersAndAwaitHandlers,
10
+ } from './eventListeners';
11
+ export { EventListener, EventType } from './eventListeners/types';
package/src/index.ts CHANGED
@@ -2,8 +2,10 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  export { default as Notifications } from './Notifications';
5
+
6
+ export { AWSPinpointProviderCommon } from './common';
7
+ export { AWSPinpointUserInfo } from './common/AWSPinpointProviderCommon/types';
5
8
  export {
6
- AWSPinpointUserInfo,
7
9
  InAppMessage,
8
10
  InAppMessageAction,
9
11
  InAppMessageButton,
@@ -15,6 +17,10 @@ export {
15
17
  InAppMessageTextAlign,
16
18
  InAppMessagingConfig,
17
19
  InAppMessagingEvent,
18
- UserInfo,
19
20
  } from './InAppMessaging';
20
- export { NotificationsConfig } from './types';
21
+ export {
22
+ PushNotificationMessage,
23
+ PushNotificationPermissions,
24
+ PushNotificationPermissionStatus,
25
+ } from './PushNotification/types';
26
+ export { NotificationsConfig, UserInfo } from './types';
package/src/types.ts CHANGED
@@ -1,11 +1,56 @@
1
1
  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- import { InAppMessagingConfig } from './InAppMessaging';
3
+
4
+ import { InAppMessagingConfig } from './InAppMessaging/types';
5
+ import { PushNotificationConfig } from './PushNotification/types';
4
6
 
5
7
  export type NotificationsCategory = 'Notifications';
6
8
 
7
- export interface NotificationsConfig extends Record<any, any> {
9
+ export type NotificationsSubCategory = 'InAppMessaging' | 'PushNotification';
10
+
11
+ export interface NotificationsProvider {
12
+ // configure provider
13
+ configure(config: object): object;
14
+
15
+ // return category ('Notifications')
16
+ getCategory(): NotificationsCategory;
17
+
18
+ // return sub-category
19
+ getSubCategory(): NotificationsSubCategory;
20
+
21
+ // return the name of you provider
22
+ getProviderName(): string;
23
+
24
+ // identify the current user with the provider
25
+ identifyUser(userId: string, userInfo: UserInfo): Promise<void>;
26
+ }
27
+
28
+ export interface NotificationsConfig {
8
29
  Notifications?: {
9
30
  InAppMessaging?: InAppMessagingConfig;
31
+ PushNotification?: PushNotificationConfig;
10
32
  };
11
33
  }
34
+
35
+ export type UserInfo = {
36
+ attributes?: Record<string, string[]>;
37
+ demographic?: {
38
+ appVersion?: string;
39
+ locale?: string;
40
+ make?: string;
41
+ model?: string;
42
+ modelVersion?: string;
43
+ platform?: string;
44
+ platformVersion?: string;
45
+ timezone?: string;
46
+ };
47
+ location?: {
48
+ city?: string;
49
+ country?: string;
50
+ latitude?: number;
51
+ longitude?: number;
52
+ postalCode?: string;
53
+ region?: string;
54
+ };
55
+ metrics?: Record<string, number>;
56
+ };