forked from pouchdb/pouchdb
-
Notifications
You must be signed in to change notification settings - Fork 8
/
pouch.js
186 lines (163 loc) · 4.33 KB
/
pouch.js
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*globals PouchAdapter: true */
"use strict";
var Pouch = function Pouch(name, opts, callback) {
if (!(this instanceof Pouch)) {
return new Pouch(name, opts, callback);
}
if (typeof opts === 'function' || typeof opts === 'undefined') {
callback = opts;
opts = {};
}
if (typeof name === 'object') {
opts = name;
name = undefined;
}
var backend = Pouch.parseAdapter(opts.name || name);
opts.name = opts.name || backend.name;
opts.adapter = opts.adapter || backend.adapter;
if (!Pouch.adapters[opts.adapter]) {
throw 'Adapter is missing';
}
if (!Pouch.adapters[opts.adapter].valid()) {
throw 'Invalid Adapter';
}
var adapter = new PouchAdapter(opts, function(err, db) {
if (err) {
if (callback) {
callback(err);
}
return;
}
for (var plugin in Pouch.plugins) {
// In future these will likely need to be async to allow the plugin
// to initialise
var pluginObj = Pouch.plugins[plugin](db);
for (var api in pluginObj) {
// We let things like the http adapter use its own implementation
// as it shares a lot of code
if (!(api in db)) {
db[api] = pluginObj[api];
}
}
}
callback(null, db);
});
for (var j in adapter) {
this[j] = adapter[j];
}
};
Pouch.DEBUG = false;
Pouch.adapters = {};
Pouch.plugins = {};
Pouch.parseAdapter = function(name) {
var match = name.match(/([a-z\-]*):\/\/(.*)/);
if (match) {
// the http adapter expects the fully qualified name
name = /http(s?)/.test(match[1]) ? match[1] + '://' + match[2] : match[2];
var adapter = match[1];
if (!Pouch.adapters[adapter].valid()) {
throw 'Invalid adapter';
}
return {name: name, adapter: match[1]};
}
var rank = {'idb': 1, 'leveldb': 2, 'websql': 3, 'http': 4, 'https': 4};
var rankedAdapter = Object.keys(Pouch.adapters).sort(function(a, b) {
return rank[a] - rank[b];
})[0];
return {
name: name,
adapter: rankedAdapter
};
};
Pouch.destroy = function(name, callback) {
for (var plugin in Pouch.plugins) {
Pouch.plugins[plugin]._delete(name);
}
var opts = Pouch.parseAdapter(name);
Pouch.adapters[opts.adapter].destroy(opts.name, callback);
};
Pouch.adapter = function (id, obj) {
if (obj.valid()) {
Pouch.adapters[id] = obj;
}
};
Pouch.plugin = function(id, obj) {
Pouch.plugins[id] = obj;
};
// Enumerate errors, add the status code so we can reflect the HTTP api
// in future
Pouch.Errors = {
MISSING_BULK_DOCS: {
status: 400,
error: 'bad_request',
reason: "Missing JSON list of 'docs'"
},
MISSING_DOC: {
status: 404,
error: 'not_found',
reason: 'missing'
},
REV_CONFLICT: {
status: 409,
error: 'conflict',
reason: 'Document update conflict'
},
INVALID_ID: {
status: 400,
error: 'invalid_id',
reason: '_id field must contain a string'
},
MISSING_ID: {
status: 412,
error: 'missing_id',
reason: '_id is required for puts'
},
RESERVED_ID: {
status: 400,
error: 'bad_request',
reason: 'Only reserved document ids may start with underscore.'
},
NOT_OPEN: {
status: 412,
error: 'precondition_failed',
reason: 'Database not open so cannot close'
},
UNKNOWN_ERROR: {
status: 500,
error: 'unknown_error',
reason: 'Database encountered an unknown error'
},
INVALID_REQUEST: {
status: 400,
error: 'invalid_request',
reason: 'Request was invalid'
},
QUERY_PARSE_ERROR: {
status: 400,
error: 'query_parse_error',
reason: 'Some query parameter is invalid'
},
BAD_REQUEST: {
status: 400,
error: 'bad_request',
reason: 'Something wrong with the request'
}
};
if (typeof module !== 'undefined' && module.exports) {
global.Pouch = Pouch;
Pouch.merge = require('./pouch.merge.js').merge;
Pouch.collate = require('./pouch.collate.js').collate;
Pouch.replicate = require('./pouch.replicate.js').replicate;
Pouch.utils = require('./pouch.utils.js');
module.exports = Pouch;
var PouchAdapter = require('./pouch.adapter.js');
// load adapters known to work under node
var adapters = ['leveldb', 'http'];
adapters.map(function(adapter) {
var adapter_path = './adapters/pouch.'+adapter+'.js';
require(adapter_path);
});
require('./plugins/pouchdb.mapreduce.js');
} else {
window.Pouch = Pouch;
}