chayns-api 1.1.0-9 → 1.2.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/cjs/calls/index.js +11 -3
  2. package/dist/cjs/components/ChaynsProvider.js +2 -5
  3. package/dist/cjs/components/withHydrationBoundary.js +5 -9
  4. package/dist/cjs/constants/languages.js +19 -0
  5. package/dist/cjs/handler/DialogHandler.js +1 -2
  6. package/dist/cjs/host/ChaynsHost.js +20 -39
  7. package/dist/cjs/host/module/ModuleHost.js +2 -20
  8. package/dist/cjs/host/module/utils/loadComponent.js +84 -42
  9. package/dist/cjs/index.js +8 -1
  10. package/dist/cjs/util/transferNestedFunctions.js +5 -2
  11. package/dist/cjs/util/url.js +1 -1
  12. package/dist/cjs/wrapper/AppWrapper.js +81 -43
  13. package/dist/cjs/wrapper/FrameWrapper.js +5 -1
  14. package/dist/cjs/wrapper/StaticChaynsApi.js +7 -0
  15. package/dist/esm/calls/index.js +8 -3
  16. package/dist/esm/components/ChaynsProvider.js +2 -5
  17. package/dist/esm/components/withHydrationBoundary.js +5 -9
  18. package/dist/esm/constants/languages.js +13 -0
  19. package/dist/esm/handler/DialogHandler.js +1 -2
  20. package/dist/esm/host/ChaynsHost.js +18 -39
  21. package/dist/esm/host/module/ModuleHost.js +2 -20
  22. package/dist/esm/host/module/utils/loadComponent.js +87 -44
  23. package/dist/esm/index.js +1 -1
  24. package/dist/esm/util/transferNestedFunctions.js +5 -2
  25. package/dist/esm/util/url.js +2 -2
  26. package/dist/esm/wrapper/AppWrapper.js +85 -45
  27. package/dist/esm/wrapper/FrameWrapper.js +5 -1
  28. package/dist/esm/wrapper/StaticChaynsApi.js +7 -0
  29. package/dist/types/calls/index.d.ts +5 -1
  30. package/dist/types/components/withHydrationBoundary.d.ts +1 -1
  31. package/dist/types/constants/languages.d.ts +12 -0
  32. package/dist/types/handler/DialogHandler.d.ts +9 -3
  33. package/dist/types/hooks/useCurrentPage.d.ts +4 -1
  34. package/dist/types/hooks/useCustomData.d.ts +1 -1
  35. package/dist/types/host/ChaynsHost.d.ts +0 -1
  36. package/dist/types/host/module/ModuleHost.d.ts +1 -0
  37. package/dist/types/host/module/utils/loadComponent.d.ts +3 -1
  38. package/dist/types/index.d.ts +1 -1
  39. package/dist/types/types/IChaynsReact.d.ts +42 -8
  40. package/dist/types/wrapper/AppWrapper.d.ts +0 -3
  41. package/dist/types/wrapper/StaticChaynsApi.d.ts +7 -0
  42. package/package.json +2 -2
@@ -12,6 +12,7 @@ var _deviceHelper = _interopRequireWildcard(require("../util/deviceHelper"));
12
12
  var _getUserInfo = _interopRequireDefault(require("../calls/getUserInfo"));
13
13
  var _sendMessage = require("../calls/sendMessage");
14
14
  var _apiListenerHelper = require("../helper/apiListenerHelper");
15
+ var _languages = require("../constants/languages");
15
16
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
16
17
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
17
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -26,13 +27,15 @@ class AppWrapper {
26
27
  var _window, _colorMode, _window2, _AppInfo$TappSelected;
27
28
  const {
28
29
  AppInfo,
29
- AppUser
30
+ AppUser,
31
+ Device
30
32
  } = retVal;
31
33
  this.accessToken = AppUser.TobitAccessToken;
32
34
  const urlParams = new URLSearchParams(location.search);
33
35
  const urlParamsLowerCase = new URLSearchParams(location.search.toLowerCase());
34
36
  let tappId = urlParamsLowerCase.get('tappid');
35
37
  let colorMode = urlParamsLowerCase.get('colormode');
38
+ let color = AppInfo.color;
36
39
  if (colorMode) {
37
40
  try {
38
41
  colorMode = Number.parseInt(colorMode, 10);
@@ -45,6 +48,24 @@ class AppWrapper {
45
48
  // ignore
46
49
  }
47
50
  }
51
+ let language = AppInfo.Language;
52
+ if (!language) {
53
+ language = _languages.DeviceLanguage[Number.parseInt(Device === null || Device === void 0 ? void 0 : Device.LanguageID, 10)] || 'de';
54
+ }
55
+ if (!color && urlParamsLowerCase.has('color')) {
56
+ color = urlParamsLowerCase.get('color');
57
+ if (!color.startsWith('#')) {
58
+ color = `#${color}`;
59
+ }
60
+ }
61
+ let userId = AppUser.TobitUserID;
62
+ if (typeof userId === 'string') {
63
+ try {
64
+ userId = Number.parseInt(userId, 10);
65
+ } catch {
66
+ // ignore
67
+ }
68
+ }
48
69
  return {
49
70
  device: (0, _deviceHelper.default)(navigator.userAgent, 'image/webp'),
50
71
  environment: {
@@ -52,12 +73,11 @@ class AppWrapper {
52
73
  runtimeEnvironment: _IChaynsReact.RuntimeEnviroment.Unknown
53
74
  },
54
75
  language: {
55
- site: AppInfo.Language,
76
+ site: language,
56
77
  translation: null,
57
- device: AppInfo.Language,
58
- active: AppInfo.Language
78
+ device: language,
79
+ active: language
59
80
  },
60
- // ToDo: Find better way to detect
61
81
  site: {
62
82
  id: AppInfo.SiteID,
63
83
  locationId: AppInfo.LocationID,
@@ -73,7 +93,7 @@ class AppWrapper {
73
93
  },
74
94
  title: AppInfo.Title,
75
95
  colorMode: (_colorMode = colorMode) !== null && _colorMode !== void 0 ? _colorMode : AppInfo.colorMode,
76
- color: AppInfo.color,
96
+ color,
77
97
  domain: AppInfo.domain,
78
98
  font: {
79
99
  id: _IChaynsReact.Font.Roboto,
@@ -89,14 +109,14 @@ class AppWrapper {
89
109
  firstName: AppUser.FirstName,
90
110
  lastName: AppUser.LastName,
91
111
  gender: _IChaynsReact.Gender.Unknown,
92
- userId: AppUser.TobitUserID,
112
+ userId: userId,
93
113
  personId: AppUser.PersonID,
94
114
  uacGroups: []
95
115
  },
96
116
  customData: null,
97
117
  isAdminModeActive: AppUser.AdminMode,
98
118
  currentPage: {
99
- id: ((_AppInfo$TappSelected = AppInfo.TappSelected) === null || _AppInfo$TappSelected === void 0 ? void 0 : _AppInfo$TappSelected.TappID) || tappId,
119
+ id: tappId || ((_AppInfo$TappSelected = AppInfo.TappSelected) === null || _AppInfo$TappSelected === void 0 ? void 0 : _AppInfo$TappSelected.TappID),
100
120
  siteId: AppInfo.SiteID
101
121
  },
102
122
  pages: AppInfo.Tapps.map(x => ({
@@ -116,12 +136,6 @@ class AppWrapper {
116
136
  notImplemented(call) {
117
137
  console.warn(`call ${call} not implement in app`);
118
138
  }
119
- dispatchDialogChange(detail) {
120
- this.dialogs = detail;
121
- this.dialogEventTarget.dispatchEvent(new CustomEvent('change', {
122
- detail
123
- }));
124
- }
125
139
  counter = 0;
126
140
  appCall(action, value = {}, {
127
141
  callback,
@@ -313,7 +327,7 @@ class AppWrapper {
313
327
  (0, _appCall.default)(callObj);
314
328
  },
315
329
  login: async (value, callback, closeCallback) => {
316
- const res = await this.appCall({}, callback);
330
+ const res = await this.appCall(54, value);
317
331
  return {
318
332
  loginState: res === null || res === void 0 ? void 0 : res.loginState
319
333
  };
@@ -365,7 +379,8 @@ class AppWrapper {
365
379
  shouldRemove
366
380
  } = (0, _apiListenerHelper.removeApiListener)('geoLocationListener', id);
367
381
  if (shouldRemove) {
368
- // App does not support removal of request geo location call with permanent true which makes this a no-op
382
+ // App does not support removal of request geo location call with permanent true which makes this a
383
+ // no-op
369
384
  }
370
385
  },
371
386
  removeScrollListener: async id => {
@@ -520,51 +535,74 @@ class AppWrapper {
520
535
  });
521
536
  },
522
537
  createDialog: config => {
523
- return new _DialogHandler.default(config, this.functions.openDialog, this.functions.closeDialog);
538
+ return new _DialogHandler.default(config, this.functions.openDialog, this.functions.closeDialog, this.functions.dispatchEventToDialogClient, this.functions.addDialogClientEventListener);
524
539
  },
525
540
  openDialog: async (config, callback) => {
526
541
  const currentDialogId = appWrapperDialogId++;
527
- const eventTarget = new EventTarget();
528
- const resolve = result => {
542
+ this.appCall(184, {
543
+ dialogContent: {
544
+ apiVersion: 5,
545
+ config
546
+ },
547
+ externalDialogUrl: 'https://tapp.chayns-static.space/api/dialog-v2/v1/index.html'
548
+ }, {
549
+ awaitResult: true
550
+ }).then(result => {
529
551
  callback(result);
530
- this.dispatchDialogChange(this.dialogs.filter(x => x.dialogId !== currentDialogId));
531
- };
532
- this.dispatchDialogChange([...this.dialogs, {
533
- config,
534
- resolve,
535
- dialogId: currentDialogId,
536
- eventTarget
537
- }]);
552
+ });
538
553
  return currentDialogId;
539
554
  },
540
- closeDialog: dialogId => {
555
+ closeDialog: (dialogId, result, buttonType = -1) => {
541
556
  const dialog = this.dialogs.find(x => x.dialogId === dialogId);
542
557
  if (dialog) {
543
558
  dialog.resolve({
544
- buttonType: -1
559
+ buttonType,
560
+ result
545
561
  });
546
562
  }
563
+ },
564
+ dispatchEventToDialogClient: () => this.notImplemented('dispatchEventToDialogClient'),
565
+ addDialogClientEventListener: () => this.notImplemented('addDialogClientEventListener'),
566
+ addAnonymousAccount: async () => {
567
+ return this.appCall(302);
547
568
  }
548
569
  };
549
570
  dialogs = [];
550
- dialogEventTarget = new EventTarget();
551
- getDialogEventTarget() {
552
- return this.dialogEventTarget;
553
- }
554
571
  async init() {
555
572
  this.values = this.mapOldApiToNew(await this.appCall(18));
556
- const callbackName = `chaynsApiV5Callback_${this.counter++}`;
557
- window.disablev4AccessTokenChangeListener = true;
558
- window[callbackName] = ({
559
- retVal: value
560
- }) => {
561
- this.mapOldApiToNew(value);
562
- };
563
573
  this.appCall(66, {
564
- enabled: true,
565
- callback: callbackName
574
+ enabled: true
566
575
  }, {
567
- awaitResult: false
576
+ callback: async () => {
577
+ this.values = this.mapOldApiToNew(await this.appCall(18));
578
+ document.dispatchEvent(new CustomEvent('chayns_api_data', {
579
+ detail: {
580
+ type: 'user',
581
+ value: this.values.user
582
+ }
583
+ }));
584
+ },
585
+ awaitResult: true
586
+ });
587
+ window.disablev4DesignSettingsChangeListener = true;
588
+ this.appCall(254, {
589
+ enabled: true
590
+ }, {
591
+ callback: ({
592
+ colorMode
593
+ }) => {
594
+ this.values.site = {
595
+ ...this.values.site,
596
+ colorMode
597
+ };
598
+ document.dispatchEvent(new CustomEvent('chayns_api_data', {
599
+ detail: {
600
+ type: 'site',
601
+ value: this.values.site
602
+ }
603
+ }));
604
+ },
605
+ awaitResult: true
568
606
  });
569
607
  return undefined;
570
608
  }
@@ -296,7 +296,11 @@ class FrameWrapper {
296
296
  // this.exposedFunctions.removeDialogHostEventListener(0);
297
297
  }
298
298
  },
299
- removeDialogClientEventListener: async () => {}
299
+ removeDialogClientEventListener: async () => {},
300
+ addAnonymousAccount: async () => {
301
+ if (!this.initialized) await this.ready;
302
+ return this.exposedFunctions.addAnonymousAccount();
303
+ }
300
304
  };
301
305
  initialized = false;
302
306
  constructor() {
@@ -17,6 +17,13 @@ class StaticChaynsApi {
17
17
  this[k] = v;
18
18
  });
19
19
  }
20
+ getUser = () => this._wrapper.values.user;
20
21
  getSite = () => this._wrapper.values.site;
22
+ getCurrentPage = () => this._wrapper.values.currentPage;
23
+ getDevice = () => this._wrapper.values.device;
24
+ getLanguage = () => this._wrapper.values.language;
25
+ getParameters = () => this._wrapper.values.parameters;
26
+ getPages = () => this._wrapper.values.pages;
27
+ getEnvironment = () => this._wrapper.values.environment;
21
28
  }
22
29
  var _default = exports.default = StaticChaynsApi;
@@ -282,18 +282,23 @@ export const storageSetItem = function () {
282
282
  export const vibrate = function () {
283
283
  return moduleWrapper.current.functions.vibrate(...arguments);
284
284
  };
285
+
285
286
  /**
286
287
  * This method creates a dialog
287
288
  */
288
- export const createDialog = function () {
289
- return moduleWrapper.current.functions.createDialog(...arguments);
290
- };
289
+ // @ts-ignore
290
+ export const createDialog = config => moduleWrapper.current.functions.createDialog(config);
291
291
  /**
292
292
  * Displays an overlay
293
293
  */
294
294
  export const setOverlay = function () {
295
295
  return moduleWrapper.current.functions.setOverlay(...arguments);
296
296
  };
297
+
298
+ /**
299
+ * Generates a temp accesstoken, only valid for short period of time (~3 days), works only when no user is logged in
300
+ */
301
+ export const addAnonymousAccount = () => moduleWrapper.current.functions.addAnonymousAccount();
297
302
  /**
298
303
  * Returns user information, only when user is logged in
299
304
  * @category User functions
@@ -7,7 +7,6 @@ import { FrameWrapper } from '../wrapper/FrameWrapper';
7
7
  import { ModuleFederationWrapper } from '../wrapper/ModuleFederationWrapper';
8
8
  import { SsrWrapper } from '../wrapper/SsrWrapper';
9
9
  import { ChaynsContext, ChaynsFunctionsContext } from './ChaynsContext';
10
- import AppDialogWrapper from './AppDialogWrapper';
11
10
  import { moduleWrapper } from './moduleWrapper';
12
11
 
13
12
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -30,7 +29,7 @@ const InitialDataProvider = /*#__PURE__*/React.memo(_ref => {
30
29
  });
31
30
  }, () => true);
32
31
  const ChaynsProvider = _ref2 => {
33
- var _customWrapper$curren, _customWrapper$curren2, _customWrapper$curren3, _customWrapper$curren4;
32
+ var _customWrapper$curren, _customWrapper$curren2, _customWrapper$curren3;
34
33
  let {
35
34
  children,
36
35
  data,
@@ -101,9 +100,7 @@ const ChaynsProvider = _ref2 => {
101
100
  value: state
102
101
  }, /*#__PURE__*/React.createElement(ChaynsFunctionsContext.Provider, {
103
102
  value: (_customWrapper$curren3 = customWrapper.current) === null || _customWrapper$curren3 === void 0 ? void 0 : _customWrapper$curren3.functions
104
- }, children, customWrapper.current instanceof AppWrapper ? /*#__PURE__*/React.createElement(AppDialogWrapper, {
105
- dialogEventTarget: (_customWrapper$curren4 = customWrapper.current) === null || _customWrapper$curren4 === void 0 ? void 0 : _customWrapper$curren4.getDialogEventTarget()
106
- }) : false)), /*#__PURE__*/React.createElement(InitialDataProvider, {
103
+ }, children)), /*#__PURE__*/React.createElement(InitialDataProvider, {
107
104
  data: state,
108
105
  renderedByServer: renderedByServer
109
106
  }));
@@ -15,6 +15,9 @@ const withHydrationBoundary = (Component, initializer, useHydrationId) => {
15
15
  throw new Error('hydration boundary was not given a id which is required');
16
16
  }
17
17
  const [store] = useState(() => {
18
+ if (!globalThis.window && id in value) {
19
+ return value[id];
20
+ }
18
21
  let initialValue = undefined;
19
22
  if (globalThis.window) {
20
23
  const htmlId = `__INITIAL_DATA_${id}__`;
@@ -23,16 +26,9 @@ const withHydrationBoundary = (Component, initializer, useHydrationId) => {
23
26
  initialValue = JSON.parse($elem.innerHTML);
24
27
  }
25
28
  }
26
- const s = initializer(initialValue);
29
+ const s = initializer(initialValue, id);
27
30
  if (!globalThis.window) {
28
- if (id in value) {
29
- console.warn(`Dehydration function for id "${id}" has been defined multiple times. This can have two reasons. The children cause suspension and therefor the hydration boundary has to mount from scratch again. You can avoid this by adding a Suspense around the children. The id is not unique. This has to be fixed or might cause hydration issues.`);
30
- }
31
- value[id] = {
32
- getState: s.getState,
33
- abort: s.abort,
34
- type: s.type
35
- };
31
+ value[id] = s;
36
32
  }
37
33
  return s;
38
34
  });
@@ -0,0 +1,13 @@
1
+ export let DeviceLanguage = /*#__PURE__*/function (DeviceLanguage) {
2
+ DeviceLanguage[DeviceLanguage["de"] = 1] = "de";
3
+ DeviceLanguage[DeviceLanguage["en"] = 2] = "en";
4
+ DeviceLanguage[DeviceLanguage["fr"] = 3] = "fr";
5
+ DeviceLanguage[DeviceLanguage["it"] = 4] = "it";
6
+ DeviceLanguage[DeviceLanguage["nl"] = 5] = "nl";
7
+ DeviceLanguage[DeviceLanguage["es"] = 6] = "es";
8
+ DeviceLanguage[DeviceLanguage["pt"] = 7] = "pt";
9
+ DeviceLanguage[DeviceLanguage["tr"] = 8] = "tr";
10
+ DeviceLanguage[DeviceLanguage["pl"] = 9] = "pl";
11
+ DeviceLanguage[DeviceLanguage["uk"] = 10] = "uk";
12
+ return DeviceLanguage;
13
+ }({});
@@ -4,7 +4,6 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4
4
  export default class DialogHandler {
5
5
  constructor(config, open, close, dispatchEvent, addDataListener) {
6
6
  _defineProperty(this, "isOpen", false);
7
- _defineProperty(this, "result", undefined);
8
7
  _defineProperty(this, "listeners", []);
9
8
  this._open = open;
10
9
  this._close = close;
@@ -38,7 +37,7 @@ export default class DialogHandler {
38
37
  return;
39
38
  }
40
39
  this.isOpen = false;
41
- this._close(this.dialogId, data);
40
+ this._close(this.dialogId, data, buttonType);
42
41
  }
43
42
  dispatchEvent(data) {
44
43
  if (!this.isOpen) {
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { startTransition, useEffect, useState } from 'react';
2
2
  import HostIframe from './iframe/HostIframe';
3
3
  import ModuleHost from './module/ModuleHost';
4
4
  const ChaynsHost = _ref => {
@@ -9,7 +9,6 @@ const ChaynsHost = _ref => {
9
9
  src,
10
10
  iFrameRef = undefined,
11
11
  loadingComponent = undefined,
12
- children = undefined,
13
12
  system,
14
13
  // shallow data
15
14
  pages,
@@ -25,8 +24,23 @@ const ChaynsHost = _ref => {
25
24
  preventStagingReplacement,
26
25
  dialog
27
26
  } = _ref;
27
+ const [isVisible, setIsVisible] = useState(type !== 'client-module' && (type !== 'server-module' || !!(system !== null && system !== void 0 && system.serverUrl)));
28
+ useEffect(() => {
29
+ if (isVisible) return;
30
+ if (typeof startTransition === 'function') {
31
+ startTransition(() => {
32
+ setIsVisible(true);
33
+ });
34
+ } else {
35
+ setIsVisible(true);
36
+ }
37
+ }, []);
38
+ if (!isVisible) {
39
+ return null;
40
+ }
28
41
  switch (type) {
29
42
  case 'client-iframe':
43
+ case 'server-iframe':
30
44
  return /*#__PURE__*/React.createElement(HostIframe, {
31
45
  iFrameRef: iFrameRef,
32
46
  iFrameProps: iFrameProps,
@@ -38,6 +52,7 @@ const ChaynsHost = _ref => {
38
52
  currentPage: currentPage,
39
53
  functions: functions,
40
54
  src: src,
55
+ postForm: type === 'server-iframe',
41
56
  language: language,
42
57
  parameters: parameters,
43
58
  environment: environment,
@@ -46,6 +61,7 @@ const ChaynsHost = _ref => {
46
61
  dialog: dialog
47
62
  });
48
63
  case 'client-module':
64
+ case 'server-module':
49
65
  return /*#__PURE__*/React.createElement(ModuleHost, {
50
66
  system: system,
51
67
  pages: pages,
@@ -63,43 +79,6 @@ const ChaynsHost = _ref => {
63
79
  preventStagingReplacement: preventStagingReplacement,
64
80
  dialog: dialog
65
81
  });
66
- case 'server-iframe':
67
- return /*#__PURE__*/React.createElement(HostIframe, {
68
- iFrameRef: iFrameRef,
69
- iFrameProps: iFrameProps,
70
- pages: pages,
71
- isAdminModeActive: isAdminModeActive,
72
- site: site,
73
- user: user,
74
- device: device,
75
- currentPage: currentPage,
76
- functions: functions,
77
- src: src,
78
- postForm: true,
79
- language: language,
80
- parameters: parameters,
81
- environment: environment,
82
- customData: customData,
83
- preventStagingReplacement: preventStagingReplacement,
84
- dialog: dialog
85
- });
86
- case 'server-module':
87
- return /*#__PURE__*/React.createElement(ModuleHost, {
88
- system: system,
89
- pages: pages,
90
- isAdminModeActive: isAdminModeActive,
91
- site: site,
92
- user: user,
93
- device: device,
94
- currentPage: currentPage,
95
- functions: functions,
96
- language: language,
97
- parameters: parameters,
98
- customData: customData,
99
- environment: environment,
100
- preventStagingReplacement: preventStagingReplacement,
101
- dialog: dialog
102
- }, children);
103
82
  default:
104
83
  return null;
105
84
  }
@@ -1,32 +1,13 @@
1
- import { init } from '@module-federation/runtime';
2
1
  import React, { useMemo } from 'react';
3
- import ReactDOM from 'react-dom';
4
2
  import loadComponent from './utils/loadComponent';
5
3
  import { replaceStagingUrl } from "../../util/url";
6
- init({
7
- // @ts-expect-error will be set by chayns-toolkit via DefinePlugin
8
- name: process.env.__PACKAGE_NAME__,
9
- remotes: [],
10
- shared: {
11
- react: {
12
- version: React.version,
13
- scope: 'default',
14
- lib: () => React
15
- },
16
- 'react-dom': {
17
- version: ReactDOM.version,
18
- scope: 'default',
19
- lib: () => ReactDOM
20
- }
21
- }
22
- });
23
4
  const System = _ref => {
24
5
  let {
25
6
  system,
26
7
  fallback,
27
8
  ...props
28
9
  } = _ref;
29
- const Component = useMemo(() => loadComponent(system.scope, system.module, system.url, undefined, system.preventSingleton), [system.scope, system.module, system.url, system.preventSingleton]);
10
+ const Component = useMemo(() => loadComponent(system.scope, system.module, globalThis.window ? system.url : system.serverUrl, undefined, system.preventSingleton), [system.scope, system.module, system.url, system.serverUrl, system.preventSingleton]);
30
11
  return /*#__PURE__*/React.createElement(React.Suspense, {
31
12
  fallback: fallback || ''
32
13
  }, /*#__PURE__*/React.createElement(Component, props));
@@ -76,6 +57,7 @@ const ModuleHost = _ref2 => {
76
57
  system: {
77
58
  scope: system.scope,
78
59
  url: replaceStagingUrl(preventStagingReplacement, system.url, environment.buildEnvironment),
60
+ serverUrl: replaceStagingUrl(preventStagingReplacement, system.serverUrl, environment.buildEnvironment),
79
61
  module: system.module,
80
62
  preventSingleton: system.preventSingleton
81
63
  },
@@ -1,63 +1,106 @@
1
+ var _process$env$__PACKAG;
2
+ import ReactDOM from 'react-dom';
1
3
  import semver from 'semver';
2
4
  import React from 'react';
3
- import { loadRemote, registerRemotes, loadShareSync } from '@module-federation/runtime';
5
+ import { loadRemote, registerRemotes, loadShareSync, init } from '@module-federation/runtime';
4
6
  const registeredScopes = {};
5
- const dynamicMap = {};
6
- export default function loadComponent(scope, module, url) {
7
- let skipCompatMode = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
8
- let preventSingleton = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
9
- if (skipCompatMode) {
10
- console.warn('[chayns-api] skipCompatMode-option is deprecated and is set automatically now');
7
+ const moduleMap = {};
8
+ const componentMap = {};
9
+ init({
10
+ // will be set by chayns-toolkit via DefinePlugin
11
+ name: (_process$env$__PACKAG = process.env.__PACKAGE_NAME__) !== null && _process$env$__PACKAG !== void 0 ? _process$env$__PACKAG : '',
12
+ remotes: [],
13
+ shared: {
14
+ react: {
15
+ version: React.version,
16
+ scope: 'default',
17
+ lib: () => React
18
+ },
19
+ 'react-dom': {
20
+ version: ReactDOM.version,
21
+ scope: 'default',
22
+ lib: () => ReactDOM
23
+ }
11
24
  }
25
+ });
26
+ export const loadModule = function (scope, module, url) {
27
+ let preventSingleton = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
12
28
  if (registeredScopes[scope] !== url || preventSingleton) {
29
+ if (scope in registeredScopes) {
30
+ console.error(`[chayns-api] call registerRemote with force for scope ${scope}. url: ${url}`);
31
+ }
13
32
  registerRemotes([{
14
33
  name: scope,
15
34
  entry: url,
16
35
  alias: scope
17
36
  }], {
18
- force: scope in registeredScopes
37
+ force: scope in registeredScopes || preventSingleton
19
38
  });
20
39
  registeredScopes[scope] = url;
21
- dynamicMap[scope] = {};
40
+ moduleMap[scope] = {};
41
+ componentMap[scope] = {};
22
42
  }
23
- if (!(module in dynamicMap[scope])) {
43
+ if (!(module in moduleMap[scope])) {
24
44
  const path = `${scope}/${module.replace(/^\.\//, '')}`;
25
- dynamicMap[scope][module] = /*#__PURE__*/React.lazy(() => {
26
- return loadRemote(path).then(async Module => {
27
- // semantically equals skipCompatMode
28
- if (typeof Module.default === 'function') {
29
- return Module;
30
- }
31
- const hostVersion = semver.minVersion(React.version);
32
- const {
33
- requiredVersion,
34
- environment
35
- } = Module.default;
36
- const shareScopes = await new Promise(resolve => {
37
- loadShareSync('react', {
38
- resolver: shareOptions => {
39
- resolve(shareOptions);
40
- return shareOptions[0];
41
- }
42
- });
43
- });
44
- const matchReactVersion = requiredVersion && semver.satisfies(hostVersion, requiredVersion) && !shareScopes.some(t => {
45
- const {
46
- version,
47
- from
48
- } = t;
49
- return semver.gt(version, hostVersion) && semver.satisfies(version, requiredVersion) || scope === from.split('-').join('_');
45
+ const promise = loadRemote(path);
46
+ promise.catch(e => {
47
+ console.error("[chayns-api] Failed to load module", scope, url, e);
48
+ // causes registerRemote with force = true on next attempt to load the component which tries to load the component again
49
+ registeredScopes[scope] = '';
50
+ });
51
+ return promise;
52
+ }
53
+ return moduleMap[scope][module];
54
+ };
55
+ const loadComponent = function (scope, module, url) {
56
+ let skipCompatMode = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
57
+ let preventSingleton = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
58
+ if (skipCompatMode) {
59
+ console.warn('[chayns-api] skipCompatMode-option is deprecated and is set automatically now');
60
+ }
61
+ if (!componentMap[scope]) {
62
+ componentMap[scope] = {};
63
+ }
64
+ if (!(module in componentMap[scope])) {
65
+ const promise = loadModule(scope, module, url, preventSingleton).then(async Module => {
66
+ if (typeof Module.default === 'function') {
67
+ return Module;
68
+ }
69
+ const hostVersion = semver.minVersion(React.version);
70
+ const {
71
+ requiredVersion,
72
+ environment
73
+ } = Module.default;
74
+ const shareScopes = await new Promise(resolve => {
75
+ loadShareSync('react', {
76
+ resolver: shareOptions => {
77
+ resolve(shareOptions);
78
+ return shareOptions[0];
79
+ }
50
80
  });
51
- if (!matchReactVersion || environment !== 'production' || process.env.NODE_ENV === 'development') {
52
- return {
53
- default: Module.default.CompatComponent
54
- };
55
- }
81
+ });
82
+ const matchReactVersion = requiredVersion && semver.satisfies(hostVersion, requiredVersion) && !shareScopes.some(_ref => {
83
+ let {
84
+ version,
85
+ from
86
+ } = _ref;
87
+ return semver.gt(version, hostVersion) && semver.satisfies(version, requiredVersion) || scope === from.split('-').join('_');
88
+ });
89
+ if (!matchReactVersion || environment !== 'production' || process.env.NODE_ENV === 'development') {
56
90
  return {
57
- default: Module.default.Component
91
+ default: Module.default.CompatComponent
58
92
  };
59
- });
93
+ }
94
+ return {
95
+ default: Module.default.Component
96
+ };
97
+ });
98
+ promise.catch(e => {
99
+ console.error("[chayns-api] Failed to load component", scope, url, e);
100
+ delete componentMap[scope][module];
60
101
  });
102
+ componentMap[scope][module] = /*#__PURE__*/React.lazy(() => promise);
61
103
  }
62
- return dynamicMap[scope][module];
63
- }
104
+ return componentMap[scope][module];
105
+ };
106
+ export default loadComponent;
package/dist/esm/index.js CHANGED
@@ -11,7 +11,7 @@ export * from './components/withCompatMode';
11
11
  export * from './constants';
12
12
  export { default as withHydrationBoundary } from './components/withHydrationBoundary';
13
13
  export { default as StaticChaynsApi } from './wrapper/StaticChaynsApi';
14
- export { default as loadComponent } from './host/module/utils/loadComponent';
14
+ export { default as loadComponent, loadModule } from './host/module/utils/loadComponent';
15
15
  export { default as DialogHandler } from './handler/DialogHandler';
16
16
  import * as _dialog from './calls/dialogs/index';
17
17
  export { _dialog as dialog };