Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / packages / unleash / UnleashFlagProvider.tsx
blobdf102d8104943a5767c15f1cab9a09b90988391d
1 import type { ReactNode } from 'react';
3 import FlagProvider from '@unleash/proxy-client-react';
4 import type { IConfig, UnleashClient } from 'unleash-proxy-client';
6 import { createPromise } from '@proton/shared/lib/helpers/promise';
7 import type { Api } from '@proton/shared/lib/interfaces';
9 import ProtonUnleashStorageProvider from './storage/UnleashStorageProvider';
11 // Just something dummy to have a valid domain because the library does new URL
12 const prefix = 'https://proton.me/';
13 const url = new URL(prefix);
15 export const createCustomFetch =
16     (api: Api): typeof window.fetch =>
17     (url, config) => {
18         if (typeof url === 'string') {
19             return api({
20                 url: `feature/v2/frontend${url.replace(prefix, '')}`,
21                 headers: config?.headers,
22                 silence: true,
23                 output: 'raw',
24             });
25         }
26         throw new Error('not supported');
27     };
29 const storageProvider = new ProtonUnleashStorageProvider();
31 export const getUnleashConfig = ({ fetch }: Pick<IConfig, 'fetch'>): IConfig => {
32     return {
33         url,
34         clientKey: '-', // set by the server
35         appName: '-', // set by the server
36         refreshInterval: 600, // refreshInterval in seconds, 10 mins
37         disableMetrics: true,
38         fetch,
39         storageProvider,
40     };
43 type SimpleFunc = () => void;
45 export const createUnleashReadyPromise = (client: UnleashClient) => {
46     let promise = createPromise<void>();
47     const readyCallbackSet: Set<SimpleFunc> = new Set();
48     const errorCallbackSet: Set<SimpleFunc> = new Set();
50     // Memoize initial states to keep value consistency between hook instances
51     let readyInitialState = false;
53     const readyListener = () => {
54         readyCallbackSet.forEach((callback) => callback());
55     };
56     const readyCallback: SimpleFunc = () => {
57         if (readyInitialState === false) {
58             promise.resolve();
59             readyInitialState = true;
60         }
61     };
62     const errorListener = () => {
63         errorCallbackSet.forEach((callback) => callback());
64     };
66     if (readyCallbackSet.size === 0) {
67         client.on('ready', readyListener);
68         client.on('error', errorListener);
69     }
71     readyCallbackSet.add(readyCallback);
72     errorCallbackSet.add(readyCallback);
74     return {
75         promise,
76         unsubscribe: () => {
77             readyCallbackSet.delete(readyCallback);
78             errorCallbackSet.delete(readyCallback);
79             if (readyCallbackSet.size === 0) {
80                 client.off('ready', readyListener);
81                 client.off('error', errorListener);
82             }
83         },
84     };
87 interface Props {
88     children: ReactNode;
89     api: Api;
92 const UnleashFlagProvider = ({ children, api }: Props) => {
93     const unleashConfig: IConfig = getUnleashConfig({ fetch: createCustomFetch(api) });
94     return <FlagProvider config={unleashConfig}>{children}</FlagProvider>;
97 export default UnleashFlagProvider;