diff --git a/package.json b/package.json index 7726780d..79c03277 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ }, "devDependencies": { "@cloudflare/workers-types": "^3.14.0", + "@sentry/types": "^7.10.0", "@types/jest": "^28.1.4", "@typescript-eslint/eslint-plugin": "^5.32.0", "@typescript-eslint/parser": "^5.32.0", @@ -58,4 +59,4 @@ "ts-jest": "^28.0.5", "typescript": "^4.7.4" } -} +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index a62ee427..b2b9564b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,15 +1,39 @@ +import type { Options as SentryOptions, StackFrame } from '@sentry/types' import type { Handler } from 'hono' import Toucan from 'toucan-js' -export const sentry = (): Handler => { +export type RewriteFrames = { + root?: string + iteratee?: (frame: StackFrame) => StackFrame +} + +type Options = { + dsn?: SentryOptions['dsn'] + allowedCookies?: string[] | RegExp + allowedHeaders?: string[] | RegExp + allowedSearchParams?: string[] | RegExp + attachStacktrace?: SentryOptions['attachStacktrace'] + debug?: SentryOptions['debug'] + environment?: SentryOptions['environment'] + maxBreadcrumbs?: SentryOptions['maxBreadcrumbs'] + pkg?: Record + release?: SentryOptions['release'] + rewriteFrames?: RewriteFrames +} + +export const sentry = (options?: Options, callback?: (sentry: Toucan) => void): Handler => { return async (c, next) => { const sentry = new Toucan({ dsn: c.env.SENTRY_DSN || c.env.NEXT_PUBLIC_SENTRY_DSN, - request: c.req, allowedHeaders: ['user-agent'], allowedSearchParams: /(.*)/, + request: c.req, + context: c.executionCtx, + ...options, }) + if (callback) callback(sentry) + try { await next() } catch (error) { diff --git a/test/index.test.ts b/test/index.test.ts index 07272036..ed31ef56 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,6 +1,16 @@ import { Hono } from 'hono' import { sentry } from '../src' +// Mock +class Context implements ExecutionContext { + passThroughOnException(): void { + throw new Error('Method not implemented.') + } + async waitUntil(promise: Promise): Promise { + await promise + } +} + const captureException = jest.fn() jest.mock('toucan-js', () => jest.fn().mockImplementation(() => ({ captureException }))) @@ -14,13 +24,15 @@ describe('Sentry middleware', () => { }) it('Should initialize Toucan', async () => { - const res = await app.request('http://localhost/sentry/foo') + const req = new Request('http://localhost/sentry/foo') + const res = await app.fetch(req, {}, new Context()) expect(res).not.toBeNull() expect(res.status).toBe(200) }) it('Should report errors', async () => { - const res = await app.request('http://localhost/sentry/error') + const req = new Request('http://localhost/sentry/error') + const res = await app.fetch(req, {}, new Context()) expect(res).not.toBeNull() expect(res.status).toBe(500) expect(captureException).toHaveBeenCalled() diff --git a/yarn.lock b/yarn.lock index 9f3c83f8..eb99b03d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -892,6 +892,11 @@ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.19.6.tgz#70513f9dca05d23d7ab9c2a6cb08d4db6763ca67" integrity sha512-QH34LMJidEUPZK78l+Frt3AaVFJhEmIi05Zf8WHd9/iTt+OqvCHBgq49DDr1FWFqyYWm/QgW/3bIoikFpfsXyQ== +"@sentry/types@^7.10.0": + version "7.10.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.10.0.tgz#c91d634768336238ac30ed750fa918326c384cbb" + integrity sha512-1UBwdbS0xXzANzp63g4eNQly/qKIXp0swP5OTKWoADvKBtL4anroLUA/l8ADMtuwFZYtVANc8WRGxM2+YmaXtg== + "@sentry/utils@6.19.6": version "6.19.6" resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.19.6.tgz#2ddc9ef036c3847084c43d0e5a55e4646bdf9021"