Nickolay - KiokuJS.Backend.CouchDB-0.01
Name
KiokuJS.Backend.CouchDB - Some clever yet compact description
SYNOPSIS
// declaring our class
Class('KiokuJS.Backend.CouchDB', {
})
// then instantiating it
var instance = new KiokuJS.Backend.CouchDB({
})
// and doing something totally awesome with it :D
instance.method(param1, param2)
DESCRIPTION
KiokuJS.Backend.CouchDB is a stub for Joose-orientied JSAN modules.
ISA
None.
DOES
None.
TRAITS
None.
ATTRIBUTES
attributeName
AttributeType attributeNameAttribute description
METHODS
methodName
method signatureMethod description
EXAMPLES
Our class can be used like this:
// then instantiating it
var instance = new KiokuJS.Backend.CouchDB({
})
and like that:
// then instantiating it
var instance = new KiokuJS.Backend.CouchDB({
})
GETTING HELP
This extension is supported via github issues tracker: http://github.com/SamuraiJack/Module-Stub/issues
For general Joose questions you can also visit #joose on irc.freenode.org or the forum at: http://joose.it/forum
SEE ALSO
Web page of this module: http://github.com/SamuraiJack/Module-Stub/
General documentation for Joose: http://openjsan.org/go/?l=Joose
BUGS
All complex software has bugs lurking in it, and this module is no exception.
Please report any bugs through the web interface at http://github.com/SamuraiJack/Module-Stub/issues
AUTHORS
Nickolay Platonov nplatonov@cpan.org
COPYRIGHT AND LICENSE
This software is Copyright (c) 2010 by Nickolay Platonov nplatonov@cpan.org.
This is free software, licensed under:
The GNU Lesser General Public License, Version 3, June 2007
Class('KiokuJS.Backend.CouchDB', {
isa : 'KiokuJS.Backend',
use : [
'JSON2',
Joose.is_NodeJS ? 'HTTP.Request.Provider.NodeJS' : 'HTTP.Request.Provider.XHR',
'KiokuJS.Backend.CouchDB.Node',
'KiokuJS.Exception.Format',
'KiokuJS.Exception.Network',
'KiokuJS.Exception.LookUp',
'KiokuJS.Exception.Overwrite',
'KiokuJS.Exception.Update',
'KiokuJS.Exception.Conflict'
],
does : [ 'KiokuJS.Backend.Feature.Overwrite', 'KiokuJS.Backend.Feature.Update' ],
has : {
dbURL : '',
host : null,
port : 5984,
prefix : '',
dbName : '',
nodeClass : Joose.I.FutureClass('KiokuJS.Backend.CouchDB.Node')
},
after : {
initialize : function () {
this.dbURL = this.dbURL.replace(/\/+$/, '')
this.prefix = this.prefix.replace(/\/+$/, '')
}
},
methods : {
getRequest : function (config) {
return new HTTP.Request.Provider.getRequest(config)
},
getURLforCouch : function () {
return 'http://' + this.host + ':' + this.port + '/' + this.prefix
},
getURLforDB : function () {
if (this.dbURL) return this.dbURL
return this.getURLforCouch() + '/' + this.dbName
}
},
continued : {
methods : {
__createDB : function () {
this.getRequest({
method : 'PUT',
url : this.getURLforDB()
}).andThen(function (res) {
this.CONTINUE(this.deserialize(res.text))
}, this)
},
__deleteDB : function () {
this.getRequest({
method : 'DELETE',
url : this.getURLforDB()
}).andThen(function (res) {
this.CONTINUE(this.deserialize(res.text))
}, this)
},
__createView : function (designDoc, viewName, map, reduce) {
var doc = {
views : {}
}
var view = doc.views[ viewName ] = {}
view.map = map.toString()
if (reduce) view.reduce = reduce.toString()
var serialized = this.serialize(doc)
this.insertDocument('_design/' + designDoc, null, serialized, 'store').now()
},
insertDocument : function (id, rev, entry, mode) {
var me = this
this.getRequest({
method : 'PUT',
url : this.getURLforDB() + '/' + id,
data : entry
}).except(function (e) {
if (e.status == 409) {
var response = me.deserialize(e.text)
if (response.error == 'conflict') {
if (mode == 'insert') throw new KiokuJS.Exception.Overwrite({ id : id, newValue : entry })
if (!rev && mode == 'update') throw new KiokuJS.Exception.Update({ message : 'ID = [' + id + ']' })
throw new KiokuJS.Exception.Conflict({ message : 'ID = [' + id + ']' + ', revision: ' + rev + ', entry: ' + entry })
}
}
throw new KiokuJS.Exception.Network({
nativeEx : e
})
}).andThen(function (res) {
var response = me.deserialize(res.text)
if (response.ok)
this.CONTINUE(response.id, response.rev)
else
throw new KiokuJS.Exception({ message : res.text })
})
},
getDocument : function (id, rev) {
var me = this
this.getRequest({
method : 'GET',
url : this.getURLforDB() + '/' + id,
query : rev ? { rev : rev } : null
}).except(function (e) {
if (e.status == 404)
throw new KiokuJS.Exception.LookUp({
id : id,
backendName : me.meta.name
})
throw new KiokuJS.Exception.Network({
nativeEx : e
})
}).andThen(function (res) {
this.CONTINUE(me.deserialize(res.text))
})
},
deleteDocument : function (id, rev) {
this.getRequest({
method : 'DELETE',
url : this.getURLforDB() + '/' + id,
query : { rev : rev }
}).except(function (e) {
if (e.status == 409)
throw new KiokuJS.Exception.Conflict({
message : 'Id [' + id + '] not found or revision [' + rev + '] is not current'
})
throw new KiokuJS.Exception.Network({
nativeEx : e
})
}).andThen(function (res) {
this.CONTINUE(me.deserialize(res.text))
})
},
get : function (idsToGet, mode) {
var me = this
var CONT = this.CONT
Joose.A.each(idsToGet, function (id) {
CONT.AND(function () {
me.getDocument(id).now()
})
})
CONT.andThen(function () {
var entries = Joose.A.map(arguments, function (returned) {
var doc = returned[0]
if (doc instanceof KiokuJS.Exception) throw doc
return me.nodeClass.entryFromDoc(doc)
})
this.CONTINUE(entries)
})
},
insert : function (entries, mode) {
var me = this
var CONT = this.CONT
var processedEntries = []
Joose.A.each(entries, function (entry, index) {
CONT.AND(function () {
var string = me.serialize(me.nodeClass.docFromEntry(entry))
me.insertDocument(entry.ID, entry.REV, string, mode).andThen(function (id, rev) {
processedEntries[ index ] = {
ID : id,
REV : rev
}
this.CONTINUE()
})
})
})
CONT.andThen(function () {
Joose.A.each(arguments, function (insertResult) {
var res = insertResult[0]
if (res instanceof KiokuJS.Exception) throw res
})
this.CONTINUE(processedEntries)
})
},
remove : function (entriesOrIds) {
var me = this
var CONT = this.CONT
Joose.A.each(entriesOrIds, function (entryOrId) {
CONT.AND(function () {
// entry
if (entryOrId === Object(entryOrId))
this.deleteDocument(entryOrId.ID, entryOrId.REV).now()
else {
this.getDocument(entryOrId, null).andThen(function (doc) {
this.deleteDocument(doc._id, doc._rev).now()
})
}
})
})
CONT.andThen(function () {
Joose.A.each(arguments, function (res) {
if (res[0] instanceof KiokuJS.Exception) throw res[0]
})
this.CONTINUE()
})
},
exists : function (idsToCheck) {
var me = this
var CONT = this.CONT
Joose.A.each(idsToCheck, function (id) {
CONT.AND(function () {
this.getDocument(id).now()
})
})
CONT.andThen(function () {
var results = Joose.A.map(arguments, function (checkResult) {
var res = checkResult[0]
if (res instanceof KiokuJS.Exception.LookUp) return false
if (res === Object(res) && res._id) return true
throw res
})
this.CONTINUE(results)
})
},
queryView : function (designDoc, viewName, query) {
this.getRequest({
method : 'GET',
url : this.getURLforDB() + '/_design/' + designDoc + '/_view/' + viewName,
query : query
}).except(function (e) {
throw new KiokuJS.Exception.Network({
nativeEx : e
})
}).andThen(function (res) {
this.CONTINUE(this.deserialize(res.text))
}, this)
},
search : function (scope, args) {
var searchArgs = Joose.O.copy(args[0])
var view = searchArgs.view
var designDoc = searchArgs.designDoc
delete searchArgs.view
delete searchArgs.designDoc
this.queryView(designDoc, view, searchArgs).andThen(function (response) {
if (searchArgs.raw) {
this.CONTINUE(response)
return
}
var ids = Joose.A.map(response.rows, function (row) {
return row.id
})
scope.lookUp.apply(scope, ids).now()
})
}
}
}
})