Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@equinor/fusion-framework

Package Overview
Dependencies
Maintainers
3
Versions
241
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@equinor/fusion-framework - npm Package Compare versions

Comparing version 1.1.0-alpha.1 to 1.1.0-alpha.2

dist/build/src/services/config.auth.d.ts

32

dist/build/src/index.d.ts
import { Services, ServiceInitiator } from './services';
interface Api extends Services {
currentApp: Services;
registerApp: (app: string, appInit: ServiceInitiator) => Promise<void>;
export { AuthClient, createAuthClient } from '@equinor/fusion-web-msal';
export interface ApiInstance {
services: Services;
}
export declare const createInstance: (init: ServiceInitiator) => Promise<Api>;
export { AuthClient, createAuthClient } from '@equinor/fusion-web-msal';
export default createInstance;
export interface FusionService extends Services {
}
export interface Fusion {
services: FusionService;
createServiceInstance: (cb: ServiceInitiator) => Promise<Services>;
}
export interface ApplicationApi {
services: Services;
}
export interface ApplicationManifest {
}
export interface ApplicationRenderer {
(fusion: Fusion, env: ApplicationManifest): ((element: HTMLElement) => void) | Promise<(element: HTMLElement) => void>;
}
export declare const createApi: (init: ServiceInitiator) => Promise<ApiInstance>;
export declare const createFusion: (api: ApiInstance) => Fusion;
export declare const initFusion: (init: ServiceInitiator) => Promise<ApiInstance>;
declare global {
interface Window {
Fusion: Fusion;
}
}
export default initFusion;

2

dist/build/src/services/http/http-client.d.ts

@@ -8,3 +8,3 @@ import { Observable, ObservableInput, Subject } from 'rxjs';

export declare class HttpRequestHandler<T extends HttpRequestInit = HttpRequestInit> extends ProcessOperators<T> {
setHeader(name: string, value: string): HttpRequestHandler<T>;
setHeader(key: string, value: string): HttpRequestHandler<T>;
}

@@ -11,0 +11,0 @@ export declare type HttpClientCreateOptions<T extends HttpRequestInit = HttpRequestInit> = {

import { HttpClient } from './http-client';
import { HttpClientConfigurator } from './http-configurator';
export declare class ClientNotFoundException extends Error {
constructor(message: string);
}
export declare class HttpClientProvider<TClient extends HttpClient = HttpClient> {
protected config: HttpClientConfigurator<TClient>;
constructor(config: HttpClientConfigurator<TClient>);
createClient<T = TClient>(name: string): T;
hasClient(key: string): boolean;
createClient<T = TClient>(key: string): T;
}

@@ -1,22 +0,5 @@

import { HttpClientProvider, HttpClientConfigurator, HttpClientMsal } from './http';
interface AuthClient {
acquireToken(req: {
scopes: string[];
}): Promise<{
accessToken: string;
} | void>;
login(): void;
}
export declare type Services = {
auth: AuthClient;
http: HttpClientProvider<HttpClientMsal>;
};
export declare type ServiceInitiator = (config: ServiceConfig) => void | Promise<void>;
interface ServiceConfig {
auth: {
client?: AuthClient;
};
http: HttpClientConfigurator<HttpClientMsal>;
}
export declare const createServices: (services?: Services | undefined) => Promise<(cb: ServiceInitiator) => Promise<Services>>;
export default createServices;
export type { Services, ServiceInitiator, ServiceConfig } from './types';
export { createServices } from './create-services';
export { default } from './create-services';
export { HttpClientMsal, HttpClient } from './http';
export type { HttpClientMsal as FusionClient } from './http';

@@ -1,22 +0,21 @@

import { BehaviorSubject } from 'rxjs';
import configureServices from './services';
export const createInstance = async (init) => {
const app$ = new BehaviorSubject({});
const rootConfig = await configureServices();
const rootServices = await rootConfig(init);
const registerApp = async (app, appInit) => {
const appConfig = await configureServices(rootServices);
const appServices = await appConfig(appInit);
app$.next({ ...app$.value, [app]: appServices });
};
export { AuthClient, createAuthClient } from '@equinor/fusion-web-msal';
export const createApi = async (init) => {
const services = await (await configureServices())(init);
return { services };
};
export const createFusion = (api) => {
const { services } = api;
const createServiceInstance = async (cb) => (await configureServices(api.services))(cb);
return {
get currentApp() {
return Object.values(app$.value)[0];
},
registerApp,
...rootServices,
services,
createServiceInstance,
};
};
export { AuthClient, createAuthClient } from '@equinor/fusion-web-msal';
export default createInstance;
export const initFusion = async (init) => {
const api = await createApi(init);
window.Fusion = createFusion(api);
return api;
};
export default initFusion;
//# sourceMappingURL=index.js.map

@@ -6,6 +6,6 @@ import { firstValueFrom, of, Subject } from 'rxjs';

export class HttpRequestHandler extends ProcessOperators {
setHeader(name, value) {
return this.set('header-' + name, (request) => {
setHeader(key, value) {
return this.set('header-' + key, (request) => {
const headers = new Headers(request.headers);
headers.append(name, value);
headers.append(key, value);
return { ...request, headers };

@@ -12,0 +12,0 @@ });

@@ -0,1 +1,6 @@

export class ClientNotFoundException extends Error {
constructor(message) {
super(message);
}
}
export class HttpClientProvider {

@@ -6,4 +11,10 @@ config;

}
createClient(name) {
const { defaultUri, onCreate, ctor = this.config.defaultHttpClientCtor, requestHandler = this.config.defaulHttpRequestHandler, } = this.config.clients[name];
hasClient(key) {
return Object.keys(this.config.clients).includes(key);
}
createClient(key) {
if (!this.hasClient(key)) {
throw new ClientNotFoundException(`No registered http client for key [${key}]`);
}
const { defaultUri, onCreate, ctor = this.config.defaultHttpClientCtor, requestHandler = this.config.defaulHttpRequestHandler, } = this.config.clients[key];
const options = { requestHandler };

@@ -10,0 +21,0 @@ const instance = new ctor(defaultUri || '', options);

@@ -1,59 +0,4 @@

import { HttpClientProvider, HttpClientConfigurator, HttpClientMsal } from './http';
const configureAuth = (config, services) => {
config.auth = { client: services?.auth };
return (_services) => {
const client = config.auth?.client;
if (!client) {
throw Error('Missing auth Client');
}
return {
auth: {
client,
acquireToken(args) {
return client.acquireToken(args);
},
login() {
client.login();
},
},
};
};
};
const configureHttp = (config) => {
config.http = new HttpClientConfigurator(HttpClientMsal);
return (services) => {
if (!config.http) {
throw Error('Missing config for HTTP');
}
config.http.defaulHttpRequestHandler.add('msal', async (request) => {
const { scopes = [] } = request;
const token = await services.auth?.acquireToken({ scopes });
if (token) {
const headers = new Headers(request.headers);
headers.append('Authorization', `Bearer ${token.accessToken}`);
return { ...request, headers };
}
});
return {
http: new HttpClientProvider(config.http),
};
};
};
export const createServices = async (services) => {
const config = {};
const build = {
auth: configureAuth(config, services),
http: configureHttp(config, services),
};
return async (init) => {
await Promise.resolve(init(config));
const services = await Object.keys(build).reduce(async (acc, key) => {
const obj = await acc;
const provider = await Promise.resolve(build[key](obj));
return Object.assign(obj, provider);
}, Promise.resolve({}));
return services;
};
};
export default createServices;
export { createServices } from './create-services';
export { default } from './create-services';
export { HttpClientMsal, HttpClient } from './http';
//# sourceMappingURL=index.js.map
import { Services, ServiceInitiator } from './services';
interface Api extends Services {
currentApp: Services;
registerApp: (app: string, appInit: ServiceInitiator) => Promise<void>;
export { AuthClient, createAuthClient } from '@equinor/fusion-web-msal';
export interface ApiInstance {
services: Services;
}
export declare const createInstance: (init: ServiceInitiator) => Promise<Api>;
export { AuthClient, createAuthClient } from '@equinor/fusion-web-msal';
export default createInstance;
export interface FusionService extends Services {
}
export interface Fusion {
services: FusionService;
createServiceInstance: (cb: ServiceInitiator) => Promise<Services>;
}
export interface ApplicationApi {
services: Services;
}
export interface ApplicationManifest {
}
export interface ApplicationRenderer {
(fusion: Fusion, env: ApplicationManifest): ((element: HTMLElement) => void) | Promise<(element: HTMLElement) => void>;
}
export declare const createApi: (init: ServiceInitiator) => Promise<ApiInstance>;
export declare const createFusion: (api: ApiInstance) => Fusion;
export declare const initFusion: (init: ServiceInitiator) => Promise<ApiInstance>;
declare global {
interface Window {
Fusion: Fusion;
}
}
export default initFusion;

@@ -8,3 +8,3 @@ import { Observable, ObservableInput, Subject } from 'rxjs';

export declare class HttpRequestHandler<T extends HttpRequestInit = HttpRequestInit> extends ProcessOperators<T> {
setHeader(name: string, value: string): HttpRequestHandler<T>;
setHeader(key: string, value: string): HttpRequestHandler<T>;
}

@@ -11,0 +11,0 @@ export declare type HttpClientCreateOptions<T extends HttpRequestInit = HttpRequestInit> = {

import { HttpClient } from './http-client';
import { HttpClientConfigurator } from './http-configurator';
export declare class ClientNotFoundException extends Error {
constructor(message: string);
}
export declare class HttpClientProvider<TClient extends HttpClient = HttpClient> {
protected config: HttpClientConfigurator<TClient>;
constructor(config: HttpClientConfigurator<TClient>);
createClient<T = TClient>(name: string): T;
hasClient(key: string): boolean;
createClient<T = TClient>(key: string): T;
}

@@ -1,22 +0,5 @@

import { HttpClientProvider, HttpClientConfigurator, HttpClientMsal } from './http';
interface AuthClient {
acquireToken(req: {
scopes: string[];
}): Promise<{
accessToken: string;
} | void>;
login(): void;
}
export declare type Services = {
auth: AuthClient;
http: HttpClientProvider<HttpClientMsal>;
};
export declare type ServiceInitiator = (config: ServiceConfig) => void | Promise<void>;
interface ServiceConfig {
auth: {
client?: AuthClient;
};
http: HttpClientConfigurator<HttpClientMsal>;
}
export declare const createServices: (services?: Services | undefined) => Promise<(cb: ServiceInitiator) => Promise<Services>>;
export default createServices;
export type { Services, ServiceInitiator, ServiceConfig } from './types';
export { createServices } from './create-services';
export { default } from './create-services';
export { HttpClientMsal, HttpClient } from './http';
export type { HttpClientMsal as FusionClient } from './http';
{
"name": "@equinor/fusion-framework",
"version": "1.1.0-alpha.1",
"version": "1.1.0-alpha.2",
"description": "",

@@ -42,3 +42,3 @@ "main": "./dist/esm/index.js",

},
"gitHead": "6659ca36422d135c79ca8b5f4eea63feca923d25"
"gitHead": "a5ebf787dbd688148257ff210828b613023db34a"
}

@@ -6,2 +6,11 @@ # Fusion Framework

## Concept
### Services
Services are modules that the framework provides for the consumer.
When initializing the framework, the system creates a object with configurators.
The initiator configures services by adding callbacks for initalaztion of the service.
The system return providers for the configured services.
__Expect breaking changes untill stable release!__

@@ -13,12 +22,16 @@

window.Fusion = await createInstance((root) => {
window.Fusion = await createInstance((build) => {
// configure auth client instance
root.auth.client = createAuthClient('my-tennant-id', 'my-client-id', '/msal/auth');
build.auth.client = createAuthClient(
'my-tennant-id',
'my-client-id',
'/msal/auth'
);
// define simple client (will use login scope)
root.http.configureClient('foo', 'https://my.services.com');
build.http.configureClient('foo', 'https://my.services.com');
// define a client with callback for init
root.http.configureClient('bar', (client) => {
build.http.configureClient('bar', (client) => {

@@ -33,6 +46,6 @@ // define base url for requests

client.requestHandler.add('custom-headers', (request) => {
const headers = new Headers(request.headers);
headers.append('x-app-version', 'v1.2.3');
headers.append('x-app-env', 'alpha');
return { ...request, headers };
const headers = new Headers(request.headers);
headers.append('x-app-version', 'v1.2.3');
headers.append('x-app-env', 'alpha');
return { ...request, headers };
});

@@ -45,60 +58,56 @@ });

## Consumer / Application
### setup
```ts
// default
window.Fusion.createClient('bar').fetch('/api/apps').subscribe(async(x) => console.log(await x.json));
export const setup = (fusion: Fusion, env: ApplicationManifest) => {
const services = fusion.createServiceInstance((config) => {
// static asset
config.http.configureClient(
'data-proxy',
'https://somewhere-test.com'
);
// by promise
window.Fusion.createClient('bar').fetchAsync('/api/apps').then(async(x) => console.log(await x.json));
// asset by provided config
config.http.configureClient(
'app-client',
env.endpoints.prod.myService
);
// TODO - add storage provider
config.state.configureStore(
'my-store',
(action$, state$, services) => {
services.http.createClient('portal').fetch('foo')
}
)
});
return (element: HTMLElement) => {
const content = document.createElement('p');
content.innerText = 'Hello Fusion';
element.appendChild(content);
}
};
```
## HttpClient
### fetch
> The fetch method of the client return an __Observable__ reponse.
>
> Observables has the advantage of cancel when unsuscribed.
>
> Secondly we can compose the flow easily with operator functions
```ts
import { fromEvent, of } from 'rxjs';
import { debounceTime, map, switchMap, takeUntil, catchError } from 'rxjs/operators';
// default
services.createClient('bar')
.fetch('/api/apps')
.subscribe(async(x) => console.log(await x.json()));
const client = window.Fusion.createClient('my-client');
// by promise
services.createClient('bar')
.fetchAsync('/api/apps')
.then(async(x) => console.log(await x.json()));
```
const input = document.createElement('input');
const result = document.createElement('pre');
### fetch
// Observe changes on input field
const input$ = fromEvent(input, 'input');
The fetch method of the client return an __Observable__ reponse.
Observables has the advantage of cancel when unsuscribed.
Secondly we can compose the flow easily with operator functions
$input.pipe(
// only call after no key input in .5s
debounceTime(500),
// extract value from event
map(x => x.currentTarget.value),
// only search when text longer than 3 characters
filter(x => x.length >=3),
// query api with input value, retry 2 times
switchMap(x => client.fetch(`api/foo?q=${x}`).pipe(retry(2))),
// extract data from response
switchMap(x => x.json()),
// process error
catchError(x => of({error: e.message})),
// cancel request if new input
takeUntil(input$)
).subscribe(json => result.innerText = JSON.stringify(json, null, 2));
```
#### React
### React
TODO move to react lib

@@ -108,3 +117,3 @@ ```tsx

import { Subscription, of } from 'rxjs';
import { debounceTime, map, switchMap, takeUntil, catchError } from 'rxjs/operators';
import { switchMap } from 'rxjs/operators';

@@ -119,3 +128,5 @@ const MyComponent = () => {

// set next value for observe when input changes
const onInput = useCallback((value: string) => input$.next(value), [input$]);
const onInput = useCallback((value: string) => {
input$.next(value), [input$];
});

@@ -144,36 +155,2 @@ useEffect(() =>{

### fetchAsync
Incase for some reason you don`t want to use __Observables__, the ```fetchAsync``` will return a promise
```ts
const client = window.Fusion.createClient('my-client');
const input = document.createElement('input');
const result = document.createElement('pre');
let controller: AbortController;
input.addEventlistner('input', (e) => {
try{
// if a controller is defined, request might be ongoing
controller && controller.abort();
// create a new abort controller
controller = new AbortController();
// query api with
const response = await client.fetch({
path: `api/foo?q=${e.currentTarget.value}`,
signal: controller.signal,
});
const json = await response.json();
result.innerText = JSON.stringify(json, null, 2)
} catch(err){
resilt.innerText = 'an error accoured'
} finally{
delete controller;
}
});
```
### RequestHandler

@@ -185,3 +162,4 @@

```ts
type ProcessOperator<T, R = T> = (request: T) => R | void | Promise<R | void>;
type ProcessOperator<T, R = T> = (request: T) =>
R | void | Promise<R | void>;
```

@@ -195,5 +173,7 @@

const headers = new Headers(request.headers);
Object.keys(values).forEach(key => headers.append(`x-${key}`, values[key]));
Object.keys(values).forEach(key => {
headers.append(`x-${key}`, values[key]);
});
return {...request, headers};
});
```

@@ -1,34 +0,70 @@

import { BehaviorSubject } from 'rxjs';
import configureServices, { Services, ServiceInitiator } from './services';
interface Api extends Services {
currentApp: Services;
registerApp: (app: string, appInit: ServiceInitiator) => Promise<void>;
// TODO
export { AuthClient, createAuthClient } from '@equinor/fusion-web-msal';
/**
* Base api instance, internal for provider (portal)
*/
export interface ApiInstance {
services: Services;
}
export const createInstance = async (init: ServiceInitiator): Promise<Api> => {
const app$ = new BehaviorSubject<Record<string, Services>>({});
const rootConfig = await configureServices();
const rootServices = await rootConfig(init);
// TODO make interface with intelisense
export interface FusionService extends Services {}
// TODO move insto services;
const registerApp = async (app: string, appInit: ServiceInitiator) => {
const appConfig = await configureServices(rootServices);
const appServices = await appConfig(appInit);
app$.next({ ...app$.value, [app]: appServices });
};
/**
* Public interface of fusion api, normally exposed on window
*/
export interface Fusion {
/**
* Configured services for Fusion
*/
services: FusionService;
/**
* Create a scoped instance of services
*/
createServiceInstance: (cb: ServiceInitiator) => Promise<Services>;
}
export interface ApplicationApi {
services: Services;
}
export interface ApplicationManifest {}
export interface ApplicationRenderer {
(fusion: Fusion, env: ApplicationManifest):
| ((element: HTMLElement) => void)
| Promise<(element: HTMLElement) => void>;
}
export const createApi = async (init: ServiceInitiator): Promise<ApiInstance> => {
const services = await (await configureServices())(init);
return { services };
};
export const createFusion = (api: ApiInstance): Fusion => {
const { services } = api;
const createServiceInstance = async (cb: ServiceInitiator): Promise<Services> =>
(await configureServices(api.services))(cb);
return {
// TODO
get currentApp(): Services {
return Object.values(app$.value)[0];
},
registerApp,
...rootServices,
services,
createServiceInstance,
};
};
// TODO
export { AuthClient, createAuthClient } from '@equinor/fusion-web-msal';
// TODO api service enpoint list
export const initFusion = async (init: ServiceInitiator): Promise<ApiInstance> => {
const api = await createApi(init);
window.Fusion = createFusion(api);
return api;
};
export default createInstance;
declare global {
interface Window {
Fusion: Fusion;
}
}
export default initFusion;
import { HttpClient, HttpRequestInit } from './http-client';
/** Extends request init with scope */
type RequestInitMsal = HttpRequestInit & { scopes?: string[] };
// TODO - add description
/** Default Client for MSAL */
export class HttpClientMsal extends HttpClient<RequestInitMsal> {
/** Scope that will be applied to all request if no scope is provided in request object */
public defaultScope: string[] = [];
/** @inheritdoc */
fetch(init: Omit<RequestInitMsal, 'uri'> | string): ReturnType<HttpClient['fetch']> {

@@ -10,0 +13,0 @@ init = typeof init === 'string' ? { path: init } : init;

@@ -9,9 +9,17 @@ import { firstValueFrom, Observable, ObservableInput, of, Subject } from 'rxjs';

/**
* Extends @see {ProcessOperators} for pre-proccessing requests.
*/
export class HttpRequestHandler<
T extends HttpRequestInit = HttpRequestInit
> extends ProcessOperators<T> {
setHeader(name: string, value: string): HttpRequestHandler<T> {
return this.set('header-' + name, (request) => {
/**
* Set header that will apply on all requests done by consumer @see {HttpClient}
* @param key - name of header
* @param value - header value
*/
setHeader(key: string, value: string): HttpRequestHandler<T> {
return this.set('header-' + key, (request) => {
const headers = new Headers(request.headers);
headers.append(name, value);
headers.append(key, value);
return { ...request, headers };

@@ -28,12 +36,21 @@ }) as unknown as HttpRequestHandler<T>;

/** Base http client for executing requests */
export class HttpClient<TRequest extends HttpRequestInit = HttpRequestInit, TResponse = Response> {
/** pre-processer of requests */
readonly requestHandler: HttpRequestHandler<TRequest>;
/** post-processer of requests */
readonly responseHandler: HttpResponseHandler<TResponse> = (x: Response) =>
Promise.resolve(x as unknown as TResponse);
/** stream of requests that are about to be executed */
protected _request$ = new Subject<TRequest>();
/** stream of request responses */
protected _response$ = new Subject<TResponse>();
/** trigger stream for aborting all ongoing requests */
protected _abort$ = new Subject<void>();
/** Observalbe stream of request */
public get request$(): Observable<TRequest> {

@@ -43,2 +60,3 @@ return this._request$.asObservable();

/** Observalbe stream of responses */
public get response$(): Observable<TResponse> {

@@ -53,2 +71,3 @@ return this._response$.asObservable();

/** internal abstract method, ment for overriding instead of overriding constructor */
protected _init(): void {

@@ -70,2 +89,34 @@ // called by children for constructor setup

/**
* Observable request.
* Simplyfies execution of request and
* note: request will not be executed until subscribe!
* @see {@link https://rxjs.dev/api/fetch/fromFetch|RXJS}
* @example
* ```ts
* // Observer changes of a input field
* const client = window.Fusion.createClient('my-client');
* const input$ = fromEvent(document.getElementById('input'), 'input');
* input$.pipe(
* // only call after no key input in .5s
* debounceTime(500),
* // extract value from event
* map(x => x.currentTarget.value),
* // only search when text longer than 2 characters
* filter(x => x.length >=3),
* // query api with input value
* switchMap(x => client.fetch(`api/foo?q=${x}`).pipe(
* // retry 2 times
* retry(2)
* // cancel request if new input
* takeUntil(input$)
* )),
* // extract data from response
* switchMap(x => x.json()),
* // process error
* catchError(x => of({error: e.message}))
* // write result to pre element
* ).subscribe(console.log);
* ```
*/
public fetch(init: Omit<TRequest, 'uri'> | string): Observable<TResponse> {

@@ -85,2 +136,27 @@ const options = typeof init === 'string' ? { path: init } : init;

* Fetch a resource as an promise
* @example
* ```ts
* let controller: AbortController;
* const client = window.Fusion.createClient('my-client');
* const input = document.getElementById('input');
* input.addEventlistner('input', (e) => {
* try{
* // if a controller is defined, request might be ongoing
* controller && controller.abort();
* // create a new abort controller
* controller = new AbortController();
* // query api with
* const response = await client.fetch({
* path: `api/foo?q=${e.currentTarget.value}`,
* signal: controller.signal,
* });
* const json = await response.json();
* result.innerText = JSON.stringify(json, null, 2)
* } catch(err){
* resilt.innerText = 'an error accoured'
* } finally{
* delete controller;
* }
* });
* ```
*/

@@ -87,0 +163,0 @@ public fetchAsync(init: Omit<TRequest, 'uri'> | string): Promise<TResponse> {

import { HttpClient } from './http-client';
import { HttpClientConfigurator } from './http-configurator';
export class ClientNotFoundException extends Error {
constructor(message: string) {
super(message);
}
}
export class HttpClientProvider<TClient extends HttpClient = HttpClient> {
constructor(protected config: HttpClientConfigurator<TClient>) {}
createClient<T = TClient>(name: string): T {
hasClient(key: string): boolean {
return Object.keys(this.config.clients).includes(key);
}
createClient<T = TClient>(key: string): T {
if (!this.hasClient(key)) {
throw new ClientNotFoundException(`No registered http client for key [${key}]`);
}
const {

@@ -13,3 +26,3 @@ defaultUri,

requestHandler = this.config.defaulHttpRequestHandler,
} = this.config.clients[name];
} = this.config.clients[key];
const options = { requestHandler };

@@ -16,0 +29,0 @@ const instance = new ctor(defaultUri || '', options) as TClient;

@@ -1,92 +0,6 @@

import { HttpClientProvider, HttpClientConfigurator, HttpClientMsal } from './http';
export type { Services, ServiceInitiator, ServiceConfig } from './types';
export { createServices } from './create-services';
export { default } from './create-services';
// TODO make provider
interface AuthClient {
acquireToken(req: { scopes: string[] }): Promise<{ accessToken: string } | void>;
login(): void;
}
export type Services = {
auth: AuthClient;
http: HttpClientProvider<HttpClientMsal>;
};
export type ServiceInitiator = (config: ServiceConfig) => void | Promise<void>;
interface ServiceConfig {
auth: {
client?: AuthClient;
};
http: HttpClientConfigurator<HttpClientMsal>;
}
type ServiceConfigurator = (
config: Partial<ServiceConfig>,
services?: Services
) => (services: Partial<Services>) => Partial<Services> | Promise<Partial<Services>>;
const configureAuth: ServiceConfigurator = (
config: Partial<ServiceConfig>,
services?: Services
) => {
config.auth = { client: services?.auth };
return (_services: Partial<Services>) => {
const client = config.auth?.client;
if (!client) {
throw Error('Missing auth Client');
}
return {
auth: {
client,
acquireToken(args: { scopes: string[] }) {
return client.acquireToken(args);
},
login() {
client.login();
},
},
};
};
};
const configureHttp: ServiceConfigurator = (config: Partial<ServiceConfig>) => {
config.http = new HttpClientConfigurator(HttpClientMsal);
return (services: Partial<Services>) => {
if (!config.http) {
throw Error('Missing config for HTTP');
}
config.http.defaulHttpRequestHandler.add('msal', async (request) => {
const { scopes = [] } = request;
const token = await services.auth?.acquireToken({ scopes });
if (token) {
const headers = new Headers(request.headers);
headers.append('Authorization', `Bearer ${token.accessToken}`);
return { ...request, headers };
}
});
return {
http: new HttpClientProvider(config.http),
};
};
};
export const createServices = async (
services?: Services
): Promise<(cb: ServiceInitiator) => Promise<Services>> => {
const config = {};
const build = {
auth: configureAuth(config, services),
http: configureHttp(config, services),
};
return async (init: (config: ServiceConfig) => void): Promise<Services> => {
await Promise.resolve(init(config as ServiceConfig));
const services = await Object.keys(build).reduce(async (acc, key) => {
const obj = await acc;
const provider = await Promise.resolve(build[key as keyof typeof build](obj));
return Object.assign(obj, provider);
}, Promise.resolve({}));
return services as Services;
};
};
export default createServices;
export { HttpClientMsal, HttpClient } from './http';
export type { HttpClientMsal as FusionClient } from './http';

@@ -12,9 +12,7 @@ {

},
"include": [
"src/**/*.ts"
],
"include": ["src/**/*.ts"],
"exclude": [
"node_modules",
"lib"
"dist",
]
}

Sorry, the diff of this file is too big to display

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

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc