Skip to content

Commit 984e1b5

Browse files
Adding support for Hono JS (#2375)
Adding plugin-hono to support capturing errors for Hono JS applications --------- Co-authored-by: Ben Wilson <ben.wilson@smartbear.com>
1 parent b96b2a4 commit 984e1b5

38 files changed

Lines changed: 9943 additions & 9078 deletions

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## [Unreleased]
4+
5+
### Added
6+
7+
- (plugin-hono) Added support for capturing errors in Hono applications [#2375](https://github.com/bugsnag/bugsnag-js/pull/2375)
8+
39
## [8.3.2] - 2025-04-24
410

511
### Fixed

dockerfiles/Dockerfile.node

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ RUN npm pack --verbose packages/node/
1919
RUN npm pack --verbose packages/plugin-express/
2020
RUN npm pack --verbose packages/plugin-koa/
2121
RUN npm pack --verbose packages/plugin-restify/
22+
RUN npm pack --verbose packages/plugin-hono/
2223

2324
# The maze-runner node tests
2425
FROM 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v9-cli as node-maze-runner

jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ module.exports = {
8080
'plugin-aws-lambda',
8181
'plugin-express',
8282
'plugin-koa',
83+
'plugin-hono',
8384
'plugin-restify',
8485
'plugin-contextualize',
8586
'plugin-server-*',

package-lock.json

Lines changed: 8547 additions & 9074 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@
8787
"test:types": "tsc -p tsconfig.json && lerna run test:types",
8888
"test:test-container-registry-login": "aws ecr get-login-password --profile=opensource --region=us-west-1 | docker login --username AWS --password-stdin 855461928731.dkr.ecr.us-west-1.amazonaws.com",
8989
"test:build-browser-container": "docker-compose up --build minimal-packager && docker-compose build --pull browser-maze-runner",
90-
"test:build-node-container": "docker-compose up --build minimal-packager && docker-compose build --pull node-maze-runner",
90+
"test:build-node-container": "docker compose up --build minimal-packager && docker compose build --pull node-maze-runner",
9191
"test:build-react-native-android": "test/react-native/scripts/build-android-locally.js",
9292
"test:build-react-native-ios": "bundle install && node -e 'require(\"./scripts/react-native-helper\").buildIOS()'",
9393
"test:build-react-native-maze-runner": "docker-compose build --pull react-native-maze-runner",
94-
"test:node": "npm run test:build-node-container && docker-compose run --use-aliases node-maze-runner",
94+
"test:node": "npm run test:build-node-container && docker compose run --use-aliases node-maze-runner",
9595
"test:react-native:ios": "npm run test:build-react-native-ios && npm run test:build-react-native-maze-runner && APP_LOCATION=build/$REACT_NATIVE_VERSION.ipa docker-compose run --use-aliases react-native-maze-runner",
9696
"local-npm:start": "verdaccio --config test/electron/local-npm-config.yml --listen 0.0.0.0:5539",
9797
"local-npm:publish-all": "lerna publish \"$VERSION_IDENTIFIER\" --yes --force-publish --exact --no-push --no-git-reset --no-git-tag-version --registry 'http://0.0.0.0:5539'",

packages/plugin-aws-lambda/src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const LambdaTimeoutApproaching = require('./lambda-timeout-approaching')
77
// warnings. See https://github.com/aws/aws-sam-cli/issues/2519
88
const MAX_TIMER_VALUE = Math.pow(2, 31) - 1
99

10-
const SERVER_PLUGIN_NAMES = ['express', 'koa', 'restify']
10+
const SERVER_PLUGIN_NAMES = ['express', 'koa', 'restify', 'hono']
1111
const isServerPluginLoaded = client => SERVER_PLUGIN_NAMES.some(name => client.getPlugin(name))
1212

1313
const BugsnagPluginAwsLambda = {

packages/plugin-hono/LICENSE.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) Bugsnag, https://www.bugsnag.com/
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the "Software"),
5+
to deal in the Software without restriction, including without limitation
6+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
7+
and/or sell copies of the Software, and to permit persons to whom the Software
8+
is furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

packages/plugin-hono/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# @bugsnag/plugin-hono
2+
3+
A [@bugsnag/js](https://github.com/bugsnag/bugsnag-js) plugin for capturing errors in Hono applications.
4+
5+
## License
6+
7+
This package is free software released under the MIT License. See [LICENSE.txt](./LICENSE.txt) for details.

packages/plugin-hono/package.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"name": "@bugsnag/plugin-hono",
3+
"version": "8.0.0",
4+
"main": "src/hono.js",
5+
"types": "types/bugsnag-hono.d.ts",
6+
"description": "@bugsnag/js error handling middleware for Hono web servers",
7+
"homepage": "https://www.bugsnag.com/",
8+
"repository": {
9+
"type": "git",
10+
"url": "git@github.com:bugsnag/bugsnag-js.git"
11+
},
12+
"publishConfig": {
13+
"access": "public"
14+
},
15+
"files": [
16+
"src",
17+
"types"
18+
],
19+
"author": "Bugsnag",
20+
"license": "MIT",
21+
"peerDependencies": {
22+
"@bugsnag/core": "^8.0.0"
23+
},
24+
"devDependencies": {
25+
"@bugsnag/core": "^8.0.0",
26+
"hono": "^4.6.3",
27+
"typescript": "^5.2.2"
28+
},
29+
"scripts": {
30+
"test:types": "tsc -p tsconfig.json"
31+
}
32+
}

packages/plugin-hono/src/hono.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
const { createMiddleware } = require('hono/factory')
2+
const extractRequestInfo = require('./request-info')
3+
const clone = require('@bugsnag/core/lib/clone-client')
4+
const handledState = {
5+
severity: 'error',
6+
unhandled: true,
7+
severityReason: {
8+
type: 'unhandledErrorMiddleware',
9+
attributes: { framework: 'Hono' }
10+
}
11+
}
12+
13+
module.exports = {
14+
name: 'hono',
15+
load: client => {
16+
const requestHandler = createMiddleware(async (c, next) => {
17+
// clone the client to be scoped to this request. If sessions are enabled, start one
18+
const requestClient = clone(client)
19+
if (requestClient._config.autoTrackSessions) {
20+
requestClient.startSession()
21+
}
22+
23+
c.bugsnag = requestClient
24+
25+
// extract request info and pass it to the relevant bugsnag properties
26+
requestClient.addOnError(async (event) => {
27+
const { metadata, request } = await getRequestAndMetadataFromReq(c)
28+
event.request = { ...event.request, ...request }
29+
event.addMetadata('request', metadata)
30+
if (event._handledState.severityReason.type === 'unhandledException') {
31+
event.severity = 'error'
32+
event._handledState = handledState
33+
}
34+
}, true)
35+
36+
await client._clientContext.run(requestClient, next)
37+
})
38+
39+
const errorHandler = createMiddleware(async (c, next) => {
40+
next()
41+
42+
if (!c.error || !client._config.autoDetectErrors) return
43+
44+
const event = client.Event.create(c.error, false, handledState, 'hono middleware', 1)
45+
46+
if (c.bugsnag) {
47+
c.bugsnag._notify(event)
48+
} else {
49+
client._logger.warn(
50+
'c.bugsnag is not defined. Make sure the @bugsnag/plugin-hono requestHandler middleware is added first.'
51+
)
52+
const { metadata, request } = await getRequestAndMetadataFromReq(c)
53+
event.request = { ...event.request, ...request }
54+
event.addMetadata('request', metadata)
55+
client._notify(event)
56+
}
57+
})
58+
59+
return { requestHandler, errorHandler }
60+
}
61+
}
62+
63+
const getRequestAndMetadataFromReq = async c => {
64+
const { body, ...requestInfo } = await extractRequestInfo(c)
65+
return {
66+
metadata: requestInfo,
67+
request: {
68+
body,
69+
url: requestInfo.url,
70+
httpMethod: requestInfo.httpMethod,
71+
httpVersion: requestInfo.httpVersion,
72+
headers: requestInfo.headers
73+
}
74+
}
75+
}
76+
77+
module.exports.default = module.exports

0 commit comments

Comments
 (0)