Socket
Socket
Sign inDemoInstall

bookshelf

Package Overview
Dependencies
Maintainers
1
Versions
87
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bookshelf - npm Package Compare versions

Comparing version 0.7.7 to 0.7.8

browser/knex.js

6

bookshelf.js

@@ -1,5 +0,5 @@

// Bookshelf.js 0.7.7
// Bookshelf.js 0.7.8
// ---------------
// (c) 2013 Tim Griesser
// (c) 2014 Tim Griesser
// Bookshelf may be freely distributed under the MIT license.

@@ -18,3 +18,3 @@ // For all details and documentation:

var bookshelf = {
VERSION: '0.7.7'
VERSION: '0.7.8'
};

@@ -21,0 +21,0 @@

@@ -9,2 +9,4 @@ ## How to contribute to Bookshelf.js

* All pull requests should be made to the `master` branch.
* Files in the `/browser` folder are built automatically. You don't need to edit them.
* All pull requests should be made to the `master` branch.

@@ -11,6 +11,2 @@ var gulp = require('gulp');

var externals = ['events', 'buffer', 'lodash', 'bluebird', 'knex', 'backbone', 'trigger-then',
'create-error', 'inflection', 'inherits', 'simple-extend', 'semver'];
var alwaysExcluded = [];
function ensureOutputDirectory() {

@@ -20,47 +16,11 @@ return fs.mkdirAsync('./browser').catch(function(){});

function buildBookshelf() {
gulp.task('build', function buildBookshelf() {
var outfile = argv.o || 'bookshelf.js';
var standalone = argv.s || 'Bookshelf';
var b = browserify(['./bookshelf.js']);
b.transform(function() {
var data = '';
function write (buf) { data += buf; }
function end () {
this.queue(data.replace("require('bluebird/js/main/promise')()", "require('bluebird')"));
this.queue(null);
}
return through(write, end);
});
alwaysExcluded.forEach(function(file) {
b.exclude(file);
});
externals.forEach(function(file) {
b.external(file);
});
var b = browserify({standalone: standalone}).add('./bookshelf.js');
ensureOutputDirectory().then(function() {
var outStream = fs.createWriteStream('./browser/' + outfile);
b.bundle({standalone: standalone}).pipe(outStream);
b.bundle().pipe(outStream);
});
}
function buildDependencies() {
var b = browserify();
externals.forEach(function(ext) {
ext === 'knex' ? b.require(path.join(__dirname, '/node_modules/knex/browser/knex.js'), {expose: 'knex'}) : b.require(ext);
});
ensureOutputDirectory().then(function() {
var depStream = fs.createWriteStream('./browser/deps.js');
b.bundle().pipe(depStream);
});
}
gulp.task('build', function() {
buildBookshelf();
buildDependencies();
});
gulp.task('build:bookshelf', buildBookshelf);
gulp.task('build:deps', buildDependencies);

@@ -67,0 +27,0 @@ // Run the test... TODO: split these out to individual components.

@@ -14,3 +14,2 @@ // Base Collection

var array = [];
var push = array.push;
var splice = array.splice;

@@ -115,4 +114,10 @@

} else {
if (order) this.models.length = 0;
push.apply(this.models, order || toAdd);
if (order) {
this.models.length = 0;
} else {
order = toAdd;
}
for (i = 0, l = order.length; i < l; ++i) {
this.models.push(order[i]);
}
}

@@ -119,0 +124,0 @@ }

@@ -69,3 +69,3 @@ // Eager Base

withRelated: subRelated[relationName],
beforeFn: withRelated[relationName] || noop
_beforeFn: withRelated[relationName] || noop
})));

@@ -72,0 +72,0 @@ }

@@ -7,3 +7,15 @@ // Events

var triggerThen = require('trigger-then');
var _ = require('lodash');
Backbone.Events.once = function(name, callback, context) {
//if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this;
var self = this;
var once = _.once(function() {
self.off(name, once);
return callback.apply(this, arguments);
});
once._callback = callback;
return this.on(name, once, context);
};
// Mixin the `triggerThen` function into all relevant Backbone objects,

@@ -10,0 +22,0 @@ // so we can have event driven async validations, functions, etc.

@@ -84,3 +84,3 @@ // Base Model

// unless `{shallow: true}` is passed in the `options`.
// Also includes _pivot_ keys for relations unless `{omitPivot: true}`
// Also includes _pivot_ keys for relations unless `{omitPivot: true}`
// is passed in `options`.

@@ -141,4 +141,13 @@ toJSON: function(options) {

var vals = {};
if (keys[0]) {
if (this.isNew(options)) {
if (!options || options.method !== 'update') {
vals[keys[0]] = d;
}
}
else if (options && options.method === 'insert') {
vals[keys[0]] = d;
}
}
if (keys[1]) vals[keys[1]] = d;
if (this.isNew(options) && keys[0] && (!options || options.method !== 'update')) vals[keys[0]] = d;
return vals;

@@ -145,0 +154,0 @@ },

@@ -31,4 +31,2 @@ // EagerRelation

// Call the function, if one exists, to constrain the eager loaded query.
options.beforeFn.call(handled, handled.query());
return handled

@@ -48,3 +46,4 @@ .sync(_.extend(options, {parentResponse: this.parentResponse}))

var groups = _.groupBy(this.parent, function(m) {
return m.get(relatedData.morphName + '_type');
var typeKeyName = relatedData.columnNames && relatedData.columnNames[0] ? relatedData.columnNames[0] : relatedData.morphName + '_type';
return m.get(typeKeyName);
});

@@ -54,6 +53,7 @@ var pending = _.reduce(groups, function(memo, val, group) {

var target = new Target();
var idKeyName = relatedData.columnNames && relatedData.columnNames[1] ? relatedData.columnNames[1] : relatedData.morphName + '_id';
memo.push(target
.query('whereIn',
_.result(target, 'idAttribute'),
_.uniq(_.invoke(groups[group], 'get', relatedData.morphName + '_id'))
_.uniq(_.invoke(groups[group], 'get', idKeyName))
)

@@ -65,3 +65,3 @@ .sync(options)

return this._eagerLoadHelper(response, relationName, {
relatedData: relatedData.instance('morphTo', Target, {morphName: relatedData.morphName})
relatedData: relatedData.instance('morphTo', Target, {morphName: relatedData.morphName, columnNames: relatedData.columnNames})
}, options);

@@ -113,2 +113,2 @@ }));

module.exports = EagerRelation;
module.exports = EagerRelation;

@@ -53,4 +53,4 @@ // Model

// to another model.
morphOne: function(Target, name, morphValue) {
return this._morphOneOrMany(Target, name, morphValue, 'morphOne');
morphOne: function(Target, name, columnNames, morphValue) {
return this._morphOneOrMany(Target, name, columnNames, morphValue, 'morphOne');
},

@@ -60,4 +60,4 @@

// to many another models.
morphMany: function(Target, name, morphValue) {
return this._morphOneOrMany(Target, name, morphValue, 'morphMany');
morphMany: function(Target, name, columnNames, morphValue) {
return this._morphOneOrMany(Target, name, columnNames, morphValue, 'morphMany');
},

@@ -68,4 +68,12 @@

morphTo: function(morphName) {
var columnNames, remainder;
if (!_.isString(morphName)) throw new Error('The `morphTo` name must be specified.');
return this._relation('morphTo', null, {morphName: morphName, candidates: _.rest(arguments)}).init(this);
if (_.isArray(arguments[1])) {
columnNames = arguments[1];
remainder = _.rest(arguments, 2);
} else {
columnNames = null;
remainder = _.rest(arguments);
}
return this._relation('morphTo', null, {morphName: morphName, columnNames: columnNames, candidates: remainder}).init(this);
},

@@ -259,5 +267,10 @@

// Helper for setting up the `morphOne` or `morphMany` relations.
_morphOneOrMany: function(Target, morphName, morphValue, type) {
_morphOneOrMany: function(Target, morphName, columnNames, morphValue, type) {
if (!_.isArray(columnNames)) {
// Shift by one place
morphValue = columnNames;
columnNames = null;
}
if (!morphName || !Target) throw new Error('The polymorphic `name` and `Target` are required.');
return this._relation(type, Target, {morphName: morphName, morphValue: morphValue}).init(this);
return this._relation(type, Target, {morphName: morphName, morphValue: morphValue, columnNames: columnNames}).init(this);
},

@@ -283,2 +296,2 @@

module.exports = BookshelfModel;
module.exports = BookshelfModel;

@@ -30,11 +30,14 @@ // Relation

if (this.isInverse()) {
// use formatted attributes so that morphKey and foreignKey will match
// attribute keys
var attributes = parent.format(_.clone(parent.attributes));
// If the parent object is eager loading, and it's a polymorphic `morphTo` relation,
// we can't know what the target will be until the models are sorted and matched.
if (this.type === 'morphTo' && !parent._isEager) {
parent.attributes = parent.format(parent.attributes);
this.target = Helpers.morphCandidate(this.candidates, parent.get(this.key('morphKey')));
this.target = Helpers.morphCandidate(this.candidates, attributes[this.key('morphKey')]);
this.targetTableName = _.result(this.target.prototype, 'tableName');
this.targetIdAttribute = _.result(this.target.prototype, 'idAttribute');
}
this.parentFk = parent.get(this.key('foreignKey'));
this.parentFk = attributes[this.key('foreignKey')];
} else {

@@ -85,2 +88,3 @@ this.parentFk = parent.id;

key: function(keyName) {
var idKeyName;
if (this[keyName]) return this[keyName];

@@ -94,8 +98,17 @@ if (keyName === 'otherKey') {

if (keyName === 'foreignKey') {
if (this.type === 'morphTo') return this[keyName] = this.morphName + '_id';
if (this.type === 'morphTo') {
idKeyName = this.columnNames && this.columnNames[1] ? this.columnNames[1] : this.morphName + '_id';
return this[keyName] = idKeyName;
}
if (this.type === 'belongsTo') return this[keyName] = singularMemo(this.targetTableName) + '_' + this.targetIdAttribute;
if (this.isMorph()) return this[keyName] = this.morphName + '_id';
if (this.isMorph()) {
idKeyName = this.columnNames && this.columnNames[1] ? this.columnNames[1] : this.morphName + '_id';
return this[keyName] = idKeyName;
}
return this[keyName] = singularMemo(this.parentTableName) + '_' + this.parentIdAttribute;
}
if (keyName === 'morphKey') return this[keyName] = this.morphName + '_type';
if (keyName === 'morphKey') {
var typeKeyName = this.columnNames && this.columnNames[0] ? this.columnNames[0] : this.morphName + '_type';
return this[keyName] = typeKeyName;
}
if (keyName === 'morphValue') return this[keyName] = this.parentTableName || this.targetTableName;

@@ -363,3 +376,9 @@ },

attach: function(ids, options) {
return this._handler('insert', ids, options);
return Promise.bind(this).then(function(){
return this.triggerThen('attaching', this, ids, options);
}).then(function() {
return this._handler('insert', ids, options);
}).then(function(resp) {
return this.triggerThen('attached', this, resp, options);
});
},

@@ -374,3 +393,9 @@

detach: function(ids, options) {
return this._handler('delete', ids, options);
return Promise.bind(this).then(function(){
return this.triggerThen('detaching', this, ids, options);
}).then(function() {
return this._handler('delete', ids, options);
}).then(function(resp) {
return this.triggerThen('detached', this, resp, options);
});
},

@@ -466,2 +491,2 @@

module.exports = BookshelfRelation;
module.exports = BookshelfRelation;

@@ -63,2 +63,5 @@ // Sync

// Call the function, if one exists, to constrain the eager loaded query.
if (options._beforeFn) options._beforeFn.call(this.syncing, options.query);
// Trigger a `fetching` event on the model, and then select the appropriate columns.

@@ -65,0 +68,0 @@ return Promise.bind(this).then(function() {

{
"name": "bookshelf",
"version": "0.7.7",
"version": "0.7.8",
"description": "A lightweight ORM for PostgreSQL, MySQL, and SQLite3",

@@ -15,3 +15,3 @@ "main": "bookshelf.js",

"type": "git",
"url": "https://github.com/tgriesser/bookshelf.git"
"url": "git://github.com/tgriesser/bookshelf.git"
},

@@ -28,31 +28,31 @@ "keywords": [

"backbone": "1.1.0",
"inflection": "~1.3.5",
"trigger-then": "0.3.x",
"bluebird": "~2.0.5",
"lodash": ">=2.0.0",
"bluebird": "^2.0.0",
"create-error": "~0.3.1",
"inflection": "^1.5.1",
"inherits": "~2.0.1",
"lodash": "^2.0.0",
"semver": "^4.1.0",
"simple-extend": "0.1.0",
"inherits": "~2.0.1",
"semver": "~2.3.0",
"create-error": "~0.3.1"
"trigger-then": "0.3.x"
},
"devDependencies": {
"minimist": "~0.0.9",
"through": "^2.3.4",
"browserify": "^4.0.0",
"browserify": "^6.2.0",
"chai": "~1.9.1",
"chai-as-promised": "~4.1.0",
"gulp": "^3.6.2",
"gulp-bump": "^0.1.8",
"gulp-git": "^0.4.2",
"gulp-git": "^0.5.3",
"gulp-shell": "^0.2.5",
"knex": "0.6.x",
"mocha": "~1.20.1",
"mysql": "~2.3.2",
"pg": "~3.3.0",
"sqlite3": "~2.2.3",
"underscore.string": "~2.3.1",
"chai-as-promised": "~4.1.0",
"chai": "~1.9.1",
"sinon-chai": "~2.5.0",
"sinon": "~1.10.2",
"jshint": "~2.5.1",
"knex": "0.7.x",
"minimist": "^1.1.0",
"mocha": "^2.0.1",
"mysql": "^2.5.2",
"node-uuid": "~1.4.1",
"jshint": "~2.5.1"
"pg": "^3.6.2",
"sinon": "^1.11.1",
"sinon-chai": "^2.6.0",
"sqlite3": "^3.0.2",
"through": "^2.3.4",
"underscore.string": "~2.3.1"
},

@@ -59,0 +59,0 @@ "author": {

@@ -93,2 +93,19 @@ var Promise = testPromise;

});
it('should support large arrays', function() {
this.timeout(15000);
var count = 200000;
var models = [];
var i;
for (i = 0; i < count; ++i) {
models.push(new collection.model({
some_id: i,
name: 'Large-' + i
}));
}
collection.set(models, {add: true, remove: false, merge: false});
equal(collection.get(count - 1).get('name'), 'Large-' + (count - 1));
});
});

@@ -95,0 +112,0 @@

@@ -59,2 +59,2 @@ var _ = require('lodash');

};
};

@@ -123,2 +123,16 @@ var Promise = global.testPromise;

});
})
// The following is for testing custom columnNames.
.then(function() {
return new Site({id: 10})
.thumbnails()
.create({
url: 'http://image.dev',
caption: 'this is a test image'
})
.then(function(photo) {
expect(photo.get('ImageableId')).to.equal(10);
expect(photo.get('ImageableType')).to.equal('sites');
expect(photo.get('url')).to.equal('http://image.dev');
});
});

@@ -183,2 +197,2 @@

};
};

@@ -182,2 +182,34 @@ var Promise = global.testPromise;

knex('thumbnails').insert([{
caption: 'Lorem ipsum Quis Ut eu nostrud ea sint aute non aliqua ut ullamco cupidatat exercitation nisi nisi.',
url: 'https://www.google.com/images/srpr/logo4w.png',
ImageableId: 1,
ImageableType: 'authors'
}, {
caption: 'Lorem ipsum Quis Ut eu nostrud ea sint aute non aliqua ut ullamco cupidatat exercitation nisi nisi.',
url: 'https://www.google.com/images/srpr/logo4w.png',
ImageableId: 2,
ImageableType: 'authors'
}, {
caption: 'Lorem ipsum Quis Ut eu nostrud ea sint aute non aliqua ut ullamco cupidatat exercitation nisi nisi.',
url: 'https://www.google.com/images/srpr/logo4w.png',
ImageableId: 1,
ImageableType: 'sites'
}, {
caption: 'Lorem ipsum Quis Ut eu nostrud ea sint aute non aliqua ut ullamco cupidatat exercitation nisi nisi.',
url: 'https://www.google.com/images/srpr/logo4w.png',
ImageableId: 1,
ImageableType: 'sites'
}, {
caption: 'Lorem ipsum Quis Ut eu nostrud ea sint aute non aliqua ut ullamco cupidatat exercitation nisi nisi.',
url: 'https://www.google.com/images/srpr/logo4w.png',
ImageableId: 2,
ImageableType: 'sites'
}, {
caption: 'Lorem ipsum Quis Ut eu nostrud ea sint aute non aliqua ut ullamco cupidatat exercitation nisi nisi.',
url: 'https://www.google.com/images/srpr/logo4w.png',
ImageableId: 2,
ImageableType: 'sites'
}]),
knex('users').insert({uid: 1, username: 'root'}),

@@ -219,2 +251,2 @@

};
};

@@ -10,3 +10,3 @@ var _ = require('lodash');

'Customer', 'Settings', 'hostnames', 'instances', 'uuid_test',
'parsed_users', 'tokens'
'parsed_users', 'tokens', 'thumbnails'
];

@@ -107,2 +107,13 @@

})
/* The following table is for testing non-standard morphTo column name
* specification. The breaking of naming convention is intentional.
* Changing it back to snake_case will break the tests!
*/
.createTable('thumbnails', function(table) {
table.increments('id');
table.string('url');
table.string('caption');
table.integer('ImageableId').notNullable();
table.string('ImageableType');
})
.createTable('Customer', function(table) {

@@ -142,2 +153,2 @@ table.increments('id');

};
};

@@ -54,2 +54,5 @@ // All Models & Collections Used in the Tests

},
thumbnails: function() {
return this.morphMany(Thumbnail, 'imageable', ["ImageableType", "ImageableId"]);
},
blogs: function() {

@@ -93,2 +96,5 @@ return this.hasMany(Blog);

},
thumbnail: function() {
return this.morphOne(Thumbnail, 'imageable', ["ImageableType", "ImageableId"]);
},
posts: function() {

@@ -218,2 +224,9 @@ return this.belongsToMany(Post);

var Thumbnail = Bookshelf.Model.extend({
tableName: 'thumbnails',
imageable: function() {
return this.morphTo('imageable', ["ImageableType", "ImageableId"], Site, Author);
}
});
// A PhotoParsed appends "_parsed" to each field name on fetch

@@ -299,2 +312,3 @@ // and removes "_parsed" when formatted

PhotoParsed: PhotoParsed,
Thumbnail: Thumbnail,
Info: Info,

@@ -301,0 +315,0 @@ Customer: Customer,

@@ -283,3 +283,3 @@ var _ = require('lodash');

model.on('fetching', function() {
throw new Error("This failed");
throw new Error('This failed');
});

@@ -596,2 +596,14 @@ return expect(model.fetch()).to.be.rejected;

it('sets created_at when {method: "insert"} is passed', function() {
var m = new bookshelf.Model(null, {hasTimestamps: true});
m.sync = function() {
equal(this.id, 1);
equal(this.get('item'), 'test');
equal(_.isDate(this.get('created_at')), true);
equal(_.isDate(this.get('updated_at')), true);
return stubSync;
};
return m.save({id: 1, item: 'test'}, {method: 'insert'});
});
it('will accept a falsy value as an option for created and ignore it', function() {

@@ -740,4 +752,29 @@ var m = new bookshelf.Model(null, {hasTimestamps: ['createdAt', null]});

describe('model.once', function() {
var Post = Models.Post;
it('event.once return a promise', function() {
var p = new Post({id: 1});
p.once('event', function() {
return Promise.resolve(1);
});
var promise = p.triggerThen('event');
equal(promise instanceof Promise, true);
promise.then(function(result) {
equal(result, 1);
});
return promise;
});
});
});
};

@@ -35,2 +35,3 @@ var _ = require('lodash');

var Role = Models.Role;
var Thumbnail = Models.Thumbnail;
var Photo = Models.Photo;

@@ -203,2 +204,30 @@ var PhotoParsed = Models.PhotoParsed;

it('has an attaching event, which will fail if an error is thrown', function(){
var site1 = new Site({id: 1});
var admin1 = new Admin({username: 'syncable', password: 'test'});
return admin1.save().then(function() {
site1.related('admins').on('attaching', function() {
throw new Error('This failed');
});
expect(site1.related('admins').attach(admin1)).to.be.rejected;
});
});
it('has an detaching event, which will fail if an error is thrown', function(){
var site1 = new Site({id: 1});
var admin1 = new Admin({username: 'syncable', password: 'test'});
return admin1.save().then(function() {
site1.related('admins').on('detaching', function() {
throw new Error('This failed');
});
return site1.related('admins').attach(admin1);
}).then(function() {
expect(site1.related('admins').detach(admin1)).to.be.rejected;
});
});
it('provides "attach" for creating or attaching records', function() {

@@ -215,5 +244,18 @@

admin1_id = admin1.id;
return Promise.all([
site1.related('admins').attach([admin1, admin2]),
site2.related('admins').attach(admin2)
site2.related('admins').attach(admin2),
site1.related('admins').on('attached', function(c) {
return c.fetch()
.then(function(c) {
equal(c.length, 2);
});
}),
site2.related('admins').on('attached', function(c) {
return c.fetch()
.then(function(c) {
equal(c.length, 1);
});
})
]);

@@ -248,11 +290,17 @@ })

expect(admins1).to.have.length(1);
return c.fetch();
}).then(function(c) {
equal(c.length, 1);
}),
admins2.detach().then(function(c) {
expect(admins2).to.have.length(0);
return c.fetch();
}).then(function(c) {
equal(c.length, 0);
}),
admins1.on('detached', function(c) {
return c.fetch()
.then(function(c) {
equal(c.length, 1);
});
}),
admins2.on('detached', function(c) {
return c.fetch()
.then(function(c) {
equal(c.length, 0);
});
})

@@ -276,3 +324,15 @@ ]);

site1.related('admins').attach([admin1, admin2]),
site2.related('admins').attach(admin2)
site2.related('admins').attach(admin2),
site1.related('admins').on('attached', function(c) {
return c.fetch()
.then(function(c) {
equal(c.length, 2);
});
}),
site2.related('admins').on('attached', function(c) {
return c.fetch()
.then(function(c) {
equal(c.length, 1);
});
})
]);

@@ -307,11 +367,17 @@ })

expect(admins1).to.have.length(1);
return c.fetch();
}).then(function(c) {
equal(c.length, 1);
}),
admins2.detach().then(function(c) {
expect(admins2).to.have.length(0);
return c.fetch();
}).then(function(c) {
equal(c.length, 0);
}),
admins1.on('detached', function(c) {
return c.fetch()
.then(function(c) {
equal(c.length, 1);
});
}),
admins2.on('detached', function(c) {
return c.fetch()
.then(function(c) {
equal(c.length, 0);
});
})

@@ -431,2 +497,10 @@ ]);

it('has no side effects for morphTo (imageable "authors", PhotoParsed)', function() {
var photoParsed = new PhotoParsed({imageable_id_parsed: 1, imageable_type_parsed: 'authors'})
return photoParsed.imageableParsed().fetch()
.then( function() {
return photoParsed.fetch()
}).then(checkTest(this));
});
it('handles morphTo (imageable "sites")', function() {

@@ -450,2 +524,40 @@ return new Photo({imageable_id: 1, imageable_type: 'sites'})

it('handles morphOne with custom columnNames (thumbnail)', function() {
return new Author({id: 1})
.thumbnail()
.fetch()
.tap(checkTest(this));
});
it('handles morphMany with custom columnNames (thumbnail)', function() {
return new Site({id: 1})
.thumbnails()
.fetch().tap(checkTest(this));
});
it('handles morphTo with custom columnNames (imageable "authors")', function() {
return new Thumbnail({ImageableId: 1, ImageableType: 'authors'})
.imageable()
.fetch().tap(checkTest(this));
});
it('handles morphTo with custom columnNames (imageable "sites")', function() {
return new Thumbnail({ImageableId: 1, ImageableType: 'sites'})
.imageable()
.fetch().tap(checkTest(this));
});
it('eager loads morphMany with custom columnNames (sites -> thumbnails)', function() {
return new Site().fetchAll({withRelated: ['thumbnails']}).tap(checkTest(this));
});
it('eager loads morphTo with custom columnNames (thumbnails -> imageable)', function() {
return Thumbnail.fetchAll({withRelated: ['imageable']}).tap(checkTest(this));
});
it('eager loads beyond the morphTo with custom columnNames, where possible', function() {
return Thumbnail.fetchAll({withRelated: ['imageable.authors']}).tap(checkTest(this));
});
});

@@ -452,0 +564,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

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