dynatrace-cordova-outsystems-plugin
Version:
This plugin gives you the ability to use the Dynatrace instrumentation in your hybrid application (Cordova, Ionic, ..). It uses the Mobile Agent, the JavaScript Agent and the Javascript Bridge. The Mobile Agent will give you all device specific values con
994 lines (703 loc) • 24.6 kB
JavaScript
// Load modules
var Crypto = require('crypto');
var Path = require('path');
var Util = require('util');
var Escape = require('./escape');
// Declare internals
var internals = {};
// Clone object or array
exports.clone = function (obj, seen) {
if (typeof obj !== 'object' ||
obj === null) {
return obj;
}
seen = seen || { orig: [], copy: [] };
var lookup = seen.orig.indexOf(obj);
if (lookup !== -1) {
return seen.copy[lookup];
}
var newObj;
var cloneDeep = false;
if (!Array.isArray(obj)) {
if (Buffer.isBuffer(obj)) {
newObj = new Buffer(obj);
}
else if (obj instanceof Date) {
newObj = new Date(obj.getTime());
}
else if (obj instanceof RegExp) {
newObj = new RegExp(obj);
}
else {
var proto = Object.getPrototypeOf(obj);
if (proto &&
proto.isImmutable) {
newObj = obj;
}
else {
newObj = Object.create(proto);
cloneDeep = true;
}
}
}
else {
newObj = [];
cloneDeep = true;
}
seen.orig.push(obj);
seen.copy.push(newObj);
if (cloneDeep) {
var keys = Object.getOwnPropertyNames(obj);
for (var i = 0, il = keys.length; i < il; ++i) {
var key = keys[i];
var descriptor = Object.getOwnPropertyDescriptor(obj, key);
if (descriptor &&
(descriptor.get ||
descriptor.set)) {
Object.defineProperty(newObj, key, descriptor);
}
else {
newObj[key] = exports.clone(obj[key], seen);
}
}
}
return newObj;
};
// Merge all the properties of source into target, source wins in conflict, and by default null and undefined from source are applied
/*eslint-disable */
exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) {
/*eslint-enable */
exports.assert(target && typeof target === 'object', 'Invalid target value: must be an object');
exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object');
if (!source) {
return target;
}
if (Array.isArray(source)) {
exports.assert(Array.isArray(target), 'Cannot merge array onto an object');
if (isMergeArrays === false) { // isMergeArrays defaults to true
target.length = 0; // Must not change target assignment
}
for (var i = 0, il = source.length; i < il; ++i) {
target.push(exports.clone(source[i]));
}
return target;
}
var keys = Object.keys(source);
for (var k = 0, kl = keys.length; k < kl; ++k) {
var key = keys[k];
var value = source[key];
if (value &&
typeof value === 'object') {
if (!target[key] ||
typeof target[key] !== 'object' ||
(Array.isArray(target[key]) ^ Array.isArray(value)) ||
value instanceof Date ||
Buffer.isBuffer(value) ||
value instanceof RegExp) {
target[key] = exports.clone(value);
}
else {
exports.merge(target[key], value, isNullOverride, isMergeArrays);
}
}
else {
if (value !== null &&
value !== undefined) { // Explicit to preserve empty strings
target[key] = value;
}
else if (isNullOverride !== false) { // Defaults to true
target[key] = value;
}
}
}
return target;
};
// Apply options to a copy of the defaults
exports.applyToDefaults = function (defaults, options, isNullOverride) {
exports.assert(defaults && typeof defaults === 'object', 'Invalid defaults value: must be an object');
exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');
if (!options) { // If no options, return null
return null;
}
var copy = exports.clone(defaults);
if (options === true) { // If options is set to true, use defaults
return copy;
}
return exports.merge(copy, options, isNullOverride === true, false);
};
// Clone an object except for the listed keys which are shallow copied
exports.cloneWithShallow = function (source, keys) {
if (!source ||
typeof source !== 'object') {
return source;
}
var storage = internals.store(source, keys); // Move shallow copy items to storage
var copy = exports.clone(source); // Deep copy the rest
internals.restore(copy, source, storage); // Shallow copy the stored items and restore
return copy;
};
internals.store = function (source, keys) {
var storage = {};
for (var i = 0, il = keys.length; i < il; ++i) {
var key = keys[i];
var value = exports.reach(source, key);
if (value !== undefined) {
storage[key] = value;
internals.reachSet(source, key, undefined);
}
}
return storage;
};
internals.restore = function (copy, source, storage) {
var keys = Object.keys(storage);
for (var i = 0, il = keys.length; i < il; ++i) {
var key = keys[i];
internals.reachSet(copy, key, storage[key]);
internals.reachSet(source, key, storage[key]);
}
};
internals.reachSet = function (obj, key, value) {
var path = key.split('.');
var ref = obj;
for (var i = 0, il = path.length; i < il; ++i) {
var segment = path[i];
if (i + 1 === il) {
ref[segment] = value;
}
ref = ref[segment];
}
};
// Apply options to defaults except for the listed keys which are shallow copied from option without merging
exports.applyToDefaultsWithShallow = function (defaults, options, keys) {
exports.assert(defaults && typeof defaults === 'object', 'Invalid defaults value: must be an object');
exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');
exports.assert(keys && Array.isArray(keys), 'Invalid keys');
if (!options) { // If no options, return null
return null;
}
var copy = exports.cloneWithShallow(defaults, keys);
if (options === true) { // If options is set to true, use defaults
return copy;
}
var storage = internals.store(options, keys); // Move shallow copy items to storage
exports.merge(copy, options, false, false); // Deep copy the rest
internals.restore(copy, options, storage); // Shallow copy the stored items and restore
return copy;
};
// Deep object or array comparison
exports.deepEqual = function (obj, ref, options, seen) {
options = options || { prototype: true };
var type = typeof obj;
if (type !== typeof ref) {
return false;
}
if (type !== 'object' ||
obj === null ||
ref === null) {
if (obj === ref) { // Copied from Deep-eql, copyright(c) 2013 Jake Luer, jake@alogicalparadox.com, MIT Licensed, https://github.com/chaijs/deep-eql
return obj !== 0 || 1 / obj === 1 / ref; // -0 / +0
}
return obj !== obj && ref !== ref; // NaN
}
seen = seen || [];
if (seen.indexOf(obj) !== -1) {
return true; // If previous comparison failed, it would have stopped execution
}
seen.push(obj);
if (Array.isArray(obj)) {
if (!Array.isArray(ref)) {
return false;
}
if (!options.part && obj.length !== ref.length) {
return false;
}
for (var i = 0, il = obj.length; i < il; ++i) {
if (options.part) {
var found = false;
for (var r = 0, rl = ref.length; r < rl; ++r) {
if (exports.deepEqual(obj[i], ref[r], options, seen)) {
found = true;
break;
}
}
return found;
}
if (!exports.deepEqual(obj[i], ref[i], options, seen)) {
return false;
}
}
return true;
}
if (Buffer.isBuffer(obj)) {
if (!Buffer.isBuffer(ref)) {
return false;
}
if (obj.length !== ref.length) {
return false;
}
for (var j = 0, jl = obj.length; j < jl; ++j) {
if (obj[j] !== ref[j]) {
return false;
}
}
return true;
}
if (obj instanceof Date) {
return (ref instanceof Date && obj.getTime() === ref.getTime());
}
if (obj instanceof RegExp) {
return (ref instanceof RegExp && obj.toString() === ref.toString());
}
if (options.prototype) {
if (Object.getPrototypeOf(obj) !== Object.getPrototypeOf(ref)) {
return false;
}
}
var keys = Object.getOwnPropertyNames(obj);
if (!options.part && keys.length !== Object.getOwnPropertyNames(ref).length) {
return false;
}
for (var k = 0, kl = keys.length; k < kl; ++k) {
var key = keys[k];
var descriptor = Object.getOwnPropertyDescriptor(obj, key);
if (descriptor.get) {
if (!exports.deepEqual(descriptor, Object.getOwnPropertyDescriptor(ref, key), options, seen)) {
return false;
}
}
else if (!exports.deepEqual(obj[key], ref[key], options, seen)) {
return false;
}
}
return true;
};
// Remove duplicate items from array
exports.unique = function (array, key) {
var index = {};
var result = [];
for (var i = 0, il = array.length; i < il; ++i) {
var id = (key ? array[i][key] : array[i]);
if (index[id] !== true) {
result.push(array[i]);
index[id] = true;
}
}
return result;
};
// Convert array into object
exports.mapToObject = function (array, key) {
if (!array) {
return null;
}
var obj = {};
for (var i = 0, il = array.length; i < il; ++i) {
if (key) {
if (array[i][key]) {
obj[array[i][key]] = true;
}
}
else {
obj[array[i]] = true;
}
}
return obj;
};
// Find the common unique items in two arrays
exports.intersect = function (array1, array2, justFirst) {
if (!array1 || !array2) {
return [];
}
var common = [];
var hash = (Array.isArray(array1) ? exports.mapToObject(array1) : array1);
var found = {};
for (var i = 0, il = array2.length; i < il; ++i) {
if (hash[array2[i]] && !found[array2[i]]) {
if (justFirst) {
return array2[i];
}
common.push(array2[i]);
found[array2[i]] = true;
}
}
return (justFirst ? null : common);
};
// Test if the reference contains the values
exports.contain = function (ref, values, options) {
/*
string -> string(s)
array -> item(s)
object -> key(s)
object -> object (key:value)
*/
var valuePairs = null;
if (typeof ref === 'object' &&
typeof values === 'object' &&
!Array.isArray(ref) &&
!Array.isArray(values)) {
valuePairs = values;
values = Object.keys(values);
}
else {
values = [].concat(values);
}
options = options || {}; // deep, once, only, part
exports.assert(arguments.length >= 2, 'Insufficient arguments');
exports.assert(typeof ref === 'string' || typeof ref === 'object', 'Reference must be string or an object');
exports.assert(values.length, 'Values array cannot be empty');
var compare, compareFlags;
if (options.deep) {
compare = exports.deepEqual;
var hasOnly = options.hasOwnProperty('only'), hasPart = options.hasOwnProperty('part');
compareFlags = {
prototype: hasOnly ? options.only : hasPart ? !options.part : false,
part: hasOnly ? !options.only : hasPart ? options.part : true
};
}
else {
compare = function (a, b) {
return a === b;
};
}
var misses = false;
var matches = new Array(values.length);
for (var i = 0, il = matches.length; i < il; ++i) {
matches[i] = 0;
}
if (typeof ref === 'string') {
var pattern = '(';
for (i = 0, il = values.length; i < il; ++i) {
var value = values[i];
exports.assert(typeof value === 'string', 'Cannot compare string reference to non-string value');
pattern += (i ? '|' : '') + exports.escapeRegex(value);
}
var regex = new RegExp(pattern + ')', 'g');
var leftovers = ref.replace(regex, function ($0, $1) {
var index = values.indexOf($1);
++matches[index];
return ''; // Remove from string
});
misses = !!leftovers;
}
else if (Array.isArray(ref)) {
for (i = 0, il = ref.length; i < il; ++i) {
for (var j = 0, jl = values.length, matched = false; j < jl && matched === false; ++j) {
matched = compare(values[j], ref[i], compareFlags) && j;
}
if (matched !== false) {
++matches[matched];
}
else {
misses = true;
}
}
}
else {
var keys = Object.keys(ref);
for (i = 0, il = keys.length; i < il; ++i) {
var key = keys[i];
var pos = values.indexOf(key);
if (pos !== -1) {
if (valuePairs &&
!compare(valuePairs[key], ref[key], compareFlags)) {
return false;
}
++matches[pos];
}
else {
misses = true;
}
}
}
var result = false;
for (i = 0, il = matches.length; i < il; ++i) {
result = result || !!matches[i];
if ((options.once && matches[i] > 1) ||
(!options.part && !matches[i])) {
return false;
}
}
if (options.only &&
misses) {
return false;
}
return result;
};
// Flatten array
exports.flatten = function (array, target) {
var result = target || [];
for (var i = 0, il = array.length; i < il; ++i) {
if (Array.isArray(array[i])) {
exports.flatten(array[i], result);
}
else {
result.push(array[i]);
}
}
return result;
};
// Convert an object key chain string ('a.b.c') to reference (object[a][b][c])
exports.reach = function (obj, chain, options) {
if (chain === false ||
chain === null ||
typeof chain === 'undefined') {
return obj;
}
options = options || {};
if (typeof options === 'string') {
options = { separator: options };
}
var path = chain.split(options.separator || '.');
var ref = obj;
for (var i = 0, il = path.length; i < il; ++i) {
var key = path[i];
if (key[0] === '-' && Array.isArray(ref)) {
key = key.slice(1, key.length);
key = ref.length - key;
}
if (!ref ||
!ref.hasOwnProperty(key) ||
(typeof ref !== 'object' && options.functions === false)) { // Only object and function can have properties
exports.assert(!options.strict || i + 1 === il, 'Missing segment', key, 'in reach path ', chain);
exports.assert(typeof ref === 'object' || options.functions === true || typeof ref !== 'function', 'Invalid segment', key, 'in reach path ', chain);
ref = options.default;
break;
}
ref = ref[key];
}
return ref;
};
exports.reachTemplate = function (obj, template, options) {
return template.replace(/{([^}]+)}/g, function ($0, chain) {
var value = exports.reach(obj, chain, options);
return (value === undefined || value === null ? '' : value);
});
};
exports.formatStack = function (stack) {
var trace = [];
for (var i = 0, il = stack.length; i < il; ++i) {
var item = stack[i];
trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]);
}
return trace;
};
exports.formatTrace = function (trace) {
var display = [];
for (var i = 0, il = trace.length; i < il; ++i) {
var row = trace[i];
display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')');
}
return display;
};
exports.callStack = function (slice) {
// http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
var v8 = Error.prepareStackTrace;
Error.prepareStackTrace = function (err, stack) {
return stack;
};
var capture = {};
Error.captureStackTrace(capture, arguments.callee); /*eslint no-caller:0 */
var stack = capture.stack;
Error.prepareStackTrace = v8;
var trace = exports.formatStack(stack);
if (slice) {
return trace.slice(slice);
}
return trace;
};
exports.displayStack = function (slice) {
var trace = exports.callStack(slice === undefined ? 1 : slice + 1);
return exports.formatTrace(trace);
};
exports.abortThrow = false;
exports.abort = function (message, hideStack) {
if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) {
throw new Error(message || 'Unknown error');
}
var stack = '';
if (!hideStack) {
stack = exports.displayStack(1).join('\n\t');
}
console.log('ABORT: ' + message + '\n\t' + stack);
process.exit(1);
};
exports.assert = function (condition /*, msg1, msg2, msg3 */) {
if (condition) {
return;
}
if (arguments.length === 2 && arguments[1] instanceof Error) {
throw arguments[1];
}
var msgs = [];
for (var i = 1, il = arguments.length; i < il; ++i) {
if (arguments[i] !== '') {
msgs.push(arguments[i]); // Avoids Array.slice arguments leak, allowing for V8 optimizations
}
}
msgs = msgs.map(function (msg) {
return typeof msg === 'string' ? msg : msg instanceof Error ? msg.message : exports.stringify(msg);
});
throw new Error(msgs.join(' ') || 'Unknown error');
};
exports.Timer = function () {
this.ts = 0;
this.reset();
};
exports.Timer.prototype.reset = function () {
this.ts = Date.now();
};
exports.Timer.prototype.elapsed = function () {
return Date.now() - this.ts;
};
exports.Bench = function () {
this.ts = 0;
this.reset();
};
exports.Bench.prototype.reset = function () {
this.ts = exports.Bench.now();
};
exports.Bench.prototype.elapsed = function () {
return exports.Bench.now() - this.ts;
};
exports.Bench.now = function () {
var ts = process.hrtime();
return (ts[0] * 1e3) + (ts[1] / 1e6);
};
// Escape string for Regex construction
exports.escapeRegex = function (string) {
// Escape ^$.*+-?=!:|\/()[]{},
return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
};
// Base64url (RFC 4648) encode
exports.base64urlEncode = function (value, encoding) {
var buf = (Buffer.isBuffer(value) ? value : new Buffer(value, encoding || 'binary'));
return buf.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
};
// Base64url (RFC 4648) decode
exports.base64urlDecode = function (value, encoding) {
if (value &&
!/^[\w\-]*$/.test(value)) {
return new Error('Invalid character');
}
try {
var buf = new Buffer(value, 'base64');
return (encoding === 'buffer' ? buf : buf.toString(encoding || 'binary'));
}
catch (err) {
return err;
}
};
// Escape attribute value for use in HTTP header
exports.escapeHeaderAttribute = function (attribute) {
// Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, "
exports.assert(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/.test(attribute), 'Bad attribute value (' + attribute + ')');
return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"'); // Escape quotes and slash
};
exports.escapeHtml = function (string) {
return Escape.escapeHtml(string);
};
exports.escapeJavaScript = function (string) {
return Escape.escapeJavaScript(string);
};
exports.nextTick = function (callback) {
return function () {
var args = arguments;
process.nextTick(function () {
callback.apply(null, args);
});
};
};
exports.once = function (method) {
if (method._hoekOnce) {
return method;
}
var once = false;
var wrapped = function () {
if (!once) {
once = true;
method.apply(null, arguments);
}
};
wrapped._hoekOnce = true;
return wrapped;
};
exports.isAbsolutePath = function (path, platform) {
if (!path) {
return false;
}
if (Path.isAbsolute) { // node >= 0.11
return Path.isAbsolute(path);
}
platform = platform || process.platform;
// Unix
if (platform !== 'win32') {
return path[0] === '/';
}
// Windows
return !!/^(?:[a-zA-Z]:[\\\/])|(?:[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/])/.test(path); // C:\ or \\something\something
};
exports.isInteger = function (value) {
return (typeof value === 'number' &&
parseFloat(value) === parseInt(value, 10) &&
!isNaN(value));
};
exports.ignore = function () { };
exports.inherits = Util.inherits;
exports.format = Util.format;
exports.transform = function (source, transform, options) {
exports.assert(source === null || source === undefined || typeof source === 'object' || Array.isArray(source), 'Invalid source object: must be null, undefined, an object, or an array');
if (Array.isArray(source)) {
var results = [];
for (var i = 0, il = source.length; i < il; ++i) {
results.push(exports.transform(source[i], transform, options));
}
return results;
}
var result = {};
var keys = Object.keys(transform);
for (var k = 0, kl = keys.length; k < kl; ++k) {
var key = keys[k];
var path = key.split('.');
var sourcePath = transform[key];
exports.assert(typeof sourcePath === 'string', 'All mappings must be "." delineated strings');
var segment;
var res = result;
while (path.length > 1) {
segment = path.shift();
if (!res[segment]) {
res[segment] = {};
}
res = res[segment];
}
segment = path.shift();
res[segment] = exports.reach(source, sourcePath, options);
}
return result;
};
exports.uniqueFilename = function (path, extension) {
if (extension) {
extension = extension[0] !== '.' ? '.' + extension : extension;
}
else {
extension = '';
}
path = Path.resolve(path);
var name = [Date.now(), process.pid, Crypto.randomBytes(8).toString('hex')].join('-') + extension;
return Path.join(path, name);
};
exports.stringify = function () {
try {
return JSON.stringify.apply(null, arguments);
}
catch (err) {
return '[Cannot display object: ' + err.message + ']';
}
};
exports.shallow = function (source) {
var target = {};
var keys = Object.keys(source);
for (var i = 0, il = keys.length; i < il; ++i) {
var key = keys[i];
target[key] = source[key];
}
return target;
};