@o3r/apis-manager
Version:
This module provides services to help you communicate with your APIs. Its responsibility is to provide an API configuration to a service factory so that it could instantiate an API with the right configurations. It contains a default configuration and a m
222 lines (214 loc) • 8.89 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, Inject, Optional, Injectable, NgModule, makeEnvironmentProviders } from '@angular/core';
/**
* Api manager is responsible to provide an api configuration to a service factory, so that it could instantiate an API
* with the right parameters. It contains a default configuration and a map of specific configurations for API / set of
* API. Configurations are only exposed through the method getConfiguration, which will merge the default configuration
* and the requested one.
*/
class ApiManager {
/**
* Map of registered Api Client associated to specific API
* Warning: This should not be used to get the ApiClient for an API, the function getConfiguration() should be used instead
*/
get registeredApiConfigurations() {
return { ...this.apiConfigurations };
}
/**
* Create an API manager using a custom ApiClient
* @param defaultConfiguration
*/
constructor(defaultConfiguration, apiConfigurations = {}) {
this.defaultConfiguration = defaultConfiguration;
this.apiConfigurations = apiConfigurations;
}
/**
* Retrieve a configuration for a specific API
* @param api API to get the configuration for
* @note When passing a string the configuration is expecting to exist else an error is thrown
* @note when passing an Api instance that does not match a registered configuration, the default one will be returned
*/
getConfiguration(api) {
if (typeof api === 'string') {
if (this.apiConfigurations[api]) {
return this.apiConfigurations[api];
}
else {
throw new Error(`Unknown API configuration: ${api}\nKnown API configurations: ${Object.keys(this.apiConfigurations).join(', ')}`);
}
}
return (api && this.apiConfigurations[api.apiName]) || this.defaultConfiguration;
}
/**
* Set or override API configuration
* @param apiClient API configuration to override to the given api
* @param api API name to override, the default configuration will be used if not specified
*/
setConfiguration(apiClient, api) {
if (api) {
this.apiConfigurations[typeof api === 'string' ? api : api.apiName] = apiClient;
}
else {
this.defaultConfiguration = apiClient;
}
}
}
/**
* Token used by the core library to provide an Api manager to services. It can be provided in the app.
*/
const API_TOKEN = new InjectionToken('Custom API manager token');
/**
* Initial APIs instantiations
*/
const INITIAL_APIS_TOKEN = new InjectionToken('Initial APIs token');
class ApiFactoryService {
constructor(apiManager, apis) {
this.apiManager = apiManager;
/** Map of loaded APIs */
this.loadedApis = {};
if (apis) {
this.updateApiMapping(apis);
}
}
/**
* Determine if the given parameter is a API class
* @param apiClass object to check
*/
isApiClass(apiClass) {
return !!apiClass.apiName && typeof apiClass === 'function';
}
/**
* Retrieve a specific API with loaded configuration
* @param apiClass class of the API to retrieve
* @param refreshCache Ignore cached API instance and refresh it
* @param customApiName override the `apiName` set in the `apiClass`
* @note When passing `customApiName` the configuration is expecting to exist else an error is thrown
* @note When passing an Api instance that does not match a registered configuration without `customApiName`, the default one will be returned
*/
getApi(apiClass, refreshCache = false, customApiName) {
const apiName = customApiName ?? apiClass.apiName;
const cache = this.loadedApis[apiName];
if (!refreshCache && cache) {
return cache;
}
const instance = new apiClass(this.getConfigFor(customApiName ?? apiClass));
this.loadedApis[apiName] = instance;
return instance;
}
/**
* Update the Map of loaded APIs.
* Note: Can be used to override the a specific API
* @param map Map of loaded APIs to update
*/
updateApiMapping(map) {
const newItems = Array.isArray(map)
? map
.reduce((acc, curr) => {
acc[curr.apiName] = curr;
return acc;
}, {})
: map;
this.loadedApis = {
...this.loadedApis,
...Object.entries(newItems)
.reduce((acc, [apiName, api]) => {
acc[apiName] = this.isApiClass(api) ? new api(this.getConfigFor(api)) : api;
return acc;
}, {})
};
}
/**
* Clear the cache of loaded APIs
* @param apis Whitelist of APIs to clear from the cache, if specified only these apis will be removed from the cache
*/
clearCache(apis) {
if (apis) {
apis.forEach((api) => delete this.loadedApis[typeof api === 'string' ? api : api.apiName]);
}
else {
this.loadedApis = {};
}
}
/**
* Retrieve the configuration for a specific API
* @param api API for which retrieving the configuration
*/
getConfigFor(api) {
return this.apiManager.getConfiguration(api);
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ApiFactoryService, deps: [{ token: API_TOKEN }, { token: INITIAL_APIS_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ApiFactoryService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ApiFactoryService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: ApiManager, decorators: [{
type: Inject,
args: [API_TOKEN]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [INITIAL_APIS_TOKEN]
}] }] });
/**
* Add a preconnect `<link>` element to the DOM
* @param baseUrl the origin href
* @param supportCrossOrigin add crossorigin attribute to the link element
*/
function appendPreconnect(baseUrl, supportCrossOrigin = true) {
const preConnectLink = document.createElement('link');
preConnectLink.setAttribute('rel', 'preconnect');
preConnectLink.setAttribute('href', baseUrl);
if (supportCrossOrigin) {
preConnectLink.setAttribute('crossorigin', '');
}
document.head.append(preConnectLink);
}
/**
* Module that needs to be imported by the application to instantiate an SDK configuration.
*/
class ApiManagerModule {
/**
* Provide a custom {@link ApiManager}
* A factory can be provided via injection to the token {@link API_TOKEN}
* @param apiManager
* @deprecated Please use {@link provideApiManager} instead, will be removed in v14.
*/
static forRoot(apiManager) {
return {
ngModule: ApiManagerModule,
providers: [
{ provide: API_TOKEN, useValue: apiManager }
]
};
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ApiManagerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
/** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: ApiManagerModule }); }
/** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ApiManagerModule, providers: [
ApiFactoryService
] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ApiManagerModule, decorators: [{
type: NgModule,
args: [{
providers: [
ApiFactoryService
]
}]
}] });
/**
* Provide a custom {@link ApiManager}
* A factory can be provided via injection to the token {@link API_TOKEN}
* @param apiManager
*/
function provideApiManager(apiManager) {
return makeEnvironmentProviders([
ApiFactoryService,
{ provide: API_TOKEN, useValue: apiManager }
]);
}
/**
* Generated bundle index. Do not edit.
*/
export { API_TOKEN, ApiFactoryService, ApiManager, ApiManagerModule, INITIAL_APIS_TOKEN, appendPreconnect, provideApiManager };
//# sourceMappingURL=o3r-apis-manager.mjs.map