694 lines
26 KiB
JavaScript
694 lines
26 KiB
JavaScript
/* eslint-disable object-shorthand */
|
|
var _ = require('lodash').noConflict(),
|
|
v1Common = require('../common/v1'),
|
|
v2Common = require('../common/v2'),
|
|
util = require('../util'),
|
|
url = require('../url'),
|
|
|
|
Builders = function (options) {
|
|
this.options = options || {};
|
|
},
|
|
script = function (entityV1, listen, key) {
|
|
return {
|
|
listen: listen,
|
|
script: {
|
|
type: 'text/javascript',
|
|
exec: _.isString(entityV1[key]) ? entityV1[key].split('\n') : entityV1[key]
|
|
}
|
|
};
|
|
},
|
|
|
|
authIdMap = {
|
|
apikey: 'apikeyAuth',
|
|
awsSigV4: 'awsSigV4',
|
|
basic: 'basicAuth',
|
|
bearer: 'bearerAuth',
|
|
digest: 'digestAuth',
|
|
hawk: 'hawkAuth',
|
|
ntlm: 'ntlmAuth',
|
|
oAuth1: 'oAuth1',
|
|
oAuth2: 'oAuth2'
|
|
},
|
|
|
|
/**
|
|
* Normalizes `description` field of an entity.
|
|
* If `description` field is absent, this is a no-op.
|
|
* Will mutate the entity.
|
|
*
|
|
* @param {Object} entity - Wrapper object, possibly containing a description field
|
|
* @param {Object} builder - Builder instance that will be called to perform normalization
|
|
* @param {Object} utilOptions - Options to be passed to util fn
|
|
*/
|
|
normalizeDescription = function (entity, builder, utilOptions) {
|
|
var retainEmptyValues = _.get(utilOptions, 'retainEmptyValues');
|
|
|
|
if (_.has(entity, 'description')) {
|
|
entity.description = builder.description(entity.description);
|
|
}
|
|
util.cleanEmptyValue(entity, 'description', retainEmptyValues);
|
|
|
|
return entity;
|
|
};
|
|
|
|
_.assign(Builders.prototype, {
|
|
|
|
/**
|
|
* Normalizes inherited v1 auth manifests.
|
|
*
|
|
* @param {Object} entityV1 - A v1 compliant wrapped auth manifest.
|
|
* @param {?Object} options - The set of options for the current auth cleansing operation.
|
|
* @param {?Boolean} [options.includeNoauth=false] - When set to true, noauth is set to ''.
|
|
*
|
|
* @returns {Object} - A v1 compliant set of auth helper attributes.
|
|
*/
|
|
auth: function (entityV1, options) {
|
|
if (!entityV1) { return; }
|
|
|
|
var auth,
|
|
params,
|
|
mapper,
|
|
currentHelper,
|
|
helperAttributes,
|
|
prioritizeV2 = this.options.prioritizeV2;
|
|
|
|
// if prioritize v2 is true, use auth as the source of truth
|
|
if (util.notLegacy(entityV1, 'auth') || (entityV1.auth && prioritizeV2)) {
|
|
return util.sanitizeAuthArray(entityV1, options);
|
|
}
|
|
if ((entityV1.currentHelper === null) || (entityV1.currentHelper === 'normal')) { return null; }
|
|
|
|
currentHelper = entityV1.currentHelper;
|
|
helperAttributes = entityV1.helperAttributes;
|
|
|
|
// if noDefaults is false and there is no currentHelper, bail out
|
|
if (!(currentHelper || this.options.noDefaults)) { return; }
|
|
// if there is a currentHelper without helperAttributes, bail out.
|
|
if (currentHelper && !helperAttributes) { return this.options.noDefaults ? undefined : null; }
|
|
|
|
!currentHelper && (currentHelper = authIdMap[helperAttributes && helperAttributes.id]);
|
|
auth = { type: v1Common.authMap[currentHelper] };
|
|
mapper = util.authMappersFromLegacy[currentHelper];
|
|
|
|
// @todo: Change this to support custom auth helpers
|
|
mapper && helperAttributes && (params = mapper(helperAttributes)) && (auth[auth.type] = params);
|
|
|
|
return util.authMapToArray({ auth: auth }, options);
|
|
},
|
|
|
|
/**
|
|
* Normalizes v1 collection events.
|
|
*
|
|
* @param {Object} entityV1 - The v1 entity to be normalized.
|
|
* @returns {Array|null} - The normalized events.
|
|
*/
|
|
events: function (entityV1) {
|
|
if (!entityV1) { return; }
|
|
if ((util.notLegacy(entityV1, 'event') || this.options.prioritizeV2) && !_.isEmpty(entityV1.events)) {
|
|
// @todo: Improve this to order prerequest events before test events
|
|
_.forEach(entityV1.events, function (event) {
|
|
!event.listen && (event.listen = 'test');
|
|
|
|
if (event.script) {
|
|
!event.script.type && (event.script.type = 'text/javascript');
|
|
|
|
// @todo: Add support for src
|
|
_.isString(event.script.exec) && (event.script.exec = event.script.exec.split('\n'));
|
|
}
|
|
});
|
|
|
|
return entityV1.events;
|
|
}
|
|
|
|
var events = [];
|
|
|
|
entityV1.preRequestScript && events.push(script(entityV1, 'prerequest', 'preRequestScript'));
|
|
entityV1.tests && events.push(script(entityV1, 'test', 'tests'));
|
|
|
|
if (events.length) { return events; }
|
|
|
|
// retain `null` events
|
|
if (entityV1.events === null) { return null; }
|
|
},
|
|
|
|
/**
|
|
* Facilitates sanitized variable transformations across all levels for v1 collection normalization.
|
|
*
|
|
* @param {Object} entity - The wrapper object containing variable definitions.
|
|
* @param {?Object} options - The set of options for the current variable transformation.
|
|
* @param {?Object} options.fallback - The set of fallback values to be applied when no variables exist.
|
|
* @param {?Boolean} options.noDefaults - When set to true, no defaults are applied.
|
|
* @param {?Boolean} options.retainIds - When set to true, ids are left as is.
|
|
* @returns {Object[]} - The set of sanitized variables.
|
|
*/
|
|
variables: function (entity, options) {
|
|
var self = this,
|
|
// Use builder's own options if override is not requested
|
|
results = util.handleVars(entity, options || this.options);
|
|
|
|
// Normalize descriptions that may have been passed in as objects
|
|
results = _.map(results, function (item) {
|
|
return normalizeDescription(item, self, options || self.options);
|
|
});
|
|
|
|
if (results.length) {
|
|
return results;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Sanitizes request v1 data.
|
|
*
|
|
* @param {Object} requestV1 - The wrapper v1 request object around the data list to be sanitized.
|
|
* @returns {Object[]} - The normalized list of request body parameters.
|
|
*/
|
|
data: function (requestV1) {
|
|
if (!requestV1) { return; }
|
|
|
|
var self = this,
|
|
mode = requestV1.dataMode,
|
|
noDefaults = this.options.noDefaults,
|
|
retainEmptyValues = this.options.retainEmptyValues;
|
|
|
|
if ((!mode || mode === 'binary') && !noDefaults) {
|
|
return retainEmptyValues ? [] : undefined;
|
|
}
|
|
if (!requestV1.data) { return; }
|
|
|
|
_.isArray(requestV1.data) && _.forEach(requestV1.data, function (datum) {
|
|
if (datum.type === 'file' && (_.has(datum, 'value') || !noDefaults)) {
|
|
datum.value = (_.isString(datum.value) || _.isArray(datum.value)) ? datum.value : null;
|
|
}
|
|
|
|
normalizeDescription(datum, self, self.options);
|
|
});
|
|
|
|
return requestV1.data;
|
|
},
|
|
|
|
/**
|
|
* Normalizes a list of header data from the incoming raw v1 request.
|
|
*
|
|
* @param {Object} requestV1 - The raw v1 request object.
|
|
* @returns {Object[]} - The normalized list of header datum values.
|
|
*/
|
|
headerData: function (requestV1) {
|
|
var self = this,
|
|
normalizedHeaderData;
|
|
|
|
if (!requestV1) { return; }
|
|
if (requestV1.headers && _.isEmpty(requestV1.headerData)) {
|
|
// this converts a newline concatenated string of headers to an array, so there are no descriptions
|
|
return v1Common.parseHeaders(requestV1.headers, true);
|
|
}
|
|
|
|
// however, if non empty headerData already exists, sanitize it.
|
|
normalizedHeaderData = _.map(requestV1.headerData, function (entity) {
|
|
return normalizeDescription(entity, self, self.options);
|
|
});
|
|
|
|
if (normalizedHeaderData.length) {
|
|
return normalizedHeaderData;
|
|
}
|
|
},
|
|
|
|
queryParams: function (requestV1) {
|
|
if (!requestV1) { return; }
|
|
|
|
var self = this,
|
|
normalizedQueryParams,
|
|
urlObj;
|
|
|
|
if (!requestV1.queryParams) {
|
|
return requestV1.url && (urlObj = url.parse(requestV1.url)) && urlObj.query;
|
|
}
|
|
|
|
normalizedQueryParams = _.map(requestV1.queryParams, function (entity) {
|
|
return normalizeDescription(entity, self, self.options);
|
|
});
|
|
|
|
if (normalizedQueryParams.length) {
|
|
return normalizedQueryParams;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Facilitates sanitized variable transformations across all levels for v1 collection normalization.
|
|
*
|
|
* @param {Object} entity - The wrapper object containing variable definitions.
|
|
* @param {?Object} [options] - The set of options for the current variable transformation.
|
|
* @param {?Object} [options.fallback] - The set of fallback values to be applied when no variables exist.
|
|
* @param {?Boolean} [options.noDefaults] - When set to true, no defaults are applied.
|
|
* @param {?Boolean} [options.retainEmptyValues] - When set to true, empty values are set to null instead of being
|
|
* removed.
|
|
* @param {?Boolean} [options.retainIds] - When set to true, ids are left as is.
|
|
* @returns {Object[]} - The set of sanitized variables.
|
|
*/
|
|
pathVariableData: function (entity, options) {
|
|
var self = this,
|
|
results = util.handleVars(entity, options, { isV1: true });
|
|
|
|
// Normalize descriptions that may have been passed in as objects
|
|
results = _.map(results, function (item) {
|
|
return normalizeDescription(item, self, self.options);
|
|
});
|
|
|
|
if (results.length) {
|
|
return results;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Normalizes a potentially raw v1 request object.
|
|
*
|
|
* @param {Object} requestV1 - The potentially raw v1 request object.
|
|
* @param {?String} collectionId - A unique identifier for the v1 collection.
|
|
* @param {?Boolean} [skipResponses=false] - When set to true, saved responses will be excluded from the result..
|
|
* @returns {Object} - The normalized v1 request object.
|
|
*/
|
|
request: function (requestV1, collectionId, skipResponses) {
|
|
if (!requestV1) { return; }
|
|
|
|
var map,
|
|
auth,
|
|
tests,
|
|
events,
|
|
mapper,
|
|
variables,
|
|
self = this,
|
|
helperAttributes,
|
|
preRequestScript,
|
|
options = this.options,
|
|
noDefaults = options.noDefaults,
|
|
retainEmpty = options.retainEmptyValues,
|
|
varOpts = { noDefaults: options.noDefaults, retainIds: options.retainIds },
|
|
units = ['queryParams', 'pathVariableData', 'headerData', 'data'];
|
|
|
|
if (!skipResponses) {
|
|
units.push('responses');
|
|
units.push('responses_order');
|
|
}
|
|
|
|
// if noDefaults is true, do not replace the id
|
|
// else
|
|
// if id is falsy, replace the id
|
|
// if retainIds is false, replace the id
|
|
!((options.retainIds && requestV1.id) || options.noDefaults) && (requestV1.id = util.uid());
|
|
|
|
normalizeDescription(requestV1, self, self.options);
|
|
|
|
units.forEach(function (unit) {
|
|
var result = self[unit](requestV1, self.options);
|
|
|
|
result && (requestV1[unit] = result);
|
|
});
|
|
|
|
if (requestV1.dataDisabled) { requestV1.dataDisabled = true; }
|
|
else if (retainEmpty) { requestV1.dataDisabled = false; }
|
|
else { delete requestV1.dataDisabled; }
|
|
|
|
// remove invalid protocolProfileBehavior property from requestV1
|
|
!util.addProtocolProfileBehavior(requestV1) && delete requestV1.protocolProfileBehavior;
|
|
|
|
collectionId && !noDefaults && (requestV1.collectionId = collectionId);
|
|
|
|
// normalized v1 requests should not have falsy helperAttributes or currentHelper
|
|
if (_.has(requestV1, 'currentHelper')) {
|
|
(requestV1.currentHelper === 'normal') && (requestV1.currentHelper = null);
|
|
|
|
if (!requestV1.currentHelper) {
|
|
(requestV1.currentHelper !== null) && (requestV1.currentHelper = null);
|
|
|
|
// @todo: Should currentHelper be recreated from helperAttributes.id if falsy?
|
|
requestV1.helperAttributes = null;
|
|
}
|
|
}
|
|
|
|
auth = self.auth(requestV1);
|
|
|
|
if (auth) {
|
|
requestV1.auth = auth;
|
|
|
|
if (_.has(requestV1, 'helperAttributes') && !requestV1.currentHelper) {
|
|
requestV1.currentHelper = authIdMap[auth.type];
|
|
}
|
|
}
|
|
else if (auth === null) { // eslint-disable-line security/detect-possible-timing-attacks
|
|
requestV1.auth = requestV1.currentHelper = requestV1.helperAttributes = null;
|
|
}
|
|
else { delete requestV1.auth; }
|
|
|
|
events = self.events(requestV1);
|
|
if (events || events === null) {
|
|
requestV1.events = events;
|
|
}
|
|
else {
|
|
delete requestV1.events;
|
|
}
|
|
|
|
variables = self.variables(requestV1, varOpts);
|
|
if (variables) {
|
|
requestV1.variables = variables;
|
|
}
|
|
else {
|
|
delete requestV1.variables;
|
|
}
|
|
|
|
if (requestV1.auth && (util.notLegacy(requestV1, 'auth') || options.prioritizeV2)) {
|
|
requestV1.currentHelper = v2Common.authMap[requestV1.auth.type];
|
|
(requestV1.currentHelper === null) && (requestV1.helperAttributes = null);
|
|
|
|
mapper = util.authMappersFromCurrent[requestV1.currentHelper];
|
|
|
|
if (mapper) {
|
|
(map = util.authArrayToMap(requestV1)) && (helperAttributes = mapper(map[requestV1.auth.type]));
|
|
helperAttributes && (requestV1.helperAttributes = helperAttributes);
|
|
}
|
|
}
|
|
|
|
if (requestV1.events && (util.notLegacy(requestV1, 'event') || options.prioritizeV2)) {
|
|
tests = preRequestScript = '';
|
|
|
|
_.forEach(requestV1.events, function (event) {
|
|
var exec = event && event.script && event.script.exec;
|
|
|
|
if (!_.isArray(exec)) { return; }
|
|
if (event.listen === 'prerequest') {
|
|
preRequestScript += exec.join('\n');
|
|
}
|
|
else if (event.listen === 'test') {
|
|
tests += exec.join('\n');
|
|
}
|
|
});
|
|
|
|
requestV1.preRequestScript = preRequestScript ? preRequestScript : null;
|
|
requestV1.tests = tests ? tests : null;
|
|
}
|
|
|
|
// prune
|
|
['preRequestScript', 'tests'].forEach(function (script) {
|
|
if (_.has(requestV1, script) && !requestV1[script] && requestV1[script] !== null) {
|
|
delete requestV1[script];
|
|
}
|
|
});
|
|
|
|
return requestV1;
|
|
},
|
|
|
|
/**
|
|
* Normalizes a potentially raw v1 response object.
|
|
*
|
|
* @param {Object} responseV1 - The potentially raw v1 response object.
|
|
* @returns {Object} - The normalized v1 response object.
|
|
*/
|
|
response: function (responseV1) {
|
|
var self = this;
|
|
|
|
// if noDefaults is true, do not replace the id
|
|
// else
|
|
// if id is falsy, replace the id
|
|
// if retainIds is false, replace the id
|
|
!((self.options.retainIds && responseV1.id) || self.options.noDefaults) && (responseV1.id = util.uid());
|
|
|
|
// the true in the next line ensures that we don't recursively go on processing responses in a request.
|
|
responseV1.request = self.request(responseV1.request, undefined, true);
|
|
|
|
!responseV1.language && (responseV1.language = 'Text');
|
|
!responseV1.previewType && (responseV1.previewType = 'html');
|
|
|
|
_.isEmpty(responseV1.cookies) && (delete responseV1.cookies);
|
|
|
|
return responseV1;
|
|
},
|
|
|
|
responses: function (requestV1) {
|
|
if (_.isEmpty(requestV1 && requestV1.responses)) { return; }
|
|
|
|
var self = this;
|
|
|
|
requestV1.responses.forEach(function (response) {
|
|
self.response(response);
|
|
});
|
|
|
|
return requestV1.responses;
|
|
},
|
|
|
|
/**
|
|
* Normalizes a request order list.
|
|
*
|
|
* @param {Object} entityV1 - An object containing a potentially raw list of folder ids.
|
|
* @returns {Array} - The normalized list of folder ids.
|
|
*/
|
|
order: function (entityV1) {
|
|
return !this.options.noDefaults && _.compact(entityV1 && entityV1.order);
|
|
},
|
|
|
|
/**
|
|
* Normalizes a folder order list.
|
|
*
|
|
* @param {Object} entityV1 - An object containing a potentially raw list of folder ids.
|
|
* @returns {Array} - The normalized list of folder ids.
|
|
*/
|
|
folders_order: function (entityV1) {
|
|
return !this.options.noDefaults && _.compact(entityV1 && entityV1.folders_order);
|
|
},
|
|
|
|
/**
|
|
* Normalizes a response order list.
|
|
*
|
|
* @param {Object} entityV1 - An object containing a potentially raw list of response ids.
|
|
* @returns {Array} - The normalized list of response ids.
|
|
*/
|
|
responses_order: function (entityV1) {
|
|
return !this.options.noDefaults && _.compact(entityV1 && entityV1.responses_order);
|
|
},
|
|
|
|
/**
|
|
* Normalizes a potentially raw v1 folders list.
|
|
*
|
|
* @param {Object} collectionV1 - The potentially raw v1 collection object.
|
|
* @returns {Object[]} - The normalized v1 collection folders list.
|
|
*/
|
|
folders: function (collectionV1) {
|
|
if (_.isEmpty(collectionV1 && collectionV1.folders)) { return; }
|
|
|
|
var auth,
|
|
events,
|
|
variables,
|
|
self = this,
|
|
order,
|
|
foldersOrder,
|
|
retainEmpty = self.options.retainEmptyValues,
|
|
varOpts = { noDefaults: self.options.noDefaults, retainIds: self.options.retainIds };
|
|
|
|
_.forEach(collectionV1.folders, function (folder) {
|
|
if (!folder) { return; }
|
|
|
|
// if noDefaults is true, do not replace the id
|
|
// else
|
|
// if id is falsy, replace the id
|
|
// if retainIds is false, replace the id
|
|
!((self.options.retainIds && folder.id) || self.options.noDefaults) && (folder.id = util.uid());
|
|
|
|
folder.description = self.description(folder.description);
|
|
util.cleanEmptyValue(folder, 'description', retainEmpty);
|
|
|
|
// remove invalid protocolProfileBehavior property
|
|
!util.addProtocolProfileBehavior(folder) && delete folder.protocolProfileBehavior;
|
|
|
|
auth = self.auth(folder);
|
|
|
|
!_.isEmpty((order = self.order(folder))) && (folder.order = order);
|
|
!_.isEmpty((foldersOrder = self.folders_order(folder))) && (folder.folders_order = foldersOrder);
|
|
|
|
(auth || (auth === null)) && (folder.auth = auth);
|
|
(events = self.events(folder)) && (folder.events = events);
|
|
(variables = self.variables(folder, varOpts)) && (folder.variables = variables);
|
|
});
|
|
|
|
return _.compact(collectionV1.folders);
|
|
},
|
|
|
|
/**
|
|
* Normalizes a potentially raw v1 request object.
|
|
*
|
|
* @param {Object} collectionV1 - The potentially raw v1 collection object.
|
|
* @returns {Object[]|*} - The normalized v1 request list.
|
|
*/
|
|
requests: function (collectionV1) {
|
|
if (_.isEmpty(collectionV1 && collectionV1.requests)) { return; }
|
|
|
|
var self = this;
|
|
|
|
collectionV1.requests.forEach(function (request) {
|
|
self.request(request);
|
|
});
|
|
|
|
return _.compact(collectionV1.requests);
|
|
},
|
|
|
|
/**
|
|
* Creates the v1.0.0 compatible description string.
|
|
*
|
|
* @param {Object} maybeObjectDescription - The description to be converted
|
|
*
|
|
* @returns {String} - The resultant v1 description.
|
|
*/
|
|
description: function (maybeObjectDescription) {
|
|
var description,
|
|
retainEmpty = _.get(this.options, 'retainEmptyValues'),
|
|
createDefaultValue = !_.get(this.options, 'noDefaults', false);
|
|
|
|
if (_.isObject(maybeObjectDescription)) {
|
|
description = _.toString(_.get(maybeObjectDescription, 'content'));
|
|
}
|
|
else {
|
|
description = maybeObjectDescription;
|
|
}
|
|
|
|
if (description) {
|
|
return description;
|
|
}
|
|
else if (description === undefined && createDefaultValue) {
|
|
return null;
|
|
}
|
|
else if (_.isEmpty(description) && retainEmpty) {
|
|
return null;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
});
|
|
|
|
module.exports = {
|
|
|
|
/**
|
|
* Normalizes a single v1 request.
|
|
*
|
|
* @param {Object} request - The v1 request to be normalized.
|
|
* @param {Object} options - The set of options for the current normalization.
|
|
* @param {?Boolean} [options.mutate=false] - When set to true, normalization is done in place.
|
|
* @param {?Boolean} [options.noDefaults=false] - When set to true, sensible defaults are not added.
|
|
* @param {?Boolean} [options.prioritizeV2=false] - When set to true, v2 style properties are checked first.
|
|
* @param {?Boolean} [options.retainEmptyValues=false] - When set to true, empty values are set to '' instead of
|
|
* being removed.
|
|
* @param {Function} callback - A function that is invoked when the normalization has completed.
|
|
* @returns {*}
|
|
*/
|
|
normalizeSingle: function (request, options, callback) {
|
|
var err,
|
|
normalized,
|
|
builders = new Builders(options);
|
|
|
|
// At this stage, mutate will not be passed ordinarily. Hence, the falsy nature of options.mutate can be used
|
|
// to selectively clone the request.
|
|
options && !options.mutate && (request = _.cloneDeep(request));
|
|
|
|
try { normalized = builders.request(request); }
|
|
catch (e) { err = e; }
|
|
|
|
if (callback) { return callback(err, normalized); }
|
|
|
|
if (err) { throw err; }
|
|
|
|
return normalized;
|
|
},
|
|
|
|
/**
|
|
* Normalizes a single v1 response.
|
|
*
|
|
* @param {Object} response - The v1 request to be normalized.
|
|
* @param {Object} options - The set of options for the current normalization.
|
|
* @param {?Boolean} [options.mutate=false] - When set to true, normalization is done in place.
|
|
* @param {?Boolean} [options.noDefaults=false] - When set to true, sensible defaults are not added.
|
|
* @param {?Boolean} [options.prioritizeV2=false] - When set to true, v2 style properties are checked first.
|
|
* @param {?Boolean} [options.retainEmptyValues=false] - When set to true, empty values are set to '' instead of
|
|
* being removed.
|
|
* @param {Function} callback - A function that is invoked when the normalization has completed.
|
|
* @returns {*}
|
|
*/
|
|
normalizeResponse: function (response, options, callback) {
|
|
var err,
|
|
normalized,
|
|
builders = new Builders(options);
|
|
|
|
// At this stage, mutate will not be passed ordinarily. Hence, the falsy nature of options.mutate can be used
|
|
// to selectively clone the response.
|
|
options && !options.mutate && (response = _.cloneDeep(response));
|
|
|
|
try { normalized = builders.response(response); }
|
|
catch (e) { err = e; }
|
|
|
|
if (callback) { return callback(err, normalized); }
|
|
|
|
if (err) { throw err; }
|
|
|
|
return normalized;
|
|
},
|
|
|
|
/**
|
|
* Converts a V1 collection to a V2 collection (performs ID replacement, etc as necessary).
|
|
*
|
|
* @param {Object} collection - The v1 collection to be normalized.
|
|
* @param {Object} options - The options for the current normalization sequence.
|
|
* @param {?Boolean} [options.mutate=false] - When set to true, normalization is done in place.
|
|
* @param {?Boolean} [options.noDefaults=false] - When set to true, sensible defaults are not added.
|
|
* @param {?Boolean} [options.prioritizeV2=false] - When set to true, v2 style properties are checked first.
|
|
* @param {?Boolean} [options.retainEmptyValues=false] - When set to true, empty values are set to '' instead of
|
|
* being removed.
|
|
* @param {Function} callback - A function invoked to indicate that the normalization has completed.
|
|
* @returns {*}
|
|
*/
|
|
normalize: function (collection, options, callback) {
|
|
// At this stage, mutate will not be passed ordinarily. Hence, the falsy nature of options.mutate can be used
|
|
// to selectively clone the collection.
|
|
options && !options.mutate && (collection = _.cloneDeep(collection));
|
|
|
|
var auth,
|
|
authOptions = { excludeNoauth: true },
|
|
builders = new Builders(options),
|
|
units = ['events', 'variables', 'order', 'folders_order', 'folders', 'requests'];
|
|
|
|
// if noDefaults is true, do not replace the id
|
|
// else
|
|
// if id is falsy, replace the id
|
|
// if retainIds is false, replace the id
|
|
!((options.retainIds && collection.id) || options.noDefaults) && (collection.id = util.uid());
|
|
|
|
normalizeDescription(collection, builders, options);
|
|
|
|
// remove invalid protocolProfileBehavior property
|
|
!util.addProtocolProfileBehavior(collection) && delete collection.protocolProfileBehavior;
|
|
|
|
try {
|
|
auth = builders.auth(collection, authOptions);
|
|
if (auth || (options.retainEmptyValues && auth === null)) {
|
|
collection.auth = auth;
|
|
}
|
|
else {
|
|
delete collection.auth;
|
|
}
|
|
|
|
units.forEach(function (unit) {
|
|
var result,
|
|
_options;
|
|
|
|
if (unit === 'variables') {
|
|
_options = { retainIds: options.retainIds, noDefaults: options.noDefaults };
|
|
}
|
|
|
|
if (!_.isEmpty(result = builders[unit](collection, _options)) || (unit === 'folders')) {
|
|
collection[unit] = result;
|
|
}
|
|
});
|
|
}
|
|
catch (e) {
|
|
if (callback) { return callback(e, null); }
|
|
throw e;
|
|
}
|
|
|
|
if (callback) { return callback(null, collection); }
|
|
|
|
return collection;
|
|
}
|
|
};
|