@equinor/fusion-framework 1.1.0-alpha.1 → 1.1.0-alpha.5
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/dist/esm/index.js +8 -19
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/modules.js +6 -0
- package/dist/esm/modules.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +13 -7
- package/dist/types/modules.d.ts +9 -0
- package/package.json +6 -11
- package/src/index.ts +29 -26
- package/src/modules.ts +16 -0
- package/tsconfig.json +12 -4
- package/README.md +0 -190
- package/dist/build/index.js +0 -13166
- package/dist/build/index.js.map +0 -1
- package/dist/build/src/__test__.d.ts +0 -1
- package/dist/build/src/index.d.ts +0 -8
- package/dist/build/src/services/http/http-client-msal.d.ts +0 -9
- package/dist/build/src/services/http/http-client.d.ts +0 -31
- package/dist/build/src/services/http/http-configurator.d.ts +0 -25
- package/dist/build/src/services/http/http-provider.d.ts +0 -7
- package/dist/build/src/services/http/index.d.ts +0 -4
- package/dist/build/src/services/index.d.ts +0 -22
- package/dist/build/src/util/process-operators.d.ts +0 -9
- package/dist/build/tsconfig.rollup.tsbuildinfo +0 -1
- package/dist/esm/__test__.js +0 -26
- package/dist/esm/__test__.js.map +0 -1
- package/dist/esm/services/http/http-client-msal.js +0 -11
- package/dist/esm/services/http/http-client-msal.js.map +0 -1
- package/dist/esm/services/http/http-client.js +0 -54
- package/dist/esm/services/http/http-client.js.map +0 -1
- package/dist/esm/services/http/http-configurator.js +0 -23
- package/dist/esm/services/http/http-configurator.js.map +0 -1
- package/dist/esm/services/http/http-provider.js +0 -14
- package/dist/esm/services/http/http-provider.js.map +0 -1
- package/dist/esm/services/http/index.js +0 -5
- package/dist/esm/services/http/index.js.map +0 -1
- package/dist/esm/services/index.js +0 -59
- package/dist/esm/services/index.js.map +0 -1
- package/dist/esm/util/process-operators.js +0 -25
- package/dist/esm/util/process-operators.js.map +0 -1
- package/dist/types/__test__.d.ts +0 -1
- package/dist/types/services/http/http-client-msal.d.ts +0 -9
- package/dist/types/services/http/http-client.d.ts +0 -31
- package/dist/types/services/http/http-configurator.d.ts +0 -25
- package/dist/types/services/http/http-provider.d.ts +0 -7
- package/dist/types/services/http/index.d.ts +0 -4
- package/dist/types/services/index.d.ts +0 -22
- package/dist/types/util/process-operators.d.ts +0 -9
- package/src/__test__.ts +0 -35
- package/src/services/http/http-client-msal.ts +0 -16
- package/src/services/http/http-client.ts +0 -91
- package/src/services/http/http-configurator.ts +0 -66
- package/src/services/http/http-provider.ts +0 -19
- package/src/services/http/index.ts +0 -4
- package/src/services/index.ts +0 -92
- package/src/util/process-operators.ts +0 -50
package/src/index.ts
CHANGED
|
@@ -1,34 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
2
|
+
import { FusionConfigurator, FusionModulesInstance, initializeFusionModules } from './modules';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
currentApp: Services;
|
|
6
|
-
registerApp: (app: string, appInit: ServiceInitiator) => Promise<void>;
|
|
7
|
-
}
|
|
4
|
+
export { FusionConfigurator };
|
|
8
5
|
|
|
9
|
-
export
|
|
10
|
-
const app$ = new BehaviorSubject<Record<string, Services>>({});
|
|
11
|
-
const rootConfig = await configureServices();
|
|
12
|
-
const rootServices = await rootConfig(init);
|
|
6
|
+
export interface AppManifest {}
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
export interface Fusion {
|
|
9
|
+
/**
|
|
10
|
+
* Configured services for Fusion
|
|
11
|
+
*/
|
|
12
|
+
modules: FusionModulesInstance;
|
|
13
|
+
/**
|
|
14
|
+
* Create a scoped instance of services
|
|
15
|
+
*/
|
|
16
|
+
// createInstance: <TModule extends Module<any, any>>(
|
|
17
|
+
// configurator: ModulesConfigurator,
|
|
18
|
+
// modules: TModule[]
|
|
19
|
+
// ) => Promise<ModuleType<Modules>>;
|
|
20
|
+
}
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
},
|
|
26
|
-
registerApp,
|
|
27
|
-
...rootServices,
|
|
22
|
+
export const initFusion = async (init: FusionConfigurator): Promise<Fusion> => {
|
|
23
|
+
const modules = await initializeFusionModules(init);
|
|
24
|
+
const fusion = {
|
|
25
|
+
modules,
|
|
28
26
|
};
|
|
27
|
+
window.Fusion = fusion;
|
|
28
|
+
return fusion;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
declare global {
|
|
32
|
+
interface Window {
|
|
33
|
+
Fusion: Fusion;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
33
36
|
|
|
34
|
-
export default
|
|
37
|
+
export default initFusion;
|
package/src/modules.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { initializeModules, ModulesInstanceType } from '@equinor/fusion-framework-module';
|
|
2
|
+
|
|
3
|
+
import type { ModulesConfigurator } from '@equinor/fusion-framework-module';
|
|
4
|
+
|
|
5
|
+
import http, { HttpModule } from '@equinor/fusion-framework-module-http';
|
|
6
|
+
import auth, { MsalModule } from '@equinor/fusion-framework-module-msal';
|
|
7
|
+
|
|
8
|
+
export type FusionModules = [HttpModule, MsalModule];
|
|
9
|
+
export const modules: FusionModules = [http, auth];
|
|
10
|
+
|
|
11
|
+
export type FusionModulesInstance = ModulesInstanceType<FusionModules>;
|
|
12
|
+
export type FusionConfigurator = ModulesConfigurator<FusionModules>;
|
|
13
|
+
|
|
14
|
+
export const initializeFusionModules = async (
|
|
15
|
+
configurator: FusionConfigurator
|
|
16
|
+
): Promise<FusionModulesInstance> => initializeModules(configurator, modules);
|
package/tsconfig.json
CHANGED
|
@@ -5,12 +5,20 @@
|
|
|
5
5
|
"rootDir": "src",
|
|
6
6
|
"declarationDir": "./dist/types",
|
|
7
7
|
"baseUrl": "src",
|
|
8
|
-
"paths": {
|
|
9
|
-
"@equinor/fusion-framework/services": ["services/index"]
|
|
10
|
-
}
|
|
11
8
|
},
|
|
9
|
+
"references": [
|
|
10
|
+
{
|
|
11
|
+
"path": "../module"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"path": "../module-http"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"path": "../module-msal"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
12
20
|
"include": [
|
|
13
|
-
"src
|
|
21
|
+
"src/**/*",
|
|
14
22
|
],
|
|
15
23
|
"exclude": [
|
|
16
24
|
"node_modules",
|
package/README.md
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
# Fusion Framework
|
|
2
|
-
🚨 **WIP**🏗
|
|
3
|
-
|
|
4
|
-
This package is under construction and currently under alpha.
|
|
5
|
-
|
|
6
|
-
__Expect breaking changes untill stable release!__
|
|
7
|
-
|
|
8
|
-
## Provider / Portal
|
|
9
|
-
```ts
|
|
10
|
-
const initialize = async() => {
|
|
11
|
-
|
|
12
|
-
window.Fusion = await createInstance((root) => {
|
|
13
|
-
|
|
14
|
-
// configure auth client instance
|
|
15
|
-
root.auth.client = createAuthClient('my-tennant-id', 'my-client-id', '/msal/auth');
|
|
16
|
-
|
|
17
|
-
// define simple client (will use login scope)
|
|
18
|
-
root.http.configureClient('foo', 'https://my.services.com');
|
|
19
|
-
|
|
20
|
-
// define a client with callback for init
|
|
21
|
-
root.http.configureClient('bar', (client) => {
|
|
22
|
-
|
|
23
|
-
// define base url for requests
|
|
24
|
-
client.uri = 'https://my.other-services.com';
|
|
25
|
-
|
|
26
|
-
// define default scope for auth request when using client instance
|
|
27
|
-
client.defaultScope = ['https://somewhere.com/read'];
|
|
28
|
-
|
|
29
|
-
// define a request proccessor - supports multiple
|
|
30
|
-
client.requestHandler.add('custom-headers', (request) => {
|
|
31
|
-
const headers = new Headers(request.headers);
|
|
32
|
-
headers.append('x-app-version', 'v1.2.3');
|
|
33
|
-
headers.append('x-app-env', 'alpha');
|
|
34
|
-
return { ...request, headers };
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Consumer / Application
|
|
42
|
-
```ts
|
|
43
|
-
// default
|
|
44
|
-
window.Fusion.createClient('bar').fetch('/api/apps').subscribe(async(x) => console.log(await x.json));
|
|
45
|
-
|
|
46
|
-
// by promise
|
|
47
|
-
window.Fusion.createClient('bar').fetchAsync('/api/apps').then(async(x) => console.log(await x.json));
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## HttpClient
|
|
51
|
-
|
|
52
|
-
### fetch
|
|
53
|
-
|
|
54
|
-
> The fetch method of the client return an __Observable__ reponse.
|
|
55
|
-
>
|
|
56
|
-
> Observables has the advantage of cancel when unsuscribed.
|
|
57
|
-
>
|
|
58
|
-
> Secondly we can compose the flow easily with operator functions
|
|
59
|
-
|
|
60
|
-
```ts
|
|
61
|
-
import { fromEvent, of } from 'rxjs';
|
|
62
|
-
import { debounceTime, map, switchMap, takeUntil, catchError } from 'rxjs/operators';
|
|
63
|
-
|
|
64
|
-
const client = window.Fusion.createClient('my-client');
|
|
65
|
-
|
|
66
|
-
const input = document.createElement('input');
|
|
67
|
-
const result = document.createElement('pre');
|
|
68
|
-
|
|
69
|
-
// Observe changes on input field
|
|
70
|
-
const input$ = fromEvent(input, 'input');
|
|
71
|
-
|
|
72
|
-
$input.pipe(
|
|
73
|
-
|
|
74
|
-
// only call after no key input in .5s
|
|
75
|
-
debounceTime(500),
|
|
76
|
-
|
|
77
|
-
// extract value from event
|
|
78
|
-
map(x => x.currentTarget.value),
|
|
79
|
-
|
|
80
|
-
// only search when text longer than 3 characters
|
|
81
|
-
filter(x => x.length >=3),
|
|
82
|
-
|
|
83
|
-
// query api with input value, retry 2 times
|
|
84
|
-
switchMap(x => client.fetch(`api/foo?q=${x}`).pipe(retry(2))),
|
|
85
|
-
|
|
86
|
-
// extract data from response
|
|
87
|
-
switchMap(x => x.json()),
|
|
88
|
-
|
|
89
|
-
// process error
|
|
90
|
-
catchError(x => of({error: e.message})),
|
|
91
|
-
|
|
92
|
-
// cancel request if new input
|
|
93
|
-
takeUntil(input$)
|
|
94
|
-
|
|
95
|
-
).subscribe(json => result.innerText = JSON.stringify(json, null, 2));
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
#### React
|
|
100
|
-
TODO move to react lib
|
|
101
|
-
```tsx
|
|
102
|
-
import { useClient } from '@equinor/fusion-framework-react';
|
|
103
|
-
import { Subscription, of } from 'rxjs';
|
|
104
|
-
import { debounceTime, map, switchMap, takeUntil, catchError } from 'rxjs/operators';
|
|
105
|
-
|
|
106
|
-
const MyComponent = () => {
|
|
107
|
-
const [query, setQuery] = useState('');
|
|
108
|
-
const [value, setValue] = useState('');
|
|
109
|
-
|
|
110
|
-
const client = useClient('my-client');
|
|
111
|
-
const input$ = useMemo(() => new Subject(), []);
|
|
112
|
-
|
|
113
|
-
// set next value for observe when input changes
|
|
114
|
-
const onInput = useCallback((value: string) => input$.next(value), [input$]);
|
|
115
|
-
|
|
116
|
-
useEffect(() =>{
|
|
117
|
-
const subscription = new Subscription();
|
|
118
|
-
|
|
119
|
-
// set query state each time input change
|
|
120
|
-
subscription.add(input$.subscribe(setQuery));
|
|
121
|
-
|
|
122
|
-
// query api on change
|
|
123
|
-
subscription.add(input$.pipe(
|
|
124
|
-
switchMap(x => client.fetch(`api/foo?q=${x}`)),
|
|
125
|
-
switchMap(x => x.json()),
|
|
126
|
-
).subscribe(setValue);
|
|
127
|
-
|
|
128
|
-
// cancel subscriptions on unmount
|
|
129
|
-
return () => subscription.unsubscribe();
|
|
130
|
-
}, []));
|
|
131
|
-
return <>
|
|
132
|
-
<input value={query} onInput={onInput} />
|
|
133
|
-
<pre>{value}</pre>
|
|
134
|
-
</>
|
|
135
|
-
};
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### fetchAsync
|
|
139
|
-
|
|
140
|
-
Incase for some reason you don`t want to use __Observables__, the ```fetchAsync``` will return a promise
|
|
141
|
-
|
|
142
|
-
```ts
|
|
143
|
-
const client = window.Fusion.createClient('my-client');
|
|
144
|
-
const input = document.createElement('input');
|
|
145
|
-
const result = document.createElement('pre');
|
|
146
|
-
|
|
147
|
-
let controller: AbortController;
|
|
148
|
-
|
|
149
|
-
input.addEventlistner('input', (e) => {
|
|
150
|
-
try{
|
|
151
|
-
// if a controller is defined, request might be ongoing
|
|
152
|
-
controller && controller.abort();
|
|
153
|
-
|
|
154
|
-
// create a new abort controller
|
|
155
|
-
controller = new AbortController();
|
|
156
|
-
|
|
157
|
-
// query api with
|
|
158
|
-
const response = await client.fetch({
|
|
159
|
-
path: `api/foo?q=${e.currentTarget.value}`,
|
|
160
|
-
signal: controller.signal,
|
|
161
|
-
});
|
|
162
|
-
const json = await response.json();
|
|
163
|
-
result.innerText = JSON.stringify(json, null, 2)
|
|
164
|
-
} catch(err){
|
|
165
|
-
resilt.innerText = 'an error accoured'
|
|
166
|
-
} finally{
|
|
167
|
-
delete controller;
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
### RequestHandler
|
|
173
|
-
|
|
174
|
-
Before a request is executed all registered request handlers are proccessed. The tail of a operator is chain to head of the next.
|
|
175
|
-
|
|
176
|
-
Handler must return same type as provided _```RequestInit```_ or _```void```_ and can be async.
|
|
177
|
-
```ts
|
|
178
|
-
type ProcessOperator<T, R = T> = (request: T) => R | void | Promise<R | void>;
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
Handlers are keyed to allow override of existing by ```client.requestHandler.set```, using ```client.requestHandler.add``` will throw error if allready defined.
|
|
182
|
-
|
|
183
|
-
```ts
|
|
184
|
-
client.requestHandler.add('custom-headers', async(request) => {
|
|
185
|
-
const values = await import('values.json');
|
|
186
|
-
const headers = new Headers(request.headers);
|
|
187
|
-
Object.keys(values).forEach(key => headers.append(`x-${key}`, values[key]));
|
|
188
|
-
return {...request, headers};
|
|
189
|
-
});
|
|
190
|
-
```
|