init: the first public commit for AFFiNE

This commit is contained in:
DarkSky
2022-07-22 15:49:21 +08:00
commit e3e3741393
1451 changed files with 108124 additions and 0 deletions
@@ -0,0 +1,63 @@
import ffcClient, { Ffc } from 'ffc-js-client-side-sdk';
import type {
IFeatureFlagSet,
IOption,
} from 'ffc-js-client-side-sdk/esm/types';
import { createContext, ReactNode, useEffect, useState } from 'react';
import { config } from './config';
/**
* Init `ffcClient`
* Ported from https://github.com/feature-flags-co/ffc-js-client-side-sdk-react-jotai-demo/blob/main/src/ffc/hooks.ts
* @private
*/
export const useInitFfcEffect = (featureFlagClient: Ffc, option: IOption) => {
const [flags, setFlags] = useState<Record<string, IFeatureFlagSet>>({});
useEffect(() => {
featureFlagClient.init(option);
featureFlagClient.on('ff_update', (changes: unknown[]) => {
if (changes.length) {
setFlags(featureFlagClient.getAllFeatureFlags());
}
});
featureFlagClient.waitUntilReady().then((data: unknown[]) => {
if (data.length) {
setFlags(featureFlagClient.getAllFeatureFlags());
}
});
return () => {
// FIX destroy ffcClient
// ffcClient.logout();
};
}, [featureFlagClient, option, setFlags]);
return flags;
};
export const FeatureFlagsContext = createContext<{
ffcClient: Ffc;
flags: IFeatureFlagSet;
// TODO use genErrorObj
}>({} as any);
/**
* @example
* ```ts
* const App = () => (
* <FeatureFlagsProvider>
* <Page />
* </FeatureFlagsProvider>
* );
* ```
*/
export const FeatureFlagsProvider = ({ children }: { children: ReactNode }) => {
const flags = useInitFfcEffect(ffcClient, config);
return (
<FeatureFlagsContext.Provider value={{ ffcClient, flags }}>
{children}
</FeatureFlagsContext.Provider>
);
};
@@ -0,0 +1,11 @@
import type { IOption } from 'ffc-js-client-side-sdk/esm/types';
export const config: IOption = {
secret: process.env['AFFINE_FEATURE_FLAG_TOKEN'],
anonymous: true,
// user: {
// userName: 'the user's user name',
// id: 'the user's unique identifier'
// }
devModePassword: '-',
};
+111
View File
@@ -0,0 +1,111 @@
// Feature Flags
// Website https://featureflag.co/
// SDK doc https://github.com/feature-flags-co/ffc-js-client-side-sdk
// Demo https://github.com/feature-flags-co/ffc-js-client-side-sdk-react-jotai-demo
import type { IUser } from 'ffc-js-client-side-sdk/esm/types';
import { useContext } from 'react';
import { FeatureFlagsContext } from './Context';
/**
* The `ffcClient` should not export to external modules.
* Do not export this please.
*
* @private
*/
const useFfcClient = () => {
const { ffcClient } = useContext(FeatureFlagsContext);
return ffcClient;
};
/**
* NOTICE: The hook can no trigger the `Ffc.sendFeatureFlagInsight`,
* may lead to inaccurate telemetry data.
*
* Use it discreetly.
*/
const useFlags = () => {
const { flags } = useContext(FeatureFlagsContext);
return flags;
};
type UseFlagFn = (<T = unknown>(flag: string) => T | undefined) &
(<T = unknown>(flag: string, defaultValue: T) => T) &
// Workaround for infers boolean as true or false
// Remove this after the issue fixed
// See https://github.com/microsoft/TypeScript/issues/29400
((flag: string, defaultValue: false) => boolean) &
((flag: string, defaultValue: true) => boolean);
/**
* Returns the specified flag.
*
* The parameter defaultValue should have the same data type with flag type.
*
* @public
* @example
* ```ts
* const App = () => {
* const flag1 = useFlag('flag1', 'default value');
* // ^? string
* const flag2 = useFlag<boolean>('flag2');
* // ^? boolean | undefined
* return <div>flag1: {flag1}</div>
* }
* ```
*/
export const useFlag = ((flag: string, defaultValue: unknown) => {
const flags = useFlags();
const ffcClient = useFfcClient();
// @ts-expect-error This is a BUG for ffc-js-client. ffc-js-client supported typed flag now.
ffcClient.sendFeatureFlagInsight(flag, defaultValue);
const value: unknown = flags[flag];
if (defaultValue === undefined) {
// Can not guess the type, return the flag value directly
return value;
}
if (value === undefined) {
return defaultValue;
}
if (typeof value !== typeof defaultValue) {
console.error(
`[Feature Flags] Flag "${flag}" type mismatch! Make ensure you have set the correct type in feature flag portal! flag type: "${typeof value}", defaultValue type: "${typeof defaultValue}"`,
'flag:',
value,
'defaultValue:',
defaultValue
);
return defaultValue;
}
return value;
}) as UseFlagFn;
/**
* Set the user after initialization
*
* If the user parameter cannot be passed by the init method,
* the following method can be used to set the user after initialization.
*
* See https://github.com/feature-flags-co/ffc-js-client-side-sdk#set-the-user-after-initialization
*/
export const useIdentifyUser = () => {
const ffcClient = useFfcClient();
return (user: IUser) => ffcClient.identify(user);
};
/**
* Set the user to anonymous user
*
* We can manually call the method logout, which will switch the current user back to anonymous user if exists already or create a new anonymous user.
*
* See https://github.com/feature-flags-co/ffc-js-client-side-sdk#set-the-user-to-anonymous-user
*/
export const useLogout = () => {
const ffcClient = useFfcClient();
return () => ffcClient.logout();
};
export { FeatureFlagsProvider } from './Context';