@asenajs/hono-adapter 1.7.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,23 +1,30 @@
1
1
  import { HTTPException } from 'hono/http-exception';
2
- import { VALIDATION_ERROR } from '@asenajs/asena/adapter';
2
+ import { HTTP_EXCEPTION, VALIDATION_ERROR, } from '@asenajs/asena/adapter';
3
+ import { flattenError } from 'zod';
3
4
  /**
4
5
  * @description Thrown when request validation fails, so the failure reaches the
5
6
  * application's `ConfigService.onError` like every other error instead of being
6
7
  * answered inside the validator middleware.
7
8
  *
8
- * Extends Hono's `HTTPException` with status 400 deliberately: an existing handler
9
- * that branches on `error instanceof HTTPException` and replies with `error.status`
10
- * keeps answering 400, so adopting this does not silently turn validation failures
11
- * into 500s.
9
+ * Extends Hono's `HTTPException` with status 400 deliberately: a handler that matches
10
+ * with `isHttpException()` - or with the older `error instanceof HTTPException` - and
11
+ * replies with `error.status` keeps answering 400, so adopting this does not silently
12
+ * turn validation failures into 500s.
13
+ *
14
+ * Note it does *not* extend `HttpException` from `@asenajs/asena/adapter`, the class
15
+ * applications throw. Both are branded, so `isHttpException()` cannot tell them apart and
16
+ * does not need to; `instanceof` can, which is one more reason not to reach for it.
12
17
  *
13
18
  * @example
14
19
  * ```typescript
15
20
  * public onError(error: Error, context: Context) {
21
+ * // Before isHttpException: ValidationError is an HTTP exception too, so the
22
+ * // generic branch below would otherwise swallow it.
16
23
  * if (isValidationError(error)) {
17
24
  * return context.send({ success: false, errors: error.issues }, 400);
18
25
  * }
19
26
  *
20
- * if (error instanceof HTTPException) {
27
+ * if (isHttpException(error)) {
21
28
  * return context.send({ error: error.message }, error.status);
22
29
  * }
23
30
  *
@@ -27,6 +34,11 @@ import { VALIDATION_ERROR } from '@asenajs/asena/adapter';
27
34
  */
28
35
  export class ValidationError extends HTTPException {
29
36
  [VALIDATION_ERROR] = true;
37
+ /**
38
+ * Also branded as an HTTP exception. Inherited from `HTTPException` in practice - see
39
+ * `brandHonoHttpException` below - but declared here too so the type states it.
40
+ */
41
+ [HTTP_EXCEPTION] = true;
30
42
  /** Which part of the request failed: `json`, `query`, `form`, `param` or `header` */
31
43
  target;
32
44
  /** Field-level failures, adapter-agnostic */
@@ -44,5 +56,107 @@ export class ValidationError extends HTTPException {
44
56
  code: issue.code,
45
57
  }));
46
58
  }
59
+ /**
60
+ * The envelope the caller sees when the application does not answer this failure itself.
61
+ *
62
+ * It lives here rather than in the adapter so a validation failure has exactly one response
63
+ * shape - the adapter used to build a richer body inline for applications with no `onError`
64
+ * and fall back to `HTTPException`'s bare `Validation failed` text for everyone else, so the
65
+ * same failure answered two different bodies depending on an unrelated hook.
66
+ *
67
+ * Built on each call rather than passed to `super` as `res`: a `Response` body can only be
68
+ * read once, and Hono may ask for this more than one time.
69
+ */
70
+ getResponse() {
71
+ return new Response(JSON.stringify({
72
+ error: 'Validation failed',
73
+ details: flattenError(this.cause),
74
+ target: this.target,
75
+ }), {
76
+ status: this.status,
77
+ headers: { 'Content-Type': 'application/json' },
78
+ });
79
+ }
47
80
  }
81
+ /**
82
+ * Brands Hono's own `HTTPException` so `isHttpException()` recognises it.
83
+ *
84
+ * `HTTPException` comes from `hono/http-exception`, so this package cannot declare the brand on
85
+ * the class - but it can put it on the prototype, which is the same thing at runtime and covers
86
+ * every instance including ones the application constructs itself.
87
+ *
88
+ * Without this the brand is a trap rather than a feature: the JSDoc on `isHttpException` tells
89
+ * users to write `if (isHttpException(error)) ... else 500`, and on this adapter every
90
+ * deliberate 401/403/404/429 raised by `hono/basic-auth`, `hono/jwt` or hono's own validator
91
+ * would take the else branch and answer 500.
92
+ *
93
+ * The brand covers one copy of `hono` and cannot reach another: it is installed on the prototype
94
+ * of the class *this* package resolved. Since 3.0.0 `hono` is a **peer** dependency, so this
95
+ * package has no resolution slot of its own and an application normally resolves exactly one copy
96
+ * - which is what makes the brand sufficient rather than a trap. Before that it was a regular
97
+ * dependency, and a downstream application that bumped its own `hono` range ended up with a second
98
+ * nested copy whose `HTTPException` was unbranded: every deliberate 400/403 answered 500 while the
99
+ * API kept responding. `warnOnNestedHono` below reports the one shape that can still produce it.
100
+ *
101
+ * Import `HTTPException` from `@asenajs/hono-adapter` rather than from `hono/http-exception` to
102
+ * stay on this package's copy regardless. The adapter's default response also checks
103
+ * `instanceof HTTPException` before the brand, so a hono exception is answered correctly even if
104
+ * this function never ran.
105
+ *
106
+ * Idempotent, and called from the HonoAdapter constructor.
107
+ */
108
+ export const brandHonoHttpException = () => {
109
+ if (Object.prototype.hasOwnProperty.call(HTTPException.prototype, HTTP_EXCEPTION)) {
110
+ return;
111
+ }
112
+ Object.defineProperty(HTTPException.prototype, HTTP_EXCEPTION, {
113
+ value: true,
114
+ enumerable: false,
115
+ configurable: true,
116
+ });
117
+ };
118
+ /**
119
+ * Warns when this package resolved a *nested* copy of `hono`.
120
+ *
121
+ * `hono` is a peer dependency, so it should always resolve from the application's own
122
+ * `node_modules`. A path under `@asenajs/hono-adapter/node_modules/hono` means a second copy was
123
+ * installed privately for this package - the exact topology that makes `brandHonoHttpException()`
124
+ * useless, because the brand lands on the prototype of *this* copy's class and an `HTTPException`
125
+ * the application threw from its own copy is neither `instanceof` it nor branded, so it is
126
+ * answered 500.
127
+ *
128
+ * This does not - and cannot - detect the *application's* copy. `import.meta.resolve` always
129
+ * answers relative to this module, Node resolution is per-importer so there is no single "the
130
+ * application's hono" to compare against, and after `asena build` or `bun build --compile` there
131
+ * is no `node_modules` to inspect at all. What it can prove is the asymmetric half: if *our* copy
132
+ * is nested, there are two. That is enough, because under a peer dependency a nested copy is the
133
+ * only way this package acquires one.
134
+ *
135
+ * Worth having even though the peer move makes the topology rare: `bun install` has been observed
136
+ * to drop the lockfile entry for a nested copy while leaving the directory on disk, so an
137
+ * application upgrading in place can still be broken by a leftover it cannot see.
138
+ *
139
+ * The path predicate is {@link isNestedHonoPath}, exported so it can be tested against both
140
+ * layouts directly - inside this repo `import.meta.resolve` always answers
141
+ * `hono-adapter/node_modules/hono`, which is the package's own root and deliberately does *not*
142
+ * match, so a test driving the real resolver could only ever assert the negative case.
143
+ */
144
+ export const isNestedHonoPath = (resolved) => resolved.includes('@asenajs/hono-adapter/node_modules/hono');
145
+ export const warnOnNestedHono = (logger) => {
146
+ try {
147
+ const resolved = import.meta.resolve('hono/http-exception');
148
+ if (!isNestedHonoPath(resolved)) {
149
+ return;
150
+ }
151
+ (logger ?? console).warn(`A nested copy of \`hono\` was found at ${resolved}.\n` +
152
+ ` \`hono\` is a peer dependency of @asenajs/hono-adapter and must resolve from your\n` +
153
+ ` application's node_modules. With two copies, an HTTPException thrown from your copy is\n` +
154
+ ` not recognised by isHttpException() and will be answered as 500.\n` +
155
+ ` Fix: rm -rf node_modules bun.lock && bun install`);
156
+ }
157
+ catch {
158
+ // `import.meta.resolve` is unavailable or throws under some bundlers and in compiled binaries.
159
+ // A diagnostic must never be the reason a server fails to boot.
160
+ }
161
+ };
48
162
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../lib/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAkD,MAAM,wBAAwB,CAAC;AAG1G;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,OAAO,eAAgB,SAAQ,aAAa;IAChC,CAAC,gBAAgB,CAAC,GAAG,IAAa,CAAC;IAEnD,qFAAqF;IACrE,MAAM,CAAS;IAE/B,6CAA6C;IAC7B,MAAM,CAAoB;IAE1C,mEAAmE;IACnD,KAAK,CAAW;IAEhC,YAAmB,KAAe,EAAE,MAAc;QAChD,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAE7C,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACzC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC/F,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,IAAI,EAAE,KAAK,CAAC,IAAI;SACjB,CAAC,CAAC,CAAC;IACN,CAAC;CACF"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../lib/errors.ts"],"names":[],"mappings":"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"}
@@ -294,9 +294,20 @@ export declare class RateLimiterMiddleware extends MiddlewareService {
294
294
  */
295
295
  handle(context: Context, next: () => Promise<void>): Promise<any>;
296
296
  /**
297
- * Cleanup resources (stop cleanup timer)
297
+ * Cleanup resources (stop cleanup timer, drop bucket state)
298
298
  *
299
- * Call this when shutting down the application.
299
+ * `@OnStop` hands this to the component lifecycle, so `server.stop()` calls it instead of the
300
+ * application having to remember to. The hook is inherited, so the `@Middleware()` subclass
301
+ * users actually register gets it without repeating the decorator - and it only fires for
302
+ * singletons, which is what a rate limiter has to be to share one bucket map across requests.
303
+ *
304
+ * The timer is `unref()`'d, so it never held the process open. What it does do is survive a
305
+ * stop/start cycle *inside* one process - twenty of them is an ordinary test suite - leaving a
306
+ * timer per stopped server still sweeping a bucket map nobody reads. The buckets go with it:
307
+ * a restarted server must not inherit the rate-limit state of the one before it, or the first
308
+ * requests after a restart get counted against a window that has already closed.
309
+ *
310
+ * Safe to call twice; the second call has nothing left to do.
300
311
  */
301
312
  destroy(): void;
302
313
  /**
@@ -46,7 +46,17 @@
46
46
  * public login() { ... }
47
47
  * ```
48
48
  */
49
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
50
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
51
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
52
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
53
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
54
+ };
55
+ var __metadata = (this && this.__metadata) || function (k, v) {
56
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
57
+ };
49
58
  import { MiddlewareService } from '../defaults';
59
+ import { OnStop } from '@asenajs/asena/decorators/ioc';
50
60
  /**
51
61
  * Rate Limiter Middleware
52
62
  *
@@ -238,14 +248,27 @@ export class RateLimiterMiddleware extends MiddlewareService {
238
248
  return await next();
239
249
  }
240
250
  /**
241
- * Cleanup resources (stop cleanup timer)
251
+ * Cleanup resources (stop cleanup timer, drop bucket state)
242
252
  *
243
- * Call this when shutting down the application.
253
+ * `@OnStop` hands this to the component lifecycle, so `server.stop()` calls it instead of the
254
+ * application having to remember to. The hook is inherited, so the `@Middleware()` subclass
255
+ * users actually register gets it without repeating the decorator - and it only fires for
256
+ * singletons, which is what a rate limiter has to be to share one bucket map across requests.
257
+ *
258
+ * The timer is `unref()`'d, so it never held the process open. What it does do is survive a
259
+ * stop/start cycle *inside* one process - twenty of them is an ordinary test suite - leaving a
260
+ * timer per stopped server still sweeping a bucket map nobody reads. The buckets go with it:
261
+ * a restarted server must not inherit the rate-limit state of the one before it, or the first
262
+ * requests after a restart get counted against a window that has already closed.
263
+ *
264
+ * Safe to call twice; the second call has nothing left to do.
244
265
  */
245
266
  destroy() {
246
267
  if (this.cleanupTimer) {
247
268
  clearInterval(this.cleanupTimer);
269
+ this.cleanupTimer = undefined;
248
270
  }
271
+ this.buckets.clear();
249
272
  }
250
273
  /**
251
274
  * Get current bucket state for a client (for testing/debugging)
@@ -300,4 +323,10 @@ export class RateLimiterMiddleware extends MiddlewareService {
300
323
  this.cleanupTimer.unref();
301
324
  }
302
325
  }
326
+ __decorate([
327
+ OnStop(),
328
+ __metadata("design:type", Function),
329
+ __metadata("design:paramtypes", []),
330
+ __metadata("design:returntype", void 0)
331
+ ], RateLimiterMiddleware.prototype, "destroy", null);
303
332
  //# sourceMappingURL=RateLimiterMiddleware.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RateLimiterMiddleware.js","sourceRoot":"","sources":["../../../lib/middlewares/RateLimiterMiddleware.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RateLimiterMiddleware.js","sourceRoot":"","sources":["../../../lib/middlewares/RateLimiterMiddleware.ts"],"names":[],"mappings":"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"}
@@ -24,4 +24,18 @@ export interface HonoAdapterOptions {
24
24
  * @see https://hono.dev/docs/api/hono#strict-mode
25
25
  */
26
26
  strict?: boolean;
27
+ /**
28
+ * Whether the adapter logs errors before delegating to the application's error handler.
29
+ *
30
+ * The adapter's line has no correlation id, so for an application that already logs in
31
+ * its own `onError` it is pure duplication that cannot be joined with the app's own
32
+ * entry. Set to `false` to leave observability entirely to the application.
33
+ *
34
+ * When enabled (the default) the level follows the status the client will see: 5xx logs
35
+ * at ERROR with a stack, anything below logs at DEBUG (or INFO when the logger has no
36
+ * `debug`) without one.
37
+ *
38
+ * @default true
39
+ */
40
+ logErrors?: boolean;
27
41
  }
@@ -1,7 +1,8 @@
1
- import type { AsenaHandler, ErrorHandler } from '@asenajs/asena/adapter';
1
+ import type { AsenaHandler, ErrorHandler, NotFoundHandler } from '@asenajs/asena/adapter';
2
2
  import type { Context } from '../defaults';
3
3
  export type HonoHandler = AsenaHandler<Context>;
4
4
  export type HonoErrorHandler = ErrorHandler<Context>;
5
+ export type HonoNotFoundHandler = NotFoundHandler<Context>;
5
6
  /**
6
7
  * Typed route handler for better type inference
7
8
  */
@@ -2,10 +2,7 @@ import { HonoAdapter } from '../../index';
2
2
  export const createHonoAdapter = (loggerOrOptions) => {
3
3
  if (loggerOrOptions && typeof loggerOrOptions === 'object' && 'logger' in loggerOrOptions) {
4
4
  const logger = loggerOrOptions.logger;
5
- return [
6
- new HonoAdapter(loggerOrOptions),
7
- logger,
8
- ];
5
+ return [new HonoAdapter(loggerOrOptions), logger];
9
6
  }
10
7
  const logger = loggerOrOptions;
11
8
  return [new HonoAdapter(logger), logger];
@@ -1 +1 @@
1
- {"version":3,"file":"createHonoAdapter.js","sourceRoot":"","sources":["../../../lib/utils/createHonoAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,eAA4D,EAC/B,EAAE;IAC/B,IAAI,eAAe,IAAI,OAAO,eAAe,KAAK,QAAQ,IAAI,QAAQ,IAAI,eAAe,EAAE,CAAC;QAC1F,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC;QAEtC,OAAO;YACL,IAAI,WAAW,CAAC,eAAqC,CAAC;YACtD,MAAM;SACP,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,eAA+B,CAAC;IAE/C,OAAO,CAAC,IAAI,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC,CAAC"}
1
+ {"version":3,"file":"createHonoAdapter.js","sourceRoot":"","sources":["../../../lib/utils/createHonoAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,eAA4D,EAC/B,EAAE;IAC/B,IAAI,eAAe,IAAI,OAAO,eAAe,KAAK,QAAQ,IAAI,QAAQ,IAAI,eAAe,EAAE,CAAC;QAC1F,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC;QAEtC,OAAO,CAAC,IAAI,WAAW,CAAC,eAAqC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,MAAM,GAAG,eAA+B,CAAC;IAE/C,OAAO,CAAC,IAAI,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC,CAAC"}
package/package.json CHANGED
@@ -9,18 +9,22 @@
9
9
  "README.md",
10
10
  "LICENSE"
11
11
  ],
12
- "version": "1.7.0",
12
+ "version": "3.0.0",
13
13
  "author": "LibirSoft",
14
14
  "repository": {
15
15
  "type": "git",
16
16
  "url": "https://github.com/AsenaJs/hono-adapter.git"
17
17
  },
18
18
  "license": "MIT",
19
+ "engines": {
20
+ "bun": ">=1.3.12"
21
+ },
19
22
  "scripts": {
20
23
  "test": "bun test",
21
24
  "test:watch": "bun test --watch",
22
25
  "test:coverage": "bun test --coverage",
23
26
  "build": "bun run clean && tsc",
27
+ "typecheck": "tsc -p tsconfig.typecheck.json",
24
28
  "clean": "rm -rf dist",
25
29
  "prepublishOnly": "bun run build",
26
30
  "benchmark": "bun run benchmark/run-benchmark.ts",
@@ -37,23 +41,26 @@
37
41
  "release": "bun run build && changeset publish"
38
42
  },
39
43
  "devDependencies": {
40
- "@asenajs/asena": "^0.8.1",
44
+ "@asenajs/asena": "^0.10.0",
41
45
  "@changesets/cli": "^2.30.0",
42
46
  "@types/bun": "latest",
43
47
  "@typescript-eslint/eslint-plugin": "^8.58.0",
44
48
  "@typescript-eslint/parser": "^8.58.0",
45
49
  "eslint": "^9.39.4",
46
50
  "eslint-config-prettier": "^9.1.2",
51
+ "hono": "^4.12.32",
47
52
  "prettier": "^3.8.1",
48
- "typescript-eslint": "^8.58.0"
53
+ "typescript": "^5.9.3",
54
+ "typescript-eslint": "^8.58.0",
55
+ "zod": "^4.3.6"
49
56
  },
50
57
  "peerDependencies": {
51
- "@asenajs/asena": "^0.8.1",
52
- "typescript": "^5.8.2"
58
+ "@asenajs/asena": "^0.10.0",
59
+ "hono": ">=4.12.9",
60
+ "typescript": "^5.8.2",
61
+ "zod": "^4.3.6"
53
62
  },
54
63
  "dependencies": {
55
- "@hono/zod-validator": "^0.9.0",
56
- "hono": "^4.12.9",
57
- "zod": "^4.3.6"
64
+ "@hono/zod-validator": "^0.9.0"
58
65
  }
59
66
  }