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:
46
node_modules/postman-sandbox/lib/bootcode.js
generated
vendored
Normal file
46
node_modules/postman-sandbox/lib/bootcode.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
const _ = require('lodash'),
|
||||
env = require('./environment');
|
||||
|
||||
let cache,
|
||||
bundler,
|
||||
cacher;
|
||||
|
||||
// we first try and load the pre-bundled file from file-cache. file cache might be absent during development phase and
|
||||
// as such, we fall back to live bundling.
|
||||
try {
|
||||
bundler = require('../.cache/bootcode');
|
||||
}
|
||||
catch (e) {
|
||||
console && console.info('sandbox: ' + e.message + '\n' +
|
||||
'bootcode is being live compiled. use `npm run cache` to use cached variant.');
|
||||
}
|
||||
|
||||
// in case bundler is not a valid function, we create a bundler that uses the environment to compile sandbox bootstrap
|
||||
// code
|
||||
!_.isFunction(bundler) && (bundler = function (done) {
|
||||
require('./bundle').load(env).compile(done);
|
||||
});
|
||||
|
||||
cacher = function (done) {
|
||||
// in case the cache is already populated, we simply forward the cached string to the caller
|
||||
if (cache) {
|
||||
return done(null, cache);
|
||||
}
|
||||
|
||||
// since the code is not cached, we fetch the code from the bundler (it could be file cached or live compiled) and
|
||||
// then cache it before forwarding it to caller.
|
||||
bundler(function (err, code) {
|
||||
if (err) { return done(err); }
|
||||
|
||||
// ensure buffer is stringified before being cached
|
||||
(code && !_.isString(code)) && (code = code.toString());
|
||||
if (code && _.isString(code)) { // before caching we check the code as string once more
|
||||
cache = code;
|
||||
cacher.cached = true; // a flag to aid debugging
|
||||
}
|
||||
|
||||
return done(null, cache);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = cacher;
|
8
node_modules/postman-sandbox/lib/bundle/bundling-options.js
generated
vendored
Normal file
8
node_modules/postman-sandbox/lib/bundle/bundling-options.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
insertGlobalVars: false,
|
||||
detectGlobals: true,
|
||||
browserField: false,
|
||||
bare: true,
|
||||
builtins: false,
|
||||
commondir: true
|
||||
};
|
18
node_modules/postman-sandbox/lib/bundle/index.browser.js
generated
vendored
Normal file
18
node_modules/postman-sandbox/lib/bundle/index.browser.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Error message to trigger if bundling is accidentally triggered inside a browser
|
||||
*
|
||||
* @constant
|
||||
* @private
|
||||
* @type {String}
|
||||
*/
|
||||
const ERROR_MESSAGE = 'sandbox: code bundling is not supported in browser. use cached templates.';
|
||||
|
||||
function StubBundle () {
|
||||
throw new Error(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
StubBundle.load = function () {
|
||||
throw new Error(ERROR_MESSAGE);
|
||||
};
|
||||
|
||||
module.exports = StubBundle;
|
138
node_modules/postman-sandbox/lib/bundle/index.js
generated
vendored
Normal file
138
node_modules/postman-sandbox/lib/bundle/index.js
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
const _ = require('lodash'),
|
||||
{ minify } = require('terser'),
|
||||
|
||||
bundlingOptions = require('./bundling-options'),
|
||||
|
||||
PREFER_BUILTIN = 'preferBuiltin',
|
||||
|
||||
/**
|
||||
* To unite components of path in holy matrimony!
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
pathJoin = function () {
|
||||
return Array.prototype.join.call(arguments, '/').replace(/\/{1,}/g, '/');
|
||||
};
|
||||
|
||||
let browserify, // loaded inside try-catch
|
||||
browserifyBuiltins; // loaded inside try-catch
|
||||
|
||||
// The modules for browserification should only be required during development of this module and as such a production
|
||||
// installation should not even trigger require of this module. But in case it does, let's make the error message a bit
|
||||
// more consumable.
|
||||
try {
|
||||
browserify = require('browserify');
|
||||
browserifyBuiltins = require('browserify/lib/builtins');
|
||||
}
|
||||
catch (e) {
|
||||
console && console.error('sandbox: bundling triggered in production module installation mode');
|
||||
throw e;
|
||||
}
|
||||
|
||||
class Bundle {
|
||||
/**
|
||||
* Create a bundle from an options template
|
||||
*
|
||||
* @param {Object} options -
|
||||
* @param {Object} options.files -
|
||||
* @param {Object.<Object>} options.require -
|
||||
* @param {Boolean} options.require.global -
|
||||
* @param {Boolean} options.require.preferBuiltin -
|
||||
* @param {String} options.require.resolve -
|
||||
* @param {String} options.require.expose -
|
||||
* @param {Boolean|Object} options.compress -
|
||||
* @param {Array.<String>} options.ignore -
|
||||
* @param {Object=} [options.bundler] -
|
||||
*/
|
||||
constructor (options) {
|
||||
/**
|
||||
* @private
|
||||
* @type {Browserify}
|
||||
*/
|
||||
this.bundler = browserify({ ...bundlingOptions, ...options.bundler }); // merge with user options
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.compress = options.compress;
|
||||
|
||||
// process any list of modules externally required and also accommodate the use of built-ins if needed
|
||||
_.forEach(options.require, (options, resolve) => {
|
||||
// allow resolution override where the required module is resolved
|
||||
// from a different name than the one provided in options
|
||||
options.resolve && (resolve = options.resolve);
|
||||
|
||||
// set the name using which the module is exported to the one marked as the module name (only in case when
|
||||
// one is not explicitly provided in options.)
|
||||
!options.expose && (options.expose = resolve);
|
||||
|
||||
if (_.get(options, PREFER_BUILTIN) && _.has(browserifyBuiltins, resolve)) { // @todo: add tests
|
||||
this.bundler.require(browserifyBuiltins[resolve], options);
|
||||
}
|
||||
else {
|
||||
this.bundler.require(require.resolve(resolve), options); // @todo: add tests for resolve failures
|
||||
}
|
||||
});
|
||||
|
||||
// ignore the items mentioned in ignore list
|
||||
_.forEach(options.ignore, this.bundler.ignore.bind(this.bundler));
|
||||
|
||||
// add files that are needed
|
||||
_.forEach(options.files, (options, file) => {
|
||||
this.bundler.add(pathJoin(__dirname, file), options);
|
||||
});
|
||||
}
|
||||
|
||||
compile (done) {
|
||||
this.bundler.bundle((err, bundle) => {
|
||||
if (err) { return done(err); }
|
||||
|
||||
// bail out if compression is disabled
|
||||
if (!this.compress) { return done(null, bundle.toString()); }
|
||||
|
||||
minify(bundle.toString(), {
|
||||
compress: {
|
||||
drop_console: true // discard calls to console.* functions
|
||||
},
|
||||
mangle: true, // Mangle names
|
||||
safari10: true, // Work around the Safari 10/11 await bug (bugs.webkit.org/show_bug.cgi?id=176685)
|
||||
keep_fnames: /Postman.*/, // Prevent discarding or mangling of function names like "Postman*"
|
||||
keep_classnames: /Postman.*/, // Prevent discarding or mangling of class names like "Postman*"
|
||||
format: {
|
||||
comments: false // Omit comments in the output
|
||||
// @note ascii_only is disabled since postman-sandbox v4
|
||||
// ascii_only: true, // Unicode characters in strings and regexps
|
||||
}
|
||||
}).then(({ code }) => {
|
||||
done(null, code);
|
||||
}).catch(done);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows one to fetch a list of dependencies required by the bundle
|
||||
*
|
||||
* @param {Function} done - receives err, dependencies:Array
|
||||
*/
|
||||
listDependencies (done) {
|
||||
const dependencies = [],
|
||||
addPackageToDependencies = function (pkg) {
|
||||
dependencies.push(pkg.name);
|
||||
};
|
||||
|
||||
this.bundler.on('package', addPackageToDependencies);
|
||||
|
||||
this.compile((err) => {
|
||||
this.bundler.removeListener('package', addPackageToDependencies);
|
||||
|
||||
return done(err, _.uniq(dependencies).sort());
|
||||
});
|
||||
}
|
||||
|
||||
static load (options) {
|
||||
return new Bundle(options);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Bundle;
|
43
node_modules/postman-sandbox/lib/environment.js
generated
vendored
Normal file
43
node_modules/postman-sandbox/lib/environment.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
module.exports = {
|
||||
bundler: {
|
||||
noParse: ['jquery']
|
||||
},
|
||||
require: {
|
||||
// builtins required by the libraries exposed for sandbox users
|
||||
events: { preferBuiltin: true, glob: true },
|
||||
path: { preferBuiltin: true, glob: true },
|
||||
timers: { preferBuiltin: true },
|
||||
_process: { preferBuiltin: true, glob: true },
|
||||
util: { preferBuiltin: true, glob: true },
|
||||
stream: { preferBuiltin: true, glob: true },
|
||||
string_decoder: { preferBuiltin: true, glob: true },
|
||||
buffer: { resolve: 'buffer/index.js', expose: 'buffer', glob: true },
|
||||
url: { preferBuiltin: true, glob: true },
|
||||
punycode: { preferBuiltin: true, glob: true },
|
||||
querystring: { preferBuiltin: true, glob: true },
|
||||
fs: { preferBuiltin: true },
|
||||
os: { preferBuiltin: true },
|
||||
'liquid-json': { expose: 'json', glob: true },
|
||||
'crypto-js': { glob: true },
|
||||
atob: { glob: true },
|
||||
btoa: { glob: true },
|
||||
ajv: { glob: true },
|
||||
tv4: { glob: true },
|
||||
xml2js: { glob: true },
|
||||
backbone: { glob: true },
|
||||
cheerio: { glob: true },
|
||||
assert: { resolve: 'assert/build/assert.js', expose: 'assert', glob: true },
|
||||
// expose has been set like this to make it easier to accommodate the async API later
|
||||
'csv-parse': { resolve: 'csv-parse/lib/sync', expose: 'csv-parse/lib/sync', glob: true },
|
||||
'postman-collection': { expose: 'postman-collection', glob: true },
|
||||
uuid: { resolve: '../vendor/uuid', expose: 'uuid', glob: true },
|
||||
chai: { glob: true },
|
||||
moment: { resolve: 'moment/min/moment.min', expose: 'moment', glob: true },
|
||||
lodash: { glob: true }
|
||||
},
|
||||
ignore: ['aws4', 'hawk', 'node-oauth1'],
|
||||
files: {
|
||||
'../vendor/sugar': true, // sugar is tricky as module. hence included as vendor.
|
||||
'../sandbox': true
|
||||
}
|
||||
};
|
170
node_modules/postman-sandbox/lib/index.js
generated
vendored
Normal file
170
node_modules/postman-sandbox/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
const _ = require('lodash'),
|
||||
uuid = require('./vendor/uuid'),
|
||||
UniversalVM = require('uvm'),
|
||||
PostmanEvent = require('postman-collection').Event,
|
||||
teleportJS = require('teleport-javascript'),
|
||||
bootcode = require('./bootcode'),
|
||||
|
||||
TO_WAIT_BUFFER = 500, // time to wait for sandbox to declare timeout
|
||||
EXECUTION_TIMEOUT_ERROR_MESSAGE = 'sandbox not responding',
|
||||
BRIDGE_DISCONNECTING_ERROR_MESSAGE = 'sandbox: execution interrupted, bridge disconnecting.';
|
||||
|
||||
class PostmanSandbox extends UniversalVM {
|
||||
constructor () {
|
||||
super();
|
||||
|
||||
this._executing = {};
|
||||
}
|
||||
|
||||
initialize (options, callback) {
|
||||
// ensure options is an object and is shallow cloned
|
||||
options = _.assign({}, options);
|
||||
this.debug = Boolean(options.debug);
|
||||
|
||||
// set the dispatch timeout of UVM based on what is set in options unless original options sends the same
|
||||
_.isFinite(options.timeout) && (options.dispatchTimeout = this.executionTimeout = options.timeout);
|
||||
|
||||
super.connect(options, (err, context) => {
|
||||
if (err) { return callback(err); }
|
||||
context.ping((err) => {
|
||||
// eslint-disable-next-line callback-return
|
||||
callback(err, context);
|
||||
context = null;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ping (callback) {
|
||||
const packet = uuid(),
|
||||
start = Date.now();
|
||||
|
||||
this.once('pong', (echo) => {
|
||||
callback((echo !== packet ? new Error('sandbox: ping packet mismatch') : null), Date.now() - start, packet);
|
||||
});
|
||||
|
||||
this.dispatch('ping', packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Event|String} target - can optionally be the code to execute
|
||||
* @param {Object} options -
|
||||
* @param {String} options.id -
|
||||
* @param {Boolean} options.debug -
|
||||
* @param {Number} options.timeout -
|
||||
* @param {Object} options.cursor -
|
||||
* @param {Object} options.context -
|
||||
* @param {Boolean} options.serializeLogs -
|
||||
* @param {Function} callback -
|
||||
*/
|
||||
execute (target, options, callback) {
|
||||
if (_.isFunction(options) && !callback) {
|
||||
callback = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
!_.isObject(options) && (options = {});
|
||||
!_.isFunction(callback) && (callback = _.noop);
|
||||
|
||||
// if the target is simple code, we make a generic event out of it
|
||||
if (_.isString(target) || _.isArray(target)) {
|
||||
target = new PostmanEvent({ script: target });
|
||||
}
|
||||
// if target is not a code and instead is not something that can be cast to an event, it is definitely an error
|
||||
else if (!_.isObject(target)) {
|
||||
return callback(new Error('sandbox: no target provided for execution'));
|
||||
}
|
||||
|
||||
const id = _.isString(options.id) ? options.id : uuid(),
|
||||
executionEventName = 'execution.result.' + id,
|
||||
consoleEventName = 'execution.console.' + id,
|
||||
executionTimeout = _.get(options, 'timeout', this.executionTimeout),
|
||||
cursor = _.clone(_.get(options, 'cursor', {})), // clone the cursor as it travels through IPC for mutation
|
||||
debugMode = _.has(options, 'debug') ? options.debug : this.debug;
|
||||
|
||||
let waiting;
|
||||
|
||||
// set the execution id in cursor
|
||||
cursor.execution = id;
|
||||
|
||||
// set execution timeout and store the interrupt in a global object (so that we can clear during dispose)
|
||||
// force trigger of the `execution.${id}` event so that the normal error flow is taken
|
||||
this._executing[id] = _.isFinite(executionTimeout) ? (waiting = setTimeout(() => {
|
||||
waiting = null;
|
||||
this.emit.bind(executionEventName, new Error(EXECUTION_TIMEOUT_ERROR_MESSAGE));
|
||||
}, executionTimeout + TO_WAIT_BUFFER)) : null;
|
||||
|
||||
// @todo decide how the results will return in a more managed fashion
|
||||
// listen to this once, so that subsequent calls are simply dropped. especially during timeout and other
|
||||
// errors
|
||||
this.once(executionEventName, (err, result) => {
|
||||
waiting && (waiting = clearTimeout(waiting)); // clear timeout interrupt
|
||||
if (Object.hasOwnProperty.call(this._executing, id)) { // clear any pending timeouts
|
||||
this._executing[id] && clearTimeout(this._executing[id]);
|
||||
delete this._executing[id];
|
||||
}
|
||||
|
||||
this.emit('execution', err, id, result);
|
||||
callback(err, result);
|
||||
});
|
||||
|
||||
this.on(consoleEventName, (cursor, level, args) => {
|
||||
if (_.get(options, 'serializeLogs')) {
|
||||
return this.emit('console', cursor, level, args);
|
||||
}
|
||||
|
||||
args = teleportJS.parse(args);
|
||||
args.unshift('console', cursor, level);
|
||||
|
||||
// eslint-disable-next-line prefer-spread
|
||||
this.emit.apply(this, args);
|
||||
});
|
||||
|
||||
// send the code to the sandbox to be intercepted and executed
|
||||
this.dispatch('execute', id, target, _.get(options, 'context', {}), {
|
||||
cursor: cursor,
|
||||
debug: debugMode,
|
||||
timeout: executionTimeout,
|
||||
legacy: _.get(options, 'legacy')
|
||||
});
|
||||
}
|
||||
|
||||
dispose () {
|
||||
_.forEach(this._executing, (irq, id) => {
|
||||
irq && clearTimeout(irq);
|
||||
|
||||
// send an abort event to the sandbox so that it can do cleanups
|
||||
this.dispatch('execution.abort.' + id);
|
||||
|
||||
// even though sandbox could bubble the result event upon receiving abort, that would reduce
|
||||
// stability of the system in case sandbox was unresponsive.
|
||||
this.emit('execution.result.' + id, new Error(BRIDGE_DISCONNECTING_ERROR_MESSAGE));
|
||||
});
|
||||
|
||||
this.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Creates a new instance of sandbox from the options that have been provided
|
||||
*
|
||||
* @param {Object=} [options] -
|
||||
* @param {Function} callback -
|
||||
*/
|
||||
createContext (options, callback) {
|
||||
if (_.isFunction(options) && !callback) {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
options = _.clone(options);
|
||||
bootcode((err, code) => {
|
||||
if (err) { return callback(err); }
|
||||
if (!code) { return callback(new Error('sandbox: bootcode missing!')); }
|
||||
|
||||
options.bootCode = code; // assign the code in options
|
||||
|
||||
new PostmanSandbox().initialize(options, callback);
|
||||
});
|
||||
}
|
||||
};
|
66
node_modules/postman-sandbox/lib/sandbox/console.js
generated
vendored
Normal file
66
node_modules/postman-sandbox/lib/sandbox/console.js
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
var teleportJS = require('teleport-javascript'),
|
||||
|
||||
arrayProtoSlice = Array.prototype.slice,
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @type {String}
|
||||
*/
|
||||
CONSOLE_EVENT_BASE = 'execution.console.',
|
||||
|
||||
/**
|
||||
* List of functions that we expect and create for console
|
||||
*
|
||||
* @constant
|
||||
* @type {String[]}
|
||||
*/
|
||||
logLevels = ['log', 'warn', 'debug', 'info', 'error'];
|
||||
|
||||
/**
|
||||
* Replacer to be used with teleport-javascript to handle cases which are not
|
||||
* handled by it.
|
||||
*
|
||||
* @param {String} key - Key of the property to replace
|
||||
* @param {Any} value - Value of property to replace
|
||||
* @return {Any} Replaced value
|
||||
*/
|
||||
function replacer (key, value) {
|
||||
if (typeof value === 'function') {
|
||||
const fnType = (value.constructor && value.constructor.name) ?
|
||||
value.constructor.name : 'Function';
|
||||
|
||||
return value.name ? `[${fnType}: ${value.name}]` : `[${fnType}]`;
|
||||
}
|
||||
|
||||
if (value instanceof WeakMap) {
|
||||
return '[WeakMap]';
|
||||
}
|
||||
else if (value instanceof WeakSet) {
|
||||
return '[WeakSet]';
|
||||
}
|
||||
else if (value instanceof ArrayBuffer) {
|
||||
return `[ArrayBuffer { byteLength: ${value.byteLength} }]`;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
function PostmanConsole (emitter, id, cursor, originalConsole) {
|
||||
const dispatch = function (level) { // create a dispatch function that emits events
|
||||
const args = arrayProtoSlice.call(arguments, 1);
|
||||
|
||||
if (originalConsole) {
|
||||
// eslint-disable-next-line prefer-spread
|
||||
originalConsole[level].apply(originalConsole, args);
|
||||
}
|
||||
|
||||
emitter.dispatch(CONSOLE_EVENT_BASE + id, cursor, level, teleportJS.stringify(args, replacer));
|
||||
};
|
||||
|
||||
// setup variants of the logger based on log levels
|
||||
logLevels.forEach((name) => {
|
||||
this[name] = dispatch.bind(emitter, name);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = PostmanConsole;
|
367
node_modules/postman-sandbox/lib/sandbox/cookie-jar.js
generated
vendored
Normal file
367
node_modules/postman-sandbox/lib/sandbox/cookie-jar.js
generated
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
const CookieJar = require('tough-cookie').CookieJar,
|
||||
ToughCookie = require('tough-cookie').Cookie,
|
||||
PostmanCookie = require('postman-collection').Cookie,
|
||||
PostmanCookieList = require('postman-collection').CookieList,
|
||||
Url = require('postman-collection').Url,
|
||||
|
||||
FUNCTION = 'function',
|
||||
OBJECT = 'object',
|
||||
STRING = 'string',
|
||||
|
||||
/**
|
||||
* Convert PostmanCookie Cookie instance to ToughCookie instance.
|
||||
*
|
||||
* @private
|
||||
* @param {PostmanCookie} cookie - Postman Cookie instance
|
||||
* @returns {ToughCookie} Tough Cookie instance
|
||||
*/
|
||||
serialize = function (cookie) {
|
||||
if (!cookie) {
|
||||
return;
|
||||
}
|
||||
|
||||
return ToughCookie.fromJSON({
|
||||
key: cookie.name || cookie.key,
|
||||
value: cookie.value,
|
||||
expires: cookie.expires,
|
||||
maxAge: cookie.maxAge,
|
||||
domain: cookie.domain,
|
||||
path: cookie.path,
|
||||
secure: cookie.secure,
|
||||
httpOnly: cookie.httpOnly,
|
||||
hostOnly: cookie.hostOnly,
|
||||
extensions: cookie.extensions
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert Tough Cookie instance to Electron Cookie instance.
|
||||
*
|
||||
* @private
|
||||
* @param {ToughCookie} cookie - Tough Cookie instance
|
||||
* @returns {ElectronCookie} Electron Cookie instance
|
||||
*/
|
||||
deserialize = function (cookie) {
|
||||
if (!cookie) {
|
||||
return;
|
||||
}
|
||||
|
||||
return new PostmanCookie({
|
||||
name: cookie.key,
|
||||
value: cookie.value,
|
||||
expires: cookie.expires === 'Infinity' ? null : cookie.expires,
|
||||
maxAge: cookie.maxAge,
|
||||
domain: cookie.domain,
|
||||
path: cookie.path,
|
||||
secure: cookie.secure,
|
||||
httpOnly: cookie.httpOnly,
|
||||
hostOnly: cookie.hostOnly,
|
||||
extensions: cookie.extensions
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Sanitize url object or string to Postman Url instance.
|
||||
*
|
||||
* @private
|
||||
* @param {Object|String} url -
|
||||
* @returns {Url|Null}
|
||||
*/
|
||||
sanitizeURL = function (url) {
|
||||
if (Url.isUrl(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (url && typeof url === STRING) {
|
||||
return new Url(url);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Executes a provided function once for each array element.
|
||||
*
|
||||
* @note not completely asynchronous, don't compare with async.each
|
||||
*
|
||||
* @private
|
||||
* @param {Array} items - Array of items to iterate over
|
||||
* @param {Function} fn - An async function to apply to each item in items
|
||||
* @param {Function} cb - A callback which is called when all iteratee functions have finished,
|
||||
* or an error occurs
|
||||
*/
|
||||
forEachWithCallback = function (items, fn, cb) {
|
||||
!cb && (cb = function () { /* (ಠ_ಠ) */ });
|
||||
|
||||
if (!(Array.isArray(items) && fn)) { return cb(); }
|
||||
|
||||
var index = 0,
|
||||
totalItems = items.length,
|
||||
next = function (err) {
|
||||
if (err || index >= totalItems) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
try {
|
||||
fn.call(items, items[index++], next);
|
||||
}
|
||||
catch (error) {
|
||||
return cb(error);
|
||||
}
|
||||
};
|
||||
|
||||
if (!totalItems) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
next();
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function to handle callback.
|
||||
*
|
||||
* @private
|
||||
* @param {Function} callback - Callback function
|
||||
* @param {Error|String} err - Error or Error message
|
||||
* @param {*} result -
|
||||
*/
|
||||
callbackHandler = function (callback, err, result) {
|
||||
if (typeof callback !== FUNCTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
return callback(err instanceof Error ? err : new Error(err));
|
||||
}
|
||||
|
||||
callback(null, result);
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function to fetch a cookie with given name.
|
||||
*
|
||||
* @private
|
||||
* @todo add CookieJar~getCookie to avoid this
|
||||
*
|
||||
* @param {CookieJar} jar - ToughCookie jar instance
|
||||
* @param {String} url - Url string
|
||||
* @param {String} name - Cookie name
|
||||
* @param {Function} callback - Callback function
|
||||
*/
|
||||
getCookie = function (jar, url, name, callback) {
|
||||
jar.getCookies(url, function (err, cookies) {
|
||||
var i,
|
||||
ii;
|
||||
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (!(cookies && cookies.length)) {
|
||||
return callback(null, null);
|
||||
}
|
||||
|
||||
for (i = 0, ii = cookies.length; i < ii; i++) {
|
||||
if (cookies[i].key === name) {
|
||||
return callback(null, cookies[i]);
|
||||
}
|
||||
}
|
||||
|
||||
callback(null, null);
|
||||
});
|
||||
};
|
||||
|
||||
class PostmanCookieJar {
|
||||
/**
|
||||
* @param {Object} cookieStore -
|
||||
*/
|
||||
constructor (cookieStore) {
|
||||
this.store = cookieStore;
|
||||
this.jar = new CookieJar(cookieStore, {
|
||||
rejectPublicSuffixes: false,
|
||||
looseMode: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cookie value with the given name.
|
||||
*
|
||||
* @param {String} url -
|
||||
* @param {String} name -
|
||||
* @param {Function} callback -
|
||||
*/
|
||||
get (url, name, callback) {
|
||||
url = sanitizeURL(url);
|
||||
|
||||
if (!url) {
|
||||
throw new TypeError('CookieJar.get() requires a valid url');
|
||||
}
|
||||
|
||||
if (typeof callback !== FUNCTION) {
|
||||
throw new TypeError('CookieJar.get() requires a callback function');
|
||||
}
|
||||
|
||||
if (typeof name !== STRING) {
|
||||
throw new TypeError('CookieJar.get() requires cookie name to be a string');
|
||||
}
|
||||
|
||||
getCookie(this.jar, url.toString(true), name, function (err, cookie) {
|
||||
if (err || !cookie) {
|
||||
return callbackHandler(callback, err, null);
|
||||
}
|
||||
|
||||
cookie = deserialize(cookie);
|
||||
|
||||
return callbackHandler(callback, null, cookie.valueOf());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the cookies for the given URL.
|
||||
*
|
||||
* @param {String} url -
|
||||
* @param {Object} [options] -
|
||||
* @param {Function} callback -
|
||||
*/
|
||||
getAll (url, options, callback) {
|
||||
url = sanitizeURL(url);
|
||||
|
||||
if (!url) {
|
||||
throw new TypeError('CookieJar.getAll() requires a valid url');
|
||||
}
|
||||
|
||||
if (typeof options === FUNCTION && !callback) {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (typeof callback !== FUNCTION) {
|
||||
throw new TypeError('CookieJar.getAll() requires a callback function');
|
||||
}
|
||||
|
||||
if (typeof options !== OBJECT) {
|
||||
throw new TypeError('CookieJar.getAll() requires options to be an object');
|
||||
}
|
||||
|
||||
options = {
|
||||
// return HttpOnly cookies by default
|
||||
http: Object.hasOwnProperty.call(options, 'http') ? Boolean(options.http) : true,
|
||||
// if undefined, auto-detect from url
|
||||
secure: Object.hasOwnProperty.call(options, 'secure') ? Boolean(options.secure) : undefined
|
||||
};
|
||||
|
||||
this.jar.getCookies(url.toString(true), options, function (err, cookies) {
|
||||
if (err) {
|
||||
return callbackHandler(callback, err);
|
||||
}
|
||||
|
||||
callbackHandler(callback, null, new PostmanCookieList(null, cookies && cookies.map(deserialize)));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or update a cookie.
|
||||
*
|
||||
* @param {String} url -
|
||||
* @param {String|Object} name -
|
||||
* @param {String|Function} [value] -
|
||||
* @param {Function} [callback] -
|
||||
*/
|
||||
set (url, name, value, callback) {
|
||||
url = sanitizeURL(url);
|
||||
|
||||
if (!url) {
|
||||
throw new TypeError('CookieJar.set() requires a valid url');
|
||||
}
|
||||
|
||||
if (typeof value === FUNCTION && !callback) {
|
||||
callback = value;
|
||||
value = null;
|
||||
}
|
||||
|
||||
var cookie;
|
||||
|
||||
// @todo avoid else-if to reduce cyclomatic complexity
|
||||
if (name && value) {
|
||||
cookie = serialize({ name, value });
|
||||
}
|
||||
else if (typeof name === OBJECT) {
|
||||
cookie = serialize(name);
|
||||
}
|
||||
else if (typeof name === STRING) {
|
||||
cookie = name;
|
||||
}
|
||||
else {
|
||||
throw new TypeError('CookieJar.set() requires a valid set cookie arguments');
|
||||
}
|
||||
|
||||
this.jar.setCookie(cookie, url.toString(true), function (err, cookie) {
|
||||
if (err) {
|
||||
return callbackHandler(callback, err);
|
||||
}
|
||||
|
||||
callbackHandler(callback, null, deserialize(cookie));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove single cookie with the given name.
|
||||
*
|
||||
* @param {String} url -
|
||||
* @param {String} name -
|
||||
* @param {Function} [callback] -
|
||||
*/
|
||||
unset (url, name, callback) {
|
||||
url = sanitizeURL(url);
|
||||
|
||||
if (!url) {
|
||||
throw new TypeError('CookieJar.unset() requires a valid url');
|
||||
}
|
||||
|
||||
if (typeof name !== STRING) {
|
||||
throw new TypeError('CookieJar.unset() requires cookie name to be a string');
|
||||
}
|
||||
|
||||
var store = this.store;
|
||||
|
||||
getCookie(this.jar, url.toString(true), name, function (err, cookie) {
|
||||
if (err || !cookie) {
|
||||
return callbackHandler(callback, err);
|
||||
}
|
||||
|
||||
store.removeCookie(cookie.domain, cookie.path, cookie.key, function (err) {
|
||||
callbackHandler(callback, err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all the cookies for the given URL.
|
||||
*
|
||||
* @param {String} url -
|
||||
* @param {Function} [callback] -
|
||||
*/
|
||||
clear (url, callback) {
|
||||
url = sanitizeURL(url);
|
||||
|
||||
if (!url) {
|
||||
throw new TypeError('CookieJar.clear() requires a valid url');
|
||||
}
|
||||
|
||||
var store = this.store;
|
||||
|
||||
this.jar.getCookies(url.toString(true), function (err, cookies) {
|
||||
if (err || !cookies) {
|
||||
return callbackHandler(callback, err);
|
||||
}
|
||||
|
||||
forEachWithCallback(cookies, function (cookie, next) {
|
||||
store.removeCookie(cookie.domain, cookie.path, cookie.key, next);
|
||||
}, function (err) {
|
||||
callbackHandler(callback, err);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PostmanCookieJar;
|
77
node_modules/postman-sandbox/lib/sandbox/cookie-store.js
generated
vendored
Normal file
77
node_modules/postman-sandbox/lib/sandbox/cookie-store.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
const _ = require('lodash'),
|
||||
|
||||
Store = require('tough-cookie').Store,
|
||||
Cookie = require('tough-cookie').Cookie,
|
||||
|
||||
EXECUTION_EVENT_BASE = 'execution.cookies.',
|
||||
EVENT_STORE_ACTION = 'store',
|
||||
STORE_METHODS = [
|
||||
'findCookie', 'findCookies', 'putCookie', 'updateCookie',
|
||||
'removeCookie', 'removeCookies', 'removeAllCookies', 'getAllCookies'
|
||||
],
|
||||
FUNCTION = 'function',
|
||||
|
||||
arrayProtoSlice = Array.prototype.slice;
|
||||
|
||||
class PostmanCookieStore extends Store {
|
||||
constructor (id, emitter, timers) {
|
||||
super();
|
||||
|
||||
this.id = id; // execution identifier
|
||||
this.emitter = emitter;
|
||||
this.timers = timers;
|
||||
}
|
||||
}
|
||||
|
||||
// Disable CookieJar's *Sync APIs
|
||||
PostmanCookieStore.prototype.synchronous = false;
|
||||
|
||||
// attach a common handler to all store methods
|
||||
STORE_METHODS.forEach(function (method) {
|
||||
PostmanCookieStore.prototype[method] = function () {
|
||||
const eventName = EXECUTION_EVENT_BASE + this.id;
|
||||
let args,
|
||||
eventId,
|
||||
callback;
|
||||
|
||||
// fetch all the arguments passed to the method
|
||||
args = arrayProtoSlice.call(arguments);
|
||||
|
||||
// adjust arguments length based on Store's prototype method
|
||||
// eslint-disable-next-line lodash/path-style
|
||||
args.length = _.get(Store.prototype, [method, 'length'], 0);
|
||||
|
||||
// move callback/last argument out of arguments
|
||||
// this will be called when timer clears the event
|
||||
callback = args.pop();
|
||||
|
||||
// set event for the callback
|
||||
eventId = this.timers.setEvent(function (err, cookies) {
|
||||
if (typeof callback !== FUNCTION) {
|
||||
throw new TypeError('callback is not a function');
|
||||
}
|
||||
|
||||
// methods: putCookie, updateCookie, removeCookie, removeCookies,
|
||||
// removeAllCookies
|
||||
// or, onError
|
||||
if (err || !cookies) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// methods: findCookies, getAllCookies
|
||||
if (Array.isArray(cookies)) {
|
||||
return callback(err, cookies.map(function (cookie) {
|
||||
return Cookie.fromJSON(cookie); // serialize cookie object
|
||||
}));
|
||||
}
|
||||
|
||||
// method: findCookie
|
||||
callback(err, Cookie.fromJSON(cookies));
|
||||
});
|
||||
|
||||
// finally, dispatch event over the bridge
|
||||
this.emitter.dispatch(eventName, eventId, EVENT_STORE_ACTION, method, args);
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = PostmanCookieStore;
|
68
node_modules/postman-sandbox/lib/sandbox/execute-context.js
generated
vendored
Normal file
68
node_modules/postman-sandbox/lib/sandbox/execute-context.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
const _ = require('lodash'),
|
||||
legacy = require('./postman-legacy-interface'),
|
||||
|
||||
NONLEGACY_SANDBOX_MARKERS = {
|
||||
'"use sandbox2";': true,
|
||||
'\'use sandbox2\';': true
|
||||
};
|
||||
|
||||
module.exports = function (scope, code, execution, console, timers, pmapi, onAssertion) {
|
||||
// if there is no code, then no point bubbling anything up
|
||||
if (!(code && _.isString(code))) {
|
||||
return timers.terminate();
|
||||
}
|
||||
|
||||
// start by resetting the scope
|
||||
scope.reset();
|
||||
|
||||
if (NONLEGACY_SANDBOX_MARKERS[code.substr(0, 15)]) {
|
||||
// ensure any previously added global variables from legacy are torn down. side-effect is that if user
|
||||
// explicitly created global variables with same name as legacy ones, they will be torn down too!
|
||||
// for that reason, the setup function tags the scope and avoids tearing down an scope that was never setup
|
||||
legacy.teardown(scope);
|
||||
}
|
||||
else {
|
||||
// prepare legacy environment, which adds a tonne of global variables
|
||||
legacy.setup(scope, execution);
|
||||
}
|
||||
|
||||
// prepare the scope's environment variables
|
||||
scope.import({
|
||||
Buffer: require('buffer').Buffer,
|
||||
// forward console
|
||||
console: console,
|
||||
// forward pm-api instance
|
||||
/**
|
||||
* The pm object encloses all information pertaining to the script being executed and
|
||||
* allows one to access a copy of the request being sent or the response received.
|
||||
* It also allows one to get and set environment and global variables.
|
||||
*
|
||||
* @type {Postman}
|
||||
*/
|
||||
pm: pmapi,
|
||||
// import the timers
|
||||
setTimeout: timers.setTimeout,
|
||||
setInterval: timers.setInterval,
|
||||
setImmediate: timers.setImmediate,
|
||||
clearTimeout: timers.clearTimeout,
|
||||
clearInterval: timers.clearInterval,
|
||||
clearImmediate: timers.clearImmediate
|
||||
});
|
||||
|
||||
scope.exec(code, function (err) {
|
||||
// we check if the execution went async by determining the timer queue length at this time
|
||||
execution.return.async = (timers.queueLength() > 0);
|
||||
|
||||
// call this hook to perform any post script execution tasks
|
||||
legacy.finish(scope, pmapi, onAssertion);
|
||||
|
||||
// if timers are running, we do not need to proceed with any logic of completing execution. instead we wait
|
||||
// for timer completion callback to fire
|
||||
if (execution.return.async) {
|
||||
return err && timers.error(err); // but if we had error, we pass it to async error handler
|
||||
}
|
||||
|
||||
// at this stage, the script is a synchronous script, we simply forward whatever has come our way
|
||||
timers.terminate(err);
|
||||
});
|
||||
};
|
163
node_modules/postman-sandbox/lib/sandbox/execute.js
generated
vendored
Normal file
163
node_modules/postman-sandbox/lib/sandbox/execute.js
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
const _ = require('lodash'),
|
||||
Scope = require('uniscope'),
|
||||
PostmanEvent = require('postman-collection').Event,
|
||||
Execution = require('./execution'),
|
||||
PostmanConsole = require('./console'),
|
||||
PostmanTimers = require('./timers'),
|
||||
PostmanAPI = require('./pmapi'),
|
||||
PostmanCookieStore = require('./cookie-store'),
|
||||
|
||||
EXECUTION_RESULT_EVENT_BASE = 'execution.result.',
|
||||
EXECUTION_REQUEST_EVENT_BASE = 'execution.request.',
|
||||
EXECUTION_ERROR_EVENT = 'execution.error',
|
||||
EXECUTION_ERROR_EVENT_BASE = 'execution.error.',
|
||||
EXECUTION_ABORT_EVENT_BASE = 'execution.abort.',
|
||||
EXECUTION_RESPONSE_EVENT_BASE = 'execution.response.',
|
||||
EXECUTION_COOKIES_EVENT_BASE = 'execution.cookies.',
|
||||
EXECUTION_ASSERTION_EVENT = 'execution.assertion',
|
||||
EXECUTION_ASSERTION_EVENT_BASE = 'execution.assertion.',
|
||||
|
||||
executeContext = require('./execute-context');
|
||||
|
||||
module.exports = function (bridge, glob) {
|
||||
// @note we use a common scope for all executions. this causes issues when scripts are run inside the sandbox
|
||||
// in parallel, but we still use this way for the legacy "persistent" behaviour needed in environment
|
||||
const scope = Scope.create({
|
||||
eval: true,
|
||||
ignore: ['require'],
|
||||
block: ['bridge']
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {String} id
|
||||
* @param {Event} event
|
||||
* @param {Object} context
|
||||
* @param {Object} options
|
||||
* @param {Boolean=} [options.debug]
|
||||
* @param {Object=} [options.cursor]
|
||||
* @param {Number=} [options.timeout]
|
||||
*
|
||||
* @note
|
||||
* options also take in legacy properties: _itemId, _itemName
|
||||
*/
|
||||
bridge.on('execute', function (id, event, context, options) {
|
||||
if (!(id && _.isString(id))) {
|
||||
return bridge.dispatch('error', new Error('sandbox: execution identifier parameter(s) missing'));
|
||||
}
|
||||
|
||||
!options && (options = {});
|
||||
!context && (context = {});
|
||||
event = (new PostmanEvent(event));
|
||||
|
||||
const executionEventName = EXECUTION_RESULT_EVENT_BASE + id,
|
||||
executionRequestEventName = EXECUTION_REQUEST_EVENT_BASE + id,
|
||||
errorEventName = EXECUTION_ERROR_EVENT_BASE + id,
|
||||
abortEventName = EXECUTION_ABORT_EVENT_BASE + id,
|
||||
responseEventName = EXECUTION_RESPONSE_EVENT_BASE + id,
|
||||
cookiesEventName = EXECUTION_COOKIES_EVENT_BASE + id,
|
||||
assertionEventName = EXECUTION_ASSERTION_EVENT_BASE + id,
|
||||
|
||||
// extract the code from event. The event can be the code itself and we know that if the event is of type
|
||||
// string.
|
||||
code = _.isFunction(event.script && event.script.toSource) && event.script.toSource(),
|
||||
// create the execution object
|
||||
execution = new Execution(id, event, context, options),
|
||||
|
||||
/**
|
||||
* Dispatch assertions from `pm.test` or legacy `test` API.
|
||||
*
|
||||
* @private
|
||||
* @param {Object[]} assertions -
|
||||
* @param {String} assertions[].name -
|
||||
* @param {Number} assertions[].index -
|
||||
* @param {Object} assertions[].error -
|
||||
* @param {Boolean} assertions[].async -
|
||||
* @param {Boolean} assertions[].passed -
|
||||
* @param {Boolean} assertions[].skipped -
|
||||
*/
|
||||
dispatchAssertions = function (assertions) {
|
||||
// Legacy `test` API accumulates all the assertions and dispatches at once
|
||||
// whereas, `pm.test` dispatch on every single assertion.
|
||||
// For compatibility, dispatch the single assertion as an array.
|
||||
!Array.isArray(assertions) && (assertions = [assertions]);
|
||||
|
||||
bridge.dispatch(assertionEventName, options.cursor, assertions);
|
||||
bridge.dispatch(EXECUTION_ASSERTION_EVENT, options.cursor, assertions);
|
||||
};
|
||||
|
||||
let waiting,
|
||||
timers;
|
||||
|
||||
// create the controlled timers
|
||||
timers = new PostmanTimers(null, function (err) {
|
||||
if (err) { // propagate the error out of sandbox
|
||||
bridge.dispatch(errorEventName, options.cursor, err);
|
||||
bridge.dispatch(EXECUTION_ERROR_EVENT, options.cursor, err);
|
||||
}
|
||||
}, function () {
|
||||
execution.return.async = true;
|
||||
}, function (err, dnd) {
|
||||
// clear timeout tracking timer
|
||||
waiting && (waiting = clearTimeout(waiting));
|
||||
|
||||
// do not allow any more timers
|
||||
if (timers) {
|
||||
timers.seal();
|
||||
timers.clearAll();
|
||||
}
|
||||
|
||||
// remove listener of disconnection event
|
||||
bridge.off(abortEventName);
|
||||
bridge.off(responseEventName);
|
||||
|
||||
if (err) { // fire extra execution error event
|
||||
bridge.dispatch(errorEventName, options.cursor, err);
|
||||
bridge.dispatch(EXECUTION_ERROR_EVENT, options.cursor, err);
|
||||
}
|
||||
|
||||
// @note delete response from the execution object to avoid dispatching
|
||||
// the large response payload back due to performance reasons.
|
||||
execution.response && (delete execution.response);
|
||||
|
||||
// fire the execution completion event
|
||||
(dnd !== true) && bridge.dispatch(executionEventName, err || null, execution);
|
||||
});
|
||||
|
||||
// if a timeout is set, we must ensure that all pending timers are cleared and an execution timeout event is
|
||||
// triggered.
|
||||
_.isFinite(options.timeout) && (waiting = setTimeout(function () {
|
||||
timers.terminate(new Error('sandbox: ' +
|
||||
(execution.return.async ? 'asynchronous' : 'synchronous') + ' script execution timeout'));
|
||||
}, options.timeout));
|
||||
|
||||
// if an abort event is sent, compute cleanup and complete
|
||||
bridge.on(abortEventName, function () {
|
||||
timers.terminate(null, true);
|
||||
});
|
||||
|
||||
// handle response event from outside sandbox
|
||||
bridge.on(responseEventName, function (id, err, res, history) {
|
||||
timers.clearEvent(id, err, res, history);
|
||||
});
|
||||
|
||||
// handle cookies event from outside sandbox
|
||||
bridge.on(cookiesEventName, function (id, err, res) {
|
||||
timers.clearEvent(id, err, res);
|
||||
});
|
||||
|
||||
// send control to the function that executes the context and prepares the scope
|
||||
executeContext(scope, code, execution,
|
||||
// if a console is sent, we use it. otherwise this also prevents erroneous referencing to any console
|
||||
// inside this closure.
|
||||
(new PostmanConsole(bridge, id, options.cursor, options.debug && glob.console)),
|
||||
timers,
|
||||
(
|
||||
new PostmanAPI(execution, function (request, callback) {
|
||||
var eventId = timers.setEvent(callback);
|
||||
|
||||
bridge.dispatch(executionRequestEventName, options.cursor, id, eventId, request);
|
||||
}, dispatchAssertions, new PostmanCookieStore(id, bridge, timers))
|
||||
),
|
||||
dispatchAssertions);
|
||||
});
|
||||
};
|
85
node_modules/postman-sandbox/lib/sandbox/execution.js
generated
vendored
Normal file
85
node_modules/postman-sandbox/lib/sandbox/execution.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
const _ = require('lodash'),
|
||||
sdk = require('postman-collection'),
|
||||
|
||||
PROPERTY = {
|
||||
REQUEST: 'request',
|
||||
SCRIPT: 'script',
|
||||
DATA: 'data',
|
||||
COOKIES: 'cookies',
|
||||
RESPONSE: 'response'
|
||||
},
|
||||
|
||||
TARGETS_WITH_REQUEST = {
|
||||
test: true,
|
||||
prerequest: true
|
||||
},
|
||||
|
||||
TARGETS_WITH_RESPONSE = {
|
||||
test: true
|
||||
},
|
||||
|
||||
CONTEXT_VARIABLE_SCOPES = ['_variables', 'environment', 'collectionVariables', 'globals'],
|
||||
|
||||
trackingOptions = { autoCompact: true };
|
||||
|
||||
class Execution {
|
||||
constructor (id, event, context, options) {
|
||||
this.id = id;
|
||||
this.target = event.listen || PROPERTY.SCRIPT;
|
||||
this.legacy = options.legacy || {};
|
||||
this.cursor = _.isObject(options.cursor) ? options.cursor : {};
|
||||
|
||||
this.data = _.get(context, PROPERTY.DATA, {});
|
||||
this.cookies = new sdk.CookieList(null, context.cookies);
|
||||
|
||||
CONTEXT_VARIABLE_SCOPES.forEach((variableScope) => {
|
||||
// normalize variable scope instances
|
||||
this[variableScope] = sdk.VariableScope.isVariableScope(context[variableScope]) ?
|
||||
context[variableScope] : new sdk.VariableScope(context[variableScope]);
|
||||
|
||||
// enable change tracking
|
||||
this[variableScope].enableTracking(trackingOptions);
|
||||
});
|
||||
|
||||
if (TARGETS_WITH_REQUEST[this.target] || _.has(context, PROPERTY.REQUEST)) {
|
||||
/**
|
||||
* @note:
|
||||
* this reference is passed on as `pm.request`, pm api adds helper functions like `to` to `pm.request`
|
||||
* sandbox overrides collection Request.prototype.toJSON to remove helpers before toJSON, see `purse.js`
|
||||
*/
|
||||
this.request = sdk.Request.isRequest(context.request) ? context.request : new sdk.Request(context.request);
|
||||
}
|
||||
|
||||
if (TARGETS_WITH_RESPONSE[this.target] || _.has(context, PROPERTY.RESPONSE)) {
|
||||
/**
|
||||
* @note:
|
||||
* this reference is passed on as `pm.response`, pm api adds helper functions like `to` to `pm.response`
|
||||
* sandbox overrides collection Response.prototype.toJSON to remove helpers before toJSON, see `purse.js`
|
||||
*/
|
||||
this.response = sdk.Response.isResponse(context.response) ?
|
||||
context.response : new sdk.Response(context.response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} Return
|
||||
*
|
||||
* @property {Boolean} async - true if the executed script was async, false otherwise
|
||||
* @property {Visualizer} visualizer - visualizer data
|
||||
* @property {*} nextRequest - next request to send
|
||||
*/
|
||||
this.return = {};
|
||||
}
|
||||
|
||||
toJSON () {
|
||||
return _.mapValues(this, function (value) {
|
||||
// if there is no specific json serialiser, return the raw value
|
||||
if (!_.isFunction(value && value.toJSON)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return value.toJSON();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Execution;
|
73
node_modules/postman-sandbox/lib/sandbox/index.js
generated
vendored
Normal file
73
node_modules/postman-sandbox/lib/sandbox/index.js
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/**!
|
||||
* @license Copyright 2016 Postdot Technologies, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* This file is the Postman scripting sandbox's bootstrap code and would during module usage be exported as part of npm
|
||||
* cache and deployed for ease of use and performance improvements.
|
||||
*
|
||||
* @note
|
||||
* This file runs within Node and browser sandboxes and standard node aspects may not 100% apply
|
||||
*/
|
||||
/* global bridge */
|
||||
|
||||
// Although we execute the user code in a well-defined scope using the uniscope
|
||||
// module but still to cutoff the reference to the globally available properties
|
||||
// we sanitize the global scope by deleting the forbidden properties in this UVM
|
||||
// and create a secure sandboxed environment.
|
||||
// @note this is executed at the very beginning of the sandbox code to make sure
|
||||
// non of the dependency can keep a reference to a global property.
|
||||
// @note since this mutates the global scope, it's possible to mess-up as we
|
||||
// update our dependencies.
|
||||
(function recreatingTheUniverse () {
|
||||
var contextObject = this,
|
||||
// 1. allow all the uniscope allowed globals
|
||||
allowedGlobals = require('uniscope/lib/allowed-globals').concat([
|
||||
// 2. allow properties which can be controlled/ignored using uniscope
|
||||
'require', 'eval', 'console',
|
||||
// 3. allow uvm internals because these will be cleared by uvm itself at the end.
|
||||
// make sure any new property added in uvm firmware is allowed here as well.
|
||||
'bridge', '__uvm_emit', '__uvm_dispatch', '__uvm_addEventListener',
|
||||
// 4.allow all the timer methods
|
||||
'setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', 'setImmediate', 'clearImmediate'
|
||||
]),
|
||||
deleteProperty = function (key) {
|
||||
// directly delete the property without setting it to `null` or `undefined`
|
||||
// because a few properties in browser context breaks the sandbox.
|
||||
// @note non-configurable keys are not deleted.
|
||||
// eslint-disable-next-line lodash/prefer-includes
|
||||
allowedGlobals.indexOf(key) === -1 && delete contextObject[key];
|
||||
};
|
||||
|
||||
do {
|
||||
// delete all forbidden properties (including non-enumerable)
|
||||
Object.getOwnPropertyNames(contextObject).forEach(deleteProperty);
|
||||
// keep looking through the prototype chain until we reach the Object prototype
|
||||
// @note this deletes the constructor as well to make sure one can't recreate the same scope
|
||||
contextObject = Object.getPrototypeOf(contextObject);
|
||||
} while (contextObject && contextObject.constructor !== Object);
|
||||
}());
|
||||
|
||||
// do include json purse
|
||||
require('./purse');
|
||||
|
||||
// setup the ping-pong and execute routines
|
||||
bridge.on('ping', require('./ping').listener('pong'));
|
||||
|
||||
// initialise execution
|
||||
require('./execute')(bridge, {
|
||||
console: (typeof console !== 'undefined' ? console : null),
|
||||
window: (typeof window !== 'undefined' ? window : null)
|
||||
});
|
||||
|
||||
// We don't need direct access to the global bridge once it's part of execution closure.
|
||||
// eslint-disable-next-line no-global-assign, no-implicit-globals, no-delete-var
|
||||
bridge = undefined; delete bridge;
|
8
node_modules/postman-sandbox/lib/sandbox/ping.js
generated
vendored
Normal file
8
node_modules/postman-sandbox/lib/sandbox/ping.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
listener (pong) {
|
||||
return function (payload) {
|
||||
this.dispatch(pong, payload);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
135
node_modules/postman-sandbox/lib/sandbox/pmapi-setup-runner.js
generated
vendored
Normal file
135
node_modules/postman-sandbox/lib/sandbox/pmapi-setup-runner.js
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* @fileOverview
|
||||
*
|
||||
* This module externally sets up the test runner on pm api. Essentially, it does not know the insides of pm-api and
|
||||
* does the job completely from outside with minimal external dependency
|
||||
*/
|
||||
const FUNCTION = 'function';
|
||||
|
||||
/**
|
||||
* @module {PMAPI~setupTestRunner}
|
||||
* @private
|
||||
*
|
||||
* @param {PMAPI} pm - an instance of PM API that it needs
|
||||
* @param {Function} onAssertionComplete - is the trigger function that is called every time a test is executed and it
|
||||
* receives the AssertionInfo object outlining details of the assertion
|
||||
*/
|
||||
module.exports = function (pm, onAssertionComplete) {
|
||||
var assertionIndex = 0,
|
||||
|
||||
/**
|
||||
* Returns an object that represents data coming out of an assertion.
|
||||
*
|
||||
* @note This is put in a function since this needs to be done from a number of place and having a single
|
||||
* function reduces the chance of bugs
|
||||
*
|
||||
* @param {String} name -
|
||||
* @param {Boolean} skipped -
|
||||
*
|
||||
* @returns {PMAPI~AssertionInfo}
|
||||
*/
|
||||
getAssertionObject = function (name, skipped) {
|
||||
/**
|
||||
* @typeDef {AssertionInfo}
|
||||
* @private
|
||||
*/
|
||||
return {
|
||||
name: String(name),
|
||||
async: false,
|
||||
skipped: Boolean(skipped),
|
||||
passed: true,
|
||||
error: null,
|
||||
index: assertionIndex++ // increment the assertion counter (do it before asserting)
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Simple function to mark an assertion as failed
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @note This is put in a function since this needs to be done from a number of place and having a single
|
||||
* function reduces the chance of bugs
|
||||
*
|
||||
* @param {Object} assertionData -
|
||||
* @param {*} err -
|
||||
*/
|
||||
markAssertionAsFailure = function (assertionData, err) {
|
||||
assertionData.error = err;
|
||||
assertionData.passed = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} name -
|
||||
* @param {Function} assert -
|
||||
* @chainable
|
||||
*/
|
||||
pm.test = function (name, assert) {
|
||||
var assertionData = getAssertionObject(name, false);
|
||||
|
||||
// if there is no assertion function, we simply move on
|
||||
if (typeof assert !== FUNCTION) {
|
||||
onAssertionComplete(assertionData);
|
||||
|
||||
return pm;
|
||||
}
|
||||
|
||||
// if a callback function was sent, then we know that the test is asynchronous
|
||||
if (assert.length) {
|
||||
try {
|
||||
assertionData.async = true; // flag that this was an async test (would be useful later)
|
||||
|
||||
// we execute assertion, but pass it a completion function, which, in turn, raises the completion
|
||||
// event. we do not need to worry about timers here since we are assuming that some timer within the
|
||||
// sandbox had actually been the source of async calls and would take care of this
|
||||
assert(function (err) {
|
||||
// at first we double check that no synchronous error has happened from the catch block below
|
||||
if (assertionData.error && assertionData.passed === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// user triggered a failure of the assertion, so we mark it the same
|
||||
if (err) {
|
||||
markAssertionAsFailure(assertionData, err);
|
||||
}
|
||||
|
||||
onAssertionComplete(assertionData);
|
||||
});
|
||||
}
|
||||
// in case a synchronous error occurs in the the async assertion, we still bail out.
|
||||
catch (e) {
|
||||
markAssertionAsFailure(assertionData, e);
|
||||
onAssertionComplete(assertionData);
|
||||
}
|
||||
}
|
||||
// if the assertion function does not expect a callback, we synchronously execute the same
|
||||
else {
|
||||
try { assert(); }
|
||||
catch (e) {
|
||||
markAssertionAsFailure(assertionData, e);
|
||||
}
|
||||
|
||||
onAssertionComplete(assertionData);
|
||||
}
|
||||
|
||||
return pm; // make it chainable
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} name -
|
||||
* @chainable
|
||||
*/
|
||||
pm.test.skip = function (name) {
|
||||
// trigger the assertion events with skips
|
||||
onAssertionComplete(getAssertionObject(name, true));
|
||||
|
||||
return pm; // chainable
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {Number}
|
||||
*/
|
||||
pm.test.index = function () {
|
||||
return assertionIndex;
|
||||
};
|
||||
};
|
285
node_modules/postman-sandbox/lib/sandbox/pmapi.js
generated
vendored
Normal file
285
node_modules/postman-sandbox/lib/sandbox/pmapi.js
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
const _ = require('lodash'),
|
||||
Ajv = require('ajv'),
|
||||
sdk = require('postman-collection'),
|
||||
PostmanCookieJar = require('./cookie-jar'),
|
||||
VariableScope = sdk.VariableScope,
|
||||
PostmanRequest = sdk.Request,
|
||||
PostmanResponse = sdk.Response,
|
||||
PostmanCookieList = sdk.CookieList,
|
||||
chai = require('chai'),
|
||||
|
||||
/**
|
||||
* Use this function to assign readonly properties to an object
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param {Object} obj -
|
||||
* @param {Object} properties -
|
||||
*/
|
||||
_assignDefinedReadonly = function (obj, properties) {
|
||||
var config = {
|
||||
writable: false
|
||||
},
|
||||
|
||||
prop;
|
||||
|
||||
for (prop in properties) {
|
||||
if (Object.hasOwnProperty.call(properties, prop) && (properties[prop] !== undefined)) {
|
||||
config.value = properties[prop];
|
||||
Object.defineProperty(obj, prop, config);
|
||||
}
|
||||
}
|
||||
|
||||
return obj; // chainable
|
||||
},
|
||||
|
||||
setupTestRunner = require('./pmapi-setup-runner');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @param {Execution} execution -
|
||||
* @param {Function} onRequest -
|
||||
* @param {Function} onAssertion -
|
||||
* @param {Object} cookieStore -
|
||||
*/
|
||||
function Postman (execution, onRequest, onAssertion, cookieStore) {
|
||||
// @todo - ensure runtime passes data in a scope format
|
||||
let iterationData = new VariableScope();
|
||||
|
||||
iterationData.syncVariablesFrom(execution.data);
|
||||
|
||||
// instead of creating new instance of variableScope,
|
||||
// reuse one so that any changes made through pm.variables.set() is directly reflected
|
||||
execution._variables.addLayer(iterationData.values);
|
||||
execution._variables.addLayer(execution.environment.values);
|
||||
execution._variables.addLayer(execution.collectionVariables.values);
|
||||
execution._variables.addLayer(execution.globals.values);
|
||||
|
||||
execution.cookies && (execution.cookies.jar = function () {
|
||||
return new PostmanCookieJar(cookieStore);
|
||||
});
|
||||
|
||||
_assignDefinedReadonly(this, /** @lends Postman.prototype */ {
|
||||
/**
|
||||
* Contains information pertaining to the script execution
|
||||
*
|
||||
* @interface Info
|
||||
*/
|
||||
|
||||
/**
|
||||
* The pm.info object contains information pertaining to the script being executed.
|
||||
* Useful information such as the request name, request Id, and iteration count are
|
||||
* stored inside of this object.
|
||||
*
|
||||
* @type {Info}
|
||||
*/
|
||||
info: _assignDefinedReadonly({}, /** @lends Info */ {
|
||||
/**
|
||||
* Contains information whether the script being executed is a "prerequest" or a "test" script.
|
||||
*
|
||||
* @type {string}
|
||||
* @instance
|
||||
*/
|
||||
eventName: execution.target,
|
||||
|
||||
/**
|
||||
* Is the value of the current iteration being run.
|
||||
*
|
||||
* @type {number}
|
||||
* @instance
|
||||
*/
|
||||
iteration: execution.cursor.iteration,
|
||||
|
||||
/**
|
||||
* Is the total number of iterations that are scheduled to run.
|
||||
*
|
||||
* @type {number}
|
||||
* @instance
|
||||
*/
|
||||
iterationCount: execution.cursor.cycles,
|
||||
|
||||
/**
|
||||
* The saved name of the individual request being run.
|
||||
*
|
||||
* @type {string}
|
||||
* @instance
|
||||
*/
|
||||
requestName: execution.legacy._itemName,
|
||||
|
||||
/**
|
||||
* The unique guid that identifies the request being run.
|
||||
*
|
||||
* @type {string}
|
||||
* @instance
|
||||
*/
|
||||
requestId: execution.legacy._itemId
|
||||
}),
|
||||
|
||||
/**
|
||||
* @type {VariableScope}
|
||||
*/
|
||||
globals: execution.globals,
|
||||
|
||||
/**
|
||||
* @type {VariableScope}
|
||||
*/
|
||||
environment: execution.environment,
|
||||
|
||||
/**
|
||||
* @type {VariableScope}
|
||||
*/
|
||||
collectionVariables: execution.collectionVariables,
|
||||
|
||||
/**
|
||||
* @type {VariableScope}
|
||||
*/
|
||||
variables: execution._variables,
|
||||
|
||||
/**
|
||||
* The iterationData object contains data from the data file provided during a collection run.
|
||||
*
|
||||
* @type {VariableScope}
|
||||
*/
|
||||
iterationData: iterationData,
|
||||
|
||||
/**
|
||||
* The request object inside pm is a representation of the request for which this script is being run.
|
||||
* For a pre-request script, this is the request that is about to be sent and when in a test script,
|
||||
* this is the representation of the request that was sent.
|
||||
*
|
||||
* @type {Request}
|
||||
*/
|
||||
request: execution.request,
|
||||
|
||||
/**
|
||||
* Inside the test scripts, the pm.response object contains all information pertaining
|
||||
* to the response that was received.
|
||||
*
|
||||
* @type {Response}
|
||||
* @customexclude true
|
||||
*/
|
||||
response: execution.response,
|
||||
|
||||
/**
|
||||
* The cookies object contains a list of cookies that are associated with the domain
|
||||
* to which the request was made.
|
||||
*
|
||||
* @type {CookieList}
|
||||
*/
|
||||
cookies: execution.cookies,
|
||||
|
||||
/**
|
||||
* @interface Visualizer
|
||||
*/
|
||||
/**
|
||||
* @type {Visualizer}
|
||||
*/
|
||||
visualizer: /** @lends Visualizer */ {
|
||||
/**
|
||||
* Set visualizer template and its options
|
||||
*
|
||||
* @instance
|
||||
* @param {String} template - visualisation layout in form of template
|
||||
* @param {Object} [data] - data object to be used in template
|
||||
* @param {Object} [options] - options to use while processing the template
|
||||
*/
|
||||
set (template, data, options) {
|
||||
if (typeof template !== 'string') {
|
||||
throw new Error(`Invalid template. Template must be of type string, found ${typeof template}`);
|
||||
}
|
||||
|
||||
if (data && typeof data !== 'object') {
|
||||
throw new Error(`Invalid data. Data must be an object, found ${typeof data}`);
|
||||
}
|
||||
|
||||
if (options && typeof options !== 'object') {
|
||||
throw new Error(`Invalid options. Options must be an object, found ${typeof options}`);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @property {String} template - template string
|
||||
* @property {Object} data - data to use while processing template
|
||||
* @property {Object} options - options to use while processing template
|
||||
*/
|
||||
execution.return.visualizer = {
|
||||
template,
|
||||
data,
|
||||
options
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear all visualizer data
|
||||
*
|
||||
* @instance
|
||||
*/
|
||||
clear () {
|
||||
execution.return.visualizer = undefined;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// extend pm api with test runner abilities
|
||||
setupTestRunner(this, onAssertion);
|
||||
|
||||
// add response assertions
|
||||
if (this.response) {
|
||||
// these are removed before serializing see `purse.js`
|
||||
Object.defineProperty(this.response, 'to', {
|
||||
get () {
|
||||
return chai.expect(this).to;
|
||||
}
|
||||
});
|
||||
}
|
||||
// add request assertions
|
||||
if (this.request) {
|
||||
// these are removed before serializing see `purse.js`
|
||||
Object.defineProperty(this.request, 'to', {
|
||||
get () {
|
||||
return chai.expect(this).to;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows one to send request from script asynchronously.
|
||||
*
|
||||
* @param {Request|String} req -
|
||||
* @param {Function} callback -
|
||||
*/
|
||||
this.sendRequest = function (req, callback) {
|
||||
var self = this;
|
||||
|
||||
if (!req) {
|
||||
return _.isFunction(callback) && callback.call(self, new Error('sendrequest: nothing to request'));
|
||||
}
|
||||
|
||||
onRequest(PostmanRequest.isRequest(req) ? req : (new PostmanRequest(req)), function (err, resp, history) {
|
||||
if (history && !PostmanCookieList.isCookieList(history.cookies)) {
|
||||
history.cookies = new PostmanCookieList({}, history.cookies);
|
||||
}
|
||||
|
||||
_.isFunction(callback) && callback.call(self, err,
|
||||
PostmanResponse.isResponse(resp) ? resp : (new PostmanResponse(resp)),
|
||||
history);
|
||||
});
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
iterationData = null; // precautionary
|
||||
}
|
||||
|
||||
// expose chai assertion library via prototype
|
||||
/**
|
||||
* @type {Chai.ExpectStatic}
|
||||
*/
|
||||
Postman.prototype.expect = chai.expect;
|
||||
|
||||
// make chai use postman extension
|
||||
chai.use(require('chai-postman')(sdk, _, Ajv));
|
||||
|
||||
// export
|
||||
module.exports = Postman;
|
420
node_modules/postman-sandbox/lib/sandbox/postman-legacy-interface.js
generated
vendored
Normal file
420
node_modules/postman-sandbox/lib/sandbox/postman-legacy-interface.js
generated
vendored
Normal file
@@ -0,0 +1,420 @@
|
||||
/* eslint-disable max-classes-per-file */
|
||||
const _ = require('lodash'),
|
||||
|
||||
scopeLibraries = {
|
||||
JSON: require('liquid-json'),
|
||||
_: require('lodash3').noConflict(),
|
||||
CryptoJS: require('crypto-js'),
|
||||
atob: require('atob'),
|
||||
btoa: require('btoa'),
|
||||
tv4: require('tv4'),
|
||||
xml2Json: require('./xml2Json'),
|
||||
Backbone: require('backbone'),
|
||||
cheerio: require('cheerio')
|
||||
},
|
||||
|
||||
LEGACY_GLOBS = [
|
||||
'tests', 'globals', 'environment', 'data', 'request', 'responseCookies', 'responseHeaders', 'responseTime',
|
||||
'responseCode', 'responseBody', 'iteration', 'postman',
|
||||
// scope libraries
|
||||
'JSON', '_', 'CryptoJS', 'atob', 'btoa', 'tv4', 'xml2Json', 'Backbone', 'cheerio'
|
||||
],
|
||||
|
||||
E = '',
|
||||
FUNCTION = 'function',
|
||||
TARGET_TEST = 'test',
|
||||
|
||||
LEGACY_ASSERTION_ERROR_MESSAGE_PREFIX = 'expected ',
|
||||
LEGACY_ASSERTION_ERROR_MESSAGE_SUFFIX = ' to be truthy',
|
||||
|
||||
/**
|
||||
* Different modes for a request body.
|
||||
*
|
||||
* @enum {String}
|
||||
*/
|
||||
REQUEST_MODES = {
|
||||
RAW: 'raw',
|
||||
URLENCODED: 'urlencoded',
|
||||
FORMDATA: 'formdata',
|
||||
FILE: 'file'
|
||||
};
|
||||
|
||||
function getRequestBody (request) {
|
||||
var mode = _.get(request, 'body.mode'),
|
||||
body = _.get(request, 'body'),
|
||||
empty = body ? body.isEmpty() : true,
|
||||
content,
|
||||
computedBody;
|
||||
|
||||
if (empty) {
|
||||
return;
|
||||
}
|
||||
|
||||
content = body[mode];
|
||||
|
||||
if (_.isFunction(content && content.all)) {
|
||||
content = content.all();
|
||||
}
|
||||
|
||||
if (mode === REQUEST_MODES.RAW) {
|
||||
computedBody = {
|
||||
body: content
|
||||
};
|
||||
}
|
||||
else if (mode === REQUEST_MODES.URLENCODED) {
|
||||
computedBody = {
|
||||
form: _.reduce(content, function (accumulator, param) {
|
||||
if (param.disabled) { return accumulator; }
|
||||
|
||||
// This is actually pretty simple,
|
||||
// If the variable already exists in the accumulator, we need to make the value an Array with
|
||||
// all the variable values inside it.
|
||||
if (accumulator[param.key]) {
|
||||
_.isArray(accumulator[param.key]) ? accumulator[param.key].push(param.value) :
|
||||
(accumulator[param.key] = [accumulator[param.key], param.value]);
|
||||
}
|
||||
else {
|
||||
accumulator[param.key] = param.value;
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}, {})
|
||||
};
|
||||
}
|
||||
else if (request.body.mode === REQUEST_MODES.FORMDATA) {
|
||||
computedBody = {
|
||||
formData: _.reduce(content, function (accumulator, param) {
|
||||
if (param.disabled) { return accumulator; }
|
||||
|
||||
// This is actually pretty simple,
|
||||
// If the variable already exists in the accumulator, we need to make the value an Array with
|
||||
// all the variable values inside it.
|
||||
if (accumulator[param.key]) {
|
||||
_.isArray(accumulator[param.key]) ? accumulator[param.key].push(param.value) :
|
||||
(accumulator[param.key] = [accumulator[param.key], param.value]);
|
||||
}
|
||||
else {
|
||||
accumulator[param.key] = param.value;
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}, {})
|
||||
};
|
||||
}
|
||||
else if (request.body.mode === REQUEST_MODES.FILE) {
|
||||
computedBody = {
|
||||
body: _.get(request, 'body.file.content')
|
||||
};
|
||||
}
|
||||
|
||||
return computedBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Raises a single assertion event with an array of assertions from legacy `tests` object.
|
||||
*
|
||||
* @param {Uniscope} scope -
|
||||
* @param {Object} pmapi -
|
||||
* @param {Function} onAssertion -
|
||||
*/
|
||||
function raiseAssertionEvent (scope, pmapi, onAssertion) {
|
||||
var tests = scope._imports && scope._imports.tests,
|
||||
assertionIndex = pmapi.test.index(),
|
||||
assertions;
|
||||
|
||||
if (_.isEmpty(tests)) {
|
||||
return;
|
||||
}
|
||||
|
||||
assertions = _.map(tests, function (value, key) {
|
||||
var assertionName = String(key),
|
||||
passed = Boolean(value),
|
||||
assertionError = null;
|
||||
|
||||
// fake an assertion error for legacy tests
|
||||
if (!passed) {
|
||||
assertionError = new Error(LEGACY_ASSERTION_ERROR_MESSAGE_PREFIX +
|
||||
String(value) + LEGACY_ASSERTION_ERROR_MESSAGE_SUFFIX);
|
||||
assertionError.name = 'AssertionError';
|
||||
}
|
||||
|
||||
// @todo Move getAssertionObject function from pmapi-setup-runner.js to a common place and reuse it here too
|
||||
return {
|
||||
name: assertionName,
|
||||
skipped: false,
|
||||
passed: passed,
|
||||
error: assertionError,
|
||||
index: assertionIndex++
|
||||
};
|
||||
});
|
||||
|
||||
onAssertion(assertions);
|
||||
}
|
||||
|
||||
class PostmanLegacyInterface {
|
||||
/**
|
||||
* @param {Object} execution -
|
||||
* @param {Object} globalvars -
|
||||
*/
|
||||
constructor (execution, globalvars) {
|
||||
this.__execution = execution;
|
||||
this.__environment = globalvars.environment;
|
||||
this.__globals = globalvars.globals;
|
||||
}
|
||||
|
||||
setEnvironmentVariable (key, value) {
|
||||
if ((value === false || value) && typeof (value && value.toString) === FUNCTION) {
|
||||
value = value.toString();
|
||||
}
|
||||
this.__environment[key] = value;
|
||||
|
||||
return this.__execution.environment.set(key, value);
|
||||
}
|
||||
|
||||
getEnvironmentVariable (key) {
|
||||
return this.__execution.environment.get(key);
|
||||
}
|
||||
|
||||
clearEnvironmentVariables () {
|
||||
for (var prop in this.__environment) {
|
||||
if (Object.hasOwnProperty.call(this.__environment, prop)) {
|
||||
delete this.__environment[prop];
|
||||
}
|
||||
}
|
||||
|
||||
return this.__execution.environment.clear();
|
||||
}
|
||||
|
||||
clearEnvironmentVariable (key) {
|
||||
key && (delete this.__environment[key]);
|
||||
|
||||
return this.__execution.environment.unset(key);
|
||||
}
|
||||
|
||||
setGlobalVariable (key, value) {
|
||||
if ((value === false || value) && typeof (value && value.toString) === FUNCTION) {
|
||||
value = value.toString();
|
||||
}
|
||||
this.__globals[key] = value;
|
||||
|
||||
return this.__execution.globals.set(key, value);
|
||||
}
|
||||
|
||||
getGlobalVariable (key) {
|
||||
return this.__execution.globals.get(key);
|
||||
}
|
||||
|
||||
clearGlobalVariables () {
|
||||
for (var prop in this.__globals) {
|
||||
if (Object.hasOwnProperty.call(this.__globals, prop)) {
|
||||
delete this.__globals[prop];
|
||||
}
|
||||
}
|
||||
|
||||
return this.__execution.globals.clear();
|
||||
}
|
||||
|
||||
clearGlobalVariable (key) {
|
||||
key && (delete this.__globals[key]);
|
||||
|
||||
return this.__execution.globals.unset(key);
|
||||
}
|
||||
|
||||
setNextRequest (what) {
|
||||
this.__execution.return && (this.__execution.return.nextRequest = what);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {PostmanLegacyInterface}
|
||||
*/
|
||||
class PostmanLegacyTestInterface extends PostmanLegacyInterface {
|
||||
/**
|
||||
* @param {String} cookieName -
|
||||
* @returns {Object}
|
||||
*/
|
||||
getResponseCookie (cookieName) {
|
||||
return this.__execution.cookies ? this.__execution.cookies.one(String(cookieName)) : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} headerName -
|
||||
* @returns {String}
|
||||
*/
|
||||
getResponseHeader (headerName) {
|
||||
var header = (this.__execution.response && this.__execution.response.headers) &&
|
||||
this.__execution.response.headers.one(headerName);
|
||||
|
||||
return header ? header.value : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
*
|
||||
* @param {Uniscope} scope -
|
||||
* @param {Execution} execution -
|
||||
*
|
||||
* @note ensure that globalvars variables added here are added as part of the LEGACY_GLOBS array
|
||||
*/
|
||||
setup (scope, execution) {
|
||||
/**
|
||||
* @name SandboxGlobals
|
||||
* @type {Object}
|
||||
*/
|
||||
var globalvars = _.assign({}, scopeLibraries);
|
||||
|
||||
// set global variables that are exposed in legacy interface
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// 1. set the tests object (irrespective of target)
|
||||
/**
|
||||
* Store your assertions in this object
|
||||
*
|
||||
* @memberOf SandboxGlobals
|
||||
* @type {Object}
|
||||
*/
|
||||
globalvars.tests = {};
|
||||
|
||||
// 2. set common environment, globals and data
|
||||
/**
|
||||
* All global variables at the initial stages when the script ran
|
||||
*
|
||||
* @memberOf SandboxGlobals
|
||||
* @type {Object}
|
||||
*/
|
||||
globalvars.globals = execution.globals.syncVariablesTo();
|
||||
|
||||
/**
|
||||
* All environment variables at the initial stages when script ran
|
||||
*
|
||||
* @memberOf SandboxGlobals
|
||||
* @type {Object}
|
||||
*/
|
||||
globalvars.environment = execution.environment.syncVariablesTo();
|
||||
|
||||
/**
|
||||
* The data object if it was passed during a collection run
|
||||
*
|
||||
* @memberOf SandboxGlobals
|
||||
* @type {Object}
|
||||
*/
|
||||
globalvars.data = execution.data || (execution.data = {});
|
||||
|
||||
// 3. set the request object in legacy structure
|
||||
/**
|
||||
* The request that will be sent (or has been sent)
|
||||
*
|
||||
* @memberOf SandboxGlobals
|
||||
* @type {Object}
|
||||
*/
|
||||
globalvars.request = execution.request ? {
|
||||
id: execution.legacy ? execution.legacy._itemId : undefined,
|
||||
name: execution.legacy ? execution.legacy._itemName : undefined,
|
||||
description: execution.request.description ?
|
||||
execution.request.description.toString() : undefined,
|
||||
headers: execution.request.headers.toObject(true, false, true, true),
|
||||
method: execution.request.method,
|
||||
url: execution.request.url.toString(),
|
||||
data: (function (request) {
|
||||
var body = getRequestBody(request);
|
||||
|
||||
return body ? (body.form || body.formData || body.body || {}) : {};
|
||||
}(execution.request))
|
||||
} : {};
|
||||
|
||||
// 4. set the response related objects
|
||||
if (execution.target === TARGET_TEST) {
|
||||
/**
|
||||
* Stores the response cookies
|
||||
*
|
||||
* @memberOf SandboxGlobals
|
||||
* @type {Array.<Object>}
|
||||
*/
|
||||
globalvars.responseCookies = execution.cookies || [];
|
||||
|
||||
/**
|
||||
* Stores the response headers with the keys being case sensitive
|
||||
*
|
||||
* @memberOf SandboxGlobals
|
||||
* @type {Array.<Object>}
|
||||
*/
|
||||
globalvars.responseHeaders = {};
|
||||
execution.response && execution.response.headers.each(function (header) {
|
||||
header && !header.disabled && (globalvars.responseHeaders[header.key] = header.value);
|
||||
});
|
||||
|
||||
/**
|
||||
* @memberOf SandboxGlobals
|
||||
* @type {Number}
|
||||
*/
|
||||
globalvars.responseTime = execution.response ? execution.response.responseTime : NaN;
|
||||
|
||||
/**
|
||||
* @memberOf SandboxGlobals
|
||||
* @type {Number}
|
||||
*/
|
||||
globalvars.responseCode = execution.response ? _.clone(execution.response.details()) : {
|
||||
code: NaN,
|
||||
name: E,
|
||||
details: E
|
||||
};
|
||||
|
||||
/**
|
||||
* @memberOf SandboxGlobals
|
||||
* @type {String}
|
||||
*/
|
||||
globalvars.responseBody = execution.response ? execution.response.text() : undefined;
|
||||
}
|
||||
|
||||
// 5. add the iteration information
|
||||
globalvars.iteration = _.isObject(execution.cursor) ? execution.cursor.iteration : 0;
|
||||
|
||||
// 6. create the postman interface object
|
||||
/**
|
||||
* @memberOf SandboxGlobals
|
||||
* @type {PostmanLegacyInterface}
|
||||
*/
|
||||
globalvars.postman = new (execution.target === TARGET_TEST ?
|
||||
PostmanLegacyTestInterface : PostmanLegacyInterface)(execution, globalvars);
|
||||
|
||||
// make a final pass to ensure that the global variables are present
|
||||
|
||||
|
||||
// all the globals are now added to scope
|
||||
scope.import(globalvars);
|
||||
globalvars = null; // dereference
|
||||
|
||||
// add a flag to ensure that when teardown is called, it does not tear down a scope that was never setup
|
||||
scope.__postman_legacy_setup = true;
|
||||
},
|
||||
|
||||
teardown (scope) {
|
||||
if (!scope.__postman_legacy_setup) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0, ii = LEGACY_GLOBS.length; i < ii; i++) {
|
||||
scope.unset(LEGACY_GLOBS[i]);
|
||||
}
|
||||
|
||||
scope.__postman_legacy_setup = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* This is the place where we should put all the tasks
|
||||
* that need to be executed after the completion of script execution
|
||||
*
|
||||
* @param {Uniscope} scope -
|
||||
* @param {Object} pmapi -
|
||||
* @param {Function} onAssertion -
|
||||
*/
|
||||
finish (scope, pmapi, onAssertion) {
|
||||
if (!scope.__postman_legacy_setup) {
|
||||
return;
|
||||
}
|
||||
|
||||
raiseAssertionEvent(scope, pmapi, onAssertion);
|
||||
}
|
||||
};
|
53
node_modules/postman-sandbox/lib/sandbox/purse.js
generated
vendored
Normal file
53
node_modules/postman-sandbox/lib/sandbox/purse.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* This module adds `.toJSON` to prototypes of objects that does not behave well with JSON.stringify() This aides in
|
||||
* accurate transport of information between IPC
|
||||
*
|
||||
*/
|
||||
try {
|
||||
Error && (Error.prototype.toJSON = function () { // eslint-disable-line no-extend-native
|
||||
return {
|
||||
type: 'Error',
|
||||
name: this.name,
|
||||
message: this.message
|
||||
};
|
||||
});
|
||||
}
|
||||
catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
const { Request, Response } = require('postman-collection');
|
||||
|
||||
/**
|
||||
* We override toJSON to not export additional helpers that sandbox adds to pm.request and pm.response.
|
||||
*/
|
||||
try {
|
||||
Request.prototype.toJSON = (function (superToJSON) { // eslint-disable-line no-extend-native
|
||||
return function () {
|
||||
var tmp = this.to,
|
||||
json;
|
||||
|
||||
// remove properties added by sandbox before doing a toJSON
|
||||
delete this.to;
|
||||
json = superToJSON.apply(this, arguments);
|
||||
|
||||
this.to = tmp;
|
||||
|
||||
return json;
|
||||
};
|
||||
}(Request.prototype.toJSON));
|
||||
|
||||
Response.prototype.toJSON = (function (superToJSON) { // eslint-disable-line no-extend-native
|
||||
return function () {
|
||||
var tmp = this.to,
|
||||
json;
|
||||
|
||||
// remove properties added by sandbox before doing a toJSON
|
||||
delete this.to;
|
||||
json = superToJSON.apply(this, arguments);
|
||||
|
||||
this.to = tmp;
|
||||
|
||||
return json;
|
||||
};
|
||||
}(Response.prototype.toJSON));
|
||||
}
|
||||
catch (e) {} // eslint-disable-line no-empty
|
309
node_modules/postman-sandbox/lib/sandbox/timers.js
generated
vendored
Normal file
309
node_modules/postman-sandbox/lib/sandbox/timers.js
generated
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
/**
|
||||
* @fileoverview This file contains the module that is required to enable specialised timers that have better control
|
||||
* on a global level.
|
||||
*
|
||||
* @todo - the architecture of this sucks even if this "works".
|
||||
* - the way to compute firing of start and end events suck
|
||||
* - basically this needs a redo with more "engineering" put into it
|
||||
*/
|
||||
const /**
|
||||
*
|
||||
* @constant {String}
|
||||
*/
|
||||
FUNCTION = 'function',
|
||||
|
||||
/**
|
||||
* The set of timer function names. We use this array to define common behaviour of all setters and clearer timer
|
||||
* functions
|
||||
*
|
||||
* @constant {Array.<String>}
|
||||
*/
|
||||
timerFunctionNames = ['Timeout', 'Interval', 'Immediate', 'Event'],
|
||||
|
||||
/**
|
||||
* This object defines a set of timer function names that are trigerred a number of times instead of a single time.
|
||||
* Such timers, when placed in generic rules, needs special attention.
|
||||
*
|
||||
* @constant {Array.<Boolean>}
|
||||
*/
|
||||
multiFireTimerFunctions = {
|
||||
Interval: true
|
||||
},
|
||||
|
||||
/**
|
||||
* This object defines a set of function timer names that do not fire based on any pre-set duration or interval.
|
||||
* Such timers, when placed in generic rules, needs special attention.
|
||||
*
|
||||
* @constant {Array.<Boolean>}
|
||||
*/
|
||||
staticTimerFunctions = {
|
||||
Event: true
|
||||
},
|
||||
|
||||
/**
|
||||
* A local copy of Slice function of Array
|
||||
*
|
||||
* @constant {Function}
|
||||
*/
|
||||
arrayProtoSlice = Array.prototype.slice,
|
||||
|
||||
/**
|
||||
* This object holds the current global timers
|
||||
*
|
||||
* @extends Timers
|
||||
*
|
||||
* @note This is a very important piece of code from compatibility standpoint.
|
||||
* The global timers need to be returned as a function that does not hold reference to the scope
|
||||
* and does not retain references to scope. Aditionally, the invocation of the timer function is
|
||||
* done without changing the scope to avoid Illegal Invocation errors.
|
||||
*
|
||||
* `timerFunctionNames` returns the suffixes of all timer operations that needs a
|
||||
* a setter and clear method.
|
||||
*/
|
||||
defaultTimers = timerFunctionNames.reduce(function (timers, name) {
|
||||
var
|
||||
|
||||
/**
|
||||
* Check if global setter function is available
|
||||
*
|
||||
* @private
|
||||
* @type {Boolean}
|
||||
*/
|
||||
// eslint-disable-next-line no-new-func
|
||||
isGlobalSetterAvailable = (new Function(`return typeof set${name} === 'function'`))(),
|
||||
|
||||
/**
|
||||
* Check if global clear function is available
|
||||
*
|
||||
* @private
|
||||
* @type {Boolean}
|
||||
*/
|
||||
// eslint-disable-next-line no-new-func
|
||||
isGlobalClearAvailable = (new Function(`return typeof clear${name} === 'function'`))();
|
||||
|
||||
if (isGlobalSetterAvailable) {
|
||||
// eslint-disable-next-line no-new-func
|
||||
timers[('set' + name)] = (new Function(`return function (fn, ms) { return set${name}(fn, ms); }`))();
|
||||
}
|
||||
|
||||
if (isGlobalClearAvailable) {
|
||||
// eslint-disable-next-line no-new-func
|
||||
timers[('clear' + name)] = (new Function(`return function (id) { return clear${name}(id); }`))();
|
||||
}
|
||||
|
||||
return timers;
|
||||
}, {});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @param {Object} [delegations] -
|
||||
* @param {Function} [onError] -
|
||||
* @param {Function} [onAnyTimerStart] -
|
||||
* @param {Function} [onAllTimerEnd] -
|
||||
*/
|
||||
function Timerz (delegations, onError, onAnyTimerStart, onAllTimerEnd) {
|
||||
var /**
|
||||
* Holds the present timers, either delegated or defaults
|
||||
*
|
||||
* @extends Timers
|
||||
*/
|
||||
timers = delegations || defaultTimers,
|
||||
dummyContext = {},
|
||||
|
||||
total = 0, // accumulator to keep track of total timers
|
||||
pending = 0, // counters to keep track of running timers
|
||||
sealed = false, // flag that stops all new timer additions
|
||||
wentAsync = false,
|
||||
computeTimerEvents;
|
||||
|
||||
// do special handling to enable emulation of immediate timers in hosts that lacks them
|
||||
if (typeof timers.setImmediate !== FUNCTION) {
|
||||
timers.setImmediate = function (callback) {
|
||||
return timers.setTimeout(callback, 0);
|
||||
};
|
||||
timers.clearImmediate = function (id) {
|
||||
return timers.clearTimeout(id);
|
||||
};
|
||||
}
|
||||
|
||||
// write special handlers for event based timers if the delegations don't contain one
|
||||
(typeof timers.setEvent !== FUNCTION) && (function () {
|
||||
var events = {},
|
||||
total = 0;
|
||||
|
||||
timers.setEvent = function (callback) {
|
||||
var id = ++total;
|
||||
|
||||
events[id] = callback;
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
timers.clearEvent = function (id) {
|
||||
var cb = events[id];
|
||||
|
||||
delete events[id];
|
||||
(typeof cb === FUNCTION) && cb.apply(dummyContext, arrayProtoSlice.call(arguments, 1));
|
||||
};
|
||||
|
||||
timers.clearAllEvents = function () {
|
||||
Object.keys(events).forEach(function (prop) {
|
||||
delete events[prop];
|
||||
});
|
||||
};
|
||||
}());
|
||||
|
||||
// create a function that decides whether to fire appropriate callbacks
|
||||
computeTimerEvents = function (increment, clearing) {
|
||||
increment && (pending += increment);
|
||||
|
||||
if (pending === 0 && computeTimerEvents.started) {
|
||||
!clearing && (typeof onAllTimerEnd === FUNCTION) && onAllTimerEnd();
|
||||
computeTimerEvents.started = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (pending > 0 && !computeTimerEvents.started) {
|
||||
!clearing && (typeof onAnyTimerStart === FUNCTION) && onAnyTimerStart();
|
||||
computeTimerEvents.started = true;
|
||||
}
|
||||
};
|
||||
|
||||
// iterate through the timer variants and create common setter and clearer function behaviours for each of them.
|
||||
timerFunctionNames.forEach(function (name) {
|
||||
// create an accumulator for all timer references
|
||||
var running = {};
|
||||
|
||||
// create the setter function for the timer
|
||||
this[('set' + name)] = function (callback) {
|
||||
// it is pointless to proceed with setter if there is no callback to execute
|
||||
if (sealed || typeof callback !== FUNCTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
var id = ++total, // get hold of the next timer id
|
||||
args = arrayProtoSlice.call(arguments);
|
||||
|
||||
args[0] = function () {
|
||||
wentAsync = true; // mark that we did go async once. this will ensure we do not pass erroneous events
|
||||
|
||||
// call the actual callback with a dummy context
|
||||
try { callback.apply(dummyContext, staticTimerFunctions[name] ? arguments : null); }
|
||||
catch (e) { onError && onError(e); }
|
||||
|
||||
// interval timers can only be cleared using clearXYZ function and hence we need not do anything
|
||||
// except call the timer
|
||||
if (staticTimerFunctions[name] || multiFireTimerFunctions[name]) {
|
||||
// do not modify counter during interval type events
|
||||
computeTimerEvents();
|
||||
}
|
||||
// when this is fired, the timer dies, so we decrement tracking counters and delete
|
||||
// irq references
|
||||
else {
|
||||
computeTimerEvents(-1);
|
||||
delete running[id];
|
||||
}
|
||||
};
|
||||
|
||||
// for static timers
|
||||
staticTimerFunctions[name] && (wentAsync = true);
|
||||
|
||||
// call the underlying timer function and keep a track of its irq
|
||||
running[id] = timers[('set' + name)].apply(this, args);
|
||||
args = null; // precaution
|
||||
|
||||
// increment the counter and return the tracking ID to be used to pass on to clearXYZ function
|
||||
computeTimerEvents(1);
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
// create the clear function of the timer
|
||||
this[('clear' + name)] = function (id) {
|
||||
var underLyingId = running[id],
|
||||
args;
|
||||
|
||||
// it is pointless and erroenous to proceed in case it seems that it is no longer running
|
||||
if (sealed || !underLyingId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// prepare args to be forwarded to clear function
|
||||
args = arrayProtoSlice.call(arguments);
|
||||
args[0] = underLyingId;
|
||||
delete running[id];
|
||||
|
||||
// fire the underlying clearing function
|
||||
|
||||
try { timers['clear' + name].apply(dummyContext, args); }
|
||||
catch (e) { onError(e); }
|
||||
|
||||
// decrement counters and call the clearing timer function
|
||||
computeTimerEvents(-1, !wentAsync);
|
||||
|
||||
args = underLyingId = null; // just a precaution
|
||||
};
|
||||
|
||||
// create a sugar function to clear all running timers of this category
|
||||
// @todo: decide how to handle clearing for underlying delegated timers, if they are instances of Timerz itself.
|
||||
if (typeof timers[('clearAll' + name + 's')] === FUNCTION) {
|
||||
// if native timers have a function to clear all timers, then use it
|
||||
this[('clearAll' + name + 's')] = function () {
|
||||
timers[('clearAll' + name + 's')]();
|
||||
Object.keys(running).forEach(function () {
|
||||
computeTimerEvents(-1, true);
|
||||
});
|
||||
};
|
||||
}
|
||||
else {
|
||||
this[('clearAll' + name + 's')] = function () {
|
||||
Object.keys(running).forEach(function (id) {
|
||||
computeTimerEvents(-1, true);
|
||||
// run clear functions except for static timers
|
||||
timers['clear' + name](running[id]);
|
||||
});
|
||||
};
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
|
||||
/**
|
||||
* @memberof Timerz.prototype
|
||||
* @returns {Number}
|
||||
*/
|
||||
this.queueLength = function () {
|
||||
return pending;
|
||||
};
|
||||
|
||||
/**
|
||||
* @memberof Timerz.prototype
|
||||
*/
|
||||
this.clearAll = function () {
|
||||
// call all internal timer clearAll function variants
|
||||
timerFunctionNames.forEach(function (name) {
|
||||
this[('clearAll' + name + 's')]();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* @memberof Timerz.prototype
|
||||
*/
|
||||
this.seal = function () {
|
||||
sealed = true;
|
||||
};
|
||||
|
||||
this.error = function (err) {
|
||||
return onError.call(dummyContext, err);
|
||||
};
|
||||
|
||||
this.terminate = function () {
|
||||
this.seal();
|
||||
this.clearAll();
|
||||
|
||||
return onAllTimerEnd.apply(dummyContext, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = Timerz;
|
23
node_modules/postman-sandbox/lib/sandbox/xml2Json.js
generated
vendored
Normal file
23
node_modules/postman-sandbox/lib/sandbox/xml2Json.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
const xml2js = require('xml2js'),
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @type {Object}
|
||||
*/
|
||||
xml2jsOptions = {
|
||||
explicitArray: false,
|
||||
// this ensures that it works in the sync sandbox we currently have in the app
|
||||
async: false,
|
||||
trim: true,
|
||||
mergeAttrs: false
|
||||
};
|
||||
|
||||
module.exports = function (string) {
|
||||
var JSON = {};
|
||||
|
||||
xml2js.parseString(string, xml2jsOptions, function (_, result) { // @todo - see who swallows the error
|
||||
JSON = result;
|
||||
});
|
||||
|
||||
return JSON;
|
||||
};
|
8644
node_modules/postman-sandbox/lib/vendor/sugar.js
generated
vendored
Normal file
8644
node_modules/postman-sandbox/lib/vendor/sugar.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
15
node_modules/postman-sandbox/lib/vendor/uuid.js
generated
vendored
Normal file
15
node_modules/postman-sandbox/lib/vendor/uuid.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
var plc = 'x',
|
||||
pattern = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',
|
||||
bit = /[xy]/g,
|
||||
replacer = function(c) {
|
||||
var r = Math.random()*16|0, v = c == plc ? r : (r&0x3|0x8);
|
||||
return v.toString(16);
|
||||
};
|
||||
|
||||
module.exports = function () {
|
||||
return pattern.replace(bit, replacer);
|
||||
};
|
||||
|
||||
module.exports.v4 = function () {
|
||||
return pattern.replace(bit, replacer);
|
||||
};
|
Reference in New Issue
Block a user