Skip to content

Commit d780165

Browse files
authored
feat(core): Add optional setup hook to integrations (#9556)
This can be used to replace some of our `setupOnce` hooks, and does not rely on global state.
1 parent 1036537 commit d780165

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

packages/core/src/integration.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,17 @@ export function setupIntegrations(client: Client, integrations: Integration[]):
101101
export function setupIntegration(client: Client, integration: Integration, integrationIndex: IntegrationIndex): void {
102102
integrationIndex[integration.name] = integration;
103103

104+
// `setupOnce` is only called the first time
104105
if (installedIntegrations.indexOf(integration.name) === -1) {
105106
integration.setupOnce(addGlobalEventProcessor, getCurrentHub);
106107
installedIntegrations.push(integration.name);
107108
}
108109

110+
// `setup` is run for each client
111+
if (integration.setup && typeof integration.setup === 'function') {
112+
integration.setup(client);
113+
}
114+
109115
if (client.on && typeof integration.preprocessEvent === 'function') {
110116
const callback = integration.preprocessEvent.bind(integration) as typeof integration.preprocessEvent;
111117
client.on('preprocessEvent', (event, hint) => callback(event, hint, client));

packages/core/test/lib/integration.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,44 @@ describe('setupIntegration', () => {
378378
expect(integration4.setupOnce).not.toHaveBeenCalled();
379379
});
380380

381+
it('calls setup for each client', () => {
382+
class CustomIntegration implements Integration {
383+
name = 'test';
384+
setupOnce = jest.fn();
385+
setup = jest.fn();
386+
}
387+
388+
const client1 = getTestClient();
389+
const client2 = getTestClient();
390+
391+
const integrationIndex = {};
392+
const integration1 = new CustomIntegration();
393+
const integration2 = new CustomIntegration();
394+
const integration3 = new CustomIntegration();
395+
const integration4 = new CustomIntegration();
396+
397+
setupIntegration(client1, integration1, integrationIndex);
398+
setupIntegration(client1, integration2, integrationIndex);
399+
setupIntegration(client2, integration3, integrationIndex);
400+
setupIntegration(client2, integration4, integrationIndex);
401+
402+
expect(integrationIndex).toEqual({ test: integration4 });
403+
expect(integration1.setupOnce).toHaveBeenCalledTimes(1);
404+
expect(integration2.setupOnce).not.toHaveBeenCalled();
405+
expect(integration3.setupOnce).not.toHaveBeenCalled();
406+
expect(integration4.setupOnce).not.toHaveBeenCalled();
407+
408+
expect(integration1.setup).toHaveBeenCalledTimes(1);
409+
expect(integration2.setup).toHaveBeenCalledTimes(1);
410+
expect(integration3.setup).toHaveBeenCalledTimes(1);
411+
expect(integration4.setup).toHaveBeenCalledTimes(1);
412+
413+
expect(integration1.setup).toHaveBeenCalledWith(client1);
414+
expect(integration2.setup).toHaveBeenCalledWith(client1);
415+
expect(integration3.setup).toHaveBeenCalledWith(client2);
416+
expect(integration4.setup).toHaveBeenCalledWith(client2);
417+
});
418+
381419
it('binds preprocessEvent for each client', () => {
382420
class CustomIntegration implements Integration {
383421
name = 'test';

packages/types/src/integration.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ export interface Integration {
2626
*/
2727
setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void;
2828

29+
/**
30+
* Set up an integration for the given client.
31+
* Receives the client as argument.
32+
*
33+
* Whenever possible, prefer this over `setupOnce`, as that is only run for the first client,
34+
* whereas `setup` runs for each client. Only truly global things (e.g. registering global handlers)
35+
* should be done in `setupOnce`.
36+
*/
37+
setup?(client: Client): void;
38+
2939
/**
3040
* An optional hook that allows to preprocess an event _before_ it is passed to all other event processors.
3141
*/

0 commit comments

Comments
 (0)