📚 Bucket DB

API Reference

This document provides a comprehensive reference for the core programmatic API of BucketDB.

Instantiation

BucketDb(options)

Factory function that creates a fully-initialized BucketDB instance.

Arguments:

  • options (Object): Configuration options.
  • dbPrefix (String): The root prefix for all data in this database.
  • nodeId (Number): A unique identifier for the current node (0-255). Used for Timesharing.
  • driver (Object, Optional): An explicit instance of a custom StorageDriver (e.g., MemoryDriver). Defaults to S3Driver if BUCKETDB_S3_BUCKET is present in the environment.
  • logLevel (String, Optional): One of 'debug', 'info', 'warn', 'error', 'silent'. Defaults to 'info'. Setting to 'silent' will mute all logs.
  • logger (Object, Optional): A custom logger instance (e.g., Pino or Winston) implementing .debug(), .info(), .warn(), and .error() methods.
  • writeForwardInterval (Number, Optional): The time window in milliseconds between timesharing checks. Defaults to 5000.
  • blockSizeBytes (Number, Optional): Block size for data blocks. Defaults to 65536.
  • maxMemoryBytes (Number, Optional): The maximum amount of memory the internal SplitPool orchestrator is allowed to use. Defaults to 104857600 (100MB).
  • cacheDriver (Object, Optional): A custom cache driver for caching S3 blocks. Defaults to an internal in-memory driver.
  • cacheBlockSize (Number, Optional): The estimated block size used by the SplitPool. Defaults to 65536.

Returns: A Database instance object.

Lifecycle Methods

Once an instance is created, you must explicitly manage its lifecycle to start and stop internal background processes (such as the write-forward service).

  • db.start(): Asynchronously initializes the database instance, including starting background daemons. This must be called before performing any database operations.
  • db.stop(): Asynchronously shuts down the database instance, ensuring all background processes are cleanly terminated and resources are released.

Example:

const { BucketDb } = require('bucket-db');
const { MemoryDriver } = require('bucket-db/lib/storage');

const db = BucketDb({
  dbPrefix: 'prod_db',
  nodeId: 0,
  driver: MemoryDriver() // Override S3 default for local dev
});

Database Methods

Once instantiated, the Database instance exposes the following methods:

db.registerSchema(schemaDef)

Registers a schema defining the structure and indexing of a specific table.

Arguments:

  • schemaDef (Object): The schema definition.
  • name (String): The table name.
  • version (Number): The schema version integer.
  • fields (Object): Record mapping field names to configuration objects ({ typeId, maxLength }).
  • primaryKey (String): The name of the field to use as the primary key.
  • indexes (Array<String>, Optional): Array of field names to create B+Tree indexes for.

Returns: undefined (Synchronous)

Example:

db.registerSchema({
  name: 'users',
  version: 1,
  fields: {
    id: { typeId: 10, maxLength: 36 }, // varchar
    email: { typeId: 10, maxLength: 255 }, // varchar
    age: { typeId: 1 } // uint8
  },
  primaryKey: 'id',
  indexes: ['email']
});

db.setTargetSchemaVersion(tableName, version)

Queues a zero-downtime schema migration. The schema versioning daemon will begin moving data in the background from older versions to the target version using a Blue/Green Storage Daemon.

Arguments:

  • tableName (String): The name of the table to migrate.
  • version (Number): The target schema version integer.

Returns: A Promise that resolves when the target state has been registered in Block 0.

db.registerFunction(name, fn, version)

Registers a synchronous JavaScript function that can be executed directly by the query engine. The function receives the fully deserialized row object as its only argument.

Constraints: Functions must be fully synchronous, pure, and have no side effects (no network calls, no file I/O).

Arguments:

  • name (String): The reference name for queries.
  • fn (Function): The JavaScript function (row) => any.
  • version (Number, Optional): Function version.

Returns: undefined (Synchronous)

Example:

db.registerFunction('isAdult', (row) => row.age >= 18);

db.registerTrigger(tableName, operation, handler)

Registers an asynchronous trigger that fires during batch mutations. See Triggers for detailed examples and blob handling instructions.

Arguments:

  • tableName (String): The name of the table to attach the trigger to.
  • operation (String): One of 'insert', 'update', 'delete', or '*'.
  • handler (Function): An async function (row, batch, dbApi, operation) => void.

Returns: undefined (Synchronous)

db.batch()

Creates a root transaction batch for performing write operations (insert, update, delete). Write-forward logic dictates that operations added to a batch are accumulated locally until flushed, at which point they are committed atomically to the distributed log.

Returns: A Batch instance.

db.query(tableName)

Initiates a read query against a table.

Arguments:

  • tableName (String): The name of the table to query.

Returns: A chainable QueryBuilder instance.

db.gc()

Performs a garbage collection sweep. It compares the live block pointers in Block 0 against physical keys to identify and delete orphaned data blocks and deleted blobs (_deleted_blobs). Uses Time-Range bounds to prevent deleting active Snapshots.

Returns: A Promise resolving to { deletedCount }.

db.Blob(buffer)

Wraps a Buffer to be intercepted as a Managed Blob during batch operations.

Arguments:

  • buffer (Buffer): The binary buffer payload.

Returns: A wrapper object to be passed to schema fields of typeId: 11.

db.getBlob(reference)

Retrieves a Managed Blob using its UUID reference. Useful when reading a blob field from a query result or inside a trigger.

Arguments:

  • reference (String): The UUID string of the blob.

Returns: A BlobReference object containing:

  • reference: The UUID string.
  • getBuffer(start, end): Returns a Promise resolving to the binary Buffer.
  • getString(start, end, encoding): Returns a Promise resolving to a String.
  • getDownloadUrl({ expiresIn }): Returns a Promise resolving to a presigned download URL (if supported by the driver).

Batch Methods

A Batch coordinates atomic writes.

batch.insert(table, doc)

Arguments:

  • table (String): The table name.
  • doc (Object): The JavaScript object to insert. Must contain the primary key.

batch.update(table, doc)

Arguments:

  • table (String): The table name.
  • doc (Object): The partial or full object to update. Must contain the primary key.

batch.delete(table, pkValue)

Arguments:

  • table (String): The table name.
  • pkValue (Any): The primary key value to logically delete.

batch.subBatch()

Creates a nested sub-batch. Calling flush() on a sub-batch merges its operations into the parent batch rather than committing to the driver.

Returns: A new Batch instance linked to the parent.

batch.flush()

Atomically commits all accumulated operations. If this is a root batch, it is written to the Write-Forward log in the storage driver and uploads any intercepted Managed Blobs.

Returns: A Promise resolving when the flush is complete.

Example:

const b = db.batch();
b.insert('users', { id: 'u1', email: 'alice@example.com', age: 30 });
b.update('users', { id: 'u2', age: 35 });
b.delete('users', 'u3');

await b.flush(); // Atomically commits the insert, update, and delete

QueryBuilder Methods

A fluent interface for constructing read queries.

queryBuilder.where(field, operator, value)

Adds a condition to the query. Valid operators: '=', '!=', '>', '>=', '<', '<=', 'IN'.

Note: If field matches the name of a registered function, the operator must be '=', and the function will be evaluated against each row.

queryBuilder.overlay(batch)

Overlays unflushed writes from an active memory Batch on top of the S3 state for Read-After-Write consistency.

queryBuilder.orderBy(field, direction)

Sorts the returned rows. Direction can be 'asc' or 'desc'.

queryBuilder.limit(n)

Limits the number of returned rows.

queryBuilder.offset(n)

Skips the first n rows.

queryBuilder.execute()

Executes the query, leveraging B+Tree indexes and the Mock Query Executor with reservoir sampling (_sample) to build an optimal execution plan dynamically.

Returns: A Promise resolving to an Array<Object> containing the matching rows.

Example:

const admins = await db.query('users')
  .where('age', '>', 21)
  .orderBy('age', 'desc')
  .limit(10)
  .execute();