Use toucan.js on Deno
parent
9b9b6d2744
commit
cbcd8fb3da
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<any>): Promise<void> {
|
||||
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<string, any>
|
||||
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')
|
||||
}
|
||||
|
|
|
@ -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<any>): Promise<void> {
|
||||
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)
|
||||
})
|
||||
|
|
19
package.json
19
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 <yusuke@kamawada.com> (https://github.com/yusukebe)",
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org",
|
||||
|
|
29
src/index.ts
29
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<any>): Promise<void> {
|
||||
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')
|
||||
}
|
||||
|
|
|
@ -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
|
||||
})
|
Loading…
Reference in New Issue