@equinor/fusion-framework-react 5.3.9 → 6.0.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/CHANGELOG.md +150 -131
- package/dist/esm/app/index.js +1 -0
- package/dist/esm/app/index.js.map +1 -1
- package/dist/esm/app/useAppProvider.js.map +1 -1
- package/dist/esm/app/useApps.js.map +1 -1
- package/dist/esm/app/useCurrentApp.js.map +1 -1
- package/dist/esm/app/useCurrentAppModule.js +11 -0
- package/dist/esm/app/useCurrentAppModule.js.map +1 -0
- package/dist/esm/app/useCurrentAppModules.js +9 -3
- package/dist/esm/app/useCurrentAppModules.js.map +1 -1
- package/dist/esm/feature-flag/index.js +5 -1
- package/dist/esm/feature-flag/index.js.map +1 -1
- package/dist/esm/feature-flag/useCurrentAppFeatures.js +12 -0
- package/dist/esm/feature-flag/useCurrentAppFeatures.js.map +1 -0
- package/dist/esm/feature-flag/useFeature.js +16 -0
- package/dist/esm/feature-flag/useFeature.js.map +1 -0
- package/dist/esm/feature-flag/useFeatures.js +27 -0
- package/dist/esm/feature-flag/useFeatures.js.map +1 -0
- package/dist/esm/feature-flag/useFrameworkFeature.js +11 -0
- package/dist/esm/feature-flag/useFrameworkFeature.js.map +1 -0
- package/dist/esm/feature-flag/useFrameworkFeatures.js +11 -0
- package/dist/esm/feature-flag/useFrameworkFeatures.js.map +1 -0
- package/dist/esm/hooks/use-http-client.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/signalr/index.js.map +1 -1
- package/dist/esm/useFramework.js.map +1 -1
- package/dist/esm/useFrameworkModule.js +10 -0
- package/dist/esm/useFrameworkModule.js.map +1 -0
- package/dist/esm/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/app/index.d.ts +1 -0
- package/dist/types/app/useCurrentAppModule.d.ts +8 -0
- package/dist/types/app/useCurrentAppModules.d.ts +2 -2
- package/dist/types/feature-flag/index.d.ts +6 -1
- package/dist/types/feature-flag/useCurrentAppFeatures.d.ts +2 -0
- package/dist/types/feature-flag/useFeature.d.ts +8 -0
- package/dist/types/feature-flag/useFeatures.d.ts +9 -0
- package/dist/types/feature-flag/useFrameworkFeature.d.ts +3 -0
- package/dist/types/feature-flag/useFrameworkFeatures.d.ts +3 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/useFrameworkModule.d.ts +3 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +7 -7
- package/src/app/index.ts +1 -0
- package/src/app/useCurrentAppModule.ts +43 -0
- package/src/app/useCurrentAppModules.ts +14 -4
- package/src/feature-flag/README.md +44 -0
- package/src/feature-flag/index.ts +7 -6
- package/src/feature-flag/useCurrentAppFeatures.ts +19 -0
- package/src/feature-flag/useFeature.ts +47 -0
- package/src/feature-flag/useFeatures.ts +77 -0
- package/src/feature-flag/useFrameworkFeature.ts +22 -0
- package/src/feature-flag/useFrameworkFeatures.ts +20 -0
- package/src/index.tsx +1 -0
- package/src/useFrameworkModule.ts +31 -0
- package/src/version.ts +1 -1
- package/tsconfig.json +4 -1
- package/dist/esm/feature-flag/useFeatureFlags.js +0 -50
- package/dist/esm/feature-flag/useFeatureFlags.js.map +0 -1
- package/dist/types/feature-flag/useFeatureFlags.d.ts +0 -21
- package/src/feature-flag/useFeatureFlags.ts +0 -113
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type { AppConfig, AppManifest, AppType, IApp } from '@equinor/fusion-framework-module-app';
|
|
2
2
|
export { useCurrentApp } from './useCurrentApp';
|
|
3
|
+
export { useCurrentAppModule } from './useCurrentAppModule';
|
|
3
4
|
export { useCurrentAppModules } from './useCurrentAppModules';
|
|
4
5
|
export { useApps } from './useApps';
|
|
5
6
|
export { useAppProvider } from './useAppProvider';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AppModules, AppModulesInstance } from '@equinor/fusion-framework-module-app';
|
|
2
|
+
import { ModuleKey, type AnyModule, ModuleTypes, ModuleType } from '@equinor/fusion-framework-module';
|
|
3
|
+
export declare const useCurrentAppModule: <TType extends unknown = unknown, TKey extends string = ModuleKey<ModuleTypes<AppModules<[TType]>>>>(moduleKey: TKey) => {
|
|
4
|
+
module?: (TType extends AnyModule ? ModuleType<TType> : AppModulesInstance[Extract<"event", TKey> | Extract<"http", TKey> | Extract<"auth", TKey> | Extract<"dispose", TKey>]) | null | undefined;
|
|
5
|
+
error?: unknown;
|
|
6
|
+
complete: boolean;
|
|
7
|
+
};
|
|
8
|
+
export default useCurrentAppModule;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { AppModulesInstance } from '@equinor/fusion-framework-module-app';
|
|
2
|
-
import { Observable } from 'rxjs';
|
|
3
2
|
import { type AnyModule } from '@equinor/fusion-framework-module';
|
|
4
3
|
export declare const useCurrentAppModules: <TModules extends AnyModule[] = []>() => {
|
|
5
|
-
modules
|
|
4
|
+
modules: AppModulesInstance<TModules> | null;
|
|
6
5
|
error?: unknown;
|
|
6
|
+
complete: boolean;
|
|
7
7
|
};
|
|
8
8
|
export default useCurrentAppModules;
|
|
@@ -1 +1,6 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { useFeature } from './useFeature';
|
|
2
|
+
export { useFeatures } from './useFeatures';
|
|
3
|
+
export { useCurrentAppFeatures } from './useCurrentAppFeatures';
|
|
4
|
+
export { useFrameworkFeature } from './useFrameworkFeature';
|
|
5
|
+
export { useFrameworkFeatures } from './useFrameworkFeatures';
|
|
6
|
+
export { IFeatureFlag, IFeatureFlagProvider } from '@equinor/fusion-framework-module-feature-flag';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type IFeatureFlag, type IFeatureFlagProvider } from '@equinor/fusion-framework-module-feature-flag';
|
|
2
|
+
export interface UseFeatureResult<T> {
|
|
3
|
+
feature?: IFeatureFlag<T>;
|
|
4
|
+
error?: unknown;
|
|
5
|
+
toggleFeature: (enable?: boolean) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare const useFeature: <T = unknown>(provider: IFeatureFlagProvider, key: string) => UseFeatureResult<T>;
|
|
8
|
+
export default useFeature;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type IFeatureFlagProvider, type IFeatureFlag } from '@equinor/fusion-framework-module-feature-flag';
|
|
2
|
+
import { type FeatureSelectorFn } from '@equinor/fusion-framework-module-feature-flag/selectors';
|
|
3
|
+
export interface UseFeaturesResult {
|
|
4
|
+
features: IFeatureFlag[];
|
|
5
|
+
error: unknown;
|
|
6
|
+
toggleFeature: (key: string, enable?: boolean) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare const useFeatures: (provider?: IFeatureFlagProvider | null, selector?: FeatureSelectorFn) => UseFeaturesResult;
|
|
9
|
+
export default useFeatures;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,4 +3,5 @@ export { FusionConfigurator } from '@equinor/fusion-framework';
|
|
|
3
3
|
export { createFrameworkProvider } from './create-framework-provider';
|
|
4
4
|
export { FrameworkProvider } from './context';
|
|
5
5
|
export { useFramework } from './useFramework';
|
|
6
|
+
export { useFrameworkModule } from './useFrameworkModule';
|
|
6
7
|
export { default, Framework } from './Framework';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { FusionModules, FusionModulesInstance } from '@equinor/fusion-framework';
|
|
2
|
+
import { AnyModule, ModuleKey, ModuleType, ModuleTypes } from '@equinor/fusion-framework-module';
|
|
3
|
+
export declare const useFrameworkModule: <TType extends unknown = unknown, TKey extends string = ModuleKey<ModuleTypes<FusionModules<[TType]>>>>(name: TKey) => TType extends AnyModule ? ModuleType<TType> | undefined : FusionModulesInstance[Extract<"context", TKey> | Extract<"event", TKey> | Extract<"http", TKey> | Extract<"auth", TKey> | Extract<"services", TKey> | Extract<"serviceDiscovery", TKey> | Extract<"dispose", TKey>] | undefined;
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "
|
|
1
|
+
export declare const version = "6.0.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -48,11 +48,11 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"rxjs": "^7.8.1",
|
|
51
|
-
"@equinor/fusion-framework": "^
|
|
51
|
+
"@equinor/fusion-framework-module": "^4.2.6",
|
|
52
52
|
"@equinor/fusion-framework-react-module": "^3.0.7",
|
|
53
|
-
"@equinor/fusion-framework-react-module-http": "^4.0.5",
|
|
54
53
|
"@equinor/fusion-observable": "^8.1.4",
|
|
55
|
-
"@equinor/fusion-framework-module": "^4.
|
|
54
|
+
"@equinor/fusion-framework-react-module-http": "^4.0.5",
|
|
55
|
+
"@equinor/fusion-framework": "^7.0.28"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/react": "^18.2.20",
|
|
@@ -62,14 +62,14 @@
|
|
|
62
62
|
"typescript": "^5.1.3",
|
|
63
63
|
"@equinor/fusion-framework-module-app": "^5.2.12",
|
|
64
64
|
"@equinor/fusion-framework-react-module-context": "^6.0.18",
|
|
65
|
-
"@equinor/fusion-framework-module-feature-flag": "^0.0
|
|
65
|
+
"@equinor/fusion-framework-module-feature-flag": "^1.0.0"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
|
68
68
|
"@types/react": "^17.0.0 || ^18.0.0",
|
|
69
69
|
"react": "^17.0.0 || ^18.0.0",
|
|
70
70
|
"react-dom": "^17.0.0 || ^18.0.0",
|
|
71
|
-
"@equinor/fusion-framework-module-
|
|
72
|
-
"@equinor/fusion-framework-
|
|
71
|
+
"@equinor/fusion-framework-react-module-signalr": "^2.0.16",
|
|
72
|
+
"@equinor/fusion-framework-module-feature-flag": "^1.0.0"
|
|
73
73
|
},
|
|
74
74
|
"peerDependenciesMeta": {
|
|
75
75
|
"@equinor/fusion-framework-react-module-context": {
|
package/src/app/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type { AppConfig, AppManifest, AppType, IApp } from '@equinor/fusion-framework-module-app';
|
|
2
2
|
|
|
3
3
|
export { useCurrentApp } from './useCurrentApp';
|
|
4
|
+
export { useCurrentAppModule } from './useCurrentAppModule';
|
|
4
5
|
export { useCurrentAppModules } from './useCurrentAppModules';
|
|
5
6
|
export { useApps } from './useApps';
|
|
6
7
|
export { useAppProvider } from './useAppProvider';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AppModules, AppModulesInstance } from '@equinor/fusion-framework-module-app';
|
|
2
|
+
import {
|
|
3
|
+
ModuleKey,
|
|
4
|
+
type AnyModule,
|
|
5
|
+
ModuleTypes,
|
|
6
|
+
ModuleType,
|
|
7
|
+
} from '@equinor/fusion-framework-module';
|
|
8
|
+
import useCurrentAppModules from './useCurrentAppModules';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Retrieves the current app module based on the provided module key.
|
|
12
|
+
* @template TType - The type of the module.
|
|
13
|
+
* @template TKey - The type of the module key.
|
|
14
|
+
* @param {TKey} moduleKey - The key of the module to retrieve.
|
|
15
|
+
* @returns {AnyModule | null | undefined} - The current app module or null if not found.
|
|
16
|
+
* @remarks
|
|
17
|
+
* - when module is null, there are no current selected application
|
|
18
|
+
* - when undefined is, the application has not enabled the requested module
|
|
19
|
+
*/
|
|
20
|
+
export const useCurrentAppModule = <
|
|
21
|
+
TType extends AnyModule | unknown = unknown,
|
|
22
|
+
TKey extends string = ModuleKey<ModuleTypes<AppModules<[TType]>>>,
|
|
23
|
+
>(
|
|
24
|
+
moduleKey: TKey,
|
|
25
|
+
): {
|
|
26
|
+
module?:
|
|
27
|
+
| (TType extends AnyModule
|
|
28
|
+
? ModuleType<TType>
|
|
29
|
+
: AppModulesInstance[Extract<keyof AppModulesInstance, TKey>])
|
|
30
|
+
| null;
|
|
31
|
+
error?: unknown;
|
|
32
|
+
complete: boolean;
|
|
33
|
+
} => {
|
|
34
|
+
const { modules, error, complete } = useCurrentAppModules();
|
|
35
|
+
const module =
|
|
36
|
+
modules === null
|
|
37
|
+
? null
|
|
38
|
+
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
+
(modules[moduleKey as keyof typeof modules] as any);
|
|
40
|
+
return { module, error, complete };
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default useCurrentAppModule;
|
|
@@ -4,6 +4,7 @@ import useCurrentApp from './useCurrentApp';
|
|
|
4
4
|
import { AppModulesInstance } from '@equinor/fusion-framework-module-app';
|
|
5
5
|
import { Observable, of } from 'rxjs';
|
|
6
6
|
import { type AnyModule } from '@equinor/fusion-framework-module';
|
|
7
|
+
import { useObservableState } from '@equinor/fusion-observable/react';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Observers the stream of current app initialized modules
|
|
@@ -14,10 +15,11 @@ import { type AnyModule } from '@equinor/fusion-framework-module';
|
|
|
14
15
|
* @returns the observable instance of initialized modules of the application
|
|
15
16
|
*/
|
|
16
17
|
export const useCurrentAppModules = <TModules extends Array<AnyModule> = []>(): {
|
|
17
|
-
modules
|
|
18
|
+
modules: AppModulesInstance<TModules> | null;
|
|
18
19
|
error?: unknown;
|
|
20
|
+
complete: boolean;
|
|
19
21
|
} => {
|
|
20
|
-
const { currentApp, error } = useCurrentApp<TModules>();
|
|
22
|
+
const { currentApp, error: appError } = useCurrentApp<TModules>();
|
|
21
23
|
const modules$ = useMemo(
|
|
22
24
|
() =>
|
|
23
25
|
currentApp
|
|
@@ -25,9 +27,17 @@ export const useCurrentAppModules = <TModules extends Array<AnyModule> = []>():
|
|
|
25
27
|
: of(null),
|
|
26
28
|
[currentApp],
|
|
27
29
|
);
|
|
28
|
-
|
|
29
|
-
modules
|
|
30
|
+
const {
|
|
31
|
+
value: modules,
|
|
30
32
|
error,
|
|
33
|
+
complete,
|
|
34
|
+
} = useObservableState(modules$, {
|
|
35
|
+
initial: (currentApp?.state.modules as unknown as AppModulesInstance<TModules>) ?? null,
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
modules,
|
|
39
|
+
error: error ?? appError,
|
|
40
|
+
complete,
|
|
31
41
|
};
|
|
32
42
|
};
|
|
33
43
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
__useCurrentAppFeatures__
|
|
2
|
+
|
|
3
|
+
Custom hook for accessing all feature flags for an application
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
const Component = () => {
|
|
7
|
+
const appFeatures = useCurrentAppFeatures();
|
|
8
|
+
if( appFeatures.features === undefined ){
|
|
9
|
+
return <p>The current app does not have features enabled</p>
|
|
10
|
+
}
|
|
11
|
+
return (
|
|
12
|
+
<>
|
|
13
|
+
{
|
|
14
|
+
appFeatures.features.map(feature => (
|
|
15
|
+
<button
|
|
16
|
+
key={feature.key}
|
|
17
|
+
disabled={ appFeatures.readOnly }
|
|
18
|
+
onClick={ () => appFeatures.toggleFeature( feature.key ) }
|
|
19
|
+
>
|
|
20
|
+
{ feature.enabled ? 'disable' : 'enable' } feature { feature.title }
|
|
21
|
+
</button>
|
|
22
|
+
))
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
</>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
__useFrameworkFeature__
|
|
31
|
+
|
|
32
|
+
Custom hook for using a framework feature
|
|
33
|
+
|
|
34
|
+
__useFrameworkFeatures__
|
|
35
|
+
|
|
36
|
+
Custom hook for using all framework features
|
|
37
|
+
|
|
38
|
+
__useFeature__
|
|
39
|
+
|
|
40
|
+
> internal hook for getting a feature from a feature flag module
|
|
41
|
+
|
|
42
|
+
__useFeatures__
|
|
43
|
+
|
|
44
|
+
> internal hook for getting features of a feature flag module
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export { useFeature } from './useFeature';
|
|
2
|
+
export { useFeatures } from './useFeatures';
|
|
3
|
+
export { useCurrentAppFeatures } from './useCurrentAppFeatures';
|
|
4
|
+
export { useFrameworkFeature } from './useFrameworkFeature';
|
|
5
|
+
export { useFrameworkFeatures } from './useFrameworkFeatures';
|
|
6
|
+
|
|
7
|
+
export { IFeatureFlag, IFeatureFlagProvider } from '@equinor/fusion-framework-module-feature-flag';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type FeatureFlagModule } from '@equinor/fusion-framework-module-feature-flag';
|
|
2
|
+
import { useCurrentAppModule } from '../app';
|
|
3
|
+
import { useFeatures, type UseFeaturesResult } from './useFeatures';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Custom hook that returns the current app features and provides a function to toggle a feature.
|
|
7
|
+
* @returns An object containing the current app features, a function to toggle a feature, and any error that occurred.
|
|
8
|
+
*/
|
|
9
|
+
export const useCurrentAppFeatures = (): UseFeaturesResult => {
|
|
10
|
+
const { module, error: moduleError } = useCurrentAppModule<FeatureFlagModule>('featureFlag');
|
|
11
|
+
|
|
12
|
+
const { features, toggleFeature, error } = useFeatures(module);
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
features,
|
|
16
|
+
toggleFeature,
|
|
17
|
+
error: error ?? moduleError,
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useCallback, useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
import { EMPTY } from 'rxjs';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
type IFeatureFlag,
|
|
7
|
+
type IFeatureFlagProvider,
|
|
8
|
+
} from '@equinor/fusion-framework-module-feature-flag';
|
|
9
|
+
|
|
10
|
+
import { useObservableState } from '@equinor/fusion-observable/react';
|
|
11
|
+
|
|
12
|
+
import { findFeature } from '@equinor/fusion-framework-module-feature-flag/selectors';
|
|
13
|
+
|
|
14
|
+
export interface UseFeatureResult<T> {
|
|
15
|
+
feature?: IFeatureFlag<T>;
|
|
16
|
+
error?: unknown;
|
|
17
|
+
/**
|
|
18
|
+
* @param enable - Optional provide new enabled state of the feature flag. _Defaults to inversion of current feature flag state_
|
|
19
|
+
*/
|
|
20
|
+
toggleFeature: (enable?: boolean) => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Custom hook that retrieves a feature flag from a feature flag provider.
|
|
25
|
+
*
|
|
26
|
+
* @template T - The type of the feature flag value.
|
|
27
|
+
* @param {IFeatureFlagProvider} provider - The feature flag provider.
|
|
28
|
+
* @param {string} key - The key of the feature flag.
|
|
29
|
+
* @returns {UseFeatureResult<T>} - An object containing the feature flag value, a function to toggle the feature flag, and any error that occurred.
|
|
30
|
+
*/
|
|
31
|
+
export const useFeature = <T = unknown>(
|
|
32
|
+
provider: IFeatureFlagProvider,
|
|
33
|
+
key: string,
|
|
34
|
+
): UseFeatureResult<T> => {
|
|
35
|
+
const feature$ = useMemo(() => provider.features$.pipe(findFeature<T>(key)), [provider, key]);
|
|
36
|
+
const { value: feature, error } = useObservableState(feature$ ?? EMPTY);
|
|
37
|
+
const toggleFeature = useCallback(
|
|
38
|
+
(enable?: boolean) => {
|
|
39
|
+
const enabled = enable === undefined ? !provider.getFeature(key)?.enabled : enable;
|
|
40
|
+
provider.toggleFeature({ key, enabled });
|
|
41
|
+
},
|
|
42
|
+
[provider, key],
|
|
43
|
+
);
|
|
44
|
+
return { feature, toggleFeature, error };
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default useFeature;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { useCallback, useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
import { of } from 'rxjs';
|
|
4
|
+
import { map } from 'rxjs/operators';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
type IFeatureFlagProvider,
|
|
8
|
+
type IFeatureFlag,
|
|
9
|
+
} from '@equinor/fusion-framework-module-feature-flag';
|
|
10
|
+
|
|
11
|
+
import { type FeatureSelectorFn } from '@equinor/fusion-framework-module-feature-flag/selectors';
|
|
12
|
+
|
|
13
|
+
import { useObservableState } from '@equinor/fusion-observable/react';
|
|
14
|
+
|
|
15
|
+
export interface UseFeaturesResult {
|
|
16
|
+
features: IFeatureFlag[];
|
|
17
|
+
error: unknown;
|
|
18
|
+
/**
|
|
19
|
+
* @param key - The key of the feature flag.
|
|
20
|
+
* @param enable - Optional provide new enabled state of the feature flag. _Defaults to inversion of current feature flag state_
|
|
21
|
+
*/
|
|
22
|
+
toggleFeature: (key: string, enable?: boolean) => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Custom hook that provides access to the feature flags and their values.
|
|
27
|
+
*
|
|
28
|
+
* @param provider - The feature flag provider.
|
|
29
|
+
* @param selector - Optional function to filter the feature flags.
|
|
30
|
+
* @returns An object containing the features, any error that occurred while retrieving them, and a function to set the enabled state of a feature flag.
|
|
31
|
+
* @throws Error if the feature flag provider is missing.
|
|
32
|
+
*/
|
|
33
|
+
export const useFeatures = (
|
|
34
|
+
provider?: IFeatureFlagProvider | null,
|
|
35
|
+
selector?: FeatureSelectorFn,
|
|
36
|
+
): UseFeaturesResult => {
|
|
37
|
+
/**
|
|
38
|
+
* Custom hook that provides access to the feature flags and their values.
|
|
39
|
+
*
|
|
40
|
+
* @returns An object containing the features and any error that occurred while retrieving them.
|
|
41
|
+
*/
|
|
42
|
+
const { value: features, error } = useObservableState(
|
|
43
|
+
useMemo(() => {
|
|
44
|
+
if (provider) {
|
|
45
|
+
return provider?.features$.pipe(
|
|
46
|
+
map((x) => {
|
|
47
|
+
const values = Object.values(x);
|
|
48
|
+
return selector ? values.filter(selector) : values;
|
|
49
|
+
}),
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return of([]);
|
|
53
|
+
}, [provider, selector]),
|
|
54
|
+
{ initial: Object.values(provider?.features ?? {}) },
|
|
55
|
+
);
|
|
56
|
+
/**
|
|
57
|
+
* Sets the enabled state of a feature flag.
|
|
58
|
+
*
|
|
59
|
+
* @param key - The key of the feature flag.
|
|
60
|
+
* @param enable - The new enabled state of the feature flag.
|
|
61
|
+
* @throws Error if IFeatureFlagProvider is missing.
|
|
62
|
+
*/
|
|
63
|
+
const toggleFeature = useCallback(
|
|
64
|
+
(key: string, enable?: boolean) => {
|
|
65
|
+
if (!provider) {
|
|
66
|
+
throw new Error('Missing IFeatureFlagProvider.');
|
|
67
|
+
}
|
|
68
|
+
const enabled = enable === undefined ? !provider.getFeature(key)?.enabled : enable;
|
|
69
|
+
|
|
70
|
+
provider.toggleFeature({ key, enabled });
|
|
71
|
+
},
|
|
72
|
+
[provider],
|
|
73
|
+
);
|
|
74
|
+
return { features, error, toggleFeature };
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export default useFeatures;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type FeatureFlagModule } from '@equinor/fusion-framework-module-feature-flag';
|
|
2
|
+
|
|
3
|
+
import { useFrameworkModule } from '../useFrameworkModule';
|
|
4
|
+
import { useFeature } from './useFeature';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Custom hook that allows accessing a framework feature based on a given feature flag key.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The type of the feature.
|
|
10
|
+
* @param {string} key - The feature flag key.
|
|
11
|
+
* @returns {ReturnType<typeof useFeature<T>>} - The result of the feature hook.
|
|
12
|
+
* @throws {Error} - If feature flagging is not enabled in the framework.
|
|
13
|
+
*/
|
|
14
|
+
export const useFrameworkFeature = <T>(key: string): ReturnType<typeof useFeature<T>> => {
|
|
15
|
+
const provider = useFrameworkModule<FeatureFlagModule>('featureFlag');
|
|
16
|
+
if (!provider) {
|
|
17
|
+
throw Error('Feature flagging is not enabled in the framework');
|
|
18
|
+
}
|
|
19
|
+
return useFeature(provider, key);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default useFrameworkFeature;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type FeatureFlagModule } from '@equinor/fusion-framework-module-feature-flag';
|
|
2
|
+
|
|
3
|
+
import { useFrameworkModule } from '../useFrameworkModule';
|
|
4
|
+
import { useFeatures } from './useFeatures';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Custom hook that provides access to framework-specific feature flags.
|
|
8
|
+
* It returns the result of the `useFeatures` hook from the `featureFlag` module.
|
|
9
|
+
* @returns The result of the `useFeatures` hook.
|
|
10
|
+
* @throws Error if feature flagging is not enabled in the framework.
|
|
11
|
+
*/
|
|
12
|
+
export const useFrameworkFeatures = (): ReturnType<typeof useFeatures> => {
|
|
13
|
+
const provider = useFrameworkModule<FeatureFlagModule>('featureFlag');
|
|
14
|
+
if (!provider) {
|
|
15
|
+
throw Error('Feature flagging is not enabled in the framework');
|
|
16
|
+
}
|
|
17
|
+
return useFeatures(provider);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default useFrameworkFeatures;
|
package/src/index.tsx
CHANGED
|
@@ -10,5 +10,6 @@ export { createFrameworkProvider } from './create-framework-provider';
|
|
|
10
10
|
export { FrameworkProvider } from './context';
|
|
11
11
|
|
|
12
12
|
export { useFramework } from './useFramework';
|
|
13
|
+
export { useFrameworkModule } from './useFrameworkModule';
|
|
13
14
|
|
|
14
15
|
export { default, Framework } from './Framework';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { FusionModules, FusionModulesInstance } from '@equinor/fusion-framework';
|
|
2
|
+
import { useFramework } from './useFramework';
|
|
3
|
+
import { AnyModule, ModuleKey, ModuleType, ModuleTypes } from '@equinor/fusion-framework-module';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Retrieves a module from the framework instance based on its name.
|
|
7
|
+
*
|
|
8
|
+
* @template TType - The type of the module to retrieve.
|
|
9
|
+
* @template TKey - The type of the module name.
|
|
10
|
+
* @param name - The name of the module to retrieve.
|
|
11
|
+
* @returns The requested module from the framework instance.
|
|
12
|
+
* @throws Error if the requested module is not included in the framework instance.
|
|
13
|
+
*/
|
|
14
|
+
export const useFrameworkModule = <
|
|
15
|
+
TType extends AnyModule | unknown = unknown,
|
|
16
|
+
TKey extends string = ModuleKey<ModuleTypes<FusionModules<[TType]>>>,
|
|
17
|
+
>(
|
|
18
|
+
name: TKey,
|
|
19
|
+
): TType extends AnyModule
|
|
20
|
+
? ModuleType<TType> | undefined
|
|
21
|
+
: FusionModulesInstance[Extract<keyof FusionModulesInstance, TKey>] | undefined => {
|
|
22
|
+
const framework = useFramework();
|
|
23
|
+
// TODO
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
const module = framework.modules[name];
|
|
27
|
+
if (!module) {
|
|
28
|
+
console.warn(`the requested module [${module}] is not included in the framework instance`);
|
|
29
|
+
}
|
|
30
|
+
return module;
|
|
31
|
+
};
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '
|
|
2
|
+
export const version = '6.0.0';
|
package/tsconfig.json
CHANGED
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
{
|
|
16
16
|
"path": "../../modules/app"
|
|
17
17
|
},
|
|
18
|
+
{
|
|
19
|
+
"path": "../../modules/feature-flag"
|
|
20
|
+
},
|
|
18
21
|
{
|
|
19
22
|
"path": "../../modules/service-discovery"
|
|
20
23
|
},
|
|
@@ -26,7 +29,7 @@
|
|
|
26
29
|
},
|
|
27
30
|
{
|
|
28
31
|
"path": "../modules/signalr"
|
|
29
|
-
}
|
|
32
|
+
},
|
|
30
33
|
],
|
|
31
34
|
"include": [
|
|
32
35
|
"src/**/*",
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { useCallback, useMemo } from 'react';
|
|
2
|
-
import { useObservableState } from '@equinor/fusion-observable/react';
|
|
3
|
-
import { useCurrentAppModules } from '../app/useCurrentAppModules';
|
|
4
|
-
import { EMPTY, map } from 'rxjs';
|
|
5
|
-
import { useFramework } from '../useFramework';
|
|
6
|
-
export const useCurrentAppFeatureFlag = (key) => {
|
|
7
|
-
const provider$ = useCurrentAppModules().modules$.pipe(map((val) => val === null || val === void 0 ? void 0 : val.featureFlag));
|
|
8
|
-
const { value: provider } = useObservableState(provider$);
|
|
9
|
-
const { value: feature, error } = useObservableState(_useFeatureFlag(key, provider));
|
|
10
|
-
const setFeatureEnabled = _useSetFeatureflag(provider);
|
|
11
|
-
return { feature, error, setFeatureEnabled };
|
|
12
|
-
};
|
|
13
|
-
export const useCurrentAppFeatureFlags = () => {
|
|
14
|
-
const provider$ = useCurrentAppModules().modules$.pipe(map((val) => val === null || val === void 0 ? void 0 : val.featureFlag));
|
|
15
|
-
const { value: provider } = useObservableState(provider$);
|
|
16
|
-
const { value: features, error } = useObservableState(_useFeatureFlags(provider));
|
|
17
|
-
const setFeatureEnabled = _useSetFeatureflag(provider);
|
|
18
|
-
return { features, error, setFeatureEnabled };
|
|
19
|
-
};
|
|
20
|
-
export const useFrameworkFeatureFlag = (key) => {
|
|
21
|
-
const provider = useFramework().modules.featureFlag;
|
|
22
|
-
const { value: feature, error } = useObservableState(_useFeatureFlag(key, provider));
|
|
23
|
-
const setFeatureEnabled = _useSetFeatureflag(provider);
|
|
24
|
-
return { feature, error, setFeatureEnabled };
|
|
25
|
-
};
|
|
26
|
-
export const useFrameworkFeatureFlags = () => {
|
|
27
|
-
const provider = useFramework().modules.featureFlag;
|
|
28
|
-
const { value: features, error } = useObservableState(_useFeatureFlags(provider));
|
|
29
|
-
const setFeatureEnabled = _useSetFeatureflag(provider);
|
|
30
|
-
return { features, error, setFeatureEnabled };
|
|
31
|
-
};
|
|
32
|
-
const _useFeatureFlag = (key, provider) => {
|
|
33
|
-
return useMemo(() => {
|
|
34
|
-
return provider ? provider.getFeature(key) : EMPTY;
|
|
35
|
-
}, [provider, key]);
|
|
36
|
-
};
|
|
37
|
-
const _useFeatureFlags = (provider) => {
|
|
38
|
-
return useMemo(() => {
|
|
39
|
-
return provider ? provider.getFeatures((_) => true) : EMPTY;
|
|
40
|
-
}, [provider]);
|
|
41
|
-
};
|
|
42
|
-
const _useSetFeatureflag = (provider) => {
|
|
43
|
-
return useCallback((key, enabled) => {
|
|
44
|
-
if (!provider) {
|
|
45
|
-
throw new Error('Missing IFeatureFlagProvider.');
|
|
46
|
-
}
|
|
47
|
-
provider.toggleFeature({ key, enabled });
|
|
48
|
-
}, [provider]);
|
|
49
|
-
};
|
|
50
|
-
//# sourceMappingURL=useFeatureFlags.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useFeatureFlags.js","sourceRoot":"","sources":["../../../src/feature-flag/useFeatureFlags.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { IFeatureFlag } from '@equinor/fusion-framework-module-feature-flag';
|
|
2
|
-
export declare const useCurrentAppFeatureFlag: (key: string) => {
|
|
3
|
-
feature: IFeatureFlag<unknown> | undefined;
|
|
4
|
-
error: unknown;
|
|
5
|
-
setFeatureEnabled: (key: string, enabled: boolean) => void;
|
|
6
|
-
};
|
|
7
|
-
export declare const useCurrentAppFeatureFlags: () => {
|
|
8
|
-
features: IFeatureFlag<unknown>[] | undefined;
|
|
9
|
-
error: unknown;
|
|
10
|
-
setFeatureEnabled: (key: string, enabled: boolean) => void;
|
|
11
|
-
};
|
|
12
|
-
export declare const useFrameworkFeatureFlag: (key: string) => {
|
|
13
|
-
feature: IFeatureFlag<unknown> | undefined;
|
|
14
|
-
error: unknown;
|
|
15
|
-
setFeatureEnabled: (key: string, enabled: boolean) => void;
|
|
16
|
-
};
|
|
17
|
-
export declare const useFrameworkFeatureFlags: () => {
|
|
18
|
-
features: IFeatureFlag<unknown>[] | undefined;
|
|
19
|
-
error: unknown;
|
|
20
|
-
setFeatureEnabled: (key: string, enabled: boolean) => void;
|
|
21
|
-
};
|