@equinor/fusion-framework-module-http 2.0.5 → 2.0.6

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 +10 -0
  2. package/dist/esm/configurator.js +1 -1
  3. package/dist/esm/configurator.js.map +1 -1
  4. package/dist/esm/index.js +0 -3
  5. package/dist/esm/index.js.map +1 -1
  6. package/dist/esm/{client-msal.js → lib/client/client-msal.js} +0 -0
  7. package/dist/esm/lib/client/client-msal.js.map +1 -0
  8. package/dist/esm/{client.js → lib/client/client.js} +5 -13
  9. package/dist/esm/lib/client/client.js.map +1 -0
  10. package/dist/esm/lib/client/index.js +4 -0
  11. package/dist/esm/lib/client/index.js.map +1 -0
  12. package/dist/esm/lib/client/types.js +2 -0
  13. package/dist/esm/lib/client/types.js.map +1 -0
  14. package/dist/esm/lib/index.js +4 -0
  15. package/dist/esm/lib/index.js.map +1 -0
  16. package/dist/esm/lib/operators/http-request-handler.js +10 -0
  17. package/dist/esm/lib/operators/http-request-handler.js.map +1 -0
  18. package/dist/esm/lib/operators/http-response-handler.js +5 -0
  19. package/dist/esm/lib/operators/http-response-handler.js.map +1 -0
  20. package/dist/esm/lib/operators/index.js +5 -0
  21. package/dist/esm/lib/operators/index.js.map +1 -0
  22. package/dist/esm/{process-operators.js → lib/operators/process-operators.js} +0 -0
  23. package/dist/esm/lib/operators/process-operators.js.map +1 -0
  24. package/dist/esm/lib/operators/request-operator-header.js +7 -0
  25. package/dist/esm/lib/operators/request-operator-header.js.map +1 -0
  26. package/dist/esm/lib/operators/types.js +2 -0
  27. package/dist/esm/lib/operators/types.js.map +1 -0
  28. package/dist/esm/lib/selectors/index.js +2 -0
  29. package/dist/esm/lib/selectors/index.js.map +1 -0
  30. package/dist/esm/{selector.js → lib/selectors/json-selector.js} +2 -1
  31. package/dist/esm/lib/selectors/json-selector.js.map +1 -0
  32. package/dist/esm/module.js +1 -1
  33. package/dist/esm/module.js.map +1 -1
  34. package/dist/esm/provider.js.map +1 -1
  35. package/dist/tsconfig.tsbuildinfo +1 -1
  36. package/dist/types/configurator.d.ts +9 -7
  37. package/dist/types/index.d.ts +1 -3
  38. package/dist/types/{client-msal.d.ts → lib/client/client-msal.d.ts} +2 -1
  39. package/dist/types/lib/client/client.d.ts +32 -0
  40. package/dist/types/lib/client/index.d.ts +3 -0
  41. package/dist/types/lib/client/types.d.ts +27 -0
  42. package/dist/types/lib/index.d.ts +3 -0
  43. package/dist/types/lib/operators/http-request-handler.d.ts +6 -0
  44. package/dist/types/lib/operators/http-response-handler.d.ts +4 -0
  45. package/dist/types/lib/operators/index.d.ts +4 -0
  46. package/dist/types/{process-operators.d.ts → lib/operators/process-operators.d.ts} +2 -2
  47. package/dist/types/lib/operators/request-operator-header.d.ts +4 -0
  48. package/dist/types/lib/operators/types.d.ts +14 -0
  49. package/dist/types/lib/selectors/index.d.ts +1 -0
  50. package/dist/types/{selector.d.ts → lib/selectors/json-selector.d.ts} +1 -0
  51. package/dist/types/module.d.ts +2 -2
  52. package/dist/types/provider.d.ts +5 -3
  53. package/package.json +23 -4
  54. package/src/configurator.ts +10 -7
  55. package/src/index.ts +2 -4
  56. package/src/{client-msal.ts → lib/client/client-msal.ts} +2 -1
  57. package/src/lib/client/client.ts +161 -0
  58. package/src/lib/client/index.ts +4 -0
  59. package/src/lib/client/types.ts +145 -0
  60. package/src/lib/index.ts +3 -0
  61. package/src/lib/operators/http-request-handler.ts +21 -0
  62. package/src/lib/operators/http-response-handler.ts +5 -0
  63. package/src/lib/operators/index.ts +5 -0
  64. package/src/{process-operators.ts → lib/operators/process-operators.ts} +2 -19
  65. package/src/lib/operators/request-operator-header.ts +12 -0
  66. package/src/lib/operators/types.ts +42 -0
  67. package/src/lib/selectors/index.ts +1 -0
  68. package/src/{selector.ts → lib/selectors/json-selector.ts} +2 -0
  69. package/src/module.ts +2 -2
  70. package/src/provider.ts +6 -3
  71. package/dist/esm/client-msal.js.map +0 -1
  72. package/dist/esm/client.js.map +0 -1
  73. package/dist/esm/process-operators.js.map +0 -1
  74. package/dist/esm/selector.js.map +0 -1
  75. package/dist/types/client.d.ts +0 -54
  76. package/src/client.ts +0 -286
@@ -1,4 +1,4 @@
1
- import { HttpClientMsal } from './client-msal';
1
+ import { HttpClientMsal } from './lib/client';
2
2
  import { IHttpClientConfigurator, HttpClientOptions } from './configurator';
3
3
  import { IHttpClientProvider } from './provider';
4
4
  import type { Module, ModuleConfigType, IModuleConfigurator } from '@equinor/fusion-framework-module';
@@ -9,7 +9,7 @@ export declare const configureHttp: (configure: (config: ModuleConfigType<HttpMo
9
9
  export declare const configureHttpClient: (name: string, args: HttpClientOptions) => IModuleConfigurator<HttpModule>;
10
10
  declare module '@equinor/fusion-framework-module' {
11
11
  interface Modules {
12
- http: HttpModule;
12
+ http: HttpMsalModule;
13
13
  }
14
14
  }
15
15
  export default module;
@@ -1,10 +1,12 @@
1
- import { HttpClient, HttpRequestHandler, IHttpClient } from './client';
1
+ import { HttpClient } from './lib/client';
2
2
  import { HttpClientOptions, HttpClientRequestInitType, IHttpClientConfigurator } from './configurator';
3
+ import type { IHttpRequestHandler } from './lib/operators';
4
+ import type { IHttpClient } from './lib/client';
3
5
  export declare class ClientNotFoundException extends Error {
4
6
  constructor(message: string);
5
7
  }
6
8
  export interface IHttpClientProvider<TClient extends IHttpClient = IHttpClient> {
7
- readonly defaultHttpRequestHandler: HttpRequestHandler<HttpClientRequestInitType<TClient>>;
9
+ readonly defaultHttpRequestHandler: IHttpRequestHandler<HttpClientRequestInitType<TClient>>;
8
10
  hasClient(key: string): boolean;
9
11
  createClient(key: string): TClient;
10
12
  createClient(key: HttpClientOptions<TClient>): TClient;
@@ -12,7 +14,7 @@ export interface IHttpClientProvider<TClient extends IHttpClient = IHttpClient>
12
14
  }
13
15
  export declare class HttpClientProvider<TClient extends IHttpClient = IHttpClient> implements IHttpClientProvider<TClient> {
14
16
  protected config: IHttpClientConfigurator<TClient>;
15
- get defaultHttpRequestHandler(): HttpRequestHandler<HttpClientRequestInitType<TClient>>;
17
+ get defaultHttpRequestHandler(): IHttpRequestHandler<HttpClientRequestInitType<TClient>>;
16
18
  constructor(config: IHttpClientConfigurator<TClient>);
17
19
  hasClient(key: string): boolean;
18
20
  createClient(keyOrConfig: string | HttpClientOptions<TClient>): TClient;
package/package.json CHANGED
@@ -1,12 +1,31 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-module-http",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "description": "",
5
5
  "main": "dist/esm/index.js",
6
+ "types": "index.d.ts",
6
7
  "exports": {
7
- ".": "./dist/esm/index.js"
8
+ ".": "./dist/esm/index.js",
9
+ "./client": "./dist/esm/lib/client/index.js",
10
+ "./operators": "./dist/esm/lib/operators/index.js",
11
+ "./selectors": "./dist/esm/lib/selectors/index.js"
12
+ },
13
+ "typesVersions": {
14
+ ">=4.2": {
15
+ "*": [
16
+ "dist/types/*"
17
+ ],
18
+ "client": [
19
+ "dist/types/lib/client/index.d.ts"
20
+ ],
21
+ "operators": [
22
+ "dist/types/lib/operators/index.d.ts"
23
+ ],
24
+ "selectors": [
25
+ "dist/types/lib/selectors/index.d.ts"
26
+ ]
27
+ }
8
28
  },
9
- "types": "dist/types/index.d.ts",
10
29
  "scripts": {
11
30
  "build": "npm run build:typescript",
12
31
  "build:typescript": "tsc -b --verbose"
@@ -29,5 +48,5 @@
29
48
  "devDependencies": {
30
49
  "typescript": "^4.8.2"
31
50
  },
32
- "gitHead": "4e92ef5173981f4e43bad9a2a2e53fb3f71da7a1"
51
+ "gitHead": "afbbc5036ce33357ea7f946a082282b72f86da30"
33
52
  }
@@ -1,7 +1,10 @@
1
- import { HttpRequestHandler, FetchRequest, IHttpClient, HttpResponseHandler } from './client';
1
+ import { HttpRequestHandler } from './lib/operators';
2
+
3
+ import type { FetchRequest, IHttpClient } from './lib/client';
4
+ import type { IHttpRequestHandler, IHttpResponseHandler } from './lib/operators';
2
5
 
3
6
  interface HttpClientConstructorOptions<TInit extends FetchRequest> {
4
- requestHandler: HttpRequestHandler<TInit>;
7
+ requestHandler: IHttpRequestHandler<TInit>;
5
8
  }
6
9
 
7
10
  interface HttpClientConstructor<TClient extends IHttpClient> {
@@ -16,8 +19,8 @@ export interface HttpClientOptions<TClient extends IHttpClient = IHttpClient> {
16
19
  defaultScopes?: string[];
17
20
  ctor?: HttpClientConstructor<TClient>;
18
21
  onCreate?: (client: TClient) => void;
19
- requestHandler?: HttpRequestHandler<HttpClientRequestInitType<TClient>>;
20
- responseHandler?: HttpResponseHandler<HttpClientRequestInitType<TClient>>;
22
+ requestHandler?: IHttpRequestHandler<HttpClientRequestInitType<TClient>>;
23
+ responseHandler?: IHttpResponseHandler<HttpClientRequestInitType<TClient>>;
21
24
  }
22
25
 
23
26
  export type HttpClientRequestInitType<T extends IHttpClient> = T extends IHttpClient<infer U>
@@ -31,7 +34,7 @@ export type HttpClientRequestInitType<T extends IHttpClient> = T extends IHttpCl
31
34
  export interface IHttpClientConfigurator<TClient extends IHttpClient = IHttpClient> {
32
35
  readonly clients: Record<string, HttpClientOptions<TClient>>;
33
36
  readonly defaultHttpClientCtor: HttpClientConstructor<TClient>;
34
- readonly defaultHttpRequestHandler: HttpRequestHandler<HttpClientRequestInitType<TClient>>;
37
+ readonly defaultHttpRequestHandler: IHttpRequestHandler<HttpClientRequestInitType<TClient>>;
35
38
 
36
39
  /**
37
40
  * Configure a client with arguments
@@ -48,14 +51,14 @@ export interface IHttpClientConfigurator<TClient extends IHttpClient = IHttpClie
48
51
  configureClient<T extends TClient>(
49
52
  name: string,
50
53
  args: HttpClientOptions<T>
51
- ): HttpClientConfigurator<TClient>;
54
+ ): IHttpClientConfigurator<TClient>;
52
55
 
53
56
  /**
54
57
  * Configure a simple client by name to an endpoint
55
58
  * @param name name of the client
56
59
  * @param uri base endpoint for the client
57
60
  */
58
- configureClient(name: string, uri: string): HttpClientConfigurator<TClient>;
61
+ configureClient(name: string, uri: string): IHttpClientConfigurator<TClient>;
59
62
 
60
63
  /**
61
64
  * Creates a client with callback configuration
package/src/index.ts CHANGED
@@ -3,12 +3,10 @@
3
3
  * @module
4
4
  */
5
5
 
6
- export { HttpClient, IHttpClient, FetchRequestInit, FetchRequest } from './client';
7
- export { HttpClientMsal } from './client-msal';
8
-
9
6
  export * from './configurator';
10
7
  export * from './provider';
11
8
  export * from './module';
12
- export * from './selector';
9
+
10
+ export type { IHttpClient } from './lib/client';
13
11
 
14
12
  export { default } from './module';
@@ -1,5 +1,6 @@
1
1
  import type { Observable } from 'rxjs';
2
- import { HttpClient, FetchRequestInit, FetchRequest } from './client';
2
+ import type { FetchRequestInit, FetchRequest } from '.';
3
+ import { HttpClient } from './client';
3
4
 
4
5
  /** Extends request init with scope */
5
6
  type MsalFetchRequest = FetchRequest & { scopes?: string[] };
@@ -0,0 +1,161 @@
1
+ import { firstValueFrom, of, Subject } from 'rxjs';
2
+ import { switchMap, takeUntil, tap } from 'rxjs/operators';
3
+ import { fromFetch } from 'rxjs/fetch';
4
+
5
+ import { HttpRequestHandler, HttpResponseHandler } from '../operators';
6
+ import { jsonSelector } from '../selectors';
7
+
8
+ import type { Observable, ObservableInput } from 'rxjs';
9
+ import type { IHttpRequestHandler, IHttpResponseHandler } from '../operators';
10
+ import type { FetchRequest, FetchRequestInit, IHttpClient, StreamResponse } from '.';
11
+
12
+ export type HttpClientCreateOptions<
13
+ TRequest extends FetchRequest = FetchRequest,
14
+ TResponse = Response
15
+ > = {
16
+ requestHandler: IHttpRequestHandler<TRequest>;
17
+ responseHandler: IHttpResponseHandler<TResponse>;
18
+ };
19
+
20
+ /** Base http client for executing requests */
21
+ export class HttpClient<TRequest extends FetchRequest = FetchRequest, TResponse = Response>
22
+ implements IHttpClient<TRequest, TResponse>
23
+ {
24
+ readonly requestHandler: IHttpRequestHandler<TRequest>;
25
+
26
+ readonly responseHandler: IHttpResponseHandler<TResponse>;
27
+
28
+ /** stream of requests that are about to be executed */
29
+ protected _request$ = new Subject<TRequest>();
30
+
31
+ /** stream of request responses */
32
+ protected _response$ = new Subject<TResponse>();
33
+
34
+ protected _abort$ = new Subject<void>();
35
+
36
+ public get request$(): Observable<TRequest> {
37
+ return this._request$.asObservable();
38
+ }
39
+
40
+ public get response$(): Observable<TResponse> {
41
+ return this._response$.asObservable();
42
+ }
43
+
44
+ constructor(
45
+ public uri: string,
46
+ options?: Partial<HttpClientCreateOptions<TRequest, TResponse>>
47
+ ) {
48
+ this.requestHandler = options?.requestHandler ?? new HttpRequestHandler<TRequest>();
49
+ this.responseHandler = options?.responseHandler ?? new HttpResponseHandler<TResponse>();
50
+ this._init();
51
+ }
52
+
53
+ /** internal abstract method, for overriding instead of overriding constructor */
54
+ protected _init(): void {
55
+ // called by children for constructor setup
56
+ }
57
+
58
+ public fetch$<T = TResponse>(
59
+ path: string,
60
+ args?: FetchRequestInit<T, TRequest, TResponse>
61
+ ): StreamResponse<T> {
62
+ return this._fetch$(path, args);
63
+ }
64
+
65
+ public fetch<T = TResponse>(
66
+ path: string,
67
+ args?: FetchRequestInit<T, TRequest, TResponse>
68
+ ): Promise<T> {
69
+ return firstValueFrom(this.fetch$<T>(path, args));
70
+ }
71
+
72
+ /** @deprecated */
73
+ public fetchAsync<T = TResponse>(
74
+ path: string,
75
+ args?: FetchRequestInit<T, TRequest, TResponse>
76
+ ): Promise<T> {
77
+ return this.fetch(path, args);
78
+ }
79
+
80
+ public json$<T = TResponse>(
81
+ path: string,
82
+ args?: FetchRequestInit<T, TRequest, TResponse>
83
+ ): StreamResponse<T> {
84
+ const body = typeof args?.body === 'object' ? JSON.stringify(args?.body) : args?.body;
85
+ const selector = args?.selector ?? jsonSelector;
86
+ const header = new Headers(args?.headers);
87
+ header.append('Content-Type', 'application/json');
88
+ return this.fetch$(path, {
89
+ ...args,
90
+ body,
91
+ selector,
92
+ } as FetchRequestInit<T, TRequest, TResponse>);
93
+ }
94
+
95
+ public json<T = TResponse>(
96
+ path: string,
97
+ args?: FetchRequestInit<T, TRequest, TResponse>
98
+ ): Promise<T> {
99
+ return firstValueFrom(this.json$<T>(path, args));
100
+ }
101
+
102
+ /** @deprecated */
103
+ public jsonAsync<T = TResponse>(
104
+ path: string,
105
+ args?: FetchRequestInit<T, TRequest, TResponse>
106
+ ): Promise<T> {
107
+ return this.json(path, args);
108
+ }
109
+
110
+ public execute<T = TResponse, TMethod extends 'fetch' | 'fetch$' | 'json' | 'json$' = 'fetch'>(
111
+ method: TMethod,
112
+ path: string,
113
+ init?: FetchRequestInit<T, TRequest, TResponse>
114
+ ): ReturnType<IHttpClient[TMethod]> {
115
+ return this[method](path, init) as ReturnType<IHttpClient[TMethod]>;
116
+ }
117
+
118
+ public abort(): void {
119
+ this._abort$.next();
120
+ }
121
+
122
+ protected _fetch$<T = TResponse>(
123
+ path: string,
124
+ args?: FetchRequestInit<T, TRequest, TResponse>
125
+ ): Observable<T> {
126
+ const { selector, ...options } = args || {};
127
+ const response$ = of({
128
+ ...options,
129
+ uri: this._resolveUrl(path),
130
+ } as TRequest).pipe(
131
+ /** prepare request, allow extensions to modify request */
132
+ switchMap((x) => this._prepareRequest(x)),
133
+ /** push request to event buss */
134
+ tap((x) => this._request$.next(x)),
135
+ /** execute request */
136
+ switchMap(({ uri, path: _path, ...init }) => fromFetch(uri, init)),
137
+ /** prepare response, allow extensions to modify response */
138
+ switchMap((x) => this._prepareResponse(x as unknown as TResponse)),
139
+ /** push response to event buss */
140
+ tap((x) => this._response$.next(x)),
141
+
142
+ switchMap((x) => (selector ? selector(x) : Promise.resolve(x))),
143
+ /** cancel request on abort signal */
144
+ takeUntil(this._abort$)
145
+ );
146
+ return response$ as unknown as Observable<T>;
147
+ }
148
+
149
+ protected _prepareRequest(init: TRequest): ObservableInput<TRequest> {
150
+ return this.requestHandler.process(init);
151
+ }
152
+
153
+ protected _prepareResponse(response: TResponse): ObservableInput<TResponse> {
154
+ return this.responseHandler.process(response);
155
+ }
156
+
157
+ protected _resolveUrl(path: string): string {
158
+ const baseUrl = this.uri || window.location.origin;
159
+ return new URL(path, baseUrl).href;
160
+ }
161
+ }
@@ -0,0 +1,4 @@
1
+ export { HttpClient } from './client';
2
+ export { HttpClientMsal } from './client-msal';
3
+
4
+ export * from './types';
@@ -0,0 +1,145 @@
1
+ import type { ObservableInput, Observable } from 'rxjs';
2
+ import type { IHttpRequestHandler, IHttpResponseHandler } from '../operators/types';
3
+
4
+ export type StreamResponse<T> = Observable<T>;
5
+
6
+ export type FetchRequest = RequestInit & {
7
+ uri: string;
8
+ path: string;
9
+ };
10
+
11
+ export type FetchRequestInit<
12
+ TReturn = unknown,
13
+ TRequest = FetchRequest,
14
+ TResponse = Response
15
+ > = Omit<TRequest, 'uri' | 'path'> & {
16
+ selector?: (response: TResponse) => ObservableInput<TReturn>;
17
+ };
18
+
19
+ export type ClientRequestInit<T extends IHttpClient, TReturn = unknown> = T extends IHttpClient<
20
+ infer TRequest,
21
+ infer TResponse
22
+ >
23
+ ? FetchRequestInit<TReturn, TRequest, TResponse>
24
+ : never;
25
+
26
+ export type ExecutionMethod = 'fetch' | 'fetch$' | 'json' | 'json$';
27
+
28
+ export type ExecutionMethodParameters<
29
+ TMethod extends ExecutionMethod = 'fetch',
30
+ TClient extends IHttpClient = IHttpClient
31
+ > = Parameters<TClient[TMethod]>;
32
+
33
+ export type ExecutionResponse<
34
+ TMethod extends ExecutionMethod = 'fetch',
35
+ TClient extends IHttpClient = IHttpClient
36
+ > = ReturnType<TClient[TMethod]>;
37
+
38
+ /**
39
+ * @template TRequest request arguments @see {@link https://developer.mozilla.org/en-US/docs/Web/API/request|request}
40
+ * @template TResponse request arguments @see {@link https://developer.mozilla.org/en-US/docs/Web/API/response|response}
41
+ */
42
+ export interface IHttpClient<TRequest extends FetchRequest = FetchRequest, TResponse = Response> {
43
+ uri: string;
44
+ /** pre-processor of requests */
45
+ readonly requestHandler: IHttpRequestHandler<TRequest>;
46
+ /** post-processor of requests */
47
+ readonly responseHandler: IHttpResponseHandler<TResponse>;
48
+
49
+ /** Observable stream of request */
50
+ request$: Observable<TRequest>;
51
+
52
+ /** Observable stream of responses */
53
+ response$: Observable<TResponse>;
54
+
55
+ /**
56
+ * Observable request.
57
+ * Simplifies execution of request and
58
+ * note: request will not be executed until subscribe!
59
+ *
60
+ * @see {@link https://rxjs.dev/api/fetch/fromFetch|RXJS}
61
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch|fetch}
62
+ * @example
63
+ * ```ts
64
+ * // Observer changes of a input field
65
+ * const client = modules.http.createClient('my-client');
66
+ * const input$ = fromEvent(document.getElementById('input'), 'input');
67
+ * input$.pipe(
68
+ * // only call after no key input in .5s
69
+ * debounceTime(500),
70
+ * // extract value from event
71
+ * map(x => x.currentTarget.value),
72
+ * // only search when text longer than 2 characters
73
+ * filter(x => x.length >=3),
74
+ * // query api with input value
75
+ * switchMap(x => client.fetch(`api/foo?q=${x}`).pipe(
76
+ * // retry 2 times
77
+ * retry(2)
78
+ * // cancel request if new input
79
+ * takeUntil(input$)
80
+ * )),
81
+ * // extract data from response
82
+ * switchMap(x => x.json()),
83
+ * // process error
84
+ * catchError(x => of({error: e.message}))
85
+ * // write result to pre element
86
+ * ).subscribe(console.log);
87
+ * ```
88
+ */
89
+ fetch$<T = TResponse>(
90
+ path: string,
91
+ init?: FetchRequestInit<T, TRequest, TResponse>
92
+ ): StreamResponse<T>;
93
+
94
+ /**
95
+ * Fetch a resource as an promise
96
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch|fetch}
97
+ * @example
98
+ * ```ts
99
+ * let controller: AbortController;
100
+ * const client = window.Fusion.createClient('my-client');
101
+ * const input = document.getElementById('input');
102
+ * input.addEventlistener('input', (e) => {
103
+ * try{
104
+ * // if a controller is defined, request might be ongoing
105
+ * controller && controller.abort();
106
+ * // create a new abort controller
107
+ * controller = new AbortController();
108
+ * // query api with
109
+ * const response = await client.fetch({
110
+ * path: `api/foo?q=${e.currentTarget.value}`,
111
+ * signal: controller.signal,
112
+ * });
113
+ * const json = await response.json();
114
+ * result.innerText = JSON.stringify(json, null, 2)
115
+ * } catch(err){
116
+ * result.innerText = 'an error occurred'
117
+ * } finally{
118
+ * delete controller;
119
+ * }
120
+ * });
121
+ * ```
122
+ */
123
+ fetch<T = TResponse>(path: string, init?: FetchRequestInit<T, TRequest, TResponse>): Promise<T>;
124
+
125
+ json$<T = TResponse>(
126
+ path: string,
127
+ init?: FetchRequestInit<T, TRequest, TResponse>
128
+ ): StreamResponse<T>;
129
+
130
+ json<T = TResponse>(path: string, init?: FetchRequestInit<T, TRequest, TResponse>): Promise<T>;
131
+
132
+ /**
133
+ *
134
+ */
135
+ execute<T = TResponse, TMethod extends 'fetch' | 'fetch$' | 'json' | 'json$' = 'fetch'>(
136
+ method: TMethod,
137
+ path: string,
138
+ init?: FetchRequestInit<T, TRequest, TResponse>
139
+ ): ReturnType<IHttpClient[TMethod]>;
140
+
141
+ /**
142
+ * Abort all ongoing request for current client
143
+ */
144
+ abort(): void;
145
+ }
@@ -0,0 +1,3 @@
1
+ export * from './client';
2
+ export * from './operators';
3
+ export * from './selectors';
@@ -0,0 +1,21 @@
1
+ import { ProcessOperators } from './process-operators';
2
+ import { requestOperatorHeader } from './request-operator-header';
3
+
4
+ import type { FetchRequest } from '../client';
5
+
6
+ /**
7
+ * Extends @see {ProcessOperators} for pre-processing requests.
8
+ */
9
+ export class HttpRequestHandler<T extends FetchRequest = FetchRequest> extends ProcessOperators<T> {
10
+ /**
11
+ * Set header that will apply on all requests done by consumer @see {HttpClient}
12
+ * @param key - name of header
13
+ * @param value - header value
14
+ */
15
+ setHeader(key: string, value: string): HttpRequestHandler<T> {
16
+ const operator = requestOperatorHeader<T>(key, value);
17
+ return this.set('header-' + key, operator) as HttpRequestHandler<T>;
18
+ }
19
+ }
20
+
21
+ export default HttpRequestHandler;
@@ -0,0 +1,5 @@
1
+ import { ProcessOperators } from './process-operators';
2
+
3
+ export class HttpResponseHandler<T = Response> extends ProcessOperators<T> {}
4
+
5
+ export default HttpResponseHandler;
@@ -0,0 +1,5 @@
1
+ export { HttpRequestHandler } from './http-request-handler';
2
+ export { HttpResponseHandler } from './http-response-handler';
3
+ export { ProcessOperators } from './process-operators';
4
+
5
+ export * from './types';
@@ -1,43 +1,26 @@
1
1
  import { from, of } from 'rxjs';
2
2
  import type { Observable } from 'rxjs';
3
3
  import { last, mergeScan } from 'rxjs/operators';
4
+ import { IProcessOperators, ProcessOperator } from './types';
4
5
 
5
- export type ProcessOperator<T, R = T> = (request: T) => R | void | Promise<R | void>;
6
-
7
- /**
8
- * Container for sync/async operators.
9
- * Pipes each operator sequential
10
- */
11
- export class ProcessOperators<T> {
6
+ export class ProcessOperators<T> implements IProcessOperators<T> {
12
7
  protected _operators: Record<string, ProcessOperator<T>> = {};
13
8
 
14
- /**
15
- * Add a new operator (throw error if already defined)
16
- */
17
9
  add(key: string, operator: ProcessOperator<T>): ProcessOperators<T> {
18
10
  if (Object.keys(this._operators).includes(key))
19
11
  throw Error(`Operator [${key}] already defined`);
20
12
  return this.set(key, operator);
21
13
  }
22
14
 
23
- /**
24
- * Add or sets a operator
25
- */
26
15
  set(key: string, operator: ProcessOperator<T>): ProcessOperators<T> {
27
16
  this._operators[key] = operator;
28
17
  return this;
29
18
  }
30
19
 
31
- /**
32
- * Get a operator, will return undefined on invalid key.
33
- */
34
20
  get(key: string): ProcessOperator<T> {
35
21
  return this._operators[key];
36
22
  }
37
23
 
38
- /**
39
- * Process registered processors.
40
- */
41
24
  process(request: T): Observable<T> {
42
25
  const operators = Object.values(this._operators);
43
26
  /** if no operators registered, just return the observable value */
@@ -0,0 +1,12 @@
1
+ import type { FetchRequest } from '../client';
2
+ import type { ProcessOperator } from './types';
3
+
4
+ export const requestOperatorHeader =
5
+ <T extends FetchRequest = FetchRequest>(key: string, value: string): ProcessOperator<T> =>
6
+ (request) => {
7
+ const headers = new Headers(request.headers);
8
+ headers.append(key, value);
9
+ return { ...request, headers };
10
+ };
11
+
12
+ export default requestOperatorHeader;
@@ -0,0 +1,42 @@
1
+ import type { Observable } from 'rxjs';
2
+ import type { FetchRequest } from '../client';
3
+
4
+ export type ProcessOperator<T, R = T> = (request: T) => R | void | Promise<R | void>;
5
+
6
+ /**
7
+ * Container for sync/async operators.
8
+ * Pipes each operator sequential
9
+ */
10
+ export interface IProcessOperators<T> {
11
+ /**
12
+ * Add a new operator (throw error if already defined)
13
+ */
14
+ add(key: string, operator: ProcessOperator<T>): IProcessOperators<T>;
15
+
16
+ /**
17
+ * Add or sets a operator
18
+ */
19
+ set(key: string, operator: ProcessOperator<T>): IProcessOperators<T>;
20
+
21
+ /**
22
+ * Get a operator, will return undefined on invalid key.
23
+ */
24
+ get(key: string): ProcessOperator<T>;
25
+
26
+ /**
27
+ * Process registered processors.
28
+ */
29
+ process(request: T): Observable<T>;
30
+ }
31
+
32
+ export interface IHttpRequestHandler<T extends FetchRequest = FetchRequest>
33
+ extends IProcessOperators<T> {
34
+ /**
35
+ * Set header that will apply on all requests done by consumer @see {HttpClient}
36
+ * @param key - name of header
37
+ * @param value - header value
38
+ */
39
+ setHeader(key: string, value: string): IHttpRequestHandler<T>;
40
+ }
41
+
42
+ export interface IHttpResponseHandler<T = Response> extends IProcessOperators<T> {}
@@ -0,0 +1 @@
1
+ export { jsonSelector } from './json-selector';
@@ -10,3 +10,5 @@ export const jsonSelector = <TType = unknown, TResponse extends Response = Respo
10
10
  throw Error('failed to parse response');
11
11
  }
12
12
  };
13
+
14
+ export default jsonSelector;
package/src/module.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { HttpClientMsal } from './client-msal';
1
+ import { HttpClientMsal } from './lib/client';
2
2
  import { IHttpClientConfigurator, HttpClientConfigurator, HttpClientOptions } from './configurator';
3
3
  import { IHttpClientProvider, HttpClientProvider } from './provider';
4
4
 
@@ -45,7 +45,7 @@ export const configureHttpClient = (
45
45
 
46
46
  declare module '@equinor/fusion-framework-module' {
47
47
  interface Modules {
48
- http: HttpModule;
48
+ http: HttpMsalModule;
49
49
  }
50
50
  }
51
51
 
package/src/provider.ts CHANGED
@@ -1,10 +1,13 @@
1
- import { HttpClient, HttpRequestHandler, IHttpClient } from './client';
1
+ import { HttpClient } from './lib/client';
2
2
  import {
3
3
  HttpClientOptions,
4
4
  HttpClientRequestInitType,
5
5
  IHttpClientConfigurator,
6
6
  } from './configurator';
7
7
 
8
+ import type { IHttpRequestHandler } from './lib/operators';
9
+ import type { IHttpClient } from './lib/client';
10
+
8
11
  export class ClientNotFoundException extends Error {
9
12
  constructor(message: string) {
10
13
  super(message);
@@ -12,7 +15,7 @@ export class ClientNotFoundException extends Error {
12
15
  }
13
16
 
14
17
  export interface IHttpClientProvider<TClient extends IHttpClient = IHttpClient> {
15
- readonly defaultHttpRequestHandler: HttpRequestHandler<HttpClientRequestInitType<TClient>>;
18
+ readonly defaultHttpRequestHandler: IHttpRequestHandler<HttpClientRequestInitType<TClient>>;
16
19
  /** check if a client is configured */
17
20
  hasClient(key: string): boolean;
18
21
  /** create a new http client */
@@ -46,7 +49,7 @@ const isURL = (url: string) => {
46
49
  export class HttpClientProvider<TClient extends IHttpClient = IHttpClient>
47
50
  implements IHttpClientProvider<TClient>
48
51
  {
49
- get defaultHttpRequestHandler(): HttpRequestHandler<HttpClientRequestInitType<TClient>> {
52
+ get defaultHttpRequestHandler(): IHttpRequestHandler<HttpClientRequestInitType<TClient>> {
50
53
  return this.config.defaultHttpRequestHandler;
51
54
  }
52
55