express-zod-api 29.2.3 → 29.3.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  ## Version 29
4
4
 
5
+ ### v29.3.1
6
+
7
+ - Fixed the `Endpoint` methods duplication issue:
8
+ - The methods given to `EndpointsFactory::build()` are now deduplicated;
9
+ - No more confusing "Route has a duplicate" error in that case and duplicate entries in the generated `Integration`.
10
+
11
+ ### v29.3.0
12
+
13
+ - Featuring Endpoint-specific status codes:
14
+ - Added `statusCode` option to `EndpointsFactory::build()` and `Middleware::constructor()` arguments;
15
+ - It can be assigned with a number or an array of numbers having at least one element;
16
+ - You can specify how exactly an Endpoint can respond or a Middleware can terminate the request handling;
17
+ - Those codes affect the generated Documentation along with the `ResultHandler` (`positive` and `negative`):
18
+ - If `ResultHandler` has a single response schema, those codes replace the configured ones (override);
19
+ - When it has different response schemas, status codes would be narrowed down (intersection):
20
+ - Failure to intersect (uncertain response schema for unlisted code) leads to `ResultHandlerError`.
21
+ - Fixed: `createRateLimitMiddleware` and `EndpointsFactory::useRateLimit` respect the custom `statusCode`:
22
+ - Rate-limit middleware was introduced in v28.7.0; its default status code remains `429`.
23
+ - Rate-limit middleware, in this regard, is supposed to declare its status code:
24
+ - But it could be a breaking change for some APIs and therefore, it's postponed until v30;
25
+ - If that behavior is desired now, you can specify the `{ statusCode: 429 }` explicitly in its configuration.
26
+
5
27
  ### v29.2.3
6
28
 
7
29
  - This version prevents the HTTP status code misuse within `ResultHandler` API response definition:
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ![CI](https://img.shields.io/github/actions/workflow/status/RobinTail/express-zod-api/node.js.yml?label=CI)
6
6
  ![OpenAPI](https://img.shields.io/github/actions/workflow/status/RobinTail/express-zod-api/oas.yml?label=OpenAPI)
7
- [![coverage](https://img.shields.io/coverallsCoverage/github/RobinTail/express-zod-api)](https://coveralls.io/github/RobinTail/express-zod-api)
7
+ [![coverage](https://coveralls.io/repos/github/RobinTail/express-zod-api/badge.svg?branch=master)](https://coveralls.io/github/RobinTail/express-zod-api)
8
8
 
9
9
  ![downloads](https://img.shields.io/npm/dw/express-zod-api.svg)
10
10
  ![GitHub Repo stars](https://img.shields.io/github/stars/RobinTail/express-zod-api.svg?style=flat)
@@ -341,12 +341,12 @@ import { Middleware } from "express-zod-api";
341
341
 
342
342
  const authMiddleware = new Middleware({
343
343
  security: {
344
- // this information is optional and used for generating documentation
345
344
  and: [
346
345
  { type: "input", name: "key" },
347
346
  { type: "header", name: "token" },
348
347
  ],
349
- },
348
+ }, // this information is optional and used for generating Documentation
349
+ statusCode: 401, // for Documentation: Middleware may interrupt handling this way
350
350
  input: z.object({
351
351
  key: z.string().min(1),
352
352
  }),
@@ -456,6 +456,7 @@ import { auth } from "express-oauth2-jwt-bearer";
456
456
  const factory = defaultEndpointsFactory.use(auth(), {
457
457
  provider: (req) => ({ auth: req.auth }), // optional, can be async
458
458
  transformer: (err) => createHttpError(401, err.message), // optional
459
+ statusCode: 401, // for Documentation: Middleware may interrupt handling this way
459
460
  });
460
461
  ```
461
462
 
@@ -908,7 +909,11 @@ Install `express-rate-limit`. Consider the `createRateLimitMiddleware()` to enab
908
909
 
909
910
  ```ts
910
911
  const endpoint = factory
911
- .useRateLimit({ windowMs: 60000, max: 100 }) // shorthand, or .addMiddleware(createRateLimitMiddleware())
912
+ .useRateLimit({
913
+ windowMs: 60000,
914
+ max: 100,
915
+ statusCode: 429, // when set explicitly, it will be reflected in the Documentation
916
+ }) // shorthand, or .addMiddleware(createRateLimitMiddleware())
912
917
  .buildVoid({
913
918
  handler: async ({ ctx: { rateLimit, logger } }) => {
914
919
  logger.debug("Features", rateLimit); // { limit, used, remaining, resetTime, getKey, resetKey }
@@ -1396,7 +1401,7 @@ response schemas and their corresponding status codes.
1396
1401
  ```ts
1397
1402
  import { ResultHandler } from "express-zod-api";
1398
1403
 
1399
- new ResultHandler({
1404
+ const resultHandler = new ResultHandler({
1400
1405
  positive: (data) => ({
1401
1406
  statusCode: [201, 202], // created or will be created
1402
1407
  schema: z.object({ status: z.literal("created"), data }),
@@ -1411,9 +1416,15 @@ new ResultHandler({
1411
1416
  schema: z.object({ status: z.literal("error"), reason: z.string() }),
1412
1417
  },
1413
1418
  ],
1414
- handler: ({ error, response, output }) => {
1415
- // your implementation here
1416
- },
1419
+ });
1420
+ ```
1421
+
1422
+ Moreover, when building an Endpoint, you can narrow the codes the Endpoint actually responds by using the local
1423
+ `statusCode` option, overriding the ones defined by the ResultHandler. That simplifies the generated Documentation:
1424
+
1425
+ ```ts
1426
+ const endpoint = new EndpointsFactory(resultHandler).build({
1427
+ statusCode: [201, 409], // narrows the responses down to "created" (201) or "conflict" (409)
1417
1428
  });
1418
1429
  ```
1419
1430
 
@@ -1 +1 @@
1
- import{A as e,C as t,F as n,G as r,K as i,L as a,M as o,P as s,Q as c,U as l,W as u,Y as d,Z as f,b as p,q as m,r as h,tt as g,v as _}from"./routing-walker-D9nfJshN.js";import{z as v}from"zod";import*as y from"ramda";import{isReferenceObject as b,isSchemaObject as x}from"openapi3-ts/oas32";const S=e=>e.type===`object`,C=y.mergeDeepWith((e,t)=>{if(Array.isArray(e)&&Array.isArray(t))return y.concat(e,t);if(e===t)return t;throw Error(`Can not flatten properties`,{cause:{a:e,b:t}})}),w=new Set([`type`,`properties`,`required`,`examples`,`description`,`additionalProperties`]),T=e=>{for(let t of Object.keys(e))if(!w.has(t))return!1;return!0},E=y.pair(!0),ee=(e,t,n)=>!(`allOf`in e)||!e.allOf?[]:e.allOf.map(e=>{if(t===`throw`&&!(e.type===`object`&&T(e)))throw Error(`Can not merge`);return y.pair(n,e)}),te=e=>{let t=[];return e.anyOf&&t.push(...y.map(E,e.anyOf)),e.oneOf&&t.push(...y.map(E,e.oneOf)),t},ne=(e,t,n,i)=>{if(!r(e.propertyNames))return;let a=[];typeof e.propertyNames.const==`string`&&a.push(e.propertyNames.const),e.propertyNames.enum&&a.push(...e.propertyNames.enum.filter(e=>typeof e==`string`));let o={...Object(e.additionalProperties)};for(let e of a)t.properties[e]??=o;i||n.push(...a)},re=(e,t,n)=>{t.examples?.length&&(e.examples=n?y.concat(e.examples||[],t.examples):a(e.examples?.filter(r)||[],t.examples.filter(r),([e,t])=>y.mergeDeepRight(e,t)))},D=(e,t=`coerce`)=>{let n=[y.pair(!1,e)],r={type:`object`,properties:{}},i=[];for(let[e,a]of n)a.description&&(r.description??=a.description),n.push(...ee(a,t,e)),n.push(...te(a)),re(r,a,e),S(a)&&(n.push([e,{examples:O(a)}]),a.properties&&(r.properties=(t===`throw`?C:y.mergeDeepRight)(r.properties,a.properties),!e&&a.required&&i.push(...a.required)),ne(a,r,i,e));return i.length&&(r.required=[...new Set(i)]),r},O=e=>Object.entries(e.properties||{}).reduce((e,[t,n])=>{let{examples:i=[]}=r(n)?n:{};return a(e,i.map(y.objOf(t)),([e,t])=>({...e,...t}))},[]),k=`x-coerce`,A=(e,t)=>{if(e[`x-coerce`]===!0)return!0;if(e.anyOf)return e.anyOf.some(e=>A(e,t));if(e.oneOf)return e.oneOf.some(e=>A(e,t));if(e.allOf)return e.allOf.every(e=>A(e,t));if(e.type===void 0||e.type===`string`)return!0;if(t===`query`&&[`array`,`object`].includes(e.type)){let n=[e.items,e.prefixItems,e.additionalItems,Object.values(e.properties??{}),e.additionalProperties,e.propertyNames];for(let e of n){if(!r(e))continue;let n=Array.isArray(e)?e:[e];for(let e of n)if(r(e)&&!A(e,t))return!1}return!0}return!1};let j;const M=()=>j??=new Set(`a-im.accept.accept-additions.accept-charset.accept-datetime.accept-encoding.accept-features.accept-language.accept-signature.access-control.access-control-request-headers.access-control-request-method.alpn.alt-used.amp-cache-transform.apply-to-redirect-ref.authorization.available-dictionary.c-ext.c-man.c-opt.c-pep.c-pep-info.cache-control.cal-managed-id.caldav-timezones.capsule-protocol.cdn-loop.cert-not-after.cert-not-before.client-cert.client-cert-chain.close.cmcd-object.cmcd-request.cmcd-session.cmcd-status.cmsd-dynamic.cmsd-static.concealed-auth-export.configuration-context.connection.content-digest.content-disposition.content-encoding.content-id.content-language.content-length.content-location.content-md5.content-range.content-script-type.content-type.cookie.cookie2.cta-common-access-token.dasl.date.dav.default-style.delta-base.deprecation.depth.derived-from.destination.detached-jws.dictionary-id.differential-id.digest.dpop.early-data.ediint-features.expect.expect-ct.ext.forwarded.from.getprofile.hobareg.host.http2-settings.if.if-match.if-modified-since.if-none-match.if-range.if-schedule-tag-match.if-unmodified-since.im.include-referred-token-binding-id.incremental.isolation.keep-alive.label.last-event-id.link.link-template.lock-token.man.max-forwards.memento-datetime.meter.method-check.method-check-expires.mime-version.negotiate.odata-entityid.odata-isolation.odata-maxversion.odata-version.opt.ordering-type.origin.origin-agent-cluster.oscore.oslc-core-version.overwrite.pep.pep-info.permissions-policy.pics-label.ping-from.ping-to.position.pragma.prefer.preference-applied.priority.profileobject.protocol.protocol-info.protocol-query.protocol-request.proxy-authorization.proxy-features.proxy-instruction.range.redirect-ref.referer.referer-root.referrer-policy.repeatability-client-id.repeatability-first-sent.repeatability-request-id.repeatability-result.replay-nonce.reporting-endpoints.repr-digest.safe.schedule-reply.schedule-tag.sec-fetch-storage-access.sec-gpc.sec-purpose.sec-token-binding.sec-websocket-extensions.sec-websocket-key.sec-websocket-protocol.sec-websocket-version.security-scheme.signature.signature-input.slug.soapaction.status-uri.sunset.surrogate-capability.tcn.te.timeout.topic.traceparent.tracestate.trailer.transfer-encoding.ttl.upgrade.urgency.uri.user-agent.variant-vary.via.want-content-digest.want-digest.want-repr-digest.want-unencoded-digest.warning.x-content-type-options.x-frame-options`.split(`.`)),N={integer:0,number:0,string:``,boolean:!1,object:{},null:null,array:[]},P=e=>e.replace(d,e=>`{${e.slice(1)}}`),F=({},e)=>{if(e.isResponse)throw new t(`Please use ez.upload() only for input.`,e);return{type:`string`,format:`binary`}},I=({jsonSchema:e})=>({...e,externalDocs:{description:`raw binary data`,url:`https://swagger.io/specification/#working-with-binary-data`}}),L=({zodSchema:e,jsonSchema:t})=>{if(!i(e,`union`)||!(`discriminator`in e._zod.def))return t;let n=e._zod.def.discriminator;return{...t,discriminator:t.discriminator??{propertyName:n}}},R=y.tryCatch(({jsonSchema:e})=>{if(!e.allOf)throw`no allOf`;return D(e,`throw`)},(e,{jsonSchema:t})=>t),z=({jsonSchema:e})=>{if(!e.anyOf||!e.anyOf.length)return e;let t=e.anyOf[0];return Object.assign(t,{type:K(t.type)})},B=e=>e,V=({jsonSchema:e},n)=>{if(n.isResponse)throw new t(`Please use ez.dateOut() for output.`,n);return e},H=({jsonSchema:e},n)=>{if(!n.isResponse)throw new t(`Please use ez.dateIn() for input.`,n);return e},U=()=>({type:`string`,format:`bigint`,pattern:`^-?\\d+$`}),W=({zodSchema:e,jsonSchema:t})=>e._zod.def.rest===null?{...t,items:{not:{}}}:t,G=e=>{let t=Array.isArray(e.type)?e.type[0]:e.type;return N?.[t]},K=e=>e===`null`?e:typeof e==`string`?[e,`null`]:e&&[...new Set(e).add(`null`)],ie=({zodSchema:e,jsonSchema:t},n)=>{let r=e._zod.def[n.isResponse?`out`:`in`],a=e._zod.def[n.isResponse?`in`:`out`];if(!i(r,`transform`))return t;let o=B(Z(a,{ctx:n}));if(x(o))if(n.isResponse){let e=u(r,G(o));if(e&&[`number`,`string`,`boolean`].includes(e))return{...t,type:e}}else{let{type:e,...t}=o;return{...t,format:`${t.format||e} (preprocessed)`}}return t},q=({jsonSchema:e})=>{if(e.type!==`object`)return e;let t=e;return!t.properties||!(`raw`in t.properties)||!r(t.properties.raw)?e:t.properties.raw},J=e=>e.length?y.fromPairs(y.zip(y.times(e=>`example${e+1}`,e.length),y.map(y.objOf(`dataValue`),e))):void 0,Y=(e,t)=>t?.has(e)||e.startsWith(`x-`)||M().has(e),ae=({method:e,path:t,security:n,inputSources:r,isHeader:i})=>{let a=new Set(l(t)),o=r.includes(`query`),s=r.includes(`params`),c=r.includes(`headers`),u=r.includes(`cookies`)||r.includes(`signedCookies`),d;c&&n&&(d=h(n,`header`));let f;return u&&n&&(f=h(n,`cookie`)),{pathParams:a,getLocation:n=>{if(s&&a.has(n)&&a.delete(n))return`path`;if(u&&f?.has(n))return`cookie`;if(c&&(i?.(n,e,t)??Y(n,d)))return`header`;if(o&&e!==`query`)return`query`},isQueryEnabled:o}},oe=({path:e,method:t,flatRequest:n,makeRef:i,composition:a,getLocation:o,description:s=`${t.toUpperCase()} ${e} Parameter`})=>{let c=[];for(let[e,t]of Object.entries(n.properties)){if(!r(t))continue;let l=o(e);if(!l)continue;let u=B(t),d=a===`components`?i(t.id||JSON.stringify(t),u,t.id||m(s,e)):u;c.push({name:e,in:l,deprecated:t.deprecated,required:n.required?.includes(e)||l===`path`,description:u.description||s,schema:d,examples:J(x(u)&&u.examples?.length?u.examples:y.pluck(e,n.examples?.filter(y.both(r,y.has(e)))||[]))})}return c},X={nullable:z,union:L,bigint:U,intersection:R,tuple:W,pipe:ie,[o]:V,[e]:H,[p]:F,[_]:q,[s]:I},se=(e,t,n)=>{let r=[e,t],i=e=>/schema\d+$/.test(e)?void 0:e;for(let e=0;e<r.length;e++){let a=r[e];if(y.is(Object,a)){if(b(a)&&!a.$ref.startsWith(`#/components`)){let e=a.$ref.split(`/`).pop(),r=t[e];if(r){let t=r.id||i(e);a.$ref=n.makeRef(t||r,B(r),t).$ref}continue}r.push(...y.values(a))}y.is(Array,a)&&r.push(...y.values(a))}return e},Z=(e,{ctx:i,rules:a=X})=>{let{$defs:o={},properties:s={}}=v.toJSONSchema(v.object({subject:e}),{unrepresentable:`any`,io:i.isResponse?`output`:`input`,override:e=>{let r=v.globalRegistry.get(e.zodSchema)?.id;if(r){let n=i.seenIds.get(r);if(n&&n!==e.zodSchema)throw new t(`The meta id "${r}" is used by two different schemas. Please make the ids unique or reuse the same schema instance.`,i);i.seenIds.set(r,e.zodSchema)}let o=n(e.zodSchema),s=a[o&&o in a?o:e.zodSchema._zod.def.type];if(s){let t={...s(e,i)};for(let t in e.jsonSchema)delete e.jsonSchema[t];Object.assign(e.jsonSchema,t)}}});return se(r(s.subject)?s.subject:{},o,i)},Q=(e,t)=>{if(b(e))return[e,!1];let n=!1,r=y.map(e=>{let[r,i]=Q(e,t);return n||=i,r}),i=y.omit(t),a={properties:i,examples:y.map(i),required:y.without(t),allOf:r,oneOf:r,anyOf:r},o=y.evolve(a,e);return[o,n||!!o.required?.length]},ce=({method:e,path:t,schema:n,mimeTypes:r,variant:i,makeRef:a,composition:o,hasMultipleStatusCodes:s,statusCode:l,brandHandling:u,seenIds:d,description:p=`${e.toUpperCase()} ${t} ${c(i)} response ${s?l:``}`.trim()})=>{if(!f(e,r))return{description:p};let h=B(Z(n,{rules:{...u,...X},ctx:{isResponse:!0,makeRef:a,path:t,method:e,seenIds:d}})),_=[];x(h)&&h.examples&&(_.push(...h.examples),delete h.examples);let v=o===`components`?a(n,h,m(p)):h;return{description:p,content:y.fromPairs(r.map(e=>[e,{[e===g.sse?`itemSchema`:`schema`]:v,examples:J(_)}]))}},le=({format:e})=>{let t={type:`http`,scheme:`bearer`};return e&&(t.bearerFormat=e),t},ue=({name:e},t)=>{let n={type:`apiKey`,in:`query`,name:e};return t?.includes(`body`)&&(t?.includes(`query`)?(n[`x-in-alternative`]=`body`,n.description=`${e} CAN also be supplied within the request body`):(n[`x-in-actual`]=`body`,n.description=`${e} MUST be supplied within the request body instead of query`)),n},de=({name:e})=>({type:`apiKey`,in:`header`,name:e}),fe=({name:e})=>({type:`apiKey`,in:`cookie`,name:e}),pe=({url:e})=>({type:`openIdConnect`,openIdConnectUrl:e}),$=({flows:e={},oauth2MetadataUrl:t})=>({type:`oauth2`,flows:y.map(e=>({...e,scopes:e.scopes||{}}),y.reject(y.isNil,e)),oauth2MetadataUrl:t}),me=(e,t=[])=>{let n=e=>e.type===`basic`?{type:`http`,scheme:`basic`}:e.type===`bearer`?le(e):e.type===`input`?ue(e,t):e.type===`header`?de(e):e.type===`cookie`?fe(e):e.type===`openid`?pe(e):$(e);return e.map(e=>e.map(({deprecated:e,...t})=>({...n(t),deprecated:e})))},he=(e,t,n)=>e.map(e=>e.reduce((e,r)=>{let i=n(r),a=[`oauth2`,`openIdConnect`].includes(r.type);return Object.assign(e,{[i]:a?t:[]})},{})),ge=({schema:e,brandHandling:t,makeRef:n,path:r,method:i,seenIds:a})=>Z(e,{rules:{...t,...X},ctx:{isResponse:!1,makeRef:n,path:r,method:i,seenIds:a}}),_e=({method:e,path:t,bodyJsonSchema:n,hasRequiredBodyProps:i,flatRequest:a,mimeType:o,makeRef:s,composition:c,paramNames:l,description:u=`${e.toUpperCase()} ${t} Request body`})=>{let d=B(n),f=[];x(d)&&d.examples&&(f.push(...d.examples),delete d.examples);let p={schema:c===`components`?s(JSON.stringify(d),d,m(u)):d,examples:J(f.length?f:a.examples?.filter(e=>r(e)&&!Array.isArray(e)).map(y.omit(l))||[])},h={description:u,content:{[o]:p}};return(i||o===g.raw)&&(h.required=!0),h},ve=e=>Object.entries(e).reduce((e,[t,n])=>{if(!n)return e;if(typeof n==`string`)return e.concat({name:t,description:n});let{url:r,...i}=n,a={...i,name:t};return r&&(a.externalDocs={...a.externalDocs,url:r}),e.concat(a)},[]),ye=(e,t=50)=>!e||e.length<=t?e:e.slice(0,Math.max(1,t||0)-1)+`…`,be=e=>e.length?e.slice():void 0;export{me as a,Q as c,P as d,ye as f,A as h,ce as i,ae as l,D as m,ge as n,he as o,k as p,oe as r,ve as s,_e as t,be as u};
1
+ import{$ as e,F as t,G as n,I as r,J as i,K as a,N as o,Q as s,R as c,W as l,X as u,j as d,nt as f,q as p,r as m,w as h,x as g,y as _}from"./routing-walker-CcgJ8aiU.js";import{z as v}from"zod";import*as y from"ramda";import{isReferenceObject as b,isSchemaObject as x}from"openapi3-ts/oas32";const S=e=>e.type===`object`,C=y.mergeDeepWith((e,t)=>{if(Array.isArray(e)&&Array.isArray(t))return y.concat(e,t);if(e===t)return t;throw Error(`Can not flatten properties`,{cause:{a:e,b:t}})}),w=new Set([`type`,`properties`,`required`,`examples`,`description`,`additionalProperties`]),T=e=>{for(let t of Object.keys(e))if(!w.has(t))return!1;return!0},E=y.pair(!0),ee=(e,t,n)=>!(`allOf`in e)||!e.allOf?[]:e.allOf.map(e=>{if(t===`throw`&&!(e.type===`object`&&T(e)))throw Error(`Can not merge`);return y.pair(n,e)}),te=e=>{let t=[];return e.anyOf&&t.push(...y.map(E,e.anyOf)),e.oneOf&&t.push(...y.map(E,e.oneOf)),t},ne=(e,t,n,r)=>{if(!a(e.propertyNames))return;let i=[];typeof e.propertyNames.const==`string`&&i.push(e.propertyNames.const),e.propertyNames.enum&&i.push(...e.propertyNames.enum.filter(e=>typeof e==`string`));let o={...Object(e.additionalProperties)};for(let e of i)t.properties[e]??=o;r||n.push(...i)},re=(e,t,n)=>{t.examples?.length&&(e.examples=n?y.concat(e.examples||[],t.examples):c(e.examples?.filter(a)||[],t.examples.filter(a),([e,t])=>y.mergeDeepRight(e,t)))},D=(e,t=`coerce`)=>{let n=[y.pair(!1,e)],r={type:`object`,properties:{}},i=[];for(let[e,a]of n)a.description&&(r.description??=a.description),n.push(...ee(a,t,e)),n.push(...te(a)),re(r,a,e),S(a)&&(n.push([e,{examples:O(a)}]),a.properties&&(r.properties=(t===`throw`?C:y.mergeDeepRight)(r.properties,a.properties),!e&&a.required&&i.push(...a.required)),ne(a,r,i,e));return i.length&&(r.required=[...new Set(i)]),r},O=e=>Object.entries(e.properties||{}).reduce((e,[t,n])=>{let{examples:r=[]}=a(n)?n:{};return c(e,r.map(y.objOf(t)),([e,t])=>({...e,...t}))},[]),k=`x-coerce`,A=(e,t)=>{if(e[`x-coerce`]===!0)return!0;if(e.anyOf)return e.anyOf.some(e=>A(e,t));if(e.oneOf)return e.oneOf.some(e=>A(e,t));if(e.allOf)return e.allOf.every(e=>A(e,t));if(e.type===void 0||e.type===`string`)return!0;if(t===`query`&&[`array`,`object`].includes(e.type)){let n=[e.items,e.prefixItems,e.additionalItems,Object.values(e.properties??{}),e.additionalProperties,e.propertyNames];for(let e of n){if(!a(e))continue;let n=Array.isArray(e)?e:[e];for(let e of n)if(a(e)&&!A(e,t))return!1}return!0}return!1};let j;const M=()=>j??=new Set(`a-im.accept.accept-additions.accept-charset.accept-datetime.accept-encoding.accept-features.accept-language.accept-signature.access-control.access-control-request-headers.access-control-request-method.alpn.alt-used.amp-cache-transform.apply-to-redirect-ref.authorization.available-dictionary.c-ext.c-man.c-opt.c-pep.c-pep-info.cache-control.cal-managed-id.caldav-timezones.capsule-protocol.cdn-loop.cert-not-after.cert-not-before.client-cert.client-cert-chain.close.cmcd-object.cmcd-request.cmcd-session.cmcd-status.cmsd-dynamic.cmsd-static.concealed-auth-export.configuration-context.connection.content-digest.content-disposition.content-encoding.content-id.content-language.content-length.content-location.content-md5.content-range.content-script-type.content-type.cookie.cookie2.cta-common-access-token.dasl.date.dav.default-style.delta-base.deprecation.depth.derived-from.destination.detached-jws.dictionary-id.differential-id.digest.dpop.early-data.ediint-features.expect.expect-ct.ext.forwarded.from.getprofile.hobareg.host.http2-settings.if.if-match.if-modified-since.if-none-match.if-range.if-schedule-tag-match.if-unmodified-since.im.include-referred-token-binding-id.incremental.isolation.keep-alive.label.last-event-id.link.link-template.lock-token.man.max-forwards.memento-datetime.meter.method-check.method-check-expires.mime-version.negotiate.odata-entityid.odata-isolation.odata-maxversion.odata-version.opt.ordering-type.origin.origin-agent-cluster.oscore.oslc-core-version.overwrite.pep.pep-info.permissions-policy.pics-label.ping-from.ping-to.position.pragma.prefer.preference-applied.priority.profileobject.protocol.protocol-info.protocol-query.protocol-request.proxy-authorization.proxy-features.proxy-instruction.range.redirect-ref.referer.referer-root.referrer-policy.repeatability-client-id.repeatability-first-sent.repeatability-request-id.repeatability-result.replay-nonce.reporting-endpoints.repr-digest.safe.schedule-reply.schedule-tag.sec-fetch-storage-access.sec-gpc.sec-purpose.sec-token-binding.sec-websocket-extensions.sec-websocket-key.sec-websocket-protocol.sec-websocket-version.security-scheme.signature.signature-input.slug.soapaction.status-uri.sunset.surrogate-capability.tcn.te.timeout.topic.traceparent.tracestate.trailer.transfer-encoding.ttl.upgrade.urgency.uri.user-agent.variant-vary.via.want-content-digest.want-digest.want-repr-digest.want-unencoded-digest.warning.x-content-type-options.x-frame-options`.split(`.`)),N={integer:0,number:0,string:``,boolean:!1,object:{},null:null,array:[]},P=e=>e.replace(u,e=>`{${e.slice(1)}}`),F=({},e)=>{if(e.isResponse)throw new h(`Please use ez.upload() only for input.`,e);return{type:`string`,format:`binary`}},I=({jsonSchema:e})=>({...e,externalDocs:{description:`raw binary data`,url:`https://swagger.io/specification/#working-with-binary-data`}}),L=({zodSchema:e,jsonSchema:t})=>{if(!p(e,`union`)||!(`discriminator`in e._zod.def))return t;let n=e._zod.def.discriminator;return{...t,discriminator:t.discriminator??{propertyName:n}}},R=y.tryCatch(({jsonSchema:e})=>{if(!e.allOf)throw`no allOf`;return D(e,`throw`)},(e,{jsonSchema:t})=>t),z=({jsonSchema:e})=>{if(!e.anyOf||!e.anyOf.length)return e;let t=e.anyOf[0];return Object.assign(t,{type:K(t.type)})},B=e=>e,V=({jsonSchema:e},t)=>{if(t.isResponse)throw new h(`Please use ez.dateOut() for output.`,t);return e},H=({jsonSchema:e},t)=>{if(!t.isResponse)throw new h(`Please use ez.dateIn() for input.`,t);return e},U=()=>({type:`string`,format:`bigint`,pattern:`^-?\\d+$`}),W=({zodSchema:e,jsonSchema:t})=>e._zod.def.rest===null?{...t,items:{not:{}}}:t,G=e=>{let t=Array.isArray(e.type)?e.type[0]:e.type;return N?.[t]},K=e=>e===`null`?e:typeof e==`string`?[e,`null`]:e&&[...new Set(e).add(`null`)],ie=({zodSchema:e,jsonSchema:t},r)=>{let i=e._zod.def[r.isResponse?`out`:`in`],a=e._zod.def[r.isResponse?`in`:`out`];if(!p(i,`transform`))return t;let o=B(Z(a,{ctx:r}));if(x(o))if(r.isResponse){let e=n(i,G(o));if(e&&[`number`,`string`,`boolean`].includes(e))return{...t,type:e}}else{let{type:e,...t}=o;return{...t,format:`${t.format||e} (preprocessed)`}}return t},q=({jsonSchema:e})=>{if(e.type!==`object`)return e;let t=e;return!t.properties||!(`raw`in t.properties)||!a(t.properties.raw)?e:t.properties.raw},J=e=>e.length?y.fromPairs(y.zip(y.times(e=>`example${e+1}`,e.length),y.map(y.objOf(`dataValue`),e))):void 0,Y=(e,t)=>t?.has(e)||e.startsWith(`x-`)||M().has(e),ae=({method:e,path:t,security:n,inputSources:r,isHeader:i})=>{let a=new Set(l(t)),o=r.includes(`query`),s=r.includes(`params`),c=r.includes(`headers`),u=r.includes(`cookies`)||r.includes(`signedCookies`),d;c&&n&&(d=m(n,`header`));let f;return u&&n&&(f=m(n,`cookie`)),{pathParams:a,getLocation:n=>{if(s&&a.has(n)&&a.delete(n))return`path`;if(u&&f?.has(n))return`cookie`;if(c&&(i?.(n,e,t)??Y(n,d)))return`header`;if(o&&e!==`query`)return`query`},isQueryEnabled:o}},oe=({path:e,method:t,flatRequest:n,makeRef:r,composition:o,getLocation:s,description:c=`${t.toUpperCase()} ${e} Parameter`})=>{let l=[];for(let[e,t]of Object.entries(n.properties)){if(!a(t))continue;let u=s(e);if(!u)continue;let d=B(t),f=o===`components`?r(t.id||JSON.stringify(t),d,t.id||i(c,e)):d;l.push({name:e,in:u,deprecated:t.deprecated,required:n.required?.includes(e)||u===`path`,description:d.description||c,schema:f,examples:J(x(d)&&d.examples?.length?d.examples:y.pluck(e,n.examples?.filter(y.both(a,y.has(e)))||[]))})}return l},X={nullable:z,union:L,bigint:U,intersection:R,tuple:W,pipe:ie,[o]:V,[d]:H,[g]:F,[_]:q,[t]:I},se=(e,t,n)=>{let r=[e,t],i=e=>/schema\d+$/.test(e)?void 0:e;for(let e=0;e<r.length;e++){let a=r[e];if(y.is(Object,a)){if(b(a)&&!a.$ref.startsWith(`#/components`)){let e=a.$ref.split(`/`).pop(),r=t[e];if(r){let t=r.id||i(e);a.$ref=n.makeRef(t||r,B(r),t).$ref}continue}r.push(...y.values(a))}y.is(Array,a)&&r.push(...y.values(a))}return e},Z=(e,{ctx:t,rules:n=X})=>{let{$defs:i={},properties:o={}}=v.toJSONSchema(v.object({subject:e}),{unrepresentable:`any`,io:t.isResponse?`output`:`input`,override:e=>{let i=v.globalRegistry.get(e.zodSchema)?.id;if(i){let n=t.seenIds.get(i);if(n&&n!==e.zodSchema)throw new h(`The meta id "${i}" is used by two different schemas. Please make the ids unique or reuse the same schema instance.`,t);t.seenIds.set(i,e.zodSchema)}let a=r(e.zodSchema),o=n[a&&a in n?a:e.zodSchema._zod.def.type];if(o){let n={...o(e,t)};for(let t in e.jsonSchema)delete e.jsonSchema[t];Object.assign(e.jsonSchema,n)}}});return se(a(o.subject)?o.subject:{},i,t)},Q=(e,t)=>{if(b(e))return[e,!1];let n=!1,r=y.map(e=>{let[r,i]=Q(e,t);return n||=i,r}),i=y.omit(t),a={properties:i,examples:y.map(i),required:y.without(t),allOf:r,oneOf:r,anyOf:r},o=y.evolve(a,e);return[o,n||!!o.required?.length]},ce=({method:t,path:n,schema:r,mimeTypes:a,variant:o,makeRef:c,composition:l,hasMultipleStatusCodes:u,statusCode:d,brandHandling:p,seenIds:m,description:h=`${t.toUpperCase()} ${n} ${e(o)} response ${u?d:``}`.trim()})=>{if(!s(t,a))return{description:h};let g=B(Z(r,{rules:{...p,...X},ctx:{isResponse:!0,makeRef:c,path:n,method:t,seenIds:m}})),_=[];x(g)&&g.examples&&(_.push(...g.examples),delete g.examples);let v=l===`components`?c(r,g,i(h)):g;return{description:h,content:y.fromPairs(a.map(e=>[e,{[e===f.sse?`itemSchema`:`schema`]:v,examples:J(_)}]))}},le=({format:e})=>{let t={type:`http`,scheme:`bearer`};return e&&(t.bearerFormat=e),t},ue=({name:e},t)=>{let n={type:`apiKey`,in:`query`,name:e};return t?.includes(`body`)&&(t?.includes(`query`)?(n[`x-in-alternative`]=`body`,n.description=`${e} CAN also be supplied within the request body`):(n[`x-in-actual`]=`body`,n.description=`${e} MUST be supplied within the request body instead of query`)),n},de=({name:e})=>({type:`apiKey`,in:`header`,name:e}),fe=({name:e})=>({type:`apiKey`,in:`cookie`,name:e}),pe=({url:e})=>({type:`openIdConnect`,openIdConnectUrl:e}),$=({flows:e={},oauth2MetadataUrl:t})=>({type:`oauth2`,flows:y.map(e=>({...e,scopes:e.scopes||{}}),y.reject(y.isNil,e)),oauth2MetadataUrl:t}),me=(e,t=[])=>{let n=e=>e.type===`basic`?{type:`http`,scheme:`basic`}:e.type===`bearer`?le(e):e.type===`input`?ue(e,t):e.type===`header`?de(e):e.type===`cookie`?fe(e):e.type===`openid`?pe(e):$(e);return e.map(e=>e.map(({deprecated:e,...t})=>({...n(t),deprecated:e})))},he=(e,t,n)=>e.map(e=>e.reduce((e,r)=>{let i=n(r),a=[`oauth2`,`openIdConnect`].includes(r.type);return Object.assign(e,{[i]:a?t:[]})},{})),ge=({schema:e,brandHandling:t,makeRef:n,path:r,method:i,seenIds:a})=>Z(e,{rules:{...t,...X},ctx:{isResponse:!1,makeRef:n,path:r,method:i,seenIds:a}}),_e=({method:e,path:t,bodyJsonSchema:n,hasRequiredBodyProps:r,flatRequest:o,mimeType:s,makeRef:c,composition:l,paramNames:u,description:d=`${e.toUpperCase()} ${t} Request body`})=>{let p=B(n),m=[];x(p)&&p.examples&&(m.push(...p.examples),delete p.examples);let h={schema:l===`components`?c(JSON.stringify(p),p,i(d)):p,examples:J(m.length?m:o.examples?.filter(e=>a(e)&&!Array.isArray(e)).map(y.omit(u))||[])},g={description:d,content:{[s]:h}};return(r||s===f.raw)&&(g.required=!0),g},ve=e=>Object.entries(e).reduce((e,[t,n])=>{if(!n)return e;if(typeof n==`string`)return e.concat({name:t,description:n});let{url:r,...i}=n,a={...i,name:t};return r&&(a.externalDocs={...a.externalDocs,url:r}),e.concat(a)},[]),ye=(e,t=50)=>!e||e.length<=t?e:e.slice(0,Math.max(1,t||0)-1)+`…`,be=e=>e.length?e.slice():void 0;export{me as a,Q as c,P as d,ye as f,A as h,ce as i,ae as l,D as m,ge as n,he as o,k as p,oe as r,ve as s,_e as t,be as u};
@@ -1,4 +1,4 @@
1
- import { M as ResponseVariant, g as CommonConfig, t as Routing } from "./routing-8iV6qx5U.js";
1
+ import { M as ResponseVariant, g as CommonConfig, t as Routing } from "./routing-uoFmENK3.js";
2
2
  import {
3
3
  c as IsHeader,
4
4
  l as depictTags,
@@ -6,7 +6,7 @@ import {
6
6
  s as Depicter,
7
7
  t as DocumentationError,
8
8
  u as trimSummary,
9
- } from "./errors-DLj5NHc7.js";
9
+ } from "./errors-BoYRbAGq.js";
10
10
  import { InfoObject, OpenApiBuilder, ServerObject } from "openapi3-ts/oas32";
11
11
  type Component = `${ResponseVariant}Response` | "requestParameter" | "requestBody";
12
12
  /** @desc user defined function that creates a component description from its properties */
@@ -1 +1 @@
1
- import{C as e,J as t,V as n,i as r,n as i,p as a,q as o,t as s,tt as c}from"./routing-walker-D9nfJshN.js";import{a as l,c as u,d,f,i as p,l as m,m as h,n as g,o as _,r as v,s as y,t as b,u as x}from"./documentation-helpers-CvDORFUg.js";import"zod";import*as S from"ramda";import{OpenApiBuilder as C}from"openapi3-ts/oas32";const w=({description:e,summary:t=e,trim:n})=>n(t);var T=class extends C{#e=new Map;#t=new Map;#n=new Map;#r=new Map;#i(e,t,n){let r=this.#n.get(e);if(!r){let t=+!n;do r=`${n??`Schema`}${t?this.#n.size+t:``}`,t++;while(this.rootDoc.components?.schemas?.[r]);this.#n.set(e,r)}return this.addSchema(r,t),{$ref:`#/components/schemas/${r}`}}#a(t,n,r){let i=r||o(n,t),a=this.#t.get(i);if(a===void 0)return this.#t.set(i,1),i;if(r)throw new e(`Duplicated operationId: "${r}"`,{method:n,isResponse:!1,path:t});return a++,this.#t.set(i,a),`${i}${a}`}#o(e){let t=JSON.stringify(e);for(let e in this.rootDoc.components?.securitySchemes||{})if(t===JSON.stringify(this.rootDoc.components?.securitySchemes?.[e]))return e;let n=(this.#e.get(e.type)||0)+1;return this.#e.set(e.type,n),`${e.type.toUpperCase()}_${n}`}#s({tags:e,server:t,info:n={title:`Generated by Express Zod API`,version:`0.0.0`}}){if(this.addInfo(n),e&&(this.rootDoc.tags=y(e)),t)for(let e of Array.isArray(t)?t:[t])this.addServer(typeof e==`string`?{url:e}:e)}#c(n,r){if(n===`head`||!r.includes(`:`))return;let i=t(r),a=this.#r.get(i);if(a!==void 0&&a!==r)throw new e(`Path has a duplicate: the normalized path "${i}" is already registered with different parameter names at "${a}"`,{method:n,path:r,isResponse:!1});a===void 0&&this.#r.set(i,r)}#l({config:t,descriptions:i,brandHandling:o,isHeader:s,summarizer:y=w,composition:C=`inline`}){let T={composition:C,brandHandling:o,makeRef:this.#i.bind(this),seenIds:new Map};return(o,C,w)=>{this.#c(o,C);let E={...T,path:C,method:o,endpoint:w},{description:D,summary:O,scopes:k,inputSchema:A,security:j}=w,M=n(o,t.inputSources),{pathParams:N,getLocation:P}=m({method:o,path:C,security:j,inputSources:M,isHeader:s}),F=this.#a(C,o,w.getOperationId(o)),I=g({...E,schema:A}),L=h(I),R=v({...E,getLocation:P,flatRequest:L,description:i?.requestParameter?.({method:o,path:C,operationId:F})});if(N.size)throw new e(`The input schema is missing the path parameter "${[...N][0]}"`,{method:o,path:C,isResponse:!1});let z={};for(let e of a){let t=w.getResponses(e);for(let{mimeTypes:n,schema:r,statusCodes:a}of t)for(let s of a)z[s]=p({...E,variant:e,schema:r,mimeTypes:n,statusCode:s,hasMultipleStatusCodes:t.length>1||a.length>1,description:i?.[`${e}Response`]?.({method:o,path:C,operationId:F,statusCode:s})})}let B;if(M.includes(`body`)){let e=S.pluck(`name`,R),[t,n]=u(I,e);B=b({...E,bodyJsonSchema:t,hasRequiredBodyProps:n,flatRequest:L,paramNames:e,mimeType:c[w.getProbableRequestType(o)],description:i?.requestBody?.({method:o,path:C,operationId:F})})}let V=_(l(r(j),M),k,e=>{let t=this.#o(e);return this.addSecurityScheme(t,e),t}),H={operationId:F,summary:y({summary:O,description:D,trim:f}),description:D,deprecated:w.isDeprecated||void 0,tags:x(w.tags),parameters:x(R),requestBody:B,security:x(V),responses:z};this.addPath(d(C),{[o]:H})}}constructor({hasHeadMethod:e=!0,...t}){super(),this.#s(t);let n=this.#l(t),r=e?i(n):n;s({...t,onEndpoint:r})}};export{T as Documentation,e as DocumentationError};
1
+ import{H as e,J as t,Y as n,i as r,n as i,nt as a,p as o,t as s,w as c}from"./routing-walker-CcgJ8aiU.js";import{a as l,c as u,d,f,i as p,l as m,m as h,n as g,o as _,r as v,s as y,t as b,u as x}from"./documentation-helpers-DBaBYdUT.js";import"zod";import*as S from"ramda";import{OpenApiBuilder as C}from"openapi3-ts/oas32";const w=({description:e,summary:t=e,trim:n})=>n(t);var T=class extends C{#e=new Map;#t=new Map;#n=new Map;#r=new Map;#i(e,t,n){let r=this.#n.get(e);if(!r){let t=+!n;do r=`${n??`Schema`}${t?this.#n.size+t:``}`,t++;while(this.rootDoc.components?.schemas?.[r]);this.#n.set(e,r)}return this.addSchema(r,t),{$ref:`#/components/schemas/${r}`}}#a(e,n,r){let i=r||t(n,e),a=this.#t.get(i);if(a===void 0)return this.#t.set(i,1),i;if(r)throw new c(`Duplicated operationId: "${r}"`,{method:n,isResponse:!1,path:e});return a++,this.#t.set(i,a),`${i}${a}`}#o(e){let t=JSON.stringify(e);for(let e in this.rootDoc.components?.securitySchemes||{})if(t===JSON.stringify(this.rootDoc.components?.securitySchemes?.[e]))return e;let n=(this.#e.get(e.type)||0)+1;return this.#e.set(e.type,n),`${e.type.toUpperCase()}_${n}`}#s({tags:e,server:t,info:n={title:`Generated by Express Zod API`,version:`0.0.0`}}){if(this.addInfo(n),e&&(this.rootDoc.tags=y(e)),t)for(let e of Array.isArray(t)?t:[t])this.addServer(typeof e==`string`?{url:e}:e)}#c(e,t){if(e===`head`||!t.includes(`:`))return;let r=n(t),i=this.#r.get(r);if(i!==void 0&&i!==t)throw new c(`Path has a duplicate: the normalized path "${r}" is already registered with different parameter names at "${i}"`,{method:e,path:t,isResponse:!1});i===void 0&&this.#r.set(r,t)}#l({config:t,descriptions:n,brandHandling:i,isHeader:s,summarizer:y=w,composition:C=`inline`}){let T={composition:C,brandHandling:i,makeRef:this.#i.bind(this),seenIds:new Map};return(i,C,w)=>{this.#c(i,C);let E={...T,path:C,method:i,endpoint:w},{description:D,summary:O,scopes:k,inputSchema:A,security:j}=w,M=e(i,t.inputSources),{pathParams:N,getLocation:P}=m({method:i,path:C,security:j,inputSources:M,isHeader:s}),F=this.#a(C,i,w.getOperationId(i)),I=g({...E,schema:A}),L=h(I),R=v({...E,getLocation:P,flatRequest:L,description:n?.requestParameter?.({method:i,path:C,operationId:F})});if(N.size)throw new c(`The input schema is missing the path parameter "${[...N][0]}"`,{method:i,path:C,isResponse:!1});let z={};for(let e of o){let t=w.getResponses(e);for(let{mimeTypes:r,schema:a,statusCodes:o}of t)for(let s of o)z[s]=p({...E,variant:e,schema:a,mimeTypes:r,statusCode:s,hasMultipleStatusCodes:t.length>1||o.length>1,description:n?.[`${e}Response`]?.({method:i,path:C,operationId:F,statusCode:s})})}let B;if(M.includes(`body`)){let e=S.pluck(`name`,R),[t,r]=u(I,e);B=b({...E,bodyJsonSchema:t,hasRequiredBodyProps:r,flatRequest:L,paramNames:e,mimeType:a[w.getProbableRequestType(i)],description:n?.requestBody?.({method:i,path:C,operationId:F})})}let V=_(l(r(j),M),k,e=>{let t=this.#o(e);return this.addSecurityScheme(t,e),t}),H={operationId:F,summary:y({summary:O,description:D,trim:f}),description:D,deprecated:w.isDeprecated||void 0,tags:x(w.tags),parameters:x(R),requestBody:B,security:x(V),responses:z};this.addPath(d(C),{[i]:H})}}constructor({hasHeadMethod:e=!0,...t}){super(),this.#s(t);let n=this.#l(t),r=e?i(n):n;s({...t,onEndpoint:r})}};export{T as Documentation,c as DocumentationError};
@@ -1,4 +1,4 @@
1
- import { D as ClientMethod, O as Method, f as Tag } from "./routing-8iV6qx5U.js";
1
+ import { D as ClientMethod, O as Method, f as Tag } from "./routing-uoFmENK3.js";
2
2
  import { z } from "zod";
3
3
  import { ReferenceObject, SchemaObjectValue, TagObject } from "openapi3-ts/oas32";
4
4
  interface ReqResCommons {
package/dist/index.d.ts CHANGED
@@ -31,14 +31,14 @@ import {
31
31
  w as Extension,
32
32
  x as arrayResultHandler,
33
33
  y as AbstractResultHandler,
34
- } from "./routing-8iV6qx5U.js";
34
+ } from "./routing-uoFmENK3.js";
35
35
  import {
36
36
  a as RoutingError,
37
37
  i as OutputValidationError,
38
38
  n as InputValidationError,
39
39
  r as MissingPeerError,
40
40
  t as DocumentationError,
41
- } from "./errors-DLj5NHc7.js";
41
+ } from "./errors-BoYRbAGq.js";
42
42
  import { z } from "zod";
43
43
  import express, { CookieOptions, Request, Response } from "express";
44
44
  import http from "node:http";
@@ -245,7 +245,16 @@ declare const createCookieMiddleware: (baseOptions?: CookieOptions) => Middlewar
245
245
  * @param options — Partial options passed to the express-rate-limit constructor.
246
246
  * @example createRateLimitMiddleware({ windowMs: 60000, max: 100 })
247
247
  */
248
- declare const createRateLimitMiddleware: (options?: Partial<Options>) => ExpressMiddleware<
248
+ declare const createRateLimitMiddleware: (
249
+ options?: Partial<Options> & {
250
+ /**
251
+ * @desc The HTTP status code to send back when a client is rate-limited.
252
+ * @default 429
253
+ * @modifies ResultHandler.negative.statusCode — overrides when specified explicitly (opt-in, no breaking changes).
254
+ */
255
+ statusCode?: number;
256
+ },
257
+ ) => ExpressMiddleware<
249
258
  AugmentedRequest,
250
259
  import("express-serve-static-core").Response<any, Record<string, any>, number>,
251
260
  {
@@ -290,6 +299,13 @@ interface BuildProps<
290
299
  * @see TagOverrides
291
300
  * */
292
301
  tag?: Tag | Tag[];
302
+ /**
303
+ * @desc The status code(s) specific to the Endpoint, overriding the ones configured by the ResultHandler.
304
+ * Narrows the response schemas of ResultHandler by status codes in the generated Documentation.
305
+ * @example [201, 403] — the Endpoint narrows the ResultHandler responses to either "Created" or "Forbidden".
306
+ * @see ApiResponse#statusCode - the status codes used by ResultHandler
307
+ * */
308
+ statusCode?: number | [number, ...number[]];
293
309
  /** @desc Marks the operation deprecated in the generated Documentation */
294
310
  deprecated?: boolean;
295
311
  }
@@ -306,6 +322,7 @@ declare class EndpointsFactory<
306
322
  > {
307
323
  protected resultHandler: AbstractResultHandler;
308
324
  protected schema: IN;
325
+ protected statusCodes: Set<number>;
309
326
  protected middlewares: AbstractMiddleware[];
310
327
  /**
311
328
  * @param resultHandler An instance of ResultHandler for handling both Endpoint outputs and all possible errors.
@@ -398,6 +415,7 @@ declare class EndpointsFactory<
398
415
  | {
399
416
  provider?: ((request: R, response: S) => AOUT | Promise<AOUT>) | undefined;
400
417
  transformer?: (err: Error) => Error;
418
+ statusCode?: number | [number, ...number[]];
401
419
  }
402
420
  | undefined,
403
421
  ) => EndpointsFactory<Extension<IN, undefined>, (CTX extends Record<string, never> ? AOUT : CTX) & AOUT, SCO>;
@@ -430,6 +448,7 @@ declare class EndpointsFactory<
430
448
  scope,
431
449
  tag,
432
450
  method,
451
+ statusCode,
433
452
  ...rest
434
453
  }: BuildProps<BIN, BOUT, IN, CTX, SCO>): Endpoint<FinalInputSchema<IN, BIN>, BOUT, CTX>;
435
454
  /**
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import{B as e,C as t,D as n,E as r,G as i,H as a,I as o,N as s,O as c,R as l,S as u,T as d,V as f,X as p,a as ee,c as m,d as te,et as ne,f as h,g,h as _,j as re,k as ie,l as v,m as y,o as ae,p as oe,s as b,t as se,tt as x,u as ce,w as le,x as ue,y as de,z as S}from"./routing-walker-D9nfJshN.js";import{t as C}from"./peer-helpers-WZaMOjAf.js";import{h as fe,l as pe,m as me,p as he}from"./documentation-helpers-CvDORFUg.js";import{globalRegistry as w,z as T}from"zod";import*as ge from"ramda";import E,{isHttpError as _e}from"http-errors";import ve,{blue as ye,cyanBright as be,green as xe,hex as D,italic as Se,red as Ce,whiteBright as O}from"ansis";import{inspect as we}from"node:util";import{performance as k}from"node:perf_hooks";import A from"express";import Te from"node:http";import Ee from"node:https";import{setInterval as De}from"node:timers/promises";import{createRequest as Oe,createResponse as ke}from"node-mocks-http";function Ae(e){return e}const je=(e,t)=>e&&t?e.and(t):e||t,Me=(e,t)=>e?e.and(t):t;var Ne=class e{#e;constructor(e){this.#e=e}async execute(...t){try{return await this.#e(...t)}catch(r){let{response:i,logger:a,error:o}=t[0],s=new n(S(r),o||void 0);e.lastResort({response:i,logger:a,error:s})}}static lastResort({error:e,logger:t,response:n}){t.error(`Result handler failure`,e);let r=m(E(500,`An error occurred while serving the result: ${e.message}.`+(e.handled?`\nOriginal error: ${e.handled.message}.`:``),{expose:_e(e.cause)?e.cause.expose:!1}));n.status(500).type(`text/plain`).end(r)}},j=class extends Ne{#e;#t;constructor(e){super(e.handler),this.#e=e.positive,this.#t=e.negative}getPositiveResponse(e){return ce(this.#e,{variant:`positive`,args:[e]})}getNegativeResponse(){return ce(this.#t,{variant:`negative`,args:[]})}};const M=T.object({status:T.literal(`error`),error:T.object({message:T.string()})});w.add(M,{examples:[{status:`error`,error:{message:`Sample error message`}}]});const N=new j({positive:e=>{let t=T.object({status:T.literal(`success`),data:e}),n=o(e);return n.length&&w.add(t,{examples:n.map(e=>({status:`success`,data:e}))}),t},negative:M,handler:({error:e,input:t,output:n,request:r,response:i,logger:a})=>{if(e){let n=b(e);v(n,a,r,t),i.status(n.statusCode).set(n.headers).json({status:`error`,error:{message:m(n)}});return}i.status(h.positive).json({status:`success`,data:n})}}),P=T.string();w.add(P,{examples:[`Sample error message`]});const F=new j({positive:e=>{let t=e instanceof T.ZodObject&&`items`in e.shape&&e.shape.items instanceof T.ZodArray?e.shape.items:T.array(T.any());if(o(t).length)return t;let n=o(e).filter(e=>i(e)&&`items`in e&&Array.isArray(e.items)).map(e=>e.items);if(n?.length){let e=t.meta();w.remove(t).add(t,{...e,examples:n})}return t},negative:{schema:P,mimeType:`text/plain`},handler:({response:e,output:t,error:n,logger:r,request:i,input:a})=>{if(n){let t=b(n);v(t,r,i,a),e.status(t.statusCode).type(`text/plain`).send(m(t));return}if(`items`in t&&Array.isArray(t.items)){e.status(h.positive).json(t.items);return}throw Error(`Property 'items' is missing in the endpoint output`)}}),I=e=>{let t=[];return e.scope&&t.push(e.scope),e.noStore&&t.push(`no-store`),e.noCache&&t.push(`no-cache`),e.maxAge!==void 0&&t.push(`max-age=${e.maxAge}`),e.sMaxAge!==void 0&&t.push(`s-maxage=${e.sMaxAge}`),e.mustRevalidate&&t.push(`must-revalidate`),e.proxyRevalidate&&t.push(`proxy-revalidate`),e.mustUnderstand&&t.push(`must-understand`),e.immutable&&t.push(`immutable`),e.noTransform&&t.push(`no-transform`),e.staleWhileRevalidate!==void 0&&t.push(`stale-while-revalidate=${e.staleWhileRevalidate}`),e.staleIfError!==void 0&&t.push(`stale-if-error=${e.staleIfError}`),t.join(`, `)},Pe={"max-age":`maxAge`,"max-stale":`maxStale`,"min-fresh":`minFresh`,"stale-if-error":`staleIfError`},Fe={"no-cache":`noCache`,"no-store":`noStore`,"no-transform":`noTransform`,"only-if-cached":`onlyIfCached`},Ie=e=>{if(!e)return;let t={};for(let n of e.toLowerCase().split(`,`)){let[e,r]=n.split(`=`),i=Pe[e.trim()];if(i){let e=parseInt(r?.trim()??``,10);isNaN(e)||(t[i]=e);continue}let a=Fe[e.trim()];a&&(t[a]=!0)}return t},L=e=>new _({handler:async({request:t,response:n})=>(e&&n.setHeader(`Cache-Control`,I(e)),{get ifNoneMatch(){let e=t.headers[`if-none-match`];if(!e)return;let n=e.trim();return n===`*`?n:n.split(`,`).map(e=>e.trim().replace(/^(?:W\/)?"/,``).replace(/"$/,``))},get ifModifiedSince(){let e=t.headers[`if-modified-since`];if(!e)return;let n=new Date(e);return isNaN(n.getTime())?void 0:n},get cacheControl(){return Ie(t.headers[`cache-control`])},addCachePolicy:t=>{n.setHeader(`Cache-Control`,I({...e,...t}))},setETag:e=>{n.setHeader(`ETag`,e.startsWith(`"`)?e:`"${e}"`)},setLastModified:e=>{n.setHeader(`Last-Modified`,e.toUTCString())},setVary:(...e)=>{n.setHeader(`Vary`,e.join(`, `))},setExpires:e=>{n.setHeader(`Expires`,e.toUTCString())},clearSiteData:()=>{n.setHeader(`Clear-Site-Data`,`"cache"`)},notModified:()=>{n.status(304).end()}})}),R=e=>new _({handler:async({request:t,response:n})=>({getCookie:e=>t.signedCookies?.[e]??t.cookies?.[e],setCookie:(t,r,i)=>{n.cookie(t,r,{...e,...i})},clearCookie:(t,r)=>{n.clearCookie(t,{...e,...r})}})}),z=e=>{let t=C(`express-rate-limit`)({...e,handler:(e,t,n,r)=>{n(E(429,r.message))}}),{getKey:n,resetKey:r}=t,i={getKey:n,resetKey:r};return new y(t,{provider:t=>({rateLimit:{...i,...t[e?.requestPropertyName??`rateLimit`]}})})};var B=class e{resultHandler;schema=void 0;middlewares=[];constructor(e){this.resultHandler=e}#e(t){let n=new e(this.resultHandler);return n.middlewares=this.middlewares.concat(t),n.schema=je(this.schema,t.schema),n}addMiddleware(e){return this.#e(e instanceof _?e:new _(e))}useCookies(...e){return this.#e(R(...e))}useCache(...e){return this.#e(L(...e))}useRateLimit(...e){return this.#e(z(...e))}use=this.addExpressMiddleware;addExpressMiddleware(...e){return this.#e(new y(...e))}addContext(e){return this.#e(new _({handler:({ctx:t})=>e(t)}))}build({input:e=l,output:t,operationId:n,scope:r,tag:i,method:a,...o}){let{middlewares:s,resultHandler:c}=this,u=typeof a==`string`?[a]:a,d=typeof n==`function`?n:e=>n&&`${n}${e===`head`?`__HEAD`:``}`,f=typeof r==`string`?[r]:r||[],p=typeof i==`string`?[i]:i||[];return new ae({...o,middlewares:s,outputSchema:t,resultHandler:c,scopes:f,tags:p,methods:u,getOperationId:d,inputSchema:Me(this.schema,e)})}buildVoid({handler:e,...t}){return this.build({...t,output:l,handler:async t=>(await e(t),{})})}};const Le=new B(N),Re=new B(F),V={debug:ye,info:xe,warn:D(`#FFA500`),error:Ce,ctx:be},H={debug:10,info:20,warn:30,error:40},ze=e=>i(e)&&Object.keys(H).some(t=>t in e),Be=e=>e in H,Ve=(e,t)=>H[e]<H[t],U=ge.memoizeWith((e,t)=>`${e}${t}`,(e,t=0)=>Intl.NumberFormat(void 0,{useGrouping:!1,minimumFractionDigits:0,maximumFractionDigits:t,style:`unit`,unitDisplay:`long`,unit:e})),He=e=>e<1e-6?U(`nanosecond`,3).format(e/1e-6):e<.001?U(`nanosecond`).format(e/1e-6):e<1?U(`microsecond`).format(e/.001):e<1e3?U(`millisecond`).format(e):e<6e4?U(`second`,2).format(e/1e3):U(`minute`,2).format(e/6e4);var W=class e{config;constructor({color:e=ve.isSupported(),level:t=p.isProduction?`warn`:`debug`,depth:n=2,ctx:r={}}={}){this.config={color:e,level:t,depth:n,ctx:r}}format(e){let{depth:t,color:n,level:r}=this.config;return we(e,{depth:t,colors:n,breakLength:r===`debug`?80:1/0,compact:r!==`debug`||3})}print(e,t,n){let{level:r,ctx:{requestId:i,...a},color:o}=this.config;if(r===`silent`||Ve(e,r))return;let s=[new Date().toISOString()];i&&s.push(o?V.ctx(i):i),s.push(o?`${V[e](e)}:`:`${e}:`,t),n!==void 0&&s.push(this.format(n)),Object.keys(a).length>0&&s.push(this.format(a)),console.log(s.join(` `))}debug(e,t){this.print(`debug`,e,t)}info(e,t){this.print(`info`,e,t)}warn(e,t){this.print(`warn`,e,t)}error(e,t){this.print(`error`,e,t)}child(t){return new e({...this.config,ctx:t})}get ctx(){return this.config.ctx}profile(e){let t=k.now();return()=>{let n=k.now()-t,{message:r,severity:i=`debug`,formatter:a=He}=typeof e==`object`?e:{message:e};this.print(typeof i==`function`?i(n):i,r,a(n))}}},Ue=class{logger;config;#e=new WeakMap;constructor(e,t){this.logger=e,this.config=t}#t(e,t,n){if(!e.isSchemaChecked){for(let e of[`input`,`output`]){let r=[T.toJSONSchema(t[`${e}Schema`],{unrepresentable:`any`})];for(let t of r){t.type&&t.type!==`object`&&this.logger.warn(`Endpoint ${e} schema is not object-based`,n);for(let e of[`allOf`,`oneOf`,`anyOf`])t[e]&&r.push(...t[e])}}if(t.getProbableRequestType()===`json`){let e=g(t.inputSchema,`input`);e&&this.logger.warn(`The final input schema of the endpoint contains an unsupported JSON payload type.`,{...n,reason:e})}for(let e of oe)for(let{mimeTypes:r,schema:i}of t.getResponses(e)){if(!r?.includes(x.json))continue;let t=g(i,`output`);t&&this.logger.warn(`The final ${e} response schema of the endpoint contains an unsupported JSON payload type.`,{...n,reason:t})}e.isSchemaChecked=!0}}#n(e,t,n,r,a){if(e.paths.has(r))return;let{pathParams:o,getLocation:s,isQueryEnabled:c}=pe({method:n,path:r,security:t.security,inputSources:f(n,this.config.inputSources)});if(!(o.size===0&&!c)){e.flat??=me(T.toJSONSchema(t.inputSchema,{unrepresentable:`any`,io:`input`,override:({zodSchema:e,jsonSchema:t})=>{(e._zod.traits.has(`$ZodPreprocess`)||`coerce`in e._zod.def&&e._zod.def.coerce)&&(t[he]=!0)}}));for(let[t,n]of Object.entries(e.flat.properties)){if(!i(n))continue;let r=s(t);(r===`path`||r===`query`)&&(r===`path`&&!e.flat.required?.includes(t)&&this.logger.warn(`The path parameter "${t}" is declared optional in the input schema, but path parameters are always required since Express matches the route only when the segment is present.`,{...a,name:t}),!fe(n,r)&&this.logger.warn(`The ${r} parameter "${t}" has a schema that most likely would not accept the parsed data, ${r===`path`?`since path parameters always arrive as strings`:`depending on the "queryParser" config option`}. Convert the parsed value from "z.string()" using ".transform()" method, or use "z.coerce" at least.`,{...a,name:t,jsonSchema:n}))}for(let e of o)this.logger.warn(`The input schema of the endpoint is most likely missing the parameter of the path it's assigned to.`,{...a,param:e});e.paths.add(r)}}check=(e,t,n)=>{let r=this.#e.get(n);r||(r={isSchemaChecked:!1,paths:new Set},this.#e.set(n,r)),this.#t(r,n,{method:e,path:t}),this.#n(r,n,e,t,{method:e,path:t})}};const G=e=>e.sort((e,t)=>ne(t)-+ne(e)||e.localeCompare(t)).join(`, `).toUpperCase(),We=e=>({method:t},n,r)=>{let i=G(e);n.set({Allow:i}),r(E(405,`${t} is not allowed`,{headers:{Allow:i}}))},Ge=({app:e,getLogger:t,config:n,routing:r})=>{let i=p.isProduction?void 0:new Ue(t(),n),a=new Map;return se({routing:r,config:n,onEndpoint:(e,t,r)=>{i?.check(e,t,r),a.has(t)||a.set(t,new Map(n.cors?[[`options`,r]]:[])),a.get(t)?.set(e,r)},onStatic:e.use.bind(e)}),a},K=({app:e,config:t,getLogger:n,...r})=>{let i=Ge({app:e,getLogger:n,config:t,...r}),a=new Map;for(let[r,o]of i){let i=Array.from(o.keys());i.includes(`get`)&&i.push(`head`);for(let[a,s]of o){let o=[];t.cors&&o.push((e,t,n)=>{t.set(`Access-Control-Allow-Methods`,G(i)),n()}),o.push(async(e,r)=>{let i=n(e);return s.execute({request:e,response:r,logger:i,config:t})}),e[a]?.(r,...o)}t.hintAllowedMethods!==!1&&a.set(r,We(i))}for(let[t,n]of a)e.all(t,n)},Ke=e=>`_httpMessage`in e&&typeof e._httpMessage==`object`&&e._httpMessage!==null&&`headersSent`in e._httpMessage&&typeof e._httpMessage.headersSent==`boolean`&&`setHeader`in e._httpMessage&&typeof e._httpMessage.setHeader==`function`,qe=e=>`server`in e&&typeof e.server==`object`&&e.server!==null&&`close`in e.server&&typeof e.server.close==`function`,Je=e=>`encrypted`in e&&typeof e.encrypted==`boolean`&&e.encrypted,Ye=({},e)=>void(!e.headersSent&&e.setHeader(`connection`,`close`)),Xe=e=>{let{promise:t,resolve:n,reject:r}=Promise.withResolvers();return e.close(e=>e?r(e):n()),t},Ze=({timeout:e=1e3,logger:t}={})=>{let n,r=new Set,i=new Set,a=e=>void i.delete(e),o=e=>a(e.destroy()),s=e=>void(Ke(e)?!e._httpMessage.headersSent&&e._httpMessage.setHeader(`connection`,`close`):o(e)),c=e=>void(n?e.destroy():i.add(e.once(`close`,()=>a(e)).once(`error`,()=>o(e)))),l=async()=>{for(let e of r)e.on(`request`,Ye);t?.info(`Graceful shutdown`,{sockets:i.size,timeout:e});for(let e of i)(Je(e)||qe(e))&&s(e);for await(let t of De(10,Date.now()))if(i.size===0||Date.now()-t>=e)break;for(let e of i)o(e);return Promise.allSettled(r.values().map(Xe))},u={sockets:i,add:(...e)=>{for(let t of e)if(!r.has(t)){r.add(t);for(let e of[`connection`,`secureConnection`])t.on(e,c)}return u},shutdown:()=>n??=l(),get isShuttingDown(){return!!n}};return u},q=Symbol.for(`express-zod-api`),Qe=({errorHandler:e,getLogger:t})=>async(n,r,i,a)=>n?e.execute({error:S(n),request:r,response:i,input:null,output:null,ctx:{},logger:t(r)}):a(),$e=({errorHandler:e,getLogger:t})=>async(n,r)=>{let i=E(404,`Can not ${n.method} ${n.path}`),a=t(n);await e.execute({request:n,response:r,logger:a,error:i,input:null,output:null,ctx:{}})},et=e=>(t,{},n)=>{if(Object.values(t?.files||[]).flat().find(({truncated:e})=>e))return n(e);n()},tt=({config:e})=>{let t=C(`cookie-parser`),{secret:n,...r}={...typeof e.cookies==`object`&&e.cookies};return t(n,Object.keys(r).length?r:void 0)},J=e=>typeof e==`function`?e:({},e,t)=>{e.set({"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Headers":`content-type`}),t()},nt=e=>({log:t=>{/not eligible/i.test(t)||e.debug(t)}}),rt=({getLogger:e,config:t})=>{let n=C(`express-fileupload`),{limitError:r,beforeUpload:i,...a}={...typeof t.upload==`object`&&t.upload},o=[];return o.push(async(t,r,o)=>{let s=e(t);return await i?.({request:t,logger:s}),n({debug:!0,...a,abortOnLimit:!1,parseNested:!0,logger:nt(s)})(t,r,o)}),r&&o.push(et(r)),o},it=(e,{},t)=>{Buffer.isBuffer(e.body)&&(e.body={raw:e.body}),t()},at=({logger:e,config:{childLoggerProvider:t,accessLogger:n=({method:e,path:t},n)=>n.debug(`${e}: ${t}`)}})=>async(r,i,a)=>{let o=await t?.({request:r,parent:e})||e;n?.(r,o),r.res&&(r.res.locals[q]={logger:o}),a()},ot=e=>t=>t?.res?.locals[q]?.logger||e;let Y=!1;const st=e=>{Y||(Y=!0,process.on(`deprecation`,({message:t,namespace:n,name:r,stack:i})=>e.warn(`${r} (${n}): ${t}`,i.split(`
2
- `).slice(1))))};let X,Z,Q;const ct=({servers:e,logger:t,options:{timeout:n,beforeExit:r,events:i=[`SIGINT`,`SIGTERM`]}})=>{X??=Ze({logger:t,timeout:n}),X.add(...e),r&&(Q??=new Set).add(r),Z??=async()=>{X?.isShuttingDown||(await X?.shutdown(),Q&&await Promise.allSettled(Q.values().map(async e=>e())),process.exit())};for(let e of i)process.listeners(e).includes(Z)||process.on(e,Z)},lt=e=>{if(e.columns<62)return;let t=Se(`for Angie`.padStart(52)),n=D(`#F5A9B8`),r=D(`#5BCEFA`),i=[r`8888888888${t}`,r`888`,r`888`,r`8888888 888 888 88888b. 888d888 .d88b. .d8888b .d8888b`,n`888 `Y8bd8P' 888 "88b 888P" d8P Y8b 88K 88K`,n`888 X88K 888 888 888 88888888 "Y8888b. "Y8888b.`,n`888 .d8""8b. 888 d88P 888 Y8b. X88 X88`,O`8888888888 888 888 88888P" 888 "Y8888 88888P' 88888P'`,O` 888`,O`8888888888P 888 888 d8888 8888888b. 8888888`,O` d88P 888 d88888 888 Y88b 888`,n` d88P 888 d88P888 888 888 888`,n` d88P .d88b. .d88888 d88P 888 888 d88P 888`,n` d88P d88""88b d88" 888 d88P 888 8888888P" 888`,r` d88P 888 888 888 888 d88P 888 888 888`,r` d88P Y88..88P Y88b 888 d8888888888 888 888`,r`d8888888888 "Y88P" "Y88888 d88P 888 888 8888888`];e.write(`
1
+ import{A as e,B as t,C as n,D as r,E as i,H as a,K as o,L as s,M as c,O as l,P as u,S as d,T as f,U as p,V as ee,Z as m,_ as h,a as te,b as ne,c as g,d as re,f as ie,g as ae,h as _,k as oe,l as v,m as y,nt as b,o as se,p as ce,s as x,t as le,tt as S,u as C,w as ue,z as de}from"./routing-walker-CcgJ8aiU.js";import{t as w}from"./peer-helpers-BQlC55XO.js";import{h as fe,l as pe,m as me,p as he}from"./documentation-helpers-DBaBYdUT.js";import{globalRegistry as T,z as E}from"zod";import*as ge from"ramda";import D,{isHttpError as _e}from"http-errors";import ve,{blue as ye,cyanBright as be,green as xe,hex as O,italic as Se,red as Ce,whiteBright as k}from"ansis";import{inspect as we}from"node:util";import{performance as Te}from"node:perf_hooks";import A from"express";import Ee from"node:http";import De from"node:https";import{setInterval as Oe}from"node:timers/promises";import{createRequest as ke,createResponse as Ae}from"node-mocks-http";function je(e){return e}const Me=(e,t)=>e&&t?e.and(t):e||t,Ne=(e,t)=>e?e.and(t):t;var Pe=class e{#e;constructor(e){this.#e=e}async execute(...n){try{return await this.#e(...n)}catch(r){let{response:i,logger:a,error:o}=n[0],s=new l(t(r),o||void 0);e.lastResort({response:i,logger:a,error:s})}}static lastResort({error:e,logger:t,response:n}){t.error(`Result handler failure`,e);let r=g(D(500,`An error occurred while serving the result: ${e.message}.`+(e.handled?`\nOriginal error: ${e.handled.message}.`:``),{expose:_e(e.cause)?e.cause.expose:!1}));n.status(500).type(`text/plain`).end(r)}},j=class extends Pe{#e;#t;constructor(e){super(e.handler),this.#e=e.positive,this.#t=e.negative}getPositiveResponse(e){return C(this.#e,{variant:`positive`,args:[e]})}getNegativeResponse(){return C(this.#t,{variant:`negative`,args:[]})}};const M=E.object({status:E.literal(`error`),error:E.object({message:E.string()})});T.add(M,{examples:[{status:`error`,error:{message:`Sample error message`}}]});const N=new j({positive:e=>{let t=E.object({status:E.literal(`success`),data:e}),n=s(e);return n.length&&T.add(t,{examples:n.map(e=>({status:`success`,data:e}))}),t},negative:M,handler:({error:e,input:t,output:n,request:r,response:i,logger:a})=>{if(e){let n=x(e);v(n,a,r,t),i.status(n.statusCode).set(n.headers).json({status:`error`,error:{message:g(n)}});return}i.status(ie.positive).json({status:`success`,data:n})}}),P=E.string();T.add(P,{examples:[`Sample error message`]});const F=new j({positive:e=>{let t=e instanceof E.ZodObject&&`items`in e.shape&&e.shape.items instanceof E.ZodArray?e.shape.items:E.array(E.any());if(s(t).length)return t;let n=s(e).filter(e=>o(e)&&`items`in e&&Array.isArray(e.items)).map(e=>e.items);if(n?.length){let e=t.meta();T.remove(t).add(t,{...e,examples:n})}return t},negative:{schema:P,mimeType:`text/plain`},handler:({response:e,output:t,error:n,logger:r,request:i,input:a})=>{if(n){let t=x(n);v(t,r,i,a),e.status(t.statusCode).type(`text/plain`).send(g(t));return}if(`items`in t&&Array.isArray(t.items)){e.status(ie.positive).json(t.items);return}throw Error(`Property 'items' is missing in the endpoint output`)}}),I=e=>{let t=[];return e.scope&&t.push(e.scope),e.noStore&&t.push(`no-store`),e.noCache&&t.push(`no-cache`),e.maxAge!==void 0&&t.push(`max-age=${e.maxAge}`),e.sMaxAge!==void 0&&t.push(`s-maxage=${e.sMaxAge}`),e.mustRevalidate&&t.push(`must-revalidate`),e.proxyRevalidate&&t.push(`proxy-revalidate`),e.mustUnderstand&&t.push(`must-understand`),e.immutable&&t.push(`immutable`),e.noTransform&&t.push(`no-transform`),e.staleWhileRevalidate!==void 0&&t.push(`stale-while-revalidate=${e.staleWhileRevalidate}`),e.staleIfError!==void 0&&t.push(`stale-if-error=${e.staleIfError}`),t.join(`, `)},Fe={"max-age":`maxAge`,"max-stale":`maxStale`,"min-fresh":`minFresh`,"stale-if-error":`staleIfError`},Ie={"no-cache":`noCache`,"no-store":`noStore`,"no-transform":`noTransform`,"only-if-cached":`onlyIfCached`},Le=e=>{if(!e)return;let t={};for(let n of e.toLowerCase().split(`,`)){let[e,r]=n.split(`=`),i=Fe[e.trim()];if(i){let e=parseInt(r?.trim()??``,10);isNaN(e)||(t[i]=e);continue}let a=Ie[e.trim()];a&&(t[a]=!0)}return t},L=e=>new _({handler:async({request:t,response:n})=>(e&&n.setHeader(`Cache-Control`,I(e)),{get ifNoneMatch(){let e=t.headers[`if-none-match`];if(!e)return;let n=e.trim();return n===`*`?n:n.split(`,`).map(e=>e.trim().replace(/^(?:W\/)?"/,``).replace(/"$/,``))},get ifModifiedSince(){let e=t.headers[`if-modified-since`];if(!e)return;let n=new Date(e);return isNaN(n.getTime())?void 0:n},get cacheControl(){return Le(t.headers[`cache-control`])},addCachePolicy:t=>{n.setHeader(`Cache-Control`,I({...e,...t}))},setETag:e=>{n.setHeader(`ETag`,e.startsWith(`"`)?e:`"${e}"`)},setLastModified:e=>{n.setHeader(`Last-Modified`,e.toUTCString())},setVary:(...e)=>{n.setHeader(`Vary`,e.join(`, `))},setExpires:e=>{n.setHeader(`Expires`,e.toUTCString())},clearSiteData:()=>{n.setHeader(`Clear-Site-Data`,`"cache"`)},notModified:()=>{n.status(304).end()}})}),R=e=>new _({handler:async({request:t,response:n})=>({getCookie:e=>t.signedCookies?.[e]??t.cookies?.[e],setCookie:(t,r,i)=>{n.cookie(t,r,{...e,...i})},clearCookie:(t,r)=>{n.clearCookie(t,{...e,...r})}})}),z=e=>{let t=w(`express-rate-limit`)({statusCode:429,...e,handler:(e,t,n,r)=>{n(D(r.statusCode,r.message))}}),{getKey:n,resetKey:r}=t,i={getKey:n,resetKey:r};return new y(t,{statusCode:e?.statusCode,provider:t=>({rateLimit:{...i,...t[e?.requestPropertyName??`rateLimit`]}})})};var B=class e{resultHandler;schema=void 0;statusCodes=new Set;middlewares=[];constructor(e){this.resultHandler=e}#e(t){let n=new e(this.resultHandler);return n.middlewares=this.middlewares.concat(t),n.schema=Me(this.schema,t.schema),n.statusCodes=this.statusCodes.union(t.statusCodes),n}addMiddleware(e){return this.#e(e instanceof _?e:new _(e))}useCookies(...e){return this.#e(R(...e))}useCache(...e){return this.#e(L(...e))}useRateLimit(...e){return this.#e(z(...e))}use=this.addExpressMiddleware;addExpressMiddleware(...e){return this.#e(new y(...e))}addContext(e){return this.#e(new _({handler:({ctx:t})=>e(t)}))}build({input:e=de,output:t,operationId:n,scope:r,tag:i,method:a,statusCode:o,...s}){let{middlewares:c,resultHandler:l}=this,u=new ae(typeof a==`string`?[a]:a),d=typeof n==`function`?n:e=>n&&`${n}${e===`head`?`__HEAD`:``}`,f=typeof r==`string`?[r]:r||[],p=typeof i==`string`?[i]:i||[];return new se({...s,middlewares:c,outputSchema:t,resultHandler:l,scopes:f,tags:p,methods:u,getOperationId:d,inputSchema:Ne(this.schema,e),statusCodes:this.statusCodes.union(new Set(typeof o==`number`?[o]:o||[]))})}buildVoid({handler:e,...t}){return this.build({...t,output:de,handler:async t=>(await e(t),{})})}};const Re=new B(N),ze=new B(F),V={debug:ye,info:xe,warn:O(`#FFA500`),error:Ce,ctx:be},H={debug:10,info:20,warn:30,error:40},Be=e=>o(e)&&Object.keys(H).some(t=>t in e),Ve=e=>e in H,He=(e,t)=>H[e]<H[t],U=ge.memoizeWith((e,t)=>`${e}${t}`,(e,t=0)=>Intl.NumberFormat(void 0,{useGrouping:!1,minimumFractionDigits:0,maximumFractionDigits:t,style:`unit`,unitDisplay:`long`,unit:e})),Ue=e=>e<1e-6?U(`nanosecond`,3).format(e/1e-6):e<.001?U(`nanosecond`).format(e/1e-6):e<1?U(`microsecond`).format(e/.001):e<1e3?U(`millisecond`).format(e):e<6e4?U(`second`,2).format(e/1e3):U(`minute`,2).format(e/6e4);var W=class e{config;constructor({color:e=ve.isSupported(),level:t=m.isProduction?`warn`:`debug`,depth:n=2,ctx:r={}}={}){this.config={color:e,level:t,depth:n,ctx:r}}format(e){let{depth:t,color:n,level:r}=this.config;return we(e,{depth:t,colors:n,breakLength:r===`debug`?80:1/0,compact:r!==`debug`||3})}print(e,t,n){let{level:r,ctx:{requestId:i,...a},color:o}=this.config;if(r===`silent`||He(e,r))return;let s=[new Date().toISOString()];i&&s.push(o?V.ctx(i):i),s.push(o?`${V[e](e)}:`:`${e}:`,t),n!==void 0&&s.push(this.format(n)),Object.keys(a).length>0&&s.push(this.format(a)),console.log(s.join(` `))}debug(e,t){this.print(`debug`,e,t)}info(e,t){this.print(`info`,e,t)}warn(e,t){this.print(`warn`,e,t)}error(e,t){this.print(`error`,e,t)}child(t){return new e({...this.config,ctx:t})}get ctx(){return this.config.ctx}profile(e){let t=Te.now();return()=>{let n=Te.now()-t,{message:r,severity:i=`debug`,formatter:a=Ue}=typeof e==`object`?e:{message:e};this.print(typeof i==`function`?i(n):i,r,a(n))}}},We=class{logger;config;#e=new WeakMap;constructor(e,t){this.logger=e,this.config=t}#t(e,t,n){if(!e.isSchemaChecked){for(let e of[`input`,`output`]){let r=[E.toJSONSchema(t[`${e}Schema`],{unrepresentable:`any`})];for(let t of r){t.type&&t.type!==`object`&&this.logger.warn(`Endpoint ${e} schema is not object-based`,n);for(let e of[`allOf`,`oneOf`,`anyOf`])t[e]&&r.push(...t[e])}}if(t.getProbableRequestType()===`json`){let e=h(t.inputSchema,`input`);e&&this.logger.warn(`The final input schema of the endpoint contains an unsupported JSON payload type.`,{...n,reason:e})}for(let e of ce)for(let{mimeTypes:r,schema:i}of t.getResponses(e)){if(!r?.includes(b.json))continue;let t=h(i,`output`);t&&this.logger.warn(`The final ${e} response schema of the endpoint contains an unsupported JSON payload type.`,{...n,reason:t})}e.isSchemaChecked=!0}}#n(e,t,n,r,i){if(e.paths.has(r))return;let{pathParams:s,getLocation:c,isQueryEnabled:l}=pe({method:n,path:r,security:t.security,inputSources:a(n,this.config.inputSources)});if(!(s.size===0&&!l)){e.flat??=me(E.toJSONSchema(t.inputSchema,{unrepresentable:`any`,io:`input`,override:({zodSchema:e,jsonSchema:t})=>{(e._zod.traits.has(`$ZodPreprocess`)||`coerce`in e._zod.def&&e._zod.def.coerce)&&(t[he]=!0)}}));for(let[t,n]of Object.entries(e.flat.properties)){if(!o(n))continue;let r=c(t);(r===`path`||r===`query`)&&(r===`path`&&!e.flat.required?.includes(t)&&this.logger.warn(`The path parameter "${t}" is declared optional in the input schema, but path parameters are always required since Express matches the route only when the segment is present.`,{...i,name:t}),!fe(n,r)&&this.logger.warn(`The ${r} parameter "${t}" has a schema that most likely would not accept the parsed data, ${r===`path`?`since path parameters always arrive as strings`:`depending on the "queryParser" config option`}. Convert the parsed value from "z.string()" using ".transform()" method, or use "z.coerce" at least.`,{...i,name:t,jsonSchema:n}))}for(let e of s)this.logger.warn(`The input schema of the endpoint is most likely missing the parameter of the path it's assigned to.`,{...i,param:e});e.paths.add(r)}}check=(e,t,n)=>{let r=this.#e.get(n);r||(r={isSchemaChecked:!1,paths:new Set},this.#e.set(n,r)),this.#t(r,n,{method:e,path:t}),this.#n(r,n,e,t,{method:e,path:t})}};const G=e=>e.sort((e,t)=>S(t)-+S(e)||e.localeCompare(t)).join(`, `).toUpperCase(),Ge=e=>({method:t},n,r)=>{let i=G(e);n.set({Allow:i}),r(D(405,`${t} is not allowed`,{headers:{Allow:i}}))},Ke=({app:e,getLogger:t,config:n,routing:r})=>{let i=m.isProduction?void 0:new We(t(),n),a=new Map;return le({routing:r,config:n,onEndpoint:(e,t,r)=>{i?.check(e,t,r),a.has(t)||a.set(t,new Map(n.cors?[[`options`,r]]:[])),a.get(t)?.set(e,r)},onStatic:e.use.bind(e)}),a},K=({app:e,config:t,getLogger:n,...r})=>{let i=Ke({app:e,getLogger:n,config:t,...r}),a=new Map;for(let[r,o]of i){let i=Array.from(o.keys());i.includes(`get`)&&i.push(`head`);for(let[a,s]of o){let o=[];t.cors&&o.push((e,t,n)=>{t.set(`Access-Control-Allow-Methods`,G(i)),n()}),o.push(async(e,r)=>{let i=n(e);return s.execute({request:e,response:r,logger:i,config:t})}),e[a]?.(r,...o)}t.hintAllowedMethods!==!1&&a.set(r,Ge(i))}for(let[t,n]of a)e.all(t,n)},qe=e=>`_httpMessage`in e&&typeof e._httpMessage==`object`&&e._httpMessage!==null&&`headersSent`in e._httpMessage&&typeof e._httpMessage.headersSent==`boolean`&&`setHeader`in e._httpMessage&&typeof e._httpMessage.setHeader==`function`,Je=e=>`server`in e&&typeof e.server==`object`&&e.server!==null&&`close`in e.server&&typeof e.server.close==`function`,Ye=e=>`encrypted`in e&&typeof e.encrypted==`boolean`&&e.encrypted,Xe=({},e)=>void(!e.headersSent&&e.setHeader(`connection`,`close`)),Ze=e=>{let{promise:t,resolve:n,reject:r}=Promise.withResolvers();return e.close(e=>e?r(e):n()),t},Qe=({timeout:e=1e3,logger:t}={})=>{let n,r=new Set,i=new Set,a=e=>void i.delete(e),o=e=>a(e.destroy()),s=e=>void(qe(e)?!e._httpMessage.headersSent&&e._httpMessage.setHeader(`connection`,`close`):o(e)),c=e=>void(n?e.destroy():i.add(e.once(`close`,()=>a(e)).once(`error`,()=>o(e)))),l=async()=>{for(let e of r)e.on(`request`,Xe);t?.info(`Graceful shutdown`,{sockets:i.size,timeout:e});for(let e of i)(Ye(e)||Je(e))&&s(e);for await(let t of Oe(10,Date.now()))if(i.size===0||Date.now()-t>=e)break;for(let e of i)o(e);return Promise.allSettled(r.values().map(Ze))},u={sockets:i,add:(...e)=>{for(let t of e)if(!r.has(t)){r.add(t);for(let e of[`connection`,`secureConnection`])t.on(e,c)}return u},shutdown:()=>n??=l(),get isShuttingDown(){return!!n}};return u},q=Symbol.for(`express-zod-api`),$e=({errorHandler:e,getLogger:n})=>async(r,i,a,o)=>r?e.execute({error:t(r),request:i,response:a,input:null,output:null,ctx:{},logger:n(i)}):o(),et=({errorHandler:e,getLogger:t})=>async(n,r)=>{let i=D(404,`Can not ${n.method} ${n.path}`),a=t(n);await e.execute({request:n,response:r,logger:a,error:i,input:null,output:null,ctx:{}})},tt=e=>(t,{},n)=>{if(Object.values(t?.files||[]).flat().find(({truncated:e})=>e))return n(e);n()},nt=({config:e})=>{let t=w(`cookie-parser`),{secret:n,...r}={...typeof e.cookies==`object`&&e.cookies};return t(n,Object.keys(r).length?r:void 0)},J=e=>typeof e==`function`?e:({},e,t)=>{e.set({"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Headers":`content-type`}),t()},rt=e=>({log:t=>{/not eligible/i.test(t)||e.debug(t)}}),it=({getLogger:e,config:t})=>{let n=w(`express-fileupload`),{limitError:r,beforeUpload:i,...a}={...typeof t.upload==`object`&&t.upload},o=[];return o.push(async(t,r,o)=>{let s=e(t);return await i?.({request:t,logger:s}),n({debug:!0,...a,abortOnLimit:!1,parseNested:!0,logger:rt(s)})(t,r,o)}),r&&o.push(tt(r)),o},at=(e,{},t)=>{Buffer.isBuffer(e.body)&&(e.body={raw:e.body}),t()},ot=({logger:e,config:{childLoggerProvider:t,accessLogger:n=({method:e,path:t},n)=>n.debug(`${e}: ${t}`)}})=>async(r,i,a)=>{let o=await t?.({request:r,parent:e})||e;n?.(r,o),r.res&&(r.res.locals[q]={logger:o}),a()},st=e=>t=>t?.res?.locals[q]?.logger||e;let Y=!1;const ct=e=>{Y||(Y=!0,process.on(`deprecation`,({message:t,namespace:n,name:r,stack:i})=>e.warn(`${r} (${n}): ${t}`,i.split(`
2
+ `).slice(1))))};let X,Z,Q;const lt=({servers:e,logger:t,options:{timeout:n,beforeExit:r,events:i=[`SIGINT`,`SIGTERM`]}})=>{X??=Qe({logger:t,timeout:n}),X.add(...e),r&&(Q??=new Set).add(r),Z??=async()=>{X?.isShuttingDown||(await X?.shutdown(),Q&&await Promise.allSettled(Q.values().map(async e=>e())),process.exit())};for(let e of i)process.listeners(e).includes(Z)||process.on(e,Z)},ut=e=>{if(e.columns<62)return;let t=Se(`for Angie`.padStart(52)),n=O(`#F5A9B8`),r=O(`#5BCEFA`),i=[r`8888888888${t}`,r`888`,r`888`,r`8888888 888 888 88888b. 888d888 .d88b. .d8888b .d8888b`,n`888 `Y8bd8P' 888 "88b 888P" d8P Y8b 88K 88K`,n`888 X88K 888 888 888 88888888 "Y8888b. "Y8888b.`,n`888 .d8""8b. 888 d88P 888 Y8b. X88 X88`,k`8888888888 888 888 88888P" 888 "Y8888 88888P' 88888P'`,k` 888`,k`8888888888P 888 888 d8888 8888888b. 8888888`,k` d88P 888 d88888 888 Y88b 888`,n` d88P 888 d88P888 888 888 888`,n` d88P .d88b. .d88888 d88P 888 888 d88P 888`,n` d88P d88""88b d88" 888 d88P 888 8888888P" 888`,r` d88P 888 888 888 888 d88P 888 888 888`,r` d88P Y88..88P Y88b 888 d8888888888 888 888`,r`d8888888888 "Y88P" "Y88888 d88P 888 888 8888888`];e.write(`
3
3
  `+i.join(`
4
4
  `)+`
5
5
 
6
- `)},ut=e=>{e.startupLogo!==!1&&lt(process.stdout);let t=e.errorHandler||N,n=ze(e.logger)?e.logger:new W(e.logger);n.debug(`Running`,{build:`v29.2.3`,env:p.env}),st(n);let r=at({logger:n,config:e}),i={getLogger:ot(n),errorHandler:t},a=$e(i),o=Qe(i);return{...i,logger:n,notFoundHandler:a,catcher:o,loggingMiddleware:r}},dt=(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,loggingMiddleware:a}=ut(e),o=e.app.use(a);return e.cors&&o.use(J(e.cors)),K({app:o,routing:t,getLogger:r,config:e}),{notFoundHandler:i,logger:n}},ft=(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,catcher:a,loggingMiddleware:o}=ut(e),s=A().disable(`x-powered-by`).set(`query parser`,e.queryParser??`simple`).use(o);if(e.beforeParsers?.({app:s,getLogger:r}),e.compression){let t=C(`compression`);s.use(t(typeof e.compression==`object`?e.compression:void 0))}return e.cookies&&s.use(tt({config:e})),e.cors&&s.use(J(e.cors)),s.use(e.jsonParser||A.json()).use(e.formParser||A.urlencoded()).use(e.rawParser||A.raw(),it),e.upload&&s.use(...rt({config:e,getLogger:r})),e.beforeRouting?.({app:s,getLogger:r}),K({app:s,routing:t,getLogger:r,config:e}),e.afterRouting?.({app:s,getLogger:r}),s.use(a,i),{app:s,logger:n}},pt=(e,t)=>{let{app:n,logger:r}=ft(e,t),i=[],a=(e,t)=>()=>e.listen(t,()=>r.info(`Listening`,t)),o=[];if(e.http){let t=Te.createServer(n);i.push(t),o.push(a(t,e.http.listen))}if(e.https){let t=Ee.createServer(e.https.options,n);i.push(t),o.push(a(t,e.https.listen))}return i.length||r.warn(`No servers configured.`),e.gracefulShutdown&&ct({logger:r,servers:i,options:e.gracefulShutdown===!0?{}:e.gracefulShutdown}),{app:n,logger:r,servers:o.map(e=>e())}},mt=e=>Oe({...e,headers:{"content-type":x.json,...e?.headers}}),ht=e=>ke(e),gt=e=>{let t={warn:[],error:[],info:[],debug:[]};return new Proxy(e||{},{get(e,n,r){return n===`_getLogs`?()=>t:Be(n)?(...e)=>t[n].push(e):Reflect.get(e,n,r)}})},_t=({requestProps:e,responseOptions:t,configProps:n,loggerProps:r})=>{let i=mt(e),a=ht({req:i,...t});a.req=t?.req||i,i.res=a;let o=gt(r);return{requestMock:i,responseMock:a,loggerMock:o,configMock:{cors:!1,logger:o,...n}}},vt=async({endpoint:e,...t})=>{let{requestMock:n,responseMock:r,loggerMock:i,configMock:a}=_t(t);return await e.execute({request:n,response:r,config:a,logger:i}),{requestMock:n,responseMock:r,loggerMock:i}},yt=async({middleware:t,ctx:n={},...r})=>{let{configMock:{inputSources:i,errorHandler:a=N},...o}=_t(r),s=e(o.requestMock,i),c={request:o.requestMock,response:o.responseMock,logger:o.loggerMock,input:s,ctx:n};try{let e=await t.execute(c);return{...o,output:e}}catch(e){return await a.execute({...c,error:S(e),output:null}),{...o,output:{}}}},$=(e,t)=>T.object({data:t,event:T.literal(e),id:T.string().optional(),retry:T.int().positive().optional()}),bt=(e,t,n)=>$(String(t),e[t]).transform(e=>[`event: ${e.event}`,`data: ${JSON.stringify(e.data)}`,``,``].join(`
7
- `)).parse({event:t,data:n}),xt=e=>e.headersSent||e.writeHead(200,{connection:`keep-alive`,"content-type":x.sse,"cache-control":`no-cache`}),St=e=>new _({handler:async({request:t,response:n})=>{let r=new AbortController,i=setTimeout(()=>xt(n),1e4);return t.once(`close`,()=>{clearTimeout(i),r.abort()}),{isClosed:()=>n.writableEnded||n.closed,signal:r.signal,emit:(t,r)=>{xt(n),n.write(bt(e,t,r),`utf-8`),n.flush?.()}}}}),Ct=e=>new j({positive:()=>{let[t,...r]=Object.entries(e).map(([e,t])=>$(e,t));if(!t)throw new n(Error(`At least one SSE event is required.`));return{mimeType:x.sse,schema:r.length?T.discriminatedUnion(`event`,[t,...r]):t}},negative:{mimeType:`text/plain`,schema:T.string()},handler:async({response:e,error:t,logger:n,request:r,input:i})=>{if(t){let a=b(t);v(a,n,r,i),e.headersSent||e.status(a.statusCode).type(`text/plain`).write(m(a),`utf-8`)}e.end()}});var wt=class extends B{constructor(e){super(Ct(e)),this.middlewares=[St(e)]}};const Tt=[`total`,`limit`,`offset`],Et=[`nextCursor`,`limit`];function Dt({style:e,itemSchema:t,itemsName:n=`items`,maxLimit:r=100,defaultLimit:i=20}){if(!Number.isInteger(r)||r<1)throw Error(`ez.paginated: maxLimit must be a positive integer`);if(!Number.isInteger(i)||i<1)throw Error(`ez.paginated: defaultLimit must be a positive integer`);if(i>r)throw Error(`ez.paginated: defaultLimit must not be greater than maxLimit`);if(e===`offset`&&Tt.includes(n))throw Error(`ez.paginated: itemsName must not match reserved keys for offset output (${Tt.join(`, `)})`);if(e===`cursor`&&Et.includes(n))throw Error(`ez.paginated: itemsName must not match reserved keys for cursor output (${Et.join(`, `)})`);let a=T.coerce.number().int().min(1).max(r).default(i).describe(`Page size (number of ${n} per page)`);if(e===`offset`){let e=T.coerce.number().int().min(0).default(0).describe(`Number of ${n} to skip`);return{input:T.object({limit:a,offset:e}),output:T.object({[n]:T.array(t).describe(`Page of ${n}`),total:T.number().int().min(0).describe(`Total number of ${n}`),limit:T.number().int().min(1).describe(`Page size used`),offset:T.number().int().min(0).describe(`Offset used`)})}}let o=T.string().optional().describe(`Cursor for the next page; omit for first page`);return{input:T.object({cursor:o,limit:a}),output:T.object({[n]:T.array(t).describe(`Page of ${n}`),nextCursor:T.string().nullable().describe(`Cursor for the next page, or null if no more pages`),limit:T.number().int().min(1).describe(`Page size used`)})}}const Ot={dateIn:re,dateOut:ie,form:u,upload:ue,raw:de,buffer:s,paginated:Dt};export{W as BuiltinLogger,t as DocumentationError,B as EndpointsFactory,wt as EventStreamFactory,le as InputValidationError,_ as Middleware,d as MissingPeerError,r as OutputValidationError,j as ResultHandler,c as RoutingError,ee as ServeStatic,Re as arrayEndpointsFactory,F as arrayResultHandler,dt as attachRouting,te as createApiResponse,L as createCacheMiddleware,Ae as createConfig,R as createCookieMiddleware,z as createRateLimitMiddleware,pt as createServer,Le as defaultEndpointsFactory,N as defaultResultHandler,b as ensureHttpError,Ot as ez,a as getMessageFromError,vt as testEndpoint,yt as testMiddleware};
6
+ `)},$=e=>{e.startupLogo!==!1&&ut(process.stdout);let t=e.errorHandler||N,n=Be(e.logger)?e.logger:new W(e.logger);n.debug(`Running`,{build:`v29.3.1`,env:m.env}),ct(n);let r=ot({logger:n,config:e}),i={getLogger:st(n),errorHandler:t},a=et(i),o=$e(i);return{...i,logger:n,notFoundHandler:a,catcher:o,loggingMiddleware:r}},dt=(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,loggingMiddleware:a}=$(e),o=e.app.use(a);return e.cors&&o.use(J(e.cors)),K({app:o,routing:t,getLogger:r,config:e}),{notFoundHandler:i,logger:n}},ft=(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,catcher:a,loggingMiddleware:o}=$(e),s=A().disable(`x-powered-by`).set(`query parser`,e.queryParser??`simple`).use(o);if(e.beforeParsers?.({app:s,getLogger:r}),e.compression){let t=w(`compression`);s.use(t(typeof e.compression==`object`?e.compression:void 0))}return e.cookies&&s.use(nt({config:e})),e.cors&&s.use(J(e.cors)),s.use(e.jsonParser||A.json()).use(e.formParser||A.urlencoded()).use(e.rawParser||A.raw(),at),e.upload&&s.use(...it({config:e,getLogger:r})),e.beforeRouting?.({app:s,getLogger:r}),K({app:s,routing:t,getLogger:r,config:e}),e.afterRouting?.({app:s,getLogger:r}),s.use(a,i),{app:s,logger:n}},pt=(e,t)=>{let{app:n,logger:r}=ft(e,t),i=[],a=(e,t)=>()=>e.listen(t,()=>r.info(`Listening`,t)),o=[];if(e.http){let t=Ee.createServer(n);i.push(t),o.push(a(t,e.http.listen))}if(e.https){let t=De.createServer(e.https.options,n);i.push(t),o.push(a(t,e.https.listen))}return i.length||r.warn(`No servers configured.`),e.gracefulShutdown&&lt({logger:r,servers:i,options:e.gracefulShutdown===!0?{}:e.gracefulShutdown}),{app:n,logger:r,servers:o.map(e=>e())}},mt=e=>ke({...e,headers:{"content-type":b.json,...e?.headers}}),ht=e=>Ae(e),gt=e=>{let t={warn:[],error:[],info:[],debug:[]};return new Proxy(e||{},{get(e,n,r){return n===`_getLogs`?()=>t:Ve(n)?(...e)=>t[n].push(e):Reflect.get(e,n,r)}})},_t=({requestProps:e,responseOptions:t,configProps:n,loggerProps:r})=>{let i=mt(e),a=ht({req:i,...t});a.req=t?.req||i,i.res=a;let o=gt(r);return{requestMock:i,responseMock:a,loggerMock:o,configMock:{cors:!1,logger:o,...n}}},vt=async({endpoint:e,...t})=>{let{requestMock:n,responseMock:r,loggerMock:i,configMock:a}=_t(t);return await e.execute({request:n,response:r,config:a,logger:i}),{requestMock:n,responseMock:r,loggerMock:i}},yt=async({middleware:e,ctx:n={},...r})=>{let{configMock:{inputSources:i,errorHandler:a=N},...o}=_t(r),s=ee(o.requestMock,i),c={request:o.requestMock,response:o.responseMock,logger:o.loggerMock,input:s,ctx:n};try{let t=await e.execute(c);return{...o,output:t}}catch(e){return await a.execute({...c,error:t(e),output:null}),{...o,output:{}}}},bt=(e,t)=>E.object({data:t,event:E.literal(e),id:E.string().optional(),retry:E.int().positive().optional()}),xt=(e,t,n)=>bt(String(t),e[t]).transform(e=>[`event: ${e.event}`,`data: ${JSON.stringify(e.data)}`,``,``].join(`
7
+ `)).parse({event:t,data:n}),St=e=>e.headersSent||e.writeHead(200,{connection:`keep-alive`,"content-type":b.sse,"cache-control":`no-cache`}),Ct=e=>new _({handler:async({request:t,response:n})=>{let r=new AbortController,i=setTimeout(()=>St(n),1e4);return t.once(`close`,()=>{clearTimeout(i),r.abort()}),{isClosed:()=>n.writableEnded||n.closed,signal:r.signal,emit:(t,r)=>{St(n),n.write(xt(e,t,r),`utf-8`),n.flush?.()}}}}),wt=e=>new j({positive:()=>{let[t,...n]=Object.entries(e).map(([e,t])=>bt(e,t));if(!t)throw new l(Error(`At least one SSE event is required.`));return{mimeType:b.sse,schema:n.length?E.discriminatedUnion(`event`,[t,...n]):t}},negative:{mimeType:`text/plain`,schema:E.string()},handler:async({response:e,error:t,logger:n,request:r,input:i})=>{if(t){let a=x(t);v(a,n,r,i),e.headersSent||e.status(a.statusCode).type(`text/plain`).write(g(a),`utf-8`)}e.end()}});var Tt=class extends B{constructor(e){super(wt(e)),this.middlewares=[Ct(e)]}};const Et=[`total`,`limit`,`offset`],Dt=[`nextCursor`,`limit`];function Ot({style:e,itemSchema:t,itemsName:n=`items`,maxLimit:r=100,defaultLimit:i=20}){if(!Number.isInteger(r)||r<1)throw Error(`ez.paginated: maxLimit must be a positive integer`);if(!Number.isInteger(i)||i<1)throw Error(`ez.paginated: defaultLimit must be a positive integer`);if(i>r)throw Error(`ez.paginated: defaultLimit must not be greater than maxLimit`);if(e===`offset`&&Et.includes(n))throw Error(`ez.paginated: itemsName must not match reserved keys for offset output (${Et.join(`, `)})`);if(e===`cursor`&&Dt.includes(n))throw Error(`ez.paginated: itemsName must not match reserved keys for cursor output (${Dt.join(`, `)})`);let a=E.coerce.number().int().min(1).max(r).default(i).describe(`Page size (number of ${n} per page)`);if(e===`offset`){let e=E.coerce.number().int().min(0).default(0).describe(`Number of ${n} to skip`);return{input:E.object({limit:a,offset:e}),output:E.object({[n]:E.array(t).describe(`Page of ${n}`),total:E.number().int().min(0).describe(`Total number of ${n}`),limit:E.number().int().min(1).describe(`Page size used`),offset:E.number().int().min(0).describe(`Offset used`)})}}let o=E.string().optional().describe(`Cursor for the next page; omit for first page`);return{input:E.object({cursor:o,limit:a}),output:E.object({[n]:E.array(t).describe(`Page of ${n}`),nextCursor:E.string().nullable().describe(`Cursor for the next page, or null if no more pages`),limit:E.number().int().min(1).describe(`Page size used`)})}}const kt={dateIn:c,dateOut:e,form:n,upload:d,raw:ne,buffer:u,paginated:Ot};export{W as BuiltinLogger,ue as DocumentationError,B as EndpointsFactory,Tt as EventStreamFactory,f as InputValidationError,_ as Middleware,i as MissingPeerError,r as OutputValidationError,j as ResultHandler,oe as RoutingError,te as ServeStatic,ze as arrayEndpointsFactory,F as arrayResultHandler,dt as attachRouting,re as createApiResponse,L as createCacheMiddleware,je as createConfig,R as createCookieMiddleware,z as createRateLimitMiddleware,pt as createServer,Re as defaultEndpointsFactory,N as defaultResultHandler,x as ensureHttpError,kt as ez,p as getMessageFromError,vt as testEndpoint,yt as testMiddleware};
@@ -1,4 +1,4 @@
1
- import { d as FlatObject, g as CommonConfig, l as EmptyObject, t as Routing } from "./routing-8iV6qx5U.js";
1
+ import { d as FlatObject, g as CommonConfig, l as EmptyObject, t as Routing } from "./routing-uoFmENK3.js";
2
2
  import { z } from "zod";
3
3
  import ts, { default as ts$1 } from "typescript";
4
4
  interface NextHandlerInc<U> {
@@ -1,13 +1,13 @@
1
- import{$ as e,A as t,F as n,K as r,M as i,P as a,W as o,Z as s,_ as c,n as l,p as u,q as d,r as f,t as p,tt as m,v as h}from"./routing-walker-D9nfJshN.js";import{t as g}from"./peer-helpers-WZaMOjAf.js";import{globalRegistry as _,z as v}from"zod";import*as y from"ramda";import b from"typescript";const x={Path:`Path`,Implementation:`Implementation`,DefaultContext:`DefaultContext`,key:`key`,path:`path`,params:`params`,ctx:`ctx`,method:`method`,request:`request`,event:`event`,data:`data`,handler:`handler`,msg:`msg`,parseRequest:`parseRequest`,substitute:`substitute`,provide:`provide`,on:`on`,implementation:`implementation`,hasBody:`hasBody`,undefined:`undefined`,response:`response`,rest:`rest`,searchParams:`searchParams`,defaultImplementation:`defaultImplementation`,hasFiles:`hasFiles`,value:`value`,File:`File`,FormData:`FormData`,headers:`headers`,body:`body`,client:`client`,contentType:`contentType`,isBlob:`isBlob`,source:`source`,Method:`Method`,SomeOf:`SomeOf`,Request:`Request`,Pagination:`Pagination`,override:`override`},S={input:`Input`,positive:`PositiveResponse`,negative:`NegativeResponse`,encoded:`EncodedResponse`,response:`Response`},C=e=>Array.from(e,e=>`"${e}"`),w=e=>e;var ee=class{serverUrl;paths=new Set;tags=new Map;registry=new Map;constructor(e){this.serverUrl=e}makeMethodType=()=>{let t=C(e).join(` | `);return`export type ${x.Method} = ${t};`};makeOmit=(e,t,n=``)=>`Omit<${e}, ${n&&`\n/** ${n} */\n`}${C(t).join(` | `)}>`;makeSomeOfType=()=>`type ${x.SomeOf}<T> = T[keyof T];`;makeRequestType=()=>`export type ${x.Request} = keyof ${S.input};`;someOf=e=>`${x.SomeOf}<${e}>`;makePathType=()=>{let e=C(this.paths).join(` | `);return`export type ${x.Path} = ${e};`};makePublicInterfaces=()=>Object.keys(S).map(e=>{let t=Array.from(this.registry).map(([t,{store:n,isDeprecated:r}])=>` ${r?`/** @deprecated */
1
+ import{F as e,G as t,I as n,J as r,N as i,Q as a,et as o,j as s,n as c,nt as l,p as u,q as d,r as f,t as p,v as m,y as h}from"./routing-walker-CcgJ8aiU.js";import{t as g}from"./peer-helpers-BQlC55XO.js";import{globalRegistry as _,z as v}from"zod";import*as y from"ramda";import b from"typescript";const x={Path:`Path`,Implementation:`Implementation`,DefaultContext:`DefaultContext`,key:`key`,path:`path`,params:`params`,ctx:`ctx`,method:`method`,request:`request`,event:`event`,data:`data`,handler:`handler`,msg:`msg`,parseRequest:`parseRequest`,substitute:`substitute`,provide:`provide`,on:`on`,implementation:`implementation`,hasBody:`hasBody`,undefined:`undefined`,response:`response`,rest:`rest`,searchParams:`searchParams`,defaultImplementation:`defaultImplementation`,hasFiles:`hasFiles`,value:`value`,File:`File`,FormData:`FormData`,headers:`headers`,body:`body`,client:`client`,contentType:`contentType`,isBlob:`isBlob`,source:`source`,Method:`Method`,SomeOf:`SomeOf`,Request:`Request`,Pagination:`Pagination`,override:`override`},S={input:`Input`,positive:`PositiveResponse`,negative:`NegativeResponse`,encoded:`EncodedResponse`,response:`Response`},C=e=>Array.from(e,e=>`"${e}"`),w=e=>e;var ee=class{serverUrl;paths=new Set;tags=new Map;registry=new Map;constructor(e){this.serverUrl=e}makeMethodType=()=>{let e=C(o).join(` | `);return`export type ${x.Method} = ${e};`};makeOmit=(e,t,n=``)=>`Omit<${e}, ${n&&`\n/** ${n} */\n`}${C(t).join(` | `)}>`;makeSomeOfType=()=>`type ${x.SomeOf}<T> = T[keyof T];`;makeRequestType=()=>`export type ${x.Request} = keyof ${S.input};`;someOf=e=>`${x.SomeOf}<${e}>`;makePathType=()=>{let e=C(this.paths).join(` | `);return`export type ${x.Path} = ${e};`};makePublicInterfaces=()=>Object.keys(S).map(e=>{let t=Array.from(this.registry).map(([t,{store:n,isDeprecated:r}])=>` ${r?`/** @deprecated */
2
2
  `:``}"${t}": ${n[e]};`).join(`
3
3
  `);return`export interface ${S[e]} {\n${t}\n}`});makeEndpointTags=()=>`export const endpointTags = {\n${Array.from(this.tags).map(([e,t])=>` "${e}": [${C(t).join(`, `)}]`).join(`,
4
4
  `)}\n}`;makeImplementationType=()=>{let e=[`${x.method}: ${x.Method}`,`${x.path}: string`,`${x.params}: Record<string, any>`,`${x.ctx}?: T`].join(`,`);return`export type ${x.Implementation}<T extends Record<string, unknown>> = (${e}) => Promise<any>;`};makeDefaultContextType=()=>`export type ${x.DefaultContext} = { ${x.override}?: (init: RequestInit) => RequestInit };`;makeParseRequestFn=()=>{let e=`${x.request}: string`,t=`[${x.Method}, ${x.Path}]`,n=`${x.request}.${w(`split`)}(/ (.+)/, 2) as ${t}`;return`const ${x.parseRequest} = (${e}) => ${n};`};makeSubstituteFn=()=>{let e=`${x.path}: string, ${x.params}: Record<string, any>`,t=`\`:\${${x.key}}\``,n=`: [typeof ${x.path}, typeof ${x.params}]`;return[`const ${x.substitute} = (${e})${n} => {`,` if (${x.params} instanceof Blob) return [${x.path}, ${x.params}] as const;`,` const ${x.rest} = { ...${x.params} };`,` for (const ${x.key} in ${x.params}) {`,` ${x.path} = ${x.path}.${w(`replace`)}(${t}, () => {`,` delete ${x.rest}[${x.key}];`,` return ${x.params}[${x.key}];`,` });`,` }`,` return [${x.path}, ${x.rest}] as const;`,`}`].join(`
5
5
  `)};makePaginationType=()=>{let e=w(`nextCursor`),t=w(`total`),n=w(`limit`),r=w(`offset`),i=`{ ${e}: string | null }`,a=`{ ${t}: number; ${n}: number; ${r}: number }`;return`type ${x.Pagination} = ${i} | ${a}`};makeClientClass=e=>{let t=w(`nextCursor`),n=w(`offset`),r=w(`limit`),i=w(`total`),a=`${x.method}, ...${x.substitute}(${x.path}, ${x.params}), ${x.ctx}`;return[`export class ${e}<T extends Record<string, unknown> = ${x.DefaultContext}> {`,` public constructor(`,` protected readonly ${x.implementation}: ${x.Implementation}<T> = ${x.defaultImplementation},`,` ) {}`,` public ${x.provide}<K extends ${x.Request}>(`,` ${x.request}: K,`,` ${x.params}: ${S.input}[K],`,` ${x.ctx}?: T,`,` ): Promise<${S.response}[K]> {`,` const [${x.method}, ${x.path}] = ${x.parseRequest}(${x.request});`,` return this.${x.implementation}(${a});`,` }`,` public static hasMore(${x.response}: ${x.Pagination}): boolean {`,` if ("${t}" in ${x.response}) return ${x.response}.${t} !== null;`,` return ${x.response}.${n} + ${x.response}.${r} < ${x.response}.${i};`,` }`,`}`].join(`
6
- `)};makeDefaultImplementation=e=>{let t=`${x.method}, ${x.path}, ${x.params}, ${x.ctx}`,n=C([`get`,`head`,`delete`]).join(`, `),r=`!${x.hasBody} || ${x.hasFiles} ? ${x.undefined} : { "Content-Type": ${x.isBlob} ? "${m.raw}" : "${m.json}" };`,i=`${x.response}.${w(`headers`)}.${w(`get`)}("content-type")`,a=`\`?\${new ${URLSearchParams.name}(${x.params})}\``;return[`const ${x.defaultImplementation}: ${x.Implementation}<${x.DefaultContext}> = async (${t}) => {`,` const ${x.isBlob} = ${x.params} instanceof Blob;`,` const ${x.hasFiles} = !${x.isBlob} && Object.${w(`values`)}(${x.params}).${w(`some`)}((one) => one instanceof Blob || one instanceof ${x.File});`,` const ${x.hasBody} = ![${n}].includes(${x.method});`,` const ${x.searchParams} = ${x.isBlob} || ${x.hasBody} ? "" : ${a};`,` const ${x.headers} = ${r}`,` let ${x.body}: RequestInit["${x.body}"] = ${x.undefined};`,` if (${x.hasBody}) {`,` if (${x.isBlob}) {`,` ${x.body} = ${x.params};`,` } else if (${x.hasFiles}) {`,` ${x.body} = new ${FormData.name}();`,` for (const [${x.key}, ${x.value}] of Object.${w(`entries`)}(${x.params}))`,` if (${x.value} !== undefined) ${x.body}.${w(`append`)}(${x.key}, ${x.value});`,` } else {`,` ${x.body} = JSON.${w(`stringify`)}(${x.params});`,` }`,` }`,` let init: RequestInit = {`,` ${w(`method`)}: ${x.method}.${w(`toUpperCase`)}(),`,` ${w(`credentials`)}: ${e?`"include"`:x.undefined},`,` ${x.headers},`,` ${x.body},`,` };`,` if (${x.ctx}?.${x.override}) init = ${x.ctx}.${x.override}(init);`,` const ${x.response} = await ${fetch.name}(`,` new ${URL.name}(\`\${${x.path}}\${${x.searchParams}}\`, "${this.serverUrl}"),`,` init,`,` );`,` const ${x.contentType} = ${i};`,` if (!${x.contentType}) return;`,` if (${x.contentType}.${w(`startsWith`)}("${m.json}")) return ${x.response}.${w(`json`)}();`,` if (${x.contentType}.${w(`startsWith`)}("text/")) return ${x.response}.${w(`text`)}();`,` return ${x.response}.${w(`blob`)}();`,`};`].join(`
6
+ `)};makeDefaultImplementation=e=>{let t=`${x.method}, ${x.path}, ${x.params}, ${x.ctx}`,n=C([`get`,`head`,`delete`]).join(`, `),r=`!${x.hasBody} || ${x.hasFiles} ? ${x.undefined} : { "Content-Type": ${x.isBlob} ? "${l.raw}" : "${l.json}" };`,i=`${x.response}.${w(`headers`)}.${w(`get`)}("content-type")`,a=`\`?\${new ${URLSearchParams.name}(${x.params})}\``;return[`const ${x.defaultImplementation}: ${x.Implementation}<${x.DefaultContext}> = async (${t}) => {`,` const ${x.isBlob} = ${x.params} instanceof Blob;`,` const ${x.hasFiles} = !${x.isBlob} && Object.${w(`values`)}(${x.params}).${w(`some`)}((one) => one instanceof Blob || one instanceof ${x.File});`,` const ${x.hasBody} = ![${n}].includes(${x.method});`,` const ${x.searchParams} = ${x.isBlob} || ${x.hasBody} ? "" : ${a};`,` const ${x.headers} = ${r}`,` let ${x.body}: RequestInit["${x.body}"] = ${x.undefined};`,` if (${x.hasBody}) {`,` if (${x.isBlob}) {`,` ${x.body} = ${x.params};`,` } else if (${x.hasFiles}) {`,` ${x.body} = new ${FormData.name}();`,` for (const [${x.key}, ${x.value}] of Object.${w(`entries`)}(${x.params}))`,` if (${x.value} !== undefined) ${x.body}.${w(`append`)}(${x.key}, ${x.value});`,` } else {`,` ${x.body} = JSON.${w(`stringify`)}(${x.params});`,` }`,` }`,` let init: RequestInit = {`,` ${w(`method`)}: ${x.method}.${w(`toUpperCase`)}(),`,` ${w(`credentials`)}: ${e?`"include"`:x.undefined},`,` ${x.headers},`,` ${x.body},`,` };`,` if (${x.ctx}?.${x.override}) init = ${x.ctx}.${x.override}(init);`,` const ${x.response} = await ${fetch.name}(`,` new ${URL.name}(\`\${${x.path}}\${${x.searchParams}}\`, "${this.serverUrl}"),`,` init,`,` );`,` const ${x.contentType} = ${i};`,` if (!${x.contentType}) return;`,` if (${x.contentType}.${w(`startsWith`)}("${l.json}")) return ${x.response}.${w(`json`)}();`,` if (${x.contentType}.${w(`startsWith`)}("text/")) return ${x.response}.${w(`text`)}();`,` return ${x.response}.${w(`blob`)}();`,`};`].join(`
7
7
  `)};makeSubscriptionClass=(e,t)=>{let n=`${x.substitute}(${x.parseRequest}(${x.request})[1], ${x.params})`,r=`Extract<R, { ${w(`event`)}: E }>["${w(`data`)}"]`,i=`(${x.msg} as ${MessageEvent.name}).${w(`data`)}`;return[`export class ${e}<`,` K extends Extract<${x.Request}, \`get \${string}\`>,`,` R extends Extract<${S.positive}[K], { ${w(`event`)}: string }>,`,`> {`,` public ${x.source}: EventSource;`,` public constructor(${x.request}: K, ${x.params}: ${S.input}[K]) {`,` const [${x.path}, ${x.rest}] = ${n};`,` const ${x.searchParams} = \`?\${new ${URLSearchParams.name}(${x.rest})}\`;`,` this.${x.source} = new EventSource(`,` new URL(\`\${${x.path}}\${${x.searchParams}}\`, "${this.serverUrl}"),`,` { ${w(`withCredentials`)}: ${t?`true`:x.undefined} }`,` );`,` }`,` public ${x.on}<E extends R["${w(`event`)}"]>(`,` ${w(`event`)}: E,`,` ${x.handler}: (${x.data}: ${r}) => void | Promise<void>,`,` ) {`,` this.${x.source}.${w(`addEventListener`)}(${x.event}, (${x.msg}) =>`,` ${x.handler}(JSON.${w(`parse`)}(${i})),`,` );`,` return this;`,` }`,`}`].join(`
8
8
  `)};makeUsageStatements=(e,t)=>[`const ${x.client} = new ${e}();`,`${x.client}.${x.provide}("get /v1/user/retrieve", { id: "10" });`,`new ${t}("get /v1/events/stream", {}).${x.on}("time", (time) => {});`].join(`
9
- `)};const T=b.factory,E=/^[A-Za-z_$][A-Za-z0-9_$]*$/,D=[b.SyntaxKind.AnyKeyword,b.SyntaxKind.BigIntKeyword,b.SyntaxKind.BooleanKeyword,b.SyntaxKind.NeverKeyword,b.SyntaxKind.NumberKeyword,b.SyntaxKind.ObjectKeyword,b.SyntaxKind.StringKeyword,b.SyntaxKind.SymbolKeyword,b.SyntaxKind.UndefinedKeyword,b.SyntaxKind.UnknownKeyword,b.SyntaxKind.VoidKeyword],O=e=>typeof e==`number`?T.createNumericLiteral(e):typeof e==`bigint`?T.createBigIntLiteral(e.toString()):typeof e==`boolean`?e?T.createTrue():T.createFalse():e===null?T.createNull():T.createStringLiteral(e),k=e=>T.createIdentifier(e),A=e=>typeof e==`string`&&E.test(e)?k(e):O(e),j=(e,t)=>typeof e==`number`?T.createKeywordTypeNode(e):typeof e==`string`||b.isIdentifier(e)?T.createTypeReferenceNode(e,t&&y.map(j,t)):e,M=e=>{let t=new Map;for(let n of e)t.set(N(n)?n.kind:n,n);return T.createUnionTypeNode(Array.from(t.values()))},N=e=>D.includes(e.kind),P=(e,t)=>b.addSyntheticLeadingComment(e,b.SyntaxKind.MultiLineCommentTrivia,`* ${t} `,!0),F=(e,t)=>{let n=b.createSourceFile(`print.ts`,``,b.ScriptTarget.Latest,!1,b.ScriptKind.TS);return b.createPrinter(t).printNode(b.EmitHint.Unspecified,e,n)},te=(e,t,{isOptional:n,hasUndefined:r=n,isDeprecated:i,comment:a}={})=>{let o=j(t),s=T.createPropertySignature(void 0,A(e),n?T.createToken(b.SyntaxKind.QuestionToken):void 0,r?M([o,j(b.SyntaxKind.UndefinedKeyword)]):o),c=y.reject(y.isNil,[i?`@deprecated`:void 0,a]);return c.length?P(s,c.join(` `)):s},I=e=>T.createLiteralTypeNode(O(e)),L=(e,{rules:t,onMissing:r,ctx:i={}})=>{let a=n(e),o=a&&a in t?t[a]:t[e._zod.def.type],s=e=>L(e,{ctx:i,rules:t,onMissing:r});return o?o(e,{...i,next:s}):r(e,i)},R={name:y.path([`name`,`text`]),type:y.path([`type`]),optional:y.path([`questionToken`])},z=({_zod:{def:e}})=>{let t=e.values.map(e=>e===void 0?j(b.SyntaxKind.UndefinedKeyword):I(e));return t.length===1?t[0]:M(t)},B=({_zod:{def:e}},{next:t})=>{let{parts:n}=e,i=0,a=()=>{let e=``;for(;i<n.length;){let t=n[i];if(r(t))break;i++,e+=t??``}return e},o=T.createTemplateHead(a()),s=[];for(;i<n.length;){let e=t(n[i++]),r=a(),o=i<n.length?T.createTemplateMiddle:T.createTemplateTail;s.push(T.createTemplateLiteralTypeSpan(e,o(r)))}return s.length?T.createTemplateLiteralType(o,s):I(o.text)},V=(e,{isResponse:t,next:n,makeAlias:r})=>{let i=()=>{let r=Object.entries(e._zod.def.shape).map(([e,r])=>{let{description:i,deprecated:a}=_.get(r)||{},o=(t?r._zod.optout:r._zod.optin)===`optional`,s=o&&!(r instanceof v.core.$ZodExactOptional);return te(e,n(r),{comment:i,isDeprecated:a,isOptional:o,hasUndefined:s})});return T.createTypeLiteralNode(r)};return c(e,{io:t?`output`:`input`})?r(e,i):i()},H=({_zod:{def:e}},{next:t})=>T.createArrayTypeNode(t(e.element)),U=({_zod:{def:e}})=>M(y.map(I,Object.values(e.entries))),W=({_zod:{def:e}},{next:t})=>M(e.options.map(t)),G=({_zod:{def:e}},{next:t})=>M([t(e.innerType),I(null)]),K=({_zod:{def:e}},{next:t})=>T.createTupleTypeNode(e.items.map(t).concat(e.rest===null?[]:T.createRestTypeNode(t(e.rest)))),q=({_zod:{def:e}},{next:t})=>{let[n,r]=[e.keyType,e.valueType].map(t),i=j(`Record`,[n,r]);return e.mode===`loose`?T.createIntersectionTypeNode([i,j(`Record`,[`PropertyKey`,r])]):i},J=y.tryCatch(e=>{if(!e.every(b.isTypeLiteralNode))throw Error(`Not objects`);let t=y.chain(y.prop(`members`),e),n=y.uniqWith((...e)=>{if(!y.eqBy(R.name,...e))return!1;if(y.both(y.eqBy(R.type),y.eqBy(R.optional))(...e))return!0;throw Error(`Has conflicting prop`)},t);return T.createTypeLiteralNode(n)},(e,t)=>T.createIntersectionTypeNode(t)),Y=({_zod:{def:e}},{next:t})=>J([e.left,e.right].map(t)),X=e=>()=>j(e),Z=({_zod:{def:e}},{next:t})=>t(e.innerType),Q=e=>j(e?b.SyntaxKind.UnknownKeyword:b.SyntaxKind.AnyKeyword),ne=({_zod:{def:e}},{next:t,isResponse:n})=>{let i=e[n?`out`:`in`],a=e[n?`in`:`out`];if(!r(i,`transform`))return t(i);let s=t(a),c={[b.SyntaxKind.AnyKeyword]:``,[b.SyntaxKind.BigIntKeyword]:BigInt(0),[b.SyntaxKind.BooleanKeyword]:!1,[b.SyntaxKind.NumberKeyword]:0,[b.SyntaxKind.ObjectKeyword]:{},[b.SyntaxKind.StringKeyword]:``,[b.SyntaxKind.UndefinedKeyword]:void 0}[s.kind],l=o(i,c),u={number:b.SyntaxKind.NumberKeyword,bigint:b.SyntaxKind.BigIntKeyword,boolean:b.SyntaxKind.BooleanKeyword,string:b.SyntaxKind.StringKeyword,undefined:b.SyntaxKind.UndefinedKeyword,object:b.SyntaxKind.ObjectKeyword};return j(l&&u[l]||Q(n))},re=()=>I(null),ie=({_zod:{def:e}},{makeAlias:t,next:n})=>t(e.getter,()=>n(e.getter())),ae=()=>j(`Blob`),oe=(e,{next:t})=>t(e._zod.def.shape.raw),se={string:X(b.SyntaxKind.StringKeyword),number:X(b.SyntaxKind.NumberKeyword),bigint:X(b.SyntaxKind.BigIntKeyword),boolean:X(b.SyntaxKind.BooleanKeyword),any:X(b.SyntaxKind.AnyKeyword),undefined:X(b.SyntaxKind.UndefinedKeyword),[i]:X(b.SyntaxKind.StringKeyword),[t]:X(b.SyntaxKind.StringKeyword),never:X(b.SyntaxKind.NeverKeyword),void:X(b.SyntaxKind.UndefinedKeyword),unknown:X(b.SyntaxKind.UnknownKeyword),null:re,array:H,tuple:K,record:q,object:V,literal:z,template_literal:B,intersection:Y,union:W,default:Z,enum:U,optional:Z,nonoptional:Z,nullable:G,catch:Z,pipe:ne,lazy:ie,readonly:Z,[a]:ae,[h]:oe},$=(e,{brandHandling:t,ctx:n})=>L(e,{rules:{...t,...se},onMissing:({},{isResponse:e})=>Q(e),ctx:n});var ce=class extends ee{#e=[];#t=new Map;#n;#r(e,t){let n=this.#t.get(e);if(!n){n=`Type${this.#t.size+1}`,this.#t.set(e,n);let r=t();this.#e.push(e=>`type ${n} = ${F(r,e)};`)}return j(n)}constructor({routing:e,config:t,brandHandling:n,variant:r=`client`,clientClassName:i=`Client`,subscriptionClassName:a=`Subscription`,serverUrl:o=`https://example.com`,noBodySchema:c=v.undefined(),hasHeadMethod:m=!0,hasCredentials:h=!1}){super(o);let g={makeAlias:this.#r.bind(this)},_={brandHandling:n,ctx:{...g,isResponse:!1}},y={brandHandling:n,ctx:{...g,isResponse:!0}},b=!1,x=(e,t,n)=>{let r=d.bind(null,e,t),{isDeprecated:i,inputSchema:a,tags:o}=n,l=`${e} ${t}`,p=r(`input`),m=f(n.security,`cookie`);m.size&&(b=!0);let h=$(a,_);this.#e.push(e=>{let t=F(h,e);return[`/** ${l} */`,`type ${p} = ${m.size?this.makeOmit(t,m,`security cookies`):t};`].join(`
10
- `)});let g=u.reduce((t,i)=>{let a=n.getResponses(i),o=[];for(let[t,{schema:n,mimeTypes:u,statusCodes:d}]of a.entries()){let a=s(e,u),f=r(i,`variant`,`${t+1}`),p=$(a?n:c,y);this.#e.push(e=>`/** ${l} */\ntype ${f} = ${F(p,e)};`);for(let e of d)o.push(` ${e}: ${f};`)}let u=r(i,`response`,`variants`);return this.#e.push(`/** ${l} */\ninterface ${u} {\n${o.join(`
11
- `)}\n}`),Object.assign(t,{[i]:u})},{});this.paths.add(t);let v={input:p,positive:this.someOf(g.positive),negative:this.someOf(g.negative),response:`${S.positive}["${l}"] | ${S.negative}["${l}"]`,encoded:`${g.positive} & ${g.negative}`};this.registry.set(l,{isDeprecated:i,store:v}),this.tags.set(l,o)};p({routing:e,config:t,onEndpoint:m?l(x):x}),this.#e.push(this.makeSomeOfType(),this.makePathType(),this.makeMethodType(),...this.makePublicInterfaces(),this.makeRequestType()),r!==`types`&&(this.#e.push(this.makeEndpointTags(),this.makeParseRequestFn(),this.makeSubstituteFn(),this.makeImplementationType(),this.makePaginationType(),this.makeDefaultContextType(),this.makeDefaultImplementation(h&&b),this.makeClientClass(i),this.makeSubscriptionClass(a,h&&b)),this.#n=this.makeUsageStatements(i,a))}print(e){let t=this.#e.map(t=>typeof t==`function`?t(e):t);return this.#n&&t.push(`// Usage example:\n/*\n${this.#n}*/`),t.join(`
9
+ `)};const T=b.factory,E=/^[A-Za-z_$][A-Za-z0-9_$]*$/,D=[b.SyntaxKind.AnyKeyword,b.SyntaxKind.BigIntKeyword,b.SyntaxKind.BooleanKeyword,b.SyntaxKind.NeverKeyword,b.SyntaxKind.NumberKeyword,b.SyntaxKind.ObjectKeyword,b.SyntaxKind.StringKeyword,b.SyntaxKind.SymbolKeyword,b.SyntaxKind.UndefinedKeyword,b.SyntaxKind.UnknownKeyword,b.SyntaxKind.VoidKeyword],O=e=>typeof e==`number`?T.createNumericLiteral(e):typeof e==`bigint`?T.createBigIntLiteral(e.toString()):typeof e==`boolean`?e?T.createTrue():T.createFalse():e===null?T.createNull():T.createStringLiteral(e),k=e=>T.createIdentifier(e),A=e=>typeof e==`string`&&E.test(e)?k(e):O(e),j=(e,t)=>typeof e==`number`?T.createKeywordTypeNode(e):typeof e==`string`||b.isIdentifier(e)?T.createTypeReferenceNode(e,t&&y.map(j,t)):e,M=e=>{let t=new Map;for(let n of e)t.set(N(n)?n.kind:n,n);return T.createUnionTypeNode(Array.from(t.values()))},N=e=>D.includes(e.kind),P=(e,t)=>b.addSyntheticLeadingComment(e,b.SyntaxKind.MultiLineCommentTrivia,`* ${t} `,!0),F=(e,t)=>{let n=b.createSourceFile(`print.ts`,``,b.ScriptTarget.Latest,!1,b.ScriptKind.TS);return b.createPrinter(t).printNode(b.EmitHint.Unspecified,e,n)},te=(e,t,{isOptional:n,hasUndefined:r=n,isDeprecated:i,comment:a}={})=>{let o=j(t),s=T.createPropertySignature(void 0,A(e),n?T.createToken(b.SyntaxKind.QuestionToken):void 0,r?M([o,j(b.SyntaxKind.UndefinedKeyword)]):o),c=y.reject(y.isNil,[i?`@deprecated`:void 0,a]);return c.length?P(s,c.join(` `)):s},I=e=>T.createLiteralTypeNode(O(e)),L=(e,{rules:t,onMissing:r,ctx:i={}})=>{let a=n(e),o=a&&a in t?t[a]:t[e._zod.def.type],s=e=>L(e,{ctx:i,rules:t,onMissing:r});return o?o(e,{...i,next:s}):r(e,i)},R={name:y.path([`name`,`text`]),type:y.path([`type`]),optional:y.path([`questionToken`])},z=({_zod:{def:e}})=>{let t=e.values.map(e=>e===void 0?j(b.SyntaxKind.UndefinedKeyword):I(e));return t.length===1?t[0]:M(t)},B=({_zod:{def:e}},{next:t})=>{let{parts:n}=e,r=0,i=()=>{let e=``;for(;r<n.length;){let t=n[r];if(d(t))break;r++,e+=t??``}return e},a=T.createTemplateHead(i()),o=[];for(;r<n.length;){let e=t(n[r++]),a=i(),s=r<n.length?T.createTemplateMiddle:T.createTemplateTail;o.push(T.createTemplateLiteralTypeSpan(e,s(a)))}return o.length?T.createTemplateLiteralType(a,o):I(a.text)},V=(e,{isResponse:t,next:n,makeAlias:r})=>{let i=()=>{let r=Object.entries(e._zod.def.shape).map(([e,r])=>{let{description:i,deprecated:a}=_.get(r)||{},o=(t?r._zod.optout:r._zod.optin)===`optional`,s=o&&!(r instanceof v.core.$ZodExactOptional);return te(e,n(r),{comment:i,isDeprecated:a,isOptional:o,hasUndefined:s})});return T.createTypeLiteralNode(r)};return m(e,{io:t?`output`:`input`})?r(e,i):i()},H=({_zod:{def:e}},{next:t})=>T.createArrayTypeNode(t(e.element)),U=({_zod:{def:e}})=>M(y.map(I,Object.values(e.entries))),W=({_zod:{def:e}},{next:t})=>M(e.options.map(t)),G=({_zod:{def:e}},{next:t})=>M([t(e.innerType),I(null)]),K=({_zod:{def:e}},{next:t})=>T.createTupleTypeNode(e.items.map(t).concat(e.rest===null?[]:T.createRestTypeNode(t(e.rest)))),q=({_zod:{def:e}},{next:t})=>{let[n,r]=[e.keyType,e.valueType].map(t),i=j(`Record`,[n,r]);return e.mode===`loose`?T.createIntersectionTypeNode([i,j(`Record`,[`PropertyKey`,r])]):i},J=y.tryCatch(e=>{if(!e.every(b.isTypeLiteralNode))throw Error(`Not objects`);let t=y.chain(y.prop(`members`),e),n=y.uniqWith((...e)=>{if(!y.eqBy(R.name,...e))return!1;if(y.both(y.eqBy(R.type),y.eqBy(R.optional))(...e))return!0;throw Error(`Has conflicting prop`)},t);return T.createTypeLiteralNode(n)},(e,t)=>T.createIntersectionTypeNode(t)),Y=({_zod:{def:e}},{next:t})=>J([e.left,e.right].map(t)),X=e=>()=>j(e),Z=({_zod:{def:e}},{next:t})=>t(e.innerType),Q=e=>j(e?b.SyntaxKind.UnknownKeyword:b.SyntaxKind.AnyKeyword),ne=({_zod:{def:e}},{next:n,isResponse:r})=>{let i=e[r?`out`:`in`],a=e[r?`in`:`out`];if(!d(i,`transform`))return n(i);let o=n(a),s={[b.SyntaxKind.AnyKeyword]:``,[b.SyntaxKind.BigIntKeyword]:BigInt(0),[b.SyntaxKind.BooleanKeyword]:!1,[b.SyntaxKind.NumberKeyword]:0,[b.SyntaxKind.ObjectKeyword]:{},[b.SyntaxKind.StringKeyword]:``,[b.SyntaxKind.UndefinedKeyword]:void 0}[o.kind],c=t(i,s),l={number:b.SyntaxKind.NumberKeyword,bigint:b.SyntaxKind.BigIntKeyword,boolean:b.SyntaxKind.BooleanKeyword,string:b.SyntaxKind.StringKeyword,undefined:b.SyntaxKind.UndefinedKeyword,object:b.SyntaxKind.ObjectKeyword};return j(c&&l[c]||Q(r))},re=()=>I(null),ie=({_zod:{def:e}},{makeAlias:t,next:n})=>t(e.getter,()=>n(e.getter())),ae=()=>j(`Blob`),oe=(e,{next:t})=>t(e._zod.def.shape.raw),se={string:X(b.SyntaxKind.StringKeyword),number:X(b.SyntaxKind.NumberKeyword),bigint:X(b.SyntaxKind.BigIntKeyword),boolean:X(b.SyntaxKind.BooleanKeyword),any:X(b.SyntaxKind.AnyKeyword),undefined:X(b.SyntaxKind.UndefinedKeyword),[i]:X(b.SyntaxKind.StringKeyword),[s]:X(b.SyntaxKind.StringKeyword),never:X(b.SyntaxKind.NeverKeyword),void:X(b.SyntaxKind.UndefinedKeyword),unknown:X(b.SyntaxKind.UnknownKeyword),null:re,array:H,tuple:K,record:q,object:V,literal:z,template_literal:B,intersection:Y,union:W,default:Z,enum:U,optional:Z,nonoptional:Z,nullable:G,catch:Z,pipe:ne,lazy:ie,readonly:Z,[e]:ae,[h]:oe},$=(e,{brandHandling:t,ctx:n})=>L(e,{rules:{...t,...se},onMissing:({},{isResponse:e})=>Q(e),ctx:n});var ce=class extends ee{#e=[];#t=new Map;#n;#r(e,t){let n=this.#t.get(e);if(!n){n=`Type${this.#t.size+1}`,this.#t.set(e,n);let r=t();this.#e.push(e=>`type ${n} = ${F(r,e)};`)}return j(n)}constructor({routing:e,config:t,brandHandling:n,variant:i=`client`,clientClassName:o=`Client`,subscriptionClassName:s=`Subscription`,serverUrl:l=`https://example.com`,noBodySchema:d=v.undefined(),hasHeadMethod:m=!0,hasCredentials:h=!1}){super(l);let g={makeAlias:this.#r.bind(this)},_={brandHandling:n,ctx:{...g,isResponse:!1}},y={brandHandling:n,ctx:{...g,isResponse:!0}},b=!1,x=(e,t,n)=>{let i=r.bind(null,e,t),{isDeprecated:o,inputSchema:s,tags:c}=n,l=`${e} ${t}`,p=i(`input`),m=f(n.security,`cookie`);m.size&&(b=!0);let h=$(s,_);this.#e.push(e=>{let t=F(h,e);return[`/** ${l} */`,`type ${p} = ${m.size?this.makeOmit(t,m,`security cookies`):t};`].join(`
10
+ `)});let g=u.reduce((t,r)=>{let o=n.getResponses(r),s=[];for(let[t,{schema:n,mimeTypes:c,statusCodes:u}]of o.entries()){let o=a(e,c),f=i(r,`variant`,`${t+1}`),p=$(o?n:d,y);this.#e.push(e=>`/** ${l} */\ntype ${f} = ${F(p,e)};`);for(let e of u)s.push(` ${e}: ${f};`)}let c=i(r,`response`,`variants`);return this.#e.push(`/** ${l} */\ninterface ${c} {\n${s.join(`
11
+ `)}\n}`),Object.assign(t,{[r]:c})},{});this.paths.add(t);let v={input:p,positive:this.someOf(g.positive),negative:this.someOf(g.negative),response:`${S.positive}["${l}"] | ${S.negative}["${l}"]`,encoded:`${g.positive} & ${g.negative}`};this.registry.set(l,{isDeprecated:o,store:v}),this.tags.set(l,c)};p({routing:e,config:t,onEndpoint:m?c(x):x}),this.#e.push(this.makeSomeOfType(),this.makePathType(),this.makeMethodType(),...this.makePublicInterfaces(),this.makeRequestType()),i!==`types`&&(this.#e.push(this.makeEndpointTags(),this.makeParseRequestFn(),this.makeSubstituteFn(),this.makeImplementationType(),this.makePaginationType(),this.makeDefaultContextType(),this.makeDefaultImplementation(h&&b),this.makeClientClass(o),this.makeSubscriptionClass(s,h&&b)),this.#n=this.makeUsageStatements(o,s))}print(e){let t=this.#e.map(t=>typeof t==`function`?t(e):t);return this.#n&&t.push(`// Usage example:\n/*\n${this.#n}*/`),t.join(`
12
12
 
13
13
  `)}async printFormatted({printerOptions:e,format:t}={}){let n=t;if(!n){try{let e=g(`prettier`).format;n=t=>e(t,{filepath:`client.ts`})}catch{}try{let e=g(`oxfmt`).format;n=async t=>{let{code:n,errors:r}=await e(`client.ts`,t);if(r.length)throw Error(`OxFmt failed to format the code`,{cause:r});return n}}catch{}}this.#n&&n&&(this.#n=await n(this.#n));let r=this.print(e);return n?n(r):r}};export{ce as Integration};
@@ -1 +1 @@
1
- import{T as e}from"./routing-walker-D9nfJshN.js";import{createRequire as t}from"node:module";let n;const r=(r,i=`default`)=>{try{let e=(n??=t(import.meta.url))(r);return i==="default"?e.default===void 0?e:e.default:e[i]}catch{throw new e(r)}};export{r as t};
1
+ import{E as e}from"./routing-walker-CcgJ8aiU.js";import{createRequire as t}from"node:module";let n;const r=(r,i=`default`)=>{try{let e=(n??=t(import.meta.url))(r);return i==="default"?e.default===void 0?e:e.default:e[i]}catch{throw new e(r)}};export{r as t};
@@ -22,6 +22,7 @@ interface ApiResponse<S extends z.ZodType> {
22
22
  /**
23
23
  * @desc The status code(s) for this response.
24
24
  * @default 200 for a positive response, 400 for a negative one
25
+ * @see BuildProps#statusCode - for Endpoint-specific overrides
25
26
  * */
26
27
  statusCode?: number | [number, ...number[]];
27
28
  /**
@@ -550,6 +551,31 @@ type Security<K extends string = string, S extends string = string> = (
550
551
  ) & {
551
552
  deprecated?: boolean;
552
553
  };
554
+ declare const frozenSetBrand: unique symbol;
555
+ /**
556
+ * @class The Set that cannot be modified at runtime.
557
+ * @desc Use it for the values stored once internally and handed out through getters declared as `ReadonlySet`.
558
+ * Use `Set` for mutable accumulators. A nominal brand makes `Set` unassignable to `FrozenSet` at the type
559
+ * level, while the immutability is enforced at runtime by the mutation methods throwing `TypeError`.
560
+ * */
561
+ declare class FrozenSet<T> extends Set<T> implements ReadonlySet<T> {
562
+ readonly [frozenSetBrand]: true;
563
+ constructor(values?: Iterable<T> | null);
564
+ /** @throws TypeError */
565
+ add(_value: T): this;
566
+ /** @throws TypeError */
567
+ delete(_value: T): boolean;
568
+ /** @throws TypeError */
569
+ clear(): void;
570
+ /** @desc The derived set is frozen as well. */
571
+ union<U>(other: ReadonlySetLike<U>): FrozenSet<T | U>;
572
+ /** @desc The derived set is frozen as well. */
573
+ intersection<U>(other: ReadonlySetLike<U>): FrozenSet<T & U>;
574
+ /** @desc The derived set is frozen as well. */
575
+ difference<U>(other: ReadonlySetLike<U>): FrozenSet<T>;
576
+ /** @desc The derived set is frozen as well. */
577
+ symmetricDifference<U>(other: ReadonlySetLike<U>): FrozenSet<T | U>;
578
+ }
553
579
  type Handler$1<IN, CTX, RET> = (params: {
554
580
  /** @desc The inputs from the enabled input sources validated against the input schema of the Middleware. */
555
581
  input: IN;
@@ -588,6 +614,7 @@ declare class Middleware<
588
614
  constructor({
589
615
  input,
590
616
  security,
617
+ statusCode,
591
618
  handler,
592
619
  }: {
593
620
  /**
@@ -601,6 +628,8 @@ declare class Middleware<
601
628
  * @see Documentation
602
629
  * */
603
630
  security?: LogicalContainer<Security<Extract<keyof z.input<IN>, string>, SCO>>;
631
+ /** @desc The status code(s) the Middleware may interrupt the request handling (used by Documentation). */
632
+ statusCode?: number | [number, ...number[]];
604
633
  /** @desc The handler returning a context available to Endpoints. */
605
634
  handler: Handler$1<z.output<IN>, CTX, RET>;
606
635
  });
@@ -631,11 +660,14 @@ declare class ExpressMiddleware<R extends Request, S extends Response, RET exten
631
660
  {
632
661
  provider,
633
662
  transformer,
663
+ statusCode,
634
664
  }?: {
635
665
  /** @desc Extracts context properties from request and response after the native middleware execution. */
636
666
  provider?: (request: R, response: S) => RET | Promise<RET>;
637
667
  /** @desc Transforms errors caught from the native middleware before they propagate further. */
638
668
  transformer?: (err: Error) => Error;
669
+ /** @desc The status code(s) the Middleware may interrupt the request handling (used by Documentation). */
670
+ statusCode?: number | [number, ...number[]];
639
671
  },
640
672
  );
641
673
  }
@@ -670,9 +702,10 @@ declare class Endpoint<IN extends IOSchema, OUT extends IOSchema, CTX extends Fl
670
702
  description?: string;
671
703
  summary?: string;
672
704
  getOperationId?: (method: ClientMethod) => string | undefined;
673
- methods?: Method[];
705
+ methods: FrozenSet<Method>;
674
706
  scopes?: string[];
675
707
  tags?: string[];
708
+ statusCodes: ReadonlySet<number>;
676
709
  });
677
710
  deprecated(): this;
678
711
  execute({
@@ -0,0 +1 @@
1
+ import{globalRegistry as e,z as t}from"zod";import*as n from"ramda";import{isPromise as r}from"node:util/types";import i,{isHttpError as a}from"http-errors";import o from"express";const s={json:`application/json`,upload:`multipart/form-data`,raw:`application/octet-stream`,sse:`text/event-stream`,form:`application/x-www-form-urlencoded`},c=[`get`,`post`,`put`,`delete`,`patch`,`query`],l=[...c,`head`],u=e=>c.includes(e),d=t.object({}),f=/:([A-Za-z0-9_]+)/g,ee=e=>e.match(f)?.map(e=>e.slice(1))||[],p=(e,t=1)=>e.replace(f,()=>`:${t++}`),te=e=>{let t=(e.header(`content-type`)||``).toLowerCase().startsWith(s.upload);return`files`in e&&t},ne={get:[`query`,`params`],post:[`body`,`params`,`files`],put:[`body`,`params`],patch:[`body`,`params`],delete:[`query`,`params`],query:[`query`,`body`,`params`]},re=[`body`,`query`,`params`],m=e=>e.method.toLowerCase(),h=(e,t={})=>{if(e===`options`)return[];let n=e===`head`?`get`:u(e)?e:void 0;return(n?t[n]||ne[n]:void 0)||re},g=(e,t={})=>{let n=m(e);return h(n,t).filter(t=>t!==`files`||te(e)).reduce((t,n)=>Object.assign(t,e[n]),{})},_=e=>e instanceof Error?e:e instanceof t.ZodError?new t.ZodRealError(e.issues):Error(String(e)),v=e=>e instanceof t.ZodError?e.issues.map(({path:e,message:n})=>`${e.length?`${t.core.toDotPath(e)}: `:``}${n}`).join(`; `):e.message,y=(e,t)=>S(e)&&`_zod`in e&&(!t||n.path([`_zod`,`def`,`type`],e)===t),b=(e,t,r)=>e.length&&t.length?n.xprod(e,t).map(r):e.concat(t),x=e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase(),ie=(...e)=>{let t=n.chain(e=>e.split(/[^A-Z0-9]/gi),e);return n.chain(e=>e.replaceAll(/[A-Z]+/g,e=>`/${e}`).split(`/`),t).map(x).join(``)},ae=n.tryCatch((e,n)=>typeof t.parse(e,n),n.always(void 0)),S=e=>typeof e==`object`&&!!e,C={_cache:void 0,get env(){return C._cache??=process.env.NODE_ENV??`development`},get isProduction(){return C.env===`production`}},oe=(e,t)=>!!t&&e!==`head`,w=`x-brand`,T=t=>{let{[w]:n}=e.get(t)||{};if(typeof n==`symbol`||typeof n==`string`||typeof n==`number`)return n},E=t=>{let{examples:n}=e.get(t)||{};return Array.isArray(n)?n:[]},D=Symbol(`Buffer`),O=()=>t.custom(e=>Buffer.isBuffer(e),{error:`Expected Buffer`}).meta({[w]:D}),k=Symbol(`DateIn`),se=({examples:e,...n}={})=>t.union([t.iso.date(),t.iso.datetime({local:!0,offset:!0})]).meta({examples:e}).transform(e=>new Date(e)).pipe(t.date()).meta({...n,[w]:k}),A=Symbol(`DateOut`),ce=(e={})=>t.date().transform(e=>e.toISOString()).pipe(t.iso.datetime()).meta({...e,[w]:A});var j=class extends Error{name=`RoutingError`;cause;constructor(e,t,n){super(e),this.cause={method:t,path:n}}},le=class extends Error{name=`DocumentationError`;cause;constructor(e,{method:t,path:n,isResponse:r}){super(e),this.cause=`${r?`Response`:`Input`} schema of an Endpoint assigned to ${t.toUpperCase()} method of ${n} path.`}},M=class extends Error{name=`IOSchemaError`},ue=class extends M{cause;name=`DeepCheckError`;constructor(e){super(`Found`,{cause:e}),this.cause=e}},N=class extends M{cause;name=`OutputValidationError`;constructor(e){let n=new t.ZodError(e.issues.map(({path:e,...t})=>({...t,path:[`output`,...e]})));super(v(n),{cause:e}),this.cause=e}},P=class extends M{cause;name=`InputValidationError`;constructor(e){super(v(e),{cause:e}),this.cause=e}},F=class extends Error{cause;handled;name=`ResultHandlerError`;constructor(e,t){super(v(e),{cause:e}),this.cause=e,this.handled=t}},de=class extends Error{name=`MissingPeerError`;constructor(e){super(`Missing peer dependency: ${e}. Please install it to use the feature.`)}};const I=Symbol(`Form`),fe=e=>(e instanceof t.ZodObject?e:t.object(e)).meta({[w]:I}),L=Symbol(`Upload`),pe=e=>S(e)&&`name`in e&&`encoding`in e&&`mimetype`in e&&`data`in e&&`tempFilePath`in e&&`truncated`in e&&`size`in e&&`md5`in e&&`mv`in e,me=()=>t.custom(e=>pe(e)&&typeof e.name==`string`&&typeof e.encoding==`string`&&typeof e.mimetype==`string`&&Buffer.isBuffer(e.data)&&typeof e.tempFilePath==`string`&&typeof e.truncated==`boolean`&&typeof e.size==`number`&&typeof e.md5==`string`&&typeof e.mv==`function`,{error:({input:e})=>({message:`Expected file upload, received ${typeof e}`})}).meta({[w]:L}),R=Symbol(`Raw`),z=t.object({raw:O()}),he=e=>z.extend(e).meta({[w]:R});function ge(e){return e?he(e):z.meta({[w]:R})}const B=(e,{io:r,condition:i})=>n.tryCatch(()=>void t.toJSONSchema(e,{io:r,unrepresentable:`any`,override:({zodSchema:e})=>{if(i(e))throw new ue(e)}}),e=>e.cause)(),_e=(e,{io:r})=>{let i=[t.toJSONSchema(e,{io:r,unrepresentable:`any`})];for(let e=0;e<i.length;e++){let t=i[e];if(n.is(Object,t)){if(t.$ref===`#`)return!0;i.push(...n.values(t))}n.is(Array,t)&&i.push(...n.values(t))}return!1},ve=e=>B(e,{condition:e=>{let t=T(e);return typeof t==`symbol`&&[L,R,I].includes(t)},io:`input`}),ye=new Set([`nan`,`symbol`,`map`,`set`,`bigint`,`void`,`promise`,`never`,`function`]),be=(e,t)=>B(e,{io:t,condition:e=>{let n=T(e),{type:r}=e._zod.def;return!!(ye.has(r)||n===D||t===`input`&&(r===`date`||n===A)||t===`output`&&(n===k||n===R||n===L))}});var V=class e extends Set{constructor(e){if(super(),e)for(let t of e)Set.prototype.add.call(this,t)}add(e){throw TypeError(`Can not add to the read only Set`)}delete(e){throw TypeError(`Can not delete from the read only Set`)}clear(){throw TypeError(`Can not clear the read only Set`)}union(t){return new e(super.union(t))}intersection(t){return new e(super.intersection(t))}difference(t){return new e(super.difference(t))}symmetricDifference(t){return new e(super.symmetricDifference(t))}},xe=class{},H=class extends xe{#e;#t;#n;#r;constructor({input:e,security:t,statusCode:n,handler:r}){super(),this.#e=e,this.#t=t,this.#n=new V(typeof n==`number`?[n]:n),this.#r=r}get security(){return this.#t}get schema(){return this.#e}get statusCodes(){return this.#n}async execute({input:e,...n}){try{let t=await(this.#e||d).parseAsync(e);return this.#r({...n,input:t})}catch(e){throw e instanceof t.ZodError?new P(e):e}}},U=class extends H{constructor(e,{provider:t=()=>({}),transformer:n=e=>e,statusCode:i}={}){super({statusCode:i,handler:async({request:i,response:a})=>{let{promise:o,resolve:s,reject:c}=Promise.withResolvers(),l=e=>{if(e&&e instanceof Error)return c(n(e));s(t(i,a))},u=e(i,a,l);return r(u)&&u.catch(l),o}})}};const W={positive:200,negative:400},Se=Object.keys(W),G=e=>e<400;function Ce(e){return e instanceof t.ZodType?{schema:e}:e}const we=(e,{variant:r,args:i})=>{typeof e==`function`&&(e=e(...i));let a={statusCodes:[W[r]],mimeTypes:[s.json]};if(e instanceof t.ZodType)return[{schema:e,...a}];if(Array.isArray(e)&&!e.length)throw new F(Error(`At least one ${r} response schema required.`));let o=(Array.isArray(e)?e:[e]).map(({schema:e,statusCode:t,mimeType:n})=>({schema:e,statusCodes:typeof t==`number`?[t]:t||a.statusCodes,mimeTypes:typeof n==`string`?[n]:n===void 0?a.mimeTypes:n})),c=n.chain(n.prop(`statusCodes`),o),l=c.find(e=>G(e)===(r===`negative`));if(l!==void 0)throw new F(Error(`The status code ${l} is not valid for a ${r} API response.`));if(o.length>1){let e=n.find(e=>c.indexOf(e)!==c.lastIndexOf(e),c);if(e!==void 0)throw new F(Error(`The status code ${e} is used by multiple response schemas.`))}return o},Te=(e,t,n)=>{let r=new Set(Array.from(t).filter(e=>G(e)===(n===`positive`)));if(!r.size)return e;if(e.length===1)return e.map(e=>({...e,statusCodes:Array.from(r)}));let i=[],a=e.reduce((e,{statusCodes:t,...n})=>{let a=new Set(t).intersection(r);return a.size?(i.push({...n,statusCodes:Array.from(a)}),e.difference(a)):e},new Set(r));if(a.size){let e=Array.from(a).join(`, `),t=a.size>1;throw new F(Error(`The ResultHandler defines multiple ${n} response schemas, but the overriding status code${t?`s`:``} ${e} of the Endpoint ${t?`are`:`is`} not listed for any of them, therefore it is unclear how such override${t?`s`:``} would be handled. Consider adding ${t?`them`:`it`} to ResultHandler.`))}return i},Ee=(e,t,{url:n},r)=>!e.expose&&t.error(`Server side error`,{error:e,url:n,payload:r}),De=e=>a(e)?e:i(e instanceof P?400:500,v(e),{cause:e.cause||e}),Oe=e=>C.isProduction&&!e.expose?i(e.statusCode).message:e.message,ke=e=>Object.entries(e._zod.def.shape).reduce((e,[t,r])=>b(e,E(r).map(n.objOf(t)),([e,t])=>({...e,...t})),[]);var K=class{nest(e){return{...e,"":this}}},Ae=class r extends K{#e;#t;#n=n.once(()=>{if(E(this.#e.outputSchema).length||!y(this.#e.outputSchema,`object`))return;let t=ke(this.#e.outputSchema);if(!t.length)return;let n=this.#e.outputSchema.meta();e.remove(this.#e.outputSchema).add(this.#e.outputSchema,{...n,examples:t})});constructor(e){super(),this.#e=e}#r(e){return new r({...this.#e,...e})}deprecated(){return this.#r({deprecated:!0})}get isDeprecated(){return this.#e.deprecated||!1}get description(){return this.#e.description}get summary(){return this.#e.summary}get methods(){return this.#e.methods}get inputSchema(){return this.#e.inputSchema}get outputSchema(){return this.#e.outputSchema}getProbableRequestType(e){return e===`query`?`form`:this.#t??=(()=>{let e=ve(this.#e.inputSchema);if(e){let t=T(e);if(t===L)return`upload`;if(t===R)return`raw`;if(t===I)return`form`}return`json`})()}getResponses(e){e===`positive`&&this.#n();let t=e===`negative`?this.#e.resultHandler.getNegativeResponse():this.#e.resultHandler.getPositiveResponse(this.#e.outputSchema);return Object.freeze(this.#e.statusCodes.size?Te(t,this.#e.statusCodes,e):t)}get security(){let e=n.pluck(`security`,this.#e.middlewares||[]);return n.reject(n.isNil,e)}get scopes(){return Object.freeze(this.#e.scopes||[])}get tags(){return Object.freeze(this.#e.tags||[])}getOperationId(e){return this.#e.getOperationId?.(e)}async#i(e){try{return await this.#e.outputSchema.parseAsync(e)}catch(e){throw e instanceof t.ZodError?new N(e):e}}async#a({method:e,logger:t,ctx:n,response:r,...i}){for(let a of this.#e.middlewares||[])if(!(e===`options`&&!(a instanceof U))&&(Object.assign(n,await a.execute({...i,ctx:n,response:r,logger:t})),r.writableEnded)){t.warn(`A middleware has closed the stream. Accumulated context:`,n);break}}async#o({input:e,...n}){let r;try{r=await this.#e.inputSchema.parseAsync(e)}catch(e){throw e instanceof t.ZodError?new P(e):e}return this.#e.handler({...n,input:r})}async#s(e){await this.#e.resultHandler.execute(e)}async execute({request:e,response:t,logger:n,config:r}){let i=m(e),a={},o,s=g(e,r.inputSources);try{if(await this.#a({method:i,input:s,request:e,response:t,logger:n,ctx:a}),t.writableEnded)return;if(i===`options`)return void t.status(200).end();let r=await this.#o({input:s,logger:n,ctx:a});if(t.writableEnded)return;o={output:await this.#i(r),error:null}}catch(e){o={output:null,error:_(e)}}await this.#s({...o,input:s,request:e,response:t,logger:n,ctx:a})}},q=class{#e;constructor(...e){this.#e=e}apply(e,t){return t(e,o.static(...this.#e))}};const J=e=>S(e)&&`or`in e,Y=e=>S(e)&&`and`in e,X=e=>!Y(e)&&!J(e),je=e=>{let t=n.filter(X,e),r=n.chain(n.prop(`and`),n.filter(Y,e)),[i,a]=n.partition(X,r),o=n.concat(t,i),s=n.filter(J,e);return n.map(n.prop(`or`),n.concat(s,a)).reduce((e,t)=>b(e,n.map(e=>X(e)?[e]:e.and,t),([e,t])=>n.concat(e,t)),n.reject(n.isEmpty,[o]))},Z=(e,t)=>Y(e)?n.chain(e=>Z(e,t),e.and):J(e)?n.chain(e=>Z(e,t),e.or):e.type===t?[e.name]:[],Me=(e,t)=>new Set(n.chain(e=>Z(e,t),e)),Ne=e=>(t,...n)=>{e(t,...n),t===`get`&&e(`head`,...n)},Pe=e=>{let[t,n]=e.trim().split(/ (.+)/,2);return n&&u(t)?[n,t]:[e]},Fe=e=>e.trim().split(`/`).filter(Boolean).join(`/`),Q=({recognizeMethodDependentRoutes:e=!0},t,n)=>Object.entries(t).map(([t,r])=>{let[i,a]=e&&u(t)&&r instanceof K?[`/`,t]:Pe(t);return[[n||``].concat(Fe(i)||[]).join(`/`)||`/`,r,a]}),Ie=(e,t)=>{throw new j(`Route with explicit method can only be assigned with Endpoint`,e,t)},Le=(e,t,n)=>{if(!(!n.size||n.has(e)))throw new j(`Method ${e} is not supported by the assigned Endpoint.`,e,t)},$=(e,t,n)=>{let r=t.includes(`:`)?p(t):t,i=`${e} ${r}`;if(n.has(i))throw new j(`Route has a duplicate: the normalized path "${r}" is already registered`,e,t);n.add(i)},Re=({routing:e,config:t,onEndpoint:n,onStatic:r})=>{let i=Q(t,e),a=new Set;for(let e=0;e<i.length;e++){let[o,s,c]=i[e];if(s instanceof K)if(c)$(c,o,a),Le(c,o,s.methods),n(c,o,s);else{let{methods:e}=s;for(let t of e.size?e:[`get`])$(t,o,a),n(t,o,s)}else c&&Ie(c,o),s instanceof q?r&&s.apply(o,r):i.splice(e+1,0,...Q(t,s,o))}};export{x as $,ce as A,_ as B,fe as C,N as D,de as E,D as F,ae as G,h as H,T as I,ie as J,S as K,E as L,se as M,k as N,F as O,O as P,oe as Q,b as R,me as S,P as T,v as U,g as V,ee as W,f as X,p as Y,C as Z,be as _,q as a,ge as b,Oe as c,Ce as d,l as et,W as f,V as g,H as h,je as i,A as j,j as k,Ee as l,U as m,Ne as n,s as nt,Ae as o,Se as p,y as q,Me as r,De as s,Re as t,u as tt,we as u,_e as v,le as w,L as x,R as y,d as z};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "express-zod-api",
3
- "version": "29.2.3",
3
+ "version": "29.3.1",
4
4
  "description": "A Typescript framework to help you get an API server up and running with I/O schema validation and custom middlewares in minutes.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1 +0,0 @@
1
- import{globalRegistry as e,z as t}from"zod";import*as n from"ramda";import{isPromise as r}from"node:util/types";import i,{isHttpError as a}from"http-errors";import o from"express";const s={json:`application/json`,upload:`multipart/form-data`,raw:`application/octet-stream`,sse:`text/event-stream`,form:`application/x-www-form-urlencoded`},c=[`get`,`post`,`put`,`delete`,`patch`,`query`],l=[...c,`head`],u=e=>c.includes(e),d=t.object({}),f=/:([A-Za-z0-9_]+)/g,ee=e=>e.match(f)?.map(e=>e.slice(1))||[],p=(e,t=1)=>e.replace(f,()=>`:${t++}`),te=e=>{let t=(e.header(`content-type`)||``).toLowerCase().startsWith(s.upload);return`files`in e&&t},ne={get:[`query`,`params`],post:[`body`,`params`,`files`],put:[`body`,`params`],patch:[`body`,`params`],delete:[`query`,`params`],query:[`query`,`body`,`params`]},re=[`body`,`query`,`params`],m=e=>e.method.toLowerCase(),h=(e,t={})=>{if(e===`options`)return[];let n=e===`head`?`get`:u(e)?e:void 0;return(n?t[n]||ne[n]:void 0)||re},g=(e,t={})=>{let n=m(e);return h(n,t).filter(t=>t!==`files`||te(e)).reduce((t,n)=>Object.assign(t,e[n]),{})},_=e=>e instanceof Error?e:e instanceof t.ZodError?new t.ZodRealError(e.issues):Error(String(e)),v=e=>e instanceof t.ZodError?e.issues.map(({path:e,message:n})=>`${e.length?`${t.core.toDotPath(e)}: `:``}${n}`).join(`; `):e.message,y=(e,t)=>S(e)&&`_zod`in e&&(!t||n.path([`_zod`,`def`,`type`],e)===t),b=(e,t,r)=>e.length&&t.length?n.xprod(e,t).map(r):e.concat(t),x=e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase(),ie=(...e)=>{let t=n.chain(e=>e.split(/[^A-Z0-9]/gi),e);return n.chain(e=>e.replaceAll(/[A-Z]+/g,e=>`/${e}`).split(`/`),t).map(x).join(``)},ae=n.tryCatch((e,n)=>typeof t.parse(e,n),n.always(void 0)),S=e=>typeof e==`object`&&!!e,C={_cache:void 0,get env(){return C._cache??=process.env.NODE_ENV??`development`},get isProduction(){return C.env===`production`}},oe=(e,t)=>!!t&&e!==`head`,w=`x-brand`,T=t=>{let{[w]:n}=e.get(t)||{};if(typeof n==`symbol`||typeof n==`string`||typeof n==`number`)return n},E=t=>{let{examples:n}=e.get(t)||{};return Array.isArray(n)?n:[]},D=Symbol(`Buffer`),O=()=>t.custom(e=>Buffer.isBuffer(e),{error:`Expected Buffer`}).meta({[w]:D}),k=Symbol(`DateIn`),se=({examples:e,...n}={})=>t.union([t.iso.date(),t.iso.datetime({local:!0,offset:!0})]).meta({examples:e}).transform(e=>new Date(e)).pipe(t.date()).meta({...n,[w]:k}),A=Symbol(`DateOut`),j=(e={})=>t.date().transform(e=>e.toISOString()).pipe(t.iso.datetime()).meta({...e,[w]:A});var M=class extends Error{name=`RoutingError`;cause;constructor(e,t,n){super(e),this.cause={method:t,path:n}}},ce=class extends Error{name=`DocumentationError`;cause;constructor(e,{method:t,path:n,isResponse:r}){super(e),this.cause=`${r?`Response`:`Input`} schema of an Endpoint assigned to ${t.toUpperCase()} method of ${n} path.`}},N=class extends Error{name=`IOSchemaError`},le=class extends N{cause;name=`DeepCheckError`;constructor(e){super(`Found`,{cause:e}),this.cause=e}},P=class extends N{cause;name=`OutputValidationError`;constructor(e){let n=new t.ZodError(e.issues.map(({path:e,...t})=>({...t,path:[`output`,...e]})));super(v(n),{cause:e}),this.cause=e}},F=class extends N{cause;name=`InputValidationError`;constructor(e){super(v(e),{cause:e}),this.cause=e}},I=class extends Error{cause;handled;name=`ResultHandlerError`;constructor(e,t){super(v(e),{cause:e}),this.cause=e,this.handled=t}},ue=class extends Error{name=`MissingPeerError`;constructor(e){super(`Missing peer dependency: ${e}. Please install it to use the feature.`)}};const L=Symbol(`Form`),de=e=>(e instanceof t.ZodObject?e:t.object(e)).meta({[w]:L}),R=Symbol(`Upload`),fe=e=>S(e)&&`name`in e&&`encoding`in e&&`mimetype`in e&&`data`in e&&`tempFilePath`in e&&`truncated`in e&&`size`in e&&`md5`in e&&`mv`in e,pe=()=>t.custom(e=>fe(e)&&typeof e.name==`string`&&typeof e.encoding==`string`&&typeof e.mimetype==`string`&&Buffer.isBuffer(e.data)&&typeof e.tempFilePath==`string`&&typeof e.truncated==`boolean`&&typeof e.size==`number`&&typeof e.md5==`string`&&typeof e.mv==`function`,{error:({input:e})=>({message:`Expected file upload, received ${typeof e}`})}).meta({[w]:R}),z=Symbol(`Raw`),B=t.object({raw:O()}),me=e=>B.extend(e).meta({[w]:z});function he(e){return e?me(e):B.meta({[w]:z})}const V=(e,{io:r,condition:i})=>n.tryCatch(()=>void t.toJSONSchema(e,{io:r,unrepresentable:`any`,override:({zodSchema:e})=>{if(i(e))throw new le(e)}}),e=>e.cause)(),ge=(e,{io:r})=>{let i=[t.toJSONSchema(e,{io:r,unrepresentable:`any`})];for(let e=0;e<i.length;e++){let t=i[e];if(n.is(Object,t)){if(t.$ref===`#`)return!0;i.push(...n.values(t))}n.is(Array,t)&&i.push(...n.values(t))}return!1},_e=e=>V(e,{condition:e=>{let t=T(e);return typeof t==`symbol`&&[R,z,L].includes(t)},io:`input`}),ve=new Set([`nan`,`symbol`,`map`,`set`,`bigint`,`void`,`promise`,`never`,`function`]),H=(e,t)=>V(e,{io:t,condition:e=>{let n=T(e),{type:r}=e._zod.def;return!!(ve.has(r)||n===D||t===`input`&&(r===`date`||n===A)||t===`output`&&(n===k||n===z||n===R))}});var ye=class{},U=class extends ye{#e;#t;#n;constructor({input:e,security:t,handler:n}){super(),this.#e=e,this.#t=t,this.#n=n}get security(){return this.#t}get schema(){return this.#e}async execute({input:e,...n}){try{let t=await(this.#e||d).parseAsync(e);return this.#n({...n,input:t})}catch(e){throw e instanceof t.ZodError?new F(e):e}}},W=class extends U{constructor(e,{provider:t=()=>({}),transformer:n=e=>e}={}){super({handler:async({request:i,response:a})=>{let{promise:o,resolve:s,reject:c}=Promise.withResolvers(),l=e=>{if(e&&e instanceof Error)return c(n(e));s(t(i,a))},u=e(i,a,l);return r(u)&&u.catch(l),o}})}};const G={positive:200,negative:400},be=Object.keys(G),xe=e=>e<400;function Se(e){return e instanceof t.ZodType?{schema:e}:e}const Ce=(e,{variant:r,args:i})=>{typeof e==`function`&&(e=e(...i));let a={statusCodes:[G[r]],mimeTypes:[s.json]};if(e instanceof t.ZodType)return[{schema:e,...a}];if(Array.isArray(e)&&!e.length)throw new I(Error(`At least one ${r} response schema required.`));let o=(Array.isArray(e)?e:[e]).map(({schema:e,statusCode:t,mimeType:n})=>({schema:e,statusCodes:typeof t==`number`?[t]:t||a.statusCodes,mimeTypes:typeof n==`string`?[n]:n===void 0?a.mimeTypes:n})),c=n.chain(n.prop(`statusCodes`),o),l=c.find(e=>xe(e)===(r===`negative`));if(l!==void 0)throw new I(Error(`The status code ${l} is not valid for a ${r} API response.`));if(o.length>1){let e=n.find(e=>c.indexOf(e)!==c.lastIndexOf(e),c);if(e!==void 0)throw new I(Error(`The status code ${e} is used by multiple response schemas.`))}return o},we=(e,t,{url:n},r)=>!e.expose&&t.error(`Server side error`,{error:e,url:n,payload:r}),Te=e=>a(e)?e:i(e instanceof F?400:500,v(e),{cause:e.cause||e}),Ee=e=>C.isProduction&&!e.expose?i(e.statusCode).message:e.message,De=e=>Object.entries(e._zod.def.shape).reduce((e,[t,r])=>b(e,E(r).map(n.objOf(t)),([e,t])=>({...e,...t})),[]);var K=class{nest(e){return{...e,"":this}}},Oe=class r extends K{#e;#t;#n=n.once(()=>{if(E(this.#e.outputSchema).length||!y(this.#e.outputSchema,`object`))return;let t=De(this.#e.outputSchema);if(!t.length)return;let n=this.#e.outputSchema.meta();e.remove(this.#e.outputSchema).add(this.#e.outputSchema,{...n,examples:t})});constructor(e){super(),this.#e=e}#r(e){return new r({...this.#e,...e})}deprecated(){return this.#r({deprecated:!0})}get isDeprecated(){return this.#e.deprecated||!1}get description(){return this.#e.description}get summary(){return this.#e.summary}get methods(){return Object.freeze(this.#e.methods)}get inputSchema(){return this.#e.inputSchema}get outputSchema(){return this.#e.outputSchema}getProbableRequestType(e){return e===`query`?`form`:this.#t??=(()=>{let e=_e(this.#e.inputSchema);if(e){let t=T(e);if(t===R)return`upload`;if(t===z)return`raw`;if(t===L)return`form`}return`json`})()}getResponses(e){return e===`positive`&&this.#n(),Object.freeze(e===`negative`?this.#e.resultHandler.getNegativeResponse():this.#e.resultHandler.getPositiveResponse(this.#e.outputSchema))}get security(){let e=n.pluck(`security`,this.#e.middlewares||[]);return n.reject(n.isNil,e)}get scopes(){return Object.freeze(this.#e.scopes||[])}get tags(){return Object.freeze(this.#e.tags||[])}getOperationId(e){return this.#e.getOperationId?.(e)}async#i(e){try{return await this.#e.outputSchema.parseAsync(e)}catch(e){throw e instanceof t.ZodError?new P(e):e}}async#a({method:e,logger:t,ctx:n,response:r,...i}){for(let a of this.#e.middlewares||[])if(!(e===`options`&&!(a instanceof W))&&(Object.assign(n,await a.execute({...i,ctx:n,response:r,logger:t})),r.writableEnded)){t.warn(`A middleware has closed the stream. Accumulated context:`,n);break}}async#o({input:e,...n}){let r;try{r=await this.#e.inputSchema.parseAsync(e)}catch(e){throw e instanceof t.ZodError?new F(e):e}return this.#e.handler({...n,input:r})}async#s(e){await this.#e.resultHandler.execute(e)}async execute({request:e,response:t,logger:n,config:r}){let i=m(e),a={},o,s=g(e,r.inputSources);try{if(await this.#a({method:i,input:s,request:e,response:t,logger:n,ctx:a}),t.writableEnded)return;if(i===`options`)return void t.status(200).end();let r=await this.#o({input:s,logger:n,ctx:a});if(t.writableEnded)return;o={output:await this.#i(r),error:null}}catch(e){o={output:null,error:_(e)}}await this.#s({...o,input:s,request:e,response:t,logger:n,ctx:a})}},q=class{#e;constructor(...e){this.#e=e}apply(e,t){return t(e,o.static(...this.#e))}};const J=e=>S(e)&&`or`in e,Y=e=>S(e)&&`and`in e,X=e=>!Y(e)&&!J(e),ke=e=>{let t=n.filter(X,e),r=n.chain(n.prop(`and`),n.filter(Y,e)),[i,a]=n.partition(X,r),o=n.concat(t,i),s=n.filter(J,e);return n.map(n.prop(`or`),n.concat(s,a)).reduce((e,t)=>b(e,n.map(e=>X(e)?[e]:e.and,t),([e,t])=>n.concat(e,t)),n.reject(n.isEmpty,[o]))},Z=(e,t)=>Y(e)?n.chain(e=>Z(e,t),e.and):J(e)?n.chain(e=>Z(e,t),e.or):e.type===t?[e.name]:[],Ae=(e,t)=>new Set(n.chain(e=>Z(e,t),e)),je=e=>(t,...n)=>{e(t,...n),t===`get`&&e(`head`,...n)},Me=e=>{let[t,n]=e.trim().split(/ (.+)/,2);return n&&u(t)?[n,t]:[e]},Ne=e=>e.trim().split(`/`).filter(Boolean).join(`/`),Q=({recognizeMethodDependentRoutes:e=!0},t,n)=>Object.entries(t).map(([t,r])=>{let[i,a]=e&&u(t)&&r instanceof K?[`/`,t]:Me(t);return[[n||``].concat(Ne(i)||[]).join(`/`)||`/`,r,a]}),Pe=(e,t)=>{throw new M(`Route with explicit method can only be assigned with Endpoint`,e,t)},Fe=(e,t,n)=>{if(!(!n||n.includes(e)))throw new M(`Method ${e} is not supported by the assigned Endpoint.`,e,t)},$=(e,t,n)=>{let r=t.includes(`:`)?p(t):t,i=`${e} ${r}`;if(n.has(i))throw new M(`Route has a duplicate: the normalized path "${r}" is already registered`,e,t);n.add(i)},Ie=({routing:e,config:t,onEndpoint:n,onStatic:r})=>{let i=Q(t,e),a=new Set;for(let e=0;e<i.length;e++){let[o,s,c]=i[e];if(s instanceof K)if(c)$(c,o,a),Fe(c,o,s.methods),n(c,o,s);else{let{methods:e=[`get`]}=s;for(let t of e)$(t,o,a),n(t,o,s)}else c&&Pe(c,o),s instanceof q?r&&s.apply(o,r):i.splice(e+1,0,...Q(t,s,o))}};export{l as $,A,g as B,ce as C,I as D,P as E,T as F,S as G,v as H,E as I,p as J,y as K,b as L,k as M,O as N,M as O,D as P,x as Q,d as R,de as S,ue as T,ee as U,h as V,ae as W,C as X,f as Y,oe as Z,ge as _,q as a,R as b,Ee as c,Se as d,u as et,G as f,H as g,U as h,ke as i,se as j,j as k,we as l,W as m,je as n,Oe as o,be as p,ie as q,Ae as r,Te as s,Ie as t,s as tt,Ce as u,z as v,F as w,pe as x,he as y,_ as z};