
Security News
gem.coop Tests Dependency Cooldowns as Package Ecosystems Move to Slow Down Attacks
gem.coop is testing registry-level dependency cooldowns to limit exposure during the brief window when malicious gems are most likely to spread.
An on disk database that indexes everything for fast querying.
npm install --save doubledb
import createDoubledb from 'doubledb';
const doubledb = await createDoubledb('./data');
// Insert a document
await doubledb.insert({
id: undefined, // defaults to uuid, must be unique
firstName: 'Joe',
lastName: 'Bloggs',
stats: {
wins: 10,
loses: 5
},
skills: ['cooking', 'running']
});
// Read operations
await doubledb.read(record.id);
await doubledb.find('firstName', 'Joe');
await doubledb.find('stats.wins', 10);
await doubledb.find('skills', 'cooking');
await doubledb.find('firstName', v => v.startsWith('J'), { skip: 20, gt: 'J', lt: 'K' });
await doubledb.filter('firstName', 'Joe');
await doubledb.filter('firstName', v => v.startsWith('J'));
await doubledb.filter('firstName', v => v.startsWith('J'), { limit: 10, skip: 20, gt: 'J', lt: 'K' });
// Update operations
await doubledb.upsert(record.id, { firstName: 'Joe', lastName: 'Bloggs' });
await doubledb.replace(record.id, { firstName: 'Joe', lastName: 'Bloggs' });
await doubledb.patch(record.id, { firstName: 'Bob' });
// Delete operation
await doubledb.remove(record.id);
// Batch operations
await doubledb.batchInsert([
{ firstName: 'Alice', lastName: 'Smith' },
{ firstName: 'Bob', lastName: 'Johnson' },
{ firstName: 'Charlie', lastName: 'Brown' }
]);
// Advanced querying
const users = await doubledb.query({
status: 'active',
age: { $gte: 18 }
}, {
limit: 10,
offset: 0,
sort: { lastName: 1 }
});
// Count documents
const totalUsers = await doubledb.count({ status: 'active' });
.read(id)Get a single record by its .id property.
If a record is found, the whole record will be returned.
If no record is found, undefined will be returned.
.find(field, value, { skip })Quickly find a single record by any field (use.dot.notation.for.nested.properties) and its exact value.
If multiple records exist, a skip option can be provided to ignore the first number of finds.
If a record is found, the whole record will be returned.
If no record is found, undefined will be returned.
.find(field, matcherFunction: (value: string) => boolean), { limit, skip, gt, lt, gte, lte })Slow find a single record by any field and test against a matcherFunction.
If multiple records exist:
skip option can be provided to ignore the first number of finds.limit option can be provided to stop after number of finds.Find using a matcherFunction will work without a gt and lt, but the indexing will be pretty useless, as it will need to scan every single record.
You should provide a gt and/or lt to let the indexer know where to begin/end.
For example:
// Will scan every record (slow)
doubledb.find('firstName', v => v.startsWith('Jo'))
// Better - starts from 'Jo'
doubledb.find('firstName', v => v.startsWith('Jo'), { gt: 'Jo' })
// Best - specify both start and end range
doubledb.find('firstName', v => v.startsWith('Jo'), { gt: 'Jo', lt: 'K' })
// More examples
doubledb.find('favouriteNumber', v => v > 5 && v < 10, { gt: 5, lt: 10 })
doubledb.find('firstName', v => ['Dave', 'Peter'].includes(v), { gt: 'Dave', lte: 'Peter' })
.filter(field, matcherFunction: (value: string) => boolean), { limit, skip, gt, lt, gte, lte })This works the exact same as .find but will return an array of all matching records instead of just the first match.
If records are found, an array will be returned containing every complete found record. If no records are found, an empty array will be returned.
.replace(key, object)Completely replace a key with a new object, losing all previous fields in the record.
.patch(key, object)Merge the new object with the existing record.
Example:
// Existing record
{
"id": "1",
"firstName": "Joe",
"lastName": "Bloggs"
}
// After running:
await doubledb.patch('1', { fullName: 'Joe Bloggs' })
// Result:
{
"id": "1",
"firstName": "Joe",
"lastName": "Bloggs",
"fullName": "Joe Bloggs"
}
.remove(key)Remove a record by its id.
.query(queryObject, options)Query the database using a complex query object with support for multiple operators and conditions.
Example:
const records = await doubledb.query({
location: 'London',
age: { $gte: 18 },
$or: [
{ status: 'active' },
{ status: 'pending' }
]
}, {
limit: 10,
offset: 0,
sort: { lastName: 1 },
project: { firstName: 1, lastName: 1 }
});
$eq: Equal to a value$ne: Not equal to a value$gt: Greater than a value$gte: Greater than or equal to a value$lt: Less than a value$lte: Less than or equal to a value$in: Value is in the provided array$nin: Value is not in the provided array$all: Array contains all the provided values$exists: Field exists or does not exist$not: Negates the condition$sw: String starts with value.count(queryObject?)Count the number of documents matching the given query criteria. If no query object is provided, returns the total number of documents in the database.
Example:
// Count total documents
const total = await doubledb.count();
// Count documents matching a simple field value
const londonCount = await doubledb.count({ location: 'London' });
// Count using operators
const activeUsersCount = await doubledb.count({
status: 'active',
age: { $gte: 18 }
});
// Count with $or conditions
const count = await doubledb.count({
$or: [
{ category: 'A' },
{ category: 'B' }
]
});
The count method supports all the same operators as the query method. For optimal performance, it uses internal counters for simple queries, while complex queries may require scanning index entries.
.batchInsert(documents)Insert multiple documents at once for better performance.
Example:
await doubledb.batchInsert([
{ firstName: 'Alice', lastName: 'Smith' },
{ firstName: 'Bob', lastName: 'Johnson' },
{ firstName: 'Charlie', lastName: 'Brown' }
]);
If the documents are successfully inserted, an array of the inserted documents will be returned. If the documents array is empty, an error will be thrown.
FAQs
An on disk database that indexes everything for fast querying.
The npm package doubledb receives a total of 14 weekly downloads. As such, doubledb popularity was classified as not popular.
We found that doubledb demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer 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.

Security News
gem.coop is testing registry-level dependency cooldowns to limit exposure during the brief window when malicious gems are most likely to spread.

Security News
Following multiple malicious extension incidents, Open VSX outlines new safeguards designed to catch risky uploads earlier.

Research
/Security News
Threat actors compromised four oorzc Open VSX extensions with more than 22,000 downloads, pushing malicious versions that install a staged loader, evade Russian-locale systems, pull C2 from Solana memos, and steal macOS credentials and wallets.