@grupodiariodaregiao/bunstone 0.4.2 → 0.4.4

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.d.ts CHANGED
@@ -55,6 +55,7 @@ export * from "./lib/jwt";
55
55
  export * from "./lib/jwt/jwt-module";
56
56
  export { JwtService } from "./lib/jwt/jwt.service";
57
57
  export * from "./lib/module";
58
+ export * from "./lib/on-module";
58
59
  export * from "./lib/openapi";
59
60
  export * from "./lib/render";
60
61
  export * from "./lib/types/options";
package/dist/index.js CHANGED
@@ -117086,12 +117086,22 @@ class AppStartup {
117086
117086
  static elysia = new Elysia;
117087
117087
  static logger = new Logger(AppStartup.name);
117088
117088
  static registeredSagas = new WeakSet;
117089
+ static initializedModuleHooks = new WeakSet;
117090
+ static destroyedModuleHooks = new WeakSet;
117091
+ static destroyPromise = null;
117092
+ static hasBeenDestroyed = false;
117093
+ static rootModule;
117089
117094
  static viewBundles = new Map;
117090
117095
  static globalRateLimitConfig;
117091
117096
  static rateLimitService = new RateLimitService;
117092
117097
  static async create(module, options) {
117093
117098
  try {
117094
117099
  AppStartup.elysia = new Elysia;
117100
+ AppStartup.rootModule = module;
117101
+ AppStartup.initializedModuleHooks = new WeakSet;
117102
+ AppStartup.destroyedModuleHooks = new WeakSet;
117103
+ AppStartup.destroyPromise = null;
117104
+ AppStartup.hasBeenDestroyed = false;
117095
117105
  const publicExists = await Bun.file("public").exists();
117096
117106
  if (!publicExists)
117097
117107
  await mkdir("./public", { recursive: true });
@@ -117144,6 +117154,9 @@ class AppStartup {
117144
117154
  message: error48 instanceof Error ? error48.message : "Internal Server Error"
117145
117155
  };
117146
117156
  });
117157
+ AppStartup.elysia.onStop(async () => {
117158
+ await AppStartup.executeDestroyLifecycle();
117159
+ });
117147
117160
  if (options?.cors) {
117148
117161
  AppStartup.elysia.use(cors(options.cors));
117149
117162
  }
@@ -117181,7 +117194,7 @@ class AppStartup {
117181
117194
  }));
117182
117195
  }
117183
117196
  AppStartup.globalRateLimitConfig = options?.rateLimit;
117184
- AppStartup.registerModules(module);
117197
+ await AppStartup.registerModules(module);
117185
117198
  return {
117186
117199
  listen: AppStartup.listen,
117187
117200
  getElysia: () => AppStartup.elysia
@@ -117293,6 +117306,28 @@ if (document.readyState === 'loading') {
117293
117306
  AppStartup.logger.log(`App is running at http://localhost:${port}`);
117294
117307
  AppStartup.elysia.listen(port);
117295
117308
  }
117309
+ static async executeDestroyLifecycle() {
117310
+ if (!AppStartup.rootModule) {
117311
+ return;
117312
+ }
117313
+ if (AppStartup.hasBeenDestroyed) {
117314
+ return;
117315
+ }
117316
+ if (AppStartup.destroyPromise) {
117317
+ await AppStartup.destroyPromise;
117318
+ return;
117319
+ }
117320
+ AppStartup.destroyPromise = (async () => {
117321
+ await AppStartup.destroyModules(AppStartup.rootModule);
117322
+ AppStartup.hasBeenDestroyed = true;
117323
+ })().catch((error48) => {
117324
+ AppStartup.logger.error(`Error while executing OnModuleDestroy hooks: ${error48?.message || error48}`);
117325
+ throw error48;
117326
+ }).finally(() => {
117327
+ AppStartup.destroyPromise = null;
117328
+ });
117329
+ await AppStartup.destroyPromise;
117330
+ }
117296
117331
  static async executeControllerMethod(context, controller, method) {
117297
117332
  const args = await processParameters(context, controller, method);
117298
117333
  const result = await controller[method](...args);
@@ -117336,7 +117371,7 @@ if (document.readyState === 'loading') {
117336
117371
  }
117337
117372
  return result;
117338
117373
  }
117339
- static registerModules(module) {
117374
+ static async registerModules(module) {
117340
117375
  const isGlobal = Reflect.getMetadata("dip:module:global", module);
117341
117376
  if (isGlobal) {
117342
117377
  const injectables = Reflect.getMetadata("dip:injectables", module);
@@ -117355,8 +117390,52 @@ if (document.readyState === 'loading') {
117355
117390
  AppStartup.registerRabbitMQConsumers(module);
117356
117391
  const modules = Reflect.getMetadata("dip:modules", module) || [];
117357
117392
  for (const mod of modules) {
117358
- AppStartup.registerModules(mod);
117393
+ await AppStartup.registerModules(mod);
117394
+ }
117395
+ await AppStartup.executeOnModuleInit(module);
117396
+ }
117397
+ static async destroyModules(module) {
117398
+ const modules = Reflect.getMetadata("dip:modules", module) || [];
117399
+ for (const mod of modules) {
117400
+ await AppStartup.destroyModules(mod);
117401
+ }
117402
+ await AppStartup.executeOnModuleDestroy(module);
117403
+ }
117404
+ static async executeOnModuleInit(module) {
117405
+ const injectables = Reflect.getMetadata("dip:injectables", module);
117406
+ if (!injectables) {
117407
+ return;
117359
117408
  }
117409
+ for (const provider of injectables.values()) {
117410
+ if (AppStartup.initializedModuleHooks.has(provider)) {
117411
+ continue;
117412
+ }
117413
+ if (AppStartup.hasOnModuleInit(provider)) {
117414
+ AppStartup.initializedModuleHooks.add(provider);
117415
+ await provider.onModuleInit();
117416
+ }
117417
+ }
117418
+ }
117419
+ static async executeOnModuleDestroy(module) {
117420
+ const injectables = Reflect.getMetadata("dip:injectables", module);
117421
+ if (!injectables) {
117422
+ return;
117423
+ }
117424
+ for (const provider of injectables.values()) {
117425
+ if (AppStartup.destroyedModuleHooks.has(provider)) {
117426
+ continue;
117427
+ }
117428
+ if (AppStartup.hasOnModuleDestroy(provider)) {
117429
+ AppStartup.destroyedModuleHooks.add(provider);
117430
+ await provider.onModuleDestroy();
117431
+ }
117432
+ }
117433
+ }
117434
+ static hasOnModuleInit(provider) {
117435
+ return !!provider && typeof provider.onModuleInit === "function";
117436
+ }
117437
+ static hasOnModuleDestroy(provider) {
117438
+ return !!provider && typeof provider.onModuleDestroy === "function";
117360
117439
  }
117361
117440
  static registerRoutes(module) {
117362
117441
  const controllers = Reflect.getMetadata("dip:module:routes", module);
@@ -9,6 +9,11 @@ export declare class AppStartup {
9
9
  private static elysia;
10
10
  private static readonly logger;
11
11
  private static readonly registeredSagas;
12
+ private static initializedModuleHooks;
13
+ private static destroyedModuleHooks;
14
+ private static destroyPromise;
15
+ private static hasBeenDestroyed;
16
+ private static rootModule;
12
17
  private static readonly viewBundles;
13
18
  private static globalRateLimitConfig;
14
19
  private static rateLimitService;
@@ -67,8 +72,14 @@ export declare class AppStartup {
67
72
  * @param port The port number to listen on.
68
73
  */
69
74
  static listen(port: number): void;
75
+ private static executeDestroyLifecycle;
70
76
  private static executeControllerMethod;
71
77
  private static registerModules;
78
+ private static destroyModules;
79
+ private static executeOnModuleInit;
80
+ private static executeOnModuleDestroy;
81
+ private static hasOnModuleInit;
82
+ private static hasOnModuleDestroy;
72
83
  private static registerRoutes;
73
84
  /**
74
85
  * Builds effective rate limit configuration by merging global config with method config
@@ -0,0 +1,2 @@
1
+ export * from "./on-module-destroy";
2
+ export * from "./on-module-init";
@@ -0,0 +1,3 @@
1
+ export interface OnModuleDestroy {
2
+ onModuleDestroy(): Promise<void> | void;
3
+ }
@@ -0,0 +1,3 @@
1
+ export interface OnModuleInit {
2
+ onModuleInit(): Promise<void> | void;
3
+ }
@@ -28,6 +28,8 @@ import { ConfigurationError } from "./errors";
28
28
  import { HttpException } from "./http-exceptions";
29
29
  import { HTTP_HEADERS_METADATA } from "./http-methods";
30
30
  import { ParamType, processParameters } from "./http-params";
31
+ import type { OnModuleDestroy } from "./on-module/on-module-destroy";
32
+ import type { OnModuleInit } from "./on-module/on-module-init";
31
33
  import {
32
34
  API_HEADERS_METADATA,
33
35
  API_OPERATION_METADATA,
@@ -57,6 +59,11 @@ export class AppStartup {
57
59
  private static elysia: Elysia = new Elysia();
58
60
  private static readonly logger = new Logger(AppStartup.name);
59
61
  private static readonly registeredSagas = new WeakSet<any>();
62
+ private static initializedModuleHooks = new WeakSet<OnModuleInit>();
63
+ private static destroyedModuleHooks = new WeakSet<OnModuleDestroy>();
64
+ private static destroyPromise: Promise<void> | null = null;
65
+ private static hasBeenDestroyed = false;
66
+ private static rootModule: any;
60
67
  private static readonly viewBundles = new Map<string, string>();
61
68
  private static globalRateLimitConfig: RateLimitGlobalConfig | undefined;
62
69
  private static rateLimitService: RateLimitService = new RateLimitService();
@@ -71,6 +78,11 @@ export class AppStartup {
71
78
  static async create(module: any, options?: Options) {
72
79
  try {
73
80
  AppStartup.elysia = new Elysia(); // Reset for each creation
81
+ AppStartup.rootModule = module;
82
+ AppStartup.initializedModuleHooks = new WeakSet<OnModuleInit>();
83
+ AppStartup.destroyedModuleHooks = new WeakSet<OnModuleDestroy>();
84
+ AppStartup.destroyPromise = null;
85
+ AppStartup.hasBeenDestroyed = false;
74
86
 
75
87
  const publicExists = await Bun.file("public").exists();
76
88
  // Ensure public directory exists before static plugin uses it
@@ -149,6 +161,10 @@ export class AppStartup {
149
161
  };
150
162
  });
151
163
 
164
+ AppStartup.elysia.onStop(async () => {
165
+ await AppStartup.executeDestroyLifecycle();
166
+ });
167
+
152
168
  if (options?.cors) {
153
169
  AppStartup.elysia.use(cors(options.cors));
154
170
  }
@@ -202,7 +218,7 @@ export class AppStartup {
202
218
  // Store global rate limit config
203
219
  AppStartup.globalRateLimitConfig = options?.rateLimit;
204
220
 
205
- AppStartup.registerModules(module);
221
+ await AppStartup.registerModules(module);
206
222
  return {
207
223
  /**
208
224
  * Starts the server on the specified port.
@@ -352,6 +368,37 @@ if (document.readyState === 'loading') {
352
368
  AppStartup.elysia.listen(port);
353
369
  }
354
370
 
371
+ private static async executeDestroyLifecycle() {
372
+ if (!AppStartup.rootModule) {
373
+ return;
374
+ }
375
+
376
+ if (AppStartup.hasBeenDestroyed) {
377
+ return;
378
+ }
379
+
380
+ if (AppStartup.destroyPromise) {
381
+ await AppStartup.destroyPromise;
382
+ return;
383
+ }
384
+
385
+ AppStartup.destroyPromise = (async () => {
386
+ await AppStartup.destroyModules(AppStartup.rootModule);
387
+ AppStartup.hasBeenDestroyed = true;
388
+ })()
389
+ .catch((error) => {
390
+ AppStartup.logger.error(
391
+ `Error while executing OnModuleDestroy hooks: ${error?.message || error}`,
392
+ );
393
+ throw error;
394
+ })
395
+ .finally(() => {
396
+ AppStartup.destroyPromise = null;
397
+ });
398
+
399
+ await AppStartup.destroyPromise;
400
+ }
401
+
355
402
  private static async executeControllerMethod(
356
403
  context: any,
357
404
  controller: any,
@@ -436,7 +483,7 @@ if (document.readyState === 'loading') {
436
483
  return result;
437
484
  }
438
485
 
439
- private static registerModules(module: any) {
486
+ private static async registerModules(module: any) {
440
487
  const isGlobal = Reflect.getMetadata("dip:module:global", module);
441
488
  if (isGlobal) {
442
489
  const injectables: Map<any, any> = Reflect.getMetadata(
@@ -461,8 +508,74 @@ if (document.readyState === 'loading') {
461
508
  const modules = Reflect.getMetadata("dip:modules", module) || [];
462
509
 
463
510
  for (const mod of modules) {
464
- AppStartup.registerModules(mod);
511
+ await AppStartup.registerModules(mod);
512
+ }
513
+
514
+ await AppStartup.executeOnModuleInit(module);
515
+ }
516
+
517
+ private static async destroyModules(module: any) {
518
+ const modules = Reflect.getMetadata("dip:modules", module) || [];
519
+
520
+ for (const mod of modules) {
521
+ await AppStartup.destroyModules(mod);
465
522
  }
523
+
524
+ await AppStartup.executeOnModuleDestroy(module);
525
+ }
526
+
527
+ private static async executeOnModuleInit(module: any) {
528
+ const injectables: Map<any, any> | undefined = Reflect.getMetadata(
529
+ "dip:injectables",
530
+ module,
531
+ );
532
+
533
+ if (!injectables) {
534
+ return;
535
+ }
536
+
537
+ for (const provider of injectables.values()) {
538
+ if (AppStartup.initializedModuleHooks.has(provider)) {
539
+ continue;
540
+ }
541
+
542
+ if (AppStartup.hasOnModuleInit(provider)) {
543
+ AppStartup.initializedModuleHooks.add(provider);
544
+ await provider.onModuleInit();
545
+ }
546
+ }
547
+ }
548
+
549
+ private static async executeOnModuleDestroy(module: any) {
550
+ const injectables: Map<any, any> | undefined = Reflect.getMetadata(
551
+ "dip:injectables",
552
+ module,
553
+ );
554
+
555
+ if (!injectables) {
556
+ return;
557
+ }
558
+
559
+ for (const provider of injectables.values()) {
560
+ if (AppStartup.destroyedModuleHooks.has(provider)) {
561
+ continue;
562
+ }
563
+
564
+ if (AppStartup.hasOnModuleDestroy(provider)) {
565
+ AppStartup.destroyedModuleHooks.add(provider);
566
+ await provider.onModuleDestroy();
567
+ }
568
+ }
569
+ }
570
+
571
+ private static hasOnModuleInit(provider: any): provider is OnModuleInit {
572
+ return !!provider && typeof provider.onModuleInit === "function";
573
+ }
574
+
575
+ private static hasOnModuleDestroy(
576
+ provider: any,
577
+ ): provider is OnModuleDestroy {
578
+ return !!provider && typeof provider.onModuleDestroy === "function";
466
579
  }
467
580
 
468
581
  private static registerRoutes(module: any) {
@@ -0,0 +1,2 @@
1
+ export * from "./on-module-destroy";
2
+ export * from "./on-module-init";
@@ -0,0 +1,3 @@
1
+ export interface OnModuleDestroy {
2
+ onModuleDestroy(): Promise<void> | void;
3
+ }
@@ -0,0 +1,3 @@
1
+ export interface OnModuleInit {
2
+ onModuleInit(): Promise<void> | void;
3
+ }
package/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "types": "./dist/*.d.ts"
14
14
  }
15
15
  },
16
- "version": "0.4.2",
16
+ "version": "0.4.4",
17
17
  "homepage": "https://bunstone.diario.one/",
18
18
  "repository": {
19
19
  "url": "https://github.com/diariodaregiao/bunstone.git",