/**
* @copyright 2015 Tridium, Inc. All Rights Reserved.
* @author Logan Byam
*/
/**
* API Status: **Development**
* @module bajaux/registry/RegistryEntry
*/
define([
'log!bajaux.registry.RegistryEntry',
'Promise',
'underscore',
'nmodule/js/rc/asyncUtils/asyncUtils' ], function (
log,
Promise,
_,
asyncUtils) {
'use strict';
const logSevere = log.severe.bind(log);
const { difference, flatten } = _;
const { doRequire } = asyncUtils;
////////////////////////////////////////////////////////////////
// Support functions
////////////////////////////////////////////////////////////////
/**
* Check to see if any of the desired values exist in the array.
*
* @inner
* @param {Array} toTest
* @param {Array} desired
* @returns {boolean} true if `desired` is empty ("I don't care") or if any
* of the values in `desired` also exist in `toTest`
*/
function hasAny(toTest, desired) {
if (!desired.length) {
return true; //don't care
}
for (let i = 0; i < desired.length; i++) {
if (toTest.indexOf(desired[i]) >= 0) {
return true;
}
}
}
/**
* Check to see if all of the desired values exist in the array.
*
* @inner
* @param {Array} toTest
* @param {Array} desired
* @returns {boolean} true if all values in `desired` also exist in `toTest`
* (independent of order)
*/
function hasAll(toTest, desired) {
return !difference(desired, toTest).length;
}
////////////////////////////////////////////////////////////////
// Exports
////////////////////////////////////////////////////////////////
/**
* An entry intended to be stored in a local `Registry`, representing a single
* RequireJS module. Additional parameters can be used to store metadata
* about this module, allowing it to be queried later in more detail.
*
* There is usually no reason to instantiate this class directly;
* a `Registry` will create them as needed.
*
* @class
* @alias module:bajaux/registry/RegistryEntry
* @param {module:bajaux/registry/Registry~QueryParams} params
* @since Niagara 4.10
*/
class RegistryEntry {
constructor(params) {
if (!params || typeof params.rjs !== 'string') {
throw new Error('rjs parameter required');
}
this.$rjs = params.rjs;
this.$deps = params.deps || [];
this.$tags = params.tags || [];
}
/**
* Resolve the RequireJS module (and any dependencies) that is represented
* by this module.
*
* @returns {Promise} promise to be resolved with the contents of
* the RequireJS module, or rejected if the module ID or any of its
* dependencies could not be loaded
*/
resolve() {
return doRequire(this.$rjs, this.$deps)
.catch((e) => {
logSevere(e);
throw e;
});
}
/**
* Check to see if this entry's metadata matches a registry query.
*
* @param {module:bajaux/registry/Registry~QueryParams|module:bajaux/registry/RegistryEntry} [params]
* @returns {boolean} true if this entry matches the query parameters and
* so should be included in the results
*/
matches(params) {
if (params instanceof RegistryEntry) {
//noinspection JSUnresolvedFunction
params = params.toJSON();
}
params = params || {};
const any = params.hasAny || params.tags,
all = params.hasAll,
rjs = params.rjs,
deps = params.deps;
if (any && !hasAny(this.$tags, any)) {
return false;
}
if (all && !hasAll(this.$tags, all)) {
return false;
}
if (rjs && this.$rjs !== rjs) {
return false;
}
//noinspection RedundantIfStatementJS
if (deps && !hasAll(flatten(this.$deps), flatten(deps))) {
return false;
}
return true;
}
/**
* Get the RequireJS ID for this entry.
* @returns {string}
*/
getJsId() { return this.$rjs; }
/**
* Get the list of RequireJS dependencies (typically builtfiles) that must
* be loaded before requiring the main RequireJS ID.
* @returns {Array.<Array.<String>>}
*/
getJsDependencies() { return this.$deps; }
/**
* Get a list of tags that serve as metadata for this entry.
* @returns {Array.<String>}
*/
getTags() { return this.$tags; }
/**
* Return a raw object representation of this entry. As a contractual
* requirement, the output of this function should be able to be passed right
* back to the constructor to create a new instance. Return `undefined` to
* indicate that this entry should never be serialized.
* @returns {Object|undefined}
*/
toJSON() {
return {
rjs: this.getJsId(),
deps: this.getJsDependencies(),
tags: this.getTags()
};
}
}
/**
* Compute a hash string for a query params object. Since the registry
* contents should never change while apps are running, we can memoize calls
* to registry query functions.
*
* @private
* @param {Object} params params object as expected by `matches()`
* @returns {String} a hash string
*/
RegistryEntry.$hashParams = function (params) {
params = params || {};
const tags = params.tags,
all = params.hasAll,
any = params.hasAny,
rjs = params.rjs,
deps = params.deps;
return 't' + (tags ? tags.join() : '') +
'r' + (rjs || '') +
'd' + (deps ? deps.join() : '') +
'l' + (all ? all.join() : '') +
'y' + (any ? any.join() : '');
};
return RegistryEntry;
});