nitrog7/node-orientdb — pull request #15 by phpnode (2014-03-14 15:54:26+00:00)
Title: WIP - Total Refactor

> note: work in progress - **do not merge**

This is a near total rewrite / refactor of the library. It aims to be faster, easier to maintain and to provide a nicer API, inspired by [nano](https://github.com/dscape/nano) but slightly different because orientdb has slightly different semantics to couch. The test suite has been replaced with one using [mocha](http://visionmedia.github.io/mocha/), run the tests using `npm test` as normal.

It is incomplete, I'm opening the PR now to get some feedback.

## Todo

- [ ] implement transactions
- [ ] implement `db.vertex` and `db.edge` api wrappers
- [ ] implement `db-freeze` and `db-release` commands
- [ ] add some examples
- [ ] add a legacy wrapper to maintain backwards compatibility with earlier versions of the lib
- [ ] properly resolve references when retrieving embedded records
- [ ] fix the *minor* detail that the tests pass but orientdb silently closes the connection when running the examples :smile:.

## API Changes
There are many, many breaking changes to the public API. However, it should be relatively straightforward to create a shim for people using the older version. I've not started this yet, it depends on demand.

### Library entry point is now a function

```js
var OrientDB = require('node-orientdb');

var server = OrientDB({
"host": "localhost",
"port": 2424,
"username": "root",
"password": "3BA5DB89CC6206DBF835B36B70FF8A0EDCEFA617A229F0D44D1D726ABA04216A"
});
```

### Database instances are accessed via `server.use()`

```js
var db = server.use('GratefulDeadConcerts');
```

### Connection established on demand.

Rather than explicitly having to call `server.connect()` and `db.open()`, the library keeps track of its state and calls these when required. E.g. this should work:

```js
var server = OrientDB(config);
server.use('GratefulDeadConcerts').class.list().then(console.log.bind(console));
```

### Related methods are grouped together under 'namespaces'

```js
db.record.create({
'@class': 'OUser',
name: 'Charles',
password: 'notmyrealpassword',
status: 'ACTIVE'
}); // promise to create a record

db.record.get('#1:1') // promise to load a record

db.record.update({
'@rid': '#1:1',
key: 'value'
}); // promise to update a record.

db.record.delete('#1:1'); // promise to delete a record

db.class.list(); // promise to list the classes on the db
db.class.create('TestClass'); // promise to create a class
db.class.create('TestChildClass', 'TestClass'); // promise to create a child class
db.class.get('TestClass'); // promise to retrieve a class

db.cluster.list(); // promise to list the clusters
db.cluster.get('ouser'); // promise to get the named cluster

// etc, not an exhaustive list

```

## Internal Changes

### 'DSL' for defining operations
This makes it easier to maintain operations (previously called commands) and keep up with changes to the orientdb protocol. It also separates the declaration of read / write commands from the execution of those commands, which allows us to do some nice optimisations e.g. avoiding a *lot* of buffer allocations.
For example, from `config-get.js`:
```js
{
...,
writer: function () {
this
.writeByte(this.opCode)
.writeInt(this.data.sessionId || -1)
.writeString(this.data.key);
},
reader: function () {
this
.readStatus('status')
.readString('value');
}
}
```

### Multiple databases per socket.
It's now possible to use one connection for multiple databases, e.g.

```js
var foo = server.use('foo'),
bar = server.use('bar');

foo.class.list().then(console.log.bind(console, 'Foo Classes'));
bar.class.list().then(console.log.bind(console, 'Bar Classes'));
```

### Promises Everywhere
No more `.callback`, everything is a bluebird promise or deferred object.

### Custom Error Classes
The lib now exposes a number of custom error classes, making it possible to catch certain types of error, for example:

```js
var errors = OrientDB.errors;

db.record.create(myrecord)
.then(console.log.bind(console, 'Created Record'))
.catch(errors.Request, function (err) {
console.log('The server rejected the request');
})
.catch(errors.Operation, function (err) {
console.log('The record is malformed and cannot be sent to the server');
})
.catch(errors.Protocol, function (err) {
console.log('The server sent a malformed or unsupported response');
})
.catch(errors.Connection, function (err) {
console.log('The server disconnected or the connection could not be established.');
});
```