@cleverbrush/server 4.0.0 → 4.2.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 +72 -0
- package/dist/CacheTag.d.ts +76 -0
- package/dist/Endpoint.d.ts +173 -39
- package/dist/Server.d.ts +1 -0
- package/dist/Subscription.d.ts +7 -0
- package/dist/chunk-BNRQFILU.js +2 -0
- package/dist/chunk-BNRQFILU.js.map +1 -0
- package/dist/contract.d.ts +2 -0
- package/dist/contract.js +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/middlewares/Idempotency.d.ts +52 -0
- package/dist/middlewares/ResponseCache.d.ts +50 -0
- package/dist/types.d.ts +45 -0
- package/package.json +6 -4
- package/dist/chunk-RQOGR2EW.js +0 -2
- package/dist/chunk-RQOGR2EW.js.map +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side idempotency middleware.
|
|
3
|
+
*
|
|
4
|
+
* Ensures mutating requests with the same idempotency key produce the
|
|
5
|
+
* same result exactly once — subsequent replays return the stored
|
|
6
|
+
* response without re-executing the handler.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import type { RequestContext } from '../RequestContext.js';
|
|
11
|
+
import type { Middleware } from '../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for {@link idempotency}.
|
|
14
|
+
*/
|
|
15
|
+
export interface ServerIdempotencyOptions {
|
|
16
|
+
/**
|
|
17
|
+
* TTL in milliseconds for stored responses.
|
|
18
|
+
* Defaults to `86_400_000` (24 hours).
|
|
19
|
+
*/
|
|
20
|
+
ttl?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Header name to read the idempotency key from.
|
|
23
|
+
* Defaults to `"x-idempotency-key"`.
|
|
24
|
+
*/
|
|
25
|
+
headerName?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Predicate that decides whether a request should be skipped.
|
|
28
|
+
* Defaults to skipping non-mutating requests (GET, HEAD, OPTIONS).
|
|
29
|
+
*/
|
|
30
|
+
skip?: (ctx: RequestContext) => boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Server-side idempotency middleware.
|
|
34
|
+
*
|
|
35
|
+
* Reads the `x-idempotency-key` header from mutating requests. If a
|
|
36
|
+
* response has already been stored for that key, it is returned
|
|
37
|
+
* immediately — the handler is never called. Otherwise the handler
|
|
38
|
+
* executes and its response is stored for future replays.
|
|
39
|
+
*
|
|
40
|
+
* GET, HEAD, and OPTIONS requests pass through without checking.
|
|
41
|
+
*
|
|
42
|
+
* @param options - Configuration.
|
|
43
|
+
* @returns A server-side {@link Middleware}.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* server.handle(CreateTodo, createHandler, {
|
|
48
|
+
* middlewares: [idempotency({ ttl: 86_400_000 })]
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function idempotency(options?: ServerIdempotencyOptions): Middleware;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side cache response middleware.
|
|
3
|
+
*
|
|
4
|
+
* Caches successful handler responses keyed by endpoint-defined cache tags.
|
|
5
|
+
* On cache hit, the response is served directly — the handler never runs.
|
|
6
|
+
* Mutating requests invalidate matching cache entries after the handler
|
|
7
|
+
* completes successfully.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import type { Middleware } from '../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for {@link cacheResponse}.
|
|
14
|
+
*/
|
|
15
|
+
export interface ServerCacheOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Default TTL in milliseconds for tags without an explicit TTL.
|
|
18
|
+
* Defaults to `60000` (60 seconds).
|
|
19
|
+
*/
|
|
20
|
+
defaultTtl?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Per-tag TTL overrides: `{ [tagName]: ttlMs }`.
|
|
23
|
+
*/
|
|
24
|
+
ttlByTag?: Record<string, number>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Server-side cache response middleware.
|
|
28
|
+
*
|
|
29
|
+
* Uses cache-tag definitions from the matched endpoint (already available
|
|
30
|
+
* on `ctx.items.__endpoint_meta.cacheTags`) to compute deterministic cache
|
|
31
|
+
* keys from request data (params, query, body, headers).
|
|
32
|
+
*
|
|
33
|
+
* - **GET**: Computes cache key → serves cached response if valid →
|
|
34
|
+
* handler never executes. On cache miss, runs the handler and caches
|
|
35
|
+
* the response.
|
|
36
|
+
* - **Mutation (POST/PUT/PATCH/DELETE)**: Lets the handler run, then
|
|
37
|
+
* invalidates all cache entries whose key starts with any of the
|
|
38
|
+
* endpoint's cache tag names.
|
|
39
|
+
*
|
|
40
|
+
* @param options - Cache configuration.
|
|
41
|
+
* @returns A server-side {@link Middleware}.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* server.handle(ListTodos, listHandler, {
|
|
46
|
+
* middlewares: [cacheResponse({ defaultTtl: 30_000 })]
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function cacheResponse(options?: ServerCacheOptions): Middleware;
|
package/dist/types.d.ts
CHANGED
|
@@ -83,6 +83,51 @@ export interface ServerOptions {
|
|
|
83
83
|
*/
|
|
84
84
|
readonly maxBodySize?: number;
|
|
85
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Represents a single uploaded file from a `multipart/form-data` request.
|
|
88
|
+
*/
|
|
89
|
+
export interface FilePart {
|
|
90
|
+
/** Original filename as provided by the client. */
|
|
91
|
+
readonly filename: string;
|
|
92
|
+
/** MIME type of the file (e.g. `'image/jpeg'`). */
|
|
93
|
+
readonly mimeType: string;
|
|
94
|
+
/** Full file contents as a Buffer. */
|
|
95
|
+
readonly buffer: Buffer;
|
|
96
|
+
/** File size in bytes. */
|
|
97
|
+
readonly size: number;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Describes a file that was rejected during multipart parsing.
|
|
101
|
+
*/
|
|
102
|
+
export interface RejectedFile {
|
|
103
|
+
/** Original filename as provided by the client. */
|
|
104
|
+
readonly filename: string;
|
|
105
|
+
/** MIME type of the file (e.g. `'application/xlsx'`). */
|
|
106
|
+
readonly mimeType: string;
|
|
107
|
+
/** Human-readable reason the file was rejected. */
|
|
108
|
+
readonly reason: string;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Configuration for file upload endpoints declared via
|
|
112
|
+
* `EndpointBuilder.upload()`.
|
|
113
|
+
*/
|
|
114
|
+
export interface UploadOptions {
|
|
115
|
+
/**
|
|
116
|
+
* Maximum allowed file size per uploaded file in bytes.
|
|
117
|
+
* @default 10_485_760 (10 MB)
|
|
118
|
+
*/
|
|
119
|
+
maxFileSize?: number;
|
|
120
|
+
/**
|
|
121
|
+
* Allowed MIME types or patterns (e.g. `'image/*'`, `'application/pdf'`).
|
|
122
|
+
* When not set, all MIME types are accepted.
|
|
123
|
+
*/
|
|
124
|
+
allowedMimeTypes?: string[];
|
|
125
|
+
/**
|
|
126
|
+
* Maximum number of files allowed in a single request.
|
|
127
|
+
* @default 10
|
|
128
|
+
*/
|
|
129
|
+
maxFileCount?: number;
|
|
130
|
+
}
|
|
86
131
|
/**
|
|
87
132
|
* Configuration for the server-side request batching endpoint, enabled via
|
|
88
133
|
* `ServerBuilder.useBatching()`.
|
package/package.json
CHANGED
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
"email": "andrew_zol@cleverbrush.com"
|
|
6
6
|
},
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@cleverbrush/auth": "^4.
|
|
9
|
-
"@cleverbrush/di": "^4.
|
|
10
|
-
"@cleverbrush/schema": "^4.
|
|
8
|
+
"@cleverbrush/auth": "^4.2.0",
|
|
9
|
+
"@cleverbrush/di": "^4.2.0",
|
|
10
|
+
"@cleverbrush/schema": "^4.2.0",
|
|
11
|
+
"@fastify/busboy": "^3.2.0",
|
|
11
12
|
"ws": "^8.20.0"
|
|
12
13
|
},
|
|
13
14
|
"devDependencies": {
|
|
15
|
+
"@types/busboy": "1.5.4",
|
|
14
16
|
"@types/ws": "^8.18.1"
|
|
15
17
|
},
|
|
16
18
|
"description": "Schema-first HTTP server framework — schema-driven controllers, DI, auto-validation, RFC 9457 errors",
|
|
@@ -53,5 +55,5 @@
|
|
|
53
55
|
},
|
|
54
56
|
"type": "module",
|
|
55
57
|
"types": "./dist/index.d.ts",
|
|
56
|
-
"version": "4.
|
|
58
|
+
"version": "4.2.0"
|
|
57
59
|
}
|
package/dist/chunk-RQOGR2EW.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var g=Symbol.for("cleverbrush.tracked");function w(n,e){return{[g]:!0,id:n,data:e}}function F(n){return n!==null&&typeof n=="object"&&g in n&&n[g]===!0}var c=class n{#a;#t;#s;#r;#o;#y;#l;#n;#d;#h;#u;#c;#p;#i;constructor(e,t="/",s=null,a=null,o=null,y=null,r=null,d=null,l=null,h=null,u=[],T=null,m=!1,S=null){this.#a=e,this.#t=t,this.#s=s,this.#r=a,this.#o=o,this.#y=y,this.#l=r,this.#n=d,this.#d=l,this.#h=h,this.#u=u,this.#c=T,this.#p=m,this.#i=S}#e(e){return new n(e.basePath??this.#a,e.pathTemplate??this.#t,e.incomingSchema!==void 0?e.incomingSchema:this.#s,e.outgoingSchema!==void 0?e.outgoingSchema:this.#r,e.querySchema!==void 0?e.querySchema:this.#o,e.headerSchema!==void 0?e.headerSchema:this.#y,e.serviceSchemas!==void 0?e.serviceSchemas:this.#l,e.authRoles!==void 0?e.authRoles:this.#n,e.summary!==void 0?e.summary:this.#d,e.description!==void 0?e.description:this.#h,e.tags??this.#u,e.operationId!==void 0?e.operationId:this.#c,e.deprecated??this.#p,e.externalDocs!==void 0?e.externalDocs:this.#i)}incoming(e){return this.#e({incomingSchema:e})}outgoing(e){return this.#e({outgoingSchema:e})}query(e){return this.#e({querySchema:e})}headers(e){return this.#e({headerSchema:e})}inject(e){return this.#e({serviceSchemas:e})}authorize(...e){let t;e.length>0&&typeof e[0]=="object"&&e[0]!==null&&"introspect"in e[0]?t=e.slice(1):t=e;let s=this.#n?[...this.#n,...t]:t;return this.#e({authRoles:s})}summary(e){return this.#e({summary:e})}description(e){return this.#e({description:e})}tags(...e){return this.#e({tags:e})}operationId(e){return this.#e({operationId:e})}deprecated(){return this.#e({deprecated:!0})}externalDocs(e,t){return this.#e({externalDocs:{url:e,description:t}})}introspect(){return{protocol:"subscription",basePath:this.#a,pathTemplate:this.#t,incomingSchema:this.#s,outgoingSchema:this.#r,querySchema:this.#o,headerSchema:this.#y,serviceSchemas:this.#l,authRoles:this.#n,summary:this.#d,description:this.#h,tags:this.#u,operationId:this.#c,deprecated:this.#p,externalDocs:this.#i}}};function R(n,e){return new c(n,e??"/")}function f(n){return n instanceof c}function z(n,e){let t=[],s=[];for(let a of Object.keys(n)){let o=n[a],y=e[a];for(let r of Object.keys(o)){let d=o[r],l=y[r],h=typeof l=="function"?l:l.handler,u=typeof l=="function"?void 0:l.middlewares;f(d)?s.push({endpoint:d,handler:h,middlewares:u}):t.push({endpoint:d,handler:h,middlewares:u})}}return{_entries:t,_subscriptions:s}}var p=class n{#a;#t;#s;#r;#o;#y;#l;#n;#d;#h;#u;#c;#p;#i;#e;#T;#m;#S;#g;#R;#f;#B;#P;constructor(e,t,s,a,o,y,r=null,d=null,l=null,h=null,u=[],T=null,m=!1,S=null,x=null,E=null,H=null,k=null,O=null,A=null,v=null,j=null,I=null){this.#a=e,this.#t=t,this.#s=s,this.#r=a,this.#o=o,this.#y=y,this.#l=r,this.#n=d,this.#d=l,this.#h=h,this.#u=u,this.#c=T,this.#p=m,this.#i=S,this.#e=x,this.#T=E,this.#m=H,this.#S=k,this.#g=O,this.#R=A,this.#f=v,this.#B=j,this.#P=I}body(e){return new n(this.#a,this.#t,this.#s,e,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}query(e){return new n(this.#a,this.#t,this.#s,this.#r,e,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}headers(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,e,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}inject(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,e,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}authorize(...e){let t;e.length>0&&typeof e[0]=="object"&&e[0]!==null&&"introspect"in e[0]?t=e.slice(1):t=e;let s=this.#n?[...this.#n,...t]:t;return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,s,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}returns(e){let t=e!=null&&typeof e=="object"&&"introspect"in e?e:null;return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,t??this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}responses(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}summary(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,e,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}description(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,e,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}tags(...e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,e,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}operationId(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,e,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}deprecated(){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,!0,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}example(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,e,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}examples(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,e,this.#S,this.#g,this.#R,this.#f,this.#B,this.#P)}producesFile(e,t){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,{contentType:e,description:t},this.#g,this.#R,this.#f,this.#B,this.#P)}get path(){let e=this.#t,t=this.#s,s;if(typeof t=="string")s=t;else{let{literals:a,segments:o}=t.introspect().templateDefinition,y="";for(let r=0;r<o.length;r++)y+=a[r]+`:${o[r].path}`;y+=a[o.length]??"",s=y}return s==="/"?e||"/":e+s}introspect(){return{method:this.#a,basePath:this.#t,pathTemplate:this.#s,bodySchema:this.#r,querySchema:this.#o,headerSchema:this.#y,serviceSchemas:this.#l,authRoles:this.#n,summary:this.#d,description:this.#h,tags:this.#u,operationId:this.#c,deprecated:this.#p,responseSchema:this.#i,responsesSchemas:this.#e,example:this.#T,examples:this.#m,producesFile:this.#S,produces:this.#g,responseHeaderSchema:this.#R,externalDocs:this.#f,links:this.#B,callbacks:this.#P}}produces(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,e,this.#R,this.#f,this.#B,this.#P)}responseHeaders(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,e,this.#f,this.#B,this.#P)}externalDocs(e,t){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,{url:e,description:t},this.#B,this.#P)}links(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,e,this.#P)}callbacks(e){return new n(this.#a,this.#t,this.#s,this.#r,this.#o,this.#y,this.#l,this.#n,this.#d,this.#h,this.#u,this.#c,this.#p,this.#i,this.#e,this.#T,this.#m,this.#S,this.#g,this.#R,this.#f,this.#B,e)}};function i(n,e,t,s,a){return new p(n,e,t??"/",null,null,null,null,s??null,a?.summary??null,a?.description??null,a?.tags??[],a?.operationId??null,a?.deprecated??!1,null,null,null,null,null,null,null)}function B(n,e){return{get:t=>i("GET",n,t,e),post:t=>i("POST",n,t,e),put:t=>i("PUT",n,t,e),patch:t=>i("PATCH",n,t,e),delete:t=>i("DELETE",n,t,e),head:t=>i("HEAD",n,t,e),options:t=>i("OPTIONS",n,t,e)}}function K(n){return{...B(n,null),authorize(...e){let t;return e.length>0&&typeof e[0]=="object"&&e[0]!==null&&"introspect"in e[0]?t=e.slice(1):t=e,B(n,t)}}}function C(n){return P}var P={get:(n,e)=>i("GET",n,e),post:(n,e)=>i("POST",n,e),put:(n,e)=>i("PUT",n,e),patch:(n,e)=>i("PATCH",n,e),delete:(n,e)=>i("DELETE",n,e),head:(n,e)=>i("HEAD",n,e),options:(n,e)=>i("OPTIONS",n,e),resource:K,subscription:(n,e)=>R(n,e)};import{object as Q,parseString as D}from"@cleverbrush/schema";function b(n){let e=Q(n);return((t,...s)=>D(e,a=>a(t,...s)))}function M(n,...e){return n!=null&&Array.isArray(n.raw)?b({})(n):b(n??{})}function U(n){for(let e of Object.values(n))Object.freeze(e);return Object.freeze(n)}function Y(n,e){let t={};for(let s of Object.keys(n))t[s]={...n[s]};for(let s of Object.keys(e))Object.hasOwn(t,s)?t[s]={...t[s],...e[s]}:t[s]={...e[s]};for(let s of Object.values(t))Object.freeze(s);return Object.freeze(t)}function $(n,...e){let t={};for(let s of e)t[s]=n[s],Object.freeze(t[s]);return Object.freeze(t)}function V(n,...e){let t=new Set(e),s={};for(let a of Object.keys(n))t.has(a)||(s[a]=n[a],Object.freeze(s[a]));return Object.freeze(s)}export{w as a,F as b,c,z as d,p as e,C as f,P as g,M as h,U as i,Y as j,$ as k,V as l};
|
|
2
|
-
//# sourceMappingURL=chunk-RQOGR2EW.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Subscription.ts","../src/Endpoint.ts","../src/route.ts","../src/contract.ts"],"sourcesContent":["import type {\n InferType,\n ObjectSchemaBuilder,\n ParseStringSchemaBuilder,\n SchemaBuilder\n} from '@cleverbrush/schema';\nimport type { RequestContext } from './RequestContext.js';\nimport type { Middleware } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Simplify — flattens intersection types for clean IDE tooltips\n// ---------------------------------------------------------------------------\n\ntype Simplify<T> = { [K in keyof T]: T[K] } & {};\n\n// ---------------------------------------------------------------------------\n// tracked() — resumable event wrapper\n// ---------------------------------------------------------------------------\n\nconst TRACKED_SYMBOL = Symbol.for('cleverbrush.tracked');\n\n/**\n * A server-sent event wrapped with a unique ID for resumable subscriptions.\n *\n * When a client reconnects, it can send the last received event ID so the\n * server resumes from that point instead of replaying everything.\n *\n * @see {@link tracked}\n */\nexport interface TrackedEvent<T = unknown> {\n /** @internal Brand marker. */\n readonly [TRACKED_SYMBOL]: true;\n /** Unique event identifier for resume tracking. */\n readonly id: string;\n /** The actual event payload. */\n readonly data: T;\n}\n\n/**\n * Wrap a server-sent event with a unique ID for resumable subscriptions.\n *\n * When a handler yields a `TrackedEvent`, the server sends the event with its\n * ID. If the client disconnects and reconnects with the last received ID,\n * the handler can skip already-delivered events.\n *\n * @param id - A unique, monotonically increasing identifier for this event.\n * @param data - The event payload to send to the client.\n * @returns A {@link TrackedEvent} wrapper.\n *\n * @example\n * ```ts\n * async function* handler({ incoming }) {\n * yield tracked('evt-1', { message: 'Hello' });\n * yield tracked('evt-2', { message: 'World' });\n * }\n * ```\n */\nexport function tracked<T>(id: string, data: T): TrackedEvent<T> {\n return { [TRACKED_SYMBOL]: true, id, data };\n}\n\n/**\n * Check whether a value is a {@link TrackedEvent}.\n * @internal\n */\nexport function isTrackedEvent(value: unknown): value is TrackedEvent {\n return (\n value !== null &&\n typeof value === 'object' &&\n TRACKED_SYMBOL in value &&\n (value as any)[TRACKED_SYMBOL] === true\n );\n}\n\n// ---------------------------------------------------------------------------\n// SubscriptionContext — the typed argument for subscription handlers\n// ---------------------------------------------------------------------------\n\ntype HasKeys<T> = keyof T extends never ? false : true;\n\ntype SubscriptionContextParts<\n TParams,\n TQuery,\n THeaders,\n TPrincipal,\n TIncoming\n> = {\n context: RequestContext;\n signal: AbortSignal;\n} & (HasKeys<TParams> extends true ? { params: TParams } : {}) &\n (HasKeys<TQuery> extends true ? { query: TQuery } : {}) &\n (HasKeys<THeaders> extends true ? { headers: THeaders } : {}) &\n (TPrincipal extends undefined ? {} : { principal: TPrincipal }) &\n ([TIncoming] extends [undefined]\n ? {}\n : {\n incoming: AsyncIterable<\n TIncoming extends SchemaBuilder<any, any, any, any, any>\n ? InferType<TIncoming>\n : TIncoming\n >;\n });\n\n/**\n * The fully-typed argument object passed to subscription handlers.\n *\n * The shape is inferred from the `SubscriptionBuilder` chain — only the keys\n * actually configured (query, headers, params, principal, incoming) are present.\n * Always includes `context` ({@link RequestContext}) and `signal` ({@link AbortSignal}).\n */\nexport type SubscriptionContext<E> =\n E extends SubscriptionBuilder<\n infer TParams,\n infer TQuery,\n infer THeaders,\n any,\n infer TPrincipal,\n any,\n infer TIncoming,\n any\n >\n ? Simplify<\n SubscriptionContextParts<\n TParams,\n TQuery,\n THeaders,\n TPrincipal,\n TIncoming\n >\n >\n : never;\n\n// ---------------------------------------------------------------------------\n// InferServices — maps { name: SchemaBuilder } to { name: InferType<Schema> }\n// ---------------------------------------------------------------------------\n\ntype InferServices<T> = {\n [K in keyof T]: T[K] extends SchemaBuilder<any, any, any, any, any>\n ? InferType<T[K]>\n : never;\n};\n\n/**\n * Extracts the injected service schemas map from a `SubscriptionBuilder`.\n */\nexport type SubscriptionServiceSchemas<E> =\n E extends SubscriptionBuilder<\n any,\n any,\n any,\n infer TServices,\n any,\n any,\n any,\n any\n >\n ? TServices\n : {};\n\n// ---------------------------------------------------------------------------\n// InferOutgoing — extracts the outgoing event type\n// ---------------------------------------------------------------------------\n\ntype OutgoingType<E> =\n E extends SubscriptionBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n infer TOutgoing\n >\n ? TOutgoing extends SchemaBuilder<any, any, any, any, any>\n ? InferType<TOutgoing> | TrackedEvent<InferType<TOutgoing>>\n : TOutgoing | TrackedEvent<TOutgoing>\n : any;\n\n// ---------------------------------------------------------------------------\n// SubscriptionHandler — the async generator function type\n// ---------------------------------------------------------------------------\n\n/**\n * The handler function type inferred from a `SubscriptionBuilder`.\n *\n * Must be an async generator that yields outgoing events. When the endpoint\n * has injected services, the handler receives a second `services` argument.\n *\n * @example\n * ```ts\n * const handler: SubscriptionHandler<typeof chatEndpoint> =\n * async function* ({ incoming, principal }) {\n * yield tracked('welcome', { text: 'Hello!' });\n * for await (const msg of incoming) {\n * yield { text: `${principal.name}: ${msg.text}` };\n * }\n * };\n * ```\n */\nexport type SubscriptionHandler<E> =\n HasKeys<SubscriptionServiceSchemas<E>> extends true\n ? (\n arg: SubscriptionContext<E>,\n services: Simplify<InferServices<SubscriptionServiceSchemas<E>>>\n ) => AsyncGenerator<OutgoingType<E>>\n : (arg: SubscriptionContext<E>) => AsyncGenerator<OutgoingType<E>>;\n\n// ---------------------------------------------------------------------------\n// SubscriptionMetadata — runtime introspection snapshot\n// ---------------------------------------------------------------------------\n\ntype RoutePath = string | ParseStringSchemaBuilder<any, any, any, any, any>;\n\n/**\n * Snapshot of all configuration set on a `SubscriptionBuilder`.\n * Used by the server for WebSocket upgrade handling and by documentation\n * generators for AsyncAPI / OpenAPI spec output.\n */\nexport interface SubscriptionMetadata {\n /** Always `'subscription'`. Distinguishes from HTTP endpoint metadata. */\n readonly protocol: 'subscription';\n readonly basePath: string;\n readonly pathTemplate: RoutePath;\n readonly incomingSchema: SchemaBuilder<any, any, any, any, any> | null;\n readonly outgoingSchema: SchemaBuilder<any, any, any, any, any> | null;\n readonly querySchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n readonly headerSchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n readonly serviceSchemas: Record<\n string,\n SchemaBuilder<any, any, any, any, any>\n > | null;\n readonly authRoles: readonly string[] | null;\n readonly summary: string | null;\n readonly description: string | null;\n readonly tags: readonly string[];\n readonly operationId: string | null;\n readonly deprecated: boolean;\n readonly externalDocs: { url: string; description?: string } | null;\n}\n\n// ---------------------------------------------------------------------------\n// SubscriptionBuilder — immutable builder for WebSocket subscription endpoints\n// ---------------------------------------------------------------------------\n\n/**\n * Immutable, fluent builder for WebSocket subscription endpoint definitions.\n *\n * All methods return a new builder instance — the original is never mutated.\n * Use `endpoint.subscription()` to obtain the first builder in the chain.\n *\n * @example\n * ```ts\n * const ChatRoom = endpoint\n * .subscription('/ws/chat')\n * .incoming(object({ text: string() }))\n * .outgoing(object({ user: string(), text: string(), timestamp: number() }))\n * .authorize(PrincipalSchema)\n * .summary('Real-time chat room');\n * ```\n */\nexport class SubscriptionBuilder<\n TParams = {},\n TQuery = {},\n THeaders = {},\n TServices = {},\n TPrincipal = undefined,\n TRoles extends string = string,\n TIncoming = undefined,\n TOutgoing = undefined\n> {\n readonly #basePath: string;\n readonly #pathTemplate: RoutePath;\n readonly #incomingSchema: SchemaBuilder<any, any, any, any, any> | null;\n readonly #outgoingSchema: SchemaBuilder<any, any, any, any, any> | null;\n readonly #querySchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n readonly #headerSchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n readonly #serviceSchemas: Record<\n string,\n SchemaBuilder<any, any, any, any, any>\n > | null;\n readonly #authRoles: readonly string[] | null;\n readonly #summary: string | null;\n readonly #description: string | null;\n readonly #tags: readonly string[];\n readonly #operationId: string | null;\n readonly #deprecated: boolean;\n readonly #externalDocs: { url: string; description?: string } | null;\n\n constructor(\n basePath: string,\n pathTemplate: RoutePath = '/',\n incomingSchema: SchemaBuilder<any, any, any, any, any> | null = null,\n outgoingSchema: SchemaBuilder<any, any, any, any, any> | null = null,\n querySchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null = null,\n headerSchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null = null,\n serviceSchemas: Record<\n string,\n SchemaBuilder<any, any, any, any, any>\n > | null = null,\n authRoles: readonly string[] | null = null,\n summary: string | null = null,\n description: string | null = null,\n tags: readonly string[] = [],\n operationId: string | null = null,\n deprecated: boolean = false,\n externalDocs: { url: string; description?: string } | null = null\n ) {\n this.#basePath = basePath;\n this.#pathTemplate = pathTemplate;\n this.#incomingSchema = incomingSchema;\n this.#outgoingSchema = outgoingSchema;\n this.#querySchema = querySchema;\n this.#headerSchema = headerSchema;\n this.#serviceSchemas = serviceSchemas;\n this.#authRoles = authRoles;\n this.#summary = summary;\n this.#description = description;\n this.#tags = tags;\n this.#operationId = operationId;\n this.#deprecated = deprecated;\n this.#externalDocs = externalDocs;\n }\n\n // -- Helper to clone with one field changed ---------------------------------\n\n #clone(\n overrides: Partial<{\n basePath: string;\n pathTemplate: RoutePath;\n incomingSchema: SchemaBuilder<any, any, any, any, any> | null;\n outgoingSchema: SchemaBuilder<any, any, any, any, any> | null;\n querySchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n headerSchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n serviceSchemas: Record<\n string,\n SchemaBuilder<any, any, any, any, any>\n > | null;\n authRoles: readonly string[] | null;\n summary: string | null;\n description: string | null;\n tags: readonly string[];\n operationId: string | null;\n deprecated: boolean;\n externalDocs: { url: string; description?: string } | null;\n }>\n ): SubscriptionBuilder<any, any, any, any, any, any, any, any> {\n return new SubscriptionBuilder(\n overrides.basePath ?? this.#basePath,\n overrides.pathTemplate ?? this.#pathTemplate,\n overrides.incomingSchema !== undefined\n ? overrides.incomingSchema\n : this.#incomingSchema,\n overrides.outgoingSchema !== undefined\n ? overrides.outgoingSchema\n : this.#outgoingSchema,\n overrides.querySchema !== undefined\n ? overrides.querySchema\n : this.#querySchema,\n overrides.headerSchema !== undefined\n ? overrides.headerSchema\n : this.#headerSchema,\n overrides.serviceSchemas !== undefined\n ? overrides.serviceSchemas\n : this.#serviceSchemas,\n overrides.authRoles !== undefined\n ? overrides.authRoles\n : this.#authRoles,\n overrides.summary !== undefined ? overrides.summary : this.#summary,\n overrides.description !== undefined\n ? overrides.description\n : this.#description,\n overrides.tags ?? this.#tags,\n overrides.operationId !== undefined\n ? overrides.operationId\n : this.#operationId,\n overrides.deprecated ?? this.#deprecated,\n overrides.externalDocs !== undefined\n ? overrides.externalDocs\n : this.#externalDocs\n );\n }\n\n /**\n * Define the schema for client→server messages.\n * Messages that do not match this schema are rejected with an error frame.\n */\n incoming<TSchema extends SchemaBuilder<any, any, any, any, any>>(\n schema: TSchema\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TSchema,\n TOutgoing\n > {\n return this.#clone({ incomingSchema: schema }) as any;\n }\n\n /**\n * Define the schema for server→client events.\n * All yielded values are validated against this schema before sending.\n */\n outgoing<TSchema extends SchemaBuilder<any, any, any, any, any>>(\n schema: TSchema\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TIncoming,\n TSchema\n > {\n return this.#clone({ outgoingSchema: schema }) as any;\n }\n\n /** Define the query string schema for the WebSocket upgrade URL. */\n query<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n >(\n schema: TSchema\n ): SubscriptionBuilder<\n TParams,\n InferType<TSchema>,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TIncoming,\n TOutgoing\n > {\n return this.#clone({ querySchema: schema }) as any;\n }\n\n /** Define expected headers on the WebSocket upgrade request. */\n headers<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n >(\n schema: TSchema\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n InferType<TSchema>,\n TServices,\n TPrincipal,\n TRoles,\n TIncoming,\n TOutgoing\n > {\n return this.#clone({ headerSchema: schema }) as any;\n }\n\n /** Declare DI services to be resolved per-connection and passed as the second handler argument. */\n inject<\n TSchemas extends Record<string, SchemaBuilder<any, any, any, any, any>>\n >(\n schemas: TSchemas\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TSchemas,\n TPrincipal,\n TRoles,\n TIncoming,\n TOutgoing\n > {\n return this.#clone({ serviceSchemas: schemas }) as any;\n }\n\n /**\n * Mark this subscription as requiring authorization.\n *\n * Overloads:\n * - `authorize(principalSchema, ...roles)` — typed principal, optional role requirements\n * - `authorize(...roles)` — untyped principal (`unknown`), optional role requirements\n */\n authorize<TSchema extends SchemaBuilder<any, any, any, any, any>>(\n principalSchema: TSchema,\n ...roles: TRoles[]\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TServices,\n InferType<TSchema>,\n TRoles,\n TIncoming,\n TOutgoing\n >;\n authorize(\n ...roles: TRoles[]\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TServices,\n unknown,\n TRoles,\n TIncoming,\n TOutgoing\n >;\n authorize(\n ...args: unknown[]\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TServices,\n any,\n TRoles,\n TIncoming,\n TOutgoing\n > {\n let roles: string[];\n if (\n args.length > 0 &&\n typeof args[0] === 'object' &&\n args[0] !== null &&\n 'introspect' in args[0]\n ) {\n roles = args.slice(1) as string[];\n } else {\n roles = args as string[];\n }\n const merged = this.#authRoles ? [...this.#authRoles, ...roles] : roles;\n return this.#clone({ authRoles: merged }) as any;\n }\n\n /** Short, human-readable summary for documentation. */\n summary(\n text: string\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TIncoming,\n TOutgoing\n > {\n return this.#clone({ summary: text }) as any;\n }\n\n /** Longer description for documentation. Supports Markdown. */\n description(\n text: string\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TIncoming,\n TOutgoing\n > {\n return this.#clone({ description: text }) as any;\n }\n\n /** Documentation tags for grouping. */\n tags(\n ...tags: string[]\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TIncoming,\n TOutgoing\n > {\n return this.#clone({ tags }) as any;\n }\n\n /** A unique, stable identifier for documentation. */\n operationId(\n id: string\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TIncoming,\n TOutgoing\n > {\n return this.#clone({ operationId: id }) as any;\n }\n\n /** Mark this subscription as deprecated in documentation. */\n deprecated(): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TIncoming,\n TOutgoing\n > {\n return this.#clone({ deprecated: true }) as any;\n }\n\n /** Link external documentation. */\n externalDocs(\n url: string,\n description?: string\n ): SubscriptionBuilder<\n TParams,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TIncoming,\n TOutgoing\n > {\n return this.#clone({ externalDocs: { url, description } }) as any;\n }\n\n /** Return an immutable snapshot of this builder's configuration as {@link SubscriptionMetadata}. */\n introspect(): SubscriptionMetadata {\n return {\n protocol: 'subscription',\n basePath: this.#basePath,\n pathTemplate: this.#pathTemplate,\n incomingSchema: this.#incomingSchema,\n outgoingSchema: this.#outgoingSchema,\n querySchema: this.#querySchema,\n headerSchema: this.#headerSchema,\n serviceSchemas: this.#serviceSchemas,\n authRoles: this.#authRoles,\n summary: this.#summary,\n description: this.#description,\n tags: this.#tags,\n operationId: this.#operationId,\n deprecated: this.#deprecated,\n externalDocs: this.#externalDocs\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Subscription handler mapping types\n// ---------------------------------------------------------------------------\n\ntype AnySubscription = SubscriptionBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>;\n\n/**\n * A single handler entry for a subscription in a handler map.\n *\n * Either a bare handler function or an object with a `handler` function\n * and optional per-subscription `middlewares`.\n */\nexport type SubscriptionHandlerEntry<E> =\n | SubscriptionHandler<E>\n | { handler: SubscriptionHandler<E>; middlewares?: Middleware[] };\n\n/**\n * Create a subscription endpoint builder.\n * @internal — used by the endpoint factory.\n */\nexport function createSubscription<TParams>(\n basePath: string,\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n): SubscriptionBuilder<TParams extends undefined ? {} : TParams>;\n\nexport function createSubscription(\n basePath: string,\n pathTemplate?: RoutePath\n): SubscriptionBuilder<any> {\n return new SubscriptionBuilder(basePath, pathTemplate ?? '/');\n}\n\n/**\n * Runtime check: is this endpoint builder a subscription?\n * @internal\n */\nexport function isSubscriptionBuilder(\n value: unknown\n): value is AnySubscription {\n return value instanceof SubscriptionBuilder;\n}\n\n/**\n * Runtime check: is this metadata from a subscription?\n * @internal\n */\nexport function isSubscriptionMetadata(\n value: unknown\n): value is SubscriptionMetadata {\n return (\n value !== null &&\n typeof value === 'object' &&\n (value as any).protocol === 'subscription'\n );\n}\n","import type {\n InferType,\n ObjectSchemaBuilder,\n ParseStringSchemaBuilder,\n PropertyDescriptorTree,\n SchemaBuilder\n} from '@cleverbrush/schema';\nimport type {\n ActionResult,\n ContentResult,\n FileResult,\n JsonResult,\n NoContentResult,\n RedirectResult,\n StatusCodeResult,\n StreamResult\n} from './ActionResult.js';\nimport type { RequestContext } from './RequestContext.js';\nimport {\n createSubscription,\n isSubscriptionBuilder,\n type SubscriptionBuilder,\n type SubscriptionHandlerEntry\n} from './Subscription.js';\nimport type { Middleware } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Simplify — flattens intersection types for clean IDE tooltips\n// ---------------------------------------------------------------------------\n\ntype Simplify<T> = { [K in keyof T]: T[K] } & {};\n\n// ---------------------------------------------------------------------------\n// ActionContext — assembles the typed argument for a handler\n// ---------------------------------------------------------------------------\n\ntype HasKeys<T> = keyof T extends never ? false : true;\n\ntype ActionContextParts<TParams, TBody, TQuery, THeaders, TPrincipal> = {\n context: RequestContext;\n} & (HasKeys<TParams> extends true ? { params: TParams } : {}) &\n (TBody extends undefined\n ? {}\n : {\n body: TBody extends SchemaBuilder<any, any, any, any, any>\n ? InferType<TBody>\n : TBody;\n }) &\n (HasKeys<TQuery> extends true ? { query: TQuery } : {}) &\n (HasKeys<THeaders> extends true ? { headers: THeaders } : {}) &\n (TPrincipal extends undefined ? {} : { principal: TPrincipal });\n\n/**\n * The fully-typed argument object passed to endpoint handlers.\n *\n * The shape is inferred from the `EndpointBuilder` chain — only the keys\n * actually configured (body, query, headers, params, principal) are present.\n */\nexport type ActionContext<E> =\n E extends EndpointBuilder<\n infer TParams,\n infer TBody,\n infer TQuery,\n infer THeaders,\n any,\n infer TPrincipal,\n any,\n any,\n any\n >\n ? Simplify<\n ActionContextParts<TParams, TBody, TQuery, THeaders, TPrincipal>\n >\n : never;\n\n// ---------------------------------------------------------------------------\n// InferServices — maps { name: SchemaBuilder } to { name: InferType<Schema> }\n// ---------------------------------------------------------------------------\n\ntype InferServices<T> = {\n [K in keyof T]: T[K] extends SchemaBuilder<any, any, any, any, any>\n ? InferType<T[K]>\n : never;\n};\n\n/**\n * Extracts the injected service schemas map from an `EndpointBuilder` type.\n * Used internally by the `Handler` type to derive the `services` argument.\n */\nexport type ServiceSchemas<E> =\n E extends EndpointBuilder<\n any,\n any,\n any,\n any,\n infer TServices,\n any,\n any,\n any,\n any\n >\n ? TServices\n : {};\n\ntype ResponseType<E> =\n E extends EndpointBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n infer TResponse,\n any\n >\n ? TResponse extends SchemaBuilder<any, any, any, any, any>\n ? InferType<TResponse>\n : TResponse\n : any;\n\n/**\n * Extracts the `TResponses` map from an `EndpointBuilder` type.\n * `TResponses` is a `Record<number, BodyType>` inferred from `.responses()`.\n */\nexport type ResponsesOf<E> =\n E extends EndpointBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n infer TResponses\n >\n ? TResponses\n : never;\n\ntype HasResponses<E> = keyof ResponsesOf<E> extends never ? false : true;\n\n/**\n * The union of permitted return values for a handler whose endpoint\n * declared `.responses()`. Each member corresponds to one declared code:\n *\n * - `null` schema (e.g. 204) → `NoContentResult` for 204, `StatusCodeResult<K>` otherwise\n * - Non-null schema for code 200 → also allows a plain object (treated as 200 by the server)\n * - Non-null schema for other codes → `JsonResult<K, Body>`\n *\n * `FileResult`, `StreamResult`, `ContentResult`, and `RedirectResult` are always\n * permitted as an escape hatch for non-JSON responses.\n */\nexport type AllowedResponseReturn<TResponses extends Record<number, any>> =\n | {\n [K in keyof TResponses & number]: TResponses[K] extends null\n ? K extends 204\n ? NoContentResult\n : StatusCodeResult<K>\n : JsonResult<K, TResponses[K]>;\n }[keyof TResponses & number]\n | (200 extends keyof TResponses\n ? TResponses[200] extends null\n ? never\n : TResponses[200]\n : never)\n | FileResult\n | StreamResult\n | ContentResult\n | RedirectResult;\n\n// ---------------------------------------------------------------------------\n// Handler — the action function type, inferred from an endpoint\n// ---------------------------------------------------------------------------\n\n/**\n * The handler function type inferred from an `EndpointBuilder`.\n *\n * When the endpoint has injected services, the handler receives a second\n * `services` argument with all resolved service instances.\n */\ntype HandlerReturn<E> =\n HasResponses<E> extends true\n ? AllowedResponseReturn<ResponsesOf<E>>\n : ResponseType<E> | ActionResult;\n\nexport type Handler<E> =\n HasKeys<ServiceSchemas<E>> extends true\n ? (\n arg: ActionContext<E>,\n services: Simplify<InferServices<ServiceSchemas<E>>>\n ) => HandlerReturn<E> | Promise<HandlerReturn<E>>\n : (\n arg: ActionContext<E>\n ) => HandlerReturn<E> | Promise<HandlerReturn<E>>;\n\n// ---------------------------------------------------------------------------\n// Handler mapping — compile-time complete endpoint → handler binding\n// ---------------------------------------------------------------------------\n\ntype AnyEndpoint = EndpointBuilder<any, any, any, any, any, any, any, any, any>;\ntype AnySubscriptionBuilder = SubscriptionBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>;\n\n/**\n * A single handler entry in a {@link HandlerMap}.\n *\n * Either a bare handler function or an object with a `handler` function and\n * optional per-endpoint `middlewares`.\n */\nexport type HandlerEntry<E> =\n | Handler<E>\n | { handler: Handler<E>; middlewares?: Middleware[] };\n\n/**\n * A compile-time complete mapping from an endpoint group structure to\n * handler entries. Every endpoint key in every group must have a\n * corresponding {@link HandlerEntry} — omitting one is a type error.\n *\n * Subscription endpoints (created via `endpoint.subscription()`) are\n * mapped to {@link SubscriptionHandlerEntry} instead of {@link HandlerEntry}.\n *\n * @typeParam TEndpoints - A record of groups, each a record of endpoint\n * builders. Typically the return type of `defineApi()` with server-side\n * extensions applied.\n */\nexport type HandlerMap<TEndpoints> = {\n [G in keyof TEndpoints]: {\n [E in keyof TEndpoints[G]]: TEndpoints[G][E] extends AnySubscriptionBuilder\n ? SubscriptionHandlerEntry<TEndpoints[G][E]>\n : TEndpoints[G][E] extends AnyEndpoint\n ? HandlerEntry<TEndpoints[G][E]>\n : never;\n };\n};\n\n/**\n * The opaque result of {@link mapHandlers}. Passed to\n * `ServerBuilder.handleAll()` to register every endpoint at once.\n */\nexport interface HandlerMapping {\n /** @internal */\n readonly _entries: ReadonlyArray<{\n endpoint: AnyEndpoint;\n handler: (...args: any[]) => any;\n middlewares?: Middleware[];\n }>;\n /** @internal */\n readonly _subscriptions: ReadonlyArray<{\n endpoint: AnySubscriptionBuilder;\n handler: (...args: any[]) => any;\n middlewares?: Middleware[];\n }>;\n}\n\n/**\n * Binds a complete set of endpoint builders to their handlers with\n * compile-time exhaustiveness checking.\n *\n * TypeScript will report an error if any endpoint in `endpoints` is\n * missing from `handlers`, or if a handler's signature does not match\n * its endpoint. This is analogous to how `@cleverbrush/mapper` tracks\n * unmapped properties at the type level.\n *\n * @param endpoints - A grouped object of extended endpoint builders\n * (e.g. after `.authorize()` / `.inject()`).\n * @param handlers - A matching grouped object of handler functions or\n * `{ handler, middlewares }` entries.\n * @returns A {@link HandlerMapping} to pass to `ServerBuilder.handleAll()`.\n *\n * @example\n * ```ts\n * const mapping = mapHandlers(endpoints, {\n * auth: {\n * register: registerHandler,\n * login: loginHandler,\n * },\n * todos: {\n * list: listTodosHandler,\n * create: createTodoHandler,\n * export: { handler: exportHandler, middlewares: [auditLog] },\n * },\n * });\n *\n * server.handleAll(mapping);\n * ```\n */\nexport function mapHandlers<\n TEndpoints extends Record<\n string,\n Record<string, AnyEndpoint | AnySubscriptionBuilder>\n >\n>(endpoints: TEndpoints, handlers: HandlerMap<TEndpoints>): HandlerMapping {\n const entries: HandlerMapping['_entries'][number][] = [];\n const subscriptions: HandlerMapping['_subscriptions'][number][] = [];\n\n for (const groupKey of Object.keys(endpoints)) {\n const group = endpoints[groupKey]!;\n const handlerGroup = (handlers as any)[groupKey];\n\n for (const endpointKey of Object.keys(group)) {\n const ep = group[endpointKey]!;\n const entry = handlerGroup[endpointKey];\n\n const handler = typeof entry === 'function' ? entry : entry.handler;\n const middlewares =\n typeof entry === 'function' ? undefined : entry.middlewares;\n\n if (isSubscriptionBuilder(ep)) {\n subscriptions.push({ endpoint: ep, handler, middlewares });\n } else {\n entries.push({\n endpoint: ep as AnyEndpoint,\n handler,\n middlewares\n });\n }\n }\n }\n\n return { _entries: entries, _subscriptions: subscriptions };\n}\n\n// ---------------------------------------------------------------------------\n// EndpointBuilder — immutable builder for endpoint definitions\n// ---------------------------------------------------------------------------\n\ntype RoutePath = string | ParseStringSchemaBuilder<any, any, any, any, any>;\n\n/**\n * Lightweight recursive property reference tree for type-safe runtime\n * expression building in `.links()` and `.callbacks()`.\n *\n * At runtime the actual value is a `PropertyDescriptorTree` from\n * `ObjectSchemaBuilder.getPropertiesFor()`, which provides `toJsonPointer()`\n * and the `SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR` marker used by the OpenAPI\n * generator to resolve path expressions automatically.\n */\nexport type PropertyRefTree<T> = {\n readonly [K in keyof T]-?: PropertyRefTree<T[K]>;\n};\n\n/**\n * A link from a response to a follow-up operation.\n *\n * @see https://spec.openapis.org/oas/v3.1.0#link-object\n */\nexport interface LinkDefinition<TResponse = any> {\n /** `operationId` of the target operation. */\n readonly operationId: string;\n /**\n * Map of target parameter names to values.\n *\n * - `Record<string, string>` — raw OpenAPI runtime expressions such as\n * `'$response.body#/id'`.\n * - Callback `(response: PropertyRefTree<TResponse>) => Record<string, unknown>` —\n * type-safe selector; properties accessed on `response` are converted to\n * `$response.body#/<pointer>` expressions automatically.\n */\n readonly parameters?:\n | Record<string, string>\n | ((\n response: TResponse extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any\n >\n ? PropertyDescriptorTree<TResponse, TResponse>\n : PropertyRefTree<any>\n ) => Record<string, unknown>);\n /** Human-readable description of the link relationship. */\n readonly description?: string;\n /** Runtime expression or literal for the linked operation's request body. */\n readonly requestBody?: string;\n}\n\n/**\n * A callback declaration for async request/response patterns.\n *\n * @see https://spec.openapis.org/oas/v3.1.0#callback-object\n */\nexport interface CallbackDefinition<TBody = any> {\n /**\n * Raw OpenAPI runtime expression for the callback URL,\n * e.g. `'{$request.body#/callbackUrl}'`.\n * Mutually exclusive with `urlFrom`.\n */\n readonly expression?: string;\n /**\n * Type-safe selector for the request body field holding the callback URL.\n * The generator converts the selected property to a\n * `'{$request.body#/<pointer>}'` expression automatically.\n * Mutually exclusive with `expression`.\n */\n readonly urlFrom?: (\n body: TBody extends ObjectSchemaBuilder<any, any, any, any, any>\n ? PropertyDescriptorTree<TBody, TBody>\n : PropertyRefTree<any>\n ) => unknown;\n /** HTTP method for the callback request (default: `'POST'`). */\n readonly method?: string;\n /** Short summary of the callback operation. */\n readonly summary?: string;\n /** Detailed description of the callback operation. */\n readonly description?: string;\n /** Request body schema for the callback payload. */\n readonly body?: SchemaBuilder<any, any, any, any, any>;\n /** Response schema expected from the callback consumer. */\n readonly response?: SchemaBuilder<any, any, any, any, any>;\n}\n\n/**\n * Snapshot of all configuration set on an `EndpointBuilder`.\n * Used by the server for routing and by `@cleverbrush/server-openapi` for\n * spec generation.\n */\nexport interface EndpointMetadata {\n readonly method: string;\n readonly basePath: string;\n readonly pathTemplate: RoutePath;\n readonly bodySchema: SchemaBuilder<any, any, any, any, any> | null;\n readonly querySchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n readonly headerSchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n readonly serviceSchemas: Record<\n string,\n SchemaBuilder<any, any, any, any, any>\n > | null;\n /**\n * Authorization roles required for this endpoint.\n * - `null` → no authorization required (public)\n * - `[]` → any authenticated user\n * - `['admin', ...]` → user must have at least one of these roles\n */\n readonly authRoles: readonly string[] | null;\n readonly summary: string | null;\n readonly description: string | null;\n readonly tags: readonly string[];\n readonly operationId: string | null;\n readonly deprecated: boolean;\n readonly responseSchema: SchemaBuilder<any, any, any, any, any> | null;\n /**\n * Per-status-code response schemas declared via `.responses()`.\n * When non-null, takes precedence over `responseSchema` for OpenAPI generation\n * and constrains the handler return type to the declared codes.\n * A `null` schema value means the response has no body (e.g. 204).\n */\n readonly responsesSchemas: Record<\n number,\n SchemaBuilder<any, any, any, any, any> | null\n > | null;\n /**\n * A single example value for the request body, emitted as `example` on the\n * OpenAPI Media Type Object.\n */\n readonly example: unknown | null;\n /**\n * A map of named examples for the request body, emitted as `examples` on the\n * OpenAPI Media Type Object. Each entry follows the OpenAPI Example Object shape.\n */\n readonly examples: Record<\n string,\n { summary?: string; description?: string; value: unknown }\n > | null;\n /**\n * When set, the endpoint produces a binary file response instead of JSON.\n * The OpenAPI spec will emit the appropriate binary content type.\n */\n readonly producesFile: {\n contentType?: string;\n description?: string;\n } | null;\n /**\n * Multiple response content types for content-negotiated endpoints.\n * Keys are MIME types; an optional `schema` overrides the default response\n * schema for that content type. When set alongside `.producesFile()`,\n * `producesFile` takes precedence.\n */\n readonly produces: Record<\n string,\n { schema?: SchemaBuilder<any, any, any, any, any> }\n > | null;\n /**\n * Schema describing response headers emitted on every response code.\n * Each property in the object schema becomes a header name with its\n * sub-schema and optional description.\n */\n readonly responseHeaderSchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n /**\n * External documentation URL for this operation, emitted as `externalDocs`\n * on the OpenAPI Operation Object.\n */\n readonly externalDocs: { url: string; description?: string } | null;\n /**\n * Response links declared via `.links()`, emitted under the primary\n * success response's `links` map in the OpenAPI spec.\n */\n readonly links: Record<string, LinkDefinition> | null;\n /**\n * Callbacks declared via `.callbacks()`, emitted as `callbacks` on the\n * OpenAPI Operation Object.\n */\n readonly callbacks: Record<string, CallbackDefinition> | null;\n}\n\n/**\n * Immutable, fluent builder for HTTP endpoint definitions.\n *\n * All methods return a new builder instance — the original is never mutated.\n * Use the {@link endpoint} singleton (or {@link createEndpoints}) to obtain\n * the first builder in the chain.\n *\n * @example\n * ```ts\n * const GetUser = endpoint\n * .get('/api/users')\n * .query(object({ id: number().coerce() }))\n * .authorize(UserPrincipal, 'admin')\n * .returns(UserSchema)\n * .summary('Get a user by ID');\n * ```\n */\n/**\n * Infers the per-code body type map from a `.responses()` schema map.\n * Each schema maps to its `InferType`; a `null` schema maps to `null`\n * (meaning the response has no body).\n */\ntype InferResponsesMap<\n T extends Record<number, SchemaBuilder<any, any, any, any, any> | null>\n> = {\n [K in keyof T]: T[K] extends SchemaBuilder<any, any, any, any, any>\n ? InferType<T[K]>\n : null;\n};\n\nexport class EndpointBuilder<\n TParams = {},\n TBody = undefined,\n TQuery = {},\n THeaders = {},\n TServices = {},\n TPrincipal = undefined,\n TRoles extends string = string,\n TResponse = any,\n TResponses extends Record<number, any> = {}\n> {\n readonly #method: string;\n readonly #basePath: string;\n readonly #pathTemplate: RoutePath;\n readonly #bodySchema: SchemaBuilder<any, any, any, any, any> | null;\n readonly #querySchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n readonly #headerSchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n readonly #serviceSchemas: Record<\n string,\n SchemaBuilder<any, any, any, any, any>\n > | null;\n readonly #authRoles: readonly string[] | null;\n readonly #summary: string | null;\n readonly #description: string | null;\n readonly #tags: readonly string[];\n readonly #operationId: string | null;\n readonly #deprecated: boolean;\n readonly #responseSchema: SchemaBuilder<any, any, any, any, any> | null;\n readonly #responsesSchemas: Record<\n number,\n SchemaBuilder<any, any, any, any, any> | null\n > | null;\n readonly #example: unknown | null;\n readonly #examples: Record<\n string,\n { summary?: string; description?: string; value: unknown }\n > | null;\n readonly #producesFile: {\n contentType?: string;\n description?: string;\n } | null;\n readonly #produces: Record<\n string,\n { schema?: SchemaBuilder<any, any, any, any, any> }\n > | null;\n readonly #responseHeaderSchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null;\n readonly #externalDocs: { url: string; description?: string } | null;\n readonly #links: Record<string, LinkDefinition> | null;\n readonly #callbacks: Record<string, CallbackDefinition> | null;\n\n constructor(\n method: string,\n basePath: string,\n pathTemplate: RoutePath,\n bodySchema: SchemaBuilder<any, any, any, any, any> | null,\n querySchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null,\n headerSchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null,\n serviceSchemas: Record<\n string,\n SchemaBuilder<any, any, any, any, any>\n > | null = null,\n authRoles: readonly string[] | null = null,\n summary: string | null = null,\n description: string | null = null,\n tags: readonly string[] = [],\n operationId: string | null = null,\n deprecated: boolean = false,\n responseSchema: SchemaBuilder<any, any, any, any, any> | null = null,\n responsesSchemas: Record<\n number,\n SchemaBuilder<any, any, any, any, any> | null\n > | null = null,\n example: unknown | null = null,\n examples: Record<\n string,\n { summary?: string; description?: string; value: unknown }\n > | null = null,\n producesFile: {\n contentType?: string;\n description?: string;\n } | null = null,\n produces: Record<\n string,\n { schema?: SchemaBuilder<any, any, any, any, any> }\n > | null = null,\n responseHeaderSchema: ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > | null = null,\n externalDocs: { url: string; description?: string } | null = null,\n links: Record<string, LinkDefinition> | null = null,\n callbacks: Record<string, CallbackDefinition> | null = null\n ) {\n this.#method = method;\n this.#basePath = basePath;\n this.#pathTemplate = pathTemplate;\n this.#bodySchema = bodySchema;\n this.#querySchema = querySchema;\n this.#headerSchema = headerSchema;\n this.#serviceSchemas = serviceSchemas;\n this.#authRoles = authRoles;\n this.#summary = summary;\n this.#description = description;\n this.#tags = tags;\n this.#operationId = operationId;\n this.#deprecated = deprecated;\n this.#responseSchema = responseSchema;\n this.#responsesSchemas = responsesSchemas;\n this.#example = example;\n this.#examples = examples;\n this.#producesFile = producesFile;\n this.#produces = produces;\n this.#responseHeaderSchema = responseHeaderSchema;\n this.#externalDocs = externalDocs;\n this.#links = links;\n this.#callbacks = callbacks;\n }\n\n /** Define the request body schema. Validation failures return 422 Problem Details. */\n body<TSchema extends SchemaBuilder<any, any, any, any, any>>(\n schema: TSchema\n ): EndpointBuilder<\n TParams,\n TSchema,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n schema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /** Define the query string schema (must be an object schema). Validation failures return 422. */\n query<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n >(\n schema: TSchema\n ): EndpointBuilder<\n TParams,\n TBody,\n InferType<TSchema>,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n schema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /** Define an expected request headers schema (must be an object schema). */\n headers<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n >(\n schema: TSchema\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n InferType<TSchema>,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n schema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /** Declare DI services to be resolved per-request and passed as the second handler argument. */\n inject<\n TSchemas extends Record<string, SchemaBuilder<any, any, any, any, any>>\n >(\n schemas: TSchemas\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TSchemas,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n schemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /**\n * Mark this endpoint as requiring authorization.\n *\n * Overloads:\n * - `authorize(principalSchema, ...roles)` — typed principal, optional role requirements\n * - `authorize(...roles)` — untyped principal (`unknown`), optional role requirements\n *\n * If no roles are specified, any authenticated user is allowed.\n */\n authorize<TSchema extends SchemaBuilder<any, any, any, any, any>>(\n principalSchema: TSchema,\n ...roles: TRoles[]\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n InferType<TSchema>,\n TRoles,\n TResponse,\n TResponses\n >;\n authorize(\n ...roles: TRoles[]\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n unknown,\n TRoles,\n TResponse,\n TResponses\n >;\n authorize(\n ...args: unknown[]\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n any,\n TRoles,\n TResponse,\n TResponses\n > {\n let roles: string[];\n if (\n args.length > 0 &&\n typeof args[0] === 'object' &&\n args[0] !== null &&\n 'introspect' in args[0]\n ) {\n // First argument is a schema — remaining are roles\n roles = args.slice(1) as string[];\n } else {\n roles = args as string[];\n }\n\n // Merge with inherited auth roles\n const merged = this.#authRoles ? [...this.#authRoles, ...roles] : roles;\n\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n merged,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /**\n * Declare the response type for OpenAPI spec generation.\n *\n * Overloads:\n * - `returns<T>()` — generic type only, no runtime schema\n * - `returns(schema)` — provides a schema for spec generation and type inference\n */\n returns<T>(): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n T,\n TResponses\n >;\n returns<TSchema extends SchemaBuilder<any, any, any, any, any>>(\n schema: TSchema\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TSchema,\n TResponses\n >;\n returns(\n _schema?: unknown\n ): EndpointBuilder<any, any, any, any, any, any, any, any, any> {\n const schema =\n _schema != null &&\n typeof _schema === 'object' &&\n 'introspect' in _schema\n ? (_schema as SchemaBuilder<any, any, any, any, any>)\n : null;\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n schema ?? this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /**\n * Declare per-status-code response schemas for OpenAPI generation and\n * handler return-type enforcement.\n *\n * Pass `null` as the schema for body-less codes (e.g. 204).\n *\n * @example\n * ```ts\n * const ep = endpoint\n * .get('/api/todos/:id')\n * .responses({\n * 200: object({ id: number(), title: string() }),\n * 404: object({ message: string() }),\n * });\n *\n * const handler: Handler<typeof ep> = ({ params }) => {\n * const todo = todos.get(params.id);\n * if (!todo) return ActionResult.notFound({ message: 'Not found' });\n * return todo; // plain object → 200\n * };\n * ```\n */\n responses<\n const T extends Record<\n number,\n SchemaBuilder<any, any, any, any, any> | null\n >\n >(\n map: T\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n InferResponsesMap<T>\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n map,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /** Short, human-readable summary for OpenAPI operation objects. */\n summary(\n text: string\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n text,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /** Longer description for OpenAPI operation objects. Supports Markdown. */\n description(\n text: string\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n text,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /** OpenAPI tags grouping this operation in generated documentation. */\n tags(\n ...tags: string[]\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /** A unique, stable identifier for this operation in OpenAPI spec. */\n operationId(\n id: string\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n id,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /** Mark this endpoint as deprecated in OpenAPI spec output. */\n deprecated(): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n true,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /**\n * Provide a single example value for the request body.\n *\n * Emitted as the `example` field on the OpenAPI Media Type Object\n * (`application/json`). Pre-fills the \"Try it out\" panel in Swagger UI.\n *\n * @param value - An example request body value.\n */\n example(\n value: TBody\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n value,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /**\n * Provide named examples for the request body.\n *\n * Each entry is emitted under the `examples` map of the OpenAPI Media Type\n * Object following the Example Object shape (`{ summary?, description?, value }`).\n *\n * @param map - A record of named examples.\n */\n examples(\n map: Record<\n string,\n { summary?: string; description?: string; value: TBody }\n >\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n map,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /**\n * Declare that this endpoint produces a binary file response.\n *\n * When set, the OpenAPI spec emits a binary content type instead of a JSON\n * schema for the success response. Takes precedence over `.returns()`.\n *\n * @param contentType - MIME type (default: `'application/octet-stream'`).\n * @param description - Optional response description for the spec.\n */\n producesFile(\n contentType?: string,\n description?: string\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n { contentType, description },\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /**\n * The full path for this endpoint, combining `basePath` and `pathTemplate`.\n *\n * For static routes this is the exact URL path (e.g. `\"/todos\"`).\n * For dynamic routes the template placeholders are included\n * (e.g. `\"/todos/:id\"`).\n */\n get path(): string {\n const base = this.#basePath;\n const tpl = this.#pathTemplate;\n let suffix: string;\n if (typeof tpl === 'string') {\n suffix = tpl;\n } else {\n const { literals, segments } = tpl.introspect().templateDefinition;\n let s = '';\n for (let i = 0; i < segments.length; i++) {\n s += literals[i] + `:${segments[i].path}`;\n }\n s += literals[segments.length] ?? '';\n suffix = s;\n }\n if (suffix === '/') return base || '/';\n return base + suffix;\n }\n\n /** Return an immutable snapshot of this builder's configuration as {@link EndpointMetadata}. */\n introspect(): EndpointMetadata {\n return {\n method: this.#method,\n basePath: this.#basePath,\n pathTemplate: this.#pathTemplate,\n bodySchema: this.#bodySchema,\n querySchema: this.#querySchema,\n headerSchema: this.#headerSchema,\n serviceSchemas: this.#serviceSchemas,\n authRoles: this.#authRoles,\n summary: this.#summary,\n description: this.#description,\n tags: this.#tags,\n operationId: this.#operationId,\n deprecated: this.#deprecated,\n responseSchema: this.#responseSchema,\n responsesSchemas: this.#responsesSchemas,\n example: this.#example,\n examples: this.#examples,\n producesFile: this.#producesFile,\n produces: this.#produces,\n responseHeaderSchema: this.#responseHeaderSchema,\n externalDocs: this.#externalDocs,\n links: this.#links,\n callbacks: this.#callbacks\n };\n }\n\n /**\n * Declare that this endpoint can produce responses in multiple content types.\n *\n * Each key is a MIME type. Provide an optional `schema` to override the\n * default response schema for that type; otherwise the schema from\n * `.returns()` / `.responses()` is reused for every declared content type.\n *\n * When used alongside `.producesFile()`, the binary response takes precedence.\n *\n * @param contentTypes - Map of MIME type → optional schema override.\n *\n * @example\n * ```ts\n * endpoint.get('/api/items')\n * .returns(object({ id: number(), name: string() }))\n * .produces({\n * 'text/csv': {},\n * 'application/xml': { schema: string() }\n * })\n * ```\n */\n produces(\n contentTypes: Record<\n string,\n { schema?: SchemaBuilder<any, any, any, any, any> }\n >\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n contentTypes,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /**\n * Declare response headers emitted by this endpoint.\n *\n * The object schema's properties become header names in the OpenAPI spec;\n * each property's sub-schema and description are emitted in the `headers`\n * map on every response code.\n *\n * @param schema - Object schema whose properties describe the response headers.\n *\n * @example\n * ```ts\n * endpoint.get('/api/items')\n * .responseHeaders(object({\n * 'X-Total-Count': number().describe('Total number of items'),\n * 'X-Page': number()\n * }))\n * ```\n */\n responseHeaders<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n >(\n schema: TSchema\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n schema,\n this.#externalDocs,\n this.#links,\n this.#callbacks\n );\n }\n\n /**\n * Link external documentation to this operation.\n *\n * Emitted as the `externalDocs` field on the OpenAPI Operation Object.\n *\n * @param url - The URL to the external documentation.\n * @param description - Optional short description of the external docs.\n */\n externalDocs(\n url: string,\n description?: string\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n { url, description },\n this.#links,\n this.#callbacks\n );\n }\n\n /**\n * Declare response links for OpenAPI spec generation.\n *\n * Links describe follow-up actions that can be taken based on the response,\n * emitted under the primary 2xx response's `links` map.\n *\n * @param defs - Record mapping link names to {@link LinkDefinition} objects.\n *\n * @example\n * ```ts\n * endpoint.get('/api/users/:id')\n * .returns(UserSchema)\n * .links({\n * GetUser: {\n * operationId: 'getUser',\n * parameters: (r) => ({ id: r.id }),\n * },\n * })\n * ```\n */\n links(\n defs: Record<string, LinkDefinition<TResponse>>\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n defs as Record<string, LinkDefinition>,\n this.#callbacks\n );\n }\n\n /**\n * Declare callbacks for OpenAPI spec generation.\n *\n * Callbacks describe async out-of-band requests that may be sent to a URL\n * provided in the request body, emitted as the `callbacks` field on the\n * OpenAPI Operation Object.\n *\n * @param defs - Record mapping callback names to {@link CallbackDefinition} objects.\n *\n * @example\n * ```ts\n * endpoint.post('/api/subscriptions')\n * .body(object({ callbackUrl: string() }))\n * .callbacks({\n * onEvent: {\n * urlFrom: (b) => b.callbackUrl,\n * method: 'POST',\n * body: EventSchema,\n * },\n * })\n * ```\n */\n callbacks(\n defs: Record<string, CallbackDefinition<TBody>>\n ): EndpointBuilder<\n TParams,\n TBody,\n TQuery,\n THeaders,\n TServices,\n TPrincipal,\n TRoles,\n TResponse,\n TResponses\n > {\n return new EndpointBuilder(\n this.#method,\n this.#basePath,\n this.#pathTemplate,\n this.#bodySchema,\n this.#querySchema,\n this.#headerSchema,\n this.#serviceSchemas,\n this.#authRoles,\n this.#summary,\n this.#description,\n this.#tags,\n this.#operationId,\n this.#deprecated,\n this.#responseSchema,\n this.#responsesSchemas,\n this.#example,\n this.#examples,\n this.#producesFile,\n this.#produces,\n this.#responseHeaderSchema,\n this.#externalDocs,\n this.#links,\n defs as Record<string, CallbackDefinition>\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// endpoint factory — creates EndpointBuilder instances\n// ---------------------------------------------------------------------------\n\n/**\n * Optional OpenAPI metadata fields accepted by `createEndpoint` / `createEndpoints`.\n */\nexport type EndpointMetadataDescriptors = {\n readonly summary?: string;\n readonly description?: string;\n readonly tags?: string[];\n readonly operationId?: string;\n readonly deprecated?: boolean;\n};\n\nfunction createEndpoint<TParams>(\n method: string,\n basePath: string,\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>,\n authRoles?: readonly string[] | null,\n meta?: EndpointMetadataDescriptors\n): EndpointBuilder<TParams extends undefined ? {} : TParams>;\n\nfunction createEndpoint(\n method: string,\n basePath: string,\n pathTemplate?: RoutePath,\n authRoles?: readonly string[] | null,\n meta?: EndpointMetadataDescriptors\n): EndpointBuilder<any> {\n return new EndpointBuilder(\n method,\n basePath,\n pathTemplate ?? '/',\n null,\n null,\n null,\n null,\n authRoles ?? null,\n meta?.summary ?? null,\n meta?.description ?? null,\n meta?.tags ?? [],\n meta?.operationId ?? null,\n meta?.deprecated ?? false,\n null,\n null,\n null,\n null,\n null,\n null,\n null\n );\n}\n\n// ---------------------------------------------------------------------------\n// ScopedEndpointFactory — resource-scoped endpoint creation\n// ---------------------------------------------------------------------------\n\ntype ScopedEndpointFactoryMethods<\n TPrincipal,\n TRoles extends string = string\n> = {\n get<TParams = {}>(\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n TPrincipal,\n TRoles,\n any,\n {}\n >;\n post<TParams = {}>(\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n TPrincipal,\n TRoles,\n any,\n {}\n >;\n put<TParams = {}>(\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n TPrincipal,\n TRoles,\n any,\n {}\n >;\n patch<TParams = {}>(\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n TPrincipal,\n TRoles,\n any,\n {}\n >;\n delete<TParams = {}>(\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n TPrincipal,\n TRoles,\n any,\n {}\n >;\n head<TParams = {}>(\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n TPrincipal,\n TRoles,\n any,\n {}\n >;\n options<TParams = {}>(\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n TPrincipal,\n TRoles,\n any,\n {}\n >;\n};\n\nexport type ScopedEndpointFactory<TRoles extends string = string> =\n ScopedEndpointFactoryMethods<undefined, TRoles> & {\n /**\n * Returns a new resource factory where all endpoints inherit\n * the given authorization requirements.\n *\n * - `authorize(principalSchema, ...roles)` — typed principal\n * - `authorize(...roles)` — untyped principal\n */\n authorize<TSchema extends SchemaBuilder<any, any, any, any, any>>(\n principalSchema: TSchema,\n ...roles: TRoles[]\n ): ScopedEndpointFactoryMethods<InferType<TSchema>, TRoles>;\n authorize(\n ...roles: TRoles[]\n ): ScopedEndpointFactoryMethods<unknown, TRoles>;\n };\n\nfunction createScopedFactoryMethods(\n basePath: string,\n authRoles: readonly string[] | null\n): ScopedEndpointFactoryMethods<any> {\n return {\n get: (pathTemplate?) =>\n createEndpoint('GET', basePath, pathTemplate, authRoles),\n post: (pathTemplate?) =>\n createEndpoint('POST', basePath, pathTemplate, authRoles),\n put: (pathTemplate?) =>\n createEndpoint('PUT', basePath, pathTemplate, authRoles),\n patch: (pathTemplate?) =>\n createEndpoint('PATCH', basePath, pathTemplate, authRoles),\n delete: (pathTemplate?) =>\n createEndpoint('DELETE', basePath, pathTemplate, authRoles),\n head: (pathTemplate?) =>\n createEndpoint('HEAD', basePath, pathTemplate, authRoles),\n options: (pathTemplate?) =>\n createEndpoint('OPTIONS', basePath, pathTemplate, authRoles)\n };\n}\n\nfunction createScopedFactory(basePath: string): ScopedEndpointFactory {\n return {\n ...createScopedFactoryMethods(basePath, null),\n authorize(...args: unknown[]): ScopedEndpointFactoryMethods<any> {\n let roles: string[];\n if (\n args.length > 0 &&\n typeof args[0] === 'object' &&\n args[0] !== null &&\n 'introspect' in args[0]\n ) {\n roles = args.slice(1) as string[];\n } else {\n roles = args as string[];\n }\n return createScopedFactoryMethods(basePath, roles);\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// EndpointFactory — top-level endpoint creation\n// ---------------------------------------------------------------------------\n\ntype EndpointFactory<TRoles extends string = string> = {\n get<TParams = {}>(\n basePath: string,\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n undefined,\n TRoles,\n any,\n {}\n >;\n post<TParams = {}>(\n basePath: string,\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n undefined,\n TRoles,\n any,\n {}\n >;\n put<TParams = {}>(\n basePath: string,\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n undefined,\n TRoles,\n any,\n {}\n >;\n patch<TParams = {}>(\n basePath: string,\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n undefined,\n TRoles,\n any,\n {}\n >;\n delete<TParams = {}>(\n basePath: string,\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n undefined,\n TRoles,\n any,\n {}\n >;\n head<TParams = {}>(\n basePath: string,\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n undefined,\n TRoles,\n any,\n {}\n >;\n options<TParams = {}>(\n basePath: string,\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): EndpointBuilder<\n TParams,\n undefined,\n {},\n {},\n {},\n undefined,\n TRoles,\n any,\n {}\n >;\n resource(basePath: string): ScopedEndpointFactory<TRoles>;\n subscription<TParams = {}>(\n basePath: string,\n pathTemplate?: ParseStringSchemaBuilder<TParams, any, any, any, any>\n ): SubscriptionBuilder<TParams, {}, {}, {}, undefined, TRoles>;\n};\n\n/**\n * Create a role-constrained endpoint factory. Roles are defined as a plain\n * `as const` object whose *values* become the string-literal union accepted\n * by `authorize()`.\n *\n * @example\n * ```ts\n * const Roles = { admin: 'admin', editor: 'editor' } as const;\n * const ep = createEndpoints(Roles);\n * ep.get('/api/admin').authorize(IPrincipal, 'admin'); // ✓\n * ep.get('/api/admin').authorize(IPrincipal, 'typo'); // ✗ type error\n * ```\n */\nexport function createEndpoints<const T extends Record<string, string>>(\n _roles: T\n): EndpointFactory<T[keyof T]> {\n return endpoint as EndpointFactory<T[keyof T]>;\n}\n\n/**\n * The global endpoint factory singleton.\n *\n * Creates `EndpointBuilder` instances for each HTTP method. Use\n * {@link createEndpoints} to get a role-constrained version.\n *\n * @example\n * ```ts\n * import { endpoint } from '@cleverbrush/server';\n *\n * const GetUsers = endpoint.get('/api/users');\n * const CreateUser = endpoint.post('/api/users').body(CreateUserSchema);\n * ```\n */\nexport const endpoint: EndpointFactory = {\n get: (basePath, pathTemplate?) =>\n createEndpoint('GET', basePath, pathTemplate),\n post: (basePath, pathTemplate?) =>\n createEndpoint('POST', basePath, pathTemplate),\n put: (basePath, pathTemplate?) =>\n createEndpoint('PUT', basePath, pathTemplate),\n patch: (basePath, pathTemplate?) =>\n createEndpoint('PATCH', basePath, pathTemplate),\n delete: (basePath, pathTemplate?) =>\n createEndpoint('DELETE', basePath, pathTemplate),\n head: (basePath, pathTemplate?) =>\n createEndpoint('HEAD', basePath, pathTemplate),\n options: (basePath, pathTemplate?) =>\n createEndpoint('OPTIONS', basePath, pathTemplate),\n resource: createScopedFactory,\n subscription: (basePath, pathTemplate?) =>\n createSubscription(basePath, pathTemplate)\n};\n","import {\n type InferType,\n type ObjectSchemaBuilder,\n object,\n type ParseStringSchemaBuilder,\n type ParseStringTemplateTag,\n type PropertyDescriptor,\n type PropertyDescriptorTree,\n parseString,\n type SchemaBuilder\n} from '@cleverbrush/schema';\n\ntype RouteTemplateTag<\n TProps extends Record<string, SchemaBuilder<any, any, any, any, any>>\n> = (\n strings: TemplateStringsArray,\n ...selectors: Array<\n (\n tree: PropertyDescriptorTree<\n ObjectSchemaBuilder<\n TProps,\n true,\n false,\n undefined,\n false,\n {},\n []\n >,\n ObjectSchemaBuilder<\n TProps,\n true,\n false,\n undefined,\n false,\n {},\n []\n >,\n string | number | boolean | Date\n >\n ) => PropertyDescriptor<\n ObjectSchemaBuilder<TProps, true, false, undefined, false, {}, []>,\n any,\n any\n >\n >\n) => ParseStringSchemaBuilder<\n InferType<\n ObjectSchemaBuilder<TProps, true, false, undefined, false, {}, []>\n >\n>;\n\nfunction createRouteTag<\n TProps extends Record<string, SchemaBuilder<any, any, any, any, any>>\n>(props: TProps): RouteTemplateTag<TProps> {\n type TSchema = ObjectSchemaBuilder<\n TProps,\n true,\n false,\n undefined,\n false,\n {},\n []\n >;\n const objectSchema = object(props) as unknown as TSchema;\n\n return ((strings: TemplateStringsArray, ...selectors: any[]) =>\n parseString(objectSchema, ($t: ParseStringTemplateTag<TSchema>) =>\n ($t as any)(strings, ...selectors)\n )) as any;\n}\n\n// Overload: route`/some/path` — used directly as a tagged template (no params)\nexport function route(\n strings: TemplateStringsArray,\n ...selectors: never[]\n): ParseStringSchemaBuilder<\n InferType<ObjectSchemaBuilder<{}, true, false, undefined, false, {}, []>>\n>;\n\n// Overload: route() — called with no args, returns a tagged template (no params)\nexport function route(): RouteTemplateTag<{}>;\n\n// Overload: route({ id: number() }) — called with props, returns a tagged template\nexport function route<\n TProps extends Record<string, SchemaBuilder<any, any, any, any, any>>\n>(props: TProps): RouteTemplateTag<TProps>;\n\n/**\n * Concise shorthand for defining a typed path template.\n *\n * @example With parameters\n * ```ts\n * const TodoById = route({ id: number().coerce() })`/${t => t.id}`;\n * ```\n *\n * @example Static path (no parameters)\n * ```ts\n * const Path = route`/some/path`;\n * // or\n * const Path = route()`/some/path`;\n * ```\n *\n * @param propsOrStrings - Either a property map for typed path segments,\n * or a `TemplateStringsArray` when used directly as a tagged template.\n * @returns A `ParseStringSchemaBuilder`, or a tagged-template function\n * that produces one.\n */\nexport function route(propsOrStrings?: any, ..._rest: any[]): any {\n // route`/some/path` — called as tagged template directly\n if (\n propsOrStrings != null &&\n Array.isArray((propsOrStrings as TemplateStringsArray).raw)\n ) {\n return createRouteTag({})(propsOrStrings as TemplateStringsArray);\n }\n\n // route() or route({...})\n return createRouteTag(propsOrStrings ?? {});\n}\n","/**\n * Browser-safe entry point for `@cleverbrush/server`.\n *\n * Re-exports the endpoint builder, factory functions and type helpers\n * needed to **define** API contracts without pulling in the Node.js server\n * runtime. Use this entry point in shared packages that are consumed by\n * both the backend (Node.js) and the frontend (browser).\n *\n * @example\n * ```ts\n * import { defineApi, endpoint, route } from '@cleverbrush/server/contract';\n * import { array, number, object, string } from '@cleverbrush/schema';\n *\n * const TodoSchema = object({ id: number(), title: string() });\n *\n * export const api = defineApi({\n * todos: {\n * list: endpoint.resource('/api/todos').get()\n * .responses({ 200: array(TodoSchema) }),\n * get: endpoint.resource('/api/todos').get(\n * route({ id: number().coerce() })`/${t => t.id}`\n * ).responses({ 200: TodoSchema }),\n * },\n * });\n * ```\n *\n * @module\n */\n\nexport {\n type ActionContext,\n type AllowedResponseReturn,\n type CallbackDefinition,\n createEndpoints,\n EndpointBuilder,\n type EndpointMetadata,\n type EndpointMetadataDescriptors,\n endpoint,\n type Handler,\n type LinkDefinition,\n type PropertyRefTree,\n type ResponsesOf,\n type ScopedEndpointFactory\n} from './Endpoint.js';\nexport { route } from './route.js';\nexport {\n SubscriptionBuilder,\n type SubscriptionContext,\n type SubscriptionHandler,\n type SubscriptionHandlerEntry,\n type SubscriptionMetadata,\n type TrackedEvent,\n tracked\n} from './Subscription.js';\n\nimport type { EndpointBuilder as _EB } from './Endpoint.js';\nimport type { SubscriptionBuilder as _SB } from './Subscription.js';\n\n// ---------------------------------------------------------------------------\n// defineApi — typed, one-level API contract grouping\n// ---------------------------------------------------------------------------\n\n/**\n * A record of named {@link EndpointBuilder} or {@link SubscriptionBuilder}\n * instances that form a single logical API group (e.g. \"todos\", \"auth\", \"live\").\n */\nexport type ApiGroup = Record<\n string,\n | _EB<any, any, any, any, any, any, any, any, any>\n | _SB<any, any, any, any, any, any, any, any>\n>;\n\n/**\n * A typed API contract with one level of grouping.\n *\n * Each key is a group name and each value is an {@link ApiGroup} — a\n * record of named endpoints.\n *\n * @example\n * ```ts\n * const contract: ApiContract = {\n * todos: { list: todosResource.get(), create: todosResource.post() },\n * auth: { login: endpoint.post('/api/auth/login') },\n * };\n * ```\n */\nexport type ApiContract = Record<string, ApiGroup>;\n\n/**\n * Defines a typed API contract with one level of grouping.\n *\n * The returned object is the **single source of truth** for both server and\n * client. The server imports it and extends each endpoint with\n * `.authorize()`, `.inject()`, and OpenAPI metadata. The client passes it\n * to `createClient()` from `@cleverbrush/client` to obtain a fully typed HTTP\n * client.\n *\n * At runtime the contract (and each group within it) is frozen with\n * `Object.freeze` to prevent accidental mutation — endpoint builders are\n * immutable by design, so every `.body()` / `.query()` / etc. call already\n * returns a **new** builder.\n *\n * @typeParam T - The exact shape of the contract, inferred from the argument.\n * @param contract - A record of named groups, each containing named endpoints.\n * @returns The same object, frozen and typed as `Readonly<T>`.\n *\n * @example\n * ```ts\n * import { defineApi, endpoint, route } from '@cleverbrush/server/contract';\n * import { array, number, object, string } from '@cleverbrush/schema';\n *\n * const TodoSchema = object({ id: number(), title: string(), completed: boolean() });\n * const todosResource = endpoint.resource('/api/todos');\n * const ById = route({ id: number().coerce() })`/${t => t.id}`;\n *\n * export const api = defineApi({\n * todos: {\n * list: todosResource.get()\n * .query(object({ page: number().optional(), limit: number().optional() }))\n * .responses({ 200: array(TodoSchema) }),\n * get: todosResource.get(ById)\n * .responses({ 200: TodoSchema }),\n * create: todosResource.post()\n * .body(object({ title: string() }))\n * .responses({ 201: TodoSchema }),\n * },\n * auth: {\n * login: endpoint.post('/api/auth/login')\n * .body(object({ email: string(), password: string() }))\n * .responses({ 200: object({ token: string() }) }),\n * },\n * });\n * ```\n */\nexport function defineApi<T extends ApiContract>(contract: T): Readonly<T> {\n for (const group of Object.values(contract)) {\n Object.freeze(group);\n }\n return Object.freeze(contract);\n}\n\n// ---------------------------------------------------------------------------\n// Contract composition utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Computes the merged type of two {@link ApiContract} objects.\n *\n * - Groups that only exist in `A` are kept as-is.\n * - Groups that only exist in `B` are kept as-is.\n * - Groups whose key appears in **both** `A` and `B` have their endpoint maps\n * intersected (`A[K] & B[K]`), making all endpoints from both sources\n * visible on the merged group.\n */\nexport type MergedContracts<A extends ApiContract, B extends ApiContract> = {\n readonly [K in keyof A | keyof B]: K extends keyof A\n ? K extends keyof B\n ? A[K] & B[K]\n : A[K]\n : K extends keyof B\n ? B[K]\n : never;\n};\n\n/**\n * Merges two API contracts into one.\n *\n * This is the primary building block for **audience-scoped bundles**: define\n * a `publicApi` that is safe to ship to every client, and a separate\n * `adminApi` that is only imported by the admin application. Combine them\n * at the admin entry point with `mergeContracts`.\n *\n * - Groups that exist in only one contract are passed through unchanged.\n * - Groups that share a key have their endpoint maps **shallowly merged**\n * (later endpoints with the same name override earlier ones, same semantics\n * as `Object.assign`).\n * - The returned contract is frozen, matching the invariant of\n * {@link defineApi}.\n *\n * @typeParam A - The shape of the first contract.\n * @typeParam B - The shape of the second contract.\n * @param a - The base contract (e.g. the public API).\n * @param b - The contract to merge in (e.g. admin-only groups).\n * @returns A new frozen contract whose type is {@link MergedContracts}`<A, B>`.\n *\n * @example\n * ```ts\n * // shared/public-api.ts — safe to import in the client bundle\n * export const publicApi = defineApi({\n * todos: { list: ..., get: ..., create: ... },\n * auth: { login: ..., register: ... },\n * });\n *\n * // shared/admin-api.ts — only imported by the admin application\n * const adminApi = defineApi({\n * admin: { activityLog: ..., banUser: ... },\n * });\n *\n * // admin-app/contract.ts\n * import { mergeContracts } from '@cleverbrush/server/contract';\n * export const fullApi = mergeContracts(publicApi, adminApi);\n * // TypeScript sees: { todos, auth, admin } — fully typed\n *\n * // client-app/contract.ts\n * import { publicApi } from 'shared/public-api';\n * // TypeScript sees: { todos, auth } — admin groups are absent\n * ```\n */\nexport function mergeContracts<A extends ApiContract, B extends ApiContract>(\n a: A,\n b: B\n): Readonly<MergedContracts<A, B>> {\n const result: Record<string, ApiGroup> = {};\n\n for (const key of Object.keys(a) as (keyof A & string)[]) {\n result[key] = { ...a[key] };\n }\n\n for (const key of Object.keys(b) as (keyof B & string)[]) {\n if (Object.hasOwn(result, key)) {\n result[key] = { ...result[key], ...b[key] };\n } else {\n result[key] = { ...b[key] };\n }\n }\n\n for (const group of Object.values(result)) {\n Object.freeze(group);\n }\n\n return Object.freeze(result) as unknown as Readonly<MergedContracts<A, B>>;\n}\n\n/**\n * Returns a new contract containing only the specified groups.\n *\n * The TypeScript return type is `Pick<T, K>` — the compiler sees exactly the\n * selected groups and no others. This provides full type safety on the\n * narrowed contract when passed to `createClient()` or used as a server\n * handler map.\n *\n * @typeParam T - The shape of the source contract.\n * @typeParam K - The union of group keys to keep.\n * @param contract - The contract to select from.\n * @param groups - The group keys to include.\n * @returns A new frozen contract with only the listed groups.\n *\n * @example\n * ```ts\n * const fullApi = defineApi({ todos: {...}, auth: {...}, admin: {...}, debug: {...} });\n *\n * // Pick only the groups the frontend needs\n * const clientApi = pickGroups(fullApi, 'todos', 'auth');\n * // TypeScript: { todos: ..., auth: ... }\n * ```\n */\nexport function pickGroups<T extends ApiContract, K extends keyof T>(\n contract: T,\n ...groups: K[]\n): Readonly<Pick<T, K>> {\n const result = {} as Pick<T, K>;\n for (const key of groups) {\n (result as Record<string, ApiGroup>)[key as string] = contract[key];\n Object.freeze((result as Record<string, ApiGroup>)[key as string]);\n }\n return Object.freeze(result);\n}\n\n/**\n * Returns a new contract with the specified groups removed.\n *\n * The TypeScript return type is `Omit<T, K>` — the listed groups are absent\n * at both runtime and compile time. Useful for stripping debug, internal, or\n * admin groups before sharing a contract with less-privileged consumers.\n *\n * @typeParam T - The shape of the source contract.\n * @typeParam K - The union of group keys to remove.\n * @param contract - The contract to omit from.\n * @param groups - The group keys to exclude.\n * @returns A new frozen contract without the listed groups.\n *\n * @example\n * ```ts\n * const fullApi = defineApi({ todos: {...}, auth: {...}, admin: {...}, debug: {...} });\n *\n * // Strip internal groups before exporting to clients\n * const publicApi = omitGroups(fullApi, 'admin', 'debug');\n * // TypeScript: { todos: ..., auth: ... }\n * ```\n */\nexport function omitGroups<T extends ApiContract, K extends keyof T>(\n contract: T,\n ...groups: K[]\n): Readonly<Omit<T, K>> {\n const excluded = new Set<string>(groups as string[]);\n const result = {} as Omit<T, K>;\n for (const key of Object.keys(contract)) {\n if (!excluded.has(key)) {\n (result as Record<string, ApiGroup>)[key] = contract[key];\n Object.freeze((result as Record<string, ApiGroup>)[key]);\n }\n }\n return Object.freeze(result);\n}\n"],"mappings":"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","names":["TRACKED_SYMBOL","tracked","id","data","isTrackedEvent","value","SubscriptionBuilder","_SubscriptionBuilder","#basePath","#pathTemplate","#incomingSchema","#outgoingSchema","#querySchema","#headerSchema","#serviceSchemas","#authRoles","#summary","#description","#tags","#operationId","#deprecated","#externalDocs","basePath","pathTemplate","incomingSchema","outgoingSchema","querySchema","headerSchema","serviceSchemas","authRoles","summary","description","tags","operationId","deprecated","externalDocs","#clone","overrides","schema","schemas","args","roles","merged","text","url","createSubscription","isSubscriptionBuilder","mapHandlers","endpoints","handlers","entries","subscriptions","groupKey","group","handlerGroup","endpointKey","ep","entry","handler","middlewares","isSubscriptionBuilder","EndpointBuilder","_EndpointBuilder","#method","#basePath","#pathTemplate","#bodySchema","#querySchema","#headerSchema","#serviceSchemas","#authRoles","#summary","#description","#tags","#operationId","#deprecated","#responseSchema","#responsesSchemas","#example","#examples","#producesFile","#produces","#responseHeaderSchema","#externalDocs","#links","#callbacks","method","basePath","pathTemplate","bodySchema","querySchema","headerSchema","serviceSchemas","authRoles","summary","description","tags","operationId","deprecated","responseSchema","responsesSchemas","example","examples","producesFile","produces","responseHeaderSchema","externalDocs","links","callbacks","schema","schemas","args","roles","merged","_schema","map","text","id","value","contentType","base","tpl","suffix","literals","segments","s","i","contentTypes","url","defs","createEndpoint","meta","createScopedFactoryMethods","createScopedFactory","createEndpoints","_roles","endpoint","createSubscription","object","parseString","createRouteTag","props","objectSchema","strings","selectors","$t","route","propsOrStrings","_rest","defineApi","contract","group","mergeContracts","a","b","result","key","pickGroups","groups","omitGroups","excluded"]}
|