elysia 2.0.0-beta.2 → 2.0.0-beta.20
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 +11 -13
- package/dist/compile/aot.js +34 -46
- package/dist/compile/aot.mjs +35 -45
- package/dist/compile/handler/descriptor.d.ts +9 -12
- package/dist/compile/handler/descriptor.js +17 -41
- package/dist/compile/handler/descriptor.mjs +18 -39
- 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 +6 -5
- package/dist/compile/handler/index.js +148 -109
- package/dist/compile/handler/index.mjs +149 -111
- package/dist/compile/handler/jit.d.ts +17 -17
- package/dist/compile/handler/jit.js +220 -148
- package/dist/compile/handler/jit.mjs +222 -151
- 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 +4 -3
- package/dist/compile/handler/reconstruct.mjs +4 -3
- 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 +1 -0
- package/dist/cookie/config.js +9 -9
- package/dist/cookie/config.mjs +9 -9
- 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 +47 -60
- package/dist/plugin/aot/core.js +172 -109
- package/dist/plugin/aot/core.mjs +169 -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 +47 -62
- package/dist/plugin/aot/source.mjs +48 -63
- 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 +29 -47
- package/dist/schema-snapshot.mjs +29 -47
- 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 +2 -6
- 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/constants.d.ts +1 -1
- 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/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 +3 -2
- package/dist/type/exports.js +13 -2
- package/dist/type/exports.mjs +10 -2
- package/dist/type/index.d.ts +10 -2
- package/dist/type/index.js +52 -15
- package/dist/type/index.mjs +55 -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 +37 -0
- package/dist/type/typebox-type-live.mjs +20 -0
- package/dist/type/typebox-type.d.ts +26 -0
- package/dist/type/typebox-type.js +135 -0
- package/dist/type/typebox-type.mjs +70 -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 +261 -94
- 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 +41 -7
- package/dist/utils.js +158 -126
- package/dist/utils.mjs +147 -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 +219 -139
- package/dist/ws/route.mjs +223 -143
- 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/plugin/aot/core.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { isStandardSchema, mergeSchemasAllStandard } from "../../compile/handler/frozen-validator.mjs";
|
|
1
|
+
import { REQUEST_SLOTS, isResponseMap, isStandardSchema, mergeSchemasAllStandard, resolveModelRef } from "../../compile/handler/frozen-validator.mjs";
|
|
2
2
|
import { composeRouteHook } from "../../compile/handler/index.mjs";
|
|
3
3
|
import { captureArtifacts, compileToSource, replayStubbability } from "./source.mjs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
|
-
import { existsSync, realpathSync } from "node:fs";
|
|
6
|
-
import { dirname, join, resolve } from "node:path";
|
|
7
|
-
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
6
|
+
import { dirname, extname, join, resolve } from "node:path";
|
|
7
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
8
8
|
import { Worker } from "node:worker_threads";
|
|
9
9
|
|
|
10
10
|
//#region src/plugin/aot/core.ts
|
|
@@ -18,8 +18,31 @@ function findPackageRoot(from = process.cwd()) {
|
|
|
18
18
|
return dir;
|
|
19
19
|
}
|
|
20
20
|
const resolveEntry = (entry) => resolve(findPackageRoot(), entry);
|
|
21
|
+
/** @internal Resolve the package condition used to evaluate an AOT entry. */
|
|
22
|
+
const resolveEntryModuleKind = (entry) => {
|
|
23
|
+
const entryPath = resolveEntry(entry);
|
|
24
|
+
switch (extname(entryPath)) {
|
|
25
|
+
case ".cjs":
|
|
26
|
+
case ".cts": return "cjs";
|
|
27
|
+
case ".mjs":
|
|
28
|
+
case ".mts":
|
|
29
|
+
case ".ts":
|
|
30
|
+
case ".tsx": return "esm";
|
|
31
|
+
case ".js":
|
|
32
|
+
case ".jsx": {
|
|
33
|
+
const packagePath = join(findPackageRoot(dirname(entryPath)), "package.json");
|
|
34
|
+
if (!existsSync(packagePath)) return "cjs";
|
|
35
|
+
const pkg = JSON.parse(readFileSync(packagePath, "utf8"));
|
|
36
|
+
if (pkg.type === "module") return "esm";
|
|
37
|
+
if (pkg.type === void 0 || pkg.type === "commonjs") return "cjs";
|
|
38
|
+
throw new Error(`[elysia-aot] package.json has unsupported "type" ${JSON.stringify(pkg.type)} for JavaScript entry ${JSON.stringify(entryPath)}.`);
|
|
39
|
+
}
|
|
40
|
+
default: throw new Error(`[elysia-aot] entry ${JSON.stringify(entryPath)} has an ambiguous module condition. Use a .cjs/.cts CommonJS entry or a .mjs/.mts/.ts/.tsx ESM entry; .js/.jsx follows the nearest package.json "type".`);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
21
43
|
const NO_STUB = {
|
|
22
44
|
jit: false,
|
|
45
|
+
staticClone: false,
|
|
23
46
|
ws: false,
|
|
24
47
|
reconstruct: false,
|
|
25
48
|
cookie: false,
|
|
@@ -27,6 +50,8 @@ const NO_STUB = {
|
|
|
27
50
|
sucrose: false,
|
|
28
51
|
compat: false,
|
|
29
52
|
bridge: false,
|
|
53
|
+
typeboxValue: false,
|
|
54
|
+
exactMirror: false,
|
|
30
55
|
adapter: false,
|
|
31
56
|
isProduction: false
|
|
32
57
|
};
|
|
@@ -47,20 +72,23 @@ const NO_STUB = {
|
|
|
47
72
|
* is not active, so the bridge must stay wired the ordinary way. No compat
|
|
48
73
|
* stub, no reroute.
|
|
49
74
|
*/
|
|
50
|
-
function planFromReport(strip, report, hasWS, mayTrace, aliases, allBridgeFree, zeroCapture, adapterStub = false, productionStub = true) {
|
|
75
|
+
function planFromReport(strip, report, hasWS, mayTrace, aliases, allBridgeFree, zeroCapture, adapterStub = false, productionStub = true, wsCookie = false, exactMirror = false) {
|
|
51
76
|
const jit = report.jit;
|
|
52
77
|
if (strip === true && !jit) throw new Error(`[elysia-aot] strip: true requires every route to be covered by the AOT handler manifest, but handler JIT is still reachable (${report.reasons.join(", ") || "unknown"}). Use strip: 'auto' to skip stubbing when the app is not fully precompiled.`);
|
|
53
78
|
const mode = !jit ? "off" : allBridgeFree ? "sealed" : hasWS && zeroCapture ? "off" : "wired";
|
|
54
79
|
return {
|
|
55
80
|
plan: {
|
|
56
81
|
jit,
|
|
82
|
+
staticClone: jit && !aliases.has("scl"),
|
|
57
83
|
ws: !hasWS,
|
|
58
84
|
reconstruct: jit && !aliases.has("va") && !aliases.has("cc") && !aliases.has("tr"),
|
|
59
|
-
cookie: jit && !aliases.has("cc"),
|
|
85
|
+
cookie: jit && !aliases.has("cc") && !wsCookie,
|
|
60
86
|
trace: !aliases.has("tr") && (jit || !mayTrace),
|
|
61
87
|
sucrose: jit,
|
|
62
88
|
compat: mode !== "off",
|
|
63
89
|
bridge: mode === "wired",
|
|
90
|
+
typeboxValue: mode !== "sealed",
|
|
91
|
+
exactMirror: exactMirror && mode !== "sealed",
|
|
64
92
|
adapter: adapterStub,
|
|
65
93
|
isProduction: productionStub
|
|
66
94
|
},
|
|
@@ -71,71 +99,48 @@ function adapterConstantsSource(target) {
|
|
|
71
99
|
if (target === "bun") return "import { BunAdapter } from './bun/index'\nexport const defaultAdapter = BunAdapter\n";
|
|
72
100
|
return "import { WebStandardAdapter } from './web-standard/index'\nexport const defaultAdapter = WebStandardAdapter\n";
|
|
73
101
|
}
|
|
74
|
-
/** Filter matching elysia's own `adapter/constants` module (src + dist). */
|
|
75
102
|
const ADAPTER_CONSTANTS_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]adapter[\\/]constants\.(m?js|ts)$/;
|
|
76
103
|
const ADAPTER_BUN_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]adapter[\\/]bun[\\/]index\.(m?js|ts)$/;
|
|
77
104
|
const IS_PRODUCTION_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]universal[\\/]is-production\.(m?js|ts)$/;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
* monorepos, linked installs). Used by esbuild as a broad pre-filter
|
|
83
|
-
*
|
|
84
|
-
* The caller must further check that the path is under the resolved elysia package root
|
|
85
|
-
* to avoid matching user code in a directory that happens to be named "elysia"
|
|
86
|
-
*
|
|
87
|
-
* @internal
|
|
88
|
-
*/
|
|
105
|
+
const TYPEBOX_TYPE_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]typebox-type\.(m?js|ts)$/;
|
|
106
|
+
const TYPEBOX_SYSTEM_LITE_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]typebox-system-lite\.(m?js|ts)$/;
|
|
107
|
+
const TYPEBOX_REQUIRE_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]typebox-value-require\.(m?js|ts)$/;
|
|
108
|
+
const EXACT_MIRROR_REQUIRE_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]validator[\\/]exact-mirror-require\.(m?js|ts)$/;
|
|
89
109
|
const ELYSIA_MODULE_FILTER = /[\\/]elysia[\\/](dist|src)[\\/].+\.(m?js|ts)x?$/;
|
|
90
|
-
|
|
91
|
-
* Build a predicate that returns `true` only for modules that are under the
|
|
92
|
-
* resolved elysia package root (i.e. actually elysia's own files).
|
|
93
|
-
*
|
|
94
|
-
* Anchoring to the real package root prevents user projects rooted in a
|
|
95
|
-
* directory named `elysia` (like this repo itself) from having their code
|
|
96
|
-
* rewritten.
|
|
97
|
-
*
|
|
98
|
-
* Pass the result to both the esbuild `filter` (convert to RegExp via
|
|
99
|
-
* `makeElysiaModuleFilterRegex`) and the Vite transform (`isElysiaModule`).
|
|
100
|
-
*/
|
|
101
|
-
function resolveElysiaRoot(from = process.cwd()) {
|
|
110
|
+
function resolveElysiaRoot(from) {
|
|
102
111
|
try {
|
|
103
112
|
return dirname(createRequire(join(from, "package.json")).resolve("elysia/package.json"));
|
|
104
113
|
} catch {
|
|
105
114
|
return from;
|
|
106
115
|
}
|
|
107
116
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
117
|
+
function resolveExactMirror(from) {
|
|
118
|
+
try {
|
|
119
|
+
createRequire(join(resolveElysiaRoot(from), "package.json")).resolve("exact-mirror");
|
|
120
|
+
return true;
|
|
121
|
+
} catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
112
125
|
function makeIsElysiaModule(elysiaRoot) {
|
|
113
126
|
const root = elysiaRoot.replace(/\\/g, "/");
|
|
114
127
|
return (path) => {
|
|
115
128
|
return path.replace(/\\/g, "/").startsWith(root + "/") && ELYSIA_MODULE_FILTER.test(path);
|
|
116
129
|
};
|
|
117
130
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
* so the `onLoad` pre-filter is as tight as possible. esbuild uses this as an
|
|
121
|
-
* initial path filter before calling the callback, so we still double-check
|
|
122
|
-
* with `makeIsElysiaModule` inside the callback.
|
|
123
|
-
*/
|
|
124
|
-
function makeElysiaModuleFilterRegex(elysiaRoot) {
|
|
125
|
-
const escaped = elysiaRoot.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
126
|
-
return new RegExp("^" + escaped + "[\\\\/](dist|src)[\\\\/].+\\.(m?js|ts)x?$");
|
|
127
|
-
}
|
|
128
|
-
function rewriteIsProductionCalls(code) {
|
|
129
|
-
return code.replace(/(?<![.?])\bisProduction\(\)/g, "true");
|
|
130
|
-
}
|
|
131
|
-
const bunAdapterStubSource = "const e=(t)=>{throw new Error(`[elysia-aot] Bun adapter was stripped for target 'web-standard' .listen() is unavailable; use the exported fetch handler or rebuild with a different target.`)}\nexport const BunAdapter={name:'bun',runtime:'bun',isWebStandard:true,parse:{},response:{},listen:e}\nexport function collectStaticRoutes(){}\n";
|
|
131
|
+
const rewriteIsProductionCalls = (code) => code.replace(/(?<![.?])\bisProduction\(\)/g, "true");
|
|
132
|
+
const bunAdapterStubSource = "const e=(t)=>{throw new Error(`[elysia-aot] Bun adapter was stripped for target 'web-standard' .listen() is unavailable; use the exported fetch handler or rebuild with a different target.`)}\nexport const BunAdapter={parse:{},response:{},listen:e}\nexport function collectStaticRoutes(){}\n";
|
|
132
133
|
const STUB_SOURCES = {
|
|
134
|
+
staticClone: [{
|
|
135
|
+
filter: /[\\/]elysia[\\/](dist|src)[\\/]compile[\\/]handler[\\/]static-clone-resolver\.(m?js|ts)$/,
|
|
136
|
+
source: `export const staticCloneResolver = undefined\n`
|
|
137
|
+
}],
|
|
133
138
|
jit: [{
|
|
134
139
|
filter: /[\\/]elysia[\\/](dist|src)[\\/]compile[\\/]handler[\\/]jit\.(m?js|ts)$/,
|
|
135
140
|
source: "const e=()=>{throw new Error(\"[elysia-aot] handler compiler JIT was stripped (strip mode) but a route needed runtime compilation. Rebuild with strip:false.\")}\nexport function compileHandlerJit(){return e()}\nexport function createInlineHandler(){return e()}\nexport function setCaptureHeaderShorthand(){}\n"
|
|
136
141
|
}, {
|
|
137
142
|
filter: /[\\/]elysia[\\/](dist|src)[\\/]compile[\\/]handler[\\/]descriptor\.(m?js|ts)$/,
|
|
138
|
-
source: "const e=()=>{throw new Error(\"[elysia-aot] handler compiler JIT was stripped (strip mode) but a route needed runtime compilation. Rebuild with strip:false.\")}\nexport function describeRoute(){return e()}\nexport const routeDescriptors=new WeakMap()\
|
|
143
|
+
source: "const e=()=>{throw new Error(\"[elysia-aot] handler compiler JIT was stripped (strip mode) but a route needed runtime compilation. Rebuild with strip:false.\")}\nexport function describeRoute(){return e()}\nexport const routeDescriptors=new WeakMap()\n"
|
|
139
144
|
}],
|
|
140
145
|
ws: [{
|
|
141
146
|
filter: /[\\/]elysia[\\/](dist|src)[\\/]ws[\\/]route\.(m?js|ts)$/,
|
|
@@ -145,13 +150,20 @@ const STUB_SOURCES = {
|
|
|
145
150
|
filter: /[\\/]elysia[\\/](dist|src)[\\/]compile[\\/]handler[\\/]reconstruct\.(m?js|ts)$/,
|
|
146
151
|
source: "const e=()=>{throw new Error(\"[elysia-aot] handler reconstruction was stripped (strip mode) but a route needed it. Rebuild with strip:false.\")}\nexport class Reconstrct {\n static validator(){return e()}\n static cookie(){return e()}\n static trace(){return e()}\n}\n"
|
|
147
152
|
}],
|
|
148
|
-
cookie: [
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
cookie: [
|
|
154
|
+
{
|
|
155
|
+
filter: /[\\/]elysia[\\/](dist|src)[\\/]cookie[\\/]crypto\.(m?js|ts)$/,
|
|
156
|
+
source: `export function resolvePendingCookie(){throw new Error("[elysia-aot] cookie support was stripped (strip mode) but a signed cookie was read. Rebuild with strip:false.")}\n`
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
filter: /[\\/]elysia[\\/](dist|src)[\\/]cookie[\\/]utils\.(m?js|ts)$/,
|
|
160
|
+
source: "const e=()=>{throw new Error(\"[elysia-aot] cookie support was stripped (strip mode) but a route used cookies. Rebuild with strip:false.\")}\nexport const hasSyncHmac=false\nexport function parseCookieRaw(){return e()}\nexport function parseCookieRawSync(){return e()}\nexport function parseCookieRawSigned(){return e()}\nexport function parseCookieRawLazy(){return e()}\nexport function parseCookieRawDeferred(){return e()}\nexport function buildCookieJar(){return e()}\nexport function signCookieValues(){return e()}\n"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
filter: /[\\/]elysia[\\/](dist|src)[\\/]cookie[\\/]config\.(m?js|ts)$/,
|
|
164
|
+
source: "const e=()=>{throw new Error(\"[elysia-aot] cookie support was stripped (strip mode) but a route used cookies. Rebuild with strip:false.\")}\nexport function compileCookieConfig(){return e()}\n"
|
|
165
|
+
}
|
|
166
|
+
],
|
|
155
167
|
trace: [{
|
|
156
168
|
filter: /[\\/]elysia[\\/](dist|src)[\\/]trace\.(m?js|ts)$/,
|
|
157
169
|
source: "const e=()=>{throw new Error(\"[elysia-aot] trace support was stripped (strip mode) but a route used trace. Rebuild with strip:false.\")}\nexport function createTracer(){return e()}\nexport function unionTracePhases(){return new Set()}\n"
|
|
@@ -159,9 +171,6 @@ const STUB_SOURCES = {
|
|
|
159
171
|
sucrose: [{
|
|
160
172
|
filter: /[\\/]elysia[\\/](dist|src)[\\/]memory\.(m?js|ts)$/,
|
|
161
173
|
source: "import { clearContextCache } from './context'\nimport { Validator } from './validator'\nexport function flushMemory() {\n clearContextCache()\n Validator.clear()\n}\n"
|
|
162
|
-
}, {
|
|
163
|
-
filter: /[\\/]elysia[\\/](dist|src)[\\/]compile[\\/]analysis-cache\.(m?js|ts)$/,
|
|
164
|
-
source: "import { clearHandlerAnalysisCaches } from './handler/index'\nimport { clearFlattenChainMemo } from '../utils'\nexport function clearAuthoringAnalysisCaches(root) {\n clearHandlerAnalysisCaches(root)\n clearFlattenChainMemo(root)\n}\n"
|
|
165
174
|
}],
|
|
166
175
|
compat: [{
|
|
167
176
|
filter: /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]compat\.(m?js|ts)$/,
|
|
@@ -170,11 +179,23 @@ const STUB_SOURCES = {
|
|
|
170
179
|
bridge: [{
|
|
171
180
|
filter: /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]bridge\.(m?js|ts)$/,
|
|
172
181
|
source: `export * from './bridge-live'\n`
|
|
182
|
+
}],
|
|
183
|
+
typeboxValue: [{
|
|
184
|
+
filter: /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]typebox-value\.(m?js|ts)$/,
|
|
185
|
+
source: `export * from './typebox-value-live'\n`
|
|
186
|
+
}],
|
|
187
|
+
exactMirror: [{
|
|
188
|
+
filter: /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]validator[\\/]exact-mirror\.(m?js|ts)$/,
|
|
189
|
+
source: `export * from './exact-mirror-live'\n`
|
|
173
190
|
}]
|
|
174
191
|
};
|
|
175
192
|
const alignStubExtensions = (stubSource, targetPath) => {
|
|
176
193
|
const ext = targetPath.slice(targetPath.lastIndexOf("."));
|
|
177
194
|
if (ext !== ".mjs" && ext !== ".js" && ext !== ".cjs") return stubSource;
|
|
195
|
+
if (ext !== ".mjs") {
|
|
196
|
+
const reexport = /^export \* from '(\.[^']+)'\n$/.exec(stubSource);
|
|
197
|
+
if (reexport) return `let m;const t=()=>m??=require('${reexport[1]}${ext}'),d=(o,k)=>Reflect.getOwnPropertyDescriptor(o,k)\nmodule.exports=new Proxy({},{get:(_,k)=>t()[k],has:(_,k)=>k in t(),ownKeys:()=>Reflect.ownKeys(t()),getOwnPropertyDescriptor:(o,k)=>{let x=d(o,k);if(x)return x;x=d(t(),k);if(x)x.configurable=true;return x},preventExtensions:o=>{for(const k of Reflect.ownKeys(t()))Object.defineProperty(o,k,d(t(),k));return Reflect.preventExtensions(o)}})\n`;
|
|
198
|
+
}
|
|
178
199
|
return stubSource.replace(/(from ')(\.[^']+)(')/g, (_m, open, spec, close) => open + (spec === "./validator" ? spec + "/index" : spec) + ext + close);
|
|
179
200
|
};
|
|
180
201
|
const OVERRIDE_MAP = {
|
|
@@ -270,6 +291,10 @@ const OVERRIDE_MAP = {
|
|
|
270
291
|
leaf: "optional",
|
|
271
292
|
export: "Optional"
|
|
272
293
|
},
|
|
294
|
+
Problem: {
|
|
295
|
+
leaf: "problem",
|
|
296
|
+
export: "Problem"
|
|
297
|
+
},
|
|
273
298
|
String: {
|
|
274
299
|
leaf: "string",
|
|
275
300
|
export: "StringType"
|
|
@@ -288,17 +313,20 @@ const OVERRIDE_MAP = {
|
|
|
288
313
|
}
|
|
289
314
|
};
|
|
290
315
|
const requireFromHere = createRequire(import.meta.url);
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
316
|
+
const moduleMeta = import.meta;
|
|
317
|
+
const loadedModuleCondition = import.meta.url.endsWith(".js") ? "cjs" : "esm";
|
|
318
|
+
const resolveSpecifier = (specifier, moduleCondition) => {
|
|
319
|
+
if (moduleCondition === "cjs") return requireFromHere.resolve(specifier);
|
|
320
|
+
if (moduleMeta.resolve) {
|
|
321
|
+
const url = moduleMeta.resolve(specifier);
|
|
322
|
+
return url.startsWith("file://") ? fileURLToPath(url) : url;
|
|
296
323
|
}
|
|
324
|
+
if (moduleCondition === "esm") throw new Error("[elysia-aot] CommonJS-loaded build plugin cannot resolve the ESM package condition. Load the build plugin through import for an ESM entry.");
|
|
297
325
|
return requireFromHere.resolve(specifier);
|
|
298
326
|
};
|
|
299
|
-
async function generateVirtualType(
|
|
300
|
-
const typePath = resolveSpecifier(
|
|
301
|
-
const typeboxPath = resolveSpecifier("typebox/type");
|
|
327
|
+
async function generateVirtualType(moduleCondition) {
|
|
328
|
+
const typePath = resolveSpecifier("elysia/type", moduleCondition);
|
|
329
|
+
const typeboxPath = resolveSpecifier("typebox/type", moduleCondition);
|
|
302
330
|
const ext = typePath.slice(typePath.lastIndexOf("."));
|
|
303
331
|
const leafDir = join(dirname(typePath), "elysia");
|
|
304
332
|
const typebox = await import(pathToFileURL(typeboxPath).href);
|
|
@@ -314,13 +342,6 @@ async function generateVirtualType(typeSpecifier = "elysia/type") {
|
|
|
314
342
|
return source;
|
|
315
343
|
}
|
|
316
344
|
const _importedEntries = /* @__PURE__ */ new Set();
|
|
317
|
-
let activeGenerationWorkers = 0;
|
|
318
|
-
let lastGenerationWorkerExit;
|
|
319
|
-
/** @internal Test diagnostic for deterministic worker cleanup. */
|
|
320
|
-
const getAotWorkerDiagnostics = () => ({
|
|
321
|
-
activeWorkers: activeGenerationWorkers,
|
|
322
|
-
lastExit: lastGenerationWorkerExit
|
|
323
|
-
});
|
|
324
345
|
/**
|
|
325
346
|
* Extension mirroring the running module's own build output, so a sibling
|
|
326
347
|
* source file can be resolved from `import.meta.url` in `.mjs`/`.js`/`.ts`
|
|
@@ -334,16 +355,15 @@ const workerUrl = () => {
|
|
|
334
355
|
return new URL("./worker" + siblingModuleExt(moduleUrl), moduleUrl);
|
|
335
356
|
};
|
|
336
357
|
/** @internal Re-evaluate an entry in a disposable worker for watch rebuilds. */
|
|
337
|
-
async function generateCompiledArtifactsIsolated(file, options) {
|
|
358
|
+
async function generateCompiledArtifactsIsolated(file, options, moduleCondition = resolveEntryModuleKind(file)) {
|
|
338
359
|
const entry = resolveEntry(file);
|
|
339
360
|
console.warn("[elysia-aot] re-evaluating \"" + entry + "\" in an isolated worker for rebuild. Top-level side effects run only inside the worker.");
|
|
340
361
|
const worker = new Worker(workerUrl(), { workerData: {
|
|
341
362
|
file: entry,
|
|
342
|
-
options
|
|
363
|
+
options,
|
|
364
|
+
moduleCondition
|
|
343
365
|
} });
|
|
344
|
-
activeGenerationWorkers++;
|
|
345
366
|
const exit = new Promise((resolve) => worker.once("exit", resolve));
|
|
346
|
-
lastGenerationWorkerExit = exit;
|
|
347
367
|
try {
|
|
348
368
|
return await new Promise((resolve, reject) => {
|
|
349
369
|
let received = false;
|
|
@@ -365,19 +385,34 @@ async function generateCompiledArtifactsIsolated(file, options) {
|
|
|
365
385
|
await worker.terminate();
|
|
366
386
|
} finally {
|
|
367
387
|
await exit;
|
|
368
|
-
activeGenerationWorkers--;
|
|
369
388
|
}
|
|
370
389
|
}
|
|
371
390
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
const
|
|
377
|
-
if (
|
|
378
|
-
|
|
391
|
+
const validatorSlotKey = ({ method, path, slot }) => `${method}\0${path}\0${slot}`;
|
|
392
|
+
/** @internal Exact logical-slot gate used by AOT mode selection. */
|
|
393
|
+
function validatorSlotSetsMatch(expected, captured) {
|
|
394
|
+
const expectedKeys = new Set(expected.map(validatorSlotKey));
|
|
395
|
+
const capturedKeys = new Set(captured.map(validatorSlotKey));
|
|
396
|
+
if (expectedKeys.size !== capturedKeys.size) return false;
|
|
397
|
+
for (const key of expectedKeys) if (!capturedKeys.has(key)) return false;
|
|
398
|
+
return true;
|
|
379
399
|
}
|
|
380
|
-
|
|
400
|
+
/**
|
|
401
|
+
* The manifest is one flat `method -> path` table with no per-app namespace,
|
|
402
|
+
* bound to whichever app builds a router first, so a mounted sub-app (a second
|
|
403
|
+
* Elysia building on its own schedule) is not representable
|
|
404
|
+
*
|
|
405
|
+
* refuse at build time rather than ship a coin flip
|
|
406
|
+
*/
|
|
407
|
+
const assertNoMount = (app, entry) => {
|
|
408
|
+
const routes = app["~routes"];
|
|
409
|
+
const mounted = [];
|
|
410
|
+
for (const route of routes) if (route[2]?.["~mount"] && !mounted.includes(route[1])) mounted.push(route[1]);
|
|
411
|
+
if (!mounted.length) return;
|
|
412
|
+
throw new Error(`[elysia-aot] "${entry}" mounts a sub-app (${mounted.join(", ")}). AOT cannot compile a mounted sub-app. Compose with .use() instead of .mount(), or disable AOT plugin`);
|
|
413
|
+
};
|
|
414
|
+
async function generateCompiledArtifacts(file, options, moduleCondition = resolveEntryModuleKind(file)) {
|
|
415
|
+
if (moduleCondition !== loadedModuleCondition) throw new Error(`[elysia-aot] entry uses the ${moduleCondition === "cjs" ? "CommonJS \"require\"" : "ESM \"import\""} package condition, but the AOT build plugin was loaded through ${loadedModuleCondition === "cjs" ? "CommonJS \"require\"" : "ESM \"import\""}; entry: ${JSON.stringify(resolveEntry(file))}. Load the plugin through ${moduleCondition === "cjs" ? "require()" : "import"} so capture and generated registration share one Elysia module instance.`);
|
|
381
416
|
const previousAotBuild = process.env.ELYSIA_AOT_BUILD;
|
|
382
417
|
process.env.ELYSIA_AOT_BUILD = "1";
|
|
383
418
|
const previousAotVerbose = process.env.ELYSIA_AOT_VERBOSE;
|
|
@@ -386,14 +421,15 @@ async function generateCompiledArtifacts(file, options) {
|
|
|
386
421
|
try {
|
|
387
422
|
const entry = resolveEntry(file);
|
|
388
423
|
const entryReal = realPath(entry);
|
|
389
|
-
if (_importedEntries.has(entryReal)) return generateCompiledArtifactsIsolated(file, options);
|
|
424
|
+
if (_importedEntries.has(entryReal)) return generateCompiledArtifactsIsolated(file, options, moduleCondition);
|
|
390
425
|
_importedEntries.add(entryReal);
|
|
391
426
|
const mod = await import(entry);
|
|
392
427
|
const app = mod.app ?? mod.default;
|
|
393
428
|
if (!app || typeof app.compile !== "function") throw new Error(`[elysia-aot] "${entry}" must export an Elysia app`);
|
|
394
429
|
const typedApp = app;
|
|
430
|
+
assertNoMount(typedApp, entry);
|
|
395
431
|
const sourceOptions = {
|
|
396
|
-
|
|
432
|
+
moduleCondition,
|
|
397
433
|
registerFrom: options?.registerFrom,
|
|
398
434
|
reconstructFrom: options?.reconstructFrom,
|
|
399
435
|
lazy: options?.lazy,
|
|
@@ -402,10 +438,13 @@ async function generateCompiledArtifacts(file, options) {
|
|
|
402
438
|
const strip = options?.strip ?? "auto";
|
|
403
439
|
const adapterStub = options?.target === "bun" ? "bun" : options?.target === "node" || options?.target === "workerd" ? "web-standard" : false;
|
|
404
440
|
const productionStub = options?.production !== false;
|
|
441
|
+
const exactMirror = resolveExactMirror(entry);
|
|
405
442
|
if (strip === false) return {
|
|
406
443
|
source: await compileToSource(typedApp, sourceOptions),
|
|
407
444
|
stub: {
|
|
408
445
|
...NO_STUB,
|
|
446
|
+
typeboxValue: true,
|
|
447
|
+
exactMirror,
|
|
409
448
|
adapter: adapterStub,
|
|
410
449
|
isProduction: productionStub
|
|
411
450
|
},
|
|
@@ -415,32 +454,51 @@ async function generateCompiledArtifacts(file, options) {
|
|
|
415
454
|
const report = replayStubbability(typedApp, artifacts.handlers);
|
|
416
455
|
const aliases = /* @__PURE__ */ new Set();
|
|
417
456
|
for (const handler of artifacts.handlers) if (handler.alias) for (const name of handler.alias.split(",")) aliases.add(name);
|
|
418
|
-
const
|
|
419
|
-
const
|
|
457
|
+
const history = typedApp["~routes"];
|
|
458
|
+
const hasWS = !!typedApp["~hasWS"] || history.some((route) => route[0] === "WS");
|
|
420
459
|
const mayTrace = !!typedApp["~hasTrace"] || history.some((route) => (route?.[4])?.trace?.length || route?.[2]?.["~mount"]);
|
|
421
|
-
|
|
460
|
+
const expectedSlots = [];
|
|
461
|
+
const declaredTypeBoxSlots = /* @__PURE__ */ new Set();
|
|
422
462
|
let routesForbidSeal = false;
|
|
463
|
+
let wsCookie = false;
|
|
423
464
|
for (const route of history) {
|
|
465
|
+
const method = route[0];
|
|
466
|
+
const path = route[1];
|
|
467
|
+
const expectTypeBoxSlot = (slot) => {
|
|
468
|
+
const identity = {
|
|
469
|
+
method,
|
|
470
|
+
path,
|
|
471
|
+
slot
|
|
472
|
+
};
|
|
473
|
+
const key = validatorSlotKey(identity);
|
|
474
|
+
if (declaredTypeBoxSlots.has(key)) routesForbidSeal = true;
|
|
475
|
+
else {
|
|
476
|
+
declaredTypeBoxSlots.add(key);
|
|
477
|
+
expectedSlots.push(identity);
|
|
478
|
+
}
|
|
479
|
+
};
|
|
424
480
|
const [, , , instance, hook, appHook, inheritedChain, macroScope] = route;
|
|
425
481
|
const hooks = composeRouteHook(instance, hook, appHook, inheritedChain, typedApp, macroScope);
|
|
482
|
+
if (method === "WS" && (hook?.cookie !== void 0 || hooks?.cookie !== void 0)) wsCookie = true;
|
|
426
483
|
if (!hooks) continue;
|
|
427
484
|
let routeHasTypeBoxDirectSlot = false;
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
]) {
|
|
435
|
-
const value = hooks[slot];
|
|
436
|
-
if (value === void 0) continue;
|
|
437
|
-
if (isStandardSchema(value)) continue;
|
|
485
|
+
const classify = (schema, slot) => {
|
|
486
|
+
if (schema === void 0) {
|
|
487
|
+
routesForbidSeal = true;
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
if (isStandardSchema(schema)) return;
|
|
438
491
|
routeHasTypeBoxDirectSlot = true;
|
|
439
|
-
|
|
492
|
+
expectTypeBoxSlot(slot);
|
|
493
|
+
};
|
|
494
|
+
for (const slot of REQUEST_SLOTS) {
|
|
495
|
+
const value = hooks[slot];
|
|
496
|
+
if (value !== void 0) classify(resolveModelRef(value, typedApp), slot);
|
|
440
497
|
}
|
|
441
|
-
if (hooks.response !== void 0
|
|
442
|
-
|
|
443
|
-
|
|
498
|
+
if (hooks.response !== void 0) {
|
|
499
|
+
const response = resolveModelRef(hooks.response, typedApp);
|
|
500
|
+
if (isResponseMap(response)) for (const status in response) classify(resolveModelRef(response[status], typedApp), `response:${status}`);
|
|
501
|
+
else classify(response, "response:200");
|
|
444
502
|
}
|
|
445
503
|
const mergeSchemas = hooks.schemas;
|
|
446
504
|
if (Array.isArray(mergeSchemas) && mergeSchemas.length > 0) {
|
|
@@ -448,13 +506,13 @@ async function generateCompiledArtifacts(file, options) {
|
|
|
448
506
|
}
|
|
449
507
|
}
|
|
450
508
|
if (typedApp["~config"]?.normalize === "typebox") routesForbidSeal = true;
|
|
451
|
-
const
|
|
452
|
-
const { plan: stub, mode } = planFromReport(strip, report, hasWS, mayTrace, aliases, (artifacts.handlers.length > 0 || artifacts.validators.length > 0) && !routesForbidSeal &&
|
|
509
|
+
const validatorSlotsMatch = validatorSlotSetsMatch(expectedSlots, artifacts.validators);
|
|
510
|
+
const { plan: stub, mode } = planFromReport(strip, report, hasWS, mayTrace, aliases, (artifacts.handlers.length > 0 || artifacts.validators.length > 0) && !routesForbidSeal && validatorSlotsMatch && artifacts.validators.every((v) => v.bridgeFree === true), artifacts.handlers.length === 0 && artifacts.validators.length === 0, adapterStub, productionStub, wsCookie, exactMirror);
|
|
453
511
|
if (options?.target === "workerd") {
|
|
454
512
|
if (!report.jit) throw new Error(`[elysia-aot] target 'workerd' but handler JIT is still reachable (${report.reasons.join(", ") || "unknown"}). Every route must be captured into the AOT manifest.`);
|
|
455
|
-
if (
|
|
513
|
+
if (!validatorSlotsMatch) console.warn("[elysia-aot] target 'workerd': captured validator slots do not exactly match declared slots; unfrozen slots compile at runtime and will fail on workerd.");
|
|
456
514
|
}
|
|
457
|
-
const virtualType = mode === "off" ? void 0 : await generateVirtualType(
|
|
515
|
+
const virtualType = mode === "off" ? void 0 : await generateVirtualType(moduleCondition);
|
|
458
516
|
return {
|
|
459
517
|
source: artifacts.source,
|
|
460
518
|
stub,
|
|
@@ -478,4 +536,4 @@ const realPath = (path) => {
|
|
|
478
536
|
};
|
|
479
537
|
|
|
480
538
|
//#endregion
|
|
481
|
-
export { ADAPTER_BUN_FILTER, ADAPTER_CONSTANTS_FILTER, ELYSIA_MODULE_FILTER, IS_PRODUCTION_FILTER, NO_STUB, OVERRIDE_MAP, SOURCE_REGEX, STUB_SOURCES, adapterConstantsSource, alignStubExtensions, bunAdapterStubSource, generateCompiledArtifacts, generateCompiledArtifactsIsolated, generateVirtualType,
|
|
539
|
+
export { ADAPTER_BUN_FILTER, ADAPTER_CONSTANTS_FILTER, ELYSIA_MODULE_FILTER, EXACT_MIRROR_REQUIRE_FILTER, IS_PRODUCTION_FILTER, NO_STUB, OVERRIDE_MAP, SOURCE_REGEX, STUB_SOURCES, TYPEBOX_REQUIRE_FILTER, TYPEBOX_SYSTEM_LITE_FILTER, TYPEBOX_TYPE_FILTER, adapterConstantsSource, alignStubExtensions, bunAdapterStubSource, generateCompiledArtifacts, generateCompiledArtifactsIsolated, generateVirtualType, makeIsElysiaModule, planFromReport, realPath, resolveElysiaRoot, resolveEntry, resolveEntryModuleKind, resolveExactMirror, rewriteIsProductionCalls, siblingModuleExt, validatorSlotSetsMatch };
|
|
@@ -28,7 +28,11 @@ let node_fs_promises = require("node:fs/promises");
|
|
|
28
28
|
const aot = (entry, options) => ({
|
|
29
29
|
name: "elysia-aot",
|
|
30
30
|
async setup(build) {
|
|
31
|
-
const
|
|
31
|
+
const entryPath = require_plugin_aot_core.resolveEntry(entry);
|
|
32
|
+
const moduleCondition = require_plugin_aot_core.resolveEntryModuleKind(entryPath);
|
|
33
|
+
if (build.initialOptions?.conditions?.includes("types")) throw new Error("[elysia-aot] esbuild conditions includes 'types'; this selects declaration files as runtime inputs. Remove the conflicting condition.");
|
|
34
|
+
if (moduleCondition === "cjs" && build.initialOptions?.conditions?.includes("import")) throw new Error("[elysia-aot] esbuild conditions includes 'import' for a CommonJS entry; this would load two Elysia module instances. Remove the conflicting condition.");
|
|
35
|
+
const hooks = require_plugin_aot_hooks.createAotPluginHooks(entry, options, moduleCondition);
|
|
32
36
|
let initial = true;
|
|
33
37
|
build.onStart(async () => {
|
|
34
38
|
if (initial) {
|
|
@@ -37,10 +41,9 @@ const aot = (entry, options) => ({
|
|
|
37
41
|
}
|
|
38
42
|
await hooks.buildStart();
|
|
39
43
|
});
|
|
40
|
-
await require_plugin_aot_hooks.setupAotOnLoad(build, hooks,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
44
|
+
await require_plugin_aot_hooks.setupAotOnLoad(build, hooks, (path) => (0, node_fs_promises.readFile)(path, "utf8"), (0, node_path.dirname)(entryPath));
|
|
45
|
+
const allowedKinds = moduleCondition === "cjs" ? new Set(["require-call", "require-resolve"]) : new Set(["import-statement", "dynamic-import"]);
|
|
46
|
+
build.onResolve({ filter: /^elysia(?:\/.*)?$/ }, (args) => allowedKinds.has(args.kind) ? void 0 : { errors: [{ text: `[elysia-aot] ${args.path} uses esbuild edge kind ${JSON.stringify(args.kind)}, which conflicts with the ${JSON.stringify(moduleCondition)} entry module condition. Use one consistent import/require condition for Elysia.` }] });
|
|
44
47
|
}
|
|
45
48
|
});
|
|
46
49
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolveEntry } from "./core.mjs";
|
|
1
|
+
import { resolveEntry, resolveEntryModuleKind } from "./core.mjs";
|
|
2
2
|
import { createAotPluginHooks, setupAotOnLoad } from "./hooks.mjs";
|
|
3
3
|
import { dirname } from "node:path";
|
|
4
4
|
import { readFile } from "node:fs/promises";
|
|
@@ -26,7 +26,11 @@ import { readFile } from "node:fs/promises";
|
|
|
26
26
|
const aot = (entry, options) => ({
|
|
27
27
|
name: "elysia-aot",
|
|
28
28
|
async setup(build) {
|
|
29
|
-
const
|
|
29
|
+
const entryPath = resolveEntry(entry);
|
|
30
|
+
const moduleCondition = resolveEntryModuleKind(entryPath);
|
|
31
|
+
if (build.initialOptions?.conditions?.includes("types")) throw new Error("[elysia-aot] esbuild conditions includes 'types'; this selects declaration files as runtime inputs. Remove the conflicting condition.");
|
|
32
|
+
if (moduleCondition === "cjs" && build.initialOptions?.conditions?.includes("import")) throw new Error("[elysia-aot] esbuild conditions includes 'import' for a CommonJS entry; this would load two Elysia module instances. Remove the conflicting condition.");
|
|
33
|
+
const hooks = createAotPluginHooks(entry, options, moduleCondition);
|
|
30
34
|
let initial = true;
|
|
31
35
|
build.onStart(async () => {
|
|
32
36
|
if (initial) {
|
|
@@ -35,10 +39,9 @@ const aot = (entry, options) => ({
|
|
|
35
39
|
}
|
|
36
40
|
await hooks.buildStart();
|
|
37
41
|
});
|
|
38
|
-
await setupAotOnLoad(build, hooks,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
});
|
|
42
|
+
await setupAotOnLoad(build, hooks, (path) => readFile(path, "utf8"), dirname(entryPath));
|
|
43
|
+
const allowedKinds = moduleCondition === "cjs" ? new Set(["require-call", "require-resolve"]) : new Set(["import-statement", "dynamic-import"]);
|
|
44
|
+
build.onResolve({ filter: /^elysia(?:\/.*)?$/ }, (args) => allowedKinds.has(args.kind) ? void 0 : { errors: [{ text: `[elysia-aot] ${args.path} uses esbuild edge kind ${JSON.stringify(args.kind)}, which conflicts with the ${JSON.stringify(moduleCondition)} entry module condition. Use one consistent import/require condition for Elysia.` }] });
|
|
42
45
|
}
|
|
43
46
|
});
|
|
44
47
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AotModuleCondition } from "./source.js";
|
|
1
2
|
import { ElysiaAotOptions } from "./core.js";
|
|
2
3
|
|
|
3
4
|
//#region src/plugin/aot/hooks.d.ts
|
|
@@ -6,23 +7,11 @@ interface AotPluginHooks {
|
|
|
6
7
|
buildEnd(): void;
|
|
7
8
|
resolveId(id: string): string | undefined;
|
|
8
9
|
load(id: string): string | undefined;
|
|
9
|
-
transform(code: string, id: string): string | undefined
|
|
10
|
+
transform(code: string, id: string): string | undefined;
|
|
10
11
|
isTransformCandidate(id: string): boolean;
|
|
11
12
|
}
|
|
12
|
-
declare const createAotPluginHooks: (entry: string, options?: ElysiaAotOptions) => AotPluginHooks;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
readText: (path: string) => Promise<string>;
|
|
16
|
-
/**
|
|
17
|
-
* resolveDir for the manifest/virtual-type module loads.
|
|
18
|
-
* esbuild needs `dirname(entryPath)` so relative imports in the manifest
|
|
19
|
-
* resolve correctly; Bun does not use it (pass undefined for Bun).
|
|
20
|
-
*/
|
|
21
|
-
resolveDir?: string;
|
|
22
|
-
}
|
|
23
|
-
declare function setupAotOnLoad(build: any, hooks: AotPluginHooks, {
|
|
24
|
-
readText,
|
|
25
|
-
resolveDir
|
|
26
|
-
}: AotOnLoadAdapterOptions): Promise<void>;
|
|
13
|
+
declare const createAotPluginHooks: (entry: string, options?: ElysiaAotOptions, moduleCondition?: AotModuleCondition) => AotPluginHooks;
|
|
14
|
+
declare const createTypeboxWiringHooks: () => AotPluginHooks;
|
|
15
|
+
declare function setupAotOnLoad(build: any, hooks: AotPluginHooks, readText: (path: string) => Promise<string>, resolveDir?: string): Promise<void>;
|
|
27
16
|
//#endregion
|
|
28
|
-
export {
|
|
17
|
+
export { AotPluginHooks, createAotPluginHooks, createTypeboxWiringHooks, setupAotOnLoad };
|