elysia 2.0.0-exp.2 → 2.0.0-exp.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/_virtual/_rolldown/runtime.js +2 -0
- package/dist/adapter/bun/index.d.ts +2 -25
- package/dist/adapter/bun/index.js +18 -12
- package/dist/adapter/bun/index.mjs +19 -13
- package/dist/adapter/bun/router.js +1 -1
- package/dist/adapter/bun/router.mjs +1 -1
- package/dist/adapter/constants.d.ts +3 -26
- package/dist/adapter/index.d.ts +1 -26
- package/dist/adapter/index.js +1 -17
- package/dist/adapter/index.mjs +1 -17
- package/dist/adapter/types.d.ts +1 -0
- package/dist/adapter/utils.d.ts +3 -4
- package/dist/adapter/utils.js +83 -81
- package/dist/adapter/utils.mjs +82 -80
- package/dist/adapter/web-standard/handler.js +6 -3
- package/dist/adapter/web-standard/handler.mjs +6 -3
- package/dist/adapter/web-standard/index.d.ts +2 -26
- package/dist/adapter/web-standard/index.js +12 -1
- package/dist/adapter/web-standard/index.mjs +12 -1
- package/dist/base.d.ts +38 -68
- package/dist/base.js +133 -97
- package/dist/base.mjs +133 -97
- package/dist/compile/aot.d.ts +22 -1
- package/dist/compile/aot.js +22 -0
- package/dist/compile/aot.mjs +22 -0
- package/dist/compile/handler/index.d.ts +2 -2
- package/dist/compile/handler/index.js +85 -456
- package/dist/compile/handler/index.mjs +86 -457
- package/dist/compile/handler/jit.d.ts +35 -0
- package/dist/compile/handler/jit.js +445 -0
- package/dist/compile/handler/jit.mjs +443 -0
- package/dist/compile/handler/params.js +3 -2
- package/dist/compile/handler/params.mjs +4 -3
- package/dist/compile/handler/reconstruct.d.ts +13 -0
- package/dist/compile/handler/reconstruct.js +29 -0
- package/dist/compile/handler/reconstruct.mjs +28 -0
- package/dist/compile/handler/utils.d.ts +2 -1
- package/dist/compile/handler/utils.js +9 -3
- package/dist/compile/handler/utils.mjs +9 -4
- package/dist/compile/jit-probe.d.ts +19 -0
- package/dist/compile/jit-probe.js +38 -0
- package/dist/compile/jit-probe.mjs +36 -0
- package/dist/cookie/index.d.ts +4 -3
- package/dist/cookie/index.js +2 -1
- package/dist/cookie/index.mjs +2 -1
- package/dist/cookie/serialize.d.ts +6 -0
- package/dist/cookie/serialize.js +28 -0
- package/dist/cookie/serialize.mjs +27 -0
- package/dist/cookie/utils.d.ts +1 -2
- package/dist/cookie/utils.js +2 -23
- package/dist/cookie/utils.mjs +5 -25
- package/dist/handler/error.js +2 -2
- package/dist/handler/error.mjs +3 -3
- package/dist/handler/fetch.js +49 -42
- package/dist/handler/fetch.mjs +50 -43
- package/dist/index.d.ts +13 -8
- package/dist/index.js +11 -4
- package/dist/index.mjs +7 -6
- package/dist/parse-query.js +1 -1
- package/dist/parse-query.mjs +1 -1
- package/dist/plugin/bun.d.ts +10 -0
- package/dist/plugin/bun.js +18 -1
- package/dist/plugin/bun.mjs +19 -2
- package/dist/plugin/core.d.ts +61 -1
- package/dist/plugin/core.js +90 -10
- package/dist/plugin/core.mjs +90 -12
- package/dist/plugin/esbuild.d.ts +10 -0
- package/dist/plugin/esbuild.js +18 -1
- package/dist/plugin/esbuild.mjs +19 -2
- package/dist/plugin/source.d.ts +38 -1
- package/dist/plugin/source.js +104 -13
- package/dist/plugin/source.mjs +102 -14
- package/dist/plugin/vite.d.ts +7 -0
- package/dist/plugin/vite.js +22 -1
- package/dist/plugin/vite.mjs +23 -2
- package/dist/sucrose.js +23 -10
- package/dist/sucrose.mjs +23 -10
- package/dist/trace.d.ts +1 -1
- package/dist/trace.js +4 -6
- package/dist/trace.mjs +4 -6
- package/dist/type/bridge.d.ts +9 -8
- package/dist/type/coerce.d.ts +20 -2
- package/dist/type/coerce.js +110 -0
- package/dist/type/coerce.mjs +109 -2
- package/dist/type/compat.js +4 -3
- package/dist/type/compat.mjs +2 -1
- package/dist/type/constants.d.ts +1 -1
- package/dist/type/elysia/boolean-string.js +1 -1
- package/dist/type/elysia/boolean-string.mjs +1 -1
- package/dist/type/elysia/file-type.js +1 -1
- package/dist/type/elysia/file-type.mjs +1 -1
- package/dist/type/elysia/integer-string.js +1 -1
- package/dist/type/elysia/integer-string.mjs +1 -1
- package/dist/type/exports.js +29 -2059
- package/dist/type/exports.mjs +7 -295
- package/dist/type/index.d.ts +6 -2
- package/dist/type/index.js +4 -0
- package/dist/type/index.mjs +3 -1
- package/dist/type/types.d.ts +1 -1
- package/dist/type/utils.js +4 -4
- package/dist/type/utils.mjs +4 -4
- package/dist/type/validator/custom-error.d.ts +10 -0
- package/dist/type/validator/custom-error.js +113 -0
- package/dist/type/validator/custom-error.mjs +110 -0
- package/dist/type/validator/default-precompute.d.ts +22 -0
- package/dist/type/validator/default-precompute.js +476 -0
- package/dist/type/validator/default-precompute.mjs +465 -0
- package/dist/type/validator/frozen-check.d.ts +11 -0
- package/dist/type/validator/frozen-check.js +19 -0
- package/dist/type/validator/frozen-check.mjs +18 -0
- package/dist/type/{validator.d.ts → validator/index.d.ts} +7 -20
- package/dist/type/validator/index.js +572 -0
- package/dist/type/validator/index.mjs +567 -0
- package/dist/type/validator/string-codec-aot.d.ts +9 -0
- package/dist/type/validator/string-codec-aot.js +106 -0
- package/dist/type/validator/string-codec-aot.mjs +102 -0
- package/dist/type/validator/validator-cache.d.ts +21 -0
- package/dist/type/validator/validator-cache.js +163 -0
- package/dist/type/validator/validator-cache.mjs +161 -0
- package/dist/types.d.ts +22 -14
- package/dist/universal/file.d.ts +1 -1
- package/dist/universal/file.js +35 -29
- package/dist/universal/file.mjs +35 -29
- package/dist/utils.d.ts +12 -1
- package/dist/utils.js +89 -45
- package/dist/utils.mjs +88 -46
- package/dist/validator/index.d.ts +1 -1
- package/dist/validator/index.js +15 -2
- package/dist/validator/index.mjs +15 -2
- package/dist/validator/route.d.ts +0 -1
- package/dist/ws/route.js +47 -24
- package/dist/ws/route.mjs +48 -25
- package/package.json +10 -4
- package/dist/type/validator.js +0 -1033
- package/dist/type/validator.mjs +0 -1029
package/dist/plugin/core.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { compileToSource } from "./source.mjs";
|
|
1
|
+
import { captureArtifacts, compileToSource, replayStubbability } from "./source.mjs";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
|
|
@@ -18,19 +18,97 @@ function resolveLoader(entryPath) {
|
|
|
18
18
|
return ext === ".js" || ext === ".mjs" || ext === ".cjs" ? "js" : ext === ".jsx" ? "jsx" : ext === ".tsx" ? "tsx" : "ts";
|
|
19
19
|
}
|
|
20
20
|
const entryFilter = (entryPath) => new RegExp("^" + entryPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "$");
|
|
21
|
+
const NO_STUB = {
|
|
22
|
+
jit: false,
|
|
23
|
+
ws: false,
|
|
24
|
+
reconstruct: false,
|
|
25
|
+
cookie: false,
|
|
26
|
+
trace: false,
|
|
27
|
+
sucrose: false
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Resolve whether handler JIT is safe to stub for `entry`, honouring the
|
|
31
|
+
* `strip` option. `'auto'` stubs only when detection proves handler JIT unused;
|
|
32
|
+
* `true` throws when handler JIT is still reachable; `false` disables.
|
|
33
|
+
*/
|
|
34
|
+
function planFromReport(strip, report, hasWS, aliases) {
|
|
35
|
+
const jit = report.jit;
|
|
36
|
+
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.`);
|
|
37
|
+
return {
|
|
38
|
+
jit,
|
|
39
|
+
ws: !hasWS,
|
|
40
|
+
reconstruct: jit && !aliases.has("va") && !aliases.has("cc") && !aliases.has("tr"),
|
|
41
|
+
cookie: jit && !aliases.has("cc"),
|
|
42
|
+
trace: jit && !aliases.has("tr"),
|
|
43
|
+
sucrose: jit
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const STUB_SOURCES = {
|
|
47
|
+
jit: [{
|
|
48
|
+
filter: /[\\/]compile[\\/]handler[\\/]jit\.(m?js|ts)$/,
|
|
49
|
+
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 setCaptureHeaderShorthand(){}\n"
|
|
50
|
+
}],
|
|
51
|
+
ws: [{
|
|
52
|
+
filter: /[\\/]ws[\\/]route\.(m?js|ts)$/,
|
|
53
|
+
source: "const e=()=>{throw new Error(\"[elysia-aot] WebSocket route builder was stripped (strip mode) but a WS route was used. Rebuild with strip:false.\")}\nexport function buildWSRoute(){return e()}\nexport function buildGlobalWSHandler(){return e()}\n"
|
|
54
|
+
}],
|
|
55
|
+
reconstruct: [{
|
|
56
|
+
filter: /[\\/]compile[\\/]handler[\\/]reconstruct\.(m?js|ts)$/,
|
|
57
|
+
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"
|
|
58
|
+
}],
|
|
59
|
+
cookie: [{
|
|
60
|
+
filter: /[\\/]cookie[\\/]utils\.(m?js|ts)$/,
|
|
61
|
+
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 createCookieJar(){return e()}\nexport function parseCookie(){return e()}\nexport function parseCookieRaw(){return e()}\nexport function parseCookieRawSync(){return e()}\nexport function buildCookieJar(){return e()}\nexport function signCookieValues(){return e()}\nexport function signCookie(){return e()}\nexport function unsignCookie(){return e()}\n"
|
|
62
|
+
}, {
|
|
63
|
+
filter: /[\\/]cookie[\\/]config\.(m?js|ts)$/,
|
|
64
|
+
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()}\nexport function isCookieSigned(){return e()}\n"
|
|
65
|
+
}],
|
|
66
|
+
trace: [{
|
|
67
|
+
filter: /[\\/]elysia[\\/](dist|src)[\\/]trace\.(m?js|ts)$/,
|
|
68
|
+
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()}\n"
|
|
69
|
+
}],
|
|
70
|
+
sucrose: [{
|
|
71
|
+
filter: /[\\/]elysia[\\/](dist|src)[\\/]memory\.(m?js|ts)$/,
|
|
72
|
+
source: "import { clearContextCache } from './context'\nimport { isBun } from './universal/constants'\nimport { Validator } from './validator'\nexport function flushMemory() {\n clearContextCache()\n Validator.clear()\n if (isBun) Bun.gc()\n else if (typeof global?.gc === 'function') global.gc()\n}\n"
|
|
73
|
+
}]
|
|
74
|
+
};
|
|
21
75
|
async function generateCompiledModule(file, options) {
|
|
76
|
+
return (await generateCompiledArtifacts(file, options)).source;
|
|
77
|
+
}
|
|
78
|
+
async function generateCompiledArtifacts(file, options) {
|
|
79
|
+
const previousAotBuild = process.env.ELYSIA_AOT_BUILD;
|
|
22
80
|
process.env.ELYSIA_AOT_BUILD = "1";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
81
|
+
try {
|
|
82
|
+
const entry = resolveEntry(file);
|
|
83
|
+
const mod = await import(entry);
|
|
84
|
+
const app = mod.app ?? mod.default;
|
|
85
|
+
if (!app || typeof app.compile !== "function") throw new Error(`[elysia-aot] "${entry}" must export an Elysia app`);
|
|
86
|
+
const typedApp = app;
|
|
87
|
+
const sourceOptions = {
|
|
88
|
+
register: true,
|
|
89
|
+
registerFrom: options?.registerFrom,
|
|
90
|
+
lazy: options?.lazy,
|
|
91
|
+
target: options?.target
|
|
92
|
+
};
|
|
93
|
+
const strip = options?.strip ?? "auto";
|
|
94
|
+
if (strip === false) return {
|
|
95
|
+
source: await compileToSource(typedApp, sourceOptions),
|
|
96
|
+
stub: NO_STUB
|
|
97
|
+
};
|
|
98
|
+
const artifacts = await captureArtifacts(typedApp, sourceOptions);
|
|
99
|
+
const report = replayStubbability(typedApp, artifacts.handlers);
|
|
100
|
+
const aliases = /* @__PURE__ */ new Set();
|
|
101
|
+
for (const handler of artifacts.handlers) if (handler.alias) for (const name of handler.alias.split(",")) aliases.add(name);
|
|
102
|
+
const hasWS = !!typedApp["~hasWS"] || !!typedApp.history?.some((route) => route?.[0] === "WS");
|
|
103
|
+
return {
|
|
104
|
+
source: artifacts.source,
|
|
105
|
+
stub: planFromReport(strip, report, hasWS, aliases)
|
|
106
|
+
};
|
|
107
|
+
} finally {
|
|
108
|
+
if (previousAotBuild === void 0) delete process.env.ELYSIA_AOT_BUILD;
|
|
109
|
+
else process.env.ELYSIA_AOT_BUILD = previousAotBuild;
|
|
110
|
+
}
|
|
33
111
|
}
|
|
34
112
|
|
|
35
113
|
//#endregion
|
|
36
|
-
export { entryFilter, generateCompiledModule, resolveEntry, resolveLoader };
|
|
114
|
+
export { STUB_SOURCES, entryFilter, generateCompiledArtifacts, generateCompiledModule, resolveEntry, resolveLoader };
|
package/dist/plugin/esbuild.d.ts
CHANGED
|
@@ -16,7 +16,17 @@ import { ElysiaAotOptions } from "./core.js";
|
|
|
16
16
|
* outfile: 'dist/index.js',
|
|
17
17
|
* plugins: [elysiaAot('src/index.ts')]
|
|
18
18
|
* })
|
|
19
|
+
*
|
|
20
|
+
* process.exit(0)
|
|
19
21
|
* ```
|
|
22
|
+
*
|
|
23
|
+
* The plugin imports your entry to capture the compiled app, running its
|
|
24
|
+
* top-level code. `.listen()` is auto-skipped during build (gated on
|
|
25
|
+
* `ELYSIA_AOT_BUILD`), but any other import-time handle — a DB pool,
|
|
26
|
+
* `setInterval`, a queue consumer — keeps the process alive after the bundle
|
|
27
|
+
* is written. End the build script with `process.exit(0)` (the bundle is
|
|
28
|
+
* already on disk), or gate the side effect with
|
|
29
|
+
* `if (!process.env.ELYSIA_AOT_BUILD)`.
|
|
20
30
|
*/
|
|
21
31
|
declare const aot: (entry: string, options?: ElysiaAotOptions) => {
|
|
22
32
|
name: string;
|
package/dist/plugin/esbuild.js
CHANGED
|
@@ -30,12 +30,22 @@ const realPath = (path) => {
|
|
|
30
30
|
* outfile: 'dist/index.js',
|
|
31
31
|
* plugins: [elysiaAot('src/index.ts')]
|
|
32
32
|
* })
|
|
33
|
+
*
|
|
34
|
+
* process.exit(0)
|
|
33
35
|
* ```
|
|
36
|
+
*
|
|
37
|
+
* The plugin imports your entry to capture the compiled app, running its
|
|
38
|
+
* top-level code. `.listen()` is auto-skipped during build (gated on
|
|
39
|
+
* `ELYSIA_AOT_BUILD`), but any other import-time handle — a DB pool,
|
|
40
|
+
* `setInterval`, a queue consumer — keeps the process alive after the bundle
|
|
41
|
+
* is written. End the build script with `process.exit(0)` (the bundle is
|
|
42
|
+
* already on disk), or gate the side effect with
|
|
43
|
+
* `if (!process.env.ELYSIA_AOT_BUILD)`.
|
|
34
44
|
*/
|
|
35
45
|
const aot = (entry, options) => ({
|
|
36
46
|
name: "elysia-aot",
|
|
37
47
|
async setup(build) {
|
|
38
|
-
const source = await require_plugin_core.
|
|
48
|
+
const { source, stub } = await require_plugin_core.generateCompiledArtifacts(entry, options);
|
|
39
49
|
const entryPath = require_plugin_core.resolveEntry(entry);
|
|
40
50
|
const entryReal = realPath(entryPath);
|
|
41
51
|
const treeShake = options?.treeShake ?? true;
|
|
@@ -52,6 +62,13 @@ const aot = (entry, options) => ({
|
|
|
52
62
|
loader: "js",
|
|
53
63
|
resolveDir: (0, node_path.dirname)(entryPath)
|
|
54
64
|
}));
|
|
65
|
+
for (const key of Object.keys(require_plugin_core.STUB_SOURCES)) {
|
|
66
|
+
if (!stub[key]) continue;
|
|
67
|
+
for (const { filter, source: stubSource } of require_plugin_core.STUB_SOURCES[key]) build.onLoad({ filter }, () => ({
|
|
68
|
+
contents: stubSource,
|
|
69
|
+
loader: "js"
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
55
72
|
if (treeShake) build.onLoad({ filter: SOURCE }, async (args) => {
|
|
56
73
|
const isEntryFile = isEntry(args.path);
|
|
57
74
|
const inModules = args.path.includes("/node_modules/");
|
package/dist/plugin/esbuild.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { entryFilter,
|
|
1
|
+
import { STUB_SOURCES, entryFilter, generateCompiledArtifacts, resolveEntry, resolveLoader } from "./core.mjs";
|
|
2
2
|
import { rewriteTypeImport } from "./treeshake.mjs";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import { dirname } from "node:path";
|
|
@@ -28,12 +28,22 @@ const realPath = (path) => {
|
|
|
28
28
|
* outfile: 'dist/index.js',
|
|
29
29
|
* plugins: [elysiaAot('src/index.ts')]
|
|
30
30
|
* })
|
|
31
|
+
*
|
|
32
|
+
* process.exit(0)
|
|
31
33
|
* ```
|
|
34
|
+
*
|
|
35
|
+
* The plugin imports your entry to capture the compiled app, running its
|
|
36
|
+
* top-level code. `.listen()` is auto-skipped during build (gated on
|
|
37
|
+
* `ELYSIA_AOT_BUILD`), but any other import-time handle — a DB pool,
|
|
38
|
+
* `setInterval`, a queue consumer — keeps the process alive after the bundle
|
|
39
|
+
* is written. End the build script with `process.exit(0)` (the bundle is
|
|
40
|
+
* already on disk), or gate the side effect with
|
|
41
|
+
* `if (!process.env.ELYSIA_AOT_BUILD)`.
|
|
32
42
|
*/
|
|
33
43
|
const aot = (entry, options) => ({
|
|
34
44
|
name: "elysia-aot",
|
|
35
45
|
async setup(build) {
|
|
36
|
-
const source = await
|
|
46
|
+
const { source, stub } = await generateCompiledArtifacts(entry, options);
|
|
37
47
|
const entryPath = resolveEntry(entry);
|
|
38
48
|
const entryReal = realPath(entryPath);
|
|
39
49
|
const treeShake = options?.treeShake ?? true;
|
|
@@ -50,6 +60,13 @@ const aot = (entry, options) => ({
|
|
|
50
60
|
loader: "js",
|
|
51
61
|
resolveDir: dirname(entryPath)
|
|
52
62
|
}));
|
|
63
|
+
for (const key of Object.keys(STUB_SOURCES)) {
|
|
64
|
+
if (!stub[key]) continue;
|
|
65
|
+
for (const { filter, source: stubSource } of STUB_SOURCES[key]) build.onLoad({ filter }, () => ({
|
|
66
|
+
contents: stubSource,
|
|
67
|
+
loader: "js"
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
53
70
|
if (treeShake) build.onLoad({ filter: SOURCE }, async (args) => {
|
|
54
71
|
const isEntryFile = isEntry(args.path);
|
|
55
72
|
const inModules = args.path.includes("/node_modules/");
|
package/dist/plugin/source.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { CapturedHandler, CapturedValidator } from "../compile/aot.js";
|
|
1
2
|
import { AnyElysia } from "../base.js";
|
|
3
|
+
import { JITProbeReason } from "../compile/jit-probe.js";
|
|
2
4
|
|
|
3
5
|
//#region src/plugin/source.d.ts
|
|
4
6
|
type AotTarget = 'bun' | 'node' | 'workerd';
|
|
@@ -34,5 +36,40 @@ interface CompileToSourceOptions {
|
|
|
34
36
|
}
|
|
35
37
|
declare const autoGroupSize: (routes: number) => number;
|
|
36
38
|
declare function compileToSource(app: AnyElysia, options?: CompileToSourceOptions): Promise<string>;
|
|
39
|
+
interface CapturedArtifacts {
|
|
40
|
+
source: string;
|
|
41
|
+
validators: CapturedValidator[];
|
|
42
|
+
handlers: CapturedHandler[];
|
|
43
|
+
}
|
|
44
|
+
declare function captureArtifacts(app: AnyElysia, options?: CompileToSourceOptions): Promise<CapturedArtifacts>;
|
|
45
|
+
interface StubbabilityReport {
|
|
46
|
+
/** Handler JIT is provably unused → handler-only strip is safe. */
|
|
47
|
+
stubbable: boolean;
|
|
48
|
+
/** `sucrose` + the handler `new Function` codegen is unused. */
|
|
49
|
+
jit: boolean;
|
|
50
|
+
/** Why handler JIT cannot be stripped, if any. */
|
|
51
|
+
reasons: JITProbeReason[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Decide whether the frozen build can run with handler JIT replaced by a
|
|
55
|
+
* throwing stub
|
|
56
|
+
*
|
|
57
|
+
* Static prediction is unsound
|
|
58
|
+
*
|
|
59
|
+
* eg. an inline-eligible handler (`() => 'ok'`) is never captured into
|
|
60
|
+
* handler manifest and falls through to `sucrose` at runtime
|
|
61
|
+
*
|
|
62
|
+
* So instead of guessing, this captures the manifest, registers it in-process
|
|
63
|
+
* and replays every route through the real `compileHandler` with a tripwire armed
|
|
64
|
+
*
|
|
65
|
+
* Handler JIT is only reported stubbable when no handler-JIT entry point was reached
|
|
66
|
+
*/
|
|
67
|
+
declare function analyzeStubbability(app: AnyElysia, options?: CompileToSourceOptions): Promise<StubbabilityReport>;
|
|
68
|
+
/**
|
|
69
|
+
* Replay a frozen build from already-captured artifacts (no second capture) and
|
|
70
|
+
* report whether handler JIT was reached. Shared by `analyzeStubbability` and
|
|
71
|
+
* the single-capture build path.
|
|
72
|
+
*/
|
|
73
|
+
declare function replayStubbability(app: AnyElysia, handlers: CapturedHandler[]): StubbabilityReport;
|
|
37
74
|
//#endregion
|
|
38
|
-
export { AotTarget, CompileToSourceOptions, autoGroupSize, compileToSource };
|
|
75
|
+
export { AotTarget, CapturedArtifacts, CompileToSourceOptions, StubbabilityReport, analyzeStubbability, autoGroupSize, captureArtifacts, compileToSource, replayStubbability };
|
package/dist/plugin/source.js
CHANGED
|
@@ -2,22 +2,102 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
const require_utils = require('../utils.js');
|
|
3
3
|
const require_universal_env = require('../universal/env.js');
|
|
4
4
|
const require_compile_aot = require('../compile/aot.js');
|
|
5
|
+
const require_validator_index = require('../validator/index.js');
|
|
6
|
+
const require_compile_jit_probe = require('../compile/jit-probe.js');
|
|
7
|
+
const require_compile_handler_jit = require('../compile/handler/jit.js');
|
|
5
8
|
const require_compile_handler_index = require('../compile/handler/index.js');
|
|
6
9
|
|
|
7
10
|
//#region src/plugin/source.ts
|
|
8
11
|
const autoGroupSize = (routes) => routes < 64 ? 1 : routes < 256 ? 2 : routes < 2048 ? 4 : routes < 8192 ? 16 : 64;
|
|
9
12
|
async function compileToSource(app, options) {
|
|
13
|
+
return (await captureArtifacts(app, options)).source;
|
|
14
|
+
}
|
|
15
|
+
async function captureArtifacts(app, options) {
|
|
16
|
+
const previousAotBuild = require_universal_env.env.ELYSIA_AOT_BUILD;
|
|
10
17
|
require_universal_env.env.ELYSIA_AOT_BUILD = "1";
|
|
11
|
-
if (!require_compile_aot.Capture.isCapturing()) throw new Error("[elysia-aot]: ELYSIA_AOT_BUILD=1 must be set to enable AOT capture mode");
|
|
12
|
-
require_compile_aot.beginValidatorCapture();
|
|
13
|
-
const modules = app.modules;
|
|
14
|
-
if (modules) await modules;
|
|
15
|
-
if (options?.target !== void 0) require_compile_handler_index.setCaptureHeaderShorthand(options.target === "bun");
|
|
16
18
|
try {
|
|
19
|
+
if (!require_compile_aot.Capture.isCapturing()) throw new Error("[elysia-aot]: ELYSIA_AOT_BUILD=1 must be set to enable AOT capture mode");
|
|
20
|
+
require_compile_aot.beginValidatorCapture();
|
|
21
|
+
const modules = app.modules;
|
|
22
|
+
if (modules) await modules;
|
|
23
|
+
if (options?.target !== void 0) require_compile_handler_jit.setCaptureHeaderShorthand(options.target === "bun");
|
|
17
24
|
app.compile();
|
|
18
|
-
|
|
25
|
+
const captured = require_compile_aot.endValidatorCapture();
|
|
26
|
+
const handlers = require_compile_aot.endHandlerCapture();
|
|
27
|
+
return {
|
|
28
|
+
source: emitModule(captured, handlers, options),
|
|
29
|
+
validators: captured,
|
|
30
|
+
handlers
|
|
31
|
+
};
|
|
19
32
|
} finally {
|
|
20
|
-
|
|
33
|
+
require_compile_handler_jit.setCaptureHeaderShorthand(void 0);
|
|
34
|
+
if (previousAotBuild === void 0) delete require_universal_env.env.ELYSIA_AOT_BUILD;
|
|
35
|
+
else require_universal_env.env.ELYSIA_AOT_BUILD = previousAotBuild;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Decide whether the frozen build can run with handler JIT replaced by a
|
|
40
|
+
* throwing stub
|
|
41
|
+
*
|
|
42
|
+
* Static prediction is unsound
|
|
43
|
+
*
|
|
44
|
+
* eg. an inline-eligible handler (`() => 'ok'`) is never captured into
|
|
45
|
+
* handler manifest and falls through to `sucrose` at runtime
|
|
46
|
+
*
|
|
47
|
+
* So instead of guessing, this captures the manifest, registers it in-process
|
|
48
|
+
* and replays every route through the real `compileHandler` with a tripwire armed
|
|
49
|
+
*
|
|
50
|
+
* Handler JIT is only reported stubbable when no handler-JIT entry point was reached
|
|
51
|
+
*/
|
|
52
|
+
async function analyzeStubbability(app, options) {
|
|
53
|
+
const { handlers } = await captureArtifacts(app, options);
|
|
54
|
+
return replayStubbability(app, handlers);
|
|
55
|
+
}
|
|
56
|
+
const materialiseHandlersForReplay = (captured) => {
|
|
57
|
+
const manifest = {};
|
|
58
|
+
for (const h of captured) (manifest[h.method] ??= {})[h.path] = {
|
|
59
|
+
a: h.alias ? h.alias.split(",") : [],
|
|
60
|
+
f: new Function(`return ${require_compile_aot.Source.handlerFactory(h.alias, h.code)}`)()
|
|
61
|
+
};
|
|
62
|
+
return manifest;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Replay a frozen build from already-captured artifacts (no second capture) and
|
|
66
|
+
* report whether handler JIT was reached. Shared by `analyzeStubbability` and
|
|
67
|
+
* the single-capture build path.
|
|
68
|
+
*/
|
|
69
|
+
function replayStubbability(app, handlers) {
|
|
70
|
+
const previousCompiled = require_compile_aot.Compiled.snapshot();
|
|
71
|
+
const previousAotBuild = require_universal_env.env.ELYSIA_AOT_BUILD;
|
|
72
|
+
if (previousAotBuild !== void 0) delete require_universal_env.env.ELYSIA_AOT_BUILD;
|
|
73
|
+
try {
|
|
74
|
+
require_compile_aot.Compiled.clear();
|
|
75
|
+
require_compile_aot.Compiled.handlers = materialiseHandlersForReplay(handlers);
|
|
76
|
+
require_validator_index.Validator.clear();
|
|
77
|
+
const history = app.history ?? [];
|
|
78
|
+
require_compile_jit_probe.JITProbe.begin();
|
|
79
|
+
for (const route of history) try {
|
|
80
|
+
if (route[0] === "WS") {
|
|
81
|
+
require_compile_jit_probe.JITProbe.end();
|
|
82
|
+
return {
|
|
83
|
+
stubbable: false,
|
|
84
|
+
jit: false,
|
|
85
|
+
reasons: ["sucrose"]
|
|
86
|
+
};
|
|
87
|
+
} else require_compile_handler_index.compileHandler(route, app);
|
|
88
|
+
} catch {
|
|
89
|
+
require_compile_jit_probe.JITProbe.end();
|
|
90
|
+
return {
|
|
91
|
+
stubbable: false,
|
|
92
|
+
jit: false,
|
|
93
|
+
reasons: ["handler:new-function"]
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return require_compile_jit_probe.JITProbe.end();
|
|
97
|
+
} finally {
|
|
98
|
+
require_compile_aot.Compiled.restore(previousCompiled);
|
|
99
|
+
require_validator_index.Validator.clear();
|
|
100
|
+
if (previousAotBuild !== void 0) require_universal_env.env.ELYSIA_AOT_BUILD = previousAotBuild;
|
|
21
101
|
}
|
|
22
102
|
}
|
|
23
103
|
function emitModule(captured, handlers, options) {
|
|
@@ -81,7 +161,10 @@ function emitModule(captured, handlers, options) {
|
|
|
81
161
|
if (c.precomputeSafe) {
|
|
82
162
|
parts.push("ps: 1");
|
|
83
163
|
if (c.precomputedDefault !== void 0) parts.push(`pd: ${JSON.stringify(c.precomputedDefault)}`);
|
|
164
|
+
if (c.precomputeNull) parts.push("pn: 1");
|
|
84
165
|
if (c.precomputedObjectDefault !== void 0) parts.push(`pod: ${JSON.stringify(c.precomputedObjectDefault)}`);
|
|
166
|
+
if (c.defaultCloner) parts.push(`dc: ${c.defaultCloner}`);
|
|
167
|
+
if (c.objectDefaultMerger) parts.push(`pm: ${c.objectDefaultMerger}`);
|
|
85
168
|
}
|
|
86
169
|
if (c.customErrors?.length) {
|
|
87
170
|
const ce = c.customErrors.map((e) => `{ p: ${JSON.stringify(e.path)}, c: ${require_compile_aot.Source.checkFactory(e.identifier, require_compile_aot.Source.checkCode(e.checkDefs, e.checkValue))}${e.external ? ", e: 1" : ""} }`).join(", ");
|
|
@@ -99,6 +182,7 @@ function emitModule(captured, handlers, options) {
|
|
|
99
182
|
}).join(", ");
|
|
100
183
|
parts.push(`ic: [${ic}]`);
|
|
101
184
|
}
|
|
185
|
+
if (c.coercePlan) parts.push(`cp: ${JSON.stringify(c.coercePlan)}`);
|
|
102
186
|
return parts;
|
|
103
187
|
};
|
|
104
188
|
const treeToSource = (tree, slotRef, sink) => {
|
|
@@ -248,16 +332,23 @@ function emitModule(captured, handlers, options) {
|
|
|
248
332
|
handlerExport += "}\n";
|
|
249
333
|
if (options?.register) handlerExport += "Compiled.handlers = handlers\n";
|
|
250
334
|
let body = "// Generated by Elysia build plugin. Do not edit.\n";
|
|
251
|
-
if (options?.register)
|
|
252
|
-
import {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
335
|
+
if (options?.register) {
|
|
336
|
+
body += `import { Compiled } from ${JSON.stringify(options.registerFrom ?? "elysia")}\n`;
|
|
337
|
+
const generated = branchDecls + unionDecls + validatorDecls + handlerDecls;
|
|
338
|
+
const needs = (symbol) => new RegExp(`\\b${symbol}\\b`).test(generated);
|
|
339
|
+
if (needs("CheckContext")) body += "import { CheckContext } from 'typebox/schema'\n";
|
|
340
|
+
if (needs("Guard")) body += "import { Guard } from 'typebox/guard'\n";
|
|
341
|
+
if (needs("Format")) body += "import { Format } from 'typebox/format'\n";
|
|
342
|
+
if (needs("Hashing")) body += "import { Hashing } from 'typebox/system'\n";
|
|
343
|
+
}
|
|
256
344
|
body += "\n" + branchDecls + (branchDecls && "\n") + unionDecls + (unionDecls && "\n") + validatorDecls + handlerDecls + "\n" + validatorExport + "\n" + handlerExport;
|
|
257
345
|
if (!lazy) body += "\nexport default validators\n";
|
|
258
346
|
return body;
|
|
259
347
|
}
|
|
260
348
|
|
|
261
349
|
//#endregion
|
|
350
|
+
exports.analyzeStubbability = analyzeStubbability;
|
|
262
351
|
exports.autoGroupSize = autoGroupSize;
|
|
263
|
-
exports.
|
|
352
|
+
exports.captureArtifacts = captureArtifacts;
|
|
353
|
+
exports.compileToSource = compileToSource;
|
|
354
|
+
exports.replayStubbability = replayStubbability;
|
package/dist/plugin/source.mjs
CHANGED
|
@@ -1,22 +1,102 @@
|
|
|
1
1
|
import { nullObject } from "../utils.mjs";
|
|
2
2
|
import { env } from "../universal/env.mjs";
|
|
3
|
-
import { Capture, Source, beginValidatorCapture, endHandlerCapture, endValidatorCapture } from "../compile/aot.mjs";
|
|
4
|
-
import {
|
|
3
|
+
import { Capture, Compiled, Source, beginValidatorCapture, endHandlerCapture, endValidatorCapture } from "../compile/aot.mjs";
|
|
4
|
+
import { Validator } from "../validator/index.mjs";
|
|
5
|
+
import { JITProbe } from "../compile/jit-probe.mjs";
|
|
6
|
+
import { setCaptureHeaderShorthand } from "../compile/handler/jit.mjs";
|
|
7
|
+
import { compileHandler } from "../compile/handler/index.mjs";
|
|
5
8
|
|
|
6
9
|
//#region src/plugin/source.ts
|
|
7
10
|
const autoGroupSize = (routes) => routes < 64 ? 1 : routes < 256 ? 2 : routes < 2048 ? 4 : routes < 8192 ? 16 : 64;
|
|
8
11
|
async function compileToSource(app, options) {
|
|
12
|
+
return (await captureArtifacts(app, options)).source;
|
|
13
|
+
}
|
|
14
|
+
async function captureArtifacts(app, options) {
|
|
15
|
+
const previousAotBuild = env.ELYSIA_AOT_BUILD;
|
|
9
16
|
env.ELYSIA_AOT_BUILD = "1";
|
|
10
|
-
if (!Capture.isCapturing()) throw new Error("[elysia-aot]: ELYSIA_AOT_BUILD=1 must be set to enable AOT capture mode");
|
|
11
|
-
beginValidatorCapture();
|
|
12
|
-
const modules = app.modules;
|
|
13
|
-
if (modules) await modules;
|
|
14
|
-
if (options?.target !== void 0) setCaptureHeaderShorthand(options.target === "bun");
|
|
15
17
|
try {
|
|
18
|
+
if (!Capture.isCapturing()) throw new Error("[elysia-aot]: ELYSIA_AOT_BUILD=1 must be set to enable AOT capture mode");
|
|
19
|
+
beginValidatorCapture();
|
|
20
|
+
const modules = app.modules;
|
|
21
|
+
if (modules) await modules;
|
|
22
|
+
if (options?.target !== void 0) setCaptureHeaderShorthand(options.target === "bun");
|
|
16
23
|
app.compile();
|
|
17
|
-
|
|
24
|
+
const captured = endValidatorCapture();
|
|
25
|
+
const handlers = endHandlerCapture();
|
|
26
|
+
return {
|
|
27
|
+
source: emitModule(captured, handlers, options),
|
|
28
|
+
validators: captured,
|
|
29
|
+
handlers
|
|
30
|
+
};
|
|
18
31
|
} finally {
|
|
19
32
|
setCaptureHeaderShorthand(void 0);
|
|
33
|
+
if (previousAotBuild === void 0) delete env.ELYSIA_AOT_BUILD;
|
|
34
|
+
else env.ELYSIA_AOT_BUILD = previousAotBuild;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Decide whether the frozen build can run with handler JIT replaced by a
|
|
39
|
+
* throwing stub
|
|
40
|
+
*
|
|
41
|
+
* Static prediction is unsound
|
|
42
|
+
*
|
|
43
|
+
* eg. an inline-eligible handler (`() => 'ok'`) is never captured into
|
|
44
|
+
* handler manifest and falls through to `sucrose` at runtime
|
|
45
|
+
*
|
|
46
|
+
* So instead of guessing, this captures the manifest, registers it in-process
|
|
47
|
+
* and replays every route through the real `compileHandler` with a tripwire armed
|
|
48
|
+
*
|
|
49
|
+
* Handler JIT is only reported stubbable when no handler-JIT entry point was reached
|
|
50
|
+
*/
|
|
51
|
+
async function analyzeStubbability(app, options) {
|
|
52
|
+
const { handlers } = await captureArtifacts(app, options);
|
|
53
|
+
return replayStubbability(app, handlers);
|
|
54
|
+
}
|
|
55
|
+
const materialiseHandlersForReplay = (captured) => {
|
|
56
|
+
const manifest = {};
|
|
57
|
+
for (const h of captured) (manifest[h.method] ??= {})[h.path] = {
|
|
58
|
+
a: h.alias ? h.alias.split(",") : [],
|
|
59
|
+
f: new Function(`return ${Source.handlerFactory(h.alias, h.code)}`)()
|
|
60
|
+
};
|
|
61
|
+
return manifest;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Replay a frozen build from already-captured artifacts (no second capture) and
|
|
65
|
+
* report whether handler JIT was reached. Shared by `analyzeStubbability` and
|
|
66
|
+
* the single-capture build path.
|
|
67
|
+
*/
|
|
68
|
+
function replayStubbability(app, handlers) {
|
|
69
|
+
const previousCompiled = Compiled.snapshot();
|
|
70
|
+
const previousAotBuild = env.ELYSIA_AOT_BUILD;
|
|
71
|
+
if (previousAotBuild !== void 0) delete env.ELYSIA_AOT_BUILD;
|
|
72
|
+
try {
|
|
73
|
+
Compiled.clear();
|
|
74
|
+
Compiled.handlers = materialiseHandlersForReplay(handlers);
|
|
75
|
+
Validator.clear();
|
|
76
|
+
const history = app.history ?? [];
|
|
77
|
+
JITProbe.begin();
|
|
78
|
+
for (const route of history) try {
|
|
79
|
+
if (route[0] === "WS") {
|
|
80
|
+
JITProbe.end();
|
|
81
|
+
return {
|
|
82
|
+
stubbable: false,
|
|
83
|
+
jit: false,
|
|
84
|
+
reasons: ["sucrose"]
|
|
85
|
+
};
|
|
86
|
+
} else compileHandler(route, app);
|
|
87
|
+
} catch {
|
|
88
|
+
JITProbe.end();
|
|
89
|
+
return {
|
|
90
|
+
stubbable: false,
|
|
91
|
+
jit: false,
|
|
92
|
+
reasons: ["handler:new-function"]
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return JITProbe.end();
|
|
96
|
+
} finally {
|
|
97
|
+
Compiled.restore(previousCompiled);
|
|
98
|
+
Validator.clear();
|
|
99
|
+
if (previousAotBuild !== void 0) env.ELYSIA_AOT_BUILD = previousAotBuild;
|
|
20
100
|
}
|
|
21
101
|
}
|
|
22
102
|
function emitModule(captured, handlers, options) {
|
|
@@ -80,7 +160,10 @@ function emitModule(captured, handlers, options) {
|
|
|
80
160
|
if (c.precomputeSafe) {
|
|
81
161
|
parts.push("ps: 1");
|
|
82
162
|
if (c.precomputedDefault !== void 0) parts.push(`pd: ${JSON.stringify(c.precomputedDefault)}`);
|
|
163
|
+
if (c.precomputeNull) parts.push("pn: 1");
|
|
83
164
|
if (c.precomputedObjectDefault !== void 0) parts.push(`pod: ${JSON.stringify(c.precomputedObjectDefault)}`);
|
|
165
|
+
if (c.defaultCloner) parts.push(`dc: ${c.defaultCloner}`);
|
|
166
|
+
if (c.objectDefaultMerger) parts.push(`pm: ${c.objectDefaultMerger}`);
|
|
84
167
|
}
|
|
85
168
|
if (c.customErrors?.length) {
|
|
86
169
|
const ce = c.customErrors.map((e) => `{ p: ${JSON.stringify(e.path)}, c: ${Source.checkFactory(e.identifier, Source.checkCode(e.checkDefs, e.checkValue))}${e.external ? ", e: 1" : ""} }`).join(", ");
|
|
@@ -98,6 +181,7 @@ function emitModule(captured, handlers, options) {
|
|
|
98
181
|
}).join(", ");
|
|
99
182
|
parts.push(`ic: [${ic}]`);
|
|
100
183
|
}
|
|
184
|
+
if (c.coercePlan) parts.push(`cp: ${JSON.stringify(c.coercePlan)}`);
|
|
101
185
|
return parts;
|
|
102
186
|
};
|
|
103
187
|
const treeToSource = (tree, slotRef, sink) => {
|
|
@@ -247,15 +331,19 @@ function emitModule(captured, handlers, options) {
|
|
|
247
331
|
handlerExport += "}\n";
|
|
248
332
|
if (options?.register) handlerExport += "Compiled.handlers = handlers\n";
|
|
249
333
|
let body = "// Generated by Elysia build plugin. Do not edit.\n";
|
|
250
|
-
if (options?.register)
|
|
251
|
-
import {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
334
|
+
if (options?.register) {
|
|
335
|
+
body += `import { Compiled } from ${JSON.stringify(options.registerFrom ?? "elysia")}\n`;
|
|
336
|
+
const generated = branchDecls + unionDecls + validatorDecls + handlerDecls;
|
|
337
|
+
const needs = (symbol) => new RegExp(`\\b${symbol}\\b`).test(generated);
|
|
338
|
+
if (needs("CheckContext")) body += "import { CheckContext } from 'typebox/schema'\n";
|
|
339
|
+
if (needs("Guard")) body += "import { Guard } from 'typebox/guard'\n";
|
|
340
|
+
if (needs("Format")) body += "import { Format } from 'typebox/format'\n";
|
|
341
|
+
if (needs("Hashing")) body += "import { Hashing } from 'typebox/system'\n";
|
|
342
|
+
}
|
|
255
343
|
body += "\n" + branchDecls + (branchDecls && "\n") + unionDecls + (unionDecls && "\n") + validatorDecls + handlerDecls + "\n" + validatorExport + "\n" + handlerExport;
|
|
256
344
|
if (!lazy) body += "\nexport default validators\n";
|
|
257
345
|
return body;
|
|
258
346
|
}
|
|
259
347
|
|
|
260
348
|
//#endregion
|
|
261
|
-
export { autoGroupSize, compileToSource };
|
|
349
|
+
export { analyzeStubbability, autoGroupSize, captureArtifacts, compileToSource, replayStubbability };
|
package/dist/plugin/vite.d.ts
CHANGED
|
@@ -23,6 +23,13 @@ interface ElysiaAotVitePlugin {
|
|
|
23
23
|
* plugins: [aot('src/index.ts')]
|
|
24
24
|
* })
|
|
25
25
|
* ```
|
|
26
|
+
*
|
|
27
|
+
* The plugin imports your entry to capture the compiled app, running its
|
|
28
|
+
* top-level code. `.listen()` is auto-skipped during build (gated on
|
|
29
|
+
* `ELYSIA_AOT_BUILD`), but any other import-time handle — a DB pool,
|
|
30
|
+
* `setInterval`, a queue consumer — can keep the build process alive after
|
|
31
|
+
* the bundle is written. Gate the side effect with
|
|
32
|
+
* `if (!process.env.ELYSIA_AOT_BUILD)`.
|
|
26
33
|
*/
|
|
27
34
|
declare const aot: (entry: string, options?: ElysiaAotOptions) => ElysiaAotVitePlugin;
|
|
28
35
|
//#endregion
|
package/dist/plugin/vite.js
CHANGED
|
@@ -18,17 +18,34 @@ const VIRTUAL = "\0elysia/compiled";
|
|
|
18
18
|
* plugins: [aot('src/index.ts')]
|
|
19
19
|
* })
|
|
20
20
|
* ```
|
|
21
|
+
*
|
|
22
|
+
* The plugin imports your entry to capture the compiled app, running its
|
|
23
|
+
* top-level code. `.listen()` is auto-skipped during build (gated on
|
|
24
|
+
* `ELYSIA_AOT_BUILD`), but any other import-time handle — a DB pool,
|
|
25
|
+
* `setInterval`, a queue consumer — can keep the build process alive after
|
|
26
|
+
* the bundle is written. Gate the side effect with
|
|
27
|
+
* `if (!process.env.ELYSIA_AOT_BUILD)`.
|
|
21
28
|
*/
|
|
22
29
|
const aot = (entry, options) => {
|
|
23
30
|
const entryPath = require_plugin_core.resolveEntry(entry);
|
|
24
31
|
const treeShake = options?.treeShake ?? true;
|
|
25
32
|
let source = "";
|
|
33
|
+
let stub = {
|
|
34
|
+
jit: false,
|
|
35
|
+
ws: false,
|
|
36
|
+
reconstruct: false,
|
|
37
|
+
cookie: false,
|
|
38
|
+
trace: false,
|
|
39
|
+
sucrose: false
|
|
40
|
+
};
|
|
26
41
|
return {
|
|
27
42
|
name: "elysia-aot",
|
|
28
43
|
enforce: "pre",
|
|
29
44
|
apply: "build",
|
|
30
45
|
async buildStart() {
|
|
31
|
-
|
|
46
|
+
const generated = await require_plugin_core.generateCompiledArtifacts(entry, options);
|
|
47
|
+
source = generated.source;
|
|
48
|
+
stub = generated.stub;
|
|
32
49
|
},
|
|
33
50
|
resolveId(id) {
|
|
34
51
|
if (id === "elysia/compiled") return VIRTUAL;
|
|
@@ -37,6 +54,10 @@ const aot = (entry, options) => {
|
|
|
37
54
|
if (id === VIRTUAL) return source;
|
|
38
55
|
},
|
|
39
56
|
transform(code, id) {
|
|
57
|
+
for (const key of Object.keys(require_plugin_core.STUB_SOURCES)) {
|
|
58
|
+
if (!stub[key]) continue;
|
|
59
|
+
for (const { filter, source: stubSource } of require_plugin_core.STUB_SOURCES[key]) if (filter.test(id)) return stubSource;
|
|
60
|
+
}
|
|
40
61
|
let out = code;
|
|
41
62
|
if (treeShake && SOURCE.test(id) && !id.includes("node_modules")) out = require_plugin_treeshake.rewriteTypeImport(out);
|
|
42
63
|
if (id === entryPath) out = `import 'elysia/compiled'\n${out}`;
|