Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
CouchDB library for Node.js with advanced entity and cache support
Features:
import SmartDb from 'smartdb';
let db = SmartDb({
databases: [
{
url: 'http://localhost:5984/userdb',
entities: {
user: { }
}
},
{
url: 'http://localhost:5984/blogdb',
entities: {
blogPost: { },
blogComment: { }
}
}
],
// This is optional. It enables you to map from document to entity
mapDocToEntity(doc) {
let type = doc.type;
if (type === 'user') return new User(doc);
if (type === 'blogPost') return new BlogPost(doc);
if (type === 'blogComment') return new BlogComment(doc);
throw new Error('Unsupported entity type: ' + type);
}
});
// Saving a user
let johnDoe = new User({
fullName: 'John Doe',
email: 'john.doe@mail.com'
});
await db.save(johnDoe);
// johnDoe._id and johnDoe._rev is automatically set by save()
// Getting a blog post by ID
let blogPost = await db.get('blogPost', blogPostId);
// The blogPost will be an instantiated entity BlogPost
Get entity by type and ID. Returns promise to entity. If no document found, will return an error.
Same as db.get() but return null instead of error when no document found.
Will also return null if id
is null/undefined, which can be useful in some situations to keep code compact.
Saves an unsaved entity. Returns promise. The properties _id and _rev will automatically be set on the given entity after save complete.
Updates an existing entity. Returns promise. Must have _id and _rev defined. Will automatically set _rev on the given entity after update complete.
Change specific properties on an entity.
let { rev } = await db.merge('user', userId, { email: 'a.new@email.com' });
Removes an entity by type and ID. Returns promise
Calls a view and returns entities based on the documents in the response.
Returns promise of entities.
Will by default use a design document with the same name as type
. However, this is configurable by using the rewriteView
option.
You do not need to pass include_docs: true
to the args, it is automatically set.
let users = await db.view('user', 'byDepartment', { key: '<DEPT_ID>' });
// If you are using entity mappings, the returned users are real entities
Calls a view and returns a promise with the raw JSON rows from CouchDB.
Useful when you want to use the key and value properties.
Will by default use a design document with the same name as type
. However, this is configurable by using the rewriteView
option.
Calls a list function and returns the raw result from CouchDB. Returns promise of body.
These are the options you can give when creating the smartdb instance:
An array of databases where you define where entities are located.
You can also set cache settings per entity.
Define one array item for each database where you have entites.
In the database url
you set the full path to the database. That includes protocol (http or https),
optional authentication, hostname and database name.
{
databases: [
{
url: 'http://username:password@somehost:5984/blog',
entities: {
blogPost: {
cacheMaxAge: 5 * 60 * 1000, // Cache for 5 minutes
cacheMaxSize: 100 // Have 100 items at most in the cache
},
blogComment: { } // Will not be cached
}
}
]
}
The property on the entity that identies the entity type. Default is 'type'
.
{
type: 'entityType'
}
Maps a document to an entity. This is useful if you want to wrap the document and add methods to interact with the data. The default is to just returns the JSON document retrieved from the database.
{
mapDocToEntity(doc) {
let map = {
user: User,
blogPost: BlogPost,
blogComment: BlogComment
};
let Constructor = map[doc.type];
return new Constructor(doc);
}
}
Maps an entity to the document to save to the database. The default is to just use JSON.stringify() on the entity.
In some cases you might want to strip it of some properties or change something before saving, then define a function here.
One way might be to have a convention to have a toDoc()
method on entities.
{
mapEntityToDoc(entity) {
if (entity.toDoc) {
return entity.toDoc();
}
return entity;
}
}
By default, smartdb uses an in-memory cache inside the same Node.js process. This works well when you only have a single Node.js process that use your CouchDB database.
If you have multiple Node.js processes the recommendation is to use the Redis cache provider that is available for smartdb.
import RedisCacheProvider from 'smartdb-rediscacheprovider'
//...
{
cacheProvider: RedisCacheProvider({ /* cache provider options */ })
}
You might want to validate your entities before sending them to CouchDB for saving. The signature of this function is
(entity, callback)
. If you return an error in the callback smartdb will not send the request to CouchDB but
instead return an error.
{
validate(entity, callback) {
if (entity.validate) {
entity.validate(callback);
}
else {
callback();
}
}
}
The default when using db.view('user', 'byDepartment', ...)
is to use the view byDepartment
in the design document user
. But you might want a different strategy. If you use this option,
define a function that given (type,viewName)
should return an array
with the following format [designDocumentName, viewName]
Personally, I use a single view per design document to be able to add a view without causing re-indexing of many other views.
{
rewriteView(type, viewName) {
return [type + '-' + viewName, 'fn'];
}
}
This means that db.view('user', 'byDepartment', ...)
would go to the
design document user-byDepartment
and the view named fn
.
For get
and merge
if entity does not exist, gives the following error:
{
name: 'EntityMissingError',
message: 'Entity is missing',
scope: 'smartdb',
entityId: 'XYZ123',
entityType: 'user'
}
For save
, merge
, remove
and update
if you get a conflict, gives the following error:
{
name: 'EntityConflictError',
message: 'Conflict when trying to persist entity change',
scope: 'smartdb',
entityId: 'XYZ123',
entityType: 'user'
request: {
method: 'PUT',
headers: { ... },
uri: 'http://...',
body: '{ ... }'
},
response: {
statusCode: 409,
headers: { ... }
}
}
(The MIT License)
Copyright (c) 2013-2022 Calle Arnesten
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
FAQs
CouchDB library with advanced entity and cache support
We found that smartdb demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.