UNPKG

186 kBJavaScriptView Raw
1// pouchdb-find plugin 9.0.0
2// Based on Mango: https://github.com/cloudant/mango
3//
4// (c) 2012-2024 Dale Harvey and the PouchDB team
5// PouchDB may be freely distributed under the Apache license, version 2.0.
6// For all details and documentation:
7// http://pouchdb.com
8(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(_dereq_,module,exports){
9// Copyright Joyent, Inc. and other Node contributors.
10//
11// Permission is hereby granted, free of charge, to any person obtaining a
12// copy of this software and associated documentation files (the
13// "Software"), to deal in the Software without restriction, including
14// without limitation the rights to use, copy, modify, merge, publish,
15// distribute, sublicense, and/or sell copies of the Software, and to permit
16// persons to whom the Software is furnished to do so, subject to the
17// following conditions:
18//
19// The above copyright notice and this permission notice shall be included
20// in all copies or substantial portions of the Software.
21//
22// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
25// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
26// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
27// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
28// USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30var objectCreate = Object.create || objectCreatePolyfill
31var objectKeys = Object.keys || objectKeysPolyfill
32var bind = Function.prototype.bind || functionBindPolyfill
33
34function EventEmitter() {
35 if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) {
36 this._events = objectCreate(null);
37 this._eventsCount = 0;
38 }
39
40 this._maxListeners = this._maxListeners || undefined;
41}
42module.exports = EventEmitter;
43
44// Backwards-compat with node 0.10.x
45EventEmitter.EventEmitter = EventEmitter;
46
47EventEmitter.prototype._events = undefined;
48EventEmitter.prototype._maxListeners = undefined;
49
50// By default EventEmitters will print a warning if more than 10 listeners are
51// added to it. This is a useful default which helps finding memory leaks.
52var defaultMaxListeners = 10;
53
54var hasDefineProperty;
55try {
56 var o = {};
57 if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 });
58 hasDefineProperty = o.x === 0;
59} catch (err) { hasDefineProperty = false }
60if (hasDefineProperty) {
61 Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
62 enumerable: true,
63 get: function() {
64 return defaultMaxListeners;
65 },
66 set: function(arg) {
67 // check whether the input is a positive number (whose value is zero or
68 // greater and not a NaN).
69 if (typeof arg !== 'number' || arg < 0 || arg !== arg)
70 throw new TypeError('"defaultMaxListeners" must be a positive number');
71 defaultMaxListeners = arg;
72 }
73 });
74} else {
75 EventEmitter.defaultMaxListeners = defaultMaxListeners;
76}
77
78// Obviously not all Emitters should be limited to 10. This function allows
79// that to be increased. Set to zero for unlimited.
80EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
81 if (typeof n !== 'number' || n < 0 || isNaN(n))
82 throw new TypeError('"n" argument must be a positive number');
83 this._maxListeners = n;
84 return this;
85};
86
87function $getMaxListeners(that) {
88 if (that._maxListeners === undefined)
89 return EventEmitter.defaultMaxListeners;
90 return that._maxListeners;
91}
92
93EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
94 return $getMaxListeners(this);
95};
96
97// These standalone emit* functions are used to optimize calling of event
98// handlers for fast cases because emit() itself often has a variable number of
99// arguments and can be deoptimized because of that. These functions always have
100// the same number of arguments and thus do not get deoptimized, so the code
101// inside them can execute faster.
102function emitNone(handler, isFn, self) {
103 if (isFn)
104 handler.call(self);
105 else {
106 var len = handler.length;
107 var listeners = arrayClone(handler, len);
108 for (var i = 0; i < len; ++i)
109 listeners[i].call(self);
110 }
111}
112function emitOne(handler, isFn, self, arg1) {
113 if (isFn)
114 handler.call(self, arg1);
115 else {
116 var len = handler.length;
117 var listeners = arrayClone(handler, len);
118 for (var i = 0; i < len; ++i)
119 listeners[i].call(self, arg1);
120 }
121}
122function emitTwo(handler, isFn, self, arg1, arg2) {
123 if (isFn)
124 handler.call(self, arg1, arg2);
125 else {
126 var len = handler.length;
127 var listeners = arrayClone(handler, len);
128 for (var i = 0; i < len; ++i)
129 listeners[i].call(self, arg1, arg2);
130 }
131}
132function emitThree(handler, isFn, self, arg1, arg2, arg3) {
133 if (isFn)
134 handler.call(self, arg1, arg2, arg3);
135 else {
136 var len = handler.length;
137 var listeners = arrayClone(handler, len);
138 for (var i = 0; i < len; ++i)
139 listeners[i].call(self, arg1, arg2, arg3);
140 }
141}
142
143function emitMany(handler, isFn, self, args) {
144 if (isFn)
145 handler.apply(self, args);
146 else {
147 var len = handler.length;
148 var listeners = arrayClone(handler, len);
149 for (var i = 0; i < len; ++i)
150 listeners[i].apply(self, args);
151 }
152}
153
154EventEmitter.prototype.emit = function emit(type) {
155 var er, handler, len, args, i, events;
156 var doError = (type === 'error');
157
158 events = this._events;
159 if (events)
160 doError = (doError && events.error == null);
161 else if (!doError)
162 return false;
163
164 // If there is no 'error' event listener then throw.
165 if (doError) {
166 if (arguments.length > 1)
167 er = arguments[1];
168 if (er instanceof Error) {
169 throw er; // Unhandled 'error' event
170 } else {
171 // At least give some kind of context to the user
172 var err = new Error('Unhandled "error" event. (' + er + ')');
173 err.context = er;
174 throw err;
175 }
176 return false;
177 }
178
179 handler = events[type];
180
181 if (!handler)
182 return false;
183
184 var isFn = typeof handler === 'function';
185 len = arguments.length;
186 switch (len) {
187 // fast cases
188 case 1:
189 emitNone(handler, isFn, this);
190 break;
191 case 2:
192 emitOne(handler, isFn, this, arguments[1]);
193 break;
194 case 3:
195 emitTwo(handler, isFn, this, arguments[1], arguments[2]);
196 break;
197 case 4:
198 emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
199 break;
200 // slower
201 default:
202 args = new Array(len - 1);
203 for (i = 1; i < len; i++)
204 args[i - 1] = arguments[i];
205 emitMany(handler, isFn, this, args);
206 }
207
208 return true;
209};
210
211function _addListener(target, type, listener, prepend) {
212 var m;
213 var events;
214 var existing;
215
216 if (typeof listener !== 'function')
217 throw new TypeError('"listener" argument must be a function');
218
219 events = target._events;
220 if (!events) {
221 events = target._events = objectCreate(null);
222 target._eventsCount = 0;
223 } else {
224 // To avoid recursion in the case that type === "newListener"! Before
225 // adding it to the listeners, first emit "newListener".
226 if (events.newListener) {
227 target.emit('newListener', type,
228 listener.listener ? listener.listener : listener);
229
230 // Re-assign `events` because a newListener handler could have caused the
231 // this._events to be assigned to a new object
232 events = target._events;
233 }
234 existing = events[type];
235 }
236
237 if (!existing) {
238 // Optimize the case of one listener. Don't need the extra array object.
239 existing = events[type] = listener;
240 ++target._eventsCount;
241 } else {
242 if (typeof existing === 'function') {
243 // Adding the second element, need to change to array.
244 existing = events[type] =
245 prepend ? [listener, existing] : [existing, listener];
246 } else {
247 // If we've already got an array, just append.
248 if (prepend) {
249 existing.unshift(listener);
250 } else {
251 existing.push(listener);
252 }
253 }
254
255 // Check for listener leak
256 if (!existing.warned) {
257 m = $getMaxListeners(target);
258 if (m && m > 0 && existing.length > m) {
259 existing.warned = true;
260 var w = new Error('Possible EventEmitter memory leak detected. ' +
261 existing.length + ' "' + String(type) + '" listeners ' +
262 'added. Use emitter.setMaxListeners() to ' +
263 'increase limit.');
264 w.name = 'MaxListenersExceededWarning';
265 w.emitter = target;
266 w.type = type;
267 w.count = existing.length;
268 if (typeof console === 'object' && console.warn) {
269 console.warn('%s: %s', w.name, w.message);
270 }
271 }
272 }
273 }
274
275 return target;
276}
277
278EventEmitter.prototype.addListener = function addListener(type, listener) {
279 return _addListener(this, type, listener, false);
280};
281
282EventEmitter.prototype.on = EventEmitter.prototype.addListener;
283
284EventEmitter.prototype.prependListener =
285 function prependListener(type, listener) {
286 return _addListener(this, type, listener, true);
287 };
288
289function onceWrapper() {
290 if (!this.fired) {
291 this.target.removeListener(this.type, this.wrapFn);
292 this.fired = true;
293 switch (arguments.length) {
294 case 0:
295 return this.listener.call(this.target);
296 case 1:
297 return this.listener.call(this.target, arguments[0]);
298 case 2:
299 return this.listener.call(this.target, arguments[0], arguments[1]);
300 case 3:
301 return this.listener.call(this.target, arguments[0], arguments[1],
302 arguments[2]);
303 default:
304 var args = new Array(arguments.length);
305 for (var i = 0; i < args.length; ++i)
306 args[i] = arguments[i];
307 this.listener.apply(this.target, args);
308 }
309 }
310}
311
312function _onceWrap(target, type, listener) {
313 var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
314 var wrapped = bind.call(onceWrapper, state);
315 wrapped.listener = listener;
316 state.wrapFn = wrapped;
317 return wrapped;
318}
319
320EventEmitter.prototype.once = function once(type, listener) {
321 if (typeof listener !== 'function')
322 throw new TypeError('"listener" argument must be a function');
323 this.on(type, _onceWrap(this, type, listener));
324 return this;
325};
326
327EventEmitter.prototype.prependOnceListener =
328 function prependOnceListener(type, listener) {
329 if (typeof listener !== 'function')
330 throw new TypeError('"listener" argument must be a function');
331 this.prependListener(type, _onceWrap(this, type, listener));
332 return this;
333 };
334
335// Emits a 'removeListener' event if and only if the listener was removed.
336EventEmitter.prototype.removeListener =
337 function removeListener(type, listener) {
338 var list, events, position, i, originalListener;
339
340 if (typeof listener !== 'function')
341 throw new TypeError('"listener" argument must be a function');
342
343 events = this._events;
344 if (!events)
345 return this;
346
347 list = events[type];
348 if (!list)
349 return this;
350
351 if (list === listener || list.listener === listener) {
352 if (--this._eventsCount === 0)
353 this._events = objectCreate(null);
354 else {
355 delete events[type];
356 if (events.removeListener)
357 this.emit('removeListener', type, list.listener || listener);
358 }
359 } else if (typeof list !== 'function') {
360 position = -1;
361
362 for (i = list.length - 1; i >= 0; i--) {
363 if (list[i] === listener || list[i].listener === listener) {
364 originalListener = list[i].listener;
365 position = i;
366 break;
367 }
368 }
369
370 if (position < 0)
371 return this;
372
373 if (position === 0)
374 list.shift();
375 else
376 spliceOne(list, position);
377
378 if (list.length === 1)
379 events[type] = list[0];
380
381 if (events.removeListener)
382 this.emit('removeListener', type, originalListener || listener);
383 }
384
385 return this;
386 };
387
388EventEmitter.prototype.removeAllListeners =
389 function removeAllListeners(type) {
390 var listeners, events, i;
391
392 events = this._events;
393 if (!events)
394 return this;
395
396 // not listening for removeListener, no need to emit
397 if (!events.removeListener) {
398 if (arguments.length === 0) {
399 this._events = objectCreate(null);
400 this._eventsCount = 0;
401 } else if (events[type]) {
402 if (--this._eventsCount === 0)
403 this._events = objectCreate(null);
404 else
405 delete events[type];
406 }
407 return this;
408 }
409
410 // emit removeListener for all listeners on all events
411 if (arguments.length === 0) {
412 var keys = objectKeys(events);
413 var key;
414 for (i = 0; i < keys.length; ++i) {
415 key = keys[i];
416 if (key === 'removeListener') continue;
417 this.removeAllListeners(key);
418 }
419 this.removeAllListeners('removeListener');
420 this._events = objectCreate(null);
421 this._eventsCount = 0;
422 return this;
423 }
424
425 listeners = events[type];
426
427 if (typeof listeners === 'function') {
428 this.removeListener(type, listeners);
429 } else if (listeners) {
430 // LIFO order
431 for (i = listeners.length - 1; i >= 0; i--) {
432 this.removeListener(type, listeners[i]);
433 }
434 }
435
436 return this;
437 };
438
439function _listeners(target, type, unwrap) {
440 var events = target._events;
441
442 if (!events)
443 return [];
444
445 var evlistener = events[type];
446 if (!evlistener)
447 return [];
448
449 if (typeof evlistener === 'function')
450 return unwrap ? [evlistener.listener || evlistener] : [evlistener];
451
452 return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
453}
454
455EventEmitter.prototype.listeners = function listeners(type) {
456 return _listeners(this, type, true);
457};
458
459EventEmitter.prototype.rawListeners = function rawListeners(type) {
460 return _listeners(this, type, false);
461};
462
463EventEmitter.listenerCount = function(emitter, type) {
464 if (typeof emitter.listenerCount === 'function') {
465 return emitter.listenerCount(type);
466 } else {
467 return listenerCount.call(emitter, type);
468 }
469};
470
471EventEmitter.prototype.listenerCount = listenerCount;
472function listenerCount(type) {
473 var events = this._events;
474
475 if (events) {
476 var evlistener = events[type];
477
478 if (typeof evlistener === 'function') {
479 return 1;
480 } else if (evlistener) {
481 return evlistener.length;
482 }
483 }
484
485 return 0;
486}
487
488EventEmitter.prototype.eventNames = function eventNames() {
489 return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
490};
491
492// About 1.5x faster than the two-arg version of Array#splice().
493function spliceOne(list, index) {
494 for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
495 list[i] = list[k];
496 list.pop();
497}
498
499function arrayClone(arr, n) {
500 var copy = new Array(n);
501 for (var i = 0; i < n; ++i)
502 copy[i] = arr[i];
503 return copy;
504}
505
506function unwrapListeners(arr) {
507 var ret = new Array(arr.length);
508 for (var i = 0; i < ret.length; ++i) {
509 ret[i] = arr[i].listener || arr[i];
510 }
511 return ret;
512}
513
514function objectCreatePolyfill(proto) {
515 var F = function() {};
516 F.prototype = proto;
517 return new F;
518}
519function objectKeysPolyfill(obj) {
520 var keys = [];
521 for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
522 keys.push(k);
523 }
524 return k;
525}
526function functionBindPolyfill(context) {
527 var fn = this;
528 return function () {
529 return fn.apply(context, arguments);
530 };
531}
532
533},{}],2:[function(_dereq_,module,exports){
534(function (factory) {
535 if (typeof exports === 'object') {
536 // Node/CommonJS
537 module.exports = factory();
538 } else if (typeof define === 'function' && define.amd) {
539 // AMD
540 define(factory);
541 } else {
542 // Browser globals (with support for web workers)
543 var glob;
544
545 try {
546 glob = window;
547 } catch (e) {
548 glob = self;
549 }
550
551 glob.SparkMD5 = factory();
552 }
553}(function (undefined) {
554
555 'use strict';
556
557 /*
558 * Fastest md5 implementation around (JKM md5).
559 * Credits: Joseph Myers
560 *
561 * @see http://www.myersdaily.org/joseph/javascript/md5-text.html
562 * @see http://jsperf.com/md5-shootout/7
563 */
564
565 /* this function is much faster,
566 so if possible we use it. Some IEs
567 are the only ones I know of that
568 need the idiotic second function,
569 generated by an if clause. */
570 var add32 = function (a, b) {
571 return (a + b) & 0xFFFFFFFF;
572 },
573 hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
574
575
576 function cmn(q, a, b, x, s, t) {
577 a = add32(add32(a, q), add32(x, t));
578 return add32((a << s) | (a >>> (32 - s)), b);
579 }
580
581 function md5cycle(x, k) {
582 var a = x[0],
583 b = x[1],
584 c = x[2],
585 d = x[3];
586
587 a += (b & c | ~b & d) + k[0] - 680876936 | 0;
588 a = (a << 7 | a >>> 25) + b | 0;
589 d += (a & b | ~a & c) + k[1] - 389564586 | 0;
590 d = (d << 12 | d >>> 20) + a | 0;
591 c += (d & a | ~d & b) + k[2] + 606105819 | 0;
592 c = (c << 17 | c >>> 15) + d | 0;
593 b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
594 b = (b << 22 | b >>> 10) + c | 0;
595 a += (b & c | ~b & d) + k[4] - 176418897 | 0;
596 a = (a << 7 | a >>> 25) + b | 0;
597 d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
598 d = (d << 12 | d >>> 20) + a | 0;
599 c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
600 c = (c << 17 | c >>> 15) + d | 0;
601 b += (c & d | ~c & a) + k[7] - 45705983 | 0;
602 b = (b << 22 | b >>> 10) + c | 0;
603 a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
604 a = (a << 7 | a >>> 25) + b | 0;
605 d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
606 d = (d << 12 | d >>> 20) + a | 0;
607 c += (d & a | ~d & b) + k[10] - 42063 | 0;
608 c = (c << 17 | c >>> 15) + d | 0;
609 b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
610 b = (b << 22 | b >>> 10) + c | 0;
611 a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
612 a = (a << 7 | a >>> 25) + b | 0;
613 d += (a & b | ~a & c) + k[13] - 40341101 | 0;
614 d = (d << 12 | d >>> 20) + a | 0;
615 c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
616 c = (c << 17 | c >>> 15) + d | 0;
617 b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
618 b = (b << 22 | b >>> 10) + c | 0;
619
620 a += (b & d | c & ~d) + k[1] - 165796510 | 0;
621 a = (a << 5 | a >>> 27) + b | 0;
622 d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
623 d = (d << 9 | d >>> 23) + a | 0;
624 c += (d & b | a & ~b) + k[11] + 643717713 | 0;
625 c = (c << 14 | c >>> 18) + d | 0;
626 b += (c & a | d & ~a) + k[0] - 373897302 | 0;
627 b = (b << 20 | b >>> 12) + c | 0;
628 a += (b & d | c & ~d) + k[5] - 701558691 | 0;
629 a = (a << 5 | a >>> 27) + b | 0;
630 d += (a & c | b & ~c) + k[10] + 38016083 | 0;
631 d = (d << 9 | d >>> 23) + a | 0;
632 c += (d & b | a & ~b) + k[15] - 660478335 | 0;
633 c = (c << 14 | c >>> 18) + d | 0;
634 b += (c & a | d & ~a) + k[4] - 405537848 | 0;
635 b = (b << 20 | b >>> 12) + c | 0;
636 a += (b & d | c & ~d) + k[9] + 568446438 | 0;
637 a = (a << 5 | a >>> 27) + b | 0;
638 d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
639 d = (d << 9 | d >>> 23) + a | 0;
640 c += (d & b | a & ~b) + k[3] - 187363961 | 0;
641 c = (c << 14 | c >>> 18) + d | 0;
642 b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
643 b = (b << 20 | b >>> 12) + c | 0;
644 a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
645 a = (a << 5 | a >>> 27) + b | 0;
646 d += (a & c | b & ~c) + k[2] - 51403784 | 0;
647 d = (d << 9 | d >>> 23) + a | 0;
648 c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
649 c = (c << 14 | c >>> 18) + d | 0;
650 b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
651 b = (b << 20 | b >>> 12) + c | 0;
652
653 a += (b ^ c ^ d) + k[5] - 378558 | 0;
654 a = (a << 4 | a >>> 28) + b | 0;
655 d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
656 d = (d << 11 | d >>> 21) + a | 0;
657 c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
658 c = (c << 16 | c >>> 16) + d | 0;
659 b += (c ^ d ^ a) + k[14] - 35309556 | 0;
660 b = (b << 23 | b >>> 9) + c | 0;
661 a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
662 a = (a << 4 | a >>> 28) + b | 0;
663 d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
664 d = (d << 11 | d >>> 21) + a | 0;
665 c += (d ^ a ^ b) + k[7] - 155497632 | 0;
666 c = (c << 16 | c >>> 16) + d | 0;
667 b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
668 b = (b << 23 | b >>> 9) + c | 0;
669 a += (b ^ c ^ d) + k[13] + 681279174 | 0;
670 a = (a << 4 | a >>> 28) + b | 0;
671 d += (a ^ b ^ c) + k[0] - 358537222 | 0;
672 d = (d << 11 | d >>> 21) + a | 0;
673 c += (d ^ a ^ b) + k[3] - 722521979 | 0;
674 c = (c << 16 | c >>> 16) + d | 0;
675 b += (c ^ d ^ a) + k[6] + 76029189 | 0;
676 b = (b << 23 | b >>> 9) + c | 0;
677 a += (b ^ c ^ d) + k[9] - 640364487 | 0;
678 a = (a << 4 | a >>> 28) + b | 0;
679 d += (a ^ b ^ c) + k[12] - 421815835 | 0;
680 d = (d << 11 | d >>> 21) + a | 0;
681 c += (d ^ a ^ b) + k[15] + 530742520 | 0;
682 c = (c << 16 | c >>> 16) + d | 0;
683 b += (c ^ d ^ a) + k[2] - 995338651 | 0;
684 b = (b << 23 | b >>> 9) + c | 0;
685
686 a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
687 a = (a << 6 | a >>> 26) + b | 0;
688 d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
689 d = (d << 10 | d >>> 22) + a | 0;
690 c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
691 c = (c << 15 | c >>> 17) + d | 0;
692 b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
693 b = (b << 21 |b >>> 11) + c | 0;
694 a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
695 a = (a << 6 | a >>> 26) + b | 0;
696 d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
697 d = (d << 10 | d >>> 22) + a | 0;
698 c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
699 c = (c << 15 | c >>> 17) + d | 0;
700 b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
701 b = (b << 21 |b >>> 11) + c | 0;
702 a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
703 a = (a << 6 | a >>> 26) + b | 0;
704 d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
705 d = (d << 10 | d >>> 22) + a | 0;
706 c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
707 c = (c << 15 | c >>> 17) + d | 0;
708 b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
709 b = (b << 21 |b >>> 11) + c | 0;
710 a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
711 a = (a << 6 | a >>> 26) + b | 0;
712 d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
713 d = (d << 10 | d >>> 22) + a | 0;
714 c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
715 c = (c << 15 | c >>> 17) + d | 0;
716 b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
717 b = (b << 21 | b >>> 11) + c | 0;
718
719 x[0] = a + x[0] | 0;
720 x[1] = b + x[1] | 0;
721 x[2] = c + x[2] | 0;
722 x[3] = d + x[3] | 0;
723 }
724
725 function md5blk(s) {
726 var md5blks = [],
727 i; /* Andy King said do it this way. */
728
729 for (i = 0; i < 64; i += 4) {
730 md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
731 }
732 return md5blks;
733 }
734
735 function md5blk_array(a) {
736 var md5blks = [],
737 i; /* Andy King said do it this way. */
738
739 for (i = 0; i < 64; i += 4) {
740 md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
741 }
742 return md5blks;
743 }
744
745 function md51(s) {
746 var n = s.length,
747 state = [1732584193, -271733879, -1732584194, 271733878],
748 i,
749 length,
750 tail,
751 tmp,
752 lo,
753 hi;
754
755 for (i = 64; i <= n; i += 64) {
756 md5cycle(state, md5blk(s.substring(i - 64, i)));
757 }
758 s = s.substring(i - 64);
759 length = s.length;
760 tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
761 for (i = 0; i < length; i += 1) {
762 tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
763 }
764 tail[i >> 2] |= 0x80 << ((i % 4) << 3);
765 if (i > 55) {
766 md5cycle(state, tail);
767 for (i = 0; i < 16; i += 1) {
768 tail[i] = 0;
769 }
770 }
771
772 // Beware that the final length might not fit in 32 bits so we take care of that
773 tmp = n * 8;
774 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
775 lo = parseInt(tmp[2], 16);
776 hi = parseInt(tmp[1], 16) || 0;
777
778 tail[14] = lo;
779 tail[15] = hi;
780
781 md5cycle(state, tail);
782 return state;
783 }
784
785 function md51_array(a) {
786 var n = a.length,
787 state = [1732584193, -271733879, -1732584194, 271733878],
788 i,
789 length,
790 tail,
791 tmp,
792 lo,
793 hi;
794
795 for (i = 64; i <= n; i += 64) {
796 md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
797 }
798
799 // Not sure if it is a bug, however IE10 will always produce a sub array of length 1
800 // containing the last element of the parent array if the sub array specified starts
801 // beyond the length of the parent array - weird.
802 // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
803 a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);
804
805 length = a.length;
806 tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
807 for (i = 0; i < length; i += 1) {
808 tail[i >> 2] |= a[i] << ((i % 4) << 3);
809 }
810
811 tail[i >> 2] |= 0x80 << ((i % 4) << 3);
812 if (i > 55) {
813 md5cycle(state, tail);
814 for (i = 0; i < 16; i += 1) {
815 tail[i] = 0;
816 }
817 }
818
819 // Beware that the final length might not fit in 32 bits so we take care of that
820 tmp = n * 8;
821 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
822 lo = parseInt(tmp[2], 16);
823 hi = parseInt(tmp[1], 16) || 0;
824
825 tail[14] = lo;
826 tail[15] = hi;
827
828 md5cycle(state, tail);
829
830 return state;
831 }
832
833 function rhex(n) {
834 var s = '',
835 j;
836 for (j = 0; j < 4; j += 1) {
837 s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];
838 }
839 return s;
840 }
841
842 function hex(x) {
843 var i;
844 for (i = 0; i < x.length; i += 1) {
845 x[i] = rhex(x[i]);
846 }
847 return x.join('');
848 }
849
850 // In some cases the fast add32 function cannot be used..
851 if (hex(md51('hello')) !== '5d41402abc4b2a76b9719d911017c592') {
852 add32 = function (x, y) {
853 var lsw = (x & 0xFFFF) + (y & 0xFFFF),
854 msw = (x >> 16) + (y >> 16) + (lsw >> 16);
855 return (msw << 16) | (lsw & 0xFFFF);
856 };
857 }
858
859 // ---------------------------------------------------
860
861 /**
862 * ArrayBuffer slice polyfill.
863 *
864 * @see https://github.com/ttaubert/node-arraybuffer-slice
865 */
866
867 if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {
868 (function () {
869 function clamp(val, length) {
870 val = (val | 0) || 0;
871
872 if (val < 0) {
873 return Math.max(val + length, 0);
874 }
875
876 return Math.min(val, length);
877 }
878
879 ArrayBuffer.prototype.slice = function (from, to) {
880 var length = this.byteLength,
881 begin = clamp(from, length),
882 end = length,
883 num,
884 target,
885 targetArray,
886 sourceArray;
887
888 if (to !== undefined) {
889 end = clamp(to, length);
890 }
891
892 if (begin > end) {
893 return new ArrayBuffer(0);
894 }
895
896 num = end - begin;
897 target = new ArrayBuffer(num);
898 targetArray = new Uint8Array(target);
899
900 sourceArray = new Uint8Array(this, begin, num);
901 targetArray.set(sourceArray);
902
903 return target;
904 };
905 })();
906 }
907
908 // ---------------------------------------------------
909
910 /**
911 * Helpers.
912 */
913
914 function toUtf8(str) {
915 if (/[\u0080-\uFFFF]/.test(str)) {
916 str = unescape(encodeURIComponent(str));
917 }
918
919 return str;
920 }
921
922 function utf8Str2ArrayBuffer(str, returnUInt8Array) {
923 var length = str.length,
924 buff = new ArrayBuffer(length),
925 arr = new Uint8Array(buff),
926 i;
927
928 for (i = 0; i < length; i += 1) {
929 arr[i] = str.charCodeAt(i);
930 }
931
932 return returnUInt8Array ? arr : buff;
933 }
934
935 function arrayBuffer2Utf8Str(buff) {
936 return String.fromCharCode.apply(null, new Uint8Array(buff));
937 }
938
939 function concatenateArrayBuffers(first, second, returnUInt8Array) {
940 var result = new Uint8Array(first.byteLength + second.byteLength);
941
942 result.set(new Uint8Array(first));
943 result.set(new Uint8Array(second), first.byteLength);
944
945 return returnUInt8Array ? result : result.buffer;
946 }
947
948 function hexToBinaryString(hex) {
949 var bytes = [],
950 length = hex.length,
951 x;
952
953 for (x = 0; x < length - 1; x += 2) {
954 bytes.push(parseInt(hex.substr(x, 2), 16));
955 }
956
957 return String.fromCharCode.apply(String, bytes);
958 }
959
960 // ---------------------------------------------------
961
962 /**
963 * SparkMD5 OOP implementation.
964 *
965 * Use this class to perform an incremental md5, otherwise use the
966 * static methods instead.
967 */
968
969 function SparkMD5() {
970 // call reset to init the instance
971 this.reset();
972 }
973
974 /**
975 * Appends a string.
976 * A conversion will be applied if an utf8 string is detected.
977 *
978 * @param {String} str The string to be appended
979 *
980 * @return {SparkMD5} The instance itself
981 */
982 SparkMD5.prototype.append = function (str) {
983 // Converts the string to utf8 bytes if necessary
984 // Then append as binary
985 this.appendBinary(toUtf8(str));
986
987 return this;
988 };
989
990 /**
991 * Appends a binary string.
992 *
993 * @param {String} contents The binary string to be appended
994 *
995 * @return {SparkMD5} The instance itself
996 */
997 SparkMD5.prototype.appendBinary = function (contents) {
998 this._buff += contents;
999 this._length += contents.length;
1000
1001 var length = this._buff.length,
1002 i;
1003
1004 for (i = 64; i <= length; i += 64) {
1005 md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
1006 }
1007
1008 this._buff = this._buff.substring(i - 64);
1009
1010 return this;
1011 };
1012
1013 /**
1014 * Finishes the incremental computation, reseting the internal state and
1015 * returning the result.
1016 *
1017 * @param {Boolean} raw True to get the raw string, false to get the hex string
1018 *
1019 * @return {String} The result
1020 */
1021 SparkMD5.prototype.end = function (raw) {
1022 var buff = this._buff,
1023 length = buff.length,
1024 i,
1025 tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1026 ret;
1027
1028 for (i = 0; i < length; i += 1) {
1029 tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);
1030 }
1031
1032 this._finish(tail, length);
1033 ret = hex(this._hash);
1034
1035 if (raw) {
1036 ret = hexToBinaryString(ret);
1037 }
1038
1039 this.reset();
1040
1041 return ret;
1042 };
1043
1044 /**
1045 * Resets the internal state of the computation.
1046 *
1047 * @return {SparkMD5} The instance itself
1048 */
1049 SparkMD5.prototype.reset = function () {
1050 this._buff = '';
1051 this._length = 0;
1052 this._hash = [1732584193, -271733879, -1732584194, 271733878];
1053
1054 return this;
1055 };
1056
1057 /**
1058 * Gets the internal state of the computation.
1059 *
1060 * @return {Object} The state
1061 */
1062 SparkMD5.prototype.getState = function () {
1063 return {
1064 buff: this._buff,
1065 length: this._length,
1066 hash: this._hash.slice()
1067 };
1068 };
1069
1070 /**
1071 * Gets the internal state of the computation.
1072 *
1073 * @param {Object} state The state
1074 *
1075 * @return {SparkMD5} The instance itself
1076 */
1077 SparkMD5.prototype.setState = function (state) {
1078 this._buff = state.buff;
1079 this._length = state.length;
1080 this._hash = state.hash;
1081
1082 return this;
1083 };
1084
1085 /**
1086 * Releases memory used by the incremental buffer and other additional
1087 * resources. If you plan to use the instance again, use reset instead.
1088 */
1089 SparkMD5.prototype.destroy = function () {
1090 delete this._hash;
1091 delete this._buff;
1092 delete this._length;
1093 };
1094
1095 /**
1096 * Finish the final calculation based on the tail.
1097 *
1098 * @param {Array} tail The tail (will be modified)
1099 * @param {Number} length The length of the remaining buffer
1100 */
1101 SparkMD5.prototype._finish = function (tail, length) {
1102 var i = length,
1103 tmp,
1104 lo,
1105 hi;
1106
1107 tail[i >> 2] |= 0x80 << ((i % 4) << 3);
1108 if (i > 55) {
1109 md5cycle(this._hash, tail);
1110 for (i = 0; i < 16; i += 1) {
1111 tail[i] = 0;
1112 }
1113 }
1114
1115 // Do the final computation based on the tail and length
1116 // Beware that the final length may not fit in 32 bits so we take care of that
1117 tmp = this._length * 8;
1118 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
1119 lo = parseInt(tmp[2], 16);
1120 hi = parseInt(tmp[1], 16) || 0;
1121
1122 tail[14] = lo;
1123 tail[15] = hi;
1124 md5cycle(this._hash, tail);
1125 };
1126
1127 /**
1128 * Performs the md5 hash on a string.
1129 * A conversion will be applied if utf8 string is detected.
1130 *
1131 * @param {String} str The string
1132 * @param {Boolean} [raw] True to get the raw string, false to get the hex string
1133 *
1134 * @return {String} The result
1135 */
1136 SparkMD5.hash = function (str, raw) {
1137 // Converts the string to utf8 bytes if necessary
1138 // Then compute it using the binary function
1139 return SparkMD5.hashBinary(toUtf8(str), raw);
1140 };
1141
1142 /**
1143 * Performs the md5 hash on a binary string.
1144 *
1145 * @param {String} content The binary string
1146 * @param {Boolean} [raw] True to get the raw string, false to get the hex string
1147 *
1148 * @return {String} The result
1149 */
1150 SparkMD5.hashBinary = function (content, raw) {
1151 var hash = md51(content),
1152 ret = hex(hash);
1153
1154 return raw ? hexToBinaryString(ret) : ret;
1155 };
1156
1157 // ---------------------------------------------------
1158
1159 /**
1160 * SparkMD5 OOP implementation for array buffers.
1161 *
1162 * Use this class to perform an incremental md5 ONLY for array buffers.
1163 */
1164 SparkMD5.ArrayBuffer = function () {
1165 // call reset to init the instance
1166 this.reset();
1167 };
1168
1169 /**
1170 * Appends an array buffer.
1171 *
1172 * @param {ArrayBuffer} arr The array to be appended
1173 *
1174 * @return {SparkMD5.ArrayBuffer} The instance itself
1175 */
1176 SparkMD5.ArrayBuffer.prototype.append = function (arr) {
1177 var buff = concatenateArrayBuffers(this._buff.buffer, arr, true),
1178 length = buff.length,
1179 i;
1180
1181 this._length += arr.byteLength;
1182
1183 for (i = 64; i <= length; i += 64) {
1184 md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
1185 }
1186
1187 this._buff = (i - 64) < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
1188
1189 return this;
1190 };
1191
1192 /**
1193 * Finishes the incremental computation, reseting the internal state and
1194 * returning the result.
1195 *
1196 * @param {Boolean} raw True to get the raw string, false to get the hex string
1197 *
1198 * @return {String} The result
1199 */
1200 SparkMD5.ArrayBuffer.prototype.end = function (raw) {
1201 var buff = this._buff,
1202 length = buff.length,
1203 tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1204 i,
1205 ret;
1206
1207 for (i = 0; i < length; i += 1) {
1208 tail[i >> 2] |= buff[i] << ((i % 4) << 3);
1209 }
1210
1211 this._finish(tail, length);
1212 ret = hex(this._hash);
1213
1214 if (raw) {
1215 ret = hexToBinaryString(ret);
1216 }
1217
1218 this.reset();
1219
1220 return ret;
1221 };
1222
1223 /**
1224 * Resets the internal state of the computation.
1225 *
1226 * @return {SparkMD5.ArrayBuffer} The instance itself
1227 */
1228 SparkMD5.ArrayBuffer.prototype.reset = function () {
1229 this._buff = new Uint8Array(0);
1230 this._length = 0;
1231 this._hash = [1732584193, -271733879, -1732584194, 271733878];
1232
1233 return this;
1234 };
1235
1236 /**
1237 * Gets the internal state of the computation.
1238 *
1239 * @return {Object} The state
1240 */
1241 SparkMD5.ArrayBuffer.prototype.getState = function () {
1242 var state = SparkMD5.prototype.getState.call(this);
1243
1244 // Convert buffer to a string
1245 state.buff = arrayBuffer2Utf8Str(state.buff);
1246
1247 return state;
1248 };
1249
1250 /**
1251 * Gets the internal state of the computation.
1252 *
1253 * @param {Object} state The state
1254 *
1255 * @return {SparkMD5.ArrayBuffer} The instance itself
1256 */
1257 SparkMD5.ArrayBuffer.prototype.setState = function (state) {
1258 // Convert string to buffer
1259 state.buff = utf8Str2ArrayBuffer(state.buff, true);
1260
1261 return SparkMD5.prototype.setState.call(this, state);
1262 };
1263
1264 SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
1265
1266 SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
1267
1268 /**
1269 * Performs the md5 hash on an array buffer.
1270 *
1271 * @param {ArrayBuffer} arr The array buffer
1272 * @param {Boolean} [raw] True to get the raw string, false to get the hex one
1273 *
1274 * @return {String} The result
1275 */
1276 SparkMD5.ArrayBuffer.hash = function (arr, raw) {
1277 var hash = md51_array(new Uint8Array(arr)),
1278 ret = hex(hash);
1279
1280 return raw ? hexToBinaryString(ret) : ret;
1281 };
1282
1283 return SparkMD5;
1284}));
1285
1286},{}],3:[function(_dereq_,module,exports){
1287"use strict";
1288
1289Object.defineProperty(exports, "__esModule", {
1290 value: true
1291});
1292Object.defineProperty(exports, "v1", {
1293 enumerable: true,
1294 get: function () {
1295 return _v.default;
1296 }
1297});
1298Object.defineProperty(exports, "v3", {
1299 enumerable: true,
1300 get: function () {
1301 return _v2.default;
1302 }
1303});
1304Object.defineProperty(exports, "v4", {
1305 enumerable: true,
1306 get: function () {
1307 return _v3.default;
1308 }
1309});
1310Object.defineProperty(exports, "v5", {
1311 enumerable: true,
1312 get: function () {
1313 return _v4.default;
1314 }
1315});
1316Object.defineProperty(exports, "NIL", {
1317 enumerable: true,
1318 get: function () {
1319 return _nil.default;
1320 }
1321});
1322Object.defineProperty(exports, "version", {
1323 enumerable: true,
1324 get: function () {
1325 return _version.default;
1326 }
1327});
1328Object.defineProperty(exports, "validate", {
1329 enumerable: true,
1330 get: function () {
1331 return _validate.default;
1332 }
1333});
1334Object.defineProperty(exports, "stringify", {
1335 enumerable: true,
1336 get: function () {
1337 return _stringify.default;
1338 }
1339});
1340Object.defineProperty(exports, "parse", {
1341 enumerable: true,
1342 get: function () {
1343 return _parse.default;
1344 }
1345});
1346
1347var _v = _interopRequireDefault(_dereq_("./v1.js"));
1348
1349var _v2 = _interopRequireDefault(_dereq_("./v3.js"));
1350
1351var _v3 = _interopRequireDefault(_dereq_("./v4.js"));
1352
1353var _v4 = _interopRequireDefault(_dereq_("./v5.js"));
1354
1355var _nil = _interopRequireDefault(_dereq_("./nil.js"));
1356
1357var _version = _interopRequireDefault(_dereq_("./version.js"));
1358
1359var _validate = _interopRequireDefault(_dereq_("./validate.js"));
1360
1361var _stringify = _interopRequireDefault(_dereq_("./stringify.js"));
1362
1363var _parse = _interopRequireDefault(_dereq_("./parse.js"));
1364
1365function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1366},{"./nil.js":5,"./parse.js":6,"./stringify.js":10,"./v1.js":11,"./v3.js":12,"./v4.js":14,"./v5.js":15,"./validate.js":16,"./version.js":17}],4:[function(_dereq_,module,exports){
1367"use strict";
1368
1369Object.defineProperty(exports, "__esModule", {
1370 value: true
1371});
1372exports.default = void 0;
1373
1374/*
1375 * Browser-compatible JavaScript MD5
1376 *
1377 * Modification of JavaScript MD5
1378 * https://github.com/blueimp/JavaScript-MD5
1379 *
1380 * Copyright 2011, Sebastian Tschan
1381 * https://blueimp.net
1382 *
1383 * Licensed under the MIT license:
1384 * https://opensource.org/licenses/MIT
1385 *
1386 * Based on
1387 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
1388 * Digest Algorithm, as defined in RFC 1321.
1389 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
1390 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
1391 * Distributed under the BSD License
1392 * See http://pajhome.org.uk/crypt/md5 for more info.
1393 */
1394function md5(bytes) {
1395 if (typeof bytes === 'string') {
1396 const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape
1397
1398 bytes = new Uint8Array(msg.length);
1399
1400 for (let i = 0; i < msg.length; ++i) {
1401 bytes[i] = msg.charCodeAt(i);
1402 }
1403 }
1404
1405 return md5ToHexEncodedArray(wordsToMd5(bytesToWords(bytes), bytes.length * 8));
1406}
1407/*
1408 * Convert an array of little-endian words to an array of bytes
1409 */
1410
1411
1412function md5ToHexEncodedArray(input) {
1413 const output = [];
1414 const length32 = input.length * 32;
1415 const hexTab = '0123456789abcdef';
1416
1417 for (let i = 0; i < length32; i += 8) {
1418 const x = input[i >> 5] >>> i % 32 & 0xff;
1419 const hex = parseInt(hexTab.charAt(x >>> 4 & 0x0f) + hexTab.charAt(x & 0x0f), 16);
1420 output.push(hex);
1421 }
1422
1423 return output;
1424}
1425/**
1426 * Calculate output length with padding and bit length
1427 */
1428
1429
1430function getOutputLength(inputLength8) {
1431 return (inputLength8 + 64 >>> 9 << 4) + 14 + 1;
1432}
1433/*
1434 * Calculate the MD5 of an array of little-endian words, and a bit length.
1435 */
1436
1437
1438function wordsToMd5(x, len) {
1439 /* append padding */
1440 x[len >> 5] |= 0x80 << len % 32;
1441 x[getOutputLength(len) - 1] = len;
1442 let a = 1732584193;
1443 let b = -271733879;
1444 let c = -1732584194;
1445 let d = 271733878;
1446
1447 for (let i = 0; i < x.length; i += 16) {
1448 const olda = a;
1449 const oldb = b;
1450 const oldc = c;
1451 const oldd = d;
1452 a = md5ff(a, b, c, d, x[i], 7, -680876936);
1453 d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
1454 c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
1455 b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
1456 a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
1457 d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
1458 c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
1459 b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
1460 a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
1461 d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
1462 c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
1463 b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
1464 a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
1465 d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
1466 c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
1467 b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
1468 a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
1469 d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
1470 c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
1471 b = md5gg(b, c, d, a, x[i], 20, -373897302);
1472 a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
1473 d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
1474 c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
1475 b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
1476 a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
1477 d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
1478 c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
1479 b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
1480 a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
1481 d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
1482 c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
1483 b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
1484 a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
1485 d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
1486 c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
1487 b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
1488 a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
1489 d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
1490 c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
1491 b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
1492 a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
1493 d = md5hh(d, a, b, c, x[i], 11, -358537222);
1494 c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
1495 b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
1496 a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
1497 d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
1498 c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
1499 b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
1500 a = md5ii(a, b, c, d, x[i], 6, -198630844);
1501 d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
1502 c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
1503 b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
1504 a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
1505 d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
1506 c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
1507 b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
1508 a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
1509 d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
1510 c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
1511 b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
1512 a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
1513 d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
1514 c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
1515 b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
1516 a = safeAdd(a, olda);
1517 b = safeAdd(b, oldb);
1518 c = safeAdd(c, oldc);
1519 d = safeAdd(d, oldd);
1520 }
1521
1522 return [a, b, c, d];
1523}
1524/*
1525 * Convert an array bytes to an array of little-endian words
1526 * Characters >255 have their high-byte silently ignored.
1527 */
1528
1529
1530function bytesToWords(input) {
1531 if (input.length === 0) {
1532 return [];
1533 }
1534
1535 const length8 = input.length * 8;
1536 const output = new Uint32Array(getOutputLength(length8));
1537
1538 for (let i = 0; i < length8; i += 8) {
1539 output[i >> 5] |= (input[i / 8] & 0xff) << i % 32;
1540 }
1541
1542 return output;
1543}
1544/*
1545 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
1546 * to work around bugs in some JS interpreters.
1547 */
1548
1549
1550function safeAdd(x, y) {
1551 const lsw = (x & 0xffff) + (y & 0xffff);
1552 const msw = (x >> 16) + (y >> 16) + (lsw >> 16);
1553 return msw << 16 | lsw & 0xffff;
1554}
1555/*
1556 * Bitwise rotate a 32-bit number to the left.
1557 */
1558
1559
1560function bitRotateLeft(num, cnt) {
1561 return num << cnt | num >>> 32 - cnt;
1562}
1563/*
1564 * These functions implement the four basic operations the algorithm uses.
1565 */
1566
1567
1568function md5cmn(q, a, b, x, s, t) {
1569 return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
1570}
1571
1572function md5ff(a, b, c, d, x, s, t) {
1573 return md5cmn(b & c | ~b & d, a, b, x, s, t);
1574}
1575
1576function md5gg(a, b, c, d, x, s, t) {
1577 return md5cmn(b & d | c & ~d, a, b, x, s, t);
1578}
1579
1580function md5hh(a, b, c, d, x, s, t) {
1581 return md5cmn(b ^ c ^ d, a, b, x, s, t);
1582}
1583
1584function md5ii(a, b, c, d, x, s, t) {
1585 return md5cmn(c ^ (b | ~d), a, b, x, s, t);
1586}
1587
1588var _default = md5;
1589exports.default = _default;
1590},{}],5:[function(_dereq_,module,exports){
1591"use strict";
1592
1593Object.defineProperty(exports, "__esModule", {
1594 value: true
1595});
1596exports.default = void 0;
1597var _default = '00000000-0000-0000-0000-000000000000';
1598exports.default = _default;
1599},{}],6:[function(_dereq_,module,exports){
1600"use strict";
1601
1602Object.defineProperty(exports, "__esModule", {
1603 value: true
1604});
1605exports.default = void 0;
1606
1607var _validate = _interopRequireDefault(_dereq_("./validate.js"));
1608
1609function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1610
1611function parse(uuid) {
1612 if (!(0, _validate.default)(uuid)) {
1613 throw TypeError('Invalid UUID');
1614 }
1615
1616 let v;
1617 const arr = new Uint8Array(16); // Parse ########-....-....-....-............
1618
1619 arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24;
1620 arr[1] = v >>> 16 & 0xff;
1621 arr[2] = v >>> 8 & 0xff;
1622 arr[3] = v & 0xff; // Parse ........-####-....-....-............
1623
1624 arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8;
1625 arr[5] = v & 0xff; // Parse ........-....-####-....-............
1626
1627 arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8;
1628 arr[7] = v & 0xff; // Parse ........-....-....-####-............
1629
1630 arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8;
1631 arr[9] = v & 0xff; // Parse ........-....-....-....-############
1632 // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes)
1633
1634 arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff;
1635 arr[11] = v / 0x100000000 & 0xff;
1636 arr[12] = v >>> 24 & 0xff;
1637 arr[13] = v >>> 16 & 0xff;
1638 arr[14] = v >>> 8 & 0xff;
1639 arr[15] = v & 0xff;
1640 return arr;
1641}
1642
1643var _default = parse;
1644exports.default = _default;
1645},{"./validate.js":16}],7:[function(_dereq_,module,exports){
1646"use strict";
1647
1648Object.defineProperty(exports, "__esModule", {
1649 value: true
1650});
1651exports.default = void 0;
1652var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
1653exports.default = _default;
1654},{}],8:[function(_dereq_,module,exports){
1655"use strict";
1656
1657Object.defineProperty(exports, "__esModule", {
1658 value: true
1659});
1660exports.default = rng;
1661// Unique ID creation requires a high quality random # generator. In the browser we therefore
1662// require the crypto API and do not support built-in fallback to lower quality random number
1663// generators (like Math.random()).
1664let getRandomValues;
1665const rnds8 = new Uint8Array(16);
1666
1667function rng() {
1668 // lazy load so that environments that need to polyfill have a chance to do so
1669 if (!getRandomValues) {
1670 // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also,
1671 // find the complete implementation of crypto (msCrypto) on IE11.
1672 getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);
1673
1674 if (!getRandomValues) {
1675 throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
1676 }
1677 }
1678
1679 return getRandomValues(rnds8);
1680}
1681},{}],9:[function(_dereq_,module,exports){
1682"use strict";
1683
1684Object.defineProperty(exports, "__esModule", {
1685 value: true
1686});
1687exports.default = void 0;
1688
1689// Adapted from Chris Veness' SHA1 code at
1690// http://www.movable-type.co.uk/scripts/sha1.html
1691function f(s, x, y, z) {
1692 switch (s) {
1693 case 0:
1694 return x & y ^ ~x & z;
1695
1696 case 1:
1697 return x ^ y ^ z;
1698
1699 case 2:
1700 return x & y ^ x & z ^ y & z;
1701
1702 case 3:
1703 return x ^ y ^ z;
1704 }
1705}
1706
1707function ROTL(x, n) {
1708 return x << n | x >>> 32 - n;
1709}
1710
1711function sha1(bytes) {
1712 const K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
1713 const H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
1714
1715 if (typeof bytes === 'string') {
1716 const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape
1717
1718 bytes = [];
1719
1720 for (let i = 0; i < msg.length; ++i) {
1721 bytes.push(msg.charCodeAt(i));
1722 }
1723 } else if (!Array.isArray(bytes)) {
1724 // Convert Array-like to Array
1725 bytes = Array.prototype.slice.call(bytes);
1726 }
1727
1728 bytes.push(0x80);
1729 const l = bytes.length / 4 + 2;
1730 const N = Math.ceil(l / 16);
1731 const M = new Array(N);
1732
1733 for (let i = 0; i < N; ++i) {
1734 const arr = new Uint32Array(16);
1735
1736 for (let j = 0; j < 16; ++j) {
1737 arr[j] = bytes[i * 64 + j * 4] << 24 | bytes[i * 64 + j * 4 + 1] << 16 | bytes[i * 64 + j * 4 + 2] << 8 | bytes[i * 64 + j * 4 + 3];
1738 }
1739
1740 M[i] = arr;
1741 }
1742
1743 M[N - 1][14] = (bytes.length - 1) * 8 / Math.pow(2, 32);
1744 M[N - 1][14] = Math.floor(M[N - 1][14]);
1745 M[N - 1][15] = (bytes.length - 1) * 8 & 0xffffffff;
1746
1747 for (let i = 0; i < N; ++i) {
1748 const W = new Uint32Array(80);
1749
1750 for (let t = 0; t < 16; ++t) {
1751 W[t] = M[i][t];
1752 }
1753
1754 for (let t = 16; t < 80; ++t) {
1755 W[t] = ROTL(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
1756 }
1757
1758 let a = H[0];
1759 let b = H[1];
1760 let c = H[2];
1761 let d = H[3];
1762 let e = H[4];
1763
1764 for (let t = 0; t < 80; ++t) {
1765 const s = Math.floor(t / 20);
1766 const T = ROTL(a, 5) + f(s, b, c, d) + e + K[s] + W[t] >>> 0;
1767 e = d;
1768 d = c;
1769 c = ROTL(b, 30) >>> 0;
1770 b = a;
1771 a = T;
1772 }
1773
1774 H[0] = H[0] + a >>> 0;
1775 H[1] = H[1] + b >>> 0;
1776 H[2] = H[2] + c >>> 0;
1777 H[3] = H[3] + d >>> 0;
1778 H[4] = H[4] + e >>> 0;
1779 }
1780
1781 return [H[0] >> 24 & 0xff, H[0] >> 16 & 0xff, H[0] >> 8 & 0xff, H[0] & 0xff, H[1] >> 24 & 0xff, H[1] >> 16 & 0xff, H[1] >> 8 & 0xff, H[1] & 0xff, H[2] >> 24 & 0xff, H[2] >> 16 & 0xff, H[2] >> 8 & 0xff, H[2] & 0xff, H[3] >> 24 & 0xff, H[3] >> 16 & 0xff, H[3] >> 8 & 0xff, H[3] & 0xff, H[4] >> 24 & 0xff, H[4] >> 16 & 0xff, H[4] >> 8 & 0xff, H[4] & 0xff];
1782}
1783
1784var _default = sha1;
1785exports.default = _default;
1786},{}],10:[function(_dereq_,module,exports){
1787"use strict";
1788
1789Object.defineProperty(exports, "__esModule", {
1790 value: true
1791});
1792exports.default = void 0;
1793
1794var _validate = _interopRequireDefault(_dereq_("./validate.js"));
1795
1796function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1797
1798/**
1799 * Convert array of 16 byte values to UUID string format of the form:
1800 * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
1801 */
1802const byteToHex = [];
1803
1804for (let i = 0; i < 256; ++i) {
1805 byteToHex.push((i + 0x100).toString(16).substr(1));
1806}
1807
1808function stringify(arr, offset = 0) {
1809 // Note: Be careful editing this code! It's been tuned for performance
1810 // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
1811 const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one
1812 // of the following:
1813 // - One or more input array values don't map to a hex octet (leading to
1814 // "undefined" in the uuid)
1815 // - Invalid input values for the RFC `version` or `variant` fields
1816
1817 if (!(0, _validate.default)(uuid)) {
1818 throw TypeError('Stringified UUID is invalid');
1819 }
1820
1821 return uuid;
1822}
1823
1824var _default = stringify;
1825exports.default = _default;
1826},{"./validate.js":16}],11:[function(_dereq_,module,exports){
1827"use strict";
1828
1829Object.defineProperty(exports, "__esModule", {
1830 value: true
1831});
1832exports.default = void 0;
1833
1834var _rng = _interopRequireDefault(_dereq_("./rng.js"));
1835
1836var _stringify = _interopRequireDefault(_dereq_("./stringify.js"));
1837
1838function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1839
1840// **`v1()` - Generate time-based UUID**
1841//
1842// Inspired by https://github.com/LiosK/UUID.js
1843// and http://docs.python.org/library/uuid.html
1844let _nodeId;
1845
1846let _clockseq; // Previous uuid creation time
1847
1848
1849let _lastMSecs = 0;
1850let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details
1851
1852function v1(options, buf, offset) {
1853 let i = buf && offset || 0;
1854 const b = buf || new Array(16);
1855 options = options || {};
1856 let node = options.node || _nodeId;
1857 let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not
1858 // specified. We do this lazily to minimize issues related to insufficient
1859 // system entropy. See #189
1860
1861 if (node == null || clockseq == null) {
1862 const seedBytes = options.random || (options.rng || _rng.default)();
1863
1864 if (node == null) {
1865 // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
1866 node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]];
1867 }
1868
1869 if (clockseq == null) {
1870 // Per 4.2.2, randomize (14 bit) clockseq
1871 clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
1872 }
1873 } // UUID timestamps are 100 nano-second units since the Gregorian epoch,
1874 // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
1875 // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
1876 // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
1877
1878
1879 let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock
1880 // cycle to simulate higher resolution clock
1881
1882 let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs)
1883
1884 const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression
1885
1886 if (dt < 0 && options.clockseq === undefined) {
1887 clockseq = clockseq + 1 & 0x3fff;
1888 } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
1889 // time interval
1890
1891
1892 if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
1893 nsecs = 0;
1894 } // Per 4.2.1.2 Throw error if too many uuids are requested
1895
1896
1897 if (nsecs >= 10000) {
1898 throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");
1899 }
1900
1901 _lastMSecs = msecs;
1902 _lastNSecs = nsecs;
1903 _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
1904
1905 msecs += 12219292800000; // `time_low`
1906
1907 const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
1908 b[i++] = tl >>> 24 & 0xff;
1909 b[i++] = tl >>> 16 & 0xff;
1910 b[i++] = tl >>> 8 & 0xff;
1911 b[i++] = tl & 0xff; // `time_mid`
1912
1913 const tmh = msecs / 0x100000000 * 10000 & 0xfffffff;
1914 b[i++] = tmh >>> 8 & 0xff;
1915 b[i++] = tmh & 0xff; // `time_high_and_version`
1916
1917 b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
1918
1919 b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
1920
1921 b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low`
1922
1923 b[i++] = clockseq & 0xff; // `node`
1924
1925 for (let n = 0; n < 6; ++n) {
1926 b[i + n] = node[n];
1927 }
1928
1929 return buf || (0, _stringify.default)(b);
1930}
1931
1932var _default = v1;
1933exports.default = _default;
1934},{"./rng.js":8,"./stringify.js":10}],12:[function(_dereq_,module,exports){
1935"use strict";
1936
1937Object.defineProperty(exports, "__esModule", {
1938 value: true
1939});
1940exports.default = void 0;
1941
1942var _v = _interopRequireDefault(_dereq_("./v35.js"));
1943
1944var _md = _interopRequireDefault(_dereq_("./md5.js"));
1945
1946function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1947
1948const v3 = (0, _v.default)('v3', 0x30, _md.default);
1949var _default = v3;
1950exports.default = _default;
1951},{"./md5.js":4,"./v35.js":13}],13:[function(_dereq_,module,exports){
1952"use strict";
1953
1954Object.defineProperty(exports, "__esModule", {
1955 value: true
1956});
1957exports.default = _default;
1958exports.URL = exports.DNS = void 0;
1959
1960var _stringify = _interopRequireDefault(_dereq_("./stringify.js"));
1961
1962var _parse = _interopRequireDefault(_dereq_("./parse.js"));
1963
1964function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1965
1966function stringToBytes(str) {
1967 str = unescape(encodeURIComponent(str)); // UTF8 escape
1968
1969 const bytes = [];
1970
1971 for (let i = 0; i < str.length; ++i) {
1972 bytes.push(str.charCodeAt(i));
1973 }
1974
1975 return bytes;
1976}
1977
1978const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
1979exports.DNS = DNS;
1980const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
1981exports.URL = URL;
1982
1983function _default(name, version, hashfunc) {
1984 function generateUUID(value, namespace, buf, offset) {
1985 if (typeof value === 'string') {
1986 value = stringToBytes(value);
1987 }
1988
1989 if (typeof namespace === 'string') {
1990 namespace = (0, _parse.default)(namespace);
1991 }
1992
1993 if (namespace.length !== 16) {
1994 throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)');
1995 } // Compute hash of namespace and value, Per 4.3
1996 // Future: Use spread syntax when supported on all platforms, e.g. `bytes =
1997 // hashfunc([...namespace, ... value])`
1998
1999
2000 let bytes = new Uint8Array(16 + value.length);
2001 bytes.set(namespace);
2002 bytes.set(value, namespace.length);
2003 bytes = hashfunc(bytes);
2004 bytes[6] = bytes[6] & 0x0f | version;
2005 bytes[8] = bytes[8] & 0x3f | 0x80;
2006
2007 if (buf) {
2008 offset = offset || 0;
2009
2010 for (let i = 0; i < 16; ++i) {
2011 buf[offset + i] = bytes[i];
2012 }
2013
2014 return buf;
2015 }
2016
2017 return (0, _stringify.default)(bytes);
2018 } // Function#name is not settable on some platforms (#270)
2019
2020
2021 try {
2022 generateUUID.name = name; // eslint-disable-next-line no-empty
2023 } catch (err) {} // For CommonJS default export support
2024
2025
2026 generateUUID.DNS = DNS;
2027 generateUUID.URL = URL;
2028 return generateUUID;
2029}
2030},{"./parse.js":6,"./stringify.js":10}],14:[function(_dereq_,module,exports){
2031"use strict";
2032
2033Object.defineProperty(exports, "__esModule", {
2034 value: true
2035});
2036exports.default = void 0;
2037
2038var _rng = _interopRequireDefault(_dereq_("./rng.js"));
2039
2040var _stringify = _interopRequireDefault(_dereq_("./stringify.js"));
2041
2042function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2043
2044function v4(options, buf, offset) {
2045 options = options || {};
2046
2047 const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
2048
2049
2050 rnds[6] = rnds[6] & 0x0f | 0x40;
2051 rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
2052
2053 if (buf) {
2054 offset = offset || 0;
2055
2056 for (let i = 0; i < 16; ++i) {
2057 buf[offset + i] = rnds[i];
2058 }
2059
2060 return buf;
2061 }
2062
2063 return (0, _stringify.default)(rnds);
2064}
2065
2066var _default = v4;
2067exports.default = _default;
2068},{"./rng.js":8,"./stringify.js":10}],15:[function(_dereq_,module,exports){
2069"use strict";
2070
2071Object.defineProperty(exports, "__esModule", {
2072 value: true
2073});
2074exports.default = void 0;
2075
2076var _v = _interopRequireDefault(_dereq_("./v35.js"));
2077
2078var _sha = _interopRequireDefault(_dereq_("./sha1.js"));
2079
2080function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2081
2082const v5 = (0, _v.default)('v5', 0x50, _sha.default);
2083var _default = v5;
2084exports.default = _default;
2085},{"./sha1.js":9,"./v35.js":13}],16:[function(_dereq_,module,exports){
2086"use strict";
2087
2088Object.defineProperty(exports, "__esModule", {
2089 value: true
2090});
2091exports.default = void 0;
2092
2093var _regex = _interopRequireDefault(_dereq_("./regex.js"));
2094
2095function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2096
2097function validate(uuid) {
2098 return typeof uuid === 'string' && _regex.default.test(uuid);
2099}
2100
2101var _default = validate;
2102exports.default = _default;
2103},{"./regex.js":7}],17:[function(_dereq_,module,exports){
2104"use strict";
2105
2106Object.defineProperty(exports, "__esModule", {
2107 value: true
2108});
2109exports.default = void 0;
2110
2111var _validate = _interopRequireDefault(_dereq_("./validate.js"));
2112
2113function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2114
2115function version(uuid) {
2116 if (!(0, _validate.default)(uuid)) {
2117 throw TypeError('Invalid UUID');
2118 }
2119
2120 return parseInt(uuid.substr(14, 1), 16);
2121}
2122
2123var _default = version;
2124exports.default = _default;
2125},{"./validate.js":16}],18:[function(_dereq_,module,exports){
2126'use strict';
2127
2128function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
2129
2130_dereq_('events');
2131_dereq_('uuid');
2132var Md5 = _interopDefault(_dereq_('spark-md5'));
2133
2134function isBinaryObject(object) {
2135 return (typeof ArrayBuffer !== 'undefined' && object instanceof ArrayBuffer) ||
2136 (typeof Blob !== 'undefined' && object instanceof Blob);
2137}
2138
2139/**
2140 * @template {ArrayBuffer | Blob} T
2141 * @param {T} object
2142 * @returns {T}
2143 */
2144function cloneBinaryObject(object) {
2145 return object instanceof ArrayBuffer
2146 ? object.slice(0)
2147 : object.slice(0, object.size, object.type);
2148}
2149
2150// most of this is borrowed from lodash.isPlainObject:
2151// https://github.com/fis-components/lodash.isplainobject/
2152// blob/29c358140a74f252aeb08c9eb28bef86f2217d4a/index.js
2153
2154var funcToString = Function.prototype.toString;
2155var objectCtorString = funcToString.call(Object);
2156
2157function isPlainObject(value) {
2158 var proto = Object.getPrototypeOf(value);
2159 /* istanbul ignore if */
2160 if (proto === null) { // not sure when this happens, but I guess it can
2161 return true;
2162 }
2163 var Ctor = proto.constructor;
2164 return (typeof Ctor == 'function' &&
2165 Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString);
2166}
2167
2168function clone(object) {
2169 var newObject;
2170 var i;
2171 var len;
2172
2173 if (!object || typeof object !== 'object') {
2174 return object;
2175 }
2176
2177 if (Array.isArray(object)) {
2178 newObject = [];
2179 for (i = 0, len = object.length; i < len; i++) {
2180 newObject[i] = clone(object[i]);
2181 }
2182 return newObject;
2183 }
2184
2185 // special case: to avoid inconsistencies between IndexedDB
2186 // and other backends, we automatically stringify Dates
2187 if (object instanceof Date && isFinite(object)) {
2188 return object.toISOString();
2189 }
2190
2191 if (isBinaryObject(object)) {
2192 return cloneBinaryObject(object);
2193 }
2194
2195 if (!isPlainObject(object)) {
2196 return object; // don't clone objects like Workers
2197 }
2198
2199 newObject = {};
2200 for (i in object) {
2201 /* istanbul ignore else */
2202 if (Object.prototype.hasOwnProperty.call(object, i)) {
2203 var value = clone(object[i]);
2204 if (typeof value !== 'undefined') {
2205 newObject[i] = value;
2206 }
2207 }
2208 }
2209 return newObject;
2210}
2211
2212// like underscore/lodash _.pick()
2213
2214var hasLocal;
2215
2216try {
2217 localStorage.setItem('_pouch_check_localstorage', 1);
2218 hasLocal = !!localStorage.getItem('_pouch_check_localstorage');
2219} catch (e) {
2220 hasLocal = false;
2221}
2222
2223const nextTick = typeof queueMicrotask === "function"
2224 ? queueMicrotask
2225 : function nextTick(fn) {
2226 Promise.resolve().then(fn);
2227 };
2228
2229function guardedConsole(method) {
2230 /* istanbul ignore else */
2231 if (typeof console !== 'undefined' && typeof console[method] === 'function') {
2232 var args = Array.prototype.slice.call(arguments, 1);
2233 console[method].apply(console, args);
2234 }
2235}
2236
2237class PouchError extends Error {
2238 constructor(status, error, reason) {
2239 super();
2240 this.status = status;
2241 this.name = error;
2242 this.message = reason;
2243 this.error = true;
2244 }
2245
2246 toString() {
2247 return JSON.stringify({
2248 status: this.status,
2249 name: this.name,
2250 message: this.message,
2251 reason: this.reason
2252 });
2253 }
2254}
2255
2256var UNAUTHORIZED = new PouchError(401, 'unauthorized', "Name or password is incorrect.");
2257var MISSING_BULK_DOCS = new PouchError(400, 'bad_request', "Missing JSON list of 'docs'");
2258var MISSING_DOC = new PouchError(404, 'not_found', 'missing');
2259var REV_CONFLICT = new PouchError(409, 'conflict', 'Document update conflict');
2260var INVALID_ID = new PouchError(400, 'bad_request', '_id field must contain a string');
2261var MISSING_ID = new PouchError(412, 'missing_id', '_id is required for puts');
2262var RESERVED_ID = new PouchError(400, 'bad_request', 'Only reserved document ids may start with underscore.');
2263var NOT_OPEN = new PouchError(412, 'precondition_failed', 'Database not open');
2264var UNKNOWN_ERROR = new PouchError(500, 'unknown_error', 'Database encountered an unknown error');
2265var BAD_ARG = new PouchError(500, 'badarg', 'Some query argument is invalid');
2266var INVALID_REQUEST = new PouchError(400, 'invalid_request', 'Request was invalid');
2267var QUERY_PARSE_ERROR = new PouchError(400, 'query_parse_error', 'Some query parameter is invalid');
2268var DOC_VALIDATION = new PouchError(500, 'doc_validation', 'Bad special document member');
2269var BAD_REQUEST = new PouchError(400, 'bad_request', 'Something wrong with the request');
2270var NOT_AN_OBJECT = new PouchError(400, 'bad_request', 'Document must be a JSON object');
2271var DB_MISSING = new PouchError(404, 'not_found', 'Database not found');
2272var IDB_ERROR = new PouchError(500, 'indexed_db_went_bad', 'unknown');
2273var WSQ_ERROR = new PouchError(500, 'web_sql_went_bad', 'unknown');
2274var LDB_ERROR = new PouchError(500, 'levelDB_went_went_bad', 'unknown');
2275var FORBIDDEN = new PouchError(403, 'forbidden', 'Forbidden by design doc validate_doc_update function');
2276var INVALID_REV = new PouchError(400, 'bad_request', 'Invalid rev format');
2277var FILE_EXISTS = new PouchError(412, 'file_exists', 'The database could not be created, the file already exists.');
2278var MISSING_STUB = new PouchError(412, 'missing_stub', 'A pre-existing attachment stub wasn\'t found');
2279var INVALID_URL = new PouchError(413, 'invalid_url', 'Provided URL is invalid');
2280
2281function createError(error, reason) {
2282 function CustomPouchError(reason) {
2283 // inherit error properties from our parent error manually
2284 // so as to allow proper JSON parsing.
2285 var names = Object.getOwnPropertyNames(error);
2286 for (var i = 0, len = names.length; i < len; i++) {
2287 if (typeof error[names[i]] !== 'function') {
2288 this[names[i]] = error[names[i]];
2289 }
2290 }
2291
2292 if (this.stack === undefined) {
2293 this.stack = (new Error()).stack;
2294 }
2295
2296 if (reason !== undefined) {
2297 this.reason = reason;
2298 }
2299 }
2300 CustomPouchError.prototype = PouchError.prototype;
2301 return new CustomPouchError(reason);
2302}
2303
2304function generateErrorFromResponse(err) {
2305
2306 if (typeof err !== 'object') {
2307 var data = err;
2308 err = UNKNOWN_ERROR;
2309 err.data = data;
2310 }
2311
2312 if ('error' in err && err.error === 'conflict') {
2313 err.name = 'conflict';
2314 err.status = 409;
2315 }
2316
2317 if (!('name' in err)) {
2318 err.name = err.error || 'unknown';
2319 }
2320
2321 if (!('status' in err)) {
2322 err.status = 500;
2323 }
2324
2325 if (!('message' in err)) {
2326 err.message = err.message || err.reason;
2327 }
2328
2329 if (!('stack' in err)) {
2330 err.stack = (new Error()).stack;
2331 }
2332
2333 return err;
2334}
2335
2336// shim for Function.prototype.name,
2337
2338// Checks if a PouchDB object is "remote" or not. This is
2339
2340function isRemote(db) {
2341 if (typeof db._remote === 'boolean') {
2342 return db._remote;
2343 }
2344 /* istanbul ignore next */
2345 if (typeof db.type === 'function') {
2346 guardedConsole('warn',
2347 'db.type() is deprecated and will be removed in ' +
2348 'a future version of PouchDB');
2349 return db.type() === 'http';
2350 }
2351 /* istanbul ignore next */
2352 return false;
2353}
2354
2355// originally parseUri 1.2.2, now patched by us
2356
2357// Based on https://github.com/alexdavid/scope-eval v0.0.3
2358
2359// this is essentially the "update sugar" function from daleharvey/pouchdb#1388
2360// the diffFun tells us what delta to apply to the doc. it either returns
2361// the doc, or false if it doesn't need to do an update after all
2362function upsert(db, docId, diffFun) {
2363 return db.get(docId)
2364 .catch(function (err) {
2365 /* istanbul ignore next */
2366 if (err.status !== 404) {
2367 throw err;
2368 }
2369 return {};
2370 })
2371 .then(function (doc) {
2372 // the user might change the _rev, so save it for posterity
2373 var docRev = doc._rev;
2374 var newDoc = diffFun(doc);
2375
2376 if (!newDoc) {
2377 // if the diffFun returns falsy, we short-circuit as
2378 // an optimization
2379 return {updated: false, rev: docRev};
2380 }
2381
2382 // users aren't allowed to modify these values,
2383 // so reset them here
2384 newDoc._id = docId;
2385 newDoc._rev = docRev;
2386 return tryAndPut(db, newDoc, diffFun);
2387 });
2388}
2389
2390function tryAndPut(db, doc, diffFun) {
2391 return db.put(doc).then(function (res) {
2392 return {
2393 updated: true,
2394 rev: res.rev
2395 };
2396 }, function (err) {
2397 /* istanbul ignore next */
2398 if (err.status !== 409) {
2399 throw err;
2400 }
2401 return upsert(db, doc._id, diffFun);
2402 });
2403}
2404
2405var thisAtob = function (str) {
2406 return atob(str);
2407};
2408
2409// Abstracts constructing a Blob object, so it also works in older
2410// browsers that don't support the native Blob constructor (e.g.
2411// old QtWebKit versions, Android < 4.4).
2412function createBlob(parts, properties) {
2413 /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */
2414 parts = parts || [];
2415 properties = properties || {};
2416 try {
2417 return new Blob(parts, properties);
2418 } catch (e) {
2419 if (e.name !== "TypeError") {
2420 throw e;
2421 }
2422 var Builder = typeof BlobBuilder !== 'undefined' ? BlobBuilder :
2423 typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder :
2424 typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder :
2425 WebKitBlobBuilder;
2426 var builder = new Builder();
2427 for (var i = 0; i < parts.length; i += 1) {
2428 builder.append(parts[i]);
2429 }
2430 return builder.getBlob(properties.type);
2431 }
2432}
2433
2434// From http://stackoverflow.com/questions/14967647/ (continues on next line)
2435// encode-decode-image-with-base64-breaks-image (2013-04-21)
2436function binaryStringToArrayBuffer(bin) {
2437 var length = bin.length;
2438 var buf = new ArrayBuffer(length);
2439 var arr = new Uint8Array(buf);
2440 for (var i = 0; i < length; i++) {
2441 arr[i] = bin.charCodeAt(i);
2442 }
2443 return buf;
2444}
2445
2446function binStringToBluffer(binString, type) {
2447 return createBlob([binaryStringToArrayBuffer(binString)], {type});
2448}
2449
2450function b64ToBluffer(b64, type) {
2451 return binStringToBluffer(thisAtob(b64), type);
2452}
2453
2454//Can't find original post, but this is close
2455
2456// simplified API. universal browser support is assumed
2457
2458// this is not used in the browser
2459
2460var setImmediateShim = self.setImmediate || self.setTimeout;
2461
2462function stringMd5(string) {
2463 return Md5.hash(string);
2464}
2465
2466// this would just be "return doc[field]", but fields
2467// can be "deep" due to dot notation
2468function getFieldFromDoc(doc, parsedField) {
2469 var value = doc;
2470 for (var i = 0, len = parsedField.length; i < len; i++) {
2471 var key = parsedField[i];
2472 value = value[key];
2473 if (!value) {
2474 break;
2475 }
2476 }
2477 return value;
2478}
2479
2480function setFieldInDoc(doc, parsedField, value) {
2481 for (var i = 0, len = parsedField.length; i < len-1; i++) {
2482 var elem = parsedField[i];
2483 doc = doc[elem] = doc[elem] || {};
2484 }
2485 doc[parsedField[len-1]] = value;
2486}
2487
2488function compare(left, right) {
2489 return left < right ? -1 : left > right ? 1 : 0;
2490}
2491
2492// Converts a string in dot notation to an array of its components, with backslash escaping
2493function parseField(fieldName) {
2494 // fields may be deep (e.g. "foo.bar.baz"), so parse
2495 var fields = [];
2496 var current = '';
2497 for (var i = 0, len = fieldName.length; i < len; i++) {
2498 var ch = fieldName[i];
2499 if (i > 0 && fieldName[i - 1] === '\\' && (ch === '$' || ch === '.')) {
2500 // escaped delimiter
2501 current = current.substring(0, current.length - 1) + ch;
2502 } else if (ch === '.') {
2503 // When `.` is not escaped (above), it is a field delimiter
2504 fields.push(current);
2505 current = '';
2506 } else { // normal character
2507 current += ch;
2508 }
2509 }
2510 fields.push(current);
2511 return fields;
2512}
2513
2514var combinationFields = ['$or', '$nor', '$not'];
2515function isCombinationalField(field) {
2516 return combinationFields.indexOf(field) > -1;
2517}
2518
2519function getKey(obj) {
2520 return Object.keys(obj)[0];
2521}
2522
2523function getValue(obj) {
2524 return obj[getKey(obj)];
2525}
2526
2527
2528// flatten an array of selectors joined by an $and operator
2529function mergeAndedSelectors(selectors) {
2530
2531 // sort to ensure that e.g. if the user specified
2532 // $and: [{$gt: 'a'}, {$gt: 'b'}], then it's collapsed into
2533 // just {$gt: 'b'}
2534 var res = {};
2535 var first = {$or: true, $nor: true};
2536
2537 selectors.forEach(function (selector) {
2538 Object.keys(selector).forEach(function (field) {
2539 var matcher = selector[field];
2540 if (typeof matcher !== 'object') {
2541 matcher = {$eq: matcher};
2542 }
2543
2544 if (isCombinationalField(field)) {
2545 // or, nor
2546 if (matcher instanceof Array) {
2547 if (first[field]) {
2548 first[field] = false;
2549 res[field] = matcher;
2550 return;
2551 }
2552
2553 var entries = [];
2554 res[field].forEach(function (existing) {
2555 Object.keys(matcher).forEach(function (key) {
2556 var m = matcher[key];
2557 var longest = Math.max(Object.keys(existing).length, Object.keys(m).length);
2558 var merged = mergeAndedSelectors([existing, m]);
2559 if (Object.keys(merged).length <= longest) {
2560 // we have a situation like: (a :{$eq :1} || ...) && (a {$eq: 2} || ...)
2561 // merging would produce a $eq 2 when actually we shouldn't ever match against these merged conditions
2562 // merged should always contain more values to be valid
2563 return;
2564 }
2565 entries.push(merged);
2566 });
2567 });
2568 res[field] = entries;
2569 } else {
2570 // not
2571 res[field] = mergeAndedSelectors([matcher]);
2572 }
2573 } else {
2574 var fieldMatchers = res[field] = res[field] || {};
2575 Object.keys(matcher).forEach(function (operator) {
2576 var value = matcher[operator];
2577
2578 if (operator === '$gt' || operator === '$gte') {
2579 return mergeGtGte(operator, value, fieldMatchers);
2580 } else if (operator === '$lt' || operator === '$lte') {
2581 return mergeLtLte(operator, value, fieldMatchers);
2582 } else if (operator === '$ne') {
2583 return mergeNe(value, fieldMatchers);
2584 } else if (operator === '$eq') {
2585 return mergeEq(value, fieldMatchers);
2586 } else if (operator === "$regex") {
2587 return mergeRegex(value, fieldMatchers);
2588 }
2589 fieldMatchers[operator] = value;
2590 });
2591 }
2592 });
2593 });
2594
2595 return res;
2596}
2597
2598
2599
2600// collapse logically equivalent gt/gte values
2601function mergeGtGte(operator, value, fieldMatchers) {
2602 if (typeof fieldMatchers.$eq !== 'undefined') {
2603 return; // do nothing
2604 }
2605 if (typeof fieldMatchers.$gte !== 'undefined') {
2606 if (operator === '$gte') {
2607 if (value > fieldMatchers.$gte) { // more specificity
2608 fieldMatchers.$gte = value;
2609 }
2610 } else { // operator === '$gt'
2611 if (value >= fieldMatchers.$gte) { // more specificity
2612 delete fieldMatchers.$gte;
2613 fieldMatchers.$gt = value;
2614 }
2615 }
2616 } else if (typeof fieldMatchers.$gt !== 'undefined') {
2617 if (operator === '$gte') {
2618 if (value > fieldMatchers.$gt) { // more specificity
2619 delete fieldMatchers.$gt;
2620 fieldMatchers.$gte = value;
2621 }
2622 } else { // operator === '$gt'
2623 if (value > fieldMatchers.$gt) { // more specificity
2624 fieldMatchers.$gt = value;
2625 }
2626 }
2627 } else {
2628 fieldMatchers[operator] = value;
2629 }
2630}
2631
2632// collapse logically equivalent lt/lte values
2633function mergeLtLte(operator, value, fieldMatchers) {
2634 if (typeof fieldMatchers.$eq !== 'undefined') {
2635 return; // do nothing
2636 }
2637 if (typeof fieldMatchers.$lte !== 'undefined') {
2638 if (operator === '$lte') {
2639 if (value < fieldMatchers.$lte) { // more specificity
2640 fieldMatchers.$lte = value;
2641 }
2642 } else { // operator === '$gt'
2643 if (value <= fieldMatchers.$lte) { // more specificity
2644 delete fieldMatchers.$lte;
2645 fieldMatchers.$lt = value;
2646 }
2647 }
2648 } else if (typeof fieldMatchers.$lt !== 'undefined') {
2649 if (operator === '$lte') {
2650 if (value < fieldMatchers.$lt) { // more specificity
2651 delete fieldMatchers.$lt;
2652 fieldMatchers.$lte = value;
2653 }
2654 } else { // operator === '$gt'
2655 if (value < fieldMatchers.$lt) { // more specificity
2656 fieldMatchers.$lt = value;
2657 }
2658 }
2659 } else {
2660 fieldMatchers[operator] = value;
2661 }
2662}
2663
2664// combine $ne values into one array
2665function mergeNe(value, fieldMatchers) {
2666 if ('$ne' in fieldMatchers) {
2667 // there are many things this could "not" be
2668 fieldMatchers.$ne.push(value);
2669 } else { // doesn't exist yet
2670 fieldMatchers.$ne = [value];
2671 }
2672}
2673
2674// add $eq into the mix
2675function mergeEq(value, fieldMatchers) {
2676 // these all have less specificity than the $eq
2677 // TODO: check for user errors here
2678 delete fieldMatchers.$gt;
2679 delete fieldMatchers.$gte;
2680 delete fieldMatchers.$lt;
2681 delete fieldMatchers.$lte;
2682 delete fieldMatchers.$ne;
2683 fieldMatchers.$eq = value;
2684}
2685
2686// combine $regex values into one array
2687function mergeRegex(value, fieldMatchers) {
2688 if ('$regex' in fieldMatchers) {
2689 // a value could match multiple regexes
2690 fieldMatchers.$regex.push(value);
2691 } else { // doesn't exist yet
2692 fieldMatchers.$regex = [value];
2693 }
2694}
2695
2696//#7458: execute function mergeAndedSelectors on nested $and
2697function mergeAndedSelectorsNested(obj) {
2698 for (var prop in obj) {
2699 if (Array.isArray(obj)) {
2700 for (var i in obj) {
2701 if (obj[i]['$and']) {
2702 obj[i] = mergeAndedSelectors(obj[i]['$and']);
2703 }
2704 }
2705 }
2706 var value = obj[prop];
2707 if (typeof value === 'object') {
2708 mergeAndedSelectorsNested(value); // <- recursive call
2709 }
2710 }
2711 return obj;
2712}
2713
2714//#7458: determine id $and is present in selector (at any level)
2715function isAndInSelector(obj, isAnd) {
2716 for (var prop in obj) {
2717 if (prop === '$and') {
2718 isAnd = true;
2719 }
2720 var value = obj[prop];
2721 if (typeof value === 'object') {
2722 isAnd = isAndInSelector(value, isAnd); // <- recursive call
2723 }
2724 }
2725 return isAnd;
2726}
2727
2728//
2729// normalize the selector
2730//
2731function massageSelector(input) {
2732 var result = clone(input);
2733
2734 //#7458: if $and is present in selector (at any level) merge nested $and
2735 if (isAndInSelector(result, false)) {
2736 result = mergeAndedSelectorsNested(result);
2737 if ('$and' in result) {
2738 result = mergeAndedSelectors(result['$and']);
2739 }
2740 }
2741
2742 ['$or', '$nor'].forEach(function (orOrNor) {
2743 if (orOrNor in result) {
2744 // message each individual selector
2745 // e.g. {foo: 'bar'} becomes {foo: {$eq: 'bar'}}
2746 result[orOrNor].forEach(function (subSelector) {
2747 var fields = Object.keys(subSelector);
2748 for (var i = 0; i < fields.length; i++) {
2749 var field = fields[i];
2750 var matcher = subSelector[field];
2751 if (typeof matcher !== 'object' || matcher === null) {
2752 subSelector[field] = {$eq: matcher};
2753 }
2754 }
2755 });
2756 }
2757 });
2758
2759 if ('$not' in result) {
2760 //This feels a little like forcing, but it will work for now,
2761 //I would like to come back to this and make the merging of selectors a little more generic
2762 result['$not'] = mergeAndedSelectors([result['$not']]);
2763 }
2764
2765 var fields = Object.keys(result);
2766
2767 for (var i = 0; i < fields.length; i++) {
2768 var field = fields[i];
2769 var matcher = result[field];
2770
2771 if (typeof matcher !== 'object' || matcher === null) {
2772 matcher = {$eq: matcher};
2773 }
2774 result[field] = matcher;
2775 }
2776
2777 normalizeArrayOperators(result);
2778
2779 return result;
2780}
2781
2782//
2783// The $ne and $regex values must be placed in an array because these operators can be used multiple times on the same field.
2784// When $and is used, mergeAndedSelectors takes care of putting some of them into arrays, otherwise it's done here.
2785//
2786function normalizeArrayOperators(selector) {
2787 Object.keys(selector).forEach(function (field) {
2788 var matcher = selector[field];
2789
2790 if (Array.isArray(matcher)) {
2791 matcher.forEach(function (matcherItem) {
2792 if (matcherItem && typeof matcherItem === 'object') {
2793 normalizeArrayOperators(matcherItem);
2794 }
2795 });
2796 } else if (field === '$ne') {
2797 selector.$ne = [matcher];
2798 } else if (field === '$regex') {
2799 selector.$regex = [matcher];
2800 } else if (matcher && typeof matcher === 'object') {
2801 normalizeArrayOperators(matcher);
2802 }
2803 });
2804}
2805
2806function pad(str, padWith, upToLength) {
2807 var padding = '';
2808 var targetLength = upToLength - str.length;
2809 /* istanbul ignore next */
2810 while (padding.length < targetLength) {
2811 padding += padWith;
2812 }
2813 return padding;
2814}
2815
2816function padLeft(str, padWith, upToLength) {
2817 var padding = pad(str, padWith, upToLength);
2818 return padding + str;
2819}
2820
2821var MIN_MAGNITUDE = -324; // verified by -Number.MIN_VALUE
2822var MAGNITUDE_DIGITS = 3; // ditto
2823var SEP = ''; // set to '_' for easier debugging
2824
2825function collate(a, b) {
2826
2827 if (a === b) {
2828 return 0;
2829 }
2830
2831 a = normalizeKey(a);
2832 b = normalizeKey(b);
2833
2834 var ai = collationIndex(a);
2835 var bi = collationIndex(b);
2836 if ((ai - bi) !== 0) {
2837 return ai - bi;
2838 }
2839 switch (typeof a) {
2840 case 'number':
2841 return a - b;
2842 case 'boolean':
2843 return a < b ? -1 : 1;
2844 case 'string':
2845 return stringCollate(a, b);
2846 }
2847 return Array.isArray(a) ? arrayCollate(a, b) : objectCollate(a, b);
2848}
2849
2850// couch considers null/NaN/Infinity/-Infinity === undefined,
2851// for the purposes of mapreduce indexes. also, dates get stringified.
2852function normalizeKey(key) {
2853 switch (typeof key) {
2854 case 'undefined':
2855 return null;
2856 case 'number':
2857 if (key === Infinity || key === -Infinity || isNaN(key)) {
2858 return null;
2859 }
2860 return key;
2861 case 'object':
2862 var origKey = key;
2863 if (Array.isArray(key)) {
2864 var len = key.length;
2865 key = new Array(len);
2866 for (var i = 0; i < len; i++) {
2867 key[i] = normalizeKey(origKey[i]);
2868 }
2869 /* istanbul ignore next */
2870 } else if (key instanceof Date) {
2871 return key.toJSON();
2872 } else if (key !== null) { // generic object
2873 key = {};
2874 for (var k in origKey) {
2875 if (Object.prototype.hasOwnProperty.call(origKey, k)) {
2876 var val = origKey[k];
2877 if (typeof val !== 'undefined') {
2878 key[k] = normalizeKey(val);
2879 }
2880 }
2881 }
2882 }
2883 }
2884 return key;
2885}
2886
2887function indexify(key) {
2888 if (key !== null) {
2889 switch (typeof key) {
2890 case 'boolean':
2891 return key ? 1 : 0;
2892 case 'number':
2893 return numToIndexableString(key);
2894 case 'string':
2895 // We've to be sure that key does not contain \u0000
2896 // Do order-preserving replacements:
2897 // 0 -> 1, 1
2898 // 1 -> 1, 2
2899 // 2 -> 2, 2
2900 /* eslint-disable no-control-regex */
2901 return key
2902 .replace(/\u0002/g, '\u0002\u0002')
2903 .replace(/\u0001/g, '\u0001\u0002')
2904 .replace(/\u0000/g, '\u0001\u0001');
2905 /* eslint-enable no-control-regex */
2906 case 'object':
2907 var isArray = Array.isArray(key);
2908 var arr = isArray ? key : Object.keys(key);
2909 var i = -1;
2910 var len = arr.length;
2911 var result = '';
2912 if (isArray) {
2913 while (++i < len) {
2914 result += toIndexableString(arr[i]);
2915 }
2916 } else {
2917 while (++i < len) {
2918 var objKey = arr[i];
2919 result += toIndexableString(objKey) +
2920 toIndexableString(key[objKey]);
2921 }
2922 }
2923 return result;
2924 }
2925 }
2926 return '';
2927}
2928
2929// convert the given key to a string that would be appropriate
2930// for lexical sorting, e.g. within a database, where the
2931// sorting is the same given by the collate() function.
2932function toIndexableString(key) {
2933 var zero = '\u0000';
2934 key = normalizeKey(key);
2935 return collationIndex(key) + SEP + indexify(key) + zero;
2936}
2937
2938function parseNumber(str, i) {
2939 var originalIdx = i;
2940 var num;
2941 var zero = str[i] === '1';
2942 if (zero) {
2943 num = 0;
2944 i++;
2945 } else {
2946 var neg = str[i] === '0';
2947 i++;
2948 var numAsString = '';
2949 var magAsString = str.substring(i, i + MAGNITUDE_DIGITS);
2950 var magnitude = parseInt(magAsString, 10) + MIN_MAGNITUDE;
2951 /* istanbul ignore next */
2952 if (neg) {
2953 magnitude = -magnitude;
2954 }
2955 i += MAGNITUDE_DIGITS;
2956 while (true) {
2957 var ch = str[i];
2958 if (ch === '\u0000') {
2959 break;
2960 } else {
2961 numAsString += ch;
2962 }
2963 i++;
2964 }
2965 numAsString = numAsString.split('.');
2966 if (numAsString.length === 1) {
2967 num = parseInt(numAsString, 10);
2968 } else {
2969 /* istanbul ignore next */
2970 num = parseFloat(numAsString[0] + '.' + numAsString[1]);
2971 }
2972 /* istanbul ignore next */
2973 if (neg) {
2974 num = num - 10;
2975 }
2976 /* istanbul ignore next */
2977 if (magnitude !== 0) {
2978 // parseFloat is more reliable than pow due to rounding errors
2979 // e.g. Number.MAX_VALUE would return Infinity if we did
2980 // num * Math.pow(10, magnitude);
2981 num = parseFloat(num + 'e' + magnitude);
2982 }
2983 }
2984 return {num, length : i - originalIdx};
2985}
2986
2987// move up the stack while parsing
2988// this function moved outside of parseIndexableString for performance
2989function pop(stack, metaStack) {
2990 var obj = stack.pop();
2991
2992 if (metaStack.length) {
2993 var lastMetaElement = metaStack[metaStack.length - 1];
2994 if (obj === lastMetaElement.element) {
2995 // popping a meta-element, e.g. an object whose value is another object
2996 metaStack.pop();
2997 lastMetaElement = metaStack[metaStack.length - 1];
2998 }
2999 var element = lastMetaElement.element;
3000 var lastElementIndex = lastMetaElement.index;
3001 if (Array.isArray(element)) {
3002 element.push(obj);
3003 } else if (lastElementIndex === stack.length - 2) { // obj with key+value
3004 var key = stack.pop();
3005 element[key] = obj;
3006 } else {
3007 stack.push(obj); // obj with key only
3008 }
3009 }
3010}
3011
3012function parseIndexableString(str) {
3013 var stack = [];
3014 var metaStack = []; // stack for arrays and objects
3015 var i = 0;
3016
3017 /*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
3018 while (true) {
3019 var collationIndex = str[i++];
3020 if (collationIndex === '\u0000') {
3021 if (stack.length === 1) {
3022 return stack.pop();
3023 } else {
3024 pop(stack, metaStack);
3025 continue;
3026 }
3027 }
3028 switch (collationIndex) {
3029 case '1':
3030 stack.push(null);
3031 break;
3032 case '2':
3033 stack.push(str[i] === '1');
3034 i++;
3035 break;
3036 case '3':
3037 var parsedNum = parseNumber(str, i);
3038 stack.push(parsedNum.num);
3039 i += parsedNum.length;
3040 break;
3041 case '4':
3042 var parsedStr = '';
3043 /*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
3044 while (true) {
3045 var ch = str[i];
3046 if (ch === '\u0000') {
3047 break;
3048 }
3049 parsedStr += ch;
3050 i++;
3051 }
3052 // perform the reverse of the order-preserving replacement
3053 // algorithm (see above)
3054 /* eslint-disable no-control-regex */
3055 parsedStr = parsedStr.replace(/\u0001\u0001/g, '\u0000')
3056 .replace(/\u0001\u0002/g, '\u0001')
3057 .replace(/\u0002\u0002/g, '\u0002');
3058 /* eslint-enable no-control-regex */
3059 stack.push(parsedStr);
3060 break;
3061 case '5':
3062 var arrayElement = { element: [], index: stack.length };
3063 stack.push(arrayElement.element);
3064 metaStack.push(arrayElement);
3065 break;
3066 case '6':
3067 var objElement = { element: {}, index: stack.length };
3068 stack.push(objElement.element);
3069 metaStack.push(objElement);
3070 break;
3071 /* istanbul ignore next */
3072 default:
3073 throw new Error(
3074 'bad collationIndex or unexpectedly reached end of input: ' +
3075 collationIndex);
3076 }
3077 }
3078}
3079
3080function arrayCollate(a, b) {
3081 var len = Math.min(a.length, b.length);
3082 for (var i = 0; i < len; i++) {
3083 var sort = collate(a[i], b[i]);
3084 if (sort !== 0) {
3085 return sort;
3086 }
3087 }
3088 return (a.length === b.length) ? 0 :
3089 (a.length > b.length) ? 1 : -1;
3090}
3091function stringCollate(a, b) {
3092 // See: https://github.com/daleharvey/pouchdb/issues/40
3093 // This is incompatible with the CouchDB implementation, but its the
3094 // best we can do for now
3095 return (a === b) ? 0 : ((a > b) ? 1 : -1);
3096}
3097function objectCollate(a, b) {
3098 var ak = Object.keys(a), bk = Object.keys(b);
3099 var len = Math.min(ak.length, bk.length);
3100 for (var i = 0; i < len; i++) {
3101 // First sort the keys
3102 var sort = collate(ak[i], bk[i]);
3103 if (sort !== 0) {
3104 return sort;
3105 }
3106 // if the keys are equal sort the values
3107 sort = collate(a[ak[i]], b[bk[i]]);
3108 if (sort !== 0) {
3109 return sort;
3110 }
3111
3112 }
3113 return (ak.length === bk.length) ? 0 :
3114 (ak.length > bk.length) ? 1 : -1;
3115}
3116// The collation is defined by erlangs ordered terms
3117// the atoms null, true, false come first, then numbers, strings,
3118// arrays, then objects
3119// null/undefined/NaN/Infinity/-Infinity are all considered null
3120function collationIndex(x) {
3121 var id = ['boolean', 'number', 'string', 'object'];
3122 var idx = id.indexOf(typeof x);
3123 //false if -1 otherwise true, but fast!!!!1
3124 if (~idx) {
3125 if (x === null) {
3126 return 1;
3127 }
3128 if (Array.isArray(x)) {
3129 return 5;
3130 }
3131 return idx < 3 ? (idx + 2) : (idx + 3);
3132 }
3133 /* istanbul ignore next */
3134 if (Array.isArray(x)) {
3135 return 5;
3136 }
3137}
3138
3139// conversion:
3140// x yyy zz...zz
3141// x = 0 for negative, 1 for 0, 2 for positive
3142// y = exponent (for negative numbers negated) moved so that it's >= 0
3143// z = mantisse
3144function numToIndexableString(num) {
3145
3146 if (num === 0) {
3147 return '1';
3148 }
3149
3150 // convert number to exponential format for easier and
3151 // more succinct string sorting
3152 var expFormat = num.toExponential().split(/e\+?/);
3153 var magnitude = parseInt(expFormat[1], 10);
3154
3155 var neg = num < 0;
3156
3157 var result = neg ? '0' : '2';
3158
3159 // first sort by magnitude
3160 // it's easier if all magnitudes are positive
3161 var magForComparison = ((neg ? -magnitude : magnitude) - MIN_MAGNITUDE);
3162 var magString = padLeft((magForComparison).toString(), '0', MAGNITUDE_DIGITS);
3163
3164 result += SEP + magString;
3165
3166 // then sort by the factor
3167 var factor = Math.abs(parseFloat(expFormat[0])); // [1..10)
3168 /* istanbul ignore next */
3169 if (neg) { // for negative reverse ordering
3170 factor = 10 - factor;
3171 }
3172
3173 var factorStr = factor.toFixed(20);
3174
3175 // strip zeros from the end
3176 factorStr = factorStr.replace(/\.?0+$/, '');
3177
3178 result += SEP + factorStr;
3179
3180 return result;
3181}
3182
3183// create a comparator based on the sort object
3184function createFieldSorter(sort) {
3185
3186 function getFieldValuesAsArray(doc) {
3187 return sort.map(function (sorting) {
3188 var fieldName = getKey(sorting);
3189 var parsedField = parseField(fieldName);
3190 var docFieldValue = getFieldFromDoc(doc, parsedField);
3191 return docFieldValue;
3192 });
3193 }
3194
3195 return function (aRow, bRow) {
3196 var aFieldValues = getFieldValuesAsArray(aRow.doc);
3197 var bFieldValues = getFieldValuesAsArray(bRow.doc);
3198 var collation = collate(aFieldValues, bFieldValues);
3199 if (collation !== 0) {
3200 return collation;
3201 }
3202 // this is what mango seems to do
3203 return compare(aRow.doc._id, bRow.doc._id);
3204 };
3205}
3206
3207function filterInMemoryFields(rows, requestDef, inMemoryFields) {
3208 rows = rows.filter(function (row) {
3209 return rowFilter(row.doc, requestDef.selector, inMemoryFields);
3210 });
3211
3212 if (requestDef.sort) {
3213 // in-memory sort
3214 var fieldSorter = createFieldSorter(requestDef.sort);
3215 rows = rows.sort(fieldSorter);
3216 if (typeof requestDef.sort[0] !== 'string' &&
3217 getValue(requestDef.sort[0]) === 'desc') {
3218 rows = rows.reverse();
3219 }
3220 }
3221
3222 if ('limit' in requestDef || 'skip' in requestDef) {
3223 // have to do the limit in-memory
3224 var skip = requestDef.skip || 0;
3225 var limit = ('limit' in requestDef ? requestDef.limit : rows.length) + skip;
3226 rows = rows.slice(skip, limit);
3227 }
3228 return rows;
3229}
3230
3231function rowFilter(doc, selector, inMemoryFields) {
3232 return inMemoryFields.every(function (field) {
3233 var matcher = selector[field];
3234 var parsedField = parseField(field);
3235 var docFieldValue = getFieldFromDoc(doc, parsedField);
3236 if (isCombinationalField(field)) {
3237 return matchCominationalSelector(field, matcher, doc);
3238 }
3239
3240 return matchSelector(matcher, doc, parsedField, docFieldValue);
3241 });
3242}
3243
3244function matchSelector(matcher, doc, parsedField, docFieldValue) {
3245 if (!matcher) {
3246 // no filtering necessary; this field is just needed for sorting
3247 return true;
3248 }
3249
3250 // is matcher an object, if so continue recursion
3251 if (typeof matcher === 'object') {
3252 return Object.keys(matcher).every(function (maybeUserOperator) {
3253 var userValue = matcher[ maybeUserOperator ];
3254 // explicit operator
3255 if (maybeUserOperator.indexOf("$") === 0) {
3256 return match(maybeUserOperator, doc, userValue, parsedField, docFieldValue);
3257 } else {
3258 var subParsedField = parseField(maybeUserOperator);
3259
3260 if (
3261 docFieldValue === undefined &&
3262 typeof userValue !== "object" &&
3263 subParsedField.length > 0
3264 ) {
3265 // the field does not exist, return or getFieldFromDoc will throw
3266 return false;
3267 }
3268
3269 var subDocFieldValue = getFieldFromDoc(docFieldValue, subParsedField);
3270
3271 if (typeof userValue === "object") {
3272 // field value is an object that might contain more operators
3273 return matchSelector(userValue, doc, parsedField, subDocFieldValue);
3274 }
3275
3276 // implicit operator
3277 return match("$eq", doc, userValue, subParsedField, subDocFieldValue);
3278 }
3279 });
3280 }
3281
3282 // no more depth, No need to recurse further
3283 return matcher === docFieldValue;
3284}
3285
3286function matchCominationalSelector(field, matcher, doc) {
3287
3288 if (field === '$or') {
3289 return matcher.some(function (orMatchers) {
3290 return rowFilter(doc, orMatchers, Object.keys(orMatchers));
3291 });
3292 }
3293
3294 if (field === '$not') {
3295 return !rowFilter(doc, matcher, Object.keys(matcher));
3296 }
3297
3298 //`$nor`
3299 return !matcher.find(function (orMatchers) {
3300 return rowFilter(doc, orMatchers, Object.keys(orMatchers));
3301 });
3302
3303}
3304
3305function match(userOperator, doc, userValue, parsedField, docFieldValue) {
3306 if (!matchers[userOperator]) {
3307 /* istanbul ignore next */
3308 throw new Error('unknown operator "' + userOperator +
3309 '" - should be one of $eq, $lte, $lt, $gt, $gte, $exists, $ne, $in, ' +
3310 '$nin, $size, $mod, $regex, $elemMatch, $type, $allMatch or $all');
3311 }
3312 return matchers[userOperator](doc, userValue, parsedField, docFieldValue);
3313}
3314
3315function fieldExists(docFieldValue) {
3316 return typeof docFieldValue !== 'undefined' && docFieldValue !== null;
3317}
3318
3319function fieldIsNotUndefined(docFieldValue) {
3320 return typeof docFieldValue !== 'undefined';
3321}
3322
3323function modField(docFieldValue, userValue) {
3324 if (typeof docFieldValue !== "number" ||
3325 parseInt(docFieldValue, 10) !== docFieldValue) {
3326 return false;
3327 }
3328
3329 var divisor = userValue[0];
3330 var mod = userValue[1];
3331
3332 return docFieldValue % divisor === mod;
3333}
3334
3335function arrayContainsValue(docFieldValue, userValue) {
3336 return userValue.some(function (val) {
3337 if (docFieldValue instanceof Array) {
3338 return docFieldValue.some(function (docFieldValueItem) {
3339 return collate(val, docFieldValueItem) === 0;
3340 });
3341 }
3342
3343 return collate(val, docFieldValue) === 0;
3344 });
3345}
3346
3347function arrayContainsAllValues(docFieldValue, userValue) {
3348 return userValue.every(function (val) {
3349 return docFieldValue.some(function (docFieldValueItem) {
3350 return collate(val, docFieldValueItem) === 0;
3351 });
3352 });
3353}
3354
3355function arraySize(docFieldValue, userValue) {
3356 return docFieldValue.length === userValue;
3357}
3358
3359function regexMatch(docFieldValue, userValue) {
3360 var re = new RegExp(userValue);
3361
3362 return re.test(docFieldValue);
3363}
3364
3365function typeMatch(docFieldValue, userValue) {
3366
3367 switch (userValue) {
3368 case 'null':
3369 return docFieldValue === null;
3370 case 'boolean':
3371 return typeof (docFieldValue) === 'boolean';
3372 case 'number':
3373 return typeof (docFieldValue) === 'number';
3374 case 'string':
3375 return typeof (docFieldValue) === 'string';
3376 case 'array':
3377 return docFieldValue instanceof Array;
3378 case 'object':
3379 return ({}).toString.call(docFieldValue) === '[object Object]';
3380 }
3381}
3382
3383var matchers = {
3384
3385 '$elemMatch': function (doc, userValue, parsedField, docFieldValue) {
3386 if (!Array.isArray(docFieldValue)) {
3387 return false;
3388 }
3389
3390 if (docFieldValue.length === 0) {
3391 return false;
3392 }
3393
3394 if (typeof docFieldValue[0] === 'object' && docFieldValue[0] !== null) {
3395 return docFieldValue.some(function (val) {
3396 return rowFilter(val, userValue, Object.keys(userValue));
3397 });
3398 }
3399
3400 return docFieldValue.some(function (val) {
3401 return matchSelector(userValue, doc, parsedField, val);
3402 });
3403 },
3404
3405 '$allMatch': function (doc, userValue, parsedField, docFieldValue) {
3406 if (!Array.isArray(docFieldValue)) {
3407 return false;
3408 }
3409
3410 /* istanbul ignore next */
3411 if (docFieldValue.length === 0) {
3412 return false;
3413 }
3414
3415 if (typeof docFieldValue[0] === 'object' && docFieldValue[0] !== null) {
3416 return docFieldValue.every(function (val) {
3417 return rowFilter(val, userValue, Object.keys(userValue));
3418 });
3419 }
3420
3421 return docFieldValue.every(function (val) {
3422 return matchSelector(userValue, doc, parsedField, val);
3423 });
3424 },
3425
3426 '$eq': function (doc, userValue, parsedField, docFieldValue) {
3427 return fieldIsNotUndefined(docFieldValue) && collate(docFieldValue, userValue) === 0;
3428 },
3429
3430 '$gte': function (doc, userValue, parsedField, docFieldValue) {
3431 return fieldIsNotUndefined(docFieldValue) && collate(docFieldValue, userValue) >= 0;
3432 },
3433
3434 '$gt': function (doc, userValue, parsedField, docFieldValue) {
3435 return fieldIsNotUndefined(docFieldValue) && collate(docFieldValue, userValue) > 0;
3436 },
3437
3438 '$lte': function (doc, userValue, parsedField, docFieldValue) {
3439 return fieldIsNotUndefined(docFieldValue) && collate(docFieldValue, userValue) <= 0;
3440 },
3441
3442 '$lt': function (doc, userValue, parsedField, docFieldValue) {
3443 return fieldIsNotUndefined(docFieldValue) && collate(docFieldValue, userValue) < 0;
3444 },
3445
3446 '$exists': function (doc, userValue, parsedField, docFieldValue) {
3447 //a field that is null is still considered to exist
3448 if (userValue) {
3449 return fieldIsNotUndefined(docFieldValue);
3450 }
3451
3452 return !fieldIsNotUndefined(docFieldValue);
3453 },
3454
3455 '$mod': function (doc, userValue, parsedField, docFieldValue) {
3456 return fieldExists(docFieldValue) && modField(docFieldValue, userValue);
3457 },
3458
3459 '$ne': function (doc, userValue, parsedField, docFieldValue) {
3460 return userValue.every(function (neValue) {
3461 return collate(docFieldValue, neValue) !== 0;
3462 });
3463 },
3464 '$in': function (doc, userValue, parsedField, docFieldValue) {
3465 return fieldExists(docFieldValue) && arrayContainsValue(docFieldValue, userValue);
3466 },
3467
3468 '$nin': function (doc, userValue, parsedField, docFieldValue) {
3469 return fieldExists(docFieldValue) && !arrayContainsValue(docFieldValue, userValue);
3470 },
3471
3472 '$size': function (doc, userValue, parsedField, docFieldValue) {
3473 return fieldExists(docFieldValue) &&
3474 Array.isArray(docFieldValue) &&
3475 arraySize(docFieldValue, userValue);
3476 },
3477
3478 '$all': function (doc, userValue, parsedField, docFieldValue) {
3479 return Array.isArray(docFieldValue) && arrayContainsAllValues(docFieldValue, userValue);
3480 },
3481
3482 '$regex': function (doc, userValue, parsedField, docFieldValue) {
3483 return fieldExists(docFieldValue) &&
3484 typeof docFieldValue == "string" &&
3485 userValue.every(function (regexValue) {
3486 return regexMatch(docFieldValue, regexValue);
3487 });
3488 },
3489
3490 '$type': function (doc, userValue, parsedField, docFieldValue) {
3491 return typeMatch(docFieldValue, userValue);
3492 }
3493};
3494
3495// return true if the given doc matches the supplied selector
3496function matchesSelector(doc, selector) {
3497 /* istanbul ignore if */
3498 if (typeof selector !== 'object') {
3499 // match the CouchDB error message
3500 throw new Error('Selector error: expected a JSON object');
3501 }
3502
3503 selector = massageSelector(selector);
3504 var row = {
3505 doc
3506 };
3507
3508 var rowsMatched = filterInMemoryFields([row], { selector }, Object.keys(selector));
3509 return rowsMatched && rowsMatched.length === 1;
3510}
3511
3512const nativeFlat = (...args) => args.flat(Infinity);
3513
3514const polyFlat = (...args) => {
3515 let res = [];
3516 for (const subArr of args) {
3517 if (Array.isArray(subArr)) {
3518 res = res.concat(polyFlat(...subArr));
3519 } else {
3520 res.push(subArr);
3521 }
3522 }
3523 return res;
3524};
3525
3526const flatten = typeof Array.prototype.flat === 'function'
3527 ? nativeFlat
3528 : polyFlat;
3529
3530function mergeObjects(arr) {
3531 const res = {};
3532 for (const element of arr) {
3533 Object.assign(res, element);
3534 }
3535 return res;
3536}
3537
3538// Selects a list of fields defined in dot notation from one doc
3539// and copies them to a new doc. Like underscore _.pick but supports nesting.
3540function pick$1(obj, arr) {
3541 const res = {};
3542 for (const field of arr) {
3543 const parsedField = parseField(field);
3544 const value = getFieldFromDoc(obj, parsedField);
3545 if (typeof value !== 'undefined') {
3546 setFieldInDoc(res, parsedField, value);
3547 }
3548 }
3549 return res;
3550}
3551
3552// e.g. ['a'], ['a', 'b'] is true, but ['b'], ['a', 'b'] is false
3553function oneArrayIsSubArrayOfOther(left, right) {
3554 for (let i = 0, len = Math.min(left.length, right.length); i < len; i++) {
3555 if (left[i] !== right[i]) {
3556 return false;
3557 }
3558 }
3559 return true;
3560}
3561
3562// e.g.['a', 'b', 'c'], ['a', 'b'] is false
3563function oneArrayIsStrictSubArrayOfOther(left, right) {
3564 if (left.length > right.length) {
3565 return false;
3566 }
3567
3568 return oneArrayIsSubArrayOfOther(left, right);
3569}
3570
3571// same as above, but treat the left array as an unordered set
3572// e.g. ['b', 'a'], ['a', 'b', 'c'] is true, but ['c'], ['a', 'b', 'c'] is false
3573function oneSetIsSubArrayOfOther(left, right) {
3574 left = left.slice();
3575 for (const field of right) {
3576 if (!left.length) {
3577 break;
3578 }
3579 const leftIdx = left.indexOf(field);
3580 if (leftIdx === -1) {
3581 return false;
3582 } else {
3583 left.splice(leftIdx, 1);
3584 }
3585 }
3586 return true;
3587}
3588
3589function arrayToObject(arr) {
3590 const res = {};
3591 for (const field of arr) {
3592 res[field] = true;
3593 }
3594 return res;
3595}
3596
3597function max(arr, fun) {
3598 let max = null;
3599 let maxScore = -1;
3600 for (const element of arr) {
3601 const score = fun(element);
3602 if (score > maxScore) {
3603 maxScore = score;
3604 max = element;
3605 }
3606 }
3607 return max;
3608}
3609
3610function arrayEquals(arr1, arr2) {
3611 if (arr1.length !== arr2.length) {
3612 return false;
3613 }
3614 for (let i = 0, len = arr1.length; i < len; i++) {
3615 if (arr1[i] !== arr2[i]) {
3616 return false;
3617 }
3618 }
3619 return true;
3620}
3621
3622function uniq(arr) {
3623 return Array.from(new Set(arr));
3624}
3625
3626/**
3627 * Callbackifyable wrapper for async functions
3628 *
3629 * @template T, Args
3630 * @param {(...args: Args) => Promise<T>} fun
3631 * @returns {<CBArgs = [...Args, (err: any, value: T) => void], InnerArgs extends Args | CBArgs>(...innerArgs: InnerArgs) => InnerArgs extends CBArgs ? void : Promise<T>}
3632 *
3633 * @example
3634 * const fn = resolveToCallback(async () => { return 42; })
3635 * // with callback:
3636 * fn((err, value) => { ... })
3637 * // with await:
3638 * const value = await fn()
3639 */
3640function resolveToCallback(fun) {
3641 return function (...args) {
3642 const maybeCallback = args[args.length - 1];
3643 if (typeof maybeCallback === "function") {
3644 const fulfilled = maybeCallback.bind(null, null);
3645 const rejected = maybeCallback.bind(null);
3646 fun.apply(this, args.slice(0, -1)).then(fulfilled, rejected);
3647 } else {
3648 return fun.apply(this, args);
3649 }
3650 };
3651}
3652
3653var h = Headers;
3654
3655// we restructure the supplied JSON considerably, because the official
3656// Mango API is very particular about a lot of this stuff, but we like
3657// to be liberal with what we accept in order to prevent mental
3658// breakdowns in our users
3659function massageCreateIndexRequest(requestDef) {
3660 requestDef = clone(requestDef);
3661
3662 if (!requestDef.index) {
3663 requestDef.index = {};
3664 }
3665
3666 for (const key of ['type', 'name', 'ddoc']) {
3667 if (requestDef.index[key]) {
3668 requestDef[key] = requestDef.index[key];
3669 delete requestDef.index[key];
3670 }
3671 }
3672
3673 if (requestDef.fields) {
3674 requestDef.index.fields = requestDef.fields;
3675 delete requestDef.fields;
3676 }
3677
3678 if (!requestDef.type) {
3679 requestDef.type = 'json';
3680 }
3681 return requestDef;
3682}
3683
3684function isNonNullObject(value) {
3685 return typeof value === 'object' && value !== null;
3686}
3687
3688// throws if the user is using the wrong query field value type
3689function checkFieldValueType(name, value, isHttp) {
3690 let message = '';
3691 let received = value;
3692 let addReceived = true;
3693 if (['$in', '$nin', '$or', '$and', '$mod', '$nor', '$all'].indexOf(name) !== -1) {
3694 if (!Array.isArray(value)) {
3695 message = 'Query operator ' + name + ' must be an array.';
3696
3697 }
3698 }
3699
3700 if (['$not', '$elemMatch', '$allMatch'].indexOf(name) !== -1) {
3701 if (!(!Array.isArray(value) && isNonNullObject(value))) {
3702 message = 'Query operator ' + name + ' must be an object.';
3703 }
3704 }
3705
3706 if (name === '$mod' && Array.isArray(value)) {
3707 if (value.length !== 2) {
3708 message = 'Query operator $mod must be in the format [divisor, remainder], ' +
3709 'where divisor and remainder are both integers.';
3710 } else {
3711 const divisor = value[0];
3712 const mod = value[1];
3713 if (divisor === 0) {
3714 message = 'Query operator $mod\'s divisor cannot be 0, cannot divide by zero.';
3715 addReceived = false;
3716 }
3717 if (typeof divisor !== 'number' || parseInt(divisor, 10) !== divisor) {
3718 message = 'Query operator $mod\'s divisor is not an integer.';
3719 received = divisor;
3720 }
3721 if (parseInt(mod, 10) !== mod) {
3722 message = 'Query operator $mod\'s remainder is not an integer.';
3723 received = mod;
3724 }
3725 }
3726 }
3727 if (name === '$exists') {
3728 if (typeof value !== 'boolean') {
3729 message = 'Query operator $exists must be a boolean.';
3730 }
3731 }
3732
3733 if (name === '$type') {
3734 const allowed = ['null', 'boolean', 'number', 'string', 'array', 'object'];
3735 const allowedStr = '"' + allowed.slice(0, allowed.length - 1).join('", "') + '", or "' + allowed[allowed.length - 1] + '"';
3736 if (typeof value !== 'string') {
3737 message = 'Query operator $type must be a string. Supported values: ' + allowedStr + '.';
3738 } else if (allowed.indexOf(value) == -1) {
3739 message = 'Query operator $type must be a string. Supported values: ' + allowedStr + '.';
3740 }
3741 }
3742
3743 if (name === '$size') {
3744 if (parseInt(value, 10) !== value) {
3745 message = 'Query operator $size must be a integer.';
3746 }
3747 }
3748
3749 if (name === '$regex') {
3750 if (typeof value !== 'string') {
3751 if (isHttp) {
3752 message = 'Query operator $regex must be a string.';
3753 } else if (!(value instanceof RegExp)) {
3754 message = 'Query operator $regex must be a string or an instance ' +
3755 'of a javascript regular expression.';
3756 }
3757 }
3758 }
3759
3760 if (message) {
3761 if (addReceived) {
3762 const type = received === null
3763 ? ' '
3764 : Array.isArray(received)
3765 ? ' array'
3766 : ' ' + typeof received;
3767 const receivedStr = isNonNullObject(received)
3768 ? JSON.stringify(received, null, '\t')
3769 : received;
3770
3771 message += ' Received' + type + ': ' + receivedStr;
3772 }
3773 throw new Error(message);
3774 }
3775}
3776
3777const requireValidation = ['$all', '$allMatch', '$and', '$elemMatch', '$exists', '$in', '$mod', '$nin', '$nor', '$not', '$or', '$regex', '$size', '$type'];
3778const arrayTypeComparisonOperators = ['$in', '$nin', '$mod', '$all'];
3779const equalityOperators = ['$eq', '$gt', '$gte', '$lt', '$lte'];
3780
3781// recursively walks down the a query selector validating any operators
3782function validateSelector(input, isHttp) {
3783 if (Array.isArray(input)) {
3784 for (const entry of input) {
3785 if (isNonNullObject(entry)) {
3786 validateSelector(entry, isHttp);
3787 }
3788 }
3789 }
3790 else {
3791 for (const [key, value] of Object.entries(input)) {
3792 if (requireValidation.indexOf(key) !== -1) {
3793 checkFieldValueType(key, value, isHttp);
3794 }
3795 if (equalityOperators.indexOf(key) !== -1) {
3796 // skip, explicit comparison operators can be anything
3797 continue;
3798 }
3799 if (arrayTypeComparisonOperators.indexOf(key) !== -1) {
3800 // skip, their values are already valid
3801 continue;
3802 }
3803 if (isNonNullObject(value)) {
3804 validateSelector(value, isHttp);
3805 }
3806 }
3807 }
3808}
3809
3810async function dbFetch(db, path, opts) {
3811 if (opts.body) {
3812 opts.body = JSON.stringify(opts.body);
3813 opts.headers = new h({ 'Content-type': 'application/json' });
3814 }
3815
3816 const response = await db.fetch(path, opts);
3817 const json = await response.json();
3818 if (!response.ok) {
3819 json.status = response.status;
3820 const pouchError = createError(json);
3821 throw generateErrorFromResponse(pouchError);
3822 }
3823 return json;
3824}
3825
3826async function createIndex(db, requestDef) {
3827 return await dbFetch(db, '_index', {
3828 method: 'POST',
3829 body: massageCreateIndexRequest(requestDef)
3830 });
3831}
3832
3833async function find(db, requestDef) {
3834 validateSelector(requestDef.selector, true);
3835 return await dbFetch(db, '_find', {
3836 method: 'POST',
3837 body: requestDef
3838 });
3839}
3840
3841async function explain(db, requestDef) {
3842 return await dbFetch(db, '_explain', {
3843 method: 'POST',
3844 body: requestDef
3845 });
3846}
3847
3848async function getIndexes(db) {
3849 return await dbFetch(db, '_index', {
3850 method: 'GET'
3851 });
3852}
3853
3854async function deleteIndex(db, indexDef) {
3855 const ddoc = indexDef.ddoc;
3856 const type = indexDef.type || 'json';
3857 const name = indexDef.name;
3858
3859 if (!ddoc) {
3860 throw new Error('you must provide an index\'s ddoc');
3861 }
3862
3863 if (!name) {
3864 throw new Error('you must provide an index\'s name');
3865 }
3866
3867 const url = '_index/' + [ddoc, type, name].map(encodeURIComponent).join('/');
3868
3869 return await dbFetch(db, url, { method: 'DELETE' });
3870}
3871
3872/*
3873 * Simple task queue to sequentialize actions. Assumes
3874 * callbacks will eventually fire (once).
3875 */
3876
3877class TaskQueue {
3878 constructor() {
3879 this.promise = Promise.resolve();
3880 }
3881
3882 add(promiseFactory) {
3883 this.promise = this.promise
3884 // just recover
3885 .catch(() => { })
3886 .then(() => promiseFactory());
3887 return this.promise;
3888 }
3889
3890 finish() {
3891 return this.promise;
3892 }
3893}
3894
3895function stringify(input) {
3896 if (!input) {
3897 return 'undefined'; // backwards compat for empty reduce
3898 }
3899 // for backwards compat with mapreduce, functions/strings are stringified
3900 // as-is. everything else is JSON-stringified.
3901 switch (typeof input) {
3902 case 'function':
3903 // e.g. a mapreduce map
3904 return input.toString();
3905 case 'string':
3906 // e.g. a mapreduce built-in _reduce function
3907 return input.toString();
3908 default:
3909 // e.g. a JSON object in the case of mango queries
3910 return JSON.stringify(input);
3911 }
3912}
3913
3914/* create a string signature for a view so we can cache it and uniq it */
3915function createViewSignature(mapFun, reduceFun) {
3916 // the "undefined" part is for backwards compatibility
3917 return stringify(mapFun) + stringify(reduceFun) + 'undefined';
3918}
3919
3920async function createView(sourceDB, viewName, mapFun, reduceFun, temporary, localDocName) {
3921 const viewSignature = createViewSignature(mapFun, reduceFun);
3922
3923 let cachedViews;
3924 if (!temporary) {
3925 // cache this to ensure we don't try to update the same view twice
3926 cachedViews = sourceDB._cachedViews = sourceDB._cachedViews || {};
3927 if (cachedViews[viewSignature]) {
3928 return cachedViews[viewSignature];
3929 }
3930 }
3931
3932 const promiseForView = sourceDB.info().then(async function (info) {
3933 const depDbName = info.db_name + '-mrview-' +
3934 (temporary ? 'temp' : stringMd5(viewSignature));
3935
3936 // save the view name in the source db so it can be cleaned up if necessary
3937 // (e.g. when the _design doc is deleted, remove all associated view data)
3938 function diffFunction(doc) {
3939 doc.views = doc.views || {};
3940 let fullViewName = viewName;
3941 if (fullViewName.indexOf('/') === -1) {
3942 fullViewName = viewName + '/' + viewName;
3943 }
3944 const depDbs = doc.views[fullViewName] = doc.views[fullViewName] || {};
3945 /* istanbul ignore if */
3946 if (depDbs[depDbName]) {
3947 return; // no update necessary
3948 }
3949 depDbs[depDbName] = true;
3950 return doc;
3951 }
3952 await upsert(sourceDB, '_local/' + localDocName, diffFunction);
3953 const res = await sourceDB.registerDependentDatabase(depDbName);
3954 const db = res.db;
3955 db.auto_compaction = true;
3956 const view = {
3957 name: depDbName,
3958 db,
3959 sourceDB,
3960 adapter: sourceDB.adapter,
3961 mapFun,
3962 reduceFun
3963 };
3964
3965 let lastSeqDoc;
3966 try {
3967 lastSeqDoc = await view.db.get('_local/lastSeq');
3968 } catch (err) {
3969 /* istanbul ignore if */
3970 if (err.status !== 404) {
3971 throw err;
3972 }
3973 }
3974
3975 view.seq = lastSeqDoc ? lastSeqDoc.seq : 0;
3976 if (cachedViews) {
3977 view.db.once('destroyed', function () {
3978 delete cachedViews[viewSignature];
3979 });
3980 }
3981 return view;
3982 });
3983
3984 if (cachedViews) {
3985 cachedViews[viewSignature] = promiseForView;
3986 }
3987 return promiseForView;
3988}
3989
3990class QueryParseError extends Error {
3991 constructor(message) {
3992 super();
3993 this.status = 400;
3994 this.name = 'query_parse_error';
3995 this.message = message;
3996 this.error = true;
3997 try {
3998 Error.captureStackTrace(this, QueryParseError);
3999 } catch (e) {}
4000 }
4001}
4002
4003class NotFoundError extends Error {
4004 constructor(message) {
4005 super();
4006 this.status = 404;
4007 this.name = 'not_found';
4008 this.message = message;
4009 this.error = true;
4010 try {
4011 Error.captureStackTrace(this, NotFoundError);
4012 } catch (e) {}
4013 }
4014}
4015
4016class BuiltInError extends Error {
4017 constructor(message) {
4018 super();
4019 this.status = 500;
4020 this.name = 'invalid_value';
4021 this.message = message;
4022 this.error = true;
4023 try {
4024 Error.captureStackTrace(this, BuiltInError);
4025 } catch (e) {}
4026 }
4027}
4028
4029function promisedCallback(promise, callback) {
4030 if (callback) {
4031 promise.then(function (res) {
4032 nextTick(function () {
4033 callback(null, res);
4034 });
4035 }, function (reason) {
4036 nextTick(function () {
4037 callback(reason);
4038 });
4039 });
4040 }
4041 return promise;
4042}
4043
4044function callbackify(fun) {
4045 return function (...args) {
4046 var cb = args.pop();
4047 var promise = fun.apply(this, args);
4048 if (typeof cb === 'function') {
4049 promisedCallback(promise, cb);
4050 }
4051 return promise;
4052 };
4053}
4054
4055// Promise finally util similar to Q.finally
4056function fin(promise, finalPromiseFactory) {
4057 return promise.then(function (res) {
4058 return finalPromiseFactory().then(function () {
4059 return res;
4060 });
4061 }, function (reason) {
4062 return finalPromiseFactory().then(function () {
4063 throw reason;
4064 });
4065 });
4066}
4067
4068function sequentialize(queue, promiseFactory) {
4069 return function () {
4070 var args = arguments;
4071 var that = this;
4072 return queue.add(function () {
4073 return promiseFactory.apply(that, args);
4074 });
4075 };
4076}
4077
4078// uniq an array of strings, order not guaranteed
4079// similar to underscore/lodash _.uniq
4080function uniq$1(arr) {
4081 var theSet = new Set(arr);
4082 var result = new Array(theSet.size);
4083 var index = -1;
4084 theSet.forEach(function (value) {
4085 result[++index] = value;
4086 });
4087 return result;
4088}
4089
4090function mapToKeysArray(map) {
4091 var result = new Array(map.size);
4092 var index = -1;
4093 map.forEach(function (value, key) {
4094 result[++index] = key;
4095 });
4096 return result;
4097}
4098
4099const persistentQueues = {};
4100const tempViewQueue = new TaskQueue();
4101const CHANGES_BATCH_SIZE = 50;
4102
4103function parseViewName(name) {
4104 // can be either 'ddocname/viewname' or just 'viewname'
4105 // (where the ddoc name is the same)
4106 return name.indexOf('/') === -1 ? [name, name] : name.split('/');
4107}
4108
4109function isGenOne(changes) {
4110 // only return true if the current change is 1-
4111 // and there are no other leafs
4112 return changes.length === 1 && /^1-/.test(changes[0].rev);
4113}
4114
4115function emitError(db, e, data) {
4116 try {
4117 db.emit('error', e);
4118 } catch (err) {
4119 guardedConsole('error',
4120 'The user\'s map/reduce function threw an uncaught error.\n' +
4121 'You can debug this error by doing:\n' +
4122 'myDatabase.on(\'error\', function (err) { debugger; });\n' +
4123 'Please double-check your map/reduce function.');
4124 guardedConsole('error', e, data);
4125 }
4126}
4127
4128/**
4129 * Returns an "abstract" mapreduce object of the form:
4130 *
4131 * {
4132 * query: queryFun,
4133 * viewCleanup: viewCleanupFun
4134 * }
4135 *
4136 * Arguments are:
4137 *
4138 * localDoc: string
4139 * This is for the local doc that gets saved in order to track the
4140 * "dependent" DBs and clean them up for viewCleanup. It should be
4141 * unique, so that indexer plugins don't collide with each other.
4142 * mapper: function (mapFunDef, emit)
4143 * Returns a map function based on the mapFunDef, which in the case of
4144 * normal map/reduce is just the de-stringified function, but may be
4145 * something else, such as an object in the case of pouchdb-find.
4146 * reducer: function (reduceFunDef)
4147 * Ditto, but for reducing. Modules don't have to support reducing
4148 * (e.g. pouchdb-find).
4149 * ddocValidator: function (ddoc, viewName)
4150 * Throws an error if the ddoc or viewName is not valid.
4151 * This could be a way to communicate to the user that the configuration for the
4152 * indexer is invalid.
4153 */
4154function createAbstractMapReduce(localDocName, mapper, reducer, ddocValidator) {
4155
4156 function tryMap(db, fun, doc) {
4157 // emit an event if there was an error thrown by a map function.
4158 // putting try/catches in a single function also avoids deoptimizations.
4159 try {
4160 fun(doc);
4161 } catch (e) {
4162 emitError(db, e, {fun, doc});
4163 }
4164 }
4165
4166 function tryReduce(db, fun, keys, values, rereduce) {
4167 // same as above, but returning the result or an error. there are two separate
4168 // functions to avoid extra memory allocations since the tryCode() case is used
4169 // for custom map functions (common) vs this function, which is only used for
4170 // custom reduce functions (rare)
4171 try {
4172 return {output : fun(keys, values, rereduce)};
4173 } catch (e) {
4174 emitError(db, e, {fun, keys, values, rereduce});
4175 return {error: e};
4176 }
4177 }
4178
4179 function sortByKeyThenValue(x, y) {
4180 const keyCompare = collate(x.key, y.key);
4181 return keyCompare !== 0 ? keyCompare : collate(x.value, y.value);
4182 }
4183
4184 function sliceResults(results, limit, skip) {
4185 skip = skip || 0;
4186 if (typeof limit === 'number') {
4187 return results.slice(skip, limit + skip);
4188 } else if (skip > 0) {
4189 return results.slice(skip);
4190 }
4191 return results;
4192 }
4193
4194 function rowToDocId(row) {
4195 const val = row.value;
4196 // Users can explicitly specify a joined doc _id, or it
4197 // defaults to the doc _id that emitted the key/value.
4198 const docId = (val && typeof val === 'object' && val._id) || row.id;
4199 return docId;
4200 }
4201
4202 function readAttachmentsAsBlobOrBuffer(res) {
4203 for (const row of res.rows) {
4204 const atts = row.doc && row.doc._attachments;
4205 if (!atts) {
4206 continue;
4207 }
4208 for (const filename of Object.keys(atts)) {
4209 const att = atts[filename];
4210 atts[filename].data = b64ToBluffer(att.data, att.content_type);
4211 }
4212 }
4213 }
4214
4215 function postprocessAttachments(opts) {
4216 return function (res) {
4217 if (opts.include_docs && opts.attachments && opts.binary) {
4218 readAttachmentsAsBlobOrBuffer(res);
4219 }
4220 return res;
4221 };
4222 }
4223
4224 function addHttpParam(paramName, opts, params, asJson) {
4225 // add an http param from opts to params, optionally json-encoded
4226 let val = opts[paramName];
4227 if (typeof val !== 'undefined') {
4228 if (asJson) {
4229 val = encodeURIComponent(JSON.stringify(val));
4230 }
4231 params.push(paramName + '=' + val);
4232 }
4233 }
4234
4235 function coerceInteger(integerCandidate) {
4236 if (typeof integerCandidate !== 'undefined') {
4237 const asNumber = Number(integerCandidate);
4238 // prevents e.g. '1foo' or '1.1' being coerced to 1
4239 if (!isNaN(asNumber) && asNumber === parseInt(integerCandidate, 10)) {
4240 return asNumber;
4241 } else {
4242 return integerCandidate;
4243 }
4244 }
4245 }
4246
4247 function coerceOptions(opts) {
4248 opts.group_level = coerceInteger(opts.group_level);
4249 opts.limit = coerceInteger(opts.limit);
4250 opts.skip = coerceInteger(opts.skip);
4251 return opts;
4252 }
4253
4254 function checkPositiveInteger(number) {
4255 if (number) {
4256 if (typeof number !== 'number') {
4257 return new QueryParseError(`Invalid value for integer: "${number}"`);
4258 }
4259 if (number < 0) {
4260 return new QueryParseError(`Invalid value for positive integer: "${number}"`);
4261 }
4262 }
4263 }
4264
4265 function checkQueryParseError(options, fun) {
4266 const startkeyName = options.descending ? 'endkey' : 'startkey';
4267 const endkeyName = options.descending ? 'startkey' : 'endkey';
4268
4269 if (typeof options[startkeyName] !== 'undefined' &&
4270 typeof options[endkeyName] !== 'undefined' &&
4271 collate(options[startkeyName], options[endkeyName]) > 0) {
4272 throw new QueryParseError('No rows can match your key range, ' +
4273 'reverse your start_key and end_key or set {descending : true}');
4274 } else if (fun.reduce && options.reduce !== false) {
4275 if (options.include_docs) {
4276 throw new QueryParseError('{include_docs:true} is invalid for reduce');
4277 } else if (options.keys && options.keys.length > 1 &&
4278 !options.group && !options.group_level) {
4279 throw new QueryParseError('Multi-key fetches for reduce views must use ' +
4280 '{group: true}');
4281 }
4282 }
4283 for (const optionName of ['group_level', 'limit', 'skip']) {
4284 const error = checkPositiveInteger(options[optionName]);
4285 if (error) {
4286 throw error;
4287 }
4288 }
4289 }
4290
4291 async function httpQuery(db, fun, opts) {
4292 // List of parameters to add to the PUT request
4293 let params = [];
4294 let body;
4295 let method = 'GET';
4296 let ok;
4297
4298 // If opts.reduce exists and is defined, then add it to the list
4299 // of parameters.
4300 // If reduce=false then the results are that of only the map function
4301 // not the final result of map and reduce.
4302 addHttpParam('reduce', opts, params);
4303 addHttpParam('include_docs', opts, params);
4304 addHttpParam('attachments', opts, params);
4305 addHttpParam('limit', opts, params);
4306 addHttpParam('descending', opts, params);
4307 addHttpParam('group', opts, params);
4308 addHttpParam('group_level', opts, params);
4309 addHttpParam('skip', opts, params);
4310 addHttpParam('stale', opts, params);
4311 addHttpParam('conflicts', opts, params);
4312 addHttpParam('startkey', opts, params, true);
4313 addHttpParam('start_key', opts, params, true);
4314 addHttpParam('endkey', opts, params, true);
4315 addHttpParam('end_key', opts, params, true);
4316 addHttpParam('inclusive_end', opts, params);
4317 addHttpParam('key', opts, params, true);
4318 addHttpParam('update_seq', opts, params);
4319
4320 // Format the list of parameters into a valid URI query string
4321 params = params.join('&');
4322 params = params === '' ? '' : '?' + params;
4323
4324 // If keys are supplied, issue a POST to circumvent GET query string limits
4325 // see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options
4326 if (typeof opts.keys !== 'undefined') {
4327 const MAX_URL_LENGTH = 2000;
4328 // according to http://stackoverflow.com/a/417184/680742,
4329 // the de facto URL length limit is 2000 characters
4330
4331 const keysAsString = `keys=${encodeURIComponent(JSON.stringify(opts.keys))}`;
4332 if (keysAsString.length + params.length + 1 <= MAX_URL_LENGTH) {
4333 // If the keys are short enough, do a GET. we do this to work around
4334 // Safari not understanding 304s on POSTs (see pouchdb/pouchdb#1239)
4335 params += (params[0] === '?' ? '&' : '?') + keysAsString;
4336 } else {
4337 method = 'POST';
4338 if (typeof fun === 'string') {
4339 body = {keys: opts.keys};
4340 } else { // fun is {map : mapfun}, so append to this
4341 fun.keys = opts.keys;
4342 }
4343 }
4344 }
4345
4346 // We are referencing a query defined in the design doc
4347 if (typeof fun === 'string') {
4348 const parts = parseViewName(fun);
4349
4350 const response = await db.fetch('_design/' + parts[0] + '/_view/' + parts[1] + params, {
4351 headers: new h({'Content-Type': 'application/json'}),
4352 method,
4353 body: JSON.stringify(body)
4354 });
4355 ok = response.ok;
4356 // status = response.status;
4357 const result = await response.json();
4358
4359 if (!ok) {
4360 result.status = response.status;
4361 throw generateErrorFromResponse(result);
4362 }
4363
4364 // fail the entire request if the result contains an error
4365 for (const row of result.rows) {
4366 /* istanbul ignore if */
4367 if (row.value && row.value.error && row.value.error === "builtin_reduce_error") {
4368 throw new Error(row.reason);
4369 }
4370 }
4371
4372 return new Promise(function (resolve) {
4373 resolve(result);
4374 }).then(postprocessAttachments(opts));
4375 }
4376
4377 // We are using a temporary view, terrible for performance, good for testing
4378 body = body || {};
4379 for (const key of Object.keys(fun)) {
4380 if (Array.isArray(fun[key])) {
4381 body[key] = fun[key];
4382 } else {
4383 body[key] = fun[key].toString();
4384 }
4385 }
4386
4387 const response = await db.fetch('_temp_view' + params, {
4388 headers: new h({'Content-Type': 'application/json'}),
4389 method: 'POST',
4390 body: JSON.stringify(body)
4391 });
4392
4393 ok = response.ok;
4394 // status = response.status;
4395 const result = await response.json();
4396 if (!ok) {
4397 result.status = response.status;
4398 throw generateErrorFromResponse(result);
4399 }
4400
4401 return new Promise(function (resolve) {
4402 resolve(result);
4403 }).then(postprocessAttachments(opts));
4404 }
4405
4406 // custom adapters can define their own api._query
4407 // and override the default behavior
4408 /* istanbul ignore next */
4409 function customQuery(db, fun, opts) {
4410 return new Promise(function (resolve, reject) {
4411 db._query(fun, opts, function (err, res) {
4412 if (err) {
4413 return reject(err);
4414 }
4415 resolve(res);
4416 });
4417 });
4418 }
4419
4420 // custom adapters can define their own api._viewCleanup
4421 // and override the default behavior
4422 /* istanbul ignore next */
4423 function customViewCleanup(db) {
4424 return new Promise(function (resolve, reject) {
4425 db._viewCleanup(function (err, res) {
4426 if (err) {
4427 return reject(err);
4428 }
4429 resolve(res);
4430 });
4431 });
4432 }
4433
4434 function defaultsTo(value) {
4435 return function (reason) {
4436 /* istanbul ignore else */
4437 if (reason.status === 404) {
4438 return value;
4439 } else {
4440 throw reason;
4441 }
4442 };
4443 }
4444
4445 // returns a promise for a list of docs to update, based on the input docId.
4446 // the order doesn't matter, because post-3.2.0, bulkDocs
4447 // is an atomic operation in all three adapters.
4448 async function getDocsToPersist(docId, view, docIdsToChangesAndEmits) {
4449 const metaDocId = '_local/doc_' + docId;
4450 const defaultMetaDoc = {_id: metaDocId, keys: []};
4451 const docData = docIdsToChangesAndEmits.get(docId);
4452 const indexableKeysToKeyValues = docData[0];
4453 const changes = docData[1];
4454
4455 function getMetaDoc() {
4456 if (isGenOne(changes)) {
4457 // generation 1, so we can safely assume initial state
4458 // for performance reasons (avoids unnecessary GETs)
4459 return Promise.resolve(defaultMetaDoc);
4460 }
4461 return view.db.get(metaDocId).catch(defaultsTo(defaultMetaDoc));
4462 }
4463
4464 function getKeyValueDocs(metaDoc) {
4465 if (!metaDoc.keys.length) {
4466 // no keys, no need for a lookup
4467 return Promise.resolve({rows: []});
4468 }
4469 return view.db.allDocs({
4470 keys: metaDoc.keys,
4471 include_docs: true
4472 });
4473 }
4474
4475 function processKeyValueDocs(metaDoc, kvDocsRes) {
4476 const kvDocs = [];
4477 const oldKeys = new Set();
4478
4479 for (const row of kvDocsRes.rows) {
4480 const doc = row.doc;
4481 if (!doc) { // deleted
4482 continue;
4483 }
4484 kvDocs.push(doc);
4485 oldKeys.add(doc._id);
4486 doc._deleted = !indexableKeysToKeyValues.has(doc._id);
4487 if (!doc._deleted) {
4488 const keyValue = indexableKeysToKeyValues.get(doc._id);
4489 if ('value' in keyValue) {
4490 doc.value = keyValue.value;
4491 }
4492 }
4493 }
4494 const newKeys = mapToKeysArray(indexableKeysToKeyValues);
4495 for (const key of newKeys) {
4496 if (!oldKeys.has(key)) {
4497 // new doc
4498 const kvDoc = {
4499 _id: key
4500 };
4501 const keyValue = indexableKeysToKeyValues.get(key);
4502 if ('value' in keyValue) {
4503 kvDoc.value = keyValue.value;
4504 }
4505 kvDocs.push(kvDoc);
4506 }
4507 }
4508 metaDoc.keys = uniq$1(newKeys.concat(metaDoc.keys));
4509 kvDocs.push(metaDoc);
4510
4511 return kvDocs;
4512 }
4513
4514 const metaDoc = await getMetaDoc();
4515 const keyValueDocs = await getKeyValueDocs(metaDoc);
4516 return processKeyValueDocs(metaDoc, keyValueDocs);
4517 }
4518
4519 function updatePurgeSeq(view) {
4520 // with this approach, we just assume to have processed all missing purges and write the latest
4521 // purgeSeq into the _local/purgeSeq doc.
4522 return view.sourceDB.get('_local/purges').then(function (res) {
4523 const purgeSeq = res.purgeSeq;
4524 return view.db.get('_local/purgeSeq').then(function (res) {
4525 return res._rev;
4526 })
4527 .catch(defaultsTo(undefined))
4528 .then(function (rev$$1) {
4529 return view.db.put({
4530 _id: '_local/purgeSeq',
4531 _rev: rev$$1,
4532 purgeSeq,
4533 });
4534 });
4535 }).catch(function (err) {
4536 if (err.status !== 404) {
4537 throw err;
4538 }
4539 });
4540 }
4541
4542 // updates all emitted key/value docs and metaDocs in the mrview database
4543 // for the given batch of documents from the source database
4544 function saveKeyValues(view, docIdsToChangesAndEmits, seq) {
4545 var seqDocId = '_local/lastSeq';
4546 return view.db.get(seqDocId)
4547 .catch(defaultsTo({_id: seqDocId, seq: 0}))
4548 .then(function (lastSeqDoc) {
4549 var docIds = mapToKeysArray(docIdsToChangesAndEmits);
4550 return Promise.all(docIds.map(function (docId) {
4551 return getDocsToPersist(docId, view, docIdsToChangesAndEmits);
4552 })).then(function (listOfDocsToPersist) {
4553 var docsToPersist = listOfDocsToPersist.flat();
4554 lastSeqDoc.seq = seq;
4555 docsToPersist.push(lastSeqDoc);
4556 // write all docs in a single operation, update the seq once
4557 return view.db.bulkDocs({docs : docsToPersist});
4558 })
4559 // TODO: this should be placed somewhere else, probably? we're querying both docs twice
4560 // (first time when getting the actual purges).
4561 .then(() => updatePurgeSeq(view));
4562 });
4563 }
4564
4565 function getQueue(view) {
4566 const viewName = typeof view === 'string' ? view : view.name;
4567 let queue = persistentQueues[viewName];
4568 if (!queue) {
4569 queue = persistentQueues[viewName] = new TaskQueue();
4570 }
4571 return queue;
4572 }
4573
4574 async function updateView(view, opts) {
4575 return sequentialize(getQueue(view), function () {
4576 return updateViewInQueue(view, opts);
4577 })();
4578 }
4579
4580 async function updateViewInQueue(view, opts) {
4581 // bind the emit function once
4582 let mapResults;
4583 let doc;
4584 let taskId;
4585
4586 function emit(key, value) {
4587 const output = {id: doc._id, key: normalizeKey(key)};
4588 // Don't explicitly store the value unless it's defined and non-null.
4589 // This saves on storage space, because often people don't use it.
4590 if (typeof value !== 'undefined' && value !== null) {
4591 output.value = normalizeKey(value);
4592 }
4593 mapResults.push(output);
4594 }
4595
4596 const mapFun = mapper(view.mapFun, emit);
4597
4598 let currentSeq = view.seq || 0;
4599
4600 function createTask() {
4601 return view.sourceDB.info().then(function (info) {
4602 taskId = view.sourceDB.activeTasks.add({
4603 name: 'view_indexing',
4604 total_items: info.update_seq - currentSeq,
4605 });
4606 });
4607 }
4608
4609 function processChange(docIdsToChangesAndEmits, seq) {
4610 return function () {
4611 return saveKeyValues(view, docIdsToChangesAndEmits, seq);
4612 };
4613 }
4614
4615 let indexed_docs = 0;
4616 const progress = {
4617 view: view.name,
4618 indexed_docs
4619 };
4620 view.sourceDB.emit('indexing', progress);
4621
4622 const queue = new TaskQueue();
4623
4624 async function processNextBatch() {
4625 const response = await view.sourceDB.changes({
4626 return_docs: true,
4627 conflicts: true,
4628 include_docs: true,
4629 style: 'all_docs',
4630 since: currentSeq,
4631 limit: opts.changes_batch_size
4632 });
4633 const purges = await getRecentPurges();
4634 return processBatch(response, purges);
4635 }
4636
4637 function getRecentPurges() {
4638 return view.db.get('_local/purgeSeq').then(function (res) {
4639 return res.purgeSeq;
4640 })
4641 .catch(defaultsTo(-1))
4642 .then(function (purgeSeq) {
4643 return view.sourceDB.get('_local/purges').then(function (res) {
4644 const recentPurges = res.purges.filter(function (purge, index) {
4645 return index > purgeSeq;
4646 }).map((purge) => purge.docId);
4647
4648 const uniquePurges = recentPurges.filter(function (docId, index) {
4649 return recentPurges.indexOf(docId) === index;
4650 });
4651
4652 return Promise.all(uniquePurges.map(function (docId) {
4653 return view.sourceDB.get(docId).then(function (doc) {
4654 return { docId, doc };
4655 })
4656 .catch(defaultsTo({ docId }));
4657 }));
4658 })
4659 .catch(defaultsTo([]));
4660 });
4661 }
4662
4663 function processBatch(response, purges) {
4664 const results = response.results;
4665 if (!results.length && !purges.length) {
4666 return;
4667 }
4668
4669 for (const purge of purges) {
4670 const index = results.findIndex(function (change) {
4671 return change.id === purge.docId;
4672 });
4673 if (index < 0) {
4674 // mimic a db.remove() on the changes feed
4675 const entry = {
4676 _id: purge.docId,
4677 doc: {
4678 _id: purge.docId,
4679 _deleted: 1,
4680 },
4681 changes: [],
4682 };
4683
4684 if (purge.doc) {
4685 // update with new winning rev after purge
4686 entry.doc = purge.doc;
4687 entry.changes.push({ rev: purge.doc._rev });
4688 }
4689
4690 results.push(entry);
4691 }
4692 }
4693
4694 const docIdsToChangesAndEmits = createDocIdsToChangesAndEmits(results);
4695
4696 queue.add(processChange(docIdsToChangesAndEmits, currentSeq));
4697
4698 indexed_docs = indexed_docs + results.length;
4699 const progress = {
4700 view: view.name,
4701 last_seq: response.last_seq,
4702 results_count: results.length,
4703 indexed_docs
4704 };
4705 view.sourceDB.emit('indexing', progress);
4706 view.sourceDB.activeTasks.update(taskId, {completed_items: indexed_docs});
4707
4708 if (results.length < opts.changes_batch_size) {
4709 return;
4710 }
4711 return processNextBatch();
4712 }
4713
4714 function createDocIdsToChangesAndEmits(results) {
4715 const docIdsToChangesAndEmits = new Map();
4716 for (const change of results) {
4717 if (change.doc._id[0] !== '_') {
4718 mapResults = [];
4719 doc = change.doc;
4720
4721 if (!doc._deleted) {
4722 tryMap(view.sourceDB, mapFun, doc);
4723 }
4724 mapResults.sort(sortByKeyThenValue);
4725
4726 const indexableKeysToKeyValues = createIndexableKeysToKeyValues(mapResults);
4727 docIdsToChangesAndEmits.set(change.doc._id, [
4728 indexableKeysToKeyValues,
4729 change.changes
4730 ]);
4731 }
4732 currentSeq = change.seq;
4733 }
4734 return docIdsToChangesAndEmits;
4735 }
4736
4737 function createIndexableKeysToKeyValues(mapResults) {
4738 const indexableKeysToKeyValues = new Map();
4739 let lastKey;
4740 for (let i = 0, len = mapResults.length; i < len; i++) {
4741 const emittedKeyValue = mapResults[i];
4742 const complexKey = [emittedKeyValue.key, emittedKeyValue.id];
4743 if (i > 0 && collate(emittedKeyValue.key, lastKey) === 0) {
4744 complexKey.push(i); // dup key+id, so make it unique
4745 }
4746 indexableKeysToKeyValues.set(toIndexableString(complexKey), emittedKeyValue);
4747 lastKey = emittedKeyValue.key;
4748 }
4749 return indexableKeysToKeyValues;
4750 }
4751
4752 try {
4753 await createTask();
4754 await processNextBatch();
4755 await queue.finish();
4756 view.seq = currentSeq;
4757 view.sourceDB.activeTasks.remove(taskId);
4758 } catch (error) {
4759 view.sourceDB.activeTasks.remove(taskId, error);
4760 }
4761 }
4762
4763 function reduceView(view, results, options) {
4764 if (options.group_level === 0) {
4765 delete options.group_level;
4766 }
4767
4768 const shouldGroup = options.group || options.group_level;
4769 const reduceFun = reducer(view.reduceFun);
4770 const groups = [];
4771 const lvl = isNaN(options.group_level)
4772 ? Number.POSITIVE_INFINITY
4773 : options.group_level;
4774
4775 for (const result of results) {
4776 const last = groups[groups.length - 1];
4777 let groupKey = shouldGroup ? result.key : null;
4778
4779 // only set group_level for array keys
4780 if (shouldGroup && Array.isArray(groupKey)) {
4781 groupKey = groupKey.slice(0, lvl);
4782 }
4783
4784 if (last && collate(last.groupKey, groupKey) === 0) {
4785 last.keys.push([result.key, result.id]);
4786 last.values.push(result.value);
4787 continue;
4788 }
4789 groups.push({
4790 keys: [[result.key, result.id]],
4791 values: [result.value],
4792 groupKey
4793 });
4794 }
4795
4796 results = [];
4797 for (const group of groups) {
4798 const reduceTry = tryReduce(view.sourceDB, reduceFun, group.keys, group.values, false);
4799 if (reduceTry.error && reduceTry.error instanceof BuiltInError) {
4800 // CouchDB returns an error if a built-in errors out
4801 throw reduceTry.error;
4802 }
4803 results.push({
4804 // CouchDB just sets the value to null if a non-built-in errors out
4805 value: reduceTry.error ? null : reduceTry.output,
4806 key: group.groupKey
4807 });
4808 }
4809 // no total_rows/offset when reducing
4810 return { rows: sliceResults(results, options.limit, options.skip) };
4811 }
4812
4813 function queryView(view, opts) {
4814 return sequentialize(getQueue(view), function () {
4815 return queryViewInQueue(view, opts);
4816 })();
4817 }
4818
4819 async function queryViewInQueue(view, opts) {
4820 let totalRows;
4821 const shouldReduce = view.reduceFun && opts.reduce !== false;
4822 const skip = opts.skip || 0;
4823 if (typeof opts.keys !== 'undefined' && !opts.keys.length) {
4824 // equivalent query
4825 opts.limit = 0;
4826 delete opts.keys;
4827 }
4828
4829 async function fetchFromView(viewOpts) {
4830 viewOpts.include_docs = true;
4831 const res = await view.db.allDocs(viewOpts);
4832 totalRows = res.total_rows;
4833
4834 return res.rows.map(function (result) {
4835 // implicit migration - in older versions of PouchDB,
4836 // we explicitly stored the doc as {id: ..., key: ..., value: ...}
4837 // this is tested in a migration test
4838 /* istanbul ignore next */
4839 if ('value' in result.doc && typeof result.doc.value === 'object' &&
4840 result.doc.value !== null) {
4841 const keys = Object.keys(result.doc.value).sort();
4842 // this detection method is not perfect, but it's unlikely the user
4843 // emitted a value which was an object with these 3 exact keys
4844 const expectedKeys = ['id', 'key', 'value'];
4845 if (!(keys < expectedKeys || keys > expectedKeys)) {
4846 return result.doc.value;
4847 }
4848 }
4849
4850 const parsedKeyAndDocId = parseIndexableString(result.doc._id);
4851 return {
4852 key: parsedKeyAndDocId[0],
4853 id: parsedKeyAndDocId[1],
4854 value: ('value' in result.doc ? result.doc.value : null)
4855 };
4856 });
4857 }
4858
4859 async function onMapResultsReady(rows) {
4860 let finalResults;
4861 if (shouldReduce) {
4862 finalResults = reduceView(view, rows, opts);
4863 } else if (typeof opts.keys === 'undefined') {
4864 finalResults = {
4865 total_rows: totalRows,
4866 offset: skip,
4867 rows
4868 };
4869 } else {
4870 // support limit, skip for keys query
4871 finalResults = {
4872 total_rows: totalRows,
4873 offset: skip,
4874 rows: sliceResults(rows,opts.limit,opts.skip)
4875 };
4876 }
4877 /* istanbul ignore if */
4878 if (opts.update_seq) {
4879 finalResults.update_seq = view.seq;
4880 }
4881 if (opts.include_docs) {
4882 const docIds = uniq$1(rows.map(rowToDocId));
4883
4884 const allDocsRes = await view.sourceDB.allDocs({
4885 keys: docIds,
4886 include_docs: true,
4887 conflicts: opts.conflicts,
4888 attachments: opts.attachments,
4889 binary: opts.binary
4890 });
4891 const docIdsToDocs = new Map();
4892 for (const row of allDocsRes.rows) {
4893 docIdsToDocs.set(row.id, row.doc);
4894 }
4895 for (const row of rows) {
4896 const docId = rowToDocId(row);
4897 const doc = docIdsToDocs.get(docId);
4898 if (doc) {
4899 row.doc = doc;
4900 }
4901 }
4902 }
4903 return finalResults;
4904 }
4905
4906 if (typeof opts.keys !== 'undefined') {
4907 const keys = opts.keys;
4908 const fetchPromises = keys.map(function (key) {
4909 const viewOpts = {
4910 startkey : toIndexableString([key]),
4911 endkey : toIndexableString([key, {}])
4912 };
4913 /* istanbul ignore if */
4914 if (opts.update_seq) {
4915 viewOpts.update_seq = true;
4916 }
4917 return fetchFromView(viewOpts);
4918 });
4919 const result = await Promise.all(fetchPromises);
4920 const flattenedResult = result.flat();
4921 return onMapResultsReady(flattenedResult);
4922 } else { // normal query, no 'keys'
4923 const viewOpts = {
4924 descending : opts.descending
4925 };
4926 /* istanbul ignore if */
4927 if (opts.update_seq) {
4928 viewOpts.update_seq = true;
4929 }
4930 let startkey;
4931 let endkey;
4932 if ('start_key' in opts) {
4933 startkey = opts.start_key;
4934 }
4935 if ('startkey' in opts) {
4936 startkey = opts.startkey;
4937 }
4938 if ('end_key' in opts) {
4939 endkey = opts.end_key;
4940 }
4941 if ('endkey' in opts) {
4942 endkey = opts.endkey;
4943 }
4944 if (typeof startkey !== 'undefined') {
4945 viewOpts.startkey = opts.descending ?
4946 toIndexableString([startkey, {}]) :
4947 toIndexableString([startkey]);
4948 }
4949 if (typeof endkey !== 'undefined') {
4950 let inclusiveEnd = opts.inclusive_end !== false;
4951 if (opts.descending) {
4952 inclusiveEnd = !inclusiveEnd;
4953 }
4954
4955 viewOpts.endkey = toIndexableString(
4956 inclusiveEnd ? [endkey, {}] : [endkey]);
4957 }
4958 if (typeof opts.key !== 'undefined') {
4959 const keyStart = toIndexableString([opts.key]);
4960 const keyEnd = toIndexableString([opts.key, {}]);
4961 if (viewOpts.descending) {
4962 viewOpts.endkey = keyStart;
4963 viewOpts.startkey = keyEnd;
4964 } else {
4965 viewOpts.startkey = keyStart;
4966 viewOpts.endkey = keyEnd;
4967 }
4968 }
4969 if (!shouldReduce) {
4970 if (typeof opts.limit === 'number') {
4971 viewOpts.limit = opts.limit;
4972 }
4973 viewOpts.skip = skip;
4974 }
4975
4976 const result = await fetchFromView(viewOpts);
4977 return onMapResultsReady(result);
4978 }
4979 }
4980
4981 async function httpViewCleanup(db) {
4982 const response = await db.fetch('_view_cleanup', {
4983 headers: new h({'Content-Type': 'application/json'}),
4984 method: 'POST'
4985 });
4986 return response.json();
4987 }
4988
4989 async function localViewCleanup(db) {
4990 try {
4991 const metaDoc = await db.get('_local/' + localDocName);
4992 const docsToViews = new Map();
4993
4994 for (const fullViewName of Object.keys(metaDoc.views)) {
4995 const parts = parseViewName(fullViewName);
4996 const designDocName = '_design/' + parts[0];
4997 const viewName = parts[1];
4998 let views = docsToViews.get(designDocName);
4999 if (!views) {
5000 views = new Set();
5001 docsToViews.set(designDocName, views);
5002 }
5003 views.add(viewName);
5004 }
5005 const opts = {
5006 keys : mapToKeysArray(docsToViews),
5007 include_docs : true
5008 };
5009
5010 const res = await db.allDocs(opts);
5011 const viewsToStatus = {};
5012 for (const row of res.rows) {
5013 const ddocName = row.key.substring(8); // cuts off '_design/'
5014 for (const viewName of docsToViews.get(row.key)) {
5015 let fullViewName = ddocName + '/' + viewName;
5016 /* istanbul ignore if */
5017 if (!metaDoc.views[fullViewName]) {
5018 // new format, without slashes, to support PouchDB 2.2.0
5019 // migration test in pouchdb's browser.migration.js verifies this
5020 fullViewName = viewName;
5021 }
5022 const viewDBNames = Object.keys(metaDoc.views[fullViewName]);
5023 // design doc deleted, or view function nonexistent
5024 const statusIsGood = row.doc && row.doc.views &&
5025 row.doc.views[viewName];
5026 for (const viewDBName of viewDBNames) {
5027 viewsToStatus[viewDBName] = viewsToStatus[viewDBName] || statusIsGood;
5028 }
5029 }
5030 }
5031
5032 const dbsToDelete = Object.keys(viewsToStatus)
5033 .filter(function (viewDBName) { return !viewsToStatus[viewDBName]; });
5034
5035 const destroyPromises = dbsToDelete.map(function (viewDBName) {
5036 return sequentialize(getQueue(viewDBName), function () {
5037 return new db.constructor(viewDBName, db.__opts).destroy();
5038 })();
5039 });
5040
5041 return Promise.all(destroyPromises).then(function () {
5042 return {ok: true};
5043 });
5044 } catch (err) {
5045 if (err.status === 404) {
5046 return {ok: true};
5047 } else {
5048 throw err;
5049 }
5050 }
5051 }
5052
5053 async function queryPromised(db, fun, opts) {
5054 /* istanbul ignore next */
5055 if (typeof db._query === 'function') {
5056 return customQuery(db, fun, opts);
5057 }
5058 if (isRemote(db)) {
5059 return httpQuery(db, fun, opts);
5060 }
5061
5062 const updateViewOpts = {
5063 changes_batch_size: db.__opts.view_update_changes_batch_size || CHANGES_BATCH_SIZE
5064 };
5065
5066 if (typeof fun !== 'string') {
5067 // temp_view
5068 checkQueryParseError(opts, fun);
5069
5070 tempViewQueue.add(async function () {
5071 const view = await createView(
5072 /* sourceDB */ db,
5073 /* viewName */ 'temp_view/temp_view',
5074 /* mapFun */ fun.map,
5075 /* reduceFun */ fun.reduce,
5076 /* temporary */ true,
5077 /* localDocName */ localDocName);
5078
5079 return fin(updateView(view, updateViewOpts).then(
5080 function () { return queryView(view, opts); }),
5081 function () { return view.db.destroy(); }
5082 );
5083 });
5084 return tempViewQueue.finish();
5085 } else {
5086 // persistent view
5087 const fullViewName = fun;
5088 const parts = parseViewName(fullViewName);
5089 const designDocName = parts[0];
5090 const viewName = parts[1];
5091
5092 const doc = await db.get('_design/' + designDocName);
5093 fun = doc.views && doc.views[viewName];
5094
5095 if (!fun) {
5096 // basic validator; it's assumed that every subclass would want this
5097 throw new NotFoundError(`ddoc ${doc._id} has no view named ${viewName}`);
5098 }
5099
5100 ddocValidator(doc, viewName);
5101 checkQueryParseError(opts, fun);
5102
5103 const view = await createView(
5104 /* sourceDB */ db,
5105 /* viewName */ fullViewName,
5106 /* mapFun */ fun.map,
5107 /* reduceFun */ fun.reduce,
5108 /* temporary */ false,
5109 /* localDocName */ localDocName);
5110
5111 if (opts.stale === 'ok' || opts.stale === 'update_after') {
5112 if (opts.stale === 'update_after') {
5113 nextTick(function () {
5114 updateView(view, updateViewOpts);
5115 });
5116 }
5117 return queryView(view, opts);
5118 } else { // stale not ok
5119 await updateView(view, updateViewOpts);
5120 return queryView(view, opts);
5121 }
5122 }
5123 }
5124
5125 function abstractQuery(fun, opts, callback) {
5126 const db = this;
5127 if (typeof opts === 'function') {
5128 callback = opts;
5129 opts = {};
5130 }
5131 opts = opts ? coerceOptions(opts) : {};
5132
5133 if (typeof fun === 'function') {
5134 fun = {map : fun};
5135 }
5136
5137 const promise = Promise.resolve().then(function () {
5138 return queryPromised(db, fun, opts);
5139 });
5140 promisedCallback(promise, callback);
5141 return promise;
5142 }
5143
5144 const abstractViewCleanup = callbackify(function () {
5145 const db = this;
5146 /* istanbul ignore next */
5147 if (typeof db._viewCleanup === 'function') {
5148 return customViewCleanup(db);
5149 }
5150 if (isRemote(db)) {
5151 return httpViewCleanup(db);
5152 }
5153 return localViewCleanup(db);
5154 });
5155
5156 return {
5157 query: abstractQuery,
5158 viewCleanup: abstractViewCleanup
5159 };
5160}
5161
5162//
5163// One thing about these mappers:
5164//
5165// Per the advice of John-David Dalton (http://youtu.be/NthmeLEhDDM),
5166// what you want to do in this case is optimize for the smallest possible
5167// function, since that's the thing that gets run over and over again.
5168//
5169// This code would be a lot simpler if all the if/elses were inside
5170// the function, but it would also be a lot less performant.
5171//
5172
5173function getDeepValue(value, path) {
5174 for (const key of path) {
5175 value = value[key];
5176 if (value === undefined) {
5177 return undefined;
5178 }
5179 }
5180 return value;
5181}
5182
5183function createDeepMultiMapper(fields, emit, selector) {
5184 return function (doc) {
5185 if (selector && !matchesSelector(doc, selector)) { return; }
5186
5187 const toEmit = [];
5188 for (const field of fields) {
5189 const value = getDeepValue(doc, parseField(field));
5190 if (value === undefined) {
5191 return;
5192 }
5193 toEmit.push(value);
5194 }
5195 emit(toEmit);
5196 };
5197}
5198
5199function createDeepSingleMapper(field, emit, selector) {
5200 const parsedField = parseField(field);
5201 return function (doc) {
5202 if (selector && !matchesSelector(doc, selector)) { return; }
5203
5204 const value = getDeepValue(doc, parsedField);
5205 if (value !== undefined) {
5206 emit(value);
5207 }
5208 };
5209}
5210
5211function createShallowSingleMapper(field, emit, selector) {
5212 return function (doc) {
5213 if (selector && !matchesSelector(doc, selector)) { return; }
5214 emit(doc[field]);
5215 };
5216}
5217
5218function createShallowMultiMapper(fields, emit, selector) {
5219 return function (doc) {
5220 if (selector && !matchesSelector(doc, selector)) { return; }
5221 const toEmit = fields.map(field => doc[field]);
5222 emit(toEmit);
5223 };
5224}
5225
5226function checkShallow(fields) {
5227 return fields.every((field) => field.indexOf('.') === -1);
5228}
5229
5230function createMapper(fields, emit, selector) {
5231 const isShallow = checkShallow(fields);
5232 const isSingle = fields.length === 1;
5233
5234 // notice we try to optimize for the most common case,
5235 // i.e. single shallow indexes
5236 if (isShallow) {
5237 if (isSingle) {
5238 return createShallowSingleMapper(fields[0], emit, selector);
5239 } else { // multi
5240 return createShallowMultiMapper(fields, emit, selector);
5241 }
5242 } else { // deep
5243 if (isSingle) {
5244 return createDeepSingleMapper(fields[0], emit, selector);
5245 } else { // multi
5246 return createDeepMultiMapper(fields, emit, selector);
5247 }
5248 }
5249}
5250
5251function mapper(mapFunDef, emit) {
5252 // mapFunDef is a list of fields
5253
5254 const fields = Object.keys(mapFunDef.fields);
5255 const partialSelector = mapFunDef.partial_filter_selector;
5256
5257 return createMapper(fields, emit, partialSelector);
5258}
5259
5260/* istanbul ignore next */
5261function reducer(/*reduceFunDef*/) {
5262 throw new Error('reduce not supported');
5263}
5264
5265function ddocValidator(ddoc, viewName) {
5266 const view = ddoc.views[viewName];
5267 // This doesn't actually need to be here apparently, but
5268 // I feel safer keeping it.
5269 /* istanbul ignore if */
5270 if (!view.map || !view.map.fields) {
5271 throw new Error('ddoc ' + ddoc._id + ' with view ' + viewName +
5272 ' doesn\'t have map.fields defined. ' +
5273 'maybe it wasn\'t created by this plugin?');
5274 }
5275}
5276
5277const abstractMapper = createAbstractMapReduce(
5278 /* localDocName */ 'indexes',
5279 mapper,
5280 reducer,
5281 ddocValidator
5282);
5283
5284function abstractMapper$1 (db) {
5285 if (db._customFindAbstractMapper) {
5286 return {
5287 // Calls the _customFindAbstractMapper, but with a third argument:
5288 // the standard findAbstractMapper query/viewCleanup.
5289 // This allows the indexeddb adapter to support partial_filter_selector.
5290 query: function addQueryFallback(signature, opts) {
5291 const fallback = abstractMapper.query.bind(this);
5292 return db._customFindAbstractMapper.query.call(this, signature, opts, fallback);
5293 },
5294 viewCleanup: function addViewCleanupFallback() {
5295 const fallback = abstractMapper.viewCleanup.bind(this);
5296 return db._customFindAbstractMapper.viewCleanup.call(this, fallback);
5297 }
5298 };
5299 }
5300 return abstractMapper;
5301}
5302
5303// normalize the "sort" value
5304function massageSort(sort) {
5305 if (!Array.isArray(sort)) {
5306 throw new Error('invalid sort json - should be an array');
5307 }
5308 return sort.map(function (sorting) {
5309 if (typeof sorting === 'string') {
5310 const obj = {};
5311 obj[sorting] = 'asc';
5312 return obj;
5313 } else {
5314 return sorting;
5315 }
5316 });
5317}
5318
5319const ddocIdPrefix = /^_design\//;
5320function massageUseIndex(useIndex) {
5321 let cleanedUseIndex = [];
5322 if (typeof useIndex === 'string') {
5323 cleanedUseIndex.push(useIndex);
5324 } else {
5325 cleanedUseIndex = useIndex;
5326 }
5327
5328 return cleanedUseIndex.map(function (name) {
5329 return name.replace(ddocIdPrefix, '');
5330 });
5331}
5332
5333function massageIndexDef(indexDef) {
5334 indexDef.fields = indexDef.fields.map(function (field) {
5335 if (typeof field === 'string') {
5336 const obj = {};
5337 obj[field] = 'asc';
5338 return obj;
5339 }
5340 return field;
5341 });
5342 if (indexDef.partial_filter_selector) {
5343 indexDef.partial_filter_selector = massageSelector(
5344 indexDef.partial_filter_selector
5345 );
5346 }
5347 return indexDef;
5348}
5349
5350function getKeyFromDoc(doc, index) {
5351 return index.def.fields.map((obj) => {
5352 const field = getKey(obj);
5353 return getFieldFromDoc(doc, parseField(field));
5354 });
5355}
5356
5357// have to do this manually because REASONS. I don't know why
5358// CouchDB didn't implement inclusive_start
5359function filterInclusiveStart(rows, targetValue, index) {
5360 const indexFields = index.def.fields;
5361 let startAt = 0;
5362 for (const row of rows) {
5363 // shave off any docs at the beginning that are <= the
5364 // target value
5365
5366 let docKey = getKeyFromDoc(row.doc, index);
5367 if (indexFields.length === 1) {
5368 docKey = docKey[0]; // only one field, not multi-field
5369 } else { // more than one field in index
5370 // in the case where e.g. the user is searching {$gt: {a: 1}}
5371 // but the index is [a, b], then we need to shorten the doc key
5372 while (docKey.length > targetValue.length) {
5373 docKey.pop();
5374 }
5375 }
5376 //ABS as we just looking for values that don't match
5377 if (Math.abs(collate(docKey, targetValue)) > 0) {
5378 // no need to filter any further; we're past the key
5379 break;
5380 }
5381 ++startAt;
5382 }
5383 return startAt > 0 ? rows.slice(startAt) : rows;
5384}
5385
5386function reverseOptions(opts) {
5387 const newOpts = clone(opts);
5388 delete newOpts.startkey;
5389 delete newOpts.endkey;
5390 delete newOpts.inclusive_start;
5391 delete newOpts.inclusive_end;
5392
5393 if ('endkey' in opts) {
5394 newOpts.startkey = opts.endkey;
5395 }
5396 if ('startkey' in opts) {
5397 newOpts.endkey = opts.startkey;
5398 }
5399 if ('inclusive_start' in opts) {
5400 newOpts.inclusive_end = opts.inclusive_start;
5401 }
5402 if ('inclusive_end' in opts) {
5403 newOpts.inclusive_start = opts.inclusive_end;
5404 }
5405 return newOpts;
5406}
5407
5408function validateIndex(index) {
5409 const ascFields = index.fields.filter(function (field) {
5410 return getValue(field) === 'asc';
5411 });
5412 if (ascFields.length !== 0 && ascFields.length !== index.fields.length) {
5413 throw new Error('unsupported mixed sorting');
5414 }
5415}
5416
5417function validateSort(requestDef, index) {
5418 if (index.defaultUsed && requestDef.sort) {
5419 const noneIdSorts = requestDef.sort.filter(function (sortItem) {
5420 return Object.keys(sortItem)[0] !== '_id';
5421 }).map(function (sortItem) {
5422 return Object.keys(sortItem)[0];
5423 });
5424
5425 if (noneIdSorts.length > 0) {
5426 throw new Error('Cannot sort on field(s) "' + noneIdSorts.join(',') +
5427 '" when using the default index');
5428 }
5429 }
5430
5431 if (index.defaultUsed) {
5432 return;
5433 }
5434}
5435
5436function validateFindRequest(requestDef) {
5437 if (typeof requestDef.selector !== 'object') {
5438 throw new Error('you must provide a selector when you find()');
5439 }
5440
5441 /*var selectors = requestDef.selector['$and'] || [requestDef.selector];
5442 for (var i = 0; i < selectors.length; i++) {
5443 var selector = selectors[i];
5444 var keys = Object.keys(selector);
5445 if (keys.length === 0) {
5446 throw new Error('invalid empty selector');
5447 }
5448 //var selection = selector[keys[0]];
5449 /*if (Object.keys(selection).length !== 1) {
5450 throw new Error('invalid selector: ' + JSON.stringify(selection) +
5451 ' - it must have exactly one key/value');
5452 }
5453 }*/
5454}
5455
5456// determine the maximum number of fields
5457// we're going to need to query, e.g. if the user
5458// has selection ['a'] and sorting ['a', 'b'], then we
5459// need to use the longer of the two: ['a', 'b']
5460function getUserFields(selector, sort) {
5461 const selectorFields = Object.keys(selector);
5462 const sortFields = sort ? sort.map(getKey) : [];
5463 let userFields;
5464 if (selectorFields.length >= sortFields.length) {
5465 userFields = selectorFields;
5466 } else {
5467 userFields = sortFields;
5468 }
5469
5470 if (sortFields.length === 0) {
5471 return {
5472 fields: userFields
5473 };
5474 }
5475
5476 // sort according to the user's preferred sorting
5477 userFields = userFields.sort(function (left, right) {
5478 let leftIdx = sortFields.indexOf(left);
5479 if (leftIdx === -1) {
5480 leftIdx = Number.MAX_VALUE;
5481 }
5482 let rightIdx = sortFields.indexOf(right);
5483 if (rightIdx === -1) {
5484 rightIdx = Number.MAX_VALUE;
5485 }
5486 return leftIdx < rightIdx ? -1 : leftIdx > rightIdx ? 1 : 0;
5487 });
5488
5489 return {
5490 fields: userFields,
5491 sortOrder: sort.map(getKey)
5492 };
5493}
5494
5495async function createIndex$1(db, requestDef) {
5496 requestDef = massageCreateIndexRequest(requestDef);
5497 const originalIndexDef = clone(requestDef.index);
5498 requestDef.index = massageIndexDef(requestDef.index);
5499
5500 validateIndex(requestDef.index);
5501
5502 // calculating md5 is expensive - memoize and only
5503 // run if required
5504 let md5;
5505 function getMd5() {
5506 return md5 || (md5 = stringMd5(JSON.stringify(requestDef)));
5507 }
5508
5509 const viewName = requestDef.name || ('idx-' + getMd5());
5510
5511 const ddocName = requestDef.ddoc || ('idx-' + getMd5());
5512 const ddocId = '_design/' + ddocName;
5513
5514 let hasInvalidLanguage = false;
5515 let viewExists = false;
5516
5517 function updateDdoc(doc) {
5518 if (doc._rev && doc.language !== 'query') {
5519 hasInvalidLanguage = true;
5520 }
5521 doc.language = 'query';
5522 doc.views = doc.views || {};
5523
5524 viewExists = !!doc.views[viewName];
5525
5526 if (viewExists) {
5527 return false;
5528 }
5529
5530 doc.views[viewName] = {
5531 map: {
5532 fields: mergeObjects(requestDef.index.fields),
5533 partial_filter_selector: requestDef.index.partial_filter_selector
5534 },
5535 reduce: '_count',
5536 options: {
5537 def: originalIndexDef
5538 }
5539 };
5540
5541 return doc;
5542 }
5543
5544 db.constructor.emit('debug', ['find', 'creating index', ddocId]);
5545
5546 await upsert(db, ddocId, updateDdoc);
5547
5548 if (hasInvalidLanguage) {
5549 throw new Error('invalid language for ddoc with id "' +
5550 ddocId +
5551 '" (should be "query")');
5552 }
5553
5554 // kick off a build
5555 // TODO: abstract-pouchdb-mapreduce should support auto-updating
5556 // TODO: should also use update_after, but pouchdb/pouchdb#3415 blocks me
5557 const signature = ddocName + '/' + viewName;
5558 await abstractMapper$1(db).query.call(db, signature, {
5559 limit: 0,
5560 reduce: false
5561 });
5562 return {
5563 id: ddocId,
5564 name: viewName,
5565 result: viewExists ? 'exists' : 'created'
5566 };
5567}
5568
5569async function getIndexes$1(db) {
5570 // just search through all the design docs and filter in-memory.
5571 // hopefully there aren't that many ddocs.
5572 const allDocsRes = await db.allDocs({
5573 startkey: '_design/',
5574 endkey: '_design/\uffff',
5575 include_docs: true
5576 });
5577 const res = {
5578 indexes: [{
5579 ddoc: null,
5580 name: '_all_docs',
5581 type: 'special',
5582 def: {
5583 fields: [{ _id: 'asc' }]
5584 }
5585 }]
5586 };
5587
5588 res.indexes = flatten(res.indexes, allDocsRes.rows.filter(function (row) {
5589 return row.doc.language === 'query';
5590 }).map(function (row) {
5591 const viewNames = row.doc.views !== undefined ? Object.keys(row.doc.views) : [];
5592
5593 return viewNames.map(function (viewName) {
5594 const view = row.doc.views[viewName];
5595 return {
5596 ddoc: row.id,
5597 name: viewName,
5598 type: 'json',
5599 def: massageIndexDef(view.options.def)
5600 };
5601 });
5602 }));
5603
5604 // these are sorted by view name for some reason
5605 res.indexes.sort(function (left, right) {
5606 return compare(left.name, right.name);
5607 });
5608 res.total_rows = res.indexes.length;
5609 return res;
5610}
5611
5612// couchdb lowest collation value
5613const COLLATE_LO = null;
5614
5615// couchdb highest collation value (TODO: well not really, but close enough amirite)
5616const COLLATE_HI = { "\uffff": {} };
5617
5618const SHORT_CIRCUIT_QUERY = {
5619 queryOpts: { limit: 0, startkey: COLLATE_HI, endkey: COLLATE_LO },
5620 inMemoryFields: [],
5621};
5622
5623// couchdb second-lowest collation value
5624
5625function checkFieldInIndex(index, field) {
5626 return index.def.fields
5627 .some((key) => getKey(key) === field);
5628}
5629
5630// so when you do e.g. $eq/$eq, we can do it entirely in the database.
5631// but when you do e.g. $gt/$eq, the first part can be done
5632// in the database, but the second part has to be done in-memory,
5633// because $gt has forced us to lose precision.
5634// so that's what this determines
5635function userOperatorLosesPrecision(selector, field) {
5636 const matcher = selector[field];
5637 const userOperator = getKey(matcher);
5638
5639 return userOperator !== '$eq';
5640}
5641
5642// sort the user fields by their position in the index,
5643// if they're in the index
5644function sortFieldsByIndex(userFields, index) {
5645 const indexFields = index.def.fields.map(getKey);
5646
5647 return userFields.slice().sort(function (a, b) {
5648 let aIdx = indexFields.indexOf(a);
5649 let bIdx = indexFields.indexOf(b);
5650 if (aIdx === -1) {
5651 aIdx = Number.MAX_VALUE;
5652 }
5653 if (bIdx === -1) {
5654 bIdx = Number.MAX_VALUE;
5655 }
5656 return compare(aIdx, bIdx);
5657 });
5658}
5659
5660// first pass to try to find fields that will need to be sorted in-memory
5661function getBasicInMemoryFields(index, selector, userFields) {
5662 userFields = sortFieldsByIndex(userFields, index);
5663
5664 // check if any of the user selectors lose precision
5665 let needToFilterInMemory = false;
5666 for (let i = 0, len = userFields.length; i < len; i++) {
5667 const field = userFields[i];
5668 if (needToFilterInMemory || !checkFieldInIndex(index, field)) {
5669 return userFields.slice(i);
5670 }
5671 if (i < len - 1 && userOperatorLosesPrecision(selector, field)) {
5672 needToFilterInMemory = true;
5673 }
5674 }
5675 return [];
5676}
5677
5678function getInMemoryFieldsFromNe(selector) {
5679 const fields = [];
5680 for (const [field, matcher] of Object.entries(selector)) {
5681 for (const operator of Object.keys(matcher)) {
5682 if (operator === '$ne') {
5683 fields.push(field);
5684 }
5685 }
5686 }
5687 return fields;
5688}
5689
5690function getInMemoryFields(coreInMemoryFields, index, selector, userFields) {
5691 const result = flatten(
5692 // in-memory fields reported as necessary by the query planner
5693 coreInMemoryFields,
5694 // combine with another pass that checks for any we may have missed
5695 getBasicInMemoryFields(index, selector, userFields),
5696 // combine with another pass that checks for $ne's
5697 getInMemoryFieldsFromNe(selector)
5698 );
5699
5700 return sortFieldsByIndex(uniq(result), index);
5701}
5702
5703// check that at least one field in the user's query is represented
5704// in the index. order matters in the case of sorts
5705function checkIndexFieldsMatch(indexFields, sortOrder, fields) {
5706 if (sortOrder) {
5707 // array has to be a strict subarray of index array. furthermore,
5708 // the sortOrder fields need to all be represented in the index
5709 const sortMatches = oneArrayIsStrictSubArrayOfOther(sortOrder, indexFields);
5710 const selectorMatches = oneArrayIsSubArrayOfOther(fields, indexFields);
5711
5712 return sortMatches && selectorMatches;
5713 }
5714
5715 // all of the user's specified fields still need to be
5716 // on the left side of the index array, although the order
5717 // doesn't matter
5718 return oneSetIsSubArrayOfOther(fields, indexFields);
5719}
5720
5721const logicalMatchers = ['$eq', '$gt', '$gte', '$lt', '$lte'];
5722function isNonLogicalMatcher(matcher) {
5723 return logicalMatchers.indexOf(matcher) === -1;
5724}
5725
5726// check all the index fields for usages of '$ne'
5727// e.g. if the user queries {foo: {$ne: 'foo'}, bar: {$eq: 'bar'}},
5728// then we can neither use an index on ['foo'] nor an index on
5729// ['foo', 'bar'], but we can use an index on ['bar'] or ['bar', 'foo']
5730function checkFieldsLogicallySound(indexFields, selector) {
5731 const firstField = indexFields[0];
5732 const matcher = selector[firstField];
5733
5734 if (typeof matcher === 'undefined') {
5735 /* istanbul ignore next */
5736 return true;
5737 }
5738
5739 const isInvalidNe = Object.keys(matcher).length === 1 &&
5740 getKey(matcher) === '$ne';
5741
5742 return !isInvalidNe;
5743}
5744
5745function checkIndexMatches(index, sortOrder, fields, selector) {
5746 const indexFields = index.def.fields.map(getKey);
5747 const fieldsMatch = checkIndexFieldsMatch(indexFields, sortOrder, fields);
5748
5749 if (!fieldsMatch) {
5750 return false;
5751 }
5752
5753 return checkFieldsLogicallySound(indexFields, selector);
5754}
5755
5756//
5757// the algorithm is very simple:
5758// take all the fields the user supplies, and if those fields
5759// are a strict subset of the fields in some index,
5760// then use that index
5761//
5762function findMatchingIndexes(selector, userFields, sortOrder, indexes) {
5763 return indexes.filter(function (index) {
5764 return checkIndexMatches(index, sortOrder, userFields, selector);
5765 });
5766}
5767
5768// find the best index, i.e. the one that matches the most fields
5769// in the user's query
5770function findBestMatchingIndex(selector, userFields, sortOrder, indexes, useIndex) {
5771 const matchingIndexes = findMatchingIndexes(selector, userFields, sortOrder, indexes);
5772
5773 if (matchingIndexes.length === 0) {
5774 if (useIndex) {
5775 throw {
5776 error: "no_usable_index",
5777 message: "There is no index available for this selector."
5778 };
5779 }
5780 // return `all_docs` as a default index;
5781 // I'm assuming that _all_docs is always first
5782 const defaultIndex = indexes[0];
5783 defaultIndex.defaultUsed = true;
5784 return defaultIndex;
5785 }
5786 if (matchingIndexes.length === 1 && !useIndex) {
5787 return matchingIndexes[0];
5788 }
5789
5790 const userFieldsMap = arrayToObject(userFields);
5791
5792 function scoreIndex(index) {
5793 const indexFields = index.def.fields.map(getKey);
5794 let score = 0;
5795 for (const indexField of indexFields) {
5796 if (userFieldsMap[indexField]) {
5797 score++;
5798 }
5799 }
5800 return score;
5801 }
5802
5803 if (useIndex) {
5804 const useIndexDdoc = '_design/' + useIndex[0];
5805 const useIndexName = useIndex.length === 2 ? useIndex[1] : false;
5806 const index = matchingIndexes.find(function (index) {
5807 if (useIndexName && index.ddoc === useIndexDdoc && useIndexName === index.name) {
5808 return true;
5809 }
5810
5811 if (index.ddoc === useIndexDdoc) {
5812 /* istanbul ignore next */
5813 return true;
5814 }
5815
5816 return false;
5817 });
5818
5819 if (!index) {
5820 throw {
5821 error: "unknown_error",
5822 message: "Could not find that index or could not use that index for the query"
5823 };
5824 }
5825 return index;
5826 }
5827
5828 return max(matchingIndexes, scoreIndex);
5829}
5830
5831function getSingleFieldQueryOptsFor(userOperator, userValue) {
5832 switch (userOperator) {
5833 case '$eq':
5834 return { key: userValue };
5835 case '$lte':
5836 return { endkey: userValue };
5837 case '$gte':
5838 return { startkey: userValue };
5839 case '$lt':
5840 return {
5841 endkey: userValue,
5842 inclusive_end: false
5843 };
5844 case '$gt':
5845 return {
5846 startkey: userValue,
5847 inclusive_start: false
5848 };
5849 }
5850
5851 return {
5852 startkey: COLLATE_LO
5853 };
5854}
5855
5856function getSingleFieldCoreQueryPlan(selector, index) {
5857 const field = getKey(index.def.fields[0]);
5858 //ignoring this because the test to exercise the branch is skipped at the moment
5859 /* istanbul ignore next */
5860 const matcher = selector[field] || {};
5861 const inMemoryFields = [];
5862 const userOperators = Object.keys(matcher);
5863
5864 let combinedOpts;
5865
5866 for (const userOperator of userOperators) {
5867 if (isNonLogicalMatcher(userOperator)) {
5868 inMemoryFields.push(field);
5869 }
5870
5871 const userValue = matcher[userOperator];
5872 const newQueryOpts = getSingleFieldQueryOptsFor(userOperator, userValue);
5873
5874 if (combinedOpts) {
5875 combinedOpts = mergeObjects([combinedOpts, newQueryOpts]);
5876 } else {
5877 combinedOpts = newQueryOpts;
5878 }
5879 }
5880
5881 return {
5882 queryOpts: combinedOpts,
5883 inMemoryFields
5884 };
5885}
5886
5887function getMultiFieldCoreQueryPlan(userOperator, userValue) {
5888 switch (userOperator) {
5889 case '$eq':
5890 return {
5891 startkey: userValue,
5892 endkey: userValue
5893 };
5894 case '$lte':
5895 return {
5896 endkey: userValue
5897 };
5898 case '$gte':
5899 return {
5900 startkey: userValue
5901 };
5902 case '$lt':
5903 return {
5904 endkey: userValue,
5905 inclusive_end: false
5906 };
5907 case '$gt':
5908 return {
5909 startkey: userValue,
5910 inclusive_start: false
5911 };
5912 }
5913}
5914
5915function getMultiFieldQueryOpts(selector, index) {
5916 const indexFields = index.def.fields.map(getKey);
5917
5918 let inMemoryFields = [];
5919 const startkey = [];
5920 const endkey = [];
5921 let inclusiveStart;
5922 let inclusiveEnd;
5923
5924 function finish(i) {
5925
5926 if (inclusiveStart !== false) {
5927 startkey.push(COLLATE_LO);
5928 }
5929 if (inclusiveEnd !== false) {
5930 endkey.push(COLLATE_HI);
5931 }
5932 // keep track of the fields where we lost specificity,
5933 // and therefore need to filter in-memory
5934 inMemoryFields = indexFields.slice(i);
5935 }
5936
5937 for (let i = 0, len = indexFields.length; i < len; i++) {
5938 const indexField = indexFields[i];
5939 const matcher = selector[indexField];
5940
5941 if (!matcher || !Object.keys(matcher).length) { // fewer fields in user query than in index
5942 finish(i);
5943 break;
5944 } else if (Object.keys(matcher).some(isNonLogicalMatcher)) { // non-logical are ignored
5945 finish(i);
5946 break;
5947 } else if (i > 0) {
5948 const usingGtlt = (
5949 '$gt' in matcher || '$gte' in matcher ||
5950 '$lt' in matcher || '$lte' in matcher);
5951 const previousKeys = Object.keys(selector[indexFields[i - 1]]);
5952 const previousWasEq = arrayEquals(previousKeys, ['$eq']);
5953 const previousWasSame = arrayEquals(previousKeys, Object.keys(matcher));
5954 const gtltLostSpecificity = usingGtlt && !previousWasEq && !previousWasSame;
5955 if (gtltLostSpecificity) {
5956 finish(i);
5957 break;
5958 }
5959 }
5960
5961 const userOperators = Object.keys(matcher);
5962 let combinedOpts = null;
5963
5964 for (const userOperator of userOperators) {
5965 const userValue = matcher[userOperator];
5966 const newOpts = getMultiFieldCoreQueryPlan(userOperator, userValue);
5967
5968 if (combinedOpts) {
5969 combinedOpts = mergeObjects([combinedOpts, newOpts]);
5970 } else {
5971 combinedOpts = newOpts;
5972 }
5973 }
5974
5975 startkey.push('startkey' in combinedOpts ? combinedOpts.startkey : COLLATE_LO);
5976 endkey.push('endkey' in combinedOpts ? combinedOpts.endkey : COLLATE_HI);
5977 if ('inclusive_start' in combinedOpts) {
5978 inclusiveStart = combinedOpts.inclusive_start;
5979 }
5980 if ('inclusive_end' in combinedOpts) {
5981 inclusiveEnd = combinedOpts.inclusive_end;
5982 }
5983 }
5984
5985 const res = {
5986 startkey,
5987 endkey
5988 };
5989
5990 if (typeof inclusiveStart !== 'undefined') {
5991 res.inclusive_start = inclusiveStart;
5992 }
5993 if (typeof inclusiveEnd !== 'undefined') {
5994 res.inclusive_end = inclusiveEnd;
5995 }
5996
5997 return {
5998 queryOpts: res,
5999 inMemoryFields
6000 };
6001}
6002
6003function shouldShortCircuit(selector) {
6004 // We have a field to select from, but not a valid value
6005 // this should result in a short circuited query
6006 // just like the http adapter (couchdb) and mongodb
6007 // see tests for issue #7810
6008
6009 // @todo Use 'Object.values' when Node.js v6 support is dropped.
6010 const values = Object.keys(selector).map(function (key) {
6011 return selector[key];
6012 });
6013 return values.some(function (val) {
6014 return typeof val === 'object' && Object.keys(val).length === 0;
6015 });
6016}
6017
6018function getDefaultQueryPlan(selector) {
6019 //using default index, so all fields need to be done in memory
6020 return {
6021 queryOpts: { startkey: null },
6022 inMemoryFields: [Object.keys(selector)]
6023 };
6024}
6025
6026function getCoreQueryPlan(selector, index) {
6027 if (index.defaultUsed) {
6028 return getDefaultQueryPlan(selector, index);
6029 }
6030
6031 if (index.def.fields.length === 1) {
6032 // one field in index, so the value was indexed as a singleton
6033 return getSingleFieldCoreQueryPlan(selector, index);
6034 }
6035 // else index has multiple fields, so the value was indexed as an array
6036 return getMultiFieldQueryOpts(selector, index);
6037}
6038
6039function planQuery(request, indexes) {
6040 const selector = request.selector;
6041 const sort = request.sort;
6042
6043 if (shouldShortCircuit(selector)) {
6044 return Object.assign({}, SHORT_CIRCUIT_QUERY, { index: indexes[0] });
6045 }
6046
6047 const userFieldsRes = getUserFields(selector, sort);
6048
6049 const userFields = userFieldsRes.fields;
6050 const sortOrder = userFieldsRes.sortOrder;
6051 const index = findBestMatchingIndex(selector, userFields, sortOrder, indexes, request.use_index);
6052
6053 const coreQueryPlan = getCoreQueryPlan(selector, index);
6054 const queryOpts = coreQueryPlan.queryOpts;
6055 const coreInMemoryFields = coreQueryPlan.inMemoryFields;
6056
6057 const inMemoryFields = getInMemoryFields(coreInMemoryFields, index, selector, userFields);
6058
6059 return {
6060 queryOpts,
6061 index,
6062 inMemoryFields
6063 };
6064}
6065
6066function indexToSignature(index) {
6067 // remove '_design/'
6068 return index.ddoc.substring(8) + '/' + index.name;
6069}
6070
6071async function doAllDocs(db, originalOpts) {
6072 const opts = clone(originalOpts);
6073
6074 // CouchDB responds in weird ways when you provide a non-string to _id;
6075 // we mimic the behavior for consistency. See issue66 tests for details.
6076 if (opts.descending) {
6077 if ('endkey' in opts && typeof opts.endkey !== 'string') {
6078 opts.endkey = '';
6079 }
6080 if ('startkey' in opts && typeof opts.startkey !== 'string') {
6081 opts.limit = 0;
6082 }
6083 } else {
6084 if ('startkey' in opts && typeof opts.startkey !== 'string') {
6085 opts.startkey = '';
6086 }
6087 if ('endkey' in opts && typeof opts.endkey !== 'string') {
6088 opts.limit = 0;
6089 }
6090 }
6091 if ('key' in opts && typeof opts.key !== 'string') {
6092 opts.limit = 0;
6093 }
6094
6095 if (opts.limit > 0 && opts.indexes_count) {
6096 // brute force and quite naive impl.
6097 // amp up the limit with the amount of (indexes) design docs
6098 // or is this too naive? How about skip?
6099 opts.original_limit = opts.limit;
6100 opts.limit += opts.indexes_count;
6101 }
6102
6103 const res = await db.allDocs(opts);
6104 // filter out any design docs that _all_docs might return
6105 res.rows = res.rows.filter(function (row) {
6106 return !/^_design\//.test(row.id);
6107 });
6108 // put back original limit
6109 if (opts.original_limit) {
6110 opts.limit = opts.original_limit;
6111 }
6112 // enforce the rows to respect the given limit
6113 res.rows = res.rows.slice(0, opts.limit);
6114 return res;
6115}
6116
6117async function queryAllOrIndex(db, opts, indexToUse) {
6118 if (indexToUse.name === '_all_docs') {
6119 return doAllDocs(db, opts);
6120 }
6121 return abstractMapper$1(db).query.call(db, indexToSignature(indexToUse), opts);
6122}
6123
6124async function find$1(db, requestDef, explain) {
6125 if (requestDef.selector) {
6126 // must be validated before massaging
6127 validateSelector(requestDef.selector, false);
6128 requestDef.selector = massageSelector(requestDef.selector);
6129 }
6130
6131 if (requestDef.sort) {
6132 requestDef.sort = massageSort(requestDef.sort);
6133 }
6134
6135 if (requestDef.use_index) {
6136 requestDef.use_index = massageUseIndex(requestDef.use_index);
6137 }
6138
6139 if (!('limit' in requestDef)) {
6140 // Match the default limit of CouchDB
6141 requestDef.limit = 25;
6142 }
6143
6144 validateFindRequest(requestDef);
6145
6146 const getIndexesRes = await getIndexes$1(db);
6147
6148 db.constructor.emit('debug', ['find', 'planning query', requestDef]);
6149 const queryPlan = planQuery(requestDef, getIndexesRes.indexes);
6150 db.constructor.emit('debug', ['find', 'query plan', queryPlan]);
6151
6152 const indexToUse = queryPlan.index;
6153
6154 validateSort(requestDef, indexToUse);
6155
6156 let opts = Object.assign({
6157 include_docs: true,
6158 reduce: false,
6159 // Add amount of index for doAllDocs to use (related to issue #7810)
6160 indexes_count: getIndexesRes.total_rows,
6161 }, queryPlan.queryOpts);
6162
6163 if ('startkey' in opts && 'endkey' in opts &&
6164 collate(opts.startkey, opts.endkey) > 0) {
6165 // can't possibly return any results, startkey > endkey
6166 /* istanbul ignore next */
6167 return { docs: [] };
6168 }
6169
6170 const isDescending = requestDef.sort &&
6171 typeof requestDef.sort[0] !== 'string' &&
6172 getValue(requestDef.sort[0]) === 'desc';
6173
6174 if (isDescending) {
6175 // either all descending or all ascending
6176 opts.descending = true;
6177 opts = reverseOptions(opts);
6178 }
6179
6180 if (!queryPlan.inMemoryFields.length) {
6181 // no in-memory filtering necessary, so we can let the
6182 // database do the limit/skip for us
6183 opts.limit = requestDef.limit;
6184 if ('skip' in requestDef) {
6185 opts.skip = requestDef.skip;
6186 }
6187 }
6188
6189 if (explain) {
6190 return Promise.resolve(queryPlan, opts);
6191 }
6192
6193 const res = await queryAllOrIndex(db, opts, indexToUse);
6194
6195
6196 if (opts.inclusive_start === false) {
6197 // may have to manually filter the first one,
6198 // since couchdb has no true inclusive_start option
6199 res.rows = filterInclusiveStart(res.rows, opts.startkey, indexToUse);
6200 }
6201
6202 if (queryPlan.inMemoryFields.length) {
6203 // need to filter some stuff in-memory
6204 res.rows = filterInMemoryFields(res.rows, requestDef, queryPlan.inMemoryFields);
6205 }
6206
6207 const resp = {
6208 docs: res.rows.map(function (row) {
6209 const doc = row.doc;
6210 if (requestDef.fields) {
6211 return pick$1(doc, requestDef.fields);
6212 }
6213 return doc;
6214 })
6215 };
6216
6217 if (indexToUse.defaultUsed) {
6218 resp.warning = 'No matching index found, create an index to optimize query time.';
6219 }
6220
6221 return resp;
6222}
6223
6224async function explain$1(db, requestDef) {
6225 const queryPlan = await find$1(db, requestDef, true);
6226
6227 return {
6228 dbname: db.name,
6229 index: queryPlan.index,
6230 selector: requestDef.selector,
6231 range: {
6232 start_key: queryPlan.queryOpts.startkey,
6233 end_key: queryPlan.queryOpts.endkey,
6234 },
6235 opts: {
6236 use_index: requestDef.use_index || [],
6237 bookmark: "nil", //hardcoded to match CouchDB since its not supported,
6238 limit: requestDef.limit,
6239 skip: requestDef.skip,
6240 sort: requestDef.sort || {},
6241 fields: requestDef.fields,
6242 conflicts: false, //hardcoded to match CouchDB since its not supported,
6243 r: [49], // hardcoded to match CouchDB since its not support
6244 },
6245 limit: requestDef.limit,
6246 skip: requestDef.skip || 0,
6247 fields: requestDef.fields,
6248 };
6249}
6250
6251async function deleteIndex$1(db, index) {
6252
6253 if (!index.ddoc) {
6254 throw new Error('you must supply an index.ddoc when deleting');
6255 }
6256
6257 if (!index.name) {
6258 throw new Error('you must supply an index.name when deleting');
6259 }
6260
6261 const docId = index.ddoc;
6262 const viewName = index.name;
6263
6264 function deltaFun(doc) {
6265 if (Object.keys(doc.views).length === 1 && doc.views[viewName]) {
6266 // only one view in this ddoc, delete the whole ddoc
6267 return {_id: docId, _deleted: true};
6268 }
6269 // more than one view here, just remove the view
6270 delete doc.views[viewName];
6271 return doc;
6272 }
6273
6274 await upsert(db, docId, deltaFun);
6275 await abstractMapper$1(db).viewCleanup.apply(db);
6276 return { ok: true };
6277}
6278
6279const plugin = {};
6280plugin.createIndex = resolveToCallback(async function (requestDef) {
6281 if (typeof requestDef !== 'object') {
6282 throw new Error('you must provide an index to create');
6283 }
6284
6285 const createIndex$$1 = isRemote(this) ?
6286 createIndex : createIndex$1;
6287 return createIndex$$1(this, requestDef);
6288});
6289
6290plugin.find = resolveToCallback(async function (requestDef) {
6291 if (typeof requestDef !== 'object') {
6292 throw new Error('you must provide search parameters to find()');
6293 }
6294
6295 const find$$1 = isRemote(this) ? find : find$1;
6296 return find$$1(this, requestDef);
6297});
6298
6299plugin.explain = resolveToCallback(async function (requestDef) {
6300 if (typeof requestDef !== 'object') {
6301 throw new Error('you must provide search parameters to explain()');
6302 }
6303
6304 const find$$1 = isRemote(this) ? explain : explain$1;
6305 return find$$1(this, requestDef);
6306});
6307
6308plugin.getIndexes = resolveToCallback(async function () {
6309 const getIndexes$$1 = isRemote(this) ? getIndexes : getIndexes$1;
6310 return getIndexes$$1(this);
6311});
6312
6313plugin.deleteIndex = resolveToCallback(async function (indexDef) {
6314 if (typeof indexDef !== 'object') {
6315 throw new Error('you must provide an index to delete');
6316 }
6317
6318 const deleteIndex$$1 = isRemote(this) ?
6319 deleteIndex : deleteIndex$1;
6320 return deleteIndex$$1(this, indexDef);
6321});
6322
6323// this code only runs in the browser, as its own dist/ script
6324
6325if (typeof PouchDB === 'undefined') {
6326 guardedConsole('error', 'pouchdb-find plugin error: ' +
6327 'Cannot find global "PouchDB" object! ' +
6328 'Did you remember to include pouchdb.js?');
6329} else {
6330 PouchDB.plugin(plugin);
6331}
6332
6333},{"events":1,"spark-md5":2,"uuid":3}]},{},[18]);