@equinor/fusion-framework-react 0.0.0-next-20230915111233

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 (79) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +906 -0
  3. package/LICENSE +21 -0
  4. package/README.md +44 -0
  5. package/dist/esm/Framework.js +10 -0
  6. package/dist/esm/Framework.js.map +1 -0
  7. package/dist/esm/app/index.js +5 -0
  8. package/dist/esm/app/index.js.map +1 -0
  9. package/dist/esm/app/useAppProvider.js +10 -0
  10. package/dist/esm/app/useAppProvider.js.map +1 -0
  11. package/dist/esm/app/useApps.js +16 -0
  12. package/dist/esm/app/useApps.js.map +1 -0
  13. package/dist/esm/app/useCurrentApp.js +19 -0
  14. package/dist/esm/app/useCurrentApp.js.map +1 -0
  15. package/dist/esm/app/useCurrentAppModules.js +15 -0
  16. package/dist/esm/app/useCurrentAppModules.js.map +1 -0
  17. package/dist/esm/context/index.js +3 -0
  18. package/dist/esm/context/index.js.map +1 -0
  19. package/dist/esm/context/useCurrentContext.js +5 -0
  20. package/dist/esm/context/useCurrentContext.js.map +1 -0
  21. package/dist/esm/context.js +4 -0
  22. package/dist/esm/context.js.map +1 -0
  23. package/dist/esm/create-framework-provider.js +24 -0
  24. package/dist/esm/create-framework-provider.js.map +1 -0
  25. package/dist/esm/hooks/index.js +3 -0
  26. package/dist/esm/hooks/index.js.map +1 -0
  27. package/dist/esm/hooks/use-current-user.js +6 -0
  28. package/dist/esm/hooks/use-current-user.js.map +1 -0
  29. package/dist/esm/hooks/use-http-client.js +13 -0
  30. package/dist/esm/hooks/use-http-client.js.map +1 -0
  31. package/dist/esm/http/index.js +3 -0
  32. package/dist/esm/http/index.js.map +1 -0
  33. package/dist/esm/index.js +6 -0
  34. package/dist/esm/index.js.map +1 -0
  35. package/dist/esm/signalr/index.js +10 -0
  36. package/dist/esm/signalr/index.js.map +1 -0
  37. package/dist/esm/useFramework.js +15 -0
  38. package/dist/esm/useFramework.js.map +1 -0
  39. package/dist/esm/version.js +2 -0
  40. package/dist/esm/version.js.map +1 -0
  41. package/dist/tsconfig.tsbuildinfo +1 -0
  42. package/dist/types/Framework.d.ts +8 -0
  43. package/dist/types/app/index.d.ts +5 -0
  44. package/dist/types/app/useAppProvider.d.ts +4 -0
  45. package/dist/types/app/useApps.d.ts +8 -0
  46. package/dist/types/app/useCurrentApp.d.ts +9 -0
  47. package/dist/types/app/useCurrentAppModules.d.ts +8 -0
  48. package/dist/types/context/index.d.ts +2 -0
  49. package/dist/types/context/useCurrentContext.d.ts +5 -0
  50. package/dist/types/context.d.ts +4 -0
  51. package/dist/types/create-framework-provider.d.ts +4 -0
  52. package/dist/types/hooks/index.d.ts +2 -0
  53. package/dist/types/hooks/use-current-user.d.ts +8 -0
  54. package/dist/types/hooks/use-http-client.d.ts +5 -0
  55. package/dist/types/http/index.d.ts +2 -0
  56. package/dist/types/index.d.ts +6 -0
  57. package/dist/types/signalr/index.d.ts +2 -0
  58. package/dist/types/useFramework.d.ts +4 -0
  59. package/dist/types/version.d.ts +1 -0
  60. package/package.json +85 -0
  61. package/src/Framework.tsx +22 -0
  62. package/src/app/index.ts +6 -0
  63. package/src/app/useAppProvider.ts +19 -0
  64. package/src/app/useApps.ts +30 -0
  65. package/src/app/useCurrentApp.ts +38 -0
  66. package/src/app/useCurrentAppModules.ts +34 -0
  67. package/src/context/index.ts +3 -0
  68. package/src/context/useCurrentContext.ts +6 -0
  69. package/src/context.ts +25 -0
  70. package/src/create-framework-provider.tsx +42 -0
  71. package/src/hooks/index.ts +2 -0
  72. package/src/hooks/use-current-user.ts +15 -0
  73. package/src/hooks/use-http-client.ts +19 -0
  74. package/src/http/index.ts +3 -0
  75. package/src/index.tsx +14 -0
  76. package/src/signalr/index.ts +38 -0
  77. package/src/useFramework.ts +27 -0
  78. package/src/version.ts +2 -0
  79. package/tsconfig.json +38 -0
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "@equinor/fusion-framework-react",
3
+ "version": "0.0.0-next-20230915111233",
4
+ "description": "",
5
+ "main": "dist/esm/index.js",
6
+ "exports": {
7
+ ".": "./dist/esm/index.js",
8
+ "./app": "./dist/esm/app/index.js",
9
+ "./context": "./dist/esm/context/index.js",
10
+ "./hooks": "./dist/esm/hooks/index.js",
11
+ "./http": "./dist/esm/http/index.js",
12
+ "./signalr": "./dist/esm/signalr/index.js"
13
+ },
14
+ "types": "dist/types/index.d.ts",
15
+ "typesVersions": {
16
+ "*": {
17
+ "app": [
18
+ "dist/types/app/index.d.ts"
19
+ ],
20
+ "context": [
21
+ "dist/types/context/index.d.ts"
22
+ ],
23
+ "hooks": [
24
+ "dist/types/hooks/index.d.ts"
25
+ ],
26
+ "http": [
27
+ "dist/types/http/index.d.ts"
28
+ ],
29
+ "signalr": [
30
+ "dist/types/signalr/index.d.ts"
31
+ ]
32
+ }
33
+ },
34
+ "keywords": [],
35
+ "author": "",
36
+ "license": "ISC",
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/equinor/fusion-framework.git",
43
+ "directory": "packages/react/framework"
44
+ },
45
+ "dependencies": {
46
+ "rxjs": "^7.8.1",
47
+ "@equinor/fusion-framework-module": "^4.2.4",
48
+ "@equinor/fusion-framework-react-module": "^3.0.5",
49
+ "@equinor/fusion-framework-react-module-http": "^0.0.0-next-20230915111233",
50
+ "@equinor/fusion-framework": "^0.0.0-next-20230915111233",
51
+ "@equinor/fusion-observable": "^8.1.1"
52
+ },
53
+ "devDependencies": {
54
+ "@types/react": "^18.2.20",
55
+ "@types/react-dom": "^18.2.7",
56
+ "react": "^18.2.0",
57
+ "react-dom": "^18.2.0",
58
+ "typescript": "^5.1.3",
59
+ "@equinor/fusion-framework-module-app": "^0.0.0-next-20230915111233",
60
+ "@equinor/fusion-framework-react-module-context": "^0.0.0-next-20230915111233"
61
+ },
62
+ "peerDependencies": {
63
+ "@types/react": "^17.0.0 || ^18.0.0",
64
+ "react": "^17.0.0 || ^18.0.0",
65
+ "react-dom": "^17.0.0 || ^18.0.0",
66
+ "@equinor/fusion-framework-react-module-signalr": "^0.0.0-next-20230915111233"
67
+ },
68
+ "peerDependenciesMeta": {
69
+ "@equinor/fusion-framework-react-module-context": {
70
+ "optional": true
71
+ },
72
+ "@equinor/fusion-framework-react-module-signalr": {
73
+ "optional": true
74
+ },
75
+ "@types/react": {
76
+ "optional": true
77
+ },
78
+ "react-dom": {
79
+ "optional": true
80
+ }
81
+ },
82
+ "scripts": {
83
+ "build": "tsc -b"
84
+ }
85
+ }
@@ -0,0 +1,22 @@
1
+ import { FusionConfigurator } from '@equinor/fusion-framework';
2
+ import { createFrameworkProvider } from './create-framework-provider';
3
+ import { PropsWithChildren, ReactNode, Suspense, useMemo } from 'react';
4
+
5
+ type ConfigureCallback = (configurator: FusionConfigurator) => void;
6
+
7
+ export const Framework = (
8
+ props: PropsWithChildren<{
9
+ readonly configure: ConfigureCallback;
10
+ readonly fallback: NonNullable<ReactNode> | null;
11
+ }>,
12
+ ) => {
13
+ const { configure, fallback, children } = props;
14
+ const Component = useMemo(() => createFrameworkProvider(configure), [configure]);
15
+ return (
16
+ <Suspense fallback={fallback}>
17
+ <Component>{children}</Component>
18
+ </Suspense>
19
+ );
20
+ };
21
+
22
+ export default Framework;
@@ -0,0 +1,6 @@
1
+ export type { AppConfig, AppManifest, AppType, IApp } from '@equinor/fusion-framework-module-app';
2
+
3
+ export { useCurrentApp } from './useCurrentApp';
4
+ export { useCurrentAppModules } from './useCurrentAppModules';
5
+ export { useApps } from './useApps';
6
+ export { useAppProvider } from './useAppProvider';
@@ -0,0 +1,19 @@
1
+ import { FusionModulesInstance } from '@equinor/fusion-framework';
2
+ import { AppModule } from '@equinor/fusion-framework-module-app';
3
+
4
+ import { useFramework } from '../useFramework';
5
+
6
+ /**
7
+ * React Hook - get appProvider interface
8
+ * @returns framework AppModule
9
+ */
10
+ export const useAppProvider = (): FusionModulesInstance<[AppModule]>['app'] => {
11
+ const provider = useFramework<[AppModule]>().modules.app;
12
+ if (!provider) {
13
+ throw Error('Current framework does not have AppModule configured');
14
+ }
15
+
16
+ return provider;
17
+ };
18
+
19
+ export default useAppProvider;
@@ -0,0 +1,30 @@
1
+ import { AppManifest } from '@equinor/fusion-framework-module-app';
2
+ import { useObservableState } from '@equinor/fusion-observable/react';
3
+ import { useMemo } from 'react';
4
+
5
+ import { useAppProvider } from './useAppProvider';
6
+
7
+ /**
8
+ * React Hook - Get apps from framework
9
+ * @param args Object with boolean member includeHidden
10
+ * @returns Object {apps, isLoading} where apps is Array of AppManifest, isLoading is a boolean on observable complete
11
+ */
12
+ export const useApps = (args?: {
13
+ includeHidden: boolean;
14
+ }): { apps: AppManifest[] | undefined; isLoading: boolean } => {
15
+ const provider = useAppProvider();
16
+ const { value: manifests, complete } = useObservableState(
17
+ useMemo(() => provider.getAllAppManifests(), [provider]),
18
+ );
19
+
20
+ const apps = useMemo(() => {
21
+ if (manifests && !args?.includeHidden) {
22
+ return manifests.filter((app) => !app.hide);
23
+ }
24
+ return manifests;
25
+ }, [args, manifests]);
26
+
27
+ return { apps, isLoading: !complete };
28
+ };
29
+
30
+ export default useApps;
@@ -0,0 +1,38 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { useObservableState } from '@equinor/fusion-observable/react';
4
+
5
+ import { type AnyModule } from '@equinor/fusion-framework-module';
6
+ import { type AppModule, type CurrentApp } from '@equinor/fusion-framework-module-app';
7
+
8
+ import { useFramework } from '../useFramework';
9
+
10
+ /**
11
+ * Observers the stream of current app and return the latest application
12
+ *
13
+ * __Warning:__ type hint templates are only hints, this does not check if the modules are actually enabled!
14
+ *
15
+ * @template TModule type hint modules which the application has configured
16
+ * @template TEnv type hint what kind of environment config the application has
17
+ */
18
+ export const useCurrentApp = <TModules extends Array<AnyModule> = [], TEnv = unknown>(): {
19
+ currentApp: CurrentApp<TModules, TEnv>;
20
+ setCurrentApp: (appKey: string) => void;
21
+ clearCurrentApp: () => void;
22
+ error?: unknown;
23
+ } => {
24
+ const provider = useFramework<[AppModule]>().modules.app;
25
+ if (!provider) {
26
+ throw Error('Current framework does not have AppModule configured');
27
+ }
28
+ const currentApp$ = useMemo(() => provider.current$, [provider]);
29
+ const { value, error } = useObservableState(currentApp$);
30
+ return {
31
+ currentApp: value as CurrentApp<TModules, TEnv>,
32
+ setCurrentApp: useMemo(() => provider.setCurrentApp.bind(provider), [provider]),
33
+ clearCurrentApp: useMemo(() => provider.clearCurrentApp.bind(provider), [provider]),
34
+ error,
35
+ };
36
+ };
37
+
38
+ export default useCurrentApp;
@@ -0,0 +1,34 @@
1
+ import { useMemo } from 'react';
2
+ import useCurrentApp from './useCurrentApp';
3
+
4
+ import { AppModulesInstance } from '@equinor/fusion-framework-module-app';
5
+ import { Observable, of } from 'rxjs';
6
+ import { type AnyModule } from '@equinor/fusion-framework-module';
7
+
8
+ /**
9
+ * Observers the stream of current app initialized modules
10
+ *
11
+ * __Warning:__ type hint templates are only hints, this does not check if the modules are actually enabled!
12
+ *
13
+ * @template TModule type hint modules which the application has configured
14
+ * @returns the observable instance of initialized modules of the application
15
+ */
16
+ export const useCurrentAppModules = <TModules extends Array<AnyModule> = []>(): {
17
+ modules$: Observable<AppModulesInstance<TModules> | null>;
18
+ error?: unknown;
19
+ } => {
20
+ const { currentApp, error } = useCurrentApp<TModules>();
21
+ const modules$ = useMemo(
22
+ () =>
23
+ currentApp
24
+ ? (currentApp.instance$ as Observable<AppModulesInstance<TModules>>)
25
+ : of(null),
26
+ [currentApp],
27
+ );
28
+ return {
29
+ modules$,
30
+ error,
31
+ };
32
+ };
33
+
34
+ export default useCurrentAppModules;
@@ -0,0 +1,3 @@
1
+ export * from '@equinor/fusion-framework-react-module-context';
2
+
3
+ export { useCurrentContext } from './useCurrentContext';
@@ -0,0 +1,6 @@
1
+ import { useCurrentContext as _useCurrentContext } from '@equinor/fusion-framework-react-module-context';
2
+ import { useFramework } from '../useFramework';
3
+
4
+ export const useCurrentContext = () => _useCurrentContext(useFramework().modules.context);
5
+
6
+ export default useCurrentContext;
package/src/context.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { createContext } from 'react';
2
+ import type { Fusion } from '@equinor/fusion-framework';
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
+ export const context = createContext<Fusion<any> | null>(null);
6
+
7
+ /**
8
+ * Component for providing framework.
9
+ *
10
+ * @remarks
11
+ * Should be created by {@link createFrameworkProvider}
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * import {FrameworkProvider} from '@equinor/fusion-framework-react';
16
+ * export const Component = (args: React.PropsWithChildren<{framework: Fusion}>) => {
17
+ * return (
18
+ * <FrameworkProvider value={args.framework}>
19
+ * {args.children}
20
+ * </FrameworkProvider>
21
+ * );
22
+ * }
23
+ * ```
24
+ */
25
+ export const FrameworkProvider = context.Provider;
@@ -0,0 +1,42 @@
1
+ import React, { lazy } from 'react';
2
+ import initFusion from '@equinor/fusion-framework';
3
+ import { FusionConfigurator } from '@equinor/fusion-framework';
4
+
5
+ import { FrameworkProvider } from './context';
6
+ import type { AnyModule } from '@equinor/fusion-framework-module';
7
+ import { ModuleProvider } from '@equinor/fusion-framework-react-module';
8
+
9
+ /**
10
+ * Create a framework provider for react.
11
+ *
12
+ * This function is for providers of framework, like a portal.
13
+ *
14
+ * @param configurator - callback for configuring modules
15
+ * @example
16
+ * ```tsx
17
+ * const config: FusionConfigurator = (config) => {}
18
+ * const Portal = () => {
19
+ * const Framework = createFrameworkProvider(config);
20
+ * return (
21
+ * <Suspense fallback={<span>loading...</span>}>
22
+ * <Framework>{children}</Framework>
23
+ * </Suspense>
24
+ * );
25
+ * };
26
+ * ```
27
+ */
28
+ export const createFrameworkProvider = <TModules extends Array<AnyModule> = []>(
29
+ cb: (configurator: FusionConfigurator<TModules>) => void | Promise<void>,
30
+ ): React.LazyExoticComponent<React.FunctionComponent<React.PropsWithChildren<unknown>>> =>
31
+ lazy(async () => {
32
+ const configurator = new FusionConfigurator<TModules>();
33
+ await cb(configurator);
34
+ const framework = await initFusion(configurator);
35
+ return {
36
+ default: ({ children }: { children?: React.ReactNode }) => (
37
+ <FrameworkProvider value={framework}>
38
+ <ModuleProvider value={framework.modules}>{children}</ModuleProvider>
39
+ </FrameworkProvider>
40
+ ),
41
+ };
42
+ });
@@ -0,0 +1,2 @@
1
+ export { useCurrentUser } from './use-current-user';
2
+ export { useHttpClient } from './use-http-client';
@@ -0,0 +1,15 @@
1
+ import { useFramework } from '../useFramework';
2
+
3
+ export type AccountInfo = {
4
+ // homeAccountId: string;
5
+ environment: string;
6
+ tenantId: string;
7
+ username: string;
8
+ localAccountId: string;
9
+ name?: string;
10
+ };
11
+
12
+ export const useCurrentUser = (): AccountInfo | undefined => {
13
+ const framework = useFramework();
14
+ return framework.modules.auth.defaultClient.account;
15
+ };
@@ -0,0 +1,19 @@
1
+ import { useMemo } from 'react';
2
+ import { Fusion } from '@equinor/fusion-framework';
3
+ import { useFramework } from '../useFramework';
4
+
5
+ type HttpClient = ReturnType<Fusion['modules']['http']['createClient']>;
6
+ type FrameworkHttpClient = 'portal' | 'people';
7
+
8
+ export const useHttpClient = (name: FrameworkHttpClient): HttpClient => {
9
+ const framework = useFramework();
10
+
11
+ const client = useMemo(() => {
12
+ if (framework.modules.http.hasClient(name)) {
13
+ return framework.modules.http.createClient(name);
14
+ }
15
+ throw Error(`no configured client for key [${name}]`);
16
+ }, [framework, name]);
17
+ // TODO - abort on unmount?
18
+ return client;
19
+ };
@@ -0,0 +1,3 @@
1
+ export { useHttpClient as useFrameworkHttpClient } from '../hooks/use-http-client';
2
+
3
+ export * from '@equinor/fusion-framework-react-module-http';
package/src/index.tsx ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * [[include:framework-react/README.MD]]
3
+ * @module
4
+ */
5
+
6
+ export type { Fusion } from '@equinor/fusion-framework';
7
+ export { FusionConfigurator } from '@equinor/fusion-framework';
8
+
9
+ export { createFrameworkProvider } from './create-framework-provider';
10
+ export { FrameworkProvider } from './context';
11
+
12
+ export { useFramework } from './useFramework';
13
+
14
+ export { default, Framework } from './Framework';
@@ -0,0 +1,38 @@
1
+ import { useFramework } from '../useFramework';
2
+
3
+ import { SignalRModule, useProviderTopic } from '@equinor/fusion-framework-react-module-signalr';
4
+
5
+ /**
6
+ * hook for subscribing to a topic of a SignalR hub
7
+ *
8
+ * @example
9
+ ```ts
10
+ // config.ts
11
+ import {enableSignalR} from '@equinor/fusion-framework-react-module-signalr';
12
+ (configurator) => enableSignalR(configurator, 'notifications');
13
+
14
+ // myHook.ts
15
+ const myHook = () => {
16
+ const topic = useSignalR('notifications', 'foo');
17
+ return useObservableState(topic).next;
18
+ }
19
+ ```
20
+ *
21
+ * @see {@link [module signalr](https://equinor.github.io/fusion-framework/modules/signalr)}
22
+ *
23
+ * @param hubId identifier of connection hub (must be configured)
24
+ * @param topicId identifier of topic to connect to
25
+ * @returns Topic
26
+ */
27
+ export const useSignalR = <T>(
28
+ hubId: string,
29
+ topicId: string,
30
+ ): ReturnType<typeof useProviderTopic<T>> => {
31
+ const provider = useFramework<[SignalRModule]>().modules.signalR;
32
+ if (!provider) {
33
+ throw Error(
34
+ 'SignalR is not configured, see @equinor/fusion-framework-react-module-signalr',
35
+ );
36
+ }
37
+ return useProviderTopic(provider, hubId, topicId);
38
+ };
@@ -0,0 +1,27 @@
1
+ import type { Fusion } from '@equinor/fusion-framework';
2
+ import type { AnyModule } from '@equinor/fusion-framework-module';
3
+
4
+ import { useContext } from 'react';
5
+ import { context } from './context';
6
+ /**
7
+ * @example
8
+ * ```ts
9
+ * const useSometing = () => {
10
+ * const fusion = useFramework();
11
+ * return fusion.something;
12
+ * }
13
+ * ```
14
+ */
15
+ export const useFramework = <TModules extends Array<AnyModule> = []>(): Fusion<TModules> => {
16
+ let framework = useContext(context);
17
+ if (!framework) {
18
+ console.warn('could not locate fusion in context!');
19
+ }
20
+ framework ??= window.Fusion;
21
+ if (!framework) {
22
+ console.error('Could not load framework, might not be initiated?');
23
+ }
24
+ return framework;
25
+ };
26
+
27
+ export default useFramework;
package/src/version.ts ADDED
@@ -0,0 +1,2 @@
1
+ // Generated by genversion.
2
+ export const version = '5.2.7';
package/tsconfig.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "extends": "../tsconfig.react.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist/esm",
5
+ "rootDir": "src",
6
+ "declarationDir": "./dist/types",
7
+ "paths": {
8
+ "react": [ "./node_modules/@types/react" ],
9
+ },
10
+ },
11
+ "references": [
12
+ {
13
+ "path": "../../framework"
14
+ },
15
+ {
16
+ "path": "../../modules/app"
17
+ },
18
+ {
19
+ "path": "../../modules/service-discovery"
20
+ },
21
+ {
22
+ "path": "../modules/context"
23
+ },
24
+ {
25
+ "path": "../modules/http"
26
+ },
27
+ {
28
+ "path": "../modules/signalr"
29
+ }
30
+ ],
31
+ "include": [
32
+ "src/**/*",
33
+ ],
34
+ "exclude": [
35
+ "node_modules",
36
+ "lib"
37
+ ]
38
+ }