Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Socket
Sign inDemoInstall

@datadog/browser-core

Package Overview
Dependencies
Maintainers
1
Versions
258
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@datadog/browser-core - npm Package Compare versions

Comparing version 1.25.0 to 1.25.1

cjs/tools/context.d.ts

28

cjs/domain/errorCollection.d.ts
import { Observable } from '../tools/observable';
import { Configuration } from './configuration';
import { StackTrace } from './tracekit';
export interface ErrorMessage {
export interface RawError {
startTime: number;
message: string;
context: {
error: ErrorContext;
http?: HttpContext;
type?: string;
stack?: string;
source: ErrorSource;
resource?: {
url: string;
statusCode: number;
method: string;
};
}
export interface ErrorContext {
kind?: string;
stack?: string;
origin: ErrorSource;
}
export interface HttpContext {
url: string;
status_code: number;
method: string;
}
export declare enum ErrorSource {

@@ -30,5 +24,5 @@ AGENT = "agent",

}
export declare type ErrorObservable = Observable<ErrorMessage>;
export declare type ErrorObservable = Observable<RawError>;
export declare function startErrorCollection(configuration: Configuration): ErrorObservable;
export declare function filterErrors(configuration: Configuration, errorObservable: Observable<ErrorMessage>): Observable<ErrorMessage>;
export declare function filterErrors(configuration: Configuration, errorObservable: Observable<RawError>): Observable<RawError>;
export declare function startConsoleTracking(errorObservable: ErrorObservable): void;

@@ -39,5 +33,5 @@ export declare function stopConsoleTracking(): void;

export declare function formatUnknownError(stackTrace: StackTrace | undefined, errorObject: any, nonErrorPrefix: string): {
kind: string | undefined;
message: string;
stack: string;
type: string | undefined;
};

@@ -44,0 +38,0 @@ export declare function toStackTraceString(stack: StackTrace): string;

@@ -43,8 +43,4 @@ "use strict";

filteredErrorObservable.notify({
context: {
error: {
origin: ErrorSource.AGENT,
},
},
message: "Reached max number of errors by minute: " + configuration.maxErrorsByMinute,
source: ErrorSource.AGENT,
startTime: performance.now(),

@@ -68,8 +64,4 @@ });

errorObservable.notify({
context: {
error: {
origin: ErrorSource.CONSOLE,
},
},
message: tslib_1.__spreadArrays(['console error:', message], optionalParams).map(formatConsoleParameters).join(' '),
source: ErrorSource.CONSOLE,
startTime: performance.now(),

@@ -96,12 +88,8 @@ });

traceKitReportHandler = function (stackTrace, _, errorObject) {
var _a = formatUnknownError(stackTrace, errorObject, 'Uncaught'), stack = _a.stack, message = _a.message, kind = _a.kind;
var _a = formatUnknownError(stackTrace, errorObject, 'Uncaught'), stack = _a.stack, message = _a.message, type = _a.type;
errorObservable.notify({
message: message,
context: {
error: {
kind: kind,
stack: stack,
origin: ErrorSource.SOURCE,
},
},
stack: stack,
type: type,
source: ErrorSource.SOURCE,
startTime: performance.now(),

@@ -121,11 +109,11 @@ });

return {
kind: stackTrace && stackTrace.name,
message: nonErrorPrefix + " " + utils_1.jsonStringify(errorObject),
stack: 'No stack, consider using an instance of Error',
type: stackTrace && stackTrace.name,
};
}
return {
kind: stackTrace.name,
message: stackTrace.message || 'Empty message',
stack: toStackTraceString(stackTrace),
type: stackTrace.name,
};

@@ -152,14 +140,10 @@ }

errorObservable.notify({
context: {
error: {
origin: ErrorSource.NETWORK,
stack: truncateResponse(request.response, configuration) || 'Failed to load',
},
http: {
method: request.method,
status_code: request.status,
url: request.url,
},
message: format(type) + " error " + request.method + " " + request.url,
resource: {
method: request.method,
statusCode: request.status,
url: request.url,
},
message: format(type) + " error " + request.method + " " + request.url,
source: ErrorSource.NETWORK,
stack: truncateResponse(request.response, configuration) || 'Failed to load',
startTime: request.startTime,

@@ -166,0 +150,0 @@ });

@@ -1,2 +0,2 @@

import * as utils from '../tools/utils';
import { Context } from '../tools/context';
import { Configuration } from './configuration';

@@ -8,5 +8,5 @@ declare enum StatusType {

export interface InternalMonitoring {
setExternalContextProvider: (provider: () => utils.Context) => void;
setExternalContextProvider: (provider: () => Context) => void;
}
export interface MonitoringMessage extends utils.Context {
export interface MonitoringMessage extends Context {
message: string;

@@ -23,4 +23,4 @@ status: StatusType;

export declare function monitor<T extends Function>(fn: T): T;
export declare function addMonitoringMessage(message: string, context?: utils.Context): void;
export declare function addMonitoringMessage(message: string, context?: Context): void;
export declare function setDebugMode(debugMode: boolean): void;
export {};

@@ -5,2 +5,3 @@ "use strict";

// tslint:disable ban-types
var context_1 = require("../tools/context");
var utils = tslib_1.__importStar(require("../tools/utils"));

@@ -43,3 +44,3 @@ var transport_1 = require("../transport/transport");

function withContext(message) {
return utils.combine({
return context_1.combine({
date: new Date().getTime(),

@@ -46,0 +47,0 @@ view: {

export { DEFAULT_CONFIGURATION, Configuration, UserConfiguration, isIntakeRequest, buildCookieOptions, } from './domain/configuration';
export { ErrorMessage, ErrorContext, HttpContext, ErrorSource, ErrorObservable, formatUnknownError, } from './domain/errorCollection';
export { ErrorSource, ErrorObservable, formatUnknownError, RawError } from './domain/errorCollection';
export { computeStackTrace } from './domain/tracekit';

@@ -11,2 +11,3 @@ export { BuildEnv, BuildMode, Datacenter, defineGlobal, makeGlobal, commonInit, checkCookiesAuthorized, checkIsNotLocalFile, } from './boot/init';

export * from './tools/utils';
export { combine, Context, ContextArray, ContextValue, deepClone, withSnakeCaseKeys } from './tools/context';
export { areCookiesAuthorized, getCookie, setCookie, COOKIE_ACCESS_DELAY } from './browser/cookie';

@@ -13,0 +14,0 @@ export { startXhrProxy, XhrCompleteContext, XhrStartContext, XhrProxy, resetXhrProxy } from './browser/xhrProxy';

@@ -38,2 +38,6 @@ "use strict";

tslib_1.__exportStar(require("./tools/utils"), exports);
var context_1 = require("./tools/context");
exports.combine = context_1.combine;
exports.deepClone = context_1.deepClone;
exports.withSnakeCaseKeys = context_1.withSnakeCaseKeys;
var cookie_1 = require("./browser/cookie");

@@ -40,0 +44,0 @@ exports.areCookiesAuthorized = cookie_1.areCookiesAuthorized;

@@ -1,2 +0,2 @@

import { Context, ContextValue } from './utils';
import { Context, ContextValue } from './context';
export declare function createContextManager(): {

@@ -3,0 +3,0 @@ get(): Context;

@@ -39,6 +39,2 @@ export declare const ONE_SECOND = 1000;

};
export declare function combine<A, B>(a: A, b: B): A & B;
export declare function combine<A, B, C>(a: A, b: B, c: C): A & B & C;
export declare function combine<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;
export declare function deepClone<T extends ContextValue>(context: T): T;
interface Assignable {

@@ -60,11 +56,2 @@ [key: string]: any;

export declare function msToNs<T>(duration: number | T): number | T;
export interface Context {
[x: string]: ContextValue;
}
export declare type ContextValue = string | number | boolean | Context | ContextArray | undefined | null;
export interface ContextArray extends Array<ContextValue> {
}
export declare function withSnakeCaseKeys(candidate: Context): Context;
export declare function deepSnakeCase(candidate: ContextValue): ContextValue;
export declare function toSnakeCase(word: string): string;
export declare function noop(): void;

@@ -71,0 +58,0 @@ /**

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
exports.ONE_SECOND = 1000;

@@ -75,76 +74,2 @@ exports.ONE_MINUTE = 60 * exports.ONE_SECOND;

exports.throttle = throttle;
var isContextArray = function (value) { return Array.isArray(value); };
var isContext = function (value) {
return !Array.isArray(value) && typeof value === 'object' && value !== null;
};
/**
* Performs a deep merge of objects and arrays.
* - Sources won't be mutated
* - Object and arrays in the output value are dereferenced ("deep cloned")
* - Arrays values are merged index by index
* - Objects are merged by keys
* - Values get replaced, unless undefined
*
* ⚠️ This function does not prevent infinite loops while merging circular references
*/
function deepMerge() {
var sources = [];
for (var _i = 0; _i < arguments.length; _i++) {
sources[_i] = arguments[_i];
}
var destination;
for (var i = sources.length - 1; i >= 0; i -= 1) {
var source = sources[i];
if (source === undefined) {
// Ignore any undefined source.
continue;
}
if (destination === undefined) {
// This is the first defined source. If it is "mergeable" (array or object), initialize the
// destination with an empty value that will be populated with all sources sub values. Else,
// just return its value.
if (isContext(source)) {
destination = {};
}
else if (isContextArray(source)) {
destination = [];
}
else {
destination = source;
break;
}
}
// At this point, 'destination' is either an array or an object. If the current 'source' has
// the same type we can merge it. Else, don't try to merge it or any other source.
if (isContext(destination) && isContext(source)) {
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
destination[key] = deepMerge(source[key], destination[key]);
}
}
}
else if (isContextArray(destination) && isContextArray(source)) {
destination.length = Math.max(destination.length, source.length);
for (var index = 0; index < source.length; index += 1) {
destination[index] = deepMerge(source[index], destination[index]);
}
}
else {
break;
}
}
return destination;
}
function combine(destination) {
var toMerge = [];
for (var _i = 1; _i < arguments.length; _i++) {
toMerge[_i - 1] = arguments[_i];
}
return deepMerge.apply(void 0, tslib_1.__spreadArrays([destination], toMerge.filter(function (object) { return object !== null; })));
}
exports.combine = combine;
function deepClone(context) {
return deepMerge(context);
}
exports.deepClone = deepClone;
function assign(target) {

@@ -194,26 +119,2 @@ var toAssign = [];

exports.msToNs = msToNs;
function withSnakeCaseKeys(candidate) {
var result = {};
Object.keys(candidate).forEach(function (key) {
result[toSnakeCase(key)] = deepSnakeCase(candidate[key]);
});
return result;
}
exports.withSnakeCaseKeys = withSnakeCaseKeys;
function deepSnakeCase(candidate) {
if (Array.isArray(candidate)) {
return candidate.map(function (value) { return deepSnakeCase(value); });
}
if (typeof candidate === 'object' && candidate !== null) {
return withSnakeCaseKeys(candidate);
}
return candidate;
}
exports.deepSnakeCase = deepSnakeCase;
function toSnakeCase(word) {
return word
.replace(/[A-Z]/g, function (uppercaseLetter, index) { return "" + (index !== 0 ? '_' : '') + uppercaseLetter.toLowerCase(); })
.replace(/-/g, '_');
}
exports.toSnakeCase = toSnakeCase;
// tslint:disable-next-line:no-empty

@@ -220,0 +121,0 @@ function noop() { }

@@ -1,2 +0,2 @@

import { Context } from '../tools/utils';
import { Context } from '../tools/context';
/**

@@ -3,0 +3,0 @@ * Use POST request without content type to:

import { Observable } from '../tools/observable';
import { Configuration } from './configuration';
import { StackTrace } from './tracekit';
export interface ErrorMessage {
export interface RawError {
startTime: number;
message: string;
context: {
error: ErrorContext;
http?: HttpContext;
type?: string;
stack?: string;
source: ErrorSource;
resource?: {
url: string;
statusCode: number;
method: string;
};
}
export interface ErrorContext {
kind?: string;
stack?: string;
origin: ErrorSource;
}
export interface HttpContext {
url: string;
status_code: number;
method: string;
}
export declare enum ErrorSource {

@@ -30,5 +24,5 @@ AGENT = "agent",

}
export declare type ErrorObservable = Observable<ErrorMessage>;
export declare type ErrorObservable = Observable<RawError>;
export declare function startErrorCollection(configuration: Configuration): ErrorObservable;
export declare function filterErrors(configuration: Configuration, errorObservable: Observable<ErrorMessage>): Observable<ErrorMessage>;
export declare function filterErrors(configuration: Configuration, errorObservable: Observable<RawError>): Observable<RawError>;
export declare function startConsoleTracking(errorObservable: ErrorObservable): void;

@@ -39,5 +33,5 @@ export declare function stopConsoleTracking(): void;

export declare function formatUnknownError(stackTrace: StackTrace | undefined, errorObject: any, nonErrorPrefix: string): {
kind: string | undefined;
message: string;
stack: string;
type: string | undefined;
};

@@ -44,0 +38,0 @@ export declare function toStackTraceString(stack: StackTrace): string;

@@ -40,8 +40,4 @@ import { __spreadArrays } from "tslib";

filteredErrorObservable.notify({
context: {
error: {
origin: ErrorSource.AGENT,
},
},
message: "Reached max number of errors by minute: " + configuration.maxErrorsByMinute,
source: ErrorSource.AGENT,
startTime: performance.now(),

@@ -64,8 +60,4 @@ });

errorObservable.notify({
context: {
error: {
origin: ErrorSource.CONSOLE,
},
},
message: __spreadArrays(['console error:', message], optionalParams).map(formatConsoleParameters).join(' '),
source: ErrorSource.CONSOLE,
startTime: performance.now(),

@@ -90,12 +82,8 @@ });

traceKitReportHandler = function (stackTrace, _, errorObject) {
var _a = formatUnknownError(stackTrace, errorObject, 'Uncaught'), stack = _a.stack, message = _a.message, kind = _a.kind;
var _a = formatUnknownError(stackTrace, errorObject, 'Uncaught'), stack = _a.stack, message = _a.message, type = _a.type;
errorObservable.notify({
message: message,
context: {
error: {
kind: kind,
stack: stack,
origin: ErrorSource.SOURCE,
},
},
stack: stack,
type: type,
source: ErrorSource.SOURCE,
startTime: performance.now(),

@@ -113,11 +101,11 @@ });

return {
kind: stackTrace && stackTrace.name,
message: nonErrorPrefix + " " + jsonStringify(errorObject),
stack: 'No stack, consider using an instance of Error',
type: stackTrace && stackTrace.name,
};
}
return {
kind: stackTrace.name,
message: stackTrace.message || 'Empty message',
stack: toStackTraceString(stackTrace),
type: stackTrace.name,
};

@@ -142,14 +130,10 @@ }

errorObservable.notify({
context: {
error: {
origin: ErrorSource.NETWORK,
stack: truncateResponse(request.response, configuration) || 'Failed to load',
},
http: {
method: request.method,
status_code: request.status,
url: request.url,
},
message: format(type) + " error " + request.method + " " + request.url,
resource: {
method: request.method,
statusCode: request.status,
url: request.url,
},
message: format(type) + " error " + request.method + " " + request.url,
source: ErrorSource.NETWORK,
stack: truncateResponse(request.response, configuration) || 'Failed to load',
startTime: request.startTime,

@@ -156,0 +140,0 @@ });

@@ -1,2 +0,2 @@

import * as utils from '../tools/utils';
import { Context } from '../tools/context';
import { Configuration } from './configuration';

@@ -8,5 +8,5 @@ declare enum StatusType {

export interface InternalMonitoring {
setExternalContextProvider: (provider: () => utils.Context) => void;
setExternalContextProvider: (provider: () => Context) => void;
}
export interface MonitoringMessage extends utils.Context {
export interface MonitoringMessage extends Context {
message: string;

@@ -23,4 +23,4 @@ status: StatusType;

export declare function monitor<T extends Function>(fn: T): T;
export declare function addMonitoringMessage(message: string, context?: utils.Context): void;
export declare function addMonitoringMessage(message: string, context?: Context): void;
export declare function setDebugMode(debugMode: boolean): void;
export {};
import { __assign } from "tslib";
// tslint:disable ban-types
import { combine } from '../tools/context';
import * as utils from '../tools/utils';

@@ -39,3 +40,3 @@ import { Batch, HttpRequest } from '../transport/transport';

function withContext(message) {
return utils.combine({
return combine({
date: new Date().getTime(),

@@ -42,0 +43,0 @@ view: {

export { DEFAULT_CONFIGURATION, Configuration, UserConfiguration, isIntakeRequest, buildCookieOptions, } from './domain/configuration';
export { ErrorMessage, ErrorContext, HttpContext, ErrorSource, ErrorObservable, formatUnknownError, } from './domain/errorCollection';
export { ErrorSource, ErrorObservable, formatUnknownError, RawError } from './domain/errorCollection';
export { computeStackTrace } from './domain/tracekit';

@@ -11,2 +11,3 @@ export { BuildEnv, BuildMode, Datacenter, defineGlobal, makeGlobal, commonInit, checkCookiesAuthorized, checkIsNotLocalFile, } from './boot/init';

export * from './tools/utils';
export { combine, Context, ContextArray, ContextValue, deepClone, withSnakeCaseKeys } from './tools/context';
export { areCookiesAuthorized, getCookie, setCookie, COOKIE_ACCESS_DELAY } from './browser/cookie';

@@ -13,0 +14,0 @@ export { startXhrProxy, XhrCompleteContext, XhrStartContext, XhrProxy, resetXhrProxy } from './browser/xhrProxy';

export { DEFAULT_CONFIGURATION, isIntakeRequest, buildCookieOptions, } from './domain/configuration';
export { ErrorSource, formatUnknownError, } from './domain/errorCollection';
export { ErrorSource, formatUnknownError } from './domain/errorCollection';
export { computeStackTrace } from './domain/tracekit';

@@ -13,2 +13,3 @@ export { BuildMode, Datacenter, defineGlobal, makeGlobal, commonInit, checkCookiesAuthorized, checkIsNotLocalFile, } from './boot/init';

export * from './tools/utils';
export { combine, deepClone, withSnakeCaseKeys } from './tools/context';
export { areCookiesAuthorized, getCookie, setCookie, COOKIE_ACCESS_DELAY } from './browser/cookie';

@@ -15,0 +16,0 @@ export { startXhrProxy, resetXhrProxy } from './browser/xhrProxy';

@@ -1,2 +0,2 @@

import { Context, ContextValue } from './utils';
import { Context, ContextValue } from './context';
export declare function createContextManager(): {

@@ -3,0 +3,0 @@ get(): Context;

@@ -39,6 +39,2 @@ export declare const ONE_SECOND = 1000;

};
export declare function combine<A, B>(a: A, b: B): A & B;
export declare function combine<A, B, C>(a: A, b: B, c: C): A & B & C;
export declare function combine<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;
export declare function deepClone<T extends ContextValue>(context: T): T;
interface Assignable {

@@ -60,11 +56,2 @@ [key: string]: any;

export declare function msToNs<T>(duration: number | T): number | T;
export interface Context {
[x: string]: ContextValue;
}
export declare type ContextValue = string | number | boolean | Context | ContextArray | undefined | null;
export interface ContextArray extends Array<ContextValue> {
}
export declare function withSnakeCaseKeys(candidate: Context): Context;
export declare function deepSnakeCase(candidate: ContextValue): ContextValue;
export declare function toSnakeCase(word: string): string;
export declare function noop(): void;

@@ -71,0 +58,0 @@ /**

@@ -1,2 +0,1 @@

import { __spreadArrays } from "tslib";
export var ONE_SECOND = 1000;

@@ -72,74 +71,2 @@ export var ONE_MINUTE = 60 * ONE_SECOND;

}
var isContextArray = function (value) { return Array.isArray(value); };
var isContext = function (value) {
return !Array.isArray(value) && typeof value === 'object' && value !== null;
};
/**
* Performs a deep merge of objects and arrays.
* - Sources won't be mutated
* - Object and arrays in the output value are dereferenced ("deep cloned")
* - Arrays values are merged index by index
* - Objects are merged by keys
* - Values get replaced, unless undefined
*
* ⚠️ This function does not prevent infinite loops while merging circular references
*/
function deepMerge() {
var sources = [];
for (var _i = 0; _i < arguments.length; _i++) {
sources[_i] = arguments[_i];
}
var destination;
for (var i = sources.length - 1; i >= 0; i -= 1) {
var source = sources[i];
if (source === undefined) {
// Ignore any undefined source.
continue;
}
if (destination === undefined) {
// This is the first defined source. If it is "mergeable" (array or object), initialize the
// destination with an empty value that will be populated with all sources sub values. Else,
// just return its value.
if (isContext(source)) {
destination = {};
}
else if (isContextArray(source)) {
destination = [];
}
else {
destination = source;
break;
}
}
// At this point, 'destination' is either an array or an object. If the current 'source' has
// the same type we can merge it. Else, don't try to merge it or any other source.
if (isContext(destination) && isContext(source)) {
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
destination[key] = deepMerge(source[key], destination[key]);
}
}
}
else if (isContextArray(destination) && isContextArray(source)) {
destination.length = Math.max(destination.length, source.length);
for (var index = 0; index < source.length; index += 1) {
destination[index] = deepMerge(source[index], destination[index]);
}
}
else {
break;
}
}
return destination;
}
export function combine(destination) {
var toMerge = [];
for (var _i = 1; _i < arguments.length; _i++) {
toMerge[_i - 1] = arguments[_i];
}
return deepMerge.apply(void 0, __spreadArrays([destination], toMerge.filter(function (object) { return object !== null; })));
}
export function deepClone(context) {
return deepMerge(context);
}
export function assign(target) {

@@ -184,23 +111,2 @@ var toAssign = [];

}
export function withSnakeCaseKeys(candidate) {
var result = {};
Object.keys(candidate).forEach(function (key) {
result[toSnakeCase(key)] = deepSnakeCase(candidate[key]);
});
return result;
}
export function deepSnakeCase(candidate) {
if (Array.isArray(candidate)) {
return candidate.map(function (value) { return deepSnakeCase(value); });
}
if (typeof candidate === 'object' && candidate !== null) {
return withSnakeCaseKeys(candidate);
}
return candidate;
}
export function toSnakeCase(word) {
return word
.replace(/[A-Z]/g, function (uppercaseLetter, index) { return "" + (index !== 0 ? '_' : '') + uppercaseLetter.toLowerCase(); })
.replace(/-/g, '_');
}
// tslint:disable-next-line:no-empty

@@ -207,0 +113,0 @@ export function noop() { }

@@ -1,2 +0,2 @@

import { Context } from '../tools/utils';
import { Context } from '../tools/context';
/**

@@ -3,0 +3,0 @@ * Use POST request without content type to:

{
"name": "@datadog/browser-core",
"version": "1.25.0",
"version": "1.25.1",
"license": "Apache-2.0",

@@ -26,3 +26,3 @@ "main": "cjs/index.js",

},
"gitHead": "3b66e416efe51c32cc0636fd57aa9cd8c90bf16b"
"gitHead": "e2a15f2b957fadc47263116af9acb960cc5354b2"
}
import { areCookiesAuthorized, CookieOptions } from '../browser/cookie'
import { buildConfiguration, UserConfiguration } from '../domain/configuration'
import { ErrorMessage, startErrorCollection } from '../domain/errorCollection'
import { RawError, startErrorCollection } from '../domain/errorCollection'
import { setDebugMode, startInternalMonitoring } from '../domain/internalMonitoring'

@@ -64,3 +64,3 @@ import { Observable } from '../tools/observable'

const internalMonitoring = startInternalMonitoring(configuration)
const errorObservable = isCollectingError ? startErrorCollection(configuration) : new Observable<ErrorMessage>()
const errorObservable = isCollectingError ? startErrorCollection(configuration) : new Observable<RawError>()

@@ -67,0 +67,0 @@ return {

@@ -6,6 +6,6 @@ import { Observable } from '../tools/observable'

import {
ErrorMessage,
ErrorSource,
filterErrors,
formatUnknownError,
RawError,
startConsoleTracking,

@@ -23,7 +23,3 @@ startRuntimeErrorTracking,

const CONSOLE_CONTEXT = {
context: {
error: {
origin: ErrorSource.CONSOLE,
},
},
source: ErrorSource.CONSOLE,
}

@@ -34,3 +30,3 @@

notifyError = jasmine.createSpy()
const errorObservable = new Observable<ErrorMessage>()
const errorObservable = new Observable<RawError>()
errorObservable.subscribe(notifyError)

@@ -69,5 +65,3 @@ startConsoleTracking(errorObservable)

console.error(new TypeError('hello'))
expect((notifyError.calls.mostRecent().args[0] as ErrorMessage).message).toContain(
'console error: TypeError: hello'
)
expect((notifyError.calls.mostRecent().args[0] as RawError).message).toContain('console error: TypeError: hello')
})

@@ -88,4 +82,4 @@ })

notifyError = jasmine.createSpy()
const errorObservable = new Observable<ErrorMessage>()
errorObservable.subscribe((e: ErrorMessage) => notifyError(e) as void)
const errorObservable = new Observable<RawError>()
errorObservable.subscribe((e: RawError) => notifyError(e) as void)

@@ -117,3 +111,3 @@ startRuntimeErrorTracking(errorObservable)

setTimeout(() => {
expect((notifyError.calls.mostRecent().args[0] as ErrorMessage).message).toEqual(ERROR_MESSAGE)
expect((notifyError.calls.mostRecent().args[0] as RawError).message).toEqual(ERROR_MESSAGE)
done()

@@ -159,3 +153,3 @@ }, 100)

expect(formatted.message).toEqual('oh snap!')
expect(formatted.kind).toEqual('TypeError')
expect(formatted.type).toEqual('TypeError')
expect(formatted.stack).toEqual(`TypeError: oh snap!

@@ -215,3 +209,3 @@ at foo(1, bar) @ http://path/to/file.js:52:15

}
const errorObservable = new Observable<ErrorMessage>()
const errorObservable = new Observable<RawError>()
errorObservableSpy = spyOn(errorObservable, 'notify')

@@ -235,7 +229,10 @@ const configuration = { requestErrorResponseLengthLimit: 32, ...SPEC_ENDPOINTS }

expect(errorObservableSpy).toHaveBeenCalledWith({
context: {
error: { origin: 'network', stack: 'Server error' },
http: { method: 'GET', status_code: 503, url: 'http://fake.com/' },
message: 'Fetch error GET http://fake.com/',
resource: {
method: 'GET',
statusCode: 503,
url: 'http://fake.com/',
},
message: 'Fetch error GET http://fake.com/',
source: 'network',
stack: 'Server error',
startTime: jasmine.any(Number),

@@ -288,3 +285,3 @@ })

expect(errorObservableSpy).toHaveBeenCalled()
const stack = (errorObservableSpy.calls.mostRecent().args[0] as ErrorMessage).context.error.stack
const stack = (errorObservableSpy.calls.mostRecent().args[0] as RawError).stack
expect(stack).toEqual('Failed to load')

@@ -299,3 +296,3 @@ done()

fetchStubManager.whenAllComplete(() => {
const stack = (errorObservableSpy.calls.mostRecent().args[0] as ErrorMessage).context.error.stack
const stack = (errorObservableSpy.calls.mostRecent().args[0] as RawError).stack
expect(stack).toEqual('Lorem ipsum dolor sit amet orci ...')

@@ -308,10 +305,6 @@ done()

describe('error limitation', () => {
let errorObservable: Observable<ErrorMessage>
let errorObservable: Observable<RawError>
let filteredSubscriber: jasmine.Spy
const CONTEXT = {
context: {
error: {
origin: ErrorSource.SOURCE,
},
},
source: ErrorSource.SOURCE,
startTime: 100,

@@ -321,3 +314,3 @@ }

beforeEach(() => {
errorObservable = new Observable<ErrorMessage>()
errorObservable = new Observable<RawError>()
const configuration: Partial<Configuration> = { maxErrorsByMinute: 2 }

@@ -350,4 +343,4 @@ jasmine.clock().install()

expect(filteredSubscriber).toHaveBeenCalledWith({
context: { error: { origin: ErrorSource.AGENT } },
message: 'Reached max number of errors by minute: 2',
source: ErrorSource.AGENT,
startTime: jasmine.any(Number),

@@ -354,0 +347,0 @@ })

@@ -9,23 +9,15 @@ import { FetchCompleteContext, resetFetchProxy, startFetchProxy } from '../browser/fetchProxy'

export interface ErrorMessage {
export interface RawError {
startTime: number
message: string
context: {
error: ErrorContext
http?: HttpContext
type?: string
stack?: string
source: ErrorSource
resource?: {
url: string
statusCode: number
method: string
}
}
export interface ErrorContext {
kind?: string
stack?: string
origin: ErrorSource
}
export interface HttpContext {
url: string
status_code: number
method: string
}
export enum ErrorSource {

@@ -40,3 +32,3 @@ AGENT = 'agent',

export type ErrorObservable = Observable<ErrorMessage>
export type ErrorObservable = Observable<RawError>
let filteredErrorsObservable: ErrorObservable

@@ -46,3 +38,3 @@

if (!filteredErrorsObservable) {
const errorObservable = new Observable<ErrorMessage>()
const errorObservable = new Observable<RawError>()
trackNetworkError(configuration, errorObservable)

@@ -56,6 +48,6 @@ startConsoleTracking(errorObservable)

export function filterErrors(configuration: Configuration, errorObservable: Observable<ErrorMessage>) {
export function filterErrors(configuration: Configuration, errorObservable: Observable<RawError>) {
let errorCount = 0
const filteredErrorObservable = new Observable<ErrorMessage>()
errorObservable.subscribe((error: ErrorMessage) => {
const filteredErrorObservable = new Observable<RawError>()
errorObservable.subscribe((error: RawError) => {
if (errorCount < configuration.maxErrorsByMinute) {

@@ -67,8 +59,4 @@ errorCount += 1

filteredErrorObservable.notify({
context: {
error: {
origin: ErrorSource.AGENT,
},
},
message: `Reached max number of errors by minute: ${configuration.maxErrorsByMinute}`,
source: ErrorSource.AGENT,
startTime: performance.now(),

@@ -89,8 +77,4 @@ })

errorObservable.notify({
context: {
error: {
origin: ErrorSource.CONSOLE,
},
},
message: ['console error:', message, ...optionalParams].map(formatConsoleParameters).join(' '),
source: ErrorSource.CONSOLE,
startTime: performance.now(),

@@ -119,12 +103,8 @@ })

traceKitReportHandler = (stackTrace: StackTrace, _: boolean, errorObject?: any) => {
const { stack, message, kind } = formatUnknownError(stackTrace, errorObject, 'Uncaught')
const { stack, message, type } = formatUnknownError(stackTrace, errorObject, 'Uncaught')
errorObservable.notify({
message,
context: {
error: {
kind,
stack,
origin: ErrorSource.SOURCE,
},
},
stack,
type,
source: ErrorSource.SOURCE,
startTime: performance.now(),

@@ -143,5 +123,5 @@ })

return {
kind: stackTrace && stackTrace.name,
message: `${nonErrorPrefix} ${jsonStringify(errorObject)}`,
stack: 'No stack, consider using an instance of Error',
type: stackTrace && stackTrace.name,
}

@@ -151,5 +131,5 @@ }

return {
kind: stackTrace.name,
message: stackTrace.message || 'Empty message',
stack: toStackTraceString(stackTrace),
type: stackTrace.name,
}

@@ -177,14 +157,10 @@ }

errorObservable.notify({
context: {
error: {
origin: ErrorSource.NETWORK,
stack: truncateResponse(request.response, configuration) || 'Failed to load',
},
http: {
method: request.method,
status_code: request.status,
url: request.url,
},
message: `${format(type)} error ${request.method} ${request.url}`,
resource: {
method: request.method,
statusCode: request.status,
url: request.url,
},
message: `${format(type)} error ${request.method} ${request.url}`,
source: ErrorSource.NETWORK,
stack: truncateResponse(request.response, configuration) || 'Failed to load',
startTime: request.startTime,

@@ -191,0 +167,0 @@ })

// tslint:disable ban-types
import { combine, Context } from '../tools/context'
import * as utils from '../tools/utils'

@@ -14,6 +15,6 @@ import { Batch, HttpRequest } from '../transport/transport'

export interface InternalMonitoring {
setExternalContextProvider: (provider: () => utils.Context) => void
setExternalContextProvider: (provider: () => Context) => void
}
export interface MonitoringMessage extends utils.Context {
export interface MonitoringMessage extends Context {
message: string

@@ -34,3 +35,3 @@ status: StatusType

let externalContextProvider: () => utils.Context
let externalContextProvider: () => Context

@@ -48,3 +49,3 @@ export function startInternalMonitoring(configuration: Configuration): InternalMonitoring {

return {
setExternalContextProvider: (provider: () => utils.Context) => {
setExternalContextProvider: (provider: () => Context) => {
externalContextProvider = provider

@@ -73,3 +74,3 @@ },

function withContext(message: MonitoringMessage) {
return utils.combine(
return combine(
{

@@ -125,3 +126,3 @@ date: new Date().getTime(),

export function addMonitoringMessage(message: string, context?: utils.Context) {
export function addMonitoringMessage(message: string, context?: Context) {
logMessageIfDebug(message)

@@ -128,0 +129,0 @@ addToMonitoringBatch({

@@ -8,10 +8,3 @@ export {

} from './domain/configuration'
export {
ErrorMessage,
ErrorContext,
HttpContext,
ErrorSource,
ErrorObservable,
formatUnknownError,
} from './domain/errorCollection'
export { ErrorSource, ErrorObservable, formatUnknownError, RawError } from './domain/errorCollection'
export { computeStackTrace } from './domain/tracekit'

@@ -46,2 +39,3 @@ export {

export * from './tools/utils'
export { combine, Context, ContextArray, ContextValue, deepClone, withSnakeCaseKeys } from './tools/context'
export { areCookiesAuthorized, getCookie, setCookie, COOKIE_ACCESS_DELAY } from './browser/cookie'

@@ -48,0 +42,0 @@ export { startXhrProxy, XhrCompleteContext, XhrStartContext, XhrProxy, resetXhrProxy } from './browser/xhrProxy'

@@ -1,2 +0,2 @@

import { Context, ContextValue } from './utils'
import { Context, ContextValue } from './context'

@@ -3,0 +3,0 @@ export function createContextManager() {

@@ -1,84 +0,4 @@

import {
combine,
deepClone,
findCommaSeparatedValue,
jsonStringify,
performDraw,
round,
safeTruncate,
throttle,
toSnakeCase,
withSnakeCaseKeys,
} from './utils'
import { findCommaSeparatedValue, jsonStringify, performDraw, round, safeTruncate, throttle } from './utils'
describe('utils', () => {
describe('combine', () => {
it('should deeply add and replace keys', () => {
const sourceA = { a: { b: 'toBeReplaced', c: 'source a' } }
const sourceB = { a: { b: 'replaced', d: 'source b' } }
expect(combine(sourceA, sourceB)).toEqual({ a: { b: 'replaced', c: 'source a', d: 'source b' } })
})
it('should not replace with undefined', () => {
expect(combine({ a: 1 }, { a: undefined as number | undefined })).toEqual({ a: 1 })
})
it('should replace a sub-value with null', () => {
// tslint:disable-next-line: no-null-keyword
expect(combine({ a: {} }, { a: null as any })).toEqual({ a: null })
})
it('should ignore null arguments', () => {
// tslint:disable-next-line: no-null-keyword
expect(combine({ a: 1 }, null)).toEqual({ a: 1 })
})
it('should merge arrays', () => {
const sourceA = [{ a: 'source a' }, 'extraString'] as any
const sourceB = [{ b: 'source b' }] as any
expect(combine(sourceA, sourceB)).toEqual([{ a: 'source a', b: 'source b' }, 'extraString'])
})
it('should merge multiple objects', () => {
expect(combine({ a: 1 }, { b: 2 }, { c: 3 })).toEqual({ a: 1, b: 2, c: 3 })
})
it('should not keep references on objects', () => {
const source = { a: { b: 1 } }
const result = combine({}, source)
expect(result.a).not.toBe(source.a)
})
it('should not keep references on arrays', () => {
const source = { a: [1] }
const result = combine({}, source)
expect(result.a).not.toBe(source.a)
})
})
describe('deepClone', () => {
it('should return a result deeply equal to the source', () => {
const clonedValue = deepClone({ a: 1 })
expect(clonedValue).toEqual({ a: 1 })
})
it('should return a different reference', () => {
const value = { a: 1 }
const clonedValue = deepClone(value)
expect(clonedValue).not.toBe(value)
})
it('should return different references for objects sub values', () => {
const value = { a: { b: 1 } }
const clonedValue = deepClone(value)
expect(clonedValue.a).not.toBe(value.a)
})
it('should return different references for arrays items', () => {
const value = { a: [1] }
const clonedValue = deepClone(value)
expect(clonedValue.a).not.toBe(value.a)
})
})
describe('throttle', () => {

@@ -303,26 +223,2 @@ let spy: jasmine.Spy

describe('format', () => {
it('should format a string to snake case', () => {
expect(toSnakeCase('camelCaseWord')).toEqual('camel_case_word')
expect(toSnakeCase('PascalCase')).toEqual('pascal_case')
expect(toSnakeCase('kebab-case')).toEqual('kebab_case')
})
it('should format object keys in snake case', () => {
expect(
withSnakeCaseKeys({
camelCase: 1,
nestedKey: { 'kebab-case': 'helloWorld', array: [{ camelCase: 1 }, { camelCase: 2 }] },
// tslint:disable-next-line: no-null-keyword
nullValue: null,
})
).toEqual({
camel_case: 1,
nested_key: { kebab_case: 'helloWorld', array: [{ camel_case: 1 }, { camel_case: 2 }] },
// tslint:disable-next-line: no-null-keyword
null_value: null,
})
})
})
describe('jsonStringify', () => {

@@ -329,0 +225,0 @@ it('should jsonStringify an object with toJSON directly defined', () => {

@@ -76,73 +76,2 @@ export const ONE_SECOND = 1000

const isContextArray = (value: ContextValue): value is ContextArray => Array.isArray(value)
const isContext = (value: ContextValue): value is Context =>
!Array.isArray(value) && typeof value === 'object' && value !== null
/**
* Performs a deep merge of objects and arrays.
* - Sources won't be mutated
* - Object and arrays in the output value are dereferenced ("deep cloned")
* - Arrays values are merged index by index
* - Objects are merged by keys
* - Values get replaced, unless undefined
*
* ⚠️ This function does not prevent infinite loops while merging circular references
*/
function deepMerge(...sources: ContextValue[]): ContextValue {
let destination: ContextValue
for (let i = sources.length - 1; i >= 0; i -= 1) {
const source = sources[i]
if (source === undefined) {
// Ignore any undefined source.
continue
}
if (destination === undefined) {
// This is the first defined source. If it is "mergeable" (array or object), initialize the
// destination with an empty value that will be populated with all sources sub values. Else,
// just return its value.
if (isContext(source)) {
destination = {}
} else if (isContextArray(source)) {
destination = []
} else {
destination = source
break
}
}
// At this point, 'destination' is either an array or an object. If the current 'source' has
// the same type we can merge it. Else, don't try to merge it or any other source.
if (isContext(destination) && isContext(source)) {
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
destination[key] = deepMerge(source[key], destination[key])
}
}
} else if (isContextArray(destination) && isContextArray(source)) {
destination.length = Math.max(destination.length, source.length)
for (let index = 0; index < source.length; index += 1) {
destination[index] = deepMerge(source[index], destination[index])
}
} else {
break
}
}
return destination
}
export function combine<A, B>(a: A, b: B): A & B
export function combine<A, B, C>(a: A, b: B, c: C): A & B & C
export function combine<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D
export function combine(destination: Context, ...toMerge: Array<Context | null>): Context {
return deepMerge(destination, ...toMerge.filter((object) => object !== null)) as Context
}
export function deepClone<T extends ContextValue>(context: T): T {
return deepMerge(context) as T
}
interface Assignable {

@@ -192,37 +121,2 @@ [key: string]: any

export interface Context {
[x: string]: ContextValue
}
export type ContextValue = string | number | boolean | Context | ContextArray | undefined | null
export interface ContextArray extends Array<ContextValue> {}
export function withSnakeCaseKeys(candidate: Context): Context {
const result: Context = {}
Object.keys(candidate as Context).forEach((key: string) => {
result[toSnakeCase(key)] = deepSnakeCase(candidate[key])
})
return result as Context
}
export function deepSnakeCase(candidate: ContextValue): ContextValue {
if (Array.isArray(candidate)) {
return candidate.map((value: ContextValue) => deepSnakeCase(value))
}
if (typeof candidate === 'object' && candidate !== null) {
return withSnakeCaseKeys(candidate)
}
return candidate
}
export function toSnakeCase(word: string) {
return word
.replace(
/[A-Z]/g,
(uppercaseLetter: string, index: number) => `${index !== 0 ? '_' : ''}${uppercaseLetter.toLowerCase()}`
)
.replace(/-/g, '_')
}
// tslint:disable-next-line:no-empty

@@ -229,0 +123,0 @@ export function noop() {}

import { monitor } from '../domain/internalMonitoring'
import { Context, DOM_EVENT, jsonStringify, noop, objectValues } from '../tools/utils'
import { Context } from '../tools/context'
import { DOM_EVENT, jsonStringify, noop, objectValues } from '../tools/utils'

@@ -4,0 +5,0 @@ // https://en.wikipedia.org/wiki/UTF-8

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc