workery
Version:
Modern web framework for building APIs on Cloudflare Workers.
2 lines (1 loc) • 3.63 kB
JavaScript
import{OpenAPIRegistry as e,OpenApiGeneratorV31 as t}from"@asteasolutions/zod-to-openapi";import*as s from"cookie";import{parseArgs as r}from"./parameters.js";import{JSONResponse as i,HTMLResponse as o}from"./responses.js";import{Router as a,fixPathSlashes as n,Route as h,searchParamsToQueries as c}from"./routing.js";import{renderSwagger as l,renderRedoc as p}from"./renderers.js";import{baseExceptionHandler as d,createResolveLater as u}from"./helpers.js";class m extends a{rootPath;title;description;version;tagsInfo;servers;contact;license;termsOfService;securitySchemes;security;openapiUrl;swaggerUrl;redocUrl;middleware;exceptionHandler;_rootPathRegex;_openapi;constructor(e){super(e),this.rootPath=e.rootPath??"/",this._rootPathRegex=new RegExp("^"+this.rootPath),this.title=e.title??"Workery API",this.description=e.description??"",this.version=e.version??"0.1.0",this.tagsInfo=e.tagsInfo??[],this.servers=[{url:this.rootPath},...e.servers??[]],this.contact=e.contact,this.license=e.license,this.termsOfService=e.termsOfService,this.securitySchemes=e.securitySchemes??{},this.security=e.security??Object.keys(this.securitySchemes).map((e=>({[e]:[]}))),this.openapiUrl=null===e.openapiUrl?null:e.openapiUrl??"/openapi.json",this.swaggerUrl=null===e.swaggerUrl?null:e.swaggerUrl??"/docs",this.redocUrl=null===e.redocUrl?null:e.redocUrl??"/redoc",this.middleware=e.middleware??[],this.routeMatcher.set(null,{middleware:this.middleware}),this.exceptionHandler=e.exceptionHandler??d,this.openapiUrl&&(this.get(this.openapiUrl,{includeInSchema:!1,responseClass:i,parameters:{},handle:()=>this.openapi()}),this.swaggerUrl&&this.get(this.swaggerUrl,{includeInSchema:!1,responseClass:o,parameters:{},handle:()=>l(n(this.rootPath+this.openapiUrl),{title:this.title})}),this.redocUrl&&this.get(this.redocUrl,{includeInSchema:!1,responseClass:o,parameters:{},handle:()=>p(n(this.rootPath+this.openapiUrl),{title:this.title})}))}include(e,t){for(const s of t.routeMatcher){const r=new h({...s,path:e+s.path,security:s.security??this.security});this.routeMatcher.push(r),this.routeMatcher.set(e,{middleware:t.middleware})}}openapi(){if(this._openapi)return this._openapi;const s=new e;for(const e of this.routeMatcher)e.includeInSchema&&s.registerPath(e.openapi());const r=new t(s.definitions);return this._openapi=r.generateDocument({openapi:"3.1.0",info:{title:this.title,version:this.version,description:this.description,contact:this.contact,license:this.license,termsOfService:this.termsOfService},servers:this.servers,tags:this.tagsInfo}),this._openapi.components=this._openapi.components||{},this._openapi.components.securitySchemes=this.securitySchemes,this._openapi}async handle(e){const{req:t}=e;try{const o=new URL(t.url),[a,n,h]=this.routeMatcher.match(t.method,o.pathname.replace(this._rootPathRegex,"")),l=s.parse(t.headers.get("Cookie")??""),p=c(o.searchParams),d={};let m;m=void 0===a?async()=>new i({detail:"Not Found"},{status:404}):null===a?async()=>new i({detail:"Method Not Allowed"},{status:405,headers:n}):async()=>{const[t,s]=u();try{const o=await r(a.parameters,{baseArgs:e,later:s,rawParameters:{params:n,queries:p,cookies:l}});let h;return o.success?(h=await a.handle({...e,...o.args}),h instanceof Response||(h=new a.responseClass(h,{status:a.statusCode}))):h=new i({detail:o.errors},{status:422}),t(h),h}catch(e){if(e instanceof Response)return t(e),e;throw e}},d[h.length-1]=m;for(let t=h.length-1;t>=0;t--)m=async()=>await h[t].handle(e,d[t]),d[t-1]=m;return await m()}catch(t){return t instanceof Response?t:await this.exceptionHandler(e,t)}}fetch=(e,t,s)=>this.handle({req:e,env:t,ctx:s})}export{m as App};