@alessiofrittoli/next-api
Version:
Next.js API utility library
1 lines • 3.22 kB
JavaScript
var server=require('next/server'),slash=require('@alessiofrittoli/url-utils/slash'),exception=require('@alessiofrittoli/exception'),utils=require('@alessiofrittoli/stream-reader/utils'),generators=require('@alessiofrittoli/web-utils/generators'),code=require('@alessiofrittoli/exception/code');var y=async d=>{let e=d?.headers||await(await import('next/headers')).headers(),t=e.get("X-Forwarded-For")?.replace(/\s/g,"").split(",").at(-1),s=e.get("X-Real-Ip")?.replace(/\s/g,"").split(",").at(-1);return t||s||null};var h={Exception:code.ErrorCode};var a=class a extends server.NextResponse{constructor(e={}){let{body:t,init:s,request:n,cors:r}=e;r&&a.cors(n,typeof r!="boolean"?r:void 0),super(t,a.CorsInit(s));}static json(e,t){return super.json(e,this.CorsInit(t))}static successJson(e,t){let s={message:e};return this.json(s,t)}static errorJson(e,t={}){let s=t.status||e.status||500;return t.status=s,e.status=s,this.json(e,t)}static stream(e,t){return new Response(generators.isGeneratorObject(e)?this.generatorToStream(e):e,this.CorsInit(t))}static emptyBody(e){return this.errorJson(new exception.Exception("Empty, invalid or locked Request Body",{code:h.Exception.EMPTY_VALUE,status:422}),e)}static cors(e,t){let s=e?.headers.get("origin")||void 0;return this.CorsOptions={...t,requestOrigin:s},this}static CorsInit(e){if(!this.CorsOptions)return e;let t=this.CorsHeaders({options:this.CorsOptions,headers:e?.headers});return this.CorsOptions=void 0,{...e,headers:t}}static CorsHeaders({options:e={},headers:t}={}){let s="*",{ALLOWED_API_ORIGINS:n}=process.env,{requestOrigin:r}=e,p=e.methods||this.CorsAllowedMethods,o=e.origin||n||s;typeof o=="string"&&o!==s&&(o=o.replace(/\s/g,"").split(",").filter(Boolean).map(slash.removeTrailingSlash)),r&&(o.includes(slash.removeTrailingSlash(r))||o===s)&&(o=r);let i=new Headers(t);i.set("Access-Control-Allow-Origin",o.toString()),typeof e.credentials<"u"&&i.set("Access-Control-Allow-Credentials",e.credentials.toString());let c=this.CorsAllowedHeaders.concat(e.headers||[]),f=this.CorsExposedHeaders.concat(e.exposedHeaders||[]);return c.length>0&&i.set("Access-Control-Allow-Headers",c.join(", ")),f.length>0&&i.set("Access-Control-Expose-Headers",f.join(", ")),p.length>0&&i.set("Access-Control-Allow-Methods",p.join(", ")),i}};a.CorsAllowedMethods=["GET","POST","PUT","PATCH","DELETE","OPTIONS","HEAD"],a.CorsAllowedHeaders=["Accept","Accept-Version","Authorization","Content-Length","Content-MD5","Content-Type","Date","X-Api-Key","X-Api-Version","X-CSRF-Token","X-Locale","X-Requested-With"],a.CorsExposedHeaders=["Connection","Retry-After","Keep-Alive","Date"],a.generatorToStream=utils.generatorToReadableStream;var l=a;var u=null,m=new Map,N=async(d,e,t,s,n,r)=>{if(!t||t===1/0)return e(d);let p=await y(d)||"::1";s&&(u&&(clearTimeout(u),u=null),u=setTimeout(()=>{m.delete(p);},s*1e3));let o=(m.get(p)||0)+1;if(m.set(p,o),o<=t)return e(d);let i={status:429,headers:s?{"Retry-After":s.toString(),"X-Max-Requests":t.toString()}:void 0},c=n?{...typeof n=="object"?n:void 0,exposedHeaders:[...typeof n=="object"?n.exposedHeaders||[]:[],"X-Max-Requests"]}:void 0;return r&&await r(p,m),new l({body:null,init:i,cors:c,request:d})};exports.withRateLimit=N;
;