@equinor/fusion-framework-module-http
Advanced tools
Comparing version 0.1.0-beta.14 to 0.1.0-beta.15
import { HttpClient } from './client'; | ||
export class HttpClientMsal extends HttpClient { | ||
defaultScopes = []; | ||
fetch(init) { | ||
init = typeof init === 'string' ? { path: init } : init; | ||
Object.assign(init, { scopes: this.defaultScopes.concat(init.scopes || []) }); | ||
return super.fetch(init); | ||
fetch(path, init) { | ||
const args = Object.assign(init || {}, { | ||
scopes: this.defaultScopes.concat(init?.scopes || []), | ||
}); | ||
return super._fetch(path, args); | ||
} | ||
@@ -9,0 +10,0 @@ } |
@@ -34,8 +34,7 @@ import { firstValueFrom, of, Subject } from 'rxjs'; | ||
} | ||
fetch(init) { | ||
const options = typeof init === 'string' ? { path: init } : init; | ||
return of({ ...options, uri: this._resolveUrl(options.path) }).pipe(switchMap((x) => this._prepareRequest(x)), tap((x) => this._request$.next(x)), switchMap(({ uri, path: _path, ...args }) => fromFetch(uri, args)), switchMap((x) => this._prepareResponse(x)), tap((x) => this._response$.next(x)), takeUntil(this._abort$)); | ||
fetch(path, args) { | ||
return this._fetch(path, args); | ||
} | ||
fetchAsync(init) { | ||
return firstValueFrom(this.fetch(init)); | ||
fetchAsync(path, args) { | ||
return firstValueFrom(this.fetch(path, args)); | ||
} | ||
@@ -45,2 +44,9 @@ abort() { | ||
} | ||
_fetch(path, args) { | ||
const { selector, ...options } = Object.assign({}, args || { selector: undefined }, { | ||
path, | ||
}); | ||
const response$ = of({ ...options, uri: this._resolveUrl(options.path) }).pipe(switchMap((x) => this._prepareRequest(x)), tap((x) => this._request$.next(x)), switchMap(({ uri, path: _path, ...args }) => fromFetch(uri, args)), switchMap((x) => this._prepareResponse(x)), tap((x) => this._response$.next(x)), switchMap((x) => (selector ? selector(x) : Promise.resolve(x))), takeUntil(this._abort$)); | ||
return response$; | ||
} | ||
_prepareRequest(init) { | ||
@@ -47,0 +53,0 @@ return this.requestHandler.process(init); |
@@ -1,9 +0,11 @@ | ||
import { HttpClient, HttpRequestInit } from './client'; | ||
declare type RequestInitMsal = HttpRequestInit & { | ||
import { Observable } from 'rxjs'; | ||
import { HttpClient, FetchRequestInit, FetchRequest } from './client'; | ||
declare type MsalFetchRequest = FetchRequest & { | ||
scopes?: string[]; | ||
}; | ||
export declare class HttpClientMsal extends HttpClient<RequestInitMsal> { | ||
declare type MsalFetchRequestInit<TReturn = unknown, TRequest = FetchRequest, TResponse = Response> = FetchRequestInit<TReturn, TRequest, TResponse> & Pick<MsalFetchRequest, 'scopes'>; | ||
export declare class HttpClientMsal<TRequest extends MsalFetchRequest = MsalFetchRequest, TResponse = Response> extends HttpClient<TRequest, TResponse> { | ||
defaultScopes: string[]; | ||
fetch(init: Omit<RequestInitMsal, 'uri'> | string): ReturnType<HttpClient['fetch']>; | ||
fetch<T = TResponse>(path: string, init?: MsalFetchRequestInit<T, TRequest, TResponse>): Observable<T>; | ||
} | ||
export default HttpClientMsal; |
import { Observable, ObservableInput, Subject } from 'rxjs'; | ||
import { ProcessOperators } from './process-operators'; | ||
export declare type HttpRequestInit = RequestInit & { | ||
export declare type FetchRequest = RequestInit & { | ||
uri: string; | ||
path: string; | ||
}; | ||
export declare class HttpRequestHandler<T extends HttpRequestInit = HttpRequestInit> extends ProcessOperators<T> { | ||
export declare type FetchRequestInit<TReturn = unknown, TRequest = FetchRequest, TResponse = Response> = Omit<TRequest, 'uri' | 'path'> & { | ||
selector?: (response: TResponse) => ObservableInput<TReturn>; | ||
}; | ||
export declare class HttpRequestHandler<T extends FetchRequest = FetchRequest> extends ProcessOperators<T> { | ||
setHeader(key: string, value: string): HttpRequestHandler<T>; | ||
} | ||
export declare type HttpClientCreateOptions<T extends HttpRequestInit = HttpRequestInit> = { | ||
export declare type HttpClientCreateOptions<T extends FetchRequest = FetchRequest> = { | ||
requestHandler: HttpRequestHandler<T>; | ||
}; | ||
export declare type HttpResponseHandler<T> = (response: Response) => Promise<T>; | ||
export interface IHttpClient<TRequest extends HttpRequestInit = HttpRequestInit, TResponse = Response> { | ||
export interface IHttpClient<TRequest extends FetchRequest = FetchRequest, TResponse = Response> { | ||
uri: string; | ||
@@ -20,7 +23,7 @@ readonly requestHandler: HttpRequestHandler<TRequest>; | ||
response$: Observable<TResponse>; | ||
fetch(init: Omit<TRequest, 'uri'> | string): Observable<TResponse>; | ||
fetchAsync(init: Omit<TRequest, 'uri'> | string): Promise<TResponse>; | ||
fetch<T = TResponse>(path: string, init?: FetchRequestInit<T, TRequest, TResponse>): Observable<T>; | ||
fetchAsync<T = TResponse>(path: string, init?: FetchRequestInit<T, TRequest, TResponse>): Promise<T>; | ||
abort(): void; | ||
} | ||
export declare class HttpClient<TRequest extends HttpRequestInit = HttpRequestInit, TResponse = Response> implements IHttpClient<TRequest, TResponse> { | ||
export declare class HttpClient<TRequest extends FetchRequest = FetchRequest, TResponse = Response> implements IHttpClient<TRequest, TResponse> { | ||
uri: string; | ||
@@ -36,5 +39,6 @@ readonly requestHandler: HttpRequestHandler<TRequest>; | ||
protected _init(): void; | ||
fetch(init: Omit<TRequest, 'uri'> | string): Observable<TResponse>; | ||
fetchAsync(init: Omit<TRequest, 'uri'> | string): Promise<TResponse>; | ||
fetch<T = TResponse>(path: string, args?: FetchRequestInit<T, TRequest, TResponse>): Observable<T>; | ||
fetchAsync<T = TResponse>(path: string, args?: FetchRequestInit<T, TRequest, TResponse>): Promise<T>; | ||
abort(): void; | ||
protected _fetch<T = TResponse>(path: string, args?: FetchRequestInit<T, TRequest, TResponse>): Observable<T>; | ||
protected _prepareRequest(init: TRequest): ObservableInput<TRequest>; | ||
@@ -41,0 +45,0 @@ protected _prepareResponse(response: Response): ObservableInput<TResponse>; |
@@ -1,3 +0,3 @@ | ||
import { HttpRequestHandler, HttpRequestInit, IHttpClient } from './client'; | ||
interface HttpClientConstructorOptions<TInit extends HttpRequestInit> { | ||
import { HttpRequestHandler, FetchRequest, IHttpClient } from './client'; | ||
interface HttpClientConstructorOptions<TInit extends FetchRequest> { | ||
requestHandler: HttpRequestHandler<TInit>; | ||
@@ -20,4 +20,4 @@ } | ||
readonly defaultHttpRequestHandler: HttpRequestHandler<HttpClientRequestInitType<TClient>>; | ||
configureClient<T extends TClient>(name: string, args: HttpClientOptions<T>): HttpClientConfigurator<TClient>; | ||
configureClient(name: string, uri: string): HttpClientConfigurator<TClient>; | ||
configureClient<T extends TClient>(name: string, args: HttpClientOptions<T>): HttpClientConfigurator<TClient>; | ||
configureClient<T extends TClient>(name: string, onCreate: (client: T) => void): HttpClientConfigurator<TClient>; | ||
@@ -24,0 +24,0 @@ hasClient(name: string): boolean; |
@@ -1,2 +0,2 @@ | ||
export { HttpClient, IHttpClient } from './client'; | ||
export { HttpClient, IHttpClient, FetchRequestInit } from './client'; | ||
export { HttpClientMsal } from './client-msal'; | ||
@@ -3,0 +3,0 @@ export * from './configurator'; |
{ | ||
"name": "@equinor/fusion-framework-module-http", | ||
"version": "0.1.0-beta.14", | ||
"version": "0.1.0-beta.15", | ||
"description": "", | ||
@@ -24,3 +24,3 @@ "main": "./dist/esm/index.js", | ||
"dependencies": { | ||
"@equinor/fusion-framework-module": "^0.1.0-beta.14" | ||
"@equinor/fusion-framework-module": "^0.1.0-beta.15" | ||
}, | ||
@@ -35,3 +35,3 @@ "types": "index.d.ts", | ||
}, | ||
"gitHead": "be4491d21f95b885efb42970ea51a305207ac493" | ||
"gitHead": "3a979afef20287423f6f7f7b1cff179706cdd3a2" | ||
} |
@@ -1,5 +0,7 @@ | ||
## Api Client | ||
## Configure | ||
### Configure | ||
```tsx | ||
Module for configuring and providing http clients | ||
### Simple | ||
```ts | ||
const configure = (config) => { | ||
@@ -11,2 +13,46 @@ config.http.configureClient( | ||
} | ||
``` | ||
### Standard | ||
```ts | ||
const configure = (config) => { | ||
config.http.configureClient( | ||
'bar', | ||
{ | ||
baseUri: 'https://foo.bar', | ||
defaultScopes: ['foobar/.default'] | ||
} | ||
); | ||
} | ||
``` | ||
### Callback | ||
```ts | ||
const configure = async(config) => { | ||
config.http.configureClient( | ||
'bar', | ||
(client): => { | ||
client.uri = 'https://foo.bar' | ||
client.defaultScopes: ['foobar/.default'] | ||
} | ||
); | ||
} | ||
``` | ||
## Consumption | ||
```ts | ||
const client = modules.http.createClient('foo'); | ||
const selector = (response: Response): Promise<FooBar> => response.json(); | ||
// stream | ||
client.fetch('/api/admin', {selector, scopes: ['foobar/.admin']}).subscribe(x => console.log(x)); | ||
// async | ||
client.fetchAsync('/api', {selector}).then(console.log); | ||
``` | ||
## Operators | ||
```ts | ||
const client = modules.http.createClient('foo'); | ||
const logger = console.debug; | ||
client.requestHandler.add((x: Request) => logger(x)); | ||
client.responseHandler.add((x: Request) => logger(x)); | ||
``` |
@@ -1,8 +0,14 @@ | ||
import { HttpClient, HttpRequestInit } from './client'; | ||
import { Observable } from 'rxjs'; | ||
import { HttpClient, FetchRequestInit, FetchRequest } from './client'; | ||
/** Extends request init with scope */ | ||
type RequestInitMsal = HttpRequestInit & { scopes?: string[] }; | ||
type MsalFetchRequest = FetchRequest & { scopes?: string[] }; | ||
type MsalFetchRequestInit<TReturn = unknown, TRequest = FetchRequest, TResponse = Response> = | ||
FetchRequestInit<TReturn, TRequest, TResponse> & Pick<MsalFetchRequest, 'scopes'>; | ||
/** Default Client for MSAL */ | ||
export class HttpClientMsal extends HttpClient<RequestInitMsal> { | ||
export class HttpClientMsal< | ||
TRequest extends MsalFetchRequest = MsalFetchRequest, | ||
TResponse = Response | ||
> extends HttpClient<TRequest, TResponse> { | ||
/** Scope that will be applied to all request if no scope is provided in request object */ | ||
@@ -12,6 +18,10 @@ public defaultScopes: string[] = []; | ||
/** @inheritdoc */ | ||
fetch(init: Omit<RequestInitMsal, 'uri'> | string): ReturnType<HttpClient['fetch']> { | ||
init = typeof init === 'string' ? { path: init } : init; | ||
Object.assign(init, { scopes: this.defaultScopes.concat(init.scopes || []) }); | ||
return super.fetch(init); | ||
fetch<T = TResponse>( | ||
path: string, | ||
init?: MsalFetchRequestInit<T, TRequest, TResponse> | ||
): Observable<T> { | ||
const args = Object.assign(init || {}, { | ||
scopes: this.defaultScopes.concat(init?.scopes || []), | ||
}) as FetchRequestInit<T, TRequest, TResponse>; | ||
return super._fetch(path, args); | ||
} | ||
@@ -18,0 +28,0 @@ } |
@@ -7,10 +7,16 @@ import { firstValueFrom, Observable, ObservableInput, of, Subject } from 'rxjs'; | ||
export type HttpRequestInit = RequestInit & { uri: string; path: string }; | ||
export type FetchRequest = RequestInit & { | ||
uri: string; | ||
path: string; | ||
}; | ||
export type FetchRequestInit<TReturn = unknown, TRequest = FetchRequest, TResponse = Response> = | ||
Omit<TRequest, 'uri' | 'path'> & { | ||
selector?: (response: TResponse) => ObservableInput<TReturn>; | ||
}; | ||
/** | ||
* Extends @see {ProcessOperators} for pre-processing requests. | ||
*/ | ||
export class HttpRequestHandler< | ||
T extends HttpRequestInit = HttpRequestInit | ||
> extends ProcessOperators<T> { | ||
export class HttpRequestHandler<T extends FetchRequest = FetchRequest> extends ProcessOperators<T> { | ||
/** | ||
@@ -30,3 +36,3 @@ * Set header that will apply on all requests done by consumer @see {HttpClient} | ||
export type HttpClientCreateOptions<T extends HttpRequestInit = HttpRequestInit> = { | ||
export type HttpClientCreateOptions<T extends FetchRequest = FetchRequest> = { | ||
requestHandler: HttpRequestHandler<T>; | ||
@@ -37,6 +43,7 @@ }; | ||
export interface IHttpClient< | ||
TRequest extends HttpRequestInit = HttpRequestInit, | ||
TResponse = Response | ||
> { | ||
/** | ||
* @template TRequest request arguments @see {@link https://developer.mozilla.org/en-US/docs/Web/API/request|request} | ||
* @template TResponse request arguments @see {@link https://developer.mozilla.org/en-US/docs/Web/API/response|response} | ||
*/ | ||
export interface IHttpClient<TRequest extends FetchRequest = FetchRequest, TResponse = Response> { | ||
uri: string; | ||
@@ -58,7 +65,9 @@ /** pre-processor of requests */ | ||
* note: request will not be executed until subscribe! | ||
* | ||
* @see {@link https://rxjs.dev/api/fetch/fromFetch|RXJS} | ||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch|fetch} | ||
* @example | ||
* ```ts | ||
* // Observer changes of a input field | ||
* const client = window.Fusion.createClient('my-client'); | ||
* const client = modules.http.createClient('my-client'); | ||
* const input$ = fromEvent(document.getElementById('input'), 'input'); | ||
@@ -87,6 +96,10 @@ * input$.pipe( | ||
*/ | ||
fetch(init: Omit<TRequest, 'uri'> | string): Observable<TResponse>; | ||
fetch<T = TResponse>( | ||
path: string, | ||
init?: FetchRequestInit<T, TRequest, TResponse> | ||
): Observable<T>; | ||
/** | ||
* Fetch a resource as an promise | ||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch|fetch} | ||
* @example | ||
@@ -118,3 +131,6 @@ * ```ts | ||
*/ | ||
fetchAsync(init: Omit<TRequest, 'uri'> | string): Promise<TResponse>; | ||
fetchAsync<T = TResponse>( | ||
path: string, | ||
init?: FetchRequestInit<T, TRequest, TResponse> | ||
): Promise<T>; | ||
@@ -128,3 +144,3 @@ /** | ||
/** Base http client for executing requests */ | ||
export class HttpClient<TRequest extends HttpRequestInit = HttpRequestInit, TResponse = Response> | ||
export class HttpClient<TRequest extends FetchRequest = FetchRequest, TResponse = Response> | ||
implements IHttpClient<TRequest, TResponse> | ||
@@ -163,5 +179,28 @@ { | ||
public fetch(init: Omit<TRequest, 'uri'> | string): Observable<TResponse> { | ||
const options = typeof init === 'string' ? { path: init } : init; | ||
return of({ ...options, uri: this._resolveUrl(options.path) } as TRequest).pipe( | ||
public fetch<T = TResponse>( | ||
path: string, | ||
args?: FetchRequestInit<T, TRequest, TResponse> | ||
): Observable<T> { | ||
return this._fetch(path, args); | ||
} | ||
public fetchAsync<T = TResponse>( | ||
path: string, | ||
args?: FetchRequestInit<T, TRequest, TResponse> | ||
): Promise<T> { | ||
return firstValueFrom(this.fetch<T>(path, args)); | ||
} | ||
public abort(): void { | ||
this._abort$.next(); | ||
} | ||
protected _fetch<T = TResponse>( | ||
path: string, | ||
args?: FetchRequestInit<T, TRequest, TResponse> | ||
): Observable<T> { | ||
const { selector, ...options } = Object.assign({}, args || { selector: undefined }, { | ||
path, | ||
}); | ||
const response$ = of({ ...options, uri: this._resolveUrl(options.path) } as TRequest).pipe( | ||
/** prepare request, allow extensions to modify request */ | ||
@@ -177,15 +216,10 @@ switchMap((x) => this._prepareRequest(x)), | ||
tap((x) => this._response$.next(x)), | ||
switchMap((x) => (selector ? selector(x) : Promise.resolve(x))), | ||
/** cancel request on abort signal */ | ||
takeUntil(this._abort$) | ||
); | ||
return response$ as unknown as Observable<T>; | ||
} | ||
public fetchAsync(init: Omit<TRequest, 'uri'> | string): Promise<TResponse> { | ||
return firstValueFrom(this.fetch(init)); | ||
} | ||
public abort(): void { | ||
this._abort$.next(); | ||
} | ||
protected _prepareRequest(init: TRequest): ObservableInput<TRequest> { | ||
@@ -192,0 +226,0 @@ return this.requestHandler.process(init); |
@@ -1,4 +0,4 @@ | ||
import { HttpRequestHandler, HttpRequestInit, IHttpClient } from './client'; | ||
import { HttpRequestHandler, FetchRequest, IHttpClient } from './client'; | ||
interface HttpClientConstructorOptions<TInit extends HttpRequestInit> { | ||
interface HttpClientConstructorOptions<TInit extends FetchRequest> { | ||
requestHandler: HttpRequestHandler<TInit>; | ||
@@ -24,2 +24,6 @@ } | ||
/** | ||
* Instance for configuring http client | ||
* @template TClient base type of client that the provider will create | ||
*/ | ||
export interface IHttpClientConfigurator<TClient extends IHttpClient = IHttpClient> { | ||
@@ -30,4 +34,14 @@ readonly clients: Record<string, HttpClientOptions<TClient>>; | ||
configureClient(name: string, uri: string): HttpClientConfigurator<TClient>; | ||
/** | ||
* Configure a client with arguments | ||
* @param name name of the client | ||
* @param args option that are used cor creating a client | ||
* @example | ||
* ```ts | ||
* configurator.http.configureClient('foo',{ | ||
* baseUri: 'https://foo.bar', | ||
* defaultScopes: ['foobar/.default'] | ||
* }); | ||
* ``` | ||
*/ | ||
configureClient<T extends TClient>( | ||
@@ -38,2 +52,19 @@ name: string, | ||
/** | ||
* Configure a simple client by name to an endpoint | ||
* @param name name of the client | ||
* @param uri base endpoint for the client | ||
*/ | ||
configureClient(name: string, uri: string): HttpClientConfigurator<TClient>; | ||
/** | ||
* Creates a client with callback configuration | ||
* @param name name of the client | ||
* @param onCreate callback when a client is created | ||
* ```ts | ||
* configurator.http.configureClient('foo',(client) => { | ||
* client.requestHandler.add('logger', (request) => console.log(request)); | ||
* }); | ||
* ``` | ||
*/ | ||
configureClient<T extends TClient>( | ||
@@ -44,5 +75,9 @@ name: string, | ||
/** | ||
* Check if there is a configuration for provided name | ||
*/ | ||
hasClient(name: string): boolean; | ||
} | ||
/** @inheritdoc */ | ||
export class HttpClientConfigurator<TClient extends IHttpClient> | ||
@@ -53,2 +88,3 @@ implements IHttpClientConfigurator<TClient> | ||
/** Get a clone of all configured clients */ | ||
public get clients(): Record<string, HttpClientOptions<TClient>> { | ||
@@ -58,4 +94,6 @@ return { ...this._clients }; | ||
/** default class for creation of http clients */ | ||
readonly defaultHttpClientCtor: HttpClientConstructor<TClient>; | ||
/** default request handler for http clients, applied on creation */ | ||
readonly defaultHttpRequestHandler = new HttpRequestHandler< | ||
@@ -65,2 +103,6 @@ HttpClientRequestInitType<TClient> | ||
/** | ||
* Create a instance of http configuration | ||
* @param client defaultHttpRequestHandler | ||
*/ | ||
constructor(client: HttpClientConstructor<TClient>) { | ||
@@ -70,2 +112,3 @@ this.defaultHttpClientCtor = client; | ||
/** @inheritdoc */ | ||
hasClient(name: string): boolean { | ||
@@ -75,2 +118,3 @@ return Object.keys(this._clients).includes(name); | ||
/** @inheritdoc */ | ||
configureClient<T extends TClient>( | ||
@@ -77,0 +121,0 @@ name: string, |
@@ -1,2 +0,7 @@ | ||
export { HttpClient, IHttpClient } from './client'; | ||
/** | ||
* [[include:module-http/README.MD]] | ||
* @module | ||
*/ | ||
export { HttpClient, IHttpClient, FetchRequestInit } from './client'; | ||
export { HttpClientMsal } from './client-msal'; | ||
@@ -3,0 +8,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
100981
816
57