@crimson-education/browser-logger 5.0.1-beta.2 → 5.0.1-beta.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.
- package/README.md +63 -85
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +46 -22
- package/lib/index.js.map +1 -1
- package/lib/logger/consoleTransport.d.ts +1 -1
- package/lib/logger/consoleTransport.d.ts.map +1 -1
- package/lib/logger/consoleTransport.js +22 -16
- package/lib/logger/consoleTransport.js.map +1 -1
- package/lib/logger/datadogTransport.d.ts +1 -1
- package/lib/logger/datadogTransport.d.ts.map +1 -1
- package/lib/logger/datadogTransport.js +8 -4
- package/lib/logger/datadogTransport.js.map +1 -1
- package/lib/logger/index.js +49 -29
- package/lib/logger/index.js.map +1 -1
- package/lib/logger/index.test.js +18 -16
- package/lib/logger/index.test.js.map +1 -1
- package/lib/logger/utils.js +9 -4
- package/lib/logger/utils.js.map +1 -1
- package/lib/reporters/amplifyReporter.d.ts +4 -4
- package/lib/reporters/amplifyReporter.d.ts.map +1 -1
- package/lib/reporters/amplifyReporter.js +133 -230
- package/lib/reporters/amplifyReporter.js.map +1 -1
- package/lib/reporters/amplifyReporter.test.js +12 -9
- package/lib/reporters/amplifyReporter.test.js.map +1 -1
- package/lib/reporters/datadogReporter.d.ts +1 -13
- package/lib/reporters/datadogReporter.d.ts.map +1 -1
- package/lib/reporters/datadogReporter.js +49 -122
- package/lib/reporters/datadogReporter.js.map +1 -1
- package/lib/reporters/gtmReporter.d.ts +1 -1
- package/lib/reporters/gtmReporter.d.ts.map +1 -1
- package/lib/reporters/gtmReporter.js +5 -1
- package/lib/reporters/gtmReporter.js.map +1 -1
- package/lib/reporters/index.js +71 -46
- package/lib/reporters/index.js.map +1 -1
- package/lib/reporters/logReporter.js +34 -24
- package/lib/reporters/logReporter.js.map +1 -1
- package/lib/reporters/posthogReporter.d.ts +51 -0
- package/lib/reporters/posthogReporter.d.ts.map +1 -0
- package/lib/reporters/posthogReporter.js +254 -0
- package/lib/reporters/posthogReporter.js.map +1 -0
- package/lib/reporters/posthogReporter.test.d.ts +2 -0
- package/lib/reporters/posthogReporter.test.d.ts.map +1 -0
- package/lib/reporters/posthogReporter.test.js +197 -0
- package/lib/reporters/posthogReporter.test.js.map +1 -0
- package/lib/types/index.js +18 -2
- package/lib/types/index.js.map +1 -1
- package/lib/types/logger.d.ts +3 -3
- package/lib/types/logger.d.ts.map +1 -1
- package/lib/types/logger.js +5 -2
- package/lib/types/logger.js.map +1 -1
- package/lib/types/reporter.d.ts +14 -6
- package/lib/types/reporter.d.ts.map +1 -1
- package/lib/types/reporter.js +2 -1
- package/lib/utils.js +5 -1
- package/lib/utils.js.map +1 -1
- package/lib/utils.test.js +4 -2
- package/lib/utils.test.js.map +1 -1
- package/package.json +17 -15
- package/src/index.ts +6 -0
- package/src/reporters/amplifyReporter.ts +140 -264
- package/src/reporters/datadogReporter.ts +22 -133
- package/src/reporters/posthogReporter.test.ts +244 -0
- package/src/reporters/posthogReporter.ts +374 -0
- package/src/types/reporter.ts +9 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { Auth } from '@aws-amplify/auth';
|
|
2
|
+
import { Analytics } from '@aws-amplify/analytics';
|
|
3
|
+
import { Endpoint, FinalizeRequestMiddleware } from '@aws-sdk/types';
|
|
4
|
+
import { HttpRequest } from '@aws-sdk/protocol-http';
|
|
5
|
+
import { PinpointClient, ServiceInputTypes, ServiceOutputTypes } from '@aws-sdk/client-pinpoint';
|
|
5
6
|
|
|
6
7
|
import {
|
|
7
8
|
IReporter,
|
|
@@ -13,164 +14,12 @@ import {
|
|
|
13
14
|
ServiceInfo,
|
|
14
15
|
} from '../types';
|
|
15
16
|
import { logger } from '../logger';
|
|
16
|
-
// Note: fetchAuthSession was previously imported but unused; removing to satisfy linter
|
|
17
|
-
import { Amplify } from '@aws-amplify/core';
|
|
18
17
|
|
|
19
18
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
20
19
|
type AttributeMap = Record<string, string[] | string | null>;
|
|
21
20
|
|
|
22
21
|
type AmplifyAutoTrackSource = 'pageView' | 'event' | 'session';
|
|
23
22
|
|
|
24
|
-
// Auto-tracking implementation for Gen2
|
|
25
|
-
class AmplifyAutoTracker {
|
|
26
|
-
private config: AmplifyReporterConfig;
|
|
27
|
-
private allMetadata: AttributeMap;
|
|
28
|
-
private currentUser: ReportUser | null = null;
|
|
29
|
-
private sessionStartTime: number = Date.now();
|
|
30
|
-
private pageViewCount: number = 0;
|
|
31
|
-
private lastPageUrl: string = window.location.href;
|
|
32
|
-
private isPageVisible: boolean = !document.hidden;
|
|
33
|
-
|
|
34
|
-
constructor(config: AmplifyReporterConfig, allMetadata: AttributeMap) {
|
|
35
|
-
this.config = config;
|
|
36
|
-
this.allMetadata = allMetadata;
|
|
37
|
-
this.setupEventListeners();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
private setupEventListeners() {
|
|
41
|
-
// Page visibility tracking
|
|
42
|
-
document.addEventListener('visibilitychange', () => {
|
|
43
|
-
this.isPageVisible = !document.hidden;
|
|
44
|
-
if (this.config.autoTrackSessions) {
|
|
45
|
-
this.trackSessionState();
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
// Page view tracking
|
|
50
|
-
if (this.config.autoTrackPageViews) {
|
|
51
|
-
// Delay initial page view to ensure Amplify is fully configured
|
|
52
|
-
// Using setTimeout(0) to defer to the next event loop tick
|
|
53
|
-
setTimeout(() => {
|
|
54
|
-
this.trackPageView();
|
|
55
|
-
}, 0);
|
|
56
|
-
|
|
57
|
-
// Track route changes for SPAs
|
|
58
|
-
let currentUrl = window.location.href;
|
|
59
|
-
const observer = new MutationObserver(() => {
|
|
60
|
-
if (window.location.href !== currentUrl) {
|
|
61
|
-
currentUrl = window.location.href;
|
|
62
|
-
this.trackPageView();
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
observer.observe(document.body, { childList: true, subtree: true });
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// User interaction tracking
|
|
69
|
-
if (this.config.autoTrackEvents) {
|
|
70
|
-
this.setupInteractionTracking();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
private trackPageView() {
|
|
75
|
-
this.pageViewCount++;
|
|
76
|
-
const pageViewEvent = {
|
|
77
|
-
message: 'Page View',
|
|
78
|
-
metadata: {
|
|
79
|
-
url: window.location.href,
|
|
80
|
-
title: document.title,
|
|
81
|
-
referrer: document.referrer,
|
|
82
|
-
pageViewCount: this.pageViewCount,
|
|
83
|
-
...this.getAutoTrackMetadata('pageView'),
|
|
84
|
-
},
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
record({
|
|
88
|
-
name: pageViewEvent.message,
|
|
89
|
-
attributes: asAttributeMap(
|
|
90
|
-
{
|
|
91
|
-
...this.allMetadata,
|
|
92
|
-
...pageViewEvent.metadata,
|
|
93
|
-
},
|
|
94
|
-
false,
|
|
95
|
-
) as Record<string, string>,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private trackSessionState() {
|
|
100
|
-
const sessionDuration = Date.now() - this.sessionStartTime;
|
|
101
|
-
const sessionEvent = {
|
|
102
|
-
message: this.isPageVisible ? 'Session Active' : 'Session Inactive',
|
|
103
|
-
metadata: {
|
|
104
|
-
sessionDuration,
|
|
105
|
-
isVisible: this.isPageVisible,
|
|
106
|
-
...this.getAutoTrackMetadata('session'),
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
record({
|
|
111
|
-
name: sessionEvent.message,
|
|
112
|
-
attributes: asAttributeMap(
|
|
113
|
-
{
|
|
114
|
-
...this.allMetadata,
|
|
115
|
-
...sessionEvent.metadata,
|
|
116
|
-
},
|
|
117
|
-
false,
|
|
118
|
-
) as Record<string, string>,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
private setupInteractionTracking() {
|
|
123
|
-
const selectorPrefix = this.config.selectorPrefix ?? 'data-analytics-';
|
|
124
|
-
|
|
125
|
-
document.addEventListener('click', (event) => {
|
|
126
|
-
const target = event.target as HTMLElement;
|
|
127
|
-
if (!target) return;
|
|
128
|
-
|
|
129
|
-
// Find the closest element with analytics attributes
|
|
130
|
-
const analyticsElement = target.closest(`[${selectorPrefix}name]`);
|
|
131
|
-
if (!analyticsElement) return;
|
|
132
|
-
|
|
133
|
-
const analyticsName = analyticsElement.getAttribute(`${selectorPrefix}name`);
|
|
134
|
-
if (!analyticsName) return;
|
|
135
|
-
|
|
136
|
-
const interactionEvent = {
|
|
137
|
-
message: 'User Interaction',
|
|
138
|
-
metadata: {
|
|
139
|
-
elementName: analyticsName,
|
|
140
|
-
elementType: target.tagName.toLowerCase(),
|
|
141
|
-
elementText: target.textContent?.slice(0, 100),
|
|
142
|
-
interactionType: 'click',
|
|
143
|
-
...this.getAutoTrackMetadata('event'),
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
record({
|
|
148
|
-
name: interactionEvent.message,
|
|
149
|
-
attributes: asAttributeMap(
|
|
150
|
-
{
|
|
151
|
-
...this.allMetadata,
|
|
152
|
-
...interactionEvent.metadata,
|
|
153
|
-
},
|
|
154
|
-
false,
|
|
155
|
-
) as Record<string, string>,
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
private getAutoTrackMetadata(source: AmplifyAutoTrackSource): Metadata {
|
|
161
|
-
const { beforeAutoTrack } = this.config;
|
|
162
|
-
return typeof beforeAutoTrack === 'function' ? (beforeAutoTrack(source) ?? {}) : {};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
public setUser(user: ReportUser | null) {
|
|
166
|
-
this.currentUser = user;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
public updateMetadata(metadata: AttributeMap) {
|
|
170
|
-
Object.assign(this.allMetadata, metadata);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
23
|
export interface AmplifyReporterConfig extends ReporterConfigBase {
|
|
175
24
|
/**
|
|
176
25
|
* AWS Region for Amplify.
|
|
@@ -180,7 +29,7 @@ export interface AmplifyReporterConfig extends ReporterConfigBase {
|
|
|
180
29
|
* The Identity Pool Id to use for reporting, if set to false, Auth.configure is not called.
|
|
181
30
|
* This must be called manually for the reporter to work.
|
|
182
31
|
*/
|
|
183
|
-
identityPoolId: string;
|
|
32
|
+
identityPoolId: string | false;
|
|
184
33
|
/**
|
|
185
34
|
* The Pinpoint App Id to report to.
|
|
186
35
|
*/
|
|
@@ -247,21 +96,19 @@ type AmplifyReporterBufferingConfig = {
|
|
|
247
96
|
};
|
|
248
97
|
|
|
249
98
|
export function amplifyReporter(info: ServiceInfo, config: AmplifyReporterConfig): IReporter {
|
|
250
|
-
|
|
251
|
-
Auth
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
},
|
|
264
|
-
});
|
|
99
|
+
if (config.identityPoolId !== false) {
|
|
100
|
+
Auth.configure({
|
|
101
|
+
region: config.region,
|
|
102
|
+
identityPoolId: config.identityPoolId,
|
|
103
|
+
userPoolId: config.userPoolId,
|
|
104
|
+
userPoolWebClientId: config.userPoolWebClientId,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const wrapAutoTrackMiddleware = (source: AmplifyAutoTrackSource) => {
|
|
109
|
+
const { beforeAutoTrack } = config;
|
|
110
|
+
return typeof beforeAutoTrack === 'function' ? () => beforeAutoTrack(source) ?? {} : undefined;
|
|
111
|
+
};
|
|
265
112
|
|
|
266
113
|
const allMetadata = asAttributeMap({
|
|
267
114
|
appName: info.service,
|
|
@@ -271,26 +118,59 @@ export function amplifyReporter(info: ServiceInfo, config: AmplifyReporterConfig
|
|
|
271
118
|
version: info.version,
|
|
272
119
|
});
|
|
273
120
|
|
|
274
|
-
|
|
275
|
-
|
|
121
|
+
Analytics.configure({
|
|
122
|
+
region: config.region,
|
|
123
|
+
appId: config.analyticsAppId,
|
|
124
|
+
endpoint: {
|
|
125
|
+
attributes: allMetadata,
|
|
126
|
+
},
|
|
127
|
+
...config.buffering,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Session autotracking is enabled by default for backwards compatibility reasons, so we _must_
|
|
131
|
+
// call this unconditionally to ensure we opt out of session tracking when `autoTrackSessions` isn't set
|
|
132
|
+
// See: https://docs.amplify.aws/lib/analytics/autotrack/q/platform/js/#session-tracking
|
|
133
|
+
Analytics.autoTrack('session', {
|
|
134
|
+
enable: config.autoTrackSessions === true,
|
|
135
|
+
attributes: wrapAutoTrackMiddleware('session'),
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (config.autoTrackPageViews) {
|
|
139
|
+
Analytics.autoTrack('pageView', {
|
|
140
|
+
enable: true,
|
|
141
|
+
eventName: 'pageView',
|
|
142
|
+
type: 'SPA',
|
|
143
|
+
provider: 'AWSPinpoint',
|
|
144
|
+
attributes: wrapAutoTrackMiddleware('pageView'),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (config.autoTrackEvents) {
|
|
149
|
+
Analytics.autoTrack('event', {
|
|
150
|
+
enable: true,
|
|
151
|
+
selectorPrefix: config.selectorPrefix ?? 'data-analytics-',
|
|
152
|
+
attributes: wrapAutoTrackMiddleware('event'),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
276
155
|
|
|
277
156
|
if (config.proxyUrl) {
|
|
278
|
-
|
|
157
|
+
installPinpointProxy(new URL(config.proxyUrl));
|
|
279
158
|
}
|
|
280
159
|
|
|
281
160
|
const reporter: IReporter = {
|
|
282
161
|
trackEvent: function (event: ReporterEvent): void {
|
|
283
|
-
record({
|
|
162
|
+
Analytics.record({
|
|
284
163
|
name: event.message,
|
|
285
164
|
attributes: asAttributeMap(
|
|
286
165
|
{
|
|
287
|
-
...allMetadata,
|
|
288
166
|
...event.metadata,
|
|
289
167
|
...event.tags,
|
|
290
168
|
},
|
|
291
169
|
false,
|
|
292
170
|
) as Record<string, string>,
|
|
293
171
|
metrics: event.metrics,
|
|
172
|
+
}).catch(() => {
|
|
173
|
+
// Swallow; see: https://crimsonhq.slack.com/archives/G4UN6Q4KF/p1648599302847539
|
|
294
174
|
});
|
|
295
175
|
},
|
|
296
176
|
addBreadcrumb: function (breadcrumb: ReporterBreadcrumb): void {
|
|
@@ -304,9 +184,11 @@ export function amplifyReporter(info: ServiceInfo, config: AmplifyReporterConfig
|
|
|
304
184
|
},
|
|
305
185
|
addMetadata: function (metadata: Metadata): void {
|
|
306
186
|
Object.assign(allMetadata, asAttributeMap(metadata, true));
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
187
|
+
Analytics.updateEndpoint({
|
|
188
|
+
attributes: allMetadata,
|
|
189
|
+
}).catch(() => {
|
|
190
|
+
// Swallow; see: https://crimsonhq.slack.com/archives/G4UN6Q4KF/p1648599302847539
|
|
191
|
+
});
|
|
310
192
|
},
|
|
311
193
|
setUser: function (user: ReportUser | null): void {
|
|
312
194
|
const userMetadata = user
|
|
@@ -315,21 +197,20 @@ export function amplifyReporter(info: ServiceInfo, config: AmplifyReporterConfig
|
|
|
315
197
|
})
|
|
316
198
|
: {};
|
|
317
199
|
Object.assign(allMetadata, asAttributeMap(userMetadata, true));
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
200
|
+
Analytics.updateEndpoint({
|
|
201
|
+
userId: user?.id ?? '',
|
|
202
|
+
attributes: allMetadata,
|
|
203
|
+
userAttributes: user
|
|
204
|
+
? asAttributeMap({
|
|
205
|
+
id: user.id,
|
|
206
|
+
email: user.email,
|
|
207
|
+
name: user.name ?? user.email,
|
|
208
|
+
username: user.username,
|
|
209
|
+
})
|
|
210
|
+
: {},
|
|
211
|
+
}).catch(() => {
|
|
212
|
+
// Swallow; see: https://crimsonhq.slack.com/archives/G4UN6Q4KF/p1648599302847539
|
|
213
|
+
});
|
|
333
214
|
},
|
|
334
215
|
setRouteName: function (routeName: string): void {
|
|
335
216
|
reporter.addMetadata({ routeName });
|
|
@@ -351,8 +232,8 @@ export function asAttributeMap(values: Record<string, unknown>, groupValues = tr
|
|
|
351
232
|
const checkedEntries = Object.entries(attributeMap).map(([key, value]) => {
|
|
352
233
|
const truncatedKey = key.length > 50 ? `___${key.slice(-47)}` : key;
|
|
353
234
|
const truncatedValue = Array.isArray(value)
|
|
354
|
-
?
|
|
355
|
-
:
|
|
235
|
+
? value?.map((val) => val.slice(0, 100)) ?? null
|
|
236
|
+
: value?.slice(0, 100) ?? null;
|
|
356
237
|
|
|
357
238
|
return [truncatedKey, truncatedValue];
|
|
358
239
|
});
|
|
@@ -383,13 +264,8 @@ export function buildAttributeMap(
|
|
|
383
264
|
Object.entries(values).forEach(([key, value]) => {
|
|
384
265
|
const combinedKey = parentKey ? [parentKey, key].join('.') : key;
|
|
385
266
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
// For event attributes (groupValues === false), Pinpoint rejects null values.
|
|
389
|
-
// In that case we omit the key entirely to avoid "Event attribute value can not be null".
|
|
390
|
-
if (groupValues) {
|
|
391
|
-
valuesWithStringArrays[combinedKey] = null;
|
|
392
|
-
}
|
|
267
|
+
if (!value) {
|
|
268
|
+
valuesWithStringArrays[combinedKey] = null;
|
|
393
269
|
} else if (groupValues && Array.isArray(value)) {
|
|
394
270
|
valuesWithStringArrays[combinedKey] = value.map((element) =>
|
|
395
271
|
typeof element === 'string' ? element : JSON.stringify(element),
|
|
@@ -406,63 +282,63 @@ export function buildAttributeMap(
|
|
|
406
282
|
return valuesWithStringArrays;
|
|
407
283
|
}
|
|
408
284
|
|
|
409
|
-
|
|
410
|
-
//
|
|
411
|
-
//
|
|
412
|
-
//
|
|
413
|
-
//
|
|
414
|
-
//
|
|
415
|
-
//
|
|
416
|
-
//
|
|
417
|
-
//
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
//
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
//
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
//
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
285
|
+
function installPinpointProxy(proxyUrl: URL) {
|
|
286
|
+
// No public API for overriding where the Pinpoint client sends events to... 🤮
|
|
287
|
+
// In theory you can pass in an `endpoint` to the Pinpoint client's constructor like any other AWS
|
|
288
|
+
// client, but Amplify's analytics doesn't expose anything we can use to get an endpoint threaded
|
|
289
|
+
// down to the Pinpoint client's constructor.
|
|
290
|
+
//
|
|
291
|
+
// The Pinpoint client _also_ isn't available synchronously because it is instantiated when events
|
|
292
|
+
// get sent out, and then reconfigured whenever the API credentials change. We need to hook `_initClients`
|
|
293
|
+
// to ensure that the Pinpoint client being used is always patched with our custom endpoint.
|
|
294
|
+
const provider = Analytics.getPluggable('AWSPinpoint') as any;
|
|
295
|
+
if (!provider || typeof provider._initClients !== 'function') {
|
|
296
|
+
logger.error(
|
|
297
|
+
'Installation of the Pinpoint proxy failed. This likely means the internals of the @aws-amplify/analytics package have changed.',
|
|
298
|
+
);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const originalInitClients = provider._initClients;
|
|
303
|
+
const requestMiddleware: FinalizeRequestMiddleware<ServiceInputTypes, ServiceOutputTypes> =
|
|
304
|
+
(next) => async (args) => {
|
|
305
|
+
const pinpointClient = provider.pinpointClient as PinpointClient | undefined;
|
|
306
|
+
|
|
307
|
+
if (pinpointClient && proxyUrl.pathname !== '/' && HttpRequest.isInstance(args.request)) {
|
|
308
|
+
// Add proxyUrl.pathname to final request url if it was provided
|
|
309
|
+
const shouldStripSlash = proxyUrl.pathname.endsWith('/');
|
|
310
|
+
args.request.path = `${proxyUrl.pathname}${args.request.path.slice(shouldStripSlash ? 1 : 0)}`;
|
|
311
|
+
|
|
312
|
+
// Wrap request body so the proxy has signing info
|
|
313
|
+
if (typeof args.request.body === 'string') {
|
|
314
|
+
const credentials = await pinpointClient.config.credentials();
|
|
315
|
+
args.request.body = JSON.stringify({
|
|
316
|
+
credentials,
|
|
317
|
+
data: JSON.parse(args.request.body),
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return next(args);
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
provider._initClients = async (credentials: unknown) => {
|
|
326
|
+
const result = await originalInitClients.call(provider, credentials);
|
|
327
|
+
const pinpointClient = provider.pinpointClient as PinpointClient | undefined;
|
|
328
|
+
|
|
329
|
+
if (pinpointClient) {
|
|
330
|
+
pinpointClient.config.endpoint = (): Promise<Endpoint> =>
|
|
331
|
+
Promise.resolve({
|
|
332
|
+
hostname: proxyUrl.hostname,
|
|
333
|
+
// Passing proxyUrl.pathname here doesn't work; it gets overridden
|
|
334
|
+
path: '/',
|
|
335
|
+
port: undefined,
|
|
336
|
+
protocol: proxyUrl.protocol,
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
pinpointClient.middlewareStack.remove(requestMiddleware);
|
|
340
|
+
pinpointClient.middlewareStack.add(requestMiddleware, { step: 'finalizeRequest' });
|
|
341
|
+
}
|
|
342
|
+
return result;
|
|
343
|
+
};
|
|
344
|
+
}
|