Fork me on GitHub

Everything here is experimental, and the API is no exception, so expect things to change in future releases.

Index

Database

Alfred.open (path_to_database, [options, ] callback)

Opens a new or an existing database that resides in path_to_database.

  • path_to_database: directory where the database files (will) reside. Must already exist.
  • callback (err, db): invoked when there is an error or the database is open. Use db to access / create / remove key maps.
  • options:
    • meta_compact_interval: default average compact interval for the metadata key map, in miliseconds. Defaults to 1 hour (1000 * 60 * 60).
    • replication_master: true if this database is going to act as a replication master. Defaults to false.
    • replication_port: replication server port for this database. Defaults to 5293.
    • replication_max_file_size_kb: maximum file size for replication temporary files on master. Defaults to 10000 KBytes.
    • replication_max_keep_ms: maximum time a replication temporary file should be kept around. Defaults to 15 days.

Example:

var Alfred = require('alfred');
Alfred.open('path/to/database/dir', function(err, db) {
  if (err) { throw err; }
  // now I have the db object to do stuff
});

Model

database.define (modelName,options)

Define a new model.

  • modelName: the model name. Ex.: "User".
  • options: Optional. The same options as db.attach:
    • buffered: if true, writes are buffered (flushes are scheduled every second after the last one by default). If false, key_map.put only callsback when data is written to disk. Defaults to true.
    • flush_interval: This determines the frequency of flushes. A flush is scheduled flush_interval miliseconds after the last one finished. In miliseconds. Defaults to 1000 (1 second).
    • type: can be 'cached_key_map' or 'indexed_key_map'. Defaults to 'cached_key_map'. ('cached_key_map' is also indexed)
    • compact_interval: average compact interval, in miliseconds. Defaults to 1 hour (1000 * 60 * 60).
    • cache_slots: Maximum number of objects to cache (only valid if type is 'cached_key_map'). Defaults to 1000.

Returns: a model instance

Model.property (name, type, schema)

Defines a new property for the model

  • name: The name of the property. You can later get and set it.
  • type: Alfred.js currently supports: 'string', 'array','object', 'number', 'integer', 'null', 'boolean' and 'any'.
  • schema: An object containing the schema definition for the property. Valid properties are:
    • optional: true or false
    • enum: the value should contain an array with the possible values
    • validateWith: pass in a function that gets the document and returns true if the document id valid.
    • pattern: pass in a RegExp that the string should conform to (in case of a string).
    • minLength: define the minimum length (in case of a string).
    • maxLength: define the maximum length (in case of a string).
    • minimum: define the minimum value (in case of a number).
    • maximum: define the maximum value (in case of a number).
    • divisibleBy: should be divisible by (in case of a number)

Example:

var User = db.define('User');
User.property('name', 'string', {
  minLength: 3,
  maxLength: 10
});
User.property('address', 'string', {
  minLength: 3,
  maxLength: 10
});
User.property('age', Number, { required: true });
User.property('sex', 'string', {
  enum: ['f', 'm'],
  required: true,
});
User.property('married', 'boolean');
User.property('email', 'string', {
  pattern: /^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+[a-zA-Z0-9]{2,4}/,
  messages: {pattern: 'IINNVVAALLIID'}
});
User.property('role', 'string', {
  validateWith: function(role) {
    return role == 'admin';
  }
});

Model.index(name, fn, options)

Creates an index if the index is not already defined.
If an index with this name already exists the index is not modified.

  • name: the name of the index. You will use this name on finders.
  • fn (document): A function that gets a document and returns the indexable falue.
  • options: object containing or not the following properties:
    • ordered: true the index should be ordered. Defaults to true.

Example:

var User = db.define('User');
User.index('age', function(user) {
  return user.age;
});

Model.get(id, callback)

Get a document by ID.

Example:

var User = db.define('User', schema);
User.get(id, function(user) {
  console.log(user.inspect());
});

Model.new([properties])

Create a new (unsaved) document.

Example:

var User = db.define('User', schema);
var user = User.new({name: 'Pedro Teixeira', role: 'admin'});

Model.destroy(id, callback)

Destroy the document by id.

  • callback: called when the model is destroyed.

Example:

var User = db.define('User', schema);
var id = '123abc';
var user = User.destroy(id);

Model.find(spec)

Starts a finder. Implements the same chainable API as the KeyMap finder, but with documents instead of raw objects.

Example:

var User = db.define('User', schema);
User.find({age: {$gt: 18, $lte: 40}}).all(function(users) {
  console.log('Found ' + users.length + ' users');
}).or({sex: {$eq: 'f'}});

Document

document.save(callback)

Saves the document

  • callback ([validationErrors]): called if validation errors detected or when saved.

Example:

var User = db.define('User', schema);
var user = User.new({name: 'Pedro Teixeira', role: 'admin'});
user.save(function(calidationErrors) {
  if (errors) {
    throw new Exception('validation errors found.');
  }
  console.log('User saved');
});

document.atomic(key, valueCallback, doneCallback)

Fetches and locks the document, preventing concurrent updates. You must return the new value from valueCallback.

  • valueCallback (document): a callback invoked with the fetched document. You must return the document to update it. Return null or undefined if you don't wish to update it.
  • doneCallback (): Called after the document is saved.

document.destroy(callback)

Destroys the document

  • callback: called when the model is destroyed.

Example:

var User = db.define('User', schema);
var id = 'abc123';
var user = User.get(id);
user.destroy(function() {
  console.log('user with id ' + id + ' destroyed');
});

Events

Database events

You should listen for error events on the database like this:

var Alfred = require('alfred');
Alfred.open('path/to/database/dir', function(err, db) {
  if (err) { throw err; }
  db.on('error', function(err) {
     console.log('OMG, an error occurred!: ' + err.message);
  });
});

Document events

You can bind for events on documents. These are the supported events:

"beforeValidate" (document)

Called after the "save" is called on the API, but before any validation is done.

"afterValidate" (document)

Called after validation is done.

"beforeSave" (document)

Called before saving is done.

"afterSave" (document)

Called after saving is done.

Example:

var User = db.define('User');
User.on('beforeSave', function(user) {
  console.log('going to save user ' + user.inspect());
});