@buenojs/bueno 0.8.4 → 0.8.5

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 (218) hide show
  1. package/README.md +136 -16
  2. package/dist/cli/{index.js → bin.js} +412 -331
  3. package/dist/container/index.js +250 -0
  4. package/dist/context/index.js +219 -0
  5. package/dist/database/index.js +493 -0
  6. package/dist/frontend/index.js +7697 -0
  7. package/dist/health/index.js +364 -0
  8. package/dist/i18n/index.js +345 -0
  9. package/dist/index.js +11043 -6482
  10. package/dist/jobs/index.js +819 -0
  11. package/dist/lock/index.js +367 -0
  12. package/dist/logger/index.js +281 -0
  13. package/dist/metrics/index.js +289 -0
  14. package/dist/middleware/index.js +77 -0
  15. package/dist/migrations/index.js +571 -0
  16. package/dist/modules/index.js +3346 -0
  17. package/dist/notification/index.js +484 -0
  18. package/dist/observability/index.js +331 -0
  19. package/dist/openapi/index.js +776 -0
  20. package/dist/orm/index.js +1356 -0
  21. package/dist/router/index.js +886 -0
  22. package/dist/rpc/index.js +691 -0
  23. package/dist/schema/index.js +400 -0
  24. package/dist/telemetry/index.js +595 -0
  25. package/dist/template/index.js +640 -0
  26. package/dist/templates/index.js +640 -0
  27. package/dist/testing/index.js +1111 -0
  28. package/dist/types/index.js +60 -0
  29. package/package.json +121 -27
  30. package/src/cache/index.ts +2 -1
  31. package/src/cli/bin.ts +2 -2
  32. package/src/cli/commands/build.ts +183 -165
  33. package/src/cli/commands/dev.ts +96 -89
  34. package/src/cli/commands/generate.ts +142 -111
  35. package/src/cli/commands/help.ts +20 -16
  36. package/src/cli/commands/index.ts +3 -6
  37. package/src/cli/commands/migration.ts +124 -105
  38. package/src/cli/commands/new.ts +294 -232
  39. package/src/cli/commands/start.ts +81 -79
  40. package/src/cli/core/args.ts +68 -50
  41. package/src/cli/core/console.ts +89 -95
  42. package/src/cli/core/index.ts +4 -4
  43. package/src/cli/core/prompt.ts +65 -62
  44. package/src/cli/core/spinner.ts +23 -20
  45. package/src/cli/index.ts +46 -38
  46. package/src/cli/templates/database/index.ts +37 -18
  47. package/src/cli/templates/database/mysql.ts +3 -3
  48. package/src/cli/templates/database/none.ts +2 -2
  49. package/src/cli/templates/database/postgresql.ts +3 -3
  50. package/src/cli/templates/database/sqlite.ts +3 -3
  51. package/src/cli/templates/deploy.ts +29 -26
  52. package/src/cli/templates/docker.ts +41 -30
  53. package/src/cli/templates/frontend/index.ts +33 -15
  54. package/src/cli/templates/frontend/none.ts +2 -2
  55. package/src/cli/templates/frontend/react.ts +18 -18
  56. package/src/cli/templates/frontend/solid.ts +15 -15
  57. package/src/cli/templates/frontend/svelte.ts +17 -17
  58. package/src/cli/templates/frontend/vue.ts +15 -15
  59. package/src/cli/templates/generators/index.ts +29 -29
  60. package/src/cli/templates/generators/types.ts +21 -21
  61. package/src/cli/templates/index.ts +6 -6
  62. package/src/cli/templates/project/api.ts +37 -36
  63. package/src/cli/templates/project/default.ts +25 -25
  64. package/src/cli/templates/project/fullstack.ts +28 -26
  65. package/src/cli/templates/project/index.ts +55 -16
  66. package/src/cli/templates/project/minimal.ts +17 -12
  67. package/src/cli/templates/project/types.ts +10 -5
  68. package/src/cli/templates/project/website.ts +14 -14
  69. package/src/cli/utils/fs.ts +55 -41
  70. package/src/cli/utils/index.ts +3 -3
  71. package/src/cli/utils/strings.ts +47 -33
  72. package/src/cli/utils/version.ts +14 -8
  73. package/src/config/env-validation.ts +100 -0
  74. package/src/config/env.ts +169 -41
  75. package/src/config/index.ts +28 -20
  76. package/src/config/loader.ts +25 -16
  77. package/src/config/merge.ts +21 -10
  78. package/src/config/types.ts +545 -25
  79. package/src/config/validation.ts +215 -7
  80. package/src/container/forward-ref.ts +22 -22
  81. package/src/container/index.ts +34 -12
  82. package/src/context/index.ts +11 -1
  83. package/src/database/index.ts +7 -190
  84. package/src/database/orm/builder.ts +457 -0
  85. package/src/database/orm/casts/index.ts +130 -0
  86. package/src/database/orm/casts/types.ts +25 -0
  87. package/src/database/orm/compiler.ts +304 -0
  88. package/src/database/orm/hooks/index.ts +114 -0
  89. package/src/database/orm/index.ts +61 -0
  90. package/src/database/orm/model-registry.ts +59 -0
  91. package/src/database/orm/model.ts +821 -0
  92. package/src/database/orm/relationships/base.ts +146 -0
  93. package/src/database/orm/relationships/belongs-to-many.ts +179 -0
  94. package/src/database/orm/relationships/belongs-to.ts +56 -0
  95. package/src/database/orm/relationships/has-many.ts +45 -0
  96. package/src/database/orm/relationships/has-one.ts +41 -0
  97. package/src/database/orm/relationships/index.ts +11 -0
  98. package/src/database/orm/scopes/index.ts +55 -0
  99. package/src/events/__tests__/event-system.test.ts +235 -0
  100. package/src/events/config.ts +238 -0
  101. package/src/events/example-usage.ts +185 -0
  102. package/src/events/index.ts +278 -0
  103. package/src/events/manager.ts +385 -0
  104. package/src/events/registry.ts +182 -0
  105. package/src/events/types.ts +124 -0
  106. package/src/frontend/api-routes.ts +65 -23
  107. package/src/frontend/bundler.ts +76 -34
  108. package/src/frontend/console-client.ts +2 -2
  109. package/src/frontend/console-stream.ts +94 -38
  110. package/src/frontend/dev-server.ts +94 -46
  111. package/src/frontend/file-router.ts +61 -19
  112. package/src/frontend/frameworks/index.ts +37 -10
  113. package/src/frontend/frameworks/react.ts +10 -8
  114. package/src/frontend/frameworks/solid.ts +11 -9
  115. package/src/frontend/frameworks/svelte.ts +15 -9
  116. package/src/frontend/frameworks/vue.ts +13 -11
  117. package/src/frontend/hmr-client.ts +12 -10
  118. package/src/frontend/hmr.ts +146 -103
  119. package/src/frontend/index.ts +14 -5
  120. package/src/frontend/islands.ts +41 -22
  121. package/src/frontend/isr.ts +59 -37
  122. package/src/frontend/layout.ts +36 -21
  123. package/src/frontend/ssr/react.ts +74 -27
  124. package/src/frontend/ssr/solid.ts +54 -20
  125. package/src/frontend/ssr/svelte.ts +48 -14
  126. package/src/frontend/ssr/vue.ts +50 -18
  127. package/src/frontend/ssr.ts +83 -39
  128. package/src/frontend/types.ts +91 -56
  129. package/src/health/index.ts +21 -9
  130. package/src/i18n/engine.ts +305 -0
  131. package/src/i18n/index.ts +38 -0
  132. package/src/i18n/loader.ts +218 -0
  133. package/src/i18n/middleware.ts +164 -0
  134. package/src/i18n/negotiator.ts +162 -0
  135. package/src/i18n/types.ts +158 -0
  136. package/src/index.ts +179 -27
  137. package/src/jobs/drivers/memory.ts +315 -0
  138. package/src/jobs/drivers/redis.ts +459 -0
  139. package/src/jobs/index.ts +30 -0
  140. package/src/jobs/queue.ts +281 -0
  141. package/src/jobs/types.ts +295 -0
  142. package/src/jobs/worker.ts +380 -0
  143. package/src/logger/index.ts +1 -3
  144. package/src/logger/transports/index.ts +62 -22
  145. package/src/metrics/index.ts +25 -16
  146. package/src/migrations/index.ts +9 -0
  147. package/src/modules/filters.ts +13 -17
  148. package/src/modules/guards.ts +49 -26
  149. package/src/modules/index.ts +409 -298
  150. package/src/modules/interceptors.ts +58 -20
  151. package/src/modules/lazy.ts +11 -19
  152. package/src/modules/lifecycle.ts +15 -7
  153. package/src/modules/metadata.ts +15 -5
  154. package/src/modules/pipes.ts +94 -72
  155. package/src/notification/channels/base.ts +68 -0
  156. package/src/notification/channels/email.ts +105 -0
  157. package/src/notification/channels/push.ts +104 -0
  158. package/src/notification/channels/sms.ts +105 -0
  159. package/src/notification/channels/whatsapp.ts +104 -0
  160. package/src/notification/index.ts +48 -0
  161. package/src/notification/service.ts +354 -0
  162. package/src/notification/types.ts +344 -0
  163. package/src/observability/__tests__/observability.test.ts +483 -0
  164. package/src/observability/breadcrumbs.ts +114 -0
  165. package/src/observability/index.ts +136 -0
  166. package/src/observability/interceptor.ts +85 -0
  167. package/src/observability/service.ts +303 -0
  168. package/src/observability/trace.ts +37 -0
  169. package/src/observability/types.ts +196 -0
  170. package/src/openapi/__tests__/decorators.test.ts +335 -0
  171. package/src/openapi/__tests__/document-builder.test.ts +285 -0
  172. package/src/openapi/__tests__/route-scanner.test.ts +334 -0
  173. package/src/openapi/__tests__/schema-generator.test.ts +275 -0
  174. package/src/openapi/decorators.ts +328 -0
  175. package/src/openapi/document-builder.ts +274 -0
  176. package/src/openapi/index.ts +112 -0
  177. package/src/openapi/metadata.ts +112 -0
  178. package/src/openapi/route-scanner.ts +289 -0
  179. package/src/openapi/schema-generator.ts +256 -0
  180. package/src/openapi/swagger-module.ts +166 -0
  181. package/src/openapi/types.ts +398 -0
  182. package/src/orm/index.ts +10 -0
  183. package/src/rpc/index.ts +3 -1
  184. package/src/schema/index.ts +9 -0
  185. package/src/security/index.ts +15 -6
  186. package/src/ssg/index.ts +9 -8
  187. package/src/telemetry/index.ts +76 -22
  188. package/src/template/index.ts +7 -0
  189. package/src/templates/engine.ts +224 -0
  190. package/src/templates/index.ts +9 -0
  191. package/src/templates/loader.ts +331 -0
  192. package/src/templates/renderers/markdown.ts +212 -0
  193. package/src/templates/renderers/simple.ts +269 -0
  194. package/src/templates/types.ts +154 -0
  195. package/src/testing/index.ts +100 -27
  196. package/src/types/optional-deps.d.ts +347 -187
  197. package/src/validation/index.ts +92 -2
  198. package/src/validation/schemas.ts +536 -0
  199. package/tests/integration/fullstack.test.ts +4 -4
  200. package/tests/unit/database.test.ts +2 -72
  201. package/tests/unit/env-validation.test.ts +166 -0
  202. package/tests/unit/events.test.ts +910 -0
  203. package/tests/unit/i18n.test.ts +455 -0
  204. package/tests/unit/jobs.test.ts +493 -0
  205. package/tests/unit/notification.test.ts +988 -0
  206. package/tests/unit/observability.test.ts +453 -0
  207. package/tests/unit/orm/builder.test.ts +323 -0
  208. package/tests/unit/orm/casts.test.ts +179 -0
  209. package/tests/unit/orm/compiler.test.ts +220 -0
  210. package/tests/unit/orm/eager-loading.test.ts +285 -0
  211. package/tests/unit/orm/hooks.test.ts +191 -0
  212. package/tests/unit/orm/model.test.ts +373 -0
  213. package/tests/unit/orm/relationships.test.ts +303 -0
  214. package/tests/unit/orm/scopes.test.ts +74 -0
  215. package/tests/unit/templates-simple.test.ts +53 -0
  216. package/tests/unit/templates.test.ts +454 -0
  217. package/tests/unit/validation.test.ts +18 -24
  218. package/tsconfig.json +11 -3
@@ -3,7 +3,7 @@
3
3
  * Supports Standard Schema validators (Zod, Valibot, ArkType)
4
4
  */
5
5
 
6
- import type { StandardSchema, StandardIssue } from "../types";
6
+ import type { StandardIssue, StandardSchema } from "../types";
7
7
  import type { BuenoConfig, DeepPartial } from "./types";
8
8
 
9
9
  /**
@@ -142,10 +142,16 @@ const DEFAULT_RULES: ValidationRule[] = [
142
142
  validate: (value) => {
143
143
  if (value === undefined) return { valid: true };
144
144
  if (typeof value !== "number") {
145
- return { valid: false, message: "Slow query threshold must be a number" };
145
+ return {
146
+ valid: false,
147
+ message: "Slow query threshold must be a number",
148
+ };
146
149
  }
147
150
  if (value < 0) {
148
- return { valid: false, message: "Slow query threshold must be non-negative" };
151
+ return {
152
+ valid: false,
153
+ message: "Slow query threshold must be non-negative",
154
+ };
149
155
  }
150
156
  return { valid: true };
151
157
  },
@@ -215,7 +221,203 @@ const DEFAULT_RULES: ValidationRule[] = [
215
221
  return { valid: false, message: "Collect interval must be a number" };
216
222
  }
217
223
  if (value < 0) {
218
- return { valid: false, message: "Collect interval must be non-negative" };
224
+ return {
225
+ valid: false,
226
+ message: "Collect interval must be non-negative",
227
+ };
228
+ }
229
+ return { valid: true };
230
+ },
231
+ },
232
+ {
233
+ path: "jobs.driver",
234
+ validate: (value) => {
235
+ if (value === undefined) return { valid: true };
236
+ if (value !== "redis" && value !== "memory") {
237
+ return {
238
+ valid: false,
239
+ message: 'Jobs driver must be "redis" or "memory"',
240
+ expected: '"redis" | "memory"',
241
+ received: value,
242
+ };
243
+ }
244
+ return { valid: true };
245
+ },
246
+ },
247
+ {
248
+ path: "jobs.concurrency",
249
+ validate: (value) => {
250
+ if (value === undefined) return { valid: true };
251
+ if (typeof value !== "number") {
252
+ return { valid: false, message: "Concurrency must be a number" };
253
+ }
254
+ if (value < 1) {
255
+ return { valid: false, message: "Concurrency must be at least 1" };
256
+ }
257
+ return { valid: true };
258
+ },
259
+ },
260
+ {
261
+ path: "jobs.maxRetries",
262
+ validate: (value) => {
263
+ if (value === undefined) return { valid: true };
264
+ if (typeof value !== "number") {
265
+ return { valid: false, message: "Max retries must be a number" };
266
+ }
267
+ if (value < 0) {
268
+ return { valid: false, message: "Max retries must be non-negative" };
269
+ }
270
+ return { valid: true };
271
+ },
272
+ },
273
+ {
274
+ path: "jobs.retryDelay",
275
+ validate: (value) => {
276
+ if (value === undefined) return { valid: true };
277
+ if (typeof value !== "number") {
278
+ return { valid: false, message: "Retry delay must be a number" };
279
+ }
280
+ if (value < 0) {
281
+ return { valid: false, message: "Retry delay must be non-negative" };
282
+ }
283
+ return { valid: true };
284
+ },
285
+ },
286
+ {
287
+ path: "jobs.batchSize",
288
+ validate: (value) => {
289
+ if (value === undefined) return { valid: true };
290
+ if (typeof value !== "number") {
291
+ return { valid: false, message: "Batch size must be a number" };
292
+ }
293
+ if (value < 1) {
294
+ return { valid: false, message: "Batch size must be at least 1" };
295
+ }
296
+ return { valid: true };
297
+ },
298
+ },
299
+ {
300
+ path: "jobs.pollInterval",
301
+ validate: (value) => {
302
+ if (value === undefined) return { valid: true };
303
+ if (typeof value !== "number") {
304
+ return { valid: false, message: "Poll interval must be a number" };
305
+ }
306
+ if (value < 100) {
307
+ return {
308
+ valid: false,
309
+ message: "Poll interval must be at least 100ms",
310
+ };
311
+ }
312
+ return { valid: true };
313
+ },
314
+ },
315
+ {
316
+ path: "jobs.jobTimeout",
317
+ validate: (value) => {
318
+ if (value === undefined) return { valid: true };
319
+ if (typeof value !== "number") {
320
+ return { valid: false, message: "Job timeout must be a number" };
321
+ }
322
+ if (value < 1000) {
323
+ return { valid: false, message: "Job timeout must be at least 1000ms" };
324
+ }
325
+ return { valid: true };
326
+ },
327
+ },
328
+ {
329
+ path: "notification.email.driver",
330
+ validate: (value) => {
331
+ if (value === undefined) return { valid: true };
332
+ const validDrivers = ["smtp", "sendgrid", "brevo", "resend"];
333
+ if (!validDrivers.includes(value as string)) {
334
+ return {
335
+ valid: false,
336
+ message: `Email driver must be one of: ${validDrivers.join(", ")}`,
337
+ expected: validDrivers.join(" | "),
338
+ received: value,
339
+ };
340
+ }
341
+ return { valid: true };
342
+ },
343
+ },
344
+ {
345
+ path: "notification.email.from",
346
+ validate: (value) => {
347
+ if (value === undefined) return { valid: true };
348
+ if (typeof value !== "string") {
349
+ return { valid: false, message: "From email must be a string" };
350
+ }
351
+ if (!value.includes("@")) {
352
+ return {
353
+ valid: false,
354
+ message: "From email must be a valid email address",
355
+ received: value,
356
+ };
357
+ }
358
+ return { valid: true };
359
+ },
360
+ },
361
+ {
362
+ path: "notification.email.smtp.port",
363
+ validate: (value) => {
364
+ if (value === undefined) return { valid: true };
365
+ if (typeof value !== "number") {
366
+ return { valid: false, message: "SMTP port must be a number" };
367
+ }
368
+ if (value < 1 || value > 65535) {
369
+ return {
370
+ valid: false,
371
+ message: "SMTP port must be between 1 and 65535",
372
+ };
373
+ }
374
+ return { valid: true };
375
+ },
376
+ },
377
+ {
378
+ path: "notification.sms.driver",
379
+ validate: (value) => {
380
+ if (value === undefined) return { valid: true };
381
+ const validDrivers = ["twilio", "aws-sns", "custom"];
382
+ if (!validDrivers.includes(value as string)) {
383
+ return {
384
+ valid: false,
385
+ message: `SMS driver must be one of: ${validDrivers.join(", ")}`,
386
+ expected: validDrivers.join(" | "),
387
+ received: value,
388
+ };
389
+ }
390
+ return { valid: true };
391
+ },
392
+ },
393
+ {
394
+ path: "notification.whatsapp.driver",
395
+ validate: (value) => {
396
+ if (value === undefined) return { valid: true };
397
+ const validDrivers = ["twilio", "custom"];
398
+ if (!validDrivers.includes(value as string)) {
399
+ return {
400
+ valid: false,
401
+ message: `WhatsApp driver must be one of: ${validDrivers.join(", ")}`,
402
+ expected: validDrivers.join(" | "),
403
+ received: value,
404
+ };
405
+ }
406
+ return { valid: true };
407
+ },
408
+ },
409
+ {
410
+ path: "notification.push.driver",
411
+ validate: (value) => {
412
+ if (value === undefined) return { valid: true };
413
+ const validDrivers = ["firebase", "apns", "custom"];
414
+ if (!validDrivers.includes(value as string)) {
415
+ return {
416
+ valid: false,
417
+ message: `Push driver must be one of: ${validDrivers.join(", ")}`,
418
+ expected: validDrivers.join(" | "),
419
+ received: value,
420
+ };
219
421
  }
220
422
  return { valid: true };
221
423
  },
@@ -296,7 +498,11 @@ export function validateConfigDefaults(
296
498
  });
297
499
  }
298
500
 
299
- if (config.cache?.driver === "redis" && !config.cache.url && !process.env.REDIS_URL) {
501
+ if (
502
+ config.cache?.driver === "redis" &&
503
+ !config.cache.url &&
504
+ !process.env.REDIS_URL
505
+ ) {
300
506
  warnings.push({
301
507
  message: "Redis cache driver selected but no Redis URL configured",
302
508
  path: "cache.url",
@@ -404,7 +610,9 @@ export async function assertValidConfig<T extends BuenoConfig = BuenoConfig>(
404
610
  // Log warnings
405
611
  if (result.warnings.length > 0) {
406
612
  for (const warning of result.warnings) {
407
- console.warn(`Config warning: ${warning.message}${warning.path ? ` (at ${warning.path})` : ""}`);
613
+ console.warn(
614
+ `Config warning: ${warning.message}${warning.path ? ` (at ${warning.path})` : ""}`,
615
+ );
408
616
  }
409
617
  }
410
618
  }
@@ -438,4 +646,4 @@ export function createCustomValidator(
438
646
  warnings: [],
439
647
  };
440
648
  };
441
- }
649
+ }
@@ -8,14 +8,14 @@
8
8
 
9
9
  /**
10
10
  * Forward reference container for lazy resolution of circular dependencies.
11
- *
11
+ *
12
12
  * @template T - The type of the referenced value
13
- *
13
+ *
14
14
  * @example
15
15
  * ```typescript
16
16
  * // Creating a forward reference
17
17
  * const ref = forwardRef(() => ServiceB);
18
- *
18
+ *
19
19
  * // Using with @Inject decorator
20
20
  * @Injectable()
21
21
  * class ServiceA {
@@ -31,7 +31,7 @@ export interface ForwardRef<T> {
31
31
  * The unique symbol identifying this as a ForwardRef
32
32
  */
33
33
  readonly __forwardRef: unique symbol;
34
-
34
+
35
35
  /**
36
36
  * Factory function that returns the actual value when called.
37
37
  * This is invoked lazily when the dependency is first accessed.
@@ -42,19 +42,19 @@ export interface ForwardRef<T> {
42
42
  /**
43
43
  * Symbol used to identify ForwardRef objects
44
44
  */
45
- const FORWARD_REF_SYMBOL = Symbol.for('buno.forwardRef');
45
+ const FORWARD_REF_SYMBOL = Symbol.for("buno.forwardRef");
46
46
 
47
47
  /**
48
48
  * Create a forward reference for circular dependency resolution.
49
- *
49
+ *
50
50
  * The provided factory function is called lazily when the dependency
51
51
  * is actually resolved, allowing the referenced class to be defined
52
52
  * later in the module loading process.
53
- *
53
+ *
54
54
  * @template T - The type of the referenced value
55
55
  * @param fn - Factory function that returns the actual token or value
56
56
  * @returns A ForwardRef object that can be used with @Inject()
57
- *
57
+ *
58
58
  * @example
59
59
  * ```typescript
60
60
  * // service-a.ts
@@ -64,12 +64,12 @@ const FORWARD_REF_SYMBOL = Symbol.for('buno.forwardRef');
64
64
  * @Inject(forwardRef(() => ServiceB))
65
65
  * private serviceB: ServiceB
66
66
  * ) {}
67
- *
67
+ *
68
68
  * doSomething() {
69
69
  * return this.serviceB.help();
70
70
  * }
71
71
  * }
72
- *
72
+ *
73
73
  * // service-b.ts
74
74
  * @Injectable()
75
75
  * export class ServiceB {
@@ -77,7 +77,7 @@ const FORWARD_REF_SYMBOL = Symbol.for('buno.forwardRef');
77
77
  * @Inject(forwardRef(() => ServiceA))
78
78
  * private serviceA: ServiceA
79
79
  * ) {}
80
- *
80
+ *
81
81
  * help() {
82
82
  * return 'helping';
83
83
  * }
@@ -93,10 +93,10 @@ export function forwardRef<T>(fn: () => T): ForwardRef<T> {
93
93
 
94
94
  /**
95
95
  * Type guard to check if a value is a ForwardRef.
96
- *
96
+ *
97
97
  * @param value - The value to check
98
98
  * @returns True if the value is a ForwardRef, false otherwise
99
- *
99
+ *
100
100
  * @example
101
101
  * ```typescript
102
102
  * const ref = forwardRef(() => MyService);
@@ -107,30 +107,30 @@ export function forwardRef<T>(fn: () => T): ForwardRef<T> {
107
107
  */
108
108
  export function isForwardRef(value: unknown): value is ForwardRef<unknown> {
109
109
  return (
110
- typeof value === 'object' &&
110
+ typeof value === "object" &&
111
111
  value !== null &&
112
- '__forwardRef' in value &&
113
- 'forwardRef' in value &&
114
- typeof (value as ForwardRef<unknown>).forwardRef === 'function'
112
+ "__forwardRef" in value &&
113
+ "forwardRef" in value &&
114
+ typeof (value as ForwardRef<unknown>).forwardRef === "function"
115
115
  );
116
116
  }
117
117
 
118
118
  /**
119
119
  * Resolve a forward reference to its actual value.
120
- *
120
+ *
121
121
  * If the provided value is a ForwardRef, this function calls its
122
122
  * factory function to get the actual value. If it's not a ForwardRef,
123
123
  * the value is returned as-is.
124
- *
124
+ *
125
125
  * @template T - The expected type of the resolved value
126
126
  * @param ref - Either a ForwardRef or a direct value
127
127
  * @returns The resolved value
128
- *
128
+ *
129
129
  * @example
130
130
  * ```typescript
131
131
  * const token = Token<ServiceB>('ServiceB');
132
132
  * const ref = forwardRef(() => token);
133
- *
133
+ *
134
134
  * // Resolves to the token
135
135
  * const actualToken = resolveForwardRef(ref);
136
136
  * ```
@@ -140,4 +140,4 @@ export function resolveForwardRef<T>(ref: ForwardRef<T> | T): T {
140
140
  return ref.forwardRef();
141
141
  }
142
142
  return ref;
143
- }
143
+ }
@@ -51,7 +51,10 @@ class ResolutionStack {
51
51
  * Track tokens that are being lazily resolved for circular dependencies.
52
52
  * These tokens have a proxy placeholder that will be resolved later.
53
53
  */
54
- private lazyResolutions = new Map<Token, { resolved: boolean; instance?: unknown }>();
54
+ private lazyResolutions = new Map<
55
+ Token,
56
+ { resolved: boolean; instance?: unknown }
57
+ >();
55
58
 
56
59
  push(token: Token): void {
57
60
  if (this.stack.has(token)) {
@@ -73,7 +76,10 @@ class ResolutionStack {
73
76
  /**
74
77
  * Mark a token as being lazily resolved (for circular dependency support)
75
78
  */
76
- markLazy(token: Token, placeholder: { resolved: boolean; instance?: unknown }): void {
79
+ markLazy(
80
+ token: Token,
81
+ placeholder: { resolved: boolean; instance?: unknown },
82
+ ): void {
77
83
  this.lazyResolutions.set(token, placeholder);
78
84
  }
79
85
 
@@ -201,8 +207,12 @@ export class Container {
201
207
  get: (target: T, prop: string | symbol): unknown => {
202
208
  // If already resolved, return the cached value
203
209
  if (placeholder.resolved && placeholder.instance) {
204
- const value = (placeholder.instance as Record<string | symbol, unknown>)[prop];
205
- return typeof value === 'function' ? value.bind(placeholder.instance) : value;
210
+ const value = (
211
+ placeholder.instance as Record<string | symbol, unknown>
212
+ )[prop];
213
+ return typeof value === "function"
214
+ ? value.bind(placeholder.instance)
215
+ : value;
206
216
  }
207
217
 
208
218
  // Resolve the actual instance
@@ -215,7 +225,7 @@ export class Container {
215
225
  // If not yet cached, we need to wait for the resolution to complete
216
226
  // This happens when the proxy is accessed during construction
217
227
  // Return a function that will resolve later
218
- if (prop === 'then') {
228
+ if (prop === "then") {
219
229
  // Make the proxy thenable for async contexts
220
230
  return undefined;
221
231
  }
@@ -223,22 +233,27 @@ export class Container {
223
233
 
224
234
  // Try to get the value from the resolved instance
225
235
  if (placeholder.instance) {
226
- const value = (placeholder.instance as Record<string | symbol, unknown>)[prop];
227
- return typeof value === 'function' ? value.bind(placeholder.instance) : value;
236
+ const value = (
237
+ placeholder.instance as Record<string | symbol, unknown>
238
+ )[prop];
239
+ return typeof value === "function"
240
+ ? value.bind(placeholder.instance)
241
+ : value;
228
242
  }
229
243
 
230
244
  // Return a no-op function for method calls during construction
231
245
  return () => undefined;
232
246
  },
233
-
247
+
234
248
  set: (target: T, prop: string | symbol, value: unknown): boolean => {
235
249
  if (placeholder.instance) {
236
- (placeholder.instance as Record<string | symbol, unknown>)[prop] = value;
250
+ (placeholder.instance as Record<string | symbol, unknown>)[prop] =
251
+ value;
237
252
  return true;
238
253
  }
239
254
  return false;
240
255
  },
241
-
256
+
242
257
  has: (target: T, prop: string | symbol): boolean => {
243
258
  if (placeholder.instance) {
244
259
  return prop in (placeholder.instance as object);
@@ -376,11 +391,18 @@ export function Inject(token: Token | ForwardRef<Token>): ParameterDecorator {
376
391
  ) => {
377
392
  const targetObj = target as object;
378
393
  const existingTokens: Array<Token | ForwardRef<Token>> =
379
- getContainerMetadata<Array<Token | ForwardRef<Token>>>(targetObj, "inject:tokens") ?? [];
394
+ getContainerMetadata<Array<Token | ForwardRef<Token>>>(
395
+ targetObj,
396
+ "inject:tokens",
397
+ ) ?? [];
380
398
  existingTokens[parameterIndex] = token;
381
399
  setContainerMetadata(targetObj, "inject:tokens", existingTokens);
382
400
  };
383
401
  }
384
402
 
385
403
  // Export getter and setter for use by modules
386
- export { getContainerMetadata as getInjectTokens, setContainerMetadata, getContainerMetadata };
404
+ export {
405
+ getContainerMetadata as getInjectTokens,
406
+ setContainerMetadata,
407
+ getContainerMetadata,
408
+ };
@@ -287,7 +287,17 @@ export class Context<V extends ContextVariables = ContextVariables> {
287
287
  /**
288
288
  * Create a new Response with current state
289
289
  */
290
- newResponse(body: Blob | ArrayBuffer | FormData | URLSearchParams | ReadableStream<unknown> | string | null, options?: ResponseInit): Response {
290
+ newResponse(
291
+ body:
292
+ | Blob
293
+ | ArrayBuffer
294
+ | FormData
295
+ | URLSearchParams
296
+ | ReadableStream<unknown>
297
+ | string
298
+ | null,
299
+ options?: ResponseInit,
300
+ ): Response {
291
301
  return new Response(body, {
292
302
  status: this._response.status,
293
303
  headers: this._response.headers,