1 |
|
2 | (function() {
|
3 | var AbstractChainedBatch, AbstractError, AbstractIterator, AbstractNoSQL, AbstractObject, CloseError, Errors, InvalidArgumentError, NotImplementedError, OpenError, inherits, setImmediate, util, xtend;
|
4 |
|
5 | xtend = require("xtend");
|
6 |
|
7 | AbstractObject = require("abstract-object");
|
8 |
|
9 | util = require("abstract-object/lib/util");
|
10 |
|
11 | inherits = util.inherits;
|
12 |
|
13 | Errors = require("./abstract-error");
|
14 |
|
15 | AbstractIterator = require("./abstract-iterator");
|
16 |
|
17 | AbstractChainedBatch = require("./abstract-chained-batch");
|
18 |
|
19 | setImmediate = global.setImmediate || process.nextTick;
|
20 |
|
21 | AbstractError = Errors.AbstractError;
|
22 |
|
23 | NotImplementedError = Errors.NotImplementedError;
|
24 |
|
25 | InvalidArgumentError = Errors.InvalidArgumentError;
|
26 |
|
27 | OpenError = Errors.OpenError;
|
28 |
|
29 | CloseError = Errors.CloseError;
|
30 |
|
31 | module.exports.AbstractNoSQL = AbstractNoSQL = (function() {
|
32 | inherits(AbstractNoSQL, AbstractObject);
|
33 |
|
34 | function AbstractNoSQL() {
|
35 | AbstractNoSQL.__super__.constructor.apply(this, arguments);
|
36 | }
|
37 |
|
38 | AbstractNoSQL.prototype.init = function(location) {
|
39 | if (location && typeof location !== "string") {
|
40 | throw new InvalidArgumentError("constructor requires a location string argument");
|
41 | }
|
42 | return this.location = location;
|
43 | };
|
44 |
|
45 | AbstractNoSQL.prototype.__defineGetter__("opened", function() {
|
46 | return !!this._opened;
|
47 | });
|
48 |
|
49 | AbstractNoSQL.prototype.setOpened = function(aValue) {
|
50 | if (aValue) {
|
51 | this._opened = true;
|
52 | this.emit("ready");
|
53 | return this.emit("open");
|
54 | } else {
|
55 | this._opened = false;
|
56 | return this.emit("closed");
|
57 | }
|
58 | };
|
59 |
|
60 | AbstractNoSQL.prototype.isExistsSync = function(key, options) {
|
61 | var err, result;
|
62 | if (options == null) {
|
63 | options = {};
|
64 | }
|
65 | if (this._isExistsSync) {
|
66 | result = this._isExistsSync(key, options);
|
67 | return result;
|
68 | } else if (this._getSync) {
|
69 | try {
|
70 | this._getSync(key, options);
|
71 | return true;
|
72 | } catch (_error) {
|
73 | err = _error;
|
74 | if (AbstractError.isNotFound(err)) {
|
75 | return false;
|
76 | } else {
|
77 | throw err;
|
78 | }
|
79 | }
|
80 | }
|
81 | throw new NotImplementedError();
|
82 | };
|
83 |
|
84 | AbstractNoSQL.prototype.getSync = function(key, options) {
|
85 | var result;
|
86 | if (this._getSync) {
|
87 | if (options == null) {
|
88 | options = {};
|
89 | }
|
90 | result = this._getSync(key, options);
|
91 | return result;
|
92 | }
|
93 | throw new NotImplementedError();
|
94 | };
|
95 |
|
96 | AbstractNoSQL.prototype.putSync = function(key, value, options) {
|
97 | var result;
|
98 | if (this._putSync) {
|
99 | if (options == null) {
|
100 | options = {};
|
101 | }
|
102 | result = this._putSync(key, value, options);
|
103 | return result;
|
104 | }
|
105 | throw new NotImplementedError();
|
106 | };
|
107 |
|
108 | AbstractNoSQL.prototype.delSync = function(key, options) {
|
109 | var result;
|
110 | if (this._delSync) {
|
111 | if (options == null) {
|
112 | options = {};
|
113 | }
|
114 | result = this._delSync(key, options);
|
115 | return result;
|
116 | }
|
117 | throw new NotImplementedError();
|
118 | };
|
119 |
|
120 | AbstractNoSQL.prototype.batchSync = function(operations, options) {
|
121 | var result;
|
122 | if (this._batchSync) {
|
123 | if (options == null) {
|
124 | options = {};
|
125 | }
|
126 | result = this._batchSync(operations, options);
|
127 | return result;
|
128 | }
|
129 | throw new NotImplementedError();
|
130 | };
|
131 |
|
132 | AbstractNoSQL.prototype.approximateSizeSync = function(start, end) {
|
133 | var result;
|
134 | if (this._approximateSizeSync) {
|
135 | result = this._approximateSizeSync(start, end);
|
136 | return result;
|
137 | }
|
138 | throw new NotImplementedError();
|
139 | };
|
140 |
|
141 | AbstractNoSQL.prototype.openSync = function(options) {
|
142 | var result;
|
143 | if (this._openSync) {
|
144 | if (options == null) {
|
145 | options = {};
|
146 | }
|
147 | result = this._openSync(options);
|
148 | if (result) {
|
149 | this.setOpened(true);
|
150 | }
|
151 | return result;
|
152 | }
|
153 | throw new NotImplementedError();
|
154 | };
|
155 |
|
156 | AbstractNoSQL.prototype.closeSync = function() {
|
157 | var result;
|
158 | if (this._closeSync) {
|
159 | result = this._closeSync();
|
160 | if (result) {
|
161 | this.setOpened(false);
|
162 | }
|
163 | return result;
|
164 | }
|
165 | throw new NotImplementedError();
|
166 | };
|
167 |
|
168 | AbstractNoSQL.prototype._open = function(options, callback) {
|
169 | var that;
|
170 | that = this;
|
171 | if (this._openSync) {
|
172 | return setImmediate(function() {
|
173 | var err, result;
|
174 | result = void 0;
|
175 | try {
|
176 | result = that._openSync(options);
|
177 | } catch (_error) {
|
178 | err = _error;
|
179 | callback(err);
|
180 | return;
|
181 | }
|
182 | if (result) {
|
183 | return callback(null, result);
|
184 | } else {
|
185 | return callback(new OpenError("can not open database."));
|
186 | }
|
187 | });
|
188 | } else {
|
189 | return setImmediate(callback);
|
190 | }
|
191 | };
|
192 |
|
193 | AbstractNoSQL.prototype._close = function(callback) {
|
194 | var that;
|
195 | that = this;
|
196 | if (this._closeSync) {
|
197 | return setImmediate(function() {
|
198 | var err, result;
|
199 | result = void 0;
|
200 | try {
|
201 | result = that._closeSync();
|
202 | } catch (_error) {
|
203 | err = _error;
|
204 | callback(err);
|
205 | return;
|
206 | }
|
207 | if (result) {
|
208 | return callback(null, result);
|
209 | } else {
|
210 | return callback(new CloseError("can not close database."));
|
211 | }
|
212 | });
|
213 | } else {
|
214 | return setImmediate(callback);
|
215 | }
|
216 | };
|
217 |
|
218 | AbstractNoSQL.prototype._isExists = function(key, options, callback) {
|
219 | var that;
|
220 | that = this;
|
221 | if (this._isExistsSync) {
|
222 | return setImmediate(function() {
|
223 | var err, result;
|
224 | result = void 0;
|
225 | try {
|
226 | result = that._isExistsSync(key, options);
|
227 | } catch (_error) {
|
228 | err = _error;
|
229 | callback(err);
|
230 | return;
|
231 | }
|
232 | return callback(null, result);
|
233 | });
|
234 | } else {
|
235 | return this._get(key, options, function(err, value) {
|
236 | if (err) {
|
237 | if (AbstractError.isNotFound(err)) {
|
238 | return callback(null, false);
|
239 | } else {
|
240 | return callback(err);
|
241 | }
|
242 | } else {
|
243 | return callback(null, true);
|
244 | }
|
245 | });
|
246 | }
|
247 | };
|
248 |
|
249 | AbstractNoSQL.prototype._get = function(key, options, callback) {
|
250 | var that;
|
251 | that = this;
|
252 | if (this._getSync) {
|
253 | return setImmediate(function() {
|
254 | var err, result;
|
255 | result = void 0;
|
256 | try {
|
257 | result = that._getSync(key, options);
|
258 | } catch (_error) {
|
259 | err = _error;
|
260 | callback(err);
|
261 | return;
|
262 | }
|
263 | return callback(null, result);
|
264 | });
|
265 | } else {
|
266 | return setImmediate(callback);
|
267 | }
|
268 | };
|
269 |
|
270 | AbstractNoSQL.prototype._put = function(key, value, options, callback) {
|
271 | var that;
|
272 | that = this;
|
273 | if (this._putSync) {
|
274 | return setImmediate(function() {
|
275 | var err, result;
|
276 | result = void 0;
|
277 | try {
|
278 | result = that._putSync(key, value, options);
|
279 | } catch (_error) {
|
280 | err = _error;
|
281 | callback(err);
|
282 | return;
|
283 | }
|
284 | return callback(null, result);
|
285 | });
|
286 | } else {
|
287 | return setImmediate(callback);
|
288 | }
|
289 | };
|
290 |
|
291 | AbstractNoSQL.prototype._del = function(key, options, callback) {
|
292 | var that;
|
293 | that = this;
|
294 | if (this._delSync) {
|
295 | return setImmediate(function() {
|
296 | var err, result;
|
297 | result = void 0;
|
298 | try {
|
299 | result = that._delSync(key, options);
|
300 | } catch (_error) {
|
301 | err = _error;
|
302 | callback(err);
|
303 | return;
|
304 | }
|
305 | return callback(null, result);
|
306 | });
|
307 | } else {
|
308 | return setImmediate(callback);
|
309 | }
|
310 | };
|
311 |
|
312 | AbstractNoSQL.prototype._batch = function(array, options, callback) {
|
313 | var that;
|
314 | that = this;
|
315 | if (this._batchSync) {
|
316 | return setImmediate(function() {
|
317 | var err, result;
|
318 | result = void 0;
|
319 | try {
|
320 | result = that._batchSync(array, options);
|
321 | } catch (_error) {
|
322 | err = _error;
|
323 | callback(err);
|
324 | return;
|
325 | }
|
326 | return callback(null, result);
|
327 | });
|
328 | } else {
|
329 | return setImmediate(callback);
|
330 | }
|
331 | };
|
332 |
|
333 | AbstractNoSQL.prototype._approximateSize = function(start, end, callback) {
|
334 | var that;
|
335 | that = this;
|
336 | if (this._approximateSizeSync) {
|
337 | return setImmediate(function() {
|
338 | var err, result;
|
339 | result = void 0;
|
340 | try {
|
341 | result = that._approximateSizeSync(start, end);
|
342 | } catch (_error) {
|
343 | err = _error;
|
344 | callback(err);
|
345 | return;
|
346 | }
|
347 | return callback(null, result);
|
348 | });
|
349 | } else {
|
350 | return setImmediate(callback);
|
351 | }
|
352 | };
|
353 |
|
354 | AbstractNoSQL.prototype.open = function(options, callback) {
|
355 | var that;
|
356 | if (typeof options === "function") {
|
357 | callback = options;
|
358 | }
|
359 | if (typeof options !== "object") {
|
360 | options = {};
|
361 | }
|
362 | options.createIfMissing = options.createIfMissing !== false;
|
363 | options.errorIfExists = !!options.errorIfExists;
|
364 | if (callback) {
|
365 | that = this;
|
366 | return this._open(options, function(err, result) {
|
367 | if (err == null) {
|
368 | that.setOpened(true);
|
369 | }
|
370 | return callback(err, result);
|
371 | });
|
372 | } else {
|
373 | return this.openSync(options);
|
374 | }
|
375 | };
|
376 |
|
377 | AbstractNoSQL.prototype.close = function(callback) {
|
378 | var that;
|
379 | if (callback) {
|
380 | if (typeof callback === "function") {
|
381 | that = this;
|
382 | return this._close(function(err, result) {
|
383 | if (err == null) {
|
384 | that.setOpened(false);
|
385 | }
|
386 | return callback(err, result);
|
387 | });
|
388 | } else {
|
389 | throw new Error("close() requires callback function argument");
|
390 | }
|
391 | } else {
|
392 | return this.closeSync();
|
393 | }
|
394 | };
|
395 |
|
396 | AbstractNoSQL.prototype.isExists = function(key, options, callback) {
|
397 | if (typeof options === "function") {
|
398 | callback = options;
|
399 | options = {};
|
400 | } else {
|
401 | if (options == null) {
|
402 | options = {};
|
403 | }
|
404 | }
|
405 | if (!this._isBuffer(key)) {
|
406 | key = String(key);
|
407 | }
|
408 | if (callback) {
|
409 | return this._isExists(key, options, callback);
|
410 | } else {
|
411 | return this.isExistsSync(key, options);
|
412 | }
|
413 | };
|
414 |
|
415 | AbstractNoSQL.prototype.get = function(key, options, callback) {
|
416 | var err;
|
417 | err = void 0;
|
418 | if (typeof options === "function") {
|
419 | callback = options;
|
420 | }
|
421 | if (err = this._checkKey(key, "key", this._isBuffer)) {
|
422 | if (callback) {
|
423 | return callback(err);
|
424 | } else {
|
425 | throw err;
|
426 | }
|
427 | }
|
428 | if (!this._isBuffer(key)) {
|
429 | key = String(key);
|
430 | }
|
431 | if (typeof options !== "object") {
|
432 | options = {};
|
433 | }
|
434 | options.asBuffer = options.asBuffer !== false;
|
435 | if (callback) {
|
436 | return this._get(key, options, callback);
|
437 | } else {
|
438 | return this.getSync(key, options);
|
439 | }
|
440 | };
|
441 |
|
442 | AbstractNoSQL.prototype.put = function(key, value, options, callback) {
|
443 | var err;
|
444 | err = void 0;
|
445 | if (typeof options === "function") {
|
446 | callback = options;
|
447 | options = {};
|
448 | } else {
|
449 | if (options == null) {
|
450 | options = {};
|
451 | }
|
452 | }
|
453 | if (err = this._checkKey(key, "key", this._isBuffer)) {
|
454 | if (callback) {
|
455 | return callback(err);
|
456 | } else {
|
457 | throw err;
|
458 | }
|
459 | }
|
460 | if (!this._isBuffer(key)) {
|
461 | key = String(key);
|
462 | }
|
463 | if ((value != null) && !this._isBuffer(value) && !process.browser) {
|
464 | value = String(value);
|
465 | }
|
466 | if (callback) {
|
467 | return this._put(key, value, options, callback);
|
468 | } else {
|
469 | return this.putSync(key, value, options);
|
470 | }
|
471 | };
|
472 |
|
473 | AbstractNoSQL.prototype.del = function(key, options, callback) {
|
474 | var err;
|
475 | err = void 0;
|
476 | if (typeof options === "function") {
|
477 | callback = options;
|
478 | options = {};
|
479 | } else {
|
480 | if (options == null) {
|
481 | options = {};
|
482 | }
|
483 | }
|
484 | if (err = this._checkKey(key, "key", this._isBuffer)) {
|
485 | if (callback) {
|
486 | return callback(err);
|
487 | } else {
|
488 | throw err;
|
489 | }
|
490 | }
|
491 | if (!this._isBuffer(key)) {
|
492 | key = String(key);
|
493 | }
|
494 | if (callback) {
|
495 | return this._del(key, options, callback);
|
496 | } else {
|
497 | return this.delSync(key, options);
|
498 | }
|
499 | };
|
500 |
|
501 | AbstractNoSQL.prototype.batch = function(array, options, callback) {
|
502 | var e, err, vError, _i, _len;
|
503 | if (!arguments.length) {
|
504 | return this._chainedBatch();
|
505 | }
|
506 | if (typeof options === "function") {
|
507 | callback = options;
|
508 | options = {};
|
509 | } else {
|
510 | if (options == null) {
|
511 | options = {};
|
512 | }
|
513 | }
|
514 | if (typeof array === "function") {
|
515 | callback = array;
|
516 | }
|
517 | if (!Array.isArray(array)) {
|
518 | vError = new Error("batch(array) requires an array argument");
|
519 | if (callback) {
|
520 | return callback(vError);
|
521 | } else {
|
522 | throw vError;
|
523 | }
|
524 | }
|
525 | for (_i = 0, _len = array.length; _i < _len; _i++) {
|
526 | e = array[_i];
|
527 | if (typeof e !== "object") {
|
528 | continue;
|
529 | }
|
530 | if (err = this._checkKey(e.type, "type", this._isBuffer)) {
|
531 | if (callback) {
|
532 | return callback(err);
|
533 | } else {
|
534 | throw err;
|
535 | }
|
536 | }
|
537 | if (err = this._checkKey(e.key, "key", this._isBuffer)) {
|
538 | if (callback) {
|
539 | return callback(err);
|
540 | } else {
|
541 | throw err;
|
542 | }
|
543 | }
|
544 | }
|
545 | if (callback) {
|
546 | return this._batch(array, options, callback);
|
547 | } else {
|
548 | return this.batchSync(array, options);
|
549 | }
|
550 | };
|
551 |
|
552 | AbstractNoSQL.prototype.approximateSize = function(start, end, callback) {
|
553 | if ((start == null) || (end == null) || typeof start === "function" || typeof end === "function") {
|
554 | throw new Error("approximateSize() requires valid `start`, `end` and `callback`(for async) arguments");
|
555 | }
|
556 | if (!this._isBuffer(start)) {
|
557 | start = String(start);
|
558 | }
|
559 | if (!this._isBuffer(end)) {
|
560 | end = String(end);
|
561 | }
|
562 | if (callback) {
|
563 | return this._approximateSize(start, end, callback);
|
564 | } else {
|
565 | return this.approximateSizeSync(start, end);
|
566 | }
|
567 | };
|
568 |
|
569 | AbstractNoSQL.prototype._setupIteratorOptions = function(options) {
|
570 | var self;
|
571 | self = this;
|
572 | options = xtend(options);
|
573 | ["start", "end", "gt", "gte", "lt", "lte"].forEach(function(o) {
|
574 | if (options[o] && self._isBuffer(options[o]) && options[o].length === 0) {
|
575 | return delete options[o];
|
576 | }
|
577 | });
|
578 | options.reverse = !!options.reverse;
|
579 | options.keys = options.keys !== false;
|
580 | options.values = options.values !== false;
|
581 | options.limit = ("limit" in options ? options.limit : -1);
|
582 | options.keyAsBuffer = options.keyAsBuffer === true;
|
583 | options.valueAsBuffer = options.valueAsBuffer === true;
|
584 | return options;
|
585 | };
|
586 |
|
587 | AbstractNoSQL.prototype.IteratorClass = AbstractIterator;
|
588 |
|
589 | AbstractNoSQL.prototype.iterator = function(options) {
|
590 | if (typeof options !== "object") {
|
591 | options = {};
|
592 | }
|
593 | options = this._setupIteratorOptions(options);
|
594 | if (typeof this._iterator === "function") {
|
595 | return this._iterator(options);
|
596 | }
|
597 | return new this.IteratorClass(this, options);
|
598 | };
|
599 |
|
600 | AbstractNoSQL.prototype._chainedBatch = function() {
|
601 | return new AbstractChainedBatch(this);
|
602 | };
|
603 |
|
604 | AbstractNoSQL.prototype._isBuffer = function(obj) {
|
605 | return Buffer.isBuffer(obj);
|
606 | };
|
607 |
|
608 | AbstractNoSQL.prototype._checkKey = function(obj, type) {
|
609 | if (obj == null) {
|
610 | return new InvalidArgumentError(type + " cannot be `null` or `undefined`");
|
611 | }
|
612 | if (this._isBuffer(obj)) {
|
613 | if (obj.length === 0) {
|
614 | return new InvalidArgumentError(type + " cannot be an empty Buffer");
|
615 | }
|
616 | } else {
|
617 | if (String(obj) === "") {
|
618 | return new InvalidArgumentError(type + " cannot be an empty String");
|
619 | }
|
620 | }
|
621 | };
|
622 |
|
623 | AbstractNoSQL.prototype.isOpen = function() {
|
624 | return !!this._opened;
|
625 | };
|
626 |
|
627 | return AbstractNoSQL;
|
628 |
|
629 | })();
|
630 |
|
631 | module.exports.AbstractLevelDOWN = AbstractNoSQL;
|
632 |
|
633 | module.exports.AbstractIterator = AbstractIterator;
|
634 |
|
635 | module.exports.AbstractChainedBatch = AbstractChainedBatch;
|
636 |
|
637 | }).call(this);
|