switching to node couchapp structure, redoing headers mapreduce
1
.couchapprc
Normal file
@ -0,0 +1 @@
|
||||
{}
|
||||
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.DS_Store
|
||||
102
app.js
Normal file
@ -0,0 +1,102 @@
|
||||
var couchapp = require('couchapp')
|
||||
, path = require('path')
|
||||
;
|
||||
|
||||
ddoc =
|
||||
{ _id:'_design/removalist'
|
||||
, rewrites :
|
||||
[ {from:"/", to:'pages/index.html'}
|
||||
, {from:"csv", to:'_list/csv/all'}
|
||||
, {from:"headers", to:'_list/urlencode/headers', query: {group: true}}
|
||||
, {from:"/api", to:'../../'}
|
||||
, {from:"/api/*", to:'../../*'}
|
||||
, {from:"/*", to:'*'}
|
||||
]
|
||||
}
|
||||
;
|
||||
|
||||
ddoc.views = {
|
||||
/**
|
||||
* A simple map function mocking _all, but allows usage with lists etc.
|
||||
*/
|
||||
all: {
|
||||
map: function(doc) {
|
||||
emit(doc.id, doc);
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
map: function(doc) {
|
||||
var keys = [];
|
||||
for (var key in doc) {
|
||||
emit(key, 1);
|
||||
}
|
||||
},
|
||||
reduce: "_sum"
|
||||
}
|
||||
};
|
||||
|
||||
ddoc.lists = {
|
||||
/**
|
||||
* Generates a CSV from all the rows in the view.
|
||||
*
|
||||
* Takes in a url encoded array of headers as an argument. You can
|
||||
* generate this by querying /_list/urlencode/headers. Pass it in
|
||||
* as the headers get parameter, e.g.: ?headers=%5B%22_id%22%2C%22_rev%5D
|
||||
*
|
||||
* @author Max Ogden
|
||||
*/
|
||||
csv: function(head, req) {
|
||||
if ('headers' in req.query) {
|
||||
var headers = JSON.parse(unescape(req.query.headers))[0];
|
||||
var row, sep = '\n', headerSent = false, startedOutput = false;
|
||||
|
||||
start({"headers":{"Content-Type" : "text/csv; charset=utf-8"}});
|
||||
send('"' + headers.join('","') + '"\n');
|
||||
while (row = getRow()) {
|
||||
for (var header in headers) {
|
||||
if (row.value[headers[header]]) {
|
||||
if (startedOutput) send(",");
|
||||
var value = row.value[headers[header]];
|
||||
if (typeof(value) == "object") value = JSON.stringify(value);
|
||||
if (typeof(value) == "string") value = value.replace(/\"/g, '""');
|
||||
send("\"" + value + "\"");
|
||||
} else {
|
||||
if (startedOutput) send(",");
|
||||
}
|
||||
startedOutput = true;
|
||||
}
|
||||
startedOutput = false;
|
||||
send('\n');
|
||||
}
|
||||
} else {
|
||||
send("You must pass in the urlencoded headers you wish to build the CSV from. Query /_list/urlencode/headers");
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Returns the urlencoded version of the view's keys
|
||||
*
|
||||
* @author Max Ogden
|
||||
*/
|
||||
urlencode: function(head, req) {
|
||||
start({"headers":{"Content-Type" : "application/json"}});
|
||||
if ('callback' in req.query) send(req.query['callback'] + "(");
|
||||
|
||||
var headers = [];
|
||||
while (row = getRow()) {
|
||||
headers.push(row.key);
|
||||
}
|
||||
send(escape(JSON.stringify(headers)));
|
||||
|
||||
if ('callback' in req.query) send(")");
|
||||
}
|
||||
}
|
||||
|
||||
ddoc.validate_doc_update = function (newDoc, oldDoc, userCtx) {
|
||||
if (newDoc._deleted === true && userCtx.roles.indexOf('_admin') === -1) {
|
||||
throw "Only admin can delete documents on this database.";
|
||||
}
|
||||
};
|
||||
|
||||
couchapp.loadAttachments(ddoc, path.join(__dirname, 'attachments'));
|
||||
|
||||
module.exports = ddoc;
|
||||
|
Before Width: | Height: | Size: 87 B After Width: | Height: | Size: 87 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
35
lists/csv.js
@ -1,35 +0,0 @@
|
||||
/**
|
||||
* Generates a CSV from all the rows in the view.
|
||||
*
|
||||
* Takes in a url encoded array of headers as an argument. You can
|
||||
* generate this by querying /_list/urlencode/headers. Pass it in
|
||||
* as the headers get parameter, e.g.: ?headers=%5B%22_id%22%2C%22_rev%5D
|
||||
*
|
||||
* @author Max Ogden
|
||||
*/
|
||||
function(head, req) {
|
||||
if ('headers' in req.query) {
|
||||
var headers = JSON.parse(unescape(req.query.headers))[0];
|
||||
var row, sep = '\n', headerSent = false, startedOutput = false;
|
||||
|
||||
start({"headers":{"Content-Type" : "text/csv; charset=utf-8"}});
|
||||
send('"' + headers.join('","') + '"\n');
|
||||
while (row = getRow()) {
|
||||
for (var header in headers) {
|
||||
if (row.value[headers[header]]) {
|
||||
if (startedOutput) send(",");
|
||||
var value = row.value[headers[header]];
|
||||
if (typeof(value) == "object") value = JSON.stringify(value);
|
||||
send("\"" + value.replace(/\"/g, '""') + "\"");
|
||||
} else {
|
||||
if (startedOutput) send(",");
|
||||
}
|
||||
startedOutput = true;
|
||||
}
|
||||
startedOutput = false;
|
||||
send('\n');
|
||||
}
|
||||
} else {
|
||||
send("You must pass in the urlencoded headers you wish to build the CSV from. Query /_list/urlencode/headers");
|
||||
}
|
||||
};
|
||||
@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Generates a simple array of json objects representing each doc in the db
|
||||
* @author Max Ogden
|
||||
*/
|
||||
function(head, req) {
|
||||
var row, out, sep = '\n';
|
||||
|
||||
start({"headers":{"Content-Type" : "application/json"}});
|
||||
|
||||
if ('callback' in req.query) send(req.query['callback'] + "(");
|
||||
|
||||
send('[');
|
||||
while (row = getRow()) {
|
||||
for (var header in row.value) {
|
||||
if (row.value[header]) {
|
||||
var value = row.value[header];
|
||||
if (typeof(value) == "object") {
|
||||
row.value[header] = "\"" + JSON.stringify(value) + "\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
send(sep + JSON.stringify(row.value));
|
||||
sep = ',\n';
|
||||
}
|
||||
send("]");
|
||||
if ('callback' in req.query) send(")");
|
||||
|
||||
};
|
||||
@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Generates a simple array of json objects representing each doc in the db
|
||||
* @author Max Ogden
|
||||
*/
|
||||
function(head, req) {
|
||||
var row, out, sep = '\n';
|
||||
|
||||
start({"headers":{"Content-Type" : "application/json"}});
|
||||
|
||||
if ('callback' in req.query) send(req.query['callback'] + "(");
|
||||
|
||||
send('{');
|
||||
while ((row = getRow())) {
|
||||
for (var header in row.value) {
|
||||
if (row.value[header]) {
|
||||
var value = row.value[header];
|
||||
if (typeof(value) == "object") {
|
||||
row.value[header] = "\"" + JSON.stringify(value) + "\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
send(sep + '"":' + JSON.stringify(row.value));
|
||||
sep = ',\n';
|
||||
}
|
||||
send("]");
|
||||
if ('callback' in req.query) send(")");
|
||||
|
||||
};
|
||||
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Returns the urlencoded version of the view value
|
||||
*
|
||||
* @author Max Ogden
|
||||
*/
|
||||
function(head, req) {
|
||||
// Send the same Content-Type as CouchDB would
|
||||
if (req.headers.Accept.indexOf('application/json')!=-1)
|
||||
start({"headers":{"Content-Type" : "application/json"}});
|
||||
else
|
||||
start({"headers":{"Content-Type" : "text/plain"}});
|
||||
|
||||
if ('callback' in req.query) send(req.query['callback'] + "(");
|
||||
|
||||
var rows = []
|
||||
while (row = getRow()) {
|
||||
rows.push(row.value)
|
||||
}
|
||||
send(escape(JSON.stringify(rows)));
|
||||
|
||||
if ('callback' in req.query) send(")");
|
||||
};
|
||||
@ -25,6 +25,4 @@ After you install it, visit this link to open Removalist:
|
||||
|
||||
You'll have to get yourself a couch. The easiest way is from [the instructions on this page](http://couchone.com/get). Once it's going, open up `http://YOURCOUCH/_utils` and create a new database to store your data.
|
||||
|
||||
You can either replicate the couchapp from my couch [max.couchone.com/apps/_design/removalist](http://max.couchone.com/apps/_design/removalist) (quickest option) or, if you want to hack on the removalist source code first, you'll need to install the [CouchApp command line utility](http://couchapp.org/page/installing) and check out this repo.
|
||||
|
||||
If you want to hack on removalist, once you have the couchapp utility working, <code>git clone</code> this repo and go into this folder and execute <code>couchapp init</code>. To upload removalist into your couch just run <code>couchapp push http://YOURCOUCH/DATABASENAME</code>. Otherwise see the Quick install section above.
|
||||
You can either replicate the couchapp from my couch [max.couchone.com/apps/_design/removalist](http://max.couchone.com/apps/_design/removalist) (quickest option) or, if you want to hack on the removalist source code first, you'll need to install `mikeal/node.couchapp.js` and clone this repo.
|
||||
@ -1,50 +0,0 @@
|
||||
[
|
||||
{
|
||||
"to": "style/*",
|
||||
"from": "style/*"
|
||||
},
|
||||
{
|
||||
"to": "script/*",
|
||||
"from": "script/*"
|
||||
},
|
||||
{
|
||||
"to": "pages/*",
|
||||
"from": "pages/*"
|
||||
},
|
||||
{
|
||||
"to": "images/*",
|
||||
"from": "images/*"
|
||||
},
|
||||
{
|
||||
"to": "pages/index.html",
|
||||
"from": ""
|
||||
},
|
||||
{
|
||||
"to": "_list/csv/all",
|
||||
"from": "csv"
|
||||
},
|
||||
{
|
||||
"to": "_list/urlencode/headers",
|
||||
"from": "headers"
|
||||
},
|
||||
{
|
||||
"to": "./",
|
||||
"from": "ddoc"
|
||||
},
|
||||
{
|
||||
"to": "./",
|
||||
"from": "api/_design/ddoc"
|
||||
},
|
||||
{
|
||||
"to": "./*",
|
||||
"from": "api/_design/ddoc/*"
|
||||
},
|
||||
{
|
||||
"to": "../../",
|
||||
"from": "api"
|
||||
},
|
||||
{
|
||||
"to": "../../*",
|
||||
"from": "api/*"
|
||||
}
|
||||
]
|
||||
@ -1,7 +0,0 @@
|
||||
/**
|
||||
* A simple map function mocking _all, but allows usage with lists etc.
|
||||
*
|
||||
*/
|
||||
function(doc) {
|
||||
emit(doc.id, doc);
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Returns an array of all of the keys in the document.
|
||||
*
|
||||
* @author Max Ogden
|
||||
*/
|
||||
function(doc) {
|
||||
var keys = [];
|
||||
for (var key in doc) {
|
||||
keys.push(key);
|
||||
}
|
||||
emit(doc, keys);
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Reduces the passed in view headers to a list of unique object key attributes
|
||||
*
|
||||
* @author Max Ogden
|
||||
*/
|
||||
function(keys, values, rereduce) {
|
||||
|
||||
function include(arr, obj) {
|
||||
return (arr.indexOf(obj) != -1);
|
||||
}
|
||||
|
||||
var headers = [];
|
||||
for (var doc in values) {
|
||||
for (var header in values[doc]) {
|
||||
if(!include(headers, values[doc][header])) {
|
||||
headers.push(values[doc][header]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||