@equinor/fusion-framework-react 8.0.0 → 8.0.1

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.
Files changed (76) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/esm/app/useAppProvider.js +1 -0
  3. package/dist/esm/app/useAppProvider.js.map +1 -1
  4. package/dist/esm/app/useCurrentApp.js +1 -0
  5. package/dist/esm/app/useCurrentApp.js.map +1 -1
  6. package/dist/esm/app/useCurrentAppModule.js +13 -6
  7. package/dist/esm/app/useCurrentAppModule.js.map +1 -1
  8. package/dist/esm/context.js +1 -20
  9. package/dist/esm/context.js.map +1 -1
  10. package/dist/esm/create-framework-provider.js +1 -1
  11. package/dist/esm/create-framework-provider.js.map +1 -1
  12. package/dist/esm/feature-flag/useFeature.js +4 -1
  13. package/dist/esm/feature-flag/useFeature.js.map +1 -1
  14. package/dist/esm/feature-flag/useFeatures.js +10 -1
  15. package/dist/esm/feature-flag/useFeatures.js.map +1 -1
  16. package/dist/esm/feature-flag/useFrameworkFeature.js +1 -0
  17. package/dist/esm/feature-flag/useFrameworkFeature.js.map +1 -1
  18. package/dist/esm/feature-flag/useFrameworkFeatures.js +1 -0
  19. package/dist/esm/feature-flag/useFrameworkFeatures.js.map +1 -1
  20. package/dist/esm/framework-provider.js +21 -0
  21. package/dist/esm/framework-provider.js.map +1 -0
  22. package/dist/esm/hooks/index.js +2 -2
  23. package/dist/esm/hooks/index.js.map +1 -1
  24. package/dist/esm/hooks/{use-current-user.js → useCurrentUser.js} +1 -1
  25. package/dist/esm/hooks/useCurrentUser.js.map +1 -0
  26. package/dist/esm/hooks/{use-http-client.js → useHttpClient.js} +3 -2
  27. package/dist/esm/hooks/useHttpClient.js.map +1 -0
  28. package/dist/esm/http/index.js +1 -1
  29. package/dist/esm/http/index.js.map +1 -1
  30. package/dist/esm/index.js +1 -1
  31. package/dist/esm/index.js.map +1 -1
  32. package/dist/esm/signalr/index.js +1 -31
  33. package/dist/esm/signalr/index.js.map +1 -1
  34. package/dist/esm/signalr/useSignalR.js +33 -0
  35. package/dist/esm/signalr/useSignalR.js.map +1 -0
  36. package/dist/esm/useFramework.js +2 -0
  37. package/dist/esm/useFramework.js.map +1 -1
  38. package/dist/esm/useFrameworkModule.js +3 -2
  39. package/dist/esm/useFrameworkModule.js.map +1 -1
  40. package/dist/esm/version.js +1 -1
  41. package/dist/tsconfig.tsbuildinfo +1 -1
  42. package/dist/types/Framework.d.ts +1 -1
  43. package/dist/types/app/useAppProvider.d.ts +1 -1
  44. package/dist/types/context.d.ts +1 -20
  45. package/dist/types/framework-provider.d.ts +19 -0
  46. package/dist/types/hooks/index.d.ts +2 -2
  47. package/dist/types/http/index.d.ts +1 -1
  48. package/dist/types/index.d.ts +1 -1
  49. package/dist/types/signalr/index.d.ts +1 -24
  50. package/dist/types/signalr/useSignalR.d.ts +24 -0
  51. package/dist/types/version.d.ts +1 -1
  52. package/package.json +15 -15
  53. package/src/app/useAppProvider.ts +1 -0
  54. package/src/app/useCurrentApp.ts +1 -0
  55. package/src/app/useCurrentAppModule.ts +13 -7
  56. package/src/context.ts +1 -21
  57. package/src/create-framework-provider.tsx +2 -2
  58. package/src/feature-flag/useFeature.ts +8 -1
  59. package/src/feature-flag/useFeatures.ts +10 -1
  60. package/src/feature-flag/useFrameworkFeature.ts +1 -0
  61. package/src/feature-flag/useFrameworkFeatures.ts +1 -0
  62. package/src/framework-provider.ts +21 -0
  63. package/src/hooks/index.ts +2 -2
  64. package/src/hooks/{use-http-client.ts → useHttpClient.ts} +2 -1
  65. package/src/http/index.ts +1 -1
  66. package/src/index.tsx +1 -1
  67. package/src/signalr/index.ts +1 -39
  68. package/src/signalr/useSignalR.ts +40 -0
  69. package/src/useFramework.ts +2 -0
  70. package/src/useFrameworkModule.ts +3 -2
  71. package/src/version.ts +1 -1
  72. package/dist/esm/hooks/use-current-user.js.map +0 -1
  73. package/dist/esm/hooks/use-http-client.js.map +0 -1
  74. /package/dist/types/hooks/{use-current-user.d.ts → useCurrentUser.d.ts} +0 -0
  75. /package/dist/types/hooks/{use-http-client.d.ts → useHttpClient.d.ts} +0 -0
  76. /package/src/hooks/{use-current-user.ts → useCurrentUser.ts} +0 -0
@@ -43,5 +43,5 @@ export declare const Framework: (props: PropsWithChildren<{
43
43
  readonly configure: ConfigureCallback;
44
44
  readonly fallback: NonNullable<ReactNode> | null;
45
45
  readonly parent?: ModulesInstance<any>;
46
- }>) => import("react/jsx-runtime").JSX.Element;
46
+ }>) => import("react").JSX.Element;
47
47
  export default Framework;
@@ -13,5 +13,5 @@ import type { AppModule } from '@equinor/fusion-framework-module-app';
13
13
  * provider.getAppManifests().subscribe(console.log);
14
14
  * ```
15
15
  */
16
- export declare const useAppProvider: () => FusionModulesInstance<[AppModule]>["app"];
16
+ export declare const useAppProvider: () => FusionModulesInstance<[AppModule]>['app'];
17
17
  export default useAppProvider;
@@ -1,20 +1 @@
1
- import type { Fusion } from '@equinor/fusion-framework';
2
- /**
3
- * Component for providing framework.
4
- *
5
- * @remarks
6
- * Should be created by {@link createFrameworkProvider}
7
- *
8
- * @example
9
- * ```tsx
10
- * import {FrameworkProvider} from '@equinor/fusion-framework-react';
11
- * export const Component = (args: React.PropsWithChildren<{framework: Fusion}>) => {
12
- * return (
13
- * <FrameworkProvider value={args.framework}>
14
- * {args.children}
15
- * </FrameworkProvider>
16
- * );
17
- * }
18
- * ```
19
- */
20
- export declare const FrameworkProvider: import("react").Provider<Fusion<any> | null>;
1
+ export {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Component for providing framework.
3
+ *
4
+ * @remarks
5
+ * Should be created by {@link createFrameworkProvider}
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import {FrameworkProvider} from '@equinor/fusion-framework-react';
10
+ * export const Component = (args: React.PropsWithChildren<{framework: Fusion}>) => {
11
+ * return (
12
+ * <FrameworkProvider value={args.framework}>
13
+ * {args.children}
14
+ * </FrameworkProvider>
15
+ * );
16
+ * }
17
+ * ```
18
+ */
19
+ export declare const FrameworkProvider: import("react").Provider<import("@equinor/fusion-framework").Fusion<any> | null>;
@@ -6,5 +6,5 @@
6
6
  *
7
7
  * @module
8
8
  */
9
- export { useCurrentUser } from './use-current-user';
10
- export { useHttpClient } from './use-http-client';
9
+ export { useCurrentUser } from './useCurrentUser';
10
+ export { useHttpClient } from './useHttpClient';
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @module
10
10
  */
11
- export { useHttpClient as useFrameworkHttpClient } from '../hooks/use-http-client';
11
+ export { useHttpClient as useFrameworkHttpClient } from '../hooks/useHttpClient';
12
12
  export * from '@equinor/fusion-framework-react-module-http';
@@ -13,7 +13,7 @@
13
13
  export type { Fusion } from '@equinor/fusion-framework';
14
14
  export { FusionConfigurator } from '@equinor/fusion-framework';
15
15
  export { createFrameworkProvider } from './create-framework-provider';
16
- export { FrameworkProvider } from './context';
16
+ export { FrameworkProvider } from './framework-provider';
17
17
  export { useFramework } from './useFramework';
18
18
  export { useFrameworkModule } from './useFrameworkModule';
19
19
  export { default, Framework } from './Framework';
@@ -1,24 +1 @@
1
- import { useProviderTopic } from '@equinor/fusion-framework-react-module-signalr';
2
- /**
3
- * hook for subscribing to a topic of a SignalR hub
4
- *
5
- * @example
6
- ```ts
7
- // config.ts
8
- import {enableSignalR} from '@equinor/fusion-framework-react-module-signalr';
9
- (configurator) => enableSignalR(configurator, 'notifications');
10
-
11
- // myHook.ts
12
- const myHook = () => {
13
- const topic = useSignalR('notifications', 'foo');
14
- return useObservableState(topic).next;
15
- }
16
- ```
17
- *
18
- * @see {@link [module signalr](https://equinor.github.io/fusion-framework/modules/signalr)}
19
- *
20
- * @param hubId identifier of connection hub (must be configured)
21
- * @param topicId identifier of topic to connect to
22
- * @returns Topic
23
- */
24
- export declare const useSignalR: <T>(hubId: string, topicId: string) => ReturnType<typeof useProviderTopic<T>>;
1
+ export { useSignalR } from './useSignalR.js';
@@ -0,0 +1,24 @@
1
+ import { useProviderTopic } from '@equinor/fusion-framework-react-module-signalr';
2
+ /**
3
+ * hook for subscribing to a topic of a SignalR hub
4
+ *
5
+ * @example
6
+ ```ts
7
+ // config.ts
8
+ import {enableSignalR} from '@equinor/fusion-framework-react-module-signalr';
9
+ (configurator) => enableSignalR(configurator, 'notifications');
10
+
11
+ // myHook.ts
12
+ const myHook = () => {
13
+ const topic = useSignalR('notifications', 'foo');
14
+ return useObservableState(topic).next;
15
+ }
16
+ ```
17
+ *
18
+ * @see {@link [module signalr](https://equinor.github.io/fusion-framework/modules/signalr)}
19
+ *
20
+ * @param hubId identifier of connection hub (must be configured)
21
+ * @param topicId identifier of topic to connect to
22
+ * @returns Topic
23
+ */
24
+ export declare const useSignalR: <T>(hubId: string, topicId: string) => ReturnType<typeof useProviderTopic<T>>;
@@ -1 +1 @@
1
- export declare const version = "8.0.0";
1
+ export declare const version = "8.0.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-react",
3
- "version": "8.0.0",
3
+ "version": "8.0.1",
4
4
  "description": "",
5
5
  "main": "dist/esm/index.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -72,31 +72,31 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "rxjs": "^7.8.1",
75
- "@equinor/fusion-framework": "^8.0.0",
76
- "@equinor/fusion-framework-module": "^6.0.0",
77
- "@equinor/fusion-framework-react-module-http": "^11.0.0",
78
- "@equinor/fusion-framework-react-module": "^4.0.0",
79
- "@equinor/fusion-observable": "^9.0.0"
75
+ "@equinor/fusion-framework": "^8.0.11",
76
+ "@equinor/fusion-framework-react-module": "^4.0.2",
77
+ "@equinor/fusion-framework-react-module-http": "^11.0.1",
78
+ "@equinor/fusion-observable": "^9.1.1",
79
+ "@equinor/fusion-framework-module": "^6.1.1"
80
80
  },
81
81
  "devDependencies": {
82
82
  "@types/react": "^19.2.7",
83
83
  "@types/react-dom": "^19.2.3",
84
84
  "react": "^19.2.1",
85
85
  "react-dom": "^19.2.1",
86
- "typescript": "^5.9.3",
87
- "@equinor/fusion-framework-module-app": "^8.0.0",
88
- "@equinor/fusion-framework-module-event": "^6.0.0",
89
- "@equinor/fusion-framework-module-feature-flag": "^2.0.0",
90
- "@equinor/fusion-framework-module-msal": "^8.0.0",
91
- "@equinor/fusion-framework-react-module-context": "^7.0.0",
92
- "@equinor/fusion-framework-react-module-signalr": "^4.0.0"
86
+ "typescript": "^7.0.2",
87
+ "@equinor/fusion-framework-module-app": "^8.0.3",
88
+ "@equinor/fusion-framework-module-event": "^6.0.1",
89
+ "@equinor/fusion-framework-module-msal": "^10.0.2",
90
+ "@equinor/fusion-framework-react-module-context": "^7.0.2",
91
+ "@equinor/fusion-framework-module-feature-flag": "^2.0.2",
92
+ "@equinor/fusion-framework-react-module-signalr": "^4.0.3"
93
93
  },
94
94
  "peerDependencies": {
95
95
  "@types/react": "^18.0.0 || ^19.0.0",
96
96
  "react": "^18.0.0 || ^19.0.0",
97
97
  "react-dom": "^18.0.0 || ^19.0.0",
98
- "@equinor/fusion-framework-react-module-signalr": "^4.0.0",
99
- "@equinor/fusion-framework-module-feature-flag": "^2.0.0"
98
+ "@equinor/fusion-framework-module-feature-flag": "^2.0.2",
99
+ "@equinor/fusion-framework-react-module-signalr": "^4.0.3"
100
100
  },
101
101
  "peerDependenciesMeta": {
102
102
  "@equinor/fusion-framework-module-event": {
@@ -18,6 +18,7 @@ import { useFramework } from '../useFramework';
18
18
  */
19
19
  export const useAppProvider = (): FusionModulesInstance<[AppModule]>['app'] => {
20
20
  const provider = useFramework<[AppModule]>().modules.app;
21
+ // Fail fast when the AppModule has not been configured on the framework
21
22
  if (!provider) {
22
23
  throw Error('Current framework does not have AppModule configured');
23
24
  }
@@ -50,6 +50,7 @@ export const useCurrentApp = <
50
50
  error?: unknown;
51
51
  } => {
52
52
  const provider = useFramework<[AppModule]>().modules.app;
53
+ // Fail fast when the AppModule has not been configured on the framework
53
54
  if (!provider) {
54
55
  throw Error('Current framework does not have AppModule configured');
55
56
  }
@@ -38,13 +38,19 @@ export const useCurrentAppModule = <
38
38
  complete: boolean;
39
39
  } => {
40
40
  const { modules, error, complete } = useCurrentAppModules();
41
- const module =
42
- modules === null
43
- ? null
44
- : modules === undefined
45
- ? undefined
46
- : // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
- (modules[moduleKey as keyof typeof modules] as any);
41
+ const module = (() => {
42
+ // Preserve an explicit null (modules not applicable) distinct from undefined (not yet loaded)
43
+ if (modules === null) {
44
+ return null;
45
+ }
46
+ // Modules are still loading; propagate undefined rather than throwing
47
+ if (modules === undefined) {
48
+ return undefined;
49
+ }
50
+ // Module lookup by dynamic key can't be statically narrowed to the exact module type; cast to any.
51
+ // biome-ignore lint/suspicious/noExplicitAny: dynamic key lookup can't be statically narrowed to the exact module type
52
+ return modules[moduleKey as keyof typeof modules] as any;
53
+ })();
48
54
  return { module, error, complete };
49
55
  };
50
56
 
package/src/context.ts CHANGED
@@ -10,25 +10,5 @@ import type { Fusion } from '@equinor/fusion-framework';
10
10
  *
11
11
  * @internal
12
12
  */
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ // biome-ignore lint/suspicious/noExplicitAny: `Fusion<any>` widens the context to accept a Fusion instance with any concrete module set
14
14
  export const context = createContext<Fusion<any> | null>(null);
15
-
16
- /**
17
- * Component for providing framework.
18
- *
19
- * @remarks
20
- * Should be created by {@link createFrameworkProvider}
21
- *
22
- * @example
23
- * ```tsx
24
- * import {FrameworkProvider} from '@equinor/fusion-framework-react';
25
- * export const Component = (args: React.PropsWithChildren<{framework: Fusion}>) => {
26
- * return (
27
- * <FrameworkProvider value={args.framework}>
28
- * {args.children}
29
- * </FrameworkProvider>
30
- * );
31
- * }
32
- * ```
33
- */
34
- export const FrameworkProvider = context.Provider;
@@ -3,7 +3,7 @@ import { lazy } from 'react';
3
3
  import initFusion from '@equinor/fusion-framework';
4
4
  import { FrameworkConfigurator } from '@equinor/fusion-framework';
5
5
 
6
- import { FrameworkProvider } from './context';
6
+ import { FrameworkProvider } from './framework-provider';
7
7
  import type { AnyModule, ModulesInstanceType } from '@equinor/fusion-framework-module';
8
8
  import { ModuleProvider } from '@equinor/fusion-framework-react-module';
9
9
 
@@ -49,7 +49,7 @@ import { ModuleProvider } from '@equinor/fusion-framework-react-module';
49
49
  */
50
50
  export const createFrameworkProvider = <
51
51
  TModules extends Array<AnyModule> = [],
52
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ // biome-ignore lint/suspicious/noExplicitAny: default must be bivariant `any`, not `unknown` \u2014 `unknown` breaks assignability when a concrete `TRef` is passed where the default-typed generic is expected
53
53
  TRef extends ModulesInstanceType<[AnyModule]> = any,
54
54
  >(
55
55
  cb: (configurator: FrameworkConfigurator<TModules>, ref?: TRef) => void | Promise<void>,
@@ -49,7 +49,14 @@ export const useFeature = <T = unknown>(
49
49
  provider: IFeatureFlagProvider,
50
50
  key: string,
51
51
  ): UseFeatureResult<T> => {
52
- const feature$ = useMemo(() => provider.features$.pipe(findFeature<T>(key)), [provider, key]);
52
+ // Narrow the features stream down to just the one matching feature by key.
53
+ const feature$ = useMemo(
54
+ () =>
55
+ provider.features$
56
+ // Keep the observable scoped to the requested feature key.
57
+ .pipe(findFeature<T>(key)),
58
+ [provider, key],
59
+ );
53
60
  const { value: feature, error } = useObservableState(feature$ ?? EMPTY);
54
61
  const toggleFeature = useCallback(
55
62
  (enable?: boolean) => {
@@ -58,11 +58,19 @@ export const useFeatures = (
58
58
  */
59
59
  const { value: features, error } = useObservableState(
60
60
  useMemo(() => {
61
+ // Only compute the feature list when a provider is available; otherwise there's nothing to observe
61
62
  if (provider) {
63
+ // Map the feature dictionary to a list, optionally narrowed by the caller-provided selector
62
64
  return provider?.features$.pipe(
63
65
  map((x) => {
64
66
  const values = Object.values(x);
65
- return selector ? values.filter(selector) : values;
67
+ // Return everything when no selector is provided
68
+ if (!selector) {
69
+ return values;
70
+ }
71
+ // Apply the caller-provided selector to narrow down the feature list
72
+ const filtered = values.filter(selector);
73
+ return filtered;
66
74
  }),
67
75
  );
68
76
  }
@@ -79,6 +87,7 @@ export const useFeatures = (
79
87
  */
80
88
  const toggleFeature = useCallback(
81
89
  (key: string, enable?: boolean) => {
90
+ // Cannot toggle a feature without a provider to persist the change
82
91
  if (!provider) {
83
92
  throw new Error('Missing IFeatureFlagProvider.');
84
93
  }
@@ -20,6 +20,7 @@ import { useFeature } from './useFeature';
20
20
  */
21
21
  export const useFrameworkFeature = <T>(key: string): ReturnType<typeof useFeature<T>> => {
22
22
  const provider = useFrameworkModule<FeatureFlagModule>('featureFlag');
23
+ // Fail fast when the FeatureFlagModule has not been enabled on the framework
23
24
  if (!provider) {
24
25
  throw Error('Feature flagging is not enabled in the framework');
25
26
  }
@@ -18,6 +18,7 @@ import { useFeatures } from './useFeatures';
18
18
  */
19
19
  export const useFrameworkFeatures = (): ReturnType<typeof useFeatures> => {
20
20
  const provider = useFrameworkModule<FeatureFlagModule>('featureFlag');
21
+ // Fail fast when the FeatureFlagModule has not been enabled on the framework
21
22
  if (!provider) {
22
23
  throw Error('Feature flagging is not enabled in the framework');
23
24
  }
@@ -0,0 +1,21 @@
1
+ import { context } from './context';
2
+
3
+ /**
4
+ * Component for providing framework.
5
+ *
6
+ * @remarks
7
+ * Should be created by {@link createFrameworkProvider}
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * import {FrameworkProvider} from '@equinor/fusion-framework-react';
12
+ * export const Component = (args: React.PropsWithChildren<{framework: Fusion}>) => {
13
+ * return (
14
+ * <FrameworkProvider value={args.framework}>
15
+ * {args.children}
16
+ * </FrameworkProvider>
17
+ * );
18
+ * }
19
+ * ```
20
+ */
21
+ export const FrameworkProvider = context.Provider;
@@ -6,5 +6,5 @@
6
6
  *
7
7
  * @module
8
8
  */
9
- export { useCurrentUser } from './use-current-user';
10
- export { useHttpClient } from './use-http-client';
9
+ export { useCurrentUser } from './useCurrentUser';
10
+ export { useHttpClient } from './useHttpClient';
@@ -25,11 +25,12 @@ export const useHttpClient = (name: FrameworkHttpClient): HttpClient => {
25
25
  const framework = useFramework();
26
26
 
27
27
  const client = useMemo(() => {
28
+ // Reuse an already-configured client for this key when one exists
28
29
  if (framework.modules.http.hasClient(name)) {
29
30
  return framework.modules.http.createClient(name);
30
31
  }
31
32
  throw Error(`no configured client for key [${name}]`);
32
33
  }, [framework, name]);
33
- // TODO - abort on unmount?
34
+ // TODO(#5085): abort on unmount?
34
35
  return client;
35
36
  };
package/src/http/index.ts CHANGED
@@ -8,6 +8,6 @@
8
8
  *
9
9
  * @module
10
10
  */
11
- export { useHttpClient as useFrameworkHttpClient } from '../hooks/use-http-client';
11
+ export { useHttpClient as useFrameworkHttpClient } from '../hooks/useHttpClient';
12
12
 
13
13
  export * from '@equinor/fusion-framework-react-module-http';
package/src/index.tsx CHANGED
@@ -15,7 +15,7 @@ export type { Fusion } from '@equinor/fusion-framework';
15
15
  export { FusionConfigurator } from '@equinor/fusion-framework';
16
16
 
17
17
  export { createFrameworkProvider } from './create-framework-provider';
18
- export { FrameworkProvider } from './context';
18
+ export { FrameworkProvider } from './framework-provider';
19
19
 
20
20
  export { useFramework } from './useFramework';
21
21
  export { useFrameworkModule } from './useFrameworkModule';
@@ -1,39 +1 @@
1
- import { useFramework } from '../useFramework';
2
-
3
- import {
4
- type SignalRModule,
5
- useProviderTopic,
6
- } from '@equinor/fusion-framework-react-module-signalr';
7
-
8
- /**
9
- * hook for subscribing to a topic of a SignalR hub
10
- *
11
- * @example
12
- ```ts
13
- // config.ts
14
- import {enableSignalR} from '@equinor/fusion-framework-react-module-signalr';
15
- (configurator) => enableSignalR(configurator, 'notifications');
16
-
17
- // myHook.ts
18
- const myHook = () => {
19
- const topic = useSignalR('notifications', 'foo');
20
- return useObservableState(topic).next;
21
- }
22
- ```
23
- *
24
- * @see {@link [module signalr](https://equinor.github.io/fusion-framework/modules/signalr)}
25
- *
26
- * @param hubId identifier of connection hub (must be configured)
27
- * @param topicId identifier of topic to connect to
28
- * @returns Topic
29
- */
30
- export const useSignalR = <T>(
31
- hubId: string,
32
- topicId: string,
33
- ): ReturnType<typeof useProviderTopic<T>> => {
34
- const provider = useFramework<[SignalRModule]>().modules.signalR;
35
- if (!provider) {
36
- throw Error('SignalR is not configured, see @equinor/fusion-framework-react-module-signalr');
37
- }
38
- return useProviderTopic(provider, hubId, topicId);
39
- };
1
+ export { useSignalR } from './useSignalR.js';
@@ -0,0 +1,40 @@
1
+ import { useFramework } from '../useFramework';
2
+
3
+ import {
4
+ type SignalRModule,
5
+ useProviderTopic,
6
+ } from '@equinor/fusion-framework-react-module-signalr';
7
+
8
+ /**
9
+ * hook for subscribing to a topic of a SignalR hub
10
+ *
11
+ * @example
12
+ ```ts
13
+ // config.ts
14
+ import {enableSignalR} from '@equinor/fusion-framework-react-module-signalr';
15
+ (configurator) => enableSignalR(configurator, 'notifications');
16
+
17
+ // myHook.ts
18
+ const myHook = () => {
19
+ const topic = useSignalR('notifications', 'foo');
20
+ return useObservableState(topic).next;
21
+ }
22
+ ```
23
+ *
24
+ * @see {@link [module signalr](https://equinor.github.io/fusion-framework/modules/signalr)}
25
+ *
26
+ * @param hubId identifier of connection hub (must be configured)
27
+ * @param topicId identifier of topic to connect to
28
+ * @returns Topic
29
+ */
30
+ export const useSignalR = <T>(
31
+ hubId: string,
32
+ topicId: string,
33
+ ): ReturnType<typeof useProviderTopic<T>> => {
34
+ const provider = useFramework<[SignalRModule]>().modules.signalR;
35
+ // Fail fast when the SignalRModule has not been configured on the framework
36
+ if (!provider) {
37
+ throw Error('SignalR is not configured, see @equinor/fusion-framework-react-module-signalr');
38
+ }
39
+ return useProviderTopic(provider, hubId, topicId);
40
+ };
@@ -26,10 +26,12 @@ import { context } from './context';
26
26
  */
27
27
  export const useFramework = <TModules extends Array<AnyModule> = []>(): Fusion<TModules> => {
28
28
  let framework = useContext(context);
29
+ // Warn loudly when the framework context is missing so integrators notice the misuse
29
30
  if (!framework) {
30
31
  console.warn('could not locate fusion in context!');
31
32
  }
32
33
  framework ??= window.Fusion;
34
+ // Surface an error when neither context nor the global fallback has the framework instance
33
35
  if (!framework) {
34
36
  console.error('Could not load framework, might not be initiated?');
35
37
  }
@@ -32,10 +32,11 @@ export const useFrameworkModule = <
32
32
  ? ModuleType<TType> | undefined
33
33
  : FusionModulesInstance[Extract<keyof FusionModulesInstance, TKey>] | undefined => {
34
34
  const framework = useFramework();
35
- // TODO
35
+ // TODO(#5082): tighten generics so this indexed lookup no longer needs @ts-expect-error
36
36
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
37
- // @ts-ignore
37
+ // @ts-expect-error
38
38
  const module = framework.modules[name];
39
+ // Warn when the requested module key does not resolve to a registered module
39
40
  if (!module) {
40
41
  console.warn(`the requested module [${module}] is not included in the framework instance`);
41
42
  }
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '8.0.0';
2
+ export const version = '8.0.1';
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-current-user.js","sourceRoot":"","sources":["../../../src/hooks/use-current-user.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAA4B,EAAE;IAC1D,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IACjC,OAAO,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,SAAS,CAAC;AACrD,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-http-client.js","sourceRoot":"","sources":["../../../src/hooks/use-http-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAQ/C;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAyB,EAAc,EAAE;IACrE,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IAEjC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE;QAC1B,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3C,OAAO,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,KAAK,CAAC,iCAAiC,IAAI,GAAG,CAAC,CAAC;IACxD,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;IACtB,2BAA2B;IAC3B,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}