feat: ✨ Created a mini nodeJS server with NewMan for testing without PostMan GUI.
This will mimic a run in a CD/CI environment or docker container.
This commit is contained in:
61
node_modules/postman-collection-transformer/lib/common/v1.js
generated
vendored
Normal file
61
node_modules/postman-collection-transformer/lib/common/v1.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
var _ = require('lodash').noConflict(),
|
||||
|
||||
regexes = {
|
||||
fold: /\r\n([ \t])/g,
|
||||
trim: /^\s*(.*\S)?\s*$/, // eslint-disable-line security/detect-unsafe-regex
|
||||
header: /^((\/\/\s*)?\S+):(.*)$/gm // eslint-disable-line security/detect-unsafe-regex
|
||||
},
|
||||
headersCommentPrefix = '//';
|
||||
|
||||
module.exports = {
|
||||
authMap: {
|
||||
apikeyAuth: 'apikey',
|
||||
basicAuth: 'basic',
|
||||
bearerAuth: 'bearer',
|
||||
digestAuth: 'digest',
|
||||
hawkAuth: 'hawk',
|
||||
oAuth1: 'oauth1',
|
||||
oAuth2: 'oauth2',
|
||||
ntlmAuth: 'ntlm',
|
||||
awsSigV4: 'awsv4',
|
||||
normal: null
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses a string of headers to an object.
|
||||
*
|
||||
* @param {String} data - A string of newline concatenated header key-value pairs.
|
||||
* @param {?Boolean} [legacy] - A flag to indicate whether the parsing is being done for v1 normalization or v1 to
|
||||
* v2 conversion.
|
||||
* @returns {Object[]|*} - The parsed list of header key-value pair objects.
|
||||
* @private
|
||||
*/
|
||||
parseHeaders: function (data, legacy) {
|
||||
if (!data) { return; }
|
||||
|
||||
var head,
|
||||
headers = [],
|
||||
statusValue = !legacy,
|
||||
match = regexes.header.exec(data),
|
||||
property = legacy ? 'enabled' : 'disabled';
|
||||
|
||||
data = data.toString().replace(regexes.fold, '$1');
|
||||
|
||||
while (match) {
|
||||
head = {
|
||||
key: match[1],
|
||||
value: match[3].replace(regexes.trim, '$1')
|
||||
};
|
||||
|
||||
if (_.startsWith(head.key, headersCommentPrefix)) {
|
||||
head[property] = statusValue;
|
||||
head.key = head.key.replace(headersCommentPrefix, '').trim();
|
||||
}
|
||||
|
||||
headers.push(head);
|
||||
match = regexes.header.exec(data);
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
};
|
57
node_modules/postman-collection-transformer/lib/common/v2.js
generated
vendored
Normal file
57
node_modules/postman-collection-transformer/lib/common/v2.js
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
var _ = require('lodash').noConflict(),
|
||||
util = require('../util'),
|
||||
|
||||
/**
|
||||
* Replenishes missing ids in v2.0.0.x collections.
|
||||
*
|
||||
* @param {*} currentItem - A collection entity on which to check for ids.
|
||||
* @returns {Object|*} - The updated item, with the correct id fields in place.
|
||||
*/
|
||||
populateIds = function (currentItem) {
|
||||
if (!currentItem) { return; }
|
||||
|
||||
// ID sanitization
|
||||
if (currentItem._postman_id) {
|
||||
currentItem.id = currentItem._postman_id;
|
||||
delete currentItem._postman_id;
|
||||
}
|
||||
|
||||
!currentItem.id && (currentItem.id = util.uid());
|
||||
|
||||
if (currentItem.response && currentItem.response.length) {
|
||||
_.forEach(currentItem.response, populateIds);
|
||||
}
|
||||
|
||||
if (currentItem.responses && currentItem.responses.length) {
|
||||
_.forEach(currentItem.responses, populateIds);
|
||||
}
|
||||
|
||||
var itemArray = currentItem.items || currentItem.item;
|
||||
|
||||
itemArray && itemArray.length && _.forEach(itemArray, populateIds);
|
||||
|
||||
return currentItem;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
authMap: {
|
||||
apikey: 'apikeyAuth',
|
||||
basic: 'basicAuth',
|
||||
bearer: 'bearerAuth',
|
||||
digest: 'digestAuth',
|
||||
hawk: 'hawkAuth',
|
||||
oauth1: 'oAuth1',
|
||||
oauth2: 'oAuth2',
|
||||
ntlm: 'ntlmAuth',
|
||||
awsv4: 'awsSigV4',
|
||||
noauth: null
|
||||
},
|
||||
modeMap: {
|
||||
file: 'binary',
|
||||
formdata: 'params',
|
||||
graphql: 'graphql',
|
||||
raw: 'raw',
|
||||
urlencoded: 'urlencoded'
|
||||
},
|
||||
populateIds: populateIds
|
||||
};
|
5
node_modules/postman-collection-transformer/lib/constants.js
generated
vendored
Normal file
5
node_modules/postman-collection-transformer/lib/constants.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
exports.SCHEMA_V2_URL = 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json';
|
||||
exports.SCHEMA_V2_1_0_URL = 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json';
|
||||
exports.SCHEMA_V1_URL = 'https://schema.getpostman.com/json/collection/v1.0.0/collection.json';
|
||||
exports.PREREQUEST_EXT = '_preRequestScript';
|
||||
exports.TESTS_EXT = '_tests';
|
152
node_modules/postman-collection-transformer/lib/converters/index.js
generated
vendored
Normal file
152
node_modules/postman-collection-transformer/lib/converters/index.js
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
var semver = require('semver'),
|
||||
FN = 'function',
|
||||
generateConverter; // constructor
|
||||
|
||||
/**
|
||||
* Prototype interface definition of a converter
|
||||
*
|
||||
* @param {Object} model - A manifest that defines the conversion process.
|
||||
* @param {String} model.input - The input version to convert from.
|
||||
* @param {String} model.output - The output version to convert to.
|
||||
* @param {Function} model.convert - A function to convert entire collections.
|
||||
* @param {Function} model.create - A function to perform creation operations.
|
||||
* @param {Function} [model.init] - An initializer function to bootstrap the generated converter.
|
||||
*
|
||||
* @throws {Error} If model definition does not meet requirements
|
||||
*/
|
||||
generateConverter = function (model) {
|
||||
var error;
|
||||
|
||||
// validate the model
|
||||
if (!model) {
|
||||
error = 'invalid definition of converter';
|
||||
}
|
||||
// ensure that the input version support is a valid semver
|
||||
else if (!semver.valid(model.input)) {
|
||||
error = 'input version support for converter is invalid';
|
||||
}
|
||||
// ensure that the output version support is a valid semver
|
||||
else if (!semver.valid(model.output)) {
|
||||
error = 'output version support for converter is invalid';
|
||||
}
|
||||
else if (typeof model.convert !== FN) {
|
||||
error = 'convert function is not defined';
|
||||
}
|
||||
else if (typeof model.convertSingle !== FN) {
|
||||
error = 'convertSingle function is not defined';
|
||||
}
|
||||
|
||||
if (semver.satisfies(model.input, model.output)) {
|
||||
error = 'input version ' + model.input + ' matches output version ' + model.output + ' for converter';
|
||||
}
|
||||
|
||||
// If we had encountered any error during validation, we simply exit by executing the callback and forwarding the
|
||||
// error.
|
||||
if (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
|
||||
return model;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* All converters
|
||||
*
|
||||
* @type {object<Converter>}
|
||||
*
|
||||
* @note this form of loading is most likely not browser friendly, find browser alternative
|
||||
*/
|
||||
converters: {
|
||||
'converter-v1-to-v2': require('./v1.0.0/converter-v1-to-v2'),
|
||||
'converter-v1-to-v21': require('./v1.0.0/converter-v1-to-v21'),
|
||||
'converter-v2-to-v1': require('./v2.0.0/converter-v2-to-v1'),
|
||||
'converter-v21-to-v1': require('./v2.1.0/converter-v21-to-v1')
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetches a converter for the given input and output versions
|
||||
*
|
||||
* @param {String} inputVersion - The version to convert from.
|
||||
* @param {String} outputVersion - The version to convert to.
|
||||
* @returns {Converter} - A converter for the given set of options.
|
||||
*/
|
||||
getConverter: function (inputVersion, outputVersion) {
|
||||
var converter;
|
||||
|
||||
inputVersion = semver.clean(inputVersion);
|
||||
outputVersion = semver.clean(outputVersion);
|
||||
|
||||
for (converter in this.converters) {
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
converter = this.converters.hasOwnProperty(converter) && this.converters[converter];
|
||||
if (converter && semver.eq(converter.input, inputVersion) && semver.eq(converter.output, outputVersion)) {
|
||||
return generateConverter(converter);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Picks the appropriate converter and converts the given collection.
|
||||
*
|
||||
* @param {Object} collection - The collection to be converted.
|
||||
* @param {Object} options - The set of options for request conversion.
|
||||
* @param {Function} callback - The function to be invoked after the completion of conversion process.
|
||||
*/
|
||||
convert: function (collection, options, callback) {
|
||||
var chosenConverter = this.getConverter(options.inputVersion, options.outputVersion);
|
||||
|
||||
if (!chosenConverter) {
|
||||
return callback(new Error('no conversion path found'));
|
||||
}
|
||||
|
||||
return chosenConverter.convert(collection, options, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Picks the appropriate converter and converts the given object.
|
||||
*
|
||||
* @param {Object} object - A single V1 request or a V2 Item.
|
||||
* @param {Object} options - The set of options for request conversion.
|
||||
* @param {Function} callback - The function to be invoked after the completion of conversion process.
|
||||
*/
|
||||
convertSingle: function (object, options, callback) {
|
||||
var chosenConverter = this.getConverter(options.inputVersion, options.outputVersion);
|
||||
|
||||
if (!chosenConverter) {
|
||||
return callback(new Error('no conversion path found'));
|
||||
}
|
||||
|
||||
return chosenConverter.convertSingle(object, options, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Picks the appropriate converter and converts the given object.
|
||||
*
|
||||
* @param {Object} object - A single V1 Response or a V2 Response.
|
||||
* @param {Object} options - The set of options for response conversion.
|
||||
* @param {Function} callback - The function invoked to mark the completion of the conversion process.
|
||||
* @returns {*}
|
||||
*/
|
||||
convertResponse: function (object, options, callback) {
|
||||
var chosenConverter = this.getConverter(options.inputVersion, options.outputVersion);
|
||||
|
||||
if (!chosenConverter) {
|
||||
return callback(new Error('no conversion path found'));
|
||||
}
|
||||
|
||||
return chosenConverter.convertResponse(object, options, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a builder, which can be used to convert individual requests, etc.
|
||||
*
|
||||
* @param {Object} options - The set of options for builder creation.
|
||||
* @returns {Function} - The builder for the given set of options.
|
||||
*/
|
||||
builder: function (options) {
|
||||
var chosenConverter = this.getConverter(options.inputVersion, options.outputVersion);
|
||||
|
||||
return chosenConverter.create(options);
|
||||
}
|
||||
};
|
885
node_modules/postman-collection-transformer/lib/converters/v1.0.0/converter-v1-to-v2.js
generated
vendored
Normal file
885
node_modules/postman-collection-transformer/lib/converters/v1.0.0/converter-v1-to-v2.js
generated
vendored
Normal file
@@ -0,0 +1,885 @@
|
||||
/* eslint-disable object-shorthand */
|
||||
var _ = require('lodash').noConflict(),
|
||||
constants = require('../../constants'),
|
||||
v1Common = require('../../common/v1'),
|
||||
util = require('../../util'),
|
||||
|
||||
headersCommentPrefix = '//',
|
||||
IS_SUBFOLDER = Symbol('_postman_isSubFolder'),
|
||||
|
||||
/**
|
||||
* A constructor that is capable of being used for one-off conversions of requests, and folders.
|
||||
*
|
||||
* @param {Object} options - The set of options for builder construction.
|
||||
* @class Builders
|
||||
* @constructor
|
||||
*/
|
||||
Builders = function (options) {
|
||||
this.options = options || {};
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse formdata & urlencoded request data.
|
||||
* - filter params missing property `key`
|
||||
* - handle file type param value
|
||||
* -cleanup `enabled` & `description`
|
||||
*
|
||||
* @param {Object[]} data - Data to parse.
|
||||
* @param {?Boolean} [retainEmpty] - To retain empty values or not.
|
||||
* @returns {Object[]} - Parsed data.
|
||||
*/
|
||||
parseFormData = function (data, retainEmpty) {
|
||||
if (!(Array.isArray(data) && data.length)) { return []; }
|
||||
|
||||
var formdata = [],
|
||||
i,
|
||||
ii,
|
||||
param;
|
||||
|
||||
for (i = 0, ii = data.length; i < ii; i++) {
|
||||
// clone param to avoid mutating data.
|
||||
// eslint-disable-next-line prefer-object-spread
|
||||
param = Object.assign({}, data[i]);
|
||||
|
||||
// skip if param is missing property `key`,
|
||||
// `key` is a required property, value can be null/undefined.
|
||||
// because in a FormParam property lists, key is used for indexing.
|
||||
if (_.isNil(param.key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// for file `type`, set `value` to `src`
|
||||
if (param.type === 'file' && !param.src && param.value) {
|
||||
param.src = (_.isString(param.value) || _.isArray(param.value)) ? param.value : null;
|
||||
delete param.value;
|
||||
}
|
||||
|
||||
// `hasOwnProperty` check ensures that it don't delete undefined property: `enabled`
|
||||
if (Object.prototype.hasOwnProperty.call(param, 'enabled')) {
|
||||
// set `disabled` flag if `enabled` is false.
|
||||
param.enabled === false && (param.disabled = true);
|
||||
|
||||
delete param.enabled; // cleanup
|
||||
}
|
||||
|
||||
// Prevent empty descriptions from showing up in the converted results. This keeps collections clean.
|
||||
util.cleanEmptyValue(param, 'description', retainEmpty);
|
||||
|
||||
formdata.push(param);
|
||||
}
|
||||
|
||||
return formdata;
|
||||
};
|
||||
|
||||
_.assign(Builders.prototype, {
|
||||
|
||||
/**
|
||||
* Constructs a V2 compatible "info" object from a V1 Postman Collection
|
||||
*
|
||||
* @param {Object} collectionV1 - A v1 collection to derive collection metadata from.
|
||||
* @returns {Object} - The resultant v2 info object.
|
||||
*/
|
||||
info: function (collectionV1) {
|
||||
var info = {
|
||||
_postman_id: collectionV1.id || util.uid(),
|
||||
name: collectionV1.name
|
||||
};
|
||||
|
||||
if (collectionV1.description) { info.description = collectionV1.description; }
|
||||
else if (this.options.retainEmptyValues) { info.description = null; }
|
||||
|
||||
info.schema = constants.SCHEMA_V2_URL;
|
||||
|
||||
return info;
|
||||
},
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
variable: function (entity, options) {
|
||||
return util.handleVars(entity, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs a V2 compatible URL object from a V1 request
|
||||
*
|
||||
* @param {Object} requestV1 - The source v1 request to extract the URL from.
|
||||
* @returns {String|Object} - The resultant URL.
|
||||
*/
|
||||
url: function (requestV1) {
|
||||
var queryParams = [],
|
||||
pathVariables = [],
|
||||
traversedVars = {},
|
||||
queryParamAltered,
|
||||
retainIds = this.options.retainIds,
|
||||
parsed = util.urlparse(requestV1.url),
|
||||
retainEmpty = this.options.retainEmptyValues;
|
||||
|
||||
// add query params
|
||||
_.forEach(requestV1.queryParams, function (queryParam) {
|
||||
(queryParam.enabled === false) && (queryParam.disabled = true);
|
||||
|
||||
delete queryParam.enabled;
|
||||
|
||||
util.cleanEmptyValue(queryParam, 'description', retainEmpty);
|
||||
|
||||
if (_.has(queryParam, 'equals')) {
|
||||
if (queryParam.equals) {
|
||||
(queryParam.value === null) && (queryParam.value = '');
|
||||
}
|
||||
else {
|
||||
// = is not appended when the value is null. However,
|
||||
// non empty value should be preserved
|
||||
queryParam.value = queryParam.value || null;
|
||||
}
|
||||
|
||||
queryParamAltered = true;
|
||||
delete queryParam.equals;
|
||||
}
|
||||
queryParams.push(queryParam);
|
||||
});
|
||||
|
||||
// only add query params from URL if not given explicitly
|
||||
if (!_.size(queryParams)) {
|
||||
// parsed query params are taken from the url, so no descriptions are available from them
|
||||
queryParams = parsed.query;
|
||||
}
|
||||
|
||||
// Merge path variables
|
||||
_.forEach(requestV1.pathVariableData, function (pathVariable) {
|
||||
pathVariable = _.clone(pathVariable);
|
||||
util.cleanEmptyValue(pathVariable, 'description', retainEmpty);
|
||||
|
||||
if (!retainIds && pathVariable.id) {
|
||||
delete pathVariable.id;
|
||||
}
|
||||
|
||||
pathVariables.push(pathVariable);
|
||||
traversedVars[pathVariable.key] = true;
|
||||
});
|
||||
// pathVariables in v1 are of the form {foo: bar}, so no descriptions can be obtained from them
|
||||
_.forEach(requestV1.pathVariables, function (value, key) {
|
||||
!traversedVars[key] && pathVariables.push({
|
||||
value: value,
|
||||
key: key
|
||||
});
|
||||
});
|
||||
|
||||
!_.isEmpty(queryParams) && (parsed.query = queryParams);
|
||||
!_.isEmpty(pathVariables) && (parsed.variable = pathVariables);
|
||||
|
||||
// If the query params have been altered, update the raw stringified URL
|
||||
queryParamAltered && (parsed.raw = util.urlunparse(parsed));
|
||||
|
||||
// return the objectified URL only if query param or path variable descriptions are present, string otherwise
|
||||
return (parsed.query || parsed.variable) ? parsed : (parsed.raw || requestV1.url);
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts the HTTP Method from a V1 request
|
||||
*
|
||||
* @param {Object} requestV1 - The v1 request to extract the request method from.
|
||||
* @returns {String} - The extracted request method.
|
||||
*/
|
||||
method: function (requestV1) {
|
||||
return requestV1.method;
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs an array of Key-Values from a raw HTTP Header string.
|
||||
*
|
||||
* @param {Object} requestV1 - The v1 request to extract header information from.
|
||||
* @returns {Object[]} - A list of header definition objects.
|
||||
*/
|
||||
header: function (requestV1) {
|
||||
if (_.isArray(requestV1.headers)) {
|
||||
return requestV1.headers;
|
||||
}
|
||||
|
||||
var headers = [],
|
||||
traversed = {},
|
||||
headerData = requestV1.headerData || [],
|
||||
retainEmpty = this.options.retainEmptyValues;
|
||||
|
||||
_.forEach(headerData, function (header) {
|
||||
if (_.startsWith(header.key, headersCommentPrefix) || (header.enabled === false)) {
|
||||
header.disabled = true;
|
||||
header.key = header.key.replace(headersCommentPrefix, '').trim();
|
||||
}
|
||||
|
||||
// prevent empty header descriptions from showing up in converted results. This keeps the collections clean
|
||||
util.cleanEmptyValue(header, 'description', retainEmpty);
|
||||
|
||||
delete header.enabled;
|
||||
headers.push(header); // @todo Improve this sequence to account for multi-valued headers
|
||||
|
||||
traversed[header.key] = true;
|
||||
});
|
||||
|
||||
// requestV1.headers is a string, so no descriptions can be obtained from it
|
||||
_.forEach(v1Common.parseHeaders(requestV1.headers), function (header) {
|
||||
!traversed[header.key] && headers.push(header);
|
||||
});
|
||||
|
||||
return headers;
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs a V2 Request compatible "body" object from a V1 Postman request
|
||||
*
|
||||
* @param {Object} requestV1 - The v1 request to extract the body from.
|
||||
* @returns {{mode: *, content: (*|string)}}
|
||||
*/
|
||||
body: function (requestV1) {
|
||||
var modes = {
|
||||
binary: 'file',
|
||||
graphql: 'graphql',
|
||||
params: 'formdata',
|
||||
raw: 'raw',
|
||||
urlencoded: 'urlencoded'
|
||||
},
|
||||
data = {},
|
||||
rawModeData,
|
||||
graphqlModeData,
|
||||
dataMode = modes[requestV1.dataMode],
|
||||
retainEmpty = this.options.retainEmptyValues,
|
||||
bodyOptions = {},
|
||||
mode,
|
||||
// flag indicating that all the props which holds request body data
|
||||
// i.e, data (urlencoded, formdata), rawModeData (raw, file) and graphqlModeData (graphql)
|
||||
// are empty.
|
||||
emptyBody = _.isEmpty(requestV1.data) && _.isEmpty(requestV1.rawModeData) &&
|
||||
_.isEmpty(requestV1.graphqlModeData);
|
||||
|
||||
// set body to null if:
|
||||
// 1. emptyBody is true and dataMode is unset
|
||||
// 2. dataMode is explicitly set to null
|
||||
// @note the explicit null check is added to ensure that body is not set
|
||||
// in case the dataMode was set to null by the app.
|
||||
if ((!dataMode && emptyBody) || requestV1.dataMode === null) {
|
||||
return retainEmpty ? null : undefined;
|
||||
}
|
||||
|
||||
// set `rawModeData` if its a string
|
||||
if (_.isString(requestV1.rawModeData)) {
|
||||
rawModeData = requestV1.rawModeData;
|
||||
}
|
||||
// check if `rawModeData` is an array like: ['rawModeData']
|
||||
else if (Array.isArray(requestV1.rawModeData) &&
|
||||
requestV1.rawModeData.length === 1 &&
|
||||
_.isString(requestV1.rawModeData[0])) {
|
||||
rawModeData = requestV1.rawModeData[0];
|
||||
}
|
||||
|
||||
// set graphqlModeData if its not empty
|
||||
if (!_.isEmpty(requestV1.graphqlModeData)) {
|
||||
graphqlModeData = requestV1.graphqlModeData;
|
||||
}
|
||||
|
||||
// set data.mode.
|
||||
// if dataMode is not set, infer from data or rawModeData or graphqlModeData
|
||||
if (dataMode) {
|
||||
data.mode = dataMode;
|
||||
}
|
||||
// at this point we are sure that the body is not empty so let's
|
||||
// infer the data mode.
|
||||
// @note its possible that multiple body types are set e.g, both
|
||||
// rawModeData and graphqlModeData are set. So, the priority will be:
|
||||
// raw -> formdata -> graphql (aligned with pre-graphql behaviour).
|
||||
//
|
||||
// set `formdata` if rawModeData is not set and data is an array
|
||||
// `data` takes higher precedence over `rawModeData`.
|
||||
else if (!rawModeData && Array.isArray(requestV1.data || requestV1.rawModeData)) {
|
||||
data.mode = 'formdata';
|
||||
}
|
||||
// set `graphql` if graphqlModeData is set
|
||||
else if (!rawModeData && graphqlModeData) {
|
||||
data.mode = 'graphql';
|
||||
}
|
||||
// set `raw` mode as default
|
||||
else {
|
||||
data.mode = 'raw';
|
||||
}
|
||||
|
||||
if (data.mode === 'raw') {
|
||||
if (rawModeData) {
|
||||
data[data.mode] = rawModeData;
|
||||
}
|
||||
else if (_.isString(requestV1.data)) {
|
||||
data[data.mode] = requestV1.data;
|
||||
}
|
||||
else {
|
||||
// empty string instead of retainEmpty check to have parity with other modes.
|
||||
data[data.mode] = '';
|
||||
}
|
||||
}
|
||||
else if (data.mode === 'graphql') {
|
||||
data[data.mode] = graphqlModeData;
|
||||
}
|
||||
else if (data.mode === 'file') {
|
||||
// rawModeData can be string or undefined.
|
||||
data[data.mode] = { src: rawModeData };
|
||||
}
|
||||
else {
|
||||
// parse data for formdata or urlencoded data modes.
|
||||
// `rawModeData` is checked in case its of type `data`.
|
||||
data[data.mode] = parseFormData(requestV1.data || requestV1.rawModeData, retainEmpty);
|
||||
}
|
||||
|
||||
if (requestV1.dataOptions) {
|
||||
// Convert v1 mode to v2 mode
|
||||
for (mode in modes) {
|
||||
if (!_.isEmpty(requestV1.dataOptions[mode])) {
|
||||
bodyOptions[modes[mode]] = requestV1.dataOptions[mode];
|
||||
}
|
||||
}
|
||||
|
||||
!_.isEmpty(bodyOptions) && (data.options = bodyOptions);
|
||||
}
|
||||
|
||||
if (requestV1.dataDisabled) { data.disabled = true; }
|
||||
else if (retainEmpty) { data.disabled = false; }
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs a V2 "events" object from a V1 Postman Request
|
||||
*
|
||||
* @param {Object} entityV1 - The v1 entity to extract script information from.
|
||||
* @returns {Object[]|*}
|
||||
*/
|
||||
event: function (entityV1) {
|
||||
if (!entityV1) { return; }
|
||||
|
||||
const retainIds = this.options.retainIds;
|
||||
|
||||
// if prioritizeV2 is true, events is used as the source of truth
|
||||
if ((util.notLegacy(entityV1, 'event') || this.options.prioritizeV2) && !_.isEmpty(entityV1.events)) {
|
||||
// in v1, `events` is regarded as the source of truth if it exists, so handle that first and bail out.
|
||||
// @todo: Improve this to order prerequest events before test events
|
||||
_.forEach(entityV1.events, function (event) {
|
||||
!event.listen && (event.listen = 'test');
|
||||
|
||||
// just delete the event.id if retainIds is not set
|
||||
if (!retainIds && event.id) {
|
||||
delete event.id;
|
||||
}
|
||||
|
||||
if (event.script) {
|
||||
// just delete the script.id if retainIds is not set
|
||||
if (!retainIds && event.script.id) {
|
||||
delete event.script.id;
|
||||
}
|
||||
|
||||
!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 = [];
|
||||
|
||||
// @todo: Extract both flows below into a common method
|
||||
if (entityV1.tests) {
|
||||
events.push({
|
||||
listen: 'test',
|
||||
script: {
|
||||
type: 'text/javascript',
|
||||
exec: _.isString(entityV1.tests) ?
|
||||
entityV1.tests.split('\n') :
|
||||
entityV1.tests
|
||||
}
|
||||
});
|
||||
}
|
||||
if (entityV1.preRequestScript) {
|
||||
events.push({
|
||||
listen: 'prerequest',
|
||||
script: {
|
||||
type: 'text/javascript',
|
||||
exec: _.isString(entityV1.preRequestScript) ?
|
||||
entityV1.preRequestScript.split('\n') :
|
||||
entityV1.preRequestScript
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return events.length ? events : undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* A number of auth parameter names have changed from V1 to V2. This function calls the appropriate
|
||||
* mapper function, and creates the V2 auth parameter object.
|
||||
*
|
||||
* @param {Object} entityV1 - The v1 entity to derive auth information from.
|
||||
* @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 null.
|
||||
* @returns {{type: *}}
|
||||
*/
|
||||
auth: function (entityV1, options) {
|
||||
if (!entityV1) { return; }
|
||||
if ((util.notLegacy(entityV1, 'auth') || this.options.prioritizeV2) && entityV1.auth) {
|
||||
return util.authArrayToMap(entityV1, options);
|
||||
}
|
||||
if (!entityV1.currentHelper || (entityV1.currentHelper === null) || (entityV1.currentHelper === 'normal')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var params,
|
||||
type = v1Common.authMap[entityV1.currentHelper] || entityV1.currentHelper,
|
||||
auth = {
|
||||
type: type
|
||||
};
|
||||
|
||||
// Some legacy versions of the App export Helper Attributes as a string.
|
||||
if (_.isString(entityV1.helperAttributes)) {
|
||||
try {
|
||||
entityV1.helperAttributes = JSON.parse(entityV1.helperAttributes);
|
||||
}
|
||||
catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (entityV1.helperAttributes && util.authMappersFromLegacy[entityV1.currentHelper]) {
|
||||
params = util.authMappersFromLegacy[entityV1.currentHelper](entityV1.helperAttributes);
|
||||
}
|
||||
|
||||
params && (auth[type] = params);
|
||||
|
||||
return auth;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a V2 format request from a V1 Postman Collection Request
|
||||
*
|
||||
* @param {Object} requestV1 - The v1 request to be transformed.
|
||||
* @returns {Object} - The converted v2 request.
|
||||
*/
|
||||
request: function (requestV1) {
|
||||
var self = this,
|
||||
request = {},
|
||||
retainEmpty = self.options.retainEmptyValues,
|
||||
units = ['auth', 'method', 'header', 'body', 'url'];
|
||||
|
||||
units.forEach(function (unit) {
|
||||
request[unit] = self[unit](requestV1);
|
||||
});
|
||||
|
||||
if (requestV1.description) { request.description = requestV1.description; }
|
||||
else if (retainEmpty) { request.description = null; }
|
||||
|
||||
return request;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a V1 cookie to a V2 cookie.
|
||||
*
|
||||
* @param {Object} cookieV1 - The v1 cookie object to convert.
|
||||
* @returns {{expires: string, hostOnly: *, httpOnly: *, domain: *, path: *, secure: *, session: *, value: *}}
|
||||
*/
|
||||
cookie: function (cookieV1) {
|
||||
return {
|
||||
expires: (new Date(cookieV1.expirationDate * 1000)).toString(),
|
||||
hostOnly: cookieV1.hostOnly,
|
||||
httpOnly: cookieV1.httpOnly,
|
||||
domain: cookieV1.domain,
|
||||
path: cookieV1.path,
|
||||
secure: cookieV1.secure,
|
||||
session: cookieV1.session,
|
||||
value: cookieV1.value,
|
||||
key: cookieV1.name
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the saved request for the given response, and handles edge cases between Apps & Sync
|
||||
*
|
||||
* Handles a lot of edge cases, so the code is not very clean.
|
||||
*
|
||||
* The Flow followed here is:
|
||||
*
|
||||
* If responseV1.requestObject is present
|
||||
* If it is a string
|
||||
* Try parsing it as JSON
|
||||
* If parsed,
|
||||
* return it
|
||||
* else
|
||||
* It is a request ID
|
||||
* If responseV1.request is present
|
||||
* If it is a string
|
||||
* Try parsing it as JSON
|
||||
* If parsed,
|
||||
* return it
|
||||
* else
|
||||
* It is a request ID
|
||||
* Look up the collection for the request ID and return it, or return undefined.
|
||||
*
|
||||
* @param {Object} responseV1 - The v1 response to be converted.
|
||||
* @returns {Object} - The converted saved request, in v2 format.
|
||||
*/
|
||||
savedRequest: function (responseV1) {
|
||||
var self = this,
|
||||
associatedRequestId;
|
||||
|
||||
if (responseV1.requestObject) {
|
||||
if (_.isString(responseV1.requestObject)) {
|
||||
try {
|
||||
return JSON.parse(responseV1.requestObject);
|
||||
}
|
||||
catch (e) {
|
||||
// if there was an error parsing it as JSON, it's probably an ID, so store it in the ID variable
|
||||
associatedRequestId = responseV1.requestObject;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return responseV1.requestObject;
|
||||
}
|
||||
}
|
||||
|
||||
if (responseV1.request) {
|
||||
if (_.isString(responseV1.request)) {
|
||||
try {
|
||||
return JSON.parse(responseV1.request);
|
||||
}
|
||||
catch (e) {
|
||||
// if there was an error parsing it as JSON, it's probably an ID, so store it in the ID variable
|
||||
associatedRequestId = responseV1.request;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return responseV1.request;
|
||||
}
|
||||
}
|
||||
|
||||
// we have a request ID
|
||||
return associatedRequestId && _.get(self, ['cache', associatedRequestId]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Since a V2 response contains the entire associated request that was sent, creating the response means it
|
||||
* also must use the V1 request.
|
||||
*
|
||||
* @param {Object} responseV1 - The response object to convert from v1 to v2.
|
||||
* @returns {Object} - The v2 response object.
|
||||
*/
|
||||
singleResponse: function (responseV1) {
|
||||
var response = {},
|
||||
self = this,
|
||||
originalRequest;
|
||||
|
||||
originalRequest = self.savedRequest(responseV1);
|
||||
|
||||
// add ids to the v2 result only if both: the id and retainIds are truthy.
|
||||
// this prevents successive exports to v2 from being overwhelmed by id diffs
|
||||
self.options.retainIds && (response.id = responseV1.id || util.uid());
|
||||
|
||||
response.name = responseV1.name || 'response';
|
||||
response.originalRequest = originalRequest ? self.request(originalRequest) : undefined;
|
||||
response.status = responseV1.responseCode && responseV1.responseCode.name || undefined;
|
||||
response.code = responseV1.responseCode && Number(responseV1.responseCode.code) || undefined;
|
||||
response._postman_previewlanguage = responseV1.language;
|
||||
response._postman_previewtype = responseV1.previewType;
|
||||
response.header = responseV1.headers;
|
||||
response.cookie = _.map(responseV1.cookies, function (cookie) {
|
||||
return self.cookie(cookie);
|
||||
});
|
||||
response.responseTime = responseV1.time;
|
||||
response.body = responseV1.text;
|
||||
|
||||
return response;
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs an array of "sample" responses (compatible with a V2 collection)
|
||||
* from a Postman Collection V1 Request.
|
||||
*
|
||||
* If response ordering via `responses_order` field is present,
|
||||
* ensure the ordering is respected while constructing responses array.
|
||||
*
|
||||
* @param {Object} requestV1 - The v1 request object to extract response information from.
|
||||
* @returns {Object[]} - The list of v2 response definitions.
|
||||
*/
|
||||
response: function (requestV1) {
|
||||
var self = this,
|
||||
responses = _.get(requestV1, 'responses', []),
|
||||
responsesCache = _.keyBy(responses, 'id'),
|
||||
responses_order = _.get(requestV1, 'responses_order', []);
|
||||
|
||||
// If ordering of responses is not available
|
||||
// Create a default ordering using the `responses` field
|
||||
if (!(responses_order && responses_order.length)) {
|
||||
responses_order = _.map(responses, 'id');
|
||||
}
|
||||
|
||||
// Filter out any response id that is not available
|
||||
responses_order = _.filter(responses_order, function (responseId) {
|
||||
return _.has(responsesCache, responseId);
|
||||
});
|
||||
|
||||
return _.map(responses_order, function (responseId) {
|
||||
return self.singleResponse(responsesCache[responseId]);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a V2 compatible ``item`` from a V1 Postman Collection Request
|
||||
*
|
||||
* @param {Object} requestV1 - Postman collection V1 request.
|
||||
* @returns {Object} - The converted request object, in v2 format.
|
||||
*/
|
||||
singleItem: function (requestV1) {
|
||||
if (!requestV1) { return; }
|
||||
|
||||
var self = this,
|
||||
retainIds = self.options.retainIds,
|
||||
units = ['request', 'response'],
|
||||
variable = self.variable(requestV1, { retainIds: retainIds }),
|
||||
item = {
|
||||
name: requestV1.name || '', // Inline building to avoid additional function call
|
||||
event: self.event(requestV1)
|
||||
};
|
||||
|
||||
retainIds && (item.id = requestV1.id || util.uid());
|
||||
// add protocolProfileBehavior property from requestV1 to the item
|
||||
util.addProtocolProfileBehavior(requestV1, item);
|
||||
|
||||
units.forEach(function (unit) {
|
||||
item[unit] = self[unit](requestV1);
|
||||
});
|
||||
|
||||
variable && variable.length && (item.variable = variable);
|
||||
|
||||
return item;
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs an array of Items & ItemGroups compatible with the V2 format.
|
||||
*
|
||||
* @param {Object} collectionV1 - The v1 collection to derive folder information from.
|
||||
* @returns {Object[]} - The list of item group definitions.
|
||||
*/
|
||||
itemGroups: function (collectionV1) {
|
||||
var self = this,
|
||||
items = [],
|
||||
itemGroupCache = {},
|
||||
retainEmpty = self.options.retainEmptyValues;
|
||||
|
||||
// Read all folder data, and prep it so that we can throw subfolders in the right places
|
||||
itemGroupCache = _.reduce(collectionV1.folders, function (accumulator, folder) {
|
||||
if (!folder) { return accumulator; }
|
||||
|
||||
var retainIds = self.options.retainIds,
|
||||
auth = self.auth(folder),
|
||||
event = self.event(folder),
|
||||
variable = self.variable(folder, { retainIds: retainIds }),
|
||||
result = {
|
||||
name: folder.name,
|
||||
item: []
|
||||
};
|
||||
|
||||
retainIds && (result.id = folder.id || util.uid());
|
||||
|
||||
if (folder.description) { result.description = folder.description; }
|
||||
else if (retainEmpty) { result.description = null; }
|
||||
|
||||
(auth || (auth === null)) && (result.auth = auth);
|
||||
event && (result.event = event);
|
||||
variable && variable.length && (result.variable = variable);
|
||||
util.addProtocolProfileBehavior(folder, result);
|
||||
|
||||
accumulator[folder.id] = result;
|
||||
|
||||
return accumulator;
|
||||
}, {});
|
||||
|
||||
// Populate each ItemGroup with subfolders
|
||||
_.forEach(collectionV1.folders, function (folderV1) {
|
||||
if (!folderV1) { return; }
|
||||
|
||||
var itemGroup = itemGroupCache[folderV1.id],
|
||||
hasSubfolders = folderV1.folders_order && folderV1.folders_order.length,
|
||||
hasRequests = folderV1.order && folderV1.order.length;
|
||||
|
||||
// Add subfolders
|
||||
hasSubfolders && _.forEach(folderV1.folders_order, function (subFolderId) {
|
||||
if (!itemGroupCache[subFolderId]) {
|
||||
// todo: figure out what to do when a collection contains a subfolder ID,
|
||||
// but the subfolder is not actually there.
|
||||
return;
|
||||
}
|
||||
|
||||
itemGroupCache[subFolderId][IS_SUBFOLDER] = true;
|
||||
|
||||
itemGroup.item.push(itemGroupCache[subFolderId]);
|
||||
});
|
||||
|
||||
// Add items
|
||||
hasRequests && _.forEach(folderV1.order, function (requestId) {
|
||||
if (!self.cache[requestId]) {
|
||||
// todo: what do we do here??
|
||||
return;
|
||||
}
|
||||
|
||||
itemGroup.item.push(self.singleItem(self.cache[requestId]));
|
||||
});
|
||||
});
|
||||
|
||||
// This compromises some self-healing, which was originally present, but the performance cost of
|
||||
// doing self-healing the right way is high, so we directly rely on collectionV1.folders_order
|
||||
// The self-healing way would be to iterate over itemGroupCache directly, but preserving the right order
|
||||
// becomes a pain in that case.
|
||||
_.forEach(_.uniq(collectionV1.folders_order || _.map(collectionV1.folders, 'id')), function (folderId) {
|
||||
var itemGroup = itemGroupCache[folderId];
|
||||
|
||||
itemGroup && !_.get(itemGroup, IS_SUBFOLDER) && items.push(itemGroup);
|
||||
});
|
||||
|
||||
// This is useful later
|
||||
self.itemGroupCache = itemGroupCache;
|
||||
|
||||
return _.compact(items);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a V2 compatible array of items from a V1 Postman Collection
|
||||
*
|
||||
* @param {Object} collectionV1 - A Postman Collection object in the V1 format.
|
||||
* @returns {Object[]} - The list of item groups (folders) in v2 format.
|
||||
*/
|
||||
item: function (collectionV1) {
|
||||
var self = this,
|
||||
requestsCache = _.keyBy(collectionV1.requests, 'id'),
|
||||
allRequests = _.map(collectionV1.requests, 'id'),
|
||||
result;
|
||||
|
||||
self.cache = requestsCache;
|
||||
result = self.itemGroups(collectionV1);
|
||||
|
||||
_.forEach(_.intersection(collectionV1.order, allRequests), function (requestId) {
|
||||
var request = self.singleItem(requestsCache[requestId]);
|
||||
|
||||
request && (result.push(request));
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
input: '1.0.0',
|
||||
output: '2.0.0',
|
||||
Builders: Builders,
|
||||
|
||||
/**
|
||||
* Converts a single V1 request to a V2 item.
|
||||
*
|
||||
* @param {Object} request - The v1 request to convert to v2.
|
||||
* @param {Object} options - The set of options for v1 -> v2 conversion.
|
||||
* @param {Function} callback - The function to be invoked when the conversion has completed.
|
||||
*/
|
||||
convertSingle: function (request, options, callback) {
|
||||
var builders = new Builders(options),
|
||||
converted,
|
||||
err;
|
||||
|
||||
try {
|
||||
converted = builders.singleItem(_.cloneDeep(request));
|
||||
}
|
||||
catch (e) {
|
||||
err = e;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
return callback(err, converted);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
return converted;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a single V1 Response to a V2 Response.
|
||||
*
|
||||
* @param {Object} response - The v1 response to convert to v2.
|
||||
* @param {Object} options - The set of options for v1 -> v2 conversion.
|
||||
* @param {Function} callback - The function to be invoked when the conversion has completed.
|
||||
*/
|
||||
convertResponse: function (response, options, callback) {
|
||||
var builders = new Builders(options),
|
||||
converted,
|
||||
err;
|
||||
|
||||
try {
|
||||
converted = builders.singleResponse(_.cloneDeep(response));
|
||||
}
|
||||
catch (e) {
|
||||
err = e;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
return callback(err, converted);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
return converted;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a V1 collection to a V2 collection (performs ID replacement, etc as necessary).
|
||||
*
|
||||
* @param {Object} collection - The v1 collection to convert to v2.
|
||||
* @param {Object} options - The set of options for v1 -> v2 conversion.
|
||||
* @param {Function} callback - The function to be invoked when the conversion has completed.
|
||||
*/
|
||||
convert: function (collection, options, callback) {
|
||||
collection = _.cloneDeep(collection);
|
||||
|
||||
var auth,
|
||||
event,
|
||||
variable,
|
||||
newCollection = {},
|
||||
units = ['info', 'item'],
|
||||
builders = new Builders(options),
|
||||
authOptions = { excludeNoauth: true },
|
||||
varOpts = options && { fallback: options.env, retainIds: options.retainIds };
|
||||
|
||||
try {
|
||||
units.forEach(function (unit) {
|
||||
newCollection[unit] = builders[unit](collection);
|
||||
});
|
||||
|
||||
(auth = builders.auth(collection, authOptions)) && (newCollection.auth = auth);
|
||||
(event = builders.event(collection)) && (newCollection.event = event);
|
||||
(variable = builders.variable(collection, varOpts)) && (newCollection.variable = variable);
|
||||
util.addProtocolProfileBehavior(collection, newCollection);
|
||||
}
|
||||
catch (e) {
|
||||
if (callback) {
|
||||
return callback(e, null);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (callback) { return callback(null, newCollection); }
|
||||
|
||||
return newCollection;
|
||||
}
|
||||
};
|
157
node_modules/postman-collection-transformer/lib/converters/v1.0.0/converter-v1-to-v21.js
generated
vendored
Normal file
157
node_modules/postman-collection-transformer/lib/converters/v1.0.0/converter-v1-to-v21.js
generated
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
/* eslint-disable object-shorthand */
|
||||
|
||||
var inherits = require('inherits'),
|
||||
_ = require('lodash').noConflict(),
|
||||
|
||||
url = require('../../url'),
|
||||
util = require('../../util'),
|
||||
constants = require('../../constants'),
|
||||
BaseBuilders = require('./converter-v1-to-v2').Builders,
|
||||
|
||||
Builders;
|
||||
|
||||
inherits(Builders = function () {
|
||||
Builders.super_.apply(this, arguments);
|
||||
}, BaseBuilders);
|
||||
|
||||
_.assign(Builders.prototype, {
|
||||
|
||||
/**
|
||||
* Derives v2.1.0 collection info from a v1.0.0 collection object.
|
||||
*
|
||||
* @param {Object} collectionV1 - The v1.0.0 collection object to be converted to v2.1.0.
|
||||
* @return {Object} - The compiled v2.x collection info manifest.
|
||||
*/
|
||||
info: function (collectionV1) {
|
||||
var info = Builders.super_.prototype.info.call(this, collectionV1);
|
||||
|
||||
info.schema = constants.SCHEMA_V2_1_0_URL;
|
||||
|
||||
return info;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts collection request urls from v1.0.0 to v2.1.0
|
||||
*
|
||||
* @param {Object} requestV1 - The v1.0.0 request url to be converted to v2.1.0.
|
||||
* @return {Object} - The objectified v2.1.0 compliant URL.
|
||||
*/
|
||||
url: function (requestV1) {
|
||||
var v21Url = Builders.super_.prototype.url.call(this, requestV1);
|
||||
|
||||
return _.isString(v21Url) ? url.parse(v21Url) : v21Url;
|
||||
},
|
||||
|
||||
/**
|
||||
* A number of auth parameter names have changed from V1 to V2. This function calls the appropriate
|
||||
* mapper function, and creates the V2 auth parameter object.
|
||||
*
|
||||
* @param {Object} entityV1 - A Collection V1 compliant request instance.
|
||||
* @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 null.
|
||||
* @returns {{type: *}} - The v2.1.0 compliant request object
|
||||
*/
|
||||
auth: function (entityV1, options) {
|
||||
// if the current auth manifest is at a parent level, no further transformation is needed.
|
||||
// @todo: Possible dead code, prune when confirmed
|
||||
if (util.notLegacy(entityV1, 'auth') && entityV1.currentHelper) {
|
||||
return util.sanitizeAuthArray(entityV1, options);
|
||||
}
|
||||
|
||||
var auth = Builders.super_.prototype.auth.call(this, entityV1, options);
|
||||
|
||||
return util.authMapToArray({ auth: auth }, options);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
input: '1.0.0',
|
||||
output: '2.1.0',
|
||||
Builders: Builders,
|
||||
|
||||
/**
|
||||
* Converts a single V1 request to a v2.1.0 item.
|
||||
*
|
||||
* @param {Object} request - The v1.0.0 request to be converted to a v2.1.0 format.
|
||||
* @param {Object} options - The set of options for the current conversion sequence.
|
||||
* @param {?Function} callback - The function invoked to mark the end of the current conversion process.
|
||||
* @returns {*}
|
||||
*/
|
||||
convertSingle: function (request, options, callback) {
|
||||
var err,
|
||||
converted,
|
||||
builders = new Builders(options);
|
||||
|
||||
try { converted = builders.singleItem(_.cloneDeep(request)); }
|
||||
catch (e) { err = e; }
|
||||
|
||||
if (callback) { return callback(err, converted); }
|
||||
|
||||
if (err) { throw err; }
|
||||
|
||||
return converted;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a single V1 Response to a v2.1.0 Response.
|
||||
*
|
||||
* @param {Object} response - The V1 compliant response to convert to a v2.1.0 format.
|
||||
* @param {Object} options - The set of options for the current conversion process.
|
||||
* @param {?Function} callback - The function invoked to mark the completion of the response conversion.
|
||||
* @returns {*}
|
||||
*/
|
||||
convertResponse: function (response, options, callback) {
|
||||
var err,
|
||||
converted,
|
||||
builders = new Builders(options);
|
||||
|
||||
try { converted = builders.singleResponse(_.cloneDeep(response)); }
|
||||
catch (e) { err = e; }
|
||||
|
||||
if (callback) { return callback(err, converted); }
|
||||
|
||||
if (err) { throw err; }
|
||||
|
||||
return converted;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a V1 collection to a V2 collection (performs ID replacement, etc as necessary).
|
||||
*
|
||||
* @param {Object} collection - The V1 collection instance to convert to a v2.1.0 format.
|
||||
* @param {Object} options - The set of options for the current conversion sequence.
|
||||
* @param {?Function} callback - The function invoked to mark the completion of the conversion process/
|
||||
* @returns {*}
|
||||
*/
|
||||
convert: function (collection, options, callback) {
|
||||
collection = _.cloneDeep(collection);
|
||||
|
||||
var auth,
|
||||
event,
|
||||
variable,
|
||||
newCollection = {},
|
||||
units = ['info', 'item'],
|
||||
builders = new Builders(options),
|
||||
authOptions = { excludeNoauth: true },
|
||||
varOpts = options && { fallback: options.env, retainIds: options.retainIds };
|
||||
|
||||
try {
|
||||
units.forEach(function (unit) {
|
||||
newCollection[unit] = builders[unit](collection);
|
||||
});
|
||||
|
||||
(auth = builders.auth(collection, authOptions)) && (newCollection.auth = auth);
|
||||
(event = builders.event(collection)) && (newCollection.event = event);
|
||||
(variable = builders.variable(collection, varOpts)) && (newCollection.variable = variable);
|
||||
util.addProtocolProfileBehavior(collection, newCollection);
|
||||
}
|
||||
catch (e) {
|
||||
if (callback) { return callback(e); }
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (callback) { return callback(null, newCollection); }
|
||||
|
||||
return newCollection;
|
||||
}
|
||||
};
|
797
node_modules/postman-collection-transformer/lib/converters/v2.0.0/converter-v2-to-v1.js
generated
vendored
Normal file
797
node_modules/postman-collection-transformer/lib/converters/v2.0.0/converter-v2-to-v1.js
generated
vendored
Normal file
@@ -0,0 +1,797 @@
|
||||
/* eslint-disable object-shorthand */
|
||||
var _ = require('lodash').noConflict(),
|
||||
util = require('../../util'),
|
||||
|
||||
v2Common = require('../../common/v2'),
|
||||
|
||||
Builders = function (options) {
|
||||
this.options = options || {};
|
||||
};
|
||||
|
||||
_.assign(Builders.prototype, {
|
||||
|
||||
/**
|
||||
* Converts v2 style auth manifests into their v1 equivalents.
|
||||
*
|
||||
* @param {Object} entityV2 - The v1 auth manifest to be transformed into v1.
|
||||
* @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 null.
|
||||
*
|
||||
* @returns {Object} The transformed auth object.
|
||||
*/
|
||||
auth: function (entityV2, options) {
|
||||
return util.authMapToArray(entityV2, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs a V1 "events" object from a V2 Postman entity
|
||||
*
|
||||
* @param {Object} entityV2 - The v2 event object to be converted.
|
||||
* @returns {Object[]} - The resultant v1 script definition.
|
||||
*/
|
||||
events: function (entityV2) {
|
||||
// events is treated as the source of truth in v1, so handle that first and bail out.
|
||||
var source = entityV2.events || entityV2.event;
|
||||
|
||||
if (_.isArray(source)) {
|
||||
// @todo: Improve this to order prerequest events before test events
|
||||
_.forEach(source, 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 source;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
return util.handleVars(entity, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts all subfolders from a v2.0.0 collection or folder
|
||||
*
|
||||
* @param {Object} folderOrCollection - Thw entity to extract child items from.
|
||||
* @returns {Object[]} - The list of extracted folder items.
|
||||
*/
|
||||
extractFolderItems: function (folderOrCollection) {
|
||||
if (!folderOrCollection) { return; }
|
||||
|
||||
var i,
|
||||
self = this,
|
||||
folders = [],
|
||||
items = folderOrCollection.item || folderOrCollection.items;
|
||||
|
||||
!_.isArray(items) && (items = [items]);
|
||||
|
||||
for (i = 0; i < items.length; i++) {
|
||||
if (items[i] && (items[i].items || items[i].item)) {
|
||||
folders.push(items[i]);
|
||||
folders = [].concat(folders, self.extractFolderItems(items[i]));
|
||||
}
|
||||
}
|
||||
|
||||
return folders;
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts all requests from a v2.0.0 collection or folder
|
||||
*
|
||||
* @param {Object} folderOrCollection - The object to extract sub-items from.
|
||||
* @returns {Object[]} - The list of extracted folder items.
|
||||
*/
|
||||
extractItems: function (folderOrCollection) {
|
||||
if (!folderOrCollection) { return; }
|
||||
|
||||
var i,
|
||||
self = this,
|
||||
requests = [],
|
||||
isFolder,
|
||||
items = folderOrCollection.item || folderOrCollection.items;
|
||||
|
||||
!_.isArray(items) && (items = [items]);
|
||||
for (i = 0; i < items.length; i++) {
|
||||
isFolder = items[i] && (items[i].items || items[i].item);
|
||||
if (items[i]) {
|
||||
isFolder ? (requests = [].concat(requests, self.extractItems(items[i]))) : requests.push(items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return requests;
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs a monolithic raw HTTP header block from a V2 header array
|
||||
*
|
||||
* @param {Object} item - The wrapper object to extract headers from.
|
||||
* @returns {*|string} - The resultant header string.
|
||||
*/
|
||||
headers: function (item) {
|
||||
if (!(item && item.request)) { return; }
|
||||
|
||||
return _.map(item.request.headers || item.request.header, function (header) {
|
||||
return (header.disabled ? '// ' : '') + header.key + ': ' + header.value;
|
||||
}).join('\n');
|
||||
},
|
||||
|
||||
/**
|
||||
* Detects the data mode from a given Postman Collection V2 item
|
||||
*
|
||||
* @param {Object} item - .
|
||||
* @returns {*|number|string}
|
||||
*/
|
||||
dataMode: function (item) {
|
||||
return v2Common.modeMap[_.get(item, 'request.body.mode')];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the appropriate request data based on the data mode.
|
||||
*
|
||||
* @param {Object} item - The .
|
||||
* @returns {Object} - The converted request body.
|
||||
*/
|
||||
data: function (item) {
|
||||
var self = this,
|
||||
mode = _.get(item, 'request.body.mode'),
|
||||
retainEmpty = this.options.retainEmptyValues;
|
||||
|
||||
if (mode === 'raw' || mode === 'file' || mode === 'graphql' || !mode) {
|
||||
return retainEmpty ? null : undefined;
|
||||
}
|
||||
|
||||
return _.map(item.request.body[mode], function (elem) {
|
||||
// Only update the value in v1 if src in v2 is non-empty
|
||||
if (elem && elem.type === 'file' && _.has(elem, 'src')) {
|
||||
elem.value = (_.isString(elem.src) || _.isArray(elem.src)) ? elem.src : null;
|
||||
delete elem.src;
|
||||
}
|
||||
|
||||
// Prevents empty request body descriptions from showing up in the result, keeps collections clean.
|
||||
elem.description = self.description(elem.description);
|
||||
_.has(elem, 'disabled') && (elem.enabled = !elem.disabled);
|
||||
|
||||
delete elem.disabled;
|
||||
|
||||
return elem;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* In case of raw request bodies, this constructs the proper raw data from a V2 item.
|
||||
*
|
||||
* @param {Object} item - The v2 request to derive body information from.
|
||||
* @returns {String} - The inferred v1 request body mode.
|
||||
*/
|
||||
rawModeData: function (item) {
|
||||
var mode = _.get(item, 'request.body.mode');
|
||||
|
||||
if (mode === 'raw') {
|
||||
return item.request.body.raw;
|
||||
}
|
||||
else if (mode === 'file') {
|
||||
return _.get(item.request.body, 'file.src');
|
||||
}
|
||||
|
||||
return this.options.retainEmptyValues ? null : undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns GraphQL data if mode is set to graphql.
|
||||
*
|
||||
* @param {Object} item - The v2 request to derive information form.
|
||||
* @returns {Object} - GraphQL request body.
|
||||
*/
|
||||
graphqlModeData: function (item) {
|
||||
var mode = _.get(item, 'request.body.mode');
|
||||
|
||||
if (mode === 'graphql') {
|
||||
return item.request.body.graphql;
|
||||
}
|
||||
|
||||
return this.options.retainEmptyValues ? null : undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates options for body from v2 format.
|
||||
*
|
||||
* @param {Object} item - The v2 request to derive information form.
|
||||
* @returns {Object} - The converted body options.
|
||||
*/
|
||||
dataOptions: function (item) {
|
||||
var options = _.get(item, 'request.body.options'),
|
||||
bodyOptions = {},
|
||||
mode;
|
||||
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert v2 mode to v1 mode
|
||||
for (mode in v2Common.modeMap) {
|
||||
if (!_.isEmpty(options[mode])) {
|
||||
bodyOptions[v2Common.modeMap[mode]] = options[mode];
|
||||
}
|
||||
}
|
||||
|
||||
return _.isEmpty(bodyOptions) ? undefined : bodyOptions;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates an object of path-variables and their values from a V2 item
|
||||
*
|
||||
* @param {Object} item - The wrapper object containing path variable information.
|
||||
* @returns {Object} - The resultant hash of path variables.
|
||||
*/
|
||||
pathVariables: function (item) {
|
||||
var variable = _.get(item, 'request.url.variables') || _.get(item, 'request.url.variable');
|
||||
|
||||
if (!variable) { return; }
|
||||
|
||||
return _.transform(variable, function (accumulator, v) {
|
||||
accumulator[v.key || v.id] = v.value; // v2.0.0 supports both key and id, v2.1.0 will drop id support
|
||||
}, {});
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a V1 URL from a V2 item
|
||||
*
|
||||
* @param {Object} item - The v2 request to extract the URL from.
|
||||
* @returns {String} - The extracted URL of the request.
|
||||
*/
|
||||
url: function (item) {
|
||||
var url = _.get(item, 'request.url');
|
||||
|
||||
if (_.isString(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (!url) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return util.urlunparse(url);
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts test from a V2 collection
|
||||
*
|
||||
* @param {Object} item - The wrapper object to extract test code from.
|
||||
* @returns {String} - The resultant test script code.
|
||||
*/
|
||||
tests: function (item) {
|
||||
var allEvents = item.events || item.event,
|
||||
events;
|
||||
|
||||
// Nothing to do if the item has no associated events
|
||||
if (!allEvents) {
|
||||
return;
|
||||
}
|
||||
|
||||
events = _.filter(allEvents, { listen: 'test' });
|
||||
|
||||
return _.map(events, function (event) {
|
||||
var tests = _.get(event, 'script.exec');
|
||||
|
||||
// @todo: Possible dead code, remove when confirmed
|
||||
if (_.isArray(tests)) {
|
||||
tests = tests.join('\n');
|
||||
}
|
||||
|
||||
return tests;
|
||||
}).join('\n');
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts the pre-request script from an Item
|
||||
*
|
||||
* @param {Object} item - The wrapper object to extract pre-request code from.
|
||||
* @returns {String} - The resultant pre-request script code.
|
||||
*/
|
||||
preRequestScript: function (item) {
|
||||
var allEvents = item.events || item.event,
|
||||
events;
|
||||
|
||||
// Nothing to do if the item has no associated events
|
||||
if (!allEvents) {
|
||||
return;
|
||||
}
|
||||
|
||||
events = _.filter(allEvents, { listen: 'prerequest' });
|
||||
|
||||
return _.map(events, function (event) {
|
||||
var tests = _.get(event, 'script.exec');
|
||||
|
||||
// @todo: Possible dead code, remove when confirmed
|
||||
if (_.isArray(tests)) {
|
||||
tests = tests.join('\n');
|
||||
}
|
||||
|
||||
return tests;
|
||||
}).join('\n');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a V2 cookie to a V1 cookie.
|
||||
*
|
||||
* @param {Object} cookieV2 - The v2 cookie object to be converted.
|
||||
* @returns {{expirationDate: *, hostOnly: *, httpOnly: *,
|
||||
* domain: (any), path: (any), secure: *, session: *, value: *, name: *}}
|
||||
*/
|
||||
cookie: function (cookieV2) {
|
||||
return {
|
||||
expirationDate: cookieV2.expires,
|
||||
hostOnly: cookieV2.hostOnly,
|
||||
httpOnly: cookieV2.httpOnly,
|
||||
domain: cookieV2.domain,
|
||||
path: cookieV2.path,
|
||||
secure: cookieV2.secure,
|
||||
session: cookieV2.session,
|
||||
value: cookieV2.value,
|
||||
name: cookieV2.key || cookieV2.name
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a V2 response object to a V1 response
|
||||
*
|
||||
* @param {Object} responseV2 - The v2 response to be converted.
|
||||
* @returns {Object} - The converted v1 response.
|
||||
*/
|
||||
response: function (responseV2) {
|
||||
var self = this,
|
||||
response = {},
|
||||
id = responseV2.id || responseV2._postman_id,
|
||||
originalRequest = responseV2.originalRequest || responseV2.request;
|
||||
|
||||
// the true in the next line ensures that we don't recursively go on processing responses in a request.
|
||||
response.request = originalRequest ? self.request({ request: originalRequest }, undefined, true) : undefined;
|
||||
|
||||
// add the requestObject to the response (needed by sync)
|
||||
try {
|
||||
response.request && (response.requestObject = JSON.stringify(response.request));
|
||||
}
|
||||
catch (e) { /* It's fine, not a fatal error, just move on. */ }
|
||||
|
||||
// do not attempt to regenerate response id here when `retainIds` is set to false
|
||||
// if id is changed here the parent's `responses_order` also needs to be changed
|
||||
// that can't be done yet
|
||||
response.id = id || util.uid();
|
||||
response.name = responseV2.name;
|
||||
response.status = responseV2.status;
|
||||
response.responseCode = {
|
||||
code: responseV2.code,
|
||||
name: responseV2.status,
|
||||
// TODO: get a list of descriptions
|
||||
detail: ''
|
||||
};
|
||||
response.language = responseV2._postman_previewlanguage || 'Text';
|
||||
response.previewType = responseV2._postman_previewtype || 'html';
|
||||
response.time = responseV2.responseTime;
|
||||
response.headers = responseV2.headers || responseV2.header;
|
||||
response.cookies = _.map(responseV2.cookies || responseV2.cookie, self.cookie);
|
||||
response.text = responseV2.body;
|
||||
response.rawDataType = 'text';
|
||||
|
||||
return response;
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts the array of responses from a V2 Item.
|
||||
*
|
||||
* @param {Object} item - The v2 item to extract saved responses from.
|
||||
* @returns {Object[]} - The list of saved response objects for the current request.
|
||||
*/
|
||||
responses: function (item) {
|
||||
var self = this,
|
||||
allResponses = item.responses || item.response;
|
||||
|
||||
if (!allResponses) { return; }
|
||||
|
||||
return _.map(allResponses, function (response) {
|
||||
return self.response(response, item);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates an ordering field for responses of a V2 Item.
|
||||
*
|
||||
* @param {Object} item - The v2 item to extract saved responses from.
|
||||
* @returns {Object[]} - The order of responses within the V2 Item.
|
||||
*/
|
||||
responses_order: function (item) {
|
||||
var allResponses = item.responses || item.response;
|
||||
|
||||
if (!allResponses) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return _.map(allResponses, 'id');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a V2 request to a V1 request.
|
||||
*
|
||||
* @param {Object} item - The v2 item to be converted.
|
||||
* @param {Object} collectionId - The collection id related to the current conversion routine.
|
||||
* @param {Boolean} [skipResponses=false] - When set to true, excludes saved responses from the result.
|
||||
* @returns {{id: *, name: *, description: (*|string|builders.description), url: *, collectionId: *, method: *,
|
||||
* currentHelper: *, helperAttributes: *}|*}
|
||||
*/
|
||||
request: function (item, collectionId, skipResponses) {
|
||||
if (!item) { return; }
|
||||
|
||||
var units = ['headers', 'dataMode', 'data', 'rawModeData', 'graphqlModeData',
|
||||
'pathVariables', 'tests', 'preRequestScript', 'url', 'dataOptions'],
|
||||
self = this,
|
||||
request,
|
||||
description,
|
||||
currentHelper,
|
||||
helperAttributes,
|
||||
req = item && item.request,
|
||||
v2Auth = req && req.auth,
|
||||
auth = self.auth(req),
|
||||
events = self.events(item),
|
||||
variables = self.variables(item, { retainIds: self.options.retainIds }),
|
||||
url = req && req.url,
|
||||
retainEmpty = self.options.retainEmptyValues,
|
||||
urlObj = _.isString(url) ? util.urlparse(url) : url;
|
||||
|
||||
if (!skipResponses) {
|
||||
units.push('responses');
|
||||
units.push('responses_order');
|
||||
}
|
||||
|
||||
if (v2Auth && v2Auth.type) {
|
||||
// @todo: Add support for custom auth helpers
|
||||
currentHelper = v2Common.authMap[v2Auth.type];
|
||||
if (util.authMappersFromCurrent[currentHelper]) {
|
||||
_.isArray(v2Auth[v2Auth.type]) && (v2Auth = util.authArrayToMap(req));
|
||||
helperAttributes = util.authMappersFromCurrent[currentHelper](v2Auth[v2Auth.type]);
|
||||
}
|
||||
else {
|
||||
helperAttributes = null;
|
||||
}
|
||||
}
|
||||
else if (v2Auth === null) {
|
||||
currentHelper = null;
|
||||
helperAttributes = null;
|
||||
}
|
||||
|
||||
request = {
|
||||
|
||||
// do not attempt to regenerate request id here when `retainIds` is set to false
|
||||
// if id is changed here the parent's `order` also needs to be changed
|
||||
// that can't be done yet
|
||||
id: item.id || item._postman_id || util.uid(),
|
||||
name: item.name,
|
||||
collectionId: collectionId,
|
||||
method: item.request ? item.request.method : undefined,
|
||||
currentHelper: currentHelper,
|
||||
helperAttributes: helperAttributes
|
||||
};
|
||||
|
||||
// add protocolProfileBehavior property from item to the request
|
||||
util.addProtocolProfileBehavior(item, request);
|
||||
|
||||
// only include the dataDisabled flag if truthy
|
||||
if (req && req.body && _.has(req.body, 'disabled') && (req.body.disabled || retainEmpty)) {
|
||||
request.dataDisabled = Boolean(req.body.disabled);
|
||||
}
|
||||
|
||||
description = item.request && self.description(item.request.description);
|
||||
|
||||
// Prevent empty request descriptions from showing up in the converted result, keeps collections clean.
|
||||
if (description) { request.description = description; }
|
||||
else if (retainEmpty) { request.description = null; }
|
||||
|
||||
(auth || (auth === null)) && (request.auth = auth);
|
||||
events && events.length && (request.events = events);
|
||||
variables && variables.length && (request.variables = variables);
|
||||
|
||||
_.forEach(units, function (unit) {
|
||||
request[unit] = self[unit](item);
|
||||
});
|
||||
|
||||
// description transformations for v2 to v1
|
||||
urlObj && (request.pathVariableData = _.map(urlObj.variables || urlObj.variable, function (v) {
|
||||
var result = { key: v.key || v.id, value: v.value };
|
||||
|
||||
// Prevent empty path variable descriptions from showing up in converted results, keeps collections clean.
|
||||
if (v.description) { result.description = self.description(v.description); }
|
||||
else if (retainEmpty) { result.description = null; }
|
||||
|
||||
return result;
|
||||
}));
|
||||
|
||||
urlObj && (request.queryParams = _.map(urlObj.query, function (queryParam) {
|
||||
// Prevents empty query param descriptions from showing up in the result, keeps collections clean.
|
||||
queryParam.description = self.description(queryParam.description);
|
||||
|
||||
_.has(queryParam, 'disabled') && (queryParam.enabled = !queryParam.disabled);
|
||||
delete queryParam.disabled;
|
||||
|
||||
return queryParam;
|
||||
}));
|
||||
|
||||
// item truthiness is already validated by this point
|
||||
request.headerData = _.map(item.request && (item.request.headers || item.request.header), function (header) {
|
||||
// Prevents empty query param descriptions from showing up in the result, keeps collections clean.
|
||||
header.description = self.description(header.description);
|
||||
|
||||
_.has(header, 'disabled') && (header.enabled = !header.disabled);
|
||||
delete header.disabled;
|
||||
|
||||
return header;
|
||||
});
|
||||
|
||||
return request;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a V1 compatible array of requests from a Postman V2 collection.
|
||||
*
|
||||
* @param {Object} collectionV2 - The v2 collection to derive v1 requests from.
|
||||
* @returns {Object[]} - The list of v1 request objects.
|
||||
*/
|
||||
requests: function (collectionV2) {
|
||||
var self = this,
|
||||
requests = [],
|
||||
info = collectionV2 && collectionV2.info,
|
||||
id = info && (info.id || info._postman_id) || collectionV2.id;
|
||||
|
||||
_.forEach(self.extractItems(collectionV2), function (item) {
|
||||
var requestV1 = self.request(item, id);
|
||||
|
||||
requests.push(requestV1);
|
||||
});
|
||||
|
||||
return requests;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a V1 compatible array of solo requestIds from a Postman collection V2
|
||||
*
|
||||
* @param {Object} collectionV2 - The v2 collection to be used for request order derivation.
|
||||
* @returns {Object[]} - The request order for the resultant v1 collection.
|
||||
*/
|
||||
order: function (collectionV2) {
|
||||
var itemArray = collectionV2.items || collectionV2.item,
|
||||
allItems = _.isArray(itemArray) ? itemArray : [itemArray];
|
||||
|
||||
// eslint-disable-next-line lodash/prefer-compact
|
||||
return _.filter(_.map(allItems, function (item) {
|
||||
if (!item) { return; }
|
||||
|
||||
var isFolder = (item.items || item.item);
|
||||
|
||||
if (!isFolder) {
|
||||
return item.id || item._postman_id;
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a V1 compatible array of folder orders from a Postman collection V2
|
||||
*
|
||||
* @param {Object} folderOrCollection - The object to derive folder order details from.
|
||||
* @returns {Object[]} - The list of folder ids that indicate the order.
|
||||
*/
|
||||
folders_order: function (folderOrCollection) {
|
||||
var itemArray = folderOrCollection.items || folderOrCollection.item,
|
||||
allItems = _.isArray(itemArray) ? itemArray : [itemArray];
|
||||
|
||||
// eslint-disable-next-line lodash/prefer-compact
|
||||
return _.filter(_.map(allItems, function (item) {
|
||||
if (!item) { return; }
|
||||
|
||||
var isFolder = (item.items || item.item);
|
||||
|
||||
if (isFolder) {
|
||||
return item.id || item._postman_id;
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates an array of V1 compatible folders from a V2 collection
|
||||
*
|
||||
* @param {Object} collectionV2 - The v2 collection to derive folder structure information from.
|
||||
* @returns {Object[]} - The list of folder definitions.
|
||||
*/
|
||||
folders: function (collectionV2) {
|
||||
var self = this,
|
||||
retainEmpty = self.options.retainEmptyValues;
|
||||
|
||||
return _.map(self.extractFolderItems(collectionV2), function (folder) {
|
||||
if (!folder) { return; }
|
||||
|
||||
var folderItems = folder.items || folder.item,
|
||||
description = self.description(folder.description),
|
||||
auth = self.auth(folder),
|
||||
events = self.events(folder),
|
||||
variables = self.variables(folder, { retainIds: self.options.retainIds }),
|
||||
|
||||
result = {
|
||||
|
||||
// do not attempt to regenerate folder id here when `retainIds` is set to false
|
||||
// if id is changed here the parent's `folder_order` also needs to be changed
|
||||
// that can't be done yet
|
||||
id: folder.id || folder._postman_id || util.uid(),
|
||||
name: folder.name,
|
||||
// eslint-disable-next-line lodash/prefer-compact
|
||||
order: _.filter(_.map(folderItems, function (f) {
|
||||
if (!f) { return; }
|
||||
|
||||
var isFolder = (f.items || f.item);
|
||||
|
||||
return !isFolder && (f.id || f._postman_id);
|
||||
})),
|
||||
folders_order: self.folders_order(folder)
|
||||
};
|
||||
|
||||
((auth && auth.type) || (auth === null)) && (result.auth = auth);
|
||||
events && events.length && (result.events = events);
|
||||
variables && variables.length && (result.variables = variables);
|
||||
util.addProtocolProfileBehavior(folder, result);
|
||||
|
||||
// Prevent empty folder descriptions from showing up in the result, keeps collections clean.
|
||||
if (description) { result.description = description; }
|
||||
else if (retainEmpty) { result.description = null; }
|
||||
|
||||
return result;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates the v1.0.0 compatible description string from the v2.0.0 description format.
|
||||
*
|
||||
* @param {Object} descriptionV2 - The v2 style description to be converted
|
||||
*
|
||||
* @returns {String} - The resultant v1 description.
|
||||
*/
|
||||
description: function (descriptionV2) {
|
||||
var description,
|
||||
retainEmpty = this.options.retainEmptyValues;
|
||||
|
||||
description = _.isObject(descriptionV2) ? descriptionV2.content : descriptionV2;
|
||||
|
||||
if (description) { return description; }
|
||||
else if (retainEmpty) { return null; }
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
input: '2.0.0',
|
||||
output: '1.0.0',
|
||||
Builders: Builders,
|
||||
|
||||
/**
|
||||
* Converts a single V2 item to a V1 request.
|
||||
*
|
||||
* @param {Object} request - The request to be converted.
|
||||
* @param {Object} options - The set of options for request conversion.
|
||||
* @param {Function} callback - The function to be invoked after conversion has completed.
|
||||
*/
|
||||
convertSingle: function (request, options, callback) {
|
||||
var builders = new Builders(options),
|
||||
clone = _.cloneDeep(request),
|
||||
converted,
|
||||
err;
|
||||
|
||||
try {
|
||||
clone = v2Common.populateIds(clone);
|
||||
converted = builders.request(clone);
|
||||
}
|
||||
catch (e) {
|
||||
err = e;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
return callback(err, converted);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
return converted;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a single V2 item to a V1 request.
|
||||
*
|
||||
* @param {Object} response - The response to be converted.
|
||||
* @param {Object} options - The set of options for request conversion.
|
||||
* @param {Function} callback - The function to be invoked after conversion has completed.
|
||||
*/
|
||||
convertResponse: function (response, options, callback) {
|
||||
var builders = new Builders(options),
|
||||
converted,
|
||||
err;
|
||||
|
||||
try {
|
||||
converted = builders.response(_.cloneDeep(response));
|
||||
}
|
||||
catch (e) {
|
||||
err = e;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
return callback(err, converted);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
return converted;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a V2 collection to a V1 collection (performs ID replacement, etc as necessary).
|
||||
*
|
||||
* @param {Object} collection - The collection to be converted.
|
||||
* @param {Object} options - The set of options for request conversion.
|
||||
* @param {Function} callback - The function to be invoked after conversion has completed.
|
||||
*/
|
||||
convert: function (collection, options, callback) {
|
||||
collection = _.cloneDeep(collection);
|
||||
|
||||
var auth,
|
||||
events,
|
||||
variables,
|
||||
builders = new Builders(options),
|
||||
authOptions = { excludeNoauth: true },
|
||||
varOpts = options && { fallback: options.env, retainIds: options.retainIds },
|
||||
units = ['order', 'folders_order', 'folders', 'requests'],
|
||||
id = _.get(collection, 'info._postman_id') || _.get(collection, 'info.id'),
|
||||
info = collection && collection.info,
|
||||
newCollection = {
|
||||
id: id && options && options.retainIds ? id : util.uid(),
|
||||
name: info && info.name
|
||||
};
|
||||
|
||||
// ensure that each item has an ID
|
||||
collection = v2Common.populateIds(collection);
|
||||
try {
|
||||
// eslint-disable-next-line max-len
|
||||
newCollection.description = builders.description(info && info.description);
|
||||
(auth = builders.auth(collection, authOptions)) && (newCollection.auth = auth);
|
||||
(events = builders.events(collection)) && (newCollection.events = events);
|
||||
(variables = builders.variables(collection, varOpts)) && (newCollection.variables = variables);
|
||||
util.addProtocolProfileBehavior(collection, newCollection);
|
||||
|
||||
units.forEach(function (unit) {
|
||||
newCollection[unit] = builders[unit](collection);
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
if (callback) {
|
||||
return callback(e, null);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
return callback(null, newCollection);
|
||||
}
|
||||
|
||||
return newCollection;
|
||||
}
|
||||
};
|
129
node_modules/postman-collection-transformer/lib/converters/v2.1.0/converter-v21-to-v1.js
generated
vendored
Normal file
129
node_modules/postman-collection-transformer/lib/converters/v2.1.0/converter-v21-to-v1.js
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
/* eslint-disable object-shorthand */
|
||||
var _ = require('lodash').noConflict(),
|
||||
util = require('../../util'),
|
||||
inherits = require('inherits'),
|
||||
|
||||
v2Common = require('../../common/v2'),
|
||||
BaseBuilders = require('../v2.0.0/converter-v2-to-v1').Builders,
|
||||
|
||||
Builders;
|
||||
|
||||
inherits(Builders = function () {
|
||||
Builders.super_.apply(this, arguments);
|
||||
}, BaseBuilders);
|
||||
|
||||
_.assign(Builders.prototype, {
|
||||
/**
|
||||
* Converts arrays of v2.1 style auth params to their v1.0.0 equivalent objects.
|
||||
*
|
||||
* @param {Object} entity - A v2.1 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 null.
|
||||
* @returns {Object} - A v1 compliant set of auth helper attributes.
|
||||
*/
|
||||
auth: function (entity, options) {
|
||||
return util.sanitizeAuthArray(entity, options);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
input: '2.1.0',
|
||||
output: '1.0.0',
|
||||
Builders: Builders,
|
||||
|
||||
/**
|
||||
* Converts a single V2 item to a V1 request.
|
||||
*
|
||||
* @param {Object} request - The request to be converted.
|
||||
* @param {Object} options - The set of options for request conversion.
|
||||
* @param {Function} callback - The function to be invoked after conversion has completed.
|
||||
*/
|
||||
convertSingle: function (request, options, callback) {
|
||||
var err,
|
||||
converted,
|
||||
clone = _.cloneDeep(request),
|
||||
builders = new Builders(options);
|
||||
|
||||
try {
|
||||
clone = v2Common.populateIds(clone);
|
||||
converted = builders.request(clone);
|
||||
}
|
||||
catch (e) { err = e; }
|
||||
|
||||
if (callback) { return callback(err, converted); }
|
||||
|
||||
if (err) { throw err; }
|
||||
|
||||
return converted;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a single V2 item to a V1 request.
|
||||
*
|
||||
* @param {Object} response - The response to be converted.
|
||||
* @param {Object} options - The set of options for request conversion.
|
||||
* @param {Function} callback - The function to be invoked after conversion has completed.
|
||||
*/
|
||||
convertResponse: function (response, options, callback) {
|
||||
var builders = new Builders(options),
|
||||
converted,
|
||||
err;
|
||||
|
||||
try { converted = builders.response(_.cloneDeep(response)); }
|
||||
catch (e) { err = e; }
|
||||
|
||||
if (callback) { return callback(err, converted); }
|
||||
|
||||
if (err) { throw err; }
|
||||
|
||||
return converted;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a V2 collection to a V1 collection (performs ID replacement, etc as necessary).
|
||||
*
|
||||
* @param {Object} collection - The collection to be converted.
|
||||
* @param {Object} options - The set of options for request conversion.
|
||||
* @param {Function} callback - The function to be invoked after conversion has completed.
|
||||
*/
|
||||
convert: function (collection, options, callback) {
|
||||
collection = _.cloneDeep(collection);
|
||||
|
||||
var auth,
|
||||
events,
|
||||
variables,
|
||||
builders = new Builders(options),
|
||||
authOptions = { excludeNoauth: true },
|
||||
units = ['order', 'folders_order', 'folders', 'requests'],
|
||||
varOpts = options && { fallback: options.env, retainIds: options.retainIds },
|
||||
id = _.get(collection, 'info._postman_id') || _.get(collection, 'info.id'),
|
||||
info = collection && collection.info,
|
||||
newCollection = {
|
||||
id: id && options && options.retainIds ? id : util.uid(),
|
||||
name: info && info.name
|
||||
};
|
||||
|
||||
// ensure that each item has an id
|
||||
collection = v2Common.populateIds(collection);
|
||||
try {
|
||||
// eslint-disable-next-line max-len
|
||||
newCollection.description = builders.description(info && info.description);
|
||||
(auth = builders.auth(collection, authOptions)) && (newCollection.auth = auth);
|
||||
(events = builders.events(collection)) && (newCollection.events = events);
|
||||
(variables = builders.variables(collection, varOpts)) && (newCollection.variables = variables);
|
||||
util.addProtocolProfileBehavior(collection, newCollection);
|
||||
|
||||
units.forEach(function (unit) {
|
||||
newCollection[unit] = builders[unit](collection);
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
if (callback) { return callback(e, null); }
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (callback) { return callback(null, newCollection); }
|
||||
|
||||
return newCollection;
|
||||
}
|
||||
};
|
97
node_modules/postman-collection-transformer/lib/index.js
generated
vendored
Normal file
97
node_modules/postman-collection-transformer/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
var semver = require('semver'),
|
||||
|
||||
util = require('./util'),
|
||||
converter = require('./converters'),
|
||||
normalizers = require('./normalizers');
|
||||
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* Converts a Collection between different versions, based on the given input.
|
||||
*
|
||||
* @param {Object} collection - The collection object to be converted.
|
||||
* @param {Object} options - The set of conversion options.
|
||||
* @param {String} options.outputVersion - The version to convert to.
|
||||
* @param {String} options.inputVersion - The version to convert from.
|
||||
* @param {Function} callback - The function invoked to mark the completion of the conversion process.
|
||||
*/
|
||||
convert: function (collection, options, callback) {
|
||||
if (!options.outputVersion || !semver.valid(options.outputVersion, true)) {
|
||||
return callback(new Error('Output version not specified or invalid: ' + options.outputVersion));
|
||||
}
|
||||
if (!options.inputVersion || !semver.valid(options.inputVersion, true)) {
|
||||
return callback(new Error('Input version not specified or invalid: ' + options.inputVersion));
|
||||
}
|
||||
|
||||
return converter.convert(collection, options, callback);
|
||||
},
|
||||
|
||||
normalize: normalizers.normalize,
|
||||
normalizeSingle: normalizers.normalizeSingle,
|
||||
normalizeResponse: normalizers.normalizeResponse,
|
||||
|
||||
/**
|
||||
* Export the utilities
|
||||
*/
|
||||
util: util,
|
||||
|
||||
/**
|
||||
* Checks whether the given object is a v1 collection
|
||||
*
|
||||
* @param {Object} object - The Object to check for v1 collection compliance.
|
||||
* @returns {Boolean} - A boolean result indicating whether or not the passed object was a v1 collection.
|
||||
*/
|
||||
isv1: function (object) {
|
||||
return Boolean(object && object.name && object.order && object.requests);
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether the given object is a v2 collection
|
||||
*
|
||||
* @param {Object} object - The Object to check for v2 collection compliance.
|
||||
* @returns {Boolean} - A boolean result indicating whether or not the passed object was a v2 collection.
|
||||
*/
|
||||
isv2: function (object) {
|
||||
return Boolean(object && object.info && object.info.schema);
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a single V1 request to a V2 Item, or a V2 item to a single V1 request.
|
||||
*
|
||||
* @param {Object} object - A V1 request or a V2 item.
|
||||
* @param {Object} options - The set of options for response conversion.
|
||||
* @param {String} options.outputVersion - The version to convert to.
|
||||
* @param {String} options.inputVersion - The version to convert from.
|
||||
* @param {Function} callback - The function invoked to mark the completion of the conversion process.
|
||||
*/
|
||||
convertSingle: function (object, options, callback) {
|
||||
if (!options.outputVersion || !semver.valid(options.outputVersion, true)) {
|
||||
return callback(new Error('Output version not specified or invalid: ' + options.outputVersion));
|
||||
}
|
||||
if (!options.inputVersion || !semver.valid(options.inputVersion, true)) {
|
||||
return callback(new Error('Input version not specified or invalid: ' + options.inputVersion));
|
||||
}
|
||||
|
||||
return converter.convertSingle(object, options, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a single V1 request to a V2 Item, or a V2 item to a single V1 request.
|
||||
*
|
||||
* @param {Object} object - A V1 request or a V2 item.
|
||||
* @param {Object} options - The set of options for response conversion.
|
||||
* @param {String} options.outputVersion - The version to convert to.
|
||||
* @param {String} options.inputVersion - The version to convert from.
|
||||
* @param {Function} callback - The function invoked to mark the completion of the conversion process.
|
||||
*/
|
||||
convertResponse: function (object, options, callback) {
|
||||
if (!options.outputVersion || !semver.valid(options.outputVersion, true)) {
|
||||
return callback(new Error('Output version not specified or invalid: ' + options.outputVersion));
|
||||
}
|
||||
if (!options.inputVersion || !semver.valid(options.inputVersion, true)) {
|
||||
return callback(new Error('Input version not specified or invalid: ' + options.inputVersion));
|
||||
}
|
||||
|
||||
return converter.convertResponse(object, options, callback);
|
||||
}
|
||||
};
|
79
node_modules/postman-collection-transformer/lib/normalizers/index.js
generated
vendored
Normal file
79
node_modules/postman-collection-transformer/lib/normalizers/index.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
/* eslint-disable object-shorthand */
|
||||
var semver = require('semver'),
|
||||
|
||||
// @todo: Add support for more normalizers
|
||||
normalizers = {
|
||||
'1.0.0': require('./v1')
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Accepts the arguments for normalization and invokes the appropriate normalizer with them.
|
||||
*
|
||||
* @param {Object} collection - The plain collection JSON to be normalized.
|
||||
* @param {Object} options - A set of options for the current normalization.
|
||||
* @param {String} options.normalizeVersion - The base collection schema version for which to normalize.
|
||||
* @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 the completion of the normalization process.
|
||||
* @returns {*}
|
||||
*/
|
||||
normalize: function (collection, options, callback) {
|
||||
var version;
|
||||
|
||||
if (!options || !(version = semver.valid(options.normalizeVersion, true)) || !normalizers[version]) {
|
||||
return callback(new Error('Version not specified or invalid: ' + options.normalizeVersion));
|
||||
}
|
||||
|
||||
return normalizers[version].normalize(collection, options, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Normalizes a single request or item as per the provided version.
|
||||
*
|
||||
* @param {Object} object - The entity to be normalized.
|
||||
* @param {Object} options - The set of options to be applied to the current normalization.
|
||||
* @param {String} options.normalizeVersion - The base collection schema version for which to normalize.
|
||||
* @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 - The function invoked when the normalization has completed.
|
||||
*/
|
||||
normalizeSingle: function (object, options, callback) {
|
||||
var version;
|
||||
|
||||
if (!options || !(version = semver.valid(options.normalizeVersion, true)) || !normalizers[version]) {
|
||||
return callback(new Error('Version not specified or invalid: ' + options.normalizeVersion));
|
||||
}
|
||||
|
||||
return normalizers[version].normalizeSingle(object, options, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Normalizes a single response as per the provided version.
|
||||
*
|
||||
* @param {Object} response - The response to be normalized.
|
||||
* @param {Object} options - The set of options to be applied to the current normalization.
|
||||
* @param {String} options.normalizeVersion - The base collection schema version for which to normalize.
|
||||
* @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 - The function invoked when the normalization has completed.
|
||||
*/
|
||||
normalizeResponse: function (response, options, callback) {
|
||||
var version;
|
||||
|
||||
if (!options || !(version = semver.valid(options.normalizeVersion, true)) || !normalizers[version]) {
|
||||
return callback(new Error('Version not specified or invalid: ' + options.normalizeVersion));
|
||||
}
|
||||
|
||||
return normalizers[version].normalizeResponse(response, options, callback);
|
||||
}
|
||||
};
|
693
node_modules/postman-collection-transformer/lib/normalizers/v1.js
generated
vendored
Normal file
693
node_modules/postman-collection-transformer/lib/normalizers/v1.js
generated
vendored
Normal file
@@ -0,0 +1,693 @@
|
||||
/* 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;
|
||||
}
|
||||
};
|
663
node_modules/postman-collection-transformer/lib/url.js
generated
vendored
Normal file
663
node_modules/postman-collection-transformer/lib/url.js
generated
vendored
Normal file
@@ -0,0 +1,663 @@
|
||||
/**
|
||||
* @fileoverview
|
||||
*
|
||||
* Copied the URL parser and unparser from the SDK.
|
||||
* @todo Move this into it's own separate module, and make the SDK and transformer depend on it.
|
||||
*/
|
||||
|
||||
const _ = require('lodash').noConflict(),
|
||||
|
||||
E = '',
|
||||
HASH = '#',
|
||||
SLASH = '/',
|
||||
COLON = ':',
|
||||
EQUALS = '=',
|
||||
AMPERSAND = '&',
|
||||
AUTH_SEPARATOR = '@',
|
||||
QUERY_SEPARATOR = '?',
|
||||
DOMAIN_SEPARATOR = '.',
|
||||
PROTOCOL_SEPARATOR = '://',
|
||||
PROTOCOL_SEPARATOR_WITH_BACKSLASH = ':\\\\',
|
||||
|
||||
STRING = 'string',
|
||||
FUNCTION = 'function',
|
||||
SAFE_REPLACE_CHAR = '_',
|
||||
CLOSING_SQUARE_BRACKET = ']',
|
||||
URL_PROPERTIES_ORDER = ['protocol', 'auth', 'host', 'port', 'path', 'query', 'hash'],
|
||||
|
||||
REGEX_HASH = /#/g,
|
||||
REGEX_EQUALS = /=/g, // eslint-disable-line no-div-regex
|
||||
REGEX_AMPERSAND = /&/g,
|
||||
REGEX_EXTRACT_VARS = /{{[^{}]*[.:/?#@&\]][^{}]*}}/g,
|
||||
REGEX_EXTRACT_VARS_IN_PARAM = /{{[^{}]*[&#=][^{}]*}}/g,
|
||||
|
||||
/**
|
||||
* Percent encode reserved chars (&, = and #) in the given string.
|
||||
*
|
||||
* @private
|
||||
* @param {String} str - String to encode
|
||||
* @param {Boolean} encodeEquals - Encode '=' if true
|
||||
* @returns {String} - Encoded string
|
||||
*/
|
||||
encodeReservedChars = function (str, encodeEquals) {
|
||||
if (!str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line lodash/prefer-includes
|
||||
str.indexOf(AMPERSAND) !== -1 && (str = str.replace(REGEX_AMPERSAND, '%26'));
|
||||
|
||||
// eslint-disable-next-line lodash/prefer-includes
|
||||
str.indexOf(HASH) !== -1 && (str = str.replace(REGEX_HASH, '%23'));
|
||||
|
||||
// eslint-disable-next-line lodash/prefer-includes
|
||||
encodeEquals && str.indexOf(EQUALS) !== -1 && (str = str.replace(REGEX_EQUALS, '%3D'));
|
||||
|
||||
return str;
|
||||
},
|
||||
|
||||
/**
|
||||
* Normalize the given param string by percent-encoding the reserved chars
|
||||
* such that it won't affect the re-parsing.
|
||||
*
|
||||
* @note `&`, `=` and `#` needs to be percent-encoded otherwise re-parsing
|
||||
* the same URL string will generate different output
|
||||
*
|
||||
* @private
|
||||
* @param {String} str - Parameter string to normalize
|
||||
* @param {Boolean} encodeEquals - If true, encode '=' while normalizing
|
||||
* @returns {String} - Normalized param string
|
||||
*/
|
||||
normalizeParam = function (str, encodeEquals) {
|
||||
// bail out if the given sting is null or empty
|
||||
if (!(str && typeof str === STRING)) {
|
||||
return str;
|
||||
}
|
||||
|
||||
// bail out if the given string does not include reserved chars
|
||||
// eslint-disable-next-line lodash/prefer-includes
|
||||
if (str.indexOf(AMPERSAND) === -1 && str.indexOf(HASH) === -1) {
|
||||
// eslint-disable-next-line lodash/prefer-includes
|
||||
if (!(encodeEquals && str.indexOf(EQUALS) !== -1)) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
var normalizedString = '',
|
||||
pointer = 0,
|
||||
variable,
|
||||
match,
|
||||
index;
|
||||
|
||||
// find all the instances of {{<variable>}} which includes reserved chars
|
||||
while ((match = REGEX_EXTRACT_VARS_IN_PARAM.exec(str)) !== null) {
|
||||
variable = match[0];
|
||||
index = match.index;
|
||||
|
||||
// [pointer, index) string is normalized + the matched variable
|
||||
normalizedString += encodeReservedChars(str.slice(pointer, index), encodeEquals) + variable;
|
||||
|
||||
// update the pointer
|
||||
pointer = index + variable.length;
|
||||
}
|
||||
|
||||
// whatever left in the string is normalized as well
|
||||
if (pointer < str.length) {
|
||||
normalizedString += encodeReservedChars(str.slice(pointer), encodeEquals);
|
||||
}
|
||||
|
||||
return normalizedString;
|
||||
},
|
||||
|
||||
/**
|
||||
* Unparses a single query param into a string.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} obj - The query parameter object to be unparsed.
|
||||
* @returns {String} - The unparsed query string.
|
||||
*/
|
||||
unparseQueryParam = function (obj) {
|
||||
if (!obj) { return E; }
|
||||
|
||||
var key = obj.key,
|
||||
value = obj.value,
|
||||
result;
|
||||
|
||||
if (typeof key === STRING) {
|
||||
result = normalizeParam(key, true);
|
||||
}
|
||||
else {
|
||||
result = E;
|
||||
}
|
||||
|
||||
if (typeof value === STRING) {
|
||||
result += EQUALS + normalizeParam(value);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses a single query param string into an object.
|
||||
*
|
||||
* @private
|
||||
* @param {String} param - The query parameter string to be parsed.
|
||||
* @returns {Object} - The parsed query object.
|
||||
*/
|
||||
parseQueryParam = function (param) {
|
||||
if (param === E) {
|
||||
return { key: null, value: null };
|
||||
}
|
||||
|
||||
var index = _.indexOf(param, EQUALS);
|
||||
|
||||
if (index < 0) {
|
||||
return { key: param, value: null };
|
||||
}
|
||||
|
||||
return {
|
||||
key: param.substr(0, index),
|
||||
value: param.substr(index + 1)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Tracks replacements done on a string and expose utility to patch replacements.
|
||||
*
|
||||
* @note due to performance reasons, it doesn't store the original string or
|
||||
* perform ops on the string.
|
||||
*
|
||||
* @private
|
||||
* @constructor
|
||||
*/
|
||||
function ReplacementTracker () {
|
||||
this.replacements = [];
|
||||
this._offset = 0;
|
||||
this._length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new replacement to track.
|
||||
*
|
||||
* @param {String} value - value being replaced
|
||||
* @param {Number} index - index of replacement
|
||||
*/
|
||||
ReplacementTracker.prototype.add = function (value, index) {
|
||||
this.replacements.push({
|
||||
value: value,
|
||||
index: index - this._offset
|
||||
});
|
||||
|
||||
this._offset += value.length - 1; // - 1 replaced character
|
||||
this._length++;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the total number of replacements.
|
||||
*
|
||||
* @returns {Number}
|
||||
*/
|
||||
ReplacementTracker.prototype.count = function () {
|
||||
return this._length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds the lower index of replacement position for a given value using inexact
|
||||
* binary search.
|
||||
*
|
||||
* @param {Number} index - index to search in replacements
|
||||
* @returns {Number}
|
||||
*/
|
||||
ReplacementTracker.prototype._findLowerIndex = function (index) {
|
||||
var length = this.count(),
|
||||
start = 0,
|
||||
end = length - 1,
|
||||
mid;
|
||||
|
||||
while (start <= end) {
|
||||
mid = (start + end) >> 1; // divide by 2
|
||||
|
||||
if (this.replacements[mid].index >= index) {
|
||||
end = mid - 1;
|
||||
}
|
||||
else {
|
||||
start = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return start >= length ? -1 : start;
|
||||
};
|
||||
|
||||
/**
|
||||
* Patches a given string by apply all the applicable replacements done in the
|
||||
* given range.
|
||||
*
|
||||
* @param {String} input - string to apply replacements on
|
||||
* @param {Number} beginIndex - index from where to apply replacements in input
|
||||
* @param {Number} endIndex - index until where to apply replacements in input
|
||||
* @returns {String}
|
||||
*/
|
||||
ReplacementTracker.prototype._applyInString = function (input, beginIndex, endIndex) {
|
||||
var index,
|
||||
replacement,
|
||||
replacementIndex,
|
||||
replacementValue,
|
||||
offset = 0,
|
||||
length = this.count();
|
||||
|
||||
// bail out if no replacements are done in the given range OR empty string
|
||||
if (!input || (index = this._findLowerIndex(beginIndex)) === -1) {
|
||||
return input;
|
||||
}
|
||||
|
||||
do {
|
||||
replacement = this.replacements[index];
|
||||
replacementIndex = replacement.index;
|
||||
replacementValue = replacement.value;
|
||||
|
||||
// bail out if all the replacements are done in the given range
|
||||
if (replacementIndex >= endIndex) {
|
||||
break;
|
||||
}
|
||||
|
||||
replacementIndex = offset + replacementIndex - beginIndex;
|
||||
input = input.slice(0, replacementIndex) + replacementValue + input.slice(replacementIndex + 1);
|
||||
offset += replacementValue.length - 1;
|
||||
} while (++index < length);
|
||||
|
||||
return input;
|
||||
};
|
||||
|
||||
/**
|
||||
* Patches a given string or array of strings by apply all the applicable
|
||||
* replacements done in the given range.
|
||||
*
|
||||
* @param {String|String[]} input - string or splitted string to apply replacements on
|
||||
* @param {Number} beginIndex - index from where to apply replacements in input
|
||||
* @param {Number} endIndex - index until where to apply replacements in input
|
||||
* @returns {String|String[]}
|
||||
*/
|
||||
ReplacementTracker.prototype.apply = function (input, beginIndex, endIndex) {
|
||||
var i,
|
||||
ii,
|
||||
length,
|
||||
_endIndex,
|
||||
_beginIndex,
|
||||
value = input;
|
||||
|
||||
// apply replacements in string
|
||||
if (typeof input === STRING) {
|
||||
return this._applyInString(input, beginIndex, endIndex);
|
||||
}
|
||||
|
||||
// apply replacements in the splitted string (Array)
|
||||
_beginIndex = beginIndex;
|
||||
|
||||
// traverse all the segments until all the replacements are patched
|
||||
for (i = 0, ii = input.length; i < ii; ++i) {
|
||||
value = input[i];
|
||||
_endIndex = _beginIndex + (length = value.length);
|
||||
|
||||
// apply replacements applicable for individual segment
|
||||
input[i] = this._applyInString(value, _beginIndex, _endIndex);
|
||||
_beginIndex += length + 1; // + 1 separator
|
||||
}
|
||||
|
||||
return input;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize the given string by replacing the variables which includes
|
||||
* reserved characters in its name.
|
||||
* The replaced characters are added to the given replacement tracker instance.
|
||||
*
|
||||
* @private
|
||||
* @param {String} str - string to normalize
|
||||
* @param {ReplacementTracker} replacements - tracker to store replacements
|
||||
* @returns {String}
|
||||
*/
|
||||
function normalizeVariables (str, replacements) {
|
||||
var normalizedString = E,
|
||||
pointer = 0, // pointer till witch the string is normalized
|
||||
variable,
|
||||
match,
|
||||
index;
|
||||
|
||||
// find all the instances of {{<variable>}} which includes reserved chars
|
||||
// "Hello {{user#name}}!!!"
|
||||
// ↑ (pointer = 0)
|
||||
while ((match = REGEX_EXTRACT_VARS.exec(str)) !== null) {
|
||||
// {{user#name}}
|
||||
variable = match[0];
|
||||
|
||||
// starting index of the {{variable}} in the string
|
||||
// "Hello {{user#name}}!!!"
|
||||
// ↑ (index = 6)
|
||||
index = match.index;
|
||||
|
||||
// [pointer, index) string is normalized + the safe replacement character
|
||||
// "Hello " + "_"
|
||||
normalizedString += str.slice(pointer, index) + SAFE_REPLACE_CHAR;
|
||||
|
||||
// track the replacement done for the {{variable}}
|
||||
replacements.add(variable, index);
|
||||
|
||||
// update the pointer
|
||||
// "Hello {{user#name}}!!!"
|
||||
// ↑ (pointer = 19)
|
||||
pointer = index + variable.length;
|
||||
}
|
||||
|
||||
// avoid slicing the string in case of no matches
|
||||
if (pointer === 0) {
|
||||
return str;
|
||||
}
|
||||
|
||||
// whatever left in the string is normalized as well
|
||||
if (pointer < str.length) {
|
||||
// "Hello _" + "!!!"
|
||||
normalizedString += str.slice(pointer);
|
||||
}
|
||||
|
||||
return normalizedString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update replaced characters in the URL object with its original value.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} url - url to apply replacements on
|
||||
* @param {ReplacementTracker} replacements - tracked replacements
|
||||
*/
|
||||
function applyReplacements (url, replacements) {
|
||||
var i,
|
||||
ii,
|
||||
prop;
|
||||
|
||||
// traverse each URL property in the given order
|
||||
for (i = 0, ii = URL_PROPERTIES_ORDER.length; i < ii; ++i) {
|
||||
prop = url[URL_PROPERTIES_ORDER[i]];
|
||||
|
||||
// bail out if the given property is not set (undefined or E)
|
||||
if (!(prop && prop.value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
prop.value = replacements.apply(prop.value, prop.beginIndex, prop.endIndex);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the input string by decomposing the URL into constituent parts,
|
||||
* such as path, host, port, etc.
|
||||
*
|
||||
* @private
|
||||
* @param {String} urlString - url string to parse
|
||||
* @returns {Object}
|
||||
*/
|
||||
function url_parse (urlString) {
|
||||
// trim leading whitespace characters
|
||||
urlString = String(urlString).trimLeft();
|
||||
|
||||
var url = {
|
||||
protocol: { value: undefined, beginIndex: 0, endIndex: 0 },
|
||||
auth: { value: undefined, beginIndex: 0, endIndex: 0 },
|
||||
host: { value: undefined, beginIndex: 0, endIndex: 0 },
|
||||
port: { value: undefined, beginIndex: 0, endIndex: 0 },
|
||||
path: { value: undefined, beginIndex: 0, endIndex: 0 },
|
||||
query: { value: undefined, beginIndex: 0, endIndex: 0 },
|
||||
hash: { value: undefined, beginIndex: 0, endIndex: 0 }
|
||||
},
|
||||
parsedUrl = {
|
||||
raw: urlString,
|
||||
protocol: undefined,
|
||||
auth: undefined,
|
||||
host: undefined,
|
||||
port: undefined,
|
||||
path: undefined,
|
||||
query: undefined,
|
||||
hash: undefined
|
||||
},
|
||||
replacements = new ReplacementTracker(),
|
||||
pointer = 0,
|
||||
length,
|
||||
index,
|
||||
port;
|
||||
|
||||
// bail out if input string is empty
|
||||
if (!urlString) {
|
||||
return parsedUrl;
|
||||
}
|
||||
|
||||
// normalize the given string
|
||||
urlString = normalizeVariables(urlString, replacements);
|
||||
length = urlString.length;
|
||||
|
||||
// 1. url.hash
|
||||
if ((index = urlString.indexOf(HASH)) !== -1) {
|
||||
// extract from the back
|
||||
url.hash.value = urlString.slice(index + 1);
|
||||
url.hash.beginIndex = pointer + index + 1;
|
||||
url.hash.endIndex = pointer + length;
|
||||
|
||||
urlString = urlString.slice(0, (length = index));
|
||||
}
|
||||
|
||||
// 2. url.query
|
||||
if ((index = urlString.indexOf(QUERY_SEPARATOR)) !== -1) {
|
||||
// extract from the back
|
||||
url.query.value = urlString.slice(index + 1).split(AMPERSAND);
|
||||
url.query.beginIndex = pointer + index + 1;
|
||||
url.query.endIndex = pointer + length;
|
||||
|
||||
urlString = urlString.slice(0, (length = index));
|
||||
}
|
||||
|
||||
// 3. url.protocol
|
||||
if ((index = urlString.indexOf(PROTOCOL_SEPARATOR)) !== -1) {
|
||||
// extract from the front
|
||||
url.protocol.value = urlString.slice(0, index);
|
||||
url.protocol.beginIndex = pointer;
|
||||
url.protocol.endIndex = pointer + index;
|
||||
|
||||
urlString = urlString.slice(index + 3);
|
||||
length -= index + 3;
|
||||
pointer += index + 3;
|
||||
}
|
||||
// protocol can be separated using :\\ as well
|
||||
else if ((index = urlString.indexOf(PROTOCOL_SEPARATOR_WITH_BACKSLASH)) !== -1) {
|
||||
// extract from the front
|
||||
url.protocol.value = urlString.slice(0, index);
|
||||
url.protocol.beginIndex = pointer;
|
||||
url.protocol.endIndex = pointer + index;
|
||||
|
||||
urlString = urlString.slice(index + 3);
|
||||
length -= index + 3;
|
||||
pointer += index + 3;
|
||||
}
|
||||
|
||||
// 4. url.path
|
||||
urlString = urlString.replace(/\\/g, '/'); // sanitize path
|
||||
if ((index = urlString.indexOf(SLASH)) !== -1) {
|
||||
// extract from the back
|
||||
url.path.value = urlString.slice(index + 1).split(SLASH);
|
||||
url.path.beginIndex = pointer + index + 1;
|
||||
url.path.endIndex = pointer + length;
|
||||
|
||||
urlString = urlString.slice(0, (length = index));
|
||||
}
|
||||
|
||||
// 5. url.auth
|
||||
if ((index = urlString.lastIndexOf(AUTH_SEPARATOR)) !== -1) {
|
||||
// extract from the front
|
||||
url.auth.value = urlString.slice(0, index);
|
||||
url.auth.beginIndex = pointer;
|
||||
url.auth.endIndex = pointer + index;
|
||||
|
||||
urlString = urlString.slice(index + 1);
|
||||
length -= index + 1;
|
||||
pointer += index + 1;
|
||||
|
||||
// separate username:password
|
||||
if ((index = url.auth.value.indexOf(COLON)) === -1) {
|
||||
url.auth.value = [url.auth.value];
|
||||
}
|
||||
else {
|
||||
url.auth.value = [url.auth.value.slice(0, index), url.auth.value.slice(index + 1)];
|
||||
}
|
||||
}
|
||||
|
||||
// 6. url.port
|
||||
if ((index = urlString.lastIndexOf(COLON)) !== -1 &&
|
||||
// eslint-disable-next-line lodash/prefer-includes
|
||||
(port = urlString.slice(index + 1)).indexOf(CLOSING_SQUARE_BRACKET) === -1
|
||||
) {
|
||||
// extract from the back
|
||||
url.port.value = port;
|
||||
url.port.beginIndex = pointer + index + 1;
|
||||
url.port.endIndex = pointer + length;
|
||||
|
||||
urlString = urlString.slice(0, (length = index));
|
||||
}
|
||||
|
||||
// 7. url.host
|
||||
if (urlString) {
|
||||
url.host.value = urlString.split(DOMAIN_SEPARATOR);
|
||||
url.host.beginIndex = pointer;
|
||||
url.host.endIndex = pointer + length;
|
||||
}
|
||||
|
||||
// apply replacements back, if any
|
||||
replacements.count() && applyReplacements(url, replacements);
|
||||
|
||||
// finally, prepare parsed url
|
||||
parsedUrl.protocol = url.protocol.value;
|
||||
parsedUrl.auth = url.auth.value;
|
||||
parsedUrl.host = url.host.value;
|
||||
parsedUrl.port = url.port.value;
|
||||
parsedUrl.path = url.path.value;
|
||||
parsedUrl.query = url.query.value;
|
||||
parsedUrl.hash = url.hash.value;
|
||||
|
||||
return parsedUrl;
|
||||
}
|
||||
|
||||
/* eslint-disable object-shorthand */
|
||||
module.exports = {
|
||||
parse: function (url) {
|
||||
if (typeof url !== STRING) {
|
||||
url = '';
|
||||
}
|
||||
|
||||
url = url_parse(url);
|
||||
|
||||
var pathVariables,
|
||||
pathVariableKeys = {};
|
||||
|
||||
if (url.auth) {
|
||||
url.auth = {
|
||||
user: url.auth[0],
|
||||
password: url.auth[1]
|
||||
};
|
||||
}
|
||||
|
||||
if (url.query) {
|
||||
url.query = url.query.map(parseQueryParam);
|
||||
}
|
||||
|
||||
// extract path variables
|
||||
pathVariables = _.transform(url.path, function (res, segment) {
|
||||
// check if the segment has path variable prefix followed by the variable name and
|
||||
// the variable is not already added in the list.
|
||||
if (_.startsWith(segment, COLON) &&
|
||||
segment !== COLON &&
|
||||
!pathVariableKeys[segment]) {
|
||||
pathVariableKeys[segment] = true;
|
||||
res.push({ key: segment.slice(1) }); // remove path variable prefix.
|
||||
}
|
||||
}, []);
|
||||
url.variable = pathVariables.length ? pathVariables : undefined;
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
unparse: function (urlObj) {
|
||||
var rawUrl = E,
|
||||
path,
|
||||
queryString,
|
||||
authString,
|
||||
firstEnabledParam = true;
|
||||
|
||||
if (urlObj.protocol) {
|
||||
rawUrl += (_.endsWith(urlObj.protocol, PROTOCOL_SEPARATOR) ?
|
||||
urlObj.protocol : urlObj.protocol + PROTOCOL_SEPARATOR);
|
||||
}
|
||||
|
||||
if (urlObj.auth) {
|
||||
if (typeof urlObj.auth.user === STRING) {
|
||||
authString = urlObj.auth.user;
|
||||
}
|
||||
|
||||
if (typeof urlObj.auth.password === STRING) {
|
||||
!authString && (authString = E);
|
||||
authString += COLON + urlObj.auth.password;
|
||||
}
|
||||
|
||||
if (typeof authString === STRING) {
|
||||
rawUrl += authString + AUTH_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
if (urlObj.host) {
|
||||
rawUrl += (_.isArray(urlObj.host) ? urlObj.host.join(DOMAIN_SEPARATOR) : urlObj.host.toString());
|
||||
}
|
||||
|
||||
if (typeof _.get(urlObj.port, 'toString') === FUNCTION) {
|
||||
rawUrl += COLON + urlObj.port.toString();
|
||||
}
|
||||
|
||||
if (urlObj.path) {
|
||||
path = (_.isArray(urlObj.path) ? urlObj.path.join(SLASH) : urlObj.path.toString());
|
||||
rawUrl += (_.startsWith(path, SLASH) ? path : SLASH + path);
|
||||
}
|
||||
|
||||
if (urlObj.query && urlObj.query.length) {
|
||||
queryString = _.reduce(urlObj.query, function (accumulator, param) {
|
||||
// ignore disabled params
|
||||
if (!param || param.disabled) {
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
// don't add '&' for the very first enabled param
|
||||
if (firstEnabledParam) {
|
||||
firstEnabledParam = false;
|
||||
}
|
||||
// add '&' before concatenating param
|
||||
else {
|
||||
accumulator += AMPERSAND;
|
||||
}
|
||||
|
||||
return accumulator + unparseQueryParam(param);
|
||||
}, E);
|
||||
|
||||
// either all the params are disabled or a single param is like { key: '' } (http://localhost?)
|
||||
// in that case, query separator ? must be included in the raw URL.
|
||||
if (queryString === E && firstEnabledParam) {
|
||||
// unset querystring if there are no enabled params
|
||||
queryString = undefined;
|
||||
}
|
||||
|
||||
if (typeof queryString === STRING) {
|
||||
rawUrl += QUERY_SEPARATOR + queryString;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof urlObj.hash === STRING) {
|
||||
rawUrl += HASH + urlObj.hash;
|
||||
}
|
||||
|
||||
return rawUrl;
|
||||
}
|
||||
};
|
464
node_modules/postman-collection-transformer/lib/util.js
generated
vendored
Normal file
464
node_modules/postman-collection-transformer/lib/util.js
generated
vendored
Normal file
@@ -0,0 +1,464 @@
|
||||
/* eslint-disable object-shorthand */
|
||||
var _ = require('lodash'),
|
||||
url = require('./url'),
|
||||
rnd = Math.random;
|
||||
|
||||
module.exports = {
|
||||
// @todo: Add support for a `json` type once it becomes available
|
||||
typeMap: {
|
||||
string: 'string',
|
||||
boolean: 'boolean',
|
||||
number: 'number'
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns unique GUID on every call as per pseudo-number RFC4122 standards.
|
||||
*
|
||||
* @type {function}
|
||||
* @returns {string}
|
||||
*/
|
||||
uid: function () {
|
||||
var n,
|
||||
r,
|
||||
E = '',
|
||||
H = '-'; // r = result , n = numeric variable for positional checks
|
||||
|
||||
// if "n" is not 9 or 14 or 19 or 24 return a random number or 4
|
||||
// if "n" is not 15 generate a random number from 0 to 15
|
||||
// `(n ^ 20 ? 16 : 4)` := unless "n" is 20, in which case a random number from 8 to 11 otherwise 4
|
||||
//
|
||||
// in other cases (if "n" is 9,14,19,24) insert "-"
|
||||
// eslint-disable-next-line curly
|
||||
for (r = n = E; n++ < 36; r += n * 51 & 52 ? (n ^ 15 ? 8 ^ rnd() * (n ^ 20 ? 16 : 4) : 4).toString(16) : H);
|
||||
|
||||
return r;
|
||||
},
|
||||
|
||||
urlparse: function (u) {
|
||||
return url.parse(u);
|
||||
},
|
||||
|
||||
urlunparse: function (urlObj) {
|
||||
return url.unparse(urlObj);
|
||||
},
|
||||
|
||||
/**
|
||||
* A generic utility method to sanitize variable transformations across collection formats.
|
||||
*
|
||||
* @param {Object} entity - A generic object that could contain variable data.
|
||||
* @param {?Object} options - The set of options for variable handling.
|
||||
* @param {?Object} options.fallback - The fallback values to be used if no variables are present.
|
||||
* @param {?Boolean} options.noDefaults - When set to true, id will be retained.
|
||||
* @param {?Boolean} options.retainEmptyValues - When set to true, empty property values will be set to ''
|
||||
* @param {?Boolean} options.retainIds - When set to true, ids are left as is.
|
||||
* instead of being deleted.
|
||||
* @param {Object} [modifiers] - A set of behavioral modifiers for variable handling.
|
||||
* @param {Boolean} [modifiers.isV1=false] - When set to true, looks for the pathVariableData property as well.
|
||||
* @returns {Object[]} - The set of sanitized entity level variables.
|
||||
*/
|
||||
handleVars: function (entity, options, modifiers) {
|
||||
!options && (options = {});
|
||||
|
||||
var self = this,
|
||||
retainIds = options.retainIds,
|
||||
noDefaults = options.noDefaults,
|
||||
isV1 = modifiers && modifiers.isV1,
|
||||
retainEmpty = options.retainEmptyValues,
|
||||
source = entity && (entity.variables || entity.variable || (isV1 && entity.pathVariableData)),
|
||||
fallback = options.fallback && options.fallback.values,
|
||||
result = _.map(source || fallback, function (item) {
|
||||
var result = {};
|
||||
|
||||
// add id only when retainIds is set
|
||||
if (retainIds) {
|
||||
// retain id only when `id` field is present
|
||||
if (_.has(item, 'id')) {
|
||||
result.id = item.id;
|
||||
}
|
||||
// or, create a new id if noDefaults is false
|
||||
else if (!noDefaults) {
|
||||
result.id = self.uid();
|
||||
}
|
||||
}
|
||||
|
||||
result.key = item.key || item.id;
|
||||
result.value = item.value;
|
||||
|
||||
item.type && (result.type = item.type === 'text' ? 'string' : item.type);
|
||||
item.disabled && (result.disabled = true);
|
||||
|
||||
if (item.description) { result.description = item.description; }
|
||||
else if (retainEmpty) { result.description = null; }
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
if (result.length) { return result; }
|
||||
},
|
||||
|
||||
/**
|
||||
* Performs auth cleansing common to all sorts of auth transformations.
|
||||
*
|
||||
* @param {Object} entity - The wrapped auth entity to be cleaned.
|
||||
* @param {?Object} options - The set of options for the current auth cleansing operation.
|
||||
* @param {?Boolean} [options.excludeNoauth=false] - When set to true, noauth is set to null.
|
||||
* @returns {Object|*} - The processed auth data.
|
||||
*/
|
||||
cleanAuth: function (entity, options) {
|
||||
!options && (options = {});
|
||||
|
||||
var auth = entity && entity.auth;
|
||||
|
||||
if (auth === null) { return null; } // eslint-disable-line security/detect-possible-timing-attacks
|
||||
if (!(auth && auth.type)) { return; }
|
||||
if (auth.type === 'noauth') {
|
||||
return options.excludeNoauth ? null : { type: 'noauth' };
|
||||
}
|
||||
|
||||
return auth;
|
||||
},
|
||||
|
||||
cleanEmptyValue: function (entity, property, retainEmpty) {
|
||||
if (_.has(entity, property) && !entity[property]) {
|
||||
retainEmpty ? (entity[property] = null) : (delete entity[property]);
|
||||
}
|
||||
|
||||
return entity;
|
||||
},
|
||||
|
||||
/**
|
||||
* Transforms an array of auth params to their object equivalent.
|
||||
*
|
||||
* @param {Object} entity - The wrapper object for the array of auth params.
|
||||
* @param {?Object} options - The set of options for the current auth cleansing operation.
|
||||
* @param {?Boolean} [options.excludeNoauth=false] - When set to true, noauth is set to null.
|
||||
* @returns {*}
|
||||
*/
|
||||
authArrayToMap: function (entity, options) {
|
||||
var type,
|
||||
result,
|
||||
self = this,
|
||||
auth = self.cleanAuth(entity, options);
|
||||
|
||||
if (!auth) { return auth; }
|
||||
|
||||
result = { type: (type = auth.type) };
|
||||
|
||||
if (type !== 'noauth') {
|
||||
result[type] = _.transform(auth[type], function (result, param) {
|
||||
result[param.key] = param.value;
|
||||
}, {});
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Transforms an object of auth params to their array equivalent.
|
||||
*
|
||||
* @param {Object} entity - The wrapper object for the array of auth params.
|
||||
* @param {?Object} options - The set of options for the current auth cleansing operation.
|
||||
* @param {?Boolean} [options.excludeNoauth=false] - When set to true, noauth is set to null.
|
||||
* @returns {*}
|
||||
*/
|
||||
authMapToArray: function (entity, options) {
|
||||
var type,
|
||||
params,
|
||||
result,
|
||||
self = this,
|
||||
auth = self.cleanAuth(entity, options);
|
||||
|
||||
if (!auth) { return auth; }
|
||||
|
||||
result = { type: (type = auth.type) };
|
||||
|
||||
if (type !== 'noauth') {
|
||||
// @todo: Handle all non _ prefixed properties, ala request bodies
|
||||
params = _.map(auth[type], function (value, key) {
|
||||
return {
|
||||
key: key,
|
||||
value: value,
|
||||
type: self.typeMap[typeof value] || 'any'
|
||||
};
|
||||
});
|
||||
|
||||
params.length && (result[type] = params);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sanitizes a collection SDK compliant auth list.
|
||||
*
|
||||
* @param {Object} entity - The wrapper entity for the auth manifest.
|
||||
* @param {?Object} options - The set of options for the current auth cleansing operation.
|
||||
* @param {?Boolean} [options.excludeNoauth=false] - When set to true, noauth is set to null.
|
||||
* @returns {Object[]} - An array of raw collection SDK compliant auth parameters.
|
||||
*/
|
||||
sanitizeAuthArray: function (entity, options) {
|
||||
var type,
|
||||
result,
|
||||
self = this,
|
||||
auth = self.cleanAuth(entity, options);
|
||||
|
||||
if (!auth) { return auth; }
|
||||
|
||||
result = { type: (type = auth.type) };
|
||||
|
||||
if (type !== 'noauth') {
|
||||
result[type] = _.map(auth[type], function (param) {
|
||||
return {
|
||||
key: param.key,
|
||||
value: param.value,
|
||||
type: (param.type === 'text' ? 'string' : param.type) || self.typeMap[typeof param.value] || 'any'
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* A helper function to determine if the provided v1 entity has legacy properties.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} entityV1 - The v1 entity to be checked for the presence of legacy properties.
|
||||
* @param {String} type - The type of property to be adjudged against.
|
||||
* @returns {Boolean|*} - A flag to indicate the legacy property status of the passed v1 entity.
|
||||
*/
|
||||
notLegacy: function (entityV1, type) {
|
||||
if (!entityV1) { return; }
|
||||
|
||||
switch (type) {
|
||||
case 'event':
|
||||
return !(entityV1.tests || entityV1.preRequestScript);
|
||||
case 'auth':
|
||||
return _.has(entityV1, 'auth') && !(_.has(entityV1, 'currentHelper') || entityV1.helperAttributes);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
authMappersFromLegacy: {
|
||||
apikeyAuth: function (oldParams) {
|
||||
return oldParams && {
|
||||
key: oldParams.key,
|
||||
value: oldParams.value,
|
||||
in: oldParams.in
|
||||
};
|
||||
},
|
||||
basicAuth: function (oldParams) {
|
||||
return oldParams && {
|
||||
username: oldParams.username,
|
||||
password: oldParams.password,
|
||||
saveHelperData: oldParams.saveToRequest,
|
||||
showPassword: false
|
||||
};
|
||||
},
|
||||
bearerAuth: function (oldParams) {
|
||||
return oldParams && {
|
||||
token: oldParams.token
|
||||
};
|
||||
},
|
||||
digestAuth: function (oldParams) {
|
||||
return oldParams && {
|
||||
algorithm: oldParams.algorithm,
|
||||
username: oldParams.username,
|
||||
realm: oldParams.realm,
|
||||
password: oldParams.password,
|
||||
nonce: oldParams.nonce,
|
||||
nonceCount: oldParams.nonceCount,
|
||||
clientNonce: oldParams.clientNonce,
|
||||
opaque: oldParams.opaque,
|
||||
qop: oldParams.qop,
|
||||
disableRetryRequest: oldParams.disableRetryRequest
|
||||
};
|
||||
},
|
||||
oAuth1: function (oldParams) {
|
||||
return oldParams && {
|
||||
consumerKey: oldParams.consumerKey,
|
||||
consumerSecret: oldParams.consumerSecret,
|
||||
token: oldParams.token,
|
||||
tokenSecret: oldParams.tokenSecret,
|
||||
signatureMethod: oldParams.signatureMethod,
|
||||
timestamp: oldParams.timestamp,
|
||||
nonce: oldParams.nonce,
|
||||
version: oldParams.version,
|
||||
realm: oldParams.realm,
|
||||
addParamsToHeader: oldParams.header,
|
||||
autoAddParam: oldParams.auto,
|
||||
addEmptyParamsToSign: oldParams.includeEmpty
|
||||
};
|
||||
},
|
||||
hawkAuth: function (oldParams) {
|
||||
return oldParams && {
|
||||
authId: oldParams.hawk_id,
|
||||
authKey: oldParams.hawk_key,
|
||||
algorithm: oldParams.algorithm,
|
||||
user: oldParams.user,
|
||||
saveHelperData: oldParams.saveToRequest,
|
||||
nonce: oldParams.nonce,
|
||||
extraData: oldParams.ext,
|
||||
appId: oldParams.app,
|
||||
delegation: oldParams.dlg,
|
||||
timestamp: oldParams.timestamp
|
||||
};
|
||||
},
|
||||
ntlmAuth: function (oldParams) {
|
||||
return oldParams && {
|
||||
username: oldParams.username,
|
||||
password: oldParams.password,
|
||||
domain: oldParams.domain,
|
||||
workstation: oldParams.workstation,
|
||||
disableRetryRequest: oldParams.disableRetryRequest
|
||||
};
|
||||
},
|
||||
oAuth2: function (oldParams) {
|
||||
return oldParams && {
|
||||
accessToken: oldParams.accessToken,
|
||||
addTokenTo: oldParams.addTokenTo,
|
||||
callBackUrl: oldParams.callBackUrl,
|
||||
authUrl: oldParams.authUrl,
|
||||
accessTokenUrl: oldParams.accessTokenUrl,
|
||||
clientId: oldParams.clientId,
|
||||
clientSecret: oldParams.clientSecret,
|
||||
clientAuth: oldParams.clientAuth,
|
||||
grantType: oldParams.grantType,
|
||||
scope: oldParams.scope,
|
||||
username: oldParams.username,
|
||||
password: oldParams.password,
|
||||
tokenType: oldParams.tokenType,
|
||||
redirectUri: oldParams.redirectUri,
|
||||
refreshToken: oldParams.refreshToken
|
||||
};
|
||||
},
|
||||
// Only exists for consistency
|
||||
awsSigV4: function (oldParams) {
|
||||
return oldParams;
|
||||
}
|
||||
},
|
||||
authMappersFromCurrent: {
|
||||
apikeyAuth: function (newParams) {
|
||||
return newParams && {
|
||||
id: 'apikey',
|
||||
key: newParams.key,
|
||||
value: newParams.value,
|
||||
in: newParams.in
|
||||
};
|
||||
},
|
||||
basicAuth: function (newParams) {
|
||||
return newParams && {
|
||||
id: 'basic',
|
||||
username: newParams.username,
|
||||
password: newParams.password,
|
||||
saveToRequest: newParams.saveHelperData
|
||||
};
|
||||
},
|
||||
bearerAuth: function (newParams) {
|
||||
return newParams && {
|
||||
id: 'bearer',
|
||||
token: newParams.token
|
||||
};
|
||||
},
|
||||
digestAuth: function (newParams) {
|
||||
return newParams && {
|
||||
id: 'digest',
|
||||
algorithm: newParams.algorithm,
|
||||
username: newParams.username,
|
||||
realm: newParams.realm,
|
||||
password: newParams.password,
|
||||
nonce: newParams.nonce,
|
||||
nonceCount: newParams.nonceCount,
|
||||
clientNonce: newParams.clientNonce,
|
||||
opaque: newParams.opaque,
|
||||
qop: newParams.qop,
|
||||
disableRetryRequest: newParams.disableRetryRequest
|
||||
};
|
||||
},
|
||||
oAuth1: function (newParams) {
|
||||
return newParams && {
|
||||
id: 'oAuth1',
|
||||
consumerKey: newParams.consumerKey,
|
||||
consumerSecret: newParams.consumerSecret,
|
||||
token: newParams.token,
|
||||
tokenSecret: newParams.tokenSecret,
|
||||
signatureMethod: newParams.signatureMethod,
|
||||
timestamp: newParams.timeStamp || newParams.timestamp,
|
||||
nonce: newParams.nonce,
|
||||
version: newParams.version,
|
||||
realm: newParams.realm,
|
||||
header: newParams.addParamsToHeader,
|
||||
auto: newParams.autoAddParam,
|
||||
includeEmpty: newParams.addEmptyParamsToSign
|
||||
};
|
||||
},
|
||||
hawkAuth: function (newParams) {
|
||||
return newParams && {
|
||||
id: 'hawk',
|
||||
hawk_id: newParams.authId,
|
||||
hawk_key: newParams.authKey,
|
||||
algorithm: newParams.algorithm,
|
||||
user: newParams.user,
|
||||
saveToRequest: newParams.saveHelperData,
|
||||
nonce: newParams.nonce,
|
||||
ext: newParams.extraData,
|
||||
app: newParams.appId,
|
||||
dlg: newParams.delegation,
|
||||
timestamp: newParams.timestamp
|
||||
};
|
||||
},
|
||||
ntlmAuth: function (newParams) {
|
||||
return newParams && {
|
||||
id: 'ntlm',
|
||||
username: newParams.username,
|
||||
password: newParams.password,
|
||||
domain: newParams.domain,
|
||||
workstation: newParams.workstation,
|
||||
disableRetryRequest: newParams.disableRetryRequest
|
||||
};
|
||||
},
|
||||
oAuth2: function (newParams) {
|
||||
return newParams && {
|
||||
id: 'oAuth2',
|
||||
accessToken: newParams.accessToken,
|
||||
addTokenTo: newParams.addTokenTo,
|
||||
callBackUrl: newParams.callBackUrl,
|
||||
authUrl: newParams.authUrl,
|
||||
accessTokenUrl: newParams.accessTokenUrl,
|
||||
clientId: newParams.clientId,
|
||||
clientSecret: newParams.clientSecret,
|
||||
clientAuth: newParams.clientAuth,
|
||||
grantType: newParams.grantType,
|
||||
scope: newParams.scope,
|
||||
username: newParams.username,
|
||||
password: newParams.password,
|
||||
tokenType: newParams.tokenType,
|
||||
redirectUri: newParams.redirectUri,
|
||||
refreshToken: newParams.refreshToken
|
||||
};
|
||||
},
|
||||
// Only exists for consistency
|
||||
awsSigV4: function (newParams) {
|
||||
return newParams;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Validate protocolProfileBehavior property's value.
|
||||
*
|
||||
* @param {Object} source - A generic object that could contain the protocolProfileBehavior property.
|
||||
* @param {?Object} destination - The destination object that needs the addition of protocolProfileBehavior.
|
||||
* @returns {Boolean} - A Boolean value to decide whether to include the property or not.
|
||||
*/
|
||||
addProtocolProfileBehavior: function (source, destination) {
|
||||
var behavior = source && source.protocolProfileBehavior;
|
||||
|
||||
// make sure it's a non-empty plain object
|
||||
if (!(_.isPlainObject(behavior) && !_.isEmpty(behavior))) { return false; }
|
||||
|
||||
destination && (destination.protocolProfileBehavior = behavior);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user