Skip to content
Draft
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
3 changes: 2 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@hawk.so/core",
"version": "1.0.0",
"description": "Base implementation for all Hawk.so SDKs",
"description": "Core error tracking logic for Hawk.so catchers",
"files": [
"dist"
],
Expand Down Expand Up @@ -34,6 +34,7 @@
},
"homepage": "https://github.com/codex-team/hawk.javascript#readme",
"devDependencies": {
"@hawk.so/types": "0.5.8",
"vite": "^7.3.1",
"vite-plugin-dts": "^4.2.4"
}
Expand Down
243 changes: 243 additions & 0 deletions packages/core/src/catcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
import { AffectedUser, EventContext, Json } from "@hawk.so/types";

Check warning on line 1 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote

Check failure on line 1 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

All imports in the declaration are only used as types. Use `import type`
import { validateContext, validateUser } from "./utils/validation";

Check warning on line 2 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote
import { Logger, LogType } from "./utils/log";

Check warning on line 3 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote

Check failure on line 3 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

'LogType' is defined but never used. Allowed unused vars must match /^_/u

Check failure on line 3 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Import "Logger" is only used as types
import { HawkInitialSettings } from "./types/base-hawk-settings";

Check warning on line 4 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote

Check failure on line 4 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

All imports in the declaration are only used as types. Use `import type`
import { HawkJavaScriptEvent } from "./types/event";

Check warning on line 5 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote

Check failure on line 5 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

All imports in the declaration are only used as types. Use `import type`
import Sanitizer from "./modules/sanitizer";

Check warning on line 6 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote
import { Transport } from "./types/transport";

Check warning on line 7 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote

Check failure on line 7 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

All imports in the declaration are only used as types. Use `import type`
import { UserManager } from "./types/user-manager";

Check warning on line 8 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote

Check failure on line 8 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

All imports in the declaration are only used as types. Use `import type`
import { isErrorProcessed, markErrorAsProcessed } from "./utils/event";

Check warning on line 9 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote
import { CatcherMessage } from "./types/catcher-message";

Check warning on line 10 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote

Check failure on line 10 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

All imports in the declaration are only used as types. Use `import type`
import log from "@hawk.so/javascript/dist/utils/log";
import { EventRejectedError } from "./errors";

export abstract class BaseCatcher {

/**
* Catcher Type
*/
protected readonly type: string;

/**
* Current bundle version
*/
private readonly release: string | undefined;

/**
* Any additional data passed by user for sending with all messages
*/
private context: EventContext | undefined;

/**
* Transport for dialog between Catcher and Collector
* (WebSocket decorator by default, or custom via settings.transport)
*/
private readonly transport: Transport;

/**
* Current authenticated user manager
*/
private readonly userManager: UserManager;

/**
* Logger function
*/
private readonly log: Logger;

constructor(
settings: HawkInitialSettings,
) {
this.release = settings.release;
this.userManager = settings.userManager;
this.log = (settings.logger ?? (() => {
})) as Logger;
}

/**
* Send test event from client
*/
public test(): void {
const fakeEvent = new Error('Hawk JavaScript Catcher test message.');

this.send(fakeEvent);
}

/**
* Public method for manual sending messages to the Hawk
* Can be called in user's try-catch blocks or by other custom logic
*
* @param message - what to send
* @param [context] - any additional data to send
*/
public send(message: Error | string, context?: EventContext): void {
void this.formatAndSend(message, context);
}

/**
* Format and send an error
*
* @param error - error to send
* @param integrationAddons - addons spoiled by Integration
* @param context - any additional data passed by user
*/
protected async formatAndSend(
error: Error | string,
context?: EventContext
): Promise<void> {
try {
const isAlreadySentError = isErrorProcessed(error);

if (isAlreadySentError) {
/**
* @todo add debug build and log this case
*/
return;
} else {
markErrorAsProcessed(error, this.log);
}

const errorFormatted = await this.prepareErrorFormatted(error, context);

this.sendErrorFormatted(errorFormatted);
} catch (e) {
if (e instanceof EventRejectedError) {
/**
* Event was rejected by user
*/
return;
}

log('Unable to send error. Seems like it is Hawk internal bug. Please, report it here: https://github.com/codex-team/hawk.javascript/issues/new', 'warn', e);
}
}

/**
* Sends formatted HawkEvent to the Collector
*
* @param errorFormatted - formatted error to send
*/
private sendErrorFormatted(errorFormatted: CatcherMessage): void {
this.transport.send(errorFormatted)
.catch((sendingError) => {
log('Transport sending error', 'error', sendingError);
});
}

/**
* Formats the event
*
* @param error - error to format
* @param context - any additional data passed by user
*/
abstract async prepareErrorFormatted(error: Error | string, context?: EventContext): Promise<CatcherMessage>

Check failure on line 132 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Missing semicolon

Check failure on line 132 in packages/core/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Missing accessibility modifier on method definition prepareErrorFormatted

/**
* Update the current user information
*
* @param user - New user information
*/
public setUser(user: AffectedUser): void {
if (!validateUser(user, this.log)) {
return;
}

this.userManager.setUser(user);
}

/**
* Update the context data that will be sent with all events
*
* @param context - New context data
*/
public setContext(context: EventContext | undefined): void {
if (!validateContext(context, this.log)) {
return;
}

this.context = context;
}

/**
* Return event type: TypeError, ReferenceError etc
*
* @param error - caught error
*/
protected getType(error: Error | string): HawkJavaScriptEvent['type'] {
if (!(error instanceof Error)) {
return null;
}

return error.name;
}

/**
* Release version
*/
protected getRelease(): HawkJavaScriptEvent['release'] {
return this.release !== undefined ? String(this.release) : null;
}

/**
* Current authenticated user
*/
protected getUser(): HawkJavaScriptEvent['user'] {
return this.userManager.getUser();
}

/**
* Collects additional information
*
* @param context - any additional data passed by user
*/
protected getContext(context?: EventContext): HawkJavaScriptEvent['context'] {
const contextMerged = {};

if (this.context !== undefined) {
Object.assign(contextMerged, this.context);
}

if (context !== undefined) {
Object.assign(contextMerged, context);
}

return Sanitizer.sanitize(contextMerged);
}

/**
* Compose raw data object
*
* @param {Error|string} error — caught error
*/
protected getRawData(error: Error | string): Json | undefined {
if (!(error instanceof Error)) {
return;
}

const stack = error.stack !== undefined ? error.stack : '';

return {
name: error.name,
message: error.message,
stack,
};
}

/**
* Return event title
*
* @param error - event from which to get the title
*/
protected getTitle(error: Error | string): string {
const notAnError = !(error instanceof Error);

/**
* Case when error is 'reason' of PromiseRejectionEvent
* and reject() provided with text reason instead of Error()
*/
if (notAnError) {
return error.toString() as string;
}

return (error as Error).message;
}
}
12 changes: 12 additions & 0 deletions packages/core/src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Error triggered when event was rejected by beforeSend method
*/
export class EventRejectedError extends Error {
/**
* @param message - error message
*/
constructor(message: string) {
super(message);
this.name = 'EventRejectedError';
}
}
Loading
Loading