@h3ravel/core 1.21.7 → 1.22.0-alpha.10

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.
package/dist/index.js CHANGED
@@ -1,6 +1,11 @@
1
+ import { createRequire } from "node:module";
1
2
  import "reflect-metadata";
2
- import { FileSystem, Logger, PathLoader } from "@h3ravel/shared";
3
- import { InvalidArgumentException, Str, dd, dump, str } from "@h3ravel/support";
3
+ import { FileSystem, Logger, PathLoader, Resolver } from "@h3ravel/shared";
4
+ import { H3, serve } from "h3";
5
+ import { CKernel, IApplication, IContainer, IController, IKernel, IRegisterer } from "@h3ravel/contracts";
6
+ import { Arr, InvalidArgumentException, Obj, RuntimeException, ServiceProvider, Str, data_get, dd, dump, str } from "@h3ravel/support";
7
+ import { AppBuilder, ConfigException, Helpers, HttpException, Inject, Injectable, MiddlewareHandler, NotFoundHttpException } from "@h3ravel/foundation";
8
+ import { createRequire as createRequire$1 } from "module";
4
9
  import fg from "fast-glob";
5
10
  import path from "node:path";
6
11
  import { detect } from "detect-port";
@@ -8,12 +13,90 @@ import dotenv from "dotenv";
8
13
  import dotenvExpand from "dotenv-expand";
9
14
  import { readFile } from "node:fs/promises";
10
15
  import semver from "semver";
11
- import { HttpContext as HttpContext$1, LogRequests, Request, Response } from "@h3ravel/http";
16
+ import { Facades } from "@h3ravel/support/facades";
12
17
 
18
+ //#region src/Manager/ContainerResolver.ts
19
+ var ContainerResolver = class ContainerResolver {
20
+ constructor(app) {
21
+ this.app = app;
22
+ }
23
+ async resolveMethodParams(instance, method, ..._default) {
24
+ /**
25
+ * Get param types for instance method
26
+ */
27
+ let params = Reflect.getMetadata("design:paramtypes", instance, String(method)) || [];
28
+ /**
29
+ * Ensure that the Application class is always available
30
+ */
31
+ if (params.length < 1 && _default.length > 0) params = _default;
32
+ /**
33
+ * Resolve the bound dependencies
34
+ */
35
+ const args = params.filter((e) => ContainerResolver.isClass(e) || e instanceof Application).map((type) => {
36
+ if (type instanceof Application) return type;
37
+ return this.app.make(type);
38
+ });
39
+ return new Promise((resolve) => {
40
+ resolve(instance[method](...args));
41
+ });
42
+ }
43
+ static isClass(C) {
44
+ return typeof C === "function" && C.prototype !== void 0 && Object.toString.call(C).substring(0, 5) === "class";
45
+ }
46
+ static isAbstract(C) {
47
+ return this.isClass(C) && C.name.startsWith("I");
48
+ }
49
+ static isCallable(C) {
50
+ return typeof C === "function" && !ContainerResolver.isClass(C);
51
+ }
52
+ };
53
+
54
+ //#endregion
13
55
  //#region src/Container.ts
14
- var Container = class {
56
+ var Container = class Container extends IContainer {
15
57
  bindings = /* @__PURE__ */ new Map();
16
58
  singletons = /* @__PURE__ */ new Map();
59
+ middlewareHandler;
60
+ /**
61
+ * The current globally available container (if any).
62
+ */
63
+ static instance;
64
+ /**
65
+ * All of the before resolving callbacks by class type.
66
+ */
67
+ beforeResolvingCallbacks = /* @__PURE__ */ new Map();
68
+ /**
69
+ * All of the after resolving callbacks by class type.
70
+ */
71
+ afterResolvingCallbacks = /* @__PURE__ */ new Map();
72
+ /**
73
+ * All of the registered rebound callbacks.
74
+ */
75
+ reboundCallbacks = /* @__PURE__ */ new Map();
76
+ /**
77
+ * The container's shared instances.
78
+ */
79
+ instances = /* @__PURE__ */ new Map();
80
+ /**
81
+ * The container's resolved instances.
82
+ */
83
+ resolvedInstances = /* @__PURE__ */ new Map();
84
+ /**
85
+ * The registered type alias.
86
+ */
87
+ aliases = /* @__PURE__ */ new Map();
88
+ /**
89
+ * The registered aliases keyed by the abstract name.
90
+ */
91
+ abstractAliases = /* @__PURE__ */ new Map();
92
+ /**
93
+ * The registered aliases keyed by the abstract name.
94
+ */
95
+ middlewares = /* @__PURE__ */ new Map();
96
+ /**
97
+ * The extension closures for services.
98
+ */
99
+ extenders = /* @__PURE__ */ new Map();
17
100
  static hasAnyDecorator(target) {
18
101
  if (Reflect.getMetadataKeys(target).length > 0) return true;
19
102
  const paramLength = target.length;
@@ -24,7 +107,22 @@ var Container = class {
24
107
  this.bindings.set(key, factory);
25
108
  }
26
109
  /**
110
+ * Bind unregistered middlewares to the service container so we can use them later
111
+ *
112
+ * @param key
113
+ * @param middleware
114
+ */
115
+ bindMiddleware(key, middleware) {
116
+ this.middlewares.set(key, middleware);
117
+ }
118
+ boundMiddlewares(key) {
119
+ if (key) return this.middlewares.get(key);
120
+ return this.middlewares.entries();
121
+ }
122
+ /**
27
123
  * Remove one or more transient services from the container
124
+ *
125
+ * @param key
28
126
  */
29
127
  unbind(key) {
30
128
  if (Array.isArray(key)) for (let i = 0; i < key.length; i++) {
@@ -36,28 +134,127 @@ var Container = class {
36
134
  this.singletons.delete(key);
37
135
  }
38
136
  }
39
- /**
40
- * Bind a singleton service to the container
41
- */
42
137
  singleton(key, factory) {
43
138
  this.bindings.set(key, () => {
44
- if (!this.singletons.has(key)) this.singletons.set(key, factory(this));
139
+ if (!this.singletons.has(key)) this.singletons.set(key, this.call(factory));
45
140
  return this.singletons.get(key);
46
141
  });
47
142
  }
143
+ /**
144
+ * Read reflected param types, resolve dependencies from the container and
145
+ * optionally transform them, finally invoke the specified method on a class instance
146
+ *
147
+ * @param instance
148
+ * @param method
149
+ * @param defaultArgs
150
+ * @param handler
151
+ * @returns
152
+ */
153
+ async invoke(instance, method, defaultArgs, handler) {
154
+ /**
155
+ * Get param types for the instance method
156
+ */
157
+ const paramTypes = Reflect.getMetadata("design:paramtypes", instance, method) || [];
158
+ /**
159
+ * Resolve the bound dependencies
160
+ */
161
+ let args = await Promise.all(paramTypes.map(async (paramType) => {
162
+ const inst = this.make(paramType);
163
+ if (handler) return await handler(inst);
164
+ return inst;
165
+ }));
166
+ /**
167
+ * Ensure that the args is always filled
168
+ */
169
+ if (args.length < 1) args = defaultArgs ?? [];
170
+ const fn = instance[method];
171
+ return Reflect.apply(fn, instance, args);
172
+ }
173
+ /**
174
+ * Read reflected param types, resolve dependencies from the container and return the result
175
+ *
176
+ * @param instance
177
+ * @param method
178
+ */
179
+ resolveParams(instance, method) {
180
+ /**
181
+ * Resolve and return the bound dependencies
182
+ */
183
+ return (Reflect.getMetadata("design:paramtypes", instance, method) || []).filter((e) => !!e).map((abstract) => {
184
+ if (typeof abstract === "function" && abstract.toString().startsWith("function Function")) return abstract;
185
+ return this.make(abstract);
186
+ });
187
+ }
48
188
  make(key) {
189
+ return this.resolve(key);
190
+ }
191
+ /**
192
+ * Resolve the gevein service from the container
193
+ *
194
+ * @param abstract
195
+ * @param raiseEvents
196
+ */
197
+ resolve(abstract, raiseEvents = true) {
198
+ abstract = this.getAlias(abstract);
49
199
  /**
50
200
  * Direct factory binding
51
201
  */
52
- if (this.bindings.has(key)) return this.bindings.get(key)();
53
- /**
202
+ let resolved;
203
+ if (this.resolvedInstances.has(abstract)) return this.resolvedInstances.get(abstract);
204
+ if (raiseEvents) this.runBeforeResolvingCallbacks(abstract);
205
+ if (this.bindings.has(abstract)) resolved = this.bindings.get(abstract)();
206
+ else if (this.instances.has(abstract)) resolved = this.instances.get(abstract);
207
+ else if (typeof abstract === "function")
208
+ /**
54
209
  * If this is a class constructor, auto-resolve via reflection
55
210
  */
56
- if (typeof key === "function") return this.build(key);
57
- throw new Error(`No binding found for key: ${typeof key === "string" ? key : key?.name}`);
211
+ resolved = this.build(abstract);
212
+ else throw new Error(`No binding found for key: ${typeof abstract === "string" ? abstract : abstract?.name}`);
213
+ /**
214
+ * If we defined any extenders for this type, we'll need to spin through them
215
+ * and apply them to the object being built. This allows for the extension
216
+ * of services, such as changing configuration or decorating the object.
217
+ */
218
+ for (const extender of this.getExtenders(abstract)) resolved = extender(resolved, this);
219
+ if (raiseEvents) this.runAfterResolvingCallbacks(abstract, resolved);
220
+ this.resolvedInstances.set(abstract, resolved);
221
+ return resolved;
222
+ }
223
+ afterResolving(key, callback) {
224
+ const existing = this.afterResolvingCallbacks.get(key) || [];
225
+ existing.push(callback);
226
+ this.afterResolvingCallbacks.set(key, existing);
227
+ }
228
+ beforeResolving(key, callback) {
229
+ const existing = this.beforeResolvingCallbacks.get(key) || [];
230
+ existing.push(callback);
231
+ this.beforeResolvingCallbacks.set(key, existing);
232
+ }
233
+ /**
234
+ * Execute all registered beforeResolving callbacks for a given key
235
+ *
236
+ * @param key
237
+ * @param resolved
238
+ */
239
+ runBeforeResolvingCallbacks(key) {
240
+ const callbacks = this.beforeResolvingCallbacks.get(key) || [];
241
+ for (let i = 0; i < callbacks.length; i++) callbacks[i](this);
242
+ }
243
+ /**
244
+ * Execute all registered afterResolving callbacks for a given key
245
+ *
246
+ * @param key
247
+ * @param resolved
248
+ */
249
+ runAfterResolvingCallbacks(key, resolved) {
250
+ const callbacks = this.afterResolvingCallbacks.get(key) || [];
251
+ for (let i = 0; i < callbacks.length; i++) callbacks[i](resolved, this);
58
252
  }
59
253
  /**
60
254
  * Automatically build a class with constructor dependency injection
255
+ *
256
+ * @param ClassType
257
+ * @returns
61
258
  */
62
259
  build(ClassType) {
63
260
  let dependencies = [];
@@ -65,44 +262,135 @@ var Container = class {
65
262
  return this.make(alias);
66
263
  });
67
264
  else dependencies = (Reflect.getMetadata("design:paramtypes", ClassType) || []).map((dep) => this.make(dep));
265
+ if (dependencies.length === 0) dependencies = [this];
68
266
  return new ClassType(...dependencies);
69
267
  }
70
268
  /**
71
- * Check if a service is registered
269
+ * Determine if a given string is an alias.
270
+ *
271
+ * @param name
272
+ */
273
+ isAlias(name) {
274
+ return this.aliases.has(name) && typeof this.aliases.get(name) !== "undefined";
275
+ }
276
+ /**
277
+ * Get the alias for an abstract if available.
278
+ *
279
+ * @param abstract
280
+ */
281
+ getAlias(abstract) {
282
+ if (typeof abstract === "string" && this.aliases.has(abstract)) return this.getAlias(this.aliases.get(abstract));
283
+ if (abstract == null) return abstract;
284
+ return this.aliases.get(abstract) ?? abstract;
285
+ }
286
+ /**
287
+ * Get the extender callbacks for a given type.
288
+ *
289
+ * @param abstract
72
290
  */
291
+ getExtenders(abstract) {
292
+ return this.extenders.get(this.getAlias(abstract)) ?? [];
293
+ }
294
+ /**
295
+ * Remove all of the extender callbacks for a given type.
296
+ *
297
+ * @param abstract
298
+ */
299
+ forgetExtenders(abstract) {
300
+ this.extenders.delete(this.getAlias(abstract));
301
+ }
302
+ alias(key, target) {
303
+ if (Array.isArray(key)) for (const [tokn, targ] of key) this.aliases.set(tokn, targ);
304
+ else this.aliases.set(key, target);
305
+ return this;
306
+ }
307
+ rebinding(abstract, callback) {
308
+ abstract = this.getAlias(abstract);
309
+ this.reboundCallbacks.set(abstract, this.reboundCallbacks.get(abstract)?.concat(callback) ?? [callback]);
310
+ if (this.bound(abstract)) return this.make(abstract);
311
+ }
312
+ bound(abstract) {
313
+ return this.bindings.has(abstract) || !!this.instances.get(abstract) || this.isAlias(abstract);
314
+ }
73
315
  has(key) {
74
- return this.bindings.has(key);
316
+ return this.bound(key);
75
317
  }
76
- };
77
-
78
- //#endregion
79
- //#region src/Di/ContainerResolver.ts
80
- var ContainerResolver = class ContainerResolver {
81
- constructor(app) {
82
- this.app = app;
318
+ /**
319
+ * Determine if the given abstract type has been resolved.
320
+ *
321
+ * @param abstract
322
+ */
323
+ resolved(abstract) {
324
+ if (this.isAlias(abstract)) abstract = this.getAlias(abstract);
325
+ return this.resolvedInstances.has(abstract) || this.instances.has(abstract);
83
326
  }
84
- async resolveMethodParams(instance, method, ..._default) {
85
- /**
86
- * Get param types for instance method
87
- */
88
- let params = Reflect.getMetadata("design:paramtypes", instance, String(method)) || [];
89
- /**
90
- * Ensure that the Application class is always available
91
- */
92
- if (params.length < 1 && _default.length > 0) params = _default;
93
- /**
94
- * Resolve the bound dependencies
95
- */
96
- const args = params.filter((e) => ContainerResolver.isClass(e) || e instanceof Application).map((type) => {
97
- if (type instanceof Application) return type;
98
- return this.app.make(type);
99
- });
100
- return new Promise((resolve) => {
101
- resolve(instance[method](...args));
102
- });
327
+ extend(abstract, closure) {
328
+ abstract = this.getAlias(abstract);
329
+ if (this.instances.has(abstract)) {
330
+ this.instances.set(abstract, closure(this.instances.get(abstract), this));
331
+ this.rebound(abstract);
332
+ } else {
333
+ this.extenders.set(abstract, this.extenders.get(abstract)?.concat(closure) ?? [closure]);
334
+ if (this.resolved(abstract)) this.rebound(abstract);
335
+ }
103
336
  }
104
- static isClass(C) {
105
- return typeof C === "function" && C.prototype !== void 0 && Object.toString.call(C).substring(0, 5) === "class";
337
+ instance(abstract, instance) {
338
+ this.removeAbstractAlias(abstract);
339
+ const isBound = this.bound(abstract);
340
+ this.aliases.delete(abstract);
341
+ this.instances.set(abstract, instance);
342
+ if (isBound) this.rebound(abstract);
343
+ return instance;
344
+ }
345
+ call(callback) {
346
+ if (ContainerResolver.isClass(callback)) return this.make(callback);
347
+ return callback(this);
348
+ }
349
+ /**
350
+ * Fire the "rebound" callbacks for the given abstract type.
351
+ *
352
+ * @param abstract
353
+ */
354
+ rebound(abstract) {
355
+ const callbacks = this.getReboundCallbacks(abstract);
356
+ if (!callbacks) return;
357
+ const instance = this.make(abstract);
358
+ for (const callback of callbacks) callback(this, instance);
359
+ }
360
+ /**
361
+ * Get the rebound callbacks for a given type.
362
+ *
363
+ * @param abstract
364
+ */
365
+ getReboundCallbacks(abstract) {
366
+ return this.reboundCallbacks.get(abstract) ?? [];
367
+ }
368
+ /**
369
+ * Remove an alias from the contextual binding alias cache.
370
+ *
371
+ * @param searched
372
+ */
373
+ removeAbstractAlias(searched) {
374
+ if (!this.aliases.has(searched)) return;
375
+ for (const [abstract, aliases] of this.abstractAliases.entries()) {
376
+ const filtered = aliases.filter((alias) => alias !== searched);
377
+ if (filtered.length > 0) this.abstractAliases.set(abstract, filtered);
378
+ else this.abstractAliases.delete(abstract);
379
+ }
380
+ }
381
+ /**
382
+ * Get the globally available instance of the container.
383
+ */
384
+ static getInstance() {
385
+ return this.instance ??= new Application(process.cwd(), "h3ravel");
386
+ }
387
+ /**
388
+ * Set the shared instance of the container.
389
+ *
390
+ * @param container
391
+ */
392
+ static setInstance(container) {
393
+ return Container.instance = container;
106
394
  }
107
395
  };
108
396
 
@@ -192,33 +480,25 @@ var ProviderRegistry = class {
192
480
  * @returns
193
481
  */
194
482
  static sort(providers) {
195
- /**
196
- * Base priority (default 0)
197
- */
198
- providers.forEach((Provider) => {
199
- const key = this.getKey(Provider);
200
- this.priorityMap.set(`${Provider.name}::${key}`, Provider.priority ?? 0);
201
- });
202
- /**
203
- * Handle before/after adjustments
204
- */
483
+ const makeKey = (Provider) => `${Provider.name}::${this.getKey(Provider)}`;
484
+ providers.sort((A, B) => (B.priority ?? 0) - (A.priority ?? 0));
485
+ const findIndex = (target) => {
486
+ if (target.includes("::")) return providers.findIndex((p) => makeKey(p) === target);
487
+ return providers.findIndex((p) => p.name === target);
488
+ };
205
489
  providers.forEach((Provider) => {
206
490
  const order = Provider.order;
207
491
  if (!order) return;
208
- const [direction, target] = order.split(":");
209
- const targetPriority = this.priorityMap.get(target) ?? 0;
210
- const key = this.getKey(Provider);
211
- if (direction === "before") this.priorityMap.set(`${Provider.name}::${key}`, targetPriority - 1);
212
- else if (direction === "after") this.priorityMap.set(`${Provider.name}::${key}`, targetPriority + 1);
213
- });
214
- /**
215
- * Return service providers sorted based on thier name and priority
216
- */
217
- return providers.sort((A, B) => {
218
- const keyA = this.getKey(A);
219
- const keyB = this.getKey(B);
220
- return (this.priorityMap.get(`${B.name}::${keyB}`) ?? 0) - (this.priorityMap.get(`${A.name}::${keyA}`) ?? 0);
492
+ const [direction, rawTarget] = order.split(":");
493
+ const targetIndex = findIndex(rawTarget);
494
+ if (targetIndex === -1) return;
495
+ const currentIndex = providers.indexOf(Provider);
496
+ if (currentIndex === -1) return;
497
+ providers.splice(currentIndex, 1);
498
+ const insertIndex = direction === "before" ? targetIndex : targetIndex + 1;
499
+ providers.splice(insertIndex, 0, Provider);
221
500
  });
501
+ return providers;
222
502
  }
223
503
  /**
224
504
  * Sort service providers
@@ -237,7 +517,8 @@ var ProviderRegistry = class {
237
517
  *
238
518
  * @param priorityMap
239
519
  */
240
- static log(providers) {
520
+ static log(providers, enabled = true) {
521
+ if (!enabled) return;
241
522
  const sorted = Array.from((providers ?? this.providers).values());
242
523
  console.table(sorted.map((P) => ({
243
524
  Name: P.constructor.name,
@@ -278,10 +559,10 @@ var ProviderRegistry = class {
278
559
  const providers = [];
279
560
  if (autoRegister) {
280
561
  for (const manifestPath of manifests) {
281
- const pkg = await this.getManifest(path.resolve(manifestPath));
562
+ const pkg = this.getManifest(path.resolve(manifestPath));
282
563
  if (pkg.h3ravel?.providers) providers.push(...await Promise.all(pkg.h3ravel.providers.map(async (name) => (await import(path.resolve(path.dirname(manifestPath), "dist/index.js")))[name])));
283
564
  }
284
- for (const provider of providers) {
565
+ for (const provider of providers.filter((e) => typeof e !== "undefined")) {
285
566
  const key = this.getKey(provider);
286
567
  this.providers.set(key, provider);
287
568
  }
@@ -294,22 +575,16 @@ var ProviderRegistry = class {
294
575
  * @param manifestPath
295
576
  * @returns
296
577
  */
297
- static async getManifest(manifestPath) {
298
- let pkg;
299
- try {
300
- pkg = (await import(manifestPath)).default;
301
- } catch {
302
- const { createRequire } = await import("module");
303
- pkg = createRequire(import.meta.url)(manifestPath);
304
- }
305
- return pkg;
578
+ static getManifest(manifestPath) {
579
+ return createRequire$1(import.meta.url)(manifestPath);
306
580
  }
307
581
  };
308
582
 
309
583
  //#endregion
310
584
  //#region src/Registerer.ts
311
- var Registerer = class Registerer {
585
+ var Registerer = class Registerer extends IRegisterer {
312
586
  constructor(app) {
587
+ super();
313
588
  this.app = app;
314
589
  }
315
590
  static register(app) {
@@ -341,31 +616,87 @@ var Registerer = class Registerer {
341
616
  }
342
617
  };
343
618
 
619
+ //#endregion
620
+ //#region src/Providers/CoreServiceProvider.ts
621
+ /**
622
+ * Bootstraps core services and bindings.
623
+ *
624
+ * Bind essential services to the container (logger, config repository).
625
+ * Register app-level singletons.
626
+ * Set up exception handling.
627
+ *
628
+ * Auto-Registered
629
+ */
630
+ var CoreServiceProvider = class extends ServiceProvider {
631
+ static priority = 999;
632
+ register() {
633
+ Object.assign(globalThis, { str });
634
+ this.app.alias(IApplication, Application);
635
+ }
636
+ boot() {}
637
+ };
638
+
344
639
  //#endregion
345
640
  //#region src/Application.ts
346
641
  var Application = class Application extends Container {
642
+ /**
643
+ * Indicates if the application has "booted".
644
+ */
645
+ #booted = false;
347
646
  paths = new PathLoader();
348
647
  context;
648
+ h3Event;
349
649
  tries = 0;
350
- booted = false;
351
650
  basePath;
352
651
  versions = {
353
652
  app: "0.0.0",
354
653
  ts: "0.0.0"
355
654
  };
655
+ namespace;
356
656
  static versions = {
357
657
  app: "0.0.0",
358
658
  ts: "0.0.0"
359
659
  };
660
+ h3App;
360
661
  providers = [];
361
662
  externalProviders = [];
362
663
  filteredProviders = [];
664
+ autoRegisterProviders = false;
665
+ /**
666
+ * The route resolver callback.
667
+ */
668
+ uriResolver;
363
669
  /**
364
670
  * List of registered console commands
365
671
  */
366
672
  registeredCommands = [];
367
- constructor(basePath) {
673
+ /**
674
+ * The array of booted callbacks.
675
+ */
676
+ bootedCallbacks = [];
677
+ /**
678
+ * The array of booting callbacks.
679
+ */
680
+ bootingCallbacks = [];
681
+ /**
682
+ * The array of terminating callbacks.
683
+ */
684
+ terminatingCallbacks = [];
685
+ /**
686
+ * Indicates if the application has been bootstrapped before.
687
+ */
688
+ bootstrapped = false;
689
+ /**
690
+ * Controls logging
691
+ */
692
+ logsDisabled = false;
693
+ /**
694
+ * The conrrent HttpContext
695
+ */
696
+ httpContext;
697
+ constructor(basePath, initializer) {
368
698
  super();
699
+ this.initializer = initializer;
369
700
  dotenvExpand.expand(dotenv.config({ quiet: true }));
370
701
  this.basePath = basePath;
371
702
  this.setPath("base", basePath);
@@ -377,6 +708,7 @@ var Application = class Application extends Container {
377
708
  * Register core bindings into the container
378
709
  */
379
710
  registerBaseBindings() {
711
+ Application.setInstance(this);
380
712
  this.bind(Application, () => this);
381
713
  this.bind("path.base", () => this.basePath);
382
714
  this.bind("load.paths", () => this.paths);
@@ -416,7 +748,7 @@ var Application = class Application extends Container {
416
748
  * Full-Stack App: Installs database, mail, queue, cache → they self-register via their providers.
417
749
  */
418
750
  async getConfiguredProviders() {
419
- return [(await import("@h3ravel/core")).CoreServiceProvider];
751
+ return [CoreServiceProvider];
420
752
  }
421
753
  async getAllProviders() {
422
754
  return [...await this.getConfiguredProviders(), ...this.externalProviders];
@@ -430,22 +762,30 @@ var Application = class Application extends Container {
430
762
  *
431
763
  * @returns
432
764
  */
433
- async quickStartup(providers, filtered = [], autoRegisterProviders = true) {
765
+ initialize(providers, filtered = [], autoRegisterProviders = true) {
766
+ /**
767
+ * Bind HTTP APP to the service container
768
+ */
769
+ this.singleton("http.app", () => {
770
+ return new H3();
771
+ });
772
+ /**
773
+ * Bind the HTTP server to the service container
774
+ */
775
+ this.singleton("http.serve", () => serve);
434
776
  this.registerProviders(providers, filtered);
435
- await this.registerConfiguredProviders(autoRegisterProviders);
436
- return this.boot();
777
+ this.autoRegisterProviders = autoRegisterProviders;
778
+ return this;
437
779
  }
438
780
  /**
439
781
  * Dynamically register all configured providers
440
- *
441
- * @param autoRegister If set to false, service providers will not be auto discovered and registered.
442
782
  */
443
- async registerConfiguredProviders(autoRegister = true) {
783
+ async registerConfiguredProviders() {
444
784
  const providers = await this.getAllProviders();
445
785
  ProviderRegistry.setSortable(false);
446
786
  ProviderRegistry.setFiltered(this.filteredProviders);
447
787
  ProviderRegistry.registerMany(providers);
448
- if (autoRegister) await ProviderRegistry.discoverProviders(autoRegister);
788
+ if (this.autoRegisterProviders) await ProviderRegistry.discoverProviders(this.autoRegisterProviders);
449
789
  ProviderRegistry.doSort();
450
790
  for (const ProviderClass of ProviderRegistry.all()) {
451
791
  if (!ProviderClass) continue;
@@ -461,7 +801,7 @@ var Application = class Application extends Container {
461
801
  */
462
802
  registerProviders(providers, filtered = []) {
463
803
  this.externalProviders.push(...providers);
464
- this.filteredProviders = filtered;
804
+ this.filteredProviders = Array.from(new Set(this.filteredProviders.concat(filtered)));
465
805
  }
466
806
  /**
467
807
  * Register a provider
@@ -486,44 +826,237 @@ var Application = class Application extends Container {
486
826
  runningInConsole() {
487
827
  return typeof process !== "undefined" && !!process.stdout && !!process.stdin;
488
828
  }
829
+ /**
830
+ * checks if the application is running in Unit Test
831
+ */
832
+ runningUnitTests() {
833
+ return process.env.VITEST === "true";
834
+ }
489
835
  getRuntimeEnv() {
490
836
  if (typeof window !== "undefined" && typeof document !== "undefined") return "browser";
491
837
  if (typeof process !== "undefined" && process.versions?.node) return "node";
492
838
  return "unknown";
493
839
  }
494
840
  /**
841
+ * Determine if the application has booted.
842
+ */
843
+ isBooted() {
844
+ return this.#booted;
845
+ }
846
+ /**
847
+ * Determine if the application has booted.
848
+ */
849
+ logging(logging = true) {
850
+ this.logsDisabled = !logging;
851
+ return this;
852
+ }
853
+ logsEnabled() {
854
+ if (this.logsDisabled) return false;
855
+ return (process.env.APP_DEBUG === "true" && process.env.EXTENDED_DEBUG !== "false" || Number(process.env.VERBOSE) > 1) && !this.providers.some((e) => e.runsInConsole);
856
+ }
857
+ /**
495
858
  * Boot all service providers after registration
496
859
  */
497
860
  async boot() {
498
- if (this.booted) return this;
861
+ if (this.#booted) return this;
862
+ this.fireAppCallbacks(this.bootingCallbacks);
863
+ /**
864
+ * Register all the configured service providers
865
+ */
866
+ await this.registerConfiguredProviders();
499
867
  /**
500
868
  * If debug is enabled, let's show the loaded service provider info
501
869
  */
502
- if ((process.env.APP_DEBUG === "true" && process.env.EXTENDED_DEBUG !== "false" || Number(process.env.VERBOSE) > 1) && !this.providers.some((e) => e.runsInConsole)) ProviderRegistry.log(this.providers);
503
- for (const provider of this.providers) if (provider.boot) if (Container.hasAnyDecorator(provider.boot))
870
+ ProviderRegistry.log(this.providers, this.logsEnabled());
871
+ for (const provider of this.providers) if (provider.boot) {
872
+ if (Container.hasAnyDecorator(provider.boot))
504
873
  /**
505
- * If the service provider is decorated use the IoC container
506
- */
507
- await this.make(provider.boot);
508
- else
874
+ * If the service provider is decorated use the IoC container
875
+ */
876
+ await this.make(provider.boot);
877
+ else
509
878
  /**
510
- * Otherwise instantiate manually so that we can at least
511
- * pass the app instance
512
- */
513
- await provider.boot(this);
514
- this.booted = true;
879
+ * Otherwise instantiate manually so that we can at least
880
+ * pass the app instance
881
+ */
882
+ await provider.boot(this);
883
+ if (provider.callBootedCallbacks) await provider.callBootedCallbacks();
884
+ }
885
+ this.#booted = true;
886
+ this.fireAppCallbacks(this.bootedCallbacks);
887
+ return this;
888
+ }
889
+ /**
890
+ * Register a new boot listener.
891
+ *
892
+ * @param callable $callback
893
+ */
894
+ booting(callback) {
895
+ this.bootingCallbacks.push(callback);
896
+ }
897
+ /**
898
+ * Register a new "booted" listener.
899
+ *
900
+ * @param callback
901
+ */
902
+ booted(callback) {
903
+ this.bootedCallbacks.push(callback);
904
+ if (this.isBooted()) callback(this);
905
+ }
906
+ /**
907
+ * Throw an HttpException with the given data.
908
+ *
909
+ * @param code
910
+ * @param message
911
+ * @param headers
912
+ *
913
+ * @throws {HttpException}
914
+ * @throws {NotFoundHttpException}
915
+ */
916
+ abort(code, message = "", headers = {}) {
917
+ if (code == 404) throw new NotFoundHttpException(message, void 0, 0, headers);
918
+ throw new HttpException(code, message, void 0, headers);
919
+ }
920
+ /**
921
+ * Register a terminating callback with the application.
922
+ *
923
+ * @param callback
924
+ */
925
+ terminating(callback) {
926
+ this.terminatingCallbacks.push(callback);
927
+ return this;
928
+ }
929
+ /**
930
+ * Terminate the application.
931
+ */
932
+ terminate() {
933
+ let index = 0;
934
+ while (index < this.terminatingCallbacks.length) {
935
+ this.call(this.terminatingCallbacks[index]);
936
+ index++;
937
+ }
938
+ }
939
+ /**
940
+ * Call the booting callbacks for the application.
941
+ *
942
+ * @param callbacks
943
+ */
944
+ fireAppCallbacks(callbacks) {
945
+ let index = 0;
946
+ while (index < callbacks.length) {
947
+ callbacks[index](this);
948
+ index++;
949
+ }
950
+ }
951
+ /**
952
+ * Handle the incoming HTTP request and send the response to the browser.
953
+ *
954
+ * @param config Configuration option to pass to the initializer
955
+ */
956
+ async handleRequest(config) {
957
+ this.h3App?.all("/**", async (event) => {
958
+ this.context = (event$1) => this.buildContext(event$1, config);
959
+ this.h3Event = event;
960
+ const context = await this.context(event);
961
+ const kernel = this.make(IKernel);
962
+ this.bind("http.context", () => context);
963
+ this.bind("http.request", () => context.request);
964
+ this.bind("http.response", () => context.response);
965
+ const response = await kernel.handle(context.request);
966
+ if (response) this.bind("http.response", () => response);
967
+ kernel.terminate(context.request, response);
968
+ let finalResponse;
969
+ if (response && ["Response", "JsonResponse"].includes(response.constructor.name)) finalResponse = response.prepare(context.request).send();
970
+ else finalResponse = response;
971
+ return finalResponse;
972
+ });
973
+ }
974
+ /**
975
+ * Build the http context
976
+ *
977
+ * @param event
978
+ * @param config
979
+ * @returns
980
+ */
981
+ async buildContext(event, config, fresh = false) {
982
+ const { HttpContext, Request, Response } = await import("@h3ravel/http");
983
+ event = config?.h3Event ?? event;
984
+ if (!fresh && event._h3ravelContext) return event._h3ravelContext;
985
+ Request.enableHttpMethodParameterOverride();
986
+ const ctx = HttpContext.init({
987
+ app: this,
988
+ request: await Request.create(event, this),
989
+ response: new Response(this, event)
990
+ }, event);
991
+ event._h3ravelContext = ctx;
992
+ return ctx;
993
+ }
994
+ /**
995
+ * Handle the incoming Artisan command.
996
+ */
997
+ async handleCommand() {
998
+ const kernel = this.make(CKernel);
999
+ const status = await kernel.handle();
1000
+ kernel.terminate(status);
1001
+ return status;
1002
+ }
1003
+ /**
1004
+ * Get the URI resolver callback.
1005
+ */
1006
+ getUriResolver() {
1007
+ return this.uriResolver ?? (() => void 0);
1008
+ }
1009
+ /**
1010
+ * Set the URI resolver callback.
1011
+ *
1012
+ * @param callback
1013
+ */
1014
+ setUriResolver(callback) {
1015
+ this.uriResolver = callback;
515
1016
  return this;
516
1017
  }
1018
+ /**
1019
+ * Determine if middleware has been disabled for the application.
1020
+ */
1021
+ shouldSkipMiddleware() {
1022
+ return this.bound("middleware.disable") && this.make("middleware.disable") === true;
1023
+ }
1024
+ /**
1025
+ * Provide safe overides for the app
1026
+ */
1027
+ configure() {
1028
+ return new AppBuilder(this).withKernels().withCommands();
1029
+ }
1030
+ /**
1031
+ * Check if the current application environment matches the one provided
1032
+ */
1033
+ environment(env$1) {
1034
+ return this.make("config").get("app.env") === env$1;
1035
+ }
517
1036
  async fire(h3App, preferredPort) {
1037
+ if (h3App) this.h3App = h3App;
1038
+ if (!this?.h3App) throw new ConfigException("[Provide a H3 app instance in the config or install @h3ravel/http]");
1039
+ return await this.serve(this.h3App, preferredPort);
1040
+ }
1041
+ /**
1042
+ * Fire up the developement server using the user provided arguments
1043
+ *
1044
+ * Port will be auto assigned if provided one is not available
1045
+ *
1046
+ * @param h3App The current H3 app instance
1047
+ * @param preferedPort If provided, this will overide the port set in the evironment
1048
+ */
1049
+ async serve(h3App, preferredPort) {
518
1050
  if (!h3App) throw new InvalidArgumentException("No valid H3 app instance was provided.");
519
- const serve = this.make("http.serve");
1051
+ await this.boot();
1052
+ const serve$1 = this.make("http.serve");
520
1053
  const port = preferredPort ?? env("PORT", 3e3);
521
1054
  const tries = env("RETRIES", 1);
522
1055
  const hostname = env("HOSTNAME", "localhost");
523
1056
  try {
524
1057
  const realPort = await detect(port);
525
1058
  if (port == realPort) {
526
- const server = serve(h3App, {
1059
+ const server = serve$1(h3App, {
527
1060
  port,
528
1061
  hostname,
529
1062
  silent: true
@@ -543,6 +1076,66 @@ var Application = class Application extends Container {
543
1076
  return this;
544
1077
  }
545
1078
  /**
1079
+ * Run the given array of bootstrap classes.
1080
+ *
1081
+ * @param bootstrappers
1082
+ */
1083
+ async bootstrapWith(bootstrappers) {
1084
+ for (const bootstrapper of bootstrappers) {
1085
+ if (this.has("app.events")) this.make("app.events").dispatch("bootstrapping: " + bootstrapper.name, [this]);
1086
+ await this.make(bootstrapper).bootstrap(this);
1087
+ if (this.has("app.events")) this.make("app.events").dispatch("bootstrapped: " + bootstrapper.name, [this]);
1088
+ }
1089
+ this.bootstrapped = true;
1090
+ }
1091
+ /**
1092
+ * Determine if the application has been bootstrapped before.
1093
+ */
1094
+ hasBeenBootstrapped() {
1095
+ return this.bootstrapped;
1096
+ }
1097
+ /**
1098
+ * Save the curretn H3 instance for possible future use.
1099
+ *
1100
+ * @param h3App The current H3 app instance
1101
+ * @returns
1102
+ */
1103
+ setH3App(h3App) {
1104
+ this.h3App = h3App;
1105
+ return this;
1106
+ }
1107
+ /**
1108
+ * Set the HttpContext.
1109
+ *
1110
+ * @param ctx
1111
+ */
1112
+ setHttpContext(ctx) {
1113
+ this.httpContext = ctx;
1114
+ return this;
1115
+ }
1116
+ getHttpContext(key) {
1117
+ return key ? this.httpContext?.[key] : this.httpContext;
1118
+ }
1119
+ /**
1120
+ * Get the application namespace.
1121
+ *
1122
+ * @throws {RuntimeException}
1123
+ */
1124
+ getNamespace() {
1125
+ if (this.namespace != null) return this.namespace;
1126
+ const pkg = createRequire(import.meta.url)(path.join(process.cwd(), "package.json"));
1127
+ for (const [namespace, pathChoice] of Object.entries(data_get(pkg, "autoload.namespaces"))) if (this.getPath("app", "/") === this.getPath("src", pathChoice)) return this.namespace = namespace;
1128
+ throw new RuntimeException("Unable to detect application namespace.");
1129
+ }
1130
+ /**
1131
+ * Get the path of the app dir
1132
+ *
1133
+ * @returns
1134
+ */
1135
+ path() {
1136
+ return this.getPath("app");
1137
+ }
1138
+ /**
546
1139
  * Get the base path of the app
547
1140
  *
548
1141
  * @returns
@@ -593,52 +1186,14 @@ var Application = class Application extends Container {
593
1186
  /**
594
1187
  * Base controller class
595
1188
  */
596
- var Controller = class {
1189
+ var Controller = class extends IController {
597
1190
  app;
598
1191
  constructor(app) {
1192
+ super();
599
1193
  this.app = app;
600
1194
  }
601
1195
  };
602
1196
 
603
- //#endregion
604
- //#region src/Di/Inject.ts
605
- function Inject(...dependencies) {
606
- return function(target) {
607
- target.__inject__ = dependencies;
608
- };
609
- }
610
- /**
611
- * Allows binding dependencies to both class and class methods
612
- *
613
- * @returns
614
- */
615
- function Injectable() {
616
- return (...args) => {
617
- if (args.length === 1) args[0];
618
- if (args.length === 3) {
619
- args[0];
620
- args[1];
621
- args[2];
622
- }
623
- };
624
- }
625
-
626
- //#endregion
627
- //#region src/Exceptions/ConfigException.ts
628
- var ConfigException = class extends Error {
629
- key;
630
- constructor(key, type = "config", cause) {
631
- const info = {
632
- any: `${key} not configured`,
633
- env: `${key} environment variable not configured`,
634
- config: `${key} config not set`
635
- };
636
- const message = Logger.log([["ERROR:", "bgRed"], [info[type], "white"]], " ", false);
637
- super(message, { cause });
638
- this.key = key;
639
- }
640
- };
641
-
642
1197
  //#endregion
643
1198
  //#region src/H3ravel.ts
644
1199
  /**
@@ -652,56 +1207,23 @@ const h3ravel = async (providers = [], basePath = process.cwd(), config = {
652
1207
  initialize: false,
653
1208
  autoload: false,
654
1209
  filteredProviders: []
655
- }, middleware = async () => void 0) => {
1210
+ }) => {
656
1211
  let h3App;
657
- const app = new Application(basePath);
658
- await app.quickStartup(providers, config.filteredProviders, config.autoload);
1212
+ const app = new Application(basePath, "h3ravel");
1213
+ if (config.customPaths) for (const [name, path$1] of Object.entries(config.customPaths)) app.setPath(name, path$1);
1214
+ app.initialize(providers, config.filteredProviders, config.autoload);
659
1215
  try {
660
1216
  h3App = app.make("http.app");
661
- app.context = async (event) => {
662
- if (event._h3ravelContext) return event._h3ravelContext;
663
- Request.enableHttpMethodParameterOverride();
664
- const ctx = HttpContext$1.init({
665
- app,
666
- request: await Request.create(event, app),
667
- response: new Response(event, app)
668
- });
669
- event._h3ravelContext = ctx;
670
- return ctx;
671
- };
672
- const kernel = new Kernel(async (event) => app.context(event), [new LogRequests()]);
673
- h3App.use((event) => kernel.handle(event, middleware));
1217
+ app.setH3App(h3App);
1218
+ app.singleton(IApplication, () => app);
1219
+ if (!Facades.getApplication()) Facades.setApplication(app);
1220
+ if (!Helpers.isLoaded()) Helpers.load(app);
1221
+ await app.handleRequest(config);
674
1222
  } catch {
675
1223
  if (!h3App && config.h3) h3App = config.h3;
676
1224
  }
677
- const originalFire = app.fire;
678
- const proxyThis = (function makeProxy(appRef, orig) {
679
- return new Proxy(appRef, {
680
- get(target, prop, receiver) {
681
- if (prop === "fire") return orig;
682
- return Reflect.get(target, prop, receiver);
683
- },
684
- has(target, prop) {
685
- if (prop === "fire") return true;
686
- return Reflect.has(target, prop);
687
- },
688
- getOwnPropertyDescriptor(target, prop) {
689
- if (prop === "fire") return {
690
- configurable: true,
691
- enumerable: false,
692
- writable: true,
693
- value: orig
694
- };
695
- return Reflect.getOwnPropertyDescriptor(target, prop);
696
- }
697
- });
698
- })(app, originalFire);
699
- if (config.initialize && h3App) return await Reflect.apply(originalFire, app, [h3App]);
700
- app.fire = function() {
701
- if (!h3App) throw new ConfigException("Provide a H3 app instance in the config or install @h3ravel/http");
702
- return Reflect.apply(originalFire, proxyThis, [h3App]);
703
- };
704
- return app;
1225
+ if (config.initialize && h3App) return await app.fire(h3App);
1226
+ return app.setH3App(h3App);
705
1227
  };
706
1228
 
707
1229
  //#endregion
@@ -712,12 +1234,23 @@ const h3ravel = async (providers = [], basePath = process.cwd(), config = {
712
1234
  */
713
1235
  var Kernel = class {
714
1236
  /**
715
- * @param context - A factory function that converts an H3Event into an HttpContext.
1237
+ * The router instance.
1238
+ */
1239
+ router;
1240
+ /**
1241
+ * A factory function that converts an H3Event into an HttpContext.
1242
+ */
1243
+ context;
1244
+ applicationContext;
1245
+ /**
1246
+ * @param app - The current application instance
716
1247
  * @param middleware - An array of middleware classes that will be executed in sequence.
717
1248
  */
718
- constructor(context, middleware = []) {
719
- this.context = context;
1249
+ constructor(app, middleware = []) {
1250
+ this.app = app;
720
1251
  this.middleware = middleware;
1252
+ this.router = app.make("router");
1253
+ this.context = async (event) => app.context(event);
721
1254
  }
722
1255
  /**
723
1256
  * Handles an incoming request and passes it through middleware before invoking the next handler.
@@ -727,145 +1260,45 @@ var Kernel = class {
727
1260
  * @returns A promise resolving to the result of the request pipeline.
728
1261
  */
729
1262
  async handle(event, next) {
1263
+ const { request } = await this.app.context(event);
730
1264
  /**
731
1265
  * Convert the raw event into a standardized HttpContext
732
1266
  */
733
- const ctx = await this.context(event);
734
- const { app } = ctx.request;
735
- /**
736
- * Bind HTTP Response instance to the service container
737
- */
738
- app.bind("http.response", () => {
739
- return ctx.response;
740
- });
741
- /**
742
- * Bind HTTP Request instance to the service container
1267
+ this.applicationContext = await this.context(event);
1268
+ /**
1269
+ * Bind HttpContext, request, and response to the container
743
1270
  */
744
- app.bind("http.request", () => {
745
- return ctx.request;
746
- });
1271
+ this.app.bind("http.context", () => this.applicationContext);
1272
+ this.app.bind("http.request", () => this.applicationContext.request);
1273
+ this.app.bind("http.response", () => this.applicationContext.response);
1274
+ this.app.middlewareHandler = this.app.has(MiddlewareHandler) ? this.app.make(MiddlewareHandler) : new MiddlewareHandler([], this.app);
1275
+ request.constructor.enableHttpMethodParameterOverride();
747
1276
  /**
748
1277
  * Run middleware stack and obtain result
749
1278
  */
750
- const result = await this.runMiddleware(ctx, () => next(ctx));
1279
+ const result = await this.app.middlewareHandler.register(this.middleware).run(this.applicationContext, next);
751
1280
  /**
752
1281
  * If a plain object is returned from a controller or middleware,
753
1282
  * automatically set the JSON Content-Type header for the response.
754
1283
  */
755
- if (result !== void 0 && this.isPlainObject(result)) event.res.headers.set("Content-Type", "application/json; charset=UTF-8");
1284
+ if (result !== void 0 && Obj.isPlainObject(result, true) && !result?.headers) event.res.headers.set("Content-Type", "application/json; charset=UTF-8");
756
1285
  return result;
757
1286
  }
758
1287
  /**
759
- * Sequentially runs middleware in the order they were registered.
760
- *
761
- * @param context - The standardized HttpContext.
762
- * @param next - Callback to execute when middleware completes.
763
- * @returns A promise resolving to the final handler's result.
764
- */
765
- async runMiddleware(context, next) {
766
- let index = -1;
767
- const runner = async (i) => {
768
- if (i <= index) throw new Error("next() called multiple times");
769
- index = i;
770
- const middleware = this.middleware[i];
771
- if (middleware)
772
- /**
773
- * Execute the current middleware and proceed to the next one
774
- */
775
- return middleware.handle(context, () => runner(i + 1));
776
- else
777
- /**
778
- * If no more middleware, call the final handler
779
- */
780
- return next(context);
781
- };
782
- return runner(0);
783
- }
784
- /**
785
- * Utility function to determine if a value is a plain object or array.
786
- *
787
- * @param value - The value to check.
788
- * @returns True if the value is a plain object or array, otherwise false.
789
- */
790
- isPlainObject(value) {
791
- return typeof value === "object" && value !== null && (value.constructor === Object || value.constructor === Array);
792
- }
793
- };
794
-
795
- //#endregion
796
- //#region src/ServiceProvider.ts
797
- const Inference = class {};
798
- var ServiceProvider = class extends Inference {
799
- /**
800
- * The current app instance
801
- */
802
- app;
803
- /**
804
- * Unique Identifier for the service providers
805
- */
806
- static uid;
807
- /**
808
- * Sort order
809
- */
810
- static order;
811
- /**
812
- * Sort priority
813
- */
814
- static priority = 0;
815
- /**
816
- * Indicate that this service provider only runs in console
817
- */
818
- static console = false;
819
- /**
820
- * List of registered console commands
821
- */
822
- registeredCommands;
823
- constructor(app) {
824
- super();
825
- this.app = app;
826
- }
827
- /**
828
- * Register the listed service providers.
829
- *
830
- * @param commands An array of console commands to register.
831
- *
832
- * @deprecated since version 1.16.0. Will be removed in future versions, use `registerCommands` instead
833
- */
834
- commands(commands) {
835
- this.registerCommands(commands);
836
- }
837
- /**
838
- * Register the listed service providers.
839
- *
840
- * @param commands An array of console commands to register.
1288
+ * Resolve the provided callback using the current H3 event instance
841
1289
  */
842
- registerCommands(commands) {
843
- this.registeredCommands = commands;
844
- }
845
- };
846
-
847
- //#endregion
848
- //#region src/Providers/CoreServiceProvider.ts
849
- /**
850
- * Bootstraps core services and bindings.
851
- *
852
- * Bind essential services to the container (logger, config repository).
853
- * Register app-level singletons.
854
- * Set up exception handling.
855
- *
856
- * Auto-Registered
857
- */
858
- var CoreServiceProvider = class extends ServiceProvider {
859
- static priority = 999;
860
- register() {
861
- Object.assign(globalThis, { str });
862
- }
863
- boot() {
864
- try {
865
- Object.assign(globalThis, { asset: this.app.make("asset") });
866
- } catch {}
1290
+ async resolve(event, middleware, handler) {
1291
+ const { Response } = await import("@h3ravel/http");
1292
+ this.middleware = Array.from(new Set([...this.middleware, ...Arr.wrap(middleware)]));
1293
+ return this.handle(event, (ctx) => new Promise((resolve) => {
1294
+ if (Resolver.isAsyncFunction(handler)) handler(ctx).then((response) => {
1295
+ if (response instanceof Response) resolve(response.prepare(ctx.request).send());
1296
+ else resolve(response);
1297
+ });
1298
+ else resolve(handler(ctx));
1299
+ }));
867
1300
  }
868
1301
  };
869
1302
 
870
1303
  //#endregion
871
- export { Application, ConfigException, Container, ContainerResolver, Controller, CoreServiceProvider, Inject, Injectable, Kernel, ProviderRegistry, Registerer, ServiceProvider, h3ravel };
1304
+ export { Application, Container, ContainerResolver, Controller, CoreServiceProvider, Inject, Injectable, Kernel, ProviderRegistry, Registerer, ServiceProvider, h3ravel };