UNPKG

3.98 kBJavaScriptView Raw
1import { arrayify, logger } from '@sentry/utils';
2import { getCurrentHub } from './hub.js';
3import { addGlobalEventProcessor } from './scope.js';
4
5const installedIntegrations = [];
6
7/** Map of integrations assigned to a client */
8
9/**
10 * Remove duplicates from the given array, preferring the last instance of any duplicate. Not guaranteed to
11 * preseve the order of integrations in the array.
12 *
13 * @private
14 */
15function filterDuplicates(integrations) {
16 const integrationsByName = {};
17
18 integrations.forEach(currentInstance => {
19 const { name } = currentInstance;
20
21 const existingInstance = integrationsByName[name];
22
23 // We want integrations later in the array to overwrite earlier ones of the same type, except that we never want a
24 // default instance to overwrite an existing user instance
25 if (existingInstance && !existingInstance.isDefaultInstance && currentInstance.isDefaultInstance) {
26 return;
27 }
28
29 integrationsByName[name] = currentInstance;
30 });
31
32 return Object.keys(integrationsByName).map(k => integrationsByName[k]);
33}
34
35/** Gets integrations to install */
36function getIntegrationsToSetup(options) {
37 const defaultIntegrations = options.defaultIntegrations || [];
38 const userIntegrations = options.integrations;
39
40 // We flag default instances, so that later we can tell them apart from any user-created instances of the same class
41 defaultIntegrations.forEach(integration => {
42 integration.isDefaultInstance = true;
43 });
44
45 let integrations;
46
47 if (Array.isArray(userIntegrations)) {
48 integrations = [...defaultIntegrations, ...userIntegrations];
49 } else if (typeof userIntegrations === 'function') {
50 integrations = arrayify(userIntegrations(defaultIntegrations));
51 } else {
52 integrations = defaultIntegrations;
53 }
54
55 const finalIntegrations = filterDuplicates(integrations);
56
57 // The `Debug` integration prints copies of the `event` and `hint` which will be passed to `beforeSend` or
58 // `beforeSendTransaction`. It therefore has to run after all other integrations, so that the changes of all event
59 // processors will be reflected in the printed values. For lack of a more elegant way to guarantee that, we therefore
60 // locate it and, assuming it exists, pop it out of its current spot and shove it onto the end of the array.
61 const debugIndex = findIndex(finalIntegrations, integration => integration.name === 'Debug');
62 if (debugIndex !== -1) {
63 const [debugInstance] = finalIntegrations.splice(debugIndex, 1);
64 finalIntegrations.push(debugInstance);
65 }
66
67 return finalIntegrations;
68}
69
70/**
71 * Given a list of integration instances this installs them all. When `withDefaults` is set to `true` then all default
72 * integrations are added unless they were already provided before.
73 * @param integrations array of integration instances
74 * @param withDefault should enable default integrations
75 */
76function setupIntegrations(integrations) {
77 const integrationIndex = {};
78
79 integrations.forEach(integration => {
80 // guard against empty provided integrations
81 if (integration) {
82 setupIntegration(integration, integrationIndex);
83 }
84 });
85
86 return integrationIndex;
87}
88
89/** Setup a single integration. */
90function setupIntegration(integration, integrationIndex) {
91 integrationIndex[integration.name] = integration;
92
93 if (installedIntegrations.indexOf(integration.name) === -1) {
94 integration.setupOnce(addGlobalEventProcessor, getCurrentHub);
95 installedIntegrations.push(integration.name);
96 (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log(`Integration installed: ${integration.name}`);
97 }
98}
99
100// Polyfill for Array.findIndex(), which is not supported in ES5
101function findIndex(arr, callback) {
102 for (let i = 0; i < arr.length; i++) {
103 if (callback(arr[i]) === true) {
104 return i;
105 }
106 }
107
108 return -1;
109}
110
111export { getIntegrationsToSetup, installedIntegrations, setupIntegration, setupIntegrations };
112//# sourceMappingURL=integration.js.map