jsdav-ext
Version:
jsDAV allows you to easily add WebDAV support to a NodeJS application. jsDAV is meant to cover the entire standard, and attempts to allow integration using an easy to understand API.
207 lines (178 loc) • 6.31 kB
JavaScript
/*
* @package jsDAV
* @subpackage DAV
* @copyright Copyright(c) 2013 Mike de Boer. <info AT mikedeboer DOT nl>
* @author Mike de Boer <info AT mikedeboer DOT nl>
* @license http://github.com/mikedeboer/jsDAV/blob/master/LICENSE MIT License
*/
;
var jsDAV_FS_Node = require("./../fs/node");
var jsDAV_iProperties = require("./../../interfaces/iProperties");
var Fs = require("fs");
var Path = require("path");
var Exc = require("./../../../shared/exceptions");
var Util = require("./../../../shared/util");
var jsDAV_FSExt_Node = module.exports = jsDAV_iProperties.extend(jsDAV_FS_Node, {
PROPS_DIR: ".jsdav",
/**
* Updates properties on this node,
*
* @param array properties
* @see jsDAV_iProperties#updateProperties
* @return bool|array
*/
updateProperties: function(properties, cbupdateprops) {
var self = this;
this.getResourceData(function(err, resourceData) {
if (err)
return cbupdateprops(err);
var propertyName, propertyValue
for (propertyName in properties) {
propertyValue = properties[propertyName];
// If it was null, we need to delete the property
if (!propertyValue) {
if (typeof resourceData[propertyName] != "undefined")
delete resourceData[propertyName];
} else {
resourceData[propertyName] = propertyValue;
}
}
self.putResourceData(resourceData, function(err) {
cbupdateprops(err, !err);
});
});
},
/**
* Returns a list of properties for this nodes.;
*
* The properties list is a list of propertynames the client requested,
* encoded as xmlnamespace#tagName, for example: http://www.example.org/namespace#author
* If the array is empty, all properties should be returned
*
* @param array properties
* @return array
*/
getProperties: function(properties, cbgetprops) {
this.getResourceData(function(err, resourceData) {
if (err)
return cbgetprops(err);
// If the array was empty, we need to return everything
if (!properties || !properties.length)
return resourceData;
var props = {};
properties.forEach(function(property) {
if (resourceData[property])
props[property] = resourceData[property];
});
cbgetprops(null, props);
});
},
/**
* Returns the path to the resource file
*
* @return string
*/
getResourceInfoPath: function() {
var parentDir = Util.splitPath(this.path)[0];
return Path.join(parentDir, this.PROPS_DIR);
},
getResourceJson: function(cbgetresjson) {
var path = this.getResourceInfoPath();
var self = this;
Fs.exists(path, function(exists) {
if (!exists)
return cbgetresjson();
Fs.readFile(path, {encoding: "utf8"}, function(err, data) {
if (err)
return cbgetresjson(err);
try {
data = JSON.parse(data);
} catch (ex) {
return cbgetresjson();
}
cbgetresjson(null, data);
});
});
},
/**
* Returns all the stored resource information
*
* @return array
*/
getResourceData: function(cbgetresdata) {
var empty = {};
var self = this;
this.getResourceJson(function(err, data) {
if (err)
return cbgetresdata(err);
if (!data)
return cbgetresdata(null, empty);
data = data[self.getName()];
if (!data || !Object.keys(data).length)
return cbgetresdata(null, empty);
cbgetresdata(null, data);
});
},
/**
* Updates the resource information
*
* @param array newData
* @return void
*/
putResourceData: function(newData, cbputresdata) {
var path = this.getResourceInfoPath();
var self = this;
this.getResourceJson(function(err, data) {
if (err)
return cbputresdata(err);
if (!data)
data = {};
data[self.getName()] = newData;
Fs.writeFile(path, JSON.stringify(data), {encoding: "utf8"}, cbputresdata);
});
},
/**
* Renames the node
*
* @param string name The new name
* @return void
*/
setName: function(name, cbfssetname) {
var parentPath = Util.splitPath(this.path)[0];
var newName = Util.splitPath(name)[1];
var newPath = Path.join(parentPath, newName);
var self = this;
this.getResourceData(function(err, data) {
if (err)
return cbfssetname(err);
self.deleteResourceData(function(err) {
if (err)
return cbfssetname(err);
Fs.rename(self.path, newPath, function(err) {
if (err)
return cbfssetname(err);
self.path = newPath;
self.putResourceData(data, cbfssetname);
});
});
});
},
/**
* @return bool
*/
deleteResourceData: function(cbdelresdata) {
// When we're deleting this node, we also need to delete any resource
// information
var path = this.getResourceInfoPath();
var self = this;
this.getResourceJson(function(err, data) {
if (err)
return cbdelresdata(err);
if (!data)
return cbdelresdata();
if (data[self.getName()])
delete data[self.getName()];
Fs.writeFile(path, JSON.stringify(data), {encoding: "utf8"}, cbdelresdata);
});
}
});