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.
Files changed (135) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +2 -0
  2. package/dist/adapter/bun/index.d.ts +2 -25
  3. package/dist/adapter/bun/index.js +18 -12
  4. package/dist/adapter/bun/index.mjs +19 -13
  5. package/dist/adapter/bun/router.js +1 -1
  6. package/dist/adapter/bun/router.mjs +1 -1
  7. package/dist/adapter/constants.d.ts +3 -26
  8. package/dist/adapter/index.d.ts +1 -26
  9. package/dist/adapter/index.js +1 -17
  10. package/dist/adapter/index.mjs +1 -17
  11. package/dist/adapter/types.d.ts +1 -0
  12. package/dist/adapter/utils.d.ts +3 -4
  13. package/dist/adapter/utils.js +83 -81
  14. package/dist/adapter/utils.mjs +82 -80
  15. package/dist/adapter/web-standard/handler.js +6 -3
  16. package/dist/adapter/web-standard/handler.mjs +6 -3
  17. package/dist/adapter/web-standard/index.d.ts +2 -26
  18. package/dist/adapter/web-standard/index.js +12 -1
  19. package/dist/adapter/web-standard/index.mjs +12 -1
  20. package/dist/base.d.ts +38 -68
  21. package/dist/base.js +133 -97
  22. package/dist/base.mjs +133 -97
  23. package/dist/compile/aot.d.ts +22 -1
  24. package/dist/compile/aot.js +22 -0
  25. package/dist/compile/aot.mjs +22 -0
  26. package/dist/compile/handler/index.d.ts +2 -2
  27. package/dist/compile/handler/index.js +85 -456
  28. package/dist/compile/handler/index.mjs +86 -457
  29. package/dist/compile/handler/jit.d.ts +35 -0
  30. package/dist/compile/handler/jit.js +445 -0
  31. package/dist/compile/handler/jit.mjs +443 -0
  32. package/dist/compile/handler/params.js +3 -2
  33. package/dist/compile/handler/params.mjs +4 -3
  34. package/dist/compile/handler/reconstruct.d.ts +13 -0
  35. package/dist/compile/handler/reconstruct.js +29 -0
  36. package/dist/compile/handler/reconstruct.mjs +28 -0
  37. package/dist/compile/handler/utils.d.ts +2 -1
  38. package/dist/compile/handler/utils.js +9 -3
  39. package/dist/compile/handler/utils.mjs +9 -4
  40. package/dist/compile/jit-probe.d.ts +19 -0
  41. package/dist/compile/jit-probe.js +38 -0
  42. package/dist/compile/jit-probe.mjs +36 -0
  43. package/dist/cookie/index.d.ts +4 -3
  44. package/dist/cookie/index.js +2 -1
  45. package/dist/cookie/index.mjs +2 -1
  46. package/dist/cookie/serialize.d.ts +6 -0
  47. package/dist/cookie/serialize.js +28 -0
  48. package/dist/cookie/serialize.mjs +27 -0
  49. package/dist/cookie/utils.d.ts +1 -2
  50. package/dist/cookie/utils.js +2 -23
  51. package/dist/cookie/utils.mjs +5 -25
  52. package/dist/handler/error.js +2 -2
  53. package/dist/handler/error.mjs +3 -3
  54. package/dist/handler/fetch.js +49 -42
  55. package/dist/handler/fetch.mjs +50 -43
  56. package/dist/index.d.ts +13 -8
  57. package/dist/index.js +11 -4
  58. package/dist/index.mjs +7 -6
  59. package/dist/parse-query.js +1 -1
  60. package/dist/parse-query.mjs +1 -1
  61. package/dist/plugin/bun.d.ts +10 -0
  62. package/dist/plugin/bun.js +18 -1
  63. package/dist/plugin/bun.mjs +19 -2
  64. package/dist/plugin/core.d.ts +61 -1
  65. package/dist/plugin/core.js +90 -10
  66. package/dist/plugin/core.mjs +90 -12
  67. package/dist/plugin/esbuild.d.ts +10 -0
  68. package/dist/plugin/esbuild.js +18 -1
  69. package/dist/plugin/esbuild.mjs +19 -2
  70. package/dist/plugin/source.d.ts +38 -1
  71. package/dist/plugin/source.js +104 -13
  72. package/dist/plugin/source.mjs +102 -14
  73. package/dist/plugin/vite.d.ts +7 -0
  74. package/dist/plugin/vite.js +22 -1
  75. package/dist/plugin/vite.mjs +23 -2
  76. package/dist/sucrose.js +23 -10
  77. package/dist/sucrose.mjs +23 -10
  78. package/dist/trace.d.ts +1 -1
  79. package/dist/trace.js +4 -6
  80. package/dist/trace.mjs +4 -6
  81. package/dist/type/bridge.d.ts +9 -8
  82. package/dist/type/coerce.d.ts +20 -2
  83. package/dist/type/coerce.js +110 -0
  84. package/dist/type/coerce.mjs +109 -2
  85. package/dist/type/compat.js +4 -3
  86. package/dist/type/compat.mjs +2 -1
  87. package/dist/type/constants.d.ts +1 -1
  88. package/dist/type/elysia/boolean-string.js +1 -1
  89. package/dist/type/elysia/boolean-string.mjs +1 -1
  90. package/dist/type/elysia/file-type.js +1 -1
  91. package/dist/type/elysia/file-type.mjs +1 -1
  92. package/dist/type/elysia/integer-string.js +1 -1
  93. package/dist/type/elysia/integer-string.mjs +1 -1
  94. package/dist/type/exports.js +29 -2059
  95. package/dist/type/exports.mjs +7 -295
  96. package/dist/type/index.d.ts +6 -2
  97. package/dist/type/index.js +4 -0
  98. package/dist/type/index.mjs +3 -1
  99. package/dist/type/types.d.ts +1 -1
  100. package/dist/type/utils.js +4 -4
  101. package/dist/type/utils.mjs +4 -4
  102. package/dist/type/validator/custom-error.d.ts +10 -0
  103. package/dist/type/validator/custom-error.js +113 -0
  104. package/dist/type/validator/custom-error.mjs +110 -0
  105. package/dist/type/validator/default-precompute.d.ts +22 -0
  106. package/dist/type/validator/default-precompute.js +476 -0
  107. package/dist/type/validator/default-precompute.mjs +465 -0
  108. package/dist/type/validator/frozen-check.d.ts +11 -0
  109. package/dist/type/validator/frozen-check.js +19 -0
  110. package/dist/type/validator/frozen-check.mjs +18 -0
  111. package/dist/type/{validator.d.ts → validator/index.d.ts} +7 -20
  112. package/dist/type/validator/index.js +572 -0
  113. package/dist/type/validator/index.mjs +567 -0
  114. package/dist/type/validator/string-codec-aot.d.ts +9 -0
  115. package/dist/type/validator/string-codec-aot.js +106 -0
  116. package/dist/type/validator/string-codec-aot.mjs +102 -0
  117. package/dist/type/validator/validator-cache.d.ts +21 -0
  118. package/dist/type/validator/validator-cache.js +163 -0
  119. package/dist/type/validator/validator-cache.mjs +161 -0
  120. package/dist/types.d.ts +22 -14
  121. package/dist/universal/file.d.ts +1 -1
  122. package/dist/universal/file.js +35 -29
  123. package/dist/universal/file.mjs +35 -29
  124. package/dist/utils.d.ts +12 -1
  125. package/dist/utils.js +89 -45
  126. package/dist/utils.mjs +88 -46
  127. package/dist/validator/index.d.ts +1 -1
  128. package/dist/validator/index.js +15 -2
  129. package/dist/validator/index.mjs +15 -2
  130. package/dist/validator/route.d.ts +0 -1
  131. package/dist/ws/route.js +47 -24
  132. package/dist/ws/route.mjs +48 -25
  133. package/package.json +10 -4
  134. package/dist/type/validator.js +0 -1033
  135. package/dist/type/validator.mjs +0 -1029
@@ -1,11 +1,11 @@
1
- import { flattenChain, getLoosePath, isNotEmpty, nullObject, requestId } from "../utils.mjs";
2
- import { NotFound } from "../error.mjs";
1
+ import { flattenChain, isNotEmpty, nullObject, requestId } from "../utils.mjs";
3
2
  import { handleSet } from "../adapter/utils.mjs";
3
+ import { NotFound } from "../error.mjs";
4
4
  import { createContext } from "../context.mjs";
5
- import { defaultAdapter } from "../adapter/constants.mjs";
6
5
  import { cachedResponse, getAsyncIndexes } from "./utils.mjs";
7
- import { createErrorHandler } from "./error.mjs";
8
6
  import { createTracer } from "../trace.mjs";
7
+ import { defaultAdapter } from "../adapter/constants.mjs";
8
+ import { createErrorHandler } from "./error.mjs";
9
9
  import { decodeComponent } from "deuri";
10
10
 
11
11
  //#region src/handler/fetch.ts
@@ -28,11 +28,17 @@ const decodeParams = (params) => {
28
28
  }
29
29
  return params;
30
30
  };
31
- const catchError = (context, handleError, afterResponse) => (error) => {
31
+ function finalizeError(context, handleError, afterResponse, error) {
32
32
  const resp = handleError(context, error);
33
- afterResponse?.(context);
33
+ if (!afterResponse) return resp;
34
+ if (resp instanceof Promise) return resp.then((r) => {
35
+ afterResponse(context);
36
+ return r;
37
+ });
38
+ afterResponse(context);
34
39
  return resp;
35
- };
40
+ }
41
+ const catchError = (context, handleError, afterResponse) => (error) => finalizeError(context, handleError, afterResponse, error);
36
42
  function findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS) {
37
43
  const path = context.path;
38
44
  if (hasWS) {
@@ -50,17 +56,23 @@ function findRoute(context, request, map, router, hasError, handleError, afterRe
50
56
  return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
51
57
  }
52
58
  }
53
- } else {
54
- const handler = map[request.method]?.[path] ?? map["*"]?.[path];
59
+ }
60
+ {
61
+ const methodMap = map[request.method];
62
+ let handler = methodMap?.[path];
63
+ if (!handler) if (!strictPath && path.length > 1 && path.charCodeAt(path.length - 1) === 47) {
64
+ const loose = path.slice(0, -1);
65
+ handler = methodMap?.[loose];
66
+ if (!handler) {
67
+ const anyMap = map["*"];
68
+ handler = anyMap?.[path] ?? anyMap?.[loose];
69
+ }
70
+ } else handler = map["*"]?.[path];
55
71
  if (handler) {
56
72
  const r = handler(context);
57
73
  return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
58
74
  }
59
- let found = router?.find(request.method, path) ?? router?.find("*", path);
60
- if (!found && !strictPath) {
61
- const loose = getLoosePath(path);
62
- if (loose !== path) found = router?.find(request.method, loose) ?? router?.find("*", loose);
63
- }
75
+ const found = router?.find(request.method, path) ?? router?.find("*", path);
64
76
  if (found) {
65
77
  context.params = decodeParams(found.params);
66
78
  const r = found.store(context);
@@ -138,25 +150,27 @@ function createFetchHandler(app) {
138
150
  const trace = new Array(traceLength);
139
151
  for (let i = 0; i < traceLength; i++) trace[i] = tracerFactories[i](context);
140
152
  context.trace = trace;
141
- const requestReports = trace.map((c) => c.request({
153
+ const requestReports = new Array(traceLength);
154
+ for (let i = 0; i < traceLength; i++) requestReports[i] = trace[i].request({
142
155
  id: context.rid,
143
156
  event: "request",
144
157
  name: "request",
145
158
  begin: performance.now(),
146
159
  total: onRequests.length
147
- }));
160
+ });
148
161
  try {
149
162
  for (let i = 0; i < onRequests.length; i++) {
150
- const endReports = requestReports.map((r) => r.resolveChild?.shift?.()?.({
163
+ const endReports = new Array(traceLength);
164
+ for (let j = 0; j < traceLength; j++) endReports[j] = requestReports[j].resolveChild?.shift?.()?.({
151
165
  id: context.rid,
152
166
  event: "request",
153
167
  name: onRequests[i].name || "anonymous",
154
168
  begin: performance.now()
155
- }));
169
+ });
156
170
  const result = asyncIndexes?.[i] ? await onRequests[i](context) : onRequests[i](context);
157
171
  for (let i = 0; i < traceLength; i++) endReports[i]?.();
158
172
  if (result !== void 0) {
159
- requestReports.forEach((r) => r.resolve());
173
+ for (let j = 0; j < traceLength; j++) requestReports[j].resolve();
160
174
  const response = mapResponse(result, context.set);
161
175
  afterResponse?.(context);
162
176
  return response;
@@ -166,9 +180,7 @@ function createFetchHandler(app) {
166
180
  return await findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS);
167
181
  } catch (error) {
168
182
  for (let i = 0; i < traceLength; i++) requestReports[i].resolve(error);
169
- const r = handleError(context, error);
170
- afterResponse?.(context);
171
- return r;
183
+ return finalizeError(context, handleError, afterResponse, error);
172
184
  }
173
185
  };
174
186
  }
@@ -190,9 +202,7 @@ function createFetchHandler(app) {
190
202
  }
191
203
  return findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS);
192
204
  } catch (error) {
193
- const r = handleError(context, error);
194
- afterResponse?.(context);
195
- return r;
205
+ return finalizeError(context, handleError, afterResponse, error);
196
206
  }
197
207
  };
198
208
  return (request) => {
@@ -210,7 +220,7 @@ function createFetchHandler(app) {
210
220
  }
211
221
  return findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS);
212
222
  } catch (error) {
213
- return handleError(context, error);
223
+ return finalizeError(context, handleError, afterResponse, error);
214
224
  }
215
225
  };
216
226
  }
@@ -234,38 +244,35 @@ function createFetchHandler(app) {
234
244
  return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
235
245
  }
236
246
  } catch (error) {
237
- const r = handleError(context, error);
238
- afterResponse?.(context);
239
- return r;
247
+ return finalizeError(context, handleError, afterResponse, error);
240
248
  }
241
249
  }
242
250
  }
243
- const handler = map[request.method]?.[path] ?? map["*"]?.[path];
251
+ const methodMap = map[request.method];
252
+ let handler = methodMap?.[path];
244
253
  try {
254
+ if (!handler) if (!strictPath && path.length > 1 && path.charCodeAt(path.length - 1) === 47) {
255
+ const loose = path.slice(0, -1);
256
+ handler = methodMap?.[loose];
257
+ if (!handler) {
258
+ const anyMap = map["*"];
259
+ handler = anyMap?.[path] ?? anyMap?.[loose];
260
+ }
261
+ } else handler = map["*"]?.[path];
245
262
  if (handler) {
246
263
  const r = handler(context);
247
264
  return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
248
265
  }
249
- let result = router?.find(request.method, path) ?? router?.find("*", path);
250
- if (!result && !strictPath) {
251
- const loose = getLoosePath(path);
252
- if (loose !== path) result = router?.find(request.method, loose) ?? router?.find("*", loose);
253
- }
266
+ const result = router?.find(request.method, path) ?? router?.find("*", path);
254
267
  if (result) {
255
268
  context.params = decodeParams(result.params);
256
269
  const r = result.store(context);
257
270
  return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
258
271
  }
259
272
  } catch (error) {
260
- const r = handleError(context, error);
261
- afterResponse?.(context);
262
- return r;
263
- }
264
- if (hasError) {
265
- const r = handleError(context, new NotFound());
266
- afterResponse?.(context);
267
- return r;
273
+ return finalizeError(context, handleError, afterResponse, error);
268
274
  }
275
+ if (hasError) return finalizeError(context, handleError, afterResponse, new NotFound());
269
276
  afterResponse?.(context, 404);
270
277
  return notFound(context);
271
278
  };
package/dist/index.d.ts CHANGED
@@ -1,16 +1,21 @@
1
- import { StatusMap } from "./constants.js";
2
- import { ElysiaError, ElysiaStatus, InternalServerError, InvalidCookieSignature, NotFound, ParseError, ValidationError, status, validationDetail } from "./error.js";
1
+ import { StatusMap, StatusMapBack } from "./constants.js";
2
+ import { ElysiaError, ElysiaStatus, InternalServerError, InvalidCookieSignature, NotFound, ParseError, SelectiveStatus, ValidationError, status, validationDetail } from "./error.js";
3
+ import { BaseCookie, CookieOptions } from "./cookie/types.js";
3
4
  import { Cookie } from "./cookie/cookie.js";
4
- import { serializeCookie } from "./cookie/utils.js";
5
5
  import { ElysiaFile, file } from "./universal/file.js";
6
- import { TraceEvent, TraceHandler, TraceListener, TraceProcess, TraceStream } from "./trace.js";
7
6
  import { env } from "./universal/env.js";
8
- import { SSEPayload } from "./types.js";
7
+ import { Server } from "./universal/server.js";
8
+ import { HTTPHeaders, InputSchema, Macro, MacroToContext, MacroToProperty, RouteSchema, SSEPayload, UnwrapRoute, UnwrapSchema } from "./types.js";
9
9
  import { AnySchema, BaseSchema, StandardJSONSchemaV1Like, StandardSchemaV1Like } from "./type/types.js";
10
+ import { TCookieField, TCookieObject } from "./type/elysia/cookie.js";
10
11
  import { FileTypeDetector, fileType, setFileTypeDetector } from "./type/elysia/file-type.js";
12
+ import { TFiles } from "./type/elysia/files.js";
13
+ import { setupTypebox } from "./type/compat.js";
14
+ import { Capture, Compiled } from "./compile/aot.js";
15
+ import { MultiValidator, StandardValidator, Validator } from "./validator/index.js";
16
+ import { TypeBoxValidator } from "./type/validator/index.js";
11
17
  import { TypeSystem, t } from "./type/index.js";
12
- import { form, redirect, sse } from "./utils.js";
18
+ import { form, prefix, redirect, sse } from "./utils.js";
13
19
  import { Context, ErrorContext, createBaseContext, createContext } from "./context.js";
14
20
  import { Elysia } from "./base.js";
15
- import { Compiled } from "./compile/aot.js";
16
- export { type AnySchema, type BaseSchema, Compiled, type Context, Cookie, Elysia, Elysia as default, ElysiaError, ElysiaFile, ElysiaStatus, type ErrorContext, type FileTypeDetector, InternalServerError, InvalidCookieSignature, NotFound, ParseError, type SSEPayload, type StandardJSONSchemaV1Like, type StandardSchemaV1Like, StatusMap, type TraceEvent, type TraceHandler, type TraceListener, type TraceProcess, type TraceStream, TypeSystem, ValidationError, createBaseContext, createContext, env, file, fileType, form, redirect, serializeCookie, setFileTypeDetector, sse, status, t, validationDetail };
21
+ export { type AnySchema, type BaseCookie, type BaseSchema, Compiled, type Context, type Cookie, type CookieOptions, Elysia, Elysia as default, ElysiaError, ElysiaFile, ElysiaStatus, type ErrorContext, type FileTypeDetector, type HTTPHeaders, type InputSchema, InternalServerError, InvalidCookieSignature, type Macro, type MacroToContext, type MacroToProperty, Capture as Manifest, MultiValidator, NotFound, ParseError, type RouteSchema, type SSEPayload, type SelectiveStatus, type Server, type StandardJSONSchemaV1Like, type StandardSchemaV1Like, StandardValidator, StatusMap, StatusMapBack, type TCookieField, type TCookieObject, type TFiles, TypeBoxValidator, TypeSystem, type UnwrapRoute, type UnwrapSchema, ValidationError, Validator, createBaseContext, createContext, env, file, fileType, form, prefix, redirect, setFileTypeDetector, setupTypebox, sse, status, t, validationDetail };
package/dist/index.js CHANGED
@@ -3,14 +3,15 @@ const require_runtime = require('./_virtual/_rolldown/runtime.js');
3
3
  const require_constants = require('./constants.js');
4
4
  const require_universal_file = require('./universal/file.js');
5
5
  const require_utils = require('./utils.js');
6
- const require_cookie_cookie = require('./cookie/cookie.js');
7
6
  const require_universal_env = require('./universal/env.js');
8
7
  const require_error = require('./error.js');
9
- const require_cookie_utils = require('./cookie/utils.js');
10
8
  const require_context = require('./context.js');
11
9
  const require_compile_aot = require('./compile/aot.js');
10
+ const require_validator_index = require('./validator/index.js');
12
11
  const require_base = require('./base.js');
13
12
  const require_type_elysia_file_type = require('./type/elysia/file-type.js');
13
+ const require_type_validator_index = require('./type/validator/index.js');
14
+ const require_type_compat = require('./type/compat.js');
14
15
  const require_type_index = require('./type/index.js');
15
16
  let typebox_system = require("typebox/system");
16
17
 
@@ -19,16 +20,20 @@ var src_default = require_base.Elysia;
19
20
 
20
21
  //#endregion
21
22
  exports.Compiled = require_compile_aot.Compiled;
22
- exports.Cookie = require_cookie_cookie.Cookie;
23
23
  exports.Elysia = require_base.Elysia;
24
24
  exports.ElysiaError = require_error.ElysiaError;
25
25
  exports.ElysiaFile = require_universal_file.ElysiaFile;
26
26
  exports.ElysiaStatus = require_error.ElysiaStatus;
27
27
  exports.InternalServerError = require_error.InternalServerError;
28
28
  exports.InvalidCookieSignature = require_error.InvalidCookieSignature;
29
+ exports.Manifest = require_compile_aot.Capture;
30
+ exports.MultiValidator = require_validator_index.MultiValidator;
29
31
  exports.NotFound = require_error.NotFound;
30
32
  exports.ParseError = require_error.ParseError;
33
+ exports.StandardValidator = require_validator_index.StandardValidator;
31
34
  exports.StatusMap = require_constants.StatusMap;
35
+ exports.StatusMapBack = require_constants.StatusMapBack;
36
+ exports.TypeBoxValidator = require_type_validator_index.TypeBoxValidator;
32
37
  Object.defineProperty(exports, 'TypeSystem', {
33
38
  enumerable: true,
34
39
  get: function () {
@@ -36,6 +41,7 @@ Object.defineProperty(exports, 'TypeSystem', {
36
41
  }
37
42
  });
38
43
  exports.ValidationError = require_error.ValidationError;
44
+ exports.Validator = require_validator_index.Validator;
39
45
  exports.createBaseContext = require_context.createBaseContext;
40
46
  exports.createContext = require_context.createContext;
41
47
  exports.default = src_default;
@@ -43,9 +49,10 @@ exports.env = require_universal_env.env;
43
49
  exports.file = require_universal_file.file;
44
50
  exports.fileType = require_type_elysia_file_type.fileType;
45
51
  exports.form = require_utils.form;
52
+ exports.prefix = require_utils.prefix;
46
53
  exports.redirect = require_utils.redirect;
47
- exports.serializeCookie = require_cookie_utils.serializeCookie;
48
54
  exports.setFileTypeDetector = require_type_elysia_file_type.setFileTypeDetector;
55
+ exports.setupTypebox = require_type_compat.setupTypebox;
49
56
  exports.sse = require_utils.sse;
50
57
  exports.status = require_error.status;
51
58
  exports.t = require_type_index.t;
package/dist/index.mjs CHANGED
@@ -1,18 +1,19 @@
1
- import { StatusMap } from "./constants.mjs";
1
+ import { StatusMap, StatusMapBack } from "./constants.mjs";
2
2
  import { ElysiaFile, file } from "./universal/file.mjs";
3
- import { form, redirect, sse } from "./utils.mjs";
4
- import { Cookie } from "./cookie/cookie.mjs";
3
+ import { form, prefix, redirect, sse } from "./utils.mjs";
5
4
  import { env } from "./universal/env.mjs";
6
5
  import { ElysiaError, ElysiaStatus, InternalServerError, InvalidCookieSignature, NotFound, ParseError, ValidationError, status, validationDetail } from "./error.mjs";
7
- import { serializeCookie } from "./cookie/utils.mjs";
8
6
  import { createBaseContext, createContext } from "./context.mjs";
9
- import { Compiled } from "./compile/aot.mjs";
7
+ import { Capture, Compiled } from "./compile/aot.mjs";
8
+ import { MultiValidator, StandardValidator, Validator } from "./validator/index.mjs";
10
9
  import { Elysia } from "./base.mjs";
11
10
  import { fileType, setFileTypeDetector } from "./type/elysia/file-type.mjs";
11
+ import { TypeBoxValidator } from "./type/validator/index.mjs";
12
+ import { setupTypebox } from "./type/compat.mjs";
12
13
  import { TypeSystem, t } from "./type/index.mjs";
13
14
 
14
15
  //#region src/index.ts
15
16
  var src_default = Elysia;
16
17
 
17
18
  //#endregion
18
- export { Compiled, Cookie, Elysia, ElysiaError, ElysiaFile, ElysiaStatus, InternalServerError, InvalidCookieSignature, NotFound, ParseError, StatusMap, TypeSystem, ValidationError, createBaseContext, createContext, src_default as default, env, file, fileType, form, redirect, serializeCookie, setFileTypeDetector, sse, status, t, validationDetail };
19
+ export { Compiled, Elysia, ElysiaError, ElysiaFile, ElysiaStatus, InternalServerError, InvalidCookieSignature, Capture as Manifest, MultiValidator, NotFound, ParseError, StandardValidator, StatusMap, StatusMapBack, TypeBoxValidator, TypeSystem, ValidationError, Validator, createBaseContext, createContext, src_default as default, env, file, fileType, form, prefix, redirect, setFileTypeDetector, setupTypebox, sse, status, t, validationDetail };
@@ -60,7 +60,7 @@ function parseQueryFromURL(input, startIndex = input.indexOf("?", 11), array, ob
60
60
  }
61
61
  else finalValue = finalValue.slice(1, -1).split(",");
62
62
  if (currentValue === void 0) result[finalKey] = finalValue;
63
- else if (Array.isArray(currentValue)) currentValue.push(...finalValue);
63
+ else if (Array.isArray(currentValue)) for (let i = 0; i < finalValue.length; i++) currentValue.push(finalValue[i]);
64
64
  else {
65
65
  result[finalKey] = finalValue;
66
66
  result[finalKey].unshift(currentValue);
@@ -58,7 +58,7 @@ function parseQueryFromURL(input, startIndex = input.indexOf("?", 11), array, ob
58
58
  }
59
59
  else finalValue = finalValue.slice(1, -1).split(",");
60
60
  if (currentValue === void 0) result[finalKey] = finalValue;
61
- else if (Array.isArray(currentValue)) currentValue.push(...finalValue);
61
+ else if (Array.isArray(currentValue)) for (let i = 0; i < finalValue.length; i++) currentValue.push(finalValue[i]);
62
62
  else {
63
63
  result[finalKey] = finalValue;
64
64
  result[finalKey].unshift(currentValue);
@@ -17,7 +17,17 @@ import { BunPlugin } from "bun";
17
17
  * outdir: 'dist',
18
18
  * plugins: [aot('src/index.ts')]
19
19
  * })
20
+ *
21
+ * process.exit(0)
20
22
  * ```
23
+ *
24
+ * The plugin imports your entry to capture the compiled app, running its
25
+ * top-level code. `.listen()` is auto-skipped during build (gated on
26
+ * `ELYSIA_AOT_BUILD`), but any other import-time handle — a DB pool,
27
+ * `setInterval`, a queue consumer — keeps the process alive after the bundle
28
+ * is written. End the build script with `process.exit(0)` (the bundle is
29
+ * already on disk), or gate the side effect with
30
+ * `if (!process.env.ELYSIA_AOT_BUILD)`.
21
31
  */
22
32
  declare const aot: (entry: string, options?: ElysiaAotOptions) => BunPlugin;
23
33
  //#endregion
@@ -28,12 +28,22 @@ const realPath = (path) => {
28
28
  * outdir: 'dist',
29
29
  * plugins: [aot('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 require_plugin_core.generateCompiledModule(entry, options);
46
+ const { source, stub } = await require_plugin_core.generateCompiledArtifacts(entry, options);
37
47
  const entryPath = require_plugin_core.resolveEntry(entry);
38
48
  const entryReal = realPath(entryPath);
39
49
  const treeShake = options?.treeShake ?? true;
@@ -49,6 +59,13 @@ const aot = (entry, options) => ({
49
59
  contents: source,
50
60
  loader: "js"
51
61
  }));
62
+ for (const key of Object.keys(require_plugin_core.STUB_SOURCES)) {
63
+ if (!stub[key]) continue;
64
+ for (const { filter, source: stubSource } of require_plugin_core.STUB_SOURCES[key]) build.onLoad({ filter }, () => ({
65
+ contents: stubSource,
66
+ loader: "js"
67
+ }));
68
+ }
52
69
  if (treeShake) build.onLoad({ filter: SOURCE }, async (args) => {
53
70
  const isEntryFile = isEntry(args.path);
54
71
  const inModules = args.path.includes("/node_modules/");
@@ -1,4 +1,4 @@
1
- import { entryFilter, generateCompiledModule, resolveEntry, resolveLoader } from "./core.mjs";
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
 
@@ -26,12 +26,22 @@ const realPath = (path) => {
26
26
  * outdir: 'dist',
27
27
  * plugins: [aot('src/index.ts')]
28
28
  * })
29
+ *
30
+ * process.exit(0)
29
31
  * ```
32
+ *
33
+ * The plugin imports your entry to capture the compiled app, running its
34
+ * top-level code. `.listen()` is auto-skipped during build (gated on
35
+ * `ELYSIA_AOT_BUILD`), but any other import-time handle — a DB pool,
36
+ * `setInterval`, a queue consumer — keeps the process alive after the bundle
37
+ * is written. End the build script with `process.exit(0)` (the bundle is
38
+ * already on disk), or gate the side effect with
39
+ * `if (!process.env.ELYSIA_AOT_BUILD)`.
30
40
  */
31
41
  const aot = (entry, options) => ({
32
42
  name: "elysia-aot",
33
43
  async setup(build) {
34
- const source = await generateCompiledModule(entry, options);
44
+ const { source, stub } = await generateCompiledArtifacts(entry, options);
35
45
  const entryPath = resolveEntry(entry);
36
46
  const entryReal = realPath(entryPath);
37
47
  const treeShake = options?.treeShake ?? true;
@@ -47,6 +57,13 @@ const aot = (entry, options) => ({
47
57
  contents: source,
48
58
  loader: "js"
49
59
  }));
60
+ for (const key of Object.keys(STUB_SOURCES)) {
61
+ if (!stub[key]) continue;
62
+ for (const { filter, source: stubSource } of STUB_SOURCES[key]) build.onLoad({ filter }, () => ({
63
+ contents: stubSource,
64
+ loader: "js"
65
+ }));
66
+ }
50
67
  if (treeShake) build.onLoad({ filter: SOURCE }, async (args) => {
51
68
  const isEntryFile = isEntry(args.path);
52
69
  const inModules = args.path.includes("/node_modules/");
@@ -33,10 +33,70 @@ interface ElysiaAotOptions {
33
33
  * @default true
34
34
  */
35
35
  treeShake?: boolean;
36
+ /**
37
+ * Replace the internal handler compiler with a throwing stub so the bundler
38
+ * can drop the handler-JIT graph
39
+ *
40
+ * This is only safe when every route is reconstructed from the frozen AOT
41
+ * handler manifest. The plugin verifies that by replaying a frozen build and
42
+ * watching whether handler JIT is reached
43
+ *
44
+ * - `'auto'` (default): stub only when the frozen replay proves handler JIT
45
+ * is unused. Skip if any route still reaches handler JIT
46
+ * - `true`: require a fully precompiled handler manifest and throw if any
47
+ * route still reaches handler JIT
48
+ * - `false`: never stub
49
+ *
50
+ * @default 'auto'
51
+ */
52
+ strip?: boolean | 'auto';
36
53
  }
37
54
  declare const resolveEntry: (entry: string) => string;
38
55
  declare function resolveLoader(entryPath: string): "js" | "jsx" | "tsx" | "ts";
39
56
  declare const entryFilter: (entryPath: string) => RegExp;
57
+ /** Runtime handler-JIT module a strip build can replace with a throwing stub. */
58
+ interface StubPlan {
59
+ /** Stub the internal handler codegen module. */
60
+ jit: boolean;
61
+ /** Stub internal WS route builders when the app declares no WS routes. */
62
+ ws: boolean;
63
+ /**
64
+ * Stub frozen-handler reconstruction (validator `va`, cookie `cc`, trace `tr`)
65
+ * when no replayed handler aliases any of them.
66
+ */
67
+ reconstruct: boolean;
68
+ /**
69
+ * Stub the request-side cookie machinery (parse / jar / signing in
70
+ * `cookie/utils` + `cookie/config`) when no replayed handler aliases the
71
+ * cookie config (`cc`)
72
+ */
73
+ cookie: boolean;
74
+ /**
75
+ * Stub the trace runtime (`trace.ts` `createTracer` + recorder machinery)
76
+ * when no replayed handler aliases trace (`tr`). The live fetch handler keeps
77
+ * `createTracer` importable but only calls it when trace handlers exist, so a
78
+ * throwing stub is unreachable once detection proves trace is unused
79
+ */
80
+ trace: boolean;
81
+ /**
82
+ * Stub the `memory` module's `clearSucroseCache` edge when handler JIT is
83
+ * stubbed. Sucrose never runs in a precompiled app, so its caches are always
84
+ * empty and the flush is a no-op — dropping the import lets the Sucrose
85
+ * analyzer tree-shake. `flushMemory`'s other clears are preserved, and the
86
+ * public `elysia/sucrose` module is left untouched
87
+ */
88
+ sucrose: boolean;
89
+ }
90
+ declare const STUB_SOURCES: Record<keyof StubPlan, Array<{
91
+ filter: RegExp;
92
+ source: string;
93
+ }>>;
40
94
  declare function generateCompiledModule(file: string, options?: ElysiaAotOptions): Promise<string>;
95
+ interface CompiledArtifacts {
96
+ source: string;
97
+ /** Handler-JIT modules detection proved safe to stub for this app. */
98
+ stub: StubPlan;
99
+ }
100
+ declare function generateCompiledArtifacts(file: string, options?: ElysiaAotOptions): Promise<CompiledArtifacts>;
41
101
  //#endregion
42
- export { ElysiaAotOptions, entryFilter, generateCompiledModule, resolveEntry, resolveLoader };
102
+ export { CompiledArtifacts, ElysiaAotOptions, STUB_SOURCES, StubPlan, entryFilter, generateCompiledArtifacts, generateCompiledModule, resolveEntry, resolveLoader };
@@ -20,22 +20,102 @@ function resolveLoader(entryPath) {
20
20
  return ext === ".js" || ext === ".mjs" || ext === ".cjs" ? "js" : ext === ".jsx" ? "jsx" : ext === ".tsx" ? "tsx" : "ts";
21
21
  }
22
22
  const entryFilter = (entryPath) => new RegExp("^" + entryPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "$");
23
+ const NO_STUB = {
24
+ jit: false,
25
+ ws: false,
26
+ reconstruct: false,
27
+ cookie: false,
28
+ trace: false,
29
+ sucrose: false
30
+ };
31
+ /**
32
+ * Resolve whether handler JIT is safe to stub for `entry`, honouring the
33
+ * `strip` option. `'auto'` stubs only when detection proves handler JIT unused;
34
+ * `true` throws when handler JIT is still reachable; `false` disables.
35
+ */
36
+ function planFromReport(strip, report, hasWS, aliases) {
37
+ const jit = report.jit;
38
+ 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.`);
39
+ return {
40
+ jit,
41
+ ws: !hasWS,
42
+ reconstruct: jit && !aliases.has("va") && !aliases.has("cc") && !aliases.has("tr"),
43
+ cookie: jit && !aliases.has("cc"),
44
+ trace: jit && !aliases.has("tr"),
45
+ sucrose: jit
46
+ };
47
+ }
48
+ const STUB_SOURCES = {
49
+ jit: [{
50
+ filter: /[\\/]compile[\\/]handler[\\/]jit\.(m?js|ts)$/,
51
+ 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"
52
+ }],
53
+ ws: [{
54
+ filter: /[\\/]ws[\\/]route\.(m?js|ts)$/,
55
+ 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"
56
+ }],
57
+ reconstruct: [{
58
+ filter: /[\\/]compile[\\/]handler[\\/]reconstruct\.(m?js|ts)$/,
59
+ 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"
60
+ }],
61
+ cookie: [{
62
+ filter: /[\\/]cookie[\\/]utils\.(m?js|ts)$/,
63
+ 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"
64
+ }, {
65
+ filter: /[\\/]cookie[\\/]config\.(m?js|ts)$/,
66
+ 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"
67
+ }],
68
+ trace: [{
69
+ filter: /[\\/]elysia[\\/](dist|src)[\\/]trace\.(m?js|ts)$/,
70
+ 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"
71
+ }],
72
+ sucrose: [{
73
+ filter: /[\\/]elysia[\\/](dist|src)[\\/]memory\.(m?js|ts)$/,
74
+ 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"
75
+ }]
76
+ };
23
77
  async function generateCompiledModule(file, options) {
78
+ return (await generateCompiledArtifacts(file, options)).source;
79
+ }
80
+ async function generateCompiledArtifacts(file, options) {
81
+ const previousAotBuild = process.env.ELYSIA_AOT_BUILD;
24
82
  process.env.ELYSIA_AOT_BUILD = "1";
25
- const entry = resolveEntry(file);
26
- const mod = await import(entry);
27
- const app = mod.app ?? mod.default;
28
- if (!app || typeof app.compile !== "function") throw new Error(`[elysia-aot] "${entry}" must export an Elysia app`);
29
- return require_plugin_source.compileToSource(app, {
30
- register: true,
31
- registerFrom: options?.registerFrom,
32
- lazy: options?.lazy,
33
- target: options?.target
34
- });
83
+ try {
84
+ const entry = resolveEntry(file);
85
+ const mod = await import(entry);
86
+ const app = mod.app ?? mod.default;
87
+ if (!app || typeof app.compile !== "function") throw new Error(`[elysia-aot] "${entry}" must export an Elysia app`);
88
+ const typedApp = app;
89
+ const sourceOptions = {
90
+ register: true,
91
+ registerFrom: options?.registerFrom,
92
+ lazy: options?.lazy,
93
+ target: options?.target
94
+ };
95
+ const strip = options?.strip ?? "auto";
96
+ if (strip === false) return {
97
+ source: await require_plugin_source.compileToSource(typedApp, sourceOptions),
98
+ stub: NO_STUB
99
+ };
100
+ const artifacts = await require_plugin_source.captureArtifacts(typedApp, sourceOptions);
101
+ const report = require_plugin_source.replayStubbability(typedApp, artifacts.handlers);
102
+ const aliases = /* @__PURE__ */ new Set();
103
+ for (const handler of artifacts.handlers) if (handler.alias) for (const name of handler.alias.split(",")) aliases.add(name);
104
+ const hasWS = !!typedApp["~hasWS"] || !!typedApp.history?.some((route) => route?.[0] === "WS");
105
+ return {
106
+ source: artifacts.source,
107
+ stub: planFromReport(strip, report, hasWS, aliases)
108
+ };
109
+ } finally {
110
+ if (previousAotBuild === void 0) delete process.env.ELYSIA_AOT_BUILD;
111
+ else process.env.ELYSIA_AOT_BUILD = previousAotBuild;
112
+ }
35
113
  }
36
114
 
37
115
  //#endregion
116
+ exports.STUB_SOURCES = STUB_SOURCES;
38
117
  exports.entryFilter = entryFilter;
118
+ exports.generateCompiledArtifacts = generateCompiledArtifacts;
39
119
  exports.generateCompiledModule = generateCompiledModule;
40
120
  exports.resolveEntry = resolveEntry;
41
121
  exports.resolveLoader = resolveLoader;