@tramvai/module-child-app 2.70.1 → 2.72.3

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.
Files changed (73) hide show
  1. package/lib/browser/child/singletonProviders.browser.js +91 -0
  2. package/lib/browser/loader.browser.js +64 -0
  3. package/lib/browser/preload.browser.js +115 -0
  4. package/lib/browser/providers.browser.js +113 -0
  5. package/lib/browser/render.browser.js +28 -0
  6. package/lib/browser/runCommand.browser.js +8 -0
  7. package/lib/browser.browser.js +17 -0
  8. package/lib/server/child/singletonProviders.es.js +24 -0
  9. package/lib/server/child/singletonProviders.js +32 -0
  10. package/lib/server/loader.es.js +48 -0
  11. package/lib/server/loader.js +52 -0
  12. package/lib/server/preload.es.js +77 -0
  13. package/lib/server/preload.js +81 -0
  14. package/lib/server/providers.es.js +131 -0
  15. package/lib/server/providers.js +135 -0
  16. package/lib/server/render-slots.es.js +50 -0
  17. package/lib/server/render-slots.js +54 -0
  18. package/lib/server/render.es.js +39 -0
  19. package/lib/server/render.js +43 -0
  20. package/lib/server/stateManager.es.js +49 -0
  21. package/lib/server/stateManager.js +54 -0
  22. package/lib/server.browser.js +2 -1082
  23. package/lib/server.es.js +5 -1067
  24. package/lib/server.js +5 -1072
  25. package/lib/shared/child/providers.browser.js +36 -0
  26. package/lib/shared/child/providers.es.js +36 -0
  27. package/lib/shared/child/providers.js +44 -0
  28. package/lib/shared/child/singletonProviders.browser.js +24 -0
  29. package/lib/shared/child/singletonProviders.es.js +24 -0
  30. package/lib/shared/child/singletonProviders.js +28 -0
  31. package/lib/shared/child/stubs.browser.js +18 -0
  32. package/lib/shared/child/stubs.es.js +18 -0
  33. package/lib/shared/child/stubs.js +22 -0
  34. package/lib/shared/child/validate.browser.js +11 -0
  35. package/lib/shared/child/validate.es.js +11 -0
  36. package/lib/shared/child/validate.js +15 -0
  37. package/lib/shared/command.browser.js +38 -0
  38. package/lib/shared/command.es.js +38 -0
  39. package/lib/shared/command.js +42 -0
  40. package/lib/shared/constants.browser.js +3 -0
  41. package/lib/shared/constants.es.js +3 -0
  42. package/lib/shared/constants.js +7 -0
  43. package/lib/shared/di.browser.js +44 -0
  44. package/lib/shared/di.es.js +44 -0
  45. package/lib/shared/di.js +48 -0
  46. package/lib/shared/loader.browser.js +7 -0
  47. package/lib/shared/loader.es.js +7 -0
  48. package/lib/shared/loader.js +11 -0
  49. package/lib/shared/providers.browser.js +231 -0
  50. package/lib/shared/providers.es.js +231 -0
  51. package/lib/shared/providers.js +235 -0
  52. package/lib/shared/react/component.browser.js +104 -0
  53. package/lib/shared/react/component.es.js +104 -0
  54. package/lib/shared/react/component.js +112 -0
  55. package/lib/shared/react/render-context.browser.js +5 -0
  56. package/lib/shared/react/render-context.es.js +5 -0
  57. package/lib/shared/react/render-context.js +9 -0
  58. package/lib/shared/render.browser.js +10 -0
  59. package/lib/shared/render.es.js +10 -0
  60. package/lib/shared/render.js +14 -0
  61. package/lib/shared/resolutionConfigManager.browser.js +58 -0
  62. package/lib/shared/resolutionConfigManager.es.js +58 -0
  63. package/lib/shared/resolutionConfigManager.js +67 -0
  64. package/lib/shared/singletonDi.browser.js +95 -0
  65. package/lib/shared/singletonDi.es.js +95 -0
  66. package/lib/shared/singletonDi.js +103 -0
  67. package/lib/shared/store.browser.js +13 -0
  68. package/lib/shared/store.es.js +13 -0
  69. package/lib/shared/store.js +18 -0
  70. package/lib/shared/webpack/moduleFederation.browser.js +49 -0
  71. package/lib/shared/webpack/moduleFederation.es.js +49 -0
  72. package/lib/shared/webpack/moduleFederation.js +54 -0
  73. package/package.json +17 -18
@@ -0,0 +1,104 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import noop from '@tinkoff/utils/function/noop';
3
+ import { memo, Suspense, useContext, useMemo, useState, useEffect } from 'react';
4
+ import { CHILD_APP_INTERNAL_RENDER_TOKEN } from '@tramvai/tokens-child-app';
5
+ import { LOGGER_TOKEN } from '@tramvai/tokens-common';
6
+ import { UniversalErrorBoundary, useDi } from '@tramvai/react';
7
+ import { useUrl } from '@tramvai/module-router';
8
+ import { RenderContext } from './render-context.browser.js';
9
+
10
+ const FailedChildAppFallback = ({ config: { name, version, tag, fallback: Fallback }, }) => {
11
+ const logger = useDi(LOGGER_TOKEN);
12
+ const log = logger('child-app:render');
13
+ // On client-side hydration errors will be handled in `hydrateRoot` `onRecoverableError` property,
14
+ // and update errors will be handled in Error Boundaries.
15
+ //
16
+ // Also, this component never be rendered at client-side, and we check environment only for safety
17
+ // (server errors logic described here https://github.com/reactjs/rfcs/blob/main/text/0215-server-errors-in-react-18.md).
18
+ //
19
+ // On server-side, we still use `renderToString`,
20
+ // and need to manually log render errors for components, wrapped in Suspense Boundaries.
21
+ if (typeof window === 'undefined') {
22
+ log.error({
23
+ event: 'failed-render',
24
+ message: 'child-app failed to render, will try to recover during hydration',
25
+ name,
26
+ version,
27
+ tag,
28
+ });
29
+ }
30
+ return Fallback ? jsx(Fallback, {}) : null;
31
+ };
32
+ const ChildAppWrapper = ({ name, version, tag, props, fallback: Fallback, }) => {
33
+ const renderManager = useContext(RenderContext);
34
+ const logger = useDi(LOGGER_TOKEN);
35
+ const log = logger('child-app:render');
36
+ const [maybeDi, maybePromiseDi] = useMemo(() => {
37
+ return renderManager.getChildDi({ name, version, tag });
38
+ }, [name, version, tag, renderManager]);
39
+ const [di, setDi] = useState(maybeDi);
40
+ const [promiseDi, setPromiseDi] = useState(maybePromiseDi);
41
+ useEffect(() => {
42
+ if (!di && promiseDi) {
43
+ // any errors with loading child-app should be handled in some other place
44
+ promiseDi
45
+ .then(setDi)
46
+ .finally(() => setPromiseDi(undefined))
47
+ .catch(noop);
48
+ }
49
+ }, [di, promiseDi]);
50
+ if (!di && promiseDi) {
51
+ // in case child-app was not rendered on ssr
52
+ // and we have to wait before it's loading
53
+ return Fallback ? jsx(Fallback, {}) : null;
54
+ }
55
+ if (!di) {
56
+ log.error({
57
+ event: 'not-found',
58
+ name,
59
+ version,
60
+ tag,
61
+ message: 'child-app was not initialized',
62
+ });
63
+ if (process.env.__TRAMVAI_CONCURRENT_FEATURES || typeof window !== 'undefined') {
64
+ throw new Error(`Child-app was not initialized, check the loading error for child-app "${name}"`);
65
+ }
66
+ return Fallback ? jsx(Fallback, {}) : null;
67
+ }
68
+ try {
69
+ const Cmp = di.get({ token: CHILD_APP_INTERNAL_RENDER_TOKEN, optional: true });
70
+ if (!Cmp) {
71
+ log.error({
72
+ event: 'empty-render',
73
+ message: 'Child-app does not provide render token',
74
+ name,
75
+ version,
76
+ tag,
77
+ });
78
+ return null;
79
+ }
80
+ return jsx(Cmp, { di: di, props: props });
81
+ }
82
+ catch (error) {
83
+ log.error({
84
+ event: 'get-render',
85
+ message: 'Cannot get render token from child-app',
86
+ error,
87
+ name,
88
+ version,
89
+ tag,
90
+ });
91
+ return null;
92
+ }
93
+ };
94
+ const ChildApp = memo((config) => {
95
+ const { fallback } = config;
96
+ const url = useUrl();
97
+ const result = (jsx(UniversalErrorBoundary, { url: url, fallback: fallback, children: jsx(ChildAppWrapper, { ...config }) }));
98
+ if (process.env.__TRAMVAI_CONCURRENT_FEATURES) {
99
+ return jsx(Suspense, { fallback: jsx(FailedChildAppFallback, { config: config }), children: result });
100
+ }
101
+ return result;
102
+ });
103
+
104
+ export { ChildApp };
@@ -0,0 +1,104 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import noop from '@tinkoff/utils/function/noop';
3
+ import { memo, Suspense, useContext, useMemo, useState, useEffect } from 'react';
4
+ import { CHILD_APP_INTERNAL_RENDER_TOKEN } from '@tramvai/tokens-child-app';
5
+ import { LOGGER_TOKEN } from '@tramvai/tokens-common';
6
+ import { UniversalErrorBoundary, useDi } from '@tramvai/react';
7
+ import { useUrl } from '@tramvai/module-router';
8
+ import { RenderContext } from './render-context.es.js';
9
+
10
+ const FailedChildAppFallback = ({ config: { name, version, tag, fallback: Fallback }, }) => {
11
+ const logger = useDi(LOGGER_TOKEN);
12
+ const log = logger('child-app:render');
13
+ // On client-side hydration errors will be handled in `hydrateRoot` `onRecoverableError` property,
14
+ // and update errors will be handled in Error Boundaries.
15
+ //
16
+ // Also, this component never be rendered at client-side, and we check environment only for safety
17
+ // (server errors logic described here https://github.com/reactjs/rfcs/blob/main/text/0215-server-errors-in-react-18.md).
18
+ //
19
+ // On server-side, we still use `renderToString`,
20
+ // and need to manually log render errors for components, wrapped in Suspense Boundaries.
21
+ if (typeof window === 'undefined') {
22
+ log.error({
23
+ event: 'failed-render',
24
+ message: 'child-app failed to render, will try to recover during hydration',
25
+ name,
26
+ version,
27
+ tag,
28
+ });
29
+ }
30
+ return Fallback ? jsx(Fallback, {}) : null;
31
+ };
32
+ const ChildAppWrapper = ({ name, version, tag, props, fallback: Fallback, }) => {
33
+ const renderManager = useContext(RenderContext);
34
+ const logger = useDi(LOGGER_TOKEN);
35
+ const log = logger('child-app:render');
36
+ const [maybeDi, maybePromiseDi] = useMemo(() => {
37
+ return renderManager.getChildDi({ name, version, tag });
38
+ }, [name, version, tag, renderManager]);
39
+ const [di, setDi] = useState(maybeDi);
40
+ const [promiseDi, setPromiseDi] = useState(maybePromiseDi);
41
+ useEffect(() => {
42
+ if (!di && promiseDi) {
43
+ // any errors with loading child-app should be handled in some other place
44
+ promiseDi
45
+ .then(setDi)
46
+ .finally(() => setPromiseDi(undefined))
47
+ .catch(noop);
48
+ }
49
+ }, [di, promiseDi]);
50
+ if (!di && promiseDi) {
51
+ // in case child-app was not rendered on ssr
52
+ // and we have to wait before it's loading
53
+ return Fallback ? jsx(Fallback, {}) : null;
54
+ }
55
+ if (!di) {
56
+ log.error({
57
+ event: 'not-found',
58
+ name,
59
+ version,
60
+ tag,
61
+ message: 'child-app was not initialized',
62
+ });
63
+ if (process.env.__TRAMVAI_CONCURRENT_FEATURES || typeof window !== 'undefined') {
64
+ throw new Error(`Child-app was not initialized, check the loading error for child-app "${name}"`);
65
+ }
66
+ return Fallback ? jsx(Fallback, {}) : null;
67
+ }
68
+ try {
69
+ const Cmp = di.get({ token: CHILD_APP_INTERNAL_RENDER_TOKEN, optional: true });
70
+ if (!Cmp) {
71
+ log.error({
72
+ event: 'empty-render',
73
+ message: 'Child-app does not provide render token',
74
+ name,
75
+ version,
76
+ tag,
77
+ });
78
+ return null;
79
+ }
80
+ return jsx(Cmp, { di: di, props: props });
81
+ }
82
+ catch (error) {
83
+ log.error({
84
+ event: 'get-render',
85
+ message: 'Cannot get render token from child-app',
86
+ error,
87
+ name,
88
+ version,
89
+ tag,
90
+ });
91
+ return null;
92
+ }
93
+ };
94
+ const ChildApp = memo((config) => {
95
+ const { fallback } = config;
96
+ const url = useUrl();
97
+ const result = (jsx(UniversalErrorBoundary, { url: url, fallback: fallback, children: jsx(ChildAppWrapper, { ...config }) }));
98
+ if (process.env.__TRAMVAI_CONCURRENT_FEATURES) {
99
+ return jsx(Suspense, { fallback: jsx(FailedChildAppFallback, { config: config }), children: result });
100
+ }
101
+ return result;
102
+ });
103
+
104
+ export { ChildApp };
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var noop = require('@tinkoff/utils/function/noop');
7
+ var react = require('react');
8
+ var tokensChildApp = require('@tramvai/tokens-child-app');
9
+ var tokensCommon = require('@tramvai/tokens-common');
10
+ var react$1 = require('@tramvai/react');
11
+ var moduleRouter = require('@tramvai/module-router');
12
+ var renderContext = require('./render-context.js');
13
+
14
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
15
+
16
+ var noop__default = /*#__PURE__*/_interopDefaultLegacy(noop);
17
+
18
+ const FailedChildAppFallback = ({ config: { name, version, tag, fallback: Fallback }, }) => {
19
+ const logger = react$1.useDi(tokensCommon.LOGGER_TOKEN);
20
+ const log = logger('child-app:render');
21
+ // On client-side hydration errors will be handled in `hydrateRoot` `onRecoverableError` property,
22
+ // and update errors will be handled in Error Boundaries.
23
+ //
24
+ // Also, this component never be rendered at client-side, and we check environment only for safety
25
+ // (server errors logic described here https://github.com/reactjs/rfcs/blob/main/text/0215-server-errors-in-react-18.md).
26
+ //
27
+ // On server-side, we still use `renderToString`,
28
+ // and need to manually log render errors for components, wrapped in Suspense Boundaries.
29
+ if (typeof window === 'undefined') {
30
+ log.error({
31
+ event: 'failed-render',
32
+ message: 'child-app failed to render, will try to recover during hydration',
33
+ name,
34
+ version,
35
+ tag,
36
+ });
37
+ }
38
+ return Fallback ? jsxRuntime.jsx(Fallback, {}) : null;
39
+ };
40
+ const ChildAppWrapper = ({ name, version, tag, props, fallback: Fallback, }) => {
41
+ const renderManager = react.useContext(renderContext.RenderContext);
42
+ const logger = react$1.useDi(tokensCommon.LOGGER_TOKEN);
43
+ const log = logger('child-app:render');
44
+ const [maybeDi, maybePromiseDi] = react.useMemo(() => {
45
+ return renderManager.getChildDi({ name, version, tag });
46
+ }, [name, version, tag, renderManager]);
47
+ const [di, setDi] = react.useState(maybeDi);
48
+ const [promiseDi, setPromiseDi] = react.useState(maybePromiseDi);
49
+ react.useEffect(() => {
50
+ if (!di && promiseDi) {
51
+ // any errors with loading child-app should be handled in some other place
52
+ promiseDi
53
+ .then(setDi)
54
+ .finally(() => setPromiseDi(undefined))
55
+ .catch(noop__default["default"]);
56
+ }
57
+ }, [di, promiseDi]);
58
+ if (!di && promiseDi) {
59
+ // in case child-app was not rendered on ssr
60
+ // and we have to wait before it's loading
61
+ return Fallback ? jsxRuntime.jsx(Fallback, {}) : null;
62
+ }
63
+ if (!di) {
64
+ log.error({
65
+ event: 'not-found',
66
+ name,
67
+ version,
68
+ tag,
69
+ message: 'child-app was not initialized',
70
+ });
71
+ if (process.env.__TRAMVAI_CONCURRENT_FEATURES || typeof window !== 'undefined') {
72
+ throw new Error(`Child-app was not initialized, check the loading error for child-app "${name}"`);
73
+ }
74
+ return Fallback ? jsxRuntime.jsx(Fallback, {}) : null;
75
+ }
76
+ try {
77
+ const Cmp = di.get({ token: tokensChildApp.CHILD_APP_INTERNAL_RENDER_TOKEN, optional: true });
78
+ if (!Cmp) {
79
+ log.error({
80
+ event: 'empty-render',
81
+ message: 'Child-app does not provide render token',
82
+ name,
83
+ version,
84
+ tag,
85
+ });
86
+ return null;
87
+ }
88
+ return jsxRuntime.jsx(Cmp, { di: di, props: props });
89
+ }
90
+ catch (error) {
91
+ log.error({
92
+ event: 'get-render',
93
+ message: 'Cannot get render token from child-app',
94
+ error,
95
+ name,
96
+ version,
97
+ tag,
98
+ });
99
+ return null;
100
+ }
101
+ };
102
+ const ChildApp = react.memo((config) => {
103
+ const { fallback } = config;
104
+ const url = moduleRouter.useUrl();
105
+ const result = (jsxRuntime.jsx(react$1.UniversalErrorBoundary, { url: url, fallback: fallback, children: jsxRuntime.jsx(ChildAppWrapper, { ...config }) }));
106
+ if (process.env.__TRAMVAI_CONCURRENT_FEATURES) {
107
+ return jsxRuntime.jsx(react.Suspense, { fallback: jsxRuntime.jsx(FailedChildAppFallback, { config: config }), children: result });
108
+ }
109
+ return result;
110
+ });
111
+
112
+ exports.ChildApp = ChildApp;
@@ -0,0 +1,5 @@
1
+ import { createContext } from 'react';
2
+
3
+ const RenderContext = createContext(null);
4
+
5
+ export { RenderContext };
@@ -0,0 +1,5 @@
1
+ import { createContext } from 'react';
2
+
3
+ const RenderContext = createContext(null);
4
+
5
+ export { RenderContext };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var react = require('react');
6
+
7
+ const RenderContext = react.createContext(null);
8
+
9
+ exports.RenderContext = RenderContext;
@@ -0,0 +1,10 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { RenderContext } from './react/render-context.browser.js';
3
+
4
+ const extendRender = ({ renderManager, }) => {
5
+ return (render) => {
6
+ return jsx(RenderContext.Provider, { value: renderManager, children: render });
7
+ };
8
+ };
9
+
10
+ export { extendRender };
@@ -0,0 +1,10 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { RenderContext } from './react/render-context.es.js';
3
+
4
+ const extendRender = ({ renderManager, }) => {
5
+ return (render) => {
6
+ return jsx(RenderContext.Provider, { value: renderManager, children: render });
7
+ };
8
+ };
9
+
10
+ export { extendRender };
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var renderContext = require('./react/render-context.js');
7
+
8
+ const extendRender = ({ renderManager, }) => {
9
+ return (render) => {
10
+ return jsxRuntime.jsx(renderContext.RenderContext.Provider, { value: renderManager, children: render });
11
+ };
12
+ };
13
+
14
+ exports.extendRender = extendRender;
@@ -0,0 +1,58 @@
1
+ import applyOrReturn from '@tinkoff/utils/function/applyOrReturn';
2
+ import flatten from '@tinkoff/utils/array/flatten';
3
+
4
+ class ChildAppResolutionConfigManager {
5
+ constructor({ configs, logger, }) {
6
+ this.hasInitialized = false;
7
+ this.rawConfigs = configs !== null && configs !== void 0 ? configs : [];
8
+ this.mapping = new Map();
9
+ this.log = logger('child-app:resolution-config');
10
+ }
11
+ async init() {
12
+ if (this.hasInitialized) {
13
+ return;
14
+ }
15
+ if (this.initPromise) {
16
+ return this.initPromise;
17
+ }
18
+ this.initPromise = (async () => {
19
+ const configs = await Promise.all(this.rawConfigs.map((rawConfig) => {
20
+ return Promise.resolve()
21
+ .then(() => {
22
+ return applyOrReturn([], rawConfig);
23
+ })
24
+ .catch((error) => {
25
+ this.log.error(error, 'Failed while resolving resolution config');
26
+ });
27
+ }));
28
+ flatten(configs).forEach((config) => {
29
+ if (config) {
30
+ this.mapping.set(config.name, config);
31
+ }
32
+ });
33
+ this.hasInitialized = true;
34
+ })();
35
+ return this.initPromise;
36
+ }
37
+ resolve({ name, version, tag = 'latest' }) {
38
+ var _a;
39
+ const fromMapping = this.mapping.get(name);
40
+ if (!fromMapping) {
41
+ return;
42
+ }
43
+ const cfg = fromMapping.byTag[tag];
44
+ if (process.env.NODE_ENV === 'development' && tag === 'debug' && !cfg) {
45
+ return {
46
+ baseUrl: 'http://localhost:4040/',
47
+ version: '0.0.0-stub',
48
+ };
49
+ }
50
+ return {
51
+ ...cfg,
52
+ baseUrl: (_a = cfg.baseUrl) !== null && _a !== void 0 ? _a : fromMapping.baseUrl,
53
+ version: version !== null && version !== void 0 ? version : cfg.version,
54
+ };
55
+ }
56
+ }
57
+
58
+ export { ChildAppResolutionConfigManager };
@@ -0,0 +1,58 @@
1
+ import applyOrReturn from '@tinkoff/utils/function/applyOrReturn';
2
+ import flatten from '@tinkoff/utils/array/flatten';
3
+
4
+ class ChildAppResolutionConfigManager {
5
+ constructor({ configs, logger, }) {
6
+ this.hasInitialized = false;
7
+ this.rawConfigs = configs !== null && configs !== void 0 ? configs : [];
8
+ this.mapping = new Map();
9
+ this.log = logger('child-app:resolution-config');
10
+ }
11
+ async init() {
12
+ if (this.hasInitialized) {
13
+ return;
14
+ }
15
+ if (this.initPromise) {
16
+ return this.initPromise;
17
+ }
18
+ this.initPromise = (async () => {
19
+ const configs = await Promise.all(this.rawConfigs.map((rawConfig) => {
20
+ return Promise.resolve()
21
+ .then(() => {
22
+ return applyOrReturn([], rawConfig);
23
+ })
24
+ .catch((error) => {
25
+ this.log.error(error, 'Failed while resolving resolution config');
26
+ });
27
+ }));
28
+ flatten(configs).forEach((config) => {
29
+ if (config) {
30
+ this.mapping.set(config.name, config);
31
+ }
32
+ });
33
+ this.hasInitialized = true;
34
+ })();
35
+ return this.initPromise;
36
+ }
37
+ resolve({ name, version, tag = 'latest' }) {
38
+ var _a;
39
+ const fromMapping = this.mapping.get(name);
40
+ if (!fromMapping) {
41
+ return;
42
+ }
43
+ const cfg = fromMapping.byTag[tag];
44
+ if (process.env.NODE_ENV === 'development' && tag === 'debug' && !cfg) {
45
+ return {
46
+ baseUrl: 'http://localhost:4040/',
47
+ version: '0.0.0-stub',
48
+ };
49
+ }
50
+ return {
51
+ ...cfg,
52
+ baseUrl: (_a = cfg.baseUrl) !== null && _a !== void 0 ? _a : fromMapping.baseUrl,
53
+ version: version !== null && version !== void 0 ? version : cfg.version,
54
+ };
55
+ }
56
+ }
57
+
58
+ export { ChildAppResolutionConfigManager };
@@ -0,0 +1,67 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var applyOrReturn = require('@tinkoff/utils/function/applyOrReturn');
6
+ var flatten = require('@tinkoff/utils/array/flatten');
7
+
8
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
+
10
+ var applyOrReturn__default = /*#__PURE__*/_interopDefaultLegacy(applyOrReturn);
11
+ var flatten__default = /*#__PURE__*/_interopDefaultLegacy(flatten);
12
+
13
+ class ChildAppResolutionConfigManager {
14
+ constructor({ configs, logger, }) {
15
+ this.hasInitialized = false;
16
+ this.rawConfigs = configs !== null && configs !== void 0 ? configs : [];
17
+ this.mapping = new Map();
18
+ this.log = logger('child-app:resolution-config');
19
+ }
20
+ async init() {
21
+ if (this.hasInitialized) {
22
+ return;
23
+ }
24
+ if (this.initPromise) {
25
+ return this.initPromise;
26
+ }
27
+ this.initPromise = (async () => {
28
+ const configs = await Promise.all(this.rawConfigs.map((rawConfig) => {
29
+ return Promise.resolve()
30
+ .then(() => {
31
+ return applyOrReturn__default["default"]([], rawConfig);
32
+ })
33
+ .catch((error) => {
34
+ this.log.error(error, 'Failed while resolving resolution config');
35
+ });
36
+ }));
37
+ flatten__default["default"](configs).forEach((config) => {
38
+ if (config) {
39
+ this.mapping.set(config.name, config);
40
+ }
41
+ });
42
+ this.hasInitialized = true;
43
+ })();
44
+ return this.initPromise;
45
+ }
46
+ resolve({ name, version, tag = 'latest' }) {
47
+ var _a;
48
+ const fromMapping = this.mapping.get(name);
49
+ if (!fromMapping) {
50
+ return;
51
+ }
52
+ const cfg = fromMapping.byTag[tag];
53
+ if (process.env.NODE_ENV === 'development' && tag === 'debug' && !cfg) {
54
+ return {
55
+ baseUrl: 'http://localhost:4040/',
56
+ version: '0.0.0-stub',
57
+ };
58
+ }
59
+ return {
60
+ ...cfg,
61
+ baseUrl: (_a = cfg.baseUrl) !== null && _a !== void 0 ? _a : fromMapping.baseUrl,
62
+ version: version !== null && version !== void 0 ? version : cfg.version,
63
+ };
64
+ }
65
+ }
66
+
67
+ exports.ChildAppResolutionConfigManager = ChildAppResolutionConfigManager;
@@ -0,0 +1,95 @@
1
+ import flatten from '@tinkoff/utils/array/flatten';
2
+ import { Container } from '@tinkoff/dippy';
3
+ import { walkOfModules, getModuleParameters } from '@tramvai/core';
4
+ import { CHILD_APP_INTERNAL_CONFIG_TOKEN, IS_CHILD_APP_DI_TOKEN, CHILD_APP_INTERNAL_ACTION_TOKEN, CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN } from '@tramvai/tokens-child-app';
5
+ import { getChildProviders } from './child/singletonProviders.browser.js';
6
+ import { commonModuleStubs } from './child/stubs.browser.js';
7
+ import { validateChildAppProvider } from './child/validate.browser.js';
8
+
9
+ class SingletonDiManager {
10
+ constructor({ logger, appDi, loader, }) {
11
+ this.cache = new Map();
12
+ this.log = logger('child-app:singleton-di-manager');
13
+ this.appDi = appDi;
14
+ this.loader = loader;
15
+ }
16
+ getChildDi(config) {
17
+ const { key, tag } = config;
18
+ if (this.cache.has(key)) {
19
+ return this.cache.get(key);
20
+ }
21
+ try {
22
+ const di = this.resolveDi(config);
23
+ if (di && tag !== 'debug') {
24
+ this.cache.set(key, di);
25
+ }
26
+ return di;
27
+ }
28
+ catch (error) {
29
+ this.log.error({
30
+ event: 'resolve-di-fail',
31
+ error,
32
+ config,
33
+ });
34
+ }
35
+ }
36
+ forEachChildDi(cb) {
37
+ this.cache.forEach((di) => {
38
+ cb(di);
39
+ });
40
+ }
41
+ resolveDi(config) {
42
+ const children = this.loader.get(config);
43
+ if (!children) {
44
+ return;
45
+ }
46
+ const di = new Container([
47
+ {
48
+ provide: CHILD_APP_INTERNAL_CONFIG_TOKEN,
49
+ useValue: config,
50
+ },
51
+ {
52
+ provide: IS_CHILD_APP_DI_TOKEN,
53
+ useValue: true,
54
+ },
55
+ ], this.appDi);
56
+ const { modules = [], providers = [], actions = [] } = children;
57
+ // add providers on the Singleton Level to make it possible to reuse providers from the root-app Container
58
+ const childProviders = getChildProviders(this.appDi);
59
+ childProviders.forEach((provider) => {
60
+ di.register(provider);
61
+ });
62
+ const resolvedModules = walkOfModules(modules);
63
+ resolvedModules.forEach((mod) => {
64
+ const moduleParameters = getModuleParameters(mod);
65
+ moduleParameters.providers.forEach((provider) => {
66
+ di.register(provider);
67
+ });
68
+ });
69
+ providers.forEach((provider) => {
70
+ if (process.env.NODE_ENV === 'development') {
71
+ validateChildAppProvider(provider);
72
+ }
73
+ di.register(provider);
74
+ });
75
+ di.register({
76
+ provide: CHILD_APP_INTERNAL_ACTION_TOKEN,
77
+ multi: true,
78
+ useValue: actions,
79
+ });
80
+ const borrowTokens = di.get({ token: CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN, optional: true });
81
+ if (borrowTokens) {
82
+ flatten(borrowTokens).forEach((token) => {
83
+ di.borrowToken(this.appDi, token);
84
+ });
85
+ }
86
+ commonModuleStubs.forEach((stub) => {
87
+ if (!di.has(stub.provide)) {
88
+ di.register(stub);
89
+ }
90
+ });
91
+ return di;
92
+ }
93
+ }
94
+
95
+ export { SingletonDiManager };