better-call 0.2.13-beta.3 → 0.2.13-beta.5

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 CHANGED
@@ -1,3 +1,9 @@
1
1
  # Better Call
2
2
 
3
- A tiny TypeScript web framework that lets you create endpoints that can be called like regular functions, while also serving as REST API endpoints. It comes with a very fast router based on radix tree (rou3)[] compatible with different web servers (Node, Bun, NextJs, SvelteKit...), and an RPC client that ensures type-safe endpoint invocations.
3
+ A tiny TypeScript web framework that lets you create endpoints that can be called like regular functions, while also serving as REST API endpoints. It comes with a very fast router [rou3](https://github.com/unjs/rou3), and an RPC client powered by [better-fetch](https://better-fetch.vercel.app) and open API generator (experimental).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm i better-call
9
+ ```
@@ -1,7 +1,10 @@
1
1
  import { IncomingMessage, ServerResponse } from 'node:http';
2
2
  import * as undici_types from 'undici-types';
3
- import { R as Router } from '../shared/better-call.b80bf494.cjs';
3
+ import { R as Router } from '../shared/better-call.21658031.cjs';
4
4
  import 'zod';
5
+ import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
6
+ import '@asteasolutions/zod-to-openapi';
7
+ import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
5
8
  import 'stream/web';
6
9
 
7
10
  declare function getRequest({ request, base, bodySizeLimit, }: {
@@ -1,7 +1,10 @@
1
1
  import { IncomingMessage, ServerResponse } from 'node:http';
2
2
  import * as undici_types from 'undici-types';
3
- import { R as Router } from '../shared/better-call.b80bf494.mjs';
3
+ import { R as Router } from '../shared/better-call.21658031.mjs';
4
4
  import 'zod';
5
+ import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
6
+ import '@asteasolutions/zod-to-openapi';
7
+ import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
5
8
  import 'stream/web';
6
9
 
7
10
  declare function getRequest({ request, base, bodySizeLimit, }: {
@@ -1,7 +1,10 @@
1
1
  import { IncomingMessage, ServerResponse } from 'node:http';
2
2
  import * as undici_types from 'undici-types';
3
- import { R as Router } from '../shared/better-call.b80bf494.js';
3
+ import { R as Router } from '../shared/better-call.21658031.js';
4
4
  import 'zod';
5
+ import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
6
+ import '@asteasolutions/zod-to-openapi';
7
+ import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
5
8
  import 'stream/web';
6
9
 
7
10
  declare function getRequest({ request, base, bodySizeLimit, }: {
package/dist/client.d.cts CHANGED
@@ -1,7 +1,9 @@
1
- import * as undici_types from 'undici-types';
2
1
  import { BetterFetchOption, BetterFetchResponse } from '@better-fetch/fetch';
3
- import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.b80bf494.cjs';
2
+ import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.21658031.cjs';
4
3
  import 'zod';
4
+ import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
5
+ import '@asteasolutions/zod-to-openapi';
6
+ import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
5
7
  import 'stream/web';
6
8
 
7
9
  type HasRequired<T extends {
@@ -28,12 +30,10 @@ type RequiredOptionKeys<C extends {
28
30
  params: true;
29
31
  });
30
32
  declare const createClient: <R extends Router | Router["endpoints"]>(options: ClientOptions) => <OPT extends UnionToIntersection<(R extends {
31
- handler: (request: Request) => Promise<undici_types.Response>;
32
33
  endpoints: Record<string, Endpoint>;
33
34
  } ? R["endpoints"] : R) extends {
34
35
  [key: string]: infer T_1;
35
36
  } ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1; } : {} : {}> extends infer T ? { [K_1 in keyof T]: UnionToIntersection<(R extends {
36
- handler: (request: Request) => Promise<undici_types.Response>;
37
37
  endpoints: Record<string, Endpoint>;
38
38
  } ? R["endpoints"] : R) extends {
39
39
  [key: string]: infer T_1;
package/dist/client.d.mts CHANGED
@@ -1,7 +1,9 @@
1
- import * as undici_types from 'undici-types';
2
1
  import { BetterFetchOption, BetterFetchResponse } from '@better-fetch/fetch';
3
- import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.b80bf494.mjs';
2
+ import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.21658031.mjs';
4
3
  import 'zod';
4
+ import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
5
+ import '@asteasolutions/zod-to-openapi';
6
+ import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
5
7
  import 'stream/web';
6
8
 
7
9
  type HasRequired<T extends {
@@ -28,12 +30,10 @@ type RequiredOptionKeys<C extends {
28
30
  params: true;
29
31
  });
30
32
  declare const createClient: <R extends Router | Router["endpoints"]>(options: ClientOptions) => <OPT extends UnionToIntersection<(R extends {
31
- handler: (request: Request) => Promise<undici_types.Response>;
32
33
  endpoints: Record<string, Endpoint>;
33
34
  } ? R["endpoints"] : R) extends {
34
35
  [key: string]: infer T_1;
35
36
  } ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1; } : {} : {}> extends infer T ? { [K_1 in keyof T]: UnionToIntersection<(R extends {
36
- handler: (request: Request) => Promise<undici_types.Response>;
37
37
  endpoints: Record<string, Endpoint>;
38
38
  } ? R["endpoints"] : R) extends {
39
39
  [key: string]: infer T_1;
package/dist/client.d.ts CHANGED
@@ -1,7 +1,9 @@
1
- import * as undici_types from 'undici-types';
2
1
  import { BetterFetchOption, BetterFetchResponse } from '@better-fetch/fetch';
3
- import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.b80bf494.js';
2
+ import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.21658031.js';
4
3
  import 'zod';
4
+ import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
5
+ import '@asteasolutions/zod-to-openapi';
6
+ import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
5
7
  import 'stream/web';
6
8
 
7
9
  type HasRequired<T extends {
@@ -28,12 +30,10 @@ type RequiredOptionKeys<C extends {
28
30
  params: true;
29
31
  });
30
32
  declare const createClient: <R extends Router | Router["endpoints"]>(options: ClientOptions) => <OPT extends UnionToIntersection<(R extends {
31
- handler: (request: Request) => Promise<undici_types.Response>;
32
33
  endpoints: Record<string, Endpoint>;
33
34
  } ? R["endpoints"] : R) extends {
34
35
  [key: string]: infer T_1;
35
36
  } ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1; } : {} : {}> extends infer T ? { [K_1 in keyof T]: UnionToIntersection<(R extends {
36
- handler: (request: Request) => Promise<undici_types.Response>;
37
37
  endpoints: Record<string, Endpoint>;
38
38
  } ? R["endpoints"] : R) extends {
39
39
  [key: string]: infer T_1;
package/dist/index.cjs CHANGED
@@ -1,24 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  const crypto = require('uncrypto');
4
+ const zodToOpenapi = require('@asteasolutions/zod-to-openapi');
5
+ const zod = require('zod');
4
6
  const rou3 = require('rou3');
5
7
 
6
8
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
7
9
 
8
10
  const crypto__default = /*#__PURE__*/_interopDefaultCompat(crypto);
9
11
 
10
- function createJSON({ asResponse }) {
11
- return async function json(json, routerResponse) {
12
- if (!asResponse) {
13
- return json;
14
- }
15
- return {
16
- body: json,
17
- routerResponse,
18
- _flag: "json"
19
- };
20
- };
21
- }
22
12
  function runValidation(options, context) {
23
13
  let request = {
24
14
  body: void 0,
@@ -329,6 +319,17 @@ const getSignedCookie = async (header, secret, key, prefix) => {
329
319
  return obj[finalKey];
330
320
  };
331
321
 
322
+ function paramToZod(path) {
323
+ const parts = path.split("/");
324
+ const params = parts.filter((part) => part.startsWith(":"));
325
+ const zod$1 = zod.z.object({});
326
+ for (const param of params) {
327
+ zod$1.merge(zod.z.object({ [param.slice(1)]: zod.z.string() }));
328
+ }
329
+ return zod$1;
330
+ }
331
+
332
+ zodToOpenapi.extendZodWithOpenApi(zod.z);
332
333
  const createResponse = (handlerResponse, response) => {
333
334
  if (handlerResponse instanceof Response) {
334
335
  response.headers.forEach((value, key) => {
@@ -381,9 +382,16 @@ const createEndpoint = (path, options, handler) => {
381
382
  throw new APIError(error.message, 400);
382
383
  }
383
384
  const context = {
384
- json: createJSON({
385
- asResponse
386
- }),
385
+ json: (json, routerResponse) => {
386
+ if (!asResponse) {
387
+ return json;
388
+ }
389
+ return {
390
+ body: json,
391
+ routerResponse,
392
+ _flag: "json"
393
+ };
394
+ },
387
395
  body: "body" in data ? data.body : void 0,
388
396
  path,
389
397
  method: "method" in ctx ? ctx.method : void 0,
@@ -446,8 +454,66 @@ const createEndpoint = (path, options, handler) => {
446
454
  };
447
455
  internalHandler.path = path;
448
456
  internalHandler.options = options;
457
+ const registry = new zodToOpenapi.OpenAPIRegistry();
458
+ registry.registerPath({
459
+ path,
460
+ method: Array.isArray(options.method) ? options.method[0].toLowerCase() : options.method.toLowerCase(),
461
+ request: {
462
+ ...options.body ? {
463
+ body: {
464
+ content: {
465
+ "application/json": {
466
+ schema: options.body
467
+ }
468
+ }
469
+ }
470
+ } : {},
471
+ ...options.query ? {
472
+ query: options.query
473
+ } : {},
474
+ params: paramToZod(path)
475
+ },
476
+ responses: {
477
+ 200: {
478
+ description: "Successful response",
479
+ content: {
480
+ "application/json": {
481
+ schema: zod.z.record(zod.z.unknown())
482
+ }
483
+ }
484
+ },
485
+ 400: {
486
+ description: "Bad request",
487
+ content: {
488
+ "application/json": {
489
+ schema: zod.z.object({
490
+ message: zod.z.string()
491
+ })
492
+ }
493
+ }
494
+ },
495
+ ...options.openAPI?.responses
496
+ }
497
+ });
498
+ internalHandler.openAPI = {
499
+ definitions: registry.definitions
500
+ };
449
501
  return internalHandler;
450
502
  };
503
+ function createEndpointCreator(opts) {
504
+ return (path, options, handler) => {
505
+ const res = createEndpoint(
506
+ path,
507
+ {
508
+ ...options,
509
+ use: [...options?.use || [], ...opts?.use || []]
510
+ },
511
+ handler
512
+ );
513
+ return res;
514
+ };
515
+ }
516
+ createEndpoint.creator = createEndpointCreator;
451
517
 
452
518
  async function getBody(request) {
453
519
  const contentType = request.headers.get("content-type") || "";
@@ -644,10 +710,23 @@ function createMiddleware(optionsOrHandler, handler) {
644
710
  );
645
711
  return endpoint;
646
712
  }
713
+ function createMiddlewareCreator(opts) {
714
+ return (handler) => {
715
+ const res = createMiddleware(
716
+ {
717
+ method: "*",
718
+ use: opts.use
719
+ },
720
+ handler
721
+ );
722
+ return res;
723
+ };
724
+ }
725
+ createMiddleware.creator = createMiddlewareCreator;
647
726
 
727
+ exports.APIError = APIError;
648
728
  exports.createEndpoint = createEndpoint;
649
729
  exports.createGetHeader = createGetHeader;
650
- exports.createJSON = createJSON;
651
730
  exports.createMiddleware = createMiddleware;
652
731
  exports.createRouter = createRouter;
653
732
  exports.createSetHeader = createSetHeader;
package/dist/index.d.cts CHANGED
@@ -1,11 +1,28 @@
1
- import { E as EndpointOptions, a as EndpointResponse, b as Endpoint, c as EndpointContext, C as CookiePrefixOptions, d as CookieOptions } from './shared/better-call.b80bf494.cjs';
2
- export { i as Context, o as Cookie, p as CookieConstraint, H as HasRequiredKeys, l as InferResponse, I as Input, h as IsEmptyObject, J as JSONResponse, P as Prettify, g as RequiredKeysOf, R as Router, S as SignedCookie, U as UnionToIntersection, e as createEndpoint, k as createGetHeader, m as createJSON, f as createRouter, j as createSetHeader, n as fromError, q as parse, s as parseSigned, r as runValidation, t as serialize, u as serializeSigned } from './shared/better-call.b80bf494.cjs';
1
+ import { E as EndpointOptions, a as EndpointResponse, b as Endpoint, c as EndpointContext, I as InferUse, C as CookiePrefixOptions, d as CookieOptions } from './shared/better-call.21658031.cjs';
2
+ export { A as APIError, j as Context, o as Cookie, p as CookieConstraint, H as HasRequiredKeys, m as InferResponse, g as Input, i as IsEmptyObject, J as JSONResponse, P as Prettify, h as RequiredKeysOf, R as Router, S as SignedCookie, U as UnionToIntersection, e as createEndpoint, l as createGetHeader, f as createRouter, k as createSetHeader, n as fromError, q as parse, s as parseSigned, r as runValidation, t as serialize, u as serializeSigned } from './shared/better-call.21658031.cjs';
3
3
  import { BufferSource } from 'stream/web';
4
4
  import 'zod';
5
+ import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
6
+ import '@asteasolutions/zod-to-openapi';
7
+ import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
5
8
 
6
9
  type MiddlewareHandler<Options extends EndpointOptions, R extends EndpointResponse> = (context: EndpointContext<any, Options>) => Promise<R>;
7
10
  declare function createMiddleware<Opts extends EndpointOptions, R extends EndpointResponse>(optionsOrHandler: MiddlewareHandler<Opts, R>): Endpoint<MiddlewareHandler<Opts, R>, Opts>;
8
11
  declare function createMiddleware<Opts extends EndpointOptions, R extends EndpointResponse>(optionsOrHandler: Opts, handler: MiddlewareHandler<Opts, R>): Endpoint<MiddlewareHandler<Opts, R>, Opts>;
12
+ declare namespace createMiddleware {
13
+ var creator: typeof createMiddlewareCreator;
14
+ }
15
+ declare function createMiddlewareCreator<E extends {
16
+ use: Endpoint[];
17
+ }>(opts: E): <R extends EndpointResponse>(handler: <InferE extends EndpointContext<any, any>>(ctx: Omit<InferE, "context"> & {
18
+ context: InferUse<E["use"]>;
19
+ }) => Promise<R>) => Endpoint<MiddlewareHandler<{
20
+ method: "*";
21
+ use: Endpoint[];
22
+ }, R>, {
23
+ method: "*";
24
+ use: Endpoint[];
25
+ }>;
9
26
 
10
27
  declare const getCookie: (cookie: string, key: string, prefix?: CookiePrefixOptions) => string | undefined;
11
28
  declare const setCookie: (header: Headers, name: string, value: string, opt?: CookieOptions) => void;
package/dist/index.d.mts CHANGED
@@ -1,11 +1,28 @@
1
- import { E as EndpointOptions, a as EndpointResponse, b as Endpoint, c as EndpointContext, C as CookiePrefixOptions, d as CookieOptions } from './shared/better-call.b80bf494.mjs';
2
- export { i as Context, o as Cookie, p as CookieConstraint, H as HasRequiredKeys, l as InferResponse, I as Input, h as IsEmptyObject, J as JSONResponse, P as Prettify, g as RequiredKeysOf, R as Router, S as SignedCookie, U as UnionToIntersection, e as createEndpoint, k as createGetHeader, m as createJSON, f as createRouter, j as createSetHeader, n as fromError, q as parse, s as parseSigned, r as runValidation, t as serialize, u as serializeSigned } from './shared/better-call.b80bf494.mjs';
1
+ import { E as EndpointOptions, a as EndpointResponse, b as Endpoint, c as EndpointContext, I as InferUse, C as CookiePrefixOptions, d as CookieOptions } from './shared/better-call.21658031.mjs';
2
+ export { A as APIError, j as Context, o as Cookie, p as CookieConstraint, H as HasRequiredKeys, m as InferResponse, g as Input, i as IsEmptyObject, J as JSONResponse, P as Prettify, h as RequiredKeysOf, R as Router, S as SignedCookie, U as UnionToIntersection, e as createEndpoint, l as createGetHeader, f as createRouter, k as createSetHeader, n as fromError, q as parse, s as parseSigned, r as runValidation, t as serialize, u as serializeSigned } from './shared/better-call.21658031.mjs';
3
3
  import { BufferSource } from 'stream/web';
4
4
  import 'zod';
5
+ import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
6
+ import '@asteasolutions/zod-to-openapi';
7
+ import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
5
8
 
6
9
  type MiddlewareHandler<Options extends EndpointOptions, R extends EndpointResponse> = (context: EndpointContext<any, Options>) => Promise<R>;
7
10
  declare function createMiddleware<Opts extends EndpointOptions, R extends EndpointResponse>(optionsOrHandler: MiddlewareHandler<Opts, R>): Endpoint<MiddlewareHandler<Opts, R>, Opts>;
8
11
  declare function createMiddleware<Opts extends EndpointOptions, R extends EndpointResponse>(optionsOrHandler: Opts, handler: MiddlewareHandler<Opts, R>): Endpoint<MiddlewareHandler<Opts, R>, Opts>;
12
+ declare namespace createMiddleware {
13
+ var creator: typeof createMiddlewareCreator;
14
+ }
15
+ declare function createMiddlewareCreator<E extends {
16
+ use: Endpoint[];
17
+ }>(opts: E): <R extends EndpointResponse>(handler: <InferE extends EndpointContext<any, any>>(ctx: Omit<InferE, "context"> & {
18
+ context: InferUse<E["use"]>;
19
+ }) => Promise<R>) => Endpoint<MiddlewareHandler<{
20
+ method: "*";
21
+ use: Endpoint[];
22
+ }, R>, {
23
+ method: "*";
24
+ use: Endpoint[];
25
+ }>;
9
26
 
10
27
  declare const getCookie: (cookie: string, key: string, prefix?: CookiePrefixOptions) => string | undefined;
11
28
  declare const setCookie: (header: Headers, name: string, value: string, opt?: CookieOptions) => void;
package/dist/index.d.ts CHANGED
@@ -1,11 +1,28 @@
1
- import { E as EndpointOptions, a as EndpointResponse, b as Endpoint, c as EndpointContext, C as CookiePrefixOptions, d as CookieOptions } from './shared/better-call.b80bf494.js';
2
- export { i as Context, o as Cookie, p as CookieConstraint, H as HasRequiredKeys, l as InferResponse, I as Input, h as IsEmptyObject, J as JSONResponse, P as Prettify, g as RequiredKeysOf, R as Router, S as SignedCookie, U as UnionToIntersection, e as createEndpoint, k as createGetHeader, m as createJSON, f as createRouter, j as createSetHeader, n as fromError, q as parse, s as parseSigned, r as runValidation, t as serialize, u as serializeSigned } from './shared/better-call.b80bf494.js';
1
+ import { E as EndpointOptions, a as EndpointResponse, b as Endpoint, c as EndpointContext, I as InferUse, C as CookiePrefixOptions, d as CookieOptions } from './shared/better-call.21658031.js';
2
+ export { A as APIError, j as Context, o as Cookie, p as CookieConstraint, H as HasRequiredKeys, m as InferResponse, g as Input, i as IsEmptyObject, J as JSONResponse, P as Prettify, h as RequiredKeysOf, R as Router, S as SignedCookie, U as UnionToIntersection, e as createEndpoint, l as createGetHeader, f as createRouter, k as createSetHeader, n as fromError, q as parse, s as parseSigned, r as runValidation, t as serialize, u as serializeSigned } from './shared/better-call.21658031.js';
3
3
  import { BufferSource } from 'stream/web';
4
4
  import 'zod';
5
+ import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
6
+ import '@asteasolutions/zod-to-openapi';
7
+ import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
5
8
 
6
9
  type MiddlewareHandler<Options extends EndpointOptions, R extends EndpointResponse> = (context: EndpointContext<any, Options>) => Promise<R>;
7
10
  declare function createMiddleware<Opts extends EndpointOptions, R extends EndpointResponse>(optionsOrHandler: MiddlewareHandler<Opts, R>): Endpoint<MiddlewareHandler<Opts, R>, Opts>;
8
11
  declare function createMiddleware<Opts extends EndpointOptions, R extends EndpointResponse>(optionsOrHandler: Opts, handler: MiddlewareHandler<Opts, R>): Endpoint<MiddlewareHandler<Opts, R>, Opts>;
12
+ declare namespace createMiddleware {
13
+ var creator: typeof createMiddlewareCreator;
14
+ }
15
+ declare function createMiddlewareCreator<E extends {
16
+ use: Endpoint[];
17
+ }>(opts: E): <R extends EndpointResponse>(handler: <InferE extends EndpointContext<any, any>>(ctx: Omit<InferE, "context"> & {
18
+ context: InferUse<E["use"]>;
19
+ }) => Promise<R>) => Endpoint<MiddlewareHandler<{
20
+ method: "*";
21
+ use: Endpoint[];
22
+ }, R>, {
23
+ method: "*";
24
+ use: Endpoint[];
25
+ }>;
9
26
 
10
27
  declare const getCookie: (cookie: string, key: string, prefix?: CookiePrefixOptions) => string | undefined;
11
28
  declare const setCookie: (header: Headers, name: string, value: string, opt?: CookieOptions) => void;
package/dist/index.mjs CHANGED
@@ -1,18 +1,8 @@
1
1
  import crypto from 'uncrypto';
2
+ import { extendZodWithOpenApi, OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
3
+ import { z } from 'zod';
2
4
  import { createRouter as createRouter$1, addRoute, findRoute, findAllRoutes } from 'rou3';
3
5
 
4
- function createJSON({ asResponse }) {
5
- return async function json(json, routerResponse) {
6
- if (!asResponse) {
7
- return json;
8
- }
9
- return {
10
- body: json,
11
- routerResponse,
12
- _flag: "json"
13
- };
14
- };
15
- }
16
6
  function runValidation(options, context) {
17
7
  let request = {
18
8
  body: void 0,
@@ -323,6 +313,17 @@ const getSignedCookie = async (header, secret, key, prefix) => {
323
313
  return obj[finalKey];
324
314
  };
325
315
 
316
+ function paramToZod(path) {
317
+ const parts = path.split("/");
318
+ const params = parts.filter((part) => part.startsWith(":"));
319
+ const zod = z.object({});
320
+ for (const param of params) {
321
+ zod.merge(z.object({ [param.slice(1)]: z.string() }));
322
+ }
323
+ return zod;
324
+ }
325
+
326
+ extendZodWithOpenApi(z);
326
327
  const createResponse = (handlerResponse, response) => {
327
328
  if (handlerResponse instanceof Response) {
328
329
  response.headers.forEach((value, key) => {
@@ -375,9 +376,16 @@ const createEndpoint = (path, options, handler) => {
375
376
  throw new APIError(error.message, 400);
376
377
  }
377
378
  const context = {
378
- json: createJSON({
379
- asResponse
380
- }),
379
+ json: (json, routerResponse) => {
380
+ if (!asResponse) {
381
+ return json;
382
+ }
383
+ return {
384
+ body: json,
385
+ routerResponse,
386
+ _flag: "json"
387
+ };
388
+ },
381
389
  body: "body" in data ? data.body : void 0,
382
390
  path,
383
391
  method: "method" in ctx ? ctx.method : void 0,
@@ -440,8 +448,66 @@ const createEndpoint = (path, options, handler) => {
440
448
  };
441
449
  internalHandler.path = path;
442
450
  internalHandler.options = options;
451
+ const registry = new OpenAPIRegistry();
452
+ registry.registerPath({
453
+ path,
454
+ method: Array.isArray(options.method) ? options.method[0].toLowerCase() : options.method.toLowerCase(),
455
+ request: {
456
+ ...options.body ? {
457
+ body: {
458
+ content: {
459
+ "application/json": {
460
+ schema: options.body
461
+ }
462
+ }
463
+ }
464
+ } : {},
465
+ ...options.query ? {
466
+ query: options.query
467
+ } : {},
468
+ params: paramToZod(path)
469
+ },
470
+ responses: {
471
+ 200: {
472
+ description: "Successful response",
473
+ content: {
474
+ "application/json": {
475
+ schema: z.record(z.unknown())
476
+ }
477
+ }
478
+ },
479
+ 400: {
480
+ description: "Bad request",
481
+ content: {
482
+ "application/json": {
483
+ schema: z.object({
484
+ message: z.string()
485
+ })
486
+ }
487
+ }
488
+ },
489
+ ...options.openAPI?.responses
490
+ }
491
+ });
492
+ internalHandler.openAPI = {
493
+ definitions: registry.definitions
494
+ };
443
495
  return internalHandler;
444
496
  };
497
+ function createEndpointCreator(opts) {
498
+ return (path, options, handler) => {
499
+ const res = createEndpoint(
500
+ path,
501
+ {
502
+ ...options,
503
+ use: [...options?.use || [], ...opts?.use || []]
504
+ },
505
+ handler
506
+ );
507
+ return res;
508
+ };
509
+ }
510
+ createEndpoint.creator = createEndpointCreator;
445
511
 
446
512
  async function getBody(request) {
447
513
  const contentType = request.headers.get("content-type") || "";
@@ -638,5 +704,18 @@ function createMiddleware(optionsOrHandler, handler) {
638
704
  );
639
705
  return endpoint;
640
706
  }
707
+ function createMiddlewareCreator(opts) {
708
+ return (handler) => {
709
+ const res = createMiddleware(
710
+ {
711
+ method: "*",
712
+ use: opts.use
713
+ },
714
+ handler
715
+ );
716
+ return res;
717
+ };
718
+ }
719
+ createMiddleware.creator = createMiddlewareCreator;
641
720
 
642
- export { createEndpoint, createGetHeader, createJSON, createMiddleware, createRouter, createSetHeader, fromError, getCookie, getSignedCookie, parse, parseSigned, runValidation, serialize, serializeSigned, setCookie, setSignedCookie };
721
+ export { APIError, createEndpoint, createGetHeader, createMiddleware, createRouter, createSetHeader, fromError, getCookie, getSignedCookie, parse, parseSigned, runValidation, serialize, serializeSigned, setCookie, setSignedCookie };