@tramvai/module-child-app 1.65.1 → 1.68.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/README.md +58 -2
- package/lib/browser/child/providers.d.ts +1 -1
- package/lib/browser/child/singletonProviders.d.ts +3 -0
- package/lib/browser/preload.d.ts +8 -2
- package/lib/server/child/singletonProviders.d.ts +3 -0
- package/lib/server/preload.d.ts +4 -5
- package/lib/server/render.d.ts +2 -1
- package/lib/server.browser.js +108 -41
- package/lib/server.es.js +121 -65
- package/lib/server.js +120 -63
- package/lib/shared/child/singletonProviders.d.ts +3 -0
- package/lib/shared/resolutionConfigManager.d.ts +14 -0
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -129,14 +129,70 @@ State for child-apps will be dehydrated on server as separate variable in the re
|
|
|
129
129
|
|
|
130
130
|
Usually child-app cannot read data from root-app stores, but the dangerous workaround that allows to subscribe on any root-app store exists.
|
|
131
131
|
|
|
132
|
-
It may be done using `
|
|
132
|
+
It may be done using `CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN` token.
|
|
133
133
|
|
|
134
|
-
This token is considered dangerous as it leads to high coupling with stores from root-app and this way stores in root-app might not change their public interface. But, in most cases, changes in stores ignore breaking change tracking and often breaks backward-compatibility. So **do not use this token if you can**, and if you should - use as little as possible from root-app and provide some fallback in case of wrong data.
|
|
134
|
+
This token is considered dangerous as it leads to high coupling with stores from root-app and this way stores in root-app might not change their public interface. But, in most cases, changes in stores ignore breaking change tracking and often breaks backward-compatibility. So **do not use this token if you can**, and if you should - use as little as possible from root-app and provide some fallback in case of wrong data.
|
|
135
|
+
|
|
136
|
+
[See how to do it](#child_app_internal_root_state_subscription_token)
|
|
135
137
|
|
|
136
138
|
:::
|
|
137
139
|
|
|
138
140
|
## API
|
|
139
141
|
|
|
142
|
+
### CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN
|
|
143
|
+
|
|
144
|
+
Allows to subscribe to any store from the root app and execute actions based on its state, e.g. to fill internal child-app state.
|
|
145
|
+
|
|
146
|
+
1. Create a new store and a new event within child-app. This store might be used inside child-app as usual store.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
import { createReducer, createEvent } from '@tramvai/state';
|
|
150
|
+
|
|
151
|
+
interface State {
|
|
152
|
+
value: string;
|
|
153
|
+
}
|
|
154
|
+
export const setRootState = createEvent<string>('child-root set state');
|
|
155
|
+
|
|
156
|
+
export const rootStore = createReducer('child-root', { value: 'child' } as State).on(
|
|
157
|
+
setRootState,
|
|
158
|
+
(state, value) => {
|
|
159
|
+
return { value };
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
2. Add provider for the `CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN` in order to subscribe to store. In subscription you can dispatch internal event from the child-app
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
provide({
|
|
168
|
+
provide: CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN,
|
|
169
|
+
multi: true,
|
|
170
|
+
useFactory: ({ context }) => {
|
|
171
|
+
return {
|
|
172
|
+
stores: ['root'],
|
|
173
|
+
listener: (state: Record<string, any>) => {
|
|
174
|
+
return context.dispatch(setRootState(`root ${state.root.value}`));
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
deps: {
|
|
179
|
+
context: CONTEXT_TOKEN,
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
3. Use internal child-app store anywhere in the child-app
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
export const StateCmp = () => {
|
|
188
|
+
const value = useSelector([rootStore], (state) => {
|
|
189
|
+
return state['child-root'].value;
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return <div id="child-state">Current Value from Root Store: {value}</div>;
|
|
193
|
+
};
|
|
194
|
+
```
|
|
195
|
+
|
|
140
196
|
## How to
|
|
141
197
|
|
|
142
198
|
### Connect a child app
|
package/lib/browser/preload.d.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import type { ChildAppCommandLineRunner, ChildAppRequestConfig, ChildAppLoader, ChildAppPreloadManager, CHILD_APP_RESOLVE_CONFIG_TOKEN } from '@tramvai/tokens-child-app';
|
|
1
|
+
import type { ChildAppCommandLineRunner, ChildAppRequestConfig, ChildAppLoader, ChildAppPreloadManager, CHILD_APP_RESOLVE_CONFIG_TOKEN, CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN } from '@tramvai/tokens-child-app';
|
|
2
2
|
import type { STORE_TOKEN } from '@tramvai/tokens-common';
|
|
3
3
|
export declare class PreloadManager implements ChildAppPreloadManager {
|
|
4
4
|
private loader;
|
|
5
5
|
private runner;
|
|
6
|
+
private store;
|
|
7
|
+
private resolutionConfigManager;
|
|
6
8
|
private resolveExternalConfig;
|
|
7
9
|
private pageHasLoaded;
|
|
8
10
|
private map;
|
|
9
11
|
private serverPreloaded;
|
|
10
12
|
private preloadMap;
|
|
11
|
-
|
|
13
|
+
private hasInitialized;
|
|
14
|
+
constructor({ loader, runner, resolutionConfigManager, resolveExternalConfig, store, }: {
|
|
12
15
|
loader: ChildAppLoader;
|
|
13
16
|
runner: ChildAppCommandLineRunner;
|
|
17
|
+
resolutionConfigManager: typeof CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN;
|
|
14
18
|
resolveExternalConfig: typeof CHILD_APP_RESOLVE_CONFIG_TOKEN;
|
|
15
19
|
store: typeof STORE_TOKEN;
|
|
16
20
|
});
|
|
@@ -19,5 +23,7 @@ export declare class PreloadManager implements ChildAppPreloadManager {
|
|
|
19
23
|
runPreloaded(): Promise<void>;
|
|
20
24
|
clearPreloaded(): Promise<void>;
|
|
21
25
|
getPreloadedList(): ChildAppRequestConfig[];
|
|
26
|
+
private initServerPreloaded;
|
|
27
|
+
private init;
|
|
22
28
|
private run;
|
|
23
29
|
}
|
package/lib/server/preload.d.ts
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
import type { ChildAppCommandLineRunner, ChildAppRequestConfig, ChildAppLoader, ChildAppPreloadManager, ChildAppStateManager, CHILD_APP_RESOLVE_CONFIG_TOKEN,
|
|
1
|
+
import type { ChildAppCommandLineRunner, ChildAppRequestConfig, ChildAppLoader, ChildAppPreloadManager, ChildAppStateManager, CHILD_APP_RESOLVE_CONFIG_TOKEN, CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN } from '@tramvai/tokens-child-app';
|
|
2
2
|
export declare class PreloadManager implements ChildAppPreloadManager {
|
|
3
3
|
private loader;
|
|
4
4
|
private runner;
|
|
5
5
|
private stateManager;
|
|
6
|
-
private
|
|
6
|
+
private resolutionConfigManager;
|
|
7
7
|
private readonly resolveFullConfig;
|
|
8
8
|
private shouldRunImmediately;
|
|
9
9
|
private map;
|
|
10
10
|
private preloadMap;
|
|
11
|
-
|
|
12
|
-
constructor({ loader, runner, stateManager, preloadExternalConfig, resolveFullConfig, }: {
|
|
11
|
+
constructor({ loader, runner, stateManager, resolutionConfigManager, resolveFullConfig, }: {
|
|
13
12
|
loader: ChildAppLoader;
|
|
14
13
|
runner: ChildAppCommandLineRunner;
|
|
15
14
|
stateManager: ChildAppStateManager;
|
|
15
|
+
resolutionConfigManager: typeof CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN;
|
|
16
16
|
resolveFullConfig: typeof CHILD_APP_RESOLVE_CONFIG_TOKEN;
|
|
17
|
-
preloadExternalConfig: typeof CHILD_APP_PRELOAD_EXTERNAL_CONFIG_TOKEN | null;
|
|
18
17
|
});
|
|
19
18
|
preload(request: ChildAppRequestConfig): Promise<void>;
|
|
20
19
|
isPreloaded(request: ChildAppRequestConfig): boolean;
|
package/lib/server/render.d.ts
CHANGED
|
@@ -2,8 +2,9 @@ import type { CUSTOM_RENDER } from '@tramvai/tokens-render';
|
|
|
2
2
|
import type { Container } from '@tinkoff/dippy';
|
|
3
3
|
import type { ChildAppDiManager, ChildAppPreloadManager, ChildAppRenderManager, ChildAppRequestConfig, CHILD_APP_RESOLVE_CONFIG_TOKEN } from '@tramvai/tokens-child-app';
|
|
4
4
|
import type { LOGGER_TOKEN } from '@tramvai/tokens-common';
|
|
5
|
-
export declare const customRender: ({ renderManager, }: {
|
|
5
|
+
export declare const customRender: ({ renderManager, diManager, }: {
|
|
6
6
|
renderManager: ChildAppRenderManager;
|
|
7
|
+
diManager: ChildAppDiManager;
|
|
7
8
|
}) => typeof CUSTOM_RENDER;
|
|
8
9
|
export declare class RenderManager implements ChildAppRenderManager {
|
|
9
10
|
private readonly preloadManager;
|
package/lib/server.browser.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { __decorate } from 'tslib';
|
|
2
2
|
import { provide, COMMAND_LINE_RUNNER_TOKEN, walkOfModules, getModuleParameters, commandLineListTokens as commandLineListTokens$1, Module } from '@tramvai/core';
|
|
3
|
-
import flatten from '@tinkoff/utils/array/flatten';
|
|
4
3
|
import { Container, ChildContainer, Scope, DI_TOKEN } from '@tinkoff/dippy';
|
|
5
|
-
import { commandLineListTokens, CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN, CHILD_APP_INTERNAL_ACTION_TOKEN, CHILD_APP_INTERNAL_CONFIG_TOKEN, IS_CHILD_APP_DI_TOKEN, CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN,
|
|
4
|
+
import { commandLineListTokens, CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN, CHILD_APP_INTERNAL_ACTION_TOKEN, CHILD_APP_INTERNAL_CONFIG_TOKEN, IS_CHILD_APP_DI_TOKEN, CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN, CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN, CHILD_APP_RESOLUTION_CONFIGS_TOKEN, CHILD_APP_RESOLVE_CONFIG_TOKEN, CHILD_APP_RESOLVE_BASE_URL_TOKEN, CHILD_APP_SINGLETON_DI_MANAGER_TOKEN, CHILD_APP_LOADER_TOKEN, CHILD_APP_DI_MANAGER_TOKEN, CHILD_APP_COMMAND_LINE_RUNNER_TOKEN, CHILD_APP_PRELOAD_MANAGER_TOKEN, CHILD_APP_RENDER_MANAGER_TOKEN, CHILD_APP_COMMON_INITIAL_STATE_TOKEN, CHILD_APP_INTERNAL_RENDER_TOKEN } from '@tramvai/tokens-child-app';
|
|
6
5
|
export * from '@tramvai/tokens-child-app';
|
|
7
6
|
import { ACTION_PAGE_RUNNER_TOKEN, CONTEXT_TOKEN, LOGGER_TOKEN, DISPATCHER_TOKEN, STORE_TOKEN, COMBINE_REDUCERS, ENV_MANAGER_TOKEN, REGISTER_CLEAR_CACHE_TOKEN, CLEAR_CACHE_TOKEN, ENV_USED_TOKEN } from '@tramvai/tokens-common';
|
|
8
7
|
import { RENDER_SLOTS, EXTEND_RENDER } from '@tramvai/tokens-render';
|
|
9
8
|
import { PAGE_SERVICE_TOKEN } from '@tramvai/tokens-router';
|
|
9
|
+
import flatten from '@tinkoff/utils/array/flatten';
|
|
10
10
|
import { Subscription, createEvent, createReducer } from '@tramvai/state';
|
|
11
11
|
import React, { createContext, useContext, useMemo, useState, useEffect, createElement } from 'react';
|
|
12
|
+
import applyOrReturn from '@tinkoff/utils/function/applyOrReturn';
|
|
12
13
|
import { loadModule } from '@tinkoff/module-loader-client';
|
|
13
14
|
import noop from '@tinkoff/utils/function/noop';
|
|
14
15
|
import { useDi } from '@tramvai/react';
|
|
15
16
|
|
|
16
|
-
const getChildProviders$
|
|
17
|
+
const getChildProviders$3 = (appDi) => {
|
|
17
18
|
const context = appDi.get(CONTEXT_TOKEN);
|
|
18
19
|
return [
|
|
19
20
|
{
|
|
@@ -55,7 +56,7 @@ const getChildProviders$1 = (appDi) => {
|
|
|
55
56
|
];
|
|
56
57
|
};
|
|
57
58
|
|
|
58
|
-
const getChildProviders = (appDi) => {
|
|
59
|
+
const getChildProviders$2 = (appDi) => {
|
|
59
60
|
const logger = appDi.get(LOGGER_TOKEN);
|
|
60
61
|
return [
|
|
61
62
|
provide({
|
|
@@ -69,7 +70,7 @@ const getChildProviders = (appDi) => {
|
|
|
69
70
|
multi: true,
|
|
70
71
|
useValue: [],
|
|
71
72
|
}),
|
|
72
|
-
...getChildProviders$
|
|
73
|
+
...getChildProviders$3(appDi),
|
|
73
74
|
];
|
|
74
75
|
};
|
|
75
76
|
|
|
@@ -136,7 +137,7 @@ class SingletonDiManager {
|
|
|
136
137
|
},
|
|
137
138
|
], this.appDi);
|
|
138
139
|
const { modules = [], providers = [], actions = [] } = children;
|
|
139
|
-
const childProviders = getChildProviders(this.appDi);
|
|
140
|
+
const childProviders = getChildProviders$2(this.appDi);
|
|
140
141
|
childProviders.forEach((provider) => {
|
|
141
142
|
di.register(provider);
|
|
142
143
|
});
|
|
@@ -170,6 +171,14 @@ class SingletonDiManager {
|
|
|
170
171
|
}
|
|
171
172
|
}
|
|
172
173
|
|
|
174
|
+
const getChildProviders$1 = (_) => {
|
|
175
|
+
return [];
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const getChildProviders = (appDi) => {
|
|
179
|
+
return getChildProviders$1();
|
|
180
|
+
};
|
|
181
|
+
|
|
173
182
|
class DiManager {
|
|
174
183
|
constructor({ appDi, loader, singletonDiManager, }) {
|
|
175
184
|
this.cache = new Map();
|
|
@@ -200,7 +209,12 @@ class DiManager {
|
|
|
200
209
|
if (!singletonDi) {
|
|
201
210
|
return;
|
|
202
211
|
}
|
|
203
|
-
|
|
212
|
+
const di = new ChildContainer(singletonDi, this.appDi);
|
|
213
|
+
const childProviders = getChildProviders(this.appDi);
|
|
214
|
+
childProviders.forEach((provider) => {
|
|
215
|
+
di.register(provider);
|
|
216
|
+
});
|
|
217
|
+
return di;
|
|
204
218
|
}
|
|
205
219
|
}
|
|
206
220
|
|
|
@@ -298,6 +312,51 @@ const resolveComponent = async (componentOrLoader) => {
|
|
|
298
312
|
: componentOrLoader;
|
|
299
313
|
};
|
|
300
314
|
|
|
315
|
+
class ChildAppResolutionConfigManager {
|
|
316
|
+
constructor({ configs }) {
|
|
317
|
+
this.hasInitialized = false;
|
|
318
|
+
this.rawConfigs = configs !== null && configs !== void 0 ? configs : [];
|
|
319
|
+
this.mapping = new Map();
|
|
320
|
+
}
|
|
321
|
+
async init() {
|
|
322
|
+
if (this.hasInitialized) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
if (this.initPromise) {
|
|
326
|
+
return this.initPromise;
|
|
327
|
+
}
|
|
328
|
+
this.initPromise = (async () => {
|
|
329
|
+
const configs = await Promise.all(this.rawConfigs.map((rawConfig) => {
|
|
330
|
+
return applyOrReturn([], rawConfig);
|
|
331
|
+
}));
|
|
332
|
+
flatten(configs).forEach((config) => {
|
|
333
|
+
this.mapping.set(config.name, config);
|
|
334
|
+
});
|
|
335
|
+
this.hasInitialized = true;
|
|
336
|
+
})();
|
|
337
|
+
return this.initPromise;
|
|
338
|
+
}
|
|
339
|
+
resolve({ name, version, tag = 'latest' }) {
|
|
340
|
+
var _a;
|
|
341
|
+
const fromMapping = this.mapping.get(name);
|
|
342
|
+
if (!fromMapping) {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
const cfg = fromMapping.byTag[tag];
|
|
346
|
+
if (process.env.NODE_ENV === 'development' && tag === 'debug' && !cfg) {
|
|
347
|
+
return {
|
|
348
|
+
baseUrl: 'http://localhost:4040/',
|
|
349
|
+
version: '0.0.0-stub',
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
return {
|
|
353
|
+
...cfg,
|
|
354
|
+
baseUrl: (_a = cfg.baseUrl) !== null && _a !== void 0 ? _a : fromMapping.baseUrl,
|
|
355
|
+
version: version !== null && version !== void 0 ? version : cfg.version,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
301
360
|
const sharedProviders = [
|
|
302
361
|
provide({
|
|
303
362
|
provide: COMBINE_REDUCERS,
|
|
@@ -310,38 +369,27 @@ const sharedProviders = [
|
|
|
310
369
|
useValue: initModuleFederation,
|
|
311
370
|
}),
|
|
312
371
|
provide({
|
|
313
|
-
provide:
|
|
314
|
-
|
|
315
|
-
const mapping = flatten(configs !== null && configs !== void 0 ? configs : []).reduce((map, config) => {
|
|
316
|
-
return map.set(config.name, config);
|
|
317
|
-
}, new Map());
|
|
318
|
-
return (({ name, version, tag = 'latest' }) => {
|
|
319
|
-
var _a;
|
|
320
|
-
const fromMapping = mapping.get(name);
|
|
321
|
-
if (!fromMapping) {
|
|
322
|
-
return null;
|
|
323
|
-
}
|
|
324
|
-
const cfg = fromMapping.byTag[tag];
|
|
325
|
-
if (process.env.NODE_ENV === 'development' && tag === 'debug' && !cfg) {
|
|
326
|
-
return {
|
|
327
|
-
baseUrl: 'http://localhost:4040/',
|
|
328
|
-
version: '0.0.0-stub',
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
return {
|
|
332
|
-
...cfg,
|
|
333
|
-
baseUrl: (_a = cfg.baseUrl) !== null && _a !== void 0 ? _a : fromMapping.baseUrl,
|
|
334
|
-
version: version !== null && version !== void 0 ? version : cfg.version,
|
|
335
|
-
};
|
|
336
|
-
});
|
|
337
|
-
},
|
|
372
|
+
provide: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
373
|
+
useClass: ChildAppResolutionConfigManager,
|
|
338
374
|
deps: {
|
|
339
375
|
configs: { token: CHILD_APP_RESOLUTION_CONFIGS_TOKEN, optional: true },
|
|
340
376
|
},
|
|
341
377
|
}),
|
|
378
|
+
provide({
|
|
379
|
+
provide: commandLineListTokens$1.resolvePageDeps,
|
|
380
|
+
multi: true,
|
|
381
|
+
useFactory: ({ resolutionConfigManager }) => {
|
|
382
|
+
return async function fallbackResolutionConfigManagerInit() {
|
|
383
|
+
await resolutionConfigManager.init();
|
|
384
|
+
};
|
|
385
|
+
},
|
|
386
|
+
deps: {
|
|
387
|
+
resolutionConfigManager: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
388
|
+
},
|
|
389
|
+
}),
|
|
342
390
|
provide({
|
|
343
391
|
provide: CHILD_APP_RESOLVE_CONFIG_TOKEN,
|
|
344
|
-
useFactory: ({ envManager, rootBaseUrl,
|
|
392
|
+
useFactory: ({ envManager, rootBaseUrl, resolutionConfigManager }) => {
|
|
345
393
|
const rawEnv = envManager.get('CHILD_APP_DEBUG');
|
|
346
394
|
const debug = new Map();
|
|
347
395
|
rawEnv === null || rawEnv === void 0 ? void 0 : rawEnv.split(';').reduce((acc, entry) => {
|
|
@@ -352,7 +400,10 @@ const sharedProviders = [
|
|
|
352
400
|
var _a, _b;
|
|
353
401
|
const { name, tag = debug.has(name) ? 'debug' : 'latest' } = request;
|
|
354
402
|
const req = { name, tag, version: request.version };
|
|
355
|
-
const config =
|
|
403
|
+
const config = resolutionConfigManager.resolve(req);
|
|
404
|
+
if (!config) {
|
|
405
|
+
throw new Error(`Child-app "${name}" with tag "${tag}" has not found`);
|
|
406
|
+
}
|
|
356
407
|
const { version, baseUrl: configBaseUrl, client, server, css, withoutCss } = config;
|
|
357
408
|
const baseUrl = (_b = (_a = debug.get(name)) !== null && _a !== void 0 ? _a : configBaseUrl) !== null && _b !== void 0 ? _b : rootBaseUrl;
|
|
358
409
|
if (!baseUrl) {
|
|
@@ -384,7 +435,7 @@ const sharedProviders = [
|
|
|
384
435
|
deps: {
|
|
385
436
|
envManager: ENV_MANAGER_TOKEN,
|
|
386
437
|
rootBaseUrl: CHILD_APP_RESOLVE_BASE_URL_TOKEN,
|
|
387
|
-
|
|
438
|
+
resolutionConfigManager: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
388
439
|
},
|
|
389
440
|
}),
|
|
390
441
|
provide({
|
|
@@ -568,21 +619,20 @@ class BrowserLoader extends Loader {
|
|
|
568
619
|
}
|
|
569
620
|
|
|
570
621
|
class PreloadManager {
|
|
571
|
-
constructor({ loader, runner, resolveExternalConfig, store, }) {
|
|
622
|
+
constructor({ loader, runner, resolutionConfigManager, resolveExternalConfig, store, }) {
|
|
572
623
|
this.pageHasLoaded = false;
|
|
573
624
|
this.map = new Map();
|
|
574
625
|
this.serverPreloaded = new Map();
|
|
575
626
|
this.preloadMap = new Map();
|
|
627
|
+
this.hasInitialized = false;
|
|
576
628
|
this.loader = loader;
|
|
577
629
|
this.runner = runner;
|
|
630
|
+
this.store = store;
|
|
631
|
+
this.resolutionConfigManager = resolutionConfigManager;
|
|
578
632
|
this.resolveExternalConfig = resolveExternalConfig;
|
|
579
|
-
const { preloaded } = store.getState(ChildAppStore);
|
|
580
|
-
preloaded.forEach((request) => {
|
|
581
|
-
const config = this.resolveExternalConfig(request);
|
|
582
|
-
this.serverPreloaded.set(config.key, config);
|
|
583
|
-
});
|
|
584
633
|
}
|
|
585
634
|
async preload(request) {
|
|
635
|
+
await this.init();
|
|
586
636
|
const config = this.resolveExternalConfig(request);
|
|
587
637
|
const { key } = config;
|
|
588
638
|
this.preloadMap.set(key, config);
|
|
@@ -607,6 +657,7 @@ class PreloadManager {
|
|
|
607
657
|
return this.map.has(key) || this.serverPreloaded.has(key);
|
|
608
658
|
}
|
|
609
659
|
async runPreloaded() {
|
|
660
|
+
await this.init();
|
|
610
661
|
const promises = [];
|
|
611
662
|
if (this.pageHasLoaded) {
|
|
612
663
|
this.map.forEach((childAppPromise) => {
|
|
@@ -651,6 +702,20 @@ class PreloadManager {
|
|
|
651
702
|
getPreloadedList() {
|
|
652
703
|
return [...this.preloadMap.values()];
|
|
653
704
|
}
|
|
705
|
+
initServerPreloaded() {
|
|
706
|
+
if (!this.hasInitialized) {
|
|
707
|
+
const { preloaded } = this.store.getState(ChildAppStore);
|
|
708
|
+
preloaded.forEach((request) => {
|
|
709
|
+
const config = this.resolveExternalConfig(request);
|
|
710
|
+
this.serverPreloaded.set(config.key, config);
|
|
711
|
+
});
|
|
712
|
+
this.hasInitialized = true;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
async init() {
|
|
716
|
+
await this.resolutionConfigManager.init();
|
|
717
|
+
this.initServerPreloaded();
|
|
718
|
+
}
|
|
654
719
|
async run(status, config) {
|
|
655
720
|
const childApp = this.loader.get(config);
|
|
656
721
|
if (!childApp) {
|
|
@@ -706,6 +771,7 @@ const browserProviders = [
|
|
|
706
771
|
deps: {
|
|
707
772
|
loader: CHILD_APP_LOADER_TOKEN,
|
|
708
773
|
runner: CHILD_APP_COMMAND_LINE_RUNNER_TOKEN,
|
|
774
|
+
resolutionConfigManager: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
709
775
|
resolveExternalConfig: CHILD_APP_RESOLVE_CONFIG_TOKEN,
|
|
710
776
|
store: STORE_TOKEN,
|
|
711
777
|
},
|
|
@@ -721,6 +787,7 @@ const browserProviders = [
|
|
|
721
787
|
logger: LOGGER_TOKEN,
|
|
722
788
|
diManager: CHILD_APP_DI_MANAGER_TOKEN,
|
|
723
789
|
preloadManager: CHILD_APP_PRELOAD_MANAGER_TOKEN,
|
|
790
|
+
resolutionConfigManager: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
724
791
|
resolveExternalConfig: CHILD_APP_RESOLVE_CONFIG_TOKEN,
|
|
725
792
|
},
|
|
726
793
|
}),
|
package/lib/server.es.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { __decorate } from 'tslib';
|
|
2
2
|
import { provide, COMMAND_LINE_RUNNER_TOKEN, walkOfModules, getModuleParameters, commandLineListTokens as commandLineListTokens$1, Module } from '@tramvai/core';
|
|
3
|
-
import flatten from '@tinkoff/utils/array/flatten';
|
|
4
3
|
import { Container, ChildContainer, Scope, DI_TOKEN } from '@tinkoff/dippy';
|
|
5
|
-
import { commandLineListTokens,
|
|
4
|
+
import { commandLineListTokens, CHILD_APP_INTERNAL_ACTION_TOKEN, CHILD_APP_INTERNAL_CONFIG_TOKEN, IS_CHILD_APP_DI_TOKEN, CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN, CHILD_APP_INTERNAL_BEFORE_RENDER_TOKEN, CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN, CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN, CHILD_APP_RESOLUTION_CONFIGS_TOKEN, CHILD_APP_RESOLVE_CONFIG_TOKEN, CHILD_APP_RESOLVE_BASE_URL_TOKEN, CHILD_APP_SINGLETON_DI_MANAGER_TOKEN, CHILD_APP_LOADER_TOKEN, CHILD_APP_DI_MANAGER_TOKEN, CHILD_APP_COMMAND_LINE_RUNNER_TOKEN, CHILD_APP_PRELOAD_MANAGER_TOKEN, CHILD_APP_RENDER_MANAGER_TOKEN, CHILD_APP_STATE_MANAGER_TOKEN, CHILD_APP_INTERNAL_RENDER_TOKEN } from '@tramvai/tokens-child-app';
|
|
6
5
|
export * from '@tramvai/tokens-child-app';
|
|
7
|
-
import { ACTION_PAGE_RUNNER_TOKEN,
|
|
6
|
+
import { ACTION_PAGE_RUNNER_TOKEN, LOGGER_TOKEN, DISPATCHER_TOKEN, STORE_TOKEN, CONTEXT_TOKEN, COMBINE_REDUCERS, ENV_MANAGER_TOKEN, REGISTER_CLEAR_CACHE_TOKEN, CLEAR_CACHE_TOKEN, ENV_USED_TOKEN, CREATE_CACHE_TOKEN } from '@tramvai/tokens-common';
|
|
8
7
|
import { RENDER_SLOTS, EXTEND_RENDER, ResourceType, ResourceSlot, RESOURCES_REGISTRY, CUSTOM_RENDER } from '@tramvai/tokens-render';
|
|
9
8
|
import { PAGE_SERVICE_TOKEN } from '@tramvai/tokens-router';
|
|
9
|
+
import flatten from '@tinkoff/utils/array/flatten';
|
|
10
10
|
import { createEvent, createReducer } from '@tramvai/state';
|
|
11
11
|
import React, { createContext, useContext, useMemo, useState, useEffect, createElement } from 'react';
|
|
12
|
+
import applyOrReturn from '@tinkoff/utils/function/applyOrReturn';
|
|
12
13
|
import { combineValidators, isUrl, endsWith } from '@tinkoff/env-validators';
|
|
13
14
|
import { safeDehydrate } from '@tramvai/safe-strings';
|
|
14
15
|
import { ServerLoader as ServerLoader$1 } from '@tinkoff/module-loader-server';
|
|
@@ -16,27 +17,8 @@ import noop from '@tinkoff/utils/function/noop';
|
|
|
16
17
|
import { renderToString } from 'react-dom/server';
|
|
17
18
|
import { useDi } from '@tramvai/react';
|
|
18
19
|
|
|
19
|
-
const getChildProviders$
|
|
20
|
-
const context = appDi.get(CONTEXT_TOKEN);
|
|
20
|
+
const getChildProviders$3 = (appDi) => {
|
|
21
21
|
return [
|
|
22
|
-
{
|
|
23
|
-
provide: commandLineListTokens.customerStart,
|
|
24
|
-
multi: true,
|
|
25
|
-
useFactory: ({ subscriptions, }) => {
|
|
26
|
-
return function resolveRootStateForChild() {
|
|
27
|
-
if (!subscriptions) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const state = context.getState();
|
|
31
|
-
return Promise.all(subscriptions.map((sub) => {
|
|
32
|
-
return sub.listener(state);
|
|
33
|
-
}));
|
|
34
|
-
};
|
|
35
|
-
},
|
|
36
|
-
deps: {
|
|
37
|
-
subscriptions: { token: CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN, optional: true },
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
22
|
provide({
|
|
41
23
|
provide: commandLineListTokens.resolvePageDeps,
|
|
42
24
|
multi: true,
|
|
@@ -53,7 +35,7 @@ const getChildProviders$1 = (appDi) => {
|
|
|
53
35
|
];
|
|
54
36
|
};
|
|
55
37
|
|
|
56
|
-
const getChildProviders = (appDi) => {
|
|
38
|
+
const getChildProviders$2 = (appDi) => {
|
|
57
39
|
const logger = appDi.get(LOGGER_TOKEN);
|
|
58
40
|
return [
|
|
59
41
|
provide({
|
|
@@ -67,7 +49,7 @@ const getChildProviders = (appDi) => {
|
|
|
67
49
|
multi: true,
|
|
68
50
|
useValue: [],
|
|
69
51
|
}),
|
|
70
|
-
...getChildProviders$
|
|
52
|
+
...getChildProviders$3(),
|
|
71
53
|
];
|
|
72
54
|
};
|
|
73
55
|
|
|
@@ -134,7 +116,7 @@ class SingletonDiManager {
|
|
|
134
116
|
},
|
|
135
117
|
], this.appDi);
|
|
136
118
|
const { modules = [], providers = [], actions = [] } = children;
|
|
137
|
-
const childProviders = getChildProviders(this.appDi);
|
|
119
|
+
const childProviders = getChildProviders$2(this.appDi);
|
|
138
120
|
childProviders.forEach((provider) => {
|
|
139
121
|
di.register(provider);
|
|
140
122
|
});
|
|
@@ -168,6 +150,34 @@ class SingletonDiManager {
|
|
|
168
150
|
}
|
|
169
151
|
}
|
|
170
152
|
|
|
153
|
+
const getChildProviders$1 = (appDi) => {
|
|
154
|
+
const store = appDi.get(STORE_TOKEN);
|
|
155
|
+
return [
|
|
156
|
+
{
|
|
157
|
+
provide: CHILD_APP_INTERNAL_BEFORE_RENDER_TOKEN,
|
|
158
|
+
multi: true,
|
|
159
|
+
useFactory: ({ subscriptions, }) => {
|
|
160
|
+
return function resolveRootStateForChild() {
|
|
161
|
+
if (!subscriptions) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const state = store.getState();
|
|
165
|
+
return Promise.all(subscriptions.map((sub) => {
|
|
166
|
+
return sub.listener(state);
|
|
167
|
+
}));
|
|
168
|
+
};
|
|
169
|
+
},
|
|
170
|
+
deps: {
|
|
171
|
+
subscriptions: { token: CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN, optional: true },
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
];
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const getChildProviders = (appDi) => {
|
|
178
|
+
return getChildProviders$1(appDi);
|
|
179
|
+
};
|
|
180
|
+
|
|
171
181
|
class DiManager {
|
|
172
182
|
constructor({ appDi, loader, singletonDiManager, }) {
|
|
173
183
|
this.cache = new Map();
|
|
@@ -198,7 +208,12 @@ class DiManager {
|
|
|
198
208
|
if (!singletonDi) {
|
|
199
209
|
return;
|
|
200
210
|
}
|
|
201
|
-
|
|
211
|
+
const di = new ChildContainer(singletonDi, this.appDi);
|
|
212
|
+
const childProviders = getChildProviders(this.appDi);
|
|
213
|
+
childProviders.forEach((provider) => {
|
|
214
|
+
di.register(provider);
|
|
215
|
+
});
|
|
216
|
+
return di;
|
|
202
217
|
}
|
|
203
218
|
}
|
|
204
219
|
|
|
@@ -296,6 +311,51 @@ const resolveComponent = async (componentOrLoader) => {
|
|
|
296
311
|
: componentOrLoader;
|
|
297
312
|
};
|
|
298
313
|
|
|
314
|
+
class ChildAppResolutionConfigManager {
|
|
315
|
+
constructor({ configs }) {
|
|
316
|
+
this.hasInitialized = false;
|
|
317
|
+
this.rawConfigs = configs !== null && configs !== void 0 ? configs : [];
|
|
318
|
+
this.mapping = new Map();
|
|
319
|
+
}
|
|
320
|
+
async init() {
|
|
321
|
+
if (this.hasInitialized) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (this.initPromise) {
|
|
325
|
+
return this.initPromise;
|
|
326
|
+
}
|
|
327
|
+
this.initPromise = (async () => {
|
|
328
|
+
const configs = await Promise.all(this.rawConfigs.map((rawConfig) => {
|
|
329
|
+
return applyOrReturn([], rawConfig);
|
|
330
|
+
}));
|
|
331
|
+
flatten(configs).forEach((config) => {
|
|
332
|
+
this.mapping.set(config.name, config);
|
|
333
|
+
});
|
|
334
|
+
this.hasInitialized = true;
|
|
335
|
+
})();
|
|
336
|
+
return this.initPromise;
|
|
337
|
+
}
|
|
338
|
+
resolve({ name, version, tag = 'latest' }) {
|
|
339
|
+
var _a;
|
|
340
|
+
const fromMapping = this.mapping.get(name);
|
|
341
|
+
if (!fromMapping) {
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
const cfg = fromMapping.byTag[tag];
|
|
345
|
+
if (process.env.NODE_ENV === 'development' && tag === 'debug' && !cfg) {
|
|
346
|
+
return {
|
|
347
|
+
baseUrl: 'http://localhost:4040/',
|
|
348
|
+
version: '0.0.0-stub',
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
return {
|
|
352
|
+
...cfg,
|
|
353
|
+
baseUrl: (_a = cfg.baseUrl) !== null && _a !== void 0 ? _a : fromMapping.baseUrl,
|
|
354
|
+
version: version !== null && version !== void 0 ? version : cfg.version,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
299
359
|
const sharedProviders = [
|
|
300
360
|
provide({
|
|
301
361
|
provide: COMBINE_REDUCERS,
|
|
@@ -308,38 +368,27 @@ const sharedProviders = [
|
|
|
308
368
|
useValue: initModuleFederation,
|
|
309
369
|
}),
|
|
310
370
|
provide({
|
|
311
|
-
provide:
|
|
312
|
-
|
|
313
|
-
const mapping = flatten(configs !== null && configs !== void 0 ? configs : []).reduce((map, config) => {
|
|
314
|
-
return map.set(config.name, config);
|
|
315
|
-
}, new Map());
|
|
316
|
-
return (({ name, version, tag = 'latest' }) => {
|
|
317
|
-
var _a;
|
|
318
|
-
const fromMapping = mapping.get(name);
|
|
319
|
-
if (!fromMapping) {
|
|
320
|
-
return null;
|
|
321
|
-
}
|
|
322
|
-
const cfg = fromMapping.byTag[tag];
|
|
323
|
-
if (process.env.NODE_ENV === 'development' && tag === 'debug' && !cfg) {
|
|
324
|
-
return {
|
|
325
|
-
baseUrl: 'http://localhost:4040/',
|
|
326
|
-
version: '0.0.0-stub',
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
return {
|
|
330
|
-
...cfg,
|
|
331
|
-
baseUrl: (_a = cfg.baseUrl) !== null && _a !== void 0 ? _a : fromMapping.baseUrl,
|
|
332
|
-
version: version !== null && version !== void 0 ? version : cfg.version,
|
|
333
|
-
};
|
|
334
|
-
});
|
|
335
|
-
},
|
|
371
|
+
provide: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
372
|
+
useClass: ChildAppResolutionConfigManager,
|
|
336
373
|
deps: {
|
|
337
374
|
configs: { token: CHILD_APP_RESOLUTION_CONFIGS_TOKEN, optional: true },
|
|
338
375
|
},
|
|
339
376
|
}),
|
|
377
|
+
provide({
|
|
378
|
+
provide: commandLineListTokens$1.resolvePageDeps,
|
|
379
|
+
multi: true,
|
|
380
|
+
useFactory: ({ resolutionConfigManager }) => {
|
|
381
|
+
return async function fallbackResolutionConfigManagerInit() {
|
|
382
|
+
await resolutionConfigManager.init();
|
|
383
|
+
};
|
|
384
|
+
},
|
|
385
|
+
deps: {
|
|
386
|
+
resolutionConfigManager: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
387
|
+
},
|
|
388
|
+
}),
|
|
340
389
|
provide({
|
|
341
390
|
provide: CHILD_APP_RESOLVE_CONFIG_TOKEN,
|
|
342
|
-
useFactory: ({ envManager, rootBaseUrl,
|
|
391
|
+
useFactory: ({ envManager, rootBaseUrl, resolutionConfigManager }) => {
|
|
343
392
|
const rawEnv = envManager.get('CHILD_APP_DEBUG');
|
|
344
393
|
const debug = new Map();
|
|
345
394
|
rawEnv === null || rawEnv === void 0 ? void 0 : rawEnv.split(';').reduce((acc, entry) => {
|
|
@@ -350,7 +399,10 @@ const sharedProviders = [
|
|
|
350
399
|
var _a, _b;
|
|
351
400
|
const { name, tag = debug.has(name) ? 'debug' : 'latest' } = request;
|
|
352
401
|
const req = { name, tag, version: request.version };
|
|
353
|
-
const config =
|
|
402
|
+
const config = resolutionConfigManager.resolve(req);
|
|
403
|
+
if (!config) {
|
|
404
|
+
throw new Error(`Child-app "${name}" with tag "${tag}" has not found`);
|
|
405
|
+
}
|
|
354
406
|
const { version, baseUrl: configBaseUrl, client, server, css, withoutCss } = config;
|
|
355
407
|
const baseUrl = (_b = (_a = debug.get(name)) !== null && _a !== void 0 ? _a : configBaseUrl) !== null && _b !== void 0 ? _b : rootBaseUrl;
|
|
356
408
|
if (!baseUrl) {
|
|
@@ -382,7 +434,7 @@ const sharedProviders = [
|
|
|
382
434
|
deps: {
|
|
383
435
|
envManager: ENV_MANAGER_TOKEN,
|
|
384
436
|
rootBaseUrl: CHILD_APP_RESOLVE_BASE_URL_TOKEN,
|
|
385
|
-
|
|
437
|
+
resolutionConfigManager: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
386
438
|
},
|
|
387
439
|
}),
|
|
388
440
|
provide({
|
|
@@ -551,23 +603,18 @@ class ServerLoader extends Loader {
|
|
|
551
603
|
}
|
|
552
604
|
|
|
553
605
|
class PreloadManager {
|
|
554
|
-
constructor({ loader, runner, stateManager,
|
|
606
|
+
constructor({ loader, runner, stateManager, resolutionConfigManager, resolveFullConfig, }) {
|
|
555
607
|
this.shouldRunImmediately = false;
|
|
556
608
|
this.map = new Map();
|
|
557
609
|
this.preloadMap = new Map();
|
|
558
|
-
this.configHasBeenPreloaded = false;
|
|
559
610
|
this.loader = loader;
|
|
560
611
|
this.runner = runner;
|
|
561
612
|
this.stateManager = stateManager;
|
|
562
|
-
this.
|
|
613
|
+
this.resolutionConfigManager = resolutionConfigManager;
|
|
563
614
|
this.resolveFullConfig = resolveFullConfig;
|
|
564
615
|
}
|
|
565
616
|
async preload(request) {
|
|
566
|
-
|
|
567
|
-
if (!this.configHasBeenPreloaded) {
|
|
568
|
-
await ((_a = this.preloadExternalConfig) === null || _a === void 0 ? void 0 : _a.call(this));
|
|
569
|
-
this.configHasBeenPreloaded = true;
|
|
570
|
-
}
|
|
617
|
+
await this.resolutionConfigManager.init();
|
|
571
618
|
const config = this.resolveFullConfig(request);
|
|
572
619
|
const { key } = config;
|
|
573
620
|
if (this.map.has(key)) {
|
|
@@ -657,8 +704,16 @@ class StateManager {
|
|
|
657
704
|
}
|
|
658
705
|
|
|
659
706
|
const LOAD_TIMEOUT = 500;
|
|
660
|
-
const customRender = ({ renderManager, }) => {
|
|
707
|
+
const customRender = ({ renderManager, diManager, }) => {
|
|
661
708
|
return async (content) => {
|
|
709
|
+
const promises = [];
|
|
710
|
+
diManager.forEachChildDi((di) => {
|
|
711
|
+
const beforeAppRender = di.get(CHILD_APP_INTERNAL_BEFORE_RENDER_TOKEN);
|
|
712
|
+
if (beforeAppRender) {
|
|
713
|
+
promises.push(Promise.all(beforeAppRender.map((fn) => fn())));
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
await Promise.all(promises);
|
|
662
717
|
let render = renderToString(content);
|
|
663
718
|
let timeouted = false;
|
|
664
719
|
await Promise.race([
|
|
@@ -806,7 +861,7 @@ const serverProviders = [
|
|
|
806
861
|
loader: CHILD_APP_LOADER_TOKEN,
|
|
807
862
|
runner: CHILD_APP_COMMAND_LINE_RUNNER_TOKEN,
|
|
808
863
|
stateManager: CHILD_APP_STATE_MANAGER_TOKEN,
|
|
809
|
-
|
|
864
|
+
resolutionConfigManager: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
810
865
|
resolveFullConfig: CHILD_APP_RESOLVE_CONFIG_TOKEN,
|
|
811
866
|
},
|
|
812
867
|
}),
|
|
@@ -843,6 +898,7 @@ const serverProviders = [
|
|
|
843
898
|
useFactory: customRender,
|
|
844
899
|
deps: {
|
|
845
900
|
renderManager: CHILD_APP_RENDER_MANAGER_TOKEN,
|
|
901
|
+
diManager: CHILD_APP_DI_MANAGER_TOKEN,
|
|
846
902
|
},
|
|
847
903
|
}),
|
|
848
904
|
provide({
|
package/lib/server.js
CHANGED
|
@@ -4,14 +4,15 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var tslib = require('tslib');
|
|
6
6
|
var core = require('@tramvai/core');
|
|
7
|
-
var flatten = require('@tinkoff/utils/array/flatten');
|
|
8
7
|
var dippy = require('@tinkoff/dippy');
|
|
9
8
|
var tokensChildApp = require('@tramvai/tokens-child-app');
|
|
10
9
|
var tokensCommon = require('@tramvai/tokens-common');
|
|
11
10
|
var tokensRender = require('@tramvai/tokens-render');
|
|
12
11
|
var tokensRouter = require('@tramvai/tokens-router');
|
|
12
|
+
var flatten = require('@tinkoff/utils/array/flatten');
|
|
13
13
|
var state = require('@tramvai/state');
|
|
14
14
|
var React = require('react');
|
|
15
|
+
var applyOrReturn = require('@tinkoff/utils/function/applyOrReturn');
|
|
15
16
|
var envValidators = require('@tinkoff/env-validators');
|
|
16
17
|
var safeStrings = require('@tramvai/safe-strings');
|
|
17
18
|
var moduleLoaderServer = require('@tinkoff/module-loader-server');
|
|
@@ -23,29 +24,11 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
23
24
|
|
|
24
25
|
var flatten__default = /*#__PURE__*/_interopDefaultLegacy(flatten);
|
|
25
26
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
27
|
+
var applyOrReturn__default = /*#__PURE__*/_interopDefaultLegacy(applyOrReturn);
|
|
26
28
|
var noop__default = /*#__PURE__*/_interopDefaultLegacy(noop);
|
|
27
29
|
|
|
28
|
-
const getChildProviders$
|
|
29
|
-
const context = appDi.get(tokensCommon.CONTEXT_TOKEN);
|
|
30
|
+
const getChildProviders$3 = (appDi) => {
|
|
30
31
|
return [
|
|
31
|
-
{
|
|
32
|
-
provide: tokensChildApp.commandLineListTokens.customerStart,
|
|
33
|
-
multi: true,
|
|
34
|
-
useFactory: ({ subscriptions, }) => {
|
|
35
|
-
return function resolveRootStateForChild() {
|
|
36
|
-
if (!subscriptions) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const state = context.getState();
|
|
40
|
-
return Promise.all(subscriptions.map((sub) => {
|
|
41
|
-
return sub.listener(state);
|
|
42
|
-
}));
|
|
43
|
-
};
|
|
44
|
-
},
|
|
45
|
-
deps: {
|
|
46
|
-
subscriptions: { token: tokensChildApp.CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN, optional: true },
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
32
|
core.provide({
|
|
50
33
|
provide: tokensChildApp.commandLineListTokens.resolvePageDeps,
|
|
51
34
|
multi: true,
|
|
@@ -62,7 +45,7 @@ const getChildProviders$1 = (appDi) => {
|
|
|
62
45
|
];
|
|
63
46
|
};
|
|
64
47
|
|
|
65
|
-
const getChildProviders = (appDi) => {
|
|
48
|
+
const getChildProviders$2 = (appDi) => {
|
|
66
49
|
const logger = appDi.get(tokensCommon.LOGGER_TOKEN);
|
|
67
50
|
return [
|
|
68
51
|
core.provide({
|
|
@@ -76,7 +59,7 @@ const getChildProviders = (appDi) => {
|
|
|
76
59
|
multi: true,
|
|
77
60
|
useValue: [],
|
|
78
61
|
}),
|
|
79
|
-
...getChildProviders$
|
|
62
|
+
...getChildProviders$3(),
|
|
80
63
|
];
|
|
81
64
|
};
|
|
82
65
|
|
|
@@ -143,7 +126,7 @@ class SingletonDiManager {
|
|
|
143
126
|
},
|
|
144
127
|
], this.appDi);
|
|
145
128
|
const { modules = [], providers = [], actions = [] } = children;
|
|
146
|
-
const childProviders = getChildProviders(this.appDi);
|
|
129
|
+
const childProviders = getChildProviders$2(this.appDi);
|
|
147
130
|
childProviders.forEach((provider) => {
|
|
148
131
|
di.register(provider);
|
|
149
132
|
});
|
|
@@ -177,6 +160,34 @@ class SingletonDiManager {
|
|
|
177
160
|
}
|
|
178
161
|
}
|
|
179
162
|
|
|
163
|
+
const getChildProviders$1 = (appDi) => {
|
|
164
|
+
const store = appDi.get(tokensCommon.STORE_TOKEN);
|
|
165
|
+
return [
|
|
166
|
+
{
|
|
167
|
+
provide: tokensChildApp.CHILD_APP_INTERNAL_BEFORE_RENDER_TOKEN,
|
|
168
|
+
multi: true,
|
|
169
|
+
useFactory: ({ subscriptions, }) => {
|
|
170
|
+
return function resolveRootStateForChild() {
|
|
171
|
+
if (!subscriptions) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const state = store.getState();
|
|
175
|
+
return Promise.all(subscriptions.map((sub) => {
|
|
176
|
+
return sub.listener(state);
|
|
177
|
+
}));
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
deps: {
|
|
181
|
+
subscriptions: { token: tokensChildApp.CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN, optional: true },
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
];
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const getChildProviders = (appDi) => {
|
|
188
|
+
return getChildProviders$1(appDi);
|
|
189
|
+
};
|
|
190
|
+
|
|
180
191
|
class DiManager {
|
|
181
192
|
constructor({ appDi, loader, singletonDiManager, }) {
|
|
182
193
|
this.cache = new Map();
|
|
@@ -207,7 +218,12 @@ class DiManager {
|
|
|
207
218
|
if (!singletonDi) {
|
|
208
219
|
return;
|
|
209
220
|
}
|
|
210
|
-
|
|
221
|
+
const di = new dippy.ChildContainer(singletonDi, this.appDi);
|
|
222
|
+
const childProviders = getChildProviders(this.appDi);
|
|
223
|
+
childProviders.forEach((provider) => {
|
|
224
|
+
di.register(provider);
|
|
225
|
+
});
|
|
226
|
+
return di;
|
|
211
227
|
}
|
|
212
228
|
}
|
|
213
229
|
|
|
@@ -305,6 +321,51 @@ const resolveComponent = async (componentOrLoader) => {
|
|
|
305
321
|
: componentOrLoader;
|
|
306
322
|
};
|
|
307
323
|
|
|
324
|
+
class ChildAppResolutionConfigManager {
|
|
325
|
+
constructor({ configs }) {
|
|
326
|
+
this.hasInitialized = false;
|
|
327
|
+
this.rawConfigs = configs !== null && configs !== void 0 ? configs : [];
|
|
328
|
+
this.mapping = new Map();
|
|
329
|
+
}
|
|
330
|
+
async init() {
|
|
331
|
+
if (this.hasInitialized) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (this.initPromise) {
|
|
335
|
+
return this.initPromise;
|
|
336
|
+
}
|
|
337
|
+
this.initPromise = (async () => {
|
|
338
|
+
const configs = await Promise.all(this.rawConfigs.map((rawConfig) => {
|
|
339
|
+
return applyOrReturn__default["default"]([], rawConfig);
|
|
340
|
+
}));
|
|
341
|
+
flatten__default["default"](configs).forEach((config) => {
|
|
342
|
+
this.mapping.set(config.name, config);
|
|
343
|
+
});
|
|
344
|
+
this.hasInitialized = true;
|
|
345
|
+
})();
|
|
346
|
+
return this.initPromise;
|
|
347
|
+
}
|
|
348
|
+
resolve({ name, version, tag = 'latest' }) {
|
|
349
|
+
var _a;
|
|
350
|
+
const fromMapping = this.mapping.get(name);
|
|
351
|
+
if (!fromMapping) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
const cfg = fromMapping.byTag[tag];
|
|
355
|
+
if (process.env.NODE_ENV === 'development' && tag === 'debug' && !cfg) {
|
|
356
|
+
return {
|
|
357
|
+
baseUrl: 'http://localhost:4040/',
|
|
358
|
+
version: '0.0.0-stub',
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
...cfg,
|
|
363
|
+
baseUrl: (_a = cfg.baseUrl) !== null && _a !== void 0 ? _a : fromMapping.baseUrl,
|
|
364
|
+
version: version !== null && version !== void 0 ? version : cfg.version,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
308
369
|
const sharedProviders = [
|
|
309
370
|
core.provide({
|
|
310
371
|
provide: tokensCommon.COMBINE_REDUCERS,
|
|
@@ -317,38 +378,27 @@ const sharedProviders = [
|
|
|
317
378
|
useValue: initModuleFederation,
|
|
318
379
|
}),
|
|
319
380
|
core.provide({
|
|
320
|
-
provide: tokensChildApp.
|
|
321
|
-
|
|
322
|
-
const mapping = flatten__default["default"](configs !== null && configs !== void 0 ? configs : []).reduce((map, config) => {
|
|
323
|
-
return map.set(config.name, config);
|
|
324
|
-
}, new Map());
|
|
325
|
-
return (({ name, version, tag = 'latest' }) => {
|
|
326
|
-
var _a;
|
|
327
|
-
const fromMapping = mapping.get(name);
|
|
328
|
-
if (!fromMapping) {
|
|
329
|
-
return null;
|
|
330
|
-
}
|
|
331
|
-
const cfg = fromMapping.byTag[tag];
|
|
332
|
-
if (process.env.NODE_ENV === 'development' && tag === 'debug' && !cfg) {
|
|
333
|
-
return {
|
|
334
|
-
baseUrl: 'http://localhost:4040/',
|
|
335
|
-
version: '0.0.0-stub',
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
return {
|
|
339
|
-
...cfg,
|
|
340
|
-
baseUrl: (_a = cfg.baseUrl) !== null && _a !== void 0 ? _a : fromMapping.baseUrl,
|
|
341
|
-
version: version !== null && version !== void 0 ? version : cfg.version,
|
|
342
|
-
};
|
|
343
|
-
});
|
|
344
|
-
},
|
|
381
|
+
provide: tokensChildApp.CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
382
|
+
useClass: ChildAppResolutionConfigManager,
|
|
345
383
|
deps: {
|
|
346
384
|
configs: { token: tokensChildApp.CHILD_APP_RESOLUTION_CONFIGS_TOKEN, optional: true },
|
|
347
385
|
},
|
|
348
386
|
}),
|
|
387
|
+
core.provide({
|
|
388
|
+
provide: core.commandLineListTokens.resolvePageDeps,
|
|
389
|
+
multi: true,
|
|
390
|
+
useFactory: ({ resolutionConfigManager }) => {
|
|
391
|
+
return async function fallbackResolutionConfigManagerInit() {
|
|
392
|
+
await resolutionConfigManager.init();
|
|
393
|
+
};
|
|
394
|
+
},
|
|
395
|
+
deps: {
|
|
396
|
+
resolutionConfigManager: tokensChildApp.CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
397
|
+
},
|
|
398
|
+
}),
|
|
349
399
|
core.provide({
|
|
350
400
|
provide: tokensChildApp.CHILD_APP_RESOLVE_CONFIG_TOKEN,
|
|
351
|
-
useFactory: ({ envManager, rootBaseUrl,
|
|
401
|
+
useFactory: ({ envManager, rootBaseUrl, resolutionConfigManager }) => {
|
|
352
402
|
const rawEnv = envManager.get('CHILD_APP_DEBUG');
|
|
353
403
|
const debug = new Map();
|
|
354
404
|
rawEnv === null || rawEnv === void 0 ? void 0 : rawEnv.split(';').reduce((acc, entry) => {
|
|
@@ -359,7 +409,10 @@ const sharedProviders = [
|
|
|
359
409
|
var _a, _b;
|
|
360
410
|
const { name, tag = debug.has(name) ? 'debug' : 'latest' } = request;
|
|
361
411
|
const req = { name, tag, version: request.version };
|
|
362
|
-
const config =
|
|
412
|
+
const config = resolutionConfigManager.resolve(req);
|
|
413
|
+
if (!config) {
|
|
414
|
+
throw new Error(`Child-app "${name}" with tag "${tag}" has not found`);
|
|
415
|
+
}
|
|
363
416
|
const { version, baseUrl: configBaseUrl, client, server, css, withoutCss } = config;
|
|
364
417
|
const baseUrl = (_b = (_a = debug.get(name)) !== null && _a !== void 0 ? _a : configBaseUrl) !== null && _b !== void 0 ? _b : rootBaseUrl;
|
|
365
418
|
if (!baseUrl) {
|
|
@@ -391,7 +444,7 @@ const sharedProviders = [
|
|
|
391
444
|
deps: {
|
|
392
445
|
envManager: tokensCommon.ENV_MANAGER_TOKEN,
|
|
393
446
|
rootBaseUrl: tokensChildApp.CHILD_APP_RESOLVE_BASE_URL_TOKEN,
|
|
394
|
-
|
|
447
|
+
resolutionConfigManager: tokensChildApp.CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
395
448
|
},
|
|
396
449
|
}),
|
|
397
450
|
core.provide({
|
|
@@ -560,23 +613,18 @@ class ServerLoader extends Loader {
|
|
|
560
613
|
}
|
|
561
614
|
|
|
562
615
|
class PreloadManager {
|
|
563
|
-
constructor({ loader, runner, stateManager,
|
|
616
|
+
constructor({ loader, runner, stateManager, resolutionConfigManager, resolveFullConfig, }) {
|
|
564
617
|
this.shouldRunImmediately = false;
|
|
565
618
|
this.map = new Map();
|
|
566
619
|
this.preloadMap = new Map();
|
|
567
|
-
this.configHasBeenPreloaded = false;
|
|
568
620
|
this.loader = loader;
|
|
569
621
|
this.runner = runner;
|
|
570
622
|
this.stateManager = stateManager;
|
|
571
|
-
this.
|
|
623
|
+
this.resolutionConfigManager = resolutionConfigManager;
|
|
572
624
|
this.resolveFullConfig = resolveFullConfig;
|
|
573
625
|
}
|
|
574
626
|
async preload(request) {
|
|
575
|
-
|
|
576
|
-
if (!this.configHasBeenPreloaded) {
|
|
577
|
-
await ((_a = this.preloadExternalConfig) === null || _a === void 0 ? void 0 : _a.call(this));
|
|
578
|
-
this.configHasBeenPreloaded = true;
|
|
579
|
-
}
|
|
627
|
+
await this.resolutionConfigManager.init();
|
|
580
628
|
const config = this.resolveFullConfig(request);
|
|
581
629
|
const { key } = config;
|
|
582
630
|
if (this.map.has(key)) {
|
|
@@ -666,8 +714,16 @@ class StateManager {
|
|
|
666
714
|
}
|
|
667
715
|
|
|
668
716
|
const LOAD_TIMEOUT = 500;
|
|
669
|
-
const customRender = ({ renderManager, }) => {
|
|
717
|
+
const customRender = ({ renderManager, diManager, }) => {
|
|
670
718
|
return async (content) => {
|
|
719
|
+
const promises = [];
|
|
720
|
+
diManager.forEachChildDi((di) => {
|
|
721
|
+
const beforeAppRender = di.get(tokensChildApp.CHILD_APP_INTERNAL_BEFORE_RENDER_TOKEN);
|
|
722
|
+
if (beforeAppRender) {
|
|
723
|
+
promises.push(Promise.all(beforeAppRender.map((fn) => fn())));
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
await Promise.all(promises);
|
|
671
727
|
let render = server.renderToString(content);
|
|
672
728
|
let timeouted = false;
|
|
673
729
|
await Promise.race([
|
|
@@ -815,7 +871,7 @@ const serverProviders = [
|
|
|
815
871
|
loader: tokensChildApp.CHILD_APP_LOADER_TOKEN,
|
|
816
872
|
runner: tokensChildApp.CHILD_APP_COMMAND_LINE_RUNNER_TOKEN,
|
|
817
873
|
stateManager: tokensChildApp.CHILD_APP_STATE_MANAGER_TOKEN,
|
|
818
|
-
|
|
874
|
+
resolutionConfigManager: tokensChildApp.CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
819
875
|
resolveFullConfig: tokensChildApp.CHILD_APP_RESOLVE_CONFIG_TOKEN,
|
|
820
876
|
},
|
|
821
877
|
}),
|
|
@@ -852,6 +908,7 @@ const serverProviders = [
|
|
|
852
908
|
useFactory: customRender,
|
|
853
909
|
deps: {
|
|
854
910
|
renderManager: tokensChildApp.CHILD_APP_RENDER_MANAGER_TOKEN,
|
|
911
|
+
diManager: tokensChildApp.CHILD_APP_DI_MANAGER_TOKEN,
|
|
855
912
|
},
|
|
856
913
|
}),
|
|
857
914
|
core.provide({
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ChildAppRequestConfig, CHILD_APP_RESOLUTION_CONFIGS_TOKEN, CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN, ResolutionConfig } from '@tramvai/tokens-child-app';
|
|
2
|
+
declare type Interface = typeof CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN;
|
|
3
|
+
export declare class ChildAppResolutionConfigManager implements Interface {
|
|
4
|
+
private rawConfigs;
|
|
5
|
+
private mapping;
|
|
6
|
+
private hasInitialized;
|
|
7
|
+
private initPromise;
|
|
8
|
+
constructor({ configs }: {
|
|
9
|
+
configs: typeof CHILD_APP_RESOLUTION_CONFIGS_TOKEN | null;
|
|
10
|
+
});
|
|
11
|
+
init(): Promise<void>;
|
|
12
|
+
resolve({ name, version, tag }: ChildAppRequestConfig): ResolutionConfig;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tramvai/module-child-app",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.68.0",
|
|
4
4
|
"description": "Module for child apps",
|
|
5
5
|
"browser": {
|
|
6
6
|
"./lib/server.js": "./lib/browser.js",
|
|
7
|
+
"./lib/server/child/singletonProviders.js": "./lib/browser/child/singletonProviders.js",
|
|
7
8
|
"./lib/server/child/providers.js": "./lib/browser/child/providers.js",
|
|
8
9
|
"./lib/server.es.js": "./lib/server.browser.js"
|
|
9
10
|
},
|
|
@@ -30,20 +31,20 @@
|
|
|
30
31
|
"@tinkoff/env-validators": "0.0.3",
|
|
31
32
|
"@tinkoff/module-loader-client": "0.3.25",
|
|
32
33
|
"@tinkoff/module-loader-server": "0.4.41",
|
|
33
|
-
"@tramvai/child-app-core": "1.
|
|
34
|
+
"@tramvai/child-app-core": "1.68.0",
|
|
34
35
|
"@tramvai/safe-strings": "0.4.3",
|
|
35
|
-
"@tramvai/tokens-child-app": "1.
|
|
36
|
+
"@tramvai/tokens-child-app": "1.68.0"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {},
|
|
38
39
|
"peerDependencies": {
|
|
39
40
|
"@tinkoff/dippy": "0.7.38",
|
|
40
41
|
"@tinkoff/utils": "^2.1.2",
|
|
41
|
-
"@tramvai/core": "1.
|
|
42
|
-
"@tramvai/state": "1.
|
|
43
|
-
"@tramvai/react": "1.
|
|
44
|
-
"@tramvai/tokens-common": "1.
|
|
45
|
-
"@tramvai/tokens-render": "1.
|
|
46
|
-
"@tramvai/tokens-router": "1.
|
|
42
|
+
"@tramvai/core": "1.68.0",
|
|
43
|
+
"@tramvai/state": "1.68.0",
|
|
44
|
+
"@tramvai/react": "1.68.0",
|
|
45
|
+
"@tramvai/tokens-common": "1.68.0",
|
|
46
|
+
"@tramvai/tokens-render": "1.68.0",
|
|
47
|
+
"@tramvai/tokens-router": "1.68.0",
|
|
47
48
|
"react": ">=16.8.0",
|
|
48
49
|
"react-dom": ">=16.8.0",
|
|
49
50
|
"object-assign": "^4.1.1",
|