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

fetch-ponyfill

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fetch-ponyfill - npm Package Compare versions

Comparing version 6.1.1 to 7.0.0

526

build/fetch-browser.js

@@ -1,11 +0,10 @@

(function (self) {
(function (global) {
'use strict';
function fetchPonyfill(options) {
var Promise = options && options.Promise || self.Promise;
var XMLHttpRequest = options && options.XMLHttpRequest || self.XMLHttpRequest;
var global = self;
var Promise = options && options.Promise || global.Promise;
var XMLHttpRequest = options && options.XMLHttpRequest || global.XMLHttpRequest;
return (function () {
var self = Object.create(global, {
var globalThis = Object.create(global, {
fetch: {

@@ -17,22 +16,33 @@ value: undefined,

(function(self) {
'use strict';
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.WHATWGFetch = {})));
}(this, (function (exports) { 'use strict';
if (self.fetch) {
return
}
var global =
(typeof globalThis !== 'undefined' && globalThis) ||
(typeof self !== 'undefined' && self) ||
(typeof global !== 'undefined' && global);
var support = {
searchParams: 'URLSearchParams' in self,
iterable: 'Symbol' in self && 'iterator' in Symbol,
blob: 'FileReader' in self && 'Blob' in self && (function() {
try {
new Blob()
return true
} catch(e) {
return false
}
})(),
formData: 'FormData' in self,
arrayBuffer: 'ArrayBuffer' in self
searchParams: 'URLSearchParams' in global,
iterable: 'Symbol' in global && 'iterator' in Symbol,
blob:
'FileReader' in global &&
'Blob' in global &&
(function() {
try {
new Blob();
return true
} catch (e) {
return false
}
})(),
formData: 'FormData' in global,
arrayBuffer: 'ArrayBuffer' in global
};
function isDataView(obj) {
return obj && DataView.prototype.isPrototypeOf(obj)
}

@@ -51,11 +61,9 @@

'[object Float64Array]'
]
];
var isDataView = function(obj) {
return obj && DataView.prototype.isPrototypeOf(obj)
}
var isArrayBufferView = ArrayBuffer.isView || function(obj) {
return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
}
var isArrayBufferView =
ArrayBuffer.isView ||
function(obj) {
return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
};
}

@@ -65,5 +73,5 @@

if (typeof name !== 'string') {
name = String(name)
name = String(name);
}
if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
if (/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(name) || name === '') {
throw new TypeError('Invalid character in header field name')

@@ -76,3 +84,3 @@ }

if (typeof value !== 'string') {
value = String(value)
value = String(value);
}

@@ -86,6 +94,6 @@ return value

next: function() {
var value = items.shift()
var value = items.shift();
return {done: value === undefined, value: value}
}
}
};

@@ -95,3 +103,3 @@ if (support.iterable) {

return iterator
}
};
}

@@ -103,16 +111,16 @@

function Headers(headers) {
this.map = {}
this.map = {};
if (headers instanceof Headers) {
headers.forEach(function(value, name) {
this.append(name, value)
}, this)
this.append(name, value);
}, this);
} else if (Array.isArray(headers)) {
headers.forEach(function(header) {
this.append(header[0], header[1])
}, this)
this.append(header[0], header[1]);
}, this);
} else if (headers) {
Object.getOwnPropertyNames(headers).forEach(function(name) {
this.append(name, headers[name])
}, this)
this.append(name, headers[name]);
}, this);
}

@@ -122,24 +130,24 @@ }

Headers.prototype.append = function(name, value) {
name = normalizeName(name)
value = normalizeValue(value)
var oldValue = this.map[name]
this.map[name] = oldValue ? oldValue+','+value : value
}
name = normalizeName(name);
value = normalizeValue(value);
var oldValue = this.map[name];
this.map[name] = oldValue ? oldValue + ', ' + value : value;
};
Headers.prototype['delete'] = function(name) {
delete this.map[normalizeName(name)]
}
delete this.map[normalizeName(name)];
};
Headers.prototype.get = function(name) {
name = normalizeName(name)
name = normalizeName(name);
return this.has(name) ? this.map[name] : null
}
};
Headers.prototype.has = function(name) {
return this.map.hasOwnProperty(normalizeName(name))
}
};
Headers.prototype.set = function(name, value) {
this.map[normalizeName(name)] = normalizeValue(value)
}
this.map[normalizeName(name)] = normalizeValue(value);
};

@@ -149,27 +157,33 @@ Headers.prototype.forEach = function(callback, thisArg) {

if (this.map.hasOwnProperty(name)) {
callback.call(thisArg, this.map[name], name, this)
callback.call(thisArg, this.map[name], name, this);
}
}
}
};
Headers.prototype.keys = function() {
var items = []
this.forEach(function(value, name) { items.push(name) })
var items = [];
this.forEach(function(value, name) {
items.push(name);
});
return iteratorFor(items)
}
};
Headers.prototype.values = function() {
var items = []
this.forEach(function(value) { items.push(value) })
var items = [];
this.forEach(function(value) {
items.push(value);
});
return iteratorFor(items)
}
};
Headers.prototype.entries = function() {
var items = []
this.forEach(function(value, name) { items.push([name, value]) })
var items = [];
this.forEach(function(value, name) {
items.push([name, value]);
});
return iteratorFor(items)
}
};
if (support.iterable) {
Headers.prototype[Symbol.iterator] = Headers.prototype.entries
Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
}

@@ -181,3 +195,3 @@

}
body.bodyUsed = true
body.bodyUsed = true;
}

@@ -188,7 +202,7 @@

reader.onload = function() {
resolve(reader.result)
}
resolve(reader.result);
};
reader.onerror = function() {
reject(reader.error)
}
reject(reader.error);
};
})

@@ -198,5 +212,5 @@ }

function readBlobAsArrayBuffer(blob) {
var reader = new FileReader()
var promise = fileReaderReady(reader)
reader.readAsArrayBuffer(blob)
var reader = new FileReader();
var promise = fileReaderReady(reader);
reader.readAsArrayBuffer(blob);
return promise

@@ -206,5 +220,5 @@ }

function readBlobAsText(blob) {
var reader = new FileReader()
var promise = fileReaderReady(reader)
reader.readAsText(blob)
var reader = new FileReader();
var promise = fileReaderReady(reader);
reader.readAsText(blob);
return promise

@@ -214,7 +228,7 @@ }

function readArrayBufferAsText(buf) {
var view = new Uint8Array(buf)
var chars = new Array(view.length)
var view = new Uint8Array(buf);
var chars = new Array(view.length);
for (var i = 0; i < view.length; i++) {
chars[i] = String.fromCharCode(view[i])
chars[i] = String.fromCharCode(view[i]);
}

@@ -228,4 +242,4 @@ return chars.join('')

} else {
var view = new Uint8Array(buf.byteLength)
view.set(new Uint8Array(buf))
var view = new Uint8Array(buf.byteLength);
view.set(new Uint8Array(buf));
return view.buffer

@@ -236,24 +250,35 @@ }

function Body() {
this.bodyUsed = false
this.bodyUsed = false;
this._initBody = function(body) {
this._bodyInit = body
/*
fetch-mock wraps the Response object in an ES6 Proxy to
provide useful test harness features such as flush. However, on
ES5 browsers without fetch or Proxy support pollyfills must be used;
the proxy-pollyfill is unable to proxy an attribute unless it exists
on the object before the Proxy is created. This change ensures
Response.bodyUsed exists on the instance, while maintaining the
semantic of setting Request.bodyUsed in the constructor before
_initBody is called.
*/
this.bodyUsed = this.bodyUsed;
this._bodyInit = body;
if (!body) {
this._bodyText = ''
this._bodyText = '';
} else if (typeof body === 'string') {
this._bodyText = body
this._bodyText = body;
} else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
this._bodyBlob = body
this._bodyBlob = body;
} else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
this._bodyFormData = body
this._bodyFormData = body;
} else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
this._bodyText = body.toString()
this._bodyText = body.toString();
} else if (support.arrayBuffer && support.blob && isDataView(body)) {
this._bodyArrayBuffer = bufferClone(body.buffer)
this._bodyArrayBuffer = bufferClone(body.buffer);
// IE 10-11 can't handle a DataView body.
this._bodyInit = new Blob([this._bodyArrayBuffer])
this._bodyInit = new Blob([this._bodyArrayBuffer]);
} else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
this._bodyArrayBuffer = bufferClone(body)
this._bodyArrayBuffer = bufferClone(body);
} else {
throw new Error('unsupported BodyInit type')
this._bodyText = body = Object.prototype.toString.call(body);
}

@@ -263,14 +288,14 @@

if (typeof body === 'string') {
this.headers.set('content-type', 'text/plain;charset=UTF-8')
this.headers.set('content-type', 'text/plain;charset=UTF-8');
} else if (this._bodyBlob && this._bodyBlob.type) {
this.headers.set('content-type', this._bodyBlob.type)
this.headers.set('content-type', this._bodyBlob.type);
} else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
}
}
}
};
if (support.blob) {
this.blob = function() {
var rejected = consumed(this)
var rejected = consumed(this);
if (rejected) {

@@ -289,15 +314,28 @@ return rejected

}
}
};
this.arrayBuffer = function() {
if (this._bodyArrayBuffer) {
return consumed(this) || Promise.resolve(this._bodyArrayBuffer)
var isConsumed = consumed(this);
if (isConsumed) {
return isConsumed
}
if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
return Promise.resolve(
this._bodyArrayBuffer.buffer.slice(
this._bodyArrayBuffer.byteOffset,
this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
)
)
} else {
return Promise.resolve(this._bodyArrayBuffer)
}
} else {
return this.blob().then(readBlobAsArrayBuffer)
}
}
};
}
this.text = function() {
var rejected = consumed(this)
var rejected = consumed(this);
if (rejected) {

@@ -316,3 +354,3 @@ return rejected

}
}
};

@@ -322,3 +360,3 @@ if (support.formData) {

return this.text().then(decode)
}
};
}

@@ -328,3 +366,3 @@

return this.text().then(JSON.parse)
}
};

@@ -335,13 +373,17 @@ return this

// HTTP methods whose capitalization should be normalized
var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'];
function normalizeMethod(method) {
var upcased = method.toUpperCase()
return (methods.indexOf(upcased) > -1) ? upcased : method
var upcased = method.toUpperCase();
return methods.indexOf(upcased) > -1 ? upcased : method
}
function Request(input, options) {
options = options || {}
var body = options.body
if (!(this instanceof Request)) {
throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.')
}
options = options || {};
var body = options.body;
if (input instanceof Request) {

@@ -351,24 +393,26 @@ if (input.bodyUsed) {

}
this.url = input.url
this.credentials = input.credentials
this.url = input.url;
this.credentials = input.credentials;
if (!options.headers) {
this.headers = new Headers(input.headers)
this.headers = new Headers(input.headers);
}
this.method = input.method
this.mode = input.mode
this.method = input.method;
this.mode = input.mode;
this.signal = input.signal;
if (!body && input._bodyInit != null) {
body = input._bodyInit
input.bodyUsed = true
body = input._bodyInit;
input.bodyUsed = true;
}
} else {
this.url = String(input)
this.url = String(input);
}
this.credentials = options.credentials || this.credentials || 'omit'
this.credentials = options.credentials || this.credentials || 'same-origin';
if (options.headers || !this.headers) {
this.headers = new Headers(options.headers)
this.headers = new Headers(options.headers);
}
this.method = normalizeMethod(options.method || this.method || 'GET')
this.mode = options.mode || this.mode || null
this.referrer = null
this.method = normalizeMethod(options.method || this.method || 'GET');
this.mode = options.mode || this.mode || null;
this.signal = options.signal || this.signal;
this.referrer = null;

@@ -378,19 +422,37 @@ if ((this.method === 'GET' || this.method === 'HEAD') && body) {

}
this._initBody(body)
this._initBody(body);
if (this.method === 'GET' || this.method === 'HEAD') {
if (options.cache === 'no-store' || options.cache === 'no-cache') {
// Search for a '_' parameter in the query string
var reParamSearch = /([?&])_=[^&]*/;
if (reParamSearch.test(this.url)) {
// If it already exists then set the value with the current time
this.url = this.url.replace(reParamSearch, '$1_=' + new Date().getTime());
} else {
// Otherwise add a new '_' parameter to the end with the current time
var reQueryString = /\?/;
this.url += (reQueryString.test(this.url) ? '&' : '?') + '_=' + new Date().getTime();
}
}
}
}
Request.prototype.clone = function() {
return new Request(this, { body: this._bodyInit })
}
return new Request(this, {body: this._bodyInit})
};
function decode(body) {
var form = new FormData()
body.trim().split('&').forEach(function(bytes) {
if (bytes) {
var split = bytes.split('=')
var name = split.shift().replace(/\+/g, ' ')
var value = split.join('=').replace(/\+/g, ' ')
form.append(decodeURIComponent(name), decodeURIComponent(value))
}
})
var form = new FormData();
body
.trim()
.split('&')
.forEach(function(bytes) {
if (bytes) {
var split = bytes.split('=');
var name = split.shift().replace(/\+/g, ' ');
var value = split.join('=').replace(/\+/g, ' ');
form.append(decodeURIComponent(name), decodeURIComponent(value));
}
});
return form

@@ -400,34 +462,37 @@ }

function parseHeaders(rawHeaders) {
var headers = new Headers()
var headers = new Headers();
// Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
// https://tools.ietf.org/html/rfc7230#section-3.2
var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ')
var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ');
preProcessedHeaders.split(/\r?\n/).forEach(function(line) {
var parts = line.split(':')
var key = parts.shift().trim()
var parts = line.split(':');
var key = parts.shift().trim();
if (key) {
var value = parts.join(':').trim()
headers.append(key, value)
var value = parts.join(':').trim();
headers.append(key, value);
}
})
});
return headers
}
Body.call(Request.prototype)
Body.call(Request.prototype);
function Response(bodyInit, options) {
if (!(this instanceof Response)) {
throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.')
}
if (!options) {
options = {}
options = {};
}
this.type = 'default'
this.status = options.status === undefined ? 200 : options.status
this.ok = this.status >= 200 && this.status < 300
this.statusText = 'statusText' in options ? options.statusText : 'OK'
this.headers = new Headers(options.headers)
this.url = options.url || ''
this._initBody(bodyInit)
this.type = 'default';
this.status = options.status === undefined ? 200 : options.status;
this.ok = this.status >= 200 && this.status < 300;
this.statusText = 'statusText' in options ? options.statusText : '';
this.headers = new Headers(options.headers);
this.url = options.url || '';
this._initBody(bodyInit);
}
Body.call(Response.prototype)
Body.call(Response.prototype);

@@ -441,11 +506,11 @@ Response.prototype.clone = function() {

})
}
};
Response.error = function() {
var response = new Response(null, {status: 0, statusText: ''})
response.type = 'error'
var response = new Response(null, {status: 0, statusText: ''});
response.type = 'error';
return response
}
};
var redirectStatuses = [301, 302, 303, 307, 308]
var redirectStatuses = [301, 302, 303, 307, 308];

@@ -458,13 +523,32 @@ Response.redirect = function(url, status) {

return new Response(null, {status: status, headers: {location: url}})
};
exports.DOMException = global.DOMException;
try {
new exports.DOMException();
} catch (err) {
exports.DOMException = function(message, name) {
this.message = message;
this.name = name;
var error = Error(message);
this.stack = error.stack;
};
exports.DOMException.prototype = Object.create(Error.prototype);
exports.DOMException.prototype.constructor = exports.DOMException;
}
self.Headers = Headers
self.Request = Request
self.Response = Response
self.fetch = function(input, init) {
function fetch(input, init) {
return new Promise(function(resolve, reject) {
var request = new Request(input, init)
var xhr = new XMLHttpRequest()
var request = new Request(input, init);
if (request.signal && request.signal.aborted) {
return reject(new exports.DOMException('Aborted', 'AbortError'))
}
var xhr = new XMLHttpRequest();
function abortXhr() {
xhr.abort();
}
xhr.onload = function() {

@@ -475,44 +559,106 @@ var options = {

headers: parseHeaders(xhr.getAllResponseHeaders() || '')
}
options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
var body = 'response' in xhr ? xhr.response : xhr.responseText
resolve(new Response(body, options))
}
};
options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL');
var body = 'response' in xhr ? xhr.response : xhr.responseText;
setTimeout(function() {
resolve(new Response(body, options));
}, 0);
};
xhr.onerror = function() {
reject(new TypeError('Network request failed'))
}
setTimeout(function() {
reject(new TypeError('Network request failed'));
}, 0);
};
xhr.ontimeout = function() {
reject(new TypeError('Network request failed'))
setTimeout(function() {
reject(new TypeError('Network request failed'));
}, 0);
};
xhr.onabort = function() {
setTimeout(function() {
reject(new exports.DOMException('Aborted', 'AbortError'));
}, 0);
};
function fixUrl(url) {
try {
return url === '' && global.location.href ? global.location.href : url
} catch (e) {
return url
}
}
xhr.open(request.method, request.url, true)
xhr.open(request.method, fixUrl(request.url), true);
if (request.credentials === 'include') {
xhr.withCredentials = true
xhr.withCredentials = true;
} else if (request.credentials === 'omit') {
xhr.withCredentials = false
xhr.withCredentials = false;
}
if ('responseType' in xhr && support.blob) {
xhr.responseType = 'blob'
if ('responseType' in xhr) {
if (support.blob) {
xhr.responseType = 'blob';
} else if (
support.arrayBuffer &&
request.headers.get('Content-Type') &&
request.headers.get('Content-Type').indexOf('application/octet-stream') !== -1
) {
xhr.responseType = 'arraybuffer';
}
}
request.headers.forEach(function(value, name) {
xhr.setRequestHeader(name, value)
})
if (init && typeof init.headers === 'object' && !(init.headers instanceof Headers)) {
Object.getOwnPropertyNames(init.headers).forEach(function(name) {
xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
});
} else {
request.headers.forEach(function(value, name) {
xhr.setRequestHeader(name, value);
});
}
xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
if (request.signal) {
request.signal.addEventListener('abort', abortXhr);
xhr.onreadystatechange = function() {
// DONE (success or failure)
if (xhr.readyState === 4) {
request.signal.removeEventListener('abort', abortXhr);
}
};
}
xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit);
})
}
self.fetch.polyfill = true
})(typeof self !== 'undefined' ? self : this);
fetch.polyfill = true;
if (!global.fetch) {
global.fetch = fetch;
global.Headers = Headers;
global.Request = Request;
global.Response = Response;
}
exports.Headers = Headers;
exports.Request = Request;
exports.Response = Response;
exports.fetch = fetch;
Object.defineProperty(exports, '__esModule', { value: true });
})));
return {
fetch: self.fetch,
Headers: self.Headers,
Request: self.Request,
Response: self.Response
fetch: globalThis.fetch,
Headers: globalThis.Headers,
Request: globalThis.Request,
Response: globalThis.Response,
DOMException: globalThis.DOMException
};

@@ -529,5 +675,5 @@ }());

} else {
self.fetchPonyfill = fetchPonyfill;
global.fetchPonyfill = fetchPonyfill;
}
}(typeof self !== 'undefined' ? self : typeof global !== 'undefined' ? global : this));
}(typeof globalThis !== 'undefined' ? globalThis : typeof self !== 'undefined' ? self : typeof global !== 'undefined' ? global : this));
# History
## 7.0.0
- Drops support for node 8. Adds node 14 to tests.
- Updates whatwg-fetch to ~3.4.1.
- Exposes `DOMException` from whatwg-fetch.
- Tests against webpack 5 and browserify 17.
## 6.1.0

@@ -4,0 +11,0 @@

@@ -16,3 +16,4 @@ export = fetchPonyfill;

Response: typeof Response;
DOMException: typeof DOMException;
}
}
{
"name": "fetch-ponyfill",
"version": "6.1.1",
"version": "7.0.0",
"description": "A ponyfill (doesn't overwrite the native fetch) for the Fetch specification https://fetch.spec.whatwg.org.",

@@ -16,6 +16,6 @@ "main": "fetch-node.js",

"test:browserify": "testem ci",
"pretest:webpack": "npm run build && webpack --mode development tests/fetch-browser.spec.js -o build/browser-test-bundle.js",
"pretest:webpack": "npm run build && webpack --mode development --entry ./tests/fetch-browser.spec.js -o build/browser-test",
"test:webpack": "testem ci",
"pretest:webpack:node": "webpack --mode development --target node tests/fetch-node.spec.js -o build/node-test-bundle.js",
"test:webpack:node": "mocha build/node-test-bundle.js",
"pretest:webpack:node": "webpack --mode development --target node --entry ./tests/fetch-node.spec.js -o build/node-test",
"test:webpack:node": "mocha build/node-test/main.js",
"build": "rimraf build && mkdirp build && node build.js > build/fetch-browser.js",

@@ -35,18 +35,18 @@ "prepublishOnly": "npm run build"

"dependencies": {
"node-fetch": "~2.6.0"
"node-fetch": "~2.6.1"
},
"devDependencies": {
"browserify": "^16.5.1",
"eslint": "~6.8.0",
"eslint-config-qubyte": "~3.0.0",
"browserify": "^17.0.0",
"eslint": "^7.12.1",
"eslint-config-qubyte": "^3.0.0",
"mkdirp": "^1.0.4",
"mocha": "^7.1.1",
"nock": "^12.0.3",
"promise": "~8.1.0",
"mocha": "^8.2.0",
"nock": "^13.0.4",
"promise": "^8.1.0",
"rimraf": "^3.0.2",
"sinon": "^9.0.1",
"testem": "3.1.0",
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11",
"whatwg-fetch": "~2.0.3"
"sinon": "^9.2.1",
"testem": "^3.2.0",
"webpack": "^5.3.0",
"webpack-cli": "^4.1.0",
"whatwg-fetch": "~3.4.1"
},

@@ -53,0 +53,0 @@ "files": [

# Fetch Ponyfill
[![Greenkeeper badge](https://badges.greenkeeper.io/qubyte/fetch-ponyfill.svg)](https://greenkeeper.io/)
> WHATWG `fetch` [ponyfill](https://ponyfill.com)

@@ -6,0 +4,0 @@

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