better-call 0.2.3-beta.1 → 0.2.3-beta.11
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/dist/client.cjs +38 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +13 -1
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +903 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +845 -1
- package/dist/index.js.map +1 -1
- package/dist/{router-D99Yh0mM.d.cts → router-DhpmtodN.d.cts} +2 -2
- package/dist/{router-D99Yh0mM.d.ts → router-DhpmtodN.d.ts} +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,904 @@
|
|
|
1
|
-
"use strict";var G=Object.create;var R=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,Z=Object.prototype.hasOwnProperty;var J=(t,e,n)=>e in t?R(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var X=(t,e)=>{for(var n in e)R(t,n,{get:e[n],enumerable:!0})},L=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Y(e))!Z.call(t,s)&&s!==n&&R(t,s,{get:()=>e[s],enumerable:!(r=z(e,s))||r.enumerable});return t};var ee=(t,e,n)=>(n=t!=null?G(V(t)):{},L(e||!t||!t.__esModule?R(n,"default",{value:t,enumerable:!0}):n,t)),te=t=>L(R({},"__esModule",{value:!0}),t);var T=(t,e,n)=>J(t,typeof e!="symbol"?e+"":e,n);var ce={};X(ce,{APIError:()=>l,createEndpoint:()=>E,createEndpointCreator:()=>ie,createMiddleware:()=>de,createMiddlewareCreator:()=>pe,createRouter:()=>ae,getBody:()=>A,getCookie:()=>S,getRequest:()=>U,getSignedCookie:()=>k,parse:()=>P,parseSigned:()=>w,serialize:()=>O,serializeSigned:()=>C,setCookie:()=>_,setResponse:()=>D,setSignedCookie:()=>b,shouldSerialize:()=>H,statusCode:()=>N,toNodeHandler:()=>fe});module.exports=te(ce);var K=require("zod");var l=class extends Error{constructor(n,r){super(`API Error: ${n} ${r?.message??""}`,{cause:r});T(this,"status");T(this,"body");this.status=n,this.body=r??{},this.stack="",this.name="BetterCallAPIError"}};var $=(t,e)=>({response:{body:e?.body??t,status:e?.status??200,statusText:e?.statusText??"OK",headers:e?.headers},body:t,_flag:"json"});var I={name:"HMAC",hash:"SHA-256"},j=async t=>{let e=typeof t=="string"?new TextEncoder().encode(t):t;return await crypto.subtle.importKey("raw",e,I,!1,["sign","verify"])},ne=async(t,e)=>{let n=await j(e),r=await crypto.subtle.sign(I.name,n,new TextEncoder().encode(t));return btoa(String.fromCharCode(...new Uint8Array(r)))},re=async(t,e,n)=>{try{let r=atob(t),s=new Uint8Array(r.length);for(let i=0,o=r.length;i<o;i++)s[i]=r.charCodeAt(i);return await crypto.subtle.verify(I,n,s,new TextEncoder().encode(e))}catch{return!1}},oe=/^[\w!#$%&'*.^`|~+-]+$/,se=/^[ !#-:<-[\]-~]*$/,P=(t,e)=>t.trim().split(";").reduce((r,s)=>{s=s.trim();let i=s.indexOf("=");if(i===-1)return r;let o=s.substring(0,i).trim();if(e&&e!==o||!oe.test(o))return r;let a=s.substring(i+1).trim();return a.startsWith('"')&&a.endsWith('"')&&(a=a.slice(1,-1)),se.test(a)&&(r[o]=decodeURIComponent(a)),r},{}),w=async(t,e,n)=>{let r={},s=await j(e);for(let[i,o]of Object.entries(P(t,n))){let a=o.lastIndexOf(".");if(a<1)continue;let p=o.substring(0,a),d=o.substring(a+1);if(d.length!==44||!d.endsWith("="))continue;let u=await re(d,p,s);r[i]=u?p:!1}return r},v=(t,e,n={})=>{let r=`${t}=${e}`;if(t.startsWith("__Secure-")&&!n.secure&&(n.secure=!0),t.startsWith("__Host-")&&(n.secure||(n.secure=!0),n.path!=="/"&&(n.path="/"),n.domain&&(n.domain=void 0)),n&&typeof n.maxAge=="number"&&n.maxAge>=0){if(n.maxAge>3456e4)throw new Error("Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration.");r+=`; Max-Age=${Math.floor(n.maxAge)}`}if(n.domain&&n.prefix!=="host"&&(r+=`; Domain=${n.domain}`),n.path&&(r+=`; Path=${n.path}`),n.expires){if(n.expires.getTime()-Date.now()>3456e7)throw new Error("Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future.");r+=`; Expires=${n.expires.toUTCString()}`}if(n.httpOnly&&(r+="; HttpOnly"),n.secure&&(r+="; Secure"),n.sameSite&&(r+=`; SameSite=${n.sameSite.charAt(0).toUpperCase()+n.sameSite.slice(1)}`),n.partitioned){if(!n.secure)throw new Error("Partitioned Cookie must have Secure attributes");r+="; Partitioned"}return r},O=(t,e,n)=>(e=encodeURIComponent(e),v(t,e,n)),C=async(t,e,n,r={})=>{let s=await ne(e,n);return e=`${e}.${s}`,e=encodeURIComponent(e),v(t,e,r)};var S=(t,e,n)=>{if(!t)return;let r=e;if(n)if(n==="secure")r="__Secure-"+e;else if(n==="host")r="__Host-"+e;else return;return P(t,r)[r]},_=(t,e,n,r)=>{let s;r?.prefix==="secure"?s=O("__Secure-"+e,n,{path:"/",...r,secure:!0}):r?.prefix==="host"?s=O("__Host-"+e,n,{...r,path:"/",secure:!0,domain:void 0}):s=O(e,n,{path:"/",...r}),t.append("Set-Cookie",s)},b=async(t,e,n,r,s)=>{let i;s?.prefix==="secure"?i=await C("__Secure-"+e,n,r,{path:"/",...s,secure:!0}):s?.prefix==="host"?i=await C("__Host-"+e,n,r,{...s,path:"/",secure:!0,domain:void 0}):i=await C(e,n,r,{path:"/",...s}),t.append("Set-Cookie",i)},k=async(t,e,n,r)=>{let s=t.get("cookie");if(!s)return;let i=n;return r&&(r==="secure"?i="__Secure-"+n:r==="host"&&(i="__Host-"+n)),(await w(s,e,i))[i]};function ie(t){return(e,n,r)=>E(e,{...n,use:[...n?.use||[],...t?.use||[]]},r)}function E(t,e,n){let r=new Headers,s=async(...i)=>{let o={setHeader(d,u){r.set(d,u)},setCookie(d,u,c){_(r,d,u,c)},getCookie(d,u){let f=i[0]?.headers?.get("cookie");return S(f||"",d,u)},getSignedCookie(d,u,c){let f=i[0]?.headers;if(!f)throw new TypeError("Headers are required");return k(f,u,d,c)},async setSignedCookie(d,u,c,f){await b(r,d,u,c,f)},redirect(d){return r.set("Location",d),new l("FOUND")},json:$,context:i[0]?.context||{},_flag:i[0]?._flag,responseHeader:r,path:t,...i[0]||{}};if(e.use?.length){let d={},u={};for(let c of e.use){let f=await c(o);if(f){let g=f.options?.body?f.options.body.parse(o.body):void 0;d={...d,...f},u={...u,...g}}}o={...o,body:{...u,...o.body},context:{...o.context||{},...d}}}try{let d=e.body?e.body.parse(o.body):o.body;o={...o,body:d?{...d,...o.body}:o.body},o.query=e.query?e.query.parse(o.query):o.query}catch(d){throw d instanceof K.ZodError?new l("BAD_REQUEST",{message:d.message,details:d.errors}):d}if(e.requireHeaders&&!o.headers)throw new l("BAD_REQUEST",{message:"Headers are required"});if(e.requireRequest&&!o.request)throw new l("BAD_REQUEST",{message:"Request is required"});let a=await n(o),p=a;if(a&&typeof a=="object"&&"_flag"in a)if(a._flag==="json"&&o._flag==="router"){let d=a.response.headers;Object.keys(d||{}).forEach(u=>{r.set(u,d[u])}),p=new Response(JSON.stringify(a.response.body),{status:a.response.status??200,statusText:a.response.statusText,headers:r})}else p=a.body;return p};return s.path=t,s.options=e,s.method=e.method,s.headers=r,s}var m=require("rou3");async function A(t){let e=t.headers.get("content-type")||"";if(t.body){if(e.includes("application/json"))return await t.json();if(e.includes("application/x-www-form-urlencoded")){let n=await t.formData(),r={};return n.forEach((s,i)=>{r[i]=s.toString()}),r}if(e.includes("multipart/form-data")){let n=await t.formData(),r={};return n.forEach((s,i)=>{r[i]=s}),r}return e.includes("text/plain")?await t.text():e.includes("application/octet-stream")?await t.arrayBuffer():e.includes("application/pdf")||e.includes("image/")||e.includes("video/")?await t.blob():e.includes("application/stream")||t.body instanceof ReadableStream?t.body:await t.text()}}function H(t){return typeof t=="object"&&t!==null&&!(t instanceof Blob)&&!(t instanceof FormData)}var N={OK:200,CREATED:201,ACCEPTED:202,NO_CONTENT:204,MULTIPLE_CHOICES:300,MOVED_PERMANENTLY:301,FOUND:302,SEE_OTHER:303,NOT_MODIFIED:304,TEMPORARY_REDIRECT:307,BAD_REQUEST:400,UNAUTHORIZED:401,PAYMENT_REQUIRED:402,FORBIDDEN:403,NOT_FOUND:404,METHOD_NOT_ALLOWED:405,NOT_ACCEPTABLE:406,PROXY_AUTHENTICATION_REQUIRED:407,REQUEST_TIMEOUT:408,CONFLICT:409,GONE:410,LENGTH_REQUIRED:411,PRECONDITION_FAILED:412,PAYLOAD_TOO_LARGE:413,URI_TOO_LONG:414,UNSUPPORTED_MEDIA_TYPE:415,RANGE_NOT_SATISFIABLE:416,EXPECTATION_FAILED:417,"I'M_A_TEAPOT":418,MISDIRECTED_REQUEST:421,UNPROCESSABLE_ENTITY:422,LOCKED:423,FAILED_DEPENDENCY:424,TOO_EARLY:425,UPGRADE_REQUIRED:426,PRECONDITION_REQUIRED:428,TOO_MANY_REQUESTS:429,REQUEST_HEADER_FIELDS_TOO_LARGE:431,UNAVAILABLE_FOR_LEGAL_REASONS:451,INTERNAL_SERVER_ERROR:500,NOT_IMPLEMENTED:501,BAD_GATEWAY:502,SERVICE_UNAVAILABLE:503,GATEWAY_TIMEOUT:504,HTTP_VERSION_NOT_SUPPORTED:505,VARIANT_ALSO_NEGOTIATES:506,INSUFFICIENT_STORAGE:507,LOOP_DETECTED:508,NOT_EXTENDED:510,NETWORK_AUTHENTICATION_REQUIRED:511};var ae=(t,e)=>{let n=Object.values(t),r=(0,m.createRouter)();for(let o of n)if(Array.isArray(o.options?.method))for(let a of o.options.method)(0,m.addRoute)(r,a,o.path,o);else(0,m.addRoute)(r,o.options.method,o.path,o);let s=(0,m.createRouter)();for(let o of e?.routerMiddleware||[])(0,m.addRoute)(s,"*",o.path,o.middleware);let i=async o=>{let a=new URL(o.url),p=a.pathname;if(e?.basePath&&(p=p.split(e.basePath)[1]),!p?.length)return e?.onError?.(new l("NOT_FOUND")),console.warn(`[better-call]: Make sure the URL has the basePath (${e?.basePath}).`),new Response(null,{status:404,statusText:"Not Found"});let d=o.method,u=(0,m.findRoute)(r,d,p),c=u?.data,f=await A(o),g=o.headers,M=Object.fromEntries(a.searchParams),q=(0,m.findAllRoutes)(s,"*",p);if(!c)return new Response(null,{status:404,statusText:"Not Found"});try{let y={};if(q?.length)for(let B of q){let W=B.data,h=await W({path:p,method:d,headers:g,params:B?.params,request:o,body:f,query:M,context:{...e?.extraContext}});if(h instanceof Response)return h;if(h?._flag==="json")return new Response(JSON.stringify(h),{headers:h.headers});h&&(y={...h,...y})}let x=await c({path:p,method:d,headers:g,params:u?.params,request:o,body:f,query:M,_flag:"router",context:{...y,...e?.extraContext}});if(x instanceof Response)return x;let F=H(x)?JSON.stringify(x):x;return new Response(F,{headers:c.headers})}catch(y){if(e?.onError){let x=await e.onError(y);if(x instanceof Response)return x}if(y instanceof l)return new Response(y.body?JSON.stringify(y.body):null,{status:N[y.status],statusText:y.status,headers:c.headers});if(e?.throwError)throw y;return new Response(null,{status:500,statusText:"Internal Server Error"})}};return{handler:async o=>{let a=e?.transformRequest?await e.transformRequest(o):o,p=await i(a);return e?.transformResponse?await e.transformResponse(p):p},endpoints:t}};function de(t,e){if(typeof t=="function")return E("*",{method:"*"},t);if(!e)throw new Error("Middleware handler is required");return E("*",{...t,method:"*"},e)}var pe=t=>{function e(n,r){if(typeof n=="function")return E("*",{method:"*"},n);if(!r)throw new Error("Middleware handler is required");return E("*",{...n,method:"*"},r)}return e};var ke=require("zod");var Me=require("http");var He=require("http"),Q=ee(require("set-cookie-parser"),1);function ue(t,e){let n=t.headers;if(!n["content-type"])return null;let r=Number(n["content-length"]);if(t.httpVersionMajor===1&&isNaN(r)&&n["transfer-encoding"]==null||r===0)return null;let s=r;if(e){if(!s)s=e;else if(s>e)throw Error(`Received content-length of ${s}, but only accept up to ${e} bytes.`)}if(t.destroyed){let a=new ReadableStream;return a.cancel(),a}let i=0,o=!1;return new ReadableStream({start(a){t.on("error",p=>{o=!0,a.error(p)}),t.on("end",()=>{o||a.close()}),t.on("data",p=>{if(!o){if(i+=p.length,i>s){o=!0,a.error(new Error(`request body size exceeded ${r?"'content-length'":"BODY_SIZE_LIMIT"} of ${s}`));return}a.enqueue(p),(a.desiredSize===null||a.desiredSize<=0)&&t.pause()}})},pull(){t.resume()},cancel(a){o=!0,t.destroy(a)}})}function U({request:t,base:e,bodySizeLimit:n}){return new Request(e+t.url,{duplex:"half",method:t.method,body:ue(t,n),headers:t.headers})}async function D(t,e){for(let[i,o]of e.headers)try{t.setHeader(i,i==="set-cookie"?Q.splitCookiesString(e.headers.get(i)):o)}catch(a){t.getHeaderNames().forEach(p=>t.removeHeader(p)),t.writeHead(500).end(String(a));return}if(t.writeHead(e.status),!e.body){t.end();return}if(e.body.locked){t.end("Fatal error: Response body is locked. This can happen when the response was already read (for example through 'response.json()' or 'response.text()').");return}let n=e.body.getReader();if(t.destroyed){n.cancel();return}let r=i=>{t.off("close",r),t.off("error",r),n.cancel(i).catch(()=>{}),i&&t.destroy(i)};t.on("close",r),t.on("error",r),s();async function s(){try{for(;;){let{done:i,value:o}=await n.read();if(i)break;if(!t.write(o)){t.once("drain",s);return}}t.end()}catch(i){r(i instanceof Error?i:new Error(String(i)))}}}function fe(t){return async(e,n)=>{let s=`${e.connection?.encrypted?"https":"http"}://${e.headers[":authority"]||e.headers.host}`,i=await t(U({base:s,request:e}));D(n,i)}}0&&(module.exports={APIError,createEndpoint,createEndpointCreator,createMiddleware,createMiddlewareCreator,createRouter,getBody,getCookie,getRequest,getSignedCookie,parse,parseSigned,serialize,serializeSigned,setCookie,setResponse,setSignedCookie,shouldSerialize,statusCode,toNodeHandler});
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
31
|
+
|
|
32
|
+
// src/index.ts
|
|
33
|
+
var src_exports = {};
|
|
34
|
+
__export(src_exports, {
|
|
35
|
+
APIError: () => APIError,
|
|
36
|
+
createEndpoint: () => createEndpoint,
|
|
37
|
+
createEndpointCreator: () => createEndpointCreator,
|
|
38
|
+
createMiddleware: () => createMiddleware,
|
|
39
|
+
createMiddlewareCreator: () => createMiddlewareCreator,
|
|
40
|
+
createRouter: () => createRouter,
|
|
41
|
+
getBody: () => getBody,
|
|
42
|
+
getCookie: () => getCookie,
|
|
43
|
+
getRequest: () => getRequest,
|
|
44
|
+
getSignedCookie: () => getSignedCookie,
|
|
45
|
+
parse: () => parse,
|
|
46
|
+
parseSigned: () => parseSigned,
|
|
47
|
+
serialize: () => serialize,
|
|
48
|
+
serializeSigned: () => serializeSigned,
|
|
49
|
+
setCookie: () => setCookie,
|
|
50
|
+
setResponse: () => setResponse,
|
|
51
|
+
setSignedCookie: () => setSignedCookie,
|
|
52
|
+
shouldSerialize: () => shouldSerialize,
|
|
53
|
+
statusCode: () => statusCode,
|
|
54
|
+
toNodeHandler: () => toNodeHandler
|
|
55
|
+
});
|
|
56
|
+
module.exports = __toCommonJS(src_exports);
|
|
57
|
+
|
|
58
|
+
// src/endpoint.ts
|
|
59
|
+
var import_zod = require("zod");
|
|
60
|
+
|
|
61
|
+
// src/error.ts
|
|
62
|
+
var APIError = class extends Error {
|
|
63
|
+
constructor(status, body) {
|
|
64
|
+
super(`API Error: ${status} ${body?.message ?? ""}`, {
|
|
65
|
+
cause: body
|
|
66
|
+
});
|
|
67
|
+
__publicField(this, "status");
|
|
68
|
+
__publicField(this, "body");
|
|
69
|
+
this.status = status;
|
|
70
|
+
this.body = body ?? {};
|
|
71
|
+
this.stack = "";
|
|
72
|
+
this.name = "BetterCallAPIError";
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// src/helper.ts
|
|
77
|
+
var json = (body, option) => {
|
|
78
|
+
return {
|
|
79
|
+
response: {
|
|
80
|
+
body: option?.body ?? body,
|
|
81
|
+
status: option?.status ?? 200,
|
|
82
|
+
statusText: option?.statusText ?? "OK",
|
|
83
|
+
headers: option?.headers
|
|
84
|
+
},
|
|
85
|
+
body,
|
|
86
|
+
_flag: "json"
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// src/cookie.ts
|
|
91
|
+
var algorithm = { name: "HMAC", hash: "SHA-256" };
|
|
92
|
+
var getCryptoKey = async (secret) => {
|
|
93
|
+
const secretBuf = typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
|
|
94
|
+
return await crypto.subtle.importKey("raw", secretBuf, algorithm, false, ["sign", "verify"]);
|
|
95
|
+
};
|
|
96
|
+
var makeSignature = async (value, secret) => {
|
|
97
|
+
const key = await getCryptoKey(secret);
|
|
98
|
+
const signature = await crypto.subtle.sign(
|
|
99
|
+
algorithm.name,
|
|
100
|
+
key,
|
|
101
|
+
new TextEncoder().encode(value)
|
|
102
|
+
);
|
|
103
|
+
return btoa(String.fromCharCode(...new Uint8Array(signature)));
|
|
104
|
+
};
|
|
105
|
+
var verifySignature = async (base64Signature, value, secret) => {
|
|
106
|
+
try {
|
|
107
|
+
const signatureBinStr = atob(base64Signature);
|
|
108
|
+
const signature = new Uint8Array(signatureBinStr.length);
|
|
109
|
+
for (let i = 0, len = signatureBinStr.length; i < len; i++) {
|
|
110
|
+
signature[i] = signatureBinStr.charCodeAt(i);
|
|
111
|
+
}
|
|
112
|
+
return await crypto.subtle.verify(
|
|
113
|
+
algorithm,
|
|
114
|
+
secret,
|
|
115
|
+
signature,
|
|
116
|
+
new TextEncoder().encode(value)
|
|
117
|
+
);
|
|
118
|
+
} catch (e) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
var validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/;
|
|
123
|
+
var validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/;
|
|
124
|
+
var parse = (cookie, name) => {
|
|
125
|
+
const pairs = cookie.trim().split(";");
|
|
126
|
+
return pairs.reduce((parsedCookie, pairStr) => {
|
|
127
|
+
pairStr = pairStr.trim();
|
|
128
|
+
const valueStartPos = pairStr.indexOf("=");
|
|
129
|
+
if (valueStartPos === -1) {
|
|
130
|
+
return parsedCookie;
|
|
131
|
+
}
|
|
132
|
+
const cookieName = pairStr.substring(0, valueStartPos).trim();
|
|
133
|
+
if (name && name !== cookieName || !validCookieNameRegEx.test(cookieName)) {
|
|
134
|
+
return parsedCookie;
|
|
135
|
+
}
|
|
136
|
+
let cookieValue = pairStr.substring(valueStartPos + 1).trim();
|
|
137
|
+
if (cookieValue.startsWith('"') && cookieValue.endsWith('"')) {
|
|
138
|
+
cookieValue = cookieValue.slice(1, -1);
|
|
139
|
+
}
|
|
140
|
+
if (validCookieValueRegEx.test(cookieValue)) {
|
|
141
|
+
parsedCookie[cookieName] = decodeURIComponent(cookieValue);
|
|
142
|
+
}
|
|
143
|
+
return parsedCookie;
|
|
144
|
+
}, {});
|
|
145
|
+
};
|
|
146
|
+
var parseSigned = async (cookie, secret, name) => {
|
|
147
|
+
const parsedCookie = {};
|
|
148
|
+
const secretKey = await getCryptoKey(secret);
|
|
149
|
+
for (const [key, value] of Object.entries(parse(cookie, name))) {
|
|
150
|
+
const signatureStartPos = value.lastIndexOf(".");
|
|
151
|
+
if (signatureStartPos < 1) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const signedValue = value.substring(0, signatureStartPos);
|
|
155
|
+
const signature = value.substring(signatureStartPos + 1);
|
|
156
|
+
if (signature.length !== 44 || !signature.endsWith("=")) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const isVerified = await verifySignature(signature, signedValue, secretKey);
|
|
160
|
+
parsedCookie[key] = isVerified ? signedValue : false;
|
|
161
|
+
}
|
|
162
|
+
return parsedCookie;
|
|
163
|
+
};
|
|
164
|
+
var _serialize = (name, value, opt = {}) => {
|
|
165
|
+
let cookie = `${name}=${value}`;
|
|
166
|
+
if (name.startsWith("__Secure-") && !opt.secure) {
|
|
167
|
+
opt.secure = true;
|
|
168
|
+
}
|
|
169
|
+
if (name.startsWith("__Host-")) {
|
|
170
|
+
if (!opt.secure) {
|
|
171
|
+
opt.secure = true;
|
|
172
|
+
}
|
|
173
|
+
if (opt.path !== "/") {
|
|
174
|
+
opt.path = "/";
|
|
175
|
+
}
|
|
176
|
+
if (opt.domain) {
|
|
177
|
+
opt.domain = void 0;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (opt && typeof opt.maxAge === "number" && opt.maxAge >= 0) {
|
|
181
|
+
if (opt.maxAge > 3456e4) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
"Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration."
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
cookie += `; Max-Age=${Math.floor(opt.maxAge)}`;
|
|
187
|
+
}
|
|
188
|
+
if (opt.domain && opt.prefix !== "host") {
|
|
189
|
+
cookie += `; Domain=${opt.domain}`;
|
|
190
|
+
}
|
|
191
|
+
if (opt.path) {
|
|
192
|
+
cookie += `; Path=${opt.path}`;
|
|
193
|
+
}
|
|
194
|
+
if (opt.expires) {
|
|
195
|
+
if (opt.expires.getTime() - Date.now() > 3456e7) {
|
|
196
|
+
throw new Error(
|
|
197
|
+
"Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future."
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
cookie += `; Expires=${opt.expires.toUTCString()}`;
|
|
201
|
+
}
|
|
202
|
+
if (opt.httpOnly) {
|
|
203
|
+
cookie += "; HttpOnly";
|
|
204
|
+
}
|
|
205
|
+
if (opt.secure) {
|
|
206
|
+
cookie += "; Secure";
|
|
207
|
+
}
|
|
208
|
+
if (opt.sameSite) {
|
|
209
|
+
cookie += `; SameSite=${opt.sameSite.charAt(0).toUpperCase() + opt.sameSite.slice(1)}`;
|
|
210
|
+
}
|
|
211
|
+
if (opt.partitioned) {
|
|
212
|
+
if (!opt.secure) {
|
|
213
|
+
throw new Error("Partitioned Cookie must have Secure attributes");
|
|
214
|
+
}
|
|
215
|
+
cookie += "; Partitioned";
|
|
216
|
+
}
|
|
217
|
+
return cookie;
|
|
218
|
+
};
|
|
219
|
+
var serialize = (name, value, opt) => {
|
|
220
|
+
value = encodeURIComponent(value);
|
|
221
|
+
return _serialize(name, value, opt);
|
|
222
|
+
};
|
|
223
|
+
var serializeSigned = async (name, value, secret, opt = {}) => {
|
|
224
|
+
const signature = await makeSignature(value, secret);
|
|
225
|
+
value = `${value}.${signature}`;
|
|
226
|
+
value = encodeURIComponent(value);
|
|
227
|
+
return _serialize(name, value, opt);
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// src/cookie-utils.ts
|
|
231
|
+
var getCookie = (cookie, key, prefix) => {
|
|
232
|
+
if (!cookie) {
|
|
233
|
+
return void 0;
|
|
234
|
+
}
|
|
235
|
+
let finalKey = key;
|
|
236
|
+
if (prefix) {
|
|
237
|
+
if (prefix === "secure") {
|
|
238
|
+
finalKey = "__Secure-" + key;
|
|
239
|
+
} else if (prefix === "host") {
|
|
240
|
+
finalKey = "__Host-" + key;
|
|
241
|
+
} else {
|
|
242
|
+
return void 0;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const obj = parse(cookie, finalKey);
|
|
246
|
+
return obj[finalKey];
|
|
247
|
+
};
|
|
248
|
+
var setCookie = (header, name, value, opt) => {
|
|
249
|
+
let cookie;
|
|
250
|
+
if (opt?.prefix === "secure") {
|
|
251
|
+
cookie = serialize("__Secure-" + name, value, { path: "/", ...opt, secure: true });
|
|
252
|
+
} else if (opt?.prefix === "host") {
|
|
253
|
+
cookie = serialize("__Host-" + name, value, {
|
|
254
|
+
...opt,
|
|
255
|
+
path: "/",
|
|
256
|
+
secure: true,
|
|
257
|
+
domain: void 0
|
|
258
|
+
});
|
|
259
|
+
} else {
|
|
260
|
+
cookie = serialize(name, value, { path: "/", ...opt });
|
|
261
|
+
}
|
|
262
|
+
header.append("Set-Cookie", cookie);
|
|
263
|
+
};
|
|
264
|
+
var setSignedCookie = async (header, name, value, secret, opt) => {
|
|
265
|
+
let cookie;
|
|
266
|
+
if (opt?.prefix === "secure") {
|
|
267
|
+
cookie = await serializeSigned("__Secure-" + name, value, secret, {
|
|
268
|
+
path: "/",
|
|
269
|
+
...opt,
|
|
270
|
+
secure: true
|
|
271
|
+
});
|
|
272
|
+
} else if (opt?.prefix === "host") {
|
|
273
|
+
cookie = await serializeSigned("__Host-" + name, value, secret, {
|
|
274
|
+
...opt,
|
|
275
|
+
path: "/",
|
|
276
|
+
secure: true,
|
|
277
|
+
domain: void 0
|
|
278
|
+
});
|
|
279
|
+
} else {
|
|
280
|
+
cookie = await serializeSigned(name, value, secret, { path: "/", ...opt });
|
|
281
|
+
}
|
|
282
|
+
header.append("Set-Cookie", cookie);
|
|
283
|
+
};
|
|
284
|
+
var getSignedCookie = async (header, secret, key, prefix) => {
|
|
285
|
+
const cookie = header.get("cookie");
|
|
286
|
+
if (!cookie) {
|
|
287
|
+
return void 0;
|
|
288
|
+
}
|
|
289
|
+
let finalKey = key;
|
|
290
|
+
if (prefix) {
|
|
291
|
+
if (prefix === "secure") {
|
|
292
|
+
finalKey = "__Secure-" + key;
|
|
293
|
+
} else if (prefix === "host") {
|
|
294
|
+
finalKey = "__Host-" + key;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const obj = await parseSigned(cookie, secret, finalKey);
|
|
298
|
+
return obj[finalKey];
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// src/endpoint.ts
|
|
302
|
+
function createEndpointCreator(opts) {
|
|
303
|
+
return (path, options, handler) => {
|
|
304
|
+
return createEndpoint(
|
|
305
|
+
path,
|
|
306
|
+
{
|
|
307
|
+
...options,
|
|
308
|
+
use: [...options?.use || [], ...opts?.use || []]
|
|
309
|
+
},
|
|
310
|
+
handler
|
|
311
|
+
);
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function createEndpoint(path, options, handler) {
|
|
315
|
+
const responseHeader = new Headers();
|
|
316
|
+
const handle = async (...ctx) => {
|
|
317
|
+
let internalCtx = {
|
|
318
|
+
setHeader(key, value) {
|
|
319
|
+
responseHeader.set(key, value);
|
|
320
|
+
},
|
|
321
|
+
setCookie(key, value, options2) {
|
|
322
|
+
setCookie(responseHeader, key, value, options2);
|
|
323
|
+
},
|
|
324
|
+
getCookie(key, prefix) {
|
|
325
|
+
const header = ctx[0]?.headers;
|
|
326
|
+
const cookieH = header?.get("cookie");
|
|
327
|
+
const cookie = getCookie(cookieH || "", key, prefix);
|
|
328
|
+
return cookie;
|
|
329
|
+
},
|
|
330
|
+
getSignedCookie(key, secret, prefix) {
|
|
331
|
+
const header = ctx[0]?.headers;
|
|
332
|
+
if (!header) {
|
|
333
|
+
throw new TypeError("Headers are required");
|
|
334
|
+
}
|
|
335
|
+
const cookie = getSignedCookie(header, secret, key, prefix);
|
|
336
|
+
return cookie;
|
|
337
|
+
},
|
|
338
|
+
async setSignedCookie(key, value, secret, options2) {
|
|
339
|
+
await setSignedCookie(responseHeader, key, value, secret, options2);
|
|
340
|
+
},
|
|
341
|
+
redirect(url) {
|
|
342
|
+
responseHeader.set("Location", url);
|
|
343
|
+
return new APIError("FOUND");
|
|
344
|
+
},
|
|
345
|
+
json,
|
|
346
|
+
context: ctx[0]?.context || {},
|
|
347
|
+
_flag: ctx[0]?._flag,
|
|
348
|
+
responseHeader,
|
|
349
|
+
path,
|
|
350
|
+
...ctx[0] || {}
|
|
351
|
+
};
|
|
352
|
+
if (options.use?.length) {
|
|
353
|
+
let middlewareContexts = {};
|
|
354
|
+
let middlewareBody = {};
|
|
355
|
+
for (const middleware of options.use) {
|
|
356
|
+
if (typeof middleware !== "function") {
|
|
357
|
+
console.warn("Middleware is not a function", {
|
|
358
|
+
middleware
|
|
359
|
+
});
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
const res2 = await middleware(internalCtx);
|
|
363
|
+
if (res2) {
|
|
364
|
+
const body = res2.options?.body ? res2.options.body.parse(internalCtx.body) : void 0;
|
|
365
|
+
middlewareContexts = {
|
|
366
|
+
...middlewareContexts,
|
|
367
|
+
...res2
|
|
368
|
+
};
|
|
369
|
+
middlewareBody = {
|
|
370
|
+
...middlewareBody,
|
|
371
|
+
...body
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
internalCtx = {
|
|
376
|
+
...internalCtx,
|
|
377
|
+
body: {
|
|
378
|
+
...middlewareBody,
|
|
379
|
+
...internalCtx.body
|
|
380
|
+
},
|
|
381
|
+
context: {
|
|
382
|
+
...internalCtx.context || {},
|
|
383
|
+
...middlewareContexts
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
const body = options.body ? options.body.parse(internalCtx.body) : internalCtx.body;
|
|
389
|
+
internalCtx = {
|
|
390
|
+
...internalCtx,
|
|
391
|
+
body: body ? {
|
|
392
|
+
...body,
|
|
393
|
+
...internalCtx.body
|
|
394
|
+
} : internalCtx.body
|
|
395
|
+
};
|
|
396
|
+
internalCtx.query = options.query ? options.query.parse(internalCtx.query) : internalCtx.query;
|
|
397
|
+
} catch (e) {
|
|
398
|
+
if (e instanceof import_zod.ZodError) {
|
|
399
|
+
throw new APIError("BAD_REQUEST", {
|
|
400
|
+
message: e.message,
|
|
401
|
+
details: e.errors
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
throw e;
|
|
405
|
+
}
|
|
406
|
+
if (options.requireHeaders && !internalCtx.headers) {
|
|
407
|
+
throw new APIError("BAD_REQUEST", {
|
|
408
|
+
message: "Headers are required"
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
if (options.requireRequest && !internalCtx.request) {
|
|
412
|
+
throw new APIError("BAD_REQUEST", {
|
|
413
|
+
message: "Request is required"
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
let res = await handler(internalCtx);
|
|
417
|
+
let actualResponse = res;
|
|
418
|
+
if (res && typeof res === "object" && "_flag" in res) {
|
|
419
|
+
if (res._flag === "json" && internalCtx._flag === "router") {
|
|
420
|
+
const h = res.response.headers;
|
|
421
|
+
Object.keys(h || {}).forEach((key) => {
|
|
422
|
+
responseHeader.set(key, h[key]);
|
|
423
|
+
});
|
|
424
|
+
actualResponse = new Response(JSON.stringify(res.response.body), {
|
|
425
|
+
status: res.response.status ?? 200,
|
|
426
|
+
statusText: res.response.statusText,
|
|
427
|
+
headers: responseHeader
|
|
428
|
+
});
|
|
429
|
+
} else {
|
|
430
|
+
actualResponse = res.body;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return actualResponse;
|
|
434
|
+
};
|
|
435
|
+
handle.path = path;
|
|
436
|
+
handle.options = options;
|
|
437
|
+
handle.method = options.method;
|
|
438
|
+
handle.headers = responseHeader;
|
|
439
|
+
return handle;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// src/router.ts
|
|
443
|
+
var import_rou3 = require("rou3");
|
|
444
|
+
|
|
445
|
+
// src/utils.ts
|
|
446
|
+
async function getBody(request) {
|
|
447
|
+
const contentType = request.headers.get("content-type") || "";
|
|
448
|
+
if (!request.body) {
|
|
449
|
+
return void 0;
|
|
450
|
+
}
|
|
451
|
+
if (contentType.includes("application/json")) {
|
|
452
|
+
return await request.json();
|
|
453
|
+
}
|
|
454
|
+
if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
455
|
+
const formData = await request.formData();
|
|
456
|
+
const result = {};
|
|
457
|
+
formData.forEach((value, key) => {
|
|
458
|
+
result[key] = value.toString();
|
|
459
|
+
});
|
|
460
|
+
return result;
|
|
461
|
+
}
|
|
462
|
+
if (contentType.includes("multipart/form-data")) {
|
|
463
|
+
const formData = await request.formData();
|
|
464
|
+
const result = {};
|
|
465
|
+
formData.forEach((value, key) => {
|
|
466
|
+
result[key] = value;
|
|
467
|
+
});
|
|
468
|
+
return result;
|
|
469
|
+
}
|
|
470
|
+
if (contentType.includes("text/plain")) {
|
|
471
|
+
return await request.text();
|
|
472
|
+
}
|
|
473
|
+
if (contentType.includes("application/octet-stream")) {
|
|
474
|
+
return await request.arrayBuffer();
|
|
475
|
+
}
|
|
476
|
+
if (contentType.includes("application/pdf") || contentType.includes("image/") || contentType.includes("video/")) {
|
|
477
|
+
const blob = await request.blob();
|
|
478
|
+
return blob;
|
|
479
|
+
}
|
|
480
|
+
if (contentType.includes("application/stream") || request.body instanceof ReadableStream) {
|
|
481
|
+
return request.body;
|
|
482
|
+
}
|
|
483
|
+
return await request.text();
|
|
484
|
+
}
|
|
485
|
+
function shouldSerialize(body) {
|
|
486
|
+
return typeof body === "object" && body !== null && !(body instanceof Blob) && !(body instanceof FormData);
|
|
487
|
+
}
|
|
488
|
+
var statusCode = {
|
|
489
|
+
OK: 200,
|
|
490
|
+
CREATED: 201,
|
|
491
|
+
ACCEPTED: 202,
|
|
492
|
+
NO_CONTENT: 204,
|
|
493
|
+
MULTIPLE_CHOICES: 300,
|
|
494
|
+
MOVED_PERMANENTLY: 301,
|
|
495
|
+
FOUND: 302,
|
|
496
|
+
SEE_OTHER: 303,
|
|
497
|
+
NOT_MODIFIED: 304,
|
|
498
|
+
TEMPORARY_REDIRECT: 307,
|
|
499
|
+
BAD_REQUEST: 400,
|
|
500
|
+
UNAUTHORIZED: 401,
|
|
501
|
+
PAYMENT_REQUIRED: 402,
|
|
502
|
+
FORBIDDEN: 403,
|
|
503
|
+
NOT_FOUND: 404,
|
|
504
|
+
METHOD_NOT_ALLOWED: 405,
|
|
505
|
+
NOT_ACCEPTABLE: 406,
|
|
506
|
+
PROXY_AUTHENTICATION_REQUIRED: 407,
|
|
507
|
+
REQUEST_TIMEOUT: 408,
|
|
508
|
+
CONFLICT: 409,
|
|
509
|
+
GONE: 410,
|
|
510
|
+
LENGTH_REQUIRED: 411,
|
|
511
|
+
PRECONDITION_FAILED: 412,
|
|
512
|
+
PAYLOAD_TOO_LARGE: 413,
|
|
513
|
+
URI_TOO_LONG: 414,
|
|
514
|
+
UNSUPPORTED_MEDIA_TYPE: 415,
|
|
515
|
+
RANGE_NOT_SATISFIABLE: 416,
|
|
516
|
+
EXPECTATION_FAILED: 417,
|
|
517
|
+
"I'M_A_TEAPOT": 418,
|
|
518
|
+
MISDIRECTED_REQUEST: 421,
|
|
519
|
+
UNPROCESSABLE_ENTITY: 422,
|
|
520
|
+
LOCKED: 423,
|
|
521
|
+
FAILED_DEPENDENCY: 424,
|
|
522
|
+
TOO_EARLY: 425,
|
|
523
|
+
UPGRADE_REQUIRED: 426,
|
|
524
|
+
PRECONDITION_REQUIRED: 428,
|
|
525
|
+
TOO_MANY_REQUESTS: 429,
|
|
526
|
+
REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
|
|
527
|
+
UNAVAILABLE_FOR_LEGAL_REASONS: 451,
|
|
528
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
529
|
+
NOT_IMPLEMENTED: 501,
|
|
530
|
+
BAD_GATEWAY: 502,
|
|
531
|
+
SERVICE_UNAVAILABLE: 503,
|
|
532
|
+
GATEWAY_TIMEOUT: 504,
|
|
533
|
+
HTTP_VERSION_NOT_SUPPORTED: 505,
|
|
534
|
+
VARIANT_ALSO_NEGOTIATES: 506,
|
|
535
|
+
INSUFFICIENT_STORAGE: 507,
|
|
536
|
+
LOOP_DETECTED: 508,
|
|
537
|
+
NOT_EXTENDED: 510,
|
|
538
|
+
NETWORK_AUTHENTICATION_REQUIRED: 511
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
// src/router.ts
|
|
542
|
+
var createRouter = (endpoints, config) => {
|
|
543
|
+
const _endpoints = Object.values(endpoints);
|
|
544
|
+
const router = (0, import_rou3.createRouter)();
|
|
545
|
+
for (const endpoint of _endpoints) {
|
|
546
|
+
if (Array.isArray(endpoint.options?.method)) {
|
|
547
|
+
for (const method of endpoint.options.method) {
|
|
548
|
+
(0, import_rou3.addRoute)(router, method, endpoint.path, endpoint);
|
|
549
|
+
}
|
|
550
|
+
} else {
|
|
551
|
+
(0, import_rou3.addRoute)(router, endpoint.options.method, endpoint.path, endpoint);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
const middlewareRouter = (0, import_rou3.createRouter)();
|
|
555
|
+
for (const route of config?.routerMiddleware || []) {
|
|
556
|
+
(0, import_rou3.addRoute)(middlewareRouter, "*", route.path, route.middleware);
|
|
557
|
+
}
|
|
558
|
+
const handler = async (request) => {
|
|
559
|
+
const url = new URL(request.url);
|
|
560
|
+
let path = url.pathname;
|
|
561
|
+
if (config?.basePath) {
|
|
562
|
+
path = path.split(config.basePath)[1];
|
|
563
|
+
}
|
|
564
|
+
if (!path?.length) {
|
|
565
|
+
config?.onError?.(new APIError("NOT_FOUND"));
|
|
566
|
+
console.warn(
|
|
567
|
+
`[better-call]: Make sure the URL has the basePath (${config?.basePath}).`
|
|
568
|
+
);
|
|
569
|
+
return new Response(null, {
|
|
570
|
+
status: 404,
|
|
571
|
+
statusText: "Not Found"
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
const method = request.method;
|
|
575
|
+
const route = (0, import_rou3.findRoute)(router, method, path);
|
|
576
|
+
const handler2 = route?.data;
|
|
577
|
+
const body = await getBody(request);
|
|
578
|
+
const headers = request.headers;
|
|
579
|
+
const query = Object.fromEntries(url.searchParams);
|
|
580
|
+
const routerMiddleware = (0, import_rou3.findAllRoutes)(middlewareRouter, "*", path);
|
|
581
|
+
if (!handler2) {
|
|
582
|
+
return new Response(null, {
|
|
583
|
+
status: 404,
|
|
584
|
+
statusText: "Not Found"
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
try {
|
|
588
|
+
let middlewareContext = {};
|
|
589
|
+
if (routerMiddleware?.length) {
|
|
590
|
+
for (const route2 of routerMiddleware) {
|
|
591
|
+
const middleware = route2.data;
|
|
592
|
+
const res = await middleware({
|
|
593
|
+
path,
|
|
594
|
+
method,
|
|
595
|
+
headers,
|
|
596
|
+
params: route2?.params,
|
|
597
|
+
request,
|
|
598
|
+
body,
|
|
599
|
+
query,
|
|
600
|
+
context: {
|
|
601
|
+
...config?.extraContext
|
|
602
|
+
}
|
|
603
|
+
});
|
|
604
|
+
if (res instanceof Response) {
|
|
605
|
+
return res;
|
|
606
|
+
}
|
|
607
|
+
if (res?._flag === "json") {
|
|
608
|
+
return new Response(JSON.stringify(res), {
|
|
609
|
+
headers: res.headers
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
if (res) {
|
|
613
|
+
middlewareContext = {
|
|
614
|
+
...res,
|
|
615
|
+
...middlewareContext
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
const handlerRes = await handler2({
|
|
621
|
+
path,
|
|
622
|
+
method,
|
|
623
|
+
headers,
|
|
624
|
+
params: route?.params,
|
|
625
|
+
request,
|
|
626
|
+
body,
|
|
627
|
+
query,
|
|
628
|
+
_flag: "router",
|
|
629
|
+
context: {
|
|
630
|
+
...middlewareContext,
|
|
631
|
+
...config?.extraContext
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
if (handlerRes instanceof Response) {
|
|
635
|
+
return handlerRes;
|
|
636
|
+
}
|
|
637
|
+
const resBody = shouldSerialize(handlerRes) ? JSON.stringify(handlerRes) : handlerRes;
|
|
638
|
+
return new Response(resBody, {
|
|
639
|
+
headers: handler2.headers
|
|
640
|
+
});
|
|
641
|
+
} catch (e) {
|
|
642
|
+
if (config?.onError) {
|
|
643
|
+
const onErrorRes = await config.onError(e);
|
|
644
|
+
if (onErrorRes instanceof Response) {
|
|
645
|
+
return onErrorRes;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
if (e instanceof APIError) {
|
|
649
|
+
return new Response(e.body ? JSON.stringify(e.body) : null, {
|
|
650
|
+
status: statusCode[e.status],
|
|
651
|
+
statusText: e.status,
|
|
652
|
+
headers: handler2.headers
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
if (config?.throwError) {
|
|
656
|
+
throw e;
|
|
657
|
+
}
|
|
658
|
+
return new Response(null, {
|
|
659
|
+
status: 500,
|
|
660
|
+
statusText: "Internal Server Error"
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
return {
|
|
665
|
+
handler: async (request) => {
|
|
666
|
+
const onReq = await config?.onRequest?.(request);
|
|
667
|
+
if (onReq instanceof Response) {
|
|
668
|
+
return onReq;
|
|
669
|
+
}
|
|
670
|
+
const req = onReq instanceof Request ? onReq : request;
|
|
671
|
+
const res = await handler(req);
|
|
672
|
+
const onRes = await config?.onResponse?.(res);
|
|
673
|
+
if (onRes instanceof Response) {
|
|
674
|
+
return onRes;
|
|
675
|
+
}
|
|
676
|
+
return res;
|
|
677
|
+
},
|
|
678
|
+
endpoints
|
|
679
|
+
};
|
|
680
|
+
};
|
|
681
|
+
|
|
682
|
+
// src/middleware.ts
|
|
683
|
+
function createMiddleware(optionsOrHandler, handler) {
|
|
684
|
+
if (typeof optionsOrHandler === "function") {
|
|
685
|
+
return createEndpoint(
|
|
686
|
+
"*",
|
|
687
|
+
{
|
|
688
|
+
method: "*"
|
|
689
|
+
},
|
|
690
|
+
optionsOrHandler
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
if (!handler) {
|
|
694
|
+
throw new Error("Middleware handler is required");
|
|
695
|
+
}
|
|
696
|
+
const endpoint = createEndpoint(
|
|
697
|
+
"*",
|
|
698
|
+
{
|
|
699
|
+
...optionsOrHandler,
|
|
700
|
+
method: "*"
|
|
701
|
+
},
|
|
702
|
+
handler
|
|
703
|
+
);
|
|
704
|
+
return endpoint;
|
|
705
|
+
}
|
|
706
|
+
var createMiddlewareCreator = (opts) => {
|
|
707
|
+
function fn(optionsOrHandler, handler) {
|
|
708
|
+
if (typeof optionsOrHandler === "function") {
|
|
709
|
+
return createEndpoint(
|
|
710
|
+
"*",
|
|
711
|
+
{
|
|
712
|
+
method: "*"
|
|
713
|
+
},
|
|
714
|
+
optionsOrHandler
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
if (!handler) {
|
|
718
|
+
throw new Error("Middleware handler is required");
|
|
719
|
+
}
|
|
720
|
+
const endpoint = createEndpoint(
|
|
721
|
+
"*",
|
|
722
|
+
{
|
|
723
|
+
...optionsOrHandler,
|
|
724
|
+
method: "*"
|
|
725
|
+
},
|
|
726
|
+
handler
|
|
727
|
+
);
|
|
728
|
+
return endpoint;
|
|
729
|
+
}
|
|
730
|
+
return fn;
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
// src/types.ts
|
|
734
|
+
var import_zod2 = require("zod");
|
|
735
|
+
|
|
736
|
+
// src/adapter/node.ts
|
|
737
|
+
var import_node_http2 = require("http");
|
|
738
|
+
|
|
739
|
+
// src/adapter/request.ts
|
|
740
|
+
var import_node_http = require("http");
|
|
741
|
+
var set_cookie_parser = __toESM(require("set-cookie-parser"), 1);
|
|
742
|
+
function get_raw_body(req, body_size_limit) {
|
|
743
|
+
const h = req.headers;
|
|
744
|
+
if (!h["content-type"]) return null;
|
|
745
|
+
const content_length = Number(h["content-length"]);
|
|
746
|
+
if (req.httpVersionMajor === 1 && isNaN(content_length) && h["transfer-encoding"] == null || content_length === 0) {
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
let length = content_length;
|
|
750
|
+
if (body_size_limit) {
|
|
751
|
+
if (!length) {
|
|
752
|
+
length = body_size_limit;
|
|
753
|
+
} else if (length > body_size_limit) {
|
|
754
|
+
throw Error(
|
|
755
|
+
`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
if (req.destroyed) {
|
|
760
|
+
const readable = new ReadableStream();
|
|
761
|
+
readable.cancel();
|
|
762
|
+
return readable;
|
|
763
|
+
}
|
|
764
|
+
let size = 0;
|
|
765
|
+
let cancelled = false;
|
|
766
|
+
return new ReadableStream({
|
|
767
|
+
start(controller) {
|
|
768
|
+
req.on("error", (error) => {
|
|
769
|
+
cancelled = true;
|
|
770
|
+
controller.error(error);
|
|
771
|
+
});
|
|
772
|
+
req.on("end", () => {
|
|
773
|
+
if (cancelled) return;
|
|
774
|
+
controller.close();
|
|
775
|
+
});
|
|
776
|
+
req.on("data", (chunk) => {
|
|
777
|
+
if (cancelled) return;
|
|
778
|
+
size += chunk.length;
|
|
779
|
+
if (size > length) {
|
|
780
|
+
cancelled = true;
|
|
781
|
+
controller.error(
|
|
782
|
+
new Error(
|
|
783
|
+
`request body size exceeded ${content_length ? "'content-length'" : "BODY_SIZE_LIMIT"} of ${length}`
|
|
784
|
+
)
|
|
785
|
+
);
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
controller.enqueue(chunk);
|
|
789
|
+
if (controller.desiredSize === null || controller.desiredSize <= 0) {
|
|
790
|
+
req.pause();
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
},
|
|
794
|
+
pull() {
|
|
795
|
+
req.resume();
|
|
796
|
+
},
|
|
797
|
+
cancel(reason) {
|
|
798
|
+
cancelled = true;
|
|
799
|
+
req.destroy(reason);
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
function getRequest({
|
|
804
|
+
request,
|
|
805
|
+
base,
|
|
806
|
+
bodySizeLimit
|
|
807
|
+
}) {
|
|
808
|
+
return new Request(base + request.url, {
|
|
809
|
+
// @ts-expect-error
|
|
810
|
+
duplex: "half",
|
|
811
|
+
method: request.method,
|
|
812
|
+
body: get_raw_body(request, bodySizeLimit),
|
|
813
|
+
headers: request.headers
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
async function setResponse(res, response) {
|
|
817
|
+
for (const [key, value] of response.headers) {
|
|
818
|
+
try {
|
|
819
|
+
res.setHeader(
|
|
820
|
+
key,
|
|
821
|
+
key === "set-cookie" ? set_cookie_parser.splitCookiesString(response.headers.get(key)) : value
|
|
822
|
+
);
|
|
823
|
+
} catch (error) {
|
|
824
|
+
res.getHeaderNames().forEach((name) => res.removeHeader(name));
|
|
825
|
+
res.writeHead(500).end(String(error));
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
res.writeHead(response.status);
|
|
830
|
+
if (!response.body) {
|
|
831
|
+
res.end();
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
if (response.body.locked) {
|
|
835
|
+
res.end(
|
|
836
|
+
"Fatal error: Response body is locked. This can happen when the response was already read (for example through 'response.json()' or 'response.text()')."
|
|
837
|
+
);
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
const reader = response.body.getReader();
|
|
841
|
+
if (res.destroyed) {
|
|
842
|
+
reader.cancel();
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
const cancel = (error) => {
|
|
846
|
+
res.off("close", cancel);
|
|
847
|
+
res.off("error", cancel);
|
|
848
|
+
reader.cancel(error).catch(() => {
|
|
849
|
+
});
|
|
850
|
+
if (error) res.destroy(error);
|
|
851
|
+
};
|
|
852
|
+
res.on("close", cancel);
|
|
853
|
+
res.on("error", cancel);
|
|
854
|
+
next();
|
|
855
|
+
async function next() {
|
|
856
|
+
try {
|
|
857
|
+
for (; ; ) {
|
|
858
|
+
const { done, value } = await reader.read();
|
|
859
|
+
if (done) break;
|
|
860
|
+
if (!res.write(value)) {
|
|
861
|
+
res.once("drain", next);
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
res.end();
|
|
866
|
+
} catch (error) {
|
|
867
|
+
cancel(error instanceof Error ? error : new Error(String(error)));
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
// src/adapter/node.ts
|
|
873
|
+
function toNodeHandler(handler) {
|
|
874
|
+
return async (req, res) => {
|
|
875
|
+
const protocol = req.connection?.encrypted ? "https" : "http";
|
|
876
|
+
const base = `${protocol}://${req.headers[":authority"] || req.headers.host}`;
|
|
877
|
+
const response = await handler(getRequest({ base, request: req }));
|
|
878
|
+
setResponse(res, response);
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
882
|
+
0 && (module.exports = {
|
|
883
|
+
APIError,
|
|
884
|
+
createEndpoint,
|
|
885
|
+
createEndpointCreator,
|
|
886
|
+
createMiddleware,
|
|
887
|
+
createMiddlewareCreator,
|
|
888
|
+
createRouter,
|
|
889
|
+
getBody,
|
|
890
|
+
getCookie,
|
|
891
|
+
getRequest,
|
|
892
|
+
getSignedCookie,
|
|
893
|
+
parse,
|
|
894
|
+
parseSigned,
|
|
895
|
+
serialize,
|
|
896
|
+
serializeSigned,
|
|
897
|
+
setCookie,
|
|
898
|
+
setResponse,
|
|
899
|
+
setSignedCookie,
|
|
900
|
+
shouldSerialize,
|
|
901
|
+
statusCode,
|
|
902
|
+
toNodeHandler
|
|
903
|
+
});
|
|
2
904
|
//# sourceMappingURL=index.cjs.map
|