@aws-amplify/analytics 5.1.7-unstable.3 → 5.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Analytics.ts CHANGED
@@ -1,405 +1,401 @@
1
- /*
2
- * Copyright 2017-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
5
- * the License. A copy of the License is located at
6
- *
7
- * http://aws.amazon.com/apache2.0/
8
- *
9
- * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
- * and limitations under the License.
12
- */
13
-
14
- import {
15
- Amplify,
16
- ConsoleLogger as Logger,
17
- Hub,
18
- Parser,
19
- } from '@aws-amplify/core';
20
- import { AWSPinpointProvider } from './Providers/AWSPinpointProvider';
21
-
22
- import {
23
- AnalyticsProvider,
24
- EventAttributes,
25
- EventMetrics,
26
- pageViewTrackOpts,
27
- } from './types';
28
- import { PageViewTracker, EventTracker, SessionTracker } from './trackers';
29
-
30
- const logger = new Logger('AnalyticsClass');
31
-
32
- const AMPLIFY_SYMBOL = (typeof Symbol !== 'undefined' &&
33
- typeof Symbol.for === 'function'
34
- ? Symbol.for('amplify_default')
35
- : '@@amplify_default') as Symbol;
36
-
37
- const dispatchAnalyticsEvent = (event: string, data: any, message: string) => {
38
- Hub.dispatch(
39
- 'analytics',
40
- { event, data, message },
41
- 'Analytics',
42
- AMPLIFY_SYMBOL
43
- );
44
- };
45
-
46
- const trackers = {
47
- pageView: PageViewTracker,
48
- event: EventTracker,
49
- session: SessionTracker,
50
- };
51
-
52
- let _instance = null;
53
-
54
- /**
55
- * Provide mobile analytics client functions
56
- */
57
- export class AnalyticsClass {
58
- private _config;
59
- private _pluggables: AnalyticsProvider[];
60
- private _disabled;
61
- private _trackers;
62
-
63
- /**
64
- * Initialize Analtyics
65
- * @param config - Configuration of the Analytics
66
- */
67
- constructor() {
68
- this._config = {};
69
- this._pluggables = [];
70
- this._disabled = false;
71
- this._trackers = {};
72
- _instance = this;
73
-
74
- this.record = this.record.bind(this);
75
- Hub.listen('auth', listener);
76
- Hub.listen('storage', listener);
77
- Hub.listen('analytics', listener);
78
- }
79
-
80
- public getModuleName() {
81
- return 'Analytics';
82
- }
83
- /**
84
- * configure Analytics
85
- * @param {Object} config - Configuration of the Analytics
86
- */
87
- public configure(config?) {
88
- if (!config) return this._config;
89
- logger.debug('configure Analytics', config);
90
- const amplifyConfig = Parser.parseMobilehubConfig(config);
91
- this._config = Object.assign(
92
- {},
93
- this._config,
94
- amplifyConfig.Analytics,
95
- config
96
- );
97
-
98
- if (this._config['disabled']) {
99
- this._disabled = true;
100
- }
101
-
102
- // turn on the autoSessionRecord if not specified
103
- if (this._config['autoSessionRecord'] === undefined) {
104
- this._config['autoSessionRecord'] = true;
105
- }
106
-
107
- this._pluggables.forEach(pluggable => {
108
- // for backward compatibility
109
- const providerConfig =
110
- pluggable.getProviderName() === 'AWSPinpoint' &&
111
- !this._config['AWSPinpoint']
112
- ? this._config
113
- : this._config[pluggable.getProviderName()];
114
-
115
- pluggable.configure({
116
- disabled: this._config['disabled'],
117
- autoSessionRecord: this._config['autoSessionRecord'],
118
- ...providerConfig,
119
- });
120
- });
121
-
122
- if (this._pluggables.length === 0) {
123
- this.addPluggable(new AWSPinpointProvider());
124
- }
125
-
126
- dispatchAnalyticsEvent(
127
- 'configured',
128
- null,
129
- `The Analytics category has been configured successfully`
130
- );
131
- logger.debug('current configuration', this._config);
132
- return this._config;
133
- }
134
-
135
- /**
136
- * add plugin into Analytics category
137
- * @param {Object} pluggable - an instance of the plugin
138
- */
139
- public addPluggable(pluggable: AnalyticsProvider) {
140
- if (pluggable && pluggable.getCategory() === 'Analytics') {
141
- this._pluggables.push(pluggable);
142
- // for backward compatibility
143
- const providerConfig =
144
- pluggable.getProviderName() === 'AWSPinpoint' &&
145
- !this._config['AWSPinpoint']
146
- ? this._config
147
- : this._config[pluggable.getProviderName()];
148
- const config = { disabled: this._config['disabled'], ...providerConfig };
149
- pluggable.configure(config);
150
- return config;
151
- }
152
- }
153
-
154
- /**
155
- * Get the plugin object
156
- * @param providerName - the name of the plugin
157
- */
158
- public getPluggable(providerName) {
159
- for (let i = 0; i < this._pluggables.length; i += 1) {
160
- const pluggable = this._pluggables[i];
161
- if (pluggable.getProviderName() === providerName) {
162
- return pluggable;
163
- }
164
- }
165
-
166
- logger.debug('No plugin found with providerName', providerName);
167
- return null;
168
- }
169
-
170
- /**
171
- * Remove the plugin object
172
- * @param providerName - the name of the plugin
173
- */
174
- public removePluggable(providerName) {
175
- let idx = 0;
176
- while (idx < this._pluggables.length) {
177
- if (this._pluggables[idx].getProviderName() === providerName) {
178
- break;
179
- }
180
- idx += 1;
181
- }
182
-
183
- if (idx === this._pluggables.length) {
184
- logger.debug('No plugin found with providerName', providerName);
185
- return;
186
- } else {
187
- this._pluggables.splice(idx, idx + 1);
188
- return;
189
- }
190
- }
191
-
192
- /**
193
- * stop sending events
194
- */
195
- public disable() {
196
- this._disabled = true;
197
- }
198
-
199
- /**
200
- * start sending events
201
- */
202
- public enable() {
203
- this._disabled = false;
204
- }
205
-
206
- /**
207
- * Record Session start
208
- * @return - A promise which resolves if buffer doesn't overflow
209
- */
210
- public async startSession(provider?: string) {
211
- const params = { event: { name: '_session.start' }, provider };
212
- return this._sendEvent(params);
213
- }
214
-
215
- /**
216
- * Record Session stop
217
- * @return - A promise which resolves if buffer doesn't overflow
218
- */
219
- public async stopSession(provider?: string) {
220
- const params = { event: { name: '_session.stop' }, provider };
221
- return this._sendEvent(params);
222
- }
223
-
224
- /**
225
- * Record one analytic event and send it to Pinpoint
226
- * @param {String} name - The name of the event
227
- * @param {Object} [attributes] - Attributes of the event
228
- * @param {Object} [metrics] - Event metrics
229
- * @return - A promise which resolves if buffer doesn't overflow
230
- */
231
- public async record(
232
- event: string | object,
233
- provider?,
234
- metrics?: EventMetrics
235
- ) {
236
- let params = null;
237
- // this is just for compatibility, going to be deprecated
238
- if (typeof event === 'string') {
239
- params = {
240
- event: {
241
- name: event,
242
- attributes: provider,
243
- metrics,
244
- },
245
- provider: 'AWSPinpoint',
246
- };
247
- } else {
248
- params = { event, provider };
249
- }
250
- return this._sendEvent(params);
251
- }
252
-
253
- public async updateEndpoint(attrs, provider?) {
254
- const event = { ...attrs, name: '_update_endpoint' };
255
-
256
- return this.record(event, provider);
257
- }
258
-
259
- private _sendEvent(params) {
260
- if (this._disabled) {
261
- logger.debug('Analytics has been disabled');
262
- return Promise.resolve();
263
- }
264
-
265
- const provider = params.provider ? params.provider : 'AWSPinpoint';
266
-
267
- return new Promise((resolve, reject) => {
268
- this._pluggables.forEach(pluggable => {
269
- if (pluggable.getProviderName() === provider) {
270
- pluggable.record(params, { resolve, reject });
271
- }
272
- });
273
- });
274
- }
275
-
276
- public autoTrack(trackerType, opts) {
277
- if (!trackers[trackerType]) {
278
- logger.debug('invalid tracker type');
279
- return;
280
- }
281
-
282
- // to sync up two different configuration ways of auto session tracking
283
- if (trackerType === 'session') {
284
- this._config['autoSessionRecord'] = opts['enable'];
285
- }
286
-
287
- const tracker = this._trackers[trackerType];
288
- if (!tracker) {
289
- this._trackers[trackerType] = new trackers[trackerType](
290
- this.record,
291
- opts
292
- );
293
- } else {
294
- tracker.configure(opts);
295
- }
296
- }
297
- }
298
-
299
- let endpointUpdated = false;
300
- let authConfigured = false;
301
- let analyticsConfigured = false;
302
- const listener = capsule => {
303
- const { channel, payload } = capsule;
304
- logger.debug('on hub capsule ' + channel, payload);
305
-
306
- switch (channel) {
307
- case 'auth':
308
- authEvent(payload);
309
- break;
310
- case 'storage':
311
- storageEvent(payload);
312
- break;
313
- case 'analytics':
314
- analyticsEvent(payload);
315
- break;
316
- default:
317
- break;
318
- }
319
- };
320
-
321
- const storageEvent = payload => {
322
- const {
323
- data: { attrs, metrics },
324
- } = payload;
325
- if (!attrs) return;
326
-
327
- if (analyticsConfigured) {
328
- _instance
329
- .record({
330
- name: 'Storage',
331
- attributes: attrs,
332
- metrics,
333
- })
334
- .catch(e => {
335
- logger.debug('Failed to send the storage event automatically', e);
336
- });
337
- }
338
- };
339
-
340
- const authEvent = payload => {
341
- const { event } = payload;
342
- if (!event) {
343
- return;
344
- }
345
-
346
- const recordAuthEvent = async eventName => {
347
- if (authConfigured && analyticsConfigured) {
348
- try {
349
- return await _instance.record({ name: `_userauth.${eventName}` });
350
- } catch (err) {
351
- logger.debug(
352
- `Failed to send the ${eventName} event automatically`,
353
- err
354
- );
355
- }
356
- }
357
- };
358
-
359
- switch (event) {
360
- case 'signIn':
361
- return recordAuthEvent('sign_in');
362
- case 'signUp':
363
- return recordAuthEvent('sign_up');
364
- case 'signOut':
365
- return recordAuthEvent('sign_out');
366
- case 'signIn_failure':
367
- return recordAuthEvent('auth_fail');
368
- case 'configured':
369
- authConfigured = true;
370
- if (authConfigured && analyticsConfigured) {
371
- sendEvents();
372
- }
373
- break;
374
- }
375
- };
376
-
377
- const analyticsEvent = payload => {
378
- const { event } = payload;
379
- if (!event) return;
380
-
381
- switch (event) {
382
- case 'pinpointProvider_configured':
383
- analyticsConfigured = true;
384
- if (authConfigured && analyticsConfigured) {
385
- sendEvents();
386
- }
387
- break;
388
- }
389
- };
390
-
391
- const sendEvents = () => {
392
- const config = _instance.configure();
393
- if (!endpointUpdated && config['autoSessionRecord']) {
394
- _instance.updateEndpoint({ immediate: true }).catch(e => {
395
- logger.debug('Failed to update the endpoint', e);
396
- });
397
- endpointUpdated = true;
398
- }
399
- _instance.autoTrack('session', {
400
- enable: config['autoSessionRecord'],
401
- });
402
- };
403
-
404
- export const Analytics = new AnalyticsClass();
405
- Amplify.register(Analytics);
1
+ /*
2
+ * Copyright 2017-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
5
+ * the License. A copy of the License is located at
6
+ *
7
+ * http://aws.amazon.com/apache2.0/
8
+ *
9
+ * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
+ * and limitations under the License.
12
+ */
13
+
14
+ import {
15
+ Amplify,
16
+ ConsoleLogger as Logger,
17
+ Hub,
18
+ Parser,
19
+ } from '@aws-amplify/core';
20
+ import { AWSPinpointProvider } from './Providers/AWSPinpointProvider';
21
+
22
+ import { AnalyticsProvider, EventMetrics } from './types';
23
+ import { PageViewTracker, EventTracker, SessionTracker } from './trackers';
24
+
25
+ const logger = new Logger('AnalyticsClass');
26
+
27
+ const AMPLIFY_SYMBOL = (
28
+ typeof Symbol !== 'undefined' && typeof Symbol.for === 'function'
29
+ ? Symbol.for('amplify_default')
30
+ : '@@amplify_default'
31
+ ) as Symbol;
32
+
33
+ const dispatchAnalyticsEvent = (event: string, data: any, message: string) => {
34
+ Hub.dispatch(
35
+ 'analytics',
36
+ { event, data, message },
37
+ 'Analytics',
38
+ AMPLIFY_SYMBOL
39
+ );
40
+ };
41
+
42
+ const trackers = {
43
+ pageView: PageViewTracker,
44
+ event: EventTracker,
45
+ session: SessionTracker,
46
+ };
47
+
48
+ let _instance = null;
49
+
50
+ /**
51
+ * Provide mobile analytics client functions
52
+ */
53
+ export class AnalyticsClass {
54
+ private _config;
55
+ private _pluggables: AnalyticsProvider[];
56
+ private _disabled;
57
+ private _trackers;
58
+
59
+ /**
60
+ * Initialize Analtyics
61
+ * @param config - Configuration of the Analytics
62
+ */
63
+ constructor() {
64
+ this._config = {};
65
+ this._pluggables = [];
66
+ this._disabled = false;
67
+ this._trackers = {};
68
+ _instance = this;
69
+
70
+ this.record = this.record.bind(this);
71
+ Hub.listen('auth', listener);
72
+ Hub.listen('storage', listener);
73
+ Hub.listen('analytics', listener);
74
+ }
75
+
76
+ public getModuleName() {
77
+ return 'Analytics';
78
+ }
79
+ /**
80
+ * configure Analytics
81
+ * @param {Object} config - Configuration of the Analytics
82
+ */
83
+ public configure(config?) {
84
+ if (!config) return this._config;
85
+ logger.debug('configure Analytics', config);
86
+ const amplifyConfig = Parser.parseMobilehubConfig(config);
87
+ this._config = Object.assign(
88
+ {},
89
+ this._config,
90
+ amplifyConfig.Analytics,
91
+ config
92
+ );
93
+
94
+ if (this._config['disabled']) {
95
+ this._disabled = true;
96
+ }
97
+
98
+ // turn on the autoSessionRecord if not specified
99
+ if (this._config['autoSessionRecord'] === undefined) {
100
+ this._config['autoSessionRecord'] = true;
101
+ }
102
+
103
+ this._pluggables.forEach((pluggable) => {
104
+ // for backward compatibility
105
+ const providerConfig =
106
+ pluggable.getProviderName() === 'AWSPinpoint' &&
107
+ !this._config['AWSPinpoint']
108
+ ? this._config
109
+ : this._config[pluggable.getProviderName()];
110
+
111
+ pluggable.configure({
112
+ disabled: this._config['disabled'],
113
+ autoSessionRecord: this._config['autoSessionRecord'],
114
+ ...providerConfig,
115
+ });
116
+ });
117
+
118
+ if (this._pluggables.length === 0) {
119
+ this.addPluggable(new AWSPinpointProvider());
120
+ }
121
+
122
+ dispatchAnalyticsEvent(
123
+ 'configured',
124
+ null,
125
+ `The Analytics category has been configured successfully`
126
+ );
127
+ logger.debug('current configuration', this._config);
128
+ return this._config;
129
+ }
130
+
131
+ /**
132
+ * add plugin into Analytics category
133
+ * @param {Object} pluggable - an instance of the plugin
134
+ */
135
+ public addPluggable(pluggable: AnalyticsProvider) {
136
+ if (pluggable && pluggable.getCategory() === 'Analytics') {
137
+ this._pluggables.push(pluggable);
138
+ // for backward compatibility
139
+ const providerConfig =
140
+ pluggable.getProviderName() === 'AWSPinpoint' &&
141
+ !this._config['AWSPinpoint']
142
+ ? this._config
143
+ : this._config[pluggable.getProviderName()];
144
+ const config = { disabled: this._config['disabled'], ...providerConfig };
145
+ pluggable.configure(config);
146
+ return config;
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Get the plugin object
152
+ * @param providerName - the name of the plugin
153
+ */
154
+ public getPluggable(providerName) {
155
+ for (let i = 0; i < this._pluggables.length; i += 1) {
156
+ const pluggable = this._pluggables[i];
157
+ if (pluggable.getProviderName() === providerName) {
158
+ return pluggable;
159
+ }
160
+ }
161
+
162
+ logger.debug('No plugin found with providerName', providerName);
163
+ return null;
164
+ }
165
+
166
+ /**
167
+ * Remove the plugin object
168
+ * @param providerName - the name of the plugin
169
+ */
170
+ public removePluggable(providerName) {
171
+ let idx = 0;
172
+ while (idx < this._pluggables.length) {
173
+ if (this._pluggables[idx].getProviderName() === providerName) {
174
+ break;
175
+ }
176
+ idx += 1;
177
+ }
178
+
179
+ if (idx === this._pluggables.length) {
180
+ logger.debug('No plugin found with providerName', providerName);
181
+ return;
182
+ } else {
183
+ this._pluggables.splice(idx, idx + 1);
184
+ return;
185
+ }
186
+ }
187
+
188
+ /**
189
+ * stop sending events
190
+ */
191
+ public disable() {
192
+ this._disabled = true;
193
+ }
194
+
195
+ /**
196
+ * start sending events
197
+ */
198
+ public enable() {
199
+ this._disabled = false;
200
+ }
201
+
202
+ /**
203
+ * Record Session start
204
+ * @return - A promise which resolves if buffer doesn't overflow
205
+ */
206
+ public async startSession(provider?: string) {
207
+ const params = { event: { name: '_session.start' }, provider };
208
+ return this._sendEvent(params);
209
+ }
210
+
211
+ /**
212
+ * Record Session stop
213
+ * @return - A promise which resolves if buffer doesn't overflow
214
+ */
215
+ public async stopSession(provider?: string) {
216
+ const params = { event: { name: '_session.stop' }, provider };
217
+ return this._sendEvent(params);
218
+ }
219
+
220
+ /**
221
+ * Record one analytic event and send it to Pinpoint
222
+ * @param {String} name - The name of the event
223
+ * @param {Object} [attributes] - Attributes of the event
224
+ * @param {Object} [metrics] - Event metrics
225
+ * @return - A promise which resolves if buffer doesn't overflow
226
+ */
227
+ public async record(
228
+ event: string | object,
229
+ provider?,
230
+ metrics?: EventMetrics
231
+ ) {
232
+ let params = null;
233
+ // this is just for compatibility, going to be deprecated
234
+ if (typeof event === 'string') {
235
+ params = {
236
+ event: {
237
+ name: event,
238
+ attributes: provider,
239
+ metrics,
240
+ },
241
+ provider: 'AWSPinpoint',
242
+ };
243
+ } else {
244
+ params = { event, provider };
245
+ }
246
+ return this._sendEvent(params);
247
+ }
248
+
249
+ public async updateEndpoint(attrs, provider?) {
250
+ const event = { ...attrs, name: '_update_endpoint' };
251
+
252
+ return this.record(event, provider);
253
+ }
254
+
255
+ private _sendEvent(params) {
256
+ if (this._disabled) {
257
+ logger.debug('Analytics has been disabled');
258
+ return Promise.resolve();
259
+ }
260
+
261
+ const provider = params.provider ? params.provider : 'AWSPinpoint';
262
+
263
+ return new Promise((resolve, reject) => {
264
+ this._pluggables.forEach((pluggable) => {
265
+ if (pluggable.getProviderName() === provider) {
266
+ pluggable.record(params, { resolve, reject });
267
+ }
268
+ });
269
+ });
270
+ }
271
+
272
+ public autoTrack(trackerType, opts) {
273
+ if (!trackers[trackerType]) {
274
+ logger.debug('invalid tracker type');
275
+ return;
276
+ }
277
+
278
+ // to sync up two different configuration ways of auto session tracking
279
+ if (trackerType === 'session') {
280
+ this._config['autoSessionRecord'] = opts['enable'];
281
+ }
282
+
283
+ const tracker = this._trackers[trackerType];
284
+ if (!tracker) {
285
+ this._trackers[trackerType] = new trackers[trackerType](
286
+ this.record,
287
+ opts
288
+ );
289
+ } else {
290
+ tracker.configure(opts);
291
+ }
292
+ }
293
+ }
294
+
295
+ let endpointUpdated = false;
296
+ let authConfigured = false;
297
+ let analyticsConfigured = false;
298
+ const listener = (capsule) => {
299
+ const { channel, payload } = capsule;
300
+ logger.debug('on hub capsule ' + channel, payload);
301
+
302
+ switch (channel) {
303
+ case 'auth':
304
+ authEvent(payload);
305
+ break;
306
+ case 'storage':
307
+ storageEvent(payload);
308
+ break;
309
+ case 'analytics':
310
+ analyticsEvent(payload);
311
+ break;
312
+ default:
313
+ break;
314
+ }
315
+ };
316
+
317
+ const storageEvent = (payload) => {
318
+ const {
319
+ data: { attrs, metrics },
320
+ } = payload;
321
+ if (!attrs) return;
322
+
323
+ if (analyticsConfigured) {
324
+ _instance
325
+ .record({
326
+ name: 'Storage',
327
+ attributes: attrs,
328
+ metrics,
329
+ })
330
+ .catch((e) => {
331
+ logger.debug('Failed to send the storage event automatically', e);
332
+ });
333
+ }
334
+ };
335
+
336
+ const authEvent = (payload) => {
337
+ const { event } = payload;
338
+ if (!event) {
339
+ return;
340
+ }
341
+
342
+ const recordAuthEvent = async (eventName) => {
343
+ if (authConfigured && analyticsConfigured) {
344
+ try {
345
+ return await _instance.record({ name: `_userauth.${eventName}` });
346
+ } catch (err) {
347
+ logger.debug(
348
+ `Failed to send the ${eventName} event automatically`,
349
+ err
350
+ );
351
+ }
352
+ }
353
+ };
354
+
355
+ switch (event) {
356
+ case 'signIn':
357
+ return recordAuthEvent('sign_in');
358
+ case 'signUp':
359
+ return recordAuthEvent('sign_up');
360
+ case 'signOut':
361
+ return recordAuthEvent('sign_out');
362
+ case 'signIn_failure':
363
+ return recordAuthEvent('auth_fail');
364
+ case 'configured':
365
+ authConfigured = true;
366
+ if (authConfigured && analyticsConfigured) {
367
+ sendEvents();
368
+ }
369
+ break;
370
+ }
371
+ };
372
+
373
+ const analyticsEvent = (payload) => {
374
+ const { event } = payload;
375
+ if (!event) return;
376
+
377
+ switch (event) {
378
+ case 'pinpointProvider_configured':
379
+ analyticsConfigured = true;
380
+ if (authConfigured && analyticsConfigured) {
381
+ sendEvents();
382
+ }
383
+ break;
384
+ }
385
+ };
386
+
387
+ const sendEvents = () => {
388
+ const config = _instance.configure();
389
+ if (!endpointUpdated && config['autoSessionRecord']) {
390
+ _instance.updateEndpoint({ immediate: true }).catch((e) => {
391
+ logger.debug('Failed to update the endpoint', e);
392
+ });
393
+ endpointUpdated = true;
394
+ }
395
+ _instance.autoTrack('session', {
396
+ enable: config['autoSessionRecord'],
397
+ });
398
+ };
399
+
400
+ export const Analytics = new AnalyticsClass();
401
+ Amplify.register(Analytics);