Skip to content

Commit

Permalink
feat: Add __spotlight.initOptions and initialEvents (#515)
Browse files Browse the repository at this point in the history
  • Loading branch information
BYK authored Sep 10, 2024
1 parent f1bcab3 commit 5b6dbba
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 17 deletions.
8 changes: 8 additions & 0 deletions .changeset/ten-comics-guess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@spotlightjs/overlay': minor
'@spotlightjs/spotlight': minor
---

Add `__spotlight.initOptions` and initialEvents support allowing providing a list of "initial events" when Spotlight
loads, not requiring the sidecar to be working. Mostly going to be used when replacing default error pages in
frameworks.
14 changes: 12 additions & 2 deletions packages/overlay/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import type { NotificationCount, SpotlightOverlayOptions } from './types';
type AppProps = Omit<SpotlightOverlayOptions, 'debug' | 'injectImmediately'> &
Required<Pick<SpotlightOverlayOptions, 'sidecarUrl'>>;

type EventData = { contentType: string; data: string | Uint8Array };

export default function App({
openOnInit = false,
showTriggerButton = true,
Expand All @@ -21,6 +23,7 @@ export default function App({
anchor,
fullPage = false,
showClearEventsButton = true,
initialEvents = {},
}: AppProps) {
const [integrationData, setIntegrationData] = useState<IntegrationData<unknown>>({});
const [isOnline, setOnline] = useState(false);
Expand Down Expand Up @@ -141,7 +144,6 @@ export default function App({
navigate(e.detail);
};

type EventData = { contentType: string; data: string };
const dispatchToContentTypeListener = ({ contentType, data }: EventData) => {
const listener = contentTypeListeners[contentType];
if (!listener) {
Expand All @@ -163,8 +165,16 @@ export default function App({
}
});

// Populate from initial events
for (const contentType in initialEvents) {
log(`Injecting initial events for ${contentType}`);
for (const data of initialEvents[contentType]) {
dispatchToContentTypeListener({ contentType, data });
}
}

return { clearEvents, onEvent, onOpen, onClose, onNavigate, onToggle };
}, [integrations, navigate, sidecarUrl, contentTypeListeners]);
}, [integrations, navigate, sidecarUrl, contentTypeListeners, initialEvents]);

useKeyPress('F12', ['ctrlKey'], eventHandlers.onToggle);

Expand Down
30 changes: 17 additions & 13 deletions packages/overlay/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export async function onClose(cb: EventListener) {
/**
* Send an event to spotlight without the sidecar
*/
export async function sendEvent(contentType: string, data: string) {
export async function sendEvent(contentType: string, data: string | Uint8Array) {
trigger('event', { contentType, data });
}

Expand Down Expand Up @@ -88,18 +88,21 @@ function isSpotlightInjected() {
return false;
}

export async function init({
openOnInit = false,
showTriggerButton = true,
injectImmediately = false,
sidecarUrl = DEFAULT_SIDECAR_URL,
anchor = DEFAULT_ANCHOR,
debug = false,
integrations,
experiments = DEFAULT_EXPERIMENTS,
fullPage = false,
showClearEventsButton = true,
}: SpotlightOverlayOptions = {}) {
export async function init(
{
openOnInit = false,
showTriggerButton = true,
injectImmediately = false,
sidecarUrl = DEFAULT_SIDECAR_URL,
anchor = DEFAULT_ANCHOR,
debug = false,
integrations,
experiments = DEFAULT_EXPERIMENTS,
fullPage = false,
showClearEventsButton = true,
initialEvents = undefined,
}: SpotlightOverlayOptions = (window as WindowWithSpotlight).__spotlight?.initOptions || {},
) {
// The undefined document guard is to avoid being initialized in a Worker
// @see https://github.com/vitejs/vite/discussions/17644#discussioncomment-10026390
if (typeof document === 'undefined') return;
Expand Down Expand Up @@ -173,6 +176,7 @@ export async function init({
anchor={anchor}
fullPage={fullPage}
showClearEventsButton={showClearEventsButton}
initialEvents={initialEvents}
/>
</SpotlightContextProvider>
</MemoryRouter>,
Expand Down
12 changes: 10 additions & 2 deletions packages/overlay/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type Integration } from './integrations/integration';
import type { Integration } from './integrations/integration';

export type ExperimentName = 'sentry:focus-local-events';

Expand Down Expand Up @@ -86,7 +86,7 @@ export type SpotlightOverlayOptions = {
/**
* If set to `true`, the Spotlight overlay will be rendered in full page mode.
* It can't be closed nor minimized.
* This is useful for replaceing error page or in when directly rendered as an html page
* This is useful for replacing error page or in when directly rendered as an html page
*/
fullPage?: boolean;

Expand All @@ -97,6 +97,13 @@ export type SpotlightOverlayOptions = {
* @default true
*/
showClearEventsButton?: boolean;

/**
* Events to be sent into Spotlight (bypassing the sidecar) right after init
*
* This is useful when replacing error pages of frameworks etc. Implies "injectImmediately".
*/
initialEvents?: Record<string, (string | Uint8Array)[]>;
};

export type NotificationCount = {
Expand All @@ -115,5 +122,6 @@ export type NotificationCount = {
export type WindowWithSpotlight = Window & {
__spotlight?: {
eventTarget?: EventTarget;
initOptions?: SpotlightOverlayOptions;
};
};

0 comments on commit 5b6dbba

Please sign in to comment.