2018-04-09 15:55:38 -07:00
|
|
|
import Service from '@ember/service';
|
|
|
|
import { assert } from '@ember/debug';
|
|
|
|
import { appConfigUrl } from 'wherehows-web/utils/api/configurator/configurator';
|
|
|
|
import { getJSON } from 'wherehows-web/utils/api/fetcher';
|
|
|
|
import { IAppConfig, IConfiguratorGetResponse } from 'wherehows-web/typings/api/configurator/configurator';
|
|
|
|
import { ApiStatus } from 'wherehows-web/utils/api';
|
|
|
|
import deepClone from 'wherehows-web/utils/deep-clone';
|
|
|
|
|
2018-07-24 11:01:50 -07:00
|
|
|
/**
|
|
|
|
* Conditional type alias for getConfig return type, if T is assignable to a key of
|
|
|
|
* IAppConfig, then return the property value, otherwise returns the IAppConfig object
|
|
|
|
*/
|
2018-08-12 13:02:01 -07:00
|
|
|
type IAppConfigOrProperty<T> = T extends keyof IAppConfig ? IAppConfig[T] : T extends undefined ? IAppConfig : never;
|
2018-07-24 11:01:50 -07:00
|
|
|
|
2018-04-09 15:55:38 -07:00
|
|
|
/**
|
|
|
|
* Holds the application configuration object
|
|
|
|
* @type {IAppConfig}
|
|
|
|
*/
|
|
|
|
const appConfig: IAppConfig = <IAppConfig>{};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Flag indicating the config object has been successfully loaded from the remote endpoint
|
|
|
|
* @type {boolean}
|
|
|
|
*/
|
|
|
|
let configLoaded = false;
|
|
|
|
|
|
|
|
export default class Configurator extends Service {
|
|
|
|
/**
|
|
|
|
* Fetches the application configuration object from the provided endpoint and augments the appConfig object
|
|
|
|
* @return {Promise<IAppConfig>}
|
|
|
|
*/
|
2018-07-24 11:01:50 -07:00
|
|
|
static async load(): Promise<IAppConfig> {
|
2018-04-09 15:55:38 -07:00
|
|
|
try {
|
|
|
|
const { status, config } = await getJSON<IConfiguratorGetResponse>({ url: appConfigUrl });
|
|
|
|
|
|
|
|
if (status === ApiStatus.OK) {
|
|
|
|
return (configLoaded = true) && Object.assign(appConfig, config);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Promise.reject(new Error(`Configuration load failed with status: ${status}`));
|
|
|
|
} catch (e) {
|
|
|
|
configLoaded = false;
|
|
|
|
|
|
|
|
return Promise.reject(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-07-24 11:01:50 -07:00
|
|
|
* Returns a copy of the last saved configuration object if one was successfully retrieved,
|
|
|
|
* or a copy of the property on the IAppConfig object, if specified
|
|
|
|
* @static
|
|
|
|
* @template K
|
|
|
|
* @param {K} [key] if provided, the value is returned with that key on the config hash is returned
|
2018-09-11 16:51:52 -07:00
|
|
|
* @param {IAppConfigOrProperty<K>} [defaultValue] if provided, will default if key is not found in config
|
2018-07-24 11:01:50 -07:00
|
|
|
* @returns {IAppConfigOrProperty<K>}
|
|
|
|
* @memberof Configurator
|
2018-04-09 15:55:38 -07:00
|
|
|
*/
|
2018-09-11 16:51:52 -07:00
|
|
|
static getConfig<K extends keyof IAppConfig | undefined>(
|
|
|
|
key?: K,
|
2018-09-12 15:33:52 -07:00
|
|
|
options: { useDefault?: boolean; default?: IAppConfigOrProperty<K> } = {}
|
2018-09-11 16:51:52 -07:00
|
|
|
): IAppConfigOrProperty<K> {
|
2018-04-09 15:55:38 -07:00
|
|
|
// Ensure that the application configuration has been successfully cached
|
2018-07-24 11:01:50 -07:00
|
|
|
assert('Please ensure you have invoked the `load` method successfully prior to calling `getConfig`.', configLoaded);
|
2018-04-09 15:55:38 -07:00
|
|
|
|
2018-08-12 13:02:01 -07:00
|
|
|
return typeof key === 'string' && appConfig.hasOwnProperty(<keyof IAppConfig>key)
|
|
|
|
? <IAppConfigOrProperty<K>>deepClone(appConfig[<keyof IAppConfig>key])
|
2018-09-12 15:33:52 -07:00
|
|
|
: options.useDefault
|
|
|
|
? <IAppConfigOrProperty<K>>options.default
|
2018-09-11 16:51:52 -07:00
|
|
|
: <IAppConfigOrProperty<K>>deepClone(appConfig);
|
2018-04-09 15:55:38 -07:00
|
|
|
}
|
|
|
|
}
|