Comparing version 0.3.0-rc.6 to 0.3.0-rc.7
@@ -1,1 +0,1 @@ | ||
export const isNotEmpty=e=>{for(let s in e)return!0;return!1};let e=(e,s)=>{if(Array.isArray(s)){e.delete("Set-Cookie");for(let r=0;r<s.length;r++){let t=s[r].indexOf("=");e.append("Set-Cookie",`${s[r].slice(0,t)}=${s[r].slice(t+1)}`)}}return e};export const mapEarlyResponse=(s,r)=>{if(r.redirect&&(r.headers.Location=r.redirect,r.status=302),r.headers["Set-Cookie"]&&(r.headers=e(new Headers(r.headers),r.headers["Set-Cookie"])),isNotEmpty(r.headers)||200!==r.status)switch(typeof s){case"string":return new Response(s,{status:r.status,headers:r.headers});case"object":if(s instanceof Error)return errorToResponse(s,r.headers);if(s instanceof Response){for(let e in r.headers)s.headers.append(e,r.headers[e]);return s}if(s instanceof Blob)return new Response(s,{status:r.status,headers:r.headers});return r.headers["Content-Type"]||(r.headers["Content-Type"]="application/json"),new Response(JSON.stringify(s),{status:r.status,headers:r.headers});case"function":if(s instanceof Blob)return new Response(s,{status:r.status,headers:r.headers});for(let e in r.headers)s.headers.append(e,r.headers[e]);return s;case"number":case"boolean":return new Response(s.toString(),{status:r.status,headers:r.headers})}else switch(typeof s){case"string":return new Response(s);case"object":if(s instanceof Response)return s;if(s instanceof Error)return errorToResponse(s,r.headers);if(s instanceof Blob)return new Response(s);return new Response(JSON.stringify(s),{headers:{"content-type":"application/json"}});case"function":if(s instanceof Blob)return new Response(s);return s;case"number":case"boolean":return new Response(s.toString())}};export const mapResponse=(s,r)=>{if(r.redirect&&(r.headers.Location=r.redirect,r.status=302),r.headers?.["Set-Cookie"])switch(r.headers=e(new Headers(r.headers),r.headers["Set-Cookie"]),typeof s){case"string":return new Response(s,{status:r.status,headers:r.headers});case"object":switch(s.constructor){case Error:return errorToResponse(s,r.headers);case Response:for(let e in r.headers)s.headers.append(e,r.headers[e]);return s;case Blob:return new Response(s,{status:r.status,headers:r.headers});default:return r.headers["Content-Type"]||(r.headers instanceof Headers?r.headers.append("Content-Type","application/json"):r.headers["Content-Type"]="application/json"),new Response(JSON.stringify(s),{status:r.status,headers:r.headers})}case"function":if(s instanceof Blob)return new Response(s,{status:r.status,headers:r.headers});return s();case"number":case"boolean":return new Response(s.toString(),{status:r.status,headers:r.headers});case"undefined":return new Response("",{status:r.status,headers:r.headers});default:return new Response(s,{status:r.status,headers:r.headers})}if(r.redirect)return Response.redirect(r.redirect,{headers:r.headers});if(Object.keys(r.headers).length||200!==r.status)switch(typeof s){case"string":return new Response(s,{status:r.status,headers:r.headers});case"object":switch(s?.constructor){case Error:return errorToResponse(s,r.headers);case Response:for(let e in r.headers)s.headers.append(e,r.headers[e]);return s;case Blob:return new Response(s,{status:r.status,headers:r.headers});default:return r.headers["Content-Type"]||(r.headers["Content-Type"]="application/json"),new Response(JSON.stringify(s),{status:r.status,headers:r.headers})}case"function":if(s instanceof Blob)return new Response(s,{status:r.status,headers:r.headers});return s();case"number":case"boolean":return new Response(s.toString(),{status:r.status,headers:r.headers});case"undefined":return new Response("",{status:r.status,headers:r.headers});default:return new Response(s,{status:r.status,headers:r.headers})}else switch(typeof s){case"string":default:return new Response(s);case"object":if(s instanceof Response)return s;if(s instanceof Error)return errorToResponse(s,r.headers);if(s instanceof Blob)return new Response(s);return new Response(JSON.stringify(s),{headers:{"content-type":"application/json"}});case"function":if(s instanceof Blob)return new Response(s);return s();case"number":case"boolean":return new Response(s.toString());case"undefined":return new Response("")}};export const errorToResponse=(e,s)=>new Response(JSON.stringify({name:e?.name,message:e?.message,cause:e?.cause}),{status:500,headers:s}); | ||
export const isNotEmpty=e=>{for(let s in e)return!0;return!1};let e=(e,s)=>{if(Array.isArray(s)){e.delete("Set-Cookie");for(let r=0;r<s.length;r++){let t=s[r].indexOf("=");e.append("Set-Cookie",`${s[r].slice(0,t)}=${s[r].slice(t+1)}`)}}return e};export const mapEarlyResponse=(s,r)=>{if(isNotEmpty(r.headers)||200!==r.status||r.redirect)switch(r.redirect&&(r.headers.Location=r.redirect,r.status=302),r.headers["Set-Cookie"]&&(r.headers=e(new Headers(r.headers),r.headers["Set-Cookie"])),typeof s){case"string":return new Response(s,{status:r.status,headers:r.headers});case"object":if(s instanceof Error)return errorToResponse(s,r.headers);if(s instanceof Response){for(let e in r.headers)s.headers.append(e,r.headers[e]);return s}if(s instanceof Blob)return new Response(s,{status:r.status,headers:r.headers});return r.headers["Content-Type"]||(r.headers["Content-Type"]="application/json"),new Response(JSON.stringify(s),{status:r.status,headers:r.headers});case"function":if(s instanceof Blob)return new Response(s,{status:r.status,headers:r.headers});for(let e in r.headers)s.headers.append(e,r.headers[e]);return s;case"number":case"boolean":return new Response(s.toString(),{status:r.status,headers:r.headers})}else switch(typeof s){case"string":return new Response(s);case"object":if(s instanceof Response)return s;if(s instanceof Error)return errorToResponse(s,r.headers);if(s instanceof Blob)return new Response(s);return new Response(JSON.stringify(s),{headers:{"content-type":"application/json"}});case"function":if(s instanceof Blob)return new Response(s);return s;case"number":case"boolean":return new Response(s.toString())}};export const mapResponse=(s,r)=>{if(Object.keys(r.headers).length||200!==r.status||r.redirect)switch(r.redirect&&(r.headers.Location=r.redirect,r.status=302),r.headers?.["Set-Cookie"]&&(r.headers=e(new Headers(r.headers),r.headers["Set-Cookie"])),typeof s){case"string":return new Response(s,{status:r.status,headers:r.headers});case"object":switch(s?.constructor){case Error:return errorToResponse(s,r.headers);case Response:for(let e in r.headers)s.headers.append(e,r.headers[e]);return s;case Blob:return new Response(s,{status:r.status,headers:r.headers});default:return r.headers["Content-Type"]||(r.headers["Content-Type"]="application/json"),new Response(JSON.stringify(s),{status:r.status,headers:r.headers})}case"function":if(s instanceof Blob)return new Response(s,{status:r.status,headers:r.headers});return s();case"number":case"boolean":return new Response(s.toString(),{status:r.status,headers:r.headers});case"undefined":return new Response("",{status:r.status,headers:r.headers});default:return new Response(s,{status:r.status,headers:r.headers})}else switch(typeof s){case"string":default:return new Response(s);case"object":if(s instanceof Response)return s;if(s instanceof Error)return errorToResponse(s,r.headers);if(s instanceof Blob)return new Response(s);return new Response(JSON.stringify(s),{headers:{"content-type":"application/json"}});case"function":if(s instanceof Blob)return new Response(s);return s();case"number":case"boolean":return new Response(s.toString());case"undefined":return new Response("")}};export const errorToResponse=(e,s)=>new Response(JSON.stringify({name:e?.name,message:e?.message,cause:e?.cause}),{status:500,headers:s}); |
@@ -229,4 +229,4 @@ /// <reference types="bun-types" /> | ||
export { ws } from './ws'; | ||
export { SCHEMA, DEFS, EXPOSED, createValidationError, getSchemaValidator, mergeDeep, mergeHook, mergeObjectArray, mapPathnameAndQueryRegEx, mapQuery } from './utils'; | ||
export { SCHEMA, DEFS, EXPOSED, createValidationError, getSchemaValidator, mergeDeep, mergeHook, mergeObjectArray, mapPathnameAndQueryRegEx } from './utils'; | ||
export type { Context, PreContext } from './context'; | ||
export type { Handler, RegisteredHook, BeforeRequestHandler, TypedRoute, OverwritableTypeRoute, ElysiaInstance, ElysiaConfig, HTTPMethod, ComposedHandler, InternalRoute, BodyParser, ErrorHandler, ErrorCode, TypedSchema, LocalHook, LocalHandler, LifeCycle, LifeCycleEvent, AfterRequestHandler, HookHandler, TypedSchemaToRoute, UnwrapSchema, LifeCycleStore, VoidLifeCycle, SchemaValidator, ExtractPath, IsPathParameter, IsAny, IsNever, UnknownFallback, WithArray, ObjectValues, PickInOrder, MaybePromise, MergeIfNotNull, ElysiaDefaultMeta, TypedRouteToEden, AnyTypedSchema, RouteToSchema, DeepMergeTwoTypes, ConnectedKeysType } from './types'; |
@@ -1,1 +0,1 @@ | ||
import{nanoid as e}from"nanoid";import{Raikiri as t}from"raikiri";import{mapResponse as r,mapEarlyResponse as s}from"./handler";import{permission as a}from"./fn";import{SCHEMA as n,EXPOSED as i,DEFS as o,mapQuery as h,clone as l,mergeHook as d,mergeDeep as u,createValidationError as f,getSchemaValidator as m,getResponseSchemaValidator as c,mapPathnameAndQueryRegEx as p}from"./utils";import{registerSchemaPath as v}from"./schema";import{mapErrorCode as g,mapErrorStatus as y}from"./error";import{runFn as b}from"./fn";import{deserialize as w}from"superjson";export default class H{store={};meta={[n]:Object.create(null),[o]:Object.create(null),[i]:Object.create(null)};decorators={[n]:this.meta[n],[o]:this.meta[o]};event={start:[],request:[],parse:[],transform:[],beforeHandle:[],afterHandle:[],error:[],stop:[]};server=null;$schema=null;router=new t;routes=[];lazyLoadModules=[];constructor(e){this.config={fn:"/~fn",...e}}_addHandler(e,t,r,s){t=t.startsWith("/")?t:`/${t}`,this.routes.push({method:e,path:t,handler:r,hooks:d(l(this.event),s)});let a=this.meta[o],i=m(s?.schema?.body??this.$schema?.body,a),h=m(s?.schema?.headers??this.$schema?.headers,a,!0),u=m(s?.schema?.params??this.$schema?.params,a),f=m(s?.schema?.query??this.$schema?.query,a),p=c(s?.schema?.response??this.$schema?.response,a);v({schema:this.meta[n],contentType:s?.schema?.contentType,hook:s,method:e,path:t,models:this.meta[o]});let g=d(l(this.event),s);g.schema||g.transform.length||g.beforeHandle.length||g.error.length||g.afterHandle.length||(g=void 0);let y={handle:r,hooks:g,validator:i||h||u||f||p?{body:i,header:h,params:u,query:f,response:p}:void 0};this.router.add(e,t,y)}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 H;r.store=this.store;let s=t(r);return 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:r,handler:a,hooks:n})=>{"/"===r?this._addHandler(t,e,a,d(n,{error:s.event.error})):this._addHandler(t,`${e}${r}`,a,d(n,{error:s.event.error}))}),this}guard(e,t){let r=new H;r.store=this.store;let s=t(r);return 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:r,handler:s,hooks:a})=>{this._addHandler(t,r,s,d(e,a))}),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}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:m(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"},{beforeHandle:r.beforeHandle,transform:r.transform,schema:{headers:r.schema?.headers,params:r.schema?.params,query:r.schema?.query}}),this}route(e,t,r,s){return this._addHandler(e,t,r,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 0===Object.keys(this.meta[i]).length&&this.post(this.config.fn??"/~fn",e=>b(e,this.meta[i])),this.meta[i]=u(this.meta[i],"function"==typeof e?e({...this.decorators,store:this.store,permission:a}):e),this}schema(e){let t=this.meta[o];return this.$schema={body:m(e.body,t),headers:m(e?.headers,t,!0),params:m(e?.params,t),query:m(e?.query,t),response:m(e?.response,t)},this}handle=async e=>{let t;let a=Object.assign({query:{},set:{status:200,headers:{}},store:this.store,request:e},this.decorators);try{let n;if(this.event.request.length)for(let e=0;e<this.event.request.length;e++){let t=this.event.request[e](a);if(t instanceof Promise&&(t=await t),t=s(t,a.set))return t}let i=e.url.match(p);if(!i)throw Error("NOT_FOUND");let o=this.router.match(e.method,i[1])??this.router.match("ALL",i[1]);if(!o)throw Error("NOT_FOUND");let l=o.store,d=l.hooks;if(d?.error&&(t=d?.error),"GET"!==e.method){let t=e.headers.get("content-type");if(t){let r=t.indexOf(";");if(-1!==r&&(t=t.slice(0,r)),this.event.parse.length)for(let e=0;e<this.event.parse.length;e++){let r=this.event.parse[e](a,t);if(r instanceof Promise&&(r=await r),void 0!==r){n=r;break}}if(void 0===n)switch(t){case"application/json":n=await e.json();break;case"text/plain":n=await e.text();break;case"application/x-www-form-urlencoded":n=h(await e.text());break;case"multipart/form-data":n={},await e.formData().then(e=>{for(let t of e.keys()){if(t in n)continue;let r=e.getAll(t);1===r.length?n[t]=r[0]:n[t]=r}});break;case"elysia/fn":n=w(await e.json())}}}if(a.body=n,a.params=o.params,i[2]&&(a.query=h(i[2])),d?.transform.length)for(let e=0;e<d.transform.length;e++){let t=d.transform[e](a);t instanceof Promise&&await t}if(l.validator){let r=l.validator;if(d?.error&&(t=d?.error),r.headers){let t={};for(let r in e.headers)t[r]=e.headers.get(r);if(!1===r.headers.Check(t))throw f("header",r.headers,t)}if(!1===r.params?.Check(a.params))throw f("params",r.params,a.params);if(!1===r.query?.Check(a.query))throw f("query",r.query,a.query);if(!1===r.body?.Check(n))throw f("body",r.body,n)}if(d?.beforeHandle.length)for(let e=0;e<d.beforeHandle.length;e++){let t=d.beforeHandle[e](a);if(t instanceof Promise&&(t=await t),null!=t){for(let e=0;e<d.afterHandle.length;e++){let r=d.afterHandle[e](a,t);r instanceof Promise&&(r=await r),r&&(t=r)}let e=s(t,a.set);if(e)return e}}let u=l.handle(a);if(u instanceof Promise&&(u=await u),!1===l.validator?.response?.Check(u))throw d?.error&&(t=d?.error),f("response",l.validator.response,u);if(d?.afterHandle.length)for(let e=0;e<d.afterHandle.length;e++){let t=d.afterHandle[e](a,u);t instanceof Promise&&(t=await t);let r=s(t,a.set);if(r)return r}return r(u,a.set)}catch(n){let r=a.set;if((!r.status||r.status<300)&&(r.status=500),t){let a=g(n.message);for(let i=0;i<t.length;i++){let o=t[i]({request:e,error:n,set:r,code:a});o instanceof Promise&&(o=await o);let h=s(o,r);if(h)return h}}return this.handleError(e,n,r)}};async handleError(e,t,s={headers:{}}){for(let a=0;a<this.event.error.length;a++){let n=this.event.error[a]({request:e,code:g(t.message),error:t,set:s});if(n instanceof Promise&&(n=await n),null!=n)return r(n,s)}return new Response("string"==typeof t.cause?t.cause:t.message,{headers:s.headers,status:y(g(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.handle,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,mapPathnameAndQueryRegEx,mapQuery}from"./utils";export{H as Elysia,a as permission}; | ||
import{nanoid as e}from"nanoid";import{Raikiri as t}from"raikiri";import{parse as r}from"fast-querystring";import{mapResponse as s,mapEarlyResponse as a}from"./handler";import{permission as n}from"./fn";import{SCHEMA as i,EXPOSED as o,DEFS as h,clone as l,mergeHook as u,mergeDeep as d,createValidationError as f,getSchemaValidator as m,getResponseSchemaValidator as c,mapPathnameAndQueryRegEx as p}from"./utils";import{registerSchemaPath as v}from"./schema";import{mapErrorCode as g,mapErrorStatus as y}from"./error";import{runFn as b}from"./fn";import{deserialize as w}from"superjson";export default class H{store={};meta={[i]:Object.create(null),[h]:Object.create(null),[o]:Object.create(null)};decorators={[i]:this.meta[i],[h]:this.meta[h],store:this.store};event={start:[],request:[],parse:[],transform:[],beforeHandle:[],afterHandle:[],error:[],stop:[]};server=null;$schema=null;router=new t;routes=[];lazyLoadModules=[];constructor(e){this.config={fn:"/~fn",...e}}_addHandler(e,t,r,s){t=t.startsWith("/")?t:`/${t}`,this.routes.push({method:e,path:t,handler:r,hooks:u(l(this.event),s)});let a=this.meta[h],n=m(s?.schema?.body??this.$schema?.body,a),o=m(s?.schema?.headers??this.$schema?.headers,a,!0),d=m(s?.schema?.params??this.$schema?.params,a),f=m(s?.schema?.query??this.$schema?.query,a),p=c(s?.schema?.response??this.$schema?.response,a);v({schema:this.meta[i],contentType:s?.schema?.contentType,hook:s,method:e,path:t,models:this.meta[h]});let g=u(l(this.event),s);g.schema||g.transform.length||g.beforeHandle.length||g.error.length||g.afterHandle.length||(g=void 0);let y={handle:r,hooks:g,validator:n||o||d||f||p?{body:n,header:o,params:d,query:f,response:p}:void 0};this.router.add(e,t,y)}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 H;r.store=this.store;let s=t(r);return s.event.request.length&&(this.event.request=[...this.event.request,...s.event.request]),this.setModel(s.meta[h]),Object.values(r.routes).forEach(({method:t,path:r,handler:a,hooks:n})=>{"/"===r?this._addHandler(t,e,a,u(n,{error:s.event.error})):this._addHandler(t,`${e}${r}`,a,u(n,{error:s.event.error}))}),this}guard(e,t){let r=new H;r.store=this.store;let s=t(r);return s.event.request.length&&(this.event.request=[...this.event.request,...s.event.request]),this.setModel(s.meta[h]),Object.values(r.routes).forEach(({method:t,path:r,handler:s,hooks:a})=>{this._addHandler(t,r,s,u(e,a))}),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}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:m(r.schema?.body,this.meta[h]),transformMessage:r.transform?Array.isArray(r.transformMessage)?r.transformMessage:[r.transformMessage]:[]}}))return t.set.status=400,"Expected a websocket connection"},{beforeHandle:r.beforeHandle,transform:r.transform,schema:{headers:r.schema?.headers,params:r.schema?.params,query:r.schema?.query}}),this}route(e,t,r,s){return this._addHandler(e,t,r,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 0===Object.keys(this.meta[o]).length&&this.post(this.config.fn??"/~fn",async e=>b(e,this.meta[o])),this.meta[o]=d(this.meta[o],"function"==typeof e?e({...this.decorators,store:this.store,permission:n}):e),this}schema(e){let t=this.meta[h];return this.$schema={body:m(e.body,t),headers:m(e?.headers,t,!0),params:m(e?.params,t),query:m(e?.query,t),response:m(e?.response,t)},this}handle=async e=>{let t;let n=this.decorators;n.request=e,n.set={status:200,headers:{}};try{let i;for(let e=0;e<this.event.request.length;e++){let t=this.event.request[e](n);if(t instanceof Promise&&(t=await t),t=a(t,n.set))return t}let o=e.url.match(p);if(!o)throw Error("NOT_FOUND");let h=this.router.match(e.method,o[1])??this.router.match("ALL",o[1]);if(!h)throw Error("NOT_FOUND");let{hooks:l,validator:u}=h.store;if(l?.error&&(t=l?.error),"GET"!==e.method){let t=e.headers.get("content-type");if(t){let s=t.indexOf(";");-1!==s&&(t=t.slice(0,s));for(let e=0;e<this.event.parse.length;e++){let r=this.event.parse[e](n,t);if(r instanceof Promise&&(r=await r),void 0!==r){i=r;break}}if(void 0===i)switch(t){case"application/json":i=await e.json();break;case"text/plain":i=await e.text();break;case"application/x-www-form-urlencoded":i=r(await e.text());break;case"multipart/form-data":i={},await e.formData().then(e=>{for(let t of e.keys()){if(t in i)continue;let r=e.getAll(t);1===r.length?i[t]=r[0]:i[t]=r}});break;case"elysia/fn":i=w(await e.json())}}}if(n.body=i,n.params=h.params,o[2]?n.query=r(o[2]):n.query={},l)for(let e=0;e<l.transform.length;e++){let t=l.transform[e](n);t instanceof Promise&&await t}if(u){if(l?.error&&(t=l?.error),u.headers){let t={};for(let r in e.headers)t[r]=e.headers.get(r);if(!1===u.headers.Check(t))throw f("header",u.headers,t)}if(!1===u.params?.Check(n.params))throw f("params",u.params,n.params);if(!1===u.query?.Check(n.query))throw f("query",u.query,n.query);if(!1===u.body?.Check(i))throw f("body",u.body,i)}if(l)for(let e=0;e<l.beforeHandle.length;e++){let t=l.beforeHandle[e](n);if(t instanceof Promise&&(t=await t),null!=t){for(let e=0;e<l.afterHandle.length;e++){let r=l.afterHandle[e](n,t);r instanceof Promise&&(r=await r),r&&(t=r)}let e=a(t,n.set);if(e)return e}}let d=h.store.handle(n);if(d instanceof Promise&&(d=await d),!1===u?.response?.Check(d))throw l?.error&&(t=l.error),f("response",u.response,d);if(l)for(let e=0;e<l.afterHandle.length;e++){let t=l.afterHandle[e](n,d);t instanceof Promise&&(t=await t);let r=a(t,n.set);if(r)return r}return s(d,n.set)}catch(s){let r=n.set;if((!r.status||r.status<300)&&(r.status=500),t){let n=g(s.message);for(let i=0;i<t.length;i++){let o=t[i]({request:e,error:s,set:r,code:n});o instanceof Promise&&(o=await o);let h=a(o,r);if(h)return h}}return this.handleError(e,s,r)}};async handleError(e,t,r={headers:{}}){for(let a=0;a<this.event.error.length;a++){let n=this.event.error[a]({request:e,code:g(t.message),error:t,set:r});if(n instanceof Promise&&(n=await n),null!=n)return s(n,r)}return new Response("string"==typeof t.cause?t.cause:t.message,{headers:r.headers,status:y(g(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.handle,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[h]||(this.meta[h][e]=t)}),this}}export{t}from"./custom-types";export{ws}from"./ws";export{SCHEMA,DEFS,EXPOSED,createValidationError,getSchemaValidator,mergeDeep,mergeHook,mergeObjectArray,mapPathnameAndQueryRegEx}from"./utils";export{H as Elysia,n as permission}; |
@@ -11,3 +11,2 @@ import { TSchema } from '@sinclair/typebox'; | ||
export declare const mapPathnameAndQueryRegEx: RegExp; | ||
export declare const mapQuery: (url: string) => Record<string, string>; | ||
export declare const mergeDeep: <A extends Object = Object, B extends Object = Object>(target: A, source: B) => DeepMergeTwoTypes<A, B>; | ||
@@ -14,0 +13,0 @@ export declare const createValidationError: (type: string, validator: TypeCheck<any>, value: any) => Error; |
@@ -1,1 +0,1 @@ | ||
import{Kind as e,Type as r}from"@sinclair/typebox";import{TypeCompiler as t}from"@sinclair/typebox/compiler";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??[]),afterHandle:mergeObjectArray(e.afterHandle??[],r?.afterHandle??[]),error:mergeObjectArray(e.error??[],r?.error??[])}};export const clone=e=>e;export const mapPathnameAndQueryRegEx=/:\/\/[^/]+([^#?]+)(?:\?([^#]+))?/;export const mapQuery=e=>{let r={},t=e.split("&");for(let e=0;e<t.length;e++){let o=t[e],n=o.indexOf("="),a=o.slice(n+1);a.includes("%")&&(a=decodeURIComponent(a)),r[o.slice(0,n)]=a}return r};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,t)=>{let o=r.Errors(t).next().value;return Error("VALIDATION",{cause:`Invalid ${e}: '${o?.path?.slice(1)||"root"}'. ${o.message}`})};export const getSchemaValidator=(e,r,o=!1)=>{if(!e||"string"==typeof e&&!(e in r))return;let n="string"==typeof e?r[e]:e;return"object"===n.type&&"additionalProperties"in n==!1&&(n.additionalProperties=o),t.Compile(n)};export const getResponseSchemaValidator=(o,n,a=!1)=>{if(!o||"string"==typeof o&&!(o in n))return;let s="string"==typeof o?n[o]:o,i=e in s?s:r.Union(Object.keys(s).map(e=>{let r=s[e];if("string"==typeof r){if(r in n){let e=n[r];return e}return}return r}).filter(e=>e));"object"===i.type&&"additionalProperties"in i==!1&&(i.additionalProperties=a);try{return t.Compile(i)}catch(e){return s}}; | ||
import{Kind as e,Type as r}from"@sinclair/typebox";import{TypeCompiler as t}from"@sinclair/typebox/compiler";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??[]),afterHandle:mergeObjectArray(e.afterHandle??[],r?.afterHandle??[]),error:mergeObjectArray(e.error??[],r?.error??[])}};export const clone=e=>e;export const mapPathnameAndQueryRegEx=/:\/\/[^/]+([^#?]+)(?:\?([^#]+))?/;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(a=>{o(r[a])&&a in e?t[a]=mergeDeep(e[a],r[a]):Object.assign(t,{[a]:r[a]})}),t};export const createValidationError=(e,r,t)=>{let o=r.Errors(t).next().value;return Error("VALIDATION",{cause:`Invalid ${e}: '${o?.path?.slice(1)||"root"}'. ${o.message}`})};export const getSchemaValidator=(e,r,o=!1)=>{if(!e||"string"==typeof e&&!(e in r))return;let a="string"==typeof e?r[e]:e;return"object"===a.type&&"additionalProperties"in a==!1&&(a.additionalProperties=o),t.Compile(a)};export const getResponseSchemaValidator=(o,a,n=!1)=>{if(!o||"string"==typeof o&&!(o in a))return;let s="string"==typeof o?a[o]:o,i=e in s?s:r.Union(Object.keys(s).map(e=>{let r=s[e];if("string"==typeof r){if(r in a){let e=a[r];return e}return}return r}).filter(e=>e));"object"===i.type&&"additionalProperties"in i==!1&&(i.additionalProperties=n);try{return t.Compile(i)}catch(e){return s}}; |
{ | ||
"name": "elysia", | ||
"description": "Fast, and friendly Bun web framework", | ||
"version": "0.3.0-rc.6", | ||
"version": "0.3.0-rc.7", | ||
"author": { | ||
@@ -94,6 +94,7 @@ "name": "saltyAom", | ||
"dependencies": { | ||
"@sinclair/typebox": "^0.25.21", | ||
"@sinclair/typebox": "^0.25.24", | ||
"fast-querystring": "^1.1.1", | ||
"nanoid": "^4.0.1", | ||
"openapi-types": "^12.1.0", | ||
"raikiri": "^0.0.0-beta.8", | ||
"raikiri": "^0.1.0-beta.0", | ||
"superjson": "^1.12.2" | ||
@@ -113,3 +114,3 @@ }, | ||
"peerDependencies": { | ||
"@sinclair/typebox": ">= 0.25.21", | ||
"@sinclair/typebox": ">= 0.25.24", | ||
"openapi-types": ">= 12.0.0" | ||
@@ -116,0 +117,0 @@ }, |
@@ -30,15 +30,15 @@ import type { Context } from './context' | ||
export const mapEarlyResponse = (response: unknown, set: Context['set']) => { | ||
if (set.redirect) { | ||
set.headers.Location = set.redirect | ||
set.status = 302 | ||
} | ||
if (isNotEmpty(set.headers) || set.status !== 200 || set.redirect) { | ||
if (set.redirect) { | ||
set.headers.Location = set.redirect | ||
set.status = 302 | ||
} | ||
if (set.headers['Set-Cookie']) | ||
// @ts-ignore | ||
set.headers = parseSetCookies( | ||
new Headers(set.headers), | ||
set.headers['Set-Cookie'] | ||
) | ||
if (set.headers['Set-Cookie']) | ||
// @ts-ignore | ||
set.headers = parseSetCookies( | ||
new Headers(set.headers), | ||
set.headers['Set-Cookie'] | ||
) | ||
if (isNotEmpty(set.headers) || set.status !== 200) | ||
switch (typeof response) { | ||
@@ -100,3 +100,3 @@ case 'string': | ||
} | ||
else | ||
} else | ||
switch (typeof response) { | ||
@@ -137,94 +137,15 @@ case 'string': | ||
): Response => { | ||
if (set.redirect) { | ||
set.headers.Location = set.redirect | ||
set.status = 302 | ||
} | ||
if (set.headers?.['Set-Cookie']) { | ||
// @ts-ignore | ||
set.headers = parseSetCookies( | ||
new Headers(set.headers), | ||
set.headers['Set-Cookie'] | ||
) | ||
switch (typeof response) { | ||
case 'string': | ||
return new Response(response, { | ||
status: set.status, | ||
headers: set.headers | ||
}) | ||
case 'object': | ||
switch (response!.constructor) { | ||
case Error: | ||
return errorToResponse(response as Error, set.headers) | ||
case Response: | ||
for (const key in set.headers) | ||
(response as Response)!.headers.append( | ||
key, | ||
set.headers[key] | ||
) | ||
return response as Response | ||
case Blob: | ||
return new Response(response as Blob, { | ||
status: set.status, | ||
headers: set.headers | ||
}) | ||
default: | ||
if (!set.headers['Content-Type']) | ||
if (set.headers instanceof Headers) | ||
set.headers.append( | ||
'Content-Type', | ||
'application/json' | ||
) | ||
else | ||
set.headers['Content-Type'] = 'application/json' | ||
return new Response(JSON.stringify(response), { | ||
status: set.status, | ||
headers: set.headers | ||
}) | ||
} | ||
// ? Maybe response function or Blob | ||
case 'function': | ||
if (response instanceof Blob) | ||
return new Response(response, { | ||
status: set.status, | ||
headers: set.headers | ||
}) | ||
return response() | ||
case 'number': | ||
case 'boolean': | ||
return new Response(response.toString(), { | ||
status: set.status, | ||
headers: set.headers | ||
}) | ||
case 'undefined': | ||
return new Response('', { | ||
status: set.status, | ||
headers: set.headers | ||
}) | ||
default: | ||
return new Response(response as any, { | ||
status: set.status, | ||
headers: set.headers | ||
}) | ||
if (Object.keys(set.headers).length || set.status !== 200 || set.redirect) { | ||
if (set.redirect) { | ||
set.headers.Location = set.redirect | ||
set.status = 302 | ||
} | ||
} | ||
if (set.redirect) | ||
return Response.redirect(set.redirect, { | ||
headers: set.headers | ||
}) | ||
if (set.headers?.['Set-Cookie']) | ||
// @ts-ignore | ||
set.headers = parseSetCookies( | ||
new Headers(set.headers), | ||
set.headers['Set-Cookie'] | ||
) | ||
if (Object.keys(set.headers).length || set.status !== 200) | ||
switch (typeof response) { | ||
@@ -296,3 +217,3 @@ case 'string': | ||
} | ||
else | ||
} else | ||
switch (typeof response) { | ||
@@ -299,0 +220,0 @@ case 'string': |
@@ -5,2 +5,4 @@ import type { Serve, Server } from 'bun' | ||
import { Raikiri } from 'raikiri' | ||
import { parse as parseQuery } from 'fast-querystring' | ||
import { mapResponse, mapEarlyResponse } from './handler' | ||
@@ -12,3 +14,2 @@ import { permission, type Permission } from './fn' | ||
DEFS, | ||
mapQuery, | ||
clone, | ||
@@ -65,2 +66,4 @@ mergeHook, | ||
const ASYNC_FN = 'AsyncFunction' | ||
/** | ||
@@ -92,3 +95,4 @@ * ### Elysia Server | ||
[SCHEMA]: this.meta[SCHEMA], | ||
[DEFS]: this.meta[DEFS] | ||
[DEFS]: this.meta[DEFS], | ||
store: this.store | ||
} | ||
@@ -1545,3 +1549,4 @@ | ||
this.config.fn ?? '/~fn', | ||
(context) => runFn(context, this.meta[EXPOSED]) as any | ||
// @ts-ignore | ||
async (context) => runFn(context, this.meta[EXPOSED]) | ||
) | ||
@@ -1608,14 +1613,8 @@ } | ||
handle = async (request: Request): Promise<Response> => { | ||
const context = Object.assign( | ||
{ | ||
query: {}, | ||
set: { | ||
status: 200, | ||
headers: {} | ||
}, | ||
store: this.store, | ||
request | ||
}, | ||
this.decorators | ||
) as any as Context | ||
const context: Context = this.decorators as any as Context | ||
context.request = request | ||
context.set = { | ||
status: 200, | ||
headers: {} | ||
} | ||
@@ -1625,10 +1624,9 @@ let handleErrors: ErrorHandler[] | undefined | ||
try { | ||
if (this.event.request.length) | ||
for (let i = 0; i < this.event.request.length; i++) { | ||
let response = this.event.request[i](context) | ||
if (response instanceof Promise) response = await response | ||
for (let i = 0; i < this.event.request.length; i++) { | ||
let response = this.event.request[i](context) | ||
if (response instanceof Promise) response = await response | ||
response = mapEarlyResponse(response, context.set) | ||
if (response) return response | ||
} | ||
response = mapEarlyResponse(response, context.set) | ||
if (response) return response | ||
} | ||
@@ -1643,5 +1641,6 @@ const fracture = request.url.match(mapPathnameAndQueryRegEx) | ||
if (!route) throw new Error('NOT_FOUND') | ||
const handler = route.store! | ||
const { hooks, validator } = route.store! | ||
const hooks = handler.hooks | ||
// const hooks = handler.hooks | ||
// const validator = handler.validator | ||
if (hooks?.error) handleErrors = hooks?.error | ||
@@ -1657,12 +1656,11 @@ | ||
if (this.event.parse.length) | ||
for (let i = 0; i < this.event.parse.length; i++) { | ||
let temp = this.event.parse[i](context, contentType) | ||
if (temp instanceof Promise) temp = await temp | ||
for (let i = 0; i < this.event.parse.length; i++) { | ||
let temp = this.event.parse[i](context, contentType) | ||
if (temp instanceof Promise) temp = await temp | ||
if (temp !== undefined) { | ||
body = temp | ||
break | ||
} | ||
if (temp !== undefined) { | ||
body = temp | ||
break | ||
} | ||
} | ||
@@ -1681,3 +1679,3 @@ // body might be empty string thus can't use !body | ||
case 'application/x-www-form-urlencoded': | ||
body = mapQuery(await request.text()) | ||
body = parseQuery(await request.text()) | ||
break | ||
@@ -1716,5 +1714,6 @@ | ||
context.params = route.params | ||
if (fracture[2]) context.query = mapQuery(fracture[2]) | ||
if (fracture[2]) context.query = parseQuery(fracture[2]) | ||
else context.query = {} | ||
if (hooks?.transform.length) | ||
if (hooks) | ||
for (let i = 0; i < hooks.transform.length; i++) { | ||
@@ -1725,5 +1724,3 @@ const operation = hooks.transform[i](context) | ||
if (handler.validator) { | ||
const validator = handler.validator | ||
if (validator) { | ||
if (hooks?.error) handleErrors = hooks?.error | ||
@@ -1762,3 +1759,3 @@ | ||
if (hooks?.beforeHandle.length) | ||
if (hooks) | ||
for (let i = 0; i < hooks.beforeHandle.length; i++) { | ||
@@ -1786,11 +1783,11 @@ let response = hooks.beforeHandle[i](context) | ||
let response = handler.handle(context) | ||
let response = route.store!.handle(context) | ||
if (response instanceof Promise) response = await response | ||
if (handler.validator?.response?.Check(response) === false) { | ||
if (hooks?.error) handleErrors = hooks?.error | ||
if (validator?.response?.Check(response) === false) { | ||
if (hooks?.error) handleErrors = hooks.error | ||
throw createValidationError( | ||
'response', | ||
handler.validator.response, | ||
validator.response, | ||
response | ||
@@ -1800,3 +1797,3 @@ ) | ||
if (hooks?.afterHandle.length) | ||
if (hooks) | ||
for (let i = 0; i < hooks.afterHandle.length; i++) { | ||
@@ -1995,4 +1992,3 @@ let newResponse = hooks.afterHandle[i](context, response) | ||
mergeObjectArray, | ||
mapPathnameAndQueryRegEx, | ||
mapQuery | ||
mapPathnameAndQueryRegEx | ||
} from './utils' | ||
@@ -1999,0 +1995,0 @@ |
@@ -71,17 +71,2 @@ import { Kind, TSchema, Type } from '@sinclair/typebox' | ||
export const mapQuery = (url: string) => { | ||
const mapped: Record<string, string> = {} | ||
const paths = url.split('&') | ||
for (let i = 0; i < paths.length; i++) { | ||
const part = paths[i] | ||
const index = part.indexOf('=') | ||
let value = part.slice(index + 1) | ||
if (value.includes('%')) value = decodeURIComponent(value) | ||
mapped[part.slice(0, index)] = value | ||
} | ||
return mapped | ||
} | ||
const isObject = (item: any): item is Object => | ||
@@ -88,0 +73,0 @@ item && typeof item === 'object' && !Array.isArray(item) |
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
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
166422
8
4394
+ Addedfast-querystring@^1.1.1
+ Addedfast-decode-uri-component@1.0.1(transitive)
+ Addedfast-querystring@1.1.2(transitive)
+ Addedraikiri@0.1.3(transitive)
- Removedraikiri@0.0.0-beta.8(transitive)
Updated@sinclair/typebox@^0.25.24
Updatedraikiri@^0.1.0-beta.0