@onebun/core 0.1.18 → 0.1.20
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/package.json +2 -2
- package/src/application/application.test.ts +4 -4
- package/src/application/application.ts +66 -4
- package/src/application/multi-service-application.ts +4 -23
- package/src/docs-examples.test.ts +400 -0
- package/src/index.ts +17 -0
- package/src/module/index.ts +1 -0
- package/src/module/lifecycle.ts +197 -0
- package/src/module/module.test.ts +146 -2
- package/src/module/module.ts +266 -75
- package/src/module/service.ts +0 -10
- package/src/types.ts +48 -3
package/src/module/module.ts
CHANGED
|
@@ -29,6 +29,13 @@ import {
|
|
|
29
29
|
type IConfig,
|
|
30
30
|
type OneBunAppConfig,
|
|
31
31
|
} from './config.interface';
|
|
32
|
+
import {
|
|
33
|
+
hasOnModuleInit,
|
|
34
|
+
hasOnApplicationInit,
|
|
35
|
+
hasOnModuleDestroy,
|
|
36
|
+
hasBeforeApplicationDestroy,
|
|
37
|
+
hasOnApplicationDestroy,
|
|
38
|
+
} from './lifecycle';
|
|
32
39
|
import { getServiceMetadata, getServiceTag } from './service';
|
|
33
40
|
|
|
34
41
|
/**
|
|
@@ -68,7 +75,7 @@ export class OneBunModule implements ModuleInstance {
|
|
|
68
75
|
private controllers: Function[] = [];
|
|
69
76
|
private controllerInstances: Map<Function, Controller> = new Map();
|
|
70
77
|
private serviceInstances: Map<Context.Tag<unknown, unknown>, unknown> = new Map();
|
|
71
|
-
private
|
|
78
|
+
private pendingServiceInits: Array<{ name: string; instance: unknown }> = [];
|
|
72
79
|
private logger: SyncLogger;
|
|
73
80
|
private config: IConfig<OneBunAppConfig>;
|
|
74
81
|
|
|
@@ -162,9 +169,6 @@ export class OneBunModule implements ModuleInstance {
|
|
|
162
169
|
// Merge layers
|
|
163
170
|
layer = Layer.merge(layer, childModule.getLayer());
|
|
164
171
|
|
|
165
|
-
// Add controllers from child module
|
|
166
|
-
controllers.push(...childModule.getControllers());
|
|
167
|
-
|
|
168
172
|
// Get exported services from child module and register them for DI
|
|
169
173
|
const exportedServices = childModule.getExportedServices();
|
|
170
174
|
for (const [tag, instance] of exportedServices) {
|
|
@@ -303,16 +307,11 @@ export class OneBunModule implements ModuleInstance {
|
|
|
303
307
|
.initializeService(this.logger, this.config);
|
|
304
308
|
}
|
|
305
309
|
|
|
306
|
-
// Track services that need
|
|
307
|
-
if (
|
|
308
|
-
|
|
309
|
-
typeof serviceInstance === 'object' &&
|
|
310
|
-
'onAsyncInit' in serviceInstance &&
|
|
311
|
-
typeof (serviceInstance as { onAsyncInit: unknown }).onAsyncInit === 'function'
|
|
312
|
-
) {
|
|
313
|
-
this.pendingAsyncInits.push({
|
|
310
|
+
// Track services that need lifecycle hooks (onModuleInit)
|
|
311
|
+
if (hasOnModuleInit(serviceInstance)) {
|
|
312
|
+
this.pendingServiceInits.push({
|
|
314
313
|
name: provider.name,
|
|
315
|
-
|
|
314
|
+
instance: serviceInstance,
|
|
316
315
|
});
|
|
317
316
|
}
|
|
318
317
|
|
|
@@ -384,48 +383,20 @@ export class OneBunModule implements ModuleInstance {
|
|
|
384
383
|
*/
|
|
385
384
|
createControllerInstances(): Effect.Effect<unknown, never, void> {
|
|
386
385
|
return Effect.sync(() => {
|
|
387
|
-
//
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
if (moduleMetadata && moduleMetadata.providers) {
|
|
393
|
-
// Create map of available services for dependency resolution
|
|
394
|
-
const availableServices = new Map<string, Function>();
|
|
395
|
-
|
|
396
|
-
// For each provider that is a class constructor, add to available services map
|
|
397
|
-
for (const provider of moduleMetadata.providers) {
|
|
398
|
-
if (typeof provider === 'function') {
|
|
399
|
-
availableServices.set(provider.name, provider);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// Also add services from imported modules
|
|
404
|
-
for (const childModule of this.childModules) {
|
|
405
|
-
const childMetadata = getModuleMetadata(childModule.moduleClass);
|
|
406
|
-
if (childMetadata?.exports) {
|
|
407
|
-
for (const exported of childMetadata.exports) {
|
|
408
|
-
if (typeof exported === 'function') {
|
|
409
|
-
availableServices.set(exported.name, exported);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
// Add global services to available services for dependency resolution
|
|
416
|
-
for (const [, instance] of globalServicesRegistry) {
|
|
417
|
-
if (instance && typeof instance === 'object') {
|
|
418
|
-
availableServices.set(instance.constructor.name, instance.constructor);
|
|
419
|
-
}
|
|
386
|
+
// Build map of available services from this module's DI scope (own providers + imported exports + global)
|
|
387
|
+
const availableServices = new Map<string, Function>();
|
|
388
|
+
for (const [, instance] of this.serviceInstances) {
|
|
389
|
+
if (instance && typeof instance === 'object') {
|
|
390
|
+
availableServices.set(instance.constructor.name, instance.constructor);
|
|
420
391
|
}
|
|
392
|
+
}
|
|
421
393
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}
|
|
394
|
+
// Automatically analyze and register dependencies for all controllers of this module
|
|
395
|
+
for (const controllerClass of this.controllers) {
|
|
396
|
+
registerControllerDependencies(controllerClass, availableServices);
|
|
426
397
|
}
|
|
427
398
|
|
|
428
|
-
//
|
|
399
|
+
// Create controller instances with automatic dependency injection
|
|
429
400
|
this.createControllersWithDI();
|
|
430
401
|
}).pipe(Effect.provide(this.rootLayer));
|
|
431
402
|
}
|
|
@@ -558,35 +529,50 @@ export class OneBunModule implements ModuleInstance {
|
|
|
558
529
|
* Setup the module and its dependencies
|
|
559
530
|
*/
|
|
560
531
|
setup(): Effect.Effect<unknown, never, void> {
|
|
561
|
-
return this.
|
|
562
|
-
// Also run
|
|
532
|
+
return this.callServicesOnModuleInit().pipe(
|
|
533
|
+
// Also run onModuleInit for child modules' services
|
|
534
|
+
Effect.flatMap(() =>
|
|
535
|
+
Effect.forEach(this.childModules, (childModule) => childModule.callServicesOnModuleInit(), {
|
|
536
|
+
discard: true,
|
|
537
|
+
}),
|
|
538
|
+
),
|
|
539
|
+
// Create controller instances in child modules first, then this module (each uses its own DI scope)
|
|
563
540
|
Effect.flatMap(() =>
|
|
564
|
-
Effect.forEach(this.childModules, (childModule) => childModule.
|
|
541
|
+
Effect.forEach(this.childModules, (childModule) => childModule.createControllerInstances(), {
|
|
565
542
|
discard: true,
|
|
566
543
|
}),
|
|
567
544
|
),
|
|
568
|
-
// Then create controller instances
|
|
569
545
|
Effect.flatMap(() => this.createControllerInstances()),
|
|
546
|
+
// Then call onModuleInit for controllers
|
|
547
|
+
Effect.flatMap(() => this.callControllersOnModuleInit()),
|
|
548
|
+
// Also run onModuleInit for child modules' controllers
|
|
549
|
+
Effect.flatMap(() =>
|
|
550
|
+
Effect.forEach(this.childModules, (childModule) => childModule.callControllersOnModuleInit(), {
|
|
551
|
+
discard: true,
|
|
552
|
+
}),
|
|
553
|
+
),
|
|
570
554
|
);
|
|
571
555
|
}
|
|
572
556
|
|
|
573
557
|
/**
|
|
574
|
-
*
|
|
558
|
+
* Call onModuleInit lifecycle hook for all services that implement it
|
|
575
559
|
*/
|
|
576
|
-
|
|
577
|
-
if (this.
|
|
560
|
+
callServicesOnModuleInit(): Effect.Effect<unknown, never, void> {
|
|
561
|
+
if (this.pendingServiceInits.length === 0) {
|
|
578
562
|
return Effect.void;
|
|
579
563
|
}
|
|
580
564
|
|
|
581
|
-
this.logger.debug(`
|
|
565
|
+
this.logger.debug(`Calling onModuleInit for ${this.pendingServiceInits.length} service(s)`);
|
|
582
566
|
|
|
583
|
-
// Run all
|
|
584
|
-
const initPromises = this.
|
|
567
|
+
// Run all service onModuleInit hooks sequentially
|
|
568
|
+
const initPromises = this.pendingServiceInits.map(async ({ name, instance }) => {
|
|
585
569
|
try {
|
|
586
|
-
|
|
587
|
-
|
|
570
|
+
if (hasOnModuleInit(instance)) {
|
|
571
|
+
await instance.onModuleInit();
|
|
572
|
+
}
|
|
573
|
+
this.logger.debug(`Service ${name} onModuleInit completed`);
|
|
588
574
|
} catch (error) {
|
|
589
|
-
this.logger.error(`Service ${name}
|
|
575
|
+
this.logger.error(`Service ${name} onModuleInit failed: ${error}`);
|
|
590
576
|
throw error;
|
|
591
577
|
}
|
|
592
578
|
});
|
|
@@ -594,45 +580,250 @@ export class OneBunModule implements ModuleInstance {
|
|
|
594
580
|
return Effect.promise(() => Promise.all(initPromises)).pipe(
|
|
595
581
|
Effect.map(() => {
|
|
596
582
|
// Clear the list after initialization
|
|
597
|
-
this.
|
|
583
|
+
this.pendingServiceInits = [];
|
|
598
584
|
}),
|
|
599
585
|
);
|
|
600
586
|
}
|
|
601
587
|
|
|
602
588
|
/**
|
|
603
|
-
*
|
|
589
|
+
* Call onModuleInit lifecycle hook for all controllers that implement it
|
|
590
|
+
*/
|
|
591
|
+
callControllersOnModuleInit(): Effect.Effect<unknown, never, void> {
|
|
592
|
+
const controllers = Array.from(this.controllerInstances.values());
|
|
593
|
+
const controllersWithInit = controllers.filter((c): c is Controller & { onModuleInit(): Promise<void> | void } =>
|
|
594
|
+
hasOnModuleInit(c),
|
|
595
|
+
);
|
|
596
|
+
|
|
597
|
+
if (controllersWithInit.length === 0) {
|
|
598
|
+
return Effect.void;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
this.logger.debug(`Calling onModuleInit for ${controllersWithInit.length} controller(s)`);
|
|
602
|
+
|
|
603
|
+
const initPromises = controllersWithInit.map(async (controller) => {
|
|
604
|
+
try {
|
|
605
|
+
await controller.onModuleInit();
|
|
606
|
+
this.logger.debug(`Controller ${controller.constructor.name} onModuleInit completed`);
|
|
607
|
+
} catch (error) {
|
|
608
|
+
this.logger.error(`Controller ${controller.constructor.name} onModuleInit failed: ${error}`);
|
|
609
|
+
throw error;
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
return Effect.promise(() => Promise.all(initPromises));
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Call onApplicationInit lifecycle hook for all services and controllers
|
|
618
|
+
*/
|
|
619
|
+
async callOnApplicationInit(): Promise<void> {
|
|
620
|
+
// Call for services
|
|
621
|
+
for (const [, instance] of this.serviceInstances) {
|
|
622
|
+
if (hasOnApplicationInit(instance)) {
|
|
623
|
+
try {
|
|
624
|
+
await instance.onApplicationInit();
|
|
625
|
+
this.logger.debug(`Service ${(instance as object).constructor.name} onApplicationInit completed`);
|
|
626
|
+
} catch (error) {
|
|
627
|
+
this.logger.error(`Service ${(instance as object).constructor.name} onApplicationInit failed: ${error}`);
|
|
628
|
+
throw error;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// Call for controllers
|
|
634
|
+
for (const [, controller] of this.controllerInstances) {
|
|
635
|
+
if (hasOnApplicationInit(controller)) {
|
|
636
|
+
try {
|
|
637
|
+
await controller.onApplicationInit();
|
|
638
|
+
this.logger.debug(`Controller ${controller.constructor.name} onApplicationInit completed`);
|
|
639
|
+
} catch (error) {
|
|
640
|
+
this.logger.error(`Controller ${controller.constructor.name} onApplicationInit failed: ${error}`);
|
|
641
|
+
throw error;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Call for child modules
|
|
647
|
+
for (const childModule of this.childModules) {
|
|
648
|
+
await childModule.callOnApplicationInit();
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Call beforeApplicationDestroy lifecycle hook for all services and controllers
|
|
654
|
+
*/
|
|
655
|
+
async callBeforeApplicationDestroy(signal?: string): Promise<void> {
|
|
656
|
+
// Call for services
|
|
657
|
+
for (const [, instance] of this.serviceInstances) {
|
|
658
|
+
if (hasBeforeApplicationDestroy(instance)) {
|
|
659
|
+
try {
|
|
660
|
+
await instance.beforeApplicationDestroy(signal);
|
|
661
|
+
this.logger.debug(`Service ${(instance as object).constructor.name} beforeApplicationDestroy completed`);
|
|
662
|
+
} catch (error) {
|
|
663
|
+
this.logger.error(`Service ${(instance as object).constructor.name} beforeApplicationDestroy failed: ${error}`);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Call for controllers
|
|
669
|
+
for (const [, controller] of this.controllerInstances) {
|
|
670
|
+
if (hasBeforeApplicationDestroy(controller)) {
|
|
671
|
+
try {
|
|
672
|
+
await controller.beforeApplicationDestroy(signal);
|
|
673
|
+
this.logger.debug(`Controller ${controller.constructor.name} beforeApplicationDestroy completed`);
|
|
674
|
+
} catch (error) {
|
|
675
|
+
this.logger.error(`Controller ${controller.constructor.name} beforeApplicationDestroy failed: ${error}`);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// Call for child modules
|
|
681
|
+
for (const childModule of this.childModules) {
|
|
682
|
+
await childModule.callBeforeApplicationDestroy(signal);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Call onModuleDestroy lifecycle hook for controllers first, then services
|
|
688
|
+
*/
|
|
689
|
+
async callOnModuleDestroy(): Promise<void> {
|
|
690
|
+
// Call for controllers first (reverse order of creation)
|
|
691
|
+
const controllers = Array.from(this.controllerInstances.values()).reverse();
|
|
692
|
+
for (const controller of controllers) {
|
|
693
|
+
if (hasOnModuleDestroy(controller)) {
|
|
694
|
+
try {
|
|
695
|
+
await controller.onModuleDestroy();
|
|
696
|
+
this.logger.debug(`Controller ${controller.constructor.name} onModuleDestroy completed`);
|
|
697
|
+
} catch (error) {
|
|
698
|
+
this.logger.error(`Controller ${controller.constructor.name} onModuleDestroy failed: ${error}`);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Call for services (reverse order of creation)
|
|
704
|
+
const services = Array.from(this.serviceInstances.values()).reverse();
|
|
705
|
+
for (const instance of services) {
|
|
706
|
+
if (hasOnModuleDestroy(instance)) {
|
|
707
|
+
try {
|
|
708
|
+
await instance.onModuleDestroy();
|
|
709
|
+
this.logger.debug(`Service ${(instance as object).constructor.name} onModuleDestroy completed`);
|
|
710
|
+
} catch (error) {
|
|
711
|
+
this.logger.error(`Service ${(instance as object).constructor.name} onModuleDestroy failed: ${error}`);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
// Call for child modules
|
|
717
|
+
for (const childModule of this.childModules) {
|
|
718
|
+
await childModule.callOnModuleDestroy();
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Call onApplicationDestroy lifecycle hook for all services and controllers
|
|
724
|
+
*/
|
|
725
|
+
async callOnApplicationDestroy(signal?: string): Promise<void> {
|
|
726
|
+
// Call for services
|
|
727
|
+
for (const [, instance] of this.serviceInstances) {
|
|
728
|
+
if (hasOnApplicationDestroy(instance)) {
|
|
729
|
+
try {
|
|
730
|
+
await instance.onApplicationDestroy(signal);
|
|
731
|
+
this.logger.debug(`Service ${(instance as object).constructor.name} onApplicationDestroy completed`);
|
|
732
|
+
} catch (error) {
|
|
733
|
+
this.logger.error(`Service ${(instance as object).constructor.name} onApplicationDestroy failed: ${error}`);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// Call for controllers
|
|
739
|
+
for (const [, controller] of this.controllerInstances) {
|
|
740
|
+
if (hasOnApplicationDestroy(controller)) {
|
|
741
|
+
try {
|
|
742
|
+
await controller.onApplicationDestroy(signal);
|
|
743
|
+
this.logger.debug(`Controller ${controller.constructor.name} onApplicationDestroy completed`);
|
|
744
|
+
} catch (error) {
|
|
745
|
+
this.logger.error(`Controller ${controller.constructor.name} onApplicationDestroy failed: ${error}`);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// Call for child modules
|
|
751
|
+
for (const childModule of this.childModules) {
|
|
752
|
+
await childModule.callOnApplicationDestroy(signal);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Get all controllers from this module and child modules (recursive).
|
|
758
|
+
* Used by the application layer for routing and lifecycle.
|
|
604
759
|
*/
|
|
605
760
|
getControllers(): Function[] {
|
|
606
|
-
|
|
761
|
+
const fromChildren = this.childModules.flatMap((child) => child.getControllers());
|
|
762
|
+
|
|
763
|
+
return [...this.controllers, ...fromChildren];
|
|
607
764
|
}
|
|
608
765
|
|
|
609
766
|
/**
|
|
610
|
-
* Get controller instance
|
|
767
|
+
* Get controller instance (searches this module then child modules recursively).
|
|
611
768
|
*/
|
|
612
769
|
getControllerInstance(controllerClass: Function): Controller | undefined {
|
|
613
770
|
const instance = this.controllerInstances.get(controllerClass);
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
771
|
+
if (instance) {
|
|
772
|
+
return instance;
|
|
773
|
+
}
|
|
774
|
+
for (const childModule of this.childModules) {
|
|
775
|
+
const childInstance = childModule.getControllerInstance(controllerClass);
|
|
776
|
+
if (childInstance) {
|
|
777
|
+
return childInstance;
|
|
778
|
+
}
|
|
617
779
|
}
|
|
780
|
+
this.logger.warn(`No instance found for controller ${controllerClass.name}`);
|
|
618
781
|
|
|
619
|
-
return
|
|
782
|
+
return undefined;
|
|
620
783
|
}
|
|
621
784
|
|
|
622
785
|
/**
|
|
623
|
-
* Get all controller instances
|
|
786
|
+
* Get all controller instances from this module and child modules (recursive).
|
|
624
787
|
*/
|
|
625
788
|
getControllerInstances(): Map<Function, Controller> {
|
|
626
|
-
|
|
789
|
+
const merged = new Map<Function, Controller>(this.controllerInstances);
|
|
790
|
+
for (const childModule of this.childModules) {
|
|
791
|
+
for (const [cls, instance] of childModule.getControllerInstances()) {
|
|
792
|
+
merged.set(cls, instance);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
return merged;
|
|
627
797
|
}
|
|
628
798
|
|
|
629
799
|
/**
|
|
630
|
-
* Get service instance
|
|
800
|
+
* Get service instance by tag
|
|
631
801
|
*/
|
|
632
802
|
getServiceInstance<T>(tag: Context.Tag<T, T>): T | undefined {
|
|
633
803
|
return this.serviceInstances.get(tag as Context.Tag<unknown, unknown>) as T | undefined;
|
|
634
804
|
}
|
|
635
805
|
|
|
806
|
+
/**
|
|
807
|
+
* Get service instance by class
|
|
808
|
+
*/
|
|
809
|
+
getServiceByClass<T>(serviceClass: new (...args: unknown[]) => T): T | undefined {
|
|
810
|
+
try {
|
|
811
|
+
const tag = getServiceTag(serviceClass);
|
|
812
|
+
|
|
813
|
+
return this.getServiceInstance(tag);
|
|
814
|
+
} catch {
|
|
815
|
+
// Service doesn't have @Service decorator or not found
|
|
816
|
+
return undefined;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Get all service instances
|
|
822
|
+
*/
|
|
823
|
+
getAllServiceInstances(): Map<Context.Tag<unknown, unknown>, unknown> {
|
|
824
|
+
return new Map(this.serviceInstances);
|
|
825
|
+
}
|
|
826
|
+
|
|
636
827
|
/**
|
|
637
828
|
* Get the Layer for this module
|
|
638
829
|
*/
|
package/src/module/service.ts
CHANGED
|
@@ -99,16 +99,6 @@ export class BaseService {
|
|
|
99
99
|
this.logger.debug(`Service ${className} initialized`);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
/**
|
|
103
|
-
* Async initialization hook - called by the framework after initializeService()
|
|
104
|
-
* Override in subclasses that need async initialization (e.g., database connections)
|
|
105
|
-
* The framework will await this method before making the service available
|
|
106
|
-
* @internal
|
|
107
|
-
*/
|
|
108
|
-
async onAsyncInit(): Promise<void> {
|
|
109
|
-
// Default: no async init needed
|
|
110
|
-
}
|
|
111
|
-
|
|
112
102
|
/**
|
|
113
103
|
* Check if service is initialized
|
|
114
104
|
* @internal
|
package/src/types.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Type } from 'arktype';
|
|
2
2
|
import type { Effect, Layer } from 'effect';
|
|
3
3
|
|
|
4
|
-
import type { Logger } from '@onebun/logger';
|
|
4
|
+
import type { Logger, LoggerOptions } from '@onebun/logger';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Base interface for all OneBun services
|
|
@@ -58,6 +58,31 @@ export interface ModuleInstance {
|
|
|
58
58
|
* Get controller instance
|
|
59
59
|
*/
|
|
60
60
|
getControllerInstance?(controllerClass: Function): unknown;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Call onApplicationInit lifecycle hook for all services and controllers
|
|
64
|
+
*/
|
|
65
|
+
callOnApplicationInit?(): Promise<void>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Call beforeApplicationDestroy lifecycle hook for all services and controllers
|
|
69
|
+
*/
|
|
70
|
+
callBeforeApplicationDestroy?(signal?: string): Promise<void>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Call onModuleDestroy lifecycle hook for controllers first, then services
|
|
74
|
+
*/
|
|
75
|
+
callOnModuleDestroy?(): Promise<void>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Call onApplicationDestroy lifecycle hook for all services and controllers
|
|
79
|
+
*/
|
|
80
|
+
callOnApplicationDestroy?(signal?: string): Promise<void>;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get service instance by class
|
|
84
|
+
*/
|
|
85
|
+
getServiceByClass?<T>(serviceClass: new (...args: unknown[]) => T): T | undefined;
|
|
61
86
|
}
|
|
62
87
|
|
|
63
88
|
/**
|
|
@@ -107,8 +132,28 @@ export interface ApplicationOptions {
|
|
|
107
132
|
development?: boolean;
|
|
108
133
|
|
|
109
134
|
/**
|
|
110
|
-
* Logger
|
|
111
|
-
*
|
|
135
|
+
* Logger configuration options.
|
|
136
|
+
* Provides a declarative way to configure logging.
|
|
137
|
+
*
|
|
138
|
+
* Priority: loggerLayer > loggerOptions > LOG_LEVEL/LOG_FORMAT env > NODE_ENV defaults
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```typescript
|
|
142
|
+
* const app = new OneBunApplication(AppModule, {
|
|
143
|
+
* loggerOptions: {
|
|
144
|
+
* minLevel: 'info',
|
|
145
|
+
* format: 'json',
|
|
146
|
+
* defaultContext: { service: 'user-service' },
|
|
147
|
+
* },
|
|
148
|
+
* });
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
loggerOptions?: LoggerOptions;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Logger layer to use (advanced).
|
|
155
|
+
* If provided, takes precedence over loggerOptions.
|
|
156
|
+
* Use loggerOptions for simpler configuration.
|
|
112
157
|
*/
|
|
113
158
|
loggerLayer?: Layer.Layer<Logger>;
|
|
114
159
|
|