@tramvai/module-child-app 2.70.0 → 2.72.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.
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
package/lib/server.js CHANGED
@@ -4,1088 +4,21 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var tslib = require('tslib');
6
6
  var core = require('@tramvai/core');
7
- var dippy = require('@tinkoff/dippy');
7
+ var providers = require('./shared/providers.js');
8
+ var providers$1 = require('./server/providers.js');
8
9
  var tokensChildApp = require('@tramvai/tokens-child-app');
9
- var tokensCommon = require('@tramvai/tokens-common');
10
- var tokensRender = require('@tramvai/tokens-render');
11
- var tokensRouter = require('@tramvai/tokens-router');
12
- var react$1 = require('@tramvai/react');
13
- var flatten = require('@tinkoff/utils/array/flatten');
14
- var state = require('@tramvai/state');
15
- var jsxRuntime = require('react/jsx-runtime');
16
- var react = require('react');
17
- var applyOrReturn = require('@tinkoff/utils/function/applyOrReturn');
18
- var envValidators = require('@tinkoff/env-validators');
19
- var safeStrings = require('@tramvai/safe-strings');
20
- var moduleLoaderServer = require('@tinkoff/module-loader-server');
21
- var noop = require('@tinkoff/utils/function/noop');
22
- var moduleRouter = require('@tramvai/module-router');
23
-
24
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
25
-
26
- var flatten__default = /*#__PURE__*/_interopDefaultLegacy(flatten);
27
- var applyOrReturn__default = /*#__PURE__*/_interopDefaultLegacy(applyOrReturn);
28
- var noop__default = /*#__PURE__*/_interopDefaultLegacy(noop);
29
-
30
- const getChildProviders$2 = (appDi) => {
31
- return [
32
- core.provide({
33
- provide: tokensChildApp.commandLineListTokens.resolvePageDeps,
34
- multi: true,
35
- useFactory: ({ actionRunner, actions }) => {
36
- return function childAppRunActions() {
37
- return actionRunner.runActions(flatten__default["default"](actions));
38
- };
39
- },
40
- deps: {
41
- actionRunner: tokensCommon.ACTION_PAGE_RUNNER_TOKEN,
42
- actions: tokensChildApp.CHILD_APP_INTERNAL_ACTION_TOKEN,
43
- },
44
- }),
45
- ];
46
- };
47
-
48
- const getChildProviders$1 = (appDi) => {
49
- const logger = appDi.get(tokensCommon.LOGGER_TOKEN);
50
- return [
51
- core.provide({
52
- provide: tokensCommon.LOGGER_TOKEN,
53
- useValue: Object.assign((opts) => {
54
- return logger('child-app').child(opts);
55
- }, logger),
56
- }),
57
- core.provide({
58
- provide: tokensRender.RENDER_SLOTS,
59
- multi: true,
60
- useValue: [],
61
- }),
62
- ...getChildProviders$2(),
63
- ];
64
- };
65
-
66
- const commonModuleStubs = [
67
- tokensCommon.DISPATCHER_TOKEN,
68
- tokensCommon.STORE_TOKEN,
69
- tokensCommon.CONTEXT_TOKEN,
70
- core.COMMAND_LINE_RUNNER_TOKEN,
71
- ].map((provide) => {
72
- return {
73
- provide,
74
- useFactory: () => {
75
- throw Object.assign(new Error('Pure usage of the token is not allowed inside ChildApp, please add `CommonChildAppModule` from module `@tramvai/module-common` to your ChildApp'), { code: 'E_STUB' });
76
- },
77
- };
78
- });
79
-
80
- const validateChildAppProvider = (provider) => {
81
- if (provider.provide.name === tokensCommon.ENV_USED_TOKEN.name) {
82
- throw new Error(`child-app Cannot use 'ENV_USED_TOKEN' as envs should be controlled by the root-app.
83
- Consider passing configs from the root-app to child-app explicitly and remove defining 'ENV_USED_TOKEN' in the child-app itself.
84
- You can still use 'ENV_MANAGER_TOKEN' in child-app to get env values`);
85
- }
86
- };
87
-
88
- class SingletonDiManager {
89
- constructor({ logger, appDi, loader, }) {
90
- this.cache = new Map();
91
- this.log = logger('child-app:singleton-di-manager');
92
- this.appDi = appDi;
93
- this.loader = loader;
94
- }
95
- getChildDi(config) {
96
- const { key, tag } = config;
97
- if (this.cache.has(key)) {
98
- return this.cache.get(key);
99
- }
100
- try {
101
- const di = this.resolveDi(config);
102
- if (di && tag !== 'debug') {
103
- this.cache.set(key, di);
104
- }
105
- return di;
106
- }
107
- catch (error) {
108
- this.log.error({
109
- event: 'resolve-di-fail',
110
- error,
111
- config,
112
- });
113
- }
114
- }
115
- forEachChildDi(cb) {
116
- this.cache.forEach((di) => {
117
- cb(di);
118
- });
119
- }
120
- resolveDi(config) {
121
- const children = this.loader.get(config);
122
- if (!children) {
123
- return;
124
- }
125
- const di = new dippy.Container([
126
- {
127
- provide: tokensChildApp.CHILD_APP_INTERNAL_CONFIG_TOKEN,
128
- useValue: config,
129
- },
130
- {
131
- provide: tokensChildApp.IS_CHILD_APP_DI_TOKEN,
132
- useValue: true,
133
- },
134
- ], this.appDi);
135
- const { modules = [], providers = [], actions = [] } = children;
136
- // add providers on the Singleton Level to make it possible to reuse providers from the root-app Container
137
- const childProviders = getChildProviders$1(this.appDi);
138
- childProviders.forEach((provider) => {
139
- di.register(provider);
140
- });
141
- const resolvedModules = core.walkOfModules(modules);
142
- resolvedModules.forEach((mod) => {
143
- const moduleParameters = core.getModuleParameters(mod);
144
- moduleParameters.providers.forEach((provider) => {
145
- di.register(provider);
146
- });
147
- });
148
- providers.forEach((provider) => {
149
- if (process.env.NODE_ENV === 'development') {
150
- validateChildAppProvider(provider);
151
- }
152
- di.register(provider);
153
- });
154
- di.register({
155
- provide: tokensChildApp.CHILD_APP_INTERNAL_ACTION_TOKEN,
156
- multi: true,
157
- useValue: actions,
158
- });
159
- const borrowTokens = di.get({ token: tokensChildApp.CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN, optional: true });
160
- if (borrowTokens) {
161
- flatten__default["default"](borrowTokens).forEach((token) => {
162
- di.borrowToken(this.appDi, token);
163
- });
164
- }
165
- commonModuleStubs.forEach((stub) => {
166
- if (!di.has(stub.provide)) {
167
- di.register(stub);
168
- }
169
- });
170
- return di;
171
- }
172
- }
173
-
174
- const getChildProviders = (appDi) => {
175
- const parentDispatcherContext = appDi.get(tokensCommon.DISPATCHER_CONTEXT_TOKEN);
176
- return [
177
- core.provide({
178
- provide: tokensCommon.DISPATCHER_CONTEXT_TOKEN,
179
- useFactory: ({ dispatcher, middlewares, initialState, parentAllowedStores }) => {
180
- return new state.ChildDispatcherContext({
181
- dispatcher,
182
- // context will be set later by the CONTEXT_TOKEN
183
- context: {},
184
- initialState: initialState !== null && initialState !== void 0 ? initialState : { stores: [] },
185
- middlewares: flatten__default["default"](middlewares || []),
186
- parentDispatcherContext,
187
- parentAllowedStores: flatten__default["default"](parentAllowedStores || []),
188
- });
189
- },
190
- deps: {
191
- dispatcher: tokensCommon.DISPATCHER_TOKEN,
192
- middlewares: { token: tokensCommon.STORE_MIDDLEWARE, optional: true },
193
- initialState: { token: tokensCommon.INITIAL_APP_STATE_TOKEN, optional: true },
194
- parentAllowedStores: {
195
- token: tokensChildApp.CHILD_APP_INTERNAL_ROOT_STATE_ALLOWED_STORE_TOKEN,
196
- optional: true,
197
- },
198
- },
199
- }),
200
- ];
201
- };
202
-
203
- class DiManager {
204
- constructor({ appDi, loader, singletonDiManager, }) {
205
- this.cache = new Map();
206
- this.appDi = appDi;
207
- this.loader = loader;
208
- this.singletonDiManager = singletonDiManager;
209
- }
210
- getChildDi(config) {
211
- const { key } = config;
212
- if (this.cache.has(key)) {
213
- return this.cache.get(key);
214
- }
215
- const di = this.resolveDi(config);
216
- di && this.cache.set(key, di);
217
- return di;
218
- }
219
- forEachChildDi(cb) {
220
- this.cache.forEach((di) => {
221
- cb(di);
222
- });
223
- }
224
- resolveDi(config) {
225
- const children = this.loader.get(config);
226
- if (!children) {
227
- return;
228
- }
229
- const singletonDi = this.singletonDiManager.getChildDi(config);
230
- if (!singletonDi) {
231
- return;
232
- }
233
- const di = new dippy.ChildContainer(singletonDi, this.appDi);
234
- // add providers on the Request Level to make it possible to reuse providers from the root-app ChildContainer
235
- const childProviders = getChildProviders(this.appDi);
236
- childProviders.forEach((provider) => {
237
- di.register(provider);
238
- });
239
- return di;
240
- }
241
- }
242
-
243
- class CommandLineRunner {
244
- constructor({ logger, rootCommandLineRunner, diManager, }) {
245
- this.log = logger('child-app:command-line-runner');
246
- this.rootCommandLineRunner = rootCommandLineRunner;
247
- this.diManager = diManager;
248
- }
249
- async run(type, status, config) {
250
- const di = this.diManager.getChildDi(config);
251
- if (!di) {
252
- return;
253
- }
254
- try {
255
- const commandLineRunner = di.get({ token: core.COMMAND_LINE_RUNNER_TOKEN, optional: true });
256
- if (commandLineRunner && commandLineRunner !== this.rootCommandLineRunner) {
257
- // TODO:child-app create independent metrics instance for child apps
258
- // for now just reuse metrics implementation from root as otherwise it fails after attempt to create metrics instance with the same name
259
- // @ts-ignore
260
- commandLineRunner.metricsInstance = this.rootCommandLineRunner.metricsInstance;
261
- await commandLineRunner.run(type, status, [], di);
262
- }
263
- }
264
- catch (error) {
265
- if (error.code !== 'E_STUB') {
266
- this.log.error({
267
- event: 'run-failed',
268
- error,
269
- type,
270
- status,
271
- config,
272
- });
273
- }
274
- }
275
- }
276
- }
277
-
278
- const setPreloaded = state.createEvent('child-app set preloaded');
279
- const initialState = {
280
- preloaded: [],
281
- };
282
- const ChildAppStore = state.createReducer('child-app', initialState).on(setPreloaded, (_, preloaded) => {
283
- return {
284
- preloaded,
285
- };
286
- });
287
-
288
- const RenderContext = react.createContext(null);
289
-
290
- const extendRender = ({ renderManager, }) => {
291
- return (render) => {
292
- return jsxRuntime.jsx(RenderContext.Provider, { value: renderManager, children: render });
293
- };
294
- };
295
-
296
- const initModuleFederation = async (container, scope = 'default') => {
297
- if (container) {
298
- await container.init(__webpack_share_scopes__[scope]);
299
- return;
300
- }
301
- await __webpack_init_sharing__('default');
302
- // currently module federation has problems with external modules
303
- // and unfourtanelly react and react-dom are marked as externals in defaults
304
- // fill sharedScope manually here
305
- const shareScope = __webpack_share_scopes__[scope];
306
- if (!shareScope.react) {
307
- shareScope.react = {
308
- '*': {
309
- get: () => () => require('react'),
310
- from: 'tramvai-mf-fix',
311
- eager: true,
312
- loaded: true,
313
- },
314
- };
315
- }
316
- if (!shareScope['react-dom']) {
317
- shareScope['react-dom'] = {
318
- '*': {
319
- get: () => () => require('react-dom'),
320
- from: 'tramvai-mf-fix',
321
- eager: true,
322
- loaded: true,
323
- },
324
- };
325
- }
326
- if (process.env.NODE_ENV === 'development') {
327
- // explicitly add react/jsx-runtime to support production builds of the child-app in dev mode
328
- if (!shareScope['react/jsx-runtime']) {
329
- shareScope['react/jsx-runtime'] = {
330
- '*': {
331
- get: () => () => require('react/jsx-runtime'),
332
- from: 'tramvai-mf-fix',
333
- eager: true,
334
- loaded: true,
335
- },
336
- };
337
- }
338
- }
339
- };
340
- const getModuleFederation = async (container, name = 'entry') => {
341
- return container.get(name);
342
- };
343
-
344
- class ChildAppResolutionConfigManager {
345
- constructor({ configs, logger, }) {
346
- this.hasInitialized = false;
347
- this.rawConfigs = configs !== null && configs !== void 0 ? configs : [];
348
- this.mapping = new Map();
349
- this.log = logger('child-app:resolution-config');
350
- }
351
- async init() {
352
- if (this.hasInitialized) {
353
- return;
354
- }
355
- if (this.initPromise) {
356
- return this.initPromise;
357
- }
358
- this.initPromise = (async () => {
359
- const configs = await Promise.all(this.rawConfigs.map((rawConfig) => {
360
- return Promise.resolve()
361
- .then(() => {
362
- return applyOrReturn__default["default"]([], rawConfig);
363
- })
364
- .catch((error) => {
365
- this.log.error(error, 'Failed while resolving resolution config');
366
- });
367
- }));
368
- flatten__default["default"](configs).forEach((config) => {
369
- if (config) {
370
- this.mapping.set(config.name, config);
371
- }
372
- });
373
- this.hasInitialized = true;
374
- })();
375
- return this.initPromise;
376
- }
377
- resolve({ name, version, tag = 'latest' }) {
378
- var _a;
379
- const fromMapping = this.mapping.get(name);
380
- if (!fromMapping) {
381
- return;
382
- }
383
- const cfg = fromMapping.byTag[tag];
384
- if (process.env.NODE_ENV === 'development' && tag === 'debug' && !cfg) {
385
- return {
386
- baseUrl: 'http://localhost:4040/',
387
- version: '0.0.0-stub',
388
- };
389
- }
390
- return {
391
- ...cfg,
392
- baseUrl: (_a = cfg.baseUrl) !== null && _a !== void 0 ? _a : fromMapping.baseUrl,
393
- version: version !== null && version !== void 0 ? version : cfg.version,
394
- };
395
- }
396
- }
397
-
398
- const sharedProviders = [
399
- core.provide({
400
- provide: tokensCommon.COMBINE_REDUCERS,
401
- multi: true,
402
- useValue: ChildAppStore,
403
- }),
404
- core.provide({
405
- provide: core.commandLineListTokens.init,
406
- multi: true,
407
- useValue: () => initModuleFederation(),
408
- }),
409
- core.provide({
410
- provide: tokensChildApp.CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
411
- useClass: ChildAppResolutionConfigManager,
412
- deps: {
413
- configs: { token: tokensChildApp.CHILD_APP_RESOLUTION_CONFIGS_TOKEN, optional: true },
414
- logger: tokensCommon.LOGGER_TOKEN,
415
- },
416
- }),
417
- core.provide({
418
- provide: core.commandLineListTokens.resolvePageDeps,
419
- multi: true,
420
- useFactory: ({ resolutionConfigManager }) => {
421
- return async function fallbackResolutionConfigManagerInit() {
422
- await resolutionConfigManager.init();
423
- };
424
- },
425
- deps: {
426
- resolutionConfigManager: tokensChildApp.CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
427
- },
428
- }),
429
- core.provide({
430
- provide: tokensChildApp.CHILD_APP_RESOLVE_CONFIG_TOKEN,
431
- useFactory: ({ envManager, logger, rootBaseUrl, resolutionConfigManager }) => {
432
- const rawEnv = envManager.get('CHILD_APP_DEBUG');
433
- const log = logger('child-app:resolve-config');
434
- const debug = new Map();
435
- rawEnv === null || rawEnv === void 0 ? void 0 : rawEnv.split(';').reduce((acc, entry) => {
436
- const [name, url] = entry.split('=');
437
- return acc.set(name, url);
438
- }, debug);
439
- return (request) => {
440
- var _a, _b;
441
- const { name, tag = debug.has(name) ? 'debug' : 'latest' } = request;
442
- const req = { name, tag, version: request.version };
443
- const config = resolutionConfigManager.resolve(req);
444
- if (!config) {
445
- log.error(`Child-app "${name}" with tag "${tag}" has not found`);
446
- return;
447
- }
448
- const { version, baseUrl: configBaseUrl, client, server, css, withoutCss } = config;
449
- const baseUrl = (_b = (_a = debug.get(name)) !== null && _a !== void 0 ? _a : configBaseUrl) !== null && _b !== void 0 ? _b : rootBaseUrl;
450
- if (!baseUrl) {
451
- throw new Error('CHILD_APP_EXTERNAL_URL was not defined');
452
- }
453
- return {
454
- name,
455
- tag,
456
- version,
457
- key: `${name}@${version}`,
458
- server: {
459
- entry: `${baseUrl}${name}/${name}_server@${version}.js`,
460
- ...server,
461
- },
462
- client: {
463
- baseUrl: `${baseUrl}${name}/`,
464
- entry: `${baseUrl}${name}/${name}_client@${version}.js`,
465
- ...client,
466
- },
467
- css: withoutCss
468
- ? undefined
469
- : {
470
- entry: `${baseUrl}${name}/${name}@${version}.css`,
471
- ...css,
472
- },
473
- };
474
- };
475
- },
476
- deps: {
477
- envManager: tokensCommon.ENV_MANAGER_TOKEN,
478
- logger: tokensCommon.LOGGER_TOKEN,
479
- rootBaseUrl: tokensChildApp.CHILD_APP_RESOLVE_BASE_URL_TOKEN,
480
- resolutionConfigManager: tokensChildApp.CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
481
- },
482
- }),
483
- core.provide({
484
- provide: tokensChildApp.CHILD_APP_RESOLVE_BASE_URL_TOKEN,
485
- useFactory: ({ envManager }) => {
486
- return envManager.get('CHILD_APP_EXTERNAL_URL');
487
- },
488
- deps: {
489
- envManager: tokensCommon.ENV_MANAGER_TOKEN,
490
- },
491
- }),
492
- core.provide({
493
- provide: tokensChildApp.CHILD_APP_SINGLETON_DI_MANAGER_TOKEN,
494
- scope: dippy.Scope.SINGLETON,
495
- useClass: SingletonDiManager,
496
- deps: {
497
- logger: tokensCommon.LOGGER_TOKEN,
498
- appDi: dippy.DI_TOKEN,
499
- loader: tokensChildApp.CHILD_APP_LOADER_TOKEN,
500
- },
501
- }),
502
- core.provide({
503
- provide: tokensChildApp.CHILD_APP_DI_MANAGER_TOKEN,
504
- useClass: DiManager,
505
- deps: {
506
- appDi: dippy.DI_TOKEN,
507
- loader: tokensChildApp.CHILD_APP_LOADER_TOKEN,
508
- singletonDiManager: tokensChildApp.CHILD_APP_SINGLETON_DI_MANAGER_TOKEN,
509
- },
510
- }),
511
- core.provide({
512
- provide: tokensChildApp.CHILD_APP_COMMAND_LINE_RUNNER_TOKEN,
513
- useClass: CommandLineRunner,
514
- deps: {
515
- logger: tokensCommon.LOGGER_TOKEN,
516
- rootCommandLineRunner: core.COMMAND_LINE_RUNNER_TOKEN,
517
- diManager: tokensChildApp.CHILD_APP_DI_MANAGER_TOKEN,
518
- },
519
- }),
520
- core.provide({
521
- provide: core.commandLineListTokens.resolvePageDeps,
522
- useFactory: ({ pageService, preloadManager }) => {
523
- return async function preloadChildAppByComponent() {
524
- var _a, _b, _c, _d, _e, _f;
525
- const [layoutComponent, nestedLayoutComponent, pageComponent] = await Promise.all([
526
- react$1.resolveLazyComponent(pageService.resolveComponentFromConfig('layout')),
527
- react$1.resolveLazyComponent(pageService.resolveComponentFromConfig('nestedLayout')),
528
- react$1.resolveLazyComponent(pageService.resolveComponentFromConfig('page')),
529
- ]);
530
- await Promise.all([
531
- ...((_b = (_a = layoutComponent === null || layoutComponent === void 0 ? void 0 : layoutComponent.childApps) === null || _a === void 0 ? void 0 : _a.map((request) => preloadManager.preload(request))) !== null && _b !== void 0 ? _b : []),
532
- ...((_d = (_c = nestedLayoutComponent === null || nestedLayoutComponent === void 0 ? void 0 : nestedLayoutComponent.childApps) === null || _c === void 0 ? void 0 : _c.map((request) => preloadManager.preload(request))) !== null && _d !== void 0 ? _d : []),
533
- ...((_f = (_e = pageComponent === null || pageComponent === void 0 ? void 0 : pageComponent.childApps) === null || _e === void 0 ? void 0 : _e.map((request) => preloadManager.preload(request))) !== null && _f !== void 0 ? _f : []),
534
- ]);
535
- };
536
- },
537
- multi: true,
538
- deps: {
539
- pageService: tokensRouter.PAGE_SERVICE_TOKEN,
540
- preloadManager: tokensChildApp.CHILD_APP_PRELOAD_MANAGER_TOKEN,
541
- },
542
- }),
543
- core.provide({
544
- provide: core.commandLineListTokens.generatePage,
545
- multi: true,
546
- useFactory: ({ preloadManager }) => {
547
- return function childAppPageRender() {
548
- preloadManager.pageRender();
549
- };
550
- },
551
- deps: {
552
- preloadManager: tokensChildApp.CHILD_APP_PRELOAD_MANAGER_TOKEN,
553
- },
554
- }),
555
- core.provide({
556
- provide: core.commandLineListTokens.clear,
557
- multi: true,
558
- useFactory: ({ preloader }) => {
559
- return function childAppClear() {
560
- return preloader.clearPreloaded();
561
- };
562
- },
563
- deps: {
564
- preloader: tokensChildApp.CHILD_APP_PRELOAD_MANAGER_TOKEN,
565
- },
566
- }),
567
- core.provide({
568
- provide: tokensCommon.REGISTER_CLEAR_CACHE_TOKEN,
569
- multi: true,
570
- useFactory: ({ diManager }) => {
571
- return (type) => {
572
- diManager.forEachChildDi((di) => {
573
- var _a;
574
- const clearCache = di.get({ token: tokensCommon.CLEAR_CACHE_TOKEN, optional: true });
575
- if (clearCache) {
576
- // first if child-app has its own CLEAR_CACHE_TOKEN implementation use only it
577
- return clearCache(type);
578
- }
579
- // otherwise pick up any REGISTER_CLEAR_CACHE_TOKEN hooks and call it
580
- const registeredClearCache = (_a = di.get({
581
- token: tokensCommon.REGISTER_CLEAR_CACHE_TOKEN,
582
- optional: true,
583
- })) !== null && _a !== void 0 ? _a : [];
584
- return Promise.all(registeredClearCache.map((clear) => clear(type)));
585
- });
586
- };
587
- },
588
- deps: {
589
- diManager: tokensChildApp.CHILD_APP_SINGLETON_DI_MANAGER_TOKEN,
590
- },
591
- }),
592
- core.provide({
593
- provide: tokensRender.EXTEND_RENDER,
594
- multi: true,
595
- useFactory: extendRender,
596
- deps: {
597
- renderManager: tokensChildApp.CHILD_APP_RENDER_MANAGER_TOKEN,
598
- },
599
- }),
600
- core.provide({
601
- provide: tokensCommon.ENV_USED_TOKEN,
602
- multi: true,
603
- useValue: [
604
- {
605
- key: 'CHILD_APP_DEBUG',
606
- dehydrate: true,
607
- optional: true,
608
- },
609
- ],
610
- }),
611
- ];
612
-
613
- class Loader {
614
- resolve(entry) {
615
- return entry.default;
616
- }
617
- }
618
-
619
- class ServerLoader extends Loader {
620
- constructor({ logger, createCache, }) {
621
- super();
622
- this.initializedMap = new WeakMap();
623
- const cache = createCache('memory', {
624
- ttl: 1000 * 60 * 60 * 24 * 5,
625
- max: 20,
626
- });
627
- this.internalLoadCache = cache;
628
- this.loader = new moduleLoaderServer.ServerLoader({
629
- cache,
630
- log: logger('child-app:loader'),
631
- });
632
- }
633
- async load(config) {
634
- await this.loader.resolveByUrl(config.server.entry, {
635
- codePrefix: `var ASSETS_PREFIX="${config.client.baseUrl}";`,
636
- displayName: config.name,
637
- kind: 'child-app',
638
- });
639
- await this.init(config);
640
- if (config.tag === 'debug') {
641
- setTimeout(() => {
642
- this.internalLoadCache.set(config.server.entry, null);
643
- }, 10000);
644
- }
645
- return this.get(config);
646
- }
647
- async init(config) {
648
- const container = this.loader.getByUrl(config.server.entry);
649
- if (container) {
650
- await initModuleFederation(container, 'default');
651
- const factory = (await getModuleFederation(container, 'entry'));
652
- const entry = factory();
653
- this.initializedMap.set(container, entry);
654
- }
655
- }
656
- get(config) {
657
- const container = this.loader.getByUrl(config.server.entry);
658
- return container && this.resolve(this.initializedMap.get(container));
659
- }
660
- }
661
-
662
- class PreloadManager {
663
- constructor({ loader, runner, stateManager, resolutionConfigManager, resolveFullConfig, }) {
664
- this.shouldRunImmediately = false;
665
- this.map = new Map();
666
- this.preloadMap = new Map();
667
- this.loader = loader;
668
- this.runner = runner;
669
- this.stateManager = stateManager;
670
- this.resolutionConfigManager = resolutionConfigManager;
671
- this.resolveFullConfig = resolveFullConfig;
672
- }
673
- async preload(request) {
674
- await this.resolutionConfigManager.init();
675
- const config = this.resolveFullConfig(request);
676
- if (!config) {
677
- return;
678
- }
679
- const { key } = config;
680
- if (this.map.has(key)) {
681
- await this.map.get(key);
682
- return;
683
- }
684
- const promise = this.loader
685
- .load(config)
686
- .catch(() => {
687
- // Actual error will be logged by the internals of this.loader
688
- })
689
- .then(() => {
690
- if (this.shouldRunImmediately) {
691
- return this.run('customer', config);
692
- }
693
- })
694
- .then(() => config);
695
- this.map.set(key, promise);
696
- this.preloadMap.set(config.key, config);
697
- if (this.shouldRunImmediately) {
698
- await promise;
699
- }
700
- }
701
- isPreloaded(request) {
702
- const config = this.resolveFullConfig(request);
703
- return !!config && this.map.has(config.key);
704
- }
705
- async runPreloaded() {
706
- this.shouldRunImmediately = true;
707
- const promises = [];
708
- this.map.forEach((childAppPromise) => {
709
- promises.push((async () => {
710
- await this.run('customer', await childAppPromise);
711
- })());
712
- });
713
- await Promise.all(promises);
714
- }
715
- pageRender() { }
716
- async clearPreloaded() {
717
- const promises = [];
718
- this.map.forEach((childAppPromise) => {
719
- promises.push((async () => {
720
- await this.run('clear', await childAppPromise);
721
- })());
722
- });
723
- await Promise.all(promises);
724
- }
725
- getPreloadedList() {
726
- return Array.from(this.preloadMap.values());
727
- }
728
- async run(status, config) {
729
- const childApp = this.loader.get(config);
730
- if (!childApp) {
731
- return;
732
- }
733
- await this.runner.run('server', status, config);
734
- await this.stateManager.registerChildApp(config);
735
- }
736
- }
737
-
738
- const executeRootStateSubscriptions = ({ store, diManager, }) => {
739
- return (render) => {
740
- const state = store.getState();
741
- diManager.forEachChildDi((di) => {
742
- const subscriptions = di.get({
743
- token: tokensChildApp.CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN,
744
- optional: true,
745
- });
746
- subscriptions === null || subscriptions === void 0 ? void 0 : subscriptions.forEach((sub) => {
747
- sub.listener(state);
748
- });
749
- });
750
- return render;
751
- };
752
- };
753
- class StateManager {
754
- constructor({ logger, diManager, }) {
755
- this.state = Object.create(null);
756
- this.log = logger('child-app:state-manager');
757
- this.diManager = diManager;
758
- }
759
- registerChildApp(config) {
760
- const di = this.diManager.getChildDi(config);
761
- const { key } = config;
762
- if (!di) {
763
- return;
764
- }
765
- try {
766
- const context = di.get(tokensCommon.CONTEXT_TOKEN);
767
- this.state[key] = context.dehydrate().dispatcher;
768
- }
769
- catch (error) {
770
- if (error.code !== 'E_STUB') {
771
- this.log.error({
772
- event: 'get-state-failed',
773
- config,
774
- });
775
- }
776
- }
777
- }
778
- getState() {
779
- return this.state;
780
- }
781
- }
782
-
783
- class RenderManager {
784
- constructor({ logger, preloadManager, diManager, resolveFullConfig, }) {
785
- this.hasRenderedSet = new Set();
786
- this.log = logger('child-app:render');
787
- this.preloadManager = preloadManager;
788
- this.diManager = diManager;
789
- this.resolveFullConfig = resolveFullConfig;
790
- }
791
- getChildDi(request) {
792
- const config = this.resolveFullConfig(request);
793
- if (!config) {
794
- throw new Error(`Child app "${request.name}" not found`);
795
- }
796
- this.hasRenderedSet.add(config.key);
797
- if (this.preloadManager.isPreloaded(request)) {
798
- return [this.diManager.getChildDi(config), undefined];
799
- }
800
- this.log.warn({
801
- message: 'Child-app has been used but not preloaded before React render',
802
- request,
803
- });
804
- return [undefined, undefined];
805
- }
806
- clear() {
807
- const preloadedList = this.preloadManager.getPreloadedList();
808
- for (const request of preloadedList) {
809
- const config = this.resolveFullConfig(request);
810
- if (!config || !this.hasRenderedSet.has(config.key)) {
811
- this.log.warn({
812
- message: 'Child-app has been preloaded but not used in React render',
813
- request,
814
- });
815
- }
816
- }
817
- this.hasRenderedSet.clear();
818
- }
819
- }
820
-
821
- const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, preloadManager, }) => {
822
- const log = logger('child-app:render:slots');
823
- const result = [];
824
- preloadManager.getPreloadedList().forEach((requestConfig) => {
825
- var _a;
826
- const config = resolveFullConfig(requestConfig);
827
- if (!config) {
828
- return;
829
- }
830
- const di = diManager.getChildDi(config);
831
- result.push({
832
- type: tokensRender.ResourceType.script,
833
- slot: tokensRender.ResourceSlot.HEAD_CORE_SCRIPTS,
834
- payload: config.client.entry,
835
- attrs: {
836
- 'data-critical': 'true',
837
- },
838
- });
839
- if (config.css) {
840
- result.push({
841
- type: tokensRender.ResourceType.style,
842
- slot: tokensRender.ResourceSlot.HEAD_CORE_STYLES,
843
- payload: (_a = config.css.entry) !== null && _a !== void 0 ? _a : null,
844
- attrs: {
845
- 'data-critical': 'true',
846
- },
847
- });
848
- }
849
- if (!di) {
850
- return;
851
- }
852
- try {
853
- const renderSlots = di.get({ token: tokensRender.RENDER_SLOTS, optional: true });
854
- if (renderSlots) {
855
- result.push(...renderSlots);
856
- }
857
- }
858
- catch (error) {
859
- log.error({
860
- event: 'get-slots-failed',
861
- config: requestConfig,
862
- });
863
- }
864
- });
865
- return result;
866
- };
867
-
868
- const GLOBAL_CHILD_STATE = '__TRAMVAI_CHILD_STATE__';
869
-
870
- const serverProviders = [
871
- core.provide({
872
- provide: tokensCommon.ENV_USED_TOKEN,
873
- multi: true,
874
- useValue: [
875
- {
876
- key: 'CHILD_APP_EXTERNAL_URL',
877
- optional: true,
878
- validator: envValidators.combineValidators([envValidators.isUrl, envValidators.endsWith('/')]),
879
- },
880
- ],
881
- }),
882
- core.provide({
883
- provide: tokensChildApp.CHILD_APP_LOADER_TOKEN,
884
- useClass: ServerLoader,
885
- scope: dippy.Scope.SINGLETON,
886
- deps: {
887
- logger: tokensCommon.LOGGER_TOKEN,
888
- createCache: tokensCommon.CREATE_CACHE_TOKEN,
889
- },
890
- }),
891
- core.provide({
892
- provide: tokensChildApp.CHILD_APP_STATE_MANAGER_TOKEN,
893
- useClass: StateManager,
894
- deps: {
895
- logger: tokensCommon.LOGGER_TOKEN,
896
- diManager: tokensChildApp.CHILD_APP_DI_MANAGER_TOKEN,
897
- resourcesRegistry: tokensRender.RESOURCES_REGISTRY,
898
- },
899
- }),
900
- core.provide({
901
- provide: tokensChildApp.CHILD_APP_PRELOAD_MANAGER_TOKEN,
902
- useClass: PreloadManager,
903
- deps: {
904
- loader: tokensChildApp.CHILD_APP_LOADER_TOKEN,
905
- runner: tokensChildApp.CHILD_APP_COMMAND_LINE_RUNNER_TOKEN,
906
- stateManager: tokensChildApp.CHILD_APP_STATE_MANAGER_TOKEN,
907
- resolutionConfigManager: tokensChildApp.CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
908
- resolveFullConfig: tokensChildApp.CHILD_APP_RESOLVE_CONFIG_TOKEN,
909
- },
910
- }),
911
- core.provide({
912
- provide: tokensRender.RENDER_SLOTS,
913
- multi: true,
914
- useFactory: ({ stateManager, preloader, store }) => {
915
- store.dispatch(setPreloaded(preloader.getPreloadedList()));
916
- return {
917
- type: tokensRender.ResourceType.asIs,
918
- slot: tokensRender.ResourceSlot.BODY_END,
919
- payload: `<script id="${GLOBAL_CHILD_STATE}" type="application/json">${safeStrings.safeStringify(stateManager.getState())}</script>`,
920
- };
921
- },
922
- deps: {
923
- stateManager: tokensChildApp.CHILD_APP_STATE_MANAGER_TOKEN,
924
- preloader: tokensChildApp.CHILD_APP_PRELOAD_MANAGER_TOKEN,
925
- store: tokensCommon.STORE_TOKEN,
926
- },
927
- }),
928
- core.provide({
929
- provide: tokensRender.RENDER_SLOTS,
930
- multi: true,
931
- useFactory: registerChildAppRenderSlots,
932
- deps: {
933
- logger: tokensCommon.LOGGER_TOKEN,
934
- diManager: tokensChildApp.CHILD_APP_DI_MANAGER_TOKEN,
935
- resolveFullConfig: tokensChildApp.CHILD_APP_RESOLVE_CONFIG_TOKEN,
936
- preloadManager: tokensChildApp.CHILD_APP_PRELOAD_MANAGER_TOKEN,
937
- },
938
- }),
939
- core.provide({
940
- provide: tokensRender.EXTEND_RENDER,
941
- multi: true,
942
- // execute subscription right before render to get the last actual data
943
- useFactory: executeRootStateSubscriptions,
944
- deps: {
945
- store: tokensCommon.STORE_TOKEN,
946
- diManager: tokensChildApp.CHILD_APP_DI_MANAGER_TOKEN,
947
- },
948
- }),
949
- core.provide({
950
- provide: tokensChildApp.CHILD_APP_RENDER_MANAGER_TOKEN,
951
- useClass: RenderManager,
952
- deps: {
953
- logger: tokensCommon.LOGGER_TOKEN,
954
- diManager: tokensChildApp.CHILD_APP_DI_MANAGER_TOKEN,
955
- preloadManager: tokensChildApp.CHILD_APP_PRELOAD_MANAGER_TOKEN,
956
- resolveFullConfig: tokensChildApp.CHILD_APP_RESOLVE_CONFIG_TOKEN,
957
- },
958
- }),
959
- core.provide({
960
- provide: core.commandLineListTokens.resolvePageDeps,
961
- multi: true,
962
- useFactory: ({ preloader }) => {
963
- return function childAppRunPreloaded() {
964
- return preloader.runPreloaded();
965
- };
966
- },
967
- deps: {
968
- preloader: tokensChildApp.CHILD_APP_PRELOAD_MANAGER_TOKEN,
969
- },
970
- }),
971
- core.provide({
972
- provide: core.commandLineListTokens.clear,
973
- multi: true,
974
- useFactory: ({ renderManager }) => {
975
- return function childAppRenderClear() {
976
- renderManager.clear();
977
- };
978
- },
979
- deps: {
980
- renderManager: tokensChildApp.CHILD_APP_RENDER_MANAGER_TOKEN,
981
- },
982
- }),
983
- ];
984
-
985
- const FailedChildAppFallback = ({ config: { name, version, tag, fallback: Fallback }, }) => {
986
- const logger = react$1.useDi(tokensCommon.LOGGER_TOKEN);
987
- const log = logger('child-app:render');
988
- // On client-side hydration errors will be handled in `hydrateRoot` `onRecoverableError` property,
989
- // and update errors will be handled in Error Boundaries.
990
- //
991
- // Also, this component never be rendered at client-side, and we check environment only for safety
992
- // (server errors logic described here https://github.com/reactjs/rfcs/blob/main/text/0215-server-errors-in-react-18.md).
993
- //
994
- // On server-side, we still use `renderToString`,
995
- // and need to manually log render errors for components, wrapped in Suspense Boundaries.
996
- if (typeof window === 'undefined') {
997
- log.error({
998
- event: 'failed-render',
999
- message: 'child-app failed to render, will try to recover during hydration',
1000
- name,
1001
- version,
1002
- tag,
1003
- });
1004
- }
1005
- return Fallback ? jsxRuntime.jsx(Fallback, {}) : null;
1006
- };
1007
- const ChildAppWrapper = ({ name, version, tag, props, fallback: Fallback, }) => {
1008
- const renderManager = react.useContext(RenderContext);
1009
- const logger = react$1.useDi(tokensCommon.LOGGER_TOKEN);
1010
- const log = logger('child-app:render');
1011
- const [maybeDi, maybePromiseDi] = react.useMemo(() => {
1012
- return renderManager.getChildDi({ name, version, tag });
1013
- }, [name, version, tag, renderManager]);
1014
- const [di, setDi] = react.useState(maybeDi);
1015
- const [promiseDi, setPromiseDi] = react.useState(maybePromiseDi);
1016
- react.useEffect(() => {
1017
- if (!di && promiseDi) {
1018
- // any errors with loading child-app should be handled in some other place
1019
- promiseDi
1020
- .then(setDi)
1021
- .finally(() => setPromiseDi(undefined))
1022
- .catch(noop__default["default"]);
1023
- }
1024
- }, [di, promiseDi]);
1025
- if (!di && promiseDi) {
1026
- // in case child-app was not rendered on ssr
1027
- // and we have to wait before it's loading
1028
- return Fallback ? jsxRuntime.jsx(Fallback, {}) : null;
1029
- }
1030
- if (!di) {
1031
- log.error({
1032
- event: 'not-found',
1033
- name,
1034
- version,
1035
- tag,
1036
- message: 'child-app was not initialized',
1037
- });
1038
- if (process.env.__TRAMVAI_CONCURRENT_FEATURES || typeof window !== 'undefined') {
1039
- throw new Error(`Child-app was not initialized, check the loading error for child-app "${name}"`);
1040
- }
1041
- return Fallback ? jsxRuntime.jsx(Fallback, {}) : null;
1042
- }
1043
- try {
1044
- const Cmp = di.get({ token: tokensChildApp.CHILD_APP_INTERNAL_RENDER_TOKEN, optional: true });
1045
- if (!Cmp) {
1046
- log.error({
1047
- event: 'empty-render',
1048
- message: 'Child-app does not provide render token',
1049
- name,
1050
- version,
1051
- tag,
1052
- });
1053
- return null;
1054
- }
1055
- return jsxRuntime.jsx(Cmp, { di: di, props: props });
1056
- }
1057
- catch (error) {
1058
- log.error({
1059
- event: 'get-render',
1060
- message: 'Cannot get render token from child-app',
1061
- error,
1062
- name,
1063
- version,
1064
- tag,
1065
- });
1066
- return null;
1067
- }
1068
- };
1069
- const ChildApp = react.memo((config) => {
1070
- const { fallback } = config;
1071
- const url = moduleRouter.useUrl();
1072
- const result = (jsxRuntime.jsx(react$1.UniversalErrorBoundary, { url: url, fallback: fallback, children: jsxRuntime.jsx(ChildAppWrapper, { ...config }) }));
1073
- if (process.env.__TRAMVAI_CONCURRENT_FEATURES) {
1074
- return jsxRuntime.jsx(react.Suspense, { fallback: jsxRuntime.jsx(FailedChildAppFallback, { config: config }), children: result });
1075
- }
1076
- return result;
1077
- });
10
+ var component = require('./shared/react/component.js');
1078
11
 
1079
12
  exports.ChildAppModule = class ChildAppModule {
1080
13
  };
1081
14
  exports.ChildAppModule = tslib.__decorate([
1082
15
  core.Module({
1083
16
  imports: [],
1084
- providers: [...sharedProviders, ...serverProviders],
17
+ providers: [...providers.sharedProviders, ...providers$1.serverProviders],
1085
18
  })
1086
19
  ], exports.ChildAppModule);
1087
20
 
1088
- exports.ChildApp = ChildApp;
21
+ exports.ChildApp = component.ChildApp;
1089
22
  Object.keys(tokensChildApp).forEach(function (k) {
1090
23
  if (k !== 'default' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
1091
24
  enumerable: true,