From 2222f73280a56d8cfe691025dd3d934ce8a108a3 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Wed, 3 Aug 2022 17:00:44 -0500 Subject: [PATCH 01/19] Add Toucan package --- package.json | 5 ++- src/index.ts | 3 +- test/index.test.ts | 4 +- yarn.lock | 108 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 112 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index d91b9511..7726780d 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "access": "public" }, "dependencies": { - "hono": "^2.0.6" + "hono": "^2.0.6", + "toucan-js": "^2.6.1" }, "devDependencies": { "@cloudflare/workers-types": "^3.14.0", @@ -57,4 +58,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 b4f43c99..116a1866 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,7 @@ import type { Handler } from 'hono' -export const hello = (message: string = 'Hello'): Handler => { +export const hello = (): Handler => { return async (c, next) => { await next() - c.res.headers.append('X-Message', message) } } diff --git a/test/index.test.ts b/test/index.test.ts index fdf360a4..23a79984 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -7,20 +7,18 @@ describe('Hello middleware', () => { app.use('/hello/*', hello()) app.get('/hello/foo', (c) => c.text('foo')) - app.use('/x/*', hello('X')) + app.use('/x/*', hello()) app.get('/x/foo', (c) => c.text('foo')) it('Should be hello message', async () => { const res = await app.request('http://localhost/hello/foo') expect(res).not.toBeNull() expect(res.status).toBe(200) - expect(res.headers.get('X-Message')).toBe('Hello') }) it('Should be X', async () => { const res = await app.request('http://localhost/x/foo') expect(res).not.toBeNull() expect(res.status).toBe(200) - expect(res.headers.get('X-Message')).toBe('X') }) }) diff --git a/yarn.lock b/yarn.lock index ef6f1b92..9f3c83f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -858,6 +858,48 @@ tiny-glob "^0.2.9" tslib "^2.4.0" +"@sentry/core@6.19.6": + version "6.19.6" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.19.6.tgz#7d4649d0148b5d0be1358ab02e2f869bf7363e9a" + integrity sha512-biEotGRr44/vBCOegkTfC9rwqaqRKIpFljKGyYU6/NtzMRooktqOhjmjmItNCMRknArdeaQwA8lk2jcZDXX3Og== + dependencies: + "@sentry/hub" "6.19.6" + "@sentry/minimal" "6.19.6" + "@sentry/types" "6.19.6" + "@sentry/utils" "6.19.6" + tslib "^1.9.3" + +"@sentry/hub@6.19.6": + version "6.19.6" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.19.6.tgz#ada83ceca0827c49534edfaba018221bc1eb75e1" + integrity sha512-PuEOBZxvx3bjxcXmWWZfWXG+orojQiWzv9LQXjIgroVMKM/GG4QtZbnWl1hOckUj7WtKNl4hEGO2g/6PyCV/vA== + dependencies: + "@sentry/types" "6.19.6" + "@sentry/utils" "6.19.6" + tslib "^1.9.3" + +"@sentry/minimal@6.19.6": + version "6.19.6" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.19.6.tgz#b6cced3708e25d322039e68ebdf8fadfa445bf7d" + integrity sha512-T1NKcv+HTlmd8EbzUgnGPl4ySQGHWMCyZ8a8kXVMZOPDzphN3fVIzkYzWmSftCWp0rpabXPt9aRF2mfBKU+mAQ== + dependencies: + "@sentry/hub" "6.19.6" + "@sentry/types" "6.19.6" + tslib "^1.9.3" + +"@sentry/types@6.19.6": + version "6.19.6" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.19.6.tgz#70513f9dca05d23d7ab9c2a6cb08d4db6763ca67" + integrity sha512-QH34LMJidEUPZK78l+Frt3AaVFJhEmIi05Zf8WHd9/iTt+OqvCHBgq49DDr1FWFqyYWm/QgW/3bIoikFpfsXyQ== + +"@sentry/utils@6.19.6": + version "6.19.6" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.19.6.tgz#2ddc9ef036c3847084c43d0e5a55e4646bdf9021" + integrity sha512-fAMWcsguL0632eWrROp/vhPgI7sBj/JROWVPzpabwVkm9z3m1rQm6iLFn4qfkZL8Ozy6NVZPXOQ7EXmeU24byg== + dependencies: + "@sentry/types" "6.19.6" + tslib "^1.9.3" + "@sinclair/typebox@^0.23.3": version "0.23.5" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.23.5.tgz#93f7b9f4e3285a7a9ade7557d9a8d36809cbc47d" @@ -915,6 +957,11 @@ resolved "https://registry.yarnpkg.com/@types/comment-json/-/comment-json-1.1.1.tgz#b4ae889912a93e64619f97989aecaff8ce889dca" integrity sha512-U70oEqvnkeSSp8BIJwJclERtT13rd9ejK7XkIzMCQQePZe3VW1b7iQggXyW4ZvfGtGeXD0pZw24q5iWNe++HqQ== +"@types/cookie@0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.5.0.tgz#14ebcd209f2555e341548c31128d4deb34dfb2b0" + integrity sha512-CJWHVHHupxBYfIlMM+qzXx4dRKIV1VzOm0cP3Wpqten8MDx1tK+y92YDXUshN1ONAfwodvKxDNkw35/pNs+izg== + "@types/graceful-fs@^4.1.3": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" @@ -1419,6 +1466,11 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + cookie@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" @@ -1582,6 +1634,13 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error-stack-parser@^2.0.6: + version "2.1.4" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" + integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== + dependencies: + stackframe "^1.3.4" + es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5: version "1.20.1" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" @@ -3534,6 +3593,11 @@ source-map-support@^0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA== + source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -3544,6 +3608,13 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +stack-generator@^2.0.5: + version "2.0.10" + resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.10.tgz#8ae171e985ed62287d4f1ed55a1633b3fb53bb4d" + integrity sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ== + dependencies: + stackframe "^1.3.4" + stack-trace@0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" @@ -3556,6 +3627,28 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +stackframe@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" + integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== + +stacktrace-gps@^3.0.4: + version "3.1.2" + resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz#0c40b24a9b119b20da4525c398795338966a2fb0" + integrity sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ== + dependencies: + source-map "0.5.6" + stackframe "^1.3.4" + +stacktrace-js@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b" + integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg== + dependencies: + error-stack-parser "^2.0.6" + stack-generator "^2.0.5" + stacktrace-gps "^3.0.4" + streamsearch@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" @@ -3727,6 +3820,19 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +toucan-js@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/toucan-js/-/toucan-js-2.6.1.tgz#358ce4251da34b72e29d764c823f1407c37a03df" + integrity sha512-G0D6lkfsQBWJhHgSagFCTc0QTWoAVfjouVZXGNv1L/N9YN2r41R0daqzpFHcAwbS4VrOTDgyiXzamfRDdub4sA== + dependencies: + "@sentry/core" "6.19.6" + "@sentry/hub" "6.19.6" + "@sentry/types" "6.19.6" + "@sentry/utils" "6.19.6" + "@types/cookie" "0.5.0" + cookie "0.5.0" + stacktrace-js "2.0.2" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -3766,7 +3872,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1: +tslib@^1.8.1, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== From f7c2dfdbb3ef16f5713f75ef287acb1833871f2b Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Wed, 3 Aug 2022 18:29:03 -0500 Subject: [PATCH 02/19] Add Toucan boilerplate --- src/index.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 116a1866..2fb40972 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,19 @@ import type { Handler } from 'hono' +import Toucan from 'toucan-js' export const hello = (): Handler => { return async (c, next) => { - await next() + const sentry = new Toucan({ + dsn: c.env.SENTRY_DSN, + request: c.req, + allowedHeaders: ['user-agent'], + allowedSearchParams: /(.*)/, + }) + + try { + await next() + } catch (error) { + sentry.captureException(error) + } } } From 855ce4eba4c8aef7dafe195747105a01e73c948c Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Wed, 3 Aug 2022 18:33:14 -0500 Subject: [PATCH 03/19] Rename --- src/index.ts | 2 +- test/index.test.ts | 17 ++++------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/index.ts b/src/index.ts index 2fb40972..424dfdf7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import type { Handler } from 'hono' import Toucan from 'toucan-js' -export const hello = (): Handler => { +export const sentry = (): Handler => { return async (c, next) => { const sentry = new Toucan({ dsn: c.env.SENTRY_DSN, diff --git a/test/index.test.ts b/test/index.test.ts index 23a79984..c25665a3 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,24 +1,15 @@ import { Hono } from 'hono' -import { hello } from '../src' +import { sentry } from '../src' -describe('Hello middleware', () => { +describe('Sentry middleware', () => { const app = new Hono() - app.use('/hello/*', hello()) + app.use('/hello/*', sentry()) app.get('/hello/foo', (c) => c.text('foo')) - app.use('/x/*', hello()) - app.get('/x/foo', (c) => c.text('foo')) - - it('Should be hello message', async () => { + it('Should initialize Toucan', async () => { const res = await app.request('http://localhost/hello/foo') expect(res).not.toBeNull() expect(res.status).toBe(200) }) - - it('Should be X', async () => { - const res = await app.request('http://localhost/x/foo') - expect(res).not.toBeNull() - expect(res.status).toBe(200) - }) }) From ca0954a3103b7d45dc6baa4b9ea348c930ffb121 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Tue, 9 Aug 2022 10:49:41 -0500 Subject: [PATCH 04/19] Mock Toucan module, check captureException call --- test/index.test.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/test/index.test.ts b/test/index.test.ts index c25665a3..07272036 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,15 +1,28 @@ import { Hono } from 'hono' import { sentry } from '../src' +const captureException = jest.fn() +jest.mock('toucan-js', () => jest.fn().mockImplementation(() => ({ captureException }))) + describe('Sentry middleware', () => { const app = new Hono() - app.use('/hello/*', sentry()) - app.get('/hello/foo', (c) => c.text('foo')) + app.use('/sentry/*', sentry()) + app.get('/sentry/foo', (c) => c.text('foo')) + app.get('/sentry/error', () => { + throw new Error('a catastrophic error') + }) it('Should initialize Toucan', async () => { - const res = await app.request('http://localhost/hello/foo') + const res = await app.request('http://localhost/sentry/foo') expect(res).not.toBeNull() expect(res.status).toBe(200) }) + + it('Should report errors', async () => { + const res = await app.request('http://localhost/sentry/error') + expect(res).not.toBeNull() + expect(res.status).toBe(500) + expect(captureException).toHaveBeenCalled() + }) }) From 992df19dd15c5a31a0951ef46a820b2e9a73ad11 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Tue, 9 Aug 2022 11:08:36 -0500 Subject: [PATCH 05/19] Update README + deno index --- README.md | 14 +++++++------- deno_dist/README.md | 14 +++++++------- deno_dist/index.ts | 17 ++++++++++++++--- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index d2a7372c..27d4f37d 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ -# Hello middleware for Hono +# Sentry middleware for Hono -An example project of the third-party middleware for [Hono](https://github.com/honojs/hono). -This middleware add `X-Message` header to the Response. +Sentry middleware for [Hono](https://github.com/honojs/hono). +This middleware sends captured exceptions to the Sentry data source named by the `SENTRY_DSN` environment variable via [toucan-js](https://github.com/robertcepa/toucan-js). ## Usage ```ts -import { hello } from '@honojs/hello' +import { sentry } from '@honojs/sentry' import { Hono } from 'hono' const app = new Hono() -app.use('*', hello('Hello!! Hono!!')) +app.use('*', sentry()) app.get('/', (c) => c.text('foo')) export default app @@ -21,12 +21,12 @@ export default app ```ts import { serve } from 'https://deno.land/std/http/server.ts' -import { hello } from 'https://deno.land/x/hono_hello/mod.ts' +import { sentry } from 'https://deno.land/x/hono_sentry/mod.ts' import { Hono } from 'https://deno.land/x/hono/mod.ts' const app = new Hono() -app.use('*', hello('Hello!! Hono!!')) +app.use('*', sentry()) app.get('/', (c) => c.text('foo')) serve(app.fetch) diff --git a/deno_dist/README.md b/deno_dist/README.md index d2a7372c..27d4f37d 100644 --- a/deno_dist/README.md +++ b/deno_dist/README.md @@ -1,17 +1,17 @@ -# Hello middleware for Hono +# Sentry middleware for Hono -An example project of the third-party middleware for [Hono](https://github.com/honojs/hono). -This middleware add `X-Message` header to the Response. +Sentry middleware for [Hono](https://github.com/honojs/hono). +This middleware sends captured exceptions to the Sentry data source named by the `SENTRY_DSN` environment variable via [toucan-js](https://github.com/robertcepa/toucan-js). ## Usage ```ts -import { hello } from '@honojs/hello' +import { sentry } from '@honojs/sentry' import { Hono } from 'hono' const app = new Hono() -app.use('*', hello('Hello!! Hono!!')) +app.use('*', sentry()) app.get('/', (c) => c.text('foo')) export default app @@ -21,12 +21,12 @@ export default app ```ts import { serve } from 'https://deno.land/std/http/server.ts' -import { hello } from 'https://deno.land/x/hono_hello/mod.ts' +import { sentry } from 'https://deno.land/x/hono_sentry/mod.ts' import { Hono } from 'https://deno.land/x/hono/mod.ts' const app = new Hono() -app.use('*', hello('Hello!! Hono!!')) +app.use('*', sentry()) app.get('/', (c) => c.text('foo')) serve(app.fetch) diff --git a/deno_dist/index.ts b/deno_dist/index.ts index e6f18bf8..1e620330 100644 --- a/deno_dist/index.ts +++ b/deno_dist/index.ts @@ -1,8 +1,19 @@ import type { Handler } from 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' +import Toucan from 'toucan-js' -export const hello = (message: string = 'Hello'): Handler => { +export const hello = (): Handler => { return async (c, next) => { - await next() - c.res.headers.append('X-Message', message) + const sentry = new Toucan({ + dsn: c.env.SENTRY_DSN, + request: c.req, + allowedHeaders: ['user-agent'], + allowedSearchParams: /(.*)/, + }) + + try { + await next() + } catch (error) { + sentry.captureException(error) + } } } From 9dc53e6428b5ac31f133fd4dc49dead9357e9ff6 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Tue, 9 Aug 2022 11:32:06 -0500 Subject: [PATCH 06/19] Toucan reference not valid for Deno --- deno_dist/index.ts | 25 ++++++++++++------------- deno_test/index.test.ts | 11 +++++------ 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/deno_dist/index.ts b/deno_dist/index.ts index 1e620330..282ef1f8 100644 --- a/deno_dist/index.ts +++ b/deno_dist/index.ts @@ -1,19 +1,18 @@ import type { Handler } from 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' -import Toucan from 'toucan-js' -export const hello = (): Handler => { +export const sentry = (): Handler => { return async (c, next) => { - const sentry = new Toucan({ - dsn: c.env.SENTRY_DSN, - request: c.req, - allowedHeaders: ['user-agent'], - allowedSearchParams: /(.*)/, - }) + // const sentry = new Toucan({ + // dsn: c.env.SENTRY_DSN, + // request: c.req, + // allowedHeaders: ['user-agent'], + // allowedSearchParams: /(.*)/, + // }) - try { - await next() - } catch (error) { - sentry.captureException(error) - } + // try { + await next() + // } catch (error) { + // sentry.captureException(error) + // } } } diff --git a/deno_test/index.test.ts b/deno_test/index.test.ts index 46cd989b..54b5d6ce 100644 --- a/deno_test/index.test.ts +++ b/deno_test/index.test.ts @@ -1,15 +1,14 @@ -import { hello } from '../deno_dist/mod.ts' +import { sentry } from '../deno_dist/mod.ts' import { assertEquals, Hono } from './deps.ts' // Test just only minimal patterns. // Because others are tested well in Cloudflare Workers environment already. -Deno.test('Hello Middleware', async () => { +Deno.test('Sentry Middleware', async () => { const app = new Hono() - app.use('/hello/*', hello()) - app.get('/hello/foo', (c) => c.text('foo')) + app.use('/sentry/*', sentry()) + app.get('/sentry/foo', (c) => c.text('foo')) - let res = await app.request('http://localhost/hello/foo') + const res = await app.request('http://localhost/sentry/foo') assertEquals(res.status, 200) - assertEquals(res.headers.get('X-Message'), 'Hello') }) From e667634a3d92ed74ea18b0c6f9ca371dab4468c7 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Tue, 9 Aug 2022 14:09:45 -0500 Subject: [PATCH 07/19] Import placeholder --- deno_dist/index.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/deno_dist/index.ts b/deno_dist/index.ts index 282ef1f8..4adbccea 100644 --- a/deno_dist/index.ts +++ b/deno_dist/index.ts @@ -1,16 +1,17 @@ import type { Handler } from 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' +// import Toucan from '../node_modules/toucan-js/dist/index.d.ts' export const sentry = (): Handler => { return async (c, next) => { - // const sentry = new Toucan({ - // dsn: c.env.SENTRY_DSN, - // request: c.req, - // allowedHeaders: ['user-agent'], - // allowedSearchParams: /(.*)/, - // }) + // const sentry = new Toucan({ + // dsn: c.env.SENTRY_DSN, + // request: c.req, + // allowedHeaders: ['user-agent'], + // allowedSearchParams: /(.*)/, + // }) // try { - await next() + await next() // } catch (error) { // sentry.captureException(error) // } From 03d66ea1b36a4f978ed8bf4dc74bdbeac74d8808 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Tue, 9 Aug 2022 14:11:25 -0500 Subject: [PATCH 08/19] Remove Deno section from main README (no module) --- README.md | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/README.md b/README.md index 27d4f37d..dcda10d8 100644 --- a/README.md +++ b/README.md @@ -17,21 +17,6 @@ app.get('/', (c) => c.text('foo')) export default app ``` -## Deno - -```ts -import { serve } from 'https://deno.land/std/http/server.ts' -import { sentry } from 'https://deno.land/x/hono_sentry/mod.ts' -import { Hono } from 'https://deno.land/x/hono/mod.ts' - -const app = new Hono() - -app.use('*', sentry()) -app.get('/', (c) => c.text('foo')) - -serve(app.fetch) -``` - ## Author Yusuke Wada From 9294150029aa4ba1703b92dbd7d59e216bfbee26 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Wed, 10 Aug 2022 14:19:22 -0500 Subject: [PATCH 09/19] Add NEXT_PUBLIC_SENTRY_DSN --- deno_dist/index.ts | 4 ++-- src/index.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deno_dist/index.ts b/deno_dist/index.ts index 4adbccea..4caeeee3 100644 --- a/deno_dist/index.ts +++ b/deno_dist/index.ts @@ -4,14 +4,14 @@ import type { Handler } from 'https://raw.githubusercontent.com/honojs/hono/v2.0 export const sentry = (): Handler => { return async (c, next) => { // const sentry = new Toucan({ - // dsn: c.env.SENTRY_DSN, + // dsn: c.env.SENTRY_DSN || || c.env.NEXT_PUBLIC_SENTRY_DSN, // request: c.req, // allowedHeaders: ['user-agent'], // allowedSearchParams: /(.*)/, // }) // try { - await next() + await next() // } catch (error) { // sentry.captureException(error) // } diff --git a/src/index.ts b/src/index.ts index 424dfdf7..61ccc962 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,7 +4,7 @@ import Toucan from 'toucan-js' export const sentry = (): Handler => { return async (c, next) => { const sentry = new Toucan({ - dsn: c.env.SENTRY_DSN, + dsn: c.env.SENTRY_DSN || c.env.NEXT_PUBLIC_SENTRY_DSN, request: c.req, allowedHeaders: ['user-agent'], allowedSearchParams: /(.*)/, From b47e0004e219d8d26b1763a24926b71cf7213776 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Wed, 10 Aug 2022 14:54:58 -0500 Subject: [PATCH 10/19] Deno library + re-throw error --- README.md | 15 +++++++++++++++ deno_dist/index.ts | 24 +++++++++++------------- src/index.ts | 1 + 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index dcda10d8..27d4f37d 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,21 @@ app.get('/', (c) => c.text('foo')) export default app ``` +## Deno + +```ts +import { serve } from 'https://deno.land/std/http/server.ts' +import { sentry } from 'https://deno.land/x/hono_sentry/mod.ts' +import { Hono } from 'https://deno.land/x/hono/mod.ts' + +const app = new Hono() + +app.use('*', sentry()) +app.get('/', (c) => c.text('foo')) + +serve(app.fetch) +``` + ## Author Yusuke Wada diff --git a/deno_dist/index.ts b/deno_dist/index.ts index 4caeeee3..4fcf0fd1 100644 --- a/deno_dist/index.ts +++ b/deno_dist/index.ts @@ -1,19 +1,17 @@ import type { Handler } from 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' -// import Toucan from '../node_modules/toucan-js/dist/index.d.ts' +import * as Sentry from 'https://deno.land/x/sentry_deno/main.ts' export const sentry = (): 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: /(.*)/, - // }) - - // try { - await next() - // } catch (error) { - // sentry.captureException(error) - // } + Sentry.init({ + dsn: c.env.SENTRY_DSN || c.env.NEXT_PUBLIC_SENTRY_DSN, + tracesSampleRate: 1.0, + }) + try { + await next() + } catch (error) { + Sentry.captureException(error) + throw error + } } } diff --git a/src/index.ts b/src/index.ts index 61ccc962..a62ee427 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,6 +14,7 @@ export const sentry = (): Handler => { await next() } catch (error) { sentry.captureException(error) + throw error } } } From 8e16d4c9a0730ea114ea627ac7b70b706c665a51 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Fri, 12 Aug 2022 00:37:53 +0900 Subject: [PATCH 11/19] Enable options and callback function --- package.json | 3 ++- src/index.ts | 28 ++++++++++++++++++++++++++-- test/index.test.ts | 16 ++++++++++++++-- yarn.lock | 5 +++++ 4 files changed, 47 insertions(+), 5 deletions(-) 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" From 9b9b6d27446c7071e0dc394d738d0bf85f1999e9 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Fri, 12 Aug 2022 01:38:59 +0900 Subject: [PATCH 12/19] do not depeds `@sentry/types` --- package.json | 3 +- src/index.ts | 21 +++++--------- yarn.lock | 78 +++++++++++++++++++++++----------------------------- 3 files changed, 42 insertions(+), 60 deletions(-) diff --git a/package.json b/package.json index 79c03277..7726780d 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ }, "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", @@ -59,4 +58,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 b2b9564b..c83c398b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,24 +1,17 @@ -import type { Options as SentryOptions, StackFrame } from '@sentry/types' import type { Handler } from 'hono' import Toucan from 'toucan-js' -export type RewriteFrames = { - root?: string - iteratee?: (frame: StackFrame) => StackFrame -} - -type Options = { - dsn?: SentryOptions['dsn'] +export type Options = { + dsn?: string allowedCookies?: string[] | RegExp allowedHeaders?: string[] | RegExp allowedSearchParams?: string[] | RegExp - attachStacktrace?: SentryOptions['attachStacktrace'] - debug?: SentryOptions['debug'] - environment?: SentryOptions['environment'] - maxBreadcrumbs?: SentryOptions['maxBreadcrumbs'] + attachStacktrace?: boolean + debug?: boolean + environment?: string + maxBreadcrumbs?: number pkg?: Record - release?: SentryOptions['release'] - rewriteFrames?: RewriteFrames + release?: string } export const sentry = (options?: Options, callback?: (sentry: Toucan) => void): Handler => { diff --git a/yarn.lock b/yarn.lock index eb99b03d..06422af4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -783,17 +783,17 @@ "@octokit/types" "^6.0.3" universal-user-agent "^6.0.0" -"@octokit/openapi-types@^12.7.0": - version "12.8.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.8.0.tgz#f4708cf948724d6e8f7d878cfd91584c1c5c0523" - integrity sha512-ydcKLs2KKcxlhpdWLzJxEBDEk/U5MUeqtqkXlrtAUXXFPs6vLl1PEGghFC/BbpleosB7iXs0Z4P2DGe7ZT5ZNg== +"@octokit/openapi-types@^12.11.0": + version "12.11.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0" + integrity sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ== "@octokit/plugin-paginate-rest@^2.16.8": - version "2.21.2" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.2.tgz#070be9bb18cb78e52b471ddc3551d28355e2d5e2" - integrity sha512-S24H0a6bBVreJtoTaRHT/gnVASbOHVTRMOVIqd9zrJBP3JozsxJB56TDuTUmd1xLI4/rAE2HNmThvVKtIdLLEw== + version "2.21.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz#7f12532797775640dbb8224da577da7dc210c87e" + integrity sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw== dependencies: - "@octokit/types" "^6.39.0" + "@octokit/types" "^6.40.0" "@octokit/plugin-request-log@^1.0.4": version "1.0.4" @@ -839,12 +839,12 @@ "@octokit/plugin-request-log" "^1.0.4" "@octokit/plugin-rest-endpoint-methods" "^5.12.0" -"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.39.0": - version "6.39.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.39.0.tgz#46ce28ca59a3d4bac0e487015949008302e78eee" - integrity sha512-Mq4N9sOAYCitTsBtDdRVrBE80lIrMBhL9Jbrw0d+j96BAzlq4V+GLHFJbHokEsVvO/9tQupQdoFdgVYhD2C8UQ== +"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.39.0", "@octokit/types@^6.40.0": + version "6.41.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04" + integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg== dependencies: - "@octokit/openapi-types" "^12.7.0" + "@octokit/openapi-types" "^12.11.0" "@pkgr/utils@^2.3.0": version "2.3.0" @@ -892,11 +892,6 @@ 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" @@ -1550,22 +1545,22 @@ define-properties@^1.1.3, define-properties@^1.1.4: object-keys "^1.1.1" denoify@^0.11.1: - version "0.11.1" - resolved "https://registry.yarnpkg.com/denoify/-/denoify-0.11.1.tgz#b3623719afdb38d8e678408f8a26bffb76d400a2" - integrity sha512-HwRxpKpx4shhIruTXuZuPPCKD+aB1DT2dMDWqgTDpbZH9IV5SU95zVW/zVkX9m8VGozDe/N9DHIIrc/AYXgz8w== + version "0.11.7" + resolved "https://registry.yarnpkg.com/denoify/-/denoify-0.11.7.tgz#58d1fa69cb954d06ab98a2de07f1a08ab8a1a73c" + integrity sha512-2JvQysrBci6Fq0abR+PZl1vGb5spXuXnU3INf/4sflkwk3yRdGi233hd0tBk9fDjNrA2iz8xVemyOv6Hdcvt+g== dependencies: "@octokit/rest" "^18.0.0" "@types/comment-json" "^1.1.1" commander "^4.1.1" comment-json "^3.0.2" - evt beta + evt "^2.3.1" get-github-default-branch-name "^0.0.4" gitignore-parser "0.0.2" glob "^7.1.6" node-fetch "^2.6.0" path-depth "^1.0.0" scripting-tools "^0.19.13" - tsafe "^0.8.0" + tsafe "^0.10.1" url-join "^4.0.1" deprecation@^2.0.0, deprecation@^2.3.1: @@ -1938,14 +1933,14 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -evt@beta: - version "2.0.0-beta.45" - resolved "https://registry.yarnpkg.com/evt/-/evt-2.0.0-beta.45.tgz#8b1a81e1376f6eba254f4ec9865531b2ed118a3e" - integrity sha512-Me2/YMCjxLgz4y0aWKIxykyJth2LHKqxc91XnsIN39IRksknObBR9Pjmxwpnhmd1lNCR6mPFv/vBt46iQWtI9g== +evt@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/evt/-/evt-2.3.1.tgz#988fc6fc255db8999240e918afe63ba6c325db99" + integrity sha512-+MU1aA0as6hOnGxzQOw9hV/xiKIB1vAY90S+WD6zMzvvhQHlY4aPHk2b8WpWsVs3XErDzlhGzCESVCAuH9kUiA== dependencies: minimal-polyfills "^2.2.1" - run-exclusive "^2.2.14" - tsafe "^0.4.1" + run-exclusive "^2.2.16" + tsafe "^0.10.1" execa@^5.0.0: version "5.1.1" @@ -3112,7 +3107,7 @@ miniflare@2.6.0: source-map-support "^0.5.20" undici "5.5.1" -minimal-polyfills@^2.1.5, minimal-polyfills@^2.2.1: +minimal-polyfills@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/minimal-polyfills/-/minimal-polyfills-2.2.1.tgz#7249d7ece666d3b4e1ec1c1b8f949eb9d44e2308" integrity sha512-WLmHQrsZob4rVYf8yHapZPNJZ3sspGa/sN8abuSD59b0FifDEE7HMfLUi24z7mPZqTpBXy4Svp+iGvAmclCmXg== @@ -3488,12 +3483,12 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" -run-exclusive@^2.2.14: - version "2.2.14" - resolved "https://registry.yarnpkg.com/run-exclusive/-/run-exclusive-2.2.14.tgz#4f41dc7843e091f10991f8708fce87b09022a0ce" - integrity sha512-NHaQfB3zPJFx7p4M06AcmoK8xz/h8YDMCdy3jxfyoC9VqIbl1U+DiVjUuAYZBRMwvj5qkQnOUGfsmyUC4k46dg== +run-exclusive@^2.2.16: + version "2.2.16" + resolved "https://registry.yarnpkg.com/run-exclusive/-/run-exclusive-2.2.16.tgz#8fa30a23037760af296c47872a5f6b38f25accf0" + integrity sha512-cdYv2LDvaBCRnrqXrwDFs1SgzGTx0EIsiEReTpsprEDR6hRUVlSyjoMYu+rez4S1gpz6YbOQxcmYFMXJQknVnQ== dependencies: - minimal-polyfills "^2.1.5" + minimal-polyfills "^2.2.1" run-parallel@^1.1.9: version "1.2.0" @@ -3857,15 +3852,10 @@ ts-jest@^28.0.5: semver "7.x" yargs-parser "^21.0.1" -tsafe@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-0.4.1.tgz#00af1be2db82abb4be531209b90232d7954e1a03" - integrity sha512-+OZ0gdgmwcru+MOSheCx+ymAvQz+1/ui+KFJRuaq0t2m8RNrlf7eSzEieptoPQXPY67Mdkqgkdjknn8azoD5sw== - -tsafe@^0.8.0: - version "0.8.1" - resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-0.8.1.tgz#9af7e1540bc04313a82d60c98056a5017c8b086b" - integrity sha512-EfPjxQHzndQAV/uh0SMGP26Wg3dCuaw8dRv2VPEuGHen5qzg2oqsMvZw2wkQFkiMisZq2fm95m5lheimW2Fpvg== +tsafe@^0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-0.10.1.tgz#8f100b901e4467c43c0484f56a063f4276683ce0" + integrity sha512-S+LrpSjoH5Pah201KS0MxtJn88HVtKf4ZxUoQuW/Hnl4IK6ALu9Qwjed7RbohDeHn+iMuug4c5Mk/z1Cq2G3nw== tsconfig-paths@^3.14.1: version "3.14.1" From cbcd8fb3da5302e155cdc84c511d4719f50af414 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Fri, 12 Aug 2022 12:41:03 +0900 Subject: [PATCH 13/19] Use toucan.js on Deno --- README.md | 2 +- deno_dist/README.md | 2 +- deno_dist/index.ts | 57 ++++++++++++++++++++++++++++++++++++----- deno_test/index.test.ts | 13 +++++++++- package.json | 21 ++++++++------- src/index.ts | 29 +++++++++++++++++++-- src/replacer.ts | 9 +++++++ 7 files changed, 111 insertions(+), 22 deletions(-) create mode 100644 src/replacer.ts diff --git a/README.md b/README.md index 27d4f37d..cbb66830 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ import { Hono } from 'https://deno.land/x/hono/mod.ts' const app = new Hono() -app.use('*', sentry()) +app.use('*', sentry({ dsn: 'https://xxxxxx@xxx.ingest.sentry.io/xxxxxx' })) app.get('/', (c) => c.text('foo')) serve(app.fetch) diff --git a/deno_dist/README.md b/deno_dist/README.md index 27d4f37d..cbb66830 100644 --- a/deno_dist/README.md +++ b/deno_dist/README.md @@ -26,7 +26,7 @@ import { Hono } from 'https://deno.land/x/hono/mod.ts' const app = new Hono() -app.use('*', sentry()) +app.use('*', sentry({ dsn: 'https://xxxxxx@xxx.ingest.sentry.io/xxxxxx' })) app.get('/', (c) => c.text('foo')) serve(app.fetch) diff --git a/deno_dist/index.ts b/deno_dist/index.ts index 4fcf0fd1..48d10319 100644 --- a/deno_dist/index.ts +++ b/deno_dist/index.ts @@ -1,17 +1,62 @@ -import type { Handler } from 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' -import * as Sentry from 'https://deno.land/x/sentry_deno/main.ts' +import type { Context, Handler } from 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' +import Toucan from "https://cdn.skypack.dev/toucan-js@2.6.1" -export const sentry = (): Handler => { +declare module 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' { + interface ContextVariableMap { + sentry: Toucan + } +} + +class MockContext implements ExecutionContext { + passThroughOnException(): void { + throw new Error('Method not implemented.') + } + async waitUntil(promise: Promise): Promise { + await promise + } +} + +export type Options = { + dsn?: string + allowedCookies?: string[] | RegExp + allowedHeaders?: string[] | RegExp + allowedSearchParams?: string[] | RegExp + attachStacktrace?: boolean + debug?: boolean + environment?: string + maxBreadcrumbs?: number + pkg?: Record + release?: string +} + +export const sentry = (options?: Options, callback?: (sentry: Toucan) => void): Handler => { return async (c, next) => { - Sentry.init({ + let hasExecutionContext = true + try { + c.executionCtx + } catch { + hasExecutionContext = false + } + const sentry = new Toucan({ dsn: c.env.SENTRY_DSN || c.env.NEXT_PUBLIC_SENTRY_DSN, - tracesSampleRate: 1.0, + allowedHeaders: ['user-agent'], + allowedSearchParams: /(.*)/, + request: c.req, + context: hasExecutionContext ? c.executionCtx : new MockContext(), + ...options, }) + + if (callback) callback(sentry) + try { await next() } catch (error) { - Sentry.captureException(error) + sentry.captureException(error) throw error } } } + +export const getSentry = (c: Context) => { + return c.get('sentry') +} diff --git a/deno_test/index.test.ts b/deno_test/index.test.ts index 54b5d6ce..c1129d3d 100644 --- a/deno_test/index.test.ts +++ b/deno_test/index.test.ts @@ -4,11 +4,22 @@ import { assertEquals, Hono } from './deps.ts' // Test just only minimal patterns. // Because others are tested well in Cloudflare Workers environment already. +// Mock +class Context implements ExecutionContext { + passThroughOnException(): void { + throw new Error('Method not implemented.') + } + async waitUntil(promise: Promise): Promise { + await promise + } +} + Deno.test('Sentry Middleware', async () => { const app = new Hono() app.use('/sentry/*', sentry()) app.get('/sentry/foo', (c) => c.text('foo')) - 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()) assertEquals(res.status, 200) }) diff --git a/package.json b/package.json index 7726780d..7c667ee3 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { - "name": "@honojs/hello", - "version": "0.0.6", - "description": "An example of third-party middleware for Hono", + "name": "@honojs/sentry", + "version": "0.0.1", + "description": "Sentry Middleware for Hono", "main": "dist/index.js", "types": "dist/index.d.ts", "files": [ - "dist" + "dist/index.js", + "dist/index.d.ts" ], "scripts": { "test": "jest", @@ -13,21 +14,19 @@ "test:all": "yarn test && yarn test:deno", "denoify": "rimraf deno_dist && denoify", "build": "rimraf dist && tsc", - "prerelease": "yarn denoify && yarn build && yarn test:all", + "prerelease": "yarn build && yarn denoify && yarn test:all", "release": "yarn publish" }, "denoify": { - "port": { - "hono": "honojs/hono" - } + "replacer": "dist/replacer.js" }, "license": "MIT", "private": false, "repository": { "type": "git", - "url": "https://github.com/honojs/middleware-template.git" + "url": "https://github.com/honojs/sentry.git" }, - "homepage": "https://github.com/honojs/middleware-template", + "homepage": "https://github.com/honojs/sentry", "author": "Yusuke Wada (https://github.com/yusukebe)", "publishConfig": { "registry": "https://registry.npmjs.org", @@ -58,4 +57,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 c83c398b..000fd0da 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,21 @@ -import type { Handler } from 'hono' +import type { Context, Handler } from 'hono' import Toucan from 'toucan-js' +declare module 'hono' { + interface ContextVariableMap { + sentry: Toucan + } +} + +class MockContext implements ExecutionContext { + passThroughOnException(): void { + throw new Error('Method not implemented.') + } + async waitUntil(promise: Promise): Promise { + await promise + } +} + export type Options = { dsn?: string allowedCookies?: string[] | RegExp @@ -16,12 +31,18 @@ export type Options = { export const sentry = (options?: Options, callback?: (sentry: Toucan) => void): Handler => { return async (c, next) => { + let hasExecutionContext = true + try { + c.executionCtx + } catch { + hasExecutionContext = false + } const sentry = new Toucan({ dsn: c.env.SENTRY_DSN || c.env.NEXT_PUBLIC_SENTRY_DSN, allowedHeaders: ['user-agent'], allowedSearchParams: /(.*)/, request: c.req, - context: c.executionCtx, + context: hasExecutionContext ? c.executionCtx : new MockContext(), ...options, }) @@ -35,3 +56,7 @@ export const sentry = (options?: Options, callback?: (sentry: Toucan) => void): } } } + +export const getSentry = (c: Context) => { + return c.get('sentry') +} diff --git a/src/replacer.ts b/src/replacer.ts new file mode 100644 index 00000000..c1a222d8 --- /dev/null +++ b/src/replacer.ts @@ -0,0 +1,9 @@ +// @denoify-ignore +import { makeThisModuleAnExecutableReplacer } from 'denoify' + +makeThisModuleAnExecutableReplacer(async ({ parsedImportExportStatement, version }) => { + if (parsedImportExportStatement.parsedArgument.nodeModuleName === 'toucan-js') { + return `import Toucan from "https://cdn.skypack.dev/toucan-js@${version}"` + } + return undefined +}) From e412336577d88314dcea0b7407b0759f53f11e35 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Fri, 12 Aug 2022 09:47:15 -0500 Subject: [PATCH 14/19] Linting --- .eslintrc.js | 1 + deno_dist/index.ts | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index d52c820e..a30cfdb1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -55,6 +55,7 @@ module.exports = defineConfig({ '@typescript-eslint/no-empty-interface': 'off', '@typescript-eslint/no-inferrable-types': 'off', '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }], }, }) diff --git a/deno_dist/index.ts b/deno_dist/index.ts index 48d10319..f9036910 100644 --- a/deno_dist/index.ts +++ b/deno_dist/index.ts @@ -1,5 +1,8 @@ -import type { Context, Handler } from 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' -import Toucan from "https://cdn.skypack.dev/toucan-js@2.6.1" +import Toucan from 'https://cdn.skypack.dev/toucan-js@2.6.1' +import type { + Context, + Handler, +} from 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' declare module 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' { interface ContextVariableMap { From 3d3e3a319c5d721426770fdc6426e54df145ffc4 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Fri, 12 Aug 2022 14:33:42 -0500 Subject: [PATCH 15/19] Add callback test --- test/index.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/index.test.ts b/test/index.test.ts index ed31ef56..29a11e2e 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -13,11 +13,12 @@ class Context implements ExecutionContext { const captureException = jest.fn() jest.mock('toucan-js', () => jest.fn().mockImplementation(() => ({ captureException }))) +const callback = jest.fn() describe('Sentry middleware', () => { const app = new Hono() - app.use('/sentry/*', sentry()) + app.use('/sentry/*', sentry(undefined, callback)) app.get('/sentry/foo', (c) => c.text('foo')) app.get('/sentry/error', () => { throw new Error('a catastrophic error') @@ -28,6 +29,7 @@ describe('Sentry middleware', () => { const res = await app.fetch(req, {}, new Context()) expect(res).not.toBeNull() expect(res.status).toBe(200) + expect(callback).toHaveBeenCalled() }) it('Should report errors', async () => { From 2b2d05dd16089b09a0516e89dff320e8c4fd7e02 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Fri, 12 Aug 2022 14:55:30 -0500 Subject: [PATCH 16/19] Add to Deno test --- deno_test/index.test.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/deno_test/index.test.ts b/deno_test/index.test.ts index c1129d3d..9b4738f3 100644 --- a/deno_test/index.test.ts +++ b/deno_test/index.test.ts @@ -1,3 +1,4 @@ +import { assertNotEquals } from 'https://deno.land/std@0.148.0/testing/asserts.ts' import { sentry } from '../deno_dist/mod.ts' import { assertEquals, Hono } from './deps.ts' @@ -18,8 +19,17 @@ Deno.test('Sentry Middleware', async () => { const app = new Hono() app.use('/sentry/*', sentry()) app.get('/sentry/foo', (c) => c.text('foo')) + app.get('/sentry/error', () => { + throw new Error('a catastrophic error') + }) - const req = new Request('http://localhost/sentry/foo') - const res = await app.fetch(req, {}, new Context()) + let req = new Request('http://localhost/sentry/foo') + let res = await app.fetch(req, {}, new Context()) + assertNotEquals(res, null) assertEquals(res.status, 200) + + req = new Request('http://localhost/sentry/error') + res = await app.fetch(req, {}, new Context()) + assertNotEquals(res, null) + assertEquals(res.status, 500) }) From d56da11417a33edd9188950feb1e64fba74bd9cc Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Fri, 12 Aug 2022 14:57:37 -0500 Subject: [PATCH 17/19] Add callback --- deno_test/index.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/deno_test/index.test.ts b/deno_test/index.test.ts index 9b4738f3..860e8854 100644 --- a/deno_test/index.test.ts +++ b/deno_test/index.test.ts @@ -17,7 +17,12 @@ class Context implements ExecutionContext { Deno.test('Sentry Middleware', async () => { const app = new Hono() - app.use('/sentry/*', sentry()) + app.use( + '/sentry/*', + sentry(undefined, (sentry) => { + sentry.captureMessage('foo') + }) + ) app.get('/sentry/foo', (c) => c.text('foo')) app.get('/sentry/error', () => { throw new Error('a catastrophic error') From 1a01ae820a6c0bbb2a84bad3e97137def61929a8 Mon Sep 17 00:00:00 2001 From: Samuel Lippert Date: Fri, 12 Aug 2022 14:58:16 -0500 Subject: [PATCH 18/19] Call setUSer --- deno_test/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deno_test/index.test.ts b/deno_test/index.test.ts index 860e8854..64960be5 100644 --- a/deno_test/index.test.ts +++ b/deno_test/index.test.ts @@ -20,7 +20,7 @@ Deno.test('Sentry Middleware', async () => { app.use( '/sentry/*', sentry(undefined, (sentry) => { - sentry.captureMessage('foo') + sentry.setUser({ id: 'test' }) }) ) app.get('/sentry/foo', (c) => c.text('foo')) From 615b0e7baace93bb2dbcd8a5b090e5399cdc515c Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Sat, 13 Aug 2022 08:42:45 +0900 Subject: [PATCH 19/19] remove Context mock from deno test It's unnecessary. --- deno_dist/index.ts | 7 ++----- deno_test/index.test.ts | 15 ++------------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/deno_dist/index.ts b/deno_dist/index.ts index f9036910..48d10319 100644 --- a/deno_dist/index.ts +++ b/deno_dist/index.ts @@ -1,8 +1,5 @@ -import Toucan from 'https://cdn.skypack.dev/toucan-js@2.6.1' -import type { - Context, - Handler, -} from 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' +import type { Context, Handler } from 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' +import Toucan from "https://cdn.skypack.dev/toucan-js@2.6.1" declare module 'https://raw.githubusercontent.com/honojs/hono/v2.0.6/deno_dist/mod.ts' { interface ContextVariableMap { diff --git a/deno_test/index.test.ts b/deno_test/index.test.ts index 64960be5..df6b4c2b 100644 --- a/deno_test/index.test.ts +++ b/deno_test/index.test.ts @@ -4,17 +4,6 @@ import { assertEquals, Hono } from './deps.ts' // Test just only minimal patterns. // Because others are tested well in Cloudflare Workers environment already. - -// Mock -class Context implements ExecutionContext { - passThroughOnException(): void { - throw new Error('Method not implemented.') - } - async waitUntil(promise: Promise): Promise { - await promise - } -} - Deno.test('Sentry Middleware', async () => { const app = new Hono() app.use( @@ -29,12 +18,12 @@ Deno.test('Sentry Middleware', async () => { }) let req = new Request('http://localhost/sentry/foo') - let res = await app.fetch(req, {}, new Context()) + let res = await app.fetch(req) assertNotEquals(res, null) assertEquals(res.status, 200) req = new Request('http://localhost/sentry/error') - res = await app.fetch(req, {}, new Context()) + res = await app.fetch(req) assertNotEquals(res, null) assertEquals(res.status, 500) })