elysia 2.0.0-beta.2 → 2.0.0-beta.21
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/adapter/bun/index.d.ts +18 -2
- package/dist/adapter/bun/index.js +467 -110
- package/dist/adapter/bun/index.mjs +467 -112
- package/dist/adapter/types.d.ts +2 -21
- package/dist/adapter/utils.d.ts +14 -3
- package/dist/adapter/utils.js +146 -87
- package/dist/adapter/utils.mjs +148 -90
- package/dist/adapter/web-standard/handler.d.ts +1 -1
- package/dist/adapter/web-standard/handler.js +47 -36
- package/dist/adapter/web-standard/handler.mjs +48 -37
- package/dist/adapter/web-standard/index.js +2 -30
- package/dist/adapter/web-standard/index.mjs +2 -30
- package/dist/adapter/web-standard/utils.js +5 -18
- package/dist/adapter/web-standard/utils.mjs +5 -18
- package/dist/base.d.ts +99 -67
- package/dist/base.js +678 -510
- package/dist/base.mjs +682 -514
- package/dist/compile/aot-capture.d.ts +2 -13
- package/dist/compile/aot-capture.js +26 -69
- package/dist/compile/aot-capture.mjs +28 -67
- package/dist/compile/aot-emit.d.ts +9 -7
- package/dist/compile/aot-emit.js +42 -19
- package/dist/compile/aot-emit.mjs +42 -20
- package/dist/compile/aot.d.ts +17 -19
- package/dist/compile/aot.js +41 -51
- package/dist/compile/aot.mjs +39 -49
- package/dist/compile/handler/descriptor.d.ts +9 -12
- package/dist/compile/handler/descriptor.js +19 -44
- package/dist/compile/handler/descriptor.mjs +20 -42
- package/dist/compile/handler/frozen-validator.d.ts +5 -10
- package/dist/compile/handler/frozen-validator.js +55 -105
- package/dist/compile/handler/frozen-validator.mjs +53 -105
- package/dist/compile/handler/index.d.ts +7 -5
- package/dist/compile/handler/index.js +270 -111
- package/dist/compile/handler/index.mjs +270 -113
- package/dist/compile/handler/jit.d.ts +19 -17
- package/dist/compile/handler/jit.js +222 -149
- package/dist/compile/handler/jit.mjs +224 -152
- package/dist/compile/handler/params.d.ts +1 -4
- package/dist/compile/handler/params.js +10 -5
- package/dist/compile/handler/params.mjs +14 -8
- package/dist/compile/handler/reconstruct.d.ts +2 -2
- package/dist/compile/handler/reconstruct.js +6 -4
- package/dist/compile/handler/reconstruct.mjs +6 -4
- package/dist/compile/handler/static-clone-resolver.d.ts +6 -0
- package/dist/compile/handler/static-clone-resolver.js +8 -0
- package/dist/compile/handler/static-clone-resolver.mjs +7 -0
- package/dist/compile/handler/utils.d.ts +22 -11
- package/dist/compile/handler/utils.js +159 -253
- package/dist/compile/handler/utils.mjs +155 -252
- package/dist/compile/jit-probe.d.ts +2 -2
- package/dist/compile/jit-probe.js +2 -3
- package/dist/compile/jit-probe.mjs +2 -3
- package/dist/compile/lexer.d.ts +7 -4
- package/dist/compile/lexer.js +268 -6
- package/dist/compile/lexer.mjs +268 -4
- package/dist/compile/utils.js +7 -4
- package/dist/compile/utils.mjs +7 -4
- package/dist/compiled.d.ts +0 -1
- package/dist/compiled.js +0 -1
- package/dist/compiled.mjs +0 -1
- package/dist/context.d.ts +14 -4
- package/dist/context.js +17 -32
- package/dist/context.mjs +19 -34
- package/dist/cookie/config.d.ts +7 -2
- package/dist/cookie/config.js +76 -16
- package/dist/cookie/config.mjs +77 -18
- package/dist/cookie/cookie.d.ts +1 -1
- package/dist/cookie/cookie.js +8 -10
- package/dist/cookie/cookie.mjs +8 -10
- package/dist/cookie/crypto.d.ts +8 -7
- package/dist/cookie/crypto.js +51 -40
- package/dist/cookie/crypto.mjs +51 -41
- package/dist/cookie/error.d.ts +1 -2
- package/dist/cookie/error.js +6 -4
- package/dist/cookie/error.mjs +6 -4
- package/dist/cookie/lib.js +7 -2
- package/dist/cookie/lib.mjs +7 -2
- package/dist/cookie/serialize.js +1 -1
- package/dist/cookie/serialize.mjs +1 -1
- package/dist/cookie/types.d.ts +10 -0
- package/dist/cookie/utils.d.ts +4 -8
- package/dist/cookie/utils.js +86 -52
- package/dist/cookie/utils.mjs +89 -54
- package/dist/error.d.ts +113 -103
- package/dist/error.js +181 -117
- package/dist/error.mjs +179 -118
- package/dist/generation.d.ts +2 -2
- package/dist/handler/error.d.ts +26 -15
- package/dist/handler/error.js +77 -96
- package/dist/handler/error.mjs +74 -97
- package/dist/handler/fetch.js +87 -108
- package/dist/handler/fetch.mjs +89 -110
- package/dist/handler/utils.d.ts +12 -6
- package/dist/handler/utils.js +84 -28
- package/dist/handler/utils.mjs +80 -28
- package/dist/index.d.ts +12 -12
- package/dist/index.js +2 -9
- package/dist/index.mjs +1 -1
- package/dist/memory.js +1 -1
- package/dist/memory.mjs +1 -1
- package/dist/package.js +1 -1
- package/dist/package.mjs +1 -1
- package/dist/plugin/aot/bun.d.ts +8 -1
- package/dist/plugin/aot/bun.js +16 -9
- package/dist/plugin/aot/bun.mjs +17 -10
- package/dist/plugin/aot/core.d.ts +52 -60
- package/dist/plugin/aot/core.js +208 -109
- package/dist/plugin/aot/core.mjs +205 -111
- package/dist/plugin/aot/esbuild.js +8 -5
- package/dist/plugin/aot/esbuild.mjs +9 -6
- package/dist/plugin/aot/hooks.d.ts +6 -17
- package/dist/plugin/aot/hooks.js +36 -14
- package/dist/plugin/aot/hooks.mjs +37 -16
- package/dist/plugin/aot/rspack-loader.d.ts +1 -5
- package/dist/plugin/aot/rspack-loader.js +1 -10
- package/dist/plugin/aot/rspack-loader.mjs +1 -10
- package/dist/plugin/aot/rspack.js +2 -5
- package/dist/plugin/aot/rspack.mjs +3 -6
- package/dist/plugin/aot/source.d.ts +6 -42
- package/dist/plugin/aot/source.js +71 -71
- package/dist/plugin/aot/source.mjs +72 -72
- package/dist/plugin/aot/treeshake.js +2 -6
- package/dist/plugin/aot/treeshake.mjs +2 -6
- package/dist/plugin/aot/unplugin.d.ts +1 -4
- package/dist/plugin/aot/unplugin.js +4 -13
- package/dist/plugin/aot/unplugin.mjs +4 -13
- package/dist/plugin/aot/vite.d.ts +2 -6
- package/dist/plugin/aot/worker.js +2 -2
- package/dist/plugin/aot/worker.mjs +2 -2
- package/dist/plugin/auto-head.js +1 -10
- package/dist/plugin/auto-head.mjs +1 -10
- package/dist/plugin/trace.d.ts +2 -1
- package/dist/route-table.d.ts +3 -0
- package/dist/route-table.js +16 -11
- package/dist/route-table.mjs +16 -11
- package/dist/schema-snapshot.d.ts +0 -4
- package/dist/schema-snapshot.js +32 -49
- package/dist/schema-snapshot.mjs +32 -49
- package/dist/sucrose.d.ts +6 -55
- package/dist/sucrose.js +103 -731
- package/dist/sucrose.mjs +102 -724
- package/dist/trace.d.ts +5 -8
- package/dist/trace.js +23 -134
- package/dist/trace.mjs +24 -135
- package/dist/type/bridge-live.d.ts +4 -2
- package/dist/type/bridge-live.js +6 -3
- package/dist/type/bridge-live.mjs +4 -2
- package/dist/type/bridge.d.ts +6 -4
- package/dist/type/bridge.js +17 -9
- package/dist/type/bridge.mjs +5 -3
- package/dist/type/coerce-plan.d.ts +5 -5
- package/dist/type/coerce-plan.js +41 -39
- package/dist/type/coerce-plan.mjs +43 -39
- package/dist/type/coerce.d.ts +3 -7
- package/dist/type/coerce.js +18 -75
- package/dist/type/coerce.mjs +19 -76
- package/dist/type/compat.d.ts +3 -0
- package/dist/type/compat.js +23 -14
- package/dist/type/compat.mjs +20 -10
- package/dist/type/elysia/array-buffer.d.ts +4 -1
- package/dist/type/elysia/array-buffer.js +17 -17
- package/dist/type/elysia/array-buffer.mjs +17 -17
- package/dist/type/elysia/array-string.js +2 -40
- package/dist/type/elysia/array-string.mjs +2 -39
- package/dist/type/elysia/array.js +5 -9
- package/dist/type/elysia/array.mjs +5 -9
- package/dist/type/elysia/boolean-string.js +2 -3
- package/dist/type/elysia/boolean-string.mjs +1 -1
- package/dist/type/elysia/boolean.js +3 -12
- package/dist/type/elysia/boolean.mjs +3 -11
- package/dist/type/elysia/cookie.d.ts +3 -4
- package/dist/type/elysia/cookie.js +5 -15
- package/dist/type/elysia/cookie.mjs +5 -15
- package/dist/type/elysia/date.js +13 -20
- package/dist/type/elysia/date.mjs +10 -16
- package/dist/type/elysia/file-type.d.ts +11 -4
- package/dist/type/elysia/file-type.js +17 -2
- package/dist/type/elysia/file-type.mjs +17 -3
- package/dist/type/elysia/file.d.ts +1 -3
- package/dist/type/elysia/file.js +11 -27
- package/dist/type/elysia/file.mjs +11 -12
- package/dist/type/elysia/files.js +7 -11
- package/dist/type/elysia/files.mjs +7 -10
- package/dist/type/elysia/form.js +2 -3
- package/dist/type/elysia/form.mjs +3 -3
- package/dist/type/elysia/integer-string.d.ts +1 -1
- package/dist/type/elysia/integer-string.js +4 -30
- package/dist/type/elysia/integer-string.mjs +5 -30
- package/dist/type/elysia/integer.js +3 -12
- package/dist/type/elysia/integer.mjs +3 -11
- package/dist/type/elysia/intersect.js +0 -5
- package/dist/type/elysia/intersect.mjs +0 -5
- package/dist/type/elysia/json-string.d.ts +7 -0
- package/dist/type/elysia/json-string.js +47 -0
- package/dist/type/elysia/json-string.mjs +46 -0
- package/dist/type/elysia/keep-config.d.ts +14 -0
- package/dist/type/elysia/keep-config.js +62 -0
- package/dist/type/elysia/keep-config.mjs +53 -0
- package/dist/type/elysia/maybe-empty.js +3 -4
- package/dist/type/elysia/maybe-empty.mjs +1 -1
- package/dist/type/elysia/nullable.js +2 -3
- package/dist/type/elysia/nullable.mjs +1 -1
- package/dist/type/elysia/number.d.ts +2 -1
- package/dist/type/elysia/number.js +19 -11
- package/dist/type/elysia/number.mjs +18 -10
- package/dist/type/elysia/numeric-enum.d.ts +1 -1
- package/dist/type/elysia/numeric-enum.js +4 -5
- package/dist/type/elysia/numeric-enum.mjs +3 -3
- package/dist/type/elysia/numeric.d.ts +4 -2
- package/dist/type/elysia/numeric.js +20 -17
- package/dist/type/elysia/numeric.mjs +19 -16
- package/dist/type/elysia/object-string.js +2 -37
- package/dist/type/elysia/object-string.mjs +2 -36
- package/dist/type/elysia/object.js +5 -9
- package/dist/type/elysia/object.mjs +5 -9
- package/dist/type/elysia/optional.js +8 -8
- package/dist/type/elysia/optional.mjs +7 -7
- package/dist/type/elysia/problem.d.ts +20 -0
- package/dist/type/elysia/problem.js +25 -0
- package/dist/type/elysia/problem.mjs +24 -0
- package/dist/type/elysia/string.js +4 -3
- package/dist/type/elysia/string.mjs +4 -2
- package/dist/type/elysia/uint8-array.d.ts +1 -1
- package/dist/type/elysia/uint8-array.js +5 -20
- package/dist/type/elysia/uint8-array.mjs +5 -19
- package/dist/type/elysia/union-enum.js +7 -8
- package/dist/type/elysia/union-enum.mjs +6 -6
- package/dist/type/elysia/union.js +0 -5
- package/dist/type/elysia/union.mjs +0 -5
- package/dist/type/elysia/utils.d.ts +2 -4
- package/dist/type/elysia/utils.js +10 -21
- package/dist/type/elysia/utils.mjs +7 -15
- package/dist/type/exports.d.ts +4 -2
- package/dist/type/exports.js +23 -2
- package/dist/type/exports.mjs +11 -2
- package/dist/type/index.d.ts +10 -2
- package/dist/type/index.js +62 -15
- package/dist/type/index.mjs +65 -11
- package/dist/type/shared.d.ts +3 -9
- package/dist/type/shared.js +44 -97
- package/dist/type/shared.mjs +43 -97
- package/dist/type/sync-require.d.ts +11 -0
- package/dist/type/sync-require.js +14 -0
- package/dist/type/sync-require.mjs +12 -0
- package/dist/type/typebox-system-lite.d.ts +2 -0
- package/dist/type/typebox-system-lite.js +34 -0
- package/dist/type/typebox-system-lite.mjs +3 -0
- package/dist/type/typebox-system-require.d.ts +7 -0
- package/dist/type/typebox-system-require.js +24 -0
- package/dist/type/typebox-system-require.mjs +23 -0
- package/dist/type/typebox-type-live.d.ts +11 -0
- package/dist/type/typebox-type-live.js +45 -0
- package/dist/type/typebox-type-live.mjs +20 -0
- package/dist/type/typebox-type.d.ts +34 -0
- package/dist/type/typebox-type.js +199 -0
- package/dist/type/typebox-type.mjs +86 -0
- package/dist/type/typebox-value-live.d.ts +11 -0
- package/dist/type/typebox-value-live.js +31 -0
- package/dist/type/typebox-value-live.mjs +13 -0
- package/dist/type/typebox-value-ops.d.ts +4 -0
- package/dist/type/typebox-value-ops.js +90 -0
- package/dist/type/typebox-value-ops.mjs +5 -0
- package/dist/type/typebox-value-require.d.ts +8 -0
- package/dist/type/typebox-value-require.js +28 -0
- package/dist/type/typebox-value-require.mjs +25 -0
- package/dist/type/typebox-value.d.ts +35 -0
- package/dist/type/typebox-value.js +161 -0
- package/dist/type/typebox-value.mjs +74 -0
- package/dist/type/utils.js +1 -10
- package/dist/type/utils.mjs +1 -10
- package/dist/type/validator/clean-safe.d.ts +2 -4
- package/dist/type/validator/clean-safe.js +15 -11
- package/dist/type/validator/clean-safe.mjs +16 -10
- package/dist/type/validator/custom-error.js +12 -16
- package/dist/type/validator/custom-error.mjs +11 -14
- package/dist/type/validator/default-precompute.d.ts +9 -1
- package/dist/type/validator/default-precompute.js +40 -77
- package/dist/type/validator/default-precompute.mjs +37 -74
- package/dist/type/validator/exact-mirror-live.d.ts +8 -0
- package/dist/type/validator/exact-mirror-live.js +22 -0
- package/dist/type/validator/exact-mirror-live.mjs +17 -0
- package/dist/type/validator/exact-mirror-require.d.ts +4 -0
- package/dist/type/validator/exact-mirror-require.js +11 -0
- package/dist/type/validator/exact-mirror-require.mjs +9 -0
- package/dist/type/validator/exact-mirror.js +8 -8
- package/dist/type/validator/exact-mirror.mjs +9 -8
- package/dist/type/validator/frozen-check.js +5 -6
- package/dist/type/validator/frozen-check.mjs +6 -7
- package/dist/type/validator/index.d.ts +1 -0
- package/dist/type/validator/index.js +169 -166
- package/dist/type/validator/index.mjs +162 -158
- package/dist/type/validator/string-codec-aot.d.ts +2 -1
- package/dist/type/validator/string-codec-aot.js +8 -2
- package/dist/type/validator/string-codec-aot.mjs +7 -2
- package/dist/type/validator/validator-cache.d.ts +5 -4
- package/dist/type/validator/validator-cache.js +41 -24
- package/dist/type/validator/validator-cache.mjs +40 -22
- package/dist/types.d.ts +263 -95
- package/dist/universal/constants.d.ts +2 -1
- package/dist/universal/constants.js +3 -1
- package/dist/universal/constants.mjs +2 -1
- package/dist/universal/env.js +2 -3
- package/dist/universal/env.mjs +2 -3
- package/dist/universal/file.d.ts +6 -4
- package/dist/universal/file.js +11 -16
- package/dist/universal/file.mjs +12 -16
- package/dist/universal/index.d.ts +2 -2
- package/dist/universal/is-production.d.ts +1 -2
- package/dist/universal/is-production.js +1 -3
- package/dist/universal/is-production.mjs +2 -3
- package/dist/universal/server.d.ts +0 -272
- package/dist/utils.d.ts +43 -7
- package/dist/utils.js +181 -126
- package/dist/utils.mjs +168 -126
- package/dist/validator/index.d.ts +1 -1
- package/dist/validator/index.js +17 -30
- package/dist/validator/index.mjs +18 -31
- package/dist/validator/route.js +2 -1
- package/dist/validator/route.mjs +2 -1
- package/dist/ws/context.d.ts +8 -1
- package/dist/ws/context.js +68 -44
- package/dist/ws/context.mjs +67 -44
- package/dist/ws/parser.js +10 -20
- package/dist/ws/parser.mjs +10 -20
- package/dist/ws/route.d.ts +2 -2
- package/dist/ws/route.js +249 -141
- package/dist/ws/route.mjs +254 -146
- package/dist/ws/types.d.ts +2 -2
- package/package.json +23 -49
- package/dist/compile/analysis-cache.d.ts +0 -6
- package/dist/compile/analysis-cache.js +0 -12
- package/dist/compile/analysis-cache.mjs +0 -11
- package/dist/cookie/index.d.ts +0 -7
- package/dist/cookie/index.js +0 -13
- package/dist/cookie/index.mjs +0 -7
- package/dist/handler/index.d.ts +0 -2
- package/dist/handler/index.js +0 -5
- package/dist/handler/index.mjs +0 -3
package/dist/ws/route.mjs
CHANGED
|
@@ -1,88 +1,27 @@
|
|
|
1
1
|
import { isBun } from "../universal/constants.mjs";
|
|
2
|
-
import { deriveEntryFn,
|
|
2
|
+
import { assignOwn, deriveEntryFn, isSocketQuiet, nullObject } from "../utils.mjs";
|
|
3
3
|
import { isBridgeLive } from "../type/bridge.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { ElysiaError, ElysiaStatus, ValidationError, elysiaErrorProblem, internalServerErrorBodyString, problemBody, problemResponse } from "../error.mjs";
|
|
5
|
+
import { hasSyncHmac } from "../cookie/crypto.mjs";
|
|
6
6
|
import { mapResponse } from "../adapter/web-standard/handler.mjs";
|
|
7
7
|
import { parseQueryFromURL } from "../parse-query.mjs";
|
|
8
|
+
import { Capture, Compiled, aotDrift, warnAotDrift } from "../compile/aot.mjs";
|
|
8
9
|
import { frozenRootOf } from "../generation.mjs";
|
|
9
|
-
import {
|
|
10
|
+
import { compileCookieConfig } from "../cookie/config.mjs";
|
|
11
|
+
import { buildCookieJar, parseCookieRaw, parseCookieRawDeferred, parseCookieRawLazy, signCookieValues } from "../cookie/utils.mjs";
|
|
12
|
+
import { finalizeRouteError } from "../handler/utils.mjs";
|
|
13
|
+
import { adoptErrorType, claimsProblemType, createErrorHandler, readAnnotation, resolveStatus, statusFallbackBody } from "../handler/error.mjs";
|
|
10
14
|
import { deriveModes, getQueryParseChannels, replaceDeriveContext } from "../compile/handler/utils.mjs";
|
|
15
|
+
import { sucrose } from "../sucrose.mjs";
|
|
11
16
|
import { StandardValidator } from "../validator/index.mjs";
|
|
12
17
|
import { RouteValidator } from "../validator/route.mjs";
|
|
13
18
|
import { buildFrozenRouteValidator, isBridgeNotInitialized } from "../compile/handler/frozen-validator.mjs";
|
|
14
|
-
import { composeRouteHook, localMacroRoot, resolveWSLocalHook } from "../compile/handler/index.mjs";
|
|
15
|
-
import { ElysiaWS, isGeneratorObject } from "./context.mjs";
|
|
19
|
+
import { composeRouteHook, localMacroRoot, resolveWSLocalHook, routeShape } from "../compile/handler/index.mjs";
|
|
20
|
+
import { ElysiaWS, isGeneratorObject, trackWSSettling } from "./context.mjs";
|
|
16
21
|
import { createMessageParser } from "./parser.mjs";
|
|
17
22
|
|
|
18
23
|
//#region src/ws/route.ts
|
|
19
24
|
const EMPTY_HOOKS = Object.freeze([]);
|
|
20
|
-
/**
|
|
21
|
-
* Build-time (route-registration-time) analysis of a WS `message` handler to
|
|
22
|
-
* decide whether the per-frame `ws.body` view must be assigned.
|
|
23
|
-
*/
|
|
24
|
-
function handlerMayTouchBody(fn) {
|
|
25
|
-
if (!fn) return false;
|
|
26
|
-
let source;
|
|
27
|
-
try {
|
|
28
|
-
source = Function.prototype.toString.call(fn);
|
|
29
|
-
} catch {
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
if (source.indexOf("[native code]") !== -1) return true;
|
|
33
|
-
if (/\bbody\b/.test(source)) return true;
|
|
34
|
-
if (/\barguments\b/.test(source)) return true;
|
|
35
|
-
if (source.indexOf("[") !== -1) return true;
|
|
36
|
-
if (source.indexOf("...") !== -1) return true;
|
|
37
|
-
const parsed = firstParamIdentifier(source);
|
|
38
|
-
if (parsed === void 0) return true;
|
|
39
|
-
const { name: wsName, bodyStart, paramsEnd } = parsed;
|
|
40
|
-
if (source.slice(0, paramsEnd).indexOf("(", 1) !== -1) return true;
|
|
41
|
-
const body = source.slice(bodyStart);
|
|
42
|
-
const safeName = wsName.replace(/[$]/g, "\\$&");
|
|
43
|
-
if (new RegExp(`(?<![\\w$.])${safeName}(?![\\w$]|\\s*\\.)`).test(body)) return true;
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
function firstParamIdentifier(source) {
|
|
47
|
-
const open = source.indexOf("(");
|
|
48
|
-
if (open === -1) {
|
|
49
|
-
const m = /^\s*(?:async\s+)?([A-Za-z_$][\w$]*)\s*=>/.exec(source);
|
|
50
|
-
if (!m) return void 0;
|
|
51
|
-
const end = m.index + m[0].length;
|
|
52
|
-
return {
|
|
53
|
-
name: m[1],
|
|
54
|
-
bodyStart: end,
|
|
55
|
-
paramsEnd: end
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
let depth = 0;
|
|
59
|
-
let close = -1;
|
|
60
|
-
for (let i = open; i < source.length; i++) {
|
|
61
|
-
const c = source[i];
|
|
62
|
-
if (c === "(") depth++;
|
|
63
|
-
else if (c === ")") {
|
|
64
|
-
depth--;
|
|
65
|
-
if (depth === 0) {
|
|
66
|
-
close = i;
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (close === -1) return void 0;
|
|
72
|
-
const params = source.slice(open + 1, close).trim();
|
|
73
|
-
if (params.length === 0) return void 0;
|
|
74
|
-
let first = params;
|
|
75
|
-
const comma = params.indexOf(",");
|
|
76
|
-
if (comma !== -1) first = params.slice(0, comma).trim();
|
|
77
|
-
if (first[0] === "{" || first[0] === "[") return void 0;
|
|
78
|
-
const m = /^([A-Za-z_$][\w$]*)/.exec(first);
|
|
79
|
-
if (!m) return void 0;
|
|
80
|
-
return {
|
|
81
|
-
name: m[1],
|
|
82
|
-
bodyStart: close + 1,
|
|
83
|
-
paramsEnd: close + 1
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
25
|
function concatHooks(...sources) {
|
|
87
26
|
let result;
|
|
88
27
|
for (let i = 0; i < sources.length; i++) {
|
|
@@ -103,7 +42,6 @@ async function applyMapResponse(ws, value, mapResponses) {
|
|
|
103
42
|
}
|
|
104
43
|
return value;
|
|
105
44
|
}
|
|
106
|
-
const isBackpressured = (status) => typeof status === "number" && status <= 0;
|
|
107
45
|
const isEmptyPayload = (payload) => {
|
|
108
46
|
if (payload === "" || payload == null) return true;
|
|
109
47
|
if (typeof payload === "string") return false;
|
|
@@ -135,7 +73,7 @@ async function handleWSResponse(ws, value, mapResponses) {
|
|
|
135
73
|
const mapped = mapResponses.length ? await applyMapResponse(ws, yielded, mapResponses) : yielded;
|
|
136
74
|
let status = ws.send(mapped);
|
|
137
75
|
const canBackpressure = !isEmptyPayload(mapped);
|
|
138
|
-
while (canBackpressure &&
|
|
76
|
+
while (canBackpressure && typeof status === "number" && status <= 0) {
|
|
139
77
|
if (ws.readyState >= 2) return;
|
|
140
78
|
await waitForDrain(ws);
|
|
141
79
|
if (ws.readyState >= 2) return;
|
|
@@ -154,6 +92,38 @@ async function handleWSResponse(ws, value, mapResponses) {
|
|
|
154
92
|
const mapped = mapResponses.length ? await applyMapResponse(ws, value, mapResponses) : value;
|
|
155
93
|
ws.send(mapped);
|
|
156
94
|
}
|
|
95
|
+
function wsErrorFrameFallback(error) {
|
|
96
|
+
if (claimsProblemType(error)) try {
|
|
97
|
+
const status = resolveStatus(error.status);
|
|
98
|
+
const served = typeof status === "number" && status >= 100 ? status : 500;
|
|
99
|
+
const stringify = (value) => typeof value === "object" && value !== null ? JSON.stringify(value) : String(value);
|
|
100
|
+
const problemFrame = (detail) => JSON.stringify(problemBody({
|
|
101
|
+
type: error.type ?? "about:blank",
|
|
102
|
+
...typeof error.code === "string" ? { code: error.code } : {},
|
|
103
|
+
detail,
|
|
104
|
+
status: served
|
|
105
|
+
}));
|
|
106
|
+
const serveMessage = () => problemFrame(statusFallbackBody(error, served));
|
|
107
|
+
const serveDetail = () => {
|
|
108
|
+
const detail = readAnnotation(error, "detail", true);
|
|
109
|
+
if (detail === void 0) return serveMessage();
|
|
110
|
+
if (detail instanceof Promise) return detail.then((resolved) => resolved === void 0 ? serveMessage() : problemFrame(resolved)).catch(() => wsLegacyFrame(error));
|
|
111
|
+
return problemFrame(detail);
|
|
112
|
+
};
|
|
113
|
+
const value = readAnnotation(error, "value", true);
|
|
114
|
+
if (value === void 0) return serveDetail();
|
|
115
|
+
if (value instanceof Promise) return value.then((resolved) => resolved === void 0 ? serveDetail() : stringify(resolved)).catch(() => wsLegacyFrame(error));
|
|
116
|
+
return stringify(value);
|
|
117
|
+
} catch {}
|
|
118
|
+
return wsLegacyFrame(error);
|
|
119
|
+
}
|
|
120
|
+
function wsLegacyFrame(error) {
|
|
121
|
+
if (error?.status) {
|
|
122
|
+
const body = statusFallbackBody(error, error.status);
|
|
123
|
+
return typeof body === "object" ? JSON.stringify(body) : String(body);
|
|
124
|
+
}
|
|
125
|
+
return internalServerErrorBodyString(error);
|
|
126
|
+
}
|
|
157
127
|
function wsErrorFrame(error) {
|
|
158
128
|
if (error instanceof ValidationError) try {
|
|
159
129
|
return JSON.stringify(error.payload);
|
|
@@ -166,12 +136,7 @@ function wsErrorFrame(error) {
|
|
|
166
136
|
} catch {}
|
|
167
137
|
if (typeof error?.toResponse === "function") {
|
|
168
138
|
if (error instanceof ElysiaError && error.toResponse === ElysiaError.prototype.toResponse) try {
|
|
169
|
-
return JSON.stringify(problemBody(
|
|
170
|
-
type: error.problemType,
|
|
171
|
-
title: error.problemTitle,
|
|
172
|
-
status: error.status ?? 500,
|
|
173
|
-
detail: error.response !== void 0 && error.response !== error.problemTitle ? error.response : void 0
|
|
174
|
-
}));
|
|
139
|
+
return JSON.stringify(problemBody(elysiaErrorProblem(error)));
|
|
175
140
|
} catch {}
|
|
176
141
|
try {
|
|
177
142
|
const r = error.toResponse();
|
|
@@ -180,13 +145,6 @@ function wsErrorFrame(error) {
|
|
|
180
145
|
}
|
|
181
146
|
return wsErrorFrameFallback(error);
|
|
182
147
|
}
|
|
183
|
-
function wsErrorFrameFallback(error) {
|
|
184
|
-
if (error?.status) {
|
|
185
|
-
const body = error.response !== void 0 ? error.response : isProduction() ? error.status >= 500 ? "Internal Server Error" : "" : error.message ?? "";
|
|
186
|
-
return typeof body === "object" ? JSON.stringify(body) : String(body);
|
|
187
|
-
}
|
|
188
|
-
return internalServerErrorBodyString(error);
|
|
189
|
-
}
|
|
190
148
|
function sendErrorFrame(ws, error) {
|
|
191
149
|
const frame = wsErrorFrame(error);
|
|
192
150
|
if (typeof frame === "string") {
|
|
@@ -202,9 +160,7 @@ function sendErrorFrame(ws, error) {
|
|
|
202
160
|
}, () => {});
|
|
203
161
|
}
|
|
204
162
|
function validateUpgradeChannel(validator, value, type) {
|
|
205
|
-
|
|
206
|
-
if (validator.hasCodec) return validator.From(value, type);
|
|
207
|
-
return validator.EncodeFrom(value, type);
|
|
163
|
+
return validator.hasCodec || validator instanceof StandardValidator ? validator.From(value, type) : validator.EncodeFrom(value, type);
|
|
208
164
|
}
|
|
209
165
|
const wsOptions = [
|
|
210
166
|
"maxPayloadLength",
|
|
@@ -217,14 +173,35 @@ const wsOptions = [
|
|
|
217
173
|
];
|
|
218
174
|
function buildWSRoute(route, app) {
|
|
219
175
|
const hook = resolveWSLocalHook(localMacroRoot(route[7] ?? route[3] ?? app, app), route[4], app) ?? nullObject();
|
|
176
|
+
const instance = route[3] ?? app;
|
|
177
|
+
const appHookChain = route[5];
|
|
178
|
+
const inheritedChain = route[6];
|
|
179
|
+
const composed = composeRouteHook(instance, route[4], appHookChain, inheritedChain, app, route[7]) ?? hook;
|
|
220
180
|
let validators;
|
|
221
|
-
const
|
|
181
|
+
const programId = frozenRootOf(app)["~programId"];
|
|
182
|
+
const captured = Compiled.getHandler(programId, "WS", route[1]);
|
|
183
|
+
let live = false;
|
|
184
|
+
if (Capture.isCapturing()) Capture.handler({
|
|
185
|
+
method: "WS",
|
|
186
|
+
path: route[1],
|
|
187
|
+
alias: "",
|
|
188
|
+
code: "",
|
|
189
|
+
k: routeShape(composed, void 0, app)
|
|
190
|
+
});
|
|
191
|
+
else if (Compiled.hasProgram(programId)) {
|
|
192
|
+
const shape = routeShape(composed, void 0, app);
|
|
193
|
+
live = shape === void 0 || captured?.k !== shape;
|
|
194
|
+
}
|
|
195
|
+
const frozenEager = isBridgeLive() || live ? void 0 : buildFrozenRouteValidator(composed, app, "WS", route[1]);
|
|
222
196
|
if (frozenEager) validators = frozenEager;
|
|
223
197
|
else try {
|
|
224
|
-
validators = new RouteValidator(
|
|
198
|
+
validators = new RouteValidator(composed, {
|
|
225
199
|
models: frozenRootOf(app)["~ext"]?.models,
|
|
226
200
|
app,
|
|
227
|
-
|
|
201
|
+
normalize: frozenRootOf(app)["~config"]?.normalize,
|
|
202
|
+
sanitize: frozenRootOf(app)["~config"]?.sanitize,
|
|
203
|
+
schemas: composed.schemas,
|
|
204
|
+
aot: live ? void 0 : {
|
|
228
205
|
method: "WS",
|
|
229
206
|
path: route[1]
|
|
230
207
|
},
|
|
@@ -232,23 +209,23 @@ function buildWSRoute(route, app) {
|
|
|
232
209
|
});
|
|
233
210
|
} catch (error) {
|
|
234
211
|
if (!isBridgeNotInitialized(error)) throw error;
|
|
235
|
-
|
|
212
|
+
if (live) throw new Error(aotDrift("WS", route[1]), { cause: error });
|
|
213
|
+
const frozen = buildFrozenRouteValidator(composed, app, "WS", route[1]);
|
|
236
214
|
if (!frozen) throw error;
|
|
237
215
|
validators = frozen;
|
|
238
216
|
}
|
|
217
|
+
if (live && captured) warnAotDrift("WS", route[1]);
|
|
239
218
|
const responseValidator = validators.response;
|
|
240
219
|
const defaultResponseValidator = responseValidator ? responseValidator[200] ?? responseValidator[Object.keys(responseValidator)[0]] : void 0;
|
|
220
|
+
const cookieIsOptional = !!composed.cookie?.["~optional"];
|
|
241
221
|
const queryChannels = getQueryParseChannels(validators.query?.schema);
|
|
242
222
|
const queryArray = queryChannels?.array;
|
|
243
223
|
const queryObject = queryChannels?.object;
|
|
244
|
-
const
|
|
245
|
-
const
|
|
246
|
-
const inheritedChain = route[6];
|
|
247
|
-
const flatAppHook = composeRouteHook(instance, void 0, appHookChain, inheritedChain, app, route[7]) ?? {};
|
|
248
|
-
const parseHooks = hook.parse == null ? [] : Array.isArray(hook.parse) ? hook.parse : [hook.parse];
|
|
224
|
+
const flatAppHook = composeRouteHook(instance, void 0, appHookChain, inheritedChain, app, route[7], false) ?? {};
|
|
225
|
+
const parseHooks = concatHooks(hook.parse);
|
|
249
226
|
const transforms = concatHooks(flatAppHook.transform, hook.transform);
|
|
250
227
|
const allBeforeHandles = concatHooks(flatAppHook.beforeHandle, hook.beforeHandle);
|
|
251
|
-
const deriveEntries =
|
|
228
|
+
const deriveEntries = concatHooks(flatAppHook["~deriveEntries"], hook["~deriveEntries"]);
|
|
252
229
|
const deriveSet = deriveEntries.length ? new Set(deriveEntries.map(deriveEntryFn)) : void 0;
|
|
253
230
|
const upgradeDeriveModes = deriveModes(allBeforeHandles, deriveEntries);
|
|
254
231
|
const messageBeforeHandles = allBeforeHandles.filter((fn) => !deriveSet?.has(fn));
|
|
@@ -256,8 +233,31 @@ function buildWSRoute(route, app) {
|
|
|
256
233
|
const mapResponses = concatHooks(flatAppHook.mapResponse, hook.mapResponse);
|
|
257
234
|
const afterResponses = concatHooks(flatAppHook.afterResponse, hook.afterResponse);
|
|
258
235
|
const errorHandlers = concatHooks(hook.error, flatAppHook.error);
|
|
236
|
+
const inference = sucrose(hook.message, {
|
|
237
|
+
beforeHandle: [
|
|
238
|
+
...allBeforeHandles,
|
|
239
|
+
hook.open,
|
|
240
|
+
hook.close,
|
|
241
|
+
hook.drain,
|
|
242
|
+
hook.ping,
|
|
243
|
+
hook.pong,
|
|
244
|
+
typeof hook.upgrade === "function" ? hook.upgrade : void 0
|
|
245
|
+
].filter(Boolean),
|
|
246
|
+
parse: parseHooks,
|
|
247
|
+
transform: transforms,
|
|
248
|
+
error: errorHandlers,
|
|
249
|
+
afterHandle: afterHandles,
|
|
250
|
+
mapResponse: mapResponses,
|
|
251
|
+
afterResponse: afterResponses
|
|
252
|
+
});
|
|
253
|
+
const cookieConfig = validators.cookie || inference.cookie ? compileCookieConfig(composed.cookie, frozenRootOf(app)["~config"]?.cookie, frozenRootOf(app)["~ext"]?.models, composed.schemas) : void 0;
|
|
254
|
+
const signCookies = cookieConfig?.hasSign ? (set) => signCookieValues(set.cookie, cookieConfig) : void 0;
|
|
259
255
|
const parseMessage = createMessageParser(parseHooks);
|
|
260
|
-
const handleUpgradeError = createErrorHandler(errorHandlers.length ? errorHandlers : void 0, ((response, set, context) =>
|
|
256
|
+
const handleUpgradeError = createErrorHandler(errorHandlers.length ? errorHandlers : void 0, ((response, set, context) => {
|
|
257
|
+
const map = () => mapResponse(response, set, context?.request);
|
|
258
|
+
const pending = signCookies?.(set);
|
|
259
|
+
return pending ? pending.then(map) : map();
|
|
260
|
+
}), frozenRootOf(app)["~config"]?.allowUnsafeValidationDetails);
|
|
261
261
|
async function handleError(ws, error) {
|
|
262
262
|
const errCtx = Object.create(ws);
|
|
263
263
|
errCtx.error = error;
|
|
@@ -271,6 +271,7 @@ function buildWSRoute(route, app) {
|
|
|
271
271
|
break;
|
|
272
272
|
}
|
|
273
273
|
if (r !== void 0) {
|
|
274
|
+
r = adoptErrorType(r, error);
|
|
274
275
|
try {
|
|
275
276
|
await handleWSResponse(ws, r, mapResponses);
|
|
276
277
|
} catch {}
|
|
@@ -280,12 +281,6 @@ function buildWSRoute(route, app) {
|
|
|
280
281
|
sendErrorFrame(ws, error);
|
|
281
282
|
}
|
|
282
283
|
const bodyValidator = validators.body;
|
|
283
|
-
function validateMessageBody(message) {
|
|
284
|
-
if (!bodyValidator) return message;
|
|
285
|
-
if (bodyValidator.hasCodec) return bodyValidator.From(message, "body");
|
|
286
|
-
if (bodyValidator instanceof StandardValidator) return bodyValidator.From(message, "body");
|
|
287
|
-
return bodyValidator.EncodeFrom(message, "body");
|
|
288
|
-
}
|
|
289
284
|
function onMessageValidationError(ws, error) {
|
|
290
285
|
if (errorHandlers.length === 0) {
|
|
291
286
|
if (frozenRootOf(app)["~config"]?.allowUnsafeValidationDetails && error instanceof ValidationError) error.allowUnsafeValidationDetails = true;
|
|
@@ -293,7 +288,6 @@ function buildWSRoute(route, app) {
|
|
|
293
288
|
}
|
|
294
289
|
return handleError(ws, error);
|
|
295
290
|
}
|
|
296
|
-
const messageHandlerTouchesBody = !!bodyValidator || handlerMayTouchBody(hook.message) || errorHandlers.some(handlerMayTouchBody);
|
|
297
291
|
const syncDispatchEligible = transforms.length === 0 && messageBeforeHandles.length === 0 && afterHandles.length === 0 && afterResponses.length === 0 && mapResponses.length === 0;
|
|
298
292
|
function finishMessageResult(ws, value) {
|
|
299
293
|
if (value === void 0) return;
|
|
@@ -308,7 +302,7 @@ function buildWSRoute(route, app) {
|
|
|
308
302
|
if (bodyValidator) {
|
|
309
303
|
let decoded;
|
|
310
304
|
try {
|
|
311
|
-
decoded =
|
|
305
|
+
decoded = validateUpgradeChannel(bodyValidator, message, "body");
|
|
312
306
|
} catch (error) {
|
|
313
307
|
return onMessageValidationError(ws, error);
|
|
314
308
|
}
|
|
@@ -319,7 +313,7 @@ function buildWSRoute(route, app) {
|
|
|
319
313
|
}
|
|
320
314
|
function runMessageSync(ws, message) {
|
|
321
315
|
try {
|
|
322
|
-
|
|
316
|
+
ws.body = message;
|
|
323
317
|
const result = hook.message(ws, message);
|
|
324
318
|
if (result instanceof Promise) return result.then((resolved) => finishMessageResult(ws, resolved), (error) => handleError(ws, error));
|
|
325
319
|
return finishMessageResult(ws, result);
|
|
@@ -405,19 +399,37 @@ function buildWSRoute(route, app) {
|
|
|
405
399
|
if (r instanceof Promise) r = await r;
|
|
406
400
|
context.params = r;
|
|
407
401
|
}
|
|
408
|
-
if (validators.query) {
|
|
402
|
+
if (validators.query || inference.query) {
|
|
409
403
|
const url = request.url;
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
404
|
+
let r = parseQueryFromURL(url, context.qi ?? url.indexOf("?"), queryArray, queryObject);
|
|
405
|
+
if (validators.query) {
|
|
406
|
+
r = validateUpgradeChannel(validators.query, r, "query");
|
|
407
|
+
if (r instanceof Promise) r = await r;
|
|
408
|
+
}
|
|
413
409
|
context.query = r;
|
|
414
410
|
}
|
|
415
|
-
if (validators.headers) {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
411
|
+
if (validators.headers || inference.headers) {
|
|
412
|
+
let r = isBun ? request.headers.toJSON() : Object.fromEntries(request.headers);
|
|
413
|
+
if (validators.headers) {
|
|
414
|
+
r = validateUpgradeChannel(validators.headers, r, "headers");
|
|
415
|
+
if (r instanceof Promise) r = await r;
|
|
416
|
+
}
|
|
419
417
|
context.headers = r;
|
|
420
418
|
}
|
|
419
|
+
if (cookieConfig) {
|
|
420
|
+
const cookieHeader = request.headers.get("cookie");
|
|
421
|
+
if (validators.cookie) {
|
|
422
|
+
const raw = await parseCookieRaw(cookieHeader, cookieConfig);
|
|
423
|
+
let r = raw;
|
|
424
|
+
if (!cookieIsOptional || Object.keys(raw).length) {
|
|
425
|
+
r = validateUpgradeChannel(validators.cookie, raw, "cookie");
|
|
426
|
+
if (r instanceof Promise) r = await r;
|
|
427
|
+
}
|
|
428
|
+
context.cookie = buildCookieJar(context.set, r, cookieConfig);
|
|
429
|
+
} else if (!cookieConfig.hasSign) context.cookie = buildCookieJar(context.set, parseCookieRawDeferred(cookieHeader, cookieConfig), cookieConfig, void 0, 1);
|
|
430
|
+
else if (hasSyncHmac && cookieConfig.verify === "lazy") context.cookie = buildCookieJar(context.set, parseCookieRawLazy(cookieHeader, cookieConfig), cookieConfig, 1);
|
|
431
|
+
else context.cookie = buildCookieJar(context.set, await parseCookieRaw(cookieHeader, cookieConfig, cookieConfig.verify === "lazy" ? 1 : void 0), cookieConfig);
|
|
432
|
+
}
|
|
421
433
|
for (let i = 0; i < transforms.length; i++) {
|
|
422
434
|
const r = transforms[i](context);
|
|
423
435
|
if (r instanceof Promise) await r;
|
|
@@ -429,9 +441,10 @@ function buildWSRoute(route, app) {
|
|
|
429
441
|
const deriveMode = upgradeDeriveModes?.[i];
|
|
430
442
|
if (deriveMode !== void 0 && !(r instanceof ElysiaStatus)) {
|
|
431
443
|
if (r && typeof r === "object") if (deriveMode) context = replaceDeriveContext(context, r);
|
|
432
|
-
else
|
|
444
|
+
else assignOwn(context, r);
|
|
433
445
|
} else if (r !== void 0) {
|
|
434
446
|
if (r instanceof Response) return r;
|
|
447
|
+
if (signCookies) await signCookies(context.set);
|
|
435
448
|
return mapResponse(r, context.set, context.request);
|
|
436
449
|
}
|
|
437
450
|
}
|
|
@@ -464,7 +477,11 @@ function buildWSRoute(route, app) {
|
|
|
464
477
|
}
|
|
465
478
|
})) return new Response("Expected a websocket connection", { status: 400 });
|
|
466
479
|
} catch (error) {
|
|
467
|
-
|
|
480
|
+
try {
|
|
481
|
+
return await handleUpgradeError(context, error);
|
|
482
|
+
} catch (thrown) {
|
|
483
|
+
return finalizeRouteError(app, context, thrown, signCookies);
|
|
484
|
+
}
|
|
468
485
|
}
|
|
469
486
|
};
|
|
470
487
|
const options = nullObject();
|
|
@@ -474,33 +491,46 @@ function buildWSRoute(route, app) {
|
|
|
474
491
|
function resolveWSOptions(entries) {
|
|
475
492
|
if (!entries || entries.length === 0) return void 0;
|
|
476
493
|
if (entries.length === 1) return { ...entries[0].value };
|
|
477
|
-
const ordered = entries.
|
|
478
|
-
entry,
|
|
479
|
-
index
|
|
480
|
-
})).sort((a, b) => b.entry.depth - a.entry.depth || a.index - b.index);
|
|
494
|
+
const ordered = entries.toSorted((a, b) => b.depth - a.depth);
|
|
481
495
|
const result = {};
|
|
482
496
|
let warned;
|
|
483
|
-
for (const
|
|
497
|
+
for (const entry of ordered) for (const key in entry.value) {
|
|
484
498
|
const incoming = entry.value[key];
|
|
485
499
|
if (key in result && result[key] !== incoming && !warned?.has(key)) {
|
|
486
500
|
(warned ??= /* @__PURE__ */ new Set()).add(key);
|
|
487
|
-
console.warn(`[Elysia] Conflicting WebSocket option '${key}' across .use(websocket())
|
|
501
|
+
console.warn(`[Elysia] Conflicting WebSocket option '${key}' across .use(websocket()). Using nearest-root registration.`);
|
|
488
502
|
}
|
|
489
503
|
result[key] = incoming;
|
|
490
504
|
}
|
|
491
505
|
return result;
|
|
492
506
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
507
|
+
const wsLimits = [
|
|
508
|
+
"maxPayloadLength",
|
|
509
|
+
"backpressureLimit",
|
|
510
|
+
"idleTimeout"
|
|
511
|
+
];
|
|
512
|
+
const routeOwnedKeys = /* @__PURE__ */ new WeakMap();
|
|
513
|
+
function accumulateWSOptions(target, routeOptions) {
|
|
514
|
+
let owned = routeOwnedKeys.get(target);
|
|
515
|
+
if (!owned) routeOwnedKeys.set(target, owned = /* @__PURE__ */ new Set());
|
|
516
|
+
for (const key in routeOptions) {
|
|
517
|
+
const incoming = routeOptions[key];
|
|
518
|
+
const current = target[key];
|
|
519
|
+
if (key in target && current !== incoming) {
|
|
520
|
+
if (isBun) {
|
|
521
|
+
console.warn(`[Elysia] Conflicting per-route WebSocket option '${key}'\nBun uses one global WebSocket config per server, per-route values are not enforced (for limits the strictest route wins, otherwise the last-registered route).`);
|
|
522
|
+
console.warn((/* @__PURE__ */ new Error()).stack);
|
|
523
|
+
}
|
|
524
|
+
if (owned.has(key) && typeof current === "number" && typeof incoming === "number" && current < incoming && wsLimits.includes(key)) continue;
|
|
499
525
|
}
|
|
526
|
+
owned.add(key);
|
|
527
|
+
target[key] = incoming;
|
|
500
528
|
}
|
|
501
|
-
Object.assign(target, routeOptions);
|
|
502
529
|
}
|
|
530
|
+
const MAX_INFLIGHT_MESSAGES = 256;
|
|
503
531
|
function buildGlobalWSHandler() {
|
|
532
|
+
let lifecycle;
|
|
533
|
+
const runLifecycle = (callback, ...args) => lifecycle ? lifecycle.run(callback, ...args) : callback(...args);
|
|
504
534
|
function getElysia(ws) {
|
|
505
535
|
let elysia = ws.data.elysia;
|
|
506
536
|
if (!elysia) {
|
|
@@ -515,39 +545,117 @@ function buildGlobalWSHandler() {
|
|
|
515
545
|
ws.send(typeof error?.message === "string" ? error.message : "Internal Server Error");
|
|
516
546
|
} catch {}
|
|
517
547
|
};
|
|
518
|
-
|
|
548
|
+
const releaseLifecycle = (ws) => {
|
|
549
|
+
if (!lifecycle?.closing && isSocketQuiet(ws)) {
|
|
550
|
+
delete ws.data["~lifecycleRun"];
|
|
551
|
+
lifecycle?.sockets.delete(ws);
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
const release = (ws) => {
|
|
555
|
+
const data = ws.data;
|
|
556
|
+
const inflight = data.inflight;
|
|
557
|
+
if (inflight) {
|
|
558
|
+
data.inflight = inflight - 1;
|
|
559
|
+
if (inflight === 1 && data.closeHandlerInvoked) releaseLifecycle(ws);
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
function dispatch(ws, message) {
|
|
563
|
+
let result;
|
|
564
|
+
try {
|
|
565
|
+
result = ws.data.message(getElysia(ws), message);
|
|
566
|
+
} catch (error) {
|
|
567
|
+
release(ws);
|
|
568
|
+
sendErrMsg(ws, error);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
if (result instanceof Promise) result.then(() => release(ws), (error) => {
|
|
572
|
+
release(ws);
|
|
573
|
+
sendErrMsg(ws, error);
|
|
574
|
+
});
|
|
575
|
+
else release(ws);
|
|
576
|
+
}
|
|
577
|
+
const handler = {
|
|
519
578
|
message(ws, message) {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
579
|
+
if (lifecycle?.closing) return;
|
|
580
|
+
const data = ws.data;
|
|
581
|
+
if (!data.message) return;
|
|
582
|
+
const inflight = (data.inflight ?? 0) + 1;
|
|
583
|
+
if (inflight > MAX_INFLIGHT_MESSAGES) {
|
|
584
|
+
try {
|
|
585
|
+
ws.close(1013, "Too many in-flight messages");
|
|
586
|
+
} catch {}
|
|
525
587
|
return;
|
|
526
588
|
}
|
|
527
|
-
|
|
589
|
+
data.inflight = inflight;
|
|
590
|
+
const opening = data.opening;
|
|
591
|
+
if (opening) return void opening.then(() => {
|
|
592
|
+
if (lifecycle?.closing || ws.readyState > 1) return release(ws);
|
|
593
|
+
dispatch(ws, message);
|
|
594
|
+
});
|
|
595
|
+
dispatch(ws, message);
|
|
528
596
|
},
|
|
529
597
|
open(ws) {
|
|
530
|
-
ws.data
|
|
598
|
+
if (lifecycle) Object.defineProperty(ws.data, "~lifecycleRun", {
|
|
599
|
+
configurable: true,
|
|
600
|
+
value: lifecycle.run
|
|
601
|
+
});
|
|
602
|
+
lifecycle?.sockets.add(ws);
|
|
603
|
+
if (lifecycle?.closing) {
|
|
604
|
+
ws.data.closeHandlerInvoked = true;
|
|
605
|
+
try {
|
|
606
|
+
ws.terminate();
|
|
607
|
+
} catch {}
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
const open = ws.data.open;
|
|
611
|
+
const result = open && runLifecycle(open, getElysia(ws));
|
|
612
|
+
if (result instanceof Promise) {
|
|
613
|
+
const clear = () => {
|
|
614
|
+
ws.data.opening = void 0;
|
|
615
|
+
releaseLifecycle(ws);
|
|
616
|
+
};
|
|
617
|
+
ws.data.opening = result.then(clear, clear);
|
|
618
|
+
}
|
|
531
619
|
},
|
|
532
620
|
drain(ws) {
|
|
621
|
+
if (lifecycle?.closing) return;
|
|
533
622
|
const elyWs = getElysia(ws);
|
|
534
623
|
drainWaiters(elyWs);
|
|
535
|
-
ws.data.drain
|
|
624
|
+
const drain = ws.data.drain;
|
|
625
|
+
trackWSSettling(ws.data, drain && runLifecycle(drain, elyWs), () => releaseLifecycle(ws));
|
|
536
626
|
},
|
|
537
627
|
close(ws, code, reason) {
|
|
538
628
|
const elyWs = getElysia(ws);
|
|
539
629
|
drainWaiters(elyWs);
|
|
540
|
-
if (ws.data.closeHandlerInvoked) return;
|
|
630
|
+
if (ws.data.closeHandlerInvoked) return releaseLifecycle(ws);
|
|
541
631
|
ws.data.closeHandlerInvoked = true;
|
|
542
|
-
|
|
632
|
+
let result;
|
|
633
|
+
try {
|
|
634
|
+
const close = ws.data.close;
|
|
635
|
+
result = close && runLifecycle(close, elyWs, code, reason);
|
|
636
|
+
} finally {
|
|
637
|
+
if (!(result instanceof Promise)) releaseLifecycle(ws);
|
|
638
|
+
}
|
|
639
|
+
if (result instanceof Promise) {
|
|
640
|
+
const closing = result.catch(() => {});
|
|
641
|
+
trackWSSettling(ws.data, closing, () => releaseLifecycle(ws));
|
|
642
|
+
}
|
|
543
643
|
},
|
|
544
644
|
ping(ws, data) {
|
|
545
|
-
|
|
645
|
+
if (lifecycle?.closing) return;
|
|
646
|
+
const ping = ws.data.ping;
|
|
647
|
+
trackWSSettling(ws.data, ping && runLifecycle(ping, getElysia(ws), data), () => releaseLifecycle(ws));
|
|
546
648
|
},
|
|
547
649
|
pong(ws, data) {
|
|
548
|
-
|
|
650
|
+
if (lifecycle?.closing) return;
|
|
651
|
+
const pong = ws.data.pong;
|
|
652
|
+
trackWSSettling(ws.data, pong && runLifecycle(pong, getElysia(ws), data), () => releaseLifecycle(ws));
|
|
549
653
|
}
|
|
550
654
|
};
|
|
655
|
+
Object.defineProperty(handler, "~lifecycle", { set(value) {
|
|
656
|
+
lifecycle = value;
|
|
657
|
+
} });
|
|
658
|
+
return handler;
|
|
551
659
|
}
|
|
552
660
|
|
|
553
661
|
//#endregion
|
package/dist/ws/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AfterResponseHandler, BaseMacro, DocumentDecoration, ErrorHandler, InlineHandlerResponse, InternalRoute, MapResponse, MaybeArray, MaybePromise, OptionalHandler, Prettify, RouteSchema, SingletonBase, TransformHandler } from "../types.js";
|
|
2
1
|
import { Context } from "../context.js";
|
|
2
|
+
import { AfterResponseHandler, BaseMacro, DocumentDecoration, ErrorHandler, InlineHandlerResponse, InternalRoute, MapResponse, MaybeArray, MaybePromise, OptionalHandler, Prettify, RouteSchema, SingletonBase, TransformHandler } from "../types.js";
|
|
3
3
|
import { AnyElysia } from "../base.js";
|
|
4
4
|
|
|
5
5
|
//#region src/ws/types.d.ts
|
|
@@ -151,7 +151,7 @@ interface WSCapability {
|
|
|
151
151
|
* Fold a single route's server-tuning options into the build-local config,
|
|
152
152
|
* warning on conflicting keys (Bun uses one global config per server).
|
|
153
153
|
*/
|
|
154
|
-
accumulateOptions(target: WSOptions, routeOptions: WSOptions
|
|
154
|
+
accumulateOptions(target: WSOptions, routeOptions: WSOptions): void;
|
|
155
155
|
}
|
|
156
156
|
//#endregion
|
|
157
157
|
export { AnyWSLocalHook, BufferSource, ElysiaWSLike, FlattenResponse, ServerWebSocket, ServerWebSocketSendStatus, WSCapability, WSHandlerResponse, WSHandlerResult, WSLocalHook, WSMessageHandler, WSOptions, WSOptionsEntry, WSParseHandler, WSResponseValidator, WSValidatorLike, WebSocketCompressor, WebSocketHandler, WebSocketReadyState };
|