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

newrelic

Package Overview
Dependencies
Maintainers
1
Versions
383
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

newrelic - npm Package Compare versions

Comparing version 0.9.13-101 to 0.9.14-105

17

lib/environment.js

@@ -155,4 +155,6 @@ 'use strict';

/**
* Take a list of packages and reduce it to a list where each package appears
* at most once, with all the versions joined into a comma-delimited list.
* Take a list of packages and reduce it to a list of pairs serialized
* to JSON (to simplify things on the collector end) where each
* package appears at most once, with all the versions joined into a
* comma-delimited list.
*

@@ -176,5 +178,10 @@ * @returns Array Sorted list of [name, version] pairs.

return Object.keys(info).map(function (key) {
return [key, info[key].join(', ')];
}).sort();
return Object.keys(info)
.map(function (key) {
return [key, info[key].join(', ')];
})
.sort()
.map(function (pair) {
return JSON.stringify(pair);
});
}

@@ -181,0 +188,0 @@

@@ -52,3 +52,3 @@ 'use strict';

*/
shimmer.wrapMethod(http.Server.prototype,
shimmer.wrapMethod(http && http.Server && http.Server.prototype,
'http.Server.prototype',

@@ -55,0 +55,0 @@ ['on', 'addListener'],

@@ -8,3 +8,6 @@ 'use strict';

module.exports = function initialize(agent, net) {
shimmer.wrapMethod(net.Server.prototype, 'net.Server.prototype', 'listen', function (original) {
shimmer.wrapMethod(net && net.Server && net.Server.prototype,
'net.Server.prototype',
'listen',
function (original) {
return function () {

@@ -11,0 +14,0 @@ // we can notice the port here

@@ -10,3 +10,3 @@ 'use strict';

module.exports = function initialize(agent, express) {
if (express.version[0] === '2') {
if (express && express.version && express.version[0] === '2') {
shimmer.wrapMethod(express, 'express', 'createServer', function (original) {

@@ -68,3 +68,3 @@ return function wrappedCreateServer() {

if (express.version[0] === '3') {
if (express && express.version && express.version[0] === '3') {
shimmer.wrapMethod(express.application,

@@ -71,0 +71,0 @@ 'express.application',

@@ -24,3 +24,6 @@ 'use strict';

module.exports = function initialize(agent, memcached) {
shimmer.wrapMethod(memcached.prototype, 'memcached.prototype', 'command', function (original) {
shimmer.wrapMethod(memcached && memcached.prototype,
'memcached.prototype',
'command',
function (original) {
return agent.tracer.segmentProxy(function () {

@@ -27,0 +30,0 @@ var state = agent.getState();

@@ -40,3 +40,6 @@ "use strict";

function addFunctionProxy(operation) {
shimmer.wrapMethod(mongodb.Collection.prototype, 'mongodb.Collection.prototype', operation, function (original) {
shimmer.wrapMethod(mongodb && mongodb.Collection && mongodb.Collection.prototype,
'mongodb.Collection.prototype',
operation,
function (original) {
return agent.tracer.segmentProxy(function () {

@@ -48,11 +51,11 @@ logger.trace("Potentially tracing MongoDB query.");

var current = state.getSegment();
// Since the shim is wrapping a collection method, collectionName should
// always be set, but better safe than sorry.
var collection = this.collectionName || 'unknown';
var collection = this.collectionName || 'unknown'
, current = state.getSegment()
, statement = new ParsedStatement(operation, collection)
, statementSegment = current.add('MongoDB/' + collection + '/' + operation,
statement.recordMetrics.bind(statement))
;
var statement = new ParsedStatement(operation, collection);
var statementSegment = current.add('MongoDB/' + collection + '/' + operation,
statement.recordMetrics.bind(statement));
logger.trace("Adding MongoDB query trace segment transaction %d.",

@@ -63,9 +66,8 @@ state.getTransaction().id);

// query terms, so add them to the segment.
if (arguments[0] && typeof(arguments[0]) !== 'function') {
statementSegment.parameters = arguments[0];
}
var terms = arguments[0];
if (terms && typeof terms !== 'function') statementSegment.parameters = terms;
state.setSegment(statementSegment);
var callback = arguments[arguments.length - 1];
if (typeof(callback) !== 'function') {
if (typeof callback !== 'function') {
// grab the cursor returned by the finder

@@ -72,0 +74,0 @@ var cursor = original.apply(this, arguments);

@@ -12,3 +12,3 @@ 'use strict';

// FIXME: need a more general way of differentiating between driver versions
if (mysql.createConnection) {
if (mysql && mysql.createConnection) {
// congratulations, you have node-mysql 2.0

@@ -67,5 +67,8 @@ shimmer.wrapMethod(mysql, 'mysql', 'createConnection', function (original) {

}
else if (mysql.Client) {
else if (mysql && mysql.Client) {
// congratulations, you have node-mysql 0.9
shimmer.wrapMethod(mysql.Client.prototype, 'mysql.Client.prototype', 'query', function (original) {
shimmer.wrapMethod(mysql && mysql.Client && mysql.Client.prototype,
'mysql.Client.prototype',
'query',
function (original) {
return agent.tracer.segmentProxy(function () {

@@ -72,0 +75,0 @@ logger.trace("Potentially tracing node-mysql 0.9 query.");

@@ -20,17 +20,19 @@ 'use strict';

module.exports = function initialize(agent, redis) {
shimmer.wrapMethod(redis.RedisClient.prototype,
shimmer.wrapMethod(redis && redis.RedisClient && redis.RedisClient.prototype,
'redis.RedisClient.prototype',
'send_command',
function wrapper(original) {
function wrapper(send_command) {
return agent.tracer.segmentProxy(function wrapped() {
logger.trace("Potentially tracing Redis command.");
var state = agent.getState();
if (!state || arguments.length < 1) return original.apply(this, arguments);
if (!state || arguments.length < 1) return send_command.apply(this, arguments);
var current = state.getSegment();
var current = state.getSegment()
, args = Array.prototype.slice.call(arguments)
, name = 'Redis/' + (args[0] || 'Unknown')
, position = args.length - 1
, segment = current.add(name, record)
, last = args[position]
;
var args = Array.prototype.slice.call(arguments);
var name = 'Redis/' + (args[0] || 'Unknown');
var segment = current.add(name, record);
logger.trace("Adding Redis command trace segment transaction %d.",

@@ -40,22 +42,21 @@ state.getTransaction().id);

var position = args.length - 1;
var last = args[position];
var finalize = function (target) {
return function () {
var returned = target.apply(this, arguments);
segment.end();
logger.trace("Redis command trace segment ended for transaction %d.",
state.getTransaction().id);
var target;
var finalize = function () {
var returned = target.apply(this, arguments);
segment.end();
logger.trace("Redis command trace segment ended for transaction %d.",
state.getTransaction().id);
return returned;
return returned;
};
};
if (typeof last === 'function') {
target = args[position];
args[position] = agent.tracer.callbackProxy(finalize);
args[position] = agent.tracer.callbackProxy(finalize(last));
}
else if (Array.isArray(last) && typeof last[last.length - 1] === 'function') {
target = last[last.length - 1];
last[last.length - 1] = agent.tracer.callbackProxy(finalize);
else if (Array.isArray(last)) {
var maybeCallback = last[last.length - 1];
if (typeof maybeCallback === 'function') {
last[last.length - 1] = agent.tracer.callbackProxy(finalize(maybeCallback));
}
}

@@ -65,9 +66,10 @@ else { // let's shove a callback in there for fun

segment.end();
logger.trace("Redis command trace segment ended for transaction %d.", state.getTransaction().id);
logger.trace("Redis command trace segment ended for transaction %d.",
state.getTransaction().id);
});
}
return original.apply(this, args);
return send_command.apply(this, args);
});
});
};

@@ -0,1 +1,9 @@

### v0.9.14-101 / beta-14 (2013-01-07):
* In some cases, the monkeypatching used by the instrumentation wasn't
written sufficiently defensively, leading to applications crashing at
startup when using the agent.
* Changed how packages and dependencies are serialized when sent to New
Relic's servers.
### v0.9.13-101 / beta-13 (2013-01-07):

@@ -2,0 +10,0 @@

{
"name": "newrelic",
"version": "0.9.13-101",
"version": "0.9.14-105",
"author": "New Relic Node.js agent team <nodejs@newrelic.com>",

@@ -5,0 +5,0 @@ "contributors": [

@@ -84,8 +84,16 @@ 'use strict';

it("should have built a flattened package list", function () {
expect(find(settings, 'Packages').length).above(5);
var packages = find(settings, 'Packages');
expect(packages.length).above(5);
packages.forEach(function (pair) {
expect(JSON.parse(pair).length).equal(2);
});
});
it("should have built a flattened dependency list", function () {
expect(find(settings, 'Dependencies').length).above(5);
var dependencies = find(settings, 'Dependencies');
expect(dependencies.length).above(5);
dependencies.forEach(function (pair) {
expect(JSON.parse(pair).length).equal(2);
});
});
});

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

, chai = require('chai')
, expect = chai.expect
, should = chai.should()

@@ -12,95 +13,118 @@ , request = require('request')

describe("an instrumented Express application", function () {
var app
, runServer
, stopServer
, agent
, fetchedResponse
, fetchedBody
, PORT = 8062
;
describe("shouldn't cause bootstrapping to fail", function () {
var agent
, initialize
;
before(function (done) {
agent = helper.instrumentMockedAgent();
before(function () {
agent = helper.loadMockedAgent();
initialize = require(path.join(__dirname, '..', 'lib',
'instrumentation', 'express'));
});
// set apdexT so apdex stats will be recorded
agent.apdexT = 1;
it("when passed no module", function () {
expect(function () { initialize(agent); }).not.throws();
});
var express = require('express');
if (express.version[0] === '3') {
app = express();
it("when passed an empty module", function () {
initialize(agent, {});
expect(function () { initialize(agent, {}); }).not.throws();
});
});
var server;
runServer = function (callback) {
var http = require('http');
describe("with a mockup server", function () {
var app
, runServer
, stopServer
, agent
, fetchedResponse
, fetchedBody
, PORT = 8062
;
server = http.createServer(app);
server.listen(8062, callback);
};
before(function (done) {
agent = helper.instrumentMockedAgent();
stopServer = function (callback) {
server.close(callback);
};
}
else {
app = express.createServer();
// set apdexT so apdex stats will be recorded
agent.apdexT = 1;
runServer = function (callback) {
app.listen(8062, callback);
};
var express = require('express');
if (express.version[0] === '3') {
app = express();
stopServer = function (callback) {
app.close(callback);
};
}
var server;
runServer = function (callback) {
var http = require('http');
app = express.createServer();
app.get('/test-get', function (req, res) {
res.send({yep : true});
});
server = http.createServer(app);
server.listen(8062, callback);
};
runServer(function () {
request.get('http://localhost:8062/test-get', function (error, response, body) {
if (error) return done(error);
stopServer = function (callback) {
server.close(callback);
};
}
else {
app = express.createServer();
fetchedResponse = response;
fetchedBody = body;
runServer = function (callback) {
app.listen(8062, callback);
};
return done();
stopServer = function (callback) {
app.close(callback);
};
}
app = express.createServer();
app.get('/test-get', function (req, res) {
res.send({yep : true});
});
runServer(function () {
request.get('http://localhost:8062/test-get', function (error, response, body) {
if (error) return done(error);
fetchedResponse = response;
fetchedBody = body;
return done();
});
});
});
});
after(function () {
stopServer();
helper.unloadAgent(agent);
});
after(function () {
stopServer();
helper.unloadAgent(agent);
});
it("should serve content", function () {
fetchedResponse.headers['content-type'].should.equal('application/json; charset=utf-8');
JSON.parse(fetchedBody).should.deep.equal({"yep":true});
});
it("should serve content", function () {
fetchedResponse.headers['content-type'].should.equal('application/json; charset=utf-8');
JSON.parse(fetchedBody).should.deep.equal({"yep":true});
});
it("should record unscoped path statistics", function () {
var stats = agent.metrics.getOrCreateMetric('WebTransaction/Uri/test-get').stats;
stats.callCount.should.equal(1);
});
it("should record unscoped path statistics", function () {
var stats = agent.metrics.getOrCreateMetric('WebTransaction/Uri/test-get').stats;
stats.callCount.should.equal(1);
});
it("should record apdex without some low-level method-wrapping problem", function () {
var stats = agent.metrics.getOrCreateApdexMetric('Apdex/Uri/test-get').stats;
stats.satisfying.should.equal(1);
});
it("should record apdex without some low-level method-wrapping problem", function () {
var stats = agent.metrics.getOrCreateApdexMetric('Apdex/Uri/test-get').stats;
stats.satisfying.should.equal(1);
});
it("should roll up web transaction statistics", function () {
var stats = agent.metrics.getOrCreateMetric('WebTransaction').stats;
stats.callCount.should.equal(1);
});
it("should roll up web transaction statistics", function () {
var stats = agent.metrics.getOrCreateMetric('WebTransaction').stats;
stats.callCount.should.equal(1);
});
it("should roll up HTTP dispatcher statistics", function () {
var stats = agent.metrics.getOrCreateMetric('HttpDispatcher').stats;
stats.callCount.should.equal(1);
});
it("should roll up HTTP dispatcher statistics", function () {
var stats = agent.metrics.getOrCreateMetric('HttpDispatcher').stats;
stats.callCount.should.equal(1);
});
it("should dump a JSON representation of its statistics", function () {
JSON.stringify(agent.metrics).should.match(/WebTransaction\/Uri\/test-get/);
it("should dump a JSON representation of its statistics", function () {
JSON.stringify(agent.metrics).should.match(/WebTransaction\/Uri\/test-get/);
});
});
});
'use strict';
var path = require('path')
, chai = require('chai')
, expect = chai.expect
, helper = require(path.join(__dirname, 'lib', 'agent_helper'))
;
describe("built-in fs module instrumentation", function () {
describe("shouldn't cause bootstrapping to fail", function () {
var agent
, initialize
;
before(function () {
agent = helper.loadMockedAgent();
initialize = require(path.join(__dirname, '..', 'lib',
'instrumentation', 'core', 'fs'));
});
it("when passed no module", function () {
expect(function () { initialize(agent); }).not.throws();
});
it("when passed an empty module", function () {
expect(function () { initialize(agent, {}); }).not.throws();
});
});
it("should pick up scope when called in a scoped transaction");
});

@@ -12,86 +12,72 @@ 'use strict';

describe("built-in http module instrumentation", function () {
var agent
, transaction
, fetchedStatusCode
, fetchedBody
;
describe("shouldn't cause bootstrapping to fail", function () {
var agent
, initialize
;
var PAYLOAD = JSON.stringify({msg : 'ok'});
before(function () {
agent = helper.loadMockedAgent();
initialize = require(path.join(__dirname, '..', 'lib',
'instrumentation', 'core', 'http'));
});
var PAGE = '<html>' +
'<head><title>test response</title></head>' +
'<body><p>I heard you like HTML.</p></body>' +
'</html>';
it("when passed no module", function () {
expect(function () { initialize(agent); }).not.throws();
});
before(function (done) {
agent = helper.instrumentMockedAgent();
var external = http.createServer(function (request, response) {
expect(agent.getTransaction()).not.equal(undefined);
response.writeHead(200,
{'Content-Length' : PAYLOAD.length,
'Content-Type' : 'application/json'});
response.end(PAYLOAD);
it("when passed an empty module", function () {
expect(function () { initialize(agent, {}); }).not.throws();
});
});
var server = http.createServer(function (request, response) {
expect(agent.getTransaction()).not.equal(undefined);
describe("with an HTTP server running inside the test", function () {
var agent
, transaction
, fetchedStatusCode
, fetchedBody
;
var req = http.request({port : 8321,
host : 'localhost',
path : '/status',
method : 'GET'},
function (requestResponse) {
if (requestResponse.statusCode !== 200) {
return done(requestResponse.statusCode);
}
var PAYLOAD = JSON.stringify({msg : 'ok'});
expect(agent.getTransaction()).not.equal(undefined);
transaction = agent.getTransaction();
var PAGE = '<html>' +
'<head><title>test response</title></head>' +
'<body><p>I heard you like HTML.</p></body>' +
'</html>';
requestResponse.setEncoding('utf8');
requestResponse.on('data', function (data) {
expect(data).equal(PAYLOAD);
});
before(function (done) {
agent = helper.instrumentMockedAgent();
response.writeHead(200,
{'Content-Length' : PAGE.length,
'Content-Type' : 'text/html'});
response.end(PAGE);
});
var external = http.createServer(function (request, response) {
expect(agent.getTransaction()).not.equal(undefined);
req.on('error', function (error) {
return done(error);
response.writeHead(200,
{'Content-Length' : PAYLOAD.length,
'Content-Type' : 'application/json'});
response.end(PAYLOAD);
});
req.end();
});
var server = http.createServer(function (request, response) {
expect(agent.getTransaction()).not.equal(undefined);
external.listen(8321, 'localhost', function () {
server.listen(8123, 'localhost', function () {
// The transaction doesn't get created until after the instrumented
// server handler fires.
expect(agent.getTransaction()).equal(undefined);
fetchedBody = '';
var req = http.request({port : 8123,
host : 'localhost',
path : '/path',
var req = http.request({port : 8321,
host : 'localhost',
path : '/status',
method : 'GET'},
function (response) {
if (response.statusCode !== 200) {
return done(response.statusCode);
function (requestResponse) {
if (requestResponse.statusCode !== 200) {
return done(requestResponse.statusCode);
}
fetchedStatusCode = response.statusCode;
expect(agent.getTransaction()).not.equal(undefined);
transaction = agent.getTransaction();
response.setEncoding('utf8');
response.on('data', function (data) {
fetchedBody = fetchedBody + data;
requestResponse.setEncoding('utf8');
requestResponse.on('data', function (data) {
expect(data).equal(PAYLOAD);
});
response.on('end', function () {
return done();
});
response.writeHead(200,
{'Content-Length' : PAGE.length,
'Content-Type' : 'text/html'});
response.end(PAGE);
});

@@ -105,46 +91,82 @@

});
external.listen(8321, 'localhost', function () {
server.listen(8123, 'localhost', function () {
// The transaction doesn't get created until after the instrumented
// server handler fires.
expect(agent.getTransaction()).equal(undefined);
fetchedBody = '';
var req = http.request({port : 8123,
host : 'localhost',
path : '/path',
method : 'GET'},
function (response) {
if (response.statusCode !== 200) {
return done(response.statusCode);
}
fetchedStatusCode = response.statusCode;
response.setEncoding('utf8');
response.on('data', function (data) {
fetchedBody = fetchedBody + data;
});
response.on('end', function () {
return done();
});
});
req.on('error', function (error) {
return done(error);
});
req.end();
});
});
});
});
after(function () {
helper.unloadAgent(agent);
});
after(function () {
helper.unloadAgent(agent);
});
it("should successfully fetch the page", function () {
fetchedStatusCode.should.equal(200);
it("should successfully fetch the page", function () {
fetchedStatusCode.should.equal(200);
should.exist(fetchedBody);
fetchedBody.should.equal(PAGE);
});
should.exist(fetchedBody);
fetchedBody.should.equal(PAGE);
});
it("should record unscoped path stats after a normal request", function () {
var stats = agent.metrics.getOrCreateMetric('WebTransaction/Uri/path').stats;
stats.callCount.should.equal(1);
});
it("should record unscoped path stats after a normal request", function () {
var stats = agent.metrics.getOrCreateMetric('WebTransaction/Uri/path').stats;
stats.callCount.should.equal(1);
});
it("should indicate that the http dispatcher is in play", function (done) {
var found = false;
it("should indicate that the http dispatcher is in play", function (done) {
var found = false;
agent.environment.toJSON().forEach(function (pair) {
if (pair[0] === 'Dispatcher' && pair[1] === 'http') found = true;
agent.environment.toJSON().forEach(function (pair) {
if (pair[0] === 'Dispatcher' && pair[1] === 'http') found = true;
});
return done(found ? null : new Error('failed to find Dispatcher configuration'));
});
return done(found ? null : new Error('failed to find Dispatcher configuration'));
});
it("should record unscoped HTTP dispatcher stats after a normal request", function () {
var stats = agent.metrics.getOrCreateMetric('HttpDispatcher').stats;
stats.callCount.should.equal(2);
});
it("should record unscoped HTTP dispatcher stats after a normal request", function () {
var stats = agent.metrics.getOrCreateMetric('HttpDispatcher').stats;
stats.callCount.should.equal(2);
});
it("should associate outbound HTTP requests with the inbound transaction", function () {
expect(transaction.metrics.getOrCreateMetric('External/localhost/http', 'External/localhost/status').stats.callCount).equal(1);
});
it("should associate outbound HTTP requests with the inbound transaction", function () {
expect(transaction.metrics.getOrCreateMetric('External/localhost/http', 'External/localhost/status').stats.callCount).equal(1);
it("should record outbound HTTP requests in the agent's metrics", function () {
expect(agent.metrics.getOrCreateMetric('External/localhost/http', 'External/localhost/status').stats.callCount).equal(1);
});
});
it("should record outbound HTTP requests in the agent's metrics", function () {
expect(agent.metrics.getOrCreateMetric('External/localhost/http', 'External/localhost/status').stats.callCount).equal(1);
});
it("shouldn't record transactions for requests for favicon.ico");
it("should capture metrics for the last byte to exit / enter as part of a response / request");
});
'use strict';
var path = require('path')
, chai = require('chai')
, expect = chai.expect
, helper = require(path.join(__dirname, 'lib', 'agent_helper'))
;
describe("agent instrumentation of memcached", function () {
describe("shouldn't cause bootstrapping to fail", function () {
var agent
, initialize
;
before(function () {
agent = helper.loadMockedAgent();
initialize = require(path.join(__dirname, '..', 'lib',
'instrumentation', 'memcached'));
});
it("when passed no module", function () {
expect(function () { initialize(agent); }).not.throws();
});
it("when passed an empty module", function () {
expect(function () { initialize(agent, {}); }).not.throws();
});
});
describe("for each operation", function () {

@@ -5,0 +31,0 @@ it("should update the global aggregate statistics");

@@ -39,2 +39,22 @@ 'use strict';

describe("shouldn't cause bootstrapping to fail", function () {
var agent
, initialize
;
before(function () {
agent = helper.loadMockedAgent();
initialize = require(path.join(__dirname, '..', 'lib',
'instrumentation', 'mongodb'));
});
it("when passed no module", function () {
expect(function () { initialize(agent); }).not.throws();
});
it("when passed an empty module", function () {
expect(function () { initialize(agent, {}); }).not.throws();
});
});
describe("for each operation", function () {

@@ -41,0 +61,0 @@ beforeEach(function (done) {

'use strict';
var path = require('path')
, chai = require('chai')
, expect = chai.expect
, helper = require(path.join(__dirname, 'lib', 'agent_helper'))
;
describe("agent instrumentation of MySQL", function () {
describe("shouldn't cause bootstrapping to fail", function () {
var agent
, initialize
;
before(function () {
agent = helper.loadMockedAgent();
initialize = require(path.join(__dirname, '..', 'lib',
'instrumentation', 'mysql'));
});
it("when passed no module", function () {
expect(function () { initialize(agent); }).not.throws();
});
it("when passed an empty module", function () {
expect(function () { initialize(agent, {}); }).not.throws();
});
});
describe("for each operation", function () {

@@ -5,0 +31,0 @@ it("should update the global database aggregate statistics");

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

, chai = require('chai')
, expect = chai.expect
, should = chai.should()

@@ -53,2 +54,23 @@ , net = require('net')

});
describe("shouldn't cause bootstrapping to fail", function () {
var agent
, initialize
;
before(function () {
agent = helper.loadMockedAgent();
initialize = require(path.join(__dirname, '..', 'lib',
'instrumentation', 'core', 'net'));
});
it("when passed no module", function () {
expect(function () { initialize(agent); }).not.throws();
});
it("when passed an empty module", function () {
expect(function () { initialize(agent, {}); }).not.throws();
});
});
});

@@ -35,2 +35,22 @@ 'use strict';

describe("agent instrumentation of Redis", function () {
describe("shouldn't cause bootstrapping to fail", function () {
var agent
, initialize
;
before(function () {
agent = helper.loadMockedAgent();
initialize = require(path.join(__dirname, '..', 'lib',
'instrumentation', 'redis'));
});
it("when passed no module", function () {
expect(function () { initialize(agent); }).not.throws();
});
it("when passed a module with no RedisClient present.", function () {
expect(function () { initialize(agent, {}); }).not.throws();
});
});
describe("for each operation", function () {

@@ -37,0 +57,0 @@ it("should update the global aggregate statistics");

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