SSB-DB2
SSB-DB2 is a new database for secure-scuttlebutt, designed as a replacement for the older `ssb-db`. Currently at version 8.1.0, it offers significant architectural changes aimed at improving performance and flexibility. Key differentiators include using `bipf` for data storage, replacing `flume` with `jitdb` for specialized indexes, supporting browser environments via `ssb-browser-core`, and enabling efficient partial replication. It has expanded capabilities beyond `ssb-db`, featuring deletion and compaction, support for customizable feed and encryption formats (defaulting to `ssb-classic`), and a powerful query language based on composable JavaScript functions. SSB-DB2 operates as a `secret-stack` plugin, registering within the `db` namespace, and is optimized for modern Node.js environments (>=16).
Common errors
-
Error: method:db.create is not in list of allowed methods.
cause The `ssb-db2` plugin was not correctly registered with the `secret-stack` instance.fixEnsure `sbot.use(require('ssb-db2'))` is called on your `secret-stack` instance before `sbot.call(null, config)`. -
TypeError: Cannot read properties of undefined (reading 'query')
cause The `db` namespace, where `ssb-db2` registers its API, is undefined, typically because `ssb-db2` failed to load or `secret-stack` was not properly initialized.fixVerify that `secret-stack` is initialized with `caps` and that `ssb-db2` is correctly added as a plugin before attempting to access `sbot.db`. -
ReferenceError: require is not defined
cause Attempting to use CommonJS `require` syntax in an ESM module context (e.g., a file with `"type": "module"` in `package.json` or a `.mjs` file).fixConvert your imports to ESM syntax (e.g., `import SecretStack from 'secret-stack'`) or ensure your files are treated as CommonJS modules. -
Error: Unknown operator 'foo'
cause Attempting to use a non-existent or misspelled query operator, or trying to import operators from the wrong path.fixDouble-check the spelling of the operator. Ensure all query operators are imported specifically from `ssb-db2/operators`, e.g., `const { where, type } = require('ssb-db2/operators')`.
Warnings
- breaking SSB-DB2 is a replacement for `ssb-db` and is *not* 100% backwards compatible. It uses a different underlying log format (`bipf` instead of `flume`) and requires a migration process if you intend to query existing `ssb-db` data. Attempting to use write APIs on `ssb-db2` while an old log exists and is being migrated can lead to inconsistent states or 'forking feeds'.
- breaking SSB-DB2 explicitly requires Node.js version 16 or higher. Older Node.js versions are not supported and will likely result in runtime errors.
- gotcha Some advanced queries require additional LevelDB index plugins, as the default `jitdb` (Just-In-Time Database) indexing only covers basic functionality. Queries relying on specific data patterns not covered by the base index will not return expected results.
- gotcha SSB-DB2 registers itself in the `db` namespace of a `secret-stack` instance. If `ssb-db` (or another plugin also registering in `db`) is used concurrently without proper compatibility layers, it can lead to conflicts or unexpected behavior.
Install
-
npm install ssb-db2 -
yarn add ssb-db2 -
pnpm add ssb-db2
Imports
- SecretStack
const SecretStack = require('secret-stack')import SecretStack from 'secret-stack'
- ssb-db2
import { ssbdb2 } from 'ssb-db2'import ssbdb2 from 'ssb-db2'
- { where, and, type, author, toCallback }
const { where, and, type, author, toCallback } = require('ssb-db2')import { where, and, type, author, toCallback } from 'ssb-db2/operators'
Quickstart
const SecretStack = require('secret-stack')
const caps = require('ssb-caps')
const fs = require('fs')
const path = require('path')
const testPath = './temp-ssb-db2-quickstart'
// Ensure a clean state for the quickstart
if (fs.existsSync(testPath)) {
fs.rmSync(testPath, { recursive: true, force: true });
}
fs.mkdirSync(testPath, { recursive: true });
const sbot = SecretStack({ caps })
.use(require('ssb-db2'))
.call(null, { path: testPath })
sbot.db.create({ content: { type: 'post', text: 'hello from ssb-db2!' } }, (err, msg) => {
if (err) {
console.error('Error publishing message:', err);
sbot.close()
return;
}
console.log('Published message:', msg.value.content);
const { where, type, toCallback } = require('ssb-db2/operators');
sbot.db.query(
where(type('post')),
toCallback((err, msgs) => {
if (err) {
console.error('Error querying messages:', err);
} else {
console.log('Found ' + msgs.length + ' post messages:');
msgs.forEach(m => console.log('- ' + m.value.content.text));
}
sbot.close();
fs.rmSync(testPath, { recursive: true, force: true }); // Clean up
})
);
});