elysia 1.4.29 → 1.4.31
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/SECURITY.md +27 -0
- package/dist/adapter/bun/compose.js +9 -4
- package/dist/adapter/bun/compose.mjs +9 -4
- package/dist/adapter/bun/handler-native.js +22 -7
- package/dist/adapter/bun/handler-native.mjs +22 -7
- package/dist/adapter/bun/index.js +22 -13
- package/dist/adapter/bun/index.mjs +22 -13
- package/dist/adapter/utils.js +63 -18
- package/dist/adapter/utils.mjs +63 -18
- package/dist/adapter/web-standard/index.js +3 -55
- package/dist/adapter/web-standard/index.mjs +3 -55
- package/dist/compose.js +50 -90
- package/dist/compose.mjs +54 -90
- package/dist/dynamic-handle.js +135 -145
- package/dist/dynamic-handle.mjs +147 -146
- package/dist/error.d.ts +11 -19
- package/dist/error.js +296 -47
- package/dist/error.mjs +289 -47
- package/dist/form-data.d.ts +3 -0
- package/dist/form-data.js +124 -0
- package/dist/form-data.mjs +103 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +38 -35
- package/dist/index.mjs +40 -38
- package/dist/replace-schema.js +8 -3
- package/dist/replace-schema.mjs +8 -3
- package/dist/schema.d.ts +8 -3
- package/dist/schema.js +368 -7
- package/dist/schema.mjs +366 -7
- package/dist/types.d.ts +12 -1
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +62 -14
- package/dist/utils.mjs +60 -14
- package/dist/ws/index.d.ts +1 -1
- package/dist/ws/index.js +111 -55
- package/dist/ws/index.mjs +111 -55
- package/package.json +4 -4
package/SECURITY.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
**Do not open a public issue for security vulnerabilities.**
|
|
4
|
+
|
|
5
|
+
Please report privately via [GitHub Security Advisories](https://github.com/elysiajs/elysia/security/advisories/new).
|
|
6
|
+
|
|
7
|
+
Please include:
|
|
8
|
+
|
|
9
|
+
- A description of the vulnerability and its impact
|
|
10
|
+
- A minimal reproduction (an `Elysia` app + the request that triggers it)
|
|
11
|
+
- The affected version(s)
|
|
12
|
+
|
|
13
|
+
You should receive an initial response within 7 days. Once confirmed, a fix will be developed privately and released with a coordinated advisory. Credit is given to reporters unless anonymity is requested.
|
|
14
|
+
|
|
15
|
+
The advisory will be published publicly once patch is published after ~7 days and the issue will be closed. If you have any questions, please contact maintainers eg. [saltyaom@gmail.com](mailto:saltyaom@gmail.com).
|
|
16
|
+
|
|
17
|
+
## Scope
|
|
18
|
+
|
|
19
|
+
In scope:
|
|
20
|
+
|
|
21
|
+
- The `elysia` package (this repository)
|
|
22
|
+
|
|
23
|
+
Out of scope:
|
|
24
|
+
|
|
25
|
+
- Official plugins and ecosystem packages (report to their own repositories under [elysiajs](https://github.com/elysiajs))
|
|
26
|
+
- Vulnerabilities in Bun or other runtimes
|
|
27
|
+
- Issues requiring a malicious or misconfigured application (e.g. developer-controlled schemas or handlers), unless they cross a trust boundary for end-user input
|
|
@@ -19,7 +19,11 @@ __export(compose_exports, {
|
|
|
19
19
|
});
|
|
20
20
|
module.exports = __toCommonJS(compose_exports);
|
|
21
21
|
var import_handler = require('./handler.js'), import_sucrose = require('../../sucrose.js'), import_compose = require('../../compose.js'), import_utils = require('../../utils.js'), import_error = require('../../error.js'), import_trace = require('../../trace.js');
|
|
22
|
-
const allocateIf = (value, condition) => condition ? value : "",
|
|
22
|
+
const allocateIf = (value, condition) => condition ? value : "", preserveEncodedSlashes = (params) => {
|
|
23
|
+
for (const key of Object.keys(params))
|
|
24
|
+
params[key].includes("/") && (params[key] = params[key].replaceAll("/", "%2F"));
|
|
25
|
+
return params;
|
|
26
|
+
}, createContext = (app, route, inference, isInline = !1) => {
|
|
23
27
|
let fnLiteral = "";
|
|
24
28
|
const defaultHeaders = app.setHeaders, hasTrace = !!app.event.trace?.length;
|
|
25
29
|
hasTrace && (fnLiteral += `const id=randomId()
|
|
@@ -31,8 +35,8 @@ const allocateIf = (value, condition) => condition ? value : "", createContext =
|
|
|
31
35
|
needsQuery && (fnLiteral += getQi);
|
|
32
36
|
const getPath = inference.path ? isDynamic ? "get path(){" + (needsQuery ? "" : getQi) + `if(qi===-1)return u.substring(s)
|
|
33
37
|
return u.substring(s,qi)
|
|
34
|
-
},` :
|
|
35
|
-
fnLiteral += allocateIf("const c=", !isInline) + "{request,store," + allocateIf("qi,", needsQuery) + allocateIf("params:request.params,", isDynamic) + getPath + allocateIf(
|
|
38
|
+
},` : "path:route," : "";
|
|
39
|
+
fnLiteral += allocateIf("const c=", !isInline) + "{request,store," + allocateIf("qi,", needsQuery) + allocateIf("params:preserveEncodedSlashes(request.params),", isDynamic) + getPath + allocateIf(
|
|
36
40
|
"url:request.url,",
|
|
37
41
|
hasTrace || inference.url || needsQuery
|
|
38
42
|
) + "redirect,status,set:{headers:" + ((0, import_utils.isNotEmpty)(defaultHeaders) ? "Object.assign({},app.setHeaders)" : "Object.create(null)") + ",status:200}", inference.server && (fnLiteral += ",get server(){return app.getServer()}"), hasTrace && (fnLiteral += ",[ELYSIA_REQUEST_ID]:id");
|
|
@@ -57,7 +61,7 @@ return u.substring(s,qi)
|
|
|
57
61
|
},
|
|
58
62
|
inference
|
|
59
63
|
);
|
|
60
|
-
let fnLiteral = "const handler=data.handler,app=data.app,store=data.store,decorator=data.decorator,redirect=data.redirect,route=data.route,mapEarlyResponse=data.mapEarlyResponse," + allocateIf("randomId=data.randomId,", hasTrace) + allocateIf("ELYSIA_REQUEST_ID=data.ELYSIA_REQUEST_ID,", hasTrace) + allocateIf("ELYSIA_TRACE=data.ELYSIA_TRACE,", hasTrace) + allocateIf("trace=data.trace,", hasTrace) + allocateIf("hoc=data.hoc,", hasHoc) + `status=data.status
|
|
64
|
+
let fnLiteral = "const handler=data.handler,app=data.app,store=data.store,decorator=data.decorator,preserveEncodedSlashes=data.preserveEncodedSlashes,redirect=data.redirect,route=data.route,mapEarlyResponse=data.mapEarlyResponse," + allocateIf("randomId=data.randomId,", hasTrace) + allocateIf("ELYSIA_REQUEST_ID=data.ELYSIA_REQUEST_ID,", hasTrace) + allocateIf("ELYSIA_TRACE=data.ELYSIA_TRACE,", hasTrace) + allocateIf("trace=data.trace,", hasTrace) + allocateIf("hoc=data.hoc,", hasHoc) + `status=data.status
|
|
61
65
|
`;
|
|
62
66
|
app.event.request?.length && (fnLiteral += `const onRequest=app.event.request.map(x=>x.fn)
|
|
63
67
|
`), fnLiteral += `${app.event.request?.find(import_compose.isAsync) ? "async" : ""} function map(request){`;
|
|
@@ -76,6 +80,7 @@ return u.substring(s,qi)
|
|
|
76
80
|
hoc: app.extender.higherOrderFunctions.map((x) => x.fn),
|
|
77
81
|
store: app.store,
|
|
78
82
|
decorator: app.decorator,
|
|
83
|
+
preserveEncodedSlashes,
|
|
79
84
|
route: route.path,
|
|
80
85
|
randomId: hasTrace ? import_utils.randomId : void 0,
|
|
81
86
|
ELYSIA_TRACE: hasTrace ? import_trace.ELYSIA_TRACE : void 0,
|
|
@@ -4,7 +4,11 @@ import { createHoc, createOnRequestHandler, isAsync } from "../../compose.mjs";
|
|
|
4
4
|
import { randomId, ELYSIA_REQUEST_ID, redirect, isNotEmpty } from "../../utils.mjs";
|
|
5
5
|
import { status } from "../../error.mjs";
|
|
6
6
|
import { ELYSIA_TRACE } from "../../trace.mjs";
|
|
7
|
-
const allocateIf = (value, condition) => condition ? value : "",
|
|
7
|
+
const allocateIf = (value, condition) => condition ? value : "", preserveEncodedSlashes = (params) => {
|
|
8
|
+
for (const key of Object.keys(params))
|
|
9
|
+
params[key].includes("/") && (params[key] = params[key].replaceAll("/", "%2F"));
|
|
10
|
+
return params;
|
|
11
|
+
}, createContext = (app, route, inference, isInline = !1) => {
|
|
8
12
|
let fnLiteral = "";
|
|
9
13
|
const defaultHeaders = app.setHeaders, hasTrace = !!app.event.trace?.length;
|
|
10
14
|
hasTrace && (fnLiteral += `const id=randomId()
|
|
@@ -16,8 +20,8 @@ const allocateIf = (value, condition) => condition ? value : "", createContext =
|
|
|
16
20
|
needsQuery && (fnLiteral += getQi);
|
|
17
21
|
const getPath = inference.path ? isDynamic ? "get path(){" + (needsQuery ? "" : getQi) + `if(qi===-1)return u.substring(s)
|
|
18
22
|
return u.substring(s,qi)
|
|
19
|
-
},` :
|
|
20
|
-
fnLiteral += allocateIf("const c=", !isInline) + "{request,store," + allocateIf("qi,", needsQuery) + allocateIf("params:request.params,", isDynamic) + getPath + allocateIf(
|
|
23
|
+
},` : "path:route," : "";
|
|
24
|
+
fnLiteral += allocateIf("const c=", !isInline) + "{request,store," + allocateIf("qi,", needsQuery) + allocateIf("params:preserveEncodedSlashes(request.params),", isDynamic) + getPath + allocateIf(
|
|
21
25
|
"url:request.url,",
|
|
22
26
|
hasTrace || inference.url || needsQuery
|
|
23
27
|
) + "redirect,status,set:{headers:" + (isNotEmpty(defaultHeaders) ? "Object.assign({},app.setHeaders)" : "Object.create(null)") + ",status:200}", inference.server && (fnLiteral += ",get server(){return app.getServer()}"), hasTrace && (fnLiteral += ",[ELYSIA_REQUEST_ID]:id");
|
|
@@ -42,7 +46,7 @@ return u.substring(s,qi)
|
|
|
42
46
|
},
|
|
43
47
|
inference
|
|
44
48
|
);
|
|
45
|
-
let fnLiteral = "const handler=data.handler,app=data.app,store=data.store,decorator=data.decorator,redirect=data.redirect,route=data.route,mapEarlyResponse=data.mapEarlyResponse," + allocateIf("randomId=data.randomId,", hasTrace) + allocateIf("ELYSIA_REQUEST_ID=data.ELYSIA_REQUEST_ID,", hasTrace) + allocateIf("ELYSIA_TRACE=data.ELYSIA_TRACE,", hasTrace) + allocateIf("trace=data.trace,", hasTrace) + allocateIf("hoc=data.hoc,", hasHoc) + `status=data.status
|
|
49
|
+
let fnLiteral = "const handler=data.handler,app=data.app,store=data.store,decorator=data.decorator,preserveEncodedSlashes=data.preserveEncodedSlashes,redirect=data.redirect,route=data.route,mapEarlyResponse=data.mapEarlyResponse," + allocateIf("randomId=data.randomId,", hasTrace) + allocateIf("ELYSIA_REQUEST_ID=data.ELYSIA_REQUEST_ID,", hasTrace) + allocateIf("ELYSIA_TRACE=data.ELYSIA_TRACE,", hasTrace) + allocateIf("trace=data.trace,", hasTrace) + allocateIf("hoc=data.hoc,", hasHoc) + `status=data.status
|
|
46
50
|
`;
|
|
47
51
|
app.event.request?.length && (fnLiteral += `const onRequest=app.event.request.map(x=>x.fn)
|
|
48
52
|
`), fnLiteral += `${app.event.request?.find(isAsync) ? "async" : ""} function map(request){`;
|
|
@@ -61,6 +65,7 @@ return u.substring(s,qi)
|
|
|
61
65
|
hoc: app.extender.higherOrderFunctions.map((x) => x.fn),
|
|
62
66
|
store: app.store,
|
|
63
67
|
decorator: app.decorator,
|
|
68
|
+
preserveEncodedSlashes,
|
|
64
69
|
route: route.path,
|
|
65
70
|
randomId: hasTrace ? randomId : void 0,
|
|
66
71
|
ELYSIA_TRACE: hasTrace ? ELYSIA_TRACE : void 0,
|
|
@@ -19,8 +19,24 @@ __export(handler_native_exports, {
|
|
|
19
19
|
});
|
|
20
20
|
module.exports = __toCommonJS(handler_native_exports);
|
|
21
21
|
var import_index = require('./index.js'), import_handler = require('./handler.js');
|
|
22
|
-
const
|
|
23
|
-
|
|
22
|
+
const isEmptyPipelineHook = (hooks) => {
|
|
23
|
+
for (const key in hooks) {
|
|
24
|
+
switch (key) {
|
|
25
|
+
case "detail":
|
|
26
|
+
case "tags":
|
|
27
|
+
case "start":
|
|
28
|
+
case "stop":
|
|
29
|
+
case "error":
|
|
30
|
+
case "afterResponse":
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const value = hooks[key];
|
|
34
|
+
if (value !== void 0 && value !== !1 && (!Array.isArray(value) || value.length))
|
|
35
|
+
return !1;
|
|
36
|
+
}
|
|
37
|
+
return !0;
|
|
38
|
+
}, createNativeStaticHandler = (handle, hooks, set) => {
|
|
39
|
+
if (typeof handle == "function" || handle instanceof Blob || !isEmptyPipelineHook(hooks)) return;
|
|
24
40
|
if ((0, import_index.isHTMLBundle)(handle)) return () => handle;
|
|
25
41
|
const response = (0, import_handler.mapResponse)(
|
|
26
42
|
handle instanceof Response ? handle.clone() : handle instanceof Promise ? handle.then(
|
|
@@ -30,11 +46,10 @@ const createNativeStaticHandler = (handle, hooks, set) => {
|
|
|
30
46
|
headers: {}
|
|
31
47
|
}
|
|
32
48
|
);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}) : () => response.clone();
|
|
49
|
+
return response instanceof Promise ? response.then((response2) => {
|
|
50
|
+
if (response2)
|
|
51
|
+
return response2.clone();
|
|
52
|
+
}) : () => response.clone();
|
|
38
53
|
};
|
|
39
54
|
// Annotate the CommonJS export names for ESM import in node:
|
|
40
55
|
0 && (module.exports = {
|
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import { isHTMLBundle } from "./index.mjs";
|
|
2
2
|
import { mapResponse } from "./handler.mjs";
|
|
3
|
-
const
|
|
4
|
-
|
|
3
|
+
const isEmptyPipelineHook = (hooks) => {
|
|
4
|
+
for (const key in hooks) {
|
|
5
|
+
switch (key) {
|
|
6
|
+
case "detail":
|
|
7
|
+
case "tags":
|
|
8
|
+
case "start":
|
|
9
|
+
case "stop":
|
|
10
|
+
case "error":
|
|
11
|
+
case "afterResponse":
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
const value = hooks[key];
|
|
15
|
+
if (value !== void 0 && value !== !1 && (!Array.isArray(value) || value.length))
|
|
16
|
+
return !1;
|
|
17
|
+
}
|
|
18
|
+
return !0;
|
|
19
|
+
}, createNativeStaticHandler = (handle, hooks, set) => {
|
|
20
|
+
if (typeof handle == "function" || handle instanceof Blob || !isEmptyPipelineHook(hooks)) return;
|
|
5
21
|
if (isHTMLBundle(handle)) return () => handle;
|
|
6
22
|
const response = mapResponse(
|
|
7
23
|
handle instanceof Response ? handle.clone() : handle instanceof Promise ? handle.then(
|
|
@@ -11,11 +27,10 @@ const createNativeStaticHandler = (handle, hooks, set) => {
|
|
|
11
27
|
headers: {}
|
|
12
28
|
}
|
|
13
29
|
);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}) : () => response.clone();
|
|
30
|
+
return response instanceof Promise ? response.then((response2) => {
|
|
31
|
+
if (response2)
|
|
32
|
+
return response2.clone();
|
|
33
|
+
}) : () => response.clone();
|
|
19
34
|
};
|
|
20
35
|
export {
|
|
21
36
|
createNativeStaticHandler
|
|
@@ -123,6 +123,9 @@ for(const [k,v] of c.request.headers.entries())c.headers[k]=v
|
|
|
123
123
|
}
|
|
124
124
|
const createStaticRoute = (iterator, { withAsync = !1 } = {}) => {
|
|
125
125
|
const staticRoutes = {}, ops = [];
|
|
126
|
+
if (app.event.request?.length || app.event.trace?.length || // @ts-expect-error private
|
|
127
|
+
app.extender.higherOrderFunctions.length)
|
|
128
|
+
return withAsync ? Promise.resolve(staticRoutes) : staticRoutes;
|
|
126
129
|
for (let [path, route] of Object.entries(iterator))
|
|
127
130
|
if (path = encodeURI(path), import_utils2.supportPerMethodInlineHandler) {
|
|
128
131
|
if (!route) continue;
|
|
@@ -235,7 +238,10 @@ for(const [k,v] of c.request.headers.entries())c.headers[k]=v
|
|
|
235
238
|
// @ts-expect-error private property
|
|
236
239
|
models: app.definitions.type,
|
|
237
240
|
normalize: app.config.normalize
|
|
238
|
-
}), validateMessage = messageValidator ? messageValidator.provider === "standard" ? (data) => messageValidator.schema["~standard"].validate(data)
|
|
241
|
+
}), validateMessage = messageValidator ? messageValidator.provider === "standard" ? (data) => messageValidator.schema["~standard"].validate(data) : (data) => ({
|
|
242
|
+
issues: messageValidator.Check(data) === !1 || void 0,
|
|
243
|
+
value: data
|
|
244
|
+
}) : void 0, responseValidator = (0, import_schema.getSchemaValidator)(response, {
|
|
239
245
|
// @ts-expect-error private property
|
|
240
246
|
modules: app.definitions.typebox,
|
|
241
247
|
// @ts-expect-error private property
|
|
@@ -310,19 +316,22 @@ for(const [k,v] of c.request.headers.entries())c.headers[k]=v
|
|
|
310
316
|
}
|
|
311
317
|
},
|
|
312
318
|
message: async (ws, _message) => {
|
|
313
|
-
const message = await parseMessage(ws, _message);
|
|
314
|
-
if (validateMessage && validateMessage(message)) {
|
|
315
|
-
const validationError = new import_error.ValidationError(
|
|
316
|
-
"message",
|
|
317
|
-
messageValidator,
|
|
318
|
-
message
|
|
319
|
-
);
|
|
320
|
-
return hasCustomErrorHandlers ? handleErrors(ws, validationError) : void ws.send(
|
|
321
|
-
validationError.message
|
|
322
|
-
);
|
|
323
|
-
}
|
|
324
319
|
try {
|
|
325
|
-
await
|
|
320
|
+
let message = await parseMessage(ws, _message);
|
|
321
|
+
const validation = validateMessage ? await validateMessage(message) : void 0;
|
|
322
|
+
if (validation?.issues) {
|
|
323
|
+
const validationError = new import_error.ValidationError(
|
|
324
|
+
"message",
|
|
325
|
+
messageValidator,
|
|
326
|
+
message,
|
|
327
|
+
!1,
|
|
328
|
+
messageValidator?.provider === "standard" ? validation.issues : void 0
|
|
329
|
+
);
|
|
330
|
+
return hasCustomErrorHandlers ? handleErrors(ws, validationError) : void ws.send(
|
|
331
|
+
validationError.message
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
validation && (message = validation.value), await handleResponse(
|
|
326
335
|
ws,
|
|
327
336
|
options.message?.(
|
|
328
337
|
new import_ws.ElysiaWS(
|
|
@@ -126,6 +126,9 @@ for(const [k,v] of c.request.headers.entries())c.headers[k]=v
|
|
|
126
126
|
}
|
|
127
127
|
const createStaticRoute = (iterator, { withAsync = !1 } = {}) => {
|
|
128
128
|
const staticRoutes = {}, ops = [];
|
|
129
|
+
if (app.event.request?.length || app.event.trace?.length || // @ts-expect-error private
|
|
130
|
+
app.extender.higherOrderFunctions.length)
|
|
131
|
+
return withAsync ? Promise.resolve(staticRoutes) : staticRoutes;
|
|
129
132
|
for (let [path, route] of Object.entries(iterator))
|
|
130
133
|
if (path = encodeURI(path), supportPerMethodInlineHandler) {
|
|
131
134
|
if (!route) continue;
|
|
@@ -238,7 +241,10 @@ for(const [k,v] of c.request.headers.entries())c.headers[k]=v
|
|
|
238
241
|
// @ts-expect-error private property
|
|
239
242
|
models: app.definitions.type,
|
|
240
243
|
normalize: app.config.normalize
|
|
241
|
-
}), validateMessage = messageValidator ? messageValidator.provider === "standard" ? (data) => messageValidator.schema["~standard"].validate(data)
|
|
244
|
+
}), validateMessage = messageValidator ? messageValidator.provider === "standard" ? (data) => messageValidator.schema["~standard"].validate(data) : (data) => ({
|
|
245
|
+
issues: messageValidator.Check(data) === !1 || void 0,
|
|
246
|
+
value: data
|
|
247
|
+
}) : void 0, responseValidator = getSchemaValidator(response, {
|
|
242
248
|
// @ts-expect-error private property
|
|
243
249
|
modules: app.definitions.typebox,
|
|
244
250
|
// @ts-expect-error private property
|
|
@@ -313,19 +319,22 @@ for(const [k,v] of c.request.headers.entries())c.headers[k]=v
|
|
|
313
319
|
}
|
|
314
320
|
},
|
|
315
321
|
message: async (ws, _message) => {
|
|
316
|
-
const message = await parseMessage(ws, _message);
|
|
317
|
-
if (validateMessage && validateMessage(message)) {
|
|
318
|
-
const validationError = new ValidationError(
|
|
319
|
-
"message",
|
|
320
|
-
messageValidator,
|
|
321
|
-
message
|
|
322
|
-
);
|
|
323
|
-
return hasCustomErrorHandlers ? handleErrors(ws, validationError) : void ws.send(
|
|
324
|
-
validationError.message
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
322
|
try {
|
|
328
|
-
await
|
|
323
|
+
let message = await parseMessage(ws, _message);
|
|
324
|
+
const validation = validateMessage ? await validateMessage(message) : void 0;
|
|
325
|
+
if (validation?.issues) {
|
|
326
|
+
const validationError = new ValidationError(
|
|
327
|
+
"message",
|
|
328
|
+
messageValidator,
|
|
329
|
+
message,
|
|
330
|
+
!1,
|
|
331
|
+
messageValidator?.provider === "standard" ? validation.issues : void 0
|
|
332
|
+
);
|
|
333
|
+
return hasCustomErrorHandlers ? handleErrors(ws, validationError) : void ws.send(
|
|
334
|
+
validationError.message
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
validation && (message = validation.value), await handleResponse(
|
|
329
338
|
ws,
|
|
330
339
|
options.message?.(
|
|
331
340
|
new ElysiaWS(
|
package/dist/adapter/utils.js
CHANGED
|
@@ -285,25 +285,70 @@ const createResponseHandler = (handler) => {
|
|
|
285
285
|
};
|
|
286
286
|
};
|
|
287
287
|
async function tee(source, branches = 2) {
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
288
|
+
const state = Array.from({ length: branches }, () => ({
|
|
289
|
+
active: !0,
|
|
290
|
+
consumed: !0
|
|
291
|
+
}));
|
|
292
|
+
if (!state.length) return [];
|
|
293
|
+
const iterator = source[Symbol.asyncIterator]?.() ?? source[Symbol.iterator]();
|
|
294
|
+
let active = state.length, current, hasValue = !1, remaining = 0, done = !1, failed = !1, sourceError, pulling, waiting = [];
|
|
295
|
+
const wake = () => {
|
|
296
|
+
const pending = waiting;
|
|
297
|
+
waiting = [];
|
|
298
|
+
for (const resolve of pending) resolve();
|
|
299
|
+
}, wait = () => new Promise((resolve) => waiting.push(resolve)), pull = () => {
|
|
300
|
+
pulling ??= Promise.resolve().then(() => iterator.next()).then((result) => {
|
|
301
|
+
if (result.done || !active || done) {
|
|
302
|
+
done = !0;
|
|
303
|
+
return;
|
|
304
304
|
}
|
|
305
|
-
|
|
306
|
-
|
|
305
|
+
current = result.value, hasValue = !0, remaining = active;
|
|
306
|
+
for (const branch of state)
|
|
307
|
+
branch.active && (branch.consumed = !1);
|
|
308
|
+
}).catch((error) => {
|
|
309
|
+
!active || done || (failed = done = !0, sourceError = error);
|
|
310
|
+
}).finally(() => {
|
|
311
|
+
pulling = void 0, wake();
|
|
312
|
+
});
|
|
313
|
+
}, stop = () => {
|
|
314
|
+
if (!done) {
|
|
315
|
+
done = !0, wake();
|
|
316
|
+
try {
|
|
317
|
+
Promise.resolve(iterator.return?.()).catch(() => {
|
|
318
|
+
});
|
|
319
|
+
} catch {
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}, close = (index) => {
|
|
323
|
+
const branch = state[index];
|
|
324
|
+
return branch.active ? (branch.active = !1, active--, hasValue && !branch.consumed && --remaining === 0 && (hasValue = !1, wake()), !0) : !1;
|
|
325
|
+
}, next = async (index) => {
|
|
326
|
+
const branch = state[index];
|
|
327
|
+
for (; branch.active; ) {
|
|
328
|
+
if (failed)
|
|
329
|
+
throw close(index), sourceError;
|
|
330
|
+
if (hasValue && !branch.consumed) {
|
|
331
|
+
branch.consumed = !0;
|
|
332
|
+
const result = { done: !1, value: current };
|
|
333
|
+
return --remaining === 0 && (hasValue = !1, wake()), result;
|
|
334
|
+
}
|
|
335
|
+
if (done) {
|
|
336
|
+
close(index);
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
hasValue || pull(), await wait();
|
|
340
|
+
}
|
|
341
|
+
return { done: !0, value: void 0 };
|
|
342
|
+
};
|
|
343
|
+
return state.map((_, index) => ({
|
|
344
|
+
next: () => next(index),
|
|
345
|
+
async return(finalValue) {
|
|
346
|
+
return close(index) && (index === 0 || !active) && stop(), { done: !0, value: finalValue };
|
|
347
|
+
},
|
|
348
|
+
[Symbol.asyncIterator]() {
|
|
349
|
+
return this;
|
|
350
|
+
}
|
|
351
|
+
}));
|
|
307
352
|
}
|
|
308
353
|
// Annotate the CommonJS export names for ESM import in node:
|
|
309
354
|
0 && (module.exports = {
|
package/dist/adapter/utils.mjs
CHANGED
|
@@ -258,25 +258,70 @@ const createResponseHandler = (handler) => {
|
|
|
258
258
|
};
|
|
259
259
|
};
|
|
260
260
|
async function tee(source, branches = 2) {
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
261
|
+
const state = Array.from({ length: branches }, () => ({
|
|
262
|
+
active: !0,
|
|
263
|
+
consumed: !0
|
|
264
|
+
}));
|
|
265
|
+
if (!state.length) return [];
|
|
266
|
+
const iterator = source[Symbol.asyncIterator]?.() ?? source[Symbol.iterator]();
|
|
267
|
+
let active = state.length, current, hasValue = !1, remaining = 0, done = !1, failed = !1, sourceError, pulling, waiting = [];
|
|
268
|
+
const wake = () => {
|
|
269
|
+
const pending = waiting;
|
|
270
|
+
waiting = [];
|
|
271
|
+
for (const resolve of pending) resolve();
|
|
272
|
+
}, wait = () => new Promise((resolve) => waiting.push(resolve)), pull = () => {
|
|
273
|
+
pulling ??= Promise.resolve().then(() => iterator.next()).then((result) => {
|
|
274
|
+
if (result.done || !active || done) {
|
|
275
|
+
done = !0;
|
|
276
|
+
return;
|
|
277
277
|
}
|
|
278
|
-
|
|
279
|
-
|
|
278
|
+
current = result.value, hasValue = !0, remaining = active;
|
|
279
|
+
for (const branch of state)
|
|
280
|
+
branch.active && (branch.consumed = !1);
|
|
281
|
+
}).catch((error) => {
|
|
282
|
+
!active || done || (failed = done = !0, sourceError = error);
|
|
283
|
+
}).finally(() => {
|
|
284
|
+
pulling = void 0, wake();
|
|
285
|
+
});
|
|
286
|
+
}, stop = () => {
|
|
287
|
+
if (!done) {
|
|
288
|
+
done = !0, wake();
|
|
289
|
+
try {
|
|
290
|
+
Promise.resolve(iterator.return?.()).catch(() => {
|
|
291
|
+
});
|
|
292
|
+
} catch {
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}, close = (index) => {
|
|
296
|
+
const branch = state[index];
|
|
297
|
+
return branch.active ? (branch.active = !1, active--, hasValue && !branch.consumed && --remaining === 0 && (hasValue = !1, wake()), !0) : !1;
|
|
298
|
+
}, next = async (index) => {
|
|
299
|
+
const branch = state[index];
|
|
300
|
+
for (; branch.active; ) {
|
|
301
|
+
if (failed)
|
|
302
|
+
throw close(index), sourceError;
|
|
303
|
+
if (hasValue && !branch.consumed) {
|
|
304
|
+
branch.consumed = !0;
|
|
305
|
+
const result = { done: !1, value: current };
|
|
306
|
+
return --remaining === 0 && (hasValue = !1, wake()), result;
|
|
307
|
+
}
|
|
308
|
+
if (done) {
|
|
309
|
+
close(index);
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
hasValue || pull(), await wait();
|
|
313
|
+
}
|
|
314
|
+
return { done: !0, value: void 0 };
|
|
315
|
+
};
|
|
316
|
+
return state.map((_, index) => ({
|
|
317
|
+
next: () => next(index),
|
|
318
|
+
async return(finalValue) {
|
|
319
|
+
return close(index) && (index === 0 || !active) && stop(), { done: !0, value: finalValue };
|
|
320
|
+
},
|
|
321
|
+
[Symbol.asyncIterator]() {
|
|
322
|
+
return this;
|
|
323
|
+
}
|
|
324
|
+
}));
|
|
280
325
|
}
|
|
281
326
|
export {
|
|
282
327
|
createResponseHandler,
|
|
@@ -54,62 +54,10 @@ for(const [k,v] of c.request.headers.entries())c.headers[k]=v
|
|
|
54
54
|
`;
|
|
55
55
|
},
|
|
56
56
|
formData(isOptional) {
|
|
57
|
-
let fnLiteral =
|
|
58
|
-
c.body={}
|
|
59
|
-
`;
|
|
57
|
+
let fnLiteral = "";
|
|
60
58
|
return isOptional ? fnLiteral += "let form;try{form=await c.request.formData()}catch{}" : fnLiteral += `const form=await c.request.formData()
|
|
61
|
-
`, fnLiteral + `
|
|
62
|
-
|
|
63
|
-
const parseArrayKey=(k)=>{const m=k.match(/^(.+)\\[(\\d+)\\]$/);return m?{name:m[1],index:parseInt(m[2],10)}:null}
|
|
64
|
-
const grouped=new Map()
|
|
65
|
-
form.forEach((v,k)=>{const l=grouped.get(k);if(l)l.push(v);else grouped.set(k,[v])})
|
|
66
|
-
for(const [key,value] of grouped){if(c.body[key])continue
|
|
67
|
-
let finalValue
|
|
68
|
-
if(value.length===1){
|
|
69
|
-
const sv=value[0]
|
|
70
|
-
if(typeof sv==='string'&&(sv.charCodeAt(0)===123||sv.charCodeAt(0)===91)){
|
|
71
|
-
try{
|
|
72
|
-
const p=JSON.parse(sv)
|
|
73
|
-
if(p&&typeof p==='object')finalValue=p
|
|
74
|
-
}catch{}
|
|
75
|
-
}
|
|
76
|
-
if(finalValue===undefined)finalValue=sv
|
|
77
|
-
}else finalValue=value
|
|
78
|
-
if(Array.isArray(finalValue)){
|
|
79
|
-
const stringValue=finalValue.find((entry)=>typeof entry==='string')
|
|
80
|
-
const files=typeof File==='undefined'?[]:finalValue.filter((entry)=>entry instanceof File)
|
|
81
|
-
if(stringValue&&files.length&&stringValue.charCodeAt(0)===123){
|
|
82
|
-
try{
|
|
83
|
-
const parsed=JSON.parse(stringValue)
|
|
84
|
-
if(parsed&&typeof parsed==='object'&&!Array.isArray(parsed)){
|
|
85
|
-
if(!('file' in parsed)&&files.length===1)parsed.file=files[0]
|
|
86
|
-
else if(!('files' in parsed)&&files.length>1)parsed.files=files
|
|
87
|
-
finalValue=parsed
|
|
88
|
-
}
|
|
89
|
-
}catch{}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
if(key.includes('.')||key.includes('[')){const keys=key.split('.')
|
|
93
|
-
const lastKey=keys.pop()
|
|
94
|
-
if(isDangerousKey(lastKey)||keys.some(isDangerousKey))continue
|
|
95
|
-
let current=c.body
|
|
96
|
-
for(const k of keys){const arrayInfo=parseArrayKey(k)
|
|
97
|
-
if(arrayInfo){if(!Array.isArray(current[arrayInfo.name]))current[arrayInfo.name]=[]
|
|
98
|
-
const existing=current[arrayInfo.name][arrayInfo.index]
|
|
99
|
-
const isFile=typeof File!=='undefined'&&existing instanceof File
|
|
100
|
-
if(!existing||typeof existing!=='object'||Array.isArray(existing)||isFile){
|
|
101
|
-
let parsed
|
|
102
|
-
if(typeof existing==='string'&&existing.charCodeAt(0)===123){
|
|
103
|
-
try{parsed=JSON.parse(existing)
|
|
104
|
-
if(!parsed||typeof parsed!=='object'||Array.isArray(parsed))parsed=undefined}catch{}
|
|
105
|
-
}
|
|
106
|
-
current[arrayInfo.name][arrayInfo.index]=parsed||{}
|
|
107
|
-
}
|
|
108
|
-
current=current[arrayInfo.name][arrayInfo.index]}else{if(!current[k]||typeof current[k]!=='object')current[k]={}
|
|
109
|
-
current=current[k]}}
|
|
110
|
-
const arrayInfo=parseArrayKey(lastKey)
|
|
111
|
-
if(arrayInfo){if(!Array.isArray(current[arrayInfo.name]))current[arrayInfo.name]=[]
|
|
112
|
-
current[arrayInfo.name][arrayInfo.index]=finalValue}else{current[lastKey]=finalValue}}else c.body[key]=finalValue}`;
|
|
59
|
+
`, fnLiteral + `c.body=parseFormData(form)
|
|
60
|
+
`;
|
|
113
61
|
}
|
|
114
62
|
}
|
|
115
63
|
},
|
|
@@ -39,62 +39,10 @@ for(const [k,v] of c.request.headers.entries())c.headers[k]=v
|
|
|
39
39
|
`;
|
|
40
40
|
},
|
|
41
41
|
formData(isOptional) {
|
|
42
|
-
let fnLiteral =
|
|
43
|
-
c.body={}
|
|
44
|
-
`;
|
|
42
|
+
let fnLiteral = "";
|
|
45
43
|
return isOptional ? fnLiteral += "let form;try{form=await c.request.formData()}catch{}" : fnLiteral += `const form=await c.request.formData()
|
|
46
|
-
`, fnLiteral + `
|
|
47
|
-
|
|
48
|
-
const parseArrayKey=(k)=>{const m=k.match(/^(.+)\\[(\\d+)\\]$/);return m?{name:m[1],index:parseInt(m[2],10)}:null}
|
|
49
|
-
const grouped=new Map()
|
|
50
|
-
form.forEach((v,k)=>{const l=grouped.get(k);if(l)l.push(v);else grouped.set(k,[v])})
|
|
51
|
-
for(const [key,value] of grouped){if(c.body[key])continue
|
|
52
|
-
let finalValue
|
|
53
|
-
if(value.length===1){
|
|
54
|
-
const sv=value[0]
|
|
55
|
-
if(typeof sv==='string'&&(sv.charCodeAt(0)===123||sv.charCodeAt(0)===91)){
|
|
56
|
-
try{
|
|
57
|
-
const p=JSON.parse(sv)
|
|
58
|
-
if(p&&typeof p==='object')finalValue=p
|
|
59
|
-
}catch{}
|
|
60
|
-
}
|
|
61
|
-
if(finalValue===undefined)finalValue=sv
|
|
62
|
-
}else finalValue=value
|
|
63
|
-
if(Array.isArray(finalValue)){
|
|
64
|
-
const stringValue=finalValue.find((entry)=>typeof entry==='string')
|
|
65
|
-
const files=typeof File==='undefined'?[]:finalValue.filter((entry)=>entry instanceof File)
|
|
66
|
-
if(stringValue&&files.length&&stringValue.charCodeAt(0)===123){
|
|
67
|
-
try{
|
|
68
|
-
const parsed=JSON.parse(stringValue)
|
|
69
|
-
if(parsed&&typeof parsed==='object'&&!Array.isArray(parsed)){
|
|
70
|
-
if(!('file' in parsed)&&files.length===1)parsed.file=files[0]
|
|
71
|
-
else if(!('files' in parsed)&&files.length>1)parsed.files=files
|
|
72
|
-
finalValue=parsed
|
|
73
|
-
}
|
|
74
|
-
}catch{}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if(key.includes('.')||key.includes('[')){const keys=key.split('.')
|
|
78
|
-
const lastKey=keys.pop()
|
|
79
|
-
if(isDangerousKey(lastKey)||keys.some(isDangerousKey))continue
|
|
80
|
-
let current=c.body
|
|
81
|
-
for(const k of keys){const arrayInfo=parseArrayKey(k)
|
|
82
|
-
if(arrayInfo){if(!Array.isArray(current[arrayInfo.name]))current[arrayInfo.name]=[]
|
|
83
|
-
const existing=current[arrayInfo.name][arrayInfo.index]
|
|
84
|
-
const isFile=typeof File!=='undefined'&&existing instanceof File
|
|
85
|
-
if(!existing||typeof existing!=='object'||Array.isArray(existing)||isFile){
|
|
86
|
-
let parsed
|
|
87
|
-
if(typeof existing==='string'&&existing.charCodeAt(0)===123){
|
|
88
|
-
try{parsed=JSON.parse(existing)
|
|
89
|
-
if(!parsed||typeof parsed!=='object'||Array.isArray(parsed))parsed=undefined}catch{}
|
|
90
|
-
}
|
|
91
|
-
current[arrayInfo.name][arrayInfo.index]=parsed||{}
|
|
92
|
-
}
|
|
93
|
-
current=current[arrayInfo.name][arrayInfo.index]}else{if(!current[k]||typeof current[k]!=='object')current[k]={}
|
|
94
|
-
current=current[k]}}
|
|
95
|
-
const arrayInfo=parseArrayKey(lastKey)
|
|
96
|
-
if(arrayInfo){if(!Array.isArray(current[arrayInfo.name]))current[arrayInfo.name]=[]
|
|
97
|
-
current[arrayInfo.name][arrayInfo.index]=finalValue}else{current[lastKey]=finalValue}}else c.body[key]=finalValue}`;
|
|
44
|
+
`, fnLiteral + `c.body=parseFormData(form)
|
|
45
|
+
`;
|
|
98
46
|
}
|
|
99
47
|
}
|
|
100
48
|
},
|