Comparing version 0.5.0-exp-230427.2352 to 0.5.0-exp-230428.1515
@@ -1,2 +0,27 @@ | ||
let e;import{parse as r}from"fast-querystring";import{mapEarlyResponse as t,mapResponse as s}from"./handler";import{SCHEMA as a,DEFS as n,createValidationError as o,removeHostnameRegex as c,removeFragmentRegex as l,removePathRegex as i,removeQueryRegex as u}from"./utils";import{mapErrorCode as d}from"./error";let f="AsyncFunction",p=e=>e.constructor.name===f,h=(e,r)=>{let t=r.slice(r.indexOf("(")+1,r.indexOf(")"));if(""===t)return!1;if(123===t.charCodeAt(0))return!!(t.includes(`{ ${e}`)||t.includes(`, ${e}`));if(r.includes(`${t}.${e}`))return!0;let s=RegExp(" (\\w+) = context","g"),a=[t];for(let e of r.matchAll(s))a.push(e[1]);let n=RegExp(`{.*?} = (${a.join("|")})`,"g");for(let[t]of r.matchAll(n))if(t.includes(`{ ${e}`)||t.includes(`, ${e}`))return!0;return!1};export const composeHandler=({method:e,hooks:c,validator:l,handler:i,handleError:u,meta:m})=>{let y="try {\n",$="GET"!==e&&(l.body||[i,...c.transform,...c.beforeHandle,...c.afterHandle].some(e=>h("body",e.toString()))),g=i.constructor.name===f||c.parse.length||c.afterHandle.find(p)||c.beforeHandle.find(p)||c.transform.find(p)||$;if($){if(y+=` | ||
let e;import{parse as r}from"fast-querystring";import{mapEarlyResponse as t,mapResponse as s}from"./handler";import{SCHEMA as a,DEFS as o,createValidationError as n,removeHostnameRegex as c,removeFragmentRegex as l,removePathRegex as i,removeQueryRegex as u}from"./utils";import{mapErrorCode as d}from"./error";let f="AsyncFunction",p=e=>e.constructor.name===f,y=(e,r)=>{let t=r.slice(r.indexOf("(")+1,r.indexOf(")"));if(""===t)return!1;if(123===t.charCodeAt(0))return!!(t.includes(`{ ${e}`)||t.includes(`, ${e}`));if(r.includes(`${t}.${e}`))return!0;let s=RegExp(" (\\w+) = context","g"),a=[t];for(let e of r.matchAll(s))a.push(e[1]);let o=RegExp(`{.*?} = (${a.join("|")})`,"g");for(let[t]of r.matchAll(o))if(t.includes(`{ ${e}`)||t.includes(`, ${e}`))return!0;return!1};export const composeHandler=({method:e,hooks:c,validator:l,handler:i,handleError:u,meta:h})=>{let m="try {\n",b="string"==typeof c.type,$="GET"!==e&&(l.body||b||[i,...c.transform,...c.beforeHandle,...c.afterHandle].some(e=>y("body",e.toString()))),g=$||i.constructor.name===f||c.parse.length||c.afterHandle.find(p)||c.beforeHandle.find(p)||c.transform.find(p);if($){if(b||l.body){if(l.body||(m+="if(body) "),m+=`try { | ||
`,l.body){let e=l.body.schema;switch(e.type){case"object":"URLEncoded"===e.elysiaMeta?m+="c.body = parseQuery(await c.request.text())":l.body.Code().includes("custom('File")?m+=`c.body = {} | ||
await c.request.formData().then((form) => { | ||
for (const key of form.keys()) { | ||
if (c.body[key]) | ||
continue | ||
const value = form.getAll(key) | ||
if (value.length === 1) | ||
c.body[key] = value[0] | ||
else c.body[key] = value | ||
} | ||
})`:m+="c.body = JSON.parse(await c.request.text())";break;case"string":m+="c.body = await c.request.text()"}}else switch(c.type){case"application/json":m+="c.body = JSON.parse(await c.request.text());";break;case"text/plain":m+="c.body = await c.request.text();";break;case"application/x-www-form-urlencoded":m+="c.body = parseQuery(await c.request.text());";break;case"multipart/form-data":m+=`c.body = {} | ||
for (const key of (await c.request.formData()).keys()) { | ||
if (c.body[key]) | ||
continue | ||
const value = form.getAll(key) | ||
if (value.length === 1) | ||
c.body[key] = value[0] | ||
else c.body[key] = value | ||
}`}m+=`} catch(error) { | ||
throw new Error('PARSE') | ||
}`}else{if(m+=` | ||
let contentType = c.request.headers.get('content-type') | ||
@@ -7,10 +32,10 @@ | ||
if (index !== -1) contentType = contentType.substring(0, index) | ||
`,c.parse.length){y+=`let used = false | ||
`;for(let e=0;e<c.parse.length;e++){let r=`bo${e}`;y+=`if(!c.request.bodyUsed) { | ||
`,c.parse.length){m+=`let used = false | ||
`;for(let e=0;e<c.parse.length;e++){let r=`bo${e}`;m+=`if(!c.request.bodyUsed) { | ||
let ${r} = parse[${e}](c, contentType); | ||
if(${r} instanceof Promise) ${r} = await ${r} | ||
if(${r} !== undefined) { c.body = ${r}; used = true } | ||
}`}y+="if (!used)"}y+=`switch (contentType) { | ||
}`}m+="if (!used)"}m+=`switch (contentType) { | ||
case 'application/json': | ||
c.body = await c.request.json() | ||
c.body = JSON.parse(await c.request.text()) | ||
break | ||
@@ -23,3 +48,3 @@ | ||
case 'application/x-www-form-urlencoded': | ||
c.body = await c.request.text().then(parseQuery) | ||
c.body = parseQuery(await c.request.text()) | ||
break | ||
@@ -30,20 +55,18 @@ | ||
await c.request.formData().then((form) => { | ||
for (const key of form.keys()) { | ||
if (c.body[key]) | ||
continue | ||
for (const key of (await c.request.formData()).keys()) { | ||
if (c.body[key]) | ||
continue | ||
const value = form.getAll(key) | ||
if (value.length === 1) | ||
c.body[key] = value[0] | ||
else c.body[key] = value | ||
} | ||
}) | ||
const value = form.getAll(key) | ||
if (value.length === 1) | ||
c.body[key] = value[0] | ||
else c.body[key] = value | ||
} | ||
break | ||
}} | ||
`}if(c?.transform)for(let e=0;e<c.transform.length;e++)y+=c.transform[e].constructor.name===f?`await transform[${e}](c);`:`transform[${e}](c);`;if(l&&(l.headers&&(y+=` | ||
`}}if(c?.transform)for(let e=0;e<c.transform.length;e++)m+=c.transform[e].constructor.name===f?`await transform[${e}](c);`:`transform[${e}](c);`;if(l&&(l.headers&&(m+=` | ||
const h = {} | ||
for (const key of c.request.headers.keys()) | ||
h[key] = c.request.headers.get(key) | ||
h[key] = c.request.headers.get(key) | ||
@@ -57,24 +80,24 @@ if (headers.Check(h) === false) { | ||
} | ||
`),l.params&&(y+="if(params.Check(c.params) === false) { throw createValidationError('params', params, c.params) }"),l.query&&(y+="if(query.Check(c.query) === false) { throw createValidationError('params', query, c.query) }"),l.body&&(y+="if(body.Check(c.body) === false) { throw createValidationError('body', body, c.body) }")),c?.beforeHandle)for(let e=0;e<c.beforeHandle.length;e++){let r=`be${e}`;if(y+=(c.beforeHandle[e].constructor.name===f?`let ${r} = await beforeHandle[${e}](c); | ||
`),l.params&&(m+="if(params.Check(c.params) === false) { throw createValidationError('params', params, c.params) }"),l.query&&(m+="if(query.Check(c.query) === false) { throw createValidationError('params', query, c.query) }"),l.body&&(m+="if(body.Check(c.body) === false) { throw createValidationError('body', body, c.body) }")),c?.beforeHandle)for(let e=0;e<c.beforeHandle.length;e++){let r=`be${e}`;if(m+=(c.beforeHandle[e].constructor.name===f?`let ${r} = await beforeHandle[${e}](c); | ||
`:`let ${r} = beforeHandle[${e}](c); | ||
`)+`if(${r} !== undefined) { | ||
`,c?.afterHandle)for(let e=0;e<c.afterHandle.length;e++){let t=`af${e}`;y+=(c.afterHandle[e].constructor.name===f?`const ${t} = await afterHandle[${e}](c, ${r}); | ||
`,c?.afterHandle)for(let e=0;e<c.afterHandle.length;e++){let t=`af${e}`;m+=(c.afterHandle[e].constructor.name===f?`const ${t} = await afterHandle[${e}](c, ${r}); | ||
`:`const ${t} = afterHandle[${e}](c, ${r}); | ||
`)+`if(${t} !== undefined) { ${r} = ${t} } | ||
`}l.response&&(y+=`if(response[c.set.status]?.Check(${r}) === false) { throw createValidationError('response', response[c.set.status], ${r}) } | ||
`),y+=`return mapEarlyResponse(${r}, c.set)} | ||
`}if(c?.afterHandle.length){y+=i.constructor.name===f?`let r = await handler(c); | ||
`}l.response&&(m+=`if(response[c.set.status]?.Check(${r}) === false) { throw createValidationError('response', response[c.set.status], ${r}) } | ||
`),m+=`return mapEarlyResponse(${r}, c.set)} | ||
`}if(c?.afterHandle.length){m+=i.constructor.name===f?`let r = await handler(c); | ||
`:`let r = handler(c); | ||
`;for(let e=0;e<c.afterHandle.length;e++){let r=`af${e}`;y+=c.afterHandle[e].constructor.name===f?`let ${r} = await afterHandle[${e}](c, r) | ||
`;for(let e=0;e<c.afterHandle.length;e++){let r=`af${e}`;m+=c.afterHandle[e].constructor.name===f?`let ${r} = await afterHandle[${e}](c, r) | ||
`:`let ${r} = afterHandle[${e}](c, r) | ||
`,l.response?y+=`if(response[c.set.status]?.Check(${r}) === false) { throw createValidationError('response', response[c.set.status], ${r}) } | ||
`,l.response?m+=`if(response[c.set.status]?.Check(${r}) === false) { throw createValidationError('response', response[c.set.status], ${r}) } | ||
${r} = mapEarlyResponse(${r}, c.set) | ||
if(${r}) return ${r}; | ||
`:y+=`if(${r}) return ${r}; | ||
`}l.response&&(y+=`if(response[c.set.status]?.Check(r) === false) { throw createValidationError('response', response[c.set.status], r) } | ||
`),y+=`return mapResponse(r, c.set); | ||
`}else l.response?y+=(i.constructor.name===f?`const r = await handler(c); | ||
`:m+=`if(${r}) return ${r}; | ||
`}l.response&&(m+=`if(response[c.set.status]?.Check(r) === false) { throw createValidationError('response', response[c.set.status], r) } | ||
`),m+=`return mapResponse(r, c.set); | ||
`}else l.response?m+=(i.constructor.name===f?`const r = await handler(c); | ||
`:`const r = handler(c); | ||
`)+`if(response[c.set.status]?.Check(r) === false) { throw createValidationError('response', response[c.set.status], r) } | ||
`+"return mapResponse(r, c.set);":y+=i.constructor.name===f?"return handler(c).then((v) => mapResponse(v, c.set))":"return mapResponse(handler(c), c.set);";y+=` | ||
`+"return mapResponse(r, c.set);":m+=i.constructor.name===f?"return handler(c).then((v) => mapResponse(v, c.set))":"return mapResponse(handler(c), c.set);";m+=` | ||
} catch(error) { | ||
@@ -105,3 +128,3 @@ ${g?"":"return (async () => {"} | ||
${g?"":"})()"} | ||
}`,y=`const { | ||
}`,m=`const { | ||
handler, | ||
@@ -130,3 +153,3 @@ handleError, | ||
}, | ||
${m?` | ||
${h?` | ||
meta, | ||
@@ -138,6 +161,6 @@ SCHEMA, | ||
return ${g?"async":""} function(c) { | ||
${m?"c[SCHEMA] = meta[SCHEMA]; c[DEFS] = meta[DEFS];":""} | ||
${h?"c[SCHEMA] = meta[SCHEMA]; c[DEFS] = meta[DEFS];":""} | ||
${y} | ||
}`;let b=Function("hooks",y);return b({handler:i,hooks:c,validator:l,handleError:u,utils:{createValidationError:o,mapResponse:s,mapEarlyResponse:t,mapErrorCode:d,parseQuery:r},meta:m,SCHEMA:m?a:void 0,DEFS:m?n:void 0})};export const composeGeneralHandler=s=>{let a=s.decorators,n=Object.keys(a).length;if(e?.[0]===n&&e[1]===s.event.request.length)return Function("data",e?.[2])({app:s,parseQuery:r,mapEarlyResponse:t,removeHostnameRegex:c,removeQueryRegex:u,removePathRegex:i,removeFragmentRegex:l});let o="";for(let e of Object.keys(a))o+=`,${e}: app.decorators.${e}`;let d=`const { | ||
${m} | ||
}`;let q=Function("hooks",m);return q({handler:i,hooks:c,validator:l,handleError:u,utils:{createValidationError:n,mapResponse:s,mapEarlyResponse:t,mapErrorCode:d,parseQuery:r},meta:h,SCHEMA:h?a:void 0,DEFS:h?o:void 0})};export const composeGeneralHandler=s=>{let a=s.decorators,o=Object.keys(a).length;if(e?.[0]===o&&e[1]===s.event.request.length)return Function("data",e?.[2])({app:s,parseQuery:r,mapEarlyResponse:t,removeHostnameRegex:c,removeQueryRegex:u,removePathRegex:i,removeFragmentRegex:l});let n="";for(let e of Object.keys(a))n+=`,${e}: app.decorators.${e}`;let d=`const { | ||
app, | ||
@@ -166,3 +189,3 @@ app: { store, router, _s: _static }, | ||
store | ||
${o} | ||
${n} | ||
} | ||
@@ -222,2 +245,2 @@ | ||
} | ||
}`;return e=[n,s.event.request.length,d],Function("data",d)({app:s,parseQuery:r,mapEarlyResponse:t,removeHostnameRegex:c,removeQueryRegex:u,removePathRegex:i,removeFragmentRegex:l})}; | ||
}`;return e=[o,s.event.request.length,d],Function("data",d)({app:s,parseQuery:r,mapEarlyResponse:t,removeHostnameRegex:c,removeQueryRegex:u,removePathRegex:i,removeFragmentRegex:l})}; |
@@ -24,4 +24,5 @@ /// <reference types="bun-types" /> | ||
Files: typeof ElysiaType.Files; | ||
URLEncoded: (typeof Type)['Object']; | ||
} | ||
} | ||
export { Type as t }; |
@@ -1,1 +0,1 @@ | ||
import{Type as e}from"@sinclair/typebox";import{TypeSystem as t}from"@sinclair/typebox/system";try{t.Format("email",e=>/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(e)),t.Format("uuid",e=>/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e)),t.Format("date",e=>!Number.isNaN(new Date(e).getTime())),t.Format("date-time",e=>!Number.isNaN(new Date(e).getTime()))}catch(e){}let i=e=>{if("string"==typeof e)switch(e.slice(-1)){case"k":return 1024*+e.slice(0,e.length-1);case"m":return 1048576*+e.slice(0,e.length-1);default:return+e}return e},r=(e,t)=>{if(!(t instanceof Blob)||e.minSize&&t.size<i(e.minSize)||e.maxSize&&t.size>i(e.maxSize))return!1;if(e.extension){if("string"==typeof e.extension){if(!t.type.startsWith(e.extension))return!1}else{for(let i=0;i<e.extension.length;i++)if(t.type.startsWith(e.extension[i]))return!0;return!1}}return!0};export const ElysiaType={File:t.CreateType("File",r),Files:t.CreateType("Files",(e,t)=>{if(!Array.isArray(t)||e.minItems&&t.length<e.minItems||e.maxItems&&t.length>e.maxItems)return!1;for(let i=0;i<t.length;i++)if(!r(e,t[i]))return!1;return!0})};e.File=e=>ElysiaType.File({default:"File",...e,extension:e?.type,type:"string",format:"binary"}),e.Files=e=>ElysiaType.Files({...e,default:"Files",extension:e?.type,type:"array",items:{...e,default:"Files",type:"string",format:"binary"}});export{e as t}; | ||
import{Type as e}from"@sinclair/typebox";import{TypeSystem as t}from"@sinclair/typebox/system";try{t.Format("email",e=>/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(e)),t.Format("uuid",e=>/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e)),t.Format("date",e=>!Number.isNaN(new Date(e).getTime())),t.Format("date-time",e=>!Number.isNaN(new Date(e).getTime()))}catch(e){}let i=e=>{if("string"==typeof e)switch(e.slice(-1)){case"k":return 1024*+e.slice(0,e.length-1);case"m":return 1048576*+e.slice(0,e.length-1);default:return+e}return e},a=(e,t)=>{if(!(t instanceof Blob)||e.minSize&&t.size<i(e.minSize)||e.maxSize&&t.size>i(e.maxSize))return!1;if(e.extension){if("string"==typeof e.extension){if(!t.type.startsWith(e.extension))return!1}else{for(let i=0;i<e.extension.length;i++)if(t.type.startsWith(e.extension[i]))return!0;return!1}}return!0};export const ElysiaType={File:t.Type("File",a),Files:t.Type("Files",(e,t)=>{if(!Array.isArray(t)||e.minItems&&t.length<e.minItems||e.maxItems&&t.length>e.maxItems)return!1;for(let i=0;i<t.length;i++)if(!a(e,t[i]))return!1;return!0})};e.URLEncoded=(t,i)=>e.Object(t,{...i,elysiaMeta:"URLEncoded"}),e.File=e=>ElysiaType.File({elysiaMeta:"File",default:"File",...e,extension:e?.type,type:"string",format:"binary"}),e.Files=e=>ElysiaType.Files({...e,elysiaMeta:"Files",default:"Files",extension:e?.type,type:"array",items:{...e,default:"Files",type:"string",format:"binary"}});export{e as t}; |
@@ -1,1 +0,1 @@ | ||
let t=new Map;t.set("INTERNAL_SERVER_ERROR",500),t.set("NOT_FOUND",404),t.set("VALIDATION",400);let r=new Set(t.keys());export const mapErrorCode=t=>r.has(t)?t:"UNKNOWN";export const mapErrorStatus=r=>t.get(r)??500;export class ValidationError extends Error{opts;constructor(t){super("VALIDATION",{cause:t.cause}),this.opts=t,Object.setPrototypeOf(this,ValidationError.prototype)}all(){return[...this.opts.validator.Errors(this.opts.value)]}} | ||
let t=new Map([["INTERNAL_SERVER_ERROR",500],["NOT_FOUND",404],["VALIDATION",400],["PARSE",400]]),r=new Set(t.keys());export const mapErrorCode=t=>r.has(t)?t:"UNKNOWN";export const mapErrorStatus=r=>t.get(r)??500;export class ValidationError extends Error{opts;constructor(t){super("VALIDATION",{cause:t.cause}),this.opts=t,Object.setPrototypeOf(this,ValidationError.prototype)}all(){return[...this.opts.validator.Errors(this.opts.value)]}} |
@@ -1,1 +0,1 @@ | ||
import{nanoid as e}from"nanoid";import{Memoirist as t}from"memoirist";import{mapResponse as r}from"./handler";import{SCHEMA as s,EXPOSED as a,DEFS as o,mergeHook as i,getSchemaValidator as h,getResponseSchemaValidator as n,mergeDeep as u}from"./utils";import{registerSchemaPath as d}from"./schema";import{mapErrorCode as l,mapErrorStatus as c}from"./error";import{composeGeneralHandler as m,composeHandler as p}from"./compose";import{ws as f}from"./ws";export default class v{config;store={};meta={[s]:Object.create(null),[o]:Object.create(null),[a]:Object.create(null)};decorators={};event={start:[],request:[],parse:[],transform:[],beforeHandle:[],afterHandle:[],error:[],stop:[]};server=null;$schema=null;router=new t;routes=[];_s=new Map;wsRouter;lazyLoadModules=[];constructor(e){this.config={fn:"/~fn",...e},this.fetch=m(this)}_addHandler(e,t,r,a,{allowMeta:u=!1}={allowMeta:!1}){t=t.startsWith("/")?t:`/${t}`,this.routes.push({method:e,path:t,handler:r,hooks:i({...this.event},a)});let l=this.meta[o];d({schema:this.meta[s],contentType:a?.schema?.contentType,hook:a,method:e,path:t,models:this.meta[o]});let c={body:h(a?.schema?.body??this.$schema?.body,l),headers:h(a?.schema?.headers??this.$schema?.headers,l,!0),params:h(a?.schema?.params??this.$schema?.params,l),query:h(a?.schema?.query??this.$schema?.query,l),response:n(a?.schema?.response??this.$schema?.response,l)},f=i(this.event,a),v=p({method:e,hooks:f,validator:c,handler:r,handleError:this.handleError,meta:u?this.meta:void 0});-1===t.indexOf(":")&&-1===t.indexOf("*")&&(this._s.has(e)||this._s.set(e,new Map),this._s.get(e).set(t,v)),this.router.add(e,t,v),this.fetch=m(this)}onStart(e){return this.event.start.push(e),this}onRequest(e){return this.event.request.push(e),this}onParse(e){return this.event.parse.splice(this.event.parse.length-1,0,e),this}onTransform(e){return this.event.transform.push(e),this}onBeforeHandle(e){return this.event.beforeHandle.push(e),this}onAfterHandle(e){return this.event.afterHandle.push(e),this}onError(e){return this.event.error.push(e),this}onStop(e){return this.event.stop.push(e),this}on(e,t){switch(e){case"start":this.event.start.push(t);break;case"request":this.event.request.push(t);break;case"parse":this.event.parse.push(t);break;case"transform":this.event.transform.push(t);break;case"beforeHandle":this.event.beforeHandle.push(t);break;case"afterHandle":this.event.afterHandle.push(t);break;case"error":this.event.error.push(t);break;case"stop":this.event.stop.push(t)}return this}group(e,t){let r=new v;r.store=this.store,this.wsRouter&&r.use(f());let s=t(r);return this.decorators=u(this.decorators,r.decorators),s.event.request.length&&(this.event.request=[...this.event.request,...s.event.request]),this.setModel(s.meta[o]),Object.values(r.routes).forEach(({method:t,path:a,handler:o,hooks:h})=>{let n="/"===a?e:`${e}${a}`,u=r.wsRouter?.find("subscribe",n);if(u){let e=r.wsRouter.history.find(([e,t])=>a===t);if(!e)return;return this.ws(n,e[2])}this._addHandler(t,n,o,i(h,{error:s.event.error}))}),r.wsRouter&&this.wsRouter&&r.wsRouter.history.forEach(([t,r,s])=>{"/"===r?this.wsRouter?.add(t,e,s):this.wsRouter?.add(t,`${e}${r}`,s)}),this}guard(e,t){let r=new v;r.store=this.store,this.wsRouter&&r.use(f());let s=t(r);return this.decorators=u(this.decorators,r.decorators),s.event.request.length&&(this.event.request=[...this.event.request,...s.event.request]),this.setModel(s.meta[o]),Object.values(r.routes).forEach(({method:t,path:a,handler:o,hooks:h})=>{let n=r.wsRouter?.find("subscribe",a);if(n){let e=r.wsRouter.history.find(([e,t])=>a===t);if(!e)return;return this.ws(a,e[2])}this._addHandler(t,a,o,i(e,{...h,error:h.error?Array.isArray(h.error)?[...h.error,...s.event.error]:[h.error,...s.event.error]:s.event.error}))}),r.wsRouter&&this.wsRouter&&r.wsRouter.history.forEach(([e,t,r])=>{this.wsRouter?.add(e,t,r)}),this}use(e){if(e instanceof Promise)return this.lazyLoadModules.push(e.then(e=>"function"==typeof e?e(this):e.default(this))),this;let t=e(this);return t instanceof Promise?(this.lazyLoadModules.push(t),this):t}if(e,t){return e?this.use(t):this}get(e,t,r){return this._addHandler("GET",e,t,r),this}post(e,t,r){return this._addHandler("POST",e,t,r),this}put(e,t,r){return this._addHandler("PUT",e,t,r),this}patch(e,t,r){return this._addHandler("PATCH",e,t,r),this}delete(e,t,r){return this._addHandler("DELETE",e,t,r),this}options(e,t,r){return this._addHandler("OPTIONS",e,t,r),this}all(e,t,r){return this._addHandler("ALL",e,t,r),this}head(e,t,r){return this._addHandler("HEAD",e,t,r),this}trace(e,t,r){return this._addHandler("TRACE",e,t,r),this}connect(e,t,r){return this._addHandler("CONNECT",e,t,r),this}ws(t,r){if(!this.wsRouter)throw Error("Can't find WebSocket. Please register WebSocket plugin first by importing 'elysia/ws'");return this.wsRouter.add("subscribe",t,r),this.get(t,t=>{if(!this.server?.upgrade(t.request,{headers:"function"==typeof r.headers?r.headers(t):r.headers,data:{...t,id:e(),message:h(r.schema?.body,this.meta[o]),transformMessage:r.transform?Array.isArray(r.transformMessage)?r.transformMessage:[r.transformMessage]:[]}}))return t.set.status=400,"Expected a websocket connection"},{parse:r.parse,beforeHandle:r.beforeHandle,transform:r.transform,schema:{headers:r.schema?.headers,params:r.schema?.params,query:r.schema?.query}}),this}route(e,t,r,{config:s,...a}={config:{allowMeta:!1}}){return this._addHandler(e,t,r,a,s),this}state(e,t){return e in this.store||(this.store[e]=t),this}decorate(e,t){return e in this.decorators||(this.decorators[e]=t),this}derive(e){return"AsyncFunction"===e.constructor.name?this.onTransform(async t=>{Object.assign(t,await e(t))}):this.onTransform(t=>{Object.assign(t,e(t))})}fn(e){return this.use(async()=>{let{fn:t}=await import("@elysiajs/fn");return t({app:this,value:e,path:this.config.fn})})}schema(e){let t=this.meta[o];return this.$schema={body:h(e.body,t),headers:h(e?.headers,t,!0),params:h(e?.params,t),query:h(e?.query,t),response:h(e?.response,t)},this}handle=async e=>this.fetch(e);handleError=async(e,t,s={headers:{}})=>{for(let a=0;a<this.event.error.length;a++){let o=this.event.error[a]({request:e,code:l(t.message),error:t,set:s});if(o instanceof Promise&&(o=await o),null!=o)return r(o,s)}return new Response("string"==typeof t.cause?t.cause:t.message,{headers:s.headers,status:c(l(t.message))})};listen=(e,t)=>{if(!Bun)throw Error("Bun to run");if("string"==typeof e&&Number.isNaN(e=+e))throw Error("Port must be a numeric value");let r=this.fetch,s="object"==typeof e?{...this.config.serve,...e,fetch:r}:{...this.config.serve,port:e,fetch:r},a=`$$Elysia:${s.port}`;globalThis[a]?(this.server=globalThis[a],this.server.reload(s)):globalThis[a]=this.server=Bun.serve(s);for(let e=0;e<this.event.start.length;e++)this.event.start[e](this);return t&&t(this.server),Promise.all(this.lazyLoadModules).then(()=>{this.server.pendingRequests||Bun.gc(!0)}),this};stop=async()=>{if(!this.server)throw Error("Elysia isn't running. Call `app.listen` to start the server.");this.server.stop();for(let e=0;e<this.event.stop.length;e++)await this.event.stop[e](this)};get modules(){return Promise.all(this.lazyLoadModules)}setModel(e){return Object.entries(e).forEach(([e,t])=>{e in this.meta[o]||(this.meta[o][e]=t)}),this}}export{t}from"./custom-types";export{ws}from"./ws";export{SCHEMA,DEFS,EXPOSED,createValidationError,getSchemaValidator,mergeDeep,mergeHook,mergeObjectArray,getPath,getPathAndQuery,getResponseSchemaValidator}from"./utils";export{ElysiaError,ValidationError}from"./validation";export{v as Elysia}; | ||
import{nanoid as e}from"nanoid";import{Memoirist as t}from"memoirist";import{mapResponse as r}from"./handler";import{SCHEMA as s,EXPOSED as a,DEFS as o,mergeHook as i,getSchemaValidator as h,getResponseSchemaValidator as n,mergeDeep as u}from"./utils";import{registerSchemaPath as d}from"./schema";import{mapErrorCode as l,mapErrorStatus as c}from"./error";import{composeGeneralHandler as p,composeHandler as m}from"./compose";import{ws as f}from"./ws";export default class v{config;store={};meta={[s]:Object.create(null),[o]:Object.create(null),[a]:Object.create(null)};decorators={};event={start:[],request:[],parse:[],transform:[],beforeHandle:[],afterHandle:[],error:[],stop:[]};server=null;$schema=null;router=new t;routes=[];_s=new Map;wsRouter;lazyLoadModules=[];constructor(e){this.config={fn:"/~fn",...e},this.fetch=p(this)}_addHandler(e,t,r,a,{allowMeta:u=!1}={allowMeta:!1}){t=t.startsWith("/")?t:`/${t}`,this.routes.push({method:e,path:t,handler:r,hooks:i({...this.event},a)});let l=this.meta[o];if(a?.type)switch(a.type){case"text":a.type="text/plain";break;case"json":a.type="application/json";break;case"formdata":a.type="multipart/form-data";break;case"urlencoded":a.type="application/x-www-form-urlencoded"}d({schema:this.meta[s],contentType:a?.type,hook:a,method:e,path:t,models:this.meta[o]});let c={body:h(a?.schema?.body??this.$schema?.body,l),headers:h(a?.schema?.headers??this.$schema?.headers,l,!0),params:h(a?.schema?.params??this.$schema?.params,l),query:h(a?.schema?.query??this.$schema?.query,l),response:n(a?.schema?.response??this.$schema?.response,l)},f=i(this.event,a),v=m({method:e,hooks:f,validator:c,handler:r,handleError:this.handleError,meta:u?this.meta:void 0});-1===t.indexOf(":")&&-1===t.indexOf("*")&&(this._s.has(e)||this._s.set(e,new Map),this._s.get(e).set(t,v)),this.router.add(e,t,v),this.fetch=p(this)}onStart(e){return this.event.start.push(e),this}onRequest(e){return this.event.request.push(e),this}onParse(e){return this.event.parse.splice(this.event.parse.length-1,0,e),this}onTransform(e){return this.event.transform.push(e),this}onBeforeHandle(e){return this.event.beforeHandle.push(e),this}onAfterHandle(e){return this.event.afterHandle.push(e),this}onError(e){return this.event.error.push(e),this}onStop(e){return this.event.stop.push(e),this}on(e,t){switch(e){case"start":this.event.start.push(t);break;case"request":this.event.request.push(t);break;case"parse":this.event.parse.push(t);break;case"transform":this.event.transform.push(t);break;case"beforeHandle":this.event.beforeHandle.push(t);break;case"afterHandle":this.event.afterHandle.push(t);break;case"error":this.event.error.push(t);break;case"stop":this.event.stop.push(t)}return this}group(e,t){let r=new v;r.store=this.store,this.wsRouter&&r.use(f());let s=t(r);return this.decorators=u(this.decorators,r.decorators),s.event.request.length&&(this.event.request=[...this.event.request,...s.event.request]),this.setModel(s.meta[o]),Object.values(r.routes).forEach(({method:t,path:a,handler:o,hooks:h})=>{let n="/"===a?e:`${e}${a}`,u=r.wsRouter?.find("subscribe",n);if(u){let e=r.wsRouter.history.find(([e,t])=>a===t);if(!e)return;return this.ws(n,e[2])}this._addHandler(t,n,o,i(h,{error:s.event.error}))}),r.wsRouter&&this.wsRouter&&r.wsRouter.history.forEach(([t,r,s])=>{"/"===r?this.wsRouter?.add(t,e,s):this.wsRouter?.add(t,`${e}${r}`,s)}),this}guard(e,t){let r=new v;r.store=this.store,this.wsRouter&&r.use(f());let s=t(r);return this.decorators=u(this.decorators,r.decorators),s.event.request.length&&(this.event.request=[...this.event.request,...s.event.request]),this.setModel(s.meta[o]),Object.values(r.routes).forEach(({method:t,path:a,handler:o,hooks:h})=>{let n=r.wsRouter?.find("subscribe",a);if(n){let e=r.wsRouter.history.find(([e,t])=>a===t);if(!e)return;return this.ws(a,e[2])}this._addHandler(t,a,o,i(e,{...h,error:h.error?Array.isArray(h.error)?[...h.error,...s.event.error]:[h.error,...s.event.error]:s.event.error}))}),r.wsRouter&&this.wsRouter&&r.wsRouter.history.forEach(([e,t,r])=>{this.wsRouter?.add(e,t,r)}),this}use(e){if(e instanceof Promise)return this.lazyLoadModules.push(e.then(e=>"function"==typeof e?e(this):e.default(this))),this;let t=e(this);return t instanceof Promise?(this.lazyLoadModules.push(t),this):t}if(e,t){return e?this.use(t):this}get(e,t,r){return this._addHandler("GET",e,t,r),this}post(e,t,r){return this._addHandler("POST",e,t,r),this}put(e,t,r){return this._addHandler("PUT",e,t,r),this}patch(e,t,r){return this._addHandler("PATCH",e,t,r),this}delete(e,t,r){return this._addHandler("DELETE",e,t,r),this}options(e,t,r){return this._addHandler("OPTIONS",e,t,r),this}all(e,t,r){return this._addHandler("ALL",e,t,r),this}head(e,t,r){return this._addHandler("HEAD",e,t,r),this}trace(e,t,r){return this._addHandler("TRACE",e,t,r),this}connect(e,t,r){return this._addHandler("CONNECT",e,t,r),this}ws(t,r){if(!this.wsRouter)throw Error("Can't find WebSocket. Please register WebSocket plugin first by importing 'elysia/ws'");return this.wsRouter.add("subscribe",t,r),this.get(t,t=>{if(!this.server?.upgrade(t.request,{headers:"function"==typeof r.headers?r.headers(t):r.headers,data:{...t,id:e(),message:h(r.schema?.body,this.meta[o]),transformMessage:r.transform?Array.isArray(r.transformMessage)?r.transformMessage:[r.transformMessage]:[]}}))return t.set.status=400,"Expected a websocket connection"},{parse:r.parse,beforeHandle:r.beforeHandle,transform:r.transform,schema:{headers:r.schema?.headers,params:r.schema?.params,query:r.schema?.query}}),this}route(e,t,r,{config:s,...a}={config:{allowMeta:!1}}){return this._addHandler(e,t,r,a,s),this}state(e,t){return e in this.store||(this.store[e]=t),this}decorate(e,t){return e in this.decorators||(this.decorators[e]=t),this}derive(e){return"AsyncFunction"===e.constructor.name?this.onTransform(async t=>{Object.assign(t,await e(t))}):this.onTransform(t=>{Object.assign(t,e(t))})}fn(e){return this.use(async()=>{let{fn:t}=await import("@elysiajs/fn");return t({app:this,value:e,path:this.config.fn})})}schema(e){let t=this.meta[o];return this.$schema={body:h(e.body,t),headers:h(e?.headers,t,!0),params:h(e?.params,t),query:h(e?.query,t),response:h(e?.response,t)},this}handle=async e=>this.fetch(e);handleError=async(e,t,s={headers:{}})=>{for(let a=0;a<this.event.error.length;a++){let o=this.event.error[a]({request:e,code:l(t.message),error:t,set:s});if(o instanceof Promise&&(o=await o),null!=o)return r(o,s)}return new Response("string"==typeof t.cause?t.cause:t.message,{headers:s.headers,status:c(l(t.message))})};listen=(e,t)=>{if(!Bun)throw Error("Bun to run");if("string"==typeof e&&Number.isNaN(e=+e))throw Error("Port must be a numeric value");let r=this.fetch,s="object"==typeof e?{...this.config.serve,...e,fetch:r}:{...this.config.serve,port:e,fetch:r};if("production"!==process.env.ENV){let e=`$$Elysia:${s.port}`;globalThis[e]?(this.server=globalThis[e],this.server.reload(s)):globalThis[e]=this.server=Bun.serve(s)}for(let e=0;e<this.event.start.length;e++)this.event.start[e](this);return t&&t(this.server),Promise.all(this.lazyLoadModules).then(()=>{Bun.gc(!0)}),this};stop=async()=>{if(!this.server)throw Error("Elysia isn't running. Call `app.listen` to start the server.");this.server.stop();for(let e=0;e<this.event.stop.length;e++)await this.event.stop[e](this)};get modules(){return Promise.all(this.lazyLoadModules)}setModel(e){return Object.entries(e).forEach(([e,t])=>{e in this.meta[o]||(this.meta[o][e]=t)}),this}}export{t}from"./custom-types";export{ws}from"./ws";export{SCHEMA,DEFS,EXPOSED,createValidationError,getSchemaValidator,mergeDeep,mergeHook,mergeObjectArray,getPath,getPathAndQuery,getResponseSchemaValidator}from"./utils";export{ElysiaError,ValidationError}from"./validation";export{v as Elysia}; |
@@ -46,2 +46,3 @@ /// <reference types="bun-types" /> | ||
export interface LifeCycleStore<Instance extends ElysiaInstance = ElysiaInstance> { | ||
type?: ContentType; | ||
start: VoidLifeCycle<Instance>[]; | ||
@@ -58,2 +59,3 @@ request: BeforeRequestHandler<any, Instance>[]; | ||
export interface RegisteredHook<Instance extends ElysiaInstance = ElysiaInstance> { | ||
type?: ContentType; | ||
schema?: TypedSchema; | ||
@@ -116,6 +118,6 @@ transform: NoReturnHandler<any, Instance>[]; | ||
type ExtractModelName<Type> = Type extends TypedSchema<infer X> ? X : never; | ||
type ContentType = MaybeArray<(string & {}) | 'text/plain' | 'application/json' | 'multipart/form-data' | 'application/x-www-form-urlencoded'>; | ||
type ContentType = MaybeArray<(string & {}) | 'text' | 'json' | 'formdata' | 'urlencoded' | 'text/plain' | 'application/json' | 'multipart/form-data' | 'application/x-www-form-urlencoded'>; | ||
export interface LocalHook<Schema extends TypedSchema = TypedSchema, Instance extends ElysiaInstance<any> = ElysiaInstance, Path extends string = string, FinalSchema extends MergeSchema<Schema, Instance['schema']> = MergeSchema<Schema, Instance['schema']>, Models extends TypedSchema = TypedSchema<ExtractModelName<Schema>>> { | ||
type?: ContentType; | ||
schema?: (Models extends Schema ? Models : Models) & { | ||
contentType?: ContentType; | ||
detail?: Partial<OpenAPIV3.OperationObject>; | ||
@@ -200,3 +202,3 @@ }; | ||
request: Request; | ||
code: 'NOT_FOUND' | 'INTERNAL_SERVER_ERROR' | 'UNKNOWN'; | ||
code: 'NOT_FOUND' | 'INTERNAL_SERVER_ERROR' | 'UNKNOWN' | 'PARSE'; | ||
error: Error; | ||
@@ -203,0 +205,0 @@ set: Context['set']; |
@@ -1,1 +0,1 @@ | ||
import{Kind as e}from"@sinclair/typebox";import{TypeCompiler as r}from"@sinclair/typebox/compiler";import{ValidationError as t}from"./validation";export const SCHEMA=Symbol("schema");export const DEFS=Symbol("definitions");export const EXPOSED=Symbol("exposed");export const mergeObjectArray=(e,r)=>[...Array.isArray(e)?e:[e],...Array.isArray(r)?r:[r]];export const mergeHook=(e,r)=>{let t="schema"in e?e.schema:null,o=r&&"schema"in r?r.schema:null;return{schema:t||o?{body:o?.body??t?.body,header:o?.headers??t?.headers,params:o?.params??t?.params,query:o?.query??t?.query,response:o?.response??t?.response,detail:mergeDeep(o?.detail??{},t?.detail??{})}:void 0,transform:mergeObjectArray(e.transform??[],r?.transform??[]),beforeHandle:mergeObjectArray(e.beforeHandle??[],r?.beforeHandle??[]),parse:mergeObjectArray(e.parse??[],r?.parse??[]),afterHandle:mergeObjectArray(e.afterHandle??[],r?.afterHandle??[]),error:mergeObjectArray(e.error??[],r?.error??[])}};export const clone=e=>e;export const getPath=e=>{let r=e.indexOf("?",11),t=e.indexOf("#",12);return e.substring(e.indexOf("/",10),-1!==r?r:-1!==t?t:void 0)};export const getPathAndQuery=e=>{let r=e.indexOf("?",11),t=e.indexOf("#",12);return -1!==r?-1!==t?[e.substring(e.indexOf("/",10),r),e.substring(r+1,t)]:[e.substring(e.indexOf("/",10),r),e.substring(r+1)]:-1!==t?[e.substring(e.indexOf("/",10),t),""]:[e.substring(e.indexOf("/",10)),""]};export const removeHostnameRegex=/^[a-z]+?:\/\/[^/]+/;export const removeQueryRegex=/\?.*?([\w=&%]+)/;export const removePathRegex=/^[^?]*(\?|$)/;export const removeFragmentRegex=/#(\S+)/;let o=e=>e&&"object"==typeof e&&!Array.isArray(e);export const mergeDeep=(e,r)=>{let t=Object.assign({},e);return o(e)&&o(r)&&Object.keys(r).forEach(n=>{o(r[n])&&n in e?t[n]=mergeDeep(e[n],r[n]):Object.assign(t,{[n]:r[n]})}),t};export const createValidationError=(e,r,o)=>{let n=r.Errors(o).First(),i=`Invalid ${e}: '${n?.path?.slice(1)||"root"}'. ${n?.message}`;return new t({cause:i,type:e,validator:r,value:o})};export const getSchemaValidator=(e,t,o=!1)=>{if(!e||"string"==typeof e&&!(e in t))return;let n="string"==typeof e?t[e]:e;return"object"===n.type&&"additionalProperties"in n==!1&&(n.additionalProperties=o),r.Compile(n)};export const getResponseSchemaValidator=(t,o,n=!1)=>{if(!t||"string"==typeof t&&!(t in o))return;let i="string"==typeof t?o[t]:t;if(e in i)return{200:r.Compile(i)};let s={};return Object.keys(i).forEach(t=>{let a=i[t];if("string"==typeof a){if(a in o){let n=o[a];n.type,s[+t]=e in n?r.Compile(n):n}return}"object"===a.type&&"additionalProperties"in a==!1&&(a.additionalProperties=n),s[+t]=e in a?r.Compile(a):a}),s}; | ||
import{Kind as e}from"@sinclair/typebox";import{TypeCompiler as r}from"@sinclair/typebox/compiler";import{ValidationError as t}from"./validation";export const SCHEMA=Symbol("schema");export const DEFS=Symbol("definitions");export const EXPOSED=Symbol("exposed");export const mergeObjectArray=(e,r)=>[...Array.isArray(e)?e:[e],...Array.isArray(r)?r:[r]];export const mergeHook=(e,r)=>{let t="schema"in e?e.schema:null,o=r&&"schema"in r?r.schema:null;return{schema:t||o?{body:o?.body??t?.body,header:o?.headers??t?.headers,params:o?.params??t?.params,query:o?.query??t?.query,response:o?.response??t?.response,detail:mergeDeep(o?.detail??{},t?.detail??{})}:void 0,transform:mergeObjectArray(e.transform??[],r?.transform??[]),beforeHandle:mergeObjectArray(e.beforeHandle??[],r?.beforeHandle??[]),parse:mergeObjectArray(e.parse??[],r?.parse??[]),afterHandle:mergeObjectArray(e.afterHandle??[],r?.afterHandle??[]),error:mergeObjectArray(e.error??[],r?.error??[]),type:e?.type||r?.type}};export const clone=e=>e;export const getPath=e=>{let r=e.indexOf("?",11),t=e.indexOf("#",12);return e.substring(e.indexOf("/",10),-1!==r?r:-1!==t?t:void 0)};export const getPathAndQuery=e=>{let r=e.indexOf("?",11),t=e.indexOf("#",12);return -1!==r?-1!==t?[e.substring(e.indexOf("/",10),r),e.substring(r+1,t)]:[e.substring(e.indexOf("/",10),r),e.substring(r+1)]:-1!==t?[e.substring(e.indexOf("/",10),t),""]:[e.substring(e.indexOf("/",10)),""]};export const removeHostnameRegex=/^[a-z]+?:\/\/[^/]+/;export const removeQueryRegex=/\?.*?([\w=&%]+)/;export const removePathRegex=/^[^?]*(\?|$)/;export const removeFragmentRegex=/#(\S+)/;let o=e=>e&&"object"==typeof e&&!Array.isArray(e);export const mergeDeep=(e,r)=>{let t=Object.assign({},e);return o(e)&&o(r)&&Object.keys(r).forEach(n=>{o(r[n])&&n in e?t[n]=mergeDeep(e[n],r[n]):Object.assign(t,{[n]:r[n]})}),t};export const createValidationError=(e,r,o)=>{let n=r.Errors(o).First(),i=`Invalid ${e}: '${n?.path?.slice(1)||"root"}'. ${n?.message}`;return new t({cause:i,type:e,validator:r,value:o})};export const getSchemaValidator=(e,t,o=!1)=>{if(!e||"string"==typeof e&&!(e in t))return;let n="string"==typeof e?t[e]:e;return"object"===n.type&&"additionalProperties"in n==!1&&(n.additionalProperties=o),r.Compile(n)};export const getResponseSchemaValidator=(t,o,n=!1)=>{if(!t||"string"==typeof t&&!(t in o))return;let i="string"==typeof t?o[t]:t;if(e in i)return{200:r.Compile(i)};let s={};return Object.keys(i).forEach(t=>{let a=i[t];if("string"==typeof a){if(a in o){let n=o[a];n.type,s[+t]=e in n?r.Compile(n):n}return}"object"===a.type&&"additionalProperties"in a==!1&&(a.additionalProperties=n),s[+t]=e in a?r.Compile(a):a}),s}; |
{ | ||
"name": "elysia", | ||
"description": "Fast, and friendly Bun web framework", | ||
"version": "0.5.0-exp-230427.2352", | ||
"version": "0.5.0-exp-230428.1515", | ||
"author": { | ||
@@ -6,0 +6,0 @@ "name": "saltyAom", |
@@ -83,5 +83,8 @@ import { Elysia } from '.' | ||
const hasStrictContentType = typeof hooks.type === 'string' | ||
const hasBody = | ||
method !== 'GET' && | ||
(validator.body || | ||
hasStrictContentType || | ||
[ | ||
@@ -95,2 +98,3 @@ handler, | ||
const maybeAsync = | ||
hasBody || | ||
handler.constructor.name === ASYNC_FN || | ||
@@ -100,7 +104,78 @@ hooks.parse.length || | ||
hooks.beforeHandle.find(isAsync) || | ||
hooks.transform.find(isAsync) || | ||
hasBody | ||
hooks.transform.find(isAsync) | ||
if (hasBody) { | ||
fnLiteral += ` | ||
if (hasBody) | ||
if (hasStrictContentType || validator.body) { | ||
if (!validator.body) fnLiteral += 'if(body) ' | ||
fnLiteral += `try {\n` | ||
if (validator.body) { | ||
// @ts-ignore | ||
const schema = validator.body.schema | ||
switch (schema.type) { | ||
case 'object': | ||
if (schema.elysiaMeta === 'URLEncoded') | ||
fnLiteral += `c.body = parseQuery(await c.request.text())` | ||
// Accept file which means it's formdata | ||
else if (validator.body.Code().includes("custom('File")) | ||
fnLiteral += `c.body = {} | ||
await c.request.formData().then((form) => { | ||
for (const key of form.keys()) { | ||
if (c.body[key]) | ||
continue | ||
const value = form.getAll(key) | ||
if (value.length === 1) | ||
c.body[key] = value[0] | ||
else c.body[key] = value | ||
} | ||
})` | ||
else { | ||
// Since it's an object an not accepting file | ||
// we can infer that it's JSON | ||
fnLiteral += `c.body = JSON.parse(await c.request.text())` | ||
} | ||
break | ||
case 'string': | ||
fnLiteral += 'c.body = await c.request.text()' | ||
break | ||
} | ||
} else | ||
switch (hooks.type) { | ||
case 'application/json': | ||
fnLiteral += `c.body = JSON.parse(await c.request.text());` | ||
break | ||
case 'text/plain': | ||
fnLiteral += `c.body = await c.request.text();` | ||
break | ||
case 'application/x-www-form-urlencoded': | ||
fnLiteral += `c.body = parseQuery(await c.request.text());` | ||
break | ||
case 'multipart/form-data': | ||
fnLiteral += `c.body = {} | ||
for (const key of (await c.request.formData()).keys()) { | ||
if (c.body[key]) | ||
continue | ||
const value = form.getAll(key) | ||
if (value.length === 1) | ||
c.body[key] = value[0] | ||
else c.body[key] = value | ||
}` | ||
break | ||
} | ||
fnLiteral += `} catch(error) { | ||
throw new Error('PARSE') | ||
}` | ||
} else { | ||
fnLiteral += ` | ||
let contentType = c.request.headers.get('content-type') | ||
@@ -113,9 +188,9 @@ | ||
if (hooks.parse.length) { | ||
fnLiteral += `let used = false\n` | ||
if (hooks.parse.length) { | ||
fnLiteral += `let used = false\n` | ||
for (let i = 0; i < hooks.parse.length; i++) { | ||
const name = `bo${i}` | ||
for (let i = 0; i < hooks.parse.length; i++) { | ||
const name = `bo${i}` | ||
fnLiteral += `if(!c.request.bodyUsed) { | ||
fnLiteral += `if(!c.request.bodyUsed) { | ||
let ${name} = parse[${i}](c, contentType); | ||
@@ -125,10 +200,10 @@ if(${name} instanceof Promise) ${name} = await ${name} | ||
}` | ||
} | ||
fnLiteral += `if (!used)` | ||
} | ||
fnLiteral += `if (!used)` | ||
} | ||
fnLiteral += `switch (contentType) { | ||
fnLiteral += `switch (contentType) { | ||
case 'application/json': | ||
c.body = await c.request.json() | ||
c.body = JSON.parse(await c.request.text()) | ||
break | ||
@@ -141,3 +216,3 @@ | ||
case 'application/x-www-form-urlencoded': | ||
c.body = await c.request.text().then(parseQuery) | ||
c.body = parseQuery(await c.request.text()) | ||
break | ||
@@ -148,13 +223,11 @@ | ||
await c.request.formData().then((form) => { | ||
for (const key of form.keys()) { | ||
if (c.body[key]) | ||
continue | ||
for (const key of (await c.request.formData()).keys()) { | ||
if (c.body[key]) | ||
continue | ||
const value = form.getAll(key) | ||
if (value.length === 1) | ||
c.body[key] = value[0] | ||
else c.body[key] = value | ||
} | ||
}) | ||
const value = form.getAll(key) | ||
if (value.length === 1) | ||
c.body[key] = value[0] | ||
else c.body[key] = value | ||
} | ||
@@ -164,4 +237,4 @@ break | ||
fnLiteral += `}}\n` | ||
} | ||
fnLiteral += `}}\n` | ||
} | ||
@@ -181,3 +254,3 @@ if (hooks?.transform) | ||
for (const key of c.request.headers.keys()) | ||
h[key] = c.request.headers.get(key) | ||
h[key] = c.request.headers.get(key) | ||
@@ -344,2 +417,4 @@ if (headers.Check(h) === false) { | ||
// console.log(fnLiteral) | ||
const createHandler = Function('hooks', fnLiteral) | ||
@@ -346,0 +421,0 @@ |
@@ -126,7 +126,4 @@ import { Type, type SchemaOptions } from '@sinclair/typebox' | ||
export const ElysiaType = { | ||
File: TypeSystem.CreateType<Blob, ElysiaTypeOptions.File>( | ||
'File', | ||
validateFile | ||
), | ||
Files: TypeSystem.CreateType<Blob[], ElysiaTypeOptions.Files>( | ||
File: TypeSystem.Type<Blob, ElysiaTypeOptions.File>('File', validateFile), | ||
Files: TypeSystem.Type<Blob[], ElysiaTypeOptions.Files>( | ||
'Files', | ||
@@ -154,7 +151,16 @@ (options, value) => { | ||
Files: typeof ElysiaType.Files | ||
URLEncoded: (typeof Type)['Object'] | ||
} | ||
} | ||
Type.URLEncoded = (property, options) => { | ||
return Type.Object(property, { | ||
...options, | ||
elysiaMeta: 'URLEncoded' | ||
}) as any | ||
} | ||
Type.File = (arg?: ElysiaTypeOptions.File) => | ||
ElysiaType.File({ | ||
elysiaMeta: 'File', | ||
default: 'File', | ||
@@ -170,2 +176,3 @@ ...arg, | ||
...arg, | ||
elysiaMeta: 'Files', | ||
default: 'Files', | ||
@@ -172,0 +179,0 @@ extension: arg?.type, |
import type { TypeCheck } from '@sinclair/typebox/compiler' | ||
import type { ErrorCode } from './types' | ||
const errorCodeToStatus = new Map<ErrorCode, number>() | ||
errorCodeToStatus.set('INTERNAL_SERVER_ERROR', 500) | ||
errorCodeToStatus.set('NOT_FOUND', 404) | ||
errorCodeToStatus.set('VALIDATION', 400) | ||
const errorCodeToStatus = new Map<ErrorCode, number>([ | ||
['INTERNAL_SERVER_ERROR', 500], | ||
['NOT_FOUND', 404], | ||
['VALIDATION', 400], | ||
['PARSE', 400] | ||
]) | ||
@@ -9,0 +11,0 @@ const knownErrors = new Set<ErrorCode>(errorCodeToStatus.keys()) |
@@ -144,5 +144,24 @@ import type { Serve, Server } from 'bun' | ||
if (hook?.type) | ||
switch (hook.type) { | ||
case 'text': | ||
hook.type = 'text/plain' | ||
break | ||
case 'json': | ||
hook.type = 'application/json' | ||
break | ||
case 'formdata': | ||
hook.type = 'multipart/form-data' | ||
break | ||
case 'urlencoded': | ||
hook.type = 'application/x-www-form-urlencoded' | ||
break | ||
} | ||
registerSchemaPath({ | ||
schema: this.meta[SCHEMA], | ||
contentType: hook?.schema?.contentType, | ||
contentType: hook?.type, | ||
hook, | ||
@@ -2267,13 +2286,15 @@ method, | ||
const key = `$$Elysia:${serve.port}` | ||
if (process.env.ENV !== 'production') { | ||
const key = `$$Elysia:${serve.port}` | ||
// ! Blasphemy ! | ||
// @ts-ignore | ||
if (globalThis[key]) { | ||
// ! Blasphemy ! | ||
// @ts-ignore | ||
this.server = globalThis[key] | ||
this.server!.reload(serve) | ||
} else { | ||
// @ts-ignore | ||
globalThis[key] = this.server = Bun.serve(serve) | ||
if (globalThis[key]) { | ||
// @ts-ignore | ||
this.server = globalThis[key] | ||
this.server!.reload(serve) | ||
} else { | ||
// @ts-ignore | ||
globalThis[key] = this.server = Bun.serve(serve) | ||
} | ||
} | ||
@@ -2287,3 +2308,3 @@ | ||
Promise.all(this.lazyLoadModules).then(() => { | ||
if (!this.server!.pendingRequests) Bun.gc(true) | ||
Bun.gc(true) | ||
}) | ||
@@ -2290,0 +2311,0 @@ |
@@ -111,2 +111,3 @@ import type { Elysia, ValidationError } from '.' | ||
> { | ||
type?: ContentType | ||
start: VoidLifeCycle<Instance>[] | ||
@@ -130,2 +131,3 @@ request: BeforeRequestHandler<any, Instance>[] | ||
> { | ||
type?: ContentType | ||
schema?: TypedSchema | ||
@@ -255,2 +257,10 @@ transform: NoReturnHandler<any, Instance>[] | ||
| (string & {}) | ||
// Shorthand for 'text/plain' | ||
| 'text' | ||
// Shorthand for 'application/json' | ||
| 'json' | ||
// Shorthand for 'multipart/form-data' | ||
| 'formdata' | ||
// Shorthand for 'application/x-www-form-urlencoded'\ | ||
| 'urlencoded' | ||
| 'text/plain' | ||
@@ -272,5 +282,5 @@ | 'application/json' | ||
> { | ||
type?: ContentType | ||
// ? I have no idea why does this infer type, but it work anyway | ||
schema?: (Models extends Schema ? Models : Models) & { | ||
contentType?: ContentType | ||
detail?: Partial<OpenAPIV3.OperationObject> | ||
@@ -509,3 +519,7 @@ } | ||
request: Request | ||
code: 'NOT_FOUND' | 'INTERNAL_SERVER_ERROR' | 'UNKNOWN' | ||
code: | ||
| 'NOT_FOUND' | ||
| 'INTERNAL_SERVER_ERROR' | ||
| 'UNKNOWN' | ||
| 'PARSE' | ||
error: Error | ||
@@ -512,0 +526,0 @@ set: Context['set'] |
@@ -60,3 +60,4 @@ import { Kind, TSchema } from '@sinclair/typebox' | ||
), | ||
error: mergeObjectArray(a.error ?? [], b?.error ?? []) | ||
error: mergeObjectArray(a.error ?? [], b?.error ?? []), | ||
type: a?.type || b?.type | ||
} | ||
@@ -63,0 +64,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
214155
5595
1