@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.
- package/docs/launchdarkly-service.mdx +142 -0
- package/docs/log-service.mdx +1 -1
- package/docs/startup.mdx +9 -0
- package/docs/web-components.mdx +53 -0
- package/package.json +2 -2
|
@@ -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
|
+
```
|
package/docs/log-service.mdx
CHANGED
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).
|
package/docs/web-components.mdx
CHANGED
|
@@ -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.
|
|
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": "
|
|
19
|
+
"gitHead": "df48bdf4994bce3971c7e4f099eeb11ebb4945e6"
|
|
20
20
|
}
|