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 =>
18 if (typeof url === 'string') {
20 url: `feature/v2/frontend${url.replace(prefix, '')}`,
21 headers: config?.headers,
26 throw new Error('not supported');
29 const storageProvider = new ProtonUnleashStorageProvider();
31 export const getUnleashConfig = ({ fetch }: Pick<IConfig, 'fetch'>): IConfig => {
34 clientKey: '-', // set by the server
35 appName: '-', // set by the server
36 refreshInterval: 600, // refreshInterval in seconds, 10 mins
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());
56 const readyCallback: SimpleFunc = () => {
57 if (readyInitialState === false) {
59 readyInitialState = true;
62 const errorListener = () => {
63 errorCallbackSet.forEach((callback) => callback());
66 if (readyCallbackSet.size === 0) {
67 client.on('ready', readyListener);
68 client.on('error', errorListener);
71 readyCallbackSet.add(readyCallback);
72 errorCallbackSet.add(readyCallback);
77 readyCallbackSet.delete(readyCallback);
78 errorCallbackSet.delete(readyCallback);
79 if (readyCallbackSet.size === 0) {
80 client.off('ready', readyListener);
81 client.off('error', errorListener);
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;