@tramvai/module-common 2.7.1 → 2.20.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/lib/index.es.js CHANGED
@@ -1,16 +1,15 @@
1
1
  import { __decorate } from 'tslib';
2
2
  import eachObj from '@tinkoff/utils/object/each';
3
- import { createBundle, Scope, Module, commandLineListTokens, COMMAND_LINE_RUNNER_TOKEN, COMMAND_LINES_TOKEN, DI_TOKEN, ACTION_PARAMETERS, ACTIONS_LIST_TOKEN, provide, IS_DI_CHILD_CONTAINER_TOKEN, BUNDLE_LIST_TOKEN } from '@tramvai/core';
3
+ import { createBundle, Scope, Module, commandLineListTokens, COMMAND_LINE_RUNNER_TOKEN, COMMAND_LINES_TOKEN, DI_TOKEN, isTramvaiAction, ACTION_PARAMETERS, ACTIONS_LIST_TOKEN, provide as provide$1, IS_DI_CHILD_CONTAINER_TOKEN, BUNDLE_LIST_TOKEN } from '@tramvai/core';
4
4
  import { EnvironmentModule } from '@tramvai/module-environment';
5
5
  import { CookieModule } from '@tramvai/module-cookie';
6
6
  export { COOKIE_MANAGER_TOKEN } from '@tramvai/module-cookie';
7
7
  import { LogModule } from '@tramvai/module-log';
8
8
  import { Hooks } from '@tinkoff/hook-runner';
9
- import { REQUEST_MANAGER_TOKEN, REQUEST, COMBINE_REDUCERS, CONTEXT_TOKEN, RESPONSE_MANAGER_TOKEN, RESPONSE, ACTION_EXECUTION_TOKEN, LOGGER_TOKEN, PUBSUB_FACTORY_TOKEN, PUBSUB_TOKEN, ROOT_PUBSUB_TOKEN, ACTION_REGISTRY_TOKEN, ACTION_CONDITIONALS, STORE_TOKEN, ACTION_PAGE_RUNNER_TOKEN, DISPATCHER_TOKEN, DISPATCHER_CONTEXT_TOKEN, STORE_MIDDLEWARE, INITIAL_APP_STATE_TOKEN, CLEAR_CACHE_TOKEN, CREATE_CACHE_TOKEN, REGISTER_CLEAR_CACHE_TOKEN, HOOK_TOKEN, COMPONENT_REGISTRY_TOKEN, BUNDLE_MANAGER_TOKEN, ADDITIONAL_BUNDLE_TOKEN } from '@tramvai/tokens-common';
9
+ import { REQUEST_MANAGER_TOKEN, REQUEST, COMBINE_REDUCERS, CONTEXT_TOKEN, RESPONSE_MANAGER_TOKEN, RESPONSE, ACTION_EXECUTION_TOKEN, ROOT_EXECUTION_CONTEXT_TOKEN, LOGGER_TOKEN, EXECUTION_CONTEXT_MANAGER_TOKEN, COMMAND_LINE_EXECUTION_CONTEXT_TOKEN, PUBSUB_FACTORY_TOKEN, PUBSUB_TOKEN, ROOT_PUBSUB_TOKEN, ACTION_REGISTRY_TOKEN, ACTION_CONDITIONALS, STORE_TOKEN, ACTION_PAGE_RUNNER_TOKEN, DISPATCHER_TOKEN, DISPATCHER_CONTEXT_TOKEN, STORE_MIDDLEWARE, INITIAL_APP_STATE_TOKEN, CLEAR_CACHE_TOKEN, CREATE_CACHE_TOKEN, REGISTER_CLEAR_CACHE_TOKEN, HOOK_TOKEN, COMPONENT_REGISTRY_TOKEN, BUNDLE_MANAGER_TOKEN, ADDITIONAL_BUNDLE_TOKEN } from '@tramvai/tokens-common';
10
10
  export * from '@tramvai/tokens-common';
11
- import { __lazyErrorHandler } from '@tramvai/react';
11
+ import { resolveLazyComponent, __lazyErrorHandler } from '@tramvai/react';
12
12
  import { fileSystemPagesEnabled, getAllFileSystemPages, isFileSystemPageComponent } from '@tramvai/experiments';
13
- import hoistNonReactStatics from 'hoist-non-react-statics';
14
13
  import pathOr from '@tinkoff/utils/object/pathOr';
15
14
  import flatten from '@tinkoff/utils/array/flatten';
16
15
  import { createEvent, createReducer, convertAction, createDispatcher, devTools, Provider } from '@tramvai/state';
@@ -18,9 +17,9 @@ import { format } from '@tinkoff/url';
18
17
  import isEmpty from '@tinkoff/utils/is/empty';
19
18
  import values from '@tinkoff/utils/object/values';
20
19
  import { METRICS_MODULE_TOKEN } from '@tramvai/tokens-metrics';
21
- import { createChildContainer, Scope as Scope$1, createToken } from '@tinkoff/dippy';
20
+ import { createChildContainer, provide, Scope as Scope$1, createToken } from '@tinkoff/dippy';
22
21
  import noop from '@tinkoff/utils/function/noop';
23
- import { isSilentError } from '@tinkoff/errors';
22
+ import { isSilentError, ConditionFailError, ExecutionAbortError } from '@tinkoff/errors';
24
23
  import { PubSub } from '@tinkoff/pubsub';
25
24
  import identity from '@tinkoff/utils/function/identity';
26
25
  import objectMap from '@tinkoff/utils/object/map';
@@ -30,6 +29,7 @@ import toArray from '@tinkoff/utils/array/toArray';
30
29
  import LRU from '@tinkoff/lru-cache-nano';
31
30
  import { SERVER_MODULE_PAPI_PRIVATE_ROUTE } from '@tramvai/tokens-server';
32
31
  import { createPapiMethod } from '@tramvai/papi';
32
+ import { AbortController } from 'node-abort-controller';
33
33
  import { jsx } from 'react/jsx-runtime';
34
34
  import { EXTEND_RENDER } from '@tramvai/tokens-render';
35
35
  import { CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN, commandLineListTokens as commandLineListTokens$1 } from '@tramvai/tokens-child-app';
@@ -77,24 +77,17 @@ class BundleManager {
77
77
  // preload `lazy` components then register actions and reducers
78
78
  if (pageComponent && bundle.components[pageComponent]) {
79
79
  const componentOrLoader = bundle.components[pageComponent];
80
- const component = typeof componentOrLoader.load === 'function'
81
- ? (await componentOrLoader.load()).default
82
- : componentOrLoader;
83
- // manually hoist static properties from preloaded component to loadable wrapper,
84
- // this open access to current page component static properties outside before rendering
85
- if (componentOrLoader !== component) {
86
- hoistNonReactStatics(componentOrLoader, component);
87
- }
80
+ const component = await resolveLazyComponent(componentOrLoader);
88
81
  // allow page components to register any other components
89
- if (component.components) {
82
+ if ('components' in component) {
90
83
  eachObj((cmp, name) => {
91
84
  this.componentRegistry.add(name, cmp, pageComponent);
92
85
  }, component.components);
93
86
  }
94
- if (component.actions) {
87
+ if ('actions' in component) {
95
88
  this.actionRegistry.add(pageComponent, component.actions);
96
89
  }
97
- if (component.reducers) {
90
+ if ('reducers' in component) {
98
91
  component.reducers.forEach((reducer) => {
99
92
  this.dispatcher.registerStore(reducer);
100
93
  });
@@ -375,14 +368,18 @@ const resolveDi = (type, status, diContainer, providers) => {
375
368
  return di;
376
369
  };
377
370
  class CommandLineRunner {
378
- constructor({ lines, rootDi, logger, metrics, }) {
371
+ constructor({ lines, rootDi, logger, metrics, executionContextManager, }) {
372
+ this.executionContextByDi = new WeakMap();
373
+ this.abortControllerByDi = new WeakMap();
379
374
  this.lines = lines;
380
375
  this.rootDi = rootDi;
381
376
  this.log = logger('command:command-line-runner');
382
377
  this.metrics = metrics;
378
+ this.executionContextManager = executionContextManager;
383
379
  }
384
380
  run(type, status, providers, customDi) {
385
381
  const di = customDi !== null && customDi !== void 0 ? customDi : resolveDi(type, status, this.rootDi, providers);
382
+ const rootExecutionContext = di.get({ token: ROOT_EXECUTION_CONTEXT_TOKEN, optional: true });
386
383
  this.log.debug({
387
384
  event: 'command-run',
388
385
  type,
@@ -394,13 +391,27 @@ class CommandLineRunner {
394
391
  const doneMetric = this.createDurationMetric();
395
392
  // eslint-disable-next-line promise/no-nesting
396
393
  return Promise.resolve()
397
- .then(() => this.createLineChain(di, line))
394
+ .then(() => {
395
+ return this.executionContextManager.withContext(rootExecutionContext, `command-line:${line.toString()}`, async (executionContext, abortController) => {
396
+ this.executionContextByDi.set(di, executionContext);
397
+ this.abortControllerByDi.set(di, abortController);
398
+ await this.createLineChain(di, line);
399
+ });
400
+ })
398
401
  .finally(() => doneMetric({ line: line.toString() }));
399
402
  });
400
403
  }, Promise.resolve())
401
404
  // После завершения цепочки отдаем context выполнения
405
+ .finally(() => {
406
+ this.executionContextByDi.delete(di);
407
+ this.abortControllerByDi.delete(di);
408
+ })
402
409
  .then(() => di));
403
410
  }
411
+ resolveExecutionContextFromDi(di) {
412
+ var _a;
413
+ return (_a = this.executionContextByDi.get(di)) !== null && _a !== void 0 ? _a : null;
414
+ }
404
415
  createLineChain(di, line) {
405
416
  let lineInstance;
406
417
  try {
@@ -452,12 +463,15 @@ class CommandLineRunner {
452
463
  return Promise.resolve()
453
464
  .then(() => instance())
454
465
  .catch((err) => {
466
+ var _a;
455
467
  this.log[isSilentError(err) ? 'debug' : 'error']({
456
468
  event: 'line-error',
457
469
  error: err,
458
470
  line: line.toString(),
459
471
  command: name,
460
472
  });
473
+ // in case if any error happens during line execution results from other line handlers will not be used anyway
474
+ (_a = this.abortControllerByDi.get(di)) === null || _a === void 0 ? void 0 : _a.abort();
461
475
  this.throwError(err, di);
462
476
  });
463
477
  }
@@ -511,7 +525,7 @@ let CommandModule = class CommandModule {
511
525
  CommandModule = __decorate([
512
526
  Module({
513
527
  providers: [
514
- {
528
+ provide({
515
529
  // Раннер процессов
516
530
  provide: COMMAND_LINE_RUNNER_TOKEN,
517
531
  scope: Scope$1.SINGLETON,
@@ -524,14 +538,27 @@ CommandModule = __decorate([
524
538
  token: METRICS_MODULE_TOKEN,
525
539
  optional: true,
526
540
  },
541
+ executionContextManager: EXECUTION_CONTEXT_MANAGER_TOKEN,
527
542
  },
528
- },
529
- {
543
+ }),
544
+ provide({
545
+ provide: COMMAND_LINE_EXECUTION_CONTEXT_TOKEN,
546
+ useFactory: ({ di, commandLineRunner, }) => {
547
+ return () => {
548
+ return commandLineRunner.resolveExecutionContextFromDi(di);
549
+ };
550
+ },
551
+ deps: {
552
+ di: DI_TOKEN,
553
+ commandLineRunner: COMMAND_LINE_RUNNER_TOKEN,
554
+ },
555
+ }),
556
+ provide({
530
557
  // Дефолтный список команл
531
558
  provide: COMMAND_LINES_TOKEN,
532
559
  scope: Scope$1.SINGLETON,
533
560
  useValue: lines$1,
534
- },
561
+ }),
535
562
  ],
536
563
  })
537
564
  ], CommandModule);
@@ -583,14 +610,19 @@ const actionTramvaiReducer = createReducer('actionTramvai', initalState).on(acti
583
610
  serverState: payload,
584
611
  }));
585
612
 
613
+ /**
614
+ * @deprecated only for compatibility with legacy createAction
615
+ */
586
616
  const actionType = {
587
617
  global: 'global',
588
618
  local: 'local',
589
619
  };
590
620
 
621
+ const DEFAULT_CONDITIONS = {};
591
622
  class ActionChecker {
592
623
  // eslint-disable-next-line max-params
593
624
  constructor(globalConditionals, payload, parameters, executionState, type) {
625
+ var _a;
594
626
  this.globalConditionals = globalConditionals;
595
627
  this.payload = payload;
596
628
  this.parameters = parameters;
@@ -604,7 +636,7 @@ class ActionChecker {
604
636
  // если экшен был уже выполнен, то считаем, что его не нужно больше выполнять
605
637
  this.status = executionState.status !== 'success';
606
638
  }
607
- this.conditions = parameters.conditions;
639
+ this.conditions = (_a = parameters.conditions) !== null && _a !== void 0 ? _a : DEFAULT_CONDITIONS;
608
640
  }
609
641
  check() {
610
642
  this.globalConditionals.forEach((filter) => {
@@ -621,6 +653,7 @@ class ActionChecker {
621
653
  }
622
654
  forbid() {
623
655
  this.executionState.status = 'forbidden';
656
+ this.executionState.forbiddenBy = this.key;
624
657
  this.forbiddenMarker = true;
625
658
  }
626
659
  allow() {
@@ -634,12 +667,16 @@ class ActionChecker {
634
667
  }
635
668
  }
636
669
 
670
+ const EMPTY_DEPS = {};
671
+ const DEFAULT_PAYLOAD = {};
637
672
  const getParameters = (action) => action[ACTION_PARAMETERS];
638
673
  class ActionExecution {
639
- constructor({ actionConditionals, store, context, di, transformAction, }) {
674
+ constructor({ store, context, di, executionContextManager, actionConditionals, transformAction, }) {
640
675
  this.actionConditionals = flatten(actionConditionals !== null && actionConditionals !== void 0 ? actionConditionals : []);
641
676
  this.context = context;
677
+ this.store = store;
642
678
  this.di = di;
679
+ this.executionContextManager = executionContextManager;
643
680
  this.execution = new Map();
644
681
  this.transformAction = transformAction || identity;
645
682
  const initialState = store.getState(actionTramvaiReducer);
@@ -649,32 +686,64 @@ class ActionExecution {
649
686
  }, initialState.serverState);
650
687
  }
651
688
  }
652
- run(action, payload, type = actionType.local) {
653
- // TODO выпилить после перевода всех экшенов к виду Action
654
- this.transformAction(action);
655
- const parameters = getParameters(action);
656
- const executionState = this.getExecutionState(parameters);
689
+ async runInContext(executionContext, action, ...params) {
690
+ var _a, _b;
691
+ let parameters;
692
+ const payload = (_a = params[0]) !== null && _a !== void 0 ? _a : DEFAULT_PAYLOAD;
693
+ // TODO: replace type with pure context usage
694
+ const type = (executionContext === null || executionContext === void 0 ? void 0 : executionContext.values.pageActions) === true ? actionType.global : actionType.local;
695
+ // TODO: remove else branch after migration to new declareAction
696
+ if (isTramvaiAction(action)) {
697
+ parameters = action;
698
+ }
699
+ else {
700
+ this.transformAction(action);
701
+ parameters = getParameters(action);
702
+ }
703
+ const executionState = this.getExecutionState(parameters.name);
657
704
  if (!this.canExecuteAction(payload, parameters, executionState, type)) {
658
- return Promise.resolve();
705
+ switch (parameters.conditionsFailResult) {
706
+ case 'reject':
707
+ return Promise.reject(new ConditionFailError({
708
+ conditionName: (_b = executionState.forbiddenBy) !== null && _b !== void 0 ? _b : 'unknown',
709
+ targetName: parameters.name,
710
+ }));
711
+ default:
712
+ return Promise.resolve();
713
+ }
659
714
  }
660
- const deps = parameters.deps ? this.di.getOfDeps(parameters.deps) : {};
661
715
  executionState.status = 'pending';
662
- return Promise.resolve()
663
- .then(() => action(this.context, payload, deps))
664
- .then((data) => {
665
- executionState.status = 'success';
666
- return data;
667
- })
668
- .catch((err) => {
669
- executionState.status = 'failed';
670
- throw err;
716
+ return this.executionContextManager.withContext(executionContext, {
717
+ name: parameters.name,
718
+ values: (executionContext === null || executionContext === void 0 ? void 0 : executionContext.values.pageActions) === true ? { pageActions: false } : undefined,
719
+ }, (executionActionContext, abortController) => {
720
+ const context = this.createActionContext(executionContext, executionActionContext, abortController, parameters);
721
+ return Promise.resolve()
722
+ .then(() => {
723
+ if (isTramvaiAction(action)) {
724
+ return action.fn.apply(context, params);
725
+ }
726
+ return action(this.context, payload, context.deps);
727
+ })
728
+ .then((data) => {
729
+ executionState.status = 'success';
730
+ return data;
731
+ })
732
+ .catch((err) => {
733
+ executionState.status = 'failed';
734
+ throw err;
735
+ });
671
736
  });
672
737
  }
673
- getExecutionState(parameters) {
674
- let executionState = this.execution.get(parameters.name);
738
+ async run(action, ...params) {
739
+ return this.runInContext(null, action, ...params);
740
+ }
741
+ getExecutionState(name) {
742
+ let executionState = this.execution.get(name);
743
+ // TODO: probably do not need to create executionState on client as it is not used
675
744
  if (!executionState) {
676
745
  executionState = { status: 'pending', state: {} };
677
- this.execution.set(parameters.name, executionState);
746
+ this.execution.set(name, executionState);
678
747
  }
679
748
  return executionState;
680
749
  }
@@ -682,6 +751,17 @@ class ActionExecution {
682
751
  const actionChecker = new ActionChecker(this.actionConditionals, payload, parameters, executionState, type);
683
752
  return actionChecker.check();
684
753
  }
754
+ createActionContext(parentExecutionContext, actionExecutionContext, abortController, parameters) {
755
+ return {
756
+ abortController,
757
+ abortSignal: actionExecutionContext === null || actionExecutionContext === void 0 ? void 0 : actionExecutionContext.abortSignal,
758
+ executeAction: this.runInContext.bind(this, actionExecutionContext),
759
+ deps: parameters.deps ? this.di.getOfDeps(parameters.deps) : EMPTY_DEPS,
760
+ actionType: (parentExecutionContext === null || parentExecutionContext === void 0 ? void 0 : parentExecutionContext.values.pageActions) ? 'page' : 'standalone',
761
+ dispatch: this.store.dispatch,
762
+ getState: this.store.getState,
763
+ };
764
+ }
685
765
  }
686
766
 
687
767
  const GLOBAL_PARAMETER = '@@global';
@@ -711,56 +791,59 @@ class ActionRegistry {
711
791
  }
712
792
  }
713
793
 
714
- const payload = {};
715
794
  class ActionPageRunner {
716
- constructor({ store, actionExecution, limitTime, logger }) {
717
- this.store = store;
718
- this.actionExecution = actionExecution;
719
- this.limitTime = limitTime;
720
- this.log = logger('action:action-page-runner');
795
+ constructor(deps) {
796
+ this.deps = deps;
797
+ this.log = deps.logger('action:action-page-runner');
721
798
  }
722
799
  // TODO stopRunAtError нужен только для редиректов на стороне сервера в экшенах. И нужно пересмотреть реализацию редиректов
723
800
  runActions(actions, stopRunAtError = () => false) {
724
- return new Promise((resolve, reject) => {
725
- const timeoutMarker = setTimeout(() => {
726
- this.log.warn(`page actions has exceeded timeout of ${this.limitTime}ms, ignore some results of execution`);
727
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
728
- endChecker();
729
- }, this.limitTime);
730
- const endChecker = () => {
731
- clearTimeout(timeoutMarker);
732
- const result = {};
733
- this.actionExecution.execution.forEach((value, key) => {
734
- // достаем значения экшенов, которые успешно выполнились, остальные выполнятся на клиенте
735
- if (value.status === 'success') {
736
- result[key] = value;
737
- }
738
- });
739
- this.syncStateActions(result);
740
- resolve();
741
- };
742
- const actionMapper = (action) => {
743
- return Promise.resolve()
744
- .then(() => this.actionExecution.run(action, payload, actionType.global))
745
- .catch((error) => {
746
- const parameters = action[ACTION_PARAMETERS];
747
- this.log.error({
748
- error,
749
- event: `action-execution-error`,
750
- message: `${parameters.name} execution error`,
801
+ return this.deps.executionContextManager.withContext(this.deps.commandLineExecutionContext(), { name: 'pageActions', values: { pageActions: true } }, (executionContext, abortController) => {
802
+ return new Promise((resolve, reject) => {
803
+ const timeoutMarker = setTimeout(() => {
804
+ this.log.warn(`page actions has exceeded timeout of ${this.deps.limitTime}ms, ignore some results of execution`);
805
+ abortController.abort();
806
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
807
+ endChecker();
808
+ }, this.deps.limitTime);
809
+ const endChecker = () => {
810
+ clearTimeout(timeoutMarker);
811
+ const result = {};
812
+ // TODO: dehydrate only actions on first level as inner actions are running on client despite their execution on server
813
+ this.deps.actionExecution.execution.forEach((value, key) => {
814
+ // достаем значения экшенов, которые успешно выполнились, остальные выполнятся на клиенте
815
+ if (value.status === 'success') {
816
+ result[key] = value;
817
+ }
751
818
  });
752
- if (stopRunAtError(error)) {
753
- clearTimeout(timeoutMarker);
754
- reject(error);
755
- }
756
- });
757
- };
758
- // eslint-disable-next-line promise/catch-or-return
759
- Promise.all(actions.map(actionMapper)).then(endChecker);
819
+ this.syncStateActions(result);
820
+ resolve();
821
+ };
822
+ const actionMapper = (action) => {
823
+ return Promise.resolve()
824
+ .then(() => this.deps.actionExecution.runInContext(executionContext, action))
825
+ .catch((error) => {
826
+ if (!isSilentError(error)) {
827
+ const parameters = isTramvaiAction(action) ? action : action[ACTION_PARAMETERS];
828
+ this.log.error({
829
+ error,
830
+ event: `action-execution-error`,
831
+ message: `${parameters.name} execution error`,
832
+ });
833
+ }
834
+ if (stopRunAtError(error)) {
835
+ clearTimeout(timeoutMarker);
836
+ reject(error);
837
+ }
838
+ });
839
+ };
840
+ // eslint-disable-next-line promise/catch-or-return
841
+ Promise.all(actions.map(actionMapper)).then(endChecker);
842
+ });
760
843
  });
761
844
  }
762
845
  syncStateActions(success) {
763
- return this.store.dispatch(actionServerStateEvent(success));
846
+ return this.deps.store.dispatch(actionServerStateEvent(success));
764
847
  }
765
848
  }
766
849
 
@@ -829,7 +912,7 @@ ActionModule = __decorate([
829
912
  useClass: ActionRegistry,
830
913
  deps: { actionsList: ACTIONS_LIST_TOKEN },
831
914
  },
832
- provide({
915
+ provide$1({
833
916
  provide: ACTION_EXECUTION_TOKEN,
834
917
  scope: Scope.REQUEST,
835
918
  useClass: ActionExecution,
@@ -838,23 +921,26 @@ ActionModule = __decorate([
838
921
  context: CONTEXT_TOKEN,
839
922
  store: STORE_TOKEN,
840
923
  di: DI_TOKEN,
924
+ executionContextManager: EXECUTION_CONTEXT_MANAGER_TOKEN,
841
925
  transformAction: {
842
926
  token: 'actionTransformAction',
843
927
  optional: true,
844
928
  },
845
929
  },
846
930
  }),
847
- {
931
+ provide$1({
848
932
  provide: ACTION_PAGE_RUNNER_TOKEN,
849
933
  scope: Scope.REQUEST,
850
934
  useClass: ActionPageRunner,
851
935
  deps: {
852
936
  actionExecution: ACTION_EXECUTION_TOKEN,
937
+ executionContextManager: EXECUTION_CONTEXT_MANAGER_TOKEN,
938
+ commandLineExecutionContext: COMMAND_LINE_EXECUTION_CONTEXT_TOKEN,
853
939
  store: STORE_TOKEN,
854
940
  limitTime: 'limitActionGlobalTimeRun',
855
941
  logger: LOGGER_TOKEN,
856
942
  },
857
- },
943
+ }),
858
944
  {
859
945
  provide: 'limitActionGlobalTimeRun',
860
946
  useValue: 500,
@@ -996,6 +1082,58 @@ CacheModule = __decorate([
996
1082
  })
997
1083
  ], CacheModule);
998
1084
 
1085
+ const EMPTY_VALUES = {};
1086
+ const normalizeOptions = (nameOrOptions) => {
1087
+ return typeof nameOrOptions === 'string' ? { name: nameOrOptions } : nameOrOptions;
1088
+ };
1089
+ class ExecutionContextManager {
1090
+ async withContext(parentContext, nameOrOptions, cb) {
1091
+ const options = normalizeOptions(nameOrOptions);
1092
+ const { name, values: selfValues = EMPTY_VALUES } = options;
1093
+ const contextName = parentContext ? `${parentContext.name}.${name}` : name;
1094
+ if (parentContext === null || parentContext === void 0 ? void 0 : parentContext.abortSignal.aborted) {
1095
+ throw new ExecutionAbortError({
1096
+ message: `Execution aborted in context "${contextName}"`,
1097
+ contextName,
1098
+ });
1099
+ }
1100
+ const abortController = new AbortController();
1101
+ let abortListener;
1102
+ let values = selfValues;
1103
+ if (parentContext) {
1104
+ values = {
1105
+ ...parentContext.values,
1106
+ ...selfValues,
1107
+ };
1108
+ abortListener = () => {
1109
+ abortController.abort();
1110
+ };
1111
+ // abort child context AbortController if parent AbortController was aborted
1112
+ parentContext.abortSignal.addEventListener('abort', abortListener);
1113
+ }
1114
+ const context = {
1115
+ name: contextName,
1116
+ abortSignal: abortController.signal,
1117
+ values,
1118
+ };
1119
+ try {
1120
+ const result = await cb(context, abortController);
1121
+ return result;
1122
+ }
1123
+ catch (error) {
1124
+ if (!error.executionContextName) {
1125
+ error.executionContextName = context.name;
1126
+ }
1127
+ throw error;
1128
+ }
1129
+ finally {
1130
+ if (abortListener) {
1131
+ parentContext.abortSignal.removeEventListener('abort', abortListener);
1132
+ }
1133
+ }
1134
+ }
1135
+ }
1136
+
999
1137
  let CommonModule = class CommonModule {
1000
1138
  };
1001
1139
  CommonModule = __decorate([
@@ -1013,13 +1151,13 @@ CommonModule = __decorate([
1013
1151
  CacheModule,
1014
1152
  ],
1015
1153
  providers: [
1016
- provide({
1154
+ provide$1({
1017
1155
  // Инстанс хук системы
1018
1156
  provide: HOOK_TOKEN,
1019
1157
  scope: Scope.SINGLETON,
1020
1158
  useClass: Hooks,
1021
1159
  }),
1022
- provide({
1160
+ provide$1({
1023
1161
  // Регистр ui компонентов
1024
1162
  provide: COMPONENT_REGISTRY_TOKEN,
1025
1163
  scope: Scope.SINGLETON,
@@ -1028,7 +1166,7 @@ CommonModule = __decorate([
1028
1166
  componentList: { token: 'componentDefaultList', optional: true },
1029
1167
  },
1030
1168
  }),
1031
- provide({
1169
+ provide$1({
1032
1170
  // Управление бандлами, хранение и получение
1033
1171
  provide: BUNDLE_MANAGER_TOKEN,
1034
1172
  scope: Scope.SINGLETON,
@@ -1054,7 +1192,7 @@ CommonModule = __decorate([
1054
1192
  logger: LOGGER_TOKEN,
1055
1193
  },
1056
1194
  }),
1057
- provide({
1195
+ provide$1({
1058
1196
  // Клиентский контекст исполнения
1059
1197
  provide: CONTEXT_TOKEN,
1060
1198
  scope: Scope.REQUEST,
@@ -1066,6 +1204,10 @@ CommonModule = __decorate([
1066
1204
  store: STORE_TOKEN,
1067
1205
  },
1068
1206
  }),
1207
+ provide$1({
1208
+ provide: EXECUTION_CONTEXT_MANAGER_TOKEN,
1209
+ useClass: ExecutionContextManager,
1210
+ }),
1069
1211
  ...providers$2,
1070
1212
  ],
1071
1213
  })
@@ -1074,7 +1216,7 @@ CommonModule = __decorate([
1074
1216
  const providers = [];
1075
1217
 
1076
1218
  const stateProviders = [
1077
- provide({
1219
+ provide$1({
1078
1220
  provide: CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN,
1079
1221
  multi: true,
1080
1222
  useValue: [DISPATCHER_TOKEN, STORE_TOKEN, CONTEXT_TOKEN],
@@ -1100,12 +1242,12 @@ const lines = {
1100
1242
  client: command,
1101
1243
  };
1102
1244
  const commandProviders = [
1103
- provide({
1245
+ provide$1({
1104
1246
  provide: CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN,
1105
1247
  multi: true,
1106
1248
  useValue: COMMAND_LINE_RUNNER_TOKEN,
1107
1249
  }),
1108
- provide({
1250
+ provide$1({
1109
1251
  provide: COMMAND_LINES_TOKEN,
1110
1252
  scope: Scope.SINGLETON,
1111
1253
  useValue: lines,
@@ -1113,7 +1255,7 @@ const commandProviders = [
1113
1255
  ];
1114
1256
 
1115
1257
  const actionsProviders = [
1116
- provide({
1258
+ provide$1({
1117
1259
  provide: CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN,
1118
1260
  multi: true,
1119
1261
  useValue: [ACTION_EXECUTION_TOKEN, ACTION_PAGE_RUNNER_TOKEN],
@@ -1134,7 +1276,7 @@ CommonChildAppModule = __decorate([
1134
1276
  ...stateProviders,
1135
1277
  ...commandProviders,
1136
1278
  ...actionsProviders,
1137
- provide({
1279
+ provide$1({
1138
1280
  provide: EXTEND_RENDER,
1139
1281
  multi: true,
1140
1282
  useFactory: ({ context }) => {
@@ -1151,4 +1293,4 @@ CommonChildAppModule = __decorate([
1151
1293
  })
1152
1294
  ], CommonChildAppModule);
1153
1295
 
1154
- export { ActionExecution, CommandModule, CommonChildAppModule, CommonModule, alwaysCondition, createConsumerContext, onlyBrowser, onlyServer, pageBrowser, pageServer };
1296
+ export { ActionExecution, CommandModule, CommonChildAppModule, CommonModule, ExecutionContextManager, alwaysCondition, createConsumerContext, onlyBrowser, onlyServer, pageBrowser, pageServer };