@getsoda/core 0.0.0-stage → 0.1.1

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 (203) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +76 -2
  3. package/dist/app/app.d.ts +70 -0
  4. package/dist/app/app.d.ts.map +1 -0
  5. package/dist/app/app.js +173 -0
  6. package/dist/app/app.js.map +1 -0
  7. package/dist/app/hot.d.ts +33 -0
  8. package/dist/app/hot.d.ts.map +1 -0
  9. package/dist/app/hot.js +46 -0
  10. package/dist/app/hot.js.map +1 -0
  11. package/dist/app/index.d.ts +7 -0
  12. package/dist/app/index.d.ts.map +1 -0
  13. package/dist/app/index.js +6 -0
  14. package/dist/app/index.js.map +1 -0
  15. package/dist/di/container.d.ts +93 -0
  16. package/dist/di/container.d.ts.map +1 -0
  17. package/dist/di/container.js +364 -0
  18. package/dist/di/container.js.map +1 -0
  19. package/dist/di/context.d.ts +42 -0
  20. package/dist/di/context.d.ts.map +1 -0
  21. package/dist/di/context.js +36 -0
  22. package/dist/di/context.js.map +1 -0
  23. package/dist/di/decorators.d.ts +94 -0
  24. package/dist/di/decorators.d.ts.map +1 -0
  25. package/dist/di/decorators.js +58 -0
  26. package/dist/di/decorators.js.map +1 -0
  27. package/dist/di/errors.d.ts +30 -0
  28. package/dist/di/errors.d.ts.map +1 -0
  29. package/dist/di/errors.js +18 -0
  30. package/dist/di/errors.js.map +1 -0
  31. package/dist/di/graph.d.ts +68 -0
  32. package/dist/di/graph.d.ts.map +1 -0
  33. package/dist/di/graph.js +250 -0
  34. package/dist/di/graph.js.map +1 -0
  35. package/dist/di/index.d.ts +18 -0
  36. package/dist/di/index.d.ts.map +1 -0
  37. package/dist/di/index.js +11 -0
  38. package/dist/di/index.js.map +1 -0
  39. package/dist/di/lifecycle.d.ts +40 -0
  40. package/dist/di/lifecycle.d.ts.map +1 -0
  41. package/dist/di/lifecycle.js +57 -0
  42. package/dist/di/lifecycle.js.map +1 -0
  43. package/dist/di/provider.d.ts +121 -0
  44. package/dist/di/provider.d.ts.map +1 -0
  45. package/dist/di/provider.js +116 -0
  46. package/dist/di/provider.js.map +1 -0
  47. package/dist/di/token.d.ts +58 -0
  48. package/dist/di/token.d.ts.map +1 -0
  49. package/dist/di/token.js +39 -0
  50. package/dist/di/token.js.map +1 -0
  51. package/dist/di/utils.d.ts +23 -0
  52. package/dist/di/utils.d.ts.map +1 -0
  53. package/dist/di/utils.js +34 -0
  54. package/dist/di/utils.js.map +1 -0
  55. package/dist/di/visibility.d.ts +32 -0
  56. package/dist/di/visibility.d.ts.map +1 -0
  57. package/dist/di/visibility.js +77 -0
  58. package/dist/di/visibility.js.map +1 -0
  59. package/dist/http/arguments.d.ts +51 -0
  60. package/dist/http/arguments.d.ts.map +1 -0
  61. package/dist/http/arguments.js +48 -0
  62. package/dist/http/arguments.js.map +1 -0
  63. package/dist/http/body.d.ts +26 -0
  64. package/dist/http/body.d.ts.map +1 -0
  65. package/dist/http/body.js +66 -0
  66. package/dist/http/body.js.map +1 -0
  67. package/dist/http/context.d.ts +74 -0
  68. package/dist/http/context.d.ts.map +1 -0
  69. package/dist/http/context.js +64 -0
  70. package/dist/http/context.js.map +1 -0
  71. package/dist/http/decorators.d.ts +137 -0
  72. package/dist/http/decorators.d.ts.map +1 -0
  73. package/dist/http/decorators.js +127 -0
  74. package/dist/http/decorators.js.map +1 -0
  75. package/dist/http/enhancers.d.ts +121 -0
  76. package/dist/http/enhancers.d.ts.map +1 -0
  77. package/dist/http/enhancers.js +126 -0
  78. package/dist/http/enhancers.js.map +1 -0
  79. package/dist/http/errors.d.ts +24 -0
  80. package/dist/http/errors.d.ts.map +1 -0
  81. package/dist/http/errors.js +17 -0
  82. package/dist/http/errors.js.map +1 -0
  83. package/dist/http/exceptions.d.ts +260 -0
  84. package/dist/http/exceptions.d.ts.map +1 -0
  85. package/dist/http/exceptions.js +77 -0
  86. package/dist/http/exceptions.js.map +1 -0
  87. package/dist/http/index.d.ts +24 -0
  88. package/dist/http/index.d.ts.map +1 -0
  89. package/dist/http/index.js +13 -0
  90. package/dist/http/index.js.map +1 -0
  91. package/dist/http/parsers.d.ts +47 -0
  92. package/dist/http/parsers.d.ts.map +1 -0
  93. package/dist/http/parsers.js +55 -0
  94. package/dist/http/parsers.js.map +1 -0
  95. package/dist/http/pipeline.d.ts +61 -0
  96. package/dist/http/pipeline.d.ts.map +1 -0
  97. package/dist/http/pipeline.js +165 -0
  98. package/dist/http/pipeline.js.map +1 -0
  99. package/dist/http/response.d.ts +21 -0
  100. package/dist/http/response.d.ts.map +1 -0
  101. package/dist/http/response.js +52 -0
  102. package/dist/http/response.js.map +1 -0
  103. package/dist/http/routes.d.ts +54 -0
  104. package/dist/http/routes.d.ts.map +1 -0
  105. package/dist/http/routes.js +191 -0
  106. package/dist/http/routes.js.map +1 -0
  107. package/dist/http/schema.d.ts +61 -0
  108. package/dist/http/schema.d.ts.map +1 -0
  109. package/dist/http/schema.js +64 -0
  110. package/dist/http/schema.js.map +1 -0
  111. package/dist/http/types.d.ts +32 -0
  112. package/dist/http/types.d.ts.map +1 -0
  113. package/dist/http/types.js +5 -0
  114. package/dist/http/types.js.map +1 -0
  115. package/dist/index.d.ts +37 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +37 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/routing/compiler.d.ts +34 -0
  120. package/dist/routing/compiler.d.ts.map +1 -0
  121. package/dist/routing/compiler.js +336 -0
  122. package/dist/routing/compiler.js.map +1 -0
  123. package/dist/routing/decode.d.ts +24 -0
  124. package/dist/routing/decode.d.ts.map +1 -0
  125. package/dist/routing/decode.js +107 -0
  126. package/dist/routing/decode.js.map +1 -0
  127. package/dist/routing/dispatch.d.ts +68 -0
  128. package/dist/routing/dispatch.d.ts.map +1 -0
  129. package/dist/routing/dispatch.js +207 -0
  130. package/dist/routing/dispatch.js.map +1 -0
  131. package/dist/routing/errors.d.ts +24 -0
  132. package/dist/routing/errors.d.ts.map +1 -0
  133. package/dist/routing/errors.js +18 -0
  134. package/dist/routing/errors.js.map +1 -0
  135. package/dist/routing/index.d.ts +10 -0
  136. package/dist/routing/index.d.ts.map +1 -0
  137. package/dist/routing/index.js +8 -0
  138. package/dist/routing/index.js.map +1 -0
  139. package/dist/routing/path.d.ts +45 -0
  140. package/dist/routing/path.d.ts.map +1 -0
  141. package/dist/routing/path.js +182 -0
  142. package/dist/routing/path.js.map +1 -0
  143. package/dist/routing/shape.d.ts +65 -0
  144. package/dist/routing/shape.d.ts.map +1 -0
  145. package/dist/routing/shape.js +148 -0
  146. package/dist/routing/shape.js.map +1 -0
  147. package/dist/routing/types.d.ts +81 -0
  148. package/dist/routing/types.d.ts.map +1 -0
  149. package/dist/routing/types.js +19 -0
  150. package/dist/routing/types.js.map +1 -0
  151. package/dist/utils/name.d.ts +15 -0
  152. package/dist/utils/name.d.ts.map +1 -0
  153. package/dist/utils/name.js +15 -0
  154. package/dist/utils/name.js.map +1 -0
  155. package/dist/utils/object.d.ts +14 -0
  156. package/dist/utils/object.d.ts.map +1 -0
  157. package/dist/utils/object.js +14 -0
  158. package/dist/utils/object.js.map +1 -0
  159. package/dist/utils/promise.d.ts +9 -0
  160. package/dist/utils/promise.d.ts.map +1 -0
  161. package/dist/utils/promise.js +9 -0
  162. package/dist/utils/promise.js.map +1 -0
  163. package/package.json +55 -4
  164. package/src/app/app.ts +252 -0
  165. package/src/app/hot.ts +60 -0
  166. package/src/app/index.ts +7 -0
  167. package/src/di/container.ts +552 -0
  168. package/src/di/context.ts +74 -0
  169. package/src/di/decorators.ts +130 -0
  170. package/src/di/errors.ts +46 -0
  171. package/src/di/graph.ts +353 -0
  172. package/src/di/index.ts +18 -0
  173. package/src/di/lifecycle.ts +83 -0
  174. package/src/di/provider.ts +231 -0
  175. package/src/di/token.ts +73 -0
  176. package/src/di/utils.ts +44 -0
  177. package/src/di/visibility.ts +107 -0
  178. package/src/http/arguments.ts +93 -0
  179. package/src/http/body.ts +81 -0
  180. package/src/http/context.ts +118 -0
  181. package/src/http/decorators.ts +262 -0
  182. package/src/http/enhancers.ts +244 -0
  183. package/src/http/errors.ts +35 -0
  184. package/src/http/exceptions.ts +109 -0
  185. package/src/http/index.ts +58 -0
  186. package/src/http/parsers.ts +110 -0
  187. package/src/http/pipeline.ts +247 -0
  188. package/src/http/response.ts +63 -0
  189. package/src/http/routes.ts +287 -0
  190. package/src/http/schema.ts +132 -0
  191. package/src/http/types.ts +44 -0
  192. package/src/index.ts +37 -0
  193. package/src/routing/compiler.ts +453 -0
  194. package/src/routing/decode.ts +134 -0
  195. package/src/routing/dispatch.ts +339 -0
  196. package/src/routing/errors.ts +30 -0
  197. package/src/routing/index.ts +10 -0
  198. package/src/routing/path.ts +244 -0
  199. package/src/routing/shape.ts +185 -0
  200. package/src/routing/types.ts +88 -0
  201. package/src/utils/name.ts +16 -0
  202. package/src/utils/object.ts +14 -0
  203. package/src/utils/promise.ts +10 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 falsea3
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,77 @@
1
- # Temporary Holding Version
1
+ # Soda
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A class-based web framework for [Bun](https://bun.sh): modules, dependency injection and decorators like [Nest](https://nestjs.com), running on Bun's native router.
4
+
5
+ - **Standard decorators.** TC39 decorators, no `experimentalDecorators`, no `reflect-metadata`.
6
+ - **Native routing.** Routes compile into `Bun.serve({ routes })`; a route without guards adds ~0.1 ns to calling the handler.
7
+ - **Modules and DI.** `inject()`, providers, async factories, global and dynamic modules, lifecycle hooks. Graph errors are reported at startup with the full resolution chain.
8
+ - **Typed requests.** Path parameters are typed from the route path; bodies are validated with any [Standard Schema](https://standardschema.dev) library (zod, valibot, arktype).
9
+ - **Request pipeline.** Guards, interceptors and exception filters, as classes, instances or functions.
10
+ - **Lifecycle.** Graceful shutdown that drains requests before destroying services, shutdown signals, `bun --hot` support.
11
+
12
+ > Soda is in early development (0.x): the API may change between minor versions.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ bun add @getsoda/core
18
+ ```
19
+
20
+ Requires Bun 1.4 or later. No TypeScript flags are needed for decorators.
21
+
22
+ ## Quick start
23
+
24
+ ```ts
25
+ import { Controller, Get, Module, Post, body, createApp, inject, int, param } from '@getsoda/core'
26
+ import type { Context } from '@getsoda/core'
27
+ import { z } from 'zod'
28
+
29
+ const CreateUser = z.object({ name: z.string().min(1) })
30
+
31
+ class UsersService {
32
+ readonly #users = new Map<number, { id: number; name: string }>()
33
+
34
+ find(id: number) {
35
+ return this.#users.get(id)
36
+ }
37
+
38
+ create(name: string) {
39
+ const user = { id: this.#users.size + 1, name }
40
+
41
+ this.#users.set(user.id, user)
42
+
43
+ return user
44
+ }
45
+ }
46
+
47
+ @Controller('users')
48
+ class UsersController {
49
+ readonly #users = inject(UsersService)
50
+
51
+ // Ready values, Nest style
52
+ @Get(':id', [param('id', int())])
53
+ findOne(id: number) {
54
+ return this.#users.find(id)
55
+ }
56
+
57
+ // Or read from the context where needed
58
+ @Post()
59
+ async create(ctx: Context) {
60
+ const { name } = await ctx.body(CreateUser)
61
+
62
+ return this.#users.create(name)
63
+ }
64
+ }
65
+
66
+ @Module({ providers: [UsersService], controllers: [UsersController] })
67
+ class AppModule {}
68
+
69
+ const app = await createApp(AppModule)
70
+
71
+ app.enableShutdownSignals()
72
+ await app.listen(3000)
73
+ ```
74
+
75
+ ## License
76
+
77
+ [MIT](./LICENSE)
@@ -0,0 +1,70 @@
1
+ /**
2
+ * @module
3
+ * The application: container, routes and server, started and stopped together.
4
+ *
5
+ * ```ts
6
+ * const app = await createApp(AppModule, { prefix: '/api' })
7
+ *
8
+ * app.enableShutdownSignals()
9
+ * await app.listen(3000)
10
+ * ```
11
+ *
12
+ * Startup creates the container (every singleton, every `onInit`), then the
13
+ * guards, interceptors and filters (their `onInit` too), and only then accepts
14
+ * requests.
15
+ *
16
+ * Shutdown stops accepting requests first and waits for the ones in flight,
17
+ * then runs `onDestroy` (guards and the like, then the container). Nest closes
18
+ * the server after `onModuleDestroy`, so requests still arrive while services
19
+ * are being destroyed; here they cannot.
20
+ */
21
+ import type { Container, ContainerOptions, ModuleImport } from '../di/index.ts';
22
+ import type { ControllerRoutesOptions } from '../http/index.ts';
23
+ import type { CompiledRoutes, CompileOptions } from '../routing/index.ts';
24
+ /**
25
+ * Options of `createApp`.
26
+ */
27
+ export interface AppOptions extends ContainerOptions, ControllerRoutesOptions, CompileOptions {
28
+ }
29
+ /**
30
+ * Where to listen. `port: 0` picks a free port.
31
+ */
32
+ export interface ListenOptions {
33
+ readonly port?: number;
34
+ readonly hostname?: string;
35
+ }
36
+ /**
37
+ * A created application.
38
+ */
39
+ export interface App {
40
+ readonly container: Container;
41
+ /** Routes for `Bun.serve()`, when serving them yourself instead of calling `listen()`. */
42
+ readonly routes: CompiledRoutes;
43
+ /** The server once `listen()` resolved. */
44
+ readonly server: Bun.Server<undefined> | undefined;
45
+ /**
46
+ * Starts serving. Under `bun --hot`, a new version of the application
47
+ * listening on the same port takes the server over from the previous one,
48
+ * which is then destroyed (its server is not stopped: it is shared).
49
+ */
50
+ listen(options?: number | ListenOptions): Promise<Bun.Server<undefined>>;
51
+ /**
52
+ * Graceful shutdown: refuses new requests, waits for those in flight, then
53
+ * runs `onDestroy` hooks. Safe to call more than once, even from a hook.
54
+ */
55
+ close(): Promise<void>;
56
+ /**
57
+ * Closes the application on `SIGTERM` and `SIGINT` (or `signals`), then lets
58
+ * the signal terminate the process. Off by default, as Nest's `enableShutdownHooks()`.
59
+ */
60
+ enableShutdownSignals(signals?: readonly NodeJS.Signals[]): this;
61
+ }
62
+ /**
63
+ * Creates the container and the routes, and runs every `onInit` hook.
64
+ *
65
+ * If anything fails, what was created is destroyed and the error is rethrown;
66
+ * if destroying fails too, everything comes as one `AggregateError`, startup
67
+ * error first, as `createContainer` does.
68
+ */
69
+ export declare const createApp: (root: ModuleImport, options?: AppOptions) => Promise<App>;
70
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/app/app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAG/E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAGzE;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,gBAAgB,EAAE,uBAAuB,EAAE,cAAc;CAAG;AAEhG;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAKD;;GAEG;AACH,MAAM,WAAW,GAAG;IAClB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,SAAS,CAAA;IAClD;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAA;IACxE;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB;;;OAGG;IACH,qBAAqB,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAA;CACjE;AAyJD;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,SAAgB,YAAY,YAAW,UAAU,KAAQ,OAAO,CAAC,GAAG,CAoBzF,CAAA"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * @module
3
+ * The application: container, routes and server, started and stopped together.
4
+ *
5
+ * ```ts
6
+ * const app = await createApp(AppModule, { prefix: '/api' })
7
+ *
8
+ * app.enableShutdownSignals()
9
+ * await app.listen(3000)
10
+ * ```
11
+ *
12
+ * Startup creates the container (every singleton, every `onInit`), then the
13
+ * guards, interceptors and filters (their `onInit` too), and only then accepts
14
+ * requests.
15
+ *
16
+ * Shutdown stops accepting requests first and waits for the ones in flight,
17
+ * then runs `onDestroy` (guards and the like, then the container). Nest closes
18
+ * the server after `onModuleDestroy`, so requests still arrive while services
19
+ * are being destroyed; here they cannot.
20
+ */
21
+ import { createContainer } from '../di/index.js';
22
+ import { destroyAll, initializeAll } from '../di/lifecycle.js';
23
+ import { buildRoutes } from '../http/index.js';
24
+ import { compileRoutes } from '../routing/index.js';
25
+ import { release, takeOver } from './hot.js';
26
+ /** Signals `enableShutdownSignals()` listens to by default. */
27
+ const DEFAULT_SIGNALS = ['SIGTERM', 'SIGINT'];
28
+ class Application {
29
+ container;
30
+ routes;
31
+ #server;
32
+ /** Set when a new version took the server over: it must not be stopped. */
33
+ #handedOver = false;
34
+ #closing;
35
+ #enhancers;
36
+ #signals = new Map();
37
+ constructor(container, routes, enhancers) {
38
+ this.container = container;
39
+ this.routes = routes;
40
+ this.#enhancers = enhancers;
41
+ }
42
+ get server() {
43
+ return this.#server;
44
+ }
45
+ async listen(options = {}) {
46
+ if (this.#closing !== undefined) {
47
+ throw new Error('Cannot listen: the application is closed');
48
+ }
49
+ if (this.#server !== undefined) {
50
+ throw new Error(`The application already listens on ${this.#server.url.href}`);
51
+ }
52
+ const { port = 0, hostname } = typeof options === 'number' ? { port: options } : options;
53
+ const server = Bun.serve({ port, hostname, ...this.routes });
54
+ this.#server = server;
55
+ if (server.port !== undefined) {
56
+ await takeOver(server.port, this);
57
+ }
58
+ return server;
59
+ }
60
+ /** Destroys this version without stopping the server a newer version now uses. */
61
+ handOver() {
62
+ this.#handedOver = true;
63
+ return this.close();
64
+ }
65
+ close() {
66
+ if (this.#closing === undefined) {
67
+ // Assigned before anything runs, so a hook calling close() gets this promise.
68
+ const { promise, resolve, reject } = Promise.withResolvers();
69
+ this.#closing = promise;
70
+ this.#shutdown().then(resolve, reject);
71
+ }
72
+ return this.#closing;
73
+ }
74
+ enableShutdownSignals(signals = DEFAULT_SIGNALS) {
75
+ for (const signal of signals) {
76
+ if (this.#signals.has(signal)) {
77
+ continue;
78
+ }
79
+ const listener = () => {
80
+ // A second signal while closing is ignored: the first one finishes the job.
81
+ if (this.#closing !== undefined) {
82
+ return;
83
+ }
84
+ this.close().then(() => {
85
+ this.#removeSignalListeners();
86
+ // Terminate as the signal would have, exit code included.
87
+ process.kill(process.pid, signal);
88
+ }, (error) => {
89
+ console.error('Error during shutdown', error);
90
+ process.exit(1);
91
+ });
92
+ };
93
+ this.#signals.set(signal, listener);
94
+ process.on(signal, listener);
95
+ }
96
+ return this;
97
+ }
98
+ async #shutdown() {
99
+ const server = this.#server;
100
+ try {
101
+ if (server !== undefined && !this.#handedOver) {
102
+ await server.stop();
103
+ }
104
+ await destroyEverything(this.#enhancers, this.container);
105
+ }
106
+ finally {
107
+ // Whatever happened, signals get their default behaviour back.
108
+ this.#removeSignalListeners();
109
+ if (server?.port !== undefined) {
110
+ release(server.port, this);
111
+ }
112
+ }
113
+ }
114
+ #removeSignalListeners() {
115
+ for (const [signal, listener] of this.#signals) {
116
+ process.off(signal, listener);
117
+ }
118
+ this.#signals.clear();
119
+ }
120
+ }
121
+ const errorsOf = (error) => (error instanceof AggregateError ? error.errors : [error]);
122
+ /**
123
+ * Destroys guards and the like, then the container; every hook runs.
124
+ * One failure is rethrown as is, several as an `AggregateError`.
125
+ */
126
+ const destroyEverything = async (enhancers, container) => {
127
+ const errors = [];
128
+ try {
129
+ await destroyAll(enhancers);
130
+ }
131
+ catch (error) {
132
+ errors.push(...errorsOf(error));
133
+ }
134
+ try {
135
+ await container.close();
136
+ }
137
+ catch (error) {
138
+ errors.push(...errorsOf(error));
139
+ }
140
+ if (errors.length === 1) {
141
+ throw errors[0];
142
+ }
143
+ if (errors.length > 1) {
144
+ throw new AggregateError(errors, `${errors.length} onDestroy hooks failed`);
145
+ }
146
+ };
147
+ /**
148
+ * Creates the container and the routes, and runs every `onInit` hook.
149
+ *
150
+ * If anything fails, what was created is destroyed and the error is rethrown;
151
+ * if destroying fails too, everything comes as one `AggregateError`, startup
152
+ * error first, as `createContainer` does.
153
+ */
154
+ export const createApp = async (root, options = {}) => {
155
+ const container = await createContainer(root, options);
156
+ let enhancers = [];
157
+ try {
158
+ const built = buildRoutes(container, options);
159
+ enhancers = built.enhancers;
160
+ await initializeAll(enhancers);
161
+ return new Application(container, compileRoutes(built.routes, options), enhancers);
162
+ }
163
+ catch (error) {
164
+ try {
165
+ await destroyEverything(enhancers, container);
166
+ }
167
+ catch (destroyError) {
168
+ throw new AggregateError([error, ...errorsOf(destroyError)], 'Startup failed, and onDestroy hooks failed while rolling back');
169
+ }
170
+ throw error;
171
+ }
172
+ };
173
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/app/app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @module
3
+ * Hot reload support for `bun --hot`.
4
+ *
5
+ * Under `--hot`, Bun re-evaluates the changed modules in the same process:
6
+ * `globalThis` survives, a second `Bun.serve()` on the same port reuses the
7
+ * running server instead of failing, and there is no hook telling the old
8
+ * module it is unloaded (`import.meta.hot` does not exist on the server).
9
+ * So the previous application, with its timers and connections, would stay
10
+ * alive forever.
11
+ *
12
+ * Applications that listen are registered here by port, in `globalThis`; a new
13
+ * application listening on a port takes it over and destroys the previous one
14
+ * without stopping the server they share. Without `--hot`, two applications
15
+ * cannot listen on the same port, so this never happens.
16
+ *
17
+ * Requests the old version is still serving at that moment may meet its
18
+ * destroyed services: a development-only window, as with any hot reload.
19
+ */
20
+ /** What the registry needs from an application. */
21
+ export interface HotApp {
22
+ /** Destroys the application without stopping its server. */
23
+ handOver(): Promise<void>;
24
+ }
25
+ /**
26
+ * Registers `app` as listening on `port`, destroying the application that listened there before.
27
+ */
28
+ export declare const takeOver: (port: number, app: HotApp) => Promise<void>;
29
+ /**
30
+ * Unregisters `app` from `port`, unless another application already took it over.
31
+ */
32
+ export declare const release: (port: number, app: HotApp) => void;
33
+ //# sourceMappingURL=hot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hot.d.ts","sourceRoot":"","sources":["../../src/app/hot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,mDAAmD;AACnD,MAAM,WAAW,MAAM;IACrB,4DAA4D;IAC5D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B;AAYD;;GAEG;AACH,eAAO,MAAM,QAAQ,SAAgB,MAAM,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CAStE,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,OAAO,SAAU,MAAM,OAAO,MAAM,KAAG,IAMnD,CAAA"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @module
3
+ * Hot reload support for `bun --hot`.
4
+ *
5
+ * Under `--hot`, Bun re-evaluates the changed modules in the same process:
6
+ * `globalThis` survives, a second `Bun.serve()` on the same port reuses the
7
+ * running server instead of failing, and there is no hook telling the old
8
+ * module it is unloaded (`import.meta.hot` does not exist on the server).
9
+ * So the previous application, with its timers and connections, would stay
10
+ * alive forever.
11
+ *
12
+ * Applications that listen are registered here by port, in `globalThis`; a new
13
+ * application listening on a port takes it over and destroys the previous one
14
+ * without stopping the server they share. Without `--hot`, two applications
15
+ * cannot listen on the same port, so this never happens.
16
+ *
17
+ * Requests the old version is still serving at that moment may meet its
18
+ * destroyed services: a development-only window, as with any hot reload.
19
+ */
20
+ const REGISTRY = Symbol.for('soda.app.listening');
21
+ const registry = () => {
22
+ const holder = globalThis;
23
+ holder[REGISTRY] ??= new Map();
24
+ return holder[REGISTRY];
25
+ };
26
+ /**
27
+ * Registers `app` as listening on `port`, destroying the application that listened there before.
28
+ */
29
+ export const takeOver = async (port, app) => {
30
+ const apps = registry();
31
+ const previous = apps.get(port);
32
+ apps.set(port, app);
33
+ if (previous !== undefined && previous !== app) {
34
+ await previous.handOver();
35
+ }
36
+ };
37
+ /**
38
+ * Unregisters `app` from `port`, unless another application already took it over.
39
+ */
40
+ export const release = (port, app) => {
41
+ const apps = registry();
42
+ if (apps.get(port) === app) {
43
+ apps.delete(port);
44
+ }
45
+ };
46
+ //# sourceMappingURL=hot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hot.js","sourceRoot":"","sources":["../../src/app/hot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAA;AAEjD,MAAM,QAAQ,GAAG,GAAwB,EAAE;IACzC,MAAM,MAAM,GAAG,UAAsE,CAAA;IAErF,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,GAAG,EAAE,CAAA;IAE9B,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAA;AACzB,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAAE,IAAY,EAAE,GAAW,EAAiB,EAAE;IACzE,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAA;IACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAE/B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAEnB,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;QAC/C,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAA;IAC3B,CAAC;AACH,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,GAAW,EAAQ,EAAE;IACzD,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAA;IAEvB,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACnB,CAAC;AACH,CAAC,CAAA"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @module
3
+ * The application: container, routes and server, started and stopped together.
4
+ */
5
+ export { createApp } from './app.ts';
6
+ export type { App, AppOptions, ListenOptions } from './app.ts';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/app/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @module
3
+ * The application: container, routes and server, started and stopped together.
4
+ */
5
+ export { createApp } from './app.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/app/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @module
3
+ * The container: creates every singleton at startup, runs lifecycle hooks, resolves tokens.
4
+ *
5
+ * Startup, in `createContainer`:
6
+ *
7
+ * 1. Build the module graph and validate it (awaiting `Promise<DynamicModule>` imports).
8
+ * 2. Run singleton factories, awaiting async ones. Their dependencies are
9
+ * declared in `inject: [...]`, so the async part of the graph is static.
10
+ * 3. Create every other singleton (providers, controllers, module classes),
11
+ * synchronously; `inject()` resolves dependencies, creating them on demand.
12
+ * 4. Call `onInit` on everything created, dependencies first.
13
+ *
14
+ * Any failure destroys what was created, in reverse order, and rejects.
15
+ * Nothing is resolved lazily on the request path: once the container is
16
+ * returned, every singleton exists.
17
+ */
18
+ import type { ModuleClass, ModuleImport } from './decorators.ts';
19
+ import type { Provider } from './provider.ts';
20
+ import type { Constructor, Token } from './token.ts';
21
+ /**
22
+ * Options of `createContainer`.
23
+ */
24
+ export interface ContainerOptions {
25
+ /**
26
+ * Providers replacing those of the same token everywhere in the graph, for tests.
27
+ * An override that matches no provider is an error.
28
+ *
29
+ * ```ts
30
+ * await createContainer(AppModule, { overrides: [provide(Database, { useValue: fakeDatabase })] })
31
+ * ```
32
+ */
33
+ readonly overrides?: readonly Provider[];
34
+ }
35
+ /**
36
+ * Options of `container.get()` and `container.runInContext()`.
37
+ */
38
+ export interface ResolveOptions {
39
+ /** Module to resolve from, instead of the root module. */
40
+ readonly from?: ModuleClass;
41
+ }
42
+ /**
43
+ * A controller created by the container, with the module that owns it.
44
+ */
45
+ export interface ControllerEntry {
46
+ readonly module: ModuleClass;
47
+ readonly controller: Constructor<unknown>;
48
+ readonly instance: unknown;
49
+ /**
50
+ * Runs `fn` where `inject()` resolves from the controller's module, as Nest
51
+ * resolves guards and interceptors from the module of their controller.
52
+ */
53
+ readonly runInContext: <R>(fn: () => R) => R;
54
+ }
55
+ /**
56
+ * A started container.
57
+ */
58
+ export interface Container {
59
+ /** Resolves `token` as `inject()` would inside the root module, or inside `options.from`. */
60
+ get<T>(token: Token<T>, options?: ResolveOptions & {
61
+ readonly optional?: false;
62
+ }): T;
63
+ get<T>(token: Token<T>, options: ResolveOptions & {
64
+ readonly optional: true;
65
+ }): T | undefined;
66
+ /**
67
+ * Runs `fn` where `inject()` works, as if it were created by the root module
68
+ * (or `options.from`): for functional guards, middleware and the like.
69
+ */
70
+ runInContext<R>(fn: () => R, options?: ResolveOptions): R;
71
+ /** Every controller, in module order. */
72
+ readonly controllers: readonly ControllerEntry[];
73
+ /**
74
+ * Calls `onDestroy` in reverse creation order, then releases every instance.
75
+ * Calling it again, even from an `onDestroy` hook, returns the same promise.
76
+ */
77
+ close(): Promise<void>;
78
+ }
79
+ /**
80
+ * Builds the graph rooted at `root`, creates every singleton and runs `onInit` hooks.
81
+ *
82
+ * ```ts
83
+ * const container = await createContainer(AppModule)
84
+ * const users = container.get(UsersService)
85
+ * await container.close()
86
+ * ```
87
+ *
88
+ * Rejects with `DiError` on graph problems. If startup fails after something was
89
+ * created, `onDestroy` runs for it first and the startup error is rethrown; if
90
+ * hooks fail too, everything is rethrown as one `AggregateError`, startup error first.
91
+ */
92
+ export declare const createContainer: (root: ModuleImport, options?: ContainerOptions) => Promise<Container>;
93
+ //# sourceMappingURL=container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/di/container.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAKhE,OAAO,KAAK,EAAE,QAAQ,EAAsB,MAAM,eAAe,CAAA;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAIpD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAA;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAA;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IACzC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,6FAA6F;IAC7F,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,CAAC,CAAA;IACpF,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG;QAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAA;KAAE,GAAG,CAAC,GAAG,SAAS,CAAA;IAC7F;;;OAGG;IACH,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,CAAC,CAAA;IACzD,yCAAyC;IACzC,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAA;IAChD;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAwaD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,SAAgB,YAAY,YAAW,gBAAgB,KAAQ,OAAO,CAAC,SAAS,CA0B3G,CAAA"}