@asenajs/hono-adapter 1.4.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.
- package/README.md +2 -2
- package/dist/lib/HonoAdapter.d.ts +41 -4
- package/dist/lib/HonoAdapter.js +166 -48
- package/dist/lib/HonoAdapter.js.map +1 -1
- package/dist/lib/HonoContextWrapper.d.ts +16 -3
- package/dist/lib/HonoContextWrapper.js +77 -2
- package/dist/lib/HonoContextWrapper.js.map +1 -1
- package/dist/lib/HonoWebsocketAdapter.d.ts +2 -16
- package/dist/lib/HonoWebsocketAdapter.js +20 -48
- package/dist/lib/HonoWebsocketAdapter.js.map +1 -1
- package/dist/lib/defaults/ValidationService.d.ts +4 -4
- package/dist/lib/middlewares/CorsMiddleware.d.ts +1 -1
- package/dist/lib/middlewares/CorsMiddleware.js +5 -6
- package/dist/lib/middlewares/CorsMiddleware.js.map +1 -1
- package/dist/lib/middlewares/RateLimiterMiddleware.d.ts +1 -1
- package/dist/lib/middlewares/RateLimiterMiddleware.js +9 -7
- package/dist/lib/middlewares/RateLimiterMiddleware.js.map +1 -1
- package/dist/lib/types/HonoAdapterOptions.d.ts +27 -0
- package/dist/lib/types/HonoAdapterOptions.js +2 -0
- package/dist/lib/types/HonoAdapterOptions.js.map +1 -0
- package/dist/lib/types/SendPingStrategy.d.ts +4 -0
- package/dist/lib/types/SendPingStrategy.js +2 -0
- package/dist/lib/types/SendPingStrategy.js.map +1 -0
- package/dist/lib/types/index.d.ts +2 -0
- package/dist/lib/types/index.js +2 -0
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/utils/createHonoAdapter.d.ts +2 -1
- package/dist/lib/utils/createHonoAdapter.js +9 -1
- package/dist/lib/utils/createHonoAdapter.js.map +1 -1
- package/dist/lib/utils/middlewareParser.d.ts +5 -1
- package/dist/lib/utils/middlewareParser.js +16 -6
- package/dist/lib/utils/middlewareParser.js.map +1 -1
- package/dist/lib/utils/routePriority.d.ts +40 -0
- package/dist/lib/utils/routePriority.js +75 -0
- package/dist/lib/utils/routePriority.js.map +1 -0
- package/dist/test/utils/testHelpers.d.ts +61 -0
- package/dist/test/utils/testHelpers.js +109 -0
- package/dist/test/utils/testHelpers.js.map +1 -0
- package/package.json +16 -13
|
@@ -5,8 +5,11 @@ 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) {
|
|
@@ -17,21 +20,28 @@ export const middlewareParser = (middlewares) => {
|
|
|
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 });
|
|
29
34
|
return;
|
|
30
35
|
}
|
|
31
|
-
// If middleware returns Response,
|
|
32
|
-
//
|
|
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.
|
|
33
39
|
if (result instanceof Response) {
|
|
34
|
-
|
|
40
|
+
context.res = new Response(result.body, {
|
|
41
|
+
status: result.status,
|
|
42
|
+
headers: result.headers,
|
|
43
|
+
});
|
|
44
|
+
return;
|
|
35
45
|
}
|
|
36
46
|
// If middleware didn't call next(), we call it here
|
|
37
47
|
// Note: Hono middleware should handle next() calls properly
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middlewareParser.js","sourceRoot":"","sources":["../../../lib/utils/middlewareParser.ts"],"names":[],"mappings":"
|
|
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.
|
|
12
|
+
"version": "1.5.0",
|
|
13
13
|
"author": "LibirSoft",
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
@@ -31,26 +31,29 @@
|
|
|
31
31
|
"format": "prettier --write .",
|
|
32
32
|
"format:check": "prettier --check .",
|
|
33
33
|
"check": "bun run lint && bun run format:check",
|
|
34
|
-
"check:fix": "bun run lint:fix && bun run format"
|
|
34
|
+
"check:fix": "bun run lint:fix && bun run format",
|
|
35
|
+
"changeset": "changeset",
|
|
36
|
+
"version": "changeset version",
|
|
37
|
+
"release": "bun run build && changeset publish"
|
|
35
38
|
},
|
|
36
39
|
"devDependencies": {
|
|
37
|
-
"@asenajs/asena": "
|
|
38
|
-
"@changesets/cli": "^2.
|
|
40
|
+
"@asenajs/asena": "^0.7.0",
|
|
41
|
+
"@changesets/cli": "^2.30.0",
|
|
39
42
|
"@types/bun": "latest",
|
|
40
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
41
|
-
"@typescript-eslint/parser": "^8.
|
|
42
|
-
"eslint": "^9.
|
|
43
|
+
"@typescript-eslint/eslint-plugin": "^8.58.0",
|
|
44
|
+
"@typescript-eslint/parser": "^8.58.0",
|
|
45
|
+
"eslint": "^9.39.4",
|
|
43
46
|
"eslint-config-prettier": "^9.1.2",
|
|
44
|
-
"prettier": "^3.
|
|
45
|
-
"typescript-eslint": "^8.
|
|
47
|
+
"prettier": "^3.8.1",
|
|
48
|
+
"typescript-eslint": "^8.58.0"
|
|
46
49
|
},
|
|
47
50
|
"peerDependencies": {
|
|
48
|
-
"@asenajs/asena": "^0.
|
|
51
|
+
"@asenajs/asena": "^0.7.0",
|
|
49
52
|
"typescript": "^5.8.2"
|
|
50
53
|
},
|
|
51
54
|
"dependencies": {
|
|
52
55
|
"@hono/zod-validator": "^0.4.3",
|
|
53
|
-
"hono": "^4.
|
|
54
|
-
"zod": "^3.
|
|
56
|
+
"hono": "^4.12.9",
|
|
57
|
+
"zod": "^4.3.6"
|
|
55
58
|
}
|
|
56
|
-
}
|
|
59
|
+
}
|