@servicetitan/web-components 29.0.0 → 30.1.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/dist/__mocks__/test-component.d.ts.map +1 -1
- package/dist/__mocks__/test-component.js +2 -1
- package/dist/__mocks__/test-component.js.map +1 -1
- package/dist/contexts/mfe-data-context.d.ts +2 -4
- package/dist/contexts/mfe-data-context.d.ts.map +1 -1
- package/dist/contexts/mfe-data-context.js.map +1 -1
- package/dist/contexts/tests/mfe-data-context.test.js.map +1 -1
- package/dist/contexts/tests/mfe-metadata-context.test.js.map +1 -1
- package/dist/event-bus.d.ts +51 -15
- package/dist/event-bus.d.ts.map +1 -1
- package/dist/event-bus.js +46 -17
- package/dist/event-bus.js.map +1 -1
- package/dist/get-value-for-environment.d.ts +5 -1
- package/dist/get-value-for-environment.d.ts.map +1 -1
- package/dist/get-value-for-environment.js +2 -1
- package/dist/get-value-for-environment.js.map +1 -1
- package/dist/loader.d.ts +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +5 -2
- package/dist/loader.js.map +1 -1
- package/dist/render.js +1 -1
- package/dist/render.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/get-ld-service-token.js +1 -1
- package/dist/utils/get-ld-service-token.js.map +1 -1
- package/package.json +14 -13
- package/src/__mocks__/test-component.tsx +3 -1
- package/src/__tests__/event-bus-types.test.ts +507 -0
- package/src/__tests__/event-bus.test.ts +5 -18
- package/src/__tests__/get-value-for-environment.test.ts +40 -22
- package/src/contexts/mfe-data-context.ts +2 -11
- package/src/contexts/tests/mfe-data-context.test.tsx +2 -2
- package/src/contexts/tests/mfe-metadata-context.test.tsx +2 -2
- package/src/event-bus.ts +105 -32
- package/src/get-value-for-environment.ts +9 -2
- package/src/loader.tsx +6 -1
- package/src/render.ts +1 -1
- package/src/types.ts +10 -0
- package/src/utils/get-ld-service-token.ts +1 -1
|
@@ -9,7 +9,7 @@ describe(`[web-components] ${useMFEMetadataContext.name}`, () => {
|
|
|
9
9
|
const shadowRoot = document.createElement('div').attachShadow({ mode: 'open' });
|
|
10
10
|
const portalShadowRoot = document.createElement('span').attachShadow({ mode: 'open' });
|
|
11
11
|
const metadata = { shadowRoot, portalShadowRoot };
|
|
12
|
-
const Wrapper: FC<PropsWithChildren
|
|
12
|
+
const Wrapper: FC<PropsWithChildren> = ({ children }) => {
|
|
13
13
|
return (
|
|
14
14
|
<MFEMetadataContext.Provider value={metadata}>
|
|
15
15
|
{children}
|
|
@@ -23,7 +23,7 @@ describe(`[web-components] ${useMFEMetadataContext.name}`, () => {
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
describe('when the MFEMetadataContext is not provided by a parent', () => {
|
|
26
|
-
const Wrapper: FC<PropsWithChildren
|
|
26
|
+
const Wrapper: FC<PropsWithChildren> = ({ children }) => {
|
|
27
27
|
return <div>{children}</div>;
|
|
28
28
|
};
|
|
29
29
|
|
package/src/event-bus.ts
CHANGED
|
@@ -1,32 +1,79 @@
|
|
|
1
|
+
import { symbolToken, SymbolToken } from '@servicetitan/react-ioc';
|
|
1
2
|
import mitt from 'mitt';
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import { JSON, JSONPrimitive, Serializable } from './types';
|
|
5
|
+
|
|
6
|
+
export const EVENT_BUS_TOKEN = symbolToken<EventBus>('EVENT_BUS_TOKEN');
|
|
7
|
+
|
|
8
|
+
export function typedEventBusToken<EventTypes extends Serializable<EventTypes>>() {
|
|
9
|
+
return symbolToken<EventBus<EventTypes>>('EVENT_BUS_TOKEN');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type EventHandler<EventTypes, Event> = (
|
|
13
|
+
data: Event extends SymbolToken<infer DataType>
|
|
14
|
+
? Serializable<DataType>
|
|
15
|
+
: Event extends keyof EventTypes
|
|
16
|
+
? EventTypes[Event]
|
|
17
|
+
: never
|
|
18
|
+
) => void;
|
|
6
19
|
|
|
7
|
-
export type EventHandler<T = unknown> = (data: T) => void;
|
|
8
20
|
type JobPayload = JSON | void;
|
|
9
21
|
|
|
10
|
-
export type JobEventHandler<
|
|
11
|
-
|
|
22
|
+
export type JobEventHandler<Event> = (defer: {
|
|
23
|
+
/**
|
|
24
|
+
* Successfully complete a job.
|
|
25
|
+
* @param result The value to return from the successfully completed job.
|
|
26
|
+
*/
|
|
27
|
+
resolve(
|
|
28
|
+
...result: Event extends SymbolToken<infer ResultType>
|
|
29
|
+
? undefined extends ResultType
|
|
30
|
+
? [Serializable<ResultType>?]
|
|
31
|
+
: [Serializable<ResultType>]
|
|
32
|
+
: [JobPayload]
|
|
33
|
+
): void;
|
|
34
|
+
/**
|
|
35
|
+
* Fail a job.
|
|
36
|
+
* @param reason The error to return from the failed job.
|
|
37
|
+
*/
|
|
12
38
|
reject(reason?: string | Error): void;
|
|
13
39
|
}) => void;
|
|
14
|
-
export type EventType = string | number | symbol;
|
|
15
|
-
export type SymbolTokenEventType<T, U extends EventType = EventType> =
|
|
16
|
-
U extends SymbolToken<any> ? SymbolToken<T> : U;
|
|
17
40
|
|
|
18
|
-
export
|
|
19
|
-
export class EventBus {
|
|
41
|
+
export class EventBus<EventTypes extends Serializable<EventTypes> = never> {
|
|
20
42
|
job = {
|
|
21
|
-
|
|
22
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Register a job event handler. Jobs event handlers return a result or an error.
|
|
45
|
+
* @param event The job event to handle.
|
|
46
|
+
* @param handler The handler to call when the event occurs. This handler is passed a `resolve` callback to return a successful result, and a `reject` callback to return an error.
|
|
47
|
+
*/
|
|
48
|
+
on: <Event extends SymbolToken<any> | keyof EventTypes>(
|
|
49
|
+
event: Event,
|
|
50
|
+
handler: JobEventHandler<Event>
|
|
51
|
+
) => {
|
|
52
|
+
this.emitter.on(event, handler);
|
|
23
53
|
},
|
|
24
|
-
|
|
25
|
-
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Deregister a job event handler.
|
|
57
|
+
* @param event The previously registered event.
|
|
58
|
+
* @param handler The previously registered handler.
|
|
59
|
+
*/
|
|
60
|
+
off: <Event extends SymbolToken<any> | keyof EventTypes>(
|
|
61
|
+
event: Event,
|
|
62
|
+
handler: JobEventHandler<Event>
|
|
63
|
+
) => {
|
|
64
|
+
this.emitter.off(event, handler);
|
|
26
65
|
},
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Send a job event.
|
|
69
|
+
* @param event The event to send.
|
|
70
|
+
* @returns a Promise that resolves or rejects depending on whether the job completes successfully.
|
|
71
|
+
*/
|
|
72
|
+
emit: <Event extends SymbolToken<any> | keyof EventTypes>(event: Event) => {
|
|
73
|
+
return new Promise<
|
|
74
|
+
Event extends SymbolToken<infer ResultType> ? Serializable<ResultType> : JobPayload
|
|
75
|
+
>((resolve, reject) => {
|
|
76
|
+
this.emitter.emit(event, {
|
|
30
77
|
resolve,
|
|
31
78
|
reject: (reason?: string | Error) => {
|
|
32
79
|
if (typeof reason === 'string' || reason instanceof Error) {
|
|
@@ -42,25 +89,51 @@ export class EventBus {
|
|
|
42
89
|
|
|
43
90
|
private emitter = mitt<any>();
|
|
44
91
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Register an event handler.
|
|
94
|
+
* @param event The event to handle.
|
|
95
|
+
* @param handler The handler to call when the event occurs.
|
|
96
|
+
*/
|
|
97
|
+
on = <Event extends SymbolToken<any> | keyof EventTypes>(
|
|
98
|
+
event: Event,
|
|
99
|
+
handler: EventHandler<EventTypes, Event>
|
|
48
100
|
) => {
|
|
49
|
-
this.emitter.on(
|
|
101
|
+
this.emitter.on(event, handler);
|
|
50
102
|
};
|
|
51
103
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Deregister an event handler.
|
|
106
|
+
* @param event The previously registered event.
|
|
107
|
+
* @param handler The previously registered handler.
|
|
108
|
+
*/
|
|
109
|
+
off = <Event extends SymbolToken<any> | keyof EventTypes>(
|
|
110
|
+
event: Event,
|
|
111
|
+
handler: EventHandler<EventTypes, Event>
|
|
55
112
|
) => {
|
|
56
|
-
this.emitter.off(
|
|
113
|
+
this.emitter.off(event, handler);
|
|
57
114
|
};
|
|
58
115
|
|
|
59
|
-
|
|
60
|
-
|
|
116
|
+
/**
|
|
117
|
+
* Send an event.
|
|
118
|
+
* @param event The event to send.
|
|
119
|
+
* @param data The data to pass to the event's handler.
|
|
120
|
+
*/
|
|
121
|
+
emit = <Event extends SymbolToken<any> | keyof EventTypes>(
|
|
122
|
+
event: Event,
|
|
123
|
+
...data: Event extends SymbolToken<infer DataType>
|
|
124
|
+
? undefined extends DataType
|
|
125
|
+
? [Serializable<DataType>?]
|
|
126
|
+
: [Serializable<DataType>]
|
|
127
|
+
: [EventTypes] extends [never]
|
|
128
|
+
? [(JSON | JSONPrimitive)?]
|
|
129
|
+
: Event extends keyof EventTypes
|
|
130
|
+
? undefined extends EventTypes[Event]
|
|
131
|
+
? [EventTypes[Event]?]
|
|
132
|
+
: [EventTypes[Event]] extends [never]
|
|
133
|
+
? []
|
|
134
|
+
: [EventTypes[Event]]
|
|
135
|
+
: never
|
|
136
|
+
) => {
|
|
137
|
+
this.emitter.emit(event, data[0]);
|
|
61
138
|
};
|
|
62
139
|
}
|
|
63
|
-
|
|
64
|
-
export function useEventBus() {
|
|
65
|
-
return useRef(new EventBus()).current;
|
|
66
|
-
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
// See https://github.com/microsoft/TypeScript/issues/29729 for why LiteralUnion
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
3
|
+
type LiteralUnion<T extends U, U = string> = T | (U & { _?: never });
|
|
4
|
+
|
|
5
|
+
export type Environment = LiteralUnion<'dev' | 'go' | 'next' | 'qa' | 'stage' | 'test'>;
|
|
2
6
|
export type EnvironmentValues = Partial<Record<Environment, string>>;
|
|
3
7
|
|
|
4
8
|
export function getValueForEnvironment(
|
|
@@ -25,7 +29,10 @@ function detectEnvironment(
|
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
for (const key of keys) {
|
|
28
|
-
if (
|
|
32
|
+
if (
|
|
33
|
+
hostname.indexOf(`${key}.servicetitan.com`) >= 0 ||
|
|
34
|
+
(key.endsWith('.st.dev') && hostname.indexOf(key) >= 0)
|
|
35
|
+
) {
|
|
29
36
|
return key;
|
|
30
37
|
}
|
|
31
38
|
}
|
package/src/loader.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
useEffect,
|
|
8
8
|
useImperativeHandle,
|
|
9
9
|
useMemo,
|
|
10
|
+
useRef,
|
|
10
11
|
} from 'react';
|
|
11
12
|
import { ErrorBoundary } from '@servicetitan/error-boundary';
|
|
12
13
|
import { type LDService } from '@servicetitan/launchdarkly-service';
|
|
@@ -23,7 +24,7 @@ import {
|
|
|
23
24
|
} from './common';
|
|
24
25
|
import { MFEContextData } from './contexts/mfe-data-context';
|
|
25
26
|
import { Delayed } from './delayed';
|
|
26
|
-
import { EventBus, EVENT_BUS_TOKEN
|
|
27
|
+
import { EventBus, EVENT_BUS_TOKEN } from './event-bus';
|
|
27
28
|
import { EXPOSED_DEPENDENCIES, EXPOSED_INSTANCE_DEPENDENCIES } from './globals';
|
|
28
29
|
import {
|
|
29
30
|
BundleInfo,
|
|
@@ -260,5 +261,9 @@ function ensureLDService(
|
|
|
260
261
|
return exposedInstanceDependencies;
|
|
261
262
|
}
|
|
262
263
|
|
|
264
|
+
function useEventBus() {
|
|
265
|
+
return useRef(new EventBus()).current;
|
|
266
|
+
}
|
|
267
|
+
|
|
263
268
|
const MINUTE = 1000 * 60;
|
|
264
269
|
const bundleCache = new TtlCache<BundleInfo>({ ttlMs: 15 * MINUTE });
|
package/src/render.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -2,3 +2,13 @@ export type JSONPrimitive = string | number | boolean | null | undefined;
|
|
|
2
2
|
|
|
3
3
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
4
4
|
export type JSON = { [key: string]: JSONPrimitive | JSON[] | JSON };
|
|
5
|
+
|
|
6
|
+
export type Serializable<T> = {
|
|
7
|
+
[P in keyof T]: T[P] extends JSONPrimitive
|
|
8
|
+
? T[P]
|
|
9
|
+
: T[P] extends (infer U)[]
|
|
10
|
+
? Serializable<U>[]
|
|
11
|
+
: T[P] extends JSON | undefined
|
|
12
|
+
? Serializable<T[P]>
|
|
13
|
+
: never;
|
|
14
|
+
};
|