UNPKG

3.38 kBJavaScriptView Raw
1var stream = require("obj-stream");
2var request = require("./request");
3var extend = require("xtend/mutable");
4var qs = require("querystring");
5
6/**
7 */
8
9var HTTPDatabase = function(options) {
10 if (!options) options = {};
11
12 this.options = options;
13 this.request = options.request || request;
14 this.idProperty = options.idProperty = options.idProperty || "uid";
15 this.prefix = options.prefix || "";
16
17 this.method = options.method || function(operation) {
18 return {
19 "insert" : "post",
20 "update" : "put",
21 "upsert" : operation.data && operation.data[operation.idProperty] ? "put" : "post",
22 "load" : "get",
23 "remove" : "del"
24 }[operation.name];
25 };
26
27 this.path = function(operation) {
28
29 var cpath = "/" + operation.collection;
30 var mpath = operation.data ? cpath + "/" + operation.data[operation.idProperty] : "";
31
32 return {
33 "insert" : cpath,
34 "update" : mpath,
35 "upsert" : operation.data && operation.data[operation.idProperty] ? mpath : cpath,
36 "load" : operation.multi ? cpath : mpath,
37 "remove" : mpath
38 }[operation.name];
39 };
40};
41
42/**
43 */
44
45var _getters = {};
46
47/**
48 */
49
50function _get(target, keypath) {
51 var getter = _getters[keypath];
52 if (!getter) {
53 getter = _getters[keypath] = new Function("target", "return target." + keypath);
54 }
55 try {
56 return getter(target);
57 } catch (e) { }
58}
59
60/**
61 */
62
63extend(HTTPDatabase.prototype, {
64 run: function(operation, next) {
65
66 var options = operation = extend({}, this.options, operation.http, operation);
67
68 var method = options.method || this.method(operation);
69
70 if (typeof method === "function") {
71 method = method(options);
72 }
73
74 if (!method) return next();
75
76 var path = options.path || this.path;
77
78 if (typeof path === "function") {
79 path = path.call(this, options);
80 }
81
82 path = path.replace(/:([^\/]+)/g, function(keypath) {
83 return _get(options, keypath.substr(1));
84 });
85
86 var transform = options.transform || function(data) {
87 return data;
88 };
89
90 var headers = options.headers;
91 if (typeof headers === "function") {
92 headers = headers.call(this, operation);
93 }
94
95 var query = options.query;
96 if (typeof query === "function") {
97 query = query(operation);
98 }
99
100 path = (options.prefix || this.prefix) + path;
101
102 if (!~path.indexOf("://") && process.browser) {
103 path = location.protocol + "//" + location.host + path;
104 }
105
106 var ops = {
107 uri: path,
108 query: query,
109 method: method,
110 headers: headers,
111 form: options.form,
112 data: options.data
113 };
114
115 this.request(ops, function(err, body) {
116 if (err) return next(err);
117 next(null, transform(body));
118 });
119 }
120});
121
122/**
123 */
124
125function _toArray(data) {
126 if (data == void 0) return [];
127 return Object.prototype.toString.call(data) === "[object Array]" ? data : [data];
128}
129
130/**
131 */
132
133module.exports = function(options) {
134
135 var db = new HTTPDatabase(options);
136
137 return function(operation) {
138 var writable = stream.writable();
139
140 process.nextTick(function() {
141 var self = this;
142 db.run(operation, function(err, data) {
143 if (err) return writable.reader.emit("error");
144 _toArray(data).forEach(writable.write.bind(writable));
145 writable.end();
146 });
147 });
148
149 return writable.reader;
150 };
151};