elysia 2.0.0-exp.11 → 2.0.0-exp.13

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 (43) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +2 -0
  2. package/dist/adapter/bun/index.d.ts +1 -1
  3. package/dist/adapter/bun/index.js +2 -0
  4. package/dist/adapter/bun/index.mjs +2 -0
  5. package/dist/adapter/constants.d.ts +1 -1
  6. package/dist/adapter/index.d.ts +1 -1
  7. package/dist/adapter/utils.d.ts +4 -1
  8. package/dist/adapter/utils.js +3 -4
  9. package/dist/adapter/utils.mjs +1 -2
  10. package/dist/adapter/web-standard/index.d.ts +1 -1
  11. package/dist/base.d.ts +35 -5
  12. package/dist/base.js +58 -7
  13. package/dist/base.mjs +58 -7
  14. package/dist/compile/handler/index.js +1 -1
  15. package/dist/compile/handler/index.mjs +1 -1
  16. package/dist/compile/handler/jit.js +2 -2
  17. package/dist/compile/handler/jit.mjs +2 -2
  18. package/dist/compile/handler/params.js +1 -1
  19. package/dist/compile/handler/params.mjs +1 -1
  20. package/dist/compile/handler/reconstruct.js +1 -1
  21. package/dist/compile/handler/reconstruct.mjs +1 -1
  22. package/dist/cookie/index.d.ts +2 -2
  23. package/dist/handler/fetch.js +19 -24
  24. package/dist/handler/fetch.mjs +19 -24
  25. package/dist/index.d.ts +3 -5
  26. package/dist/index.js +0 -4
  27. package/dist/index.mjs +1 -3
  28. package/dist/type/elysia/file-type.d.ts +1 -1
  29. package/dist/type/exports.js +29 -2059
  30. package/dist/type/exports.mjs +7 -295
  31. package/dist/type/index.d.ts +3 -1
  32. package/dist/type/validator/index.d.ts +1 -1
  33. package/dist/types.d.ts +3 -3
  34. package/dist/universal/file.d.ts +8 -8
  35. package/dist/universal/file.js +8 -8
  36. package/dist/universal/file.mjs +8 -8
  37. package/dist/utils.d.ts +1 -1
  38. package/dist/validator/index.d.ts +1 -1
  39. package/dist/validator/index.js +2 -2
  40. package/dist/validator/index.mjs +2 -2
  41. package/dist/ws/route.js +5 -1
  42. package/dist/ws/route.mjs +6 -2
  43. package/package.json +8 -3
@@ -32,6 +32,7 @@ var __copyProps = (to, from, except, desc) => {
32
32
  }
33
33
  return to;
34
34
  };
35
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
35
36
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
36
37
  value: mod,
37
38
  enumerable: true
@@ -40,4 +41,5 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
40
41
  //#endregion
41
42
 
42
43
  exports.__exportAll = __exportAll;
44
+ exports.__reExport = __reExport;
43
45
  exports.__toESM = __toESM;
@@ -6,7 +6,7 @@ import { AnyElysia } from "../../base.js";
6
6
  declare function collectStaticRoutes(app: AnyElysia): readonly [Record<string, Record<string, Response>>, Promise<void>[]] | undefined;
7
7
  declare const BunAdapter: {
8
8
  parse: {
9
- default: (context: Context, contentType: string) => string | Record<string, unknown> | unknown[] | ArrayBuffer | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
9
+ default: (context: Context, contentType: string) => string | unknown[] | ArrayBuffer | Record<string, unknown> | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
10
10
  json: (context: Context) => MaybePromise<Record<keyof any, undefined> | unknown[]>;
11
11
  text: (context: Context) => MaybePromise<string>;
12
12
  urlencoded: (context: Context) => MaybePromise<Record<string, string | string[]>>;
@@ -47,6 +47,8 @@ const BunAdapter = require_adapter_index.createAdapter({
47
47
  const hasWs = app["~hasWS"];
48
48
  if (!serve.fetch) serve.fetch = (request, server) => app.fetch(request, server);
49
49
  app.server = Bun.serve(serve);
50
+ const onSetup = app["~ext"]?.setup;
51
+ if (onSetup) for (let i = 0; i < onSetup.length; i++) onSetup[i](app);
50
52
  if (!hasWs) callback?.(app.server);
51
53
  queueMicrotask(() => {
52
54
  if (!app.pending) serve.fetch = app.fetch;
@@ -46,6 +46,8 @@ const BunAdapter = createAdapter({
46
46
  const hasWs = app["~hasWS"];
47
47
  if (!serve.fetch) serve.fetch = (request, server) => app.fetch(request, server);
48
48
  app.server = Bun.serve(serve);
49
+ const onSetup = app["~ext"]?.setup;
50
+ if (onSetup) for (let i = 0; i < onSetup.length; i++) onSetup[i](app);
49
51
  if (!hasWs) callback?.(app.server);
50
52
  queueMicrotask(() => {
51
53
  if (!app.pending) serve.fetch = app.fetch;
@@ -5,7 +5,7 @@ import { AnyElysia } from "../base.js";
5
5
  //#region src/adapter/constants.d.ts
6
6
  declare const defaultAdapter: {
7
7
  parse: {
8
- default: (context: Context, contentType: string) => string | Record<string, unknown> | unknown[] | ArrayBuffer | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
8
+ default: (context: Context, contentType: string) => string | unknown[] | ArrayBuffer | Record<string, unknown> | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
9
9
  json: (context: Context) => MaybePromise<Record<keyof any, undefined> | unknown[]>;
10
10
  text: (context: Context) => MaybePromise<string>;
11
11
  urlencoded: (context: Context) => MaybePromise<Record<string, string | string[]>>;
@@ -7,7 +7,7 @@ import { AnyElysia } from "../base.js";
7
7
  //#region src/adapter/index.d.ts
8
8
  declare function createAdapter(adapter: ElysiaAdapterOptions): {
9
9
  parse: {
10
- default: (context: Context, contentType: string) => string | Record<string, unknown> | unknown[] | ArrayBuffer | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
10
+ default: (context: Context, contentType: string) => string | unknown[] | ArrayBuffer | Record<string, unknown> | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
11
11
  json: (context: Context) => MaybePromise<Record<keyof any, undefined> | unknown[]>;
12
12
  text: (context: Context) => MaybePromise<string>;
13
13
  urlencoded: (context: Context) => MaybePromise<Record<string, string | string[]>>;
@@ -18,7 +18,10 @@ interface CreateHandlerParameter {
18
18
  mapResponse(response: unknown, set: Context['set'], request?: Request): Response;
19
19
  mapCompactResponse(response: unknown, request?: Request): Response;
20
20
  }
21
- declare function createStreamHandler(_: CreateHandlerParameter): (generator: Generator | AsyncGenerator | ReadableStream, set?: Context["set"], request?: Request, skipFormat?: boolean) => Promise<Response>;
21
+ declare function createStreamHandler({
22
+ mapResponse,
23
+ mapCompactResponse
24
+ }: CreateHandlerParameter): (generator: Generator | AsyncGenerator | ReadableStream, set?: Context["set"], request?: Request, skipFormat?: boolean) => Promise<Response>;
22
25
  declare function streamResponse(response: Response): AsyncGenerator<any, void, any>;
23
26
  declare function handleSet(set: Context['set']): void;
24
27
  declare function mergeHeaders(responseHeaders: Headers, setHeaders: Context['set']['headers']): Headers;
@@ -3,7 +3,6 @@ const require_universal_constants = require('../universal/constants.js');
3
3
  const require_constants = require('../constants.js');
4
4
  const require_utils = require('../utils.js');
5
5
  const require_cookie_serialize = require('../cookie/serialize.js');
6
- const require_adapter_web_standard_handler = require('./web-standard/handler.js');
7
6
 
8
7
  //#region src/adapter/utils.ts
9
8
  const setCookie = "set-cookie";
@@ -121,15 +120,15 @@ function enqueueBinaryChunk(controller, chunk) {
121
120
  }
122
121
  return false;
123
122
  }
124
- function createStreamHandler(_) {
123
+ function createStreamHandler({ mapResponse, mapCompactResponse }) {
125
124
  return async (generator, set, request, skipFormat) => {
126
125
  let init = generator.next?.();
127
126
  if (set) handleSet(set);
128
127
  if (init instanceof Promise) init = await init;
129
128
  if (init?.value instanceof ReadableStream) generator = init.value;
130
129
  else if (init && (typeof init?.done === "undefined" || init?.done)) {
131
- if (set) return require_adapter_web_standard_handler.mapResponse(init.value, set, request);
132
- return require_adapter_web_standard_handler.mapCompactResponse(init.value, request);
130
+ if (set) return mapResponse(init.value, set, request);
131
+ return mapCompactResponse(init.value, request);
133
132
  }
134
133
  const isSSE = !skipFormat && (init?.value?.sse ?? generator?.sse ?? set?.headers["content-type"]?.startsWith("text/event-stream"));
135
134
  const format = isSSE ? (data) => `data: ${data}\n\n` : (data) => data;
@@ -2,7 +2,6 @@ import { hasHeaderShorthand, isBun } from "../universal/constants.mjs";
2
2
  import { StatusMap } from "../constants.mjs";
3
3
  import { isNotEmpty, nullObject } from "../utils.mjs";
4
4
  import { serializeCookie } from "../cookie/serialize.mjs";
5
- import { mapCompactResponse, mapResponse } from "./web-standard/handler.mjs";
6
5
 
7
6
  //#region src/adapter/utils.ts
8
7
  const setCookie = "set-cookie";
@@ -120,7 +119,7 @@ function enqueueBinaryChunk(controller, chunk) {
120
119
  }
121
120
  return false;
122
121
  }
123
- function createStreamHandler(_) {
122
+ function createStreamHandler({ mapResponse, mapCompactResponse }) {
124
123
  return async (generator, set, request, skipFormat) => {
125
124
  let init = generator.next?.();
126
125
  if (set) handleSet(set);
@@ -5,7 +5,7 @@ import { AnyElysia } from "../../base.js";
5
5
  //#region src/adapter/web-standard/index.d.ts
6
6
  declare const WebStandardAdapter: {
7
7
  parse: {
8
- default: (context: Context, contentType: string) => string | Record<string, unknown> | unknown[] | ArrayBuffer | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
8
+ default: (context: Context, contentType: string) => string | unknown[] | ArrayBuffer | Record<string, unknown> | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
9
9
  json: (context: Context) => MaybePromise<Record<keyof any, undefined> | unknown[]>;
10
10
  text: (context: Context) => MaybePromise<string>;
11
11
  urlencoded: (context: Context) => MaybePromise<Record<string, string | string[]>>;
package/dist/base.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { ElysiaStatus } from "./error.js";
2
2
  import { TraceHandler } from "./trace.js";
3
- import { ListenCallback, Serve, Server } from "./universal/server.js";
4
- import { AddRoute, AddWSRoute, AfterHandler, AfterResponseHandler, AnyErrorConstructor, AnyLocalHook, BodyHandler, CompiledHandler, CreateEden, DefaultEphemeral, DefaultMetadata, DefaultSingleton, DefinitionBase, DocumentDecoration, ElysiaConfig, ElysiaHandlerToResponseSchemaAmbiguous, EphemeralType, ErrorDefinitionEntry, ErrorHandler, EventScope, ExcludeElysiaResponse, ExtractErrorFromHandle, GuardLocalHook, HTTPMethod, InlineHandler, InlineHandlerNonMacro, InputSchema, InputSchemaKey, InternalRoute, IntersectIfObjectSchema, JoinPath, LocalHook, Macro, MacroToContext, MacroToProperty, MapResponse, MaybeArray, MaybePromise, MergeElysiaInstances, MergeSchema, MergeScopedSchemas, MetadataBase, NonResolvableMacroKey, ObjectMacroDefs, OptionalHandler, PreHandler, Prettify, PublicRoute, ResolveRouteErrors, RouteBase, SingletonBase, TransformHandler, UnionResponseStatus, UnwrapRoute, WrapFn } from "./types.js";
5
3
  import { AnySchema } from "./type/types.js";
4
+ import { ListenCallback, Serve, Server } from "./universal/server.js";
5
+ import { AddRoute, AddWSRoute, AfterHandler, AfterResponseHandler, AnyErrorConstructor, AnyLocalHook, BodyHandler, CompiledHandler, CreateEden, DefaultEphemeral, DefaultMetadata, DefaultSingleton, DefinitionBase, DocumentDecoration, ElysiaConfig, ElysiaHandlerToResponseSchemaAmbiguous, EphemeralType, ErrorDefinitionEntry, ErrorHandler, EventScope, ExcludeElysiaResponse, ExtractErrorFromHandle, GracefulHandler, GuardLocalHook, HTTPMethod, InlineHandler, InlineHandlerNonMacro, InputSchema, InputSchemaKey, InternalRoute, IntersectIfObjectSchema, JoinPath, LocalHook, Macro, MacroToContext, MacroToProperty, MapResponse, MaybeArray, MaybePromise, MergeElysiaInstances, MergeSchema, MergeScopedSchemas, MetadataBase, NonResolvableMacroKey, ObjectMacroDefs, OptionalHandler, PreHandler, Prettify, PublicRoute, ResolveRouteErrors, RouteBase, SingletonBase, TransformHandler, UnionResponseStatus, UnwrapRoute, WrapFn } from "./types.js";
6
6
  import { ChainNode } from "./utils.js";
7
7
  import { Context, ErrorContext, LifecycleContext } from "./context.js";
8
8
  import { WSHandlerResponse, WSLocalHook, WSMessageHandler } from "./ws/types.js";
@@ -34,6 +34,8 @@ declare class Elysia<const in out BasePath extends string = '', const in out Sco
34
34
  error?: Map<AnyErrorConstructor, string>;
35
35
  parser?: Record<string, BodyHandler<any, any>>;
36
36
  hoc?: WrapFn<any>[];
37
+ setup?: GracefulHandler<any>[];
38
+ cleanup?: GracefulHandler<any>[];
37
39
  };
38
40
  '~hookChain'?: ChainNode;
39
41
  server?: Server;
@@ -175,8 +177,21 @@ declare class Elysia<const in out BasePath extends string = '', const in out Sco
175
177
  parser: Metadata['parser'] & { [name in Name]: BodyHandler<any, any> };
176
178
  response: Metadata['response'];
177
179
  }, Routes, Ephemeral, Volatile>;
178
- onStart(_listener?: unknown): this;
179
- onStop(_listener?: unknown): this;
180
+ /**
181
+ * ### setup | Life cycle event
182
+ * Called after server is ready for serving
183
+ *
184
+ * ---
185
+ * @example
186
+ * ```typescript
187
+ * new Elysia()
188
+ * .setup(({ server }) => {
189
+ * console.log("Running at ${server?.url}:${server?.port}")
190
+ * })
191
+ * .listen(3000)
192
+ * ```
193
+ */
194
+ setup(handler: MaybeArray<GracefulHandler<this>>): this;
180
195
  transform(fn: MaybeArray<TransformHandler<MergeSchema<{}, {}, BasePath>, Singleton & {
181
196
  derive: Ephemeral['derive'] & Volatile['derive'];
182
197
  }>>): this;
@@ -990,7 +1005,22 @@ declare class Elysia<const in out BasePath extends string = '', const in out Sco
990
1005
  listen(options: string | number | Partial<Serve>, callback?: ListenCallback): this;
991
1006
  wrap<T extends (...params: any) => MaybePromise<Response> = (request: Request, ...rest: any[]) => MaybePromise<Response>>(callback: WrapFn<T>): this;
992
1007
  /**
993
- * Stop the underlying server (if any). Mirrors `Server.stop()`.
1008
+ * ### cleanup | Life cycle event
1009
+ * Called after server stop serving request
1010
+ *
1011
+ * ---
1012
+ * @example
1013
+ * ```typescript
1014
+ * new Elysia()
1015
+ * .cleanup((app) => {
1016
+ * closeDatabase()
1017
+ * })
1018
+ * ```
1019
+ */
1020
+ cleanup(handler: MaybeArray<GracefulHandler<this>>): this;
1021
+ /**
1022
+ * Stop the underlying server (if any), running every `cleanup` handler once
1023
+ * it has stopped. Mirrors `Server.stop()`.
994
1024
  *
995
1025
  * @param closeActiveConnections Pass `true` to terminate in-flight
996
1026
  * requests and WebSocket connections immediately. Defaults to
package/dist/base.js CHANGED
@@ -5,10 +5,11 @@ const require_constants = require('./constants.js');
5
5
  const require_utils = require('./utils.js');
6
6
  const require_type_bridge = require('./type/bridge.js');
7
7
  const require_universal_env = require('./universal/env.js');
8
+ const require_compile_aot = require('./compile/aot.js');
9
+ const require_compile_handler_index = require('./compile/handler/index.js');
8
10
  const require_ws_route = require('./ws/route.js');
9
11
  const require_adapter_bun_index = require('./adapter/bun/index.js');
10
12
  const require_handler_fetch = require('./handler/fetch.js');
11
- const require_compile_handler_index = require('./compile/handler/index.js');
12
13
  let memoirist = require("memoirist");
13
14
  memoirist = require_runtime.__toESM(memoirist);
14
15
 
@@ -173,10 +174,24 @@ var Elysia = class Elysia {
173
174
  parsers[name] = fn;
174
175
  return this;
175
176
  }
176
- onStart(_listener) {
177
- return this;
178
- }
179
- onStop(_listener) {
177
+ /**
178
+ * ### setup | Life cycle event
179
+ * Called after server is ready for serving
180
+ *
181
+ * ---
182
+ * @example
183
+ * ```typescript
184
+ * new Elysia()
185
+ * .setup(({ server }) => {
186
+ * console.log("Running at ${server?.url}:${server?.port}")
187
+ * })
188
+ * .listen(3000)
189
+ * ```
190
+ */
191
+ setup(handler) {
192
+ const arr = this.#ext.setup ??= [];
193
+ if (Array.isArray(handler)) arr.push(...handler);
194
+ else arr.push(handler);
180
195
  return this;
181
196
  }
182
197
  transform(scopeOrFn, fn) {
@@ -518,7 +533,7 @@ var Elysia = class Elysia {
518
533
  }
519
534
  const hookChain = app["~hookChain"];
520
535
  if (app["~ext"]) {
521
- const { decorator, store, headers, models, parser, macro, error, hoc } = app["~ext"];
536
+ const { decorator, store, headers, models, parser, macro, error, hoc, setup, cleanup } = app["~ext"];
522
537
  const ext = this["~ext"] ??= require_utils.nullObject();
523
538
  if (decorator) {
524
539
  const cloned = require_utils.clonePlainDecorators(decorator);
@@ -540,6 +555,12 @@ var Elysia = class Elysia {
540
555
  if (hoc) if (ext.hoc) {
541
556
  for (const fn of hoc) if (!ext.hoc.includes(fn)) ext.hoc.push(fn);
542
557
  } else ext.hoc = hoc.slice();
558
+ if (setup) if (ext.setup) {
559
+ for (const fn of setup) if (!ext.setup.includes(fn)) ext.setup.push(fn);
560
+ } else ext.setup = setup.slice();
561
+ if (cleanup) if (ext.cleanup) {
562
+ for (const fn of cleanup) if (!ext.cleanup.includes(fn)) ext.cleanup.push(fn);
563
+ } else ext.cleanup = cleanup.slice();
543
564
  }
544
565
  if (app.#hasPlugin || app.#hasGlobal || hookChain) {
545
566
  let pluginEvents;
@@ -803,6 +824,10 @@ var Elysia = class Elysia {
803
824
  this["~config"] ??= require_utils.nullObject();
804
825
  this["~config"].precompile = true;
805
826
  this.#routerBuilt = false;
827
+ if (require_compile_aot.Capture.isCapturing()) {
828
+ this.#compiled = void 0;
829
+ this.#fetchFn = void 0;
830
+ }
806
831
  this.fetch;
807
832
  return this;
808
833
  }
@@ -1014,7 +1039,27 @@ var Elysia = class Elysia {
1014
1039
  return this;
1015
1040
  }
1016
1041
  /**
1017
- * Stop the underlying server (if any). Mirrors `Server.stop()`.
1042
+ * ### cleanup | Life cycle event
1043
+ * Called after server stop serving request
1044
+ *
1045
+ * ---
1046
+ * @example
1047
+ * ```typescript
1048
+ * new Elysia()
1049
+ * .cleanup((app) => {
1050
+ * closeDatabase()
1051
+ * })
1052
+ * ```
1053
+ */
1054
+ cleanup(handler) {
1055
+ const arr = this.#ext.cleanup ??= [];
1056
+ if (Array.isArray(handler)) arr.push(...handler);
1057
+ else arr.push(handler);
1058
+ return this;
1059
+ }
1060
+ /**
1061
+ * Stop the underlying server (if any), running every `cleanup` handler once
1062
+ * it has stopped. Mirrors `Server.stop()`.
1018
1063
  *
1019
1064
  * @param closeActiveConnections Pass `true` to terminate in-flight
1020
1065
  * requests and WebSocket connections immediately. Defaults to
@@ -1025,6 +1070,12 @@ var Elysia = class Elysia {
1025
1070
  if (!server) return;
1026
1071
  const r = server.stop?.(closeActiveConnections);
1027
1072
  this.server = void 0;
1073
+ const handlers = this["~ext"]?.cleanup;
1074
+ const fire = handlers ? () => {
1075
+ for (let i = 0; i < handlers.length; i++) handlers[i](this);
1076
+ } : void 0;
1077
+ if (r && typeof r.then === "function") return fire ? r.then(fire) : r;
1078
+ fire?.();
1028
1079
  return r;
1029
1080
  }
1030
1081
  };
package/dist/base.mjs CHANGED
@@ -3,10 +3,11 @@ import { MethodMap, isDynamicRegex, needEncodeRegex } from "./constants.mjs";
3
3
  import { clonePlainDecorators, coalesceStandaloneSchemas, createErrorEventHandler, eventProperties, flattenChain, fnOrigin, fnv1a, getLoosePath, hookToGuard, isEmpty, isNotEmpty, isRecordNumber, joinPath, mapMethodBack, mergeDeep, mergeResponse, nullObject, pushField, replaceUrlPath, schemaProperties } from "./utils.mjs";
4
4
  import { Ref } from "./type/bridge.mjs";
5
5
  import { env } from "./universal/env.mjs";
6
+ import { Capture } from "./compile/aot.mjs";
7
+ import { buildNativeStaticResponse, compileHandler, composeRouteHook } from "./compile/handler/index.mjs";
6
8
  import { buildWSRoute } from "./ws/route.mjs";
7
9
  import { BunAdapter } from "./adapter/bun/index.mjs";
8
10
  import { applyHoc, createFetchHandler } from "./handler/fetch.mjs";
9
- import { buildNativeStaticResponse, compileHandler, composeRouteHook } from "./compile/handler/index.mjs";
10
11
  import Memoirist from "memoirist";
11
12
 
12
13
  //#region src/base.ts
@@ -170,10 +171,24 @@ var Elysia = class Elysia {
170
171
  parsers[name] = fn;
171
172
  return this;
172
173
  }
173
- onStart(_listener) {
174
- return this;
175
- }
176
- onStop(_listener) {
174
+ /**
175
+ * ### setup | Life cycle event
176
+ * Called after server is ready for serving
177
+ *
178
+ * ---
179
+ * @example
180
+ * ```typescript
181
+ * new Elysia()
182
+ * .setup(({ server }) => {
183
+ * console.log("Running at ${server?.url}:${server?.port}")
184
+ * })
185
+ * .listen(3000)
186
+ * ```
187
+ */
188
+ setup(handler) {
189
+ const arr = this.#ext.setup ??= [];
190
+ if (Array.isArray(handler)) arr.push(...handler);
191
+ else arr.push(handler);
177
192
  return this;
178
193
  }
179
194
  transform(scopeOrFn, fn) {
@@ -515,7 +530,7 @@ var Elysia = class Elysia {
515
530
  }
516
531
  const hookChain = app["~hookChain"];
517
532
  if (app["~ext"]) {
518
- const { decorator, store, headers, models, parser, macro, error, hoc } = app["~ext"];
533
+ const { decorator, store, headers, models, parser, macro, error, hoc, setup, cleanup } = app["~ext"];
519
534
  const ext = this["~ext"] ??= nullObject();
520
535
  if (decorator) {
521
536
  const cloned = clonePlainDecorators(decorator);
@@ -537,6 +552,12 @@ var Elysia = class Elysia {
537
552
  if (hoc) if (ext.hoc) {
538
553
  for (const fn of hoc) if (!ext.hoc.includes(fn)) ext.hoc.push(fn);
539
554
  } else ext.hoc = hoc.slice();
555
+ if (setup) if (ext.setup) {
556
+ for (const fn of setup) if (!ext.setup.includes(fn)) ext.setup.push(fn);
557
+ } else ext.setup = setup.slice();
558
+ if (cleanup) if (ext.cleanup) {
559
+ for (const fn of cleanup) if (!ext.cleanup.includes(fn)) ext.cleanup.push(fn);
560
+ } else ext.cleanup = cleanup.slice();
540
561
  }
541
562
  if (app.#hasPlugin || app.#hasGlobal || hookChain) {
542
563
  let pluginEvents;
@@ -800,6 +821,10 @@ var Elysia = class Elysia {
800
821
  this["~config"] ??= nullObject();
801
822
  this["~config"].precompile = true;
802
823
  this.#routerBuilt = false;
824
+ if (Capture.isCapturing()) {
825
+ this.#compiled = void 0;
826
+ this.#fetchFn = void 0;
827
+ }
803
828
  this.fetch;
804
829
  return this;
805
830
  }
@@ -1011,7 +1036,27 @@ var Elysia = class Elysia {
1011
1036
  return this;
1012
1037
  }
1013
1038
  /**
1014
- * Stop the underlying server (if any). Mirrors `Server.stop()`.
1039
+ * ### cleanup | Life cycle event
1040
+ * Called after server stop serving request
1041
+ *
1042
+ * ---
1043
+ * @example
1044
+ * ```typescript
1045
+ * new Elysia()
1046
+ * .cleanup((app) => {
1047
+ * closeDatabase()
1048
+ * })
1049
+ * ```
1050
+ */
1051
+ cleanup(handler) {
1052
+ const arr = this.#ext.cleanup ??= [];
1053
+ if (Array.isArray(handler)) arr.push(...handler);
1054
+ else arr.push(handler);
1055
+ return this;
1056
+ }
1057
+ /**
1058
+ * Stop the underlying server (if any), running every `cleanup` handler once
1059
+ * it has stopped. Mirrors `Server.stop()`.
1015
1060
  *
1016
1061
  * @param closeActiveConnections Pass `true` to terminate in-flight
1017
1062
  * requests and WebSocket connections immediately. Defaults to
@@ -1022,6 +1067,12 @@ var Elysia = class Elysia {
1022
1067
  if (!server) return;
1023
1068
  const r = server.stop?.(closeActiveConnections);
1024
1069
  this.server = void 0;
1070
+ const handlers = this["~ext"]?.cleanup;
1071
+ const fire = handlers ? () => {
1072
+ for (let i = 0; i < handlers.length; i++) handlers[i](this);
1073
+ } : void 0;
1074
+ if (r && typeof r.then === "function") return fire ? r.then(fire) : r;
1075
+ fire?.();
1025
1076
  return r;
1026
1077
  }
1027
1078
  };
@@ -1,10 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_utils = require('../../utils.js');
3
3
  const require_compile_aot = require('../aot.js');
4
- const require_adapter_constants = require('../../adapter/constants.js');
5
4
  const require_compile_handler_params = require('./params.js');
6
5
  const require_compile_handler_jit = require('./jit.js');
7
6
  const require_compile_handler_reconstruct = require('./reconstruct.js');
7
+ const require_adapter_constants = require('../../adapter/constants.js');
8
8
 
9
9
  //#region src/compile/handler/index.ts
10
10
  function applyHook(localHook, appHook, rootHook, appHookFresh = false) {
@@ -1,9 +1,9 @@
1
1
  import { cloneHook, eventProperties, flattenChain, flattenChainMemo, fnOrigin, isLocalScope, mapMethodBack, mergeHook, nullObject } from "../../utils.mjs";
2
2
  import { Compiled } from "../aot.mjs";
3
- import { defaultAdapter } from "../../adapter/constants.mjs";
4
3
  import { resolveHandlerParams } from "./params.mjs";
5
4
  import { compileHandlerJit, setCaptureHeaderShorthand } from "./jit.mjs";
6
5
  import { Reconstrct } from "./reconstruct.mjs";
6
+ import { defaultAdapter } from "../../adapter/constants.mjs";
7
7
 
8
8
  //#region src/compile/handler/index.ts
9
9
  function applyHook(localHook, appHook, rootHook, appHookFresh = false) {
@@ -9,10 +9,10 @@ const require_sucrose = require('../../sucrose.js');
9
9
  const require_compile_aot = require('../aot.js');
10
10
  const require_compile_utils = require('../utils.js');
11
11
  const require_compile_handler_utils = require('./utils.js');
12
- const require_handler_utils = require('../../handler/utils.js');
13
- const require_trace = require('../../trace.js');
14
12
  const require_cookie_config = require('../../cookie/config.js');
15
13
  const require_cookie_utils = require('../../cookie/utils.js');
14
+ const require_handler_utils = require('../../handler/utils.js');
15
+ const require_trace = require('../../trace.js');
16
16
  const require_compile_jit_probe = require('../jit-probe.js');
17
17
 
18
18
  //#region src/compile/handler/jit.ts
@@ -8,10 +8,10 @@ import { sucrose } from "../../sucrose.mjs";
8
8
  import { Capture } from "../aot.mjs";
9
9
  import { isAsyncFunction, isAsyncLifecycle, mayReturnPromise } from "../utils.mjs";
10
10
  import { cloneResponse, getQueryParseArgs, hasRequestBody, mapAfterHandle, mapAfterResponse, mapBeforeHandle, mapError, mapMapResponse, mapTransform } from "./utils.mjs";
11
- import { forwardError } from "../../handler/utils.mjs";
12
- import { createTracer } from "../../trace.mjs";
13
11
  import { compileCookieConfig } from "../../cookie/config.mjs";
14
12
  import { buildCookieJar, parseCookieRaw, parseCookieRawSync, signCookieValues } from "../../cookie/utils.mjs";
13
+ import { forwardError } from "../../handler/utils.mjs";
14
+ import { createTracer } from "../../trace.mjs";
15
15
  import { JITProbe } from "../jit-probe.mjs";
16
16
 
17
17
  //#region src/compile/handler/jit.ts
@@ -4,8 +4,8 @@ const require_adapter_utils = require('../../adapter/utils.js');
4
4
  const require_error = require('../../error.js');
5
5
  const require_parse_query = require('../../parse-query.js');
6
6
  const require_compile_handler_utils = require('./utils.js');
7
- const require_handler_utils = require('../../handler/utils.js');
8
7
  const require_cookie_utils = require('../../cookie/utils.js');
8
+ const require_handler_utils = require('../../handler/utils.js');
9
9
 
10
10
  //#region src/compile/handler/params.ts
11
11
  const HANDLER_PARAMS = {
@@ -3,8 +3,8 @@ import { tee } from "../../adapter/utils.mjs";
3
3
  import { ElysiaStatus, ParseError, ValidationError } from "../../error.mjs";
4
4
  import { parseQueryFromURL } from "../../parse-query.mjs";
5
5
  import { cloneResponse, hasRequestBody } from "./utils.mjs";
6
- import { forwardError } from "../../handler/utils.mjs";
7
6
  import { buildCookieJar, parseCookieRaw, parseCookieRawSync, signCookieValues } from "../../cookie/utils.mjs";
7
+ import { forwardError } from "../../handler/utils.mjs";
8
8
 
9
9
  //#region src/compile/handler/params.ts
10
10
  const HANDLER_PARAMS = {
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_validator_route = require('../../validator/route.js');
3
- const require_trace = require('../../trace.js');
4
3
  const require_cookie_config = require('../../cookie/config.js');
4
+ const require_trace = require('../../trace.js');
5
5
 
6
6
  //#region src/compile/handler/reconstruct.ts
7
7
  var Reconstrct = class {
@@ -1,6 +1,6 @@
1
1
  import { RouteValidator } from "../../validator/route.mjs";
2
- import { createTracer } from "../../trace.mjs";
3
2
  import { compileCookieConfig } from "../../cookie/config.mjs";
3
+ import { createTracer } from "../../trace.mjs";
4
4
 
5
5
  //#region src/compile/handler/reconstruct.ts
6
6
  var Reconstrct = class {
@@ -1,5 +1,5 @@
1
- import { CookieOptions } from "./types.js";
1
+ import { BaseCookie, CookieOptions } from "./types.js";
2
2
  import { Cookie } from "./cookie.js";
3
3
  import { serializeCookie } from "./serialize.js";
4
4
  import { createCookieJar, parseCookie, signCookie, unsignCookie } from "./utils.js";
5
- export { Cookie, type CookieOptions, createCookieJar, parseCookie, serializeCookie, signCookie, unsignCookie };
5
+ export { type BaseCookie, Cookie, type CookieOptions, createCookieJar, parseCookie, serializeCookie, signCookie, unsignCookie };
@@ -4,10 +4,10 @@ const require_utils = require('../utils.js');
4
4
  const require_adapter_utils = require('../adapter/utils.js');
5
5
  const require_error = require('../error.js');
6
6
  const require_context = require('../context.js');
7
- const require_adapter_constants = require('../adapter/constants.js');
8
7
  const require_handler_utils = require('./utils.js');
9
- const require_handler_error = require('./error.js');
10
8
  const require_trace = require('../trace.js');
9
+ const require_adapter_constants = require('../adapter/constants.js');
10
+ const require_handler_error = require('./error.js');
11
11
  let deuri = require("deuri");
12
12
 
13
13
  //#region src/handler/fetch.ts
@@ -30,11 +30,17 @@ const decodeParams = (params) => {
30
30
  }
31
31
  return params;
32
32
  };
33
- const catchError = (context, handleError, afterResponse) => (error) => {
33
+ function finalizeError(context, handleError, afterResponse, error) {
34
34
  const resp = handleError(context, error);
35
- afterResponse?.(context);
35
+ if (!afterResponse) return resp;
36
+ if (resp instanceof Promise) return resp.then((r) => {
37
+ afterResponse(context);
38
+ return r;
39
+ });
40
+ afterResponse(context);
36
41
  return resp;
37
- };
42
+ }
43
+ const catchError = (context, handleError, afterResponse) => (error) => finalizeError(context, handleError, afterResponse, error);
38
44
  function findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS) {
39
45
  const path = context.path;
40
46
  if (hasWS) {
@@ -52,7 +58,8 @@ function findRoute(context, request, map, router, hasError, handleError, afterRe
52
58
  return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
53
59
  }
54
60
  }
55
- } else {
61
+ }
62
+ {
56
63
  const methodMap = map[request.method];
57
64
  let handler = methodMap?.[path];
58
65
  if (!handler) if (!strictPath && path.length > 1 && path.charCodeAt(path.length - 1) === 47) {
@@ -175,9 +182,7 @@ function createFetchHandler(app) {
175
182
  return await findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS);
176
183
  } catch (error) {
177
184
  for (let i = 0; i < traceLength; i++) requestReports[i].resolve(error);
178
- const r = handleError(context, error);
179
- afterResponse?.(context);
180
- return r;
185
+ return finalizeError(context, handleError, afterResponse, error);
181
186
  }
182
187
  };
183
188
  }
@@ -199,9 +204,7 @@ function createFetchHandler(app) {
199
204
  }
200
205
  return findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS);
201
206
  } catch (error) {
202
- const r = handleError(context, error);
203
- afterResponse?.(context);
204
- return r;
207
+ return finalizeError(context, handleError, afterResponse, error);
205
208
  }
206
209
  };
207
210
  return (request) => {
@@ -219,7 +222,7 @@ function createFetchHandler(app) {
219
222
  }
220
223
  return findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS);
221
224
  } catch (error) {
222
- return handleError(context, error);
225
+ return finalizeError(context, handleError, afterResponse, error);
223
226
  }
224
227
  };
225
228
  }
@@ -243,9 +246,7 @@ function createFetchHandler(app) {
243
246
  return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
244
247
  }
245
248
  } catch (error) {
246
- const r = handleError(context, error);
247
- afterResponse?.(context);
248
- return r;
249
+ return finalizeError(context, handleError, afterResponse, error);
249
250
  }
250
251
  }
251
252
  }
@@ -271,15 +272,9 @@ function createFetchHandler(app) {
271
272
  return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
272
273
  }
273
274
  } catch (error) {
274
- const r = handleError(context, error);
275
- afterResponse?.(context);
276
- return r;
277
- }
278
- if (hasError) {
279
- const r = handleError(context, new require_error.NotFound());
280
- afterResponse?.(context);
281
- return r;
275
+ return finalizeError(context, handleError, afterResponse, error);
282
276
  }
277
+ if (hasError) return finalizeError(context, handleError, afterResponse, new require_error.NotFound());
283
278
  afterResponse?.(context, 404);
284
279
  return notFound(context);
285
280
  };