Stackedit/couchdb/setup.js

181 lines
4.0 KiB
JavaScript
Raw Permalink Normal View History

2014-09-09 23:37:21 +00:00
var validate = function(newDoc) {
Object.keys(newDoc).forEach(function(key) {
if(key[0] !== '_' && [
'updated',
'tags',
'title'
].indexOf(key) === -1) {
throw({forbidden: 'Unknown document attribute: ' + key});
}
});
var toString = Object.prototype.toString;
if(toString.call(newDoc._id) !== '[object String]') {
throw({forbidden: 'ID must be a string.'});
}
if(!newDoc._id.match(/[a-zA-Z0-9]{24}/)) {
throw({forbidden: 'Invalid ID format.'});
}
2014-09-11 23:36:19 +00:00
if(newDoc._deleted) {
if(newDoc.updated !== undefined ||
newDoc.tags !== undefined ||
newDoc.title !== undefined ||
newDoc._attachments !== undefined) {
throw({forbidden: 'Deleted document must be empty.'});
}
return;
}
2014-09-09 23:37:21 +00:00
if(toString.call(newDoc.updated) !== '[object Number]') {
throw({forbidden: 'Update time must be an integer.'});
}
if(newDoc.updated > Date.now() + 300000) {
2014-09-09 23:37:21 +00:00
throw({forbidden: 'Update time is in the future, please check your clock!'});
}
if(toString.call(newDoc.title) !== '[object String]') {
throw({forbidden: 'Title must be a string.'});
}
if(!newDoc.title) {
throw({forbidden: 'Title is empty.'});
}
if(newDoc.title.length >= 256) {
throw({forbidden: 'Title too long.'});
}
if(newDoc.tags !== undefined) {
if(toString.call(newDoc.tags) !== '[object Array]') {
throw({forbidden: 'Tags must be an array.'});
}
if(newDoc.tags.length >= 16) {
throw({forbidden: 'Too many tags.'});
}
newDoc.tags.forEach(function(tag) {
if(toString.call(tag) !== '[object String]') {
throw({forbidden: 'Tags must contain strings only.'});
}
if(!tag) {
throw({forbidden: 'Tag is empty.'});
}
if(tag.length > 32) {
throw({forbidden: 'Tag is too long.'});
}
});
}
var attachment = (newDoc._attachments || {}).content;
if(!attachment) {
throw({forbidden: 'Missing attached content.'});
}
if(attachment.content_type != 'text/plain') {
throw({forbidden: 'Invalid content type.'});
}
if(Object.keys(newDoc._attachments).length > 1) {
throw({forbidden: 'Too many attachments.'});
}
};
var byUpdate = function(doc) {
2014-09-11 23:36:19 +00:00
if(!doc.tags || !doc.tags.length) {
emit(doc.updated, null);
}
2014-09-09 23:37:21 +00:00
};
var byTagAndUpdate = function(doc) {
doc.tags && doc.tags.forEach(function(tag) {
emit([
tag,
doc.updated
], null);
});
};
var ddocs = [
{
path: '/_design/validate',
body: {
validate_doc_update: validate.toString()
}
},
{
path: '/_design/by_update',
body: {
views: {
default: {
map: byUpdate.toString()
}
}
}
},
{
path: '/_design/by_tag_and_update',
body: {
views: {
default: {
map: byTagAndUpdate.toString()
}
}
}
}
];
if(process.argv.length < 3) {
console.error('Missing URL parameter');
process.exit(-1);
}
2014-09-09 23:37:21 +00:00
var url = require('url').parse(process.argv[2]);
var request = require(url.protocol === 'https:' ? 'https' : 'http').request;
2014-09-09 23:37:21 +00:00
function onError(err, body) {
console.error(err);
body && console.error(body);
process.exit(1);
}
function uploadDdoc() {
if(ddocs.length === 0) {
return console.log('All design documents updated successfully.');
2014-09-09 23:37:21 +00:00
}
var ddoc = ddocs.shift();
var options = {
hostname: url.hostname,
port: url.port,
path: url.path + ddoc.path,
auth: url.auth,
method: 'GET'
};
request(options, function(res) {
var body = '';
res
.on('data', function(chunk) {
body += chunk;
})
.on('end', function() {
2014-10-14 21:34:46 +00:00
if(res.statusCode == 200) {
ddoc.body._rev = JSON.parse(body)._rev;
}
var options = {
hostname: url.hostname,
port: url.port,
path: url.path + ddoc.path,
auth: url.auth,
method: 'PUT',
headers: {
'Content-type': 'application/json'
}
};
request(options, function(res) {
var body = '';
res
.on('data', function(chunk) {
body += chunk;
})
.on('end', function() {
res.statusCode >= 300 && onError('Status code: ' + res.statusCode, body);
uploadDdoc();
});
})
.on('error', onError)
.end(JSON.stringify(ddoc.body));
});
})
.on('error', onError)
.end();
}
uploadDdoc();