elysia 2.0.0-exp.42 → 2.0.0-exp.44

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 (171) hide show
  1. package/dist/adapter/bun/index.d.ts +1 -1
  2. package/dist/adapter/bun/index.js +123 -74
  3. package/dist/adapter/bun/index.mjs +123 -74
  4. package/dist/adapter/default-headers.d.ts +4 -0
  5. package/dist/adapter/default-headers.js +7 -0
  6. package/dist/adapter/default-headers.mjs +5 -0
  7. package/dist/adapter/types.d.ts +4 -37
  8. package/dist/adapter/utils.d.ts +4 -2
  9. package/dist/adapter/utils.js +16 -0
  10. package/dist/adapter/utils.mjs +15 -1
  11. package/dist/adapter/web-standard/handler.js +35 -32
  12. package/dist/adapter/web-standard/handler.mjs +36 -33
  13. package/dist/adapter/web-standard/index.js +14 -10
  14. package/dist/adapter/web-standard/index.mjs +14 -10
  15. package/dist/base.d.ts +27 -8
  16. package/dist/base.js +274 -98
  17. package/dist/base.mjs +275 -99
  18. package/dist/compile/aot-capture.d.ts +2 -1
  19. package/dist/compile/aot-capture.js +22 -6
  20. package/dist/compile/aot-capture.mjs +22 -7
  21. package/dist/compile/aot.d.ts +54 -3
  22. package/dist/compile/aot.js +148 -19
  23. package/dist/compile/aot.mjs +141 -20
  24. package/dist/compile/handler/descriptor.d.ts +90 -0
  25. package/dist/compile/handler/descriptor.js +210 -0
  26. package/dist/compile/handler/descriptor.mjs +205 -0
  27. package/dist/compile/handler/frozen-validator.d.ts +4 -3
  28. package/dist/compile/handler/frozen-validator.js +106 -9
  29. package/dist/compile/handler/frozen-validator.mjs +106 -10
  30. package/dist/compile/handler/index.d.ts +4 -2
  31. package/dist/compile/handler/index.js +104 -53
  32. package/dist/compile/handler/index.mjs +104 -54
  33. package/dist/compile/handler/jit.d.ts +12 -5
  34. package/dist/compile/handler/jit.js +119 -176
  35. package/dist/compile/handler/jit.mjs +124 -182
  36. package/dist/compile/handler/params.d.ts +3 -0
  37. package/dist/compile/handler/params.js +5 -0
  38. package/dist/compile/handler/params.mjs +8 -3
  39. package/dist/compile/handler/reconstruct.js +7 -4
  40. package/dist/compile/handler/reconstruct.mjs +7 -4
  41. package/dist/compile/handler/utils.d.ts +1 -2
  42. package/dist/compile/handler/utils.js +1 -2
  43. package/dist/compile/handler/utils.mjs +2 -2
  44. package/dist/compile/lexer.d.ts +1 -1
  45. package/dist/compile/plan/emit.d.ts +21 -0
  46. package/dist/compile/plan/emit.js +457 -0
  47. package/dist/compile/plan/emit.mjs +456 -0
  48. package/dist/compile/plan/plan.d.ts +76 -0
  49. package/dist/compile/plan/plan.js +130 -0
  50. package/dist/compile/plan/plan.mjs +128 -0
  51. package/dist/context.d.ts +4 -4
  52. package/dist/context.js +41 -9
  53. package/dist/context.mjs +42 -10
  54. package/dist/cookie/config.d.ts +2 -0
  55. package/dist/cookie/config.js +2 -1
  56. package/dist/cookie/config.mjs +2 -1
  57. package/dist/cookie/cookie.js +7 -2
  58. package/dist/cookie/cookie.mjs +8 -2
  59. package/dist/cookie/crypto.d.ts +15 -0
  60. package/dist/cookie/crypto.js +125 -0
  61. package/dist/cookie/crypto.mjs +113 -0
  62. package/dist/cookie/index.d.ts +3 -2
  63. package/dist/cookie/index.js +3 -3
  64. package/dist/cookie/index.mjs +3 -2
  65. package/dist/cookie/utils.d.ts +5 -15
  66. package/dist/cookie/utils.js +61 -121
  67. package/dist/cookie/utils.mjs +44 -104
  68. package/dist/error.js +58 -6
  69. package/dist/error.mjs +58 -6
  70. package/dist/experimental/resume.d.ts +11 -0
  71. package/dist/experimental/resume.js +12 -0
  72. package/dist/experimental/resume.mjs +11 -0
  73. package/dist/generation.d.ts +23 -0
  74. package/dist/generation.js +13 -0
  75. package/dist/generation.mjs +10 -0
  76. package/dist/handler/error.js +4 -5
  77. package/dist/handler/error.mjs +6 -7
  78. package/dist/handler/fetch.js +63 -66
  79. package/dist/handler/fetch.mjs +63 -66
  80. package/dist/handler/utils.d.ts +8 -1
  81. package/dist/handler/utils.js +16 -1
  82. package/dist/handler/utils.mjs +13 -1
  83. package/dist/index.d.ts +11 -11
  84. package/dist/memory.js +1 -1
  85. package/dist/memory.mjs +1 -1
  86. package/dist/package.js +11 -0
  87. package/dist/package.mjs +5 -0
  88. package/dist/plugin/aot/core.d.ts +2 -1
  89. package/dist/plugin/aot/core.js +23 -8
  90. package/dist/plugin/aot/core.mjs +23 -9
  91. package/dist/plugin/aot/hooks.d.ts +14 -0
  92. package/dist/plugin/aot/hooks.js +75 -0
  93. package/dist/plugin/aot/hooks.mjs +74 -0
  94. package/dist/plugin/aot/rspack-loader.d.ts +23 -0
  95. package/dist/plugin/aot/rspack-loader.js +44 -0
  96. package/dist/plugin/aot/rspack-loader.mjs +40 -0
  97. package/dist/plugin/aot/rspack.d.ts +23 -0
  98. package/dist/plugin/aot/rspack.js +86 -0
  99. package/dist/plugin/aot/rspack.mjs +83 -0
  100. package/dist/plugin/aot/source.d.ts +3 -2
  101. package/dist/plugin/aot/source.js +10 -8
  102. package/dist/plugin/aot/source.mjs +11 -9
  103. package/dist/plugin/aot/unplugin.d.ts +54 -0
  104. package/dist/plugin/aot/unplugin.js +68 -0
  105. package/dist/plugin/aot/unplugin.mjs +66 -0
  106. package/dist/plugin/aot/vite.js +7 -68
  107. package/dist/plugin/aot/vite.mjs +7 -68
  108. package/dist/route-table.d.ts +26 -0
  109. package/dist/route-table.js +63 -0
  110. package/dist/route-table.mjs +60 -0
  111. package/dist/schema-snapshot.d.ts +5 -0
  112. package/dist/schema-snapshot.js +111 -0
  113. package/dist/schema-snapshot.mjs +108 -0
  114. package/dist/sucrose.d.ts +13 -1
  115. package/dist/sucrose.js +122 -55
  116. package/dist/sucrose.mjs +121 -56
  117. package/dist/type/bridge-live.d.ts +3 -3
  118. package/dist/type/bridge.d.ts +3 -3
  119. package/dist/type/coerce-plan.js +1 -1
  120. package/dist/type/coerce-plan.mjs +1 -1
  121. package/dist/type/constants.d.ts +1 -1
  122. package/dist/type/elysia/array-string.js +1 -1
  123. package/dist/type/elysia/array-string.mjs +1 -1
  124. package/dist/type/elysia/boolean-string.js +1 -1
  125. package/dist/type/elysia/boolean-string.mjs +1 -1
  126. package/dist/type/elysia/date.js +1 -1
  127. package/dist/type/elysia/date.mjs +1 -1
  128. package/dist/type/elysia/file-type.d.ts +1 -1
  129. package/dist/type/elysia/files.js +1 -1
  130. package/dist/type/elysia/files.mjs +1 -1
  131. package/dist/type/elysia/integer-string.js +1 -1
  132. package/dist/type/elysia/integer-string.mjs +1 -1
  133. package/dist/type/elysia/maybe-empty.js +1 -1
  134. package/dist/type/elysia/maybe-empty.mjs +1 -1
  135. package/dist/type/elysia/nullable.js +1 -1
  136. package/dist/type/elysia/nullable.mjs +1 -1
  137. package/dist/type/elysia/numeric-enum.js +1 -1
  138. package/dist/type/elysia/numeric-enum.mjs +1 -1
  139. package/dist/type/elysia/numeric.js +1 -1
  140. package/dist/type/elysia/numeric.mjs +1 -1
  141. package/dist/type/elysia/object-string.js +1 -1
  142. package/dist/type/elysia/object-string.mjs +1 -1
  143. package/dist/type/elysia/string.js +16 -3
  144. package/dist/type/elysia/string.mjs +16 -3
  145. package/dist/type/elysia/utils.d.ts +3 -1
  146. package/dist/type/elysia/utils.js +7 -2
  147. package/dist/type/elysia/utils.mjs +6 -2
  148. package/dist/type/exports.d.ts +1 -1
  149. package/dist/type/index.d.ts +1 -1
  150. package/dist/type/validator/clean-safe.d.ts +2 -1
  151. package/dist/type/validator/clean-safe.js +9 -1
  152. package/dist/type/validator/clean-safe.mjs +10 -2
  153. package/dist/type/validator/index.d.ts +1 -1
  154. package/dist/type/validator/index.js +239 -57
  155. package/dist/type/validator/index.mjs +240 -58
  156. package/dist/type/validator/string-codec-aot.d.ts +1 -1
  157. package/dist/type/validator/string-codec-aot.js +2 -0
  158. package/dist/type/validator/string-codec-aot.mjs +2 -0
  159. package/dist/types.d.ts +141 -6
  160. package/dist/utils.d.ts +2 -3
  161. package/dist/utils.js +0 -2
  162. package/dist/utils.mjs +1 -2
  163. package/dist/validator/index.d.ts +6 -3
  164. package/dist/validator/index.js +23 -12
  165. package/dist/validator/index.mjs +23 -12
  166. package/dist/validator/route.d.ts +1 -1
  167. package/dist/ws/context.d.ts +2 -2
  168. package/dist/ws/route.d.ts +1 -1
  169. package/dist/ws/route.js +80 -11
  170. package/dist/ws/route.mjs +80 -11
  171. package/package.json +30 -6
@@ -1,7 +1,7 @@
1
1
  import { AnyElysia } from "../../base.js";
2
2
  import { ElysiaAdapterOptions } from "../types.js";
3
3
  //#region src/adapter/bun/index.d.ts
4
- declare function collectStaticRoutes(app: AnyElysia): readonly [Record<string, Record<string, Response>>, Promise<void>[]] | undefined;
4
+ declare function collectStaticRoutes(app: AnyElysia): readonly [Record<string, Record<string, Response>>, readonly []] | undefined;
5
5
  declare const BunAdapter: ElysiaAdapterOptions;
6
6
  //#endregion
7
7
  export { BunAdapter, collectStaticRoutes };
@@ -3,34 +3,42 @@ const require_adapter_index = require('../index.js');
3
3
  const require_constants = require('../../constants.js');
4
4
  const require_utils = require('../../utils.js');
5
5
  const require_adapter_web_standard_index = require('../web-standard/index.js');
6
+ const require_generation = require('../../generation.js');
6
7
  const require_compile_handler_index = require('../../compile/handler/index.js');
7
- const require_memory = require('../../memory.js');
8
+ const require_route_table = require('../../route-table.js');
8
9
  const require_ws_route = require('../../ws/route.js');
9
10
 
10
11
  //#region src/adapter/bun/index.ts
12
+ const nativeStaticMethods = new Set([
13
+ "GET",
14
+ "POST",
15
+ "PUT",
16
+ "DELETE",
17
+ "PATCH",
18
+ "HEAD",
19
+ "OPTIONS"
20
+ ]);
11
21
  function collectStaticRoutes(app) {
12
22
  if (app["~config"]?.nativeStaticResponse === false) return;
13
23
  app.fetch;
14
- const fetchLevelHook = require_utils.flattenChain(app["~hookChain"]);
15
- if (fetchLevelHook?.request?.length || fetchLevelHook?.trace?.length || app["~ext"]?.hoc?.length) return;
16
- const history = app["~routes"];
17
- if (!history?.length) return;
24
+ const frozenRoot = require_generation.frozenRootOf(app);
25
+ const fetchLevelHook = require_utils.flattenChain(frozenRoot["~hookChain"]);
26
+ if (fetchLevelHook?.request?.length || fetchLevelHook?.trace?.length || frozenRoot["~ext"]?.hoc?.length) return;
27
+ const table = app["~generation"]?.routeTable ?? app["~routeTable"];
28
+ const length = table?.length ?? 0;
29
+ if (!table || !length) return;
30
+ const methods = table.method;
31
+ const paths = table.path;
18
32
  const ready = require_utils.nullObject();
19
- const pending = [];
20
- const strictPath = app["~config"]?.strictPath === true;
33
+ const strictPath = frozenRoot["~config"]?.strictPath === true;
21
34
  const seen = /* @__PURE__ */ new Map();
22
- for (let i = 0; i < history.length; i++) {
23
- const route = history[i];
24
- const method = route[0];
25
- seen.set(method + " " + route[1], i);
26
- }
35
+ for (let i = 0; i < length; i++) seen.set(methods[i] + " " + paths[i], i);
27
36
  let explicitPaths;
28
37
  if (!strictPath) {
29
38
  explicitPaths = /* @__PURE__ */ new Map();
30
- for (let i = 0; i < history.length; i++) {
31
- const route = history[i];
32
- const method = route[0];
33
- const path = route[1];
39
+ for (let i = 0; i < length; i++) {
40
+ const method = methods[i];
41
+ const path = paths[i];
34
42
  let set = explicitPaths.get(method);
35
43
  if (!set) explicitPaths.set(method, set = /* @__PURE__ */ new Set());
36
44
  set.add(path);
@@ -42,20 +50,15 @@ function collectStaticRoutes(app) {
42
50
  }
43
51
  const add = (method, path, value) => {
44
52
  if (require_constants.needEncodeRegex.test(path)) path = encodeURI(path);
45
- if (value instanceof Promise) pending.push(value.then((resolved) => {
46
- if (resolved instanceof Response) (ready[path] ??= require_utils.nullObject())[method] = resolved;
47
- }, (err) => {
48
- console.error(`[Elysia] Static route ${method} ${path} failed to resolve:`, err);
49
- }));
50
- else (ready[path] ??= require_utils.nullObject())[method] = value;
53
+ (ready[path] ??= require_utils.nullObject())[method] = value;
51
54
  };
52
- for (let i = 0; i < history.length; i++) {
53
- const route = history[i];
54
- if (route[0] === "WS") continue;
55
- const method = route[0];
56
- const path = route[1];
55
+ for (let i = 0; i < length; i++) {
56
+ const method = methods[i];
57
+ if (method === "WS") continue;
58
+ const path = paths[i];
57
59
  if (seen.get(method + " " + path) !== i) continue;
58
- const value = require_compile_handler_index.buildNativeStaticResponse(route, app);
60
+ if (!nativeStaticMethods.has(method)) continue;
61
+ const value = require_compile_handler_index.buildNativeStaticResponse(require_route_table.routeRow(table, i), app);
59
62
  if (!value) continue;
60
63
  add(method, path, value);
61
64
  if (!strictPath && !require_constants.isDynamicRegex.test(path)) {
@@ -63,8 +66,8 @@ function collectStaticRoutes(app) {
63
66
  if (loose !== path && !explicitPaths?.get(method)?.has(loose)) add(method, loose, value);
64
67
  }
65
68
  }
66
- if (!Object.keys(ready).length && !pending.length) return;
67
- return [ready, pending];
69
+ if (!Object.keys(ready).length) return;
70
+ return [ready, []];
68
71
  }
69
72
  const BunAdapter = require_adapter_index.createAdapter({
70
73
  name: "bun",
@@ -84,58 +87,104 @@ const BunAdapter = require_adapter_index.createAdapter({
84
87
  ..._config,
85
88
  ..._options
86
89
  } : _options;
87
- const server = app.server = Bun.serve(serve);
88
90
  const onSetup = app["~ext"]?.setup;
89
- let setupReady;
90
- if (onSetup) {
91
+ const needsGate = app.pending || !!onSetup?.length;
92
+ let ready;
93
+ const build = () => {
94
+ const fetch = app.fetch;
95
+ let routes;
96
+ try {
97
+ routes = collectStaticRoutes(app);
98
+ } catch (error) {
99
+ console.warn("[Elysia] Native static promotion was skipped:", error);
100
+ }
101
+ const hasWs = app["~hasWS"];
102
+ let websocket;
103
+ if (hasWs) {
104
+ const defaultConfig = require_generation.frozenRootOf(app)["~config"]?.websocket;
105
+ websocket = defaultConfig ? Object.assign(require_ws_route.buildGlobalWSHandler(), defaultConfig) : require_ws_route.buildGlobalWSHandler();
106
+ }
107
+ return {
108
+ fetch,
109
+ routes,
110
+ websocket
111
+ };
112
+ };
113
+ let built;
114
+ if (!needsGate) built = build();
115
+ if (needsGate) serve.fetch = (request, server) => ready.then(() => app.fetch(request, server));
116
+ else serve.fetch = built.fetch;
117
+ const server = app.server = Bun.serve(serve);
118
+ const reload = () => {
119
+ try {
120
+ server.reload(serve);
121
+ } catch (error) {
122
+ if (!serve.routes) throw error;
123
+ delete serve.routes;
124
+ console.warn("[Elysia] Native static promotion was skipped:", error);
125
+ try {
126
+ server.reload(serve);
127
+ } catch (fallbackError) {
128
+ console.error("[Elysia] Failed to reload Bun server:", fallbackError);
129
+ throw fallbackError;
130
+ }
131
+ }
132
+ };
133
+ const setup = () => {
134
+ const onSetup = app["~ext"]?.setup;
135
+ if (!onSetup) return;
91
136
  let pendingSetups;
92
137
  for (let i = 0; i < onSetup.length; i++) {
93
138
  const result = onSetup[i](app);
94
139
  if (result && typeof result.then === "function") (pendingSetups ??= []).push(result);
95
140
  }
96
- if (pendingSetups) setupReady = Promise.all(pendingSetups);
97
- }
98
- const hasWs = app["~hasWS"];
99
- if (!hasWs) {
100
- if (callback) if (setupReady) setupReady.then(() => callback(app.server));
101
- else callback(app.server);
102
- }
103
- queueMicrotask(() => {
141
+ if (pendingSetups) return Promise.all(pendingSetups);
142
+ };
143
+ const rollback = (error) => {
104
144
  if (app.server !== server) return;
105
- if (!app.pending) serve.fetch = app.fetch;
106
- const buildWebSocket = () => {
107
- const defaultConfig = app["~config"]?.websocket;
108
- serve.websocket = defaultConfig ? Object.assign(require_ws_route.buildGlobalWSHandler(), defaultConfig) : require_ws_route.buildGlobalWSHandler();
109
- };
110
- if (hasWs) buildWebSocket();
111
- const collectRoutes = () => {
112
- const staticRoutes = collectStaticRoutes(app);
113
- if (!staticRoutes) return;
114
- if (staticRoutes[1].length) return Promise.all(staticRoutes[1]).then(() => {
115
- if (app.server !== server) return;
116
- serve.routes = staticRoutes[0];
117
- app.server.reload(serve);
118
- });
119
- if (Object.keys(staticRoutes[0]).length) serve.routes = staticRoutes[0];
120
- };
121
- if (app.pending) {
122
- app.server.reload(serve);
123
- const reloadAfterModules = () => {
124
- if (app.server !== server) return;
125
- serve.fetch = app.fetch;
126
- if (hasWs || app["~hasWS"]) buildWebSocket();
127
- collectRoutes();
128
- app.server.reload(serve);
129
- };
130
- app.modules.then(reloadAfterModules, reloadAfterModules);
131
- } else {
132
- collectRoutes();
133
- app.server.reload(serve);
145
+ try {
146
+ server.stop(true);
147
+ } catch (stopError) {
148
+ console.error(stopError);
149
+ } finally {
150
+ app.server = void 0;
134
151
  }
135
- require_memory.flushMemory();
136
- if (hasWs && callback) if (setupReady) setupReady.then(() => callback(app.server));
137
- else callback(app.server);
138
- });
152
+ const cleanup = app["~ext"]?.cleanup;
153
+ if (cleanup) for (let i = cleanup.length - 1; i >= 0; i--) try {
154
+ const result = cleanup[i](app);
155
+ if (result && typeof result.then === "function") Promise.resolve(result).catch(console.error);
156
+ } catch (cleanupError) {
157
+ console.error(cleanupError);
158
+ }
159
+ return error;
160
+ };
161
+ const publish = () => {
162
+ if (app.server !== server) return;
163
+ built ??= build();
164
+ serve.fetch = built.fetch;
165
+ if (built.websocket) serve.websocket = built.websocket;
166
+ if (built.routes) serve.routes = built.routes[0];
167
+ if (needsGate || built.websocket || built.routes) reload();
168
+ if (callback) callback(server);
169
+ };
170
+ const start = () => {
171
+ if (app.server !== server) return;
172
+ const setupReady = setup();
173
+ if (setupReady && typeof setupReady.then === "function") return Promise.resolve(setupReady).then(publish);
174
+ publish();
175
+ };
176
+ try {
177
+ if (app.pending) ready = app.modules.then(start);
178
+ else {
179
+ const result = start();
180
+ if (result && typeof result.then === "function") ready = result;
181
+ else if (needsGate) ready = Promise.resolve();
182
+ }
183
+ ready?.catch(rollback);
184
+ } catch (error) {
185
+ rollback(error);
186
+ throw error;
187
+ }
139
188
  }
140
189
  });
141
190
 
@@ -2,34 +2,42 @@ import { createAdapter } from "../index.mjs";
2
2
  import { isDynamicRegex, needEncodeRegex } from "../../constants.mjs";
3
3
  import { flattenChain, getLoosePath, nullObject } from "../../utils.mjs";
4
4
  import { WebStandardAdapter } from "../web-standard/index.mjs";
5
+ import { frozenRootOf } from "../../generation.mjs";
5
6
  import { buildNativeStaticResponse } from "../../compile/handler/index.mjs";
6
- import { flushMemory } from "../../memory.mjs";
7
+ import { routeRow } from "../../route-table.mjs";
7
8
  import { buildGlobalWSHandler } from "../../ws/route.mjs";
8
9
 
9
10
  //#region src/adapter/bun/index.ts
11
+ const nativeStaticMethods = new Set([
12
+ "GET",
13
+ "POST",
14
+ "PUT",
15
+ "DELETE",
16
+ "PATCH",
17
+ "HEAD",
18
+ "OPTIONS"
19
+ ]);
10
20
  function collectStaticRoutes(app) {
11
21
  if (app["~config"]?.nativeStaticResponse === false) return;
12
22
  app.fetch;
13
- const fetchLevelHook = flattenChain(app["~hookChain"]);
14
- if (fetchLevelHook?.request?.length || fetchLevelHook?.trace?.length || app["~ext"]?.hoc?.length) return;
15
- const history = app["~routes"];
16
- if (!history?.length) return;
23
+ const frozenRoot = frozenRootOf(app);
24
+ const fetchLevelHook = flattenChain(frozenRoot["~hookChain"]);
25
+ if (fetchLevelHook?.request?.length || fetchLevelHook?.trace?.length || frozenRoot["~ext"]?.hoc?.length) return;
26
+ const table = app["~generation"]?.routeTable ?? app["~routeTable"];
27
+ const length = table?.length ?? 0;
28
+ if (!table || !length) return;
29
+ const methods = table.method;
30
+ const paths = table.path;
17
31
  const ready = nullObject();
18
- const pending = [];
19
- const strictPath = app["~config"]?.strictPath === true;
32
+ const strictPath = frozenRoot["~config"]?.strictPath === true;
20
33
  const seen = /* @__PURE__ */ new Map();
21
- for (let i = 0; i < history.length; i++) {
22
- const route = history[i];
23
- const method = route[0];
24
- seen.set(method + " " + route[1], i);
25
- }
34
+ for (let i = 0; i < length; i++) seen.set(methods[i] + " " + paths[i], i);
26
35
  let explicitPaths;
27
36
  if (!strictPath) {
28
37
  explicitPaths = /* @__PURE__ */ new Map();
29
- for (let i = 0; i < history.length; i++) {
30
- const route = history[i];
31
- const method = route[0];
32
- const path = route[1];
38
+ for (let i = 0; i < length; i++) {
39
+ const method = methods[i];
40
+ const path = paths[i];
33
41
  let set = explicitPaths.get(method);
34
42
  if (!set) explicitPaths.set(method, set = /* @__PURE__ */ new Set());
35
43
  set.add(path);
@@ -41,20 +49,15 @@ function collectStaticRoutes(app) {
41
49
  }
42
50
  const add = (method, path, value) => {
43
51
  if (needEncodeRegex.test(path)) path = encodeURI(path);
44
- if (value instanceof Promise) pending.push(value.then((resolved) => {
45
- if (resolved instanceof Response) (ready[path] ??= nullObject())[method] = resolved;
46
- }, (err) => {
47
- console.error(`[Elysia] Static route ${method} ${path} failed to resolve:`, err);
48
- }));
49
- else (ready[path] ??= nullObject())[method] = value;
52
+ (ready[path] ??= nullObject())[method] = value;
50
53
  };
51
- for (let i = 0; i < history.length; i++) {
52
- const route = history[i];
53
- if (route[0] === "WS") continue;
54
- const method = route[0];
55
- const path = route[1];
54
+ for (let i = 0; i < length; i++) {
55
+ const method = methods[i];
56
+ if (method === "WS") continue;
57
+ const path = paths[i];
56
58
  if (seen.get(method + " " + path) !== i) continue;
57
- const value = buildNativeStaticResponse(route, app);
59
+ if (!nativeStaticMethods.has(method)) continue;
60
+ const value = buildNativeStaticResponse(routeRow(table, i), app);
58
61
  if (!value) continue;
59
62
  add(method, path, value);
60
63
  if (!strictPath && !isDynamicRegex.test(path)) {
@@ -62,8 +65,8 @@ function collectStaticRoutes(app) {
62
65
  if (loose !== path && !explicitPaths?.get(method)?.has(loose)) add(method, loose, value);
63
66
  }
64
67
  }
65
- if (!Object.keys(ready).length && !pending.length) return;
66
- return [ready, pending];
68
+ if (!Object.keys(ready).length) return;
69
+ return [ready, []];
67
70
  }
68
71
  const BunAdapter = createAdapter({
69
72
  name: "bun",
@@ -83,58 +86,104 @@ const BunAdapter = createAdapter({
83
86
  ..._config,
84
87
  ..._options
85
88
  } : _options;
86
- const server = app.server = Bun.serve(serve);
87
89
  const onSetup = app["~ext"]?.setup;
88
- let setupReady;
89
- if (onSetup) {
90
+ const needsGate = app.pending || !!onSetup?.length;
91
+ let ready;
92
+ const build = () => {
93
+ const fetch = app.fetch;
94
+ let routes;
95
+ try {
96
+ routes = collectStaticRoutes(app);
97
+ } catch (error) {
98
+ console.warn("[Elysia] Native static promotion was skipped:", error);
99
+ }
100
+ const hasWs = app["~hasWS"];
101
+ let websocket;
102
+ if (hasWs) {
103
+ const defaultConfig = frozenRootOf(app)["~config"]?.websocket;
104
+ websocket = defaultConfig ? Object.assign(buildGlobalWSHandler(), defaultConfig) : buildGlobalWSHandler();
105
+ }
106
+ return {
107
+ fetch,
108
+ routes,
109
+ websocket
110
+ };
111
+ };
112
+ let built;
113
+ if (!needsGate) built = build();
114
+ if (needsGate) serve.fetch = (request, server) => ready.then(() => app.fetch(request, server));
115
+ else serve.fetch = built.fetch;
116
+ const server = app.server = Bun.serve(serve);
117
+ const reload = () => {
118
+ try {
119
+ server.reload(serve);
120
+ } catch (error) {
121
+ if (!serve.routes) throw error;
122
+ delete serve.routes;
123
+ console.warn("[Elysia] Native static promotion was skipped:", error);
124
+ try {
125
+ server.reload(serve);
126
+ } catch (fallbackError) {
127
+ console.error("[Elysia] Failed to reload Bun server:", fallbackError);
128
+ throw fallbackError;
129
+ }
130
+ }
131
+ };
132
+ const setup = () => {
133
+ const onSetup = app["~ext"]?.setup;
134
+ if (!onSetup) return;
90
135
  let pendingSetups;
91
136
  for (let i = 0; i < onSetup.length; i++) {
92
137
  const result = onSetup[i](app);
93
138
  if (result && typeof result.then === "function") (pendingSetups ??= []).push(result);
94
139
  }
95
- if (pendingSetups) setupReady = Promise.all(pendingSetups);
96
- }
97
- const hasWs = app["~hasWS"];
98
- if (!hasWs) {
99
- if (callback) if (setupReady) setupReady.then(() => callback(app.server));
100
- else callback(app.server);
101
- }
102
- queueMicrotask(() => {
140
+ if (pendingSetups) return Promise.all(pendingSetups);
141
+ };
142
+ const rollback = (error) => {
103
143
  if (app.server !== server) return;
104
- if (!app.pending) serve.fetch = app.fetch;
105
- const buildWebSocket = () => {
106
- const defaultConfig = app["~config"]?.websocket;
107
- serve.websocket = defaultConfig ? Object.assign(buildGlobalWSHandler(), defaultConfig) : buildGlobalWSHandler();
108
- };
109
- if (hasWs) buildWebSocket();
110
- const collectRoutes = () => {
111
- const staticRoutes = collectStaticRoutes(app);
112
- if (!staticRoutes) return;
113
- if (staticRoutes[1].length) return Promise.all(staticRoutes[1]).then(() => {
114
- if (app.server !== server) return;
115
- serve.routes = staticRoutes[0];
116
- app.server.reload(serve);
117
- });
118
- if (Object.keys(staticRoutes[0]).length) serve.routes = staticRoutes[0];
119
- };
120
- if (app.pending) {
121
- app.server.reload(serve);
122
- const reloadAfterModules = () => {
123
- if (app.server !== server) return;
124
- serve.fetch = app.fetch;
125
- if (hasWs || app["~hasWS"]) buildWebSocket();
126
- collectRoutes();
127
- app.server.reload(serve);
128
- };
129
- app.modules.then(reloadAfterModules, reloadAfterModules);
130
- } else {
131
- collectRoutes();
132
- app.server.reload(serve);
144
+ try {
145
+ server.stop(true);
146
+ } catch (stopError) {
147
+ console.error(stopError);
148
+ } finally {
149
+ app.server = void 0;
133
150
  }
134
- flushMemory();
135
- if (hasWs && callback) if (setupReady) setupReady.then(() => callback(app.server));
136
- else callback(app.server);
137
- });
151
+ const cleanup = app["~ext"]?.cleanup;
152
+ if (cleanup) for (let i = cleanup.length - 1; i >= 0; i--) try {
153
+ const result = cleanup[i](app);
154
+ if (result && typeof result.then === "function") Promise.resolve(result).catch(console.error);
155
+ } catch (cleanupError) {
156
+ console.error(cleanupError);
157
+ }
158
+ return error;
159
+ };
160
+ const publish = () => {
161
+ if (app.server !== server) return;
162
+ built ??= build();
163
+ serve.fetch = built.fetch;
164
+ if (built.websocket) serve.websocket = built.websocket;
165
+ if (built.routes) serve.routes = built.routes[0];
166
+ if (needsGate || built.websocket || built.routes) reload();
167
+ if (callback) callback(server);
168
+ };
169
+ const start = () => {
170
+ if (app.server !== server) return;
171
+ const setupReady = setup();
172
+ if (setupReady && typeof setupReady.then === "function") return Promise.resolve(setupReady).then(publish);
173
+ publish();
174
+ };
175
+ try {
176
+ if (app.pending) ready = app.modules.then(start);
177
+ else {
178
+ const result = start();
179
+ if (result && typeof result.then === "function") ready = result;
180
+ else if (needsGate) ready = Promise.resolve();
181
+ }
182
+ ready?.catch(rollback);
183
+ } catch (error) {
184
+ rollback(error);
185
+ throw error;
186
+ }
138
187
  }
139
188
  });
140
189
 
@@ -0,0 +1,4 @@
1
+ //#region src/adapter/default-headers.d.ts
2
+ declare const defaultHeaders = "\0";
3
+ //#endregion
4
+ export { defaultHeaders };
@@ -0,0 +1,7 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ //#region src/adapter/default-headers.ts
4
+ const defaultHeaders = "\0";
5
+
6
+ //#endregion
7
+ exports.defaultHeaders = defaultHeaders;
@@ -0,0 +1,5 @@
1
+ //#region src/adapter/default-headers.ts
2
+ const defaultHeaders = "\0";
3
+
4
+ //#endregion
5
+ export { defaultHeaders };
@@ -1,5 +1,5 @@
1
1
  import { ListenCallback, Serve } from "../universal/server.js";
2
- import { AnyLocalHook, MaybePromise } from "../types.js";
2
+ import { MaybePromise } from "../types.js";
3
3
  import { Context } from "../context.js";
4
4
  import { AnyElysia } from "../base.js";
5
5
 
@@ -30,58 +30,25 @@ interface ElysiaAdapterOptions {
30
30
  */
31
31
  websocket?: boolean;
32
32
  listen?(app: AnyElysia, options: string | number | Partial<Serve>, callback?: ListenCallback): void;
33
- /**
34
- * Stop server from serving
35
- *
36
- * ---
37
- * @example
38
- * ```typescript
39
- * app.stop()
40
- * ```
41
- *
42
- * @example
43
- * ```typescript
44
- * app.stop(true) // Abruptly any requests inflight
45
- * ```
46
- */
47
- stop?(app: AnyElysia, closeActiveConnections?: boolean): Promise<void>;
48
33
  parse: {
49
34
  json: (context: Context) => MaybePromise<Record<keyof any, undefined> | unknown[]>;
50
35
  text: (context: Context) => MaybePromise<string>;
51
36
  urlencoded: (context: Context) => MaybePromise<Record<string, string | string[]>>;
52
37
  arrayBuffer: (context: Context) => MaybePromise<ArrayBuffer>;
53
38
  formData: (context: Context) => MaybePromise<Record<string, unknown>>;
54
- default: (context: Context, contentType: string) => MaybePromise<any>;
39
+ default: (context: Context, contentType: string, normalized?: boolean) => MaybePromise<any>;
55
40
  };
56
41
  response: {
57
42
  /**
58
43
  * Map return response on every case
59
44
  */
60
- map(response: unknown, set: Context['set'], ...params: unknown[]): unknown;
45
+ map(response: unknown, set: Context['set'], ...params: unknown[]): unknown; /** Support immutable shared default headers. */
46
+ supportsDefaultHeaderSink?: true;
61
47
  /**
62
48
  * Map response without cookie, status or headers
63
49
  */
64
50
  compact?(response: unknown, ...params: unknown[]): unknown;
65
- /**
66
- * Compile inline to value
67
- *
68
- * @example
69
- * ```ts
70
- * Elysia().get('/', 'static')
71
- * ```
72
- */
73
- static?(handle: unknown, hooks: AnyLocalHook, setHeaders?: Context['set']['headers'], ...params: unknown[]): (() => unknown) | undefined;
74
- /**
75
- * If the runtime support cloning response
76
- *
77
- * eg. Bun.serve({ static })
78
- */
79
- nativeStatic?(handle: unknown, hooks: AnyLocalHook, set?: Context['set']): (() => MaybePromise<Response>) | undefined;
80
51
  };
81
- /**
82
- * override Elysia's default fetch function
83
- */
84
- fetch?(app: AnyElysia): (request: Request) => MaybePromise<Response>;
85
52
  }
86
53
  //#endregion
87
54
  export { ElysiaAdapterOptions };
@@ -1,9 +1,11 @@
1
+ import { BaseCookie } from "../cookie/types.js";
1
2
  import { StatusMap } from "../constants.js";
2
3
  import { ElysiaFile } from "../universal/file.js";
3
- import { BaseCookie } from "../cookie/types.js";
4
4
  import { HTTPHeaders } from "../types.js";
5
5
  import { Context } from "../context.js";
6
6
  //#region src/adapter/utils.d.ts
7
+ declare function materializeSetHeaders(set: Context['set']): any;
8
+ declare function normalizeContentType(contentType: string): string;
7
9
  declare function handleFile(response: File | Blob | ElysiaFile, set?: Context['set'], request?: Request, size?: number): Response;
8
10
  declare function parseSetCookies(headers: Headers, setCookie: string[]): Headers;
9
11
  declare function responseToSetHeaders(response: Response, set?: Context['set']): {
@@ -45,4 +47,4 @@ declare function createResponseHandler(handler: CreateHandlerParameter): (respon
45
47
  */
46
48
  declare function tee<T>(source: AsyncIterable<T>, branches?: number, cap?: number, capBytes?: number): AsyncIterableIterator<T>[];
47
49
  //#endregion
48
- export { createResponseHandler, createStreamHandler, handleFile, handleSet, parseSetCookies, responseToSetHeaders, streamResponse, tee };
50
+ export { createResponseHandler, createStreamHandler, handleFile, handleSet, materializeSetHeaders, normalizeContentType, parseSetCookies, responseToSetHeaders, streamResponse, tee };
@@ -4,13 +4,24 @@ const require_constants = require('../constants.js');
4
4
  const require_utils = require('../utils.js');
5
5
  const require_adapter_skip_clone = require('./skip-clone.js');
6
6
  const require_cookie_serialize = require('../cookie/serialize.js');
7
+ const require_adapter_default_headers = require('./default-headers.js');
7
8
 
8
9
  //#region src/adapter/utils.ts
9
10
  const setCookie = "set-cookie";
11
+ function materializeSetHeaders(set) {
12
+ const headers = set.headers;
13
+ if (headers["\0"] !== headers) return headers;
14
+ return set.headers = Object.assign(require_utils.nullObject(), headers);
15
+ }
10
16
  const sseFormat = (data) => `data: ${data}\n\n`;
11
17
  const identityFormat = (data) => data;
12
18
  const textEncoder = new TextEncoder();
13
19
  const encodeChunk = (s) => textEncoder.encode(s);
20
+ function normalizeContentType(contentType) {
21
+ if (contentType === "application/json") return contentType;
22
+ const end = contentType.indexOf(";");
23
+ return (end === -1 ? contentType : contentType.slice(0, end)).trim().toLowerCase();
24
+ }
14
25
  function handleFile(response, set, request, size = response.size) {
15
26
  if (!require_universal_constants.isBun && response instanceof Promise) return response.then((res) => handleFile(res, set, request, size));
16
27
  const rangeHeader = request?.headers.get("range");
@@ -92,6 +103,7 @@ function parseSetCookies(headers, setCookie) {
92
103
  }
93
104
  function responseToSetHeaders(response, set) {
94
105
  if (set && set.headers instanceof Headers) normalizeHeaders(set);
106
+ if (set) materializeSetHeaders(set);
95
107
  if (set?.headers) {
96
108
  if (response) if (require_universal_constants.hasHeaderShorthand) Object.assign(set.headers, response.headers.toJSON());
97
109
  else for (const [key, value] of response.headers.entries()) set.headers[key] = value;
@@ -148,6 +160,7 @@ function createStreamHandler({ mapResponse, mapCompactResponse }) {
148
160
  const isSSE = !skipFormat && (init?.value?.sse ?? generator?.sse ?? (set?.headers instanceof Headers ? set.headers.get("content-type")?.startsWith("text/event-stream") : set?.headers["content-type"]?.startsWith("text/event-stream")));
149
161
  const format = isSSE ? sseFormat : identityFormat;
150
162
  const contentType = isSSE ? "text/event-stream" : init?.value && typeof init?.value === "object" ? ArrayBuffer.isView(init.value) ? "application/octet-stream" : "application/json" : "text/plain";
163
+ if (set) materializeSetHeaders(set);
151
164
  const headers = set?.headers;
152
165
  if (headers instanceof Headers) {
153
166
  if (!headers.has("transfer-encoding")) headers.set("transfer-encoding", "chunked");
@@ -259,6 +272,7 @@ function handleSet(set) {
259
272
  set.headers = flat;
260
273
  }
261
274
  if (set.cookie && require_utils.isNotEmpty(set.cookie)) {
275
+ materializeSetHeaders(set);
262
276
  const cookie = require_cookie_serialize.serializeCookie(set.cookie);
263
277
  if (cookie) {
264
278
  const existing = set.headers[setCookie];
@@ -513,6 +527,8 @@ exports.createResponseHandler = createResponseHandler;
513
527
  exports.createStreamHandler = createStreamHandler;
514
528
  exports.handleFile = handleFile;
515
529
  exports.handleSet = handleSet;
530
+ exports.materializeSetHeaders = materializeSetHeaders;
531
+ exports.normalizeContentType = normalizeContentType;
516
532
  exports.parseSetCookies = parseSetCookies;
517
533
  exports.responseToSetHeaders = responseToSetHeaders;
518
534
  exports.streamResponse = streamResponse;