@servicetitan/docs-uikit 28.1.0 → 28.2.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.
@@ -0,0 +1,142 @@
1
+ ---
2
+ title: LaunchDarkly Service
3
+ ---
4
+
5
+ #### [CHANGELOG (@servicetitan/launchdarkly-service)](https://github.com/servicetitan/uikit/blob/master/packages/launchdarkly-service/CHANGELOG.md)
6
+
7
+ ServiceTitan's LaunchDarkly platform has multiple "projects" (e.g., Dispatch Center, Contact Center, FleetPro),
8
+ each with its own set of feature flags and client-side IDs that authorize connections.
9
+
10
+ LaunchDarkly's SDKs require applications to create a separate client connection to the LaunchDarkly backend for each project.
11
+ However, if applications and MFEs create multiple, independent connections to the same LaunchDarkly project, it can degrade performance
12
+ and cause the uikit to behave inconsistently. It also harms performance to teardown and recreate connections each time an
13
+ MFE is unloaded and reloaded.
14
+
15
+ To prevent these issues **@servicetitan/launchdarkly-service** implements a coordinated approach for creating
16
+ and reusing client connections for LaunchDarkly projects.
17
+ Instead of using **LDProvider**, **withLDProvider** or **withAsyncLDProvider** from the LaunchDarkly React SDK, use **LDProvider** from **@servicetitan/launchdarkly-service**.
18
+
19
+ ## Usage
20
+
21
+ **@servicetitan/launchdarkly-service** allows host applications and MFEs to share and reuse connections to LaunchDarkly. It ensures that only one connection is created for each LaunchDarkly project. To use:
22
+
23
+ 1. Wrap the MFE application (or code within the host) with [`LDProvider`](#ldprovider) from `@servicetitan/launchdarkly-service`.
24
+ 2. Wrap the host application with [`LDServiceProvider`](#ldserviceprovider) (if applicable).
25
+ 3. Use the standard [hooks](https://docs.launchdarkly.com/sdk/client-side/react/react-web#hooks) from the [launchdarkly-react-client-sdk](https://docs.launchdarkly.com/sdk/client-side/react/react-web) to access feature flags and the client object.
26
+
27
+ ## API
28
+
29
+ ### LDProvider
30
+
31
+ `LDProvider` provides LaunchDarkly feature flags within hosts and MFEs.
32
+ It ensures that hosts and MFEs share one client connection to each LaunchDarkly project (as identified by the client-side ID).
33
+
34
+ #### Props
35
+
36
+ | Name | Type | Description |
37
+ | :---------------------- | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
38
+ | `clientSideID` | `string` | The client-side ID that authorizes the client to connect to a particular LaunchDarkly project. The [getValueForEnvironment](./web-components#getvalueforenvironment) helper provides a convenient way to map Monolith environments to the corresponding client-side ID. |
39
+ | `projectName` | `string` | The name of the LaunchDarkly project, for logs and error messages. |
40
+ | `context` | `object` | (Optional) Context for targeting rules. Defaults to anonymous user. Use LaunchDarkly's [`identify`](https://docs.launchdarkly.com/sdk/features/identify) method to change the context after initialization. |
41
+ | `waitForInitialization` | `boolean` | (Optional) Whether or not to wait until flags values are available before rendering children. Defaults to `true` |
42
+
43
+ :::caution
44
+ When a `context` is provided, only the initial value takes affect. Subsequent calls with the same client-side ID reuse the client that was created with the initial context.
45
+
46
+ This is typically only a problem when different code paths call `LDProvider` with different contexts. To avoid this, create a standard `LDProvider` wrapper for each project (see example below).
47
+ If that isn't practical, you can use [`getContext`](https://launchdarkly.github.io/js-client-sdk/interfaces/LDClient.html#getContext) and [`identify`](https://launchdarkly.github.io/js-client-sdk/interfaces/LDClient.html#identify) to fetch and amend the active context.
48
+ :::
49
+
50
+ :::caution
51
+ When `waitForInitialization` is set to false, the UI could render immediately, with no flags,
52
+ and the LaunchDarkly SDK won't automatically re-render components when the flags become available.
53
+ If this is a problem, you can [subscribe to flag changes](https://docs.launchdarkly.com/sdk/features/flag-changes)
54
+ and manually trigger updates.
55
+ :::
56
+
57
+ #### Examples
58
+
59
+ For example, to provide feature flags for the TitanAdvisor project, create a `TitanAdvisorLDProvider` component that wraps its children with the appropriate `LDProvider`:
60
+
61
+ ```tsx title="titan-advisor-ld-provider.tsx"
62
+ import { LDProvider } from '@servicetitan/launchdarkly-service';
63
+ import { getValueForEnvironment } from '@servicetitan/web-components'
64
+ import { FC, PropsWithChildren, useMemo } from 'react';
65
+
66
+ export const TitanAdvisorLDProvider: FC<PropsWithChildren> = ({ children }) => {
67
+ const clientSideID = useMemo(() => {
68
+ return getValueForEnvironment({
69
+ dev: '669fe6e5cc97eb103be7a620',
70
+ go: '669fe5bff00a0c0fa60b25e4',
71
+ next: '669fe5bff00a0c0fa60b25e4' // using 'go' here, but could also be 'qa'
72
+ qa: '669fe6d6f00a0c0fa60b2721',
73
+ stage: '669fe65979abf310b860236e',
74
+ });
75
+ }, []);
76
+
77
+ if (!clientSideID) {
78
+ // This only happens in the "test" environment, because "test" was omitted above.
79
+ return children;
80
+ }
81
+
82
+ return (
83
+ <LDProvider clientSideID={clientSideID} projectName="TitanAdvisor">
84
+ {children}
85
+ </LDProvider>
86
+ );
87
+ };
88
+ ```
89
+
90
+ Then, to provide those flags globally to the entire TitanAdvisor MFE, wrap the MFE's `App`:
91
+
92
+ ```tsx title="app.tsx"
93
+ import { FC, StrictMode } from 'react';
94
+
95
+ import { TitanAdvisorLDProvider } from './titan-advisor-ld-provider';
96
+
97
+ export const App: FC = () => {
98
+ return (
99
+ <StrictMode>
100
+ <TitanAdvisorLDProvider>
101
+ {...}
102
+ </TitanAdvisorLDProvider>
103
+ </StrictMode>
104
+ );
105
+ };
106
+ ```
107
+
108
+ Or, to provide TitanAdvisor flags to a component in the Monolith, wrap the component:
109
+
110
+ ```tsx
111
+ // Rename original Component to ComponentUnwrapped
112
+ const ComponentUnwrapped: FC<ComponentProps> = props => {};
113
+
114
+ // Export wrapped Component
115
+ export const Component: FC<ComponentProps> = props => {
116
+ return (
117
+ <TitanAdvisorLDProvider>
118
+ <ComponentUnwrapped {...props} />
119
+ </TitanAdvisorLDProvider>
120
+ );
121
+ };
122
+ ```
123
+
124
+ ### LDServiceProvider
125
+
126
+ `LDServiceProvider` enables sharing and reusing LaunchDarkly clients outside the Monolith.
127
+ Simply wrap the host with `LDServiceProvider` to ensure that it and embedded MFEs use a single connection for each LaunchDarkly project.
128
+
129
+ ```tsx
130
+ import { FC, StrictMode } from 'react';
131
+ import { LogService } from '@servicetitan/launchdarkly-service';
132
+
133
+ export const HostApp: FC = () => {
134
+ return(
135
+ <StrictMode>
136
+ <LDServiceProvider>
137
+ {...}
138
+ </LDServiceProvider>
139
+ </StrictMode>
140
+ );
141
+ };
142
+ ```
@@ -90,7 +90,7 @@ export const App: FC = () => {
90
90
  <StrictMode>
91
91
  <LogService>
92
92
  {...}
93
- <LogService>
93
+ </LogService>
94
94
  </StrictMode>
95
95
  );
96
96
  };
package/docs/startup.mdx CHANGED
@@ -357,6 +357,15 @@ Or you can set an object with detailed configs:
357
357
  }
358
358
  }
359
359
  ```
360
+
361
+ Or you can use relative path to a file that exports an object with detailed configs (useful to share configs between multiple MFEs in repo):
362
+ ```json title="package.json"
363
+ {
364
+ "cli": {
365
+ "web-component": "../../config/web-component.js"
366
+ }
367
+ }
368
+ ```
360
369
  ###### Web component config options
361
370
 
362
371
  - `branches` - Set git branch specific configs, used for publishing. See [Branch configs](#branch-configs).
@@ -153,6 +153,59 @@ The following metadata about an MFE is available from `useMFEMetadataContext` ho
153
153
  | `shadowRoot` | ShadowRoot | ShadowRoot root node of which the MFE is rendered within |
154
154
  | `portalShadowRoot` | ShadowRoot | ShadowRoot root node of the "portal" tied to the MFE, which is used to render elements in a div directly under the body element |
155
155
 
156
+ ### getValueForEnvironment
157
+
158
+ `getValueForEnvironment` detects the Monolith environment and returns a corresponding value.
159
+
160
+ :::caution
161
+ When no value is provided for the detected environment, `getValueForEnvironment` returns `undefined`.
162
+ :::
163
+
164
+ #### Props
165
+
166
+ | Name | Type | Description |
167
+ | :------------------- | :----------------------------- | :----------------------------------------------------------------------------------------- |
168
+ | `values` | `Record<Environment, string>` | Object that maps each environment to a value (see below). |
169
+ | `defaultEnvironment` | `Environment` | The environment to use when the current environment is not recognized. Defaults to `"qa"`. |
170
+ | `hostname` | `string` | The hostname of the current environment. Defaults to `window.location.hostname` |
171
+
172
+ The recognized environments are:
173
+
174
+ | Environment | Description |
175
+ | :---------- | :-------------------------------------------------------------- |
176
+ | **dev** | Development environment (e.g., `localhost`) |
177
+ | **go** | Production environment |
178
+ | **qa** | QA environment |
179
+ | **next** | Next environment |
180
+ | **stage** | Staging environment |
181
+ | **test** | Unit test environment (i.e., `process.env.NODE_ENV === 'test'`) |
182
+
183
+ #### Examples
184
+
185
+ Determine LaunchDarkly client-side ID for TitanAdvisor project.
186
+
187
+ ```tsx
188
+ function useTitanAdvisorClientSideID() {
189
+ return useMemo(() => {
190
+ return getValueForEnvironment({
191
+ dev: '669fe6e5cc97eb103be7a620',
192
+ go: '669fe5bff00a0c0fa60b25e4',
193
+ next: '669fe5bff00a0c0fa60b25e4', // same a 'go' but could also be 'qa'
194
+ qa: '669fe6d6f00a0c0fa60b2721',
195
+ stage: '669fe65979abf310b860236e',
196
+ });
197
+ }, []);
198
+ }
199
+ ```
200
+
201
+ :::info
202
+ Note that because the environment is fixed for the life the application, it is safe to memoize the return value.
203
+ :::
204
+
205
+ :::caution
206
+ Do not call `getValueForEnvironment` globally, outside a React component or hook. That usage assumes that all the information needed to determine the environment is available immediately when the Javascript runtime loads and before the application is initialized. While that might work it might also change in the future.
207
+ :::
208
+
156
209
  ### EVENT_BUS_TOKEN - Emitting Events to MFEs
157
210
 
158
211
  Sometimes you may need to send events from the host to the MFE or the other way around, the EventBus ([mitt](https://github.com/developit/mitt) is used under the hood) should cover these needs. Starting <code>v22.1.0</code> you can also send payload.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/docs-uikit",
3
- "version": "28.1.0",
3
+ "version": "28.2.0",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,5 +16,5 @@
16
16
  "cli": {
17
17
  "webpack": false
18
18
  },
19
- "gitHead": "27d173aad0e016014bed59385886d0fd7ca3fb17"
19
+ "gitHead": "df48bdf4994bce3971c7e4f099eeb11ebb4945e6"
20
20
  }