Skip to content

Commit 31d54df

Browse files
committed
refactor: init BreadcrumbStore in BrowserBreadcrumbsMessageProcessor
1 parent 9a10955 commit 31d54df

9 files changed

Lines changed: 66 additions & 81 deletions

packages/core/src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,4 @@ export { StackParser } from './modules/stack-parser';
1212
export { buildElementSelector } from './utils/selector';
1313
export { isErrorProcessed, markErrorAsProcessed } from './utils/event';
1414
export type { BreadcrumbStore, BreadcrumbsAPI, BreadcrumbHint, BreadcrumbInput } from './breadcrumbs/breadcrumb-store';
15-
export type { ErrorSnapshot, MessageProcessor, ProcessingPayload } from './messages/message-processor';
16-
export { BreadcrumbsMessageProcessor } from './messages/breadcrumbs-message-processor';
15+
export type { MessageProcessor, ProcessingPayload } from './messages/message-processor';

packages/core/src/messages/breadcrumbs-message-processor.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

packages/core/src/messages/message-processor.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,6 @@ export type ProcessingPayload<T extends CatcherMessageType> =
2121
addons: Partial<ExtractAddons<T>>;
2222
};
2323

24-
/**
25-
* Snapshot of event context captured synchronously at error time,
26-
* before any processing.
27-
*/
28-
export interface ErrorSnapshot {
29-
/**
30-
* Original caught error.
31-
*/
32-
error?: Error | string;
33-
34-
/**
35-
* Breadcrumbs captured at error time.
36-
*/
37-
breadcrumbs?: Breadcrumb[];
38-
}
39-
4024
/**
4125
* Single step in message processing pipeline before message is sent.
4226
*
@@ -49,11 +33,11 @@ export interface MessageProcessor<T extends CatcherMessageType = CatcherMessageT
4933
* Dropped message won't be sent.
5034
*
5135
* @param payload - processed event message payload with partially-built addons
52-
* @param snapshot - additional context with original error
36+
* @param error - original error
5337
* @returns modified payload, or `null` to drop message
5438
*/
5539
apply(
5640
payload: ProcessingPayload<T>,
57-
snapshot?: ErrorSnapshot,
41+
error?: Error | string,
5842
): ProcessingPayload<T> | null
5943
}

packages/javascript/src/catcher.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { ConsoleCatcher } from './addons/consoleCatcher';
1515
import { BrowserBreadcrumbStore } from './addons/breadcrumbs';
1616
import type { BreadcrumbStore, MessageProcessor, ProcessingPayload } from '@hawk.so/core';
1717
import {
18-
BreadcrumbsMessageProcessor,
1918
HawkUserManager,
2019
isErrorProcessed,
2120
isLoggerSet,
@@ -34,6 +33,7 @@ import { BrowserRandomGenerator } from './utils/random';
3433
import { BrowserAddonMessageProcessor } from './messages/browser-addon-message-processor';
3534
import { ConsoleOutputAddonMessageProcessor } from './messages/console-output-addon-message-processor';
3635
import { DebugAddonMessageProcessor } from './messages/debug-addon-message-processor';
36+
import { BrowserBreadcrumbsMessageProcessor } from './messages/browser-breadcrumbs-message-processor';
3737

3838
/**
3939
* Allow to use global VERSION, that will be overwritten by Webpack
@@ -126,7 +126,7 @@ export default class Catcher {
126126
/**
127127
* Breadcrumb store instance
128128
*/
129-
private readonly breadcrumbStore: BrowserBreadcrumbStore | null;
129+
private readonly breadcrumbStore: BrowserBreadcrumbStore | null = null;
130130

131131
/**
132132
* Manages currently authenticated user identity.
@@ -207,10 +207,7 @@ export default class Catcher {
207207
*/
208208
if (settings.breadcrumbs !== false) {
209209
this.breadcrumbStore = BrowserBreadcrumbStore.getInstance();
210-
this.breadcrumbStore.init(settings.breadcrumbs ?? {});
211-
this.messageProcessors.push(new BreadcrumbsMessageProcessor());
212-
} else {
213-
this.breadcrumbStore = null;
210+
this.messageProcessors.push(new BrowserBreadcrumbsMessageProcessor(settings.breadcrumbs ?? {}));
214211
}
215212

216213
if (this.debug) {
@@ -409,14 +406,10 @@ export default class Catcher {
409406
markErrorAsProcessed(error);
410407
}
411408

412-
const snapshot = {
413-
error,
414-
breadcrumbs: this.breadcrumbStore?.get()
415-
};
416409
let processingPayload = await this.buildBasePayload(error, context);
417410

418411
for (const processor of this.messageProcessors) {
419-
const result = processor.apply(processingPayload, snapshot);
412+
const result = processor.apply(processingPayload, error);
420413

421414
if (result === null) {
422415
return;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type { MessageProcessor, ProcessingPayload } from '@hawk.so/core';
2+
import { BreadcrumbsOptions, BrowserBreadcrumbStore } from '../addons/breadcrumbs';
3+
import { ErrorsCatcherType } from '@hawk.so/types/src/catchers/catcher-message';
4+
5+
/**
6+
* Attaches breadcrumbs to payload.
7+
*/
8+
export class BrowserBreadcrumbsMessageProcessor<T extends ErrorsCatcherType> implements MessageProcessor<T> {
9+
10+
constructor(options: BreadcrumbsOptions = {}) {
11+
const breadcrumbStore = BrowserBreadcrumbStore.getInstance();
12+
breadcrumbStore.init(options);
13+
}
14+
15+
/**
16+
* Sets `payload.breadcrumbs` from snapshot if non-empty; skips otherwise.
17+
*
18+
* @param payload - event message payload to enrich
19+
* @returns modified payload with breadcrumbs set, or original payload unchanged
20+
*/
21+
public apply(
22+
payload: ProcessingPayload<T>
23+
): ProcessingPayload<T> | null {
24+
const breadcrumbs = BrowserBreadcrumbStore.getInstance().get();
25+
if (breadcrumbs.length > 0) {
26+
payload.breadcrumbs = breadcrumbs;
27+
}
28+
29+
return payload;
30+
}
31+
}

packages/javascript/src/messages/debug-addon-message-processor.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ErrorSnapshot, MessageProcessor, ProcessingPayload } from '@hawk.so/core';
1+
import type { MessageProcessor, ProcessingPayload } from '@hawk.so/core';
22

33
/**
44
* Appends `RAW_EVENT_DATA` to the event addons for debug purposes.
@@ -9,21 +9,21 @@ export class DebugAddonMessageProcessor implements MessageProcessor<'errors/java
99
* Skips if snapshot error is missing or not Error instance.
1010
*
1111
* @param payload - event message payload to enrich
12-
* @param snapshot - snapshot carrying original caught error
12+
* @param error - original error
1313
* @returns modified payload with RAW_EVENT_DATA set, or original payload unchanged
1414
*/
1515
public apply(
1616
payload: ProcessingPayload<'errors/javascript'>,
17-
snapshot?: ErrorSnapshot
17+
error?: Error | string,
1818
): ProcessingPayload<'errors/javascript'> | null {
19-
if (!(snapshot?.error instanceof Error)) {
19+
if (!(error instanceof Error)) {
2020
return payload;
2121
}
2222

2323
payload.addons.RAW_EVENT_DATA = {
24-
name: snapshot.error.name,
25-
message: snapshot.error.message,
26-
stack: snapshot.error.stack ?? '',
24+
name: error.name,
25+
message: error.message,
26+
stack: error.stack ?? '',
2727
};
2828

2929
return payload;

packages/javascript/tests/catcher.breadcrumbs.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ describe('Catcher', () => {
1111
beforeEach(() => {
1212
localStorage.clear();
1313
mockParse.mockResolvedValue([]);
14-
(BrowserBreadcrumbStore as any).instance?.destroy();
14+
BrowserBreadcrumbStore.getInstance().clear();
15+
// (BrowserBreadcrumbStore as any).instance?.destroy();
1516
});
1617

1718
// ── Breadcrumbs trail ─────────────────────────────────────────────────────
@@ -21,7 +22,7 @@ describe('Catcher', () => {
2122
describe('breadcrumbs trail', () => {
2223
it('should include recorded breadcrumbs', async () => {
2324
const { sendSpy, transport } = createTransport();
24-
const hawk = createCatcher(transport, { breadcrumbs: {} });
25+
const hawk = createCatcher(transport, { breadcrumbs: { trackFetch: false } });
2526

2627
hawk.breadcrumbs.add({ message: 'button clicked', timestamp: Date.now() });
2728
hawk.send(new Error('e'));
@@ -36,7 +37,7 @@ describe('Catcher', () => {
3637
it('should omit breadcrumbs when none have been recorded', async () => {
3738
const { sendSpy, transport } = createTransport();
3839

39-
createCatcher(transport, { breadcrumbs: {} }).send(new Error('e'));
40+
createCatcher(transport, { breadcrumbs: { trackFetch: false } }).send(new Error('e'));
4041
await wait();
4142

4243
expect(getLastPayload(sendSpy).breadcrumbs).toBeFalsy();
@@ -50,7 +51,7 @@ describe('Catcher', () => {
5051

5152
it('should omit breadcrumbs cleared before payload was sent', async () => {
5253
const { sendSpy, transport } = createTransport();
53-
const hawk = createCatcher(transport, { breadcrumbs: {} });
54+
const hawk = createCatcher(transport, { breadcrumbs: { trackFetch: false } });
5455

5556
hawk.breadcrumbs.add({ message: 'click', timestamp: Date.now() });
5657
hawk.breadcrumbs.clear();

packages/javascript/tests/messages/breadcrumbs-message-processor.test.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
1-
import { describe, expect, it } from 'vitest';
2-
import { BreadcrumbsMessageProcessor } from '@hawk.so/core';
1+
import { beforeEach, describe, expect, it, vi } from 'vitest';
32
import { makePayload } from './message-processor.helpers';
3+
import { BrowserBreadcrumbsMessageProcessor } from '../../src/messages/browser-breadcrumbs-message-processor';
4+
import { BrowserBreadcrumbStore } from '../../src/addons/breadcrumbs';
45

56
describe('BreadcrumbsMessageProcessor', () => {
6-
const processor = new BreadcrumbsMessageProcessor();
7+
const processor = new BrowserBreadcrumbsMessageProcessor();
78

8-
it('should attach breadcrumbs from snapshot to payload', () => {
9-
const breadcrumbs = [{ message: 'click', timestamp: 1 }];
10-
11-
const result = processor.apply(makePayload(), { breadcrumbs });
12-
13-
expect(result?.breadcrumbs).toEqual(breadcrumbs);
9+
beforeEach(() => {
10+
BrowserBreadcrumbStore.getInstance().clear()
1411
});
1512

16-
it('should not set payload breadcrumbs when snapshot has empty array', () => {
17-
const result = processor.apply(makePayload(), { breadcrumbs: [] });
13+
it('should attach breadcrumbs from snapshot to payload', () => {
14+
const breadcrumbs = { message: 'click', timestamp: 1 };
15+
BrowserBreadcrumbStore.getInstance().add(breadcrumbs)
1816

19-
expect(result?.breadcrumbs).toBeUndefined();
17+
const result = processor.apply(makePayload());
18+
19+
expect(result?.breadcrumbs).toHaveLength(1)
20+
expect(result?.breadcrumbs).toContainEqual(breadcrumbs);
2021
});
2122

22-
it('should not set payload breadcrumbs when snapshot is absent', () => {
23+
it('should not set payload breadcrumbs when breadcrumb store is empty', () => {
2324
const result = processor.apply(makePayload());
2425

2526
expect(result?.breadcrumbs).toBeUndefined();

packages/javascript/tests/messages/debug-message-processor.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ describe('DebugMessageProcessor', () => {
88
it('should add RAW_EVENT_DATA when hint.error is an Error instance', () => {
99
const error = new TypeError('boom');
1010

11-
const result = processor.apply(makePayload(), { error });
11+
const result = processor.apply(makePayload(), error);
1212

1313
expect(result?.addons?.RAW_EVENT_DATA).toMatchObject({
1414
name: 'TypeError',
@@ -18,7 +18,7 @@ describe('DebugMessageProcessor', () => {
1818
});
1919

2020
it('should not add RAW_EVENT_DATA when hint.error is a string', () => {
21-
const result = processor.apply(makePayload(), { error: 'string reason' });
21+
const result = processor.apply(makePayload(), 'string reason');
2222

2323
expect(result?.addons?.RAW_EVENT_DATA).toBeUndefined();
2424
});

0 commit comments

Comments
 (0)