Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

thinky

Package Overview
Dependencies
Maintainers
1
Versions
129
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

thinky - npm Package Compare versions

Comparing version 0.1.0 to 0.1.1

test/thinky.js

4

lib/document.js

@@ -66,3 +66,7 @@ var eventEmitter = require('events').EventEmitter;

Document.prototype.update = function(newDoc) {
//TODO
}
var document = module.exports = exports = Document;

107

lib/index.js

@@ -14,19 +14,45 @@ /*!

this.models = {};
this.defaultSettings = {
host: 'localhost',
port: 28015,
db: 'test',
poolMax: 10,
poolMin: 1,
enforce: { type: true, missing: false, extra: false }
};
this.options = {};
};
Thinky.prototype.connect = function(options) {
var self = this;
if (!(options instanceof Object)) options = {}
this.host = options.host || 'localhost';
this.port = options.port || 28015;
this.db = options.db || 'test';
if (!(options instanceof Object)) {
options = {};
}
else if (options === null) {
options = {};
}
else if (Object.prototype.toString.call(options) === '[object Array]') {
options = {};
}
//TODO use this.setOptions and add checks
this.options = {
host: options.host || this.defaultSettings.host,
port: options.port || this.defaultSettings.port,
db: options.db || this.defaultSettings.db,
poolMax: options.poolMax || 10,
poolMin: options.poolMin || 1
poolMin: options.poolMin || 1,
enforce: this.options.enforce || this.defaultSettings.enforce
}
this.createPool();
//TODO add option for not using a pool
};
Thinky.prototype.createPool = function () {
var self = this;
this.pool = gpool.Pool({

@@ -36,5 +62,4 @@ name: 'rethinkdbPool',

r.connect({
host: self.host,
port: self.port,
db: self.db
host: self.options.host,
port: self.options.port
}, function(error, conn) {

@@ -47,4 +72,4 @@ return cb(error, conn);

},
max: self.poolMax,
min: self.poolMin,
max: self.options.poolMax,
min: self.options.poolMin,
idleTimeoutMillis: 30000,

@@ -57,3 +82,3 @@ log: function(what, level) {

})
};
}

@@ -63,11 +88,35 @@ Thinky.prototype.getOptions = function () {

};
Thinky.prototype.setOptions = function (options, overwrite) {
//TODO if we change poolMax or poolMin, we have to recreate a pool
if (overwrite) {
this.options = options;
Thinky.prototype.setOptions = function (options) {
shouldDrain = false;
for(var key in options) {
if ((key === 'host') || (key === 'port')) shouldDrain = true;
this.setOption(key, options[key], false);
}
if (shouldDrain === true) {
this.disconnect();
this.createPool();
}
return this.options;
};
Thinky.prototype.setOption = function (key, value, drainPool) {
drainPool = drainPool || true;
//TODO Update generic pool to be able to change the pool size.
if (key === 'enforce') {
this.options.enforce = this.checkEnforce(value, this.defaultSettings.enforce);
}
else {
for(var key in options) {
this.options[key] = options[key]
if (value === null) {
this.options[key] = this.defaultSettings[key];
}
else {
this.options[key] = value;
}
if (drainPool === true) {
if ((key === 'host') || (key === 'port')) {
this.disconnect();
this.createPool();
}
}
}

@@ -77,8 +126,20 @@ return this.options;

Thinky.prototype.checkEnforce = function(newValue, defaultValue) {
if (newValue === true) {
return {missing: true, extra: true, type: true}
}
else if (newValue === false) {
return {missing: false, extra: false, type: false}
}
else if ((newValue != null) && (typeof newValue === 'object')
&& (typeof settings.enforce.extra === 'boolean')
&& (typeof settings.enforce.type === 'boolean')
&& (typeof settings.enforce.missing === 'boolean')) {
return newValue
}
else {
return defaultValue
}
Thinky.prototype.setOption = function (key, value) {
//TODO if we change poolMax or poolMin, we have to recreate a pool
this.options[key] = value;
return this;
};
}

@@ -85,0 +146,0 @@ Thinky.prototype.getOption = function (key) {

var r = require('rethinkdb');
var Document = require('./document.js');
function Model(name, schema, settings, pool) {
function Model(name, schema, settings, thinky) {
settings = settings || {};

@@ -9,10 +9,16 @@

this.schema = schema;
this.settings = {};
this.settings.primaryKey = (settings.primaryKey)? settings.primaryKey: 'id';
this.settings.enforce = (settings.enforce)? settings.enforce: false;
this.settings.pool = pool;
this.checkEnforce = thinky.checkEnforce; // TODO fix ugliness
this.settings = {
primaryKey: settings.primaryKey || 'id',
enforce: this.checkEnforce(settings.enforce, thinky.options.enforce)
};
this.thinky = thinky;
this.pool = thinky.pool;
this.thinkyOptions = thinky.options
}
Model.compile = function(name, schema, settings, thinky) {
modelProto = new Model(name, schema, settings, thinky.pool);
modelProto = new Model(name, schema, settings, thinky);
function model(doc, docSettings) {

@@ -22,3 +28,3 @@ doc = doc || {};

docSettings = docSettings || {};
var enforce = (docSettings.enforce != null)? docSettings.enforce: modelProto.settings.enforce;
var enforce = modelProto.checkEnforce(docSettings.enforce, modelProto.settings.enforce);

@@ -47,4 +53,5 @@ result = {}

//TODO Let people default arrays/object
//TODO Implement maxLenght, minLenght
Model.prototype.createBasedOnSchema = function(result, doc, originalDoc, enforce, prefix, schema) {
var enforce = enforce || false;
var enforce = enforce; // Add another check here?
var prefix = prefix || '';

@@ -82,3 +89,3 @@

if (enforce) {
if (enforce.extra === true) {
// TODO Throw if doc has too many fields

@@ -96,3 +103,6 @@ }

}
else if (enforce) {
else if ((enforce.missing === true) && (doc[key] == null)) {
throw new Error("Value for "+prefix+"["+key+"] must be defined")
}
else if ((doc[key] != null) && (enforce.type === true)) {
throw new Error("Value for "+prefix+"["+key+"] must be a "+type.name)

@@ -110,3 +120,3 @@ }

result[key] = schema_key['default'](originalDoc);
if ((enforce) && (result[key] !== typeOf)) {
if ((enforce.type === true) && (typeof result[key] !== typeOf)) {
throw new Error("The default function did not return a "+type.name+" for "+prefix+"["+key+"]");

@@ -119,3 +129,6 @@ }

}
else if (enforce) {
else if ((enforce.missing === true) && (doc[key] == null)) {
throw new Error("Value for "+prefix+"["+key+"] must be defined")
}
else if ((doc[key] != null) && (enforce.type === true)) {
throw new Error("Value for "+prefix+"["+key+"] must be a "+type.name);

@@ -139,13 +152,5 @@ }

// Called on the model
Model.prototype.getSettings = function() {
return this.settings;
}
Model.prototype.getSettings2 = function() {
return this.settings;
}

@@ -156,16 +161,7 @@ Model.prototype.getPrimaryKey = function() {

// Called by the document
Model.prototype.getDocument = function() {
return this.__proto__;
}
Model.prototype.defineOnModel = function(name, fn) {
this.getModel()[name] = fn;
}
Model.prototype.save = function(callback) {
//TODO Implement replace
var self = this; // The document
var model = this.getModel();
model.getSettings().pool.acquire( function(error, connection) {
model.pool.acquire( function(error, connection) {
if (error) {

@@ -179,3 +175,4 @@ return callback(error, null);

var primaryKey = model.getPrimaryKey();
r.table(model.name).get(self[primaryKey]).update(self, {returnVals: true}).run(connection, function(error, result) {
//TODO remove the r.expr around self when the driver will be fixed regarding circular reference
r.db(model.thinkyOptions.db).table(model.name).get(self[primaryKey]).update(r.expr(self), {returnVals: true}).run(connection, function(error, result) {
if (error) {

@@ -191,3 +188,3 @@ if ((callback) && (typeof callback === 'function')) callback(error, null);;

if ((callback) && (typeof callback === 'function')) callback(error, self);
model.getSettings().pool.release(connection);
model.pool.release(connection);
self.emit('save', self, result.old_val);

@@ -199,3 +196,4 @@ }

else {
r.table(model.name).insert(self, {returnVals: true}).run(connection, function(error, result) {
//TODO remove the r.expr around self when the driver will be fixed regarding circular reference
r.db(model.thinkyOptions.db).table(model.name).insert(r.expr(self), {returnVals: true}).run(connection, function(error, result) {
if (error) {

@@ -212,6 +210,7 @@ if ((callback) && (typeof callback === 'function')) callback(error, null);

// We can release the connection because we get back an object
model.getSettings().pool.release(connection);
model.pool.release(connection);
self.emit('save', self, result.old_val);
}
});
}

@@ -225,3 +224,3 @@ });

var model = this.__proto__;
model.getSettings().pool.acquire( function(error, connection) {
model.pool.acquire( function(error, connection) {
if (error) {

@@ -231,7 +230,7 @@ return callback(error, null);

if (Object.prototype.toString.call(id) === '[object Array]') {
var table = r.table(model.name);
var table = r.db(model.thinkyOptions.db).table(model.name);
table.getAll.apply(table, id).run( connection, function(error, cursor) {
if (error) {
callback(error, null);
model.getSettings().pool.release(connection);
model.pool.release(connection);
}

@@ -242,3 +241,3 @@ else {

callback(error, null);
model.getSettings().pool.release(connection);
model.pool.release(connection);
}

@@ -253,3 +252,3 @@ else {

callback(null, docs);
model.getSettings().pool.release(connection);
model.pool.release(connection);
}

@@ -263,3 +262,3 @@ });

//TODO Handle type error
r.table(model.name).get(id).run( connection, function(error, result) {
r.db(model.thinkyOptions.db).table(model.name).get(id).run( connection, function(error, result) {
var doc = null;

@@ -270,3 +269,3 @@ if ((error == null) && (result != null)) {

callback(error, doc);
model.getSettings().pool.release(connection);
model.pool.release(connection);
});

@@ -280,10 +279,10 @@ }

var model = this.__proto__;
model.getSettings().pool.acquire( function(error, connection) {
model.pool.acquire( function(error, connection) {
if (error) {
return callback(error, null);
}
r.table(model.name).filter(filter).run( connection, function(error, cursor) {
r.db(model.thinkyOptions.db).table(model.name).filter(filter).run( connection, function(error, cursor) {
if (error) {
callback(error, null);
model.getSettings().pool.release(connection);
model.pool.release(connection);
}

@@ -294,3 +293,3 @@ else {

callback(error, null);
model.getSettings().pool.release(connection);
model.pool.release(connection);
}

@@ -305,3 +304,3 @@ else {

callback(null, docs);
model.getSettings().pool.release(connection);
model.pool.release(connection);
}

@@ -318,3 +317,19 @@ });

Model.prototype.count = function(callback) {
//TODO
var self = this;
var model = this.__proto__;
model.pool.acquire( function(error, connection) {
if (error) {
return callback(error, null);
}
r.db(model.thinkyOptions.db).table(model.name).count().run( connection, function(error, result) {
if (error) {
callback(error, null);
model.pool.release(connection);
}
else {
callback(null, result);
model.pool.release(connection);
}
});
});
}

@@ -321,0 +336,0 @@

{
"name": "thinky",
"version": "0.1.0",
"version": "0.1.1",
"description": "RethinkDB ORM for Node.js",

@@ -26,3 +26,6 @@ "main": "lib/index.js",

"url": "https://github.com/neumino/thinky/issues"
},
"dependencies":{
"generic-pool": ">= 2.0.3"
}
}

@@ -1,47 +0,261 @@

Thinky
====
# Thinky
JavaScript ORM for RethinkDB.
JavaScript ORM for RethinkDB.
_Note_: Alpha release
### Quick start
How to use
====
Simple case:
Install:
```
var thinky = require('lib/index.js');
npm install thinky
```
Use
```javascript
var thinky = require('thinky');
thinky.connect({});
var Cat = thinky.createModel('Cat', {name: String});
// Create a model
var Cat = thinky.createModel('Cat', {name: String});
// Create custom methods
Cat.define('hello', function() { console.log("Hello, I'm "+this.name) });
cat = new Cat({name: 'Catou'});
cat.hello();
cat.insert(function(err, result) {
// Create a new object
kitty = new Cat({name: 'Kitty'});
kitty.hello(); // Log "Hello, I'm Kitty
kitty.save(function(err, result) {
if (err) throw err;
cat = result;
console.log("Kitty has been saved in the database");
})
```
### Docs
_Note_: Work in progress.
Advanced case:
#### Thinky
__Thinky.connect(__ options __)__
options (object): object with the fields
- host: RethinkDB host (default "localhost")
- port: RethinkDB port for client (default to 28015)
- db: default database (default to "test")
- poolMax: The maximum number of connections in the pool (default to 10)
- poolMin: The minimum number of connections in the pool (default to 1)
- enforce: represents if the schemas should be enforced or not. Its value can be:
- an object with the 3 fields:
- missing // throw on missing fields // default to false
- extra // throw if extra fields are provided // default to false
- type // throw if the type is not the one expected // default to true
- a boolean that set all 3 parameters to the same value
_Note_: The behavior of enforce may change. Since there are more than two cases
- Be flexible
- Forbid extra fields
- Forbid missing fields
- Forbid extra AND missing fields
__Thinky.getOptions()__
Returns all the options previously set.
__Thinky.getOption(__ optionName __)__
Returns the value for _optionName_. Possible values:
- host: RethinkDB host
- port: RethinkDB port for client
- db: default database
- poolMax: The maximum number of connections in the pool
- poolMin: The minimum number of connections in the pool
- enforce: Boolean that represent if the schemas should be enforced or not
__Thinky.setOptions(__ options __)__
Overwrite the options defined in _options_.
The argument _options_ is an object that can have the following fields
- host: RethinkDB host (default "localhost")
- port: RethinkDB port for client (default to 28015)
- db: default database (default to "test")
- poolMax: The maximum number of connections in the pool (default to 10)
- poolMin: The minimum number of connections in the pool (default to 1)
Setting a value to null will delete the value.
_Note_: Almost useless for now since we don't recreate/update the pool
__Thinky.disconnect()__
Close all the connections.
__Thinky.createModel(__ name, schema, settings __)__
Create a new model
- name: name of the model
- schema: An object which fields can have the following values:
- String
- Number
- Boolean
- Array
- Object
- settings (object): settings for the model
- enforce: Boolean that represent if the schemas should be enforced or not
Valid schema can be:
```
Read the code (or the tests)
{ name: String }
{ name: { type: String } } // {name: "Kitty"} or { name: { type: "Kitty" } }?
{ name: { type: String, default: value/function }
{ name: { type: [String, Number, ...] }
{ age: { type: Number, min: ..., max: ...} }
{ comments: { type: Array, min: ..., max: ...} }
{ arrayOfStrings: [ String ] }
{ arrayOfStrings: [ String, maxLength, minLength ] }
```
Coming soon: default with object and arrays.
Contribute
====
You are welcome to do a pull request
TODO
====
- Fully test insert/update/replace
- Add filter
#### Model
__Model.compile(__ name, schema, settings, thinky __)__
_Internal method_
__Model.createBasedOnSchema(__ result, doc, originalDoc, enforce, prefix, schema __)__
_Internal method_
__Model.checkType(__ result, doc, originalDoc, schema, key, type, typeOf, prefix, enforce __)__
_Internal method_
__Model.define(__ key, method __)__
Define a method on the model that can be called by any instances of the model.
__Model.setSchema(__ schema __)__
Change the schema -- Not tested (I think)
__Model.getSettings(__ __)__
Return the settings of the model.
__Model.getDocument(__ __)__
Return the document.
__Model.getPrimaryKey(__ __)__
Return the primary key
__Model.save(__ callback, overwrite __)__
Save the object in the database. Thinky will call insert or update depending
on whether how the object was created.
overwrite: not implemented yet
__Model.get(__ id or [ids], callback __)__
Retrieve one or more documents
__Model.filter(__ filterFunction __)__
Retrieve document based on the filter.
__Model.count(__ __)__
Return the number of element in the table of your model.
__Model.mapReduce(__ filterFunction __)__
Not yet implemented
#### Document
__Document.getDocument(__ __)__
_Internal method?_
__Document.getModel(__ __)__
Return the model of the document.
__Document.getSettings(__ __)__
__Document.define(__ name, method __)__
__Document.replace(__ newDoc __)__
_Not implemented yet_
All method of EventEmitter are available on Document. They do not pollute the document itself.
### Internals
When you create a new object from a model, the object has the following chain of prototypes
object -> DocumentObject -> Document -> model
Run the tests
```
mocha
```
### Contribute
You are welcome to do a pull request.
### TODO
- Write the docs
- Get a cake
- Add more complex queries
- Update pool when poolMax/poolMin changes
About
====
### About
Author: Michel Tu -- orphee@gmail.com -- www.justonepixel.com
License
====
### License
Copyright (c) 2013 Michel Tu <orphee@gmail.com>

@@ -48,0 +262,0 @@

@@ -170,3 +170,3 @@ var thinky = require('../lib/index.js');

});
it('should miss the String field', function() {
it('should miss the String field', function() {
Cat = thinky.createModel('Cat', { fieldString: {_type: String }});

@@ -186,3 +186,6 @@ minou = new Cat({});

var value = "noString";
Cat = thinky.createModel('Cat', { fieldString: {_type: String, default: function() { return value }}});
Cat = thinky.createModel('Cat', { fieldString: {
_type: String,
default: function() { return value }
}});
minou = new Cat({});

@@ -194,3 +197,6 @@ should(Object.prototype.toString.call(catou) === '[object Object]');

var value = "noString";
Cat = thinky.createModel('Cat', { fieldString: {_type: String, default: function(doc) { return doc.value }}});
Cat = thinky.createModel('Cat', { fieldString: {
_type: String,
default: function(doc) { return doc.value }
}});
minou = new Cat({value: value});

@@ -333,4 +339,16 @@ should(Object.prototype.toString.call(catou) === '[object Object]');

});
describe('count', function() {
it('should return the number of document in the table', function(done){
Cat.filter(function(doc) { return true },
function(error, result) {
should.not.exists(error);
Cat.count( function(error, resultCount) {
should.not.exists(error);
result.should.have.length(resultCount);
done();
});
}
)
});
});
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc