@servicetitan/web-components 28.1.1 → 28.3.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 (66) hide show
  1. package/dist/common.d.ts +10 -0
  2. package/dist/common.d.ts.map +1 -1
  3. package/dist/common.js +1 -0
  4. package/dist/common.js.map +1 -1
  5. package/dist/get-value-for-environment.d.ts +4 -0
  6. package/dist/get-value-for-environment.d.ts.map +1 -0
  7. package/dist/get-value-for-environment.js +26 -0
  8. package/dist/get-value-for-environment.js.map +1 -0
  9. package/dist/globals.d.ts +4 -3
  10. package/dist/globals.d.ts.map +1 -1
  11. package/dist/globals.js +4 -2
  12. package/dist/globals.js.map +1 -1
  13. package/dist/index.d.ts +3 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +3 -2
  16. package/dist/index.js.map +1 -1
  17. package/dist/loader.d.ts.map +1 -1
  18. package/dist/loader.js +39 -8
  19. package/dist/loader.js.map +1 -1
  20. package/dist/register.d.ts.map +1 -1
  21. package/dist/register.js +21 -4
  22. package/dist/register.js.map +1 -1
  23. package/dist/utils/get-bundle-info.d.ts +15 -3
  24. package/dist/utils/get-bundle-info.d.ts.map +1 -1
  25. package/dist/utils/get-bundle-info.js +4 -1
  26. package/dist/utils/get-bundle-info.js.map +1 -1
  27. package/dist/utils/get-element-name.d.ts +1 -1
  28. package/dist/utils/get-element-name.d.ts.map +1 -1
  29. package/dist/utils/get-ld-service-token.d.ts +4 -0
  30. package/dist/utils/get-ld-service-token.d.ts.map +1 -0
  31. package/dist/utils/get-ld-service-token.js +11 -0
  32. package/dist/utils/get-ld-service-token.js.map +1 -0
  33. package/dist/utils/get-mfe-has-compatible-launchdarkly-version.d.ts +11 -0
  34. package/dist/utils/get-mfe-has-compatible-launchdarkly-version.d.ts.map +1 -0
  35. package/dist/utils/get-mfe-has-compatible-launchdarkly-version.js +16 -0
  36. package/dist/utils/get-mfe-has-compatible-launchdarkly-version.js.map +1 -0
  37. package/dist/utils/index.d.ts +1 -0
  38. package/dist/utils/index.d.ts.map +1 -1
  39. package/dist/utils/index.js +1 -0
  40. package/dist/utils/index.js.map +1 -1
  41. package/dist/utils/validate-bundle-info.d.ts +7 -4
  42. package/dist/utils/validate-bundle-info.d.ts.map +1 -1
  43. package/dist/utils/validate-bundle-info.js +30 -12
  44. package/dist/utils/validate-bundle-info.js.map +1 -1
  45. package/dist/utils/web-component.d.ts +4 -1
  46. package/dist/utils/web-component.d.ts.map +1 -1
  47. package/dist/utils/web-component.js +15 -2
  48. package/dist/utils/web-component.js.map +1 -1
  49. package/package.json +17 -12
  50. package/src/__tests__/get-value-for-environment.test.ts +77 -0
  51. package/src/__tests__/globals.test.ts +4 -8
  52. package/src/__tests__/loader.test.tsx +152 -13
  53. package/src/__tests__/register-legacy-root.test.tsx +2 -5
  54. package/src/common.ts +10 -0
  55. package/src/get-value-for-environment.ts +42 -0
  56. package/src/globals.ts +12 -3
  57. package/src/index.ts +3 -2
  58. package/src/loader.tsx +46 -9
  59. package/src/register.tsx +21 -8
  60. package/src/utils/__tests__/get-mfe-has-compatible-launchdarkly-version.test.ts +54 -0
  61. package/src/utils/get-bundle-info.ts +27 -10
  62. package/src/utils/get-ld-service-token.ts +13 -0
  63. package/src/utils/get-mfe-has-compatible-launchdarkly-version.ts +20 -0
  64. package/src/utils/index.ts +1 -0
  65. package/src/utils/validate-bundle-info.ts +40 -19
  66. package/src/utils/web-component.tsx +23 -2
@@ -1,6 +1,7 @@
1
1
  export * from './get-bundle-info';
2
2
  export * from './get-element-name';
3
3
  export * from './get-entry-points';
4
+ export * from './get-ld-service-token';
4
5
  export * from './get-mfe-supports-rerendering';
5
6
  export * from './get-version-mismatches';
6
7
  export * from './is-versioned-url';
@@ -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,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"}
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,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,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"}
@@ -1,6 +1,7 @@
1
1
  export * from './get-bundle-info';
2
2
  export * from './get-element-name';
3
3
  export * from './get-entry-points';
4
+ export * from './get-ld-service-token';
4
5
  export * from './get-mfe-supports-rerendering';
5
6
  export * from './get-version-mismatches';
6
7
  export * from './is-versioned-url';
@@ -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,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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,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"}
@@ -1,9 +1,12 @@
1
1
  import { Log } from '@servicetitan/log-service';
2
- import { ExposedDependencies } from '../common';
2
+ import { ExposedDependencies, ExposedInstanceDependencies } from '../common';
3
3
  import { BundleInfo } from './get-bundle-info';
4
- export declare function validateBundleInfo({ mismatch }: BundleInfo, { exposedDependencies, logService, packageName, }: {
4
+ interface Context {
5
5
  exposedDependencies?: ExposedDependencies;
6
+ exposedInstanceDependencies?: ExposedInstanceDependencies;
6
7
  logService?: Log;
7
- packageName: string;
8
- }): void;
8
+ packageUrl: string;
9
+ }
10
+ export declare function validateBundleInfo({ mismatch, mfeHasCompatibleLaunchDarklyVersion }: BundleInfo, { exposedDependencies, exposedInstanceDependencies, logService, packageUrl }: Context): void;
11
+ export {};
9
12
  //# sourceMappingURL=validate-bundle-info.d.ts.map
@@ -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,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
+ {"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,2BAA2B,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,UAAU,OAAO;IACb,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,2BAA2B,CAAC,EAAE,2BAA2B,CAAC;IAC1D,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACtB;AACD,wBAAgB,kBAAkB,CAC9B,EAAE,QAAQ,EAAE,mCAAmC,EAAE,EAAE,UAAU,EAC7D,EAAE,mBAAwB,EAAE,2BAA2B,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,OAAO,QAwC7F"}
@@ -1,19 +1,37 @@
1
- export function validateBundleInfo({ mismatch }, { exposedDependencies = {}, logService, packageName, }) {
2
- if (!mismatch || !logService) {
1
+ export function validateBundleInfo({ mismatch, mfeHasCompatibleLaunchDarklyVersion }, { exposedDependencies = {}, exposedInstanceDependencies, logService, packageUrl }) {
2
+ var _a, _b;
3
+ if (!logService) {
3
4
  return;
4
5
  }
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
- });
6
+ if (mismatch) {
7
+ const data = { package: packageUrl, dependencies: JSON.stringify(mismatch) };
8
+ if (Object.keys(exposedDependencies).length === 0) {
9
+ logService.warning({
10
+ category: 'MicroFrontends.NoExposedDependencies',
11
+ message: 'Cannot use light bundle because the host is not exposing dependencies or the list of shared dependencies is empty.',
12
+ data,
13
+ });
14
+ }
15
+ else {
16
+ logService.warning({
17
+ category: 'MicroFrontends.DependenciesMismatch',
18
+ message: 'Some of the package dependencies have incompatible versions.',
19
+ data,
20
+ });
21
+ }
12
22
  }
13
- else {
23
+ /**
24
+ * Note, only checking false here because the value is undefined when the host
25
+ * or the MFE isn't using LaunchDarkly at all.
26
+ */
27
+ if (mfeHasCompatibleLaunchDarklyVersion === false) {
28
+ const data = {
29
+ package: packageUrl,
30
+ hostVersion: (_b = (_a = exposedInstanceDependencies === null || exposedInstanceDependencies === void 0 ? void 0 : exposedInstanceDependencies.launchDarkly) === null || _a === void 0 ? void 0 : _a.version) !== null && _b !== void 0 ? _b : '',
31
+ };
14
32
  logService.warning({
15
- category: 'MicroFrontends.DependenciesMismatch',
16
- message: 'Some of the package dependencies have incompatible versions.',
33
+ category: 'MicroFrontends.LaunchDarklyMismatch',
34
+ message: 'LaunchDarkly versions are incompatible',
17
35
  data,
18
36
  });
19
37
  }
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"validate-bundle-info.js","sourceRoot":"","sources":["../../src/utils/validate-bundle-info.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,kBAAkB,CAC9B,EAAE,QAAQ,EAAE,mCAAmC,EAAc,EAC7D,EAAE,mBAAmB,GAAG,EAAE,EAAE,2BAA2B,EAAE,UAAU,EAAE,UAAU,EAAW;;IAE1F,IAAI,CAAC,UAAU,EAAE,CAAC;QACd,OAAO;IACX,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACX,MAAM,IAAI,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7E,IAAI,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,UAAU,CAAC,OAAO,CAAC;gBACf,QAAQ,EAAE,sCAAsC;gBAChD,OAAO,EACH,oHAAoH;gBACxH,IAAI;aACP,CAAC,CAAC;QACP,CAAC;aAAM,CAAC;YACJ,UAAU,CAAC,OAAO,CAAC;gBACf,QAAQ,EAAE,qCAAqC;gBAC/C,OAAO,EAAE,8DAA8D;gBACvE,IAAI;aACP,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED;;;OAGG;IAEH,IAAI,mCAAmC,KAAK,KAAK,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG;YACT,OAAO,EAAE,UAAU;YACnB,WAAW,EAAE,MAAA,MAAA,2BAA2B,aAA3B,2BAA2B,uBAA3B,2BAA2B,CAAE,YAAY,0CAAE,OAAO,mCAAI,EAAE;SACxE,CAAC;QACF,UAAU,CAAC,OAAO,CAAC;YACf,QAAQ,EAAE,qCAAqC;YAC/C,OAAO,EAAE,wCAAwC;YACjD,IAAI;SACP,CAAC,CAAC;IACP,CAAC;AACL,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { Log } from '@servicetitan/log-service';
2
- import { ExposedDependencies } from '../common';
2
+ import { type LDService } from '@servicetitan/launchdarkly-service';
3
+ import { ExposedDependencies, ExposedInstanceDependencies } from '../common';
3
4
  import { EventBus } from '../event-bus';
4
5
  import { BundleInfo } from './get-bundle-info';
5
6
  import { LoaderDataProps } from '../loader';
@@ -8,6 +9,8 @@ interface WebComponentProps {
8
9
  bundleInfo: BundleInfo;
9
10
  eventBus: EventBus;
10
11
  exposedDependencies?: ExposedDependencies;
12
+ exposedInstanceDependencies?: ExposedInstanceDependencies;
13
+ ldService?: LDService;
11
14
  logService?: Log;
12
15
  }
13
16
  export declare function webComponent(props: WebComponentProps): ({ LoadingFallback, ...props }: LoaderDataProps) => import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"web-component.d.ts","sourceRoot":"","sources":["../../src/utils/web-component.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAGhD,OAAO,EAAE,mBAAmB,EAAiB,MAAM,WAAW,CAAC;AAE/D,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,UAAU,iBAAiB;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,UAAU,CAAC,EAAE,GAAG,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,mCAKV,eAAe,6CAoDzD"}
1
+ {"version":3,"file":"web-component.d.ts","sourceRoot":"","sources":["../../src/utils/web-component.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAGpE,OAAO,EAAE,mBAAmB,EAAE,2BAA2B,EAAiB,MAAM,WAAW,CAAC;AAE5F,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,UAAU,iBAAiB;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,2BAA2B,CAAC,EAAE,2BAA2B,CAAC;IAC1D,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,UAAU,CAAC,EAAE,GAAG,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,mCAUV,eAAe,6CAuDzD"}
@@ -4,17 +4,21 @@ import { useOptionalDependencies } from '@servicetitan/react-ioc';
4
4
  import { getElementName } from './get-element-name';
5
5
  import { HistoryManager } from '../history-manager';
6
6
  export function webComponent(props) {
7
- const { basename, bundleInfo, eventBus, exposedDependencies, logService } = props;
7
+ var _a;
8
+ const { basename, bundleInfo, eventBus, exposedDependencies, ldService, logService } = props;
8
9
  const { WebComponent, disposer, mfeSupportsRerendering } = bundleInfo;
9
10
  const elementName = getElementName(bundleInfo);
11
+ const exposedInstanceDependencies = ensureLDVersion(props.exposedInstanceDependencies, (_a = bundleInfo.bundledWith) === null || _a === void 0 ? void 0 : _a['launchdarkly-js-client-sdk']);
10
12
  return ({ LoadingFallback, ...props }) => {
11
13
  const [isLoading, setIsLoading] = useState(true);
12
14
  const [historyManager] = useOptionalDependencies(HistoryManager);
13
15
  const handleRef = (webComponent) => {
14
16
  webComponent === null || webComponent === void 0 ? void 0 : webComponent.provide({
17
+ ldService,
15
18
  logService,
16
19
  historyManager,
17
20
  exposedDependencies,
21
+ exposedInstanceDependencies,
18
22
  eventBus,
19
23
  basename,
20
24
  onReady: () => {
@@ -36,7 +40,9 @@ export function webComponent(props) {
36
40
  const key = mfeSupportsRerendering ? undefined : stringifiedData;
37
41
  const dataAttrs = useMemo(() => composeDataAttributes(props.data), [props.data]);
38
42
  const styleUrls = getStyleUrls(bundleInfo);
39
- return (_jsxs(Fragment, { children: [isLoading && _jsx(LoadingFallback, {}), _jsx(WebComponent, { ref: handleRef, class: props.className, ...(styleUrls && { 'style-urls': styleUrls }), ...dataAttrs, "data-mfe-data": stringifiedData, "data-mfe-name": elementName }, key)] }));
43
+ return (_jsxs(Fragment, { children: [isLoading && _jsx(LoadingFallback, {}), _jsx(WebComponent, {
44
+ // @ts-expect-error because property ref does not exist on IntrinsicAttributes
45
+ ref: handleRef, class: props.className, ...(styleUrls && { 'style-urls': styleUrls }), ...dataAttrs, "data-mfe-data": stringifiedData, "data-mfe-name": elementName }, key)] }));
40
46
  };
41
47
  }
42
48
  /*
@@ -49,6 +55,13 @@ function composeDataAttributes(data = {}) {
49
55
  value,
50
56
  ]));
51
57
  }
58
+ function ensureLDVersion(exposedInstanceDependencies = {}, version) {
59
+ var _a;
60
+ if (version && !((_a = exposedInstanceDependencies.launchDarkly) === null || _a === void 0 ? void 0 : _a.ldService)) {
61
+ return { ...exposedInstanceDependencies, launchDarkly: { version } };
62
+ }
63
+ return exposedInstanceDependencies;
64
+ }
52
65
  function getStyleUrls({ urls }) {
53
66
  if (urls.css.length) {
54
67
  return encodeURIComponent(JSON.stringify(urls.css));
@@ -1 +1 @@
1
- {"version":3,"file":"web-component.js","sourceRoot":"","sources":["../../src/utils/web-component.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"web-component.js","sourceRoot":"","sources":["../../src/utils/web-component.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/web-components",
3
- "version": "28.1.1",
3
+ "version": "28.3.0",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,34 +15,36 @@
15
15
  "src"
16
16
  ],
17
17
  "dependencies": {
18
- "@servicetitan/error-boundary": "28.1.1",
18
+ "@servicetitan/error-boundary": "28.3.0",
19
19
  "lodash.get": "~4.4.2",
20
20
  "mitt": "~3.0.1",
21
21
  "semver": "~7.6.3"
22
22
  },
23
23
  "devDependencies": {
24
- "@servicetitan/anvil2": "^1.16.7",
25
- "@servicetitan/design-system": "~14.5.0",
26
- "@servicetitan/log-service": "28.1.1",
27
- "@servicetitan/react-ioc": "28.1.1",
24
+ "@servicetitan/anvil2": "^1.16.13",
25
+ "@servicetitan/design-system": "~14.5.1",
26
+ "@servicetitan/launchdarkly-service": "28.3.0",
27
+ "@servicetitan/log-service": "28.3.0",
28
+ "@servicetitan/react-ioc": "28.3.0",
28
29
  "@testing-library/dom": "^10.4.0",
29
30
  "@testing-library/jest-dom": "^6.6.3",
30
- "@testing-library/react": "^16.0.1",
31
+ "@testing-library/react": "^16.1.0",
31
32
  "@types/history": "~4.7.10",
32
33
  "@types/lodash.get": "~4.4.6",
33
34
  "@types/react": "~18.3.3",
34
35
  "@types/react-dom": "~18.3.0",
35
36
  "@types/semver": "~7.5.8",
36
37
  "history": "~4.10.1",
38
+ "launchdarkly-react-client-sdk": "^3.6.0",
37
39
  "react": "~18.3.1",
38
40
  "react-dom": "~18.3.1",
39
41
  "shadow-dom-testing-library": "^1.11.3"
40
42
  },
41
43
  "peerDependencies": {
42
- "@servicetitan/anvil2": ">=1.16.7",
43
- "@servicetitan/design-system": ">=14.5.0",
44
- "@servicetitan/log-service": "28.1.1",
45
- "@servicetitan/react-ioc": "28.1.1",
44
+ "@servicetitan/anvil2": ">=1.16.13",
45
+ "@servicetitan/design-system": ">=14.5.1",
46
+ "@servicetitan/log-service": "28.3.0",
47
+ "@servicetitan/react-ioc": "28.3.0",
46
48
  "history": "~4.10.1",
47
49
  "react": ">=17.0.2",
48
50
  "react-dom": ">=17.0.2"
@@ -53,6 +55,9 @@
53
55
  },
54
56
  "@servicetitan/design-system": {
55
57
  "optional": true
58
+ },
59
+ "@servicetitan/launchdarkly-service": {
60
+ "optional": true
56
61
  }
57
62
  },
58
63
  "publishConfig": {
@@ -61,5 +66,5 @@
61
66
  "cli": {
62
67
  "webpack": false
63
68
  },
64
- "gitHead": "35c714f4eaf0ba60dd6fa3fc583f0283edfb4a44"
69
+ "gitHead": "63ce3ca18966fc5522a3b61df5e4c55f82b4272e"
65
70
  }
@@ -0,0 +1,77 @@
1
+ import {
2
+ Environment,
3
+ EnvironmentValues,
4
+ getValueForEnvironment,
5
+ } from '../get-value-for-environment';
6
+
7
+ describe(`[web-components] ${getValueForEnvironment.name}`, () => {
8
+ const originalLocation = window.location;
9
+ const values: EnvironmentValues = {
10
+ dev: 'dev-value',
11
+ go: 'go-value',
12
+ next: 'next-value',
13
+ qa: 'qa-value',
14
+ stage: 'stage-value',
15
+ test: 'test-value',
16
+ };
17
+ let hostname: string | undefined;
18
+ let defaultEnvironment: Environment | undefined;
19
+
20
+ const subject = () => getValueForEnvironment(values, defaultEnvironment, hostname);
21
+
22
+ beforeAll(() => {
23
+ Object.defineProperty(window, 'location', {
24
+ configurable: true,
25
+ value: new URL('https://example.com'),
26
+ });
27
+ });
28
+ afterAll(() => {
29
+ Object.defineProperty(window, 'location', {
30
+ configurable: true,
31
+ value: originalLocation,
32
+ });
33
+ });
34
+
35
+ beforeEach(() => {
36
+ hostname = undefined;
37
+ defaultEnvironment = undefined;
38
+ process.env.NODE_ENV = 'production';
39
+ });
40
+
41
+ test('returns id for "qa" environment', () => {
42
+ expect(subject()).toBe(values.qa);
43
+ });
44
+
45
+ describe('when in test environment', () => {
46
+ beforeEach(() => (process.env.NODE_ENV = 'test'));
47
+
48
+ test('returns id for "test" environment', () => {
49
+ expect(subject()).toBe(values.test);
50
+ });
51
+ });
52
+
53
+ describe('with a default environment', () => {
54
+ beforeEach(() => (defaultEnvironment = 'dev'));
55
+
56
+ test('returns id for default environment', () => {
57
+ expect(subject()).toBe(values[defaultEnvironment!]);
58
+ });
59
+ });
60
+
61
+ describe.each([
62
+ { host: '127.0.0.1', key: 'dev' },
63
+ { host: 'localhost', key: 'dev' },
64
+ { host: 'go.servicetitan.com', key: 'go' },
65
+ { host: 'next.servicetitan.com', key: 'next' },
66
+ { host: 'stage.servicetitan.com', key: 'stage' },
67
+ ] as {
68
+ host: string;
69
+ key: Environment;
70
+ }[])('when hostname contains "$host"', ({ host, key }) => {
71
+ beforeEach(() => (hostname = host));
72
+
73
+ test(`returns id for "${key}" environment`, () => {
74
+ expect(subject()).toBe(values[key]);
75
+ });
76
+ });
77
+ });
@@ -1,6 +1,6 @@
1
1
  describe('[web-components] globals', () => {
2
2
  function itExportsGlobal(globalName: string) {
3
- test(`exports the global ${globalName}`, () => {
3
+ test(`exports "${globalName}"`, () => {
4
4
  jest.isolateModules(() => {
5
5
  const globalValue = 'foo';
6
6
  Object.assign(global, { [globalName]: globalValue });
@@ -10,11 +10,7 @@ describe('[web-components] globals', () => {
10
10
  });
11
11
  }
12
12
 
13
- describe('EXPOSED_DEPENDENCIES', () => {
14
- itExportsGlobal('EXPOSED_DEPENDENCIES');
15
- });
16
-
17
- describe('WEB_COMPONENT_NAME', () => {
18
- itExportsGlobal('WEB_COMPONENT_NAME');
19
- });
13
+ ['EXPOSED_DEPENDENCIES', 'EXPOSED_INSTANCE_DEPENDENCIES', 'WEB_COMPONENT_NAME'].forEach(name =>
14
+ itExportsGlobal(name)
15
+ );
20
16
  });
@@ -1,20 +1,27 @@
1
1
  import '@testing-library/jest-dom';
2
2
  import { act, render, screen, waitFor } from '@testing-library/react';
3
+ import { LD_SERVICE_TOKEN } from '@servicetitan/launchdarkly-service';
3
4
  import { Log } from '@servicetitan/log-service';
4
5
  import { Provider, ProviderProps } from '@servicetitan/react-ioc';
5
6
  import { FC, RefObject, useEffect, useRef } from 'react';
6
7
 
7
8
  import * as common from '../common';
8
- import { Entries, EXPOSED_DEPENDENCIES_TOKEN } from '../common';
9
+ import {
10
+ EXPOSED_DEPENDENCIES_TOKEN,
11
+ EXPOSED_INSTANCE_DEPENDENCIES_TOKEN,
12
+ Entries,
13
+ ExposedDependencies,
14
+ ExposedInstanceDependencies,
15
+ } from '../common';
9
16
  import { EVENT_BUS_TOKEN } from '../event-bus';
10
17
  import { HistoryManager } from '../history-manager';
11
18
  import { Loader, LoaderProps } from '../loader';
12
19
  import { Metadata } from '../utils/get-bundle-info';
20
+ import { getMFEHasCompatibleLaunchDarklyVersion } from '../utils/get-mfe-has-compatible-launchdarkly-version';
13
21
  import { getVersionMismatches } from '../utils/get-version-mismatches';
14
22
 
15
- jest.mock('../utils/get-version-mismatches', () => ({
16
- getVersionMismatches: jest.fn(),
17
- }));
23
+ jest.mock('../utils/get-mfe-has-compatible-launchdarkly-version');
24
+ jest.mock('../utils/get-version-mismatches');
18
25
 
19
26
  describe('[web-components] Loader', () => {
20
27
  const localHosts = ['localhost', '127.0.0.1'];
@@ -112,6 +119,7 @@ describe('[web-components] Loader', () => {
112
119
  }
113
120
  return getJsonMockFns[url]();
114
121
  });
122
+ jest.mocked(getMFEHasCompatibleLaunchDarklyVersion).mockReturnValue(true);
115
123
  jest.mocked(getVersionMismatches).mockReturnValue({});
116
124
  });
117
125
 
@@ -594,10 +602,11 @@ describe('[web-components] Loader', () => {
594
602
  [Log, 'logService'],
595
603
  [HistoryManager, 'historyManager'],
596
604
  [EXPOSED_DEPENDENCIES_TOKEN, 'exposedDependencies'],
605
+ [EXPOSED_INSTANCE_DEPENDENCIES_TOKEN, 'exposedInstanceDependencies'],
597
606
  [EVENT_BUS_TOKEN, 'eventBus'],
598
607
  ] as [any, string][]
599
608
  ).forEach(([klass, propName]) => {
600
- describe(`when ${propName} is provided to the parent <Provider>`, () => {
609
+ describe(`when ${propName} is provided`, () => {
601
610
  beforeEach(() => {
602
611
  singletons?.push({ provide: klass, useValue: propName });
603
612
  });
@@ -609,6 +618,104 @@ describe('[web-components] Loader', () => {
609
618
  });
610
619
  });
611
620
 
621
+ describe('when ldService is provided via EXPOSED_INSTANCE_DEPENDENCIES', () => {
622
+ const ldService = Symbol('ldService');
623
+
624
+ beforeEach(() => {
625
+ singletons?.push({
626
+ provide: EXPOSED_INSTANCE_DEPENDENCIES_TOKEN,
627
+ useValue: { launchDarkly: { version: '1.0', ldService } },
628
+ });
629
+ });
630
+
631
+ test('provides ldService to the web component', async () => {
632
+ await webComponentReadySetup();
633
+ expect(webComponentState.ldService).toEqual(ldService);
634
+ });
635
+
636
+ describe('when MFE has incompatible LaunchDarkly version', () => {
637
+ beforeEach(() => {
638
+ jest.mocked(getMFEHasCompatibleLaunchDarklyVersion).mockReturnValue(false);
639
+ });
640
+
641
+ test('does not provide ldService to the web component', async () => {
642
+ await webComponentReadySetup();
643
+ expect(webComponentState.ldService).toBeUndefined();
644
+ });
645
+ });
646
+ });
647
+
648
+ describe('when only LaunchDarkly version is provided via EXPOSED_INTERNAL_DEPENDENCIES', () => {
649
+ beforeEach(() => {
650
+ singletons?.push({
651
+ provide: EXPOSED_INSTANCE_DEPENDENCIES_TOKEN,
652
+ useValue: { launchDarkly: { version: '1.0' } },
653
+ });
654
+ });
655
+
656
+ describe('when ldService is provided via LD_SERVICE_TOKEN', () => {
657
+ const ldService = Symbol('ldService');
658
+
659
+ beforeEach(() =>
660
+ singletons?.push({ provide: LD_SERVICE_TOKEN, useValue: ldService })
661
+ );
662
+
663
+ test('add ldService to exposedInternalDependencies provided to web component', async () => {
664
+ await webComponentReadySetup();
665
+ expect(webComponentState.exposedInstanceDependencies).toEqual(
666
+ expect.objectContaining({
667
+ launchDarkly: expect.objectContaining({ ldService }),
668
+ })
669
+ );
670
+ });
671
+
672
+ test('provides ldService to the web component', async () => {
673
+ await webComponentReadySetup();
674
+ expect(webComponentState.ldService).toEqual(ldService);
675
+ });
676
+ });
677
+ });
678
+
679
+ describe('when metadata.bundledWith includes LaunchDarkly', () => {
680
+ const version = '1.0.0';
681
+
682
+ beforeEach(() => {
683
+ metadata.bundledWith = { 'launchdarkly-js-client-sdk': version };
684
+ });
685
+
686
+ function itAddsLaunchDarklyVersion() {
687
+ test('adds LaunchDarkly version to exposedInternalDependencies provided to web component', async () => {
688
+ await webComponentReadySetup();
689
+
690
+ expect(webComponentState.exposedInstanceDependencies).toEqual(
691
+ expect.objectContaining({ launchDarkly: { version } })
692
+ );
693
+ });
694
+ }
695
+
696
+ describe('when EXPOSED_INTERNAL_DEPENDENCIES omits launchDarkly', () => {
697
+ beforeEach(() => {
698
+ singletons?.push({
699
+ provide: EXPOSED_INSTANCE_DEPENDENCIES_TOKEN,
700
+ useValue: {},
701
+ });
702
+ });
703
+
704
+ itAddsLaunchDarklyVersion();
705
+ });
706
+
707
+ describe('when EXPOSED_INTERNAL_DEPENDENCIES.launchDarkly omits ldService', () => {
708
+ beforeEach(() => {
709
+ singletons?.push({
710
+ provide: EXPOSED_INSTANCE_DEPENDENCIES_TOKEN,
711
+ useValue: { launchDarkly: { version: '1.2.3' } },
712
+ });
713
+ });
714
+
715
+ itAddsLaunchDarklyVersion();
716
+ });
717
+ });
718
+
612
719
  describe('when onDispose is called from the web component', () => {
613
720
  async function onDisposeSetup() {
614
721
  await webComponentReadySetup();
@@ -670,19 +777,28 @@ describe('[web-components] Loader', () => {
670
777
  });
671
778
 
672
779
  describe('when there are version mismatches', () => {
780
+ const exposedDependencies: ExposedDependencies = {
781
+ foo: { variable: 'foo', version: '1.0' },
782
+ };
783
+ const exposedInstanceDependencies: ExposedInstanceDependencies = {
784
+ launchDarkly: { version: '1.0' },
785
+ };
673
786
  const mismatchedDeps = {
674
- foo: {
675
- host: 'bar',
676
- package: 'baz',
677
- },
787
+ foo: { host: '1.0', package: '2.0' },
678
788
  };
679
789
 
680
790
  beforeEach(() => {
681
791
  jest.mocked(getVersionMismatches).mockReturnValue(mismatchedDeps);
682
- singletons?.push({
683
- provide: EXPOSED_DEPENDENCIES_TOKEN,
684
- useValue: { foo: 'bar' },
685
- });
792
+ singletons?.push(
793
+ {
794
+ provide: EXPOSED_DEPENDENCIES_TOKEN,
795
+ useValue: exposedDependencies,
796
+ },
797
+ {
798
+ provide: EXPOSED_INSTANCE_DEPENDENCIES_TOKEN,
799
+ useValue: exposedInstanceDependencies,
800
+ }
801
+ );
686
802
  });
687
803
 
688
804
  itAddsJsEntrypointToWebComponent(
@@ -733,6 +849,29 @@ describe('[web-components] Loader', () => {
733
849
  );
734
850
  });
735
851
  });
852
+
853
+ describe('when MFE has incompatible version of LaunchDarkly', () => {
854
+ beforeEach(() => {
855
+ jest.mocked(getMFEHasCompatibleLaunchDarklyVersion).mockReturnValue(
856
+ false
857
+ );
858
+ });
859
+
860
+ test('logs "LaunchDarkly mismatch" warning', async () => {
861
+ await webComponentReadySetup();
862
+
863
+ expect(logService.warning).toHaveBeenCalledWith(
864
+ expect.objectContaining({
865
+ category: 'MicroFrontends.LaunchDarklyMismatch',
866
+ data: {
867
+ package: props.src,
868
+ hostVersion:
869
+ exposedInstanceDependencies.launchDarkly?.version,
870
+ },
871
+ })
872
+ );
873
+ });
874
+ });
736
875
  });
737
876
  });
738
877
  });
@@ -1,5 +1,5 @@
1
1
  import '@testing-library/jest-dom';
2
- import { render, waitFor } from '@testing-library/react';
2
+ import { render } from '@testing-library/react';
3
3
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
4
4
  // @ts-ignore because Jest mistakenly complains that "'shadow-dom-testing-library' cannot be imported using this construct".
5
5
  import { screen } from 'shadow-dom-testing-library';
@@ -30,10 +30,7 @@ describe('[web-components] register', () => {
30
30
  test('useMFEDataContext provides updated data', async () => {
31
31
  setup();
32
32
 
33
- await waitFor(() => {
34
- expect(screen.getByShadowText(`Prop: string, Value: "baz"`)).toBeInTheDocument();
35
- });
36
- expect(screen.getByShadowText(`Data: string, Value: "baz"`)).toBeInTheDocument();
33
+ expect(await screen.findByShadowText(`Data: string, Value: "baz"`)).toBeInTheDocument();
37
34
  });
38
35
  });
39
36
  });
package/src/common.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { useRef } from 'react';
2
2
 
3
3
  import { symbolToken } from '@servicetitan/react-ioc';
4
+ import { type LDService } from '@servicetitan/launchdarkly-service';
4
5
  import { Log } from '@servicetitan/log-service';
5
6
 
6
7
  import { EventBus } from './event-bus';
@@ -14,17 +15,26 @@ export type ExposedDependencies = Record<
14
15
  }
15
16
  >;
16
17
 
18
+ export interface ExposedInstanceDependencies {
19
+ launchDarkly?: { version: string; ldService?: LDService };
20
+ }
21
+
17
22
  export const BASENAME_TOKEN = symbolToken<string>('BASENAME_TOKEN');
18
23
  export const EXPOSED_DEPENDENCIES_TOKEN = symbolToken<ExposedDependencies>(
19
24
  'EXPOSED_DEPENDENCIES_TOKEN'
20
25
  );
26
+ export const EXPOSED_INSTANCE_DEPENDENCIES_TOKEN = symbolToken<ExposedInstanceDependencies>(
27
+ 'EXPOSED_INSTANCE_DEPENDENCIES_TOKEN'
28
+ );
21
29
  export const IS_WEB_COMPONENT_TOKEN = symbolToken<boolean>('IS_WEB_COMPONENT_TOKEN');
22
30
  export const RENDER_ROOT_TOKEN = symbolToken<ShadowRoot>('RENDER_ROOT_TOKEN');
23
31
 
24
32
  export interface Entries {
33
+ ldService?: LDService;
25
34
  logService?: Log;
26
35
  historyManager?: HistoryManager;
27
36
  exposedDependencies?: ExposedDependencies;
37
+ exposedInstanceDependencies?: ExposedInstanceDependencies;
28
38
  eventBus?: EventBus;
29
39
  basename?: string;
30
40
  onReady: () => void;