Skip to content

Instantly share code, notes, and snippets.

@judell
Last active August 29, 2015 13:57
Show Gist options
  • Save judell/9744381 to your computer and use it in GitHub Desktop.
Save judell/9744381 to your computer and use it in GitHub Desktop.
draft of CouchDB adaptor for TiddlyWiki
/*\
title: $:/plugins/tiddlywiki/tiddlyweb/tiddlywebadaptor.js
type: application/javascript
module-type: syncadaptor
A sync adaptor module for synchronising with Couch compatible servers
\*/
(function () {
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
function CouchDBAdaptor(syncer) {
this.syncer = syncer;
this.host = this.getHost();
this.recipe = undefined;
this.logger = new $tw.utils.Logger("CouchDBAdaptor");
}
CouchDBAdaptor.prototype.getHost = function () { }
CouchDBAdaptor.prototype.getTiddlerInfo = function (tiddler) {
return {
bag: tiddler.fields["bag"]
};
};
/*
Get the current status of the TiddlyWeb connection
*/
CouchDBAdaptor.prototype.getStatus = function (callback) {
// debugger;
console.log('getStatus');
var self = this;
if (callback) {
callback(null, false, null);
}
};
/*
Provide the array of skinny tiddler that the syncer is looking for
*/
CouchDBAdaptor.prototype.getSkinnyTiddlers = function (callback) {
// debugger;
var self = this;
couchdb.get("SkinnyTiddlers", function (err, doc) {
self.logger.log('got Skinny Tiddlers: ')
self.logger.log(doc);
callback(null, doc.tiddlers);
});
};
/*
Save a tiddler and invoke the callback with (err,adaptorInfo,revision)
*/
CouchDBAdaptor.prototype.saveTiddler = function (tiddler, callback) {
// debugger;
var title_to_save = tiddler.fields.title;
this.logger.log('saving ' + title_to_save);
var self = this;
var changeCount = this.syncer.wiki.getChangeCount(title_to_save).toString();
couchdb.get("SkinnyTiddlers", function (err, doc) {
var skinnies = [];
var found = false;
self.syncer.wiki.forEachTiddler({ sortField: "title" }, function (title, tiddler) {
var tiddlerFields = {};
$tw.utils.each(tiddler.fields, function (field, name) {
// if (name !== "text") {
if (name !== "text") {
tiddlerFields[name] = tiddler.fields[name];
}
});
tiddlerFields["revision"] = self.syncer.wiki.getChangeCount(title);
tiddlerFields.type = tiddlerFields.type || "text/vnd.tiddlywiki";
skinnies.push(tiddlerFields);
});
var new_doc = {
_id: "SkinnyTiddlers",
_rev: doc._rev,
tiddlers: skinnies
}
couchdb.put(new_doc, function (err, resp) {
console.log(err);
console.log(resp);
});
});
couchdb.get(title_to_save, function (err, doc) {
if (err == null) {
couchdb.put(tiddler.fields, title_to_save, doc._rev, {}, function (err, response) { console.log(err); console.log(response); });
}
else {
if (err.status == 404) {
couchdb.put(tiddler.fields, title_to_save, null, {}, function (err, response) { console.log(err); console.log(response); });
}
else {
console.log(err);
}
}
});
var enqueue_load = false;
// if (!tiddler.fields['draft.of']) {
if (enqueue_load) {
console.log('queueing load for ' + title_to_save);
self.syncer.enqueueSyncTask({
type: "load",
title: title_to_save
});
}
var ETag = '"' + encodeURIComponent(title_to_save) + "/" + changeCount + ":" + '"';
var etagInfo = self.parseEtag(ETag);
callback(null, {
bag: etagInfo.bag
}, etagInfo.revision);
};
/*
Load a tiddler and invoke the callback with (err,tiddlerFields)
*/
CouchDBAdaptor.prototype.loadTiddler = function (title, callback) {
console.log('loading ' + title);
// debugger;
var self = this;
couchdb.get(title, function (err, doc) {
console.log(err);
console.log('loaded ' + doc);
delete doc._id;
delete doc._rev;
if (doc['modified'])
doc['modified'] = new Date(doc['modified']);
if (doc['created'])
doc['created'] = new Date(doc['created']);
callback(null, doc);
});
};
/*
Delete a tiddler and invoke the callback with (err)
*/
CouchDBAdaptor.prototype.deleteTiddler = function (title, callback) {
console.log('deleting ' + title);
// debugger;
var self = this,
bag = this.syncer.tiddlerInfo[title].adaptorInfo.bag;
// If we don't have a bag it means that the tiddler hasn't been seen by the server, so we don't need to delete it
if (!bag) {
return callback(null);
}
couchdb.get(title, function (err, doc) {
couchdb.remove(doc, function (err, doc) {
});
});
callback(null);
};
/*
Split a TiddlyWeb Etag into its constituent parts. For example:
```
"system-images_public/unsyncedIcon/946151:9f11c278ccde3a3149f339f4a1db80dd4369fc04"
```
Note that the value includes the opening and closing double quotes.
The parts are:
```
<bag>/<title>/<revision>:<hash>
```
*/
CouchDBAdaptor.prototype.parseEtag = function (etag) {
var firstSlash = etag.indexOf("/"),
lastSlash = etag.lastIndexOf("/"),
colon = etag.lastIndexOf(":");
if (firstSlash === -1 || lastSlash === -1 || colon === -1) {
return null;
} else {
return {
bag: decodeURIComponent(etag.substring(1, firstSlash)),
title: decodeURIComponent(etag.substring(firstSlash + 1, lastSlash)),
revision: etag.substring(lastSlash + 1, colon)
};
}
};
if ($tw.browser) {
exports.adaptorClass = CouchDBAdaptor;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment