forked from postmanlabs/postman-sandbox
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
33 changed files
with
10,152 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
lib/sandbox/vendor/sugar.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"tags": { | ||
"allowUnknownTags": true, | ||
"dictionaries": ["jsdoc", "closure"] | ||
}, | ||
"source": { | ||
"include": [ ], | ||
"includePattern": ".+\\.js(doc)?$", | ||
"excludePattern": "(^|\\/|\\\\)_" | ||
}, | ||
|
||
"plugins": [ | ||
"plugins/markdown" | ||
], | ||
|
||
"templates": { | ||
"cleverLinks": false, | ||
"monospaceLinks": false, | ||
"highlightTutorialCode" : true | ||
}, | ||
|
||
"opts": { | ||
"template": "./node_modules/postman-jsdoc-theme", | ||
"encoding": "utf8", | ||
"destination": "./out/docs", | ||
"recurse": true, | ||
"readme": "README.md" | ||
}, | ||
|
||
"markdown": { | ||
"parser": "gfm", | ||
"hardwrap": false | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/**! | ||
* @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. | ||
*/ | ||
module.exports = require('./lib'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
var _ = require('lodash'), | ||
bundle = require('./bundle'), | ||
env = require('./environment'), | ||
|
||
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.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) { | ||
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 | ||
} | ||
code && _.isString(code) && (cache = code); | ||
|
||
return done(null, cache); | ||
}); | ||
}; | ||
|
||
module.exports = cacher; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module.exports = { | ||
insertGlobalVars: false, | ||
browserField: false, | ||
bare: true, | ||
builtins: false, | ||
commondir: true | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* Error message to trigger if bundling is accidentally triggered inside a browser | ||
* | ||
* @constant | ||
* @private | ||
* @type {String} | ||
*/ | ||
var ERROR_MESSAGE = 'sandbox: code bundling is not supported in browser. use cached templates.', | ||
StubBundle; | ||
|
||
StubBundle = function StubBundle () { | ||
throw new Error(ERROR_MESSAGE); | ||
}; | ||
|
||
StubBundle.load = function () { | ||
throw new Error(ERROR_MESSAGE); | ||
}; | ||
|
||
module.exports = StubBundle; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
var _ = require('lodash'), | ||
browserify = require('browserify'), | ||
browserifyBuiltins = require('browserify/lib/builtins'), | ||
bundlingOptions = require('./bundling-options'), | ||
|
||
PREFER_BUILTIN = 'preferBuiltin', | ||
|
||
defaultCompressOptions = { | ||
transformer: 'uglifyify', | ||
options: { | ||
output: {ascii_only: true}, | ||
global: true | ||
} | ||
}, | ||
|
||
Bundle; | ||
|
||
/** | ||
* Create a bundle from an options template | ||
* @constructor | ||
* | ||
* @param {Object} options | ||
* @param {Object} options.files | ||
* @param {Object} options.require | ||
* @param {Boolean|Object} options.compress | ||
* @param {Object=} [options.bundler] | ||
*/ | ||
Bundle = function (options) { | ||
/** | ||
* @private | ||
* @memberOf Bundler.prototype | ||
* @type {Browserify} | ||
*/ | ||
this.bundler = browserify(_.defaults(options.bundler, bundlingOptions)); // merge with user options | ||
|
||
// add the transformer for compression | ||
if (options.compress) { | ||
this.bundler.transform(_.defaults(options.compress, defaultCompressOptions.options), | ||
defaultCompressOptions.transformer); | ||
} | ||
|
||
// process any list of modules externally required and also accommodate the use of built-ins if needed | ||
_.forEach(options.require, function (options, resolve) { | ||
if (_.get(options, PREFER_BUILTIN) && _.has(browserifyBuiltins, resolve)) { // @todo: add tests | ||
this.bundler.require(browserifyBuiltins[resolve], _.defaults(options, { | ||
expose: resolve | ||
})); | ||
} | ||
else { | ||
this.bundler.require(require.resolve(resolve), options); // @todo: add tests for resolve failures | ||
} | ||
}.bind(this)); | ||
|
||
// add files that are needed | ||
_.forEach(options.files, function (options, file) { | ||
this.bundler.add(file, options); | ||
}.bind(this)); | ||
}; | ||
|
||
_.assign(Bundle.prototype, /** @lends Bundle.prototype */ { | ||
compile: function (done) { | ||
return this.bundler.bundle(done); | ||
} | ||
}); | ||
|
||
_.assign(Bundle, /** @lends Bundle */ { | ||
load: function (options) { | ||
return new Bundle(options); | ||
} | ||
}); | ||
|
||
module.exports = Bundle; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
module.exports = { | ||
require: { | ||
events: {preferBuiltin: true}, | ||
_process: {preferBuiltin: true}, | ||
timers: {preferBuiltin: true}, | ||
'buffer-browserify': {expose: 'buffer'}, | ||
'liquid-json': {expose: 'json'}, | ||
lodash3: {expose: 'lodash'}, | ||
'crypto-js': true, | ||
atob: true, | ||
btoa: true, | ||
tv4: true, | ||
xml2js: true, | ||
backbone: true, | ||
cheerio: true | ||
}, | ||
files: { | ||
'./lib/sandbox/vendor/sugar': true, | ||
'./lib/sandbox/purse': true, | ||
'./lib/sandbox': true | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
var _ = require('lodash'), | ||
inherits = require('inherits'), | ||
uuid = require('uuid'), | ||
UniversalVM = require('uvm'), | ||
bootcode = require('./bootcode'), | ||
|
||
PostmanSandbox; | ||
|
||
|
||
PostmanSandbox = function PostmanSandbox (options, callback) { | ||
this.executing = {}; | ||
|
||
UniversalVM.call(this, options, function (err, context) { | ||
if (err) { return callback(err); } | ||
context.ping(function (err) { | ||
callback(err, context); | ||
context = null; | ||
}); | ||
}); | ||
}; | ||
|
||
inherits(PostmanSandbox, UniversalVM); | ||
|
||
_.assign(PostmanSandbox.prototype, { | ||
ping: function (callback) { | ||
var packet = uuid(), | ||
start = Date.now(); | ||
|
||
this.once('pong', function (echo) { | ||
callback((echo !== packet ? new Error('sandbox: ping packet mismatch') : null), Date.now() - start, packet); | ||
}); | ||
|
||
this.dispatch('ping', packet); | ||
}, | ||
|
||
/** | ||
* @param {String} code | ||
* @param {Object} options | ||
* @param {Boolean} options.debug | ||
* @param {Number} options.timeout | ||
* @param {String} options.scriptType - 'test', 'prerequest' | ||
* @param {Object} options.legacy | ||
* @param {Object} options.legacy.environment | ||
* @param {Object} options.legacy.globals | ||
* @param {Object} options.legacy.request | ||
* @param {Object} options.legacy.responseCookies | ||
* @param {Object} options.legacy.responseHeaders | ||
* @param {String} options.legacy.responseBody | ||
* @param {Number} options.legacy.responseTime | ||
* @param {Object} options.legacy.responseCode | ||
* @param {Object} options.legacy.tests | ||
* @param {Number} options.legacy.iteration | ||
* @param {Function} callback | ||
*/ | ||
execute: function (code, options, callback) { | ||
if (_.isFunction(options) && !callback) { | ||
callback = options; | ||
options = null; | ||
} | ||
!_.isObject(options) && (options = {}); | ||
|
||
var id = uuid(), | ||
executionEventName = `execution.${id}`; | ||
this.executing[id] = true; | ||
|
||
// @todo decide how the results will return in a more managed fashion | ||
this.once(executionEventName, function (err, result) { | ||
delete this.executing[id]; | ||
this.emit('execution', err, id, result); | ||
callback(err, result); | ||
}); | ||
|
||
// set execution timeout | ||
// @todo add tests | ||
_.isFinite(options.timeout) && setTimeout(this.emit.bind(this, executionEventName, | ||
new Error('sandbox: execution timeout')), options.timeout); | ||
|
||
// send the code to the sendbox to be intercepted and executed | ||
this.dispatch('execute', id, code, _.omit(options, 'data'), _.get(options, 'data', {})); | ||
}, | ||
|
||
dispose: function () { | ||
Object.keys(this.executing[id]).forEach(function (id) { | ||
this.emit(`execution.${id}`, new Error('sandbox: execution interrupted, bridge disconnecting.')); | ||
}); | ||
this.disconnect(); | ||
} | ||
}); | ||
|
||
_.assign(PostmanSandbox, { | ||
create: function (options, callback) { | ||
return new PostmanSandbox(options, callback); | ||
} | ||
}); | ||
|
||
module.exports = { | ||
createContext: function (options, callback) { | ||
if (_.isFunction(options) && !callback) { | ||
callback = options; | ||
options = {}; | ||
} | ||
|
||
options = _.clone(options); | ||
bootcode(function (err, code) { | ||
if (err) { return callback(err); } | ||
if (!code) { return callback(new Error('sandbox: bootcode missing!')); } | ||
|
||
options.bootcode = code; // assign the code in options | ||
PostmanSandbox.create(options, callback); | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
var Scope = require('uniscope'), | ||
postmanLegacyInterface = require('./postman-legacy-interface'); | ||
var gg = this; | ||
module.exports = { | ||
listener: function (prefix, ctx) { | ||
/** | ||
* @param {String} id | ||
* @param {Code} code | ||
* @param {Object} options | ||
* @param {String} options.scriptType // @todo make sdk event | ||
* @param {Object} data | ||
* @param {Object~VariableScope} data.globals | ||
* @param {Object~VariableScope} data.environment | ||
* @param {Object} data.cursor | ||
* @param {Object} data.iterationData | ||
* @param {Object~Request} data.request | ||
* @param {Object~Response} data.response | ||
* @param {Object} data.legacy | ||
* @param {Array} data.legacy.responseCookies, | ||
* @param {String} data.legacy.responseBody, | ||
* @param {Object} data.legacy.responseCode, | ||
* @param {Object} data.legacy.responseHeaders, | ||
* @param {Object} data.legacy.responseTime | ||
*/ | ||
return function (id, code, options, data) { | ||
var bridge = this, | ||
legacyInterface = postmanLegacyInterface.create(_.pick(options, 'scriptType'), _.get(data, 'legacy')), | ||
scope = Scope.create({ | ||
console: options.debug, | ||
eval: true | ||
}, { | ||
postman: legacyInterface | ||
}), | ||
dispatchEventName = prefix + id, | ||
done = (function (dispatchEventName) { | ||
var sealed = false; | ||
|
||
return function (err) { | ||
if (sealed) { return; } | ||
sealed = true; | ||
bridge.dispatch(dispatchEventName, err || null); | ||
}; | ||
}(dispatchEventName)); | ||
|
||
scope.exec(code, done); | ||
}; | ||
} | ||
}; |
Oops, something went wrong.