@servicetitan/docs-uikit 31.5.1 → 31.6.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.
@@ -63,14 +63,13 @@ title: BREAKING CHANGES
63
63
 
64
64
  ### [@servicetitan/ajax-handlers](./ajax-handlers)
65
65
 
66
- - Changed [**withMicroservice**](./ajax-handlers#parameters) arguments to a single options object.
66
+ - Changed [**withMicroservice**](./ajax-handlers/with-microservice#parameters) arguments to a single options object.
67
67
 
68
68
  ## v24.0.0
69
69
 
70
70
  ### [@servicetitan/startup](./startup)
71
71
 
72
72
  - Upgraded **Typescript** from v4 to v5, which adds correctness improvements that will reveal previously undetected ambiguities. In particular,
73
-
74
73
  - Type checks for enums are stricter because all **enum** values get their own type
75
74
  - **string** and **boolean** values aren't implicitly converted to numbers. Use the `+` operator to explicitly convert values to numbers in mathematical expressions. (e.g., `return +str > 42;`)
76
75
 
@@ -0,0 +1,12 @@
1
+ ---
2
+ title: AJAX Handlers
3
+ ---
4
+
5
+ #### [CHANGELOG (@servicetitan/ajax-handlers)](https://github.com/servicetitan/uikit/blob/master/packages/ajax-handlers/CHANGELOG.md)
6
+
7
+ `@servicetitan/ajax-handlers` provides utilities for handling AJAX requests, authentication, and response processing in ServiceTitan applications. It includes automatic date parsing, authentication wrappers for protected resources, and comprehensive error handling.
8
+
9
+ ## API
10
+
11
+ - [withMicroservice](./with-microservice.mdx) - Use `withMicroservice` to wrap components and authenticate requests to protected resources with support for Bearer and Token Server authentication.
12
+ - [initAjaxHandlersParseDates](./init-ajax-handlers-parse-dates.mdx) - Use `initAjaxHandlersParseDates` to automatically transform date strings in axios responses into JavaScript Date objects.
@@ -0,0 +1,74 @@
1
+ ---
2
+ title: initAjaxHandlersParseDates
3
+ ---
4
+
5
+ `initAjaxHandlersParseDates` is a function that automatically transforms date strings in axios responses into JavaScript Date objects. This eliminates the need for manual date parsing throughout your application.
6
+
7
+ ## Usage
8
+
9
+ Call this function once in your application's initialization code, typically before making any axios requests:
10
+
11
+ ```tsx
12
+ import { initAjaxHandlersParseDates } from '@servicetitan/ajax-handlers';
13
+
14
+ // Initialize date parsing for all axios responses
15
+ initAjaxHandlersParseDates();
16
+ ```
17
+
18
+ ## How It Works
19
+
20
+ The function adds a response transformer to the global axios defaults that:
21
+
22
+ 1. Automatically detects and parses date strings in response data
23
+ 2. Recursively traverses objects and arrays to find date strings
24
+ 3. Preserves other data types unchanged (including Blobs)
25
+ 4. Handles parsing errors gracefully by returning the original data
26
+
27
+ ## Supported Date Formats
28
+
29
+ The parser recognizes two date formats commonly used in APIs:
30
+
31
+ ### ISO 8601 Format
32
+
33
+ Supports standard ISO date strings with optional time zones and milliseconds:
34
+
35
+ - `2024-03-15T10:30:45Z`
36
+ - `2024-03-15T10:30:45.123Z`
37
+ - `2024-03-15T10:30:45+05:00`
38
+ - `2024-03-15T10:30:45.789-08:00`
39
+
40
+ ### .NET JSON Date Format
41
+
42
+ Supports the legacy .NET JSON date format:
43
+
44
+ - `/Date(1710504645000)/`
45
+ - `/Date(1710504645000-0800)/`
46
+ - `/Date(-62135596800000)/` (negative timestamps for dates before 1970)
47
+
48
+ ## Example
49
+
50
+ ```tsx
51
+ import axios from 'axios';
52
+ import { initAjaxHandlersParseDates } from '@servicetitan/ajax-handlers';
53
+
54
+ // Initialize date parsing once
55
+ initAjaxHandlersParseDates();
56
+
57
+ // Now all axios responses will have dates automatically parsed
58
+ const response = await axios.get('/api/users/123');
59
+
60
+ // response.data might look like:
61
+ // {
62
+ // id: 123,
63
+ // name: 'John Doe',
64
+ // createdAt: Date object (not a string!),
65
+ // lastLogin: Date object (not a string!),
66
+ // metadata: {
67
+ // updatedAt: Date object (not a string!)
68
+ // }
69
+ // }
70
+
71
+ // You can immediately use Date methods
72
+ console.log(response.data.createdAt.getFullYear());
73
+ console.log(response.data.lastLogin.toLocaleDateString());
74
+ ```
@@ -1,15 +1,11 @@
1
1
  ---
2
- title: AJAX Handlers
2
+ title: withMicroservice
3
3
  ---
4
4
 
5
- #### [CHANGELOG (@servicetitan/ajax-handlers)](https://github.com/servicetitan/uikit/blob/master/packages/ajax-handlers/CHANGELOG.md)
6
-
7
- ## withMicroservice
8
-
9
5
  `withMicroservice` is a higher-order function that wraps a component and authenticates
10
6
  its requests to protected resources.
11
7
 
12
- ### Usage
8
+ ## Usage
13
9
 
14
10
  The best way to use `withMicroservice` is to wrap the component in the ES module body. E.g.,
15
11
 
@@ -54,7 +50,7 @@ const App = () => {
54
50
  }
55
51
  ```
56
52
 
57
- ### Parameters
53
+ ## Parameters
58
54
 
59
55
  `withMicroservice` accepts an object with the following properties:
60
56
 
@@ -70,27 +66,27 @@ const App = () => {
70
66
  | `preAuthenticateCallback` | `(error?: any) => void` | (optional) callback to call after pre-authentication succeeds or fails. If pre-authentication fails, the error is passed to the first parameter of the callback. |
71
67
  | `tokens` | `Symbol[]` | (optional) symbols to use to provide `baseURL` to autogenerated API services and child components |
72
68
 
73
- #### authAdapter{#auth-adapter}
69
+ ### authAdapter{#auth-adapter}
74
70
 
75
71
  Use `authAdapter` to select the authentication scheme. One of,
76
72
 
77
- | Value | Description |
78
- | :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------ |
79
- | "bearer" | **Bearer** authentication sends the bearer token returned by `authURL` in the **Authorization** header of requests. Uses BearerTokenAuth adapter. |
80
- | "token" | **Token** authentication uses the Token Server's "silent login" protocol to add secure cookies to requests. Uses TokenServerAuth adapter. |
73
+ | Value | Description |
74
+ | :-------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ |
75
+ | "bearer" | **Bearer** authentication sends the bearer token returned by `authURL` in the **Authorization** header of requests. Uses BearerTokenAuth adapter. |
76
+ | "token" | **Token** authentication uses the Token Server's "silent login" protocol to add secure cookies to requests. Uses TokenServerAuth adapter. |
81
77
  | `(context: WithMicroserviceContext) => AuthAdapter` | Custom authentication uses the adapter returned by a function to decorate requests. |
82
78
 
83
79
  See [Authentication Adapters](#authentication-adapters) for more information.
84
80
 
85
- #### authUrl
81
+ ### authUrl
86
82
 
87
83
  The authentication endpoint for protected resources.
88
84
 
89
- - For **Bearer** authentication, this is the endpoint that returns the bearer token to send in **Authorization** headers. Defaults to `${baseURL}/auth`.
85
+ - For **Bearer** authentication, this is the endpoint that returns the bearer token to send in **Authorization** headers. Defaults to `${baseURL}/auth`.
90
86
 
91
- - For **Token server** authentication, this is the "silent login" endpoint. Defaults to `${baseURL}/bff/silent-login`.
87
+ - For **Token server** authentication, this is the "silent login" endpoint. Defaults to `${baseURL}/bff/silent-login`.
92
88
 
93
- #### preAuthenticate{#pre-authenticate}
89
+ ### preAuthenticate{#pre-authenticate}
94
90
 
95
91
  Controls when authentication happens:
96
92
 
@@ -101,9 +97,9 @@ Controls when authentication happens:
101
97
 
102
98
  When using Token Server authentication, authentication is always performed after the component is loaded and this value is ignored.
103
99
 
104
- #### tokens
100
+ ### tokens
105
101
 
106
- The main purpose of `tokens` is to [provide](./react-ioc#provide) the `baseURL` to autogenerated API services.
102
+ The main purpose of `tokens` is to [provide](../react-ioc#provide) the `baseURL` to autogenerated API services.
107
103
  For example,
108
104
 
109
105
  ```tsx
@@ -138,11 +134,11 @@ const Component = () => {
138
134
  }
139
135
  ```
140
136
 
141
- ### Authentication Adapters{#authentication-adapters}
137
+ ## Authentication Adapters{#authentication-adapters}
142
138
 
143
139
  `withMicroservice` uses authentication adapters in order to perform authentication in different ways depending on your needs.
144
140
 
145
- #### BearerTokenAuth
141
+ ### BearerTokenAuth
146
142
 
147
143
  The default adapter is the `BearerTokenAuth` adapter. When authentication occurs, a request is sent to the `authURL` in order to retrieve a token. Then any requests made using the `baseURL` will add the `Authorization: Bearer ...` header with the stored token.
148
144
 
@@ -156,7 +152,7 @@ const App = withMicroservice({
156
152
  });
157
153
  ```
158
154
 
159
- #### TokenServerAuth{#token-server-auth}
155
+ ### TokenServerAuth{#token-server-auth}
160
156
 
161
157
  The `TokenServerAuth` adapter allows you to authenticate with a backend that is using the `ServiceTitan.Ium.Bff` NuGet package ([see TokenServer documentation for details](/docs/projects/ium/tokenserver-new-app-integration/)).
162
158
 
@@ -177,8 +173,8 @@ const App = withMicroservice({
177
173
  ```tsx title="Custom adapter"
178
174
  const options: TokenServerAuthOptions = {
179
175
  authInfoURL: '/custom/authinfo',
180
- onError: (defaultErrorHandler) => {
181
- console.error('There was an error');
176
+ onError: (defaultErrorHandler, error) => {
177
+ console.error(error, error.data);
182
178
  defaultErrorHandler();
183
179
  },
184
180
  };
@@ -189,12 +185,20 @@ const App = withMicroservice({
189
185
  });
190
186
  ```
191
187
 
192
- ##### TokenServerAuthOptions
193
- | Name | Type | Description |
194
- | :------------ | :------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
195
- | `authInfoURL` | `string` | (optional) URL to fetch authentication parameters from. Defaults to `'/bff/authinfo'`. |
196
- | `onError` | `(defaultErrorHandler: () => void) => void;` | (optional) Callback to call when an error occurs during authentication. Defaults to reloading the page a maximum of 1 time. First parameter is a function to call the default error handler. |
188
+ #### TokenServerAuthOptions
189
+
190
+ | Name | Type | Description |
191
+ | :------------ | :--------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |
192
+ | `authInfoURL` | `string` | (optional) URL to fetch authentication parameters from. Defaults to `'/bff/authinfo'`. |
193
+ | `onError` | `(defaultErrorHandler: () => void, error: Error) => void;` | (optional) Callback to call when an error occurs during authentication. Defaults to reloading the page a maximum of 1 time. |
194
+
195
+ The `onError` callback is passed the following arguments:
196
+
197
+ | Name | Type | Description |
198
+ | :-------------------- | :--------- | :------------------------------------------------------------------------------------------------- |
199
+ | `defaultErrorHandler` | `Function` | The default error handler. |
200
+ | `error` | `Error` | An error object with a `data` property that contains the data associated with the failure, if any. |
197
201
 
198
- ### Authorization
202
+ ## Authorization
199
203
 
200
204
  `withMicroservice` currently only assists with performing authentication for requests of protected resources. There are currently no plans to implement authorization until we see concrete Token Server usage examples by product teams. If you find that having any sort of implementation for authorization would be helpful, especially in regards to Token Server implementation, please bring any ideas or discussions to the Frontend Platform team's attention so that we can create a platform solution.
@@ -0,0 +1,133 @@
1
+ ---
2
+ title: DataDog RUM
3
+ ---
4
+
5
+ #### [CHANGELOG (@servicetitan/datadog-rum)](https://github.com/servicetitan/uikit/blob/master/packages/datadog-rum/CHANGELOG.md)
6
+
7
+ [`@servicetitan/datadog-rum`](https://github.com/servicetitan/uikit/tree/master/packages/datadog-rum) helps configure DataDog RUM JS SDK in standalone applications. It enriches RUM events with information useful for application and MFE monitoring, and troubleshooting.
8
+
9
+ ## Configuration snippet
10
+
11
+ ```tsx
12
+ import { beforeSend, DatadogProvider } from '@servicetitan/datadog-rum';
13
+ import { datadogRum } from '@datadog/browser-rum';
14
+
15
+ const isEnabled = /.*go\d*\.servicetitan\.com/.test(window.location.hostname);
16
+
17
+ if (isEnabled) {
18
+ datadogRum.init({
19
+ applicationId: '<APPLICATION_ID>',
20
+ clientToken: '<CLIENT_TOKEN>',
21
+ site: 'datadoghq.com',
22
+ service: '<SERVICE_NAME>',
23
+ env: '<ENV_NAME>',
24
+ version: '<APPLICATION_VERSION>',
25
+ sessionSampleRate: 100,
26
+ sessionReplaySampleRate: 0,
27
+ defaultPrivacyLevel: 'mask-user-input',
28
+ beforeSend: beforeSend(),
29
+ });
30
+ }
31
+
32
+ const Root = () => {
33
+ const user = useCurrentUser(); // application-specific hook that identifies the user
34
+
35
+ return (
36
+ <DatadogProvider isEnabled={isEnabled} user={user}>
37
+ <Application />
38
+ </DatadogProvider>
39
+ );
40
+ };
41
+ ```
42
+
43
+ ## DatadogProvider
44
+
45
+ `DatadogProvider` is a higher-order component that supplies RUM SDK with:
46
+
47
+ - Information about the user session
48
+ - Sanitized view event names (`@view.name`) when hash-based routing is used
49
+
50
+ ### Usage
51
+
52
+ Wrap your application with `DatadogProvider` close to the root. E.g.,
53
+
54
+ ```tsx
55
+ import { DatadogProvider } from '@servicetitan/datadog-rum';
56
+
57
+ const Root = () =>
58
+ return (
59
+ <DatadogProvider isEnabled={isEnabled} user={user}>
60
+ ...
61
+ </DatadogProvider>
62
+ );
63
+ };
64
+ ```
65
+
66
+ If your application uses hash-based routing, `DatadogProvider` should be placed inside `HashRouter`. E.g.,
67
+
68
+ ```tsx
69
+ import { HashRouter } from 'react-router-dom';
70
+ import { DatadogProvider } from '@servicetitan/datadog-rum';
71
+
72
+ const Root = () => {
73
+ return (
74
+ <HashRouter>
75
+ <DatadogProvider isEnabled={isEnabled} user={user} options={{ hashRouting: true }}>
76
+ ...
77
+ </DatadogProvider>
78
+ </HashRouter>
79
+ );
80
+ };
81
+ ```
82
+
83
+ ### Parameters
84
+
85
+ | Name | Type | Description |
86
+ | :---------- | :-------- | :------------------------------------------ |
87
+ | `isEnabled` | `boolean` | Enables DD RUM instrumentation |
88
+ | `user` | `User` | (optional) User session information |
89
+ | `options` | `Options` | (optional) Additional configuration options |
90
+
91
+ #### `User`
92
+
93
+ | Name | Type | Description |
94
+ | :-------------- | :----------------------------- | :----------------------------------- |
95
+ | `id` | `string` | User ID |
96
+ | `[key: string]` | `string \| number \| string[]` | (optional) Arbitrary user attributes |
97
+
98
+ #### `Options`
99
+
100
+ | Name | Type | Description |
101
+ | :------------ | :-------- | :------------------------------------------ |
102
+ | `hashRouting` | `boolean` | Sanitizes view names for hash-based routing |
103
+
104
+ ## `beforeSend`
105
+
106
+ `beforeSend` is a callback function for enriching RUM events. Supported functionality:
107
+
108
+ - Adds MFE name and version for error and resource events coming from MFEs (`@error.service`, `@resource.service`, `@error.version`, and `@resource.version`)
109
+ - Adds Cloudflare Ray ID for resource events (`@resource.cfRay`)
110
+
111
+ ### Usage
112
+
113
+ ```ts
114
+ import { beforeSend } from '@servicetitan/datadog-rum';
115
+ import { datadogRum } from '@datadog/browser-rum';
116
+
117
+ const isEnabled = /.*go\d*\.servicetitan\.com/.test(window.location.hostname);
118
+
119
+ if (isEnabled) {
120
+ datadogRum.init({
121
+ applicationId: '<APPLICATION_ID>',
122
+ clientToken: '<CLIENT_TOKEN>',
123
+ site: 'datadoghq.com',
124
+ service: '<SERVICE_NAME>',
125
+ env: '<ENV_NAME>',
126
+ version: '<APPLICATION_VERSION>',
127
+ sessionSampleRate: 100,
128
+ sessionReplaySampleRate: 0,
129
+ defaultPrivacyLevel: 'mask-user-input',
130
+ beforeSend: beforeSend(), // <--beforeSend() returns handler that enriches events
131
+ });
132
+ }
133
+ ```
@@ -192,6 +192,32 @@ npm pkg set "main"="dist/index.js" -w packages/lib
192
192
 
193
193
  ---
194
194
 
195
+ ### require-all-react-dependencies
196
+
197
+ Ensures that any package which depends on either `react` or `react-dom` explicitly lists both as dependencies.
198
+ React and ReactDOM are tightly coupled and should always be paired together to avoid runtime issues.
199
+
200
+ #### ✅ Autofix
201
+
202
+ This rule supports autofix.
203
+ It adds the missing `react` or `react-dom` dependency, using the same version that is already present. For example, given:
204
+
205
+ ```json title="package.json"
206
+ {
207
+ "dependencies": {
208
+ "react": "^18.3.1"
209
+ }
210
+ }
211
+ ```
212
+
213
+ It runs:
214
+
215
+ ```sh
216
+ npm pkg set dependencies["react-dom"]="^18.3.1"
217
+ ```
218
+
219
+ ---
220
+
195
221
  ### require-explicit-side-effects
196
222
 
197
223
  Warns if a package is missing the `sideEffects` property in its `package.json`.
@@ -290,6 +316,22 @@ It sets the version of each dependency to the [highest](#highest-versions) of th
290
316
 
291
317
  ---
292
318
 
319
+ ### require-one-react-version
320
+
321
+ Ensures the same version of `react` and `react-dom` is used across the workspace.
322
+
323
+ These two packages are fundamentally designed to work together, with `react-dom` relying heavily on the internal structures and mechanisms exposed by `react`.
324
+
325
+ While React 17 introduced features for gradual upgrades and potentially using multiple React versions in specific scenarios, maintaining synchronized versions of `react` and `react-dom` is the recommended and safest practice to ensure compatibility and avoid unforeseen issues.
326
+
327
+ #### ✅ Autofix
328
+
329
+ This rule supports autofix.
330
+ It sets `react` and `react-dom` to the most common version in the repo.
331
+ If multiple versions tie for the most common, it uses the [highest](#highest-versions) version among the top contenders.
332
+
333
+ ---
334
+
293
335
  ### require-one-uikit-version
294
336
 
295
337
  Ensures the same version of related `uikit` packages is installed across the workspace.
@@ -2,10 +2,204 @@
2
2
  title: test
3
3
  ---
4
4
 
5
- Runs all existing tests in all packages.
5
+ Runs your project's tests.
6
6
 
7
- To run tests a subset of tests is possible to pass paths to specific directories or test files as positional parameters.
7
+ - Supports both Jest and Vitest.
8
+ - Automatically selects the test runner based on your workspace configuration or the `--runner` option.
9
+ - Handles runner-specific arguments and passes them through to the underlying test tool.
10
+
11
+ ## Usage
12
+
13
+ Run all tests with Jest (default):
14
+
15
+ ```sh
16
+ npx startup test
17
+ ```
18
+
19
+ Run all tests with Vitest:
20
+
21
+ ```sh
22
+ npx startup test --runner vitest
23
+ ```
24
+
25
+ :::tip
26
+ Use the double-dash (--) separator to pass arguments to an `npm` script.
27
+ This separator indicates that any arguments following it should be passed directly to the script being executed, rather than being interpreted by `npm` itself.
28
+ For example, given the standard `startup test` script:
29
+
30
+ ```json
31
+ {
32
+ "test": "npx startup test"
33
+ }
34
+ ```
35
+
36
+ Running,
37
+
38
+ ```sh
39
+ npm run test -- --runner vitest
40
+ ```
41
+
42
+ Executes,
43
+
44
+ ```sh
45
+ npx startup test --runner vitest
46
+ ```
47
+
48
+ :::
49
+
50
+ ## Running Specific Tests
51
+
52
+ To run specific tests, pass their file names or paths as additional arguments.
53
+ This works just like running Jest and Vitest directly, simply specify the file(s) you want to test:
54
+
55
+ ### Examples
56
+
57
+ Run a specific test with Jest (default):
58
+
59
+ ```sh
60
+ npx startup test app.test.tsx
61
+ ```
62
+
63
+ Run a specific test with Vitest:
64
+
65
+ ```sh
66
+ npx startup test --runner vitest app.test.tsx
67
+ ```
68
+
69
+ ## Using Jest
70
+
71
+ The `startup test` command uses the Jest test runner by default.
72
+
73
+ ### Configuration
74
+
75
+ The Jest runner provides a default, built-in configuration optimized for ServiceTitan workspaces.
76
+
77
+ You can override the defaults by specifying [Jest options](https://jestjs.io/docs/configuration) in your workspace `package.json` under the `"cli.jest"` key (the `"cli.test"` key also works, for backward compatibility). You can also use a standard Jest config file (such as `jest.config.js`) to override defaults.
78
+
79
+ Any options passed directly via the command line (e.g., `npx startup test --coverage`) take the highest precedence.
80
+
81
+ :::caution
82
+ If your project includes a standard Jest config file and also specifies Jest options in the workspace `package.json`, ensure that the configurations are mutually exclusive.
83
+ To avoid confusing or unexpected behavior, do not specify the same setting in both locations.
84
+ :::
85
+
86
+ ### Examples
87
+
88
+ Use the workspace `package.json` to set up code that runs before each test file is executed:
89
+
90
+ ```json title="package.json"
91
+ {
92
+ "cli": {
93
+ "jest": {
94
+ "setupFilesAfterEnv": ["<rootDir>/jest.setup.ts"]
95
+ }
96
+ }
97
+ }
98
+ ```
99
+
100
+ :::note
101
+ For backward compatibility, you may also use the `ci.test` key:
102
+ :::
103
+
104
+ ---
105
+
106
+ Use `jest.config.js` to increase Jest's `testTimeout` on Windows:
107
+
108
+ ```js title="jest.config.js"
109
+ module.exports = {
110
+ testTimeout: process.platform === 'win32' ? 60 * 1000 : undefined, // increase timeout on Windows
111
+ };
112
+ ```
113
+
114
+ ---
115
+
116
+ Use the command line to collect test coverage:
117
+
118
+ ```sh
119
+ npx startup test --coverage
120
+ ```
121
+
122
+ Use the command line to enable Jest's watch mode:
123
+
124
+ ```sh
125
+ npx startup test --watch
126
+ ```
127
+
128
+ ## Using Vitest
129
+
130
+ ✨ New in **v31.6.0** ✨
131
+
132
+ You can change the default test runner to `vitest` in your workspace's `package.json`:
133
+
134
+ ```json title="package.json"
135
+ {
136
+ "cli": {
137
+ "testRunner": "vitest"
138
+ }
139
+ }
140
+ ```
141
+
142
+ Or override it per invocation with the `--runner` option.
143
+
144
+ ### Configuration
145
+
146
+ The Vitest runner uses a layered configuration approach to provide sensible defaults while allowing full customization.
147
+
148
+ - Uses the default, built-in configuration as a base.
149
+ - Applies workspace overrides from `package.json`.
150
+ - Applies overrides from your Vitest config file.
151
+ - Applies command line options last.
152
+
153
+ 1. **Default Configuration:**
154
+ The runner starts with a built-in default configuration optimized for ServiceTitan workspaces. This includes sensible coverage settings, the environment (`jsdom`), file exclusions, and more.
155
+
156
+ 2. **Workspace Configuration:**
157
+ You can override defaults by specifying [Vitest options](https://vitest.dev/config) in your workspace `package.json` under the `"cli.vitest"` key.
158
+
159
+ 3. **Vitest Config File:**
160
+ If your project includes a standard Vitest config file (such as `vitest.config.ts` or `vite.config.ts`), its settings will override both the defaults and workspace configuration.
161
+
162
+ 4. **Command Line Arguments:**
163
+ Any options passed directly via the command line (e.g., `npx startup test --runner vitest --coverage`) take highest precedence and override all previous configuration layers.
164
+
165
+ ### Examples
166
+
167
+ Use workspace `package.json` to make `vitest` APIs available [globally](https://vitest.dev/config/#globals) like Jest:
168
+
169
+ ```json title="package.json"
170
+ {
171
+ "cli": {
172
+ "vitest": {
173
+ "globals": true
174
+ }
175
+ }
176
+ }
177
+ ```
178
+
179
+ ---
180
+
181
+ Use Vitest config file to disable watch mode:
182
+
183
+ ```ts title="vitest.config.mts"
184
+ import { defineConfig } from 'vitest/config';
185
+
186
+ export default defineConfig({
187
+ test: {
188
+ watch: false,
189
+ },
190
+ });
191
+ ```
192
+
193
+ ---
194
+
195
+ Use the command line to disable watch mode:
196
+
197
+ ```sh
198
+ npx startup test --runner vitest --run
199
+ ```
200
+
201
+ Use the command line to collect code coverage:
8
202
 
9
203
  ```sh
10
- npx startup test -- packages/desktop/app/modules/inventory/
204
+ npx startup test --runner vitest --coverage
11
205
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/docs-uikit",
3
- "version": "31.5.1",
3
+ "version": "31.6.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": "8eb35a6e98b9e3cb3b18b452ce9ba76f278d0e61"
19
+ "gitHead": "533bcbd267e11c88700b29f539ca1cb5de6440ae"
20
20
  }