@asenajs/hono-adapter 1.3.0 → 1.5.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.
Files changed (39) hide show
  1. package/README.md +2 -2
  2. package/dist/lib/HonoAdapter.d.ts +41 -4
  3. package/dist/lib/HonoAdapter.js +169 -54
  4. package/dist/lib/HonoAdapter.js.map +1 -1
  5. package/dist/lib/HonoContextWrapper.d.ts +16 -3
  6. package/dist/lib/HonoContextWrapper.js +77 -2
  7. package/dist/lib/HonoContextWrapper.js.map +1 -1
  8. package/dist/lib/HonoWebsocketAdapter.d.ts +2 -16
  9. package/dist/lib/HonoWebsocketAdapter.js +25 -53
  10. package/dist/lib/HonoWebsocketAdapter.js.map +1 -1
  11. package/dist/lib/defaults/ValidationService.d.ts +4 -4
  12. package/dist/lib/middlewares/CorsMiddleware.d.ts +1 -1
  13. package/dist/lib/middlewares/CorsMiddleware.js +5 -6
  14. package/dist/lib/middlewares/CorsMiddleware.js.map +1 -1
  15. package/dist/lib/middlewares/RateLimiterMiddleware.d.ts +1 -1
  16. package/dist/lib/middlewares/RateLimiterMiddleware.js +11 -9
  17. package/dist/lib/middlewares/RateLimiterMiddleware.js.map +1 -1
  18. package/dist/lib/types/HonoAdapterOptions.d.ts +27 -0
  19. package/dist/lib/types/HonoAdapterOptions.js +2 -0
  20. package/dist/lib/types/HonoAdapterOptions.js.map +1 -0
  21. package/dist/lib/types/SendPingStrategy.d.ts +4 -0
  22. package/dist/lib/types/SendPingStrategy.js +2 -0
  23. package/dist/lib/types/SendPingStrategy.js.map +1 -0
  24. package/dist/lib/types/index.d.ts +2 -0
  25. package/dist/lib/types/index.js +2 -0
  26. package/dist/lib/types/index.js.map +1 -1
  27. package/dist/lib/utils/createHonoAdapter.d.ts +2 -1
  28. package/dist/lib/utils/createHonoAdapter.js +9 -1
  29. package/dist/lib/utils/createHonoAdapter.js.map +1 -1
  30. package/dist/lib/utils/middlewareParser.d.ts +5 -1
  31. package/dist/lib/utils/middlewareParser.js +19 -4
  32. package/dist/lib/utils/middlewareParser.js.map +1 -1
  33. package/dist/lib/utils/routePriority.d.ts +40 -0
  34. package/dist/lib/utils/routePriority.js +75 -0
  35. package/dist/lib/utils/routePriority.js.map +1 -0
  36. package/dist/test/utils/testHelpers.d.ts +61 -0
  37. package/dist/test/utils/testHelpers.js +109 -0
  38. package/dist/test/utils/testHelpers.js.map +1 -0
  39. package/package.json +21 -15
@@ -5,27 +5,42 @@ import { createFactory } from 'hono/factory';
5
5
  * - Reuses context wrappers when possible
6
6
  * - Handles middleware return values (false stops pipeline)
7
7
  * - Adds error handling
8
+ *
9
+ * @param middlewares - Asena middlewares to convert
10
+ * @param getServer - Lazy server getter (server available at request time, not registration time)
8
11
  */
9
- export const middlewareParser = (middlewares) => {
12
+ export const middlewareParser = (middlewares, getServer) => {
10
13
  const factory = createFactory();
11
14
  return middlewares.map((middleware) => {
12
15
  if (middleware.override) {
13
- // @ts-ignore - Allow override middleware to use raw Hono context
16
+ // @ts-expect-error - Allow override middleware to use raw Hono context
14
17
  return (c, next) => middleware.handle(c, next);
15
18
  }
16
19
  return factory.createMiddleware(async (context, next) => {
17
20
  // Reuse wrapper if already exists in context (performance optimization)
18
21
  let wrapper = context.get('_asenaContextWrapper');
19
22
  if (!wrapper) {
20
- wrapper = new HonoContextWrapper(context);
23
+ wrapper = new HonoContextWrapper(context, getServer?.());
21
24
  context.set('_asenaContextWrapper', wrapper);
22
25
  }
23
26
  // eslint-disable-next-line no-useless-catch
24
27
  try {
25
28
  // Call middleware handler
26
29
  const result = await middleware.handle(wrapper, next);
27
- // If middleware returns false, stop the pipeline
30
+ // If middleware returns false, stop the pipeline and return 403
31
+ // (consistent with Ergenecore adapter behavior)
28
32
  if (result === false) {
33
+ context.res = new Response('Forbidden', { status: 403 });
34
+ return;
35
+ }
36
+ // If middleware returns Response, set it on the Hono context.
37
+ // Raw Response return may not propagate through factory.createMiddleware,
38
+ // so we set c.res directly to ensure Hono uses this response.
39
+ if (result instanceof Response) {
40
+ context.res = new Response(result.body, {
41
+ status: result.status,
42
+ headers: result.headers,
43
+ });
29
44
  return;
30
45
  }
31
46
  // If middleware didn't call next(), we call it here
@@ -1 +1 @@
1
- {"version":3,"file":"middlewareParser.js","sourceRoot":"","sources":["../../../lib/utils/middlewareParser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,WAAiD,EAAuB,EAAE;IACzG,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAEhC,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QACpC,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;YACxB,iEAAiE;YACjE,OAAO,CAAC,CAAU,EAAE,IAAc,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACpE,CAAC;QAED,OAAO,OAAO,CAAC,gBAAgB,CAAC,KAAK,EAAE,OAAgB,EAAE,IAAU,EAAE,EAAE;YACrE,wEAAwE;YACxE,IAAI,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAuB,CAAC;YAExE,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBAC1C,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;YAC/C,CAAC;YAED,4CAA4C;YAC5C,IAAI,CAAC;gBACH,0BAA0B;gBAC1B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBAEtD,iDAAiD;gBACjD,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;oBACrB,OAAO;gBACT,CAAC;gBAED,oDAAoD;gBACpD,4DAA4D;YAC9D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,oCAAoC;gBACpC,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
1
+ {"version":3,"file":"middlewareParser.js","sourceRoot":"","sources":["../../../lib/utils/middlewareParser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,WAAiD,EACjD,SAA2C,EACtB,EAAE;IACvB,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAEhC,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QACpC,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;YACxB,uEAAuE;YACvE,OAAO,CAAC,CAAU,EAAE,IAAc,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACpE,CAAC;QAED,OAAO,OAAO,CAAC,gBAAgB,CAAC,KAAK,EAAE,OAAgB,EAAE,IAAU,EAAE,EAAE;YACrE,wEAAwE;YACxE,IAAI,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAuB,CAAC;YAExE,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,IAAI,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;gBACzD,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;YAC/C,CAAC;YAED,4CAA4C;YAC5C,IAAI,CAAC;gBACH,0BAA0B;gBAC1B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBAEtD,gEAAgE;gBAChE,gDAAgD;gBAChD,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;oBACrB,OAAO,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;oBAEzD,OAAO;gBACT,CAAC;gBAED,8DAA8D;gBAC9D,0EAA0E;gBAC1E,8DAA8D;gBAC9D,IAAI,MAAM,YAAY,QAAQ,EAAE,CAAC;oBAC/B,OAAO,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE;wBACtC,MAAM,EAAE,MAAM,CAAC,MAAM;wBACrB,OAAO,EAAE,MAAM,CAAC,OAAO;qBACxB,CAAC,CAAC;oBAEH,OAAO;gBACT,CAAC;gBAED,oDAAoD;gBACpD,4DAA4D;YAC9D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,oCAAoC;gBACpC,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Route priority sorting for Hono adapter.
3
+ *
4
+ * Hono matches routes in registration order — the first matching route wins.
5
+ * This utility sorts routes so that more specific (static) paths are registered
6
+ * before less specific (param, wildcard) paths, following the industry-standard
7
+ * priority hierarchy used by Fastify's find-my-way radix tree router.
8
+ *
9
+ * Priority hierarchy (highest to lowest):
10
+ * 1. Static segments (/count, /search)
11
+ * 2. Parametric segments (/:id, /:name)
12
+ * 3. Wildcard segments (/*, /**)
13
+ * 4. Longer (more specific) paths before shorter ones
14
+ *
15
+ * @see https://github.com/delvedor/find-my-way — Fastify's router priority algorithm
16
+ */
17
+ /**
18
+ * Returns a priority score for a single path segment.
19
+ *
20
+ * @param segment - A single path segment (between slashes)
21
+ * @returns 0 for static, 1 for param, 2 for wildcard
22
+ */
23
+ export declare function segmentScore(segment: string): number;
24
+ /**
25
+ * Compares two route paths for registration priority.
26
+ *
27
+ * Returns negative if `a` should be registered before `b` (higher priority),
28
+ * positive if `b` should be registered before `a`,
29
+ * 0 if they have equal priority.
30
+ *
31
+ * @param pathA - First route path
32
+ * @param pathB - Second route path
33
+ * @returns Comparison result for Array.sort()
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * routes.sort((a, b) => compareRoutePriority(a.path, b.path));
38
+ * ```
39
+ */
40
+ export declare function compareRoutePriority(pathA: string, pathB: string): number;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Route priority sorting for Hono adapter.
3
+ *
4
+ * Hono matches routes in registration order — the first matching route wins.
5
+ * This utility sorts routes so that more specific (static) paths are registered
6
+ * before less specific (param, wildcard) paths, following the industry-standard
7
+ * priority hierarchy used by Fastify's find-my-way radix tree router.
8
+ *
9
+ * Priority hierarchy (highest to lowest):
10
+ * 1. Static segments (/count, /search)
11
+ * 2. Parametric segments (/:id, /:name)
12
+ * 3. Wildcard segments (/*, /**)
13
+ * 4. Longer (more specific) paths before shorter ones
14
+ *
15
+ * @see https://github.com/delvedor/find-my-way — Fastify's router priority algorithm
16
+ */
17
+ /**
18
+ * Returns a priority score for a single path segment.
19
+ *
20
+ * @param segment - A single path segment (between slashes)
21
+ * @returns 0 for static, 1 for param, 2 for wildcard
22
+ */
23
+ export function segmentScore(segment) {
24
+ if (segment === '*' || segment.includes('*'))
25
+ return 2;
26
+ if (segment.startsWith(':'))
27
+ return 1;
28
+ return 0;
29
+ }
30
+ /**
31
+ * Compares two route paths for registration priority.
32
+ *
33
+ * Returns negative if `a` should be registered before `b` (higher priority),
34
+ * positive if `b` should be registered before `a`,
35
+ * 0 if they have equal priority.
36
+ *
37
+ * @param pathA - First route path
38
+ * @param pathB - Second route path
39
+ * @returns Comparison result for Array.sort()
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * routes.sort((a, b) => compareRoutePriority(a.path, b.path));
44
+ * ```
45
+ */
46
+ export function compareRoutePriority(pathA, pathB) {
47
+ const segA = pathA.split('/').filter(Boolean);
48
+ const segB = pathB.split('/').filter(Boolean);
49
+ // Wildcard paths always go last — a path containing * is less specific than any non-wildcard path
50
+ const aHasWildcard = segA.some((s) => s === '*' || s.includes('*'));
51
+ const bHasWildcard = segB.some((s) => s === '*' || s.includes('*'));
52
+ if (aHasWildcard && !bHasWildcard)
53
+ return 1;
54
+ if (!aHasWildcard && bHasWildcard)
55
+ return -1;
56
+ // Segment-by-segment comparison
57
+ const maxLen = Math.max(segA.length, segB.length);
58
+ for (let i = 0; i < maxLen; i++) {
59
+ const a = segA[i];
60
+ const b = segB[i];
61
+ // One path ran out of segments — longer path is more specific, goes first
62
+ if (!a && b)
63
+ return 1;
64
+ if (a && !b)
65
+ return -1;
66
+ const scoreA = segmentScore(a);
67
+ const scoreB = segmentScore(b);
68
+ // Different segment types at this position — lower score wins
69
+ if (scoreA !== scoreB)
70
+ return scoreA - scoreB;
71
+ }
72
+ // Identical priority — maintain original order (stable sort)
73
+ return 0;
74
+ }
75
+ //# sourceMappingURL=routePriority.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routePriority.js","sourceRoot":"","sources":["../../../lib/utils/routePriority.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IAEvD,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IAEtC,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAa,EAAE,KAAa;IAC/D,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAE9C,kGAAkG;IAClG,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IAEpE,IAAI,YAAY,IAAI,CAAC,YAAY;QAAE,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC,YAAY,IAAI,YAAY;QAAE,OAAO,CAAC,CAAC,CAAC;IAE7C,gCAAgC;IAChC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAElD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAElB,0EAA0E;QAC1E,IAAI,CAAC,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC;QAEvB,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAE/B,8DAA8D;QAC9D,IAAI,MAAM,KAAK,MAAM;YAAE,OAAO,MAAM,GAAG,MAAM,CAAC;IAChD,CAAC;IAED,6DAA6D;IAC7D,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { HonoAdapter } from '../../lib/HonoAdapter';
2
+ import { HonoWebsocketAdapter } from '../../lib/HonoWebsocketAdapter';
3
+ import type { ServerLogger } from '@asenajs/asena/logger';
4
+ import type { BaseMiddleware } from '@asenajs/asena/adapter';
5
+ import type { Context as HonoAdapterContext } from '../../lib/defaults';
6
+ import { HttpMethod } from '@asenajs/asena/web-types';
7
+ import type { HonoAdapterOptions } from '../../lib/types';
8
+ /**
9
+ * Creates a mock ServerLogger with all methods as mock functions.
10
+ * This is the ONLY mock we use in the entire test suite.
11
+ */
12
+ export declare function createMockLogger(): ServerLogger;
13
+ /**
14
+ * Creates a test HonoAdapter with mock logger and port 0 (random available port).
15
+ */
16
+ export declare function createTestAdapter(opts?: Partial<HonoAdapterOptions>): {
17
+ adapter: HonoAdapter;
18
+ logger: ServerLogger;
19
+ wsAdapter: HonoWebsocketAdapter;
20
+ };
21
+ /**
22
+ * Starts the adapter server and returns connection info.
23
+ */
24
+ export declare function startTestServer(adapter: HonoAdapter): Promise<{
25
+ server: Bun.Server<import("@asenajs/asena/web-socket").WebSocketData<any>>;
26
+ port: number;
27
+ baseUrl: string;
28
+ }>;
29
+ /**
30
+ * Shortcut for registering a route with sensible defaults.
31
+ */
32
+ export declare function registerRoute(adapter: HonoAdapter, overrides: {
33
+ method?: HttpMethod;
34
+ path?: string;
35
+ handler?: (ctx: HonoAdapterContext) => any;
36
+ middlewares?: BaseMiddleware<HonoAdapterContext>[];
37
+ staticServe?: any;
38
+ validator?: any;
39
+ controllerName?: string;
40
+ controllerBasePath?: string;
41
+ }): Promise<void>;
42
+ /**
43
+ * Creates a BaseMiddleware with configurable behavior.
44
+ *
45
+ * @param behavior - What the middleware does:
46
+ * - 'next' (default): calls next() and returns true
47
+ * - 'block': returns false to stop the chain
48
+ * - 'response': returns a Response object
49
+ * - 'throw': throws an error
50
+ * - 'setHeader': sets a response header then calls next()
51
+ * - Function: custom behavior
52
+ */
53
+ export declare function createTestMiddleware(behavior?: 'next' | 'block' | 'response' | 'throw' | 'setHeader' | ((ctx: HonoAdapterContext, next: () => Promise<void>) => any), options?: {
54
+ headerName?: string;
55
+ headerValue?: string;
56
+ override?: boolean;
57
+ }): BaseMiddleware<HonoAdapterContext>;
58
+ /**
59
+ * Waits for a specified number of milliseconds.
60
+ */
61
+ export declare function sleep(ms: number): Promise<void>;
@@ -0,0 +1,109 @@
1
+ import { mock } from 'bun:test';
2
+ import { HonoAdapter } from '../../lib/HonoAdapter';
3
+ import { HonoWebsocketAdapter } from '../../lib/HonoWebsocketAdapter';
4
+ import { HttpMethod } from '@asenajs/asena/web-types';
5
+ /**
6
+ * Creates a mock ServerLogger with all methods as mock functions.
7
+ * This is the ONLY mock we use in the entire test suite.
8
+ */
9
+ export function createMockLogger() {
10
+ return {
11
+ info: mock(() => { }),
12
+ warn: mock(() => { }),
13
+ error: mock(() => { }),
14
+ profile: mock(() => { }),
15
+ };
16
+ }
17
+ /**
18
+ * Creates a test HonoAdapter with mock logger and port 0 (random available port).
19
+ */
20
+ export function createTestAdapter(opts) {
21
+ const logger = opts?.logger ?? createMockLogger();
22
+ const wsAdapter = opts?.websocketAdapter ?? new HonoWebsocketAdapter(logger);
23
+ const adapter = new HonoAdapter({
24
+ logger,
25
+ websocketAdapter: wsAdapter,
26
+ app: opts?.app,
27
+ strict: opts?.strict ?? false,
28
+ });
29
+ adapter.setPort(0);
30
+ return { adapter, logger, wsAdapter };
31
+ }
32
+ /**
33
+ * Starts the adapter server and returns connection info.
34
+ */
35
+ export async function startTestServer(adapter) {
36
+ const server = await adapter.start();
37
+ const port = server.port;
38
+ const baseUrl = `http://localhost:${port}`;
39
+ return { server, port, baseUrl };
40
+ }
41
+ /**
42
+ * Shortcut for registering a route with sensible defaults.
43
+ */
44
+ export async function registerRoute(adapter, overrides) {
45
+ await adapter.registerRoute({
46
+ method: overrides.method ?? HttpMethod.GET,
47
+ path: overrides.path ?? '/test',
48
+ handler: overrides.handler ?? ((ctx) => ctx.send({ ok: true })),
49
+ middlewares: overrides.middlewares ?? [],
50
+ staticServe: overrides.staticServe ?? null,
51
+ validator: overrides.validator ?? null,
52
+ controllerName: overrides.controllerName,
53
+ controllerBasePath: overrides.controllerBasePath,
54
+ });
55
+ }
56
+ /**
57
+ * Creates a BaseMiddleware with configurable behavior.
58
+ *
59
+ * @param behavior - What the middleware does:
60
+ * - 'next' (default): calls next() and returns true
61
+ * - 'block': returns false to stop the chain
62
+ * - 'response': returns a Response object
63
+ * - 'throw': throws an error
64
+ * - 'setHeader': sets a response header then calls next()
65
+ * - Function: custom behavior
66
+ */
67
+ export function createTestMiddleware(behavior = 'next', options) {
68
+ let handleFn;
69
+ switch (behavior) {
70
+ case 'next':
71
+ handleFn = async (_ctx, next) => {
72
+ await next();
73
+ return true;
74
+ };
75
+ break;
76
+ case 'block':
77
+ handleFn = async () => false;
78
+ break;
79
+ case 'response':
80
+ handleFn = async () => new Response(JSON.stringify({ blocked: true }), { status: 403 });
81
+ break;
82
+ case 'throw':
83
+ handleFn = async () => {
84
+ throw new Error('Middleware error');
85
+ };
86
+ break;
87
+ case 'setHeader':
88
+ handleFn = async (ctx, next) => {
89
+ ctx.setResponseHeader?.(options?.headerName ?? 'X-Test-Middleware', options?.headerValue ?? 'applied');
90
+ await next();
91
+ return true;
92
+ };
93
+ break;
94
+ default:
95
+ handleFn = behavior;
96
+ break;
97
+ }
98
+ return {
99
+ handle: mock(handleFn),
100
+ override: options?.override ?? false,
101
+ };
102
+ }
103
+ /**
104
+ * Waits for a specified number of milliseconds.
105
+ */
106
+ export function sleep(ms) {
107
+ return new Promise((resolve) => setTimeout(resolve, ms));
108
+ }
109
+ //# sourceMappingURL=testHelpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testHelpers.js","sourceRoot":"","sources":["../../../test/utils/testHelpers.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "README.md",
10
10
  "LICENSE"
11
11
  ],
12
- "version": "1.3.0",
12
+ "version": "1.5.0",
13
13
  "author": "LibirSoft",
14
14
  "repository": {
15
15
  "type": "git",
@@ -25,29 +25,35 @@
25
25
  "prepublishOnly": "bun run build",
26
26
  "benchmark": "bun run benchmark/run-benchmark.ts",
27
27
  "benchmark:native": "bun run benchmark/native-hono.ts",
28
- "benchmark:adapter": "bun run benchmark/hono-adapter.ts"
28
+ "benchmark:adapter": "bun run benchmark/hono-adapter.ts",
29
+ "lint": "eslint .",
30
+ "lint:fix": "eslint . --fix",
31
+ "format": "prettier --write .",
32
+ "format:check": "prettier --check .",
33
+ "check": "bun run lint && bun run format:check",
34
+ "check:fix": "bun run lint:fix && bun run format",
35
+ "changeset": "changeset",
36
+ "version": "changeset version",
37
+ "release": "bun run build && changeset publish"
29
38
  },
30
39
  "devDependencies": {
31
- "@changesets/cli": "^2.29.7",
40
+ "@asenajs/asena": "^0.7.0",
41
+ "@changesets/cli": "^2.30.0",
32
42
  "@types/bun": "latest",
33
- "@typescript-eslint/eslint-plugin": "^6.21.0",
34
- "eslint": "^8.57.1",
35
- "eslint-config-alloy": "^5.1.2",
43
+ "@typescript-eslint/eslint-plugin": "^8.58.0",
44
+ "@typescript-eslint/parser": "^8.58.0",
45
+ "eslint": "^9.39.4",
36
46
  "eslint-config-prettier": "^9.1.2",
37
- "eslint-plugin-alloy": "^1.2.1",
38
- "eslint-plugin-import": "^2.32.0",
39
- "eslint-plugin-n": "^16.6.2",
40
- "eslint-plugin-prettier": "^5.5.4",
41
- "eslint-plugin-promise": "^6.6.0",
42
- "prettier": "^3.6.2"
47
+ "prettier": "^3.8.1",
48
+ "typescript-eslint": "^8.58.0"
43
49
  },
44
50
  "peerDependencies": {
51
+ "@asenajs/asena": "^0.7.0",
45
52
  "typescript": "^5.8.2"
46
53
  },
47
54
  "dependencies": {
48
- "@asenajs/asena": "^0.5.0",
49
55
  "@hono/zod-validator": "^0.4.3",
50
- "hono": "^4.10.1",
51
- "zod": "^3.25.76"
56
+ "hono": "^4.12.9",
57
+ "zod": "^4.3.6"
52
58
  }
53
59
  }