-
Notifications
You must be signed in to change notification settings - Fork 0
/
couchdb.lua
164 lines (135 loc) · 3.92 KB
/
couchdb.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
-- Copyright (C) 2010 Ministério da Cultura do Brasil
-- Copyright (C) 2010 Lincoln de Sousa <[email protected]>
-- Copyright (C) 2010 Thiago Silva <[email protected]>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Affero General Public License for more details.
--
-- You should have received a copy of the GNU Affero General Public License
-- along with this program. If not, see <http:https://www.gnu.org/licenses/>
module("couchdb", package.seeall)
local json = require("json")
local http = require("socket.http")
local ltn12 = require("ltn12")
-- Prototypes
local Session = {uri="http:https://localhost:5984"}
local Database = {session=nil, name=nil}
local Document = {id=nil, rev=nil, schema=nil}
-- util
local function delegate(parent)
local obj = {}
local mt = {}
setmetatable(obj, mt)
mt.__index = parent
return obj
end
function select(tb, fun)
local ret = {}
for k,v in pairs(tb) do
if (fun(v,k)) then
ret[k] = v
end
end
return ret
end
-- Local functions
local function _do_request(url, method, content)
local t = {}
local source = nil
local headers = nil
-- Converting lua object in content to json. If content is set, we should
-- also set the Content-Type header
if content then
local ct = json.encode(content)
source = ltn12.source.string(ct)
headers = {}
headers['Content-Type'] = 'application/json'
headers['Content-Length'] = #ct
end
local _, code, headers, human_readable_error = http.request{
url=url,
method=method,
headers=headers,
sink=ltn12.sink.table(t),
source=source
}
-- Getting the body content from the ltn12 sink
local body = table.concat(t)
-- Handling all errors together
if code > 299 then
error(human_readable_error)
else
return json.decode(body)
end
end
-- Constructors
function create_session(uri)
local obj = delegate(Session)
obj.uri = uri or obj.uri
return obj
end
function create_database(session,name)
local obj = delegate(Database)
obj.session, obj.name = session, name
return obj
end
function create_document(schema)
local obj = delegate(Document)
if schema.id then
obj.id = schema.id
obj.schema = select(schema, function(v,k) return k ~= 'id' end)
else
obj.schema = schema
end
return obj
end
-- Session methods
function Session:all_dbs()
local result = {}
for _, v in pairs(_do_request(self.uri .. "/_all_dbs", "GET")) do
table.insert(result, create_database(self, v))
end
return result
end
-- Database methods
function Database:create()
_do_request(self.session.uri .. "/" .. self.name, "PUT")
end
function Database:delete()
return _do_request(self.session.uri .. "/" .. self.name, "DELETE")
end
function Database:put(doc)
local result = nil
if doc.id then
result = _do_request(
string.format("%s/%s/%s", self.session.uri, self.name, doc.id),
"PUT", doc.schema)
else
result = _do_request(
string.format("%s/%s", self.session.uri, self.name), "POST",
doc.schema)
end
doc.id = result.id
doc.rev = result.rev
end
function Database:delete_doc(doc)
local uri = string.format(
"%s/%s/%s?rev=%s", self.session.uri, self.name, doc.id, doc.rev)
local result =_do_request(uri, "DELETE")
doc.id = nil
doc.rev = nil
return result
end
function Database:all_docs()
local uri = string.format("%s/%s/_all_docs", self.session.uri, self.name)
return _do_request(uri, "GET")
end
-- Document methods
return _M