elysia 0.4.3 → 0.4.4
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/compose.js +2 -2
- package/dist/handler.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/compose.ts +4 -3
- package/src/handler.ts +18 -17
- package/src/index.ts +4 -6
package/dist/compose.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{parse as e}from"fast-querystring";import{
|
|
1
|
+
import{parse as e}from"fast-querystring";import{mapEarlyResponse as r,mapResponse as t}from"./handler";import{createValidationError as a}from"./utils";import{mapErrorCode as s}from"./error";let n="AsyncFunction",o=e=>e.constructor.name===n;export const composeHandler=({method:c,hooks:l,validator:d,handler:i,handleError:f})=>{let p="try {\n",u="GET"!==c||i.constructor.name===n||l.parse.length||l.afterHandle.find(o)||l.beforeHandle.find(o)||l.transform.find(o);if(u){if(p+=`
|
|
2
2
|
let contentType = c.request.headers.get('content-type');
|
|
3
3
|
|
|
4
4
|
if (contentType) {
|
|
@@ -126,4 +126,4 @@ if(${r}) return ${r};
|
|
|
126
126
|
}
|
|
127
127
|
} = hooks
|
|
128
128
|
|
|
129
|
-
return ${u?"async":""} function(c) {${p}}`.replace(/\t/g,"");let h=Function("hooks",p);return h({handler:i,hooks:l,validator:d,handleError:f,utils:{createValidationError:
|
|
129
|
+
return ${u?"async":""} function(c) {${p}}`.replace(/\t/g,"");let h=Function("hooks",p);return h({handler:i,hooks:l,validator:d,handleError:f,utils:{createValidationError:a,mapResponse:t,mapEarlyResponse:r,mapErrorCode:s,parseQuery:e}})};
|
package/dist/handler.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const isNotEmpty=e=>{for(let s in e)return!0;return!1};let e=(e,s)=>{
|
|
1
|
+
export const isNotEmpty=e=>{for(let s in e)return!0;return!1};let e=(e,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)||r.status||r.redirect)switch(r.redirect&&(r.headers.Location=r.redirect,r.status=302),r.headers["Set-Cookie"]&&Array.isArray(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});case Promise:return s.then(e=>{let s=mapEarlyResponse(e,r);if(void 0!==s)return s});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});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":switch(s?.constructor){case Error:return errorToResponse(s,r.headers);case Response:return s;case Blob:return new Response(s);case Promise:return s.then(e=>{let s=mapEarlyResponse(e,r);if(void 0!==s)return s});default: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(isNotEmpty(r.headers)||r.status||r.redirect)switch(r.redirect&&(r.headers.Location=r.redirect,r.status=302),r.headers["Set-Cookie"]&&Array.isArray(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});case Promise:return s.then(e=>mapResponse(e,r));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":return new Response(s);case"object":switch(s?.constructor){case Error:return errorToResponse(s,r.headers);case Response:return s;case Blob:return new Response(s);case Promise:return s.then(e=>mapResponse(e,r));default: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("");default:return new Response(s)}};export const errorToResponse=(e,s)=>new Response(JSON.stringify({name:e?.name,message:e?.message,cause:e?.cause}),{status:500,headers:s});
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
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{SCHEMA as
|
|
1
|
+
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{SCHEMA as i,EXPOSED as o,DEFS as h,clone as n,mergeHook as u,getSchemaValidator as d,getResponseSchemaValidator as l,mapPathnameAndQueryRegEx as c,mergeDeep as m}from"./utils";import{registerSchemaPath as p}from"./schema";import{mapErrorCode as f,mapErrorStatus as v}from"./error";import{composeHandler as y}from"./compose";import{ws as g}from"./ws";export default class b{config;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=[];wsRouter;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({...this.event},s)});let a=this.meta[h],o=d(s?.schema?.body??this.$schema?.body,a),c=d(s?.schema?.headers??this.$schema?.headers,a,!0),m=d(s?.schema?.params??this.$schema?.params,a),f=d(s?.schema?.query??this.$schema?.query,a),v=l(s?.schema?.response??this.$schema?.response,a);p({schema:this.meta[i],contentType:s?.schema?.contentType,hook:s,method:e,path:t,models:this.meta[h]});let g=u(n(this.event),s),b={handle:y({method:e,hooks:g,validator:{body:o,headers:c,params:m,query:f,response:v},handler:r,handleError:this.handleError}),onError:g.error};this.router.add(e,t,b)}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 b;r.store=this.store,this.wsRouter&&r.use(g());let s=t(r);return this.decorators=m(this.decorators,r.decorators),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:a,handler:i,hooks:o})=>{let h="/"===a?e:`${e}${a}`,n=r.wsRouter?.match("subscribe",h);if(n){let e=r.wsRouter.history.find(([e,t])=>a===t);if(!e)return;return this.ws(h,e[2])}this._addHandler(t,h,i,u(o,{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 b;r.store=this.store,this.wsRouter&&r.use(g());let s=t(r);return this.decorators=m(this.decorators,r.decorators),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:s,handler:a,hooks:i})=>{let o=r.wsRouter?.match("subscribe",s);if(o){let e=r.wsRouter.history.find(([e,t])=>s===t);if(!e)return;return this.ws(s,e[2])}this._addHandler(t,s,a,u(e,i))}),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:d(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 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[h];return this.$schema={body:d(e.body,t),headers:d(e?.headers,t,!0),params:d(e?.params,t),query:d(e?.query,t),response:d(e?.response,t)},this}handle=async e=>this.innerHandle(e);innerHandle=e=>{let t=this.decorators;if(t.request=e,t.set={headers:{},status:200},this.event.request.length)try{for(let e=0;e<this.event.request.length;e++){let r=a(this.event.request[e](t),t.set);if(r)return r}}catch(r){return this.handleError(e,r,t.set)}let s=c.exec(e.url),i=this.router.match(e.method,s[1])??this.router.match("ALL",s[1]);return i?(t.params=i.params,s[2]?t.query=r(s[2]):t.query={},i.store.handle(t)):this.handleError(e,Error("NOT_FOUND"),t.set)};handleError=async(e,t,r={headers:{}})=>{for(let a=0;a<this.event.error.length;a++){let i=this.event.error[a]({request:e,code:f(t.message),error:t,set:r});if(i instanceof Promise&&(i=await i),null!=i)return s(i,r)}return new Response("string"==typeof t.cause?t.cause:t.message,{headers:r.headers,status:v(f(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.innerHandle,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{ElysiaError,ValidationError}from"./validation";export{b as Elysia};
|
package/package.json
CHANGED
package/src/compose.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
import { Elysia } from '.'
|
|
2
|
+
|
|
1
3
|
import { parse as parseQuery } from 'fast-querystring'
|
|
2
4
|
|
|
3
|
-
import { createValidationError } from './utils'
|
|
4
5
|
import { mapEarlyResponse, mapResponse } from './handler'
|
|
6
|
+
import { createValidationError } from './utils'
|
|
7
|
+
import { mapErrorCode } from './error'
|
|
5
8
|
|
|
6
|
-
import { Elysia } from '.'
|
|
7
9
|
import type {
|
|
8
10
|
HTTPMethod,
|
|
9
11
|
LocalHandler,
|
|
10
12
|
RegisteredHook,
|
|
11
13
|
SchemaValidator
|
|
12
14
|
} from './types'
|
|
13
|
-
import { mapErrorCode } from './error'
|
|
14
15
|
|
|
15
16
|
const ASYNC_FN = 'AsyncFunction'
|
|
16
17
|
const isAsync = (x: Function) => x.constructor.name === ASYNC_FN
|
package/src/handler.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/* eslint-disable no-case-declarations */
|
|
2
|
-
import type { MaybePromise } from './types'
|
|
3
2
|
import type { Context } from './context'
|
|
4
3
|
|
|
5
4
|
export const isNotEmpty = (obj: Object) => {
|
|
@@ -8,20 +7,16 @@ export const isNotEmpty = (obj: Object) => {
|
|
|
8
7
|
return false
|
|
9
8
|
}
|
|
10
9
|
|
|
11
|
-
const parseSetCookies = (headers: Headers, setCookie: string
|
|
12
|
-
|
|
13
|
-
headers.delete('Set-Cookie')
|
|
10
|
+
const parseSetCookies = (headers: Headers, setCookie: string[]) => {
|
|
11
|
+
headers.delete('Set-Cookie')
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
for (let i = 0; i < setCookie.length; i++) {
|
|
14
|
+
const index = setCookie[i].indexOf('=')
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
)}`
|
|
23
|
-
)
|
|
24
|
-
}
|
|
16
|
+
headers.append(
|
|
17
|
+
'Set-Cookie',
|
|
18
|
+
`${setCookie[i].slice(0, index)}=${setCookie[i].slice(index + 1)}`
|
|
19
|
+
)
|
|
25
20
|
}
|
|
26
21
|
|
|
27
22
|
return headers
|
|
@@ -32,13 +27,16 @@ export const mapEarlyResponse = (
|
|
|
32
27
|
response: unknown,
|
|
33
28
|
set: Context['set']
|
|
34
29
|
): Response | undefined => {
|
|
35
|
-
if (isNotEmpty(set.headers) || set.status
|
|
30
|
+
if (isNotEmpty(set.headers) || set.status || set.redirect) {
|
|
36
31
|
if (set.redirect) {
|
|
37
32
|
set.headers.Location = set.redirect
|
|
38
33
|
set.status = 302
|
|
39
34
|
}
|
|
40
35
|
|
|
41
|
-
if (
|
|
36
|
+
if (
|
|
37
|
+
set.headers['Set-Cookie'] &&
|
|
38
|
+
Array.isArray(set.headers['Set-Cookie'])
|
|
39
|
+
)
|
|
42
40
|
// @ts-ignore
|
|
43
41
|
set.headers = parseSetCookies(
|
|
44
42
|
new Headers(set.headers),
|
|
@@ -171,13 +169,16 @@ export const mapResponse = (
|
|
|
171
169
|
response: unknown,
|
|
172
170
|
set: Context['set']
|
|
173
171
|
): Response => {
|
|
174
|
-
if (
|
|
172
|
+
if (isNotEmpty(set.headers) || set.status || set.redirect) {
|
|
175
173
|
if (set.redirect) {
|
|
176
174
|
set.headers.Location = set.redirect
|
|
177
175
|
set.status = 302
|
|
178
176
|
}
|
|
179
177
|
|
|
180
|
-
if (
|
|
178
|
+
if (
|
|
179
|
+
set.headers['Set-Cookie'] &&
|
|
180
|
+
Array.isArray(set.headers['Set-Cookie'])
|
|
181
|
+
)
|
|
181
182
|
// @ts-ignore
|
|
182
183
|
set.headers = parseSetCookies(
|
|
183
184
|
new Headers(set.headers),
|
package/src/index.ts
CHANGED
|
@@ -1817,8 +1817,6 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
|
|
|
1817
1817
|
path,
|
|
1818
1818
|
// @ts-ignore
|
|
1819
1819
|
(context) => {
|
|
1820
|
-
console.log('Got', context.request.url)
|
|
1821
|
-
|
|
1822
1820
|
if (
|
|
1823
1821
|
// @ts-ignore
|
|
1824
1822
|
this.server?.upgrade(context.request, {
|
|
@@ -2169,14 +2167,14 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
|
|
|
2169
2167
|
/**
|
|
2170
2168
|
* Handle can be either sync or async to save performance.
|
|
2171
2169
|
*
|
|
2172
|
-
* Beside
|
|
2170
|
+
* Beside benchmark purpose, please use 'handle' instead.
|
|
2173
2171
|
*/
|
|
2174
2172
|
innerHandle = (request: Request): MaybePromise<Response> => {
|
|
2175
2173
|
const context: Context = this.decorators as any as Context
|
|
2176
2174
|
context.request = request
|
|
2177
2175
|
context.set = {
|
|
2178
|
-
|
|
2179
|
-
|
|
2176
|
+
headers: {},
|
|
2177
|
+
status: 200
|
|
2180
2178
|
}
|
|
2181
2179
|
|
|
2182
2180
|
if (this.event.request.length)
|
|
@@ -2192,7 +2190,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
|
|
|
2192
2190
|
return this.handleError(request, error as Error, context.set)
|
|
2193
2191
|
}
|
|
2194
2192
|
|
|
2195
|
-
const fracture = request.url
|
|
2193
|
+
const fracture = mapPathnameAndQueryRegEx.exec(request.url)!
|
|
2196
2194
|
const route =
|
|
2197
2195
|
this.router.match(request.method, fracture[1]) ??
|
|
2198
2196
|
this.router.match('ALL', fracture[1])
|