elysia 0.4.14 → 0.5.0-beta.0
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/cjs/compose.d.ts +17 -0
- package/dist/cjs/compose.js +257 -0
- package/dist/cjs/context.d.ts +20 -0
- package/dist/cjs/context.js +1 -0
- package/dist/cjs/custom-types.d.ts +30 -0
- package/dist/cjs/custom-types.js +1 -0
- package/dist/cjs/error.d.ts +24 -0
- package/dist/cjs/error.js +1 -0
- package/dist/cjs/handler.d.ts +6 -0
- package/dist/cjs/handler.js +1 -0
- package/dist/cjs/index.d.ts +445 -0
- package/dist/cjs/index.js +5 -0
- package/dist/cjs/schema.d.ts +15 -0
- package/dist/cjs/schema.js +1 -0
- package/dist/cjs/types.d.ts +263 -0
- package/dist/cjs/types.js +1 -0
- package/dist/cjs/utils.d.ts +11 -0
- package/dist/cjs/utils.js +1 -0
- package/dist/cjs/ws/index.d.ts +28 -0
- package/dist/cjs/ws/index.js +1 -0
- package/dist/cjs/ws/types.d.ts +55 -0
- package/dist/cjs/ws/types.js +1 -0
- package/dist/compose.d.ts +12 -4
- package/dist/compose.js +185 -57
- package/dist/context.d.ts +4 -3
- package/dist/custom-types.d.ts +5 -1
- package/dist/custom-types.js +1 -1
- package/dist/error.d.ts +20 -11
- package/dist/error.js +1 -1
- package/dist/handler.js +1 -1
- package/dist/index.d.ts +78 -37
- package/dist/index.js +5 -1
- package/dist/schema.d.ts +3 -6
- package/dist/schema.js +1 -1
- package/dist/types.d.ts +78 -54
- package/dist/utils.d.ts +1 -5
- package/dist/utils.js +1 -1
- package/dist/ws/index.js +1 -1
- package/dist/ws/types.d.ts +2 -0
- package/package.json +20 -11
- package/dist/validation.d.ts +0 -16
- package/dist/validation.js +0 -1
- package/src/compose.ts +0 -295
- package/src/context.ts +0 -31
- package/src/custom-types.ts +0 -179
- package/src/error.ts +0 -32
- package/src/handler.ts +0 -335
- package/src/index.ts +0 -2462
- package/src/schema.ts +0 -209
- package/src/types.ts +0 -593
- package/src/utils.ts +0 -180
- package/src/validation.ts +0 -26
- package/src/ws/index.ts +0 -230
- package/src/ws/types.ts +0 -199
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Elysia } from '.';
|
|
2
|
+
import { SCHEMA, DEFS } from './utils';
|
|
3
|
+
import type { ComposedHandler, HTTPMethod, LocalHandler, RegisteredHook, SchemaValidator } from './types';
|
|
4
|
+
import { TAnySchema } from '@sinclair/typebox';
|
|
5
|
+
export declare const hasReturn: (fnLiteral: string) => boolean;
|
|
6
|
+
export declare const isFnUse: (keyword: string, fnLiteral: string) => boolean;
|
|
7
|
+
export declare const findElysiaMeta: (type: string, schema: TAnySchema, found?: string[], parent?: string) => string[] | "root" | null;
|
|
8
|
+
export declare const composeHandler: ({ path, method, hooks, validator, handler, handleError, meta }: {
|
|
9
|
+
path: string;
|
|
10
|
+
method: HTTPMethod;
|
|
11
|
+
hooks: RegisteredHook<any>;
|
|
12
|
+
validator: SchemaValidator;
|
|
13
|
+
handler: LocalHandler<any, any>;
|
|
14
|
+
handleError: Elysia['handleError'];
|
|
15
|
+
meta?: (Record<typeof SCHEMA, {}> & Record<typeof DEFS, {}> & Record<typeof import("./utils").EXPOSED, {}>) | undefined;
|
|
16
|
+
}) => ComposedHandler;
|
|
17
|
+
export declare const composeGeneralHandler: (app: Elysia<any>) => any;
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import{parse as e}from"fast-querystring";import{mapEarlyResponse as r,mapResponse as t}from"./handler";import{SCHEMA as a,DEFS as s}from"./utils";import{ParseError as o,NotFoundError as n,ValidationError as c,InternalServerError as l}from"./error";let i="AsyncFunction",f=e=>e.constructor.name===i,d=new Headers,u=RegExp(" (\\w+) = context","g");export const hasReturn=e=>{let r=e.indexOf(")");return 61===e.charCodeAt(r+2)&&123!==e.charCodeAt(r+5)||e.includes("return")};export const isFnUse=(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.match(RegExp(`${t}(.${e}|\\["${e}"\\])`)))return!0;let a=[t];for(let e of r.matchAll(u))a.push(e[1]);let s=RegExp(`{.*?} = (${a.join("|")})`,"g");for(let[t]of r.matchAll(s))if(t.includes(`{ ${e}`)||t.includes(`, ${e}`))return!0;return!1};export const findElysiaMeta=(e,r,t=[],a="")=>{if("object"===r.type){let s=r.properties;for(let r in s){let o=s[r],n=a?a+"."+r:r;if("object"===o.type){findElysiaMeta(e,o,t,n);continue}if(o.anyOf){for(let r of o.anyOf)findElysiaMeta(e,r,t,n);continue}o.elysiaMeta===e&&t.push(n)}return 0===t.length?null:t}return r?.elysiaMeta===e?(a&&t.push(a),"root"):null};export const composeHandler=({path:u,method:p,hooks:y,validator:h,handler:m,handleError:$,meta:b})=>{let w="try {\n",E="string"==typeof y.type,q=h||"GET"!==p?[m,...y.transform,...y.beforeHandle,...y.afterHandle].map(e=>e.toString()):[],g="GET"!==p&&(h.body||E||q.some(e=>isFnUse("body",e))),k=h.headers||q.some(e=>isFnUse("headers",e));k&&(w+=d.toJSON?`c.headers = c.request.headers.toJSON()
|
|
2
|
+
`:`c.headers = {}
|
|
3
|
+
for (const key of c.request.headers.keys())
|
|
4
|
+
h[key] = c.request.headers.get(key)
|
|
5
|
+
|
|
6
|
+
if (headers.Check(h) === false) {
|
|
7
|
+
throw throw new ValidationError(
|
|
8
|
+
'header',
|
|
9
|
+
headers,
|
|
10
|
+
h
|
|
11
|
+
)
|
|
12
|
+
}
|
|
13
|
+
`);let x=h.query||q.some(e=>isFnUse("query",e));x&&(w+=`const url = c.request.url
|
|
14
|
+
|
|
15
|
+
if(url.charCodeAt(c.query) === 63 || (c.query = url.indexOf("?", ${11+u.split("/").map(e=>e.startsWith(":")?"-":"").length})) !== -1) {
|
|
16
|
+
c.query = parseQuery(url.substring(c.query + 1))
|
|
17
|
+
} else {
|
|
18
|
+
c.query = {}
|
|
19
|
+
}
|
|
20
|
+
`);let H=g||m.constructor.name===i||y.parse.length||y.afterHandle.find(f)||y.beforeHandle.find(f)||y.transform.find(f);if(g){let e=h?.body?.schema;if(e&&"anyOf"in e){let r=!1,t=e.anyOf[0].type;for(let a of e.anyOf)if(a.type!==t){r=!0;break}r&&(e=void 0)}if(E||e){if(e)"object"===e.type?"URLEncoded"===e.elysiaMeta?w+="c.body = parseQuery(await c.request.text())":h.body.Code().includes("custom('File")?w+=`c.body = {}
|
|
21
|
+
|
|
22
|
+
await c.request.formData().then((form) => {
|
|
23
|
+
for (const key of form.keys()) {
|
|
24
|
+
if (c.body[key])
|
|
25
|
+
continue
|
|
26
|
+
|
|
27
|
+
const value = form.getAll(key)
|
|
28
|
+
if (value.length === 1)
|
|
29
|
+
c.body[key] = value[0]
|
|
30
|
+
else c.body[key] = value
|
|
31
|
+
}
|
|
32
|
+
})`:w+="c.body = JSON.parse(await c.request.text())":w+="c.body = await c.request.text()";else switch(y.type){case"application/json":w+="c.body = JSON.parse(await c.request.text());";break;case"text/plain":w+="c.body = await c.request.text();";break;case"application/x-www-form-urlencoded":w+="c.body = parseQuery(await c.request.text());";break;case"multipart/form-data":w+=`c.body = {}
|
|
33
|
+
|
|
34
|
+
for (const key of (await c.request.formData()).keys()) {
|
|
35
|
+
if (c.body[key])
|
|
36
|
+
continue
|
|
37
|
+
|
|
38
|
+
const value = form.getAll(key)
|
|
39
|
+
if (value.length === 1)
|
|
40
|
+
c.body[key] = value[0]
|
|
41
|
+
else c.body[key] = value
|
|
42
|
+
}`}}else{if(w+="\n"+(k?"let contentType = c.headers['content-type']":"let contentType = c.request.headers.get('content-type')")+`
|
|
43
|
+
if (contentType) {
|
|
44
|
+
const index = contentType.indexOf(';')
|
|
45
|
+
if (index !== -1) contentType = contentType.substring(0, index)
|
|
46
|
+
`,y.parse.length){w+=`let used = false
|
|
47
|
+
`;for(let e=0;e<y.parse.length;e++){let r=`bo${e}`;w+=`if(!c.request.bodyUsed) {
|
|
48
|
+
let ${r} = parse[${e}](c, contentType);
|
|
49
|
+
if(${r} instanceof Promise) ${r} = await ${r}
|
|
50
|
+
if(${r} !== undefined) { c.body = ${r}; used = true }
|
|
51
|
+
}`}w+="if (!used)"}w+=`switch (contentType) {
|
|
52
|
+
case 'application/json':
|
|
53
|
+
c.body = JSON.parse(await c.request.text())
|
|
54
|
+
break
|
|
55
|
+
|
|
56
|
+
case 'text/plain':
|
|
57
|
+
c.body = await c.request.text()
|
|
58
|
+
break
|
|
59
|
+
|
|
60
|
+
case 'application/x-www-form-urlencoded':
|
|
61
|
+
c.body = parseQuery(await c.request.text())
|
|
62
|
+
break
|
|
63
|
+
|
|
64
|
+
case 'multipart/form-data':
|
|
65
|
+
c.body = {}
|
|
66
|
+
|
|
67
|
+
for (const key of (await c.request.formData()).keys()) {
|
|
68
|
+
if (c.body[key])
|
|
69
|
+
continue
|
|
70
|
+
|
|
71
|
+
const value = form.getAll(key)
|
|
72
|
+
if (value.length === 1)
|
|
73
|
+
c.body[key] = value[0]
|
|
74
|
+
else c.body[key] = value
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
break
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
`}w+="\n"}if(h.params){let e=findElysiaMeta("Numeric",h.params.schema);if(e){if("object"==typeof e)for(let r of e)w+=`c.params.${r} = +c.params.${r}`;w+="\n"}}if(h.query){let e=findElysiaMeta("Numeric",h.query.schema);if(e){if("object"==typeof e)for(let r of e)w+=`c.query.${r} = +c.query.${r}`;w+="\n"}}if(h.headers){let e=findElysiaMeta("Numeric",h.headers.schema);if(e){if("object"==typeof e)for(let r of e)w+=`c.headers.${r} = +c.headers.${r}`;w+="\n"}}if(h.body){let e=findElysiaMeta("Numeric",h.body.schema);if(e){switch(typeof e){case"string":w+="c.body = +c.body";break;case"object":for(let r of e)w+=`c.body.${r} = +c.body.${r}`}w+="\n"}}if(y?.transform)for(let e=0;e<y.transform.length;e++)w+=y.transform[e].constructor.name===i?`await transform[${e}](c);`:`transform[${e}](c);`;if(h&&(h.headers&&(w+=`
|
|
81
|
+
if (headers.Check(c.headers) === false) {
|
|
82
|
+
throw new ValidationError(
|
|
83
|
+
'header',
|
|
84
|
+
headers,
|
|
85
|
+
c.headers
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
`),h.params&&(w+="if(params.Check(c.params) === false) { throw new ValidationError('params', params, c.params) }"),h.query&&(w+="if(query.Check(c.query) === false) { throw new ValidationError('query', query, c.query) }"),h.body&&(w+="if(body.Check(c.body) === false) { throw new ValidationError('body', body, c.body) }")),y?.beforeHandle)for(let e=0;e<y.beforeHandle.length;e++){let r=`be${e}`,t=hasReturn(y.beforeHandle[e].toString());if(t){if(w+=(y.beforeHandle[e].constructor.name===i?`let ${r} = await beforeHandle[${e}](c);
|
|
89
|
+
`:`let ${r} = beforeHandle[${e}](c);
|
|
90
|
+
`)+`if(${r} !== undefined) {
|
|
91
|
+
`,y?.afterHandle)for(let e=0;e<y.afterHandle.length;e++){let t=hasReturn(y.afterHandle[e].toString());if(t){let t=`af${e}`;w+=(y.afterHandle[e].constructor.name===i?`const ${t} = await afterHandle[${e}](c, ${r});
|
|
92
|
+
`:`const ${t} = afterHandle[${e}](c, ${r});
|
|
93
|
+
`)+`if(${t} !== undefined) { ${r} = ${t} }
|
|
94
|
+
`}else w+=y.afterHandle[e].constructor.name===i?`await afterHandle[${e}](c, ${r});
|
|
95
|
+
`:`afterHandle[${e}](c, ${r});
|
|
96
|
+
`}h.response&&(w+=`if(response[c.set.status]?.Check(${r}) === false) {
|
|
97
|
+
if(!(response instanceof Error))
|
|
98
|
+
throw new ValidationError('response', response[c.set.status], ${r})
|
|
99
|
+
}
|
|
100
|
+
`),w+=`return mapEarlyResponse(${r}, c.set)}
|
|
101
|
+
`}else w+=y.beforeHandle[e].constructor.name===i?`await beforeHandle[${e}](c);
|
|
102
|
+
`:`beforeHandle[${e}](c);
|
|
103
|
+
`}if(y?.afterHandle.length){w+=m.constructor.name===i?`let r = await handler(c);
|
|
104
|
+
`:`let r = handler(c);
|
|
105
|
+
`;for(let e=0;e<y.afterHandle.length;e++){let r=`af${e}`,t=hasReturn(y.afterHandle[e].toString());t?(w+=y.afterHandle[e].constructor.name===i?`let ${r} = await afterHandle[${e}](c, r)
|
|
106
|
+
`:`let ${r} = afterHandle[${e}](c, r)
|
|
107
|
+
`,h.response?w+=`if(response[c.set.status]?.Check(${r}) === false) {
|
|
108
|
+
if(!(response instanceof Error))
|
|
109
|
+
throw new ValidationError('response', response[c.set.status], ${r})
|
|
110
|
+
}
|
|
111
|
+
${r} = mapEarlyResponse(${r}, c.set)
|
|
112
|
+
if(${r}) return ${r};
|
|
113
|
+
`:w+=`if(${r}) return ${r};
|
|
114
|
+
`):w+=y.afterHandle[e].constructor.name===i?`await afterHandle[${e}](c, r)
|
|
115
|
+
`:`afterHandle[${e}](c, r)
|
|
116
|
+
`}h.response&&(w+=`if(response[c.set.status]?.Check(r) === false) {
|
|
117
|
+
if(!(response instanceof Error))
|
|
118
|
+
throw new ValidationError('response', response[c.set.status], r)
|
|
119
|
+
}
|
|
120
|
+
`),w+=`return mapResponse(r, c.set);
|
|
121
|
+
`}else h.response?w+=(m.constructor.name===i?`const r = await handler(c);
|
|
122
|
+
`:`const r = handler(c);
|
|
123
|
+
`)+`if(response[c.set.status]?.Check(r) === false) {
|
|
124
|
+
if(!(response instanceof Error))
|
|
125
|
+
throw new ValidationError('response', response[c.set.status], r)
|
|
126
|
+
}
|
|
127
|
+
`+"return mapResponse(r, c.set);":w+=m.constructor.name===i?"return mapResponse(await handler(c), c.set);":"return mapResponse(handler(c), c.set);";w+=`
|
|
128
|
+
} catch(error) {
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
${H?"":"return (async () => {"}
|
|
132
|
+
const set = c.set
|
|
133
|
+
|
|
134
|
+
if (!set.status || set.status < 300) set.status = 500
|
|
135
|
+
|
|
136
|
+
${y.error.length?`for (let i = 0; i < handleErrors.length; i++) {
|
|
137
|
+
let handled = handleErrors[i]({
|
|
138
|
+
request: c.request,
|
|
139
|
+
error: error,
|
|
140
|
+
set,
|
|
141
|
+
code: error.code ?? "UNKNOWN"
|
|
142
|
+
})
|
|
143
|
+
if (handled instanceof Promise) handled = await handled
|
|
144
|
+
|
|
145
|
+
const response = mapEarlyResponse(handled, set)
|
|
146
|
+
if (response) return response
|
|
147
|
+
}`:""}
|
|
148
|
+
|
|
149
|
+
return handleError(c.request, error, set)
|
|
150
|
+
${H?"":"})()"}
|
|
151
|
+
}`,w=`const {
|
|
152
|
+
handler,
|
|
153
|
+
handleError,
|
|
154
|
+
hooks: {
|
|
155
|
+
transform,
|
|
156
|
+
beforeHandle,
|
|
157
|
+
afterHandle,
|
|
158
|
+
parse,
|
|
159
|
+
error: handleErrors
|
|
160
|
+
},
|
|
161
|
+
validator: {
|
|
162
|
+
body,
|
|
163
|
+
headers,
|
|
164
|
+
params,
|
|
165
|
+
query,
|
|
166
|
+
response
|
|
167
|
+
},
|
|
168
|
+
utils: {
|
|
169
|
+
mapResponse,
|
|
170
|
+
mapEarlyResponse,
|
|
171
|
+
mapErrorCode,
|
|
172
|
+
parseQuery
|
|
173
|
+
},
|
|
174
|
+
error: {
|
|
175
|
+
ParseError,
|
|
176
|
+
NotFoundError,
|
|
177
|
+
ValidationError,
|
|
178
|
+
InternalServerError
|
|
179
|
+
},
|
|
180
|
+
${b?`
|
|
181
|
+
meta,
|
|
182
|
+
SCHEMA,
|
|
183
|
+
DEFS,`:""}
|
|
184
|
+
} = hooks
|
|
185
|
+
|
|
186
|
+
const parseError = new ParseError()
|
|
187
|
+
|
|
188
|
+
return ${H?"async":""} function(c) {
|
|
189
|
+
${b?"c[SCHEMA] = meta[SCHEMA]; c[DEFS] = meta[DEFS];":""}
|
|
190
|
+
${w}
|
|
191
|
+
}`;let v=Function("hooks",w);return v({handler:m,hooks:y,validator:h,handleError:$,utils:{mapResponse:t,mapEarlyResponse:r,parseQuery:e},error:{ParseError:o,NotFoundError:n,ValidationError:c,InternalServerError:l},meta:b,SCHEMA:b?a:void 0,DEFS:b?s:void 0})};export const composeGeneralHandler=e=>{let t="";for(let r of Object.keys(e.decorators))t+=`,${r}: app.decorators.${r}`;let a=e.staticRouter,s="";for(let[e,r]of Object.entries(a.map))s+=`case '${e}':
|
|
192
|
+
switch(method) {
|
|
193
|
+
${r}}
|
|
194
|
+
|
|
195
|
+
`;let o=`const {
|
|
196
|
+
app,
|
|
197
|
+
app: { store, router, staticRouter },
|
|
198
|
+
${e.event.request.length?"mapEarlyResponse,":""}
|
|
199
|
+
NotFoundError
|
|
200
|
+
} = data
|
|
201
|
+
|
|
202
|
+
const getPath = /\\/[^?#]+/g
|
|
203
|
+
const notFound = new NotFoundError()
|
|
204
|
+
|
|
205
|
+
${e.event.request.length?`const onRequest = app.event.request
|
|
206
|
+
const requestLength = app.event.request.length`:""}
|
|
207
|
+
|
|
208
|
+
${a.variables}
|
|
209
|
+
|
|
210
|
+
const find = router.find.bind(router)
|
|
211
|
+
|
|
212
|
+
return function(request) {
|
|
213
|
+
const ctx = {
|
|
214
|
+
request,
|
|
215
|
+
store,
|
|
216
|
+
set: {
|
|
217
|
+
headers: {},
|
|
218
|
+
status: 200
|
|
219
|
+
}
|
|
220
|
+
${t}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
${e.event.request.length?`
|
|
224
|
+
try {
|
|
225
|
+
for (let i = 0; i < requestLength; i++) {
|
|
226
|
+
const response = mapEarlyResponse(
|
|
227
|
+
onRequest[i](ctx),
|
|
228
|
+
ctx.set
|
|
229
|
+
)
|
|
230
|
+
if (response) return response
|
|
231
|
+
}
|
|
232
|
+
} catch (error) {
|
|
233
|
+
return app.handleError(request, error, ctx.set)
|
|
234
|
+
}`:""}
|
|
235
|
+
|
|
236
|
+
getPath.lastIndex = 11
|
|
237
|
+
const { url, method } = request,
|
|
238
|
+
path = getPath.exec(url)?.[0] ?? '/'
|
|
239
|
+
|
|
240
|
+
ctx.query = getPath.lastIndex
|
|
241
|
+
|
|
242
|
+
switch(path) {
|
|
243
|
+
${s}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const route = find(method, path)
|
|
247
|
+
if (route === null)
|
|
248
|
+
return app.handleError(
|
|
249
|
+
request,
|
|
250
|
+
notFound,
|
|
251
|
+
ctx.set
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
ctx.params = route.params
|
|
255
|
+
|
|
256
|
+
return route.store(ctx)
|
|
257
|
+
}`;return Function("data",o)({app:e,mapEarlyResponse:r,NotFoundError:n})};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
2
|
+
import type { Elysia, TypedRoute, DEFS, SCHEMA, TypedSchema } from '.';
|
|
3
|
+
export interface Context<Route extends TypedRoute = TypedRoute, Store extends Elysia['store'] = Elysia['store']> {
|
|
4
|
+
request: Request;
|
|
5
|
+
headers: undefined extends Route['headers'] ? Record<string, unknown> : Route['headers'];
|
|
6
|
+
query: undefined extends Route['query'] ? Record<string, unknown> : Route['query'];
|
|
7
|
+
params: Route['params'];
|
|
8
|
+
body: Route['body'];
|
|
9
|
+
store: Store;
|
|
10
|
+
[SCHEMA]?: TypedSchema;
|
|
11
|
+
[DEFS]?: {
|
|
12
|
+
[index: string]: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
set: {
|
|
15
|
+
headers: Record<string, string>;
|
|
16
|
+
status?: number;
|
|
17
|
+
redirect?: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export type PreContext<Route extends TypedRoute = TypedRoute, Store extends Elysia['store'] = Elysia['store']> = Omit<Context<Route, Store>, 'query' | 'params' | 'body'>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
2
|
+
import { Type, type SchemaOptions, type NumericOptions } from '@sinclair/typebox';
|
|
3
|
+
type MaybeArray<T> = T | T[];
|
|
4
|
+
export declare namespace ElysiaTypeOptions {
|
|
5
|
+
type Numeric = NumericOptions<number>;
|
|
6
|
+
type FileUnit = number | `${number}${'k' | 'm'}`;
|
|
7
|
+
interface File extends SchemaOptions {
|
|
8
|
+
type?: MaybeArray<(string & {}) | 'image' | 'image/jpeg' | 'image/png' | 'image/gif' | 'image/tiff' | 'image/x-icon' | 'image/svg' | 'image/webp' | 'image/avif' | 'audio' | 'audio/mpeg' | 'audio/x-ms-wma' | 'audio/vnd.rn-realaudio' | 'audio/x-wav' | 'video' | 'video/mpeg' | 'video/mp4' | 'video/quicktime' | 'video/x-ms-wmv' | 'video/x-msvideo' | 'video/x-flv' | 'video/webm' | 'text' | 'text/css' | 'text/csv' | 'text/html' | 'text/javascript' | 'text/plain' | 'text/xml' | 'application' | 'application/ogg' | 'application/pdf' | 'application/xhtml' | 'application/html' | 'application/json' | 'application/ld+json' | 'application/xml' | 'application/zip'>;
|
|
9
|
+
minSize?: FileUnit;
|
|
10
|
+
maxSize?: FileUnit;
|
|
11
|
+
}
|
|
12
|
+
interface Files extends File {
|
|
13
|
+
minItems?: number;
|
|
14
|
+
maxItems?: number;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export declare const ElysiaType: {
|
|
18
|
+
readonly Numeric: (options?: Partial<NumericOptions<number>> | undefined) => import("@sinclair/typebox").TUnsafe<number>;
|
|
19
|
+
readonly File: (options?: Partial<ElysiaTypeOptions.File> | undefined) => import("@sinclair/typebox").TUnsafe<Blob>;
|
|
20
|
+
readonly Files: (options?: Partial<ElysiaTypeOptions.Files> | undefined) => import("@sinclair/typebox").TUnsafe<Blob[]>;
|
|
21
|
+
};
|
|
22
|
+
declare module '@sinclair/typebox' {
|
|
23
|
+
interface TypeBuilder {
|
|
24
|
+
Numeric: typeof ElysiaType.Numeric;
|
|
25
|
+
File: typeof ElysiaType.File;
|
|
26
|
+
Files: typeof ElysiaType.Files;
|
|
27
|
+
URLEncoded: (typeof Type)['Object'];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export { Type as t };
|
|
@@ -0,0 +1 @@
|
|
|
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={Numeric:t.Type("Numeric",{}),File:t.Type("File",r),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(!r(e,t[i]))return!1;return!0})};e.Numeric=t=>e.Number({...t,elysiaMeta:"Numeric"}),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};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { TypeCheck } from '@sinclair/typebox/compiler';
|
|
2
|
+
export declare class InternalServerError extends Error {
|
|
3
|
+
code: string;
|
|
4
|
+
status: number;
|
|
5
|
+
constructor();
|
|
6
|
+
}
|
|
7
|
+
export declare class NotFoundError extends Error {
|
|
8
|
+
code: string;
|
|
9
|
+
status: number;
|
|
10
|
+
constructor();
|
|
11
|
+
}
|
|
12
|
+
export declare class ParseError extends Error {
|
|
13
|
+
code: string;
|
|
14
|
+
status: number;
|
|
15
|
+
constructor();
|
|
16
|
+
}
|
|
17
|
+
export declare class ValidationError extends Error {
|
|
18
|
+
validator: TypeCheck<any>;
|
|
19
|
+
value: unknown;
|
|
20
|
+
code: string;
|
|
21
|
+
status: number;
|
|
22
|
+
constructor(type: string, validator: TypeCheck<any>, value: unknown);
|
|
23
|
+
get all(): import("@sinclair/typebox/compiler").ValueError[];
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class InternalServerError extends Error{code="NOT_FOUND";status=500;constructor(){super("INTERNAL_SERVER_ERROR")}}export class NotFoundError extends Error{code="NOT_FOUND";status=404;constructor(){super("NOT_FOUND")}}export class ParseError extends Error{code="PARSE";status=400;constructor(){super("PARSE")}}export class ValidationError extends Error{validator;value;code;status;constructor(r,t,s){let o=t.Errors(s).First();super(`Invalid ${r}: '${o?.path?.slice(1)||"root"}'. ${o?.message}`),this.validator=t,this.value=s,this.code="VALIDATION",this.status=400}get all(){return[...this.validator.Errors(this.value)]}}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
2
|
+
import type { Context } from './context';
|
|
3
|
+
export declare const isNotEmpty: (obj: Object) => boolean;
|
|
4
|
+
export declare const mapEarlyResponse: (response: unknown, set: Context['set']) => Response | undefined;
|
|
5
|
+
export declare const mapResponse: (response: unknown, set: Context['set']) => Response;
|
|
6
|
+
export declare const errorToResponse: (error: Error, headers?: HeadersInit) => Response;
|
|
@@ -0,0 +1 @@
|
|
|
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)||200!==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.name){case"Object":case"Array":case void 0:return Response.json(s,{status:r.status,headers:r.headers});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":default: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})}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?.name){case"Object":case"Array":case void 0:return Response.json(s);case"Response":return s;case"Error":return errorToResponse(s,r.headers);case"Blob":default:return new Response(s);case"Promise":return s.then(e=>{let s=mapEarlyResponse(e,r);if(void 0!==s)return s})}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)||200!==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?.name){case"Object":case"Array":case void 0:return Response.json(s,{status:r.status,headers:r.headers});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":default:return new Response(s,{status:r.status,headers:r.headers});case"Promise":return s.then(e=>mapResponse(e,r))}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?.name){case"Object":case"Array":case void 0:return Response.json(s);case"Response":return s;case"Error":return errorToResponse(s,r.headers);case"Blob":default:return new Response(s);case"Promise":return s.then(e=>{let s=mapEarlyResponse(e,r);return void 0!==s?s:new Response("")})}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});
|