@interaktiv/mibuilder-core
Version:
Core libraries to interact with MiBuilder projects.
316 lines (267 loc) • 8.82 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Config = void 0;
var _types = require("@interaktiv/types");
var _mibuilderError = require("../mibuilder-error");
var _configGroup = require("./config-group");
const INVALID_PATH_REGEX = /[["?<>|\]]+/;
const MIBUILDER_CONFIG_FILE_NAME = 'mibuilder-config.json';
const CONFIG_GROUP = {
APP: 'app',
TEMPLATE: 'template',
CLI: 'cli',
API: 'api',
ANDROID: 'android',
MATCH: 'match',
FLINT: 'flint'
};
const configNames = (0, _types.definiteValuesOf)(CONFIG_GROUP);
const isValidGroup = group => configNames.includes(group);
/**
* Tests whether a path is in the correct format; the value doesn't include the
* characters "[", "]", "?", "<", ">", "?", "|"
*
* @param {String} value The path as a string.
* @return {Boolean} Returns true if path is valid
*/
const validatePathDoesNotContainInvalidChars = value => INVALID_PATH_REGEX.test(value) === false;
/**
* The files where mibuilder config values are stored for projects and the
* global space.
*
* The configs are saved in different groups {@link CONFIG_GROUP}
*
* *Note:* It is not recommended to instantiate this object directly when
* resolving config values. Instead use {@link ConfigAggregator}
*
* TODO: Update example
* ```javascript
* ```
*/
class Config extends _configGroup.ConfigGroup {
/**
* Returns the default file name for a config file.
*
* **See** {@link MIBUILDER_CONFIG_FILE_NAME}
*
* @return {String} The file name of the config file
*/
static getFileName() {
return MIBUILDER_CONFIG_FILE_NAME;
}
/**
* Gets default options.
*
* @param {Boolean} [isGlobal=true] Make the config global.
* @param {String} filename Override the default file. {@link Config.getFileName}
* @return {Object} The default options
*/
// eslint-disable-next-line default-param-last
static getDefaultOptions(isGlobal = true, filename) {
return _configGroup.ConfigGroup.getOptions(CONFIG_GROUP.CLI, filename || Config.getFileName(), isGlobal);
}
/**
* Constructor
*
* **Do not directly construct instances of this class -- use {@link Aliases.create} instead.**
*
* @param {Object} [options] The options for the class instance
*/
constructor(options) {
super(options || Config.getDefaultOptions(true));
}
/**
* Initializer for supported config types.
*/
async init() {
if (!Config.allowedGroups) Config.allowedGroups = configNames;
if (!Config.allowedProperties) {
Config.allowedProperties = [{
group: 'app',
key: 'workspace',
input: {
validator: validatePathDoesNotContainInvalidChars,
failedMessage: 'Specify a valid file path'
}
}, {
group: 'template',
key: 'sshPrivateKeyPath',
input: {
validator: validatePathDoesNotContainInvalidChars,
failedMessage: 'Specify a valid file path'
}
}, {
group: 'template',
key: 'sshPublicKeyPath',
input: {
validator: validatePathDoesNotContainInvalidChars,
failedMessage: 'Specify a valid file path'
}
}, // TODO: Add input.validator for web url or file path
{
group: 'template',
key: 'remoteOrigin'
}, // TODO: Add input.validator for web url
{
group: 'api',
key: 'getContentEndpoint'
}, {
group: 'android',
key: 'googlePlayJsonKeyPath',
input: {
validator: validatePathDoesNotContainInvalidChars,
failedMessage: 'Specify a valid file path'
}
}, // TODO: Add input.validator for web url
{
group: 'match',
key: 'gitUrl'
}, // TODO: Add input.validator for web url
{
group: 'flint',
key: 'gitUrl'
}];
}
await super.init();
}
/**
* Returns an object representing the supported allowed groups.
*
* @return {Object} the allowed groups
*/
static getAllowedGroups() {
if (!Config.allowedGroups) {
throw new _mibuilderError.MiBuilderError('Config meta information has not been initialized.', undefined, ['Use Config.create()']);
}
return Config.allowedGroups;
}
static getAllowedProperties() {
if (!Config.allowedProperties) {
throw new _mibuilderError.MiBuilderError('Config meta information has not been initialized.', undefined, ['Use Config.create()']);
}
return Config.allowedProperties;
}
static getKeyAndGroupFromPath(path) {
if ((0, _types.isString)(path) === false) return {
group: CONFIG_GROUP.CLI,
key: null
};
const parts = path.split('.');
if (parts.length === 1) return {
group: CONFIG_GROUP.CLI,
key: parts[0]
};
return {
group: parts[0],
key: parts[1]
};
}
/**
* Don't use kit's set to prevent nested object save.
* Used internally by {@link ConfigStore}
*
* @param {Object} contents The contents of the group
* @param {String} key The key in the contents
* @param {*} value The value for the key
*/
setMethod(contents, key, value) {
contents[key] = value;
}
/**
* Get an alias from a key and group. Shorthand for
* `Alias.create({}).get(path)`. Returns the promise resolved when the
* alias is created.
*
* @param {Boolean} isGlobal True for a global config. False for a local config.
* @param {String} path The path to the config.
*/
static async fetch(isGlobal, path) {
const {
group,
key
} = Config.getKeyAndGroupFromPath(path);
if (isValidGroup(group) === false) {
throw new _mibuilderError.MiBuilderError('You have specified an invalid config group in which to save your values. Please verify that you are specifying a valid config group', 'InvalidConfigGroup');
}
const config = await Config.create(Config.getDefaultOptions(isGlobal));
return config.getInGroup(key, group);
}
/**
* The value of a supported config property.
*
* @param {Boolean} isGlobal True for a global config. False for a local config.
* @param {String} path The name of the property to set.
* @param {Boolean} value The property value.
* @return {*} The value
*/
static async update(isGlobal, path, value) {
const {
group,
key
} = Config.getKeyAndGroupFromPath(path);
if (isValidGroup(group) === false) {
throw new _mibuilderError.MiBuilderError('You have specified an invalid config group in which to save your values. Please verify that you are specifying a valid config group', 'InvalidConfigGroup');
}
const config = await Config.create(Config.getDefaultOptions(isGlobal));
config.setInGroup(key, value, group);
return config.write();
}
/**
* Clear all the configured properties both local and global.
*/
static async clear() {
const globalConfig = await Config.create(Config.getDefaultOptions(true));
globalConfig.clear();
await globalConfig.write();
const localConfig = await Config.create(Config.getDefaultOptions(false));
localConfig.clear();
await localConfig.write();
}
/**
* Writes Config properties.
*
* @param {Object} newContents The new Config value to persist
* @return {Object} The current config
*/
async write(newContents) {
if (newContents != null) {
this.setContentsFromObject(newContents);
}
await super.write();
return this.getContents();
}
/**
* Sets a value for a property.
*
* **Throws** *{@link MiBuilderError}{ name: 'InvalidConfigValue' }* If the input validator fails.
*
* @param {String} path The property path to set.
* @param {*} value The value of the property.
* @return {Object} The config content
*/
set(path, value) {
const {
group,
key
} = Config.getKeyAndGroupFromPath(path);
if (isValidGroup(group) === false) {
throw new _mibuilderError.MiBuilderError('You have specified an invalid config group in which to save your values. Please verify that you are specifying a valid config group', 'InvalidConfigGroup');
}
const property = Config.allowedProperties.find(prop => prop.group === group && prop.key === key);
if (property == null) {
throw new _mibuilderError.MiBuilderError(`Unknown config name "${key}"`, 'UnknownConfigKey');
}
if (property.input && property.input.validator(value) === false) {
throw new _mibuilderError.MiBuilderError(`Invalid config value. ${property.input.failedMessage}`, 'InvalidConfigValue');
}
this.setInGroup(property.key, value, property.group);
return this.getContents();
}
}
/**
* Different groups of configs.
*/
exports.Config = Config;
Config.Group = CONFIG_GROUP;