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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"version": "0.0.0",
"packageManager": "yarn@4.12.0",
"workspaces": [
"packages/core",
"packages/javascript",
"packages/sveltekit",
"packages/sveltekit/playground"
Expand Down
40 changes: 40 additions & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "@hawk.so/core",
"version": "1.0.0",
"description": "Base implementation for all Hawk.so SDKs",
"files": [
"dist"
],
"main": "./dist/hawk-core.umd.js",
"module": "./dist/hawk-core.mjs",
"types": "dist/index.d.ts",
"exports": {
".": {
"source": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/hawk-core.mjs",
"require": "./dist/hawk-core.umd.js"
}
},
"scripts": {
"build": "vite build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/codex-team/hawk.javascript.git",
"directory": "packages/core"
},
"author": {
"name": "CodeX",
"email": "team@codex.so"
},
"license": "AGPL-3.0-only",
"bugs": {
"url": "https://github.com/codex-team/hawk.javascript/issues"
},
"homepage": "https://github.com/codex-team/hawk.javascript#readme",
"devDependencies": {
"vite": "^7.3.1",
"vite-plugin-dts": "^4.2.4"
}
}
3 changes: 3 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type { HawkStorage } from './types/storage';
export type { UserManager } from './types/user-manager';
export { StorageUserManager } from './types/storage-user-manager';
63 changes: 63 additions & 0 deletions packages/core/src/types/storage-user-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { AffectedUser } from "@hawk.so/types";

Check warning on line 1 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote

Check failure on line 1 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

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

Check warning on line 2 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote
import { HawkStorage } from "./storage";

Check warning on line 3 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote

Check failure on line 3 in packages/core/src/types/storage-user-manager.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 "./user-manager";

Check warning on line 4 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote

Check failure on line 4 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

All imports in the declaration are only used as types. Use `import type`

/**
* Storage key used to persist the user identifier.
*/
const HAWK_USER_STORAGE_KEY = 'hawk-user-id';

/**
* {@link UserManager} implementation that persists the affected user
* via an injected {@link HawkStorage} backend.
*/
export class StorageUserManager implements UserManager {

Check warning on line 15 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Block must not be padded by blank lines

/**
* Underlying storage used to read and write the user identifier.
*/
private readonly storage: HawkStorage;

/**
* @param storage - Storage backend to use for persistence.
*/
constructor(storage: HawkStorage) {
this.storage = storage;
}

/**
* Returns the stored user if one exists. Otherwise, generates a new identifier,
* saves it in storage under {@linkcode HAWK_USER_STORAGE_KEY}, and returns the new user.
*/
getUser(): AffectedUser {

Check failure on line 33 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Missing accessibility modifier on method definition getUser
const storedId = this.storage.getItem(HAWK_USER_STORAGE_KEY);
if (storedId) {

Check warning on line 35 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Expected blank line before this statement
return {
id: storedId,
};
}

const userId = id()

Check failure on line 41 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Missing semicolon
this.storage.setItem(HAWK_USER_STORAGE_KEY, userId);

Check warning on line 42 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Expected blank line before this statement
return {

Check warning on line 43 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Expected blank line before this statement
id: userId

Check warning on line 44 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Missing trailing comma
};
}

/**
* Persists the given user's identifier in storage.
*
* @param user - The affected user to store.
*/
setUser(user: AffectedUser): void {

Check failure on line 53 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Missing accessibility modifier on method definition setUser
this.storage.setItem(HAWK_USER_STORAGE_KEY, user.id);
}

/**
* Removes the stored user identifier from storage.
*/
clear(): void {

Check failure on line 60 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Missing accessibility modifier on method definition clear
this.storage.removeItem(HAWK_USER_STORAGE_KEY)

Check failure on line 61 in packages/core/src/types/storage-user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

Missing semicolon
}
}
27 changes: 27 additions & 0 deletions packages/core/src/types/storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Abstract key–value storage contract used by Hawk internals
* (e.g. {@link StorageUserManager}) to persist data across sessions.

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

View workflow job for this annotation

GitHub Actions / lint

The type 'StorageUserManager' is undefined
*/
export interface HawkStorage {
/**
* Returns the value associated with the given key, or `null` if none exists.
*
* @param key - Storage key to look up.
*/
getItem(key: string): string | null

/**
* Persists a value under the given key.
*
* @param key - Storage key.
* @param value - Value to store.
*/
setItem(key: string, value: string): void

/**
* Removes the entry for the given key.
*
* @param key - Storage key to remove.
*/
removeItem(key: string): void
}
26 changes: 26 additions & 0 deletions packages/core/src/types/user-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { AffectedUser } from "@hawk.so/types";

Check failure on line 1 in packages/core/src/types/user-manager.ts

View workflow job for this annotation

GitHub Actions / lint

All imports in the declaration are only used as types. Use `import type`

/**
* Contract for user identity managers.
*
* Implementations are responsible for persisting and retrieving the
* {@link AffectedUser} that is attached to every error report sent by the catcher.
*/
export interface UserManager {
/**
* Returns the current affected user, creating one if none exists yet.
*/
getUser(): AffectedUser

/**
* Replaces the stored user with the provided one.
*
* @param user - The affected user to persist.
*/
setUser(user: AffectedUser): void

/**
* Removes any previously stored user data.
*/
clear(): void
}
File renamed without changes.
10 changes: 10 additions & 0 deletions packages/core/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": [
"src/**/*"
]
}
22 changes: 22 additions & 0 deletions packages/core/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import path from 'path';
import dts from 'vite-plugin-dts';
import { defineConfig } from 'vite';

export default defineConfig(() => {
return {
build: {
copyPublicDir: false,
lib: {
entry: path.resolve(__dirname, 'src', 'index.ts'),
name: 'HawkCore',
fileName: 'hawk-core',
},
},

plugins: [
dts({
tsconfigPath: './tsconfig.json',
}),
],
};
});
1 change: 1 addition & 0 deletions packages/javascript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
},
"homepage": "https://github.com/codex-team/hawk.javascript#readme",
"dependencies": {
"@hawk.so/core": "workspace:^",
"error-stack-parser": "^2.1.4"
},
"devDependencies": {
Expand Down
48 changes: 15 additions & 33 deletions packages/javascript/src/catcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import StackParser from './modules/stackParser';
import type { CatcherMessage, HawkInitialSettings, BreadcrumbsAPI, Transport } from './types';
import { VueIntegration } from './integrations/vue';
import { id } from './utils/id';
import type {
AffectedUser,
EventContext,
Expand All @@ -19,6 +18,8 @@
import { ConsoleCatcher } from './addons/consoleCatcher';
import { BreadcrumbManager } from './addons/breadcrumbs';
import { validateUser, validateContext, isValidEventPayload } from './utils/validation';
import { StorageUserManager, UserManager } from "@hawk.so/core";

Check failure on line 21 in packages/javascript/src/catcher.ts

View workflow job for this annotation

GitHub Actions / lint

Import "UserManager" is only used as types
import { HawkLocalStorage } from "./modules/local-storage";

/**
* Allow to use global VERSION, that will be overwritten by Webpack
Expand Down Expand Up @@ -62,11 +63,6 @@
*/
private readonly release: string | undefined;

/**
* Current authenticated user
*/
private user: AffectedUser;

/**
* Any additional data passed by user for sending with all messages
*/
Expand Down Expand Up @@ -111,6 +107,11 @@
*/
private readonly breadcrumbManager: BreadcrumbManager | null;

/**
* Current authenticated user manager instance
*/
private readonly userManager: UserManager = new StorageUserManager(new HawkLocalStorage());

/**
* Catcher constructor
*
Expand All @@ -126,7 +127,9 @@
this.token = settings.token;
this.debug = settings.debug || false;
this.release = settings.release !== undefined ? String(settings.release) : undefined;
this.setUser(settings.user || Catcher.getGeneratedUser());
if (settings.user) {
this.setUser(settings.user);
}
this.setContext(settings.context || undefined);
this.beforeSend = settings.beforeSend;
this.disableVueErrorHandler =
Expand Down Expand Up @@ -189,27 +192,6 @@
}
}

/**
* Generates user if no one provided via HawkCatcher settings
* After generating, stores user for feature requests
*/
private static getGeneratedUser(): AffectedUser {
let userId: string;
const LOCAL_STORAGE_KEY = 'hawk-user-id';
const storedId = localStorage.getItem(LOCAL_STORAGE_KEY);

if (storedId) {
userId = storedId;
} else {
userId = id();
localStorage.setItem(LOCAL_STORAGE_KEY, userId);
}

return {
id: userId,
};
}

/**
* Send test event from client
*/
Expand Down Expand Up @@ -272,14 +254,14 @@
return;
}

this.user = user;
this.userManager.setUser(user);
}

/**
* Clear current user information (revert to generated user)
* Clear current user information
*/
public clearUser(): void {
this.user = Catcher.getGeneratedUser();
this.userManager.clear()
}

/**
Expand Down Expand Up @@ -533,7 +515,7 @@
private getIntegrationId(): string {
try {
const decodedIntegrationToken: DecodedIntegrationToken = JSON.parse(atob(this.token));
const { integrationId } = decodedIntegrationToken;
const {integrationId} = decodedIntegrationToken;

if (!integrationId || integrationId === '') {
throw new Error();
Expand Down Expand Up @@ -568,7 +550,7 @@
* Current authenticated user
*/
private getUser(): HawkJavaScriptEvent['user'] {
return this.user || null;
return this.userManager.getUser();
}

/**
Expand Down
21 changes: 21 additions & 0 deletions packages/javascript/src/modules/local-storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { HawkStorage } from "@hawk.so/core";

/**
* {@link HawkStorage} implementation backed by the browser's {@linkcode localStorage}.
*/
export class HawkLocalStorage implements HawkStorage {
/** @inheritDoc */
public getItem(key: string): string | null {
return localStorage.getItem(key);
}

/** @inheritDoc */
public setItem(key: string, value: string): void {
localStorage.setItem(key, value);
}

/** @inheritDoc */
public removeItem(key: string): void {
localStorage.removeItem(key);
}
}
1 change: 1 addition & 0 deletions packages/javascript/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default defineConfig(() => {
fileName: 'hawk',
},
rollupOptions: {
external: ['@hawk.so/core'],
plugins: [
license({
thirdParty: {
Expand Down
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -576,10 +576,20 @@ __metadata:
languageName: node
linkType: hard

"@hawk.so/core@workspace:^, @hawk.so/core@workspace:packages/core":
version: 0.0.0-use.local
resolution: "@hawk.so/core@workspace:packages/core"
dependencies:
vite: "npm:^7.3.1"
vite-plugin-dts: "npm:^4.2.4"
languageName: unknown
linkType: soft

"@hawk.so/javascript@npm:^3.0.0, @hawk.so/javascript@workspace:packages/javascript":
version: 0.0.0-use.local
resolution: "@hawk.so/javascript@workspace:packages/javascript"
dependencies:
"@hawk.so/core": "workspace:^"
"@hawk.so/types": "npm:0.5.8"
error-stack-parser: "npm:^2.1.4"
jsdom: "npm:^28.0.0"
Expand Down
Loading