Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): Ensure there's only one global spotlight event target #121

Merged
merged 2 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/spotty-seahorses-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@spotlightjs/core': patch
---

fix(core): Ensure there's only one global spotlight event target
5 changes: 3 additions & 2 deletions packages/core/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import { useEffect, useState } from 'react';
import Debugger from './components/Debugger';
import Trigger, { type Anchor } from './components/Trigger';
import type { Integration, IntegrationData } from './integrations/integration';
import { getSpotlightEventTarget } from './lib/eventTarget';
import { connectToSidecar } from './sidecar';
import { TriggerButtonCount } from './types';

import spotlightEventTarget from './lib/eventTarget';

type AppProps = {
fullScreen?: boolean;
showTriggerButton?: boolean;
Expand Down Expand Up @@ -58,6 +57,8 @@ export default function App({
};
}, [integrations, sidecar]);

const spotlightEventTarget = getSpotlightEventTarget();

useEffect(() => {
const onOpen = () => {
console.log('[Spotlight] Open');
Expand Down
12 changes: 5 additions & 7 deletions packages/core/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import ReactDOM from 'react-dom/client';

import fontStyles from '@fontsource/raleway/index.css?inline';
import spotlightEventTarget from './lib/eventTarget.ts';

import App from './App.tsx';
import { DEFAULT_ANCHOR, type Anchor } from './components/Trigger.tsx';
import globalStyles from './index.css?inline';
import { default as sentry } from './integrations/console/index.ts';
import type { Integration } from './integrations/integration.ts';
import { initIntegrations } from './integrations/integration.ts';
import { getSpotlightEventTarget } from './lib/eventTarget.ts';
import { WindowWithSpotlight } from './types.ts';

export { default as console } from './integrations/console/index.ts';
Expand All @@ -25,21 +25,21 @@ function createStyleSheet(styles: string) {
* Open the Spotlight debugger Window
*/
export async function openSpotlight() {
spotlightEventTarget.dispatchEvent(new CustomEvent('open'));
getSpotlightEventTarget().dispatchEvent(new CustomEvent('open'));
}

/**
* Close the Spotlight debugger Window
*/
export async function closeSpotlight() {
spotlightEventTarget.dispatchEvent(new CustomEvent('close'));
getSpotlightEventTarget().dispatchEvent(new CustomEvent('close'));
}

/**
* Invokes the passed in callback when the Spotlight debugger Window is closed
*/
export async function onClose(cb: () => void) {
spotlightEventTarget.addEventListener('closed', cb);
getSpotlightEventTarget().addEventListener('closed', cb);
}

const DEFAULT_SIDECAR = 'http://localhost:8969/stream';
Expand Down Expand Up @@ -67,7 +67,7 @@ export async function init({
// We only want to intialize and inject spotlight once. If it's already
// been initialized, we can just bail out.
const windowWithSpotlight = window as WindowWithSpotlight;
if (windowWithSpotlight.__spotlight_initialized) {
if (windowWithSpotlight.__spotlight) {
return;
}

Expand Down Expand Up @@ -118,6 +118,4 @@ export async function init({
injectSpotlight();
});
}

windowWithSpotlight.__spotlight_initialized = true;
}
34 changes: 33 additions & 1 deletion packages/core/src/lib/eventTarget.ts
Original file line number Diff line number Diff line change
@@ -1 +1,33 @@
export default new EventTarget();
import { WindowWithSpotlight } from '~/types';

const fallbackEventTarget = new EventTarget();

/**
* Returns the global singleton event target for spotlight.
*
* This is used to communicate between spotlight and the outside world.
* To avoid instances where multiple versions of spotlight code are loaded,
* we put the target onto the global object.
*
* @see https://github.com/getsentry/spotlight/issues/68
*
* In case of window being undefined (e.g. in SSR), we return a fallback event target.
* which is local to one spotlight code instance.
*/
export function getSpotlightEventTarget(): EventTarget {
if (typeof window === 'undefined') {
return fallbackEventTarget;
}

const windowWithSpotlight = window as WindowWithSpotlight;

if (!windowWithSpotlight.__spotlight) {
windowWithSpotlight.__spotlight = {};
}

if (!windowWithSpotlight.__spotlight.eventTarget) {
windowWithSpotlight.__spotlight.eventTarget = new EventTarget();
}

return windowWithSpotlight.__spotlight.eventTarget;
}
4 changes: 3 additions & 1 deletion packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ export type TriggerButtonCount = {
};

export type WindowWithSpotlight = Window & {
__spotlight_initialized?: boolean;
__spotlight?: {
eventTarget?: EventTarget;
};
};