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

browserstacktunnel-wrapper

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

browserstacktunnel-wrapper - npm Package Compare versions

Comparing version 1.2.1 to 1.3.0

5

package.json
{
"name": "browserstacktunnel-wrapper",
"description": "A Node.js wrapper for the BrowserStack java tunnel client ",
"version": "1.2.1",
"version": "1.3.0",
"homepage": "https://github.com/pghalliday/node-BrowserStackTunnel.git",

@@ -48,5 +48,4 @@ "author": {

"dependencies": {
"unzip": "~0.1.9",
"fs-extra": "~0.8.1"
"unzip": "~0.1.9"
}
}

2

README.md

@@ -32,3 +32,3 @@ node-BrowserStackTunnel

linux64Bin: 'your_bin_dir', // optionally override the default bin directory for the Linux 64 bit binary
jarFile: 'your_jar_file', // on other platforms, optionally override the default path to the BrowserStackTunnel.jar file
win32Bin: 'your_bin_dir', // optionally override the default bin directory for the win32 binary
tunnelIdentifier: 'my_tunnel', // optionally set the -tunnelIdentifier option

@@ -35,0 +35,0 @@ skipCheck: true, // optionally set the -skipCheck option

@@ -6,3 +6,2 @@ var util = require('util'),

os = require('os'),
JarBinary = require('./JarBinary'),
ZipBinary = require('./ZipBinary');

@@ -30,3 +29,3 @@

default:
binary = new JarBinary(options.jarFile);
binary = new ZipBinary('win32', null, options.win32Bin, 'exe');
break;

@@ -33,0 +32,0 @@ }

@@ -6,8 +6,8 @@ var path = require('path'),

function ZipBinary(platform, arch, bin) {
function ZipBinary(platform, arch, bin, ext) {
'use strict';
var self = this;
self.bin = bin || path.resolve(path.join(__dirname, '..', 'bin', platform, arch));
self.path = path.resolve(path.join(self.bin, 'BrowserStackLocal'));
self.bin = bin || path.resolve(path.join(__dirname, '..', 'bin', arch ? path.join(platform, arch) : platform));
self.path = path.resolve(path.join(self.bin, 'BrowserStackLocal' + (ext ? '.' + ext : '')));
self.command = self.path;

@@ -20,4 +20,4 @@ self.args = [];

});
https.get('https://www.browserstack.com/browserstack-local/BrowserStackLocal-' + platform + '-' + arch + '.zip', function (response) {
console.log('BrowserStackTunnel: download binary for ' + platform + '-' + arch + ' ...');
https.get('https://www.browserstack.com/browserstack-local/BrowserStackLocal-' + platform + (arch ? '-' + arch : '') + '.zip', function (response) {
console.log('BrowserStackTunnel: download binary for ' + platform + (arch ? '-' + arch : '') + ' ...');
extractStream.on('close', function () {

@@ -24,0 +24,0 @@ console.log('BrowserStackTunnel: download complete');

@@ -71,3 +71,2 @@ var util = require('util'),

bin: {
'BrowserStackTunnel.jar': 1,
darwin: {

@@ -81,2 +80,5 @@ 'BrowserStackLocal': 1

'BrowserStackLocal': 1
},
win32: {
'BrowserStackLocal': 1
}

@@ -83,0 +85,0 @@ }

@@ -13,8 +13,2 @@ var expect = require('expect.js'),

var jb = mocks.loadFile('./src/JarBinary.js', {
http: httpMock,
'fs-extra': fsMock
});
var JarBinary = jb.JarBinary;
var zb = mocks.loadFile('./src/ZipBinary.js', {

@@ -32,3 +26,2 @@ https: httpMock,

os: osMock,
'./JarBinary': JarBinary,
'./ZipBinary': ZipBinary

@@ -39,4 +32,3 @@ });

NEW_BINARY_FILE = NEW_BINARY_DIR + '/BrowserStackLocal',
JAR_FILE = '/bin/BrowserStackTunnel.jar',
NEW_JAR_FILE = '/bin/new/BrowserStackTunnel.jar',
NEW_WIN32_BINARY_FILE = NEW_BINARY_DIR + '/BrowserStackLocal.exe',
OSX_BINARY_DIR = '/bin/darwin',

@@ -48,6 +40,8 @@ OSX_BINARY_FILE = OSX_BINARY_DIR + '/BrowserStackLocal',

LINUX_32_BINARY_FILE = LINUX_32_BINARY_DIR + '/BrowserStackLocal',
JAR_URL = 'http://www.browserstack.com/BrowserStackTunnel.jar',
WIN32_BINARY_DIR = '/bin/win32',
WIN32_BINARY_FILE = WIN32_BINARY_DIR + '/BrowserStackLocal.exe',
OSX_BINARY_URL = 'https://www.browserstack.com/browserstack-local/BrowserStackLocal-darwin-x64.zip',
LINUX_64_BINARY_URL = 'https://www.browserstack.com/browserstack-local/BrowserStackLocal-linux-x64.zip',
LINUX_32_BINARY_URL = 'https://www.browserstack.com/browserstack-local/BrowserStackLocal-linux-ia32.zip',
WIN32_BINARY_URL = 'https://www.browserstack.com/browserstack-local/BrowserStackLocal-win32.zip',
HOST_NAME = 'localhost',

@@ -88,3 +82,3 @@ PORT = 8080,

}],
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -105,3 +99,3 @@ browserStackTunnel.stop(function (error) {

}],
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -113,3 +107,5 @@ browserStackTunnel.start(function (error) {

process.emit('mock:child_process:stdout:data', 'monkey----- **Error: Could not connect to server: ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- **Error: Could not connect to server: ----monkey');
}, 100);
});

@@ -125,3 +121,3 @@

}],
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -133,3 +129,5 @@ browserStackTunnel.start(function (error) {

process.emit('mock:child_process:stdout:data', 'monkey----- **Error: You provided an invalid key ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- **Error: You provided an invalid key ----monkey');
}, 100);
});

@@ -145,3 +143,3 @@

}],
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -157,10 +155,50 @@

});
});
process.emit('mock:child_process:stdout:data', 'monkey----- **Error: There is another JAR already running ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});
it('should error if started when another instance is already running', function (done) {
var browserStackTunnel1 = new bs.BrowserStackTunnel({
key: KEY,
hosts: [{
name: HOST_NAME,
port: PORT,
sslFlag: SSL_FLAG
}],
win32Bin: WIN32_BINARY_DIR
});
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
var browserStackTunnel2 = new bs.BrowserStackTunnel({
key: KEY,
hosts: [{
name: HOST_NAME,
port: PORT,
sslFlag: SSL_FLAG
}],
win32Bin: WIN32_BINARY_DIR
});
browserStackTunnel1.start(function (error) {
if (error) {
expect().fail(function () { return error; });
}
browserStackTunnel2.start(function (error) {
expect(error.message).to.be('child already started');
done();
});
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- **Error: There is another JAR already running ----monkey');
}, 100);
});
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});
it('should download new jar if prompted that a new version exists as auto download is not compatible with our use of spawn', function (done) {
it('should download new binary if prompted that a new version exists as auto download is not compatible with our use of spawn', function (done) {
var browserStackTunnel = new bs.BrowserStackTunnel({

@@ -173,3 +211,3 @@ key: 'MONKEY_KEY',

}],
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -180,11 +218,14 @@ browserStackTunnel.start(function (error) {

}
expect(fsMock.fileNameCreated).to.equal(JAR_FILE);
expect(fsMock.fileName).to.equal(JAR_FILE);
expect(httpMock.url).to.equal(JAR_URL);
expect(fsMock.fileNameModded).to.equal(WIN32_BINARY_FILE);
expect(fsMock.mode).to.equal('0755');
expect(unzipMock.dirName).to.equal(WIN32_BINARY_DIR);
expect(httpMock.url).to.equal(WIN32_BINARY_URL);
done();
});
process.emit('mock:child_process:stdout:data', 'monkey----- **There is a new version of BrowserStackTunnel.jar available on server ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
process.emit('mock:child_process:stdout:data', 'monkey----- **There is a new version of BrowserStackTunnel.jar available on server ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
}, 100);

@@ -206,3 +247,3 @@ });

}],
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -216,5 +257,3 @@ browserStackTunnel.start(function (error) {

spawnSpy,
'java', [
'-jar',
JAR_FILE,
WIN32_BINARY_FILE, [
KEY,

@@ -228,6 +267,8 @@ HOST_NAME + ',' + PORT + ',' + SSL_FLAG + ',' + HOST_NAME2 + ',' + PORT2 + ',' + SSL_FLAG2

process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});
it('should use the specified jar file', function (done) {
it('should use the specified binary directory', function (done) {
spawnSpy.reset();

@@ -242,3 +283,3 @@ var browserStackTunnel = new bs.BrowserStackTunnel({

}],
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -252,5 +293,3 @@ browserStackTunnel.start(function (error) {

spawnSpy,
'java', [
'-jar',
JAR_FILE,
WIN32_BINARY_FILE, [
KEY,

@@ -264,3 +303,5 @@ HOST_NAME + ',' + PORT + ',' + SSL_FLAG

process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});

@@ -278,3 +319,3 @@

tunnelIdentifier: 'my_tunnel',
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -288,5 +329,3 @@ browserStackTunnel.start(function (error) {

spawnSpy,
'java', [
'-jar',
JAR_FILE,
WIN32_BINARY_FILE, [
KEY,

@@ -302,3 +341,5 @@ HOST_NAME + ',' + PORT + ',' + SSL_FLAG,

process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});

@@ -316,3 +357,3 @@

skipCheck: true,
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -326,5 +367,3 @@ browserStackTunnel.start(function (error) {

spawnSpy,
'java', [
'-jar',
JAR_FILE,
WIN32_BINARY_FILE, [
KEY,

@@ -339,3 +378,5 @@ HOST_NAME + ',' + PORT + ',' + SSL_FLAG,

process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});

@@ -353,3 +394,3 @@

v: true,
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -363,5 +404,3 @@ browserStackTunnel.start(function (error) {

spawnSpy,
'java', [
'-jar',
JAR_FILE,
WIN32_BINARY_FILE, [
KEY,

@@ -376,3 +415,5 @@ HOST_NAME + ',' + PORT + ',' + SSL_FLAG,

process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});

@@ -390,3 +431,3 @@

skipCheck: true,
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -400,5 +441,3 @@ browserStackTunnel.start(function (error) {

spawnSpy,
'java', [
'-jar',
JAR_FILE,
WIN32_BINARY_FILE, [
KEY,

@@ -413,3 +452,5 @@ HOST_NAME + ',' + PORT + ',' + SSL_FLAG,

process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});

@@ -430,3 +471,3 @@

proxyHost: PROXY_HOST,
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -440,5 +481,3 @@ browserStackTunnel.start(function (error) {

spawnSpy,
'java', [
'-jar',
JAR_FILE,
WIN32_BINARY_FILE, [
KEY,

@@ -460,3 +499,5 @@ HOST_NAME + ',' + PORT + ',' + SSL_FLAG,

process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});

@@ -478,3 +519,3 @@

}],
jarFile: NEW_JAR_FILE
win32Bin: NEW_BINARY_DIR
});

@@ -485,5 +526,6 @@ browserStackTunnel.start(function (error) {

}
expect(fsMock.fileNameCreated).to.equal(NEW_JAR_FILE);
expect(fsMock.fileName).to.equal(NEW_JAR_FILE);
expect(httpMock.url).to.equal(JAR_URL);
expect(fsMock.fileNameModded).to.equal(NEW_WIN32_BINARY_FILE);
expect(fsMock.mode).to.equal('0755');
expect(unzipMock.dirName).to.equal(NEW_BINARY_DIR);
expect(httpMock.url).to.equal(WIN32_BINARY_URL);
done();

@@ -497,3 +539,3 @@ });

it('should download new jar if prompted that a new version exists as auto download is not compatible with our use of spawn', function (done) {
it('should download new binary if prompted that a new version exists as auto download is not compatible with our use of spawn', function (done) {
var browserStackTunnel = new bs.BrowserStackTunnel({

@@ -506,3 +548,3 @@ key: 'MONKEY_KEY',

}],
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -513,15 +555,18 @@ browserStackTunnel.start(function (error) {

}
expect(fsMock.fileNameCreated).to.equal(JAR_FILE);
expect(fsMock.fileName).to.equal(JAR_FILE);
expect(httpMock.url).to.equal(JAR_URL);
expect(fsMock.fileNameModded).to.equal(WIN32_BINARY_FILE);
expect(fsMock.mode).to.equal('0755');
expect(unzipMock.dirName).to.equal(WIN32_BINARY_DIR);
expect(httpMock.url).to.equal(WIN32_BINARY_URL);
done();
});
process.emit('mock:child_process:stdout:data', 'monkey----- **There is a new version of BrowserStackTunnel.jar available on server ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
process.emit('mock:child_process:stdout:data', 'monkey----- **There is a new version of BrowserStackTunnel.jar available on server ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
}, 100);
});
it('should use the specified jar file', function (done) {
it('should use the specified binary directory', function (done) {
spawnSpy.reset();

@@ -536,3 +581,3 @@ var browserStackTunnel = new bs.BrowserStackTunnel({

}],
jarFile: JAR_FILE
win32Bin: WIN32_BINARY_DIR
});

@@ -546,5 +591,3 @@ browserStackTunnel.start(function (error) {

spawnSpy,
'java', [
'-jar',
JAR_FILE,
WIN32_BINARY_FILE, [
KEY,

@@ -558,3 +601,5 @@ HOST_NAME + ',' + PORT + ',' + SSL_FLAG

process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});

@@ -616,5 +661,7 @@ });

process.emit('mock:child_process:stdout:data', 'monkey----- **There is a new version of BrowserStackTunnel.jar available on server ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
process.emit('mock:child_process:stdout:data', 'monkey----- **There is a new version of BrowserStackTunnel.jar available on server ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
}, 100);

@@ -651,3 +698,5 @@ });

process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});

@@ -709,5 +758,7 @@ });

process.emit('mock:child_process:stdout:data', 'monkey----- **There is a new version of BrowserStackTunnel.jar available on server ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
process.emit('mock:child_process:stdout:data', 'monkey----- **There is a new version of BrowserStackTunnel.jar available on server ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
}, 100);

@@ -744,3 +795,5 @@ });

process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});

@@ -802,5 +855,7 @@ });

process.emit('mock:child_process:stdout:data', 'monkey----- **There is a new version of BrowserStackTunnel.jar available on server ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
process.emit('mock:child_process:stdout:data', 'monkey----- **There is a new version of BrowserStackTunnel.jar available on server ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
}, 100);

@@ -837,3 +892,5 @@ });

process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
setTimeout(function () {
process.emit('mock:child_process:stdout:data', 'monkey----- Press Ctrl-C to exit ----monkey');
}, 100);
});

@@ -840,0 +897,0 @@ });

@@ -18,7 +18,13 @@ var expect = require('expect.js');

var ARCH = 'arch';
var EXT = 'exe';
var DEFAULT_BINARY_DIR = path.resolve(path.join(__dirname, '../../bin', PLATFORM, ARCH));
var DEFAULT_BINARY_DIR_NO_ARCH = path.resolve(path.join(__dirname, '../../bin', PLATFORM));
var DEFAULT_BINARY_FILE = path.join(DEFAULT_BINARY_DIR, 'BrowserStackLocal');
var DEFAULT_BINARY_FILE_WITH_EXT = path.join(DEFAULT_BINARY_DIR, 'BrowserStackLocal.' + EXT);
var DEFAULT_BINARY_FILE_NO_ARCH = path.join(DEFAULT_BINARY_DIR_NO_ARCH, 'BrowserStackLocal');
var OTHER_BINARY_DIR = '/bin';
var OTHER_BINARY_FILE = path.join(OTHER_BINARY_DIR, 'BrowserStackLocal');
var OTHER_BINARY_FILE_WITH_EXT = path.join(OTHER_BINARY_DIR, 'BrowserStackLocal.' + EXT);
var ZIP_URL = 'https://www.browserstack.com/browserstack-local/BrowserStackLocal-' + PLATFORM + '-' + ARCH + '.zip';
var ZIP_URL_NO_ARCH = 'https://www.browserstack.com/browserstack-local/BrowserStackLocal-' + PLATFORM + '.zip';

@@ -46,2 +52,9 @@ describe('ZipBinary', function () {

describe('with extension', function () {
it('should have the correct path', function () {
zipBinary = new ZipBinary(PLATFORM, ARCH, null, EXT);
expect(zipBinary.path).to.equal(DEFAULT_BINARY_FILE_WITH_EXT);
});
});
it('should have the correct command', function () {

@@ -56,3 +69,3 @@ expect(zipBinary.command).to.equal(DEFAULT_BINARY_FILE);

describe('#update', function () {
it('should download the jar file', function (done) {
it('should download the zip file', function (done) {
zipBinary.update(function () {

@@ -66,2 +79,15 @@ expect(fsMock.fileNameModded).to.equal(DEFAULT_BINARY_FILE);

});
describe('with no arch', function () {
it('should download the zip file', function (done) {
zipBinary = new ZipBinary(PLATFORM);
zipBinary.update(function () {
expect(fsMock.fileNameModded).to.equal(DEFAULT_BINARY_FILE_NO_ARCH);
expect(fsMock.mode).to.equal('0755');
expect(unzipMock.dirName).to.equal(DEFAULT_BINARY_DIR_NO_ARCH);
expect(httpMock.url).to.equal(ZIP_URL_NO_ARCH);
done();
});
});
});
});

@@ -79,2 +105,9 @@ });

describe('with extension', function () {
it('should have the correct path', function () {
zipBinary = new ZipBinary(PLATFORM, ARCH, OTHER_BINARY_DIR, EXT);
expect(zipBinary.path).to.equal(OTHER_BINARY_FILE_WITH_EXT);
});
});
it('should have the correct command', function () {

@@ -89,3 +122,3 @@ expect(zipBinary.command).to.equal(OTHER_BINARY_FILE);

describe('#update', function () {
it('should download the jar file', function (done) {
it('should download the zip file', function (done) {
zipBinary.update(function () {

@@ -99,4 +132,17 @@ expect(fsMock.fileNameModded).to.equal(OTHER_BINARY_FILE);

});
describe('with no arch', function () {
it('should download the zip file', function (done) {
zipBinary = new ZipBinary(PLATFORM, null, OTHER_BINARY_DIR);
zipBinary.update(function () {
expect(fsMock.fileNameModded).to.equal(OTHER_BINARY_FILE);
expect(fsMock.mode).to.equal('0755');
expect(unzipMock.dirName).to.equal(OTHER_BINARY_DIR);
expect(httpMock.url).to.equal(ZIP_URL_NO_ARCH);
done();
});
});
});
});
});
});
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