@fluojs/runtime 1.0.0-beta.8 → 1.0.0

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/bootstrap.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import { Container } from '@fluojs/di';
2
- import { DefaultBinder } from '@fluojs/http/internal';
3
2
  import { InvariantError } from '@fluojs/core';
4
- import { defineModuleMetadata, getClassDiMetadata } from '@fluojs/core/internal';
5
3
  import { createDispatcher, createHandlerMapping } from '@fluojs/http';
6
4
  import { DuplicateProviderError } from './errors.js';
7
5
  import { createBootstrapTimingDiagnostics } from './health/diagnostics.js';
6
+ import { defineRuntimeModuleMetadata, getRuntimeClassDiMetadata } from './internal/core-metadata.js';
7
+ import { RuntimeDefaultBinder } from './internal/http-runtime.js';
8
8
  import { createConsoleApplicationLogger } from './logging/logger.js';
9
9
  import { compileModuleGraph, providerToken } from './module-graph.js';
10
10
  import { createRuntimePlatformShell } from './platform-shell.js';
11
- import { APPLICATION_LOGGER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, PLATFORM_SHELL, RUNTIME_CONTAINER } from './tokens.js';
11
+ import { APPLICATION_LOGGER, BOOTSTRAP_READY_SIGNAL, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, PLATFORM_SHELL, RUNTIME_CLEANUP_REGISTRATION, RUNTIME_CONTAINER } from './tokens.js';
12
12
  const DEFAULT_MICROSERVICE_TOKEN = Symbol.for('fluo.microservices.service');
13
13
  const runtimePerformance = globalThis.performance;
14
14
  async function runExceptionFilters(filters, error, request, response, requestId) {
@@ -26,16 +26,16 @@ async function runExceptionFilters(filters, error, request, response, requestId)
26
26
  }
27
27
  function providerScope(provider) {
28
28
  if (typeof provider === 'function') {
29
- return getClassDiMetadata(provider)?.scope ?? 'singleton';
29
+ return getRuntimeClassDiMetadata(provider)?.scope ?? 'singleton';
30
30
  }
31
31
  if ('useValue' in provider) {
32
32
  return 'singleton';
33
33
  }
34
34
  if ('useClass' in provider) {
35
- return provider.scope ?? getClassDiMetadata(provider.useClass)?.scope ?? 'singleton';
35
+ return provider.scope ?? getRuntimeClassDiMetadata(provider.useClass)?.scope ?? 'singleton';
36
36
  }
37
37
  if ('useFactory' in provider) {
38
- return provider.scope ?? (provider.resolverClass ? getClassDiMetadata(provider.resolverClass)?.scope : undefined) ?? 'singleton';
38
+ return provider.scope ?? (provider.resolverClass ? getRuntimeClassDiMetadata(provider.resolverClass)?.scope : undefined) ?? 'singleton';
39
39
  }
40
40
  return 'singleton';
41
41
  }
@@ -65,6 +65,33 @@ async function runCleanupCallbacks(cleanups) {
65
65
  }
66
66
  return errors;
67
67
  }
68
+ function createRuntimeCleanupRegistration(cleanups) {
69
+ return cleanup => {
70
+ cleanups.push(cleanup);
71
+ return () => {
72
+ const index = cleanups.indexOf(cleanup);
73
+ if (index >= 0) {
74
+ cleanups.splice(index, 1);
75
+ }
76
+ };
77
+ };
78
+ }
79
+ function createBootstrapReadySignal() {
80
+ let markReady;
81
+ let markFailed;
82
+ const ready = new Promise((resolve, reject) => {
83
+ markReady = resolve;
84
+ markFailed = reject;
85
+ });
86
+ ready.catch(() => undefined);
87
+ return {
88
+ markFailed,
89
+ markReady,
90
+ wait() {
91
+ return ready;
92
+ }
93
+ };
94
+ }
68
95
  async function closeRuntimeResources(options) {
69
96
  const errors = [];
70
97
  resetReadinessState(options.modules);
@@ -140,6 +167,15 @@ function hasReadinessStateMethods(value) {
140
167
  function isMicroserviceRuntime(value) {
141
168
  return hasMethod(value, 'listen');
142
169
  }
170
+ function hasMicroserviceRuntimeClose(value) {
171
+ return typeof value.close === 'function';
172
+ }
173
+ async function closeMicroserviceRuntime(runtime, signal) {
174
+ if (!hasMicroserviceRuntimeClose(runtime)) {
175
+ return;
176
+ }
177
+ await runtime.close(signal);
178
+ }
143
179
  function resetReadinessState(modules) {
144
180
  for (const compiledModule of modules) {
145
181
  if (hasReadinessStateMethods(compiledModule.type)) {
@@ -306,7 +342,7 @@ function registerModuleMiddleware(container, modules) {
306
342
  * @returns The same `moduleType` reference for fluent helper composition.
307
343
  */
308
344
  export function defineModule(moduleType, definition) {
309
- defineModuleMetadata(moduleType, definition);
345
+ defineRuntimeModuleMetadata(moduleType, definition);
310
346
  return moduleType;
311
347
  }
312
348
 
@@ -348,6 +384,7 @@ class FluoApplication {
348
384
  applicationState = 'bootstrapped';
349
385
  closed = false;
350
386
  closingPromise;
387
+ listenPromise;
351
388
  contextResolutionCache = new Map();
352
389
  lifecycleInstances;
353
390
  connectedMicroservices = [];
@@ -391,24 +428,70 @@ class FluoApplication {
391
428
  if (!isMicroserviceRuntime(runtime)) {
392
429
  throw new InvariantError('Resolved microservice token does not implement listen().');
393
430
  }
394
- const microservice = new FluoMicroserviceApplication(this, this.logger, runtime);
431
+ const microservice = new FluoMicroserviceApplication(this, this.logger, runtime, false);
395
432
  this.connectedMicroservices.push(microservice);
396
433
  return microservice;
397
434
  }
398
435
  async startAllMicroservices() {
399
- await Promise.all(this.connectedMicroservices.map(async microservice => microservice.listen()));
436
+ const startedMicroservices = [];
437
+ for (const microservice of this.connectedMicroservices) {
438
+ try {
439
+ await microservice.listen();
440
+ startedMicroservices.push(microservice);
441
+ } catch (error) {
442
+ await this.rollbackStartedMicroservices(startedMicroservices);
443
+ throw error;
444
+ }
445
+ }
446
+ }
447
+ async rollbackStartedMicroservices(startedMicroservices) {
448
+ for (const microservice of [...startedMicroservices].reverse()) {
449
+ try {
450
+ await microservice.close('bootstrap-failed');
451
+ } catch (rollbackError) {
452
+ this.logger.error('Failed to roll back a started microservice after startup failure.', rollbackError, 'FluoApplication');
453
+ }
454
+ }
455
+ }
456
+ async closeConnectedMicroservices(signal) {
457
+ const errors = [];
458
+ for (const microservice of [...this.connectedMicroservices].reverse()) {
459
+ try {
460
+ await microservice.close(signal);
461
+ } catch (error) {
462
+ errors.push(error);
463
+ }
464
+ }
465
+ if (errors.length > 0) {
466
+ throw createLifecycleCloseError(errors);
467
+ }
400
468
  }
401
469
 
402
470
  /**
403
471
  * 준비 검사를 통과한 뒤 어댑터에 바인딩을 위임하고 상태를 `ready`로 전이한다.
404
472
  */
405
473
  async listen() {
406
- if (this.applicationState === 'closed') {
474
+ if (this.closed || this.closingPromise || this.applicationState === 'closed') {
407
475
  throw new InvariantError('Application cannot listen after it has been closed.');
408
476
  }
409
477
  if (this.applicationState === 'ready') {
410
478
  return;
411
479
  }
480
+ if (this.listenPromise) {
481
+ await this.listenPromise;
482
+ return;
483
+ }
484
+ this.listenPromise = this.startListening();
485
+ try {
486
+ await this.listenPromise;
487
+ } finally {
488
+ this.listenPromise = undefined;
489
+ }
490
+ }
491
+ async startListening() {
492
+ if (this.closed || this.closingPromise || this.applicationState === 'closed') {
493
+ throw new InvariantError('Application cannot listen after it has been closed.');
494
+ }
412
495
  if (!this.hasHttpAdapter) {
413
496
  throw new InvariantError('Application cannot listen without an HTTP adapter. Provide options.adapter for HTTP startup, or use createApplicationContext() for adapterless DI-only bootstrap.');
414
497
  }
@@ -419,6 +502,9 @@ class FluoApplication {
419
502
  this.logger.error('Failed to start the HTTP adapter.', error, 'FluoApplication');
420
503
  throw error;
421
504
  }
505
+ if (this.closed || this.closingPromise) {
506
+ throw new InvariantError('Application startup was interrupted by shutdown.');
507
+ }
422
508
  this.applicationState = 'ready';
423
509
  this.logger.log('fluo application successfully started.', 'FluoApplication');
424
510
  }
@@ -438,14 +524,32 @@ class FluoApplication {
438
524
  return;
439
525
  }
440
526
  this.closingPromise = (async () => {
441
- await closeRuntimeResources({
442
- adapter: this.adapter,
443
- container: this.container,
444
- lifecycleInstances: this.lifecycleInstances,
445
- modules: this.modules,
446
- runtimeCleanup: this.runtimeCleanup,
447
- signal
448
- });
527
+ const errors = [];
528
+ if (this.listenPromise) {
529
+ try {
530
+ await this.listenPromise;
531
+ } catch {}
532
+ }
533
+ try {
534
+ await this.closeConnectedMicroservices(signal);
535
+ } catch (error) {
536
+ errors.push(error);
537
+ }
538
+ try {
539
+ await closeRuntimeResources({
540
+ adapter: this.adapter,
541
+ container: this.container,
542
+ lifecycleInstances: this.lifecycleInstances,
543
+ modules: this.modules,
544
+ runtimeCleanup: this.runtimeCleanup,
545
+ signal
546
+ });
547
+ } catch (error) {
548
+ errors.push(error);
549
+ }
550
+ if (errors.length > 0) {
551
+ throw createLifecycleCloseError(errors);
552
+ }
449
553
  this.closed = true;
450
554
  this.applicationState = 'closed';
451
555
  })();
@@ -506,11 +610,13 @@ class FluoApplicationContext {
506
610
  class FluoMicroserviceApplication {
507
611
  closed = false;
508
612
  closingPromise;
613
+ listenPromise;
509
614
  microserviceState = 'bootstrapped';
510
- constructor(context, logger, runtime) {
615
+ constructor(context, logger, runtime, closeContextOnClose) {
511
616
  this.context = context;
512
617
  this.logger = logger;
513
618
  this.runtime = runtime;
619
+ this.closeContextOnClose = closeContextOnClose;
514
620
  }
515
621
  get container() {
516
622
  return this.context.container;
@@ -528,13 +634,31 @@ class FluoMicroserviceApplication {
528
634
  return this.context.get(token);
529
635
  }
530
636
  async listen() {
531
- if (this.microserviceState === 'closed') {
637
+ if (this.closed || this.closingPromise || this.microserviceState === 'closed') {
532
638
  throw new InvariantError('Microservice cannot listen after it has been closed.');
533
639
  }
534
640
  if (this.microserviceState === 'ready') {
535
641
  return;
536
642
  }
643
+ if (this.listenPromise) {
644
+ await this.listenPromise;
645
+ return;
646
+ }
647
+ this.listenPromise = this.startListening();
648
+ try {
649
+ await this.listenPromise;
650
+ } finally {
651
+ this.listenPromise = undefined;
652
+ }
653
+ }
654
+ async startListening() {
655
+ if (this.closed || this.closingPromise || this.microserviceState === 'closed') {
656
+ throw new InvariantError('Microservice cannot listen after it has been closed.');
657
+ }
537
658
  await this.runtime.listen();
659
+ if (this.closed || this.closingPromise) {
660
+ throw new InvariantError('Microservice startup was interrupted by shutdown.');
661
+ }
538
662
  this.microserviceState = 'ready';
539
663
  this.logger.log('fluo microservice successfully started.', 'FluoFactory');
540
664
  }
@@ -559,7 +683,29 @@ class FluoMicroserviceApplication {
559
683
  return;
560
684
  }
561
685
  this.closingPromise = (async () => {
562
- await this.context.close(signal);
686
+ if (this.listenPromise) {
687
+ try {
688
+ await this.listenPromise;
689
+ } catch {}
690
+ }
691
+ if (this.closeContextOnClose) {
692
+ const errors = [];
693
+ try {
694
+ await closeMicroserviceRuntime(this.runtime, signal);
695
+ } catch (error) {
696
+ errors.push(error);
697
+ }
698
+ try {
699
+ await this.context.close(signal);
700
+ } catch (error) {
701
+ errors.push(error);
702
+ }
703
+ if (errors.length > 0) {
704
+ throw createLifecycleCloseError(errors);
705
+ }
706
+ } else {
707
+ await closeMicroserviceRuntime(this.runtime, signal);
708
+ }
563
709
  this.closed = true;
564
710
  this.microserviceState = 'closed';
565
711
  })();
@@ -754,13 +900,19 @@ function createRuntimeProviders(options, logger) {
754
900
  useValue: logger
755
901
  }];
756
902
  }
757
- function registerRuntimeBootstrapTokens(bootstrapped, adapter, platformShell) {
903
+ function registerRuntimeBootstrapTokens(bootstrapped, adapter, platformShell, runtimeCleanup, bootstrapReadySignal) {
758
904
  registerRuntimeContextTokens(bootstrapped, {
759
905
  provide: HTTP_APPLICATION_ADAPTER,
760
906
  useValue: adapter
761
907
  }, {
762
908
  provide: PLATFORM_SHELL,
763
909
  useValue: platformShell
910
+ }, {
911
+ provide: RUNTIME_CLEANUP_REGISTRATION,
912
+ useValue: createRuntimeCleanupRegistration(runtimeCleanup)
913
+ }, {
914
+ provide: BOOTSTRAP_READY_SIGNAL,
915
+ useValue: bootstrapReadySignal
764
916
  });
765
917
  }
766
918
  function registerRuntimeContextTokens(bootstrapped, ...providers) {
@@ -772,21 +924,28 @@ function registerRuntimeContextTokens(bootstrapped, ...providers) {
772
924
  useValue: bootstrapped.modules
773
925
  });
774
926
  }
775
- function registerRuntimeApplicationContextTokens(bootstrapped, platformShell) {
927
+ function registerRuntimeApplicationContextTokens(bootstrapped, platformShell, runtimeCleanup, bootstrapReadySignal) {
776
928
  registerRuntimeContextTokens(bootstrapped, {
777
929
  provide: PLATFORM_SHELL,
778
930
  useValue: platformShell
931
+ }, {
932
+ provide: RUNTIME_CLEANUP_REGISTRATION,
933
+ useValue: createRuntimeCleanupRegistration(runtimeCleanup)
934
+ }, {
935
+ provide: BOOTSTRAP_READY_SIGNAL,
936
+ useValue: bootstrapReadySignal
779
937
  });
780
938
  }
781
939
  async function resolveBootstrapLifecycleInstances(bootstrapped, resolvedInstances) {
782
940
  const lifecycleProviders = [...bootstrapped.effectiveProviders.runtimeProviders, ...bootstrapped.effectiveProviders.moduleProviders];
783
941
  return resolveLifecycleInstances(bootstrapped.container, lifecycleProviders, resolvedInstances);
784
942
  }
785
- async function runBootstrapLifecycle(modules, lifecycleInstances, logger, platformShell) {
943
+ async function runBootstrapLifecycle(modules, lifecycleInstances, logger, platformShell, bootstrapReadySignal) {
786
944
  resetReadinessState(modules);
787
945
  await runBootstrapHooks(lifecycleInstances);
788
946
  await platformShell.start();
789
947
  markReadinessState(modules);
948
+ bootstrapReadySignal.markReady();
790
949
  logCompiledModules(logger, modules);
791
950
  }
792
951
  function createFilterErrorHandler(filters) {
@@ -809,7 +968,7 @@ function createRuntimeDispatcherOptions(bootstrapped, options, handlerMapping, e
809
968
  rootContainer: bootstrapped.container
810
969
  };
811
970
  if (converters.length > 0) {
812
- dispatcherOptions.binder = new DefaultBinder(converters);
971
+ dispatcherOptions.binder = new RuntimeDefaultBinder(converters);
813
972
  }
814
973
  if (errorHandler) {
815
974
  dispatcherOptions.onError = errorHandler;
@@ -845,6 +1004,7 @@ export async function bootstrapApplication(options) {
845
1004
  async listen() {}
846
1005
  };
847
1006
  const runtimeCleanup = [];
1007
+ const bootstrapReadySignal = createBootstrapReadySignal();
848
1008
  const platformShell = createRuntimePlatformShell(options.platform?.components);
849
1009
  const timingEnabled = options.diagnostics?.timing === true;
850
1010
  const timingStart = timingEnabled ? runtimePerformance.now() : 0;
@@ -856,8 +1016,9 @@ export async function bootstrapApplication(options) {
856
1016
  const bootstrapped = bootstrapModule(options.rootModule, {
857
1017
  duplicateProviderPolicy: options.duplicateProviderPolicy,
858
1018
  logger,
1019
+ moduleGraphCache: options.moduleGraphCache,
859
1020
  providers: runtimeProviders,
860
- validationTokens: [RUNTIME_CONTAINER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER]
1021
+ validationTokens: [RUNTIME_CONTAINER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, RUNTIME_CLEANUP_REGISTRATION, BOOTSTRAP_READY_SIGNAL]
861
1022
  });
862
1023
  if (timingEnabled) {
863
1024
  timingPhases.push({
@@ -866,7 +1027,7 @@ export async function bootstrapApplication(options) {
866
1027
  });
867
1028
  }
868
1029
  const registerTokensStart = timingEnabled ? runtimePerformance.now() : 0;
869
- registerRuntimeBootstrapTokens(bootstrapped, adapter, platformShell);
1030
+ registerRuntimeBootstrapTokens(bootstrapped, adapter, platformShell, runtimeCleanup, bootstrapReadySignal);
870
1031
  if (timingEnabled) {
871
1032
  timingPhases.push({
872
1033
  durationMs: runtimePerformance.now() - registerTokensStart,
@@ -889,7 +1050,7 @@ export async function bootstrapApplication(options) {
889
1050
  });
890
1051
  }
891
1052
  const lifecycleStart = timingEnabled ? runtimePerformance.now() : 0;
892
- await runBootstrapLifecycle(bootstrapped.modules, lifecycleInstances, logger, platformShell);
1053
+ await runBootstrapLifecycle(bootstrapped.modules, lifecycleInstances, logger, platformShell, bootstrapReadySignal);
893
1054
  if (timingEnabled) {
894
1055
  timingPhases.push({
895
1056
  durationMs: runtimePerformance.now() - lifecycleStart,
@@ -905,8 +1066,9 @@ export async function bootstrapApplication(options) {
905
1066
  });
906
1067
  }
907
1068
  const bootstrapTiming = timingEnabled ? createBootstrapTimingDiagnostics(timingPhases, runtimePerformance.now() - timingStart) : undefined;
908
- return new FluoApplication(bootstrapped.container, bootstrapped.modules, options.rootModule, dispatcher, bootstrapTiming, adapter, hasHttpAdapter, platformShell, lifecycleInstances, logger, runtimeCleanup, createContextCacheableTokenSet(bootstrapped.effectiveProviders, [RUNTIME_CONTAINER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, PLATFORM_SHELL]));
1069
+ return new FluoApplication(bootstrapped.container, bootstrapped.modules, options.rootModule, dispatcher, bootstrapTiming, adapter, hasHttpAdapter, platformShell, lifecycleInstances, logger, runtimeCleanup, createContextCacheableTokenSet(bootstrapped.effectiveProviders, [RUNTIME_CONTAINER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, PLATFORM_SHELL, RUNTIME_CLEANUP_REGISTRATION, BOOTSTRAP_READY_SIGNAL]));
909
1070
  } catch (error) {
1071
+ bootstrapReadySignal.markFailed(error);
910
1072
  logger.error('Failed to bootstrap the fluo application. Check the error below for what failed and how to fix it.', error, 'FluoFactory');
911
1073
  await runBootstrapFailureCleanup({
912
1074
  container: bootstrappedContainer,
@@ -953,6 +1115,7 @@ export class FluoFactory {
953
1115
  let bootstrappedContainer;
954
1116
  let bootstrappedModules = [];
955
1117
  const runtimeCleanup = [];
1118
+ const bootstrapReadySignal = createBootstrapReadySignal();
956
1119
  const platformShell = createRuntimePlatformShell(options.platform?.components);
957
1120
  const timingEnabled = options.diagnostics?.timing === true;
958
1121
  const timingStart = timingEnabled ? runtimePerformance.now() : 0;
@@ -964,8 +1127,9 @@ export class FluoFactory {
964
1127
  const bootstrapped = bootstrapModule(rootModule, {
965
1128
  duplicateProviderPolicy: options.duplicateProviderPolicy,
966
1129
  logger,
1130
+ moduleGraphCache: options.moduleGraphCache,
967
1131
  providers: runtimeProviders,
968
- validationTokens: [RUNTIME_CONTAINER, COMPILED_MODULES]
1132
+ validationTokens: [RUNTIME_CONTAINER, COMPILED_MODULES, RUNTIME_CLEANUP_REGISTRATION, BOOTSTRAP_READY_SIGNAL]
969
1133
  });
970
1134
  if (timingEnabled) {
971
1135
  timingPhases.push({
@@ -974,7 +1138,7 @@ export class FluoFactory {
974
1138
  });
975
1139
  }
976
1140
  const registerTokensStart = timingEnabled ? runtimePerformance.now() : 0;
977
- registerRuntimeApplicationContextTokens(bootstrapped, platformShell);
1141
+ registerRuntimeApplicationContextTokens(bootstrapped, platformShell, runtimeCleanup, bootstrapReadySignal);
978
1142
  if (timingEnabled) {
979
1143
  timingPhases.push({
980
1144
  durationMs: runtimePerformance.now() - registerTokensStart,
@@ -997,7 +1161,7 @@ export class FluoFactory {
997
1161
  });
998
1162
  }
999
1163
  const lifecycleStart = timingEnabled ? runtimePerformance.now() : 0;
1000
- await runBootstrapLifecycle(bootstrapped.modules, lifecycleInstances, logger, platformShell);
1164
+ await runBootstrapLifecycle(bootstrapped.modules, lifecycleInstances, logger, platformShell, bootstrapReadySignal);
1001
1165
  if (timingEnabled) {
1002
1166
  timingPhases.push({
1003
1167
  durationMs: runtimePerformance.now() - lifecycleStart,
@@ -1005,8 +1169,9 @@ export class FluoFactory {
1005
1169
  });
1006
1170
  }
1007
1171
  const bootstrapTiming = timingEnabled ? createBootstrapTimingDiagnostics(timingPhases, runtimePerformance.now() - timingStart) : undefined;
1008
- return new FluoApplicationContext(bootstrapped.container, bootstrapped.modules, rootModule, bootstrapTiming, lifecycleInstances, runtimeCleanup, createContextCacheableTokenSet(bootstrapped.effectiveProviders, [RUNTIME_CONTAINER, COMPILED_MODULES, PLATFORM_SHELL]));
1172
+ return new FluoApplicationContext(bootstrapped.container, bootstrapped.modules, rootModule, bootstrapTiming, lifecycleInstances, runtimeCleanup, createContextCacheableTokenSet(bootstrapped.effectiveProviders, [RUNTIME_CONTAINER, COMPILED_MODULES, PLATFORM_SHELL, RUNTIME_CLEANUP_REGISTRATION, BOOTSTRAP_READY_SIGNAL]));
1009
1173
  } catch (error) {
1174
+ bootstrapReadySignal.markFailed(error);
1010
1175
  logger.error('Failed to bootstrap application context. Check the error below for what failed and how to fix it.', error, 'FluoFactory');
1011
1176
  await runBootstrapFailureCleanup({
1012
1177
  container: bootstrappedContainer,
@@ -1038,9 +1203,13 @@ export class FluoFactory {
1038
1203
  if (!isMicroserviceRuntime(runtime)) {
1039
1204
  throw new InvariantError('Resolved microservice token does not implement listen().');
1040
1205
  }
1041
- return new FluoMicroserviceApplication(context, logger, runtime);
1206
+ return new FluoMicroserviceApplication(context, logger, runtime, true);
1042
1207
  } catch (error) {
1043
- await context.close('bootstrap-failed');
1208
+ try {
1209
+ await context.close('bootstrap-failed');
1210
+ } catch (cleanupError) {
1211
+ logger.error('Failed to clean up after microservice bootstrap failure.', cleanupError, 'FluoFactory');
1212
+ }
1044
1213
  logger.error('Failed to bootstrap microservice context. Check the error below for what failed and how to fix it.', error, 'FluoFactory');
1045
1214
  throw error;
1046
1215
  }
@@ -1 +1 @@
1
- {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/health/diagnostics.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAY,KAAK,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACpC,aAAa,EAAE,+BAA+B,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,0BAA0B,EAAE,CAAC;IACxC,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;IACjD,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC9C,aAAa,EAAE,KAAK,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC,CAAC;IACH,aAAa,EAAE,KAAK,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IACH,eAAe,EAAE,KAAK,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,0BAA0B,CAAC,MAAM,CAAC,CAAC;QACjD,KAAK,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC,CAAC;IACH,iBAAiB,EAAE,KAAK,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EACA,kBAAkB,GAClB,yBAAyB,GACzB,6BAA6B,GAC7B,yBAAyB,GACzB,mBAAmB,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,CAAC,CAAC;CACZ;AAiFD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,EAAE,UAAU,EAAE,UAAU,GAAG,uBAAuB,CAkEjI;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM,CAoCtF;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,oBAAoB,EAAE,EAC9B,OAAO,EAAE,MAAM,GACd,0BAA0B,CAS5B"}
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/health/diagnostics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAY,KAAK,EAAE,MAAM,YAAY,CAAC;AAGlD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACpC,aAAa,EAAE,+BAA+B,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,0BAA0B,EAAE,CAAC;IACxC,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;IACjD,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC9C,aAAa,EAAE,KAAK,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC,CAAC;IACH,aAAa,EAAE,KAAK,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IACH,eAAe,EAAE,KAAK,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,0BAA0B,CAAC,MAAM,CAAC,CAAC;QACjD,KAAK,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC,CAAC;IACH,iBAAiB,EAAE,KAAK,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EACA,kBAAkB,GAClB,yBAAyB,GACzB,6BAA6B,GAC7B,yBAAyB,GACzB,mBAAmB,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,CAAC,CAAC;CACZ;AAiFD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,EAAE,UAAU,EAAE,UAAU,GAAG,uBAAuB,CAkEjI;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM,CAoCtF;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,oBAAoB,EAAE,EAC9B,OAAO,EAAE,MAAM,GACd,0BAA0B,CAS5B"}
@@ -1,4 +1,4 @@
1
- import { getClassDiMetadata } from '@fluojs/core/internal';
1
+ import { getRuntimeClassDiMetadata } from '../internal/core-metadata.js';
2
2
 
3
3
  /**
4
4
  * Describes the runtime diagnostics graph contract.
@@ -56,16 +56,16 @@ function providerShape(provider) {
56
56
  }
57
57
  function providerScope(provider) {
58
58
  if (typeof provider === 'function') {
59
- return getClassDiMetadata(provider)?.scope ?? 'singleton';
59
+ return getRuntimeClassDiMetadata(provider)?.scope ?? 'singleton';
60
60
  }
61
61
  if ('useValue' in provider || 'useExisting' in provider) {
62
62
  return 'singleton';
63
63
  }
64
64
  if ('useFactory' in provider) {
65
- return provider.scope ?? (provider.resolverClass ? getClassDiMetadata(provider.resolverClass)?.scope : undefined) ?? 'singleton';
65
+ return provider.scope ?? (provider.resolverClass ? getRuntimeClassDiMetadata(provider.resolverClass)?.scope : undefined) ?? 'singleton';
66
66
  }
67
67
  if ('useClass' in provider) {
68
- return provider.scope ?? getClassDiMetadata(provider.useClass)?.scope ?? 'singleton';
68
+ return provider.scope ?? getRuntimeClassDiMetadata(provider.useClass)?.scope ?? 'singleton';
69
69
  }
70
70
  return 'singleton';
71
71
  }
@@ -28,12 +28,25 @@ export interface HealthModuleOptions {
28
28
  /**
29
29
  * Defines the readiness check type.
30
30
  */
31
- export type ReadinessCheck = () => boolean | Promise<boolean>;
31
+ export type ReadinessCheck = (ctx: import('@fluojs/http').RequestContext) => boolean | Promise<boolean>;
32
32
  /**
33
- * Create health module.
33
+ * Runtime health module facade for application module imports.
34
+ */
35
+ export declare class HealthModule {
36
+ /**
37
+ * Creates a runtime-owned `/health` and `/ready` module.
38
+ *
39
+ * @param options Runtime health endpoint options.
40
+ * @returns A module class that can be imported into an application module.
41
+ */
42
+ static forRoot(options?: HealthModuleOptions): ModuleType;
43
+ }
44
+ /**
45
+ * Creates a runtime-owned `/health` and `/ready` module.
34
46
  *
35
- * @param options The options.
36
- * @returns The create health module result.
47
+ * @deprecated Prefer `HealthModule.forRoot(...)` for application-facing module registration.
48
+ * @param options Runtime health endpoint options.
49
+ * @returns A module class that can be imported into an application module.
37
50
  */
38
51
  export declare function createHealthModule(options?: HealthModuleOptions): ModuleType;
39
52
  //# sourceMappingURL=health.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/health/health.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,IAAI,GAAG,aAAa,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,aAAa,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,cAAc,EAAE,cAAc,KACrD,YAAY,GACZ,mBAAmB,GACnB,OAAO,CAAC,YAAY,GAAG,mBAAmB,CAAC,CAAC;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE9D;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,UAAU,CA0EhF"}
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/health/health.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,IAAI,GAAG,aAAa,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,aAAa,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,cAAc,EAAE,cAAc,KACrD,YAAY,GACZ,mBAAmB,GACnB,OAAO,CAAC,YAAY,GAAG,mBAAmB,CAAC,CAAC;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,OAAO,cAAc,EAAE,cAAc,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAkFxG;;GAEG;AACH,qBAAa,YAAY;IACvB;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,mBAAwB,GAAG,UAAU;CAG9D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,UAAU,CAEhF"}
@@ -26,13 +26,7 @@ import { defineModule } from '../bootstrap.js';
26
26
  * Defines the readiness check type.
27
27
  */
28
28
 
29
- /**
30
- * Create health module.
31
- *
32
- * @param options The options.
33
- * @returns The create health module result.
34
- */
35
- export function createHealthModule(options = {}) {
29
+ function createRuntimeHealthModule(options = {}) {
36
30
  let _initProto, _initClass;
37
31
  const basePath = options.path ?? '';
38
32
  const readinessChecks = [];
@@ -75,7 +69,7 @@ export function createHealthModule(options = {}) {
75
69
  };
76
70
  }
77
71
  for (const check of readinessChecks) {
78
- const result = await check();
72
+ const result = await check(ctx);
79
73
  if (!result) {
80
74
  ctx.response.setStatus(503);
81
75
  return {
@@ -91,7 +85,7 @@ export function createHealthModule(options = {}) {
91
85
  _initClass();
92
86
  }
93
87
  }
94
- class HealthModule {
88
+ class RuntimeHealthModule {
95
89
  static addReadinessCheck(fn) {
96
90
  readinessChecks.push(fn);
97
91
  }
@@ -102,8 +96,37 @@ export function createHealthModule(options = {}) {
102
96
  ready = false;
103
97
  }
104
98
  }
105
- defineModule(HealthModule, {
99
+ Object.defineProperty(RuntimeHealthModule, 'name', {
100
+ value: 'HealthModule'
101
+ });
102
+ defineModule(RuntimeHealthModule, {
106
103
  controllers: [_HealthController]
107
104
  });
108
- return HealthModule;
105
+ return RuntimeHealthModule;
106
+ }
107
+
108
+ /**
109
+ * Runtime health module facade for application module imports.
110
+ */
111
+ export class HealthModule {
112
+ /**
113
+ * Creates a runtime-owned `/health` and `/ready` module.
114
+ *
115
+ * @param options Runtime health endpoint options.
116
+ * @returns A module class that can be imported into an application module.
117
+ */
118
+ static forRoot(options = {}) {
119
+ return createRuntimeHealthModule(options);
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Creates a runtime-owned `/health` and `/ready` module.
125
+ *
126
+ * @deprecated Prefer `HealthModule.forRoot(...)` for application-facing module registration.
127
+ * @param options Runtime health endpoint options.
128
+ * @returns A module class that can be imported into an application module.
129
+ */
130
+ export function createHealthModule(options = {}) {
131
+ return HealthModule.forRoot(options);
109
132
  }
@@ -1 +1 @@
1
- {"version":3,"file":"http-adapter-shared.d.ts","sourceRoot":"","sources":["../src/http-adapter-shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,WAAW,EAEhB,KAAK,sBAAsB,EAE3B,KAAK,cAAc,EAEnB,KAAK,sBAAsB,EAC5B,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEvG;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,WAAW,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,0CAA0C;IAC1C,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,6DAA6D;IAC7D,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,qCAAqC;IACrC,eAAe,CAAC,EAAE,KAAK,GAAG,sBAAsB,CAAC;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,sCACf,SAAQ,IAAI,CAAC,wBAAwB,EAAE,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC,EACzE,4BAA4B;IAC9B,0CAA0C;IAC1C,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,gCAAiC,SAAQ,sCAAsC;IAC9F,4FAA4F;IAC5F,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0CAA0C;IAC1C,oBAAoB,CAAC,EAAE,+BAA+B,CAAC;CACxD;AAED;;GAEG;AACH,MAAM,MAAM,+BAA+B,GAAG,CAC5C,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,iBAAiB,EACzB,kBAAkB,CAAC,EAAE,MAAM,KACxB,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AAEzB,KAAK,6BAA6B,GAAG,sBAAsB,GAAG;IAC5D,eAAe,IAAI,uBAAuB,CAAC;CAC5C,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,+BAA+B,CACnD,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,sCAAsC,EAC/C,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,WAAW,CAAC,CAQtB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,4BAA4B,GAAG,cAAc,EAAE,CAkBnG;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,CAItF;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,gCAAgC,EACzC,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,WAAW,CAAC,CA6CtB"}
1
+ {"version":3,"file":"http-adapter-shared.d.ts","sourceRoot":"","sources":["../src/http-adapter-shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,WAAW,EAEhB,KAAK,sBAAsB,EAE3B,KAAK,cAAc,EAEnB,KAAK,sBAAsB,EAC5B,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEvG;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,WAAW,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,0CAA0C;IAC1C,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,6DAA6D;IAC7D,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,qCAAqC;IACrC,eAAe,CAAC,EAAE,KAAK,GAAG,sBAAsB,CAAC;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,sCACf,SAAQ,IAAI,CAAC,wBAAwB,EAAE,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC,EACzE,4BAA4B;IAC9B,0CAA0C;IAC1C,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,gCAAiC,SAAQ,sCAAsC;IAC9F,4FAA4F;IAC5F,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0CAA0C;IAC1C,oBAAoB,CAAC,EAAE,+BAA+B,CAAC;CACxD;AAED;;GAEG;AACH,MAAM,MAAM,+BAA+B,GAAG,CAC5C,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,iBAAiB,EACzB,kBAAkB,CAAC,EAAE,MAAM,KACxB,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AAEzB,KAAK,6BAA6B,GAAG,sBAAsB,GAAG;IAC5D,eAAe,IAAI,uBAAuB,CAAC;CAC5C,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,+BAA+B,CACnD,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,sCAAsC,EAC/C,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,WAAW,CAAC,CAQtB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,4BAA4B,GAAG,cAAc,EAAE,CAkBnG;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,CAItF;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,gCAAgC,EACzC,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,WAAW,CAAC,CA+EtB"}