@servicetitan/web-components 24.1.3 → 24.2.1

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 (39) hide show
  1. package/dist/delayed.d.ts +6 -0
  2. package/dist/delayed.d.ts.map +1 -0
  3. package/dist/delayed.js +12 -0
  4. package/dist/delayed.js.map +1 -0
  5. package/dist/loader.d.ts +2 -0
  6. package/dist/loader.d.ts.map +1 -1
  7. package/dist/loader.js +32 -16
  8. package/dist/loader.js.map +1 -1
  9. package/dist/utils/get-bundle-info.d.ts +1 -0
  10. package/dist/utils/get-bundle-info.d.ts.map +1 -1
  11. package/dist/utils/get-bundle-info.js +2 -0
  12. package/dist/utils/get-bundle-info.js.map +1 -1
  13. package/dist/utils/get-mfe-has-unique-chunk-namespace.d.ts +3 -0
  14. package/dist/utils/get-mfe-has-unique-chunk-namespace.d.ts.map +1 -0
  15. package/dist/utils/get-mfe-has-unique-chunk-namespace.js +12 -0
  16. package/dist/utils/get-mfe-has-unique-chunk-namespace.js.map +1 -0
  17. package/dist/utils/index.d.ts +1 -0
  18. package/dist/utils/index.d.ts.map +1 -1
  19. package/dist/utils/index.js +1 -0
  20. package/dist/utils/index.js.map +1 -1
  21. package/dist/utils/ttl-cache.d.ts +17 -0
  22. package/dist/utils/ttl-cache.d.ts.map +1 -0
  23. package/dist/utils/ttl-cache.js +65 -0
  24. package/dist/utils/ttl-cache.js.map +1 -0
  25. package/dist/utils/validate-bundle-info.d.ts +3 -1
  26. package/dist/utils/validate-bundle-info.d.ts.map +1 -1
  27. package/dist/utils/validate-bundle-info.js +15 -4
  28. package/dist/utils/validate-bundle-info.js.map +1 -1
  29. package/package.json +8 -9
  30. package/src/__tests__/delayed.test.tsx +50 -0
  31. package/src/__tests__/loader.test.tsx +143 -23
  32. package/src/delayed.tsx +18 -0
  33. package/src/loader.tsx +57 -24
  34. package/src/utils/__tests__/ttl-cache.test.ts +98 -0
  35. package/src/utils/get-bundle-info.ts +2 -0
  36. package/src/utils/get-mfe-has-unique-chunk-namespace.ts +14 -0
  37. package/src/utils/index.ts +1 -0
  38. package/src/utils/ttl-cache.ts +64 -0
  39. package/src/utils/validate-bundle-info.ts +21 -4
@@ -0,0 +1,6 @@
1
+ import { FC, PropsWithChildren } from 'react';
2
+ export type DelayedProps = PropsWithChildren<{
3
+ delayMs?: number;
4
+ }>;
5
+ export declare const Delayed: FC<DelayedProps>;
6
+ //# sourceMappingURL=delayed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delayed.d.ts","sourceRoot":"","sources":["../src/delayed.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAuB,MAAM,OAAO,CAAC;AAEnE,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC,YAAY,CAWpC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { useEffect, useState } from 'react';
2
+ export const Delayed = ({ delayMs = 200, children }) => {
3
+ const [timedOut, setTimedOut] = useState(delayMs <= 0);
4
+ useEffect(() => {
5
+ if (delayMs > 0) {
6
+ const timer = setTimeout(() => setTimedOut(true), delayMs);
7
+ return () => clearTimeout(timer);
8
+ }
9
+ }, [delayMs]);
10
+ return timedOut ? children : null;
11
+ };
12
+ //# sourceMappingURL=delayed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delayed.js","sourceRoot":"","sources":["../src/delayed.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyB,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAMnE,MAAM,CAAC,MAAM,OAAO,GAAqB,CAAC,EAAE,OAAO,GAAG,GAAG,EAAE,QAAQ,EAAgB,EAAE,EAAE;IACnF,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;IAEvD,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YACd,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;YAC3D,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;IACL,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC,CAAC"}
package/dist/loader.d.ts CHANGED
@@ -11,9 +11,11 @@ export interface LoaderProps<T> {
11
11
  data?: MFEContextData<T>;
12
12
  basename?: string;
13
13
  loadingFallback?: FallbackNode;
14
+ loadingFallbackDelayed?: boolean;
14
15
  errorFallback?: FallbackNode;
15
16
  className?: string;
16
17
  retries?: number;
18
+ cache?: boolean | number;
17
19
  onRequestError?(error: GetJsonError): boolean;
18
20
  }
19
21
  export type LoaderDataProps = Pick<LoaderProps<{}>, 'data' | 'className'> & {
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEH,SAAS,EAOZ,MAAM,OAAO,CAAC;AAKf,OAAO,EAGH,YAAY,EAEf,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAgC,MAAM,aAAa,CAAC;AAIrE,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;AAEjC,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;AAEzD,MAAM,WAAW,WAAW,CAAC,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uHAAuH;IACvH,IAAI,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,YAAY,CAAC;IAC/B,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC;CACjD;AAED,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,GAAG;IACxE,eAAe,EAAE,MAAM,GAAG,CAAC,OAAO,CAAC;CACtC,CAAC;AAEF,eAAO,MAAM,MAAM,sGAyDjB,CAAC"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEH,SAAS,EAOZ,MAAM,OAAO,CAAC;AAKf,OAAO,EAGH,YAAY,EAEf,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAgC,MAAM,aAAa,CAAC;AAWrE,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;AAEjC,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;AAEzD,MAAM,WAAW,WAAW,CAAC,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uHAAuH;IACvH,IAAI,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,YAAY,CAAC;IAC/B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,cAAc,CAAC,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC;CACjD;AAED,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,GAAG;IACxE,eAAe,EAAE,MAAM,GAAG,CAAC,OAAO,CAAC;CACtC,CAAC;AAEF,eAAO,MAAM,MAAM,sGA4DjB,CAAC"}
package/dist/loader.js CHANGED
@@ -13,19 +13,22 @@ import { ErrorBoundary } from '@servicetitan/error-boundary';
13
13
  import { Log } from '@servicetitan/log-service';
14
14
  import { useOptionalDependencies } from '@servicetitan/react-ioc';
15
15
  import { EXPOSED_DEPENDENCIES_TOKEN, useCancelation, } from './common';
16
+ import { Delayed } from './delayed';
16
17
  import { EVENT_BUS_TOKEN, useEventBus } from './event-bus';
17
18
  import { EXPOSED_DEPENDENCIES } from './globals';
18
- import { getBundleInfo, validateBundleInfo, loadScripts, webComponent } from './utils';
19
+ import { TtlCache, getBundleInfo, validateBundleInfo, loadScripts, webComponent, } from './utils';
19
20
  export const Loader = forwardRef((props, ref) => {
20
21
  var _a;
21
- const { basename, fallbackSrc, onRequestError, retries, src } = props;
22
+ const { cache = true, basename, fallbackSrc, onRequestError, retries, src } = props;
23
+ const { loadingFallback, loadingFallbackDelayed = true } = props;
22
24
  const bus = useEventBus();
23
25
  const [logService, exposedDependencies = EXPOSED_DEPENDENCIES, eventBus = bus] = useOptionalDependencies(Log, EXPOSED_DEPENDENCIES_TOKEN, EVENT_BUS_TOKEN);
24
26
  const cancelation = useCancelation();
25
- const LoadingFallback = useMemo(() => getFallback(props.loadingFallback, 'Loading...'), [props.loadingFallback]);
27
+ const LoadingFallback = useMemo(() => getFallback(loadingFallback, 'Loading...', { delayed: loadingFallbackDelayed }), [loadingFallback, loadingFallbackDelayed]);
26
28
  const ErrorFallback = useMemo(() => getFallback(props.errorFallback, 'Something went wrong'), [props.errorFallback]);
27
29
  const Loader = useMemo(() => lazyLoader({
28
30
  basename,
31
+ cache,
29
32
  cancelation,
30
33
  exposedDependencies,
31
34
  eventBus,
@@ -36,6 +39,7 @@ export const Loader = forwardRef((props, ref) => {
36
39
  src,
37
40
  }), [
38
41
  basename,
42
+ cache,
39
43
  cancelation,
40
44
  exposedDependencies,
41
45
  eventBus,
@@ -62,20 +66,29 @@ function lazyLoader(props) {
62
66
  }
63
67
  function lazyWebComponent(props) {
64
68
  const { basename, cancelation, exposedDependencies, eventBus, fallbackSrc, logService, onRequestError, retries, src, } = props;
69
+ let { cache } = props;
65
70
  return lazy(() => __awaiter(this, void 0, void 0, function* () {
66
- let bundleInfo;
67
- try {
68
- bundleInfo = yield getBundleInfo(src, fallbackSrc, exposedDependencies, cancelation.signal, retries, onRequestError);
69
- }
70
- catch (e) {
71
- if (cancelation.signal.aborted) {
72
- return {
73
- default: () => null,
74
- };
71
+ let bundleInfo = cache ? bundleCache.get(src) : undefined;
72
+ if (!bundleInfo) {
73
+ try {
74
+ bundleInfo = yield getBundleInfo(src, fallbackSrc, exposedDependencies, cancelation.signal, retries, onRequestError);
75
+ }
76
+ catch (e) {
77
+ if (cancelation.signal.aborted) {
78
+ return {
79
+ default: () => null,
80
+ };
81
+ }
82
+ throw e;
83
+ }
84
+ if (cache === true && !bundleInfo.mfeHasUniqueChunkNamespace) {
85
+ cache = -1;
86
+ }
87
+ if (cache) {
88
+ bundleCache.set(src, bundleInfo, typeof cache === 'number' ? cache : undefined);
75
89
  }
76
- throw e;
90
+ validateBundleInfo(bundleInfo, { exposedDependencies, logService, packageName: src });
77
91
  }
78
- validateBundleInfo(bundleInfo, { logService, packageName: src });
79
92
  yield loadScripts(bundleInfo);
80
93
  return {
81
94
  default: webComponent({
@@ -88,7 +101,10 @@ function lazyWebComponent(props) {
88
101
  };
89
102
  }));
90
103
  }
91
- function getFallback(node, message) {
92
- return () => (node !== undefined ? node : _jsx("h2", { children: message }));
104
+ function getFallback(node, message, { delayed = false } = {}) {
105
+ const fallbackNode = node !== undefined ? node : _jsx("h2", { children: message });
106
+ return delayed ? () => _jsx(Delayed, { children: fallbackNode }) : () => fallbackNode;
93
107
  }
108
+ const MINUTE = 1000 * 60;
109
+ const bundleCache = new TtlCache({ ttlMs: 15 * MINUTE });
94
110
  //# sourceMappingURL=loader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.tsx"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ export type BundleInfo = Awaited<ReturnType<typeof getBundleInfo>>;
14
14
  export declare function getBundleInfo(mainPackageUrl: string, fallbackPackageUrl: string | undefined, exposedDependencies?: ExposedDependencies, signal?: AbortSignal, retries?: number, onRequestError?: (error: GetJsonError) => void): Promise<{
15
15
  disposer: () => void;
16
16
  mfeSupportsRerendering: boolean;
17
+ mfeHasUniqueChunkNamespace: boolean;
17
18
  mismatch: Record<string, {
18
19
  host: string;
19
20
  package: string;
@@ -1 +1 @@
1
- {"version":3,"file":"get-bundle-info.d.ts","sourceRoot":"","sources":["../../src/utils/get-bundle-info.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAW,YAAY,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,WAAW,EAAkB,MAAM,oBAAoB,CAAC;AAKjE,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACjD,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QAAC,EAAE,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACjE;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC;AAEnE,wBAAsB,aAAa,CAC/B,cAAc,EAAE,MAAM,EACtB,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,mBAAmB,GAAE,mBAAwB,EAC7C,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,MAAM,EAChB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI;;;;;;;;;GA+DjD"}
1
+ {"version":3,"file":"get-bundle-info.d.ts","sourceRoot":"","sources":["../../src/utils/get-bundle-info.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAW,YAAY,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,WAAW,EAAkB,MAAM,oBAAoB,CAAC;AAMjE,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACjD,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QAAC,EAAE,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACjE;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC;AAEnE,wBAAsB,aAAa,CAC/B,cAAc,EAAE,MAAM,EACtB,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,mBAAmB,GAAE,mBAAwB,EAC7C,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,MAAM,EAChB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI;;;;;;;;;;GAgEjD"}
@@ -14,6 +14,7 @@ import { getEntrypoints } from './get-entry-points';
14
14
  import { getMFESupportsRerendering } from './get-mfe-supports-rerendering';
15
15
  import { getVersionMismatches } from './get-version-mismatches';
16
16
  import { isVersionedUrl } from './is-versioned-url';
17
+ import { getMFEHasUniqueChunkNamespace } from './get-mfe-has-unique-chunk-namespace';
17
18
  export function getBundleInfo(mainPackageUrl_1, fallbackPackageUrl_1) {
18
19
  return __awaiter(this, arguments, void 0, function* (mainPackageUrl, fallbackPackageUrl, exposedDependencies = {}, signal, retries, onRequestError) {
19
20
  var _a;
@@ -65,6 +66,7 @@ export function getBundleInfo(mainPackageUrl_1, fallbackPackageUrl_1) {
65
66
  return {
66
67
  disposer,
67
68
  mfeSupportsRerendering: getMFESupportsRerendering(bundledWith, dependencies),
69
+ mfeHasUniqueChunkNamespace: getMFEHasUniqueChunkNamespace(bundledWith),
68
70
  mismatch: hasMismatch ? mismatch : undefined,
69
71
  urls,
70
72
  WebComponent: name,
@@ -1 +1 @@
1
- {"version":3,"file":"get-bundle-info.js","sourceRoot":"","sources":["../../src/utils/get-bundle-info.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"get-bundle-info.js","sourceRoot":"","sources":["../../src/utils/get-bundle-info.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Metadata } from './get-bundle-info';
2
+ export declare function getMFEHasUniqueChunkNamespace(bundledWith: Metadata['bundledWith']): boolean;
3
+ //# sourceMappingURL=get-mfe-has-unique-chunk-namespace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-mfe-has-unique-chunk-namespace.d.ts","sourceRoot":"","sources":["../../src/utils/get-mfe-has-unique-chunk-namespace.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG7C,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,QAAQ,CAAC,aAAa,CAAC,WAEjF"}
@@ -0,0 +1,12 @@
1
+ import semver from 'semver';
2
+ // Check if the MFE loads it's chunks into a unique global chunk namespace
3
+ export function getMFEHasUniqueChunkNamespace(bundledWith) {
4
+ return !!isSupportedVersion(bundledWith === null || bundledWith === void 0 ? void 0 : bundledWith['@servicetitan/startup']);
5
+ }
6
+ function isSupportedVersion(version) {
7
+ const minVersion = version && semver.minVersion(version);
8
+ if (minVersion) {
9
+ return semver.gte(minVersion, '27.2.0');
10
+ }
11
+ }
12
+ //# sourceMappingURL=get-mfe-has-unique-chunk-namespace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-mfe-has-unique-chunk-namespace.js","sourceRoot":"","sources":["../../src/utils/get-mfe-has-unique-chunk-namespace.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,0EAA0E;AAC1E,MAAM,UAAU,6BAA6B,CAAC,WAAoC;IAC9E,OAAO,CAAC,CAAC,kBAAkB,CAAC,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAG,uBAAuB,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAgB;IACxC,MAAM,UAAU,GAAG,OAAO,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IACzD,IAAI,UAAU,EAAE,CAAC;QACb,OAAO,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;AACL,CAAC"}
@@ -4,6 +4,7 @@ export * from './get-mfe-supports-rerendering';
4
4
  export * from './get-version-mismatches';
5
5
  export * from './is-versioned-url';
6
6
  export * from './load-scripts';
7
+ export * from './ttl-cache';
7
8
  export * from './validate-bundle-info';
8
9
  export * from './web-component';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC"}
@@ -4,6 +4,7 @@ export * from './get-mfe-supports-rerendering';
4
4
  export * from './get-version-mismatches';
5
5
  export * from './is-versioned-url';
6
6
  export * from './load-scripts';
7
+ export * from './ttl-cache';
7
8
  export * from './validate-bundle-info';
8
9
  export * from './web-component';
9
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface TtlCacheOptions {
2
+ ttlMs?: number;
3
+ }
4
+ export declare class TtlCache<T = any> {
5
+ private data;
6
+ private timers;
7
+ private ttl;
8
+ constructor({ ttlMs }?: TtlCacheOptions);
9
+ set(key: string, value: T, ttl?: number): void;
10
+ get(key: string): T | undefined;
11
+ has(key: string): boolean;
12
+ delete(key: string): void;
13
+ clear(): void;
14
+ private cancelTimeout;
15
+ private setTimeout;
16
+ }
17
+ //# sourceMappingURL=ttl-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ttl-cache.d.ts","sourceRoot":"","sources":["../../src/utils/ttl-cache.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,QAAQ,CAAC,CAAC,GAAG,GAAG;IACzB,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,MAAM,CAA6C;IAC3D,OAAO,CAAC,GAAG,CAAS;gBAER,EAAE,KAAmB,EAAE,GAAE,eAAoB;IAUzD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM;IAKvC,GAAG,CAAC,GAAG,EAAE,MAAM;IAIf,GAAG,CAAC,GAAG,EAAE,MAAM;IAIf,MAAM,CAAC,GAAG,EAAE,MAAM;IAKlB,KAAK;IAML,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,UAAU;CASrB"}
@@ -0,0 +1,65 @@
1
+ const MINUTE = 1000 * 60;
2
+ const DEFAULT_TTL = 5 * MINUTE;
3
+ export class TtlCache {
4
+ constructor({ ttlMs = DEFAULT_TTL } = {}) {
5
+ Object.defineProperty(this, "data", {
6
+ enumerable: true,
7
+ configurable: true,
8
+ writable: true,
9
+ value: void 0
10
+ });
11
+ Object.defineProperty(this, "timers", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: void 0
16
+ });
17
+ Object.defineProperty(this, "ttl", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: void 0
22
+ });
23
+ if (ttlMs < 0) {
24
+ throw new Error('default TTL must be zero or greater');
25
+ }
26
+ this.data = new Map();
27
+ this.timers = new Map();
28
+ this.ttl = ttlMs;
29
+ }
30
+ set(key, value, ttl) {
31
+ this.setTimeout(key, ttl !== null && ttl !== void 0 ? ttl : this.ttl);
32
+ this.data.set(key, value);
33
+ }
34
+ get(key) {
35
+ return this.data.get(key);
36
+ }
37
+ has(key) {
38
+ return this.data.has(key);
39
+ }
40
+ delete(key) {
41
+ this.cancelTimeout(key);
42
+ this.data.delete(key);
43
+ }
44
+ clear() {
45
+ this.data.clear();
46
+ this.timers.forEach(value => clearTimeout(value));
47
+ this.timers.clear();
48
+ }
49
+ cancelTimeout(key) {
50
+ const id = this.timers.get(key);
51
+ if (id) {
52
+ clearTimeout(id);
53
+ this.timers.delete(key);
54
+ }
55
+ }
56
+ setTimeout(key, ttl) {
57
+ this.cancelTimeout(key);
58
+ if (ttl < 0) {
59
+ return;
60
+ }
61
+ const id = setTimeout(() => this.delete(key), ttl);
62
+ this.timers.set(key, id);
63
+ }
64
+ }
65
+ //# sourceMappingURL=ttl-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ttl-cache.js","sourceRoot":"","sources":["../../src/utils/ttl-cache.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;AACzB,MAAM,WAAW,GAAG,CAAC,GAAG,MAAM,CAAC;AAM/B,MAAM,OAAO,QAAQ;IAKjB,YAAY,EAAE,KAAK,GAAG,WAAW,KAAsB,EAAE;QAJjD;;;;;WAAqB;QACrB;;;;;WAAmD;QACnD;;;;;WAAY;QAGhB,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAQ,EAAE,GAAY;QACnC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,aAAH,GAAG,cAAH,GAAG,GAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,GAAG,CAAC,GAAW;QACX,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,GAAG,CAAC,GAAW;QACX,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM,CAAC,GAAW;QACd,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAEO,aAAa,CAAC,GAAW;QAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,EAAE,EAAE,CAAC;YACL,YAAY,CAAC,EAAE,CAAC,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;IACL,CAAC;IAEO,UAAU,CAAC,GAAW,EAAE,GAAW;QACvC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YACV,OAAO;QACX,CAAC;QAED,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC7B,CAAC;CACJ"}
@@ -1,6 +1,8 @@
1
1
  import { Log } from '@servicetitan/log-service';
2
+ import { ExposedDependencies } from '../common';
2
3
  import { BundleInfo } from './get-bundle-info';
3
- export declare function validateBundleInfo({ mismatch }: BundleInfo, { logService, packageName }: {
4
+ export declare function validateBundleInfo({ mismatch }: BundleInfo, { exposedDependencies, logService, packageName, }: {
5
+ exposedDependencies?: ExposedDependencies;
4
6
  logService?: Log;
5
7
  packageName: string;
6
8
  }): void;
@@ -1 +1 @@
1
- {"version":3,"file":"validate-bundle-info.d.ts","sourceRoot":"","sources":["../../src/utils/validate-bundle-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,wBAAgB,kBAAkB,CAC9B,EAAE,QAAQ,EAAE,EAAE,UAAU,EACxB,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE;IAAE,UAAU,CAAC,EAAE,GAAG,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,QASzE"}
1
+ {"version":3,"file":"validate-bundle-info.d.ts","sourceRoot":"","sources":["../../src/utils/validate-bundle-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,wBAAgB,kBAAkB,CAC9B,EAAE,QAAQ,EAAE,EAAE,UAAU,EACxB,EACI,mBAAwB,EACxB,UAAU,EACV,WAAW,GACd,EAAE;IAAE,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAAC,UAAU,CAAC,EAAE,GAAG,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,QAqB1F"}
@@ -1,9 +1,20 @@
1
- export function validateBundleInfo({ mismatch }, { logService, packageName }) {
2
- if (mismatch) {
3
- logService === null || logService === void 0 ? void 0 : logService.warning({
1
+ export function validateBundleInfo({ mismatch }, { exposedDependencies = {}, logService, packageName, }) {
2
+ if (!mismatch || !logService) {
3
+ return;
4
+ }
5
+ const data = { package: packageName, dependencies: JSON.stringify(mismatch) };
6
+ if (Object.keys(exposedDependencies).length === 0) {
7
+ logService.warning({
8
+ category: 'MicroFrontends.NoExposedDependencies',
9
+ message: 'Cannot use light bundle because the host is not exposing dependencies or the list of shared dependencies is empty.',
10
+ data,
11
+ });
12
+ }
13
+ else {
14
+ logService.warning({
4
15
  category: 'MicroFrontends.DependenciesMismatch',
5
16
  message: 'Some of the package dependencies have incompatible versions.',
6
- data: { package: packageName, dependencies: JSON.stringify(mismatch) },
17
+ data,
7
18
  });
8
19
  }
9
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validate-bundle-info.js","sourceRoot":"","sources":["../../src/utils/validate-bundle-info.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,kBAAkB,CAC9B,EAAE,QAAQ,EAAc,EACxB,EAAE,UAAU,EAAE,WAAW,EAA6C;IAEtE,IAAI,QAAQ,EAAE,CAAC;QACX,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,OAAO,CAAC;YAChB,QAAQ,EAAE,qCAAqC;YAC/C,OAAO,EAAE,8DAA8D;YACvE,IAAI,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;SACzE,CAAC,CAAC;IACP,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"validate-bundle-info.js","sourceRoot":"","sources":["../../src/utils/validate-bundle-info.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,kBAAkB,CAC9B,EAAE,QAAQ,EAAc,EACxB,EACI,mBAAmB,GAAG,EAAE,EACxB,UAAU,EACV,WAAW,GACwE;IAEvF,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU,EAAE,CAAC;QAC3B,OAAO;IACX,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC9E,IAAI,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,UAAU,CAAC,OAAO,CAAC;YACf,QAAQ,EAAE,sCAAsC;YAChD,OAAO,EACH,oHAAoH;YACxH,IAAI;SACP,CAAC,CAAC;IACP,CAAC;SAAM,CAAC;QACJ,UAAU,CAAC,OAAO,CAAC;YACf,QAAQ,EAAE,qCAAqC;YAC/C,OAAO,EAAE,8DAA8D;YACvE,IAAI;SACP,CAAC,CAAC;IACP,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/web-components",
3
- "version": "24.1.3",
3
+ "version": "24.2.1",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,16 +15,16 @@
15
15
  "src"
16
16
  ],
17
17
  "dependencies": {
18
- "@servicetitan/error-boundary": "24.1.3",
18
+ "@servicetitan/error-boundary": "24.2.0",
19
19
  "lodash.get": "~4.4.2",
20
20
  "mitt": "~3.0.1",
21
21
  "semver": "~7.6.2"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@servicetitan/design-system": "~14.0.0",
25
- "@servicetitan/log-service": "24.1.3",
26
- "@servicetitan/react-ioc": "24.1.3",
27
- "@testing-library/dom": "^10.2.0",
25
+ "@servicetitan/log-service": "24.2.0",
26
+ "@servicetitan/react-ioc": "24.2.0",
27
+ "@testing-library/dom": "^10.3.1",
28
28
  "@testing-library/jest-dom": "^6.4.5",
29
29
  "@testing-library/react": "^16.0.0",
30
30
  "@types/history": "~4.7.10",
@@ -39,8 +39,8 @@
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@servicetitan/design-system": ">=12.6.2",
42
- "@servicetitan/log-service": "24.1.3",
43
- "@servicetitan/react-ioc": "24.1.3",
42
+ "@servicetitan/log-service": "24.2.0",
43
+ "@servicetitan/react-ioc": "24.2.0",
44
44
  "history": "~4.10.1",
45
45
  "react": ">=17.0.2",
46
46
  "react-dom": ">=17.0.2"
@@ -50,6 +50,5 @@
50
50
  },
51
51
  "cli": {
52
52
  "webpack": false
53
- },
54
- "gitHead": "8b7d1f1e3141d9691fd2bb93ca759dcc319a924c"
53
+ }
55
54
  }
@@ -0,0 +1,50 @@
1
+ import '@testing-library/jest-dom';
2
+ import { act, render, screen } from '@testing-library/react';
3
+
4
+ import { Delayed, DelayedProps } from '../delayed';
5
+
6
+ describe(`${Delayed.name}`, () => {
7
+ const content = 'foo';
8
+ let props: DelayedProps;
9
+
10
+ beforeEach(() => {
11
+ jest.useFakeTimers();
12
+ props = {};
13
+ });
14
+
15
+ const subject = () => render(<Delayed {...props}>{content}</Delayed>);
16
+
17
+ test('renders content after 200ms delay', () => {
18
+ subject();
19
+
20
+ act(() => jest.advanceTimersByTime(199));
21
+ expect(screen.queryByText(content)).not.toBeInTheDocument();
22
+
23
+ act(() => jest.advanceTimersByTime(1));
24
+ expect(screen.getByText(content)).toBeInTheDocument();
25
+ });
26
+
27
+ describe('with zero delay', () => {
28
+ beforeEach(() => (props.delayMs = 0));
29
+
30
+ test('renders content immediately', () => {
31
+ subject();
32
+
33
+ expect(screen.getByText(content)).toBeInTheDocument();
34
+ });
35
+ });
36
+
37
+ describe('with custom delay', () => {
38
+ beforeEach(() => (props.delayMs = 1000));
39
+
40
+ test('renders content after specified delay', () => {
41
+ subject();
42
+
43
+ act(() => jest.advanceTimersByTime(props.delayMs! - 1));
44
+ expect(screen.queryByText(content)).not.toBeInTheDocument();
45
+
46
+ act(() => jest.advanceTimersByTime(1));
47
+ expect(screen.queryByText(content)).toBeInTheDocument();
48
+ });
49
+ });
50
+ });
@@ -44,11 +44,7 @@ describe('[web-components] Loader', () => {
44
44
  let metadata: Metadata;
45
45
 
46
46
  function setStartupVersion(version: string | undefined) {
47
- if (!version) {
48
- metadata.bundledWith = undefined;
49
- } else {
50
- metadata.bundledWith = { '@servicetitan/startup': version };
51
- }
47
+ metadata.bundledWith = version ? { '@servicetitan/startup': version } : undefined;
52
48
  }
53
49
 
54
50
  beforeAll(() => {
@@ -103,8 +99,8 @@ describe('[web-components] Loader', () => {
103
99
  },
104
100
  },
105
101
  };
106
- setStartupVersion('22.14.0');
107
- props = { src: baseUrl };
102
+ setStartupVersion('27.2.0');
103
+ props = { src: baseUrl, cache: false };
108
104
  onloadRef = null;
109
105
  singletons = [];
110
106
  initializeGetJsonMockFns();
@@ -128,9 +124,10 @@ describe('[web-components] Loader', () => {
128
124
  return render(<Root />);
129
125
  }
130
126
 
131
- test('renders default loading fallback', () => {
127
+ test('renders default loading fallback', async () => {
132
128
  subject();
133
- expect(screen.getByText(/loading/i)).toBeInTheDocument();
129
+
130
+ await waitFor(() => expect(screen.getByText(/loading/i)).toBeInTheDocument());
134
131
  });
135
132
 
136
133
  describe('with ref parameter', () => {
@@ -162,37 +159,38 @@ describe('[web-components] Loader', () => {
162
159
  props.loadingFallback = <div>foo</div>;
163
160
  });
164
161
 
165
- test('renders provided loading fallback', () => {
162
+ test('renders provided loading fallback', async () => {
166
163
  subject();
167
- expect(screen.getByText('foo')).toBeInTheDocument();
164
+
165
+ await waitFor(() => expect(screen.getByText('foo')).toBeInTheDocument());
168
166
  });
169
167
 
170
168
  test('preserves component state when loading fallback is updated', () => {
171
169
  const renderResult = subject();
172
170
  expect(common.getJson).toHaveBeenCalledTimes(1);
171
+
173
172
  props.loadingFallback = <div>foo</div>;
174
173
  renderResult.rerender(<Root />);
174
+
175
175
  expect(common.getJson).toHaveBeenCalledTimes(1);
176
176
  });
177
177
  });
178
178
 
179
179
  describe('when the loadingFallback throws an error', () => {
180
180
  beforeEach(() => {
181
- // suppress console.error that appears in the test output
182
- jest.spyOn(console, 'error').mockImplementation(jest.fn);
181
+ jest.spyOn(console, 'error').mockImplementation(jest.fn); // suppress console output
183
182
  const ThrowError: FC = () => {
184
183
  throw new Error('woops');
185
184
  };
186
- props.loadingFallback = (
187
- <div>
188
- <ThrowError />
189
- </div>
190
- );
185
+ props.loadingFallback = <ThrowError />;
191
186
  });
192
187
 
193
- test('renders default error fallback', () => {
188
+ test('renders default error fallback', async () => {
194
189
  subject();
195
- expect(screen.getByText(/something went wrong/i)).toBeInTheDocument();
190
+
191
+ await waitFor(() =>
192
+ expect(screen.getByText(/something went wrong/i)).toBeInTheDocument()
193
+ );
196
194
  });
197
195
 
198
196
  describe('when an errorFallback is provided', () => {
@@ -200,13 +198,24 @@ describe('[web-components] Loader', () => {
200
198
  props.errorFallback = <div>bar</div>;
201
199
  });
202
200
 
203
- test('renders provided error fallback', () => {
201
+ test('renders provided error fallback', async () => {
204
202
  subject();
205
- expect(screen.getByText('bar')).toBeInTheDocument();
203
+
204
+ await waitFor(() => expect(screen.getByText('bar')).toBeInTheDocument());
206
205
  });
207
206
  });
208
207
  });
209
208
 
209
+ describe('when loadingFallback is not delayed', () => {
210
+ beforeEach(() => (props.loadingFallbackDelayed = false));
211
+
212
+ test('renders loading fallback immediately', () => {
213
+ subject();
214
+
215
+ expect(screen.getByText(/loading/i)).toBeInTheDocument();
216
+ });
217
+ });
218
+
210
219
  describe('when a script tag (with a webComponent data attr) for this bundle is in the DOM before Loader is rendered', () => {
211
220
  beforeEach(() => {
212
221
  const script = document.createElement('script');
@@ -637,6 +646,10 @@ describe('[web-components] Loader', () => {
637
646
 
638
647
  beforeEach(() => {
639
648
  jest.mocked(getVersionMismatches).mockReturnValue(mismatchedDeps);
649
+ singletons?.push({
650
+ provide: EXPOSED_DEPENDENCIES_TOKEN,
651
+ useValue: { foo: 'bar' },
652
+ });
640
653
  });
641
654
 
642
655
  itAddsJsEntrypointToWebComponent(
@@ -656,7 +669,7 @@ describe('[web-components] Loader', () => {
656
669
  singletons?.push({ provide: Log, useValue: logService });
657
670
  });
658
671
 
659
- test('logs a warning', async () => {
672
+ test('logs "mismatch" warning', async () => {
660
673
  await webComponentReadySetup();
661
674
 
662
675
  expect(logService.warning).toHaveBeenCalledWith(
@@ -669,6 +682,24 @@ describe('[web-components] Loader', () => {
669
682
  })
670
683
  );
671
684
  });
685
+
686
+ describe('when host exposes no dependencies', () => {
687
+ beforeEach(() => {
688
+ singletons = singletons?.filter(
689
+ ({ provide }: any) => provide !== EXPOSED_DEPENDENCIES_TOKEN
690
+ );
691
+ });
692
+
693
+ test('logs "no dependencies" warning', async () => {
694
+ await webComponentReadySetup();
695
+
696
+ expect(logService.warning).toHaveBeenCalledWith(
697
+ expect.objectContaining({
698
+ category: 'MicroFrontends.NoExposedDependencies',
699
+ })
700
+ );
701
+ });
702
+ });
672
703
  });
673
704
  });
674
705
  });
@@ -678,4 +709,93 @@ describe('[web-components] Loader', () => {
678
709
  expect(onloadRef).toBeNull();
679
710
  });
680
711
  });
712
+
713
+ describe('when cache is enabled', () => {
714
+ beforeAll(() => {
715
+ jest.useFakeTimers();
716
+ jest.spyOn(console, 'error').mockImplementation(jest.fn); // suppress "suspended resource finished loading inside a test" error
717
+ });
718
+
719
+ beforeEach(() => delete props.cache);
720
+
721
+ function preloadComponent({ id, cache }: { id?: string; cache?: boolean | number } = {}) {
722
+ if (id) {
723
+ props.src = `http://localhost/${id}`;
724
+ initializeGetJsonMockFns(props.src);
725
+ }
726
+ if (cache !== undefined) {
727
+ props.cache = cache;
728
+ }
729
+ subject();
730
+ jest.mocked(common.getJson).mockClear();
731
+ }
732
+
733
+ function itReloadsMetadataAfter(delay: number, description: string) {
734
+ test(`reloads metadata after ${description}`, () => {
735
+ act(() => jest.advanceTimersByTime(delay - 1));
736
+ subject();
737
+ expect(common.getJson).toHaveBeenCalledTimes(0);
738
+
739
+ act(() => jest.advanceTimersByTime(1));
740
+ subject();
741
+ expect(common.getJson).toHaveBeenCalledTimes(1);
742
+ });
743
+ }
744
+
745
+ function itNeverReloadsMetadata() {
746
+ test('never reloads metadata', () => {
747
+ jest.runOnlyPendingTimers();
748
+ subject();
749
+
750
+ expect(common.getJson).toHaveBeenCalledTimes(0);
751
+ });
752
+ }
753
+
754
+ describe('when component was previously loaded', () => {
755
+ beforeEach(() => preloadComponent({ id: 'mfe1' }));
756
+
757
+ test('uses cached metadata', () => {
758
+ subject();
759
+
760
+ expect(common.getJson).toHaveBeenCalledTimes(0);
761
+ });
762
+
763
+ itReloadsMetadataAfter(1000 * 60 * 15, 'fifteen minutes');
764
+ });
765
+
766
+ describe('when component has custom ttl', () => {
767
+ const customTtl = 1000 * 60; // one minute
768
+
769
+ beforeEach(() => preloadComponent({ id: 'mfe2', cache: customTtl }));
770
+
771
+ itReloadsMetadataAfter(customTtl, 'custom ttl');
772
+ });
773
+
774
+ describe('when component has indefinite ttl', () => {
775
+ beforeEach(() => preloadComponent({ id: 'mfe3', cache: -1 }));
776
+
777
+ itNeverReloadsMetadata();
778
+ });
779
+
780
+ describe('when component has zero ttl', () => {
781
+ beforeEach(() => preloadComponent({ id: 'mfe4', cache: 0 }));
782
+
783
+ test('always reloads metadata', () => {
784
+ subject();
785
+ expect(common.getJson).toHaveBeenCalledTimes(1);
786
+
787
+ subject();
788
+ expect(common.getJson).toHaveBeenCalledTimes(2);
789
+ });
790
+ });
791
+
792
+ describe("when mfe doesn't have unique chunk namespace", () => {
793
+ beforeEach(() => {
794
+ preloadComponent({ id: 'mfe5' });
795
+ setStartupVersion('27.1.1');
796
+ });
797
+
798
+ itNeverReloadsMetadata();
799
+ });
800
+ });
681
801
  });
@@ -0,0 +1,18 @@
1
+ import { FC, PropsWithChildren, useEffect, useState } from 'react';
2
+
3
+ export type DelayedProps = PropsWithChildren<{
4
+ delayMs?: number;
5
+ }>;
6
+
7
+ export const Delayed: FC<DelayedProps> = ({ delayMs = 200, children }: DelayedProps) => {
8
+ const [timedOut, setTimedOut] = useState(delayMs <= 0);
9
+
10
+ useEffect(() => {
11
+ if (delayMs > 0) {
12
+ const timer = setTimeout(() => setTimedOut(true), delayMs);
13
+ return () => clearTimeout(timer);
14
+ }
15
+ }, [delayMs]);
16
+
17
+ return timedOut ? children : null;
18
+ };
package/src/loader.tsx CHANGED
@@ -19,9 +19,17 @@ import {
19
19
  useCancelation,
20
20
  } from './common';
21
21
  import { MFEContextData } from './contexts/mfe-data-context';
22
+ import { Delayed } from './delayed';
22
23
  import { EventBus, EVENT_BUS_TOKEN, useEventBus } from './event-bus';
23
24
  import { EXPOSED_DEPENDENCIES } from './globals';
24
- import { BundleInfo, getBundleInfo, validateBundleInfo, loadScripts, webComponent } from './utils';
25
+ import {
26
+ BundleInfo,
27
+ TtlCache,
28
+ getBundleInfo,
29
+ validateBundleInfo,
30
+ loadScripts,
31
+ webComponent,
32
+ } from './utils';
25
33
 
26
34
  export type LoaderRef = EventBus;
27
35
 
@@ -34,9 +42,11 @@ export interface LoaderProps<T> {
34
42
  data?: MFEContextData<T>;
35
43
  basename?: string;
36
44
  loadingFallback?: FallbackNode;
45
+ loadingFallbackDelayed?: boolean;
37
46
  errorFallback?: FallbackNode;
38
47
  className?: string;
39
48
  retries?: number;
49
+ cache?: boolean | number;
40
50
  onRequestError?(error: GetJsonError): boolean;
41
51
  }
42
52
 
@@ -45,7 +55,8 @@ export type LoaderDataProps = Pick<LoaderProps<{}>, 'data' | 'className'> & {
45
55
  };
46
56
 
47
57
  export const Loader = forwardRef<LoaderRef, LoaderProps<{}>>((props, ref) => {
48
- const { basename, fallbackSrc, onRequestError, retries, src } = props;
58
+ const { cache = true, basename, fallbackSrc, onRequestError, retries, src } = props;
59
+ const { loadingFallback, loadingFallbackDelayed = true } = props;
49
60
 
50
61
  const bus = useEventBus();
51
62
  const [logService, exposedDependencies = EXPOSED_DEPENDENCIES, eventBus = bus] =
@@ -53,8 +64,8 @@ export const Loader = forwardRef<LoaderRef, LoaderProps<{}>>((props, ref) => {
53
64
  const cancelation = useCancelation();
54
65
 
55
66
  const LoadingFallback = useMemo(
56
- () => getFallback(props.loadingFallback, 'Loading...'),
57
- [props.loadingFallback]
67
+ () => getFallback(loadingFallback, 'Loading...', { delayed: loadingFallbackDelayed }),
68
+ [loadingFallback, loadingFallbackDelayed]
58
69
  );
59
70
 
60
71
  const ErrorFallback = useMemo(
@@ -66,6 +77,7 @@ export const Loader = forwardRef<LoaderRef, LoaderProps<{}>>((props, ref) => {
66
77
  () =>
67
78
  lazyLoader({
68
79
  basename,
80
+ cache,
69
81
  cancelation,
70
82
  exposedDependencies,
71
83
  eventBus,
@@ -77,6 +89,7 @@ export const Loader = forwardRef<LoaderRef, LoaderProps<{}>>((props, ref) => {
77
89
  }),
78
90
  [
79
91
  basename,
92
+ cache,
80
93
  cancelation,
81
94
  exposedDependencies,
82
95
  eventBus,
@@ -145,28 +158,40 @@ function lazyWebComponent(props: LazyLoaderProps) {
145
158
  src,
146
159
  } = props;
147
160
 
161
+ let { cache } = props;
162
+
148
163
  return lazy<(props: LoaderDataProps) => JSX.Element | null>(async () => {
149
- let bundleInfo: BundleInfo;
150
- try {
151
- bundleInfo = await getBundleInfo(
152
- src,
153
- fallbackSrc,
154
- exposedDependencies,
155
- cancelation.signal,
156
- retries,
157
- onRequestError
158
- );
159
- } catch (e) {
160
- if (cancelation.signal.aborted) {
161
- return {
162
- default: () => null,
163
- };
164
+ let bundleInfo: BundleInfo | undefined = cache ? bundleCache.get(src) : undefined;
165
+ if (!bundleInfo) {
166
+ try {
167
+ bundleInfo = await getBundleInfo(
168
+ src,
169
+ fallbackSrc,
170
+ exposedDependencies,
171
+ cancelation.signal,
172
+ retries,
173
+ onRequestError
174
+ );
175
+ } catch (e) {
176
+ if (cancelation.signal.aborted) {
177
+ return {
178
+ default: () => null,
179
+ };
180
+ }
181
+
182
+ throw e;
164
183
  }
165
184
 
166
- throw e;
167
- }
185
+ if (cache === true && !bundleInfo.mfeHasUniqueChunkNamespace) {
186
+ cache = -1;
187
+ }
188
+
189
+ if (cache) {
190
+ bundleCache.set(src, bundleInfo, typeof cache === 'number' ? cache : undefined);
191
+ }
168
192
 
169
- validateBundleInfo(bundleInfo, { logService, packageName: src });
193
+ validateBundleInfo(bundleInfo, { exposedDependencies, logService, packageName: src });
194
+ }
170
195
 
171
196
  await loadScripts(bundleInfo);
172
197
 
@@ -182,6 +207,14 @@ function lazyWebComponent(props: LazyLoaderProps) {
182
207
  });
183
208
  }
184
209
 
185
- function getFallback(node: FallbackNode | undefined, message: string) {
186
- return () => (node !== undefined ? (node as ReactElement) : <h2>{message}</h2>);
210
+ function getFallback(
211
+ node: FallbackNode | undefined,
212
+ message: string,
213
+ { delayed = false }: { delayed?: boolean } = {}
214
+ ) {
215
+ const fallbackNode = node !== undefined ? (node as ReactElement) : <h2>{message}</h2>;
216
+ return delayed ? () => <Delayed>{fallbackNode}</Delayed> : () => fallbackNode;
187
217
  }
218
+
219
+ const MINUTE = 1000 * 60;
220
+ const bundleCache = new TtlCache<BundleInfo>({ ttlMs: 15 * MINUTE });
@@ -0,0 +1,98 @@
1
+ import { TtlCache } from '../ttl-cache';
2
+
3
+ describe(`${TtlCache.name}`, () => {
4
+ const key = 'foo';
5
+ const value = 'bar';
6
+
7
+ let cache: TtlCache<string>;
8
+
9
+ beforeEach(() => {
10
+ jest.useFakeTimers();
11
+ cache = new TtlCache();
12
+ });
13
+
14
+ test('cache rejects invalid default ttl', () => {
15
+ expect(() => new TtlCache({ ttlMs: -1 })).toThrow();
16
+ });
17
+
18
+ describe('when cache omits key', () => {
19
+ test('has returns false', () => {
20
+ expect(cache.has(key)).toBe(false);
21
+ });
22
+
23
+ test('get returns undefined', () => {
24
+ expect(cache.get(key)).toBeUndefined();
25
+ });
26
+ });
27
+
28
+ describe('when cache contains key', () => {
29
+ const elements = {
30
+ [key]: value,
31
+ [`other-${key}`]: `other-${value}`,
32
+ };
33
+
34
+ beforeEach(() => {
35
+ Object.entries(elements).map(([key, value]) => cache.set(key, value));
36
+ });
37
+
38
+ test('has returns true', () => {
39
+ expect(cache.has(key)).toBe(true);
40
+ });
41
+
42
+ test('get returns value', () => {
43
+ expect(cache.get(key)).toBe(value);
44
+ });
45
+
46
+ test('set replaces value', () => {
47
+ const newValue = `new-${value}`;
48
+
49
+ cache.set(key, newValue);
50
+
51
+ expect(cache.get(key)).toBe(newValue);
52
+ });
53
+
54
+ test('delete removes key', () => {
55
+ cache.delete(key);
56
+
57
+ expect(cache.has(key)).toBe(false);
58
+ });
59
+
60
+ test('clear removes all keys', () => {
61
+ cache.clear();
62
+
63
+ Object.keys(elements).forEach(key => expect(cache.has(key)).toBe(false));
64
+ });
65
+
66
+ test('removes keys after five minutes', () => {
67
+ jest.advanceTimersByTime(1000 * 60 * 5 - 1);
68
+ Object.keys(elements).forEach(key => expect(cache.has(key)).toBe(true));
69
+
70
+ jest.advanceTimersByTime(1);
71
+ Object.keys(elements).forEach(key => expect(cache.has(key)).toBe(false));
72
+ });
73
+
74
+ describe('when key has custom ttl', () => {
75
+ const ttl = 1000 * 60 * 10;
76
+
77
+ beforeEach(() => cache.set(key, value, ttl));
78
+
79
+ test('removes key after custom ttl', () => {
80
+ jest.advanceTimersByTime(ttl - 1);
81
+ expect(cache.has(key)).toBe(true);
82
+
83
+ jest.advanceTimersByTime(1);
84
+ expect(cache.has(key)).toBe(false);
85
+ });
86
+ });
87
+
88
+ describe('when key has negative ttl', () => {
89
+ beforeEach(() => cache.set(key, value, -1));
90
+
91
+ test('never removes key', () => {
92
+ jest.runOnlyPendingTimers();
93
+
94
+ expect(cache.has(key)).toBe(true);
95
+ });
96
+ });
97
+ });
98
+ });
@@ -6,6 +6,7 @@ import { EntryPoints, getEntrypoints } from './get-entry-points';
6
6
  import { getMFESupportsRerendering } from './get-mfe-supports-rerendering';
7
7
  import { getVersionMismatches } from './get-version-mismatches';
8
8
  import { isVersionedUrl } from './is-versioned-url';
9
+ import { getMFEHasUniqueChunkNamespace } from './get-mfe-has-unique-chunk-namespace';
9
10
 
10
11
  export interface Metadata {
11
12
  name: string;
@@ -82,6 +83,7 @@ export async function getBundleInfo(
82
83
  return {
83
84
  disposer,
84
85
  mfeSupportsRerendering: getMFESupportsRerendering(bundledWith, dependencies),
86
+ mfeHasUniqueChunkNamespace: getMFEHasUniqueChunkNamespace(bundledWith),
85
87
  mismatch: hasMismatch ? mismatch : undefined,
86
88
  urls,
87
89
  WebComponent: name,
@@ -0,0 +1,14 @@
1
+ import semver from 'semver';
2
+ import { Metadata } from './get-bundle-info';
3
+
4
+ // Check if the MFE loads it's chunks into a unique global chunk namespace
5
+ export function getMFEHasUniqueChunkNamespace(bundledWith: Metadata['bundledWith']) {
6
+ return !!isSupportedVersion(bundledWith?.['@servicetitan/startup']);
7
+ }
8
+
9
+ function isSupportedVersion(version?: string) {
10
+ const minVersion = version && semver.minVersion(version);
11
+ if (minVersion) {
12
+ return semver.gte(minVersion, '27.2.0');
13
+ }
14
+ }
@@ -4,5 +4,6 @@ export * from './get-mfe-supports-rerendering';
4
4
  export * from './get-version-mismatches';
5
5
  export * from './is-versioned-url';
6
6
  export * from './load-scripts';
7
+ export * from './ttl-cache';
7
8
  export * from './validate-bundle-info';
8
9
  export * from './web-component';
@@ -0,0 +1,64 @@
1
+ const MINUTE = 1000 * 60;
2
+ const DEFAULT_TTL = 5 * MINUTE;
3
+
4
+ export interface TtlCacheOptions {
5
+ ttlMs?: number;
6
+ }
7
+
8
+ export class TtlCache<T = any> {
9
+ private data: Map<string, T>;
10
+ private timers: Map<string, ReturnType<typeof setTimeout>>;
11
+ private ttl: number;
12
+
13
+ constructor({ ttlMs = DEFAULT_TTL }: TtlCacheOptions = {}) {
14
+ if (ttlMs < 0) {
15
+ throw new Error('default TTL must be zero or greater');
16
+ }
17
+
18
+ this.data = new Map();
19
+ this.timers = new Map();
20
+ this.ttl = ttlMs;
21
+ }
22
+
23
+ set(key: string, value: T, ttl?: number) {
24
+ this.setTimeout(key, ttl ?? this.ttl);
25
+ this.data.set(key, value);
26
+ }
27
+
28
+ get(key: string) {
29
+ return this.data.get(key);
30
+ }
31
+
32
+ has(key: string) {
33
+ return this.data.has(key);
34
+ }
35
+
36
+ delete(key: string) {
37
+ this.cancelTimeout(key);
38
+ this.data.delete(key);
39
+ }
40
+
41
+ clear() {
42
+ this.data.clear();
43
+ this.timers.forEach(value => clearTimeout(value));
44
+ this.timers.clear();
45
+ }
46
+
47
+ private cancelTimeout(key: string) {
48
+ const id = this.timers.get(key);
49
+ if (id) {
50
+ clearTimeout(id);
51
+ this.timers.delete(key);
52
+ }
53
+ }
54
+
55
+ private setTimeout(key: string, ttl: number) {
56
+ this.cancelTimeout(key);
57
+ if (ttl < 0) {
58
+ return;
59
+ }
60
+
61
+ const id = setTimeout(() => this.delete(key), ttl);
62
+ this.timers.set(key, id);
63
+ }
64
+ }
@@ -1,15 +1,32 @@
1
1
  import { Log } from '@servicetitan/log-service';
2
+ import { ExposedDependencies } from '../common';
2
3
  import { BundleInfo } from './get-bundle-info';
3
4
 
4
5
  export function validateBundleInfo(
5
6
  { mismatch }: BundleInfo,
6
- { logService, packageName }: { logService?: Log; packageName: string }
7
+ {
8
+ exposedDependencies = {},
9
+ logService,
10
+ packageName,
11
+ }: { exposedDependencies?: ExposedDependencies; logService?: Log; packageName: string }
7
12
  ) {
8
- if (mismatch) {
9
- logService?.warning({
13
+ if (!mismatch || !logService) {
14
+ return;
15
+ }
16
+
17
+ const data = { package: packageName, dependencies: JSON.stringify(mismatch) };
18
+ if (Object.keys(exposedDependencies).length === 0) {
19
+ logService.warning({
20
+ category: 'MicroFrontends.NoExposedDependencies',
21
+ message:
22
+ 'Cannot use light bundle because the host is not exposing dependencies or the list of shared dependencies is empty.',
23
+ data,
24
+ });
25
+ } else {
26
+ logService.warning({
10
27
  category: 'MicroFrontends.DependenciesMismatch',
11
28
  message: 'Some of the package dependencies have incompatible versions.',
12
- data: { package: packageName, dependencies: JSON.stringify(mismatch) },
29
+ data,
13
30
  });
14
31
  }
15
32
  }