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

tcomb

Package Overview
Dependencies
Maintainers
1
Versions
74
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tcomb - npm Package Compare versions

Comparing version 0.0.12 to 0.1.0

index.js

2

build/tcomb.min.js

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

!function(a,b){"use strict";"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?module.exports=b():a.t=b()}(this,function(){"use strict";function a(a){throw w=!0,new Error(a)}function b(a){x.onFail(a)}function c(a){if(a!==!0){var c=y.call(arguments,1),d=c[0]?e.apply(null,c):"assert failed";b(d)}}function d(a,b,d){for(var e in b)b.hasOwnProperty(e)&&(d||c(!a.hasOwnProperty(e),"cannot overwrite property %s",e),a[e]=b[e]);return a}function e(){function a(a,f){if("%%"===a)return"%";if(d>=c)return a;var g=e.formatters[f];return g?g(b[d++]):a}var b=y.call(arguments),c=b.length,d=1,f=b[0],g=f.replace(/%([a-z%])/g,a);return c>d&&(g+=" "+b.slice(d).join(" ")),g}function f(a,b){return"function"==typeof b?e("Func",b.name):b}function g(a){return G.is(a)&&F.is(a.meta)}function h(a){return E.is(a)&&a.every(g)}function i(a){return c(g(a),"Invalid argument `type` of value `%j` supplied to `getName()`, expected a type.",a),a.meta.name}function j(a,b,d){return A.is(a)?h(d)?e(d.length>1?"%s([%s])":"%s(%s)",b,d.map(i).join(", ")):b:(c(B.is(a),z.ERR_BAD_COMBINATOR_ARGUMENT,"name",a,b,"a `maybe(Str)`"),a)}function k(a,b){c(!(a instanceof b),z.ERR_NEW_OPERATOR_FORBIDDEN,i(b))}function l(){c(G.is(x.update),z.ERR_OPTIONS_UPDATE_MISSING);var a=this,b=y.call(arguments),d=x.update.apply(a,b);return a(d)}function m(a){return k(this,m),a}function n(a,b){function d(b){return k(this,d),c(d.is(b),z.ERR_BAD_TYPE_VALUE,b,a,e("a `%s`",a)),b}return d.meta={kind:"primitive",name:a},d.is=b,d}function o(a,b){function d(e,f){if(c(F.is(e),z.ERR_BAD_TYPE_VALUE,e,b,"an `Obj`"),d.is(e))return e;if(!(this instanceof d))return new d(e,f);for(var g in a)if(a.hasOwnProperty(g)){var h=a[g],i=e[g];this[g]=h.is(i)?i:h(i,f)}f||Object.freeze(this)}return b=j(b,"struct"),c(F.is(a),z.ERR_BAD_COMBINATOR_ARGUMENT,"props",a,b,"an `Obj`"),d.meta={kind:"struct",props:a,name:b},d.is=function(a){return a instanceof d},d.update=l,d}function p(a,b){function d(a,e){k(this,d),c(G.is(d.dispatch),"unimplemented %s.dispatch()",b);var f=d.dispatch(a);return f(a,e)}var e="union";return b=j(b,e,a),c(h(a)&&a.length>=2,z.ERR_BAD_COMBINATOR_ARGUMENT,"types",a,e,"a list(type) of length >= 2"),d.meta={kind:"union",types:a,name:b},d.is=function(b){return a.some(function(a){return a.is(b)})},d}function q(a,b){function d(b,c){return k(this,d),A.is(b)?null:a(b,c)}var e="maybe";return b=j(b,e,[a]),c(g(a),z.ERR_BAD_COMBINATOR_ARGUMENT,"type",a,e,"a type"),"maybe"===a.meta.kind?a:(d.meta={kind:"maybe",type:a,name:b},d.is=function(b){return A.is(b)||a.is(b)},d)}function r(a,b){function d(a){return k(this,d),c(d.is(a),z.ERR_BAD_TYPE_VALUE,a,b,e),a}b=j(b,"enums"),c(F.is(a),z.ERR_BAD_COMBINATOR_ARGUMENT,"map",a,b,"an `Obj`");var e="a `Str`";return d.meta={kind:"enums",map:a,name:b},d.is=function(b){return B.is(b)&&a.hasOwnProperty(b)},d}function s(a,b){function d(e,f){if(k(this,d),c(E.is(e)&&e.length===g,z.ERR_BAD_TYPE_VALUE,e,b,m),d.isTuple(e))return e;for(var h=[],i=0;g>i;i++){var j=a[i],l=e[i];h.push(j.is(l)?l:j(l,f))}return f||Object.freeze(h),h}var f="tuple";b=j(b,f,a),c(h(a)&&a.length>=2,z.ERR_BAD_COMBINATOR_ARGUMENT,"types",a,f,"a list(type) of length >= 2");var g=a.length,m=e("a tuple `(%s)`",a.map(i).join(", "));return d.meta={kind:"tuple",types:a,name:b},d.isTuple=function(b){return a.every(function(a,c){return a.is(b[c])})},d.is=function(a){return E.is(a)&&a.length===g&&d.isTuple(a)},d.update=l,d}function t(a,b,d){function e(f,g){k(this,e);var i=a(f,g);return c(b(i),z.ERR_BAD_TYPE_VALUE,f,d,h),i}var f="subtype";d=j(d,f,[a]),c(g(a),z.ERR_BAD_COMBINATOR_ARGUMENT,"type",a,f,"a type"),c(G.is(b),z.ERR_BAD_COMBINATOR_ARGUMENT,"predicate",b,f,"a `Func`");var h=b.__doc__||"a valid value for the predicate";return e.meta={kind:"subtype",type:a,predicate:b,name:d},e.is=function(c){return a.is(c)&&b(c)},e}function u(a,b){function d(e,f){if(k(this,d),c(E.is(e),z.ERR_BAD_TYPE_VALUE,e,b,h),d.isList(e))return e;for(var g=[],i=0,j=e.length;j>i;i++){var l=e[i];g.push(a.is(l)?l:a(l,f))}return f||Object.freeze(g),g}var f="list";b=j(b,f,[a]),c(g(a),z.ERR_BAD_COMBINATOR_ARGUMENT,"type",a,f,"a type");var h=e("a list of `%s`",i(a));return d.meta={kind:"list",type:a,name:b},d.isList=function(b){return b.every(a.is)},d.is=function(a){return E.is(a)&&d.isList(a)},d.update=l,d}function v(a,b,d,e){function f(){var c=y.call(arguments);c.length<b.length&&(c.length=b.length),c=a.is(c)?c:a(c);var e=b.apply(null,c);return d&&(e=d.is(e)?e:d(e)),e}return e=e||"func()",c(g(a),z.ERR_BAD_COMBINATOR_ARGUMENT,"Arguments",a,e,"a type"),c(G.is(b),z.ERR_BAD_COMBINATOR_ARGUMENT,"f",b,e,"a `Func`"),c(A.is(d)||g(d),z.ERR_BAD_COMBINATOR_ARGUMENT,"Return",d,e,"a type"),d=d||null,g(b)&&b.meta.Arguments===a&&b.meta.Return===d?b:(f.is=function(a){return a===f},f.meta={kind:"func",Arguments:a,f:b,Return:d,name:e},f)}var w=!1,x={onFail:a,update:null},y=Array.prototype.slice,z={ERR_BAD_TYPE_VALUE:"Invalid type argument `value` of value `%j` supplied to `%s`, expected %s.",ERR_BAD_COMBINATOR_ARGUMENT:"Invalid combinator argument `%s` of value `%j` supplied to `%s`, expected %s.",ERR_OPTIONS_UPDATE_MISSING:"Missing `options.update` implementation",ERR_NEW_OPERATOR_FORBIDDEN:"Operator `new` is forbidden for `%s`"};e.formatters={s:function(a){return String(a)},j:function(a){return JSON.stringify(a,f)}},m.meta={kind:"any",name:"Any"},m.is=function(){return!0};var A=n("Nil",function(a){return null===a||void 0===a}),B=n("Str",function(a){return"string"==typeof a}),C=n("Num",function(a){return"number"==typeof a&&isFinite(a)&&!isNaN(a)}),D=n("Bool",function(a){return a===!0||a===!1}),E=n("Arr",function(a){return a instanceof Array}),F=n("Obj",function(a){return!A.is(a)&&"object"==typeof a&&!E.is(a)}),G=n("Func",function(a){return"function"==typeof a}),H=n("Err",function(a){return a instanceof Error}),I=n("Re",function(a){return a instanceof RegExp}),J=n("Dat",function(a){return a instanceof Date});return r.of=function(a,b){a=B.is(a)?a.split(" "):a;var c={};return a.forEach(function(a){c[a]=a}),r(c,b)},{errs:z,options:x,assert:c,mixin:d,format:e,isType:g,getName:i,fail:b,slice:y,Any:m,Nil:A,Str:B,Num:C,Bool:D,Arr:E,Obj:F,Func:G,Err:H,Re:I,Dat:J,struct:o,enums:r,union:p,maybe:q,tuple:s,subtype:t,list:u,func:v}});
!function(a,b){"use strict";"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?module.exports=b():a.t=b()}(this,function(){"use strict";function a(a){throw x=!0,new Error(a)}function b(a){y.onFail(a)}function c(a){if(a!==!0){var c=z.call(arguments,1),d=c[0]?e.apply(null,c):"assert failed";b(d)}}function d(a,b,d){for(var e in b)b.hasOwnProperty(e)&&(d||c(!a.hasOwnProperty(e),"cannot overwrite property %s",e),a[e]=b[e]);return a}function e(){function a(a,f){if("%%"===a)return"%";if(d>=c)return a;var g=e.formatters[f];return g?g(b[d++]):a}var b=z.call(arguments),c=b.length,d=1,f=b[0],g=f.replace(/%([a-z%])/g,a);return c>d&&(g+=" "+b.slice(d).join(" ")),g}function f(a,b){return"function"==typeof b?e("Func",b.name):b}function g(a){return H.is(a)&&G.is(a.meta)}function h(a){return F.is(a)&&a.every(g)}function i(a){return c(g(a),"Invalid argument `type` of value `%j` supplied to `getName()`, expected a type.",a),a.meta.name}function j(a,b,d){return B.is(a)?h(d)?e(d.length>1?"%s([%s])":"%s(%s)",b,d.map(i).join(", ")):b:(c(C.is(a),A.ERR_BAD_COMBINATOR_ARGUMENT,"name",a,b,"a `maybe(Str)`"),a)}function k(a,b){c(!(a instanceof b),A.ERR_NEW_OPERATOR_FORBIDDEN,i(b))}function l(){c(H.is(y.update),A.ERR_OPTIONS_UPDATE_MISSING);var a=this,b=z.call(arguments),d=y.update.apply(y.update,b);return a(d)}function m(a){return k(this,m),a}function n(a,b){function d(b){return k(this,d),c(d.is(b),A.ERR_BAD_TYPE_VALUE,b,a,e("a `%s`",a)),b}return d.meta={kind:"primitive",name:a},d.is=b,d}function o(a,b){function d(e,f){if(c(G.is(e),A.ERR_BAD_TYPE_VALUE,e,b,"an `Obj`"),d.is(e))return e;if(!(this instanceof d))return new d(e,f);for(var g in a)if(a.hasOwnProperty(g)){var h=a[g],i=e[g];this[g]=h.is(i)?i:h(i,f)}f||Object.freeze(this)}return b=j(b,"struct"),c(G.is(a),A.ERR_BAD_COMBINATOR_ARGUMENT,"props",a,b,"an `Obj`"),d.meta={kind:"struct",props:a,name:b},d.is=function(a){return a instanceof d},d.update=l,d}function p(a,b){function d(a,e){k(this,d),c(H.is(d.dispatch),"unimplemented %s.dispatch()",b);var f=d.dispatch(a);return f(a,e)}var e="union";return b=j(b,e,a),c(h(a)&&a.length>=2,A.ERR_BAD_COMBINATOR_ARGUMENT,"types",a,e,"a list(type) of length >= 2"),d.meta={kind:"union",types:a,name:b},d.is=function(b){return a.some(function(a){return a.is(b)})},d}function q(a,b){function d(b,c){return k(this,d),B.is(b)?null:a(b,c)}var e="maybe";return b=j(b,e,[a]),c(g(a),A.ERR_BAD_COMBINATOR_ARGUMENT,"type",a,e,"a type"),"maybe"===a.meta.kind?a:(d.meta={kind:"maybe",type:a,name:b},d.is=function(b){return B.is(b)||a.is(b)},d)}function r(a,b){function d(a){return k(this,d),c(d.is(a),A.ERR_BAD_TYPE_VALUE,a,b,e),a}b=j(b,"enums"),c(G.is(a),A.ERR_BAD_COMBINATOR_ARGUMENT,"map",a,b,"an `Obj`");var e="a valid enum";return d.meta={kind:"enums",map:a,name:b},d.is=function(b){return C.is(b)&&a.hasOwnProperty(b)},d}function s(a,b){function d(e,f){if(k(this,d),c(F.is(e)&&e.length===g,A.ERR_BAD_TYPE_VALUE,e,b,m),d.isTuple(e))return e;for(var h=[],i=0;g>i;i++){var j=a[i],l=e[i];h.push(j.is(l)?l:j(l,f))}return f||Object.freeze(h),h}var f="tuple";b=j(b,f,a),c(h(a)&&a.length>=2,A.ERR_BAD_COMBINATOR_ARGUMENT,"types",a,f,"a list(type) of length >= 2");var g=a.length,m=e("a tuple `(%s)`",a.map(i).join(", "));return d.meta={kind:"tuple",types:a,name:b},d.isTuple=function(b){return a.every(function(a,c){return a.is(b[c])})},d.is=function(a){return F.is(a)&&a.length===g&&d.isTuple(a)},d.update=l,d}function t(a,b,d){function e(f,g){k(this,e);var i=a(f,g);return c(b(i),A.ERR_BAD_TYPE_VALUE,f,d,h),i}var f="subtype";d=j(d,f,[a]),c(g(a),A.ERR_BAD_COMBINATOR_ARGUMENT,"type",a,f,"a type"),c(H.is(b),A.ERR_BAD_COMBINATOR_ARGUMENT,"predicate",b,f,"a `Func`");var h=b.__doc__||"a valid value for the predicate";return e.meta={kind:"subtype",type:a,predicate:b,name:d},e.is=function(c){return a.is(c)&&b(c)},e}function u(a,b){function d(e,f){if(k(this,d),c(F.is(e),A.ERR_BAD_TYPE_VALUE,e,b,h),d.isList(e))return e;for(var g=[],i=0,j=e.length;j>i;i++){var l=e[i];g.push(a.is(l)?l:a(l,f))}return f||Object.freeze(g),g}var f="list";b=j(b,f,[a]),c(g(a),A.ERR_BAD_COMBINATOR_ARGUMENT,"type",a,f,"a type");var h=e("a list of `%s`",i(a));return d.meta={kind:"list",type:a,name:b},d.isList=function(b){return b.every(a.is)},d.is=function(a){return F.is(a)&&d.isList(a)},d.update=l,d}function v(a,b){function d(e,f){if(k(this,d),c(G.is(e),A.ERR_BAD_TYPE_VALUE,e,b,h),d.isDict(e))return e;var g={};for(var i in e)if(e.hasOwnProperty(i)){var j=e[i];g[i]=a.is(j)?j:a(j,f)}return f||Object.freeze(g),g}var f="dict";b=j(b,f,[a]),c(g(a),A.ERR_BAD_COMBINATOR_ARGUMENT,"type",a,f,"a type");var h=e("a dict of `%s`",i(a));return d.meta={kind:"dict",type:a,name:b},d.isDict=function(b){for(var c in b)if(b.hasOwnProperty(c)&&!a.is(b[c]))return!1;return!0},d.is=function(a){return G.is(a)&&d.isDict(a)},d.update=l,d}function w(a,b,d,e){function f(){var c=z.call(arguments);c.length<b.length&&(c.length=b.length),c=a.is(c)?c:a(c);var e=b.apply(null,c);return d&&(e=d.is(e)?e:d(e)),e}return e=e||"func()",c(g(a),A.ERR_BAD_COMBINATOR_ARGUMENT,"Arguments",a,e,"a type"),c(H.is(b),A.ERR_BAD_COMBINATOR_ARGUMENT,"f",b,e,"a `Func`"),c(B.is(d)||g(d),A.ERR_BAD_COMBINATOR_ARGUMENT,"Return",d,e,"a type"),d=d||null,g(b)&&b.meta.Arguments===a&&b.meta.Return===d?b:(f.is=function(a){return a===f},f.meta={kind:"func",Arguments:a,f:b,Return:d,name:e},f)}var x=!1,y={onFail:a,update:null},z=Array.prototype.slice,A={ERR_BAD_TYPE_VALUE:"Invalid type argument `value` of value `%j` supplied to `%s`, expected %s.",ERR_BAD_COMBINATOR_ARGUMENT:"Invalid combinator argument `%s` of value `%j` supplied to `%s`, expected %s.",ERR_OPTIONS_UPDATE_MISSING:"Missing `options.update` implementation",ERR_NEW_OPERATOR_FORBIDDEN:"Operator `new` is forbidden for `%s`"};e.formatters={s:function(a){return String(a)},j:function(a){return JSON.stringify(a,f)}},m.meta={kind:"any",name:"Any"},m.is=function(){return!0};var B=n("Nil",function(a){return null===a||void 0===a}),C=n("Str",function(a){return"string"==typeof a}),D=n("Num",function(a){return"number"==typeof a&&isFinite(a)&&!isNaN(a)}),E=n("Bool",function(a){return a===!0||a===!1}),F=n("Arr",function(a){return a instanceof Array}),G=n("Obj",function(a){return!B.is(a)&&"object"==typeof a&&!F.is(a)}),H=n("Func",function(a){return"function"==typeof a}),I=n("Err",function(a){return a instanceof Error}),J=n("Re",function(a){return a instanceof RegExp}),K=n("Dat",function(a){return a instanceof Date});return r.of=function(a,b){a=C.is(a)?a.split(" "):a;var c={};return a.forEach(function(a){c[a]=a}),r(c,b)},{options:y,assert:c,mixin:d,format:e,isType:g,getName:i,fail:b,slice:z,Any:m,Nil:B,Str:C,Num:D,Bool:E,Arr:F,Obj:G,Func:H,Err:I,Re:J,Dat:K,struct:o,enums:r,union:p,maybe:q,tuple:s,subtype:t,list:u,dict:v,func:w}});
//# sourceMappingURL=tcomb.min.js.map
Roadmap
=======
- TODO subtype combinator: add a reference to the super type prototype, fix #22
- TODO add `Dict(A, B)` combinator, for dictionaries, fix #21
# v0.1.0
# v.0.0.12
- added `Dict(A)` combinator, for dictionaries, fix #21
# v0.0.12
- more verbose error messages, fix #25
- list#is() depends on `this`, fix #27
- tuple#is() depends on `this`, fix #28
**BREAKING**
- `enums.of()` should generate values equals to keys, fix #23
# v.0.0.11
# v0.0.11

@@ -16,0 +20,0 @@ - forbid the use of `new` for all types but structs, fix #8

@@ -14,15 +14,2 @@ module.exports = function (grunt) {

rig: {
compile: {
options: {
banner: banner + '\n\n'
},
files: {
'build/tcomb.js': [
'src/tcomb.js'
]
}
}
},
jshint: {

@@ -34,3 +21,3 @@ options: {

all: [
'build/tcomb.js'
'index.js'
]

@@ -52,3 +39,3 @@ },

files: {
'build/tcomb.min.js': ['build/tcomb.js']
'build/tcomb.min.js': ['index.js']
}

@@ -73,3 +60,3 @@ }

emu: {
'README.md': 'build/tcomb.js'
'README.md': 'index.js'
}

@@ -80,3 +67,2 @@

// plugins
grunt.loadNpmTasks('grunt-rigger');
grunt.loadNpmTasks('grunt-contrib-jshint');

@@ -95,6 +81,6 @@ grunt.loadNpmTasks('grunt-mocha-test');

});
grunt.registerTask('doc', ['rig', 'emu']);
grunt.registerTask('doc', ['emu']);
grunt.registerTask('test', ['mochaTest']);
grunt.registerTask('default', ['rig', 'test', 'watch']);
grunt.registerTask('build', ['rig', 'jshint', 'test', 'uglify', 'emu']);
grunt.registerTask('default', ['test', 'watch']);
grunt.registerTask('build', ['jshint', 'test', 'uglify', 'emu']);
};
{
"name": "tcomb",
"version": "0.0.12",
"version": "0.1.0",
"description": "Pragmatic runtime type checking for JavaScript",
"main": "build/tcomb.js",
"main": "index.js",
"scripts": {

@@ -20,13 +20,13 @@ "cover": "istanbul cover _mocha -- --ui bdd -R dot"

"devDependencies": {
"mocha": "*",
"grunt": "*",
"grunt-rigger": "*",
"grunt-contrib-jshint": "*",
"grunt-mocha-test": "*",
"grunt-contrib-uglify": "*",
"grunt-contrib-watch": "*",
"grunt-cli": "*",
"jshint-stylish": "*",
"istanbul": "*",
"emu": "*"
"emu": "^0.0.2",
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13",
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-uglify": "^0.5.1",
"grunt-contrib-watch": "^0.6.1",
"grunt-mocha-test": "^0.11.0",
"istanbul": "^0.3.0",
"jshint-stylish": "^0.4.0",
"mocha": "^1.21.4",
"react": "*"
},

@@ -33,0 +33,0 @@ "tags": [

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

# tcomb
% tcomb

@@ -6,7 +6,17 @@ ![tcomb logo](http://gcanti.github.io/resources/tcomb/logo.png)

tcomb is a library for Node.js and the browser (2K gzipped) which allows you to **check the types** of
JavaScript values at runtime with a simple syntax. It is great for checking external input,
for testing and for **adding safety** to your internal code.
JavaScript values at runtime with a simple syntax. It's great for **Domain Driven Design**, for checking external input,
for testing and for adding safety to your internal code.
Some features include:
# Contents
- [Features](#features)
- [Quick Examples](#quick-examples)
- [Setup](#setup)
- [Requirements](#requirements)
- [Tests](#tests)
- [The Idea](#the-idea)
- [Api](#api)
## Features
- **write complex domain models** in a breeze and with small code footprint

@@ -45,2 +55,3 @@ - easy debugging

- list
- dict
- function type (experimental)

@@ -60,3 +71,4 @@

price: union(Num, Price), // a price (dollars) OR in another currency
dim: tuple([Num, Num]) // dimensions (width, height)
size: tuple([Num, Num]), // width x height
warranty: dict(Num) // a dictionary country -> covered years
});

@@ -80,3 +92,7 @@

price: {currency: 'EUR', amount: 100},
dim: [2.4, 4.1]
size: [2.4, 4.1],
warranty: {
US: 2,
IT: 1
}
};

@@ -123,5 +139,5 @@

or download the `build/tcomb.js` file.
or download the `build/tcomb.min.js` file.
### Requirements
## Requirements

@@ -189,5 +205,3 @@ This library uses a few ES5 methods

TODO: better docs
Adds to structs, tuples and lists a static method `update` that returns a new instance
Adds to structs, tuples, lists and dicts a static method `update` that returns a new instance
without modifying the original.

@@ -199,3 +213,5 @@

// see http://facebook.github.io/react/docs/update.html
options.update = React.addons.update;
options.update = function (x, updates) {
return React.addons.update(mixin({}, x), updates);
};
var p1 = Point({x: 0, y: 0});

@@ -444,2 +460,24 @@ var p2 = Point.update(p1, {x: {$set: 1}}); // => Point({x: 1, y: 0})

### dict(type, [name])
Defines a dictionary Str -> type.
- `type` the type of the values
- `name` optional string useful for debugging
Example
```javascript
// defines a dictionary of numbers
var Tel = dict(Num);
```
#### is(x)
Returns `true` if `x` is an instance of the dict.
```javascript
Tel.is({'jack': 4098, 'sape': 4139}); // => true
```
### func(Arguments, f, [Return], [name])

@@ -446,0 +484,0 @@

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