ts-typed-api 0.2.13 → 0.2.15

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/dist/handler.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { ApiDefinitionSchema } from "./definition";
2
2
  import { createRouteHandler } from "./router";
3
+ import { MiddlewareResponse } from "./object-handlers";
3
4
  import express from "express";
4
5
  export type SpecificRouteHandler<TDef extends ApiDefinitionSchema> = {
5
6
  [TDomain_ in keyof TDef['endpoints']]: {
6
7
  [TRouteKey_ in keyof TDef['endpoints'][TDomain_]]: ReturnType<typeof createRouteHandler<TDef, TDomain_, TRouteKey_>>;
7
8
  }[keyof TDef['endpoints'][TDomain_]];
8
9
  }[keyof TDef['endpoints']];
9
- export type EndpointMiddleware<TDef extends ApiDefinitionSchema = ApiDefinitionSchema> = (req: express.Request, res: express.Response, next: express.NextFunction, endpointInfo: {
10
+ export type EndpointMiddleware<TDef extends ApiDefinitionSchema = ApiDefinitionSchema> = (req: express.Request, res: MiddlewareResponse, next: express.NextFunction, endpointInfo: {
10
11
  [TDomain in keyof TDef['endpoints']]: {
11
12
  domain: TDomain;
12
13
  routeKey: keyof TDef['endpoints'][TDomain];
package/dist/handler.js CHANGED
@@ -302,7 +302,7 @@ middlewares) {
302
302
  baseUrl: expressReq.baseUrl,
303
303
  url: expressReq.url,
304
304
  };
305
- // Augment expressRes with the .respond method, using TDef
305
+ // Augment expressRes with the .respond and .setHeader methods, using TDef
306
306
  const typedExpressRes = expressRes;
307
307
  typedExpressRes.respond = (status, dataForResponse) => {
308
308
  // Use the passed apiDefinition object
@@ -347,6 +347,11 @@ middlewares) {
347
347
  });
348
348
  }
349
349
  };
350
+ typedExpressRes.setHeader = (name, value) => {
351
+ // Call the original Express setHeader method to avoid recursion
352
+ Object.getPrototypeOf(expressRes).setHeader.call(expressRes, name, value);
353
+ return typedExpressRes;
354
+ };
350
355
  const specificHandlerFn = handler;
351
356
  await specificHandlerFn(finalTypedReq, typedExpressRes);
352
357
  }
@@ -412,10 +417,11 @@ middlewares) {
412
417
  const wrappedMiddleware = async (req, res, next) => {
413
418
  try {
414
419
  // Add respond method to res for middleware compatibility
415
- res.respond = createRespondFunction(routeDefinition, (status, data) => {
420
+ const middlewareRes = res;
421
+ middlewareRes.respond = createRespondFunction(routeDefinition, (status, data) => {
416
422
  res.status(status).json(data);
417
423
  });
418
- await middleware(req, res, next, { domain: currentDomain, routeKey: currentRouteKey });
424
+ await middleware(req, middlewareRes, next, { domain: currentDomain, routeKey: currentRouteKey });
419
425
  }
420
426
  catch (error) {
421
427
  next(error);
@@ -329,7 +329,11 @@ function registerHonoRouteHandlers(app, apiDefinition, routeHandlers, middleware
329
329
  originalUrl: c.req.url
330
330
  };
331
331
  const fakeRes = {
332
- respond: c.respond
332
+ respond: c.respond,
333
+ setHeader: (name, value) => {
334
+ c.header(name, value);
335
+ return fakeRes;
336
+ }
333
337
  };
334
338
  const specificHandlerFn = handler;
335
339
  await specificHandlerFn(fakeReq, fakeRes);
@@ -457,6 +461,20 @@ function registerHonoRouteHandlers(app, apiDefinition, routeHandlers, middleware
457
461
  error: [{ field: "general", type: "general", message: "Internal server error: Constructed response failed validation." }]
458
462
  }, 500);
459
463
  }
464
+ },
465
+ status: (status) => {
466
+ // For middleware that might use status, but since not used, stub
467
+ c.__response = new Response(null, { status: status });
468
+ },
469
+ json: (data) => {
470
+ // Send json response
471
+ c.__response = c.json(data);
472
+ },
473
+ setHeader: (name, value) => {
474
+ c.header(name, value);
475
+ },
476
+ end: () => {
477
+ // Perhaps do nothing or set response
460
478
  }
461
479
  };
462
480
  // Call Express-style middleware
@@ -7,15 +7,22 @@ export type EndpointInfo<TDef extends ApiDefinitionSchema = ApiDefinitionSchema>
7
7
  routeKey: keyof TDef['endpoints'][TDomain];
8
8
  };
9
9
  }[keyof TDef['endpoints']];
10
- export type EndpointMiddleware<TDef extends ApiDefinitionSchema = ApiDefinitionSchema> = (req: express.Request, res: express.Response, next: express.NextFunction, endpointInfo: EndpointInfo<TDef>) => void | Promise<void>;
11
- export type SimpleMiddleware = (req: express.Request, res: express.Response, next: express.NextFunction) => void | Promise<void>;
12
- export type UniversalEndpointMiddleware = (req: express.Request, res: express.Response, next: express.NextFunction, endpointInfo: {
10
+ export type EndpointMiddleware<TDef extends ApiDefinitionSchema = ApiDefinitionSchema> = (req: express.Request, res: MiddlewareResponse, next: express.NextFunction, endpointInfo: EndpointInfo<TDef>) => void | Promise<void>;
11
+ export type SimpleMiddleware = (req: express.Request, res: MiddlewareResponse, next: express.NextFunction) => void | Promise<void>;
12
+ export type UniversalEndpointMiddleware = (req: express.Request, res: MiddlewareResponse, next: express.NextFunction, endpointInfo: {
13
13
  domain: string;
14
14
  routeKey: string;
15
15
  }) => void | Promise<void>;
16
+ export interface MiddlewareResponse {
17
+ respond(status: number, data: any): void;
18
+ status(code: number): this;
19
+ json(data: any): void;
20
+ setHeader(name: string, value: string): void;
21
+ end(): void;
22
+ }
16
23
  export type EndpointMiddlewareCtx<Ctx extends Record<string, any> = Record<string, any>, TDef extends ApiDefinitionSchema = ApiDefinitionSchema> = ((req: express.Request & {
17
24
  ctx?: Ctx;
18
- }, res: express.Response, next: express.NextFunction, endpointInfo: EndpointInfo<TDef>) => void | Promise<void>) | ((c: any, next: any) => void | Promise<void>);
25
+ }, res: MiddlewareResponse, next: express.NextFunction, endpointInfo: EndpointInfo<TDef>) => void | Promise<void>) | ((c: any, next: any) => void | Promise<void>);
19
26
  export type AnyMiddleware<TDef extends ApiDefinitionSchema = ApiDefinitionSchema> = EndpointMiddleware<TDef> | UniversalEndpointMiddleware | SimpleMiddleware;
20
27
  type HandlerFunction<TDef extends ApiDefinitionSchema, TDomain extends keyof TDef['endpoints'], TRouteKey extends keyof TDef['endpoints'][TDomain], Ctx extends Record<string, any> = Record<string, any>> = (req: TypedRequest<TDef, TDomain, TRouteKey, ApiParams<TDef, TDomain, TRouteKey>, ApiBody<TDef, TDomain, TRouteKey>, ApiQuery<TDef, TDomain, TRouteKey>, Record<string, any>, Ctx>, res: TypedResponse<TDef, TDomain, TRouteKey>) => Promise<void> | void;
21
28
  export type ObjectHandlers<TDef extends ApiDefinitionSchema, Ctx extends Record<string, any> = Record<string, any>> = {
package/dist/router.d.ts CHANGED
@@ -14,6 +14,7 @@ type ResponseDataForStatus<TDef extends ApiDefinitionSchema, TDomain extends key
14
14
  type RespondFunction<TDef extends ApiDefinitionSchema, TDomain extends keyof TDef['endpoints'], TRouteName extends keyof TDef['endpoints'][TDomain]> = <TStatusLocal extends keyof TDef['endpoints'][TDomain][TRouteName]['responses'] & number>(status: TStatusLocal, data: ResponseDataForStatus<TDef, TDomain, TRouteName, TStatusLocal>) => void;
15
15
  export interface TypedResponse<TDef extends ApiDefinitionSchema, TDomain extends keyof TDef['endpoints'], TRouteName extends keyof TDef['endpoints'][TDomain], L extends Record<string, any> = Record<string, any>> extends express.Response<any, L> {
16
16
  respond: RespondFunction<TDef, TDomain, TRouteName>;
17
+ setHeader: (name: string, value: string) => this;
17
18
  json: <B = any>(body: B) => this;
18
19
  }
19
20
  export declare function createRouteHandler<TDef extends ApiDefinitionSchema, TDomain extends keyof TDef['endpoints'], TRouteKey extends keyof TDef['endpoints'][TDomain], // Using direct keyof for simplicity
@@ -34,6 +34,15 @@ export const PublicApiDefinition = CreateApiDefinition({
34
34
  200: z.enum(["pong"]),
35
35
  })
36
36
  },
37
+ customHeaders: {
38
+ method: 'GET',
39
+ path: '/custom-headers',
40
+ responses: CreateResponses({
41
+ 200: z.object({
42
+ message: z.string()
43
+ }),
44
+ })
45
+ },
37
46
  }
38
47
  }
39
48
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-typed-api",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
4
4
  "description": "A lightweight, type-safe RPC library for TypeScript with Zod validation",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/handler.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { ApiDefinitionSchema, RouteSchema, UnifiedError, FileUploadConfig } from "./definition";
3
3
  import { createRouteHandler, TypedRequest, TypedResponse } from "./router";
4
+ import { MiddlewareResponse } from "./object-handlers";
4
5
  import express from "express";
5
6
  import multer from "multer";
6
7
 
@@ -16,7 +17,7 @@ export type SpecificRouteHandler<TDef extends ApiDefinitionSchema> = {
16
17
  // Type for middleware function that receives endpoint information with type safety
17
18
  export type EndpointMiddleware<TDef extends ApiDefinitionSchema = ApiDefinitionSchema> = (
18
19
  req: express.Request,
19
- res: express.Response,
20
+ res: MiddlewareResponse,
20
21
  next: express.NextFunction,
21
22
  endpointInfo: {
22
23
  [TDomain in keyof TDef['endpoints']]: {
@@ -354,7 +355,7 @@ export function registerRouteHandlers<TDef extends ApiDefinitionSchema>(
354
355
  url: expressReq.url,
355
356
  } as TypedRequest<TDef, typeof currentDomain, typeof currentRouteKey>;
356
357
 
357
- // Augment expressRes with the .respond method, using TDef
358
+ // Augment expressRes with the .respond and .setHeader methods, using TDef
358
359
  const typedExpressRes = expressRes as TypedResponse<TDef, typeof currentDomain, typeof currentRouteKey>;
359
360
 
360
361
  typedExpressRes.respond = (status, dataForResponse) => {
@@ -407,6 +408,12 @@ export function registerRouteHandlers<TDef extends ApiDefinitionSchema>(
407
408
  }
408
409
  };
409
410
 
411
+ typedExpressRes.setHeader = (name: string, value: string) => {
412
+ // Call the original Express setHeader method to avoid recursion
413
+ Object.getPrototypeOf(expressRes).setHeader.call(expressRes, name, value);
414
+ return typedExpressRes;
415
+ };
416
+
410
417
  const specificHandlerFn = handler as (
411
418
  req: TypedRequest<TDef, typeof currentDomain, typeof currentRouteKey>,
412
419
  res: TypedResponse<TDef, typeof currentDomain, typeof currentRouteKey>
@@ -474,10 +481,11 @@ export function registerRouteHandlers<TDef extends ApiDefinitionSchema>(
474
481
  const wrappedMiddleware: express.RequestHandler = async (req, res, next) => {
475
482
  try {
476
483
  // Add respond method to res for middleware compatibility
477
- (res as any).respond = createRespondFunction(routeDefinition, (status, data) => {
484
+ const middlewareRes = res as any;
485
+ middlewareRes.respond = createRespondFunction(routeDefinition, (status, data) => {
478
486
  res.status(status).json(data);
479
487
  });
480
- await middleware(req, res, next, { domain: currentDomain, routeKey: currentRouteKey } as any);
488
+ await middleware(req, middlewareRes as MiddlewareResponse, next, { domain: currentDomain, routeKey: currentRouteKey } as any);
481
489
  } catch (error) {
482
490
  next(error);
483
491
  }
@@ -407,7 +407,11 @@ export function registerHonoRouteHandlers<
407
407
  } as TypedRequest<TDef, typeof currentDomain, typeof currentRouteKey>;
408
408
 
409
409
  const fakeRes = {
410
- respond: (c as any).respond
410
+ respond: (c as any).respond,
411
+ setHeader: (name: string, value: string) => {
412
+ c.header(name, value);
413
+ return fakeRes;
414
+ }
411
415
  } as TypedResponse<TDef, typeof currentDomain, typeof currentRouteKey>;
412
416
 
413
417
  const specificHandlerFn = handler as (
@@ -546,6 +550,20 @@ export function registerHonoRouteHandlers<
546
550
  error: [{ field: "general", type: "general", message: "Internal server error: Constructed response failed validation." }]
547
551
  }, 500);
548
552
  }
553
+ },
554
+ status: (status: number) => {
555
+ // For middleware that might use status, but since not used, stub
556
+ (c as any).__response = new Response(null, { status: status });
557
+ },
558
+ json: (data: any) => {
559
+ // Send json response
560
+ (c as any).__response = c.json(data);
561
+ },
562
+ setHeader: (name: string, value: string) => {
563
+ c.header(name, value);
564
+ },
565
+ end: () => {
566
+ // Perhaps do nothing or set response
549
567
  }
550
568
  };
551
569
 
@@ -13,7 +13,7 @@ export type EndpointInfo<TDef extends ApiDefinitionSchema = ApiDefinitionSchema>
13
13
  // Type for middleware function that receives endpoint information
14
14
  export type EndpointMiddleware<TDef extends ApiDefinitionSchema = ApiDefinitionSchema> = (
15
15
  req: express.Request,
16
- res: express.Response,
16
+ res: MiddlewareResponse,
17
17
  next: express.NextFunction,
18
18
  endpointInfo: EndpointInfo<TDef>
19
19
  ) => void | Promise<void>;
@@ -21,14 +21,14 @@ export type EndpointMiddleware<TDef extends ApiDefinitionSchema = ApiDefinitionS
21
21
  // Type for simple middleware that doesn't need endpoint information
22
22
  export type SimpleMiddleware = (
23
23
  req: express.Request,
24
- res: express.Response,
24
+ res: MiddlewareResponse,
25
25
  next: express.NextFunction
26
26
  ) => void | Promise<void>;
27
27
 
28
28
  // Type for middleware that can work with any API definition
29
29
  export type UniversalEndpointMiddleware = (
30
30
  req: express.Request,
31
- res: express.Response,
31
+ res: MiddlewareResponse,
32
32
  next: express.NextFunction,
33
33
  endpointInfo: {
34
34
  domain: string;
@@ -36,13 +36,22 @@ export type UniversalEndpointMiddleware = (
36
36
  }
37
37
  ) => void | Promise<void>;
38
38
 
39
+ // Custom response interface for framework-agnostic middleware
40
+ export interface MiddlewareResponse {
41
+ respond(status: number, data: any): void;
42
+ status(code: number): this;
43
+ json(data: any): void;
44
+ setHeader(name: string, value: string): void;
45
+ end(): void;
46
+ }
47
+
39
48
  // Unified middleware type that works for both Express and Hono with context typing
40
49
  export type EndpointMiddlewareCtx<
41
50
  Ctx extends Record<string, any> = Record<string, any>,
42
51
  TDef extends ApiDefinitionSchema = ApiDefinitionSchema
43
52
  > =
44
53
  // Express version: (req, res, next, endpointInfo)
45
- ((req: express.Request & { ctx?: Ctx }, res: express.Response, next: express.NextFunction, endpointInfo: EndpointInfo<TDef>) => void | Promise<void>) |
54
+ ((req: express.Request & { ctx?: Ctx }, res: MiddlewareResponse, next: express.NextFunction, endpointInfo: EndpointInfo<TDef>) => void | Promise<void>) |
46
55
  // Hono version: (c, next) - context is passed via c.req.ctx -> c.ctx copying
47
56
  ((c: any, next: any) => void | Promise<void>);
48
57
 
package/src/router.ts CHANGED
@@ -59,6 +59,7 @@ export interface TypedResponse<
59
59
  L extends Record<string, any> = Record<string, any>
60
60
  > extends express.Response<any, L> {
61
61
  respond: RespondFunction<TDef, TDomain, TRouteName>;
62
+ setHeader: (name: string, value: string) => this;
62
63
  json: <B = any>(body: B) => this; // Keep original json
63
64
  }
64
65
 
package/tests/setup.ts CHANGED
@@ -7,12 +7,18 @@ import { PublicApiDefinition as SimplePublicApiDefinition, PrivateApiDefinition
7
7
  import { PublicApiDefinition as AdvancedPublicApiDefinition, PrivateApiDefinition as AdvancedPrivateApiDefinition } from '../examples/advanced/definitions';
8
8
  import { RegisterHandlers, RegisterHonoHandlers, CreateApiDefinition, CreateResponses, CreateTypedHonoHandlerWithContext } from '../src';
9
9
  import { z } from 'zod';
10
+ import { EndpointMiddlewareCtx } from '../src/object-handlers';
10
11
 
11
12
  // Shared handler definitions for simple API
12
13
  const simplePublicHandlers = {
13
14
  common: {
14
15
  ping: async (req: any, res: any) => {
15
16
  res.respond(200, "pong");
17
+ },
18
+ customHeaders: async (req: any, res: any) => {
19
+ res.setHeader('X-Custom-Test', 'test-value');
20
+ res.setHeader('X-Another-Header', 'another-value');
21
+ res.respond(200, { message: "headers set" });
16
22
  }
17
23
  },
18
24
  status: {
@@ -444,7 +450,7 @@ async function startHonoServer(): Promise<void> {
444
450
  });
445
451
  }
446
452
 
447
- type Ctx = { user?: string; noAuth?: boolean; forbidden?: boolean }
453
+ type Ctx = { user?: string; noAuth?: boolean; forbidden?: boolean, middlewareData?: string }
448
454
 
449
455
  // Shared handlers for middleware tests
450
456
  const middlewareTestHandlers = {
@@ -471,74 +477,45 @@ const middlewareTestHandlers = {
471
477
  // Generic middleware setup function
472
478
  function setupMiddlewareApp(app: any, isHono: boolean) {
473
479
  // Define middleware functions
474
- const loggingMiddleware = isHono ?
475
- async (req: any, res: any, next: any, endpointInfo: any) => {
476
- console.log(`[Test Hono] ${req.method} ${req.path} - Domain: ${endpointInfo.domain}, Route: ${endpointInfo.routeKey}`);
477
- await next();
478
- } :
479
- (req: express.Request, res: express.Response, next: express.NextFunction, endpointInfo: any) => {
480
- console.log(`[Test] ${req.method} ${req.path} - Domain: ${endpointInfo.domain}, Route: ${endpointInfo.routeKey}`);
481
- next();
482
- };
483
-
484
- const contextMiddleware = isHono ?
485
- async (req: any, res: any, next: any) => {
486
- req.ctx = { ...req.ctx, middlewareData: "middleware-added-data" };
487
- await next();
488
- } :
489
- (req: express.Request, res: express.Response, next: express.NextFunction) => {
490
- (req as any).ctx = { middlewareData: "middleware-added-data" };
491
- next();
492
- };
493
-
494
- const authMiddleware = isHono ?
495
- async (req: any, res: any, next: any, endpointInfo: any) => {
496
- // Only apply auth checks to protected routes
497
- if (endpointInfo.domain === 'public' && endpointInfo.routeKey === 'protected') {
498
- const authHeader = req.headers?.authorization;
499
- if (!authHeader) {
500
- (res as any).respond(401, { error: "No authorization header" });
501
- } else if (authHeader === 'Bearer valid-token') {
502
- req.ctx = { ...req.ctx, user: 'testuser' };
503
- await next();
504
- } else {
505
- (res as any).respond(403, { error: "Forbidden" });
506
- }
507
- } else {
480
+ const loggingMiddleware: EndpointMiddlewareCtx<Ctx> = async (req, res, next, endpointInfo) => {
481
+ console.log(`[Test] ${req.method} ${req.path} - Domain: ${endpointInfo.domain}, Route: ${endpointInfo.routeKey}`);
482
+ await next();
483
+ }
484
+
485
+ const contextMiddleware: EndpointMiddlewareCtx<Ctx> = async (req, res, next) => {
486
+ req.ctx = { ...req.ctx, middlewareData: "middleware-added-data" };
487
+ await next();
488
+ }
489
+
490
+ const authMiddleware: EndpointMiddlewareCtx<Ctx> = async (req, res, next, endpointInfo) => {
491
+ // Only apply auth checks to protected routes
492
+ if (endpointInfo.domain === 'public' && endpointInfo.routeKey === 'protected') {
493
+ const authHeader = req.headers?.authorization;
494
+ if (!authHeader) {
495
+ res.respond(401, { error: "No authorization header" });
496
+ } else if (authHeader === 'Bearer valid-token') {
497
+ req.ctx = { ...req.ctx, user: 'testuser' };
508
498
  await next();
509
- }
510
- } :
511
- (req: any, res: any, next: any, endpointInfo: any) => {
512
- // Only apply auth checks to protected routes
513
- if (endpointInfo.domain === 'public' && endpointInfo.routeKey === 'protected') {
514
- const authHeader = req.headers?.authorization;
515
- if (!authHeader) {
516
- (res as any).respond(401, { error: "No authorization header" });
517
- } else if (authHeader === 'Bearer valid-token') {
518
- req.ctx = { ...req.ctx, user: 'testuser' };
519
- next();
520
- } else {
521
- (res as any).respond(403, { error: "Forbidden" });
522
- }
523
499
  } else {
524
- next();
500
+ res.respond(403, { error: "Forbidden" });
525
501
  }
526
- };
502
+ } else {
503
+ await next();
504
+ }
505
+ }
506
+
507
+ const middlewares = [
508
+ loggingMiddleware,
509
+ contextMiddleware,
510
+ authMiddleware
511
+ ]
527
512
 
528
513
  // Register handlers with middleware
529
514
  if (isHono) {
530
515
  const hndl = CreateTypedHonoHandlerWithContext<Ctx>();
531
- hndl(app, MiddlewareTestApiDefinition, middlewareTestHandlers, [
532
- loggingMiddleware,
533
- contextMiddleware,
534
- authMiddleware
535
- ]);
516
+ hndl(app, MiddlewareTestApiDefinition, middlewareTestHandlers, middlewares);
536
517
  } else {
537
- RegisterHandlers(app, MiddlewareTestApiDefinition, middlewareTestHandlers, [
538
- loggingMiddleware,
539
- contextMiddleware,
540
- authMiddleware
541
- ]);
518
+ RegisterHandlers(app, MiddlewareTestApiDefinition, middlewareTestHandlers, middlewares);
542
519
  }
543
520
  }
544
521
 
@@ -74,6 +74,39 @@ describe.each([
74
74
 
75
75
  expect(result).toBe('pong');
76
76
  });
77
+
78
+ test('should set response headers', async () => {
79
+ // Direct HTTP call to test header setting
80
+ const response = await fetch(`${baseUrl}/api/v1/public/ping`);
81
+ const contentType = response.headers.get('content-type');
82
+
83
+ // Check that standard headers are set
84
+ if (serverName === 'Express') {
85
+ expect(contentType).toBe('application/json; charset=utf-8');
86
+ } else {
87
+ // Hono sets content-type differently
88
+ expect(contentType).toBe('application/json');
89
+ }
90
+ expect(response.status).toBe(200);
91
+ });
92
+
93
+ test('should set custom headers', async () => {
94
+ // Direct HTTP call to test custom header setting
95
+ const response = await fetch(`${baseUrl}/api/v1/public/custom-headers`);
96
+ const data = await response.json();
97
+
98
+ // Check response data (unified response format)
99
+ expect(data.data).toEqual({ message: "headers set" });
100
+ expect(data).not.toHaveProperty('error'); // Error should not be present for success responses
101
+ expect(response.status).toBe(200);
102
+
103
+ // Check custom headers
104
+ const customHeader = response.headers.get('x-custom-test');
105
+ const anotherHeader = response.headers.get('x-another-header');
106
+
107
+ expect(customHeader).toBe('test-value');
108
+ expect(anotherHeader).toBe('another-value');
109
+ });
77
110
  });
78
111
 
79
112
  describe('Private API', () => {