신동해

Add MongoDB lib, Update server.js

Showing 298 changed files with 4706 additions and 0 deletions
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../semver/bin/semver" "$@"
else
exec node "$basedir/../semver/bin/semver" "$@"
fi
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver" %*
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../semver/bin/semver" $args
} else {
& "$basedir/node$exe" "$basedir/../semver/bin/semver" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../semver/bin/semver" $args
} else {
& "node$exe" "$basedir/../semver/bin/semver" $args
}
$ret=$LASTEXITCODE
}
exit $ret
......@@ -21,6 +21,15 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"node_modules/bl": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
"integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
"dependencies": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
}
},
"node_modules/body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
......@@ -41,6 +50,14 @@
"node": ">= 0.8"
}
},
"node_modules/bson": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
"integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==",
"engines": {
"node": ">=0.6.19"
}
},
"node_modules/bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
......@@ -81,6 +98,11 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
......@@ -89,6 +111,14 @@
"ms": "2.0.0"
}
},
"node_modules/denque": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz",
"integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==",
"engines": {
"node": ">=0.10"
}
},
"node_modules/depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
......@@ -240,6 +270,11 @@
"node": ">= 0.10"
}
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
......@@ -248,6 +283,12 @@
"node": ">= 0.6"
}
},
"node_modules/memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"optional": true
},
"node_modules/merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
......@@ -291,6 +332,44 @@
"node": ">= 0.6"
}
},
"node_modules/mongodb": {
"version": "3.6.4",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.4.tgz",
"integrity": "sha512-Y+Ki9iXE9jI+n9bVtbTOOdK0B95d6wVGSucwtBkvQ+HIvVdTCfpVRp01FDC24uhC/Q2WXQ8Lpq3/zwtB5Op9Qw==",
"dependencies": {
"bl": "^2.2.1",
"bson": "^1.1.4",
"denque": "^1.4.1",
"require_optional": "^1.0.1",
"safe-buffer": "^5.1.2"
},
"engines": {
"node": ">=4"
},
"optionalDependencies": {
"saslprep": "^1.0.0"
},
"peerDependenciesMeta": {
"aws4": {
"optional": true
},
"bson-ext": {
"optional": true
},
"kerberos": {
"optional": true
},
"mongodb-client-encryption": {
"optional": true
},
"mongodb-extjson": {
"optional": true
},
"snappy": {
"optional": true
}
}
},
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
......@@ -328,6 +407,11 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
......@@ -370,6 +454,37 @@
"node": ">= 0.8"
}
},
"node_modules/readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/require_optional": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
"dependencies": {
"resolve-from": "^2.0.0",
"semver": "^5.1.0"
}
},
"node_modules/resolve-from": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
"integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
......@@ -380,6 +495,26 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/saslprep": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
"optional": true,
"dependencies": {
"sparse-bitfield": "^3.0.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"bin": {
"semver": "bin/semver"
}
},
"node_modules/send": {
"version": "0.17.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
......@@ -427,6 +562,15 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
"node_modules/sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
"optional": true,
"dependencies": {
"memory-pager": "^1.0.2"
}
},
"node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
......@@ -435,6 +579,14 @@
"node": ">= 0.6"
}
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
......@@ -463,6 +615,11 @@
"node": ">= 0.8"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
......
{
"predef": [ ]
, "bitwise": false
, "camelcase": false
, "curly": false
, "eqeqeq": false
, "forin": false
, "immed": false
, "latedef": false
, "noarg": true
, "noempty": true
, "nonew": true
, "plusplus": false
, "quotmark": true
, "regexp": false
, "undef": true
, "unused": true
, "strict": false
, "trailing": true
, "maxlen": 120
, "asi": true
, "boss": true
, "debug": true
, "eqnull": true
, "esnext": false
, "evil": true
, "expr": true
, "funcscope": false
, "globalstrict": false
, "iterator": false
, "lastsemic": true
, "laxbreak": true
, "laxcomma": true
, "loopfunc": true
, "multistr": false
, "onecase": false
, "proto": false
, "regexdash": false
, "scripturl": true
, "smarttabs": false
, "shadow": false
, "sub": true
, "supernew": false
, "validthis": true
, "browser": true
, "couch": false
, "devel": false
, "dojo": false
, "mootools": false
, "node": true
, "nonstandard": true
, "prototypejs": false
, "rhino": false
, "worker": true
, "wsh": false
, "nomen": false
, "onevar": false
, "passfail": false
, "esversion": 3
}
\ No newline at end of file
sudo: false
language: node_js
node_js:
- '4'
- '6'
- '8'
- '9'
- '10'
branches:
only:
- master
notifications:
email:
- rod@vagg.org
- matteo.collina@gmail.com
The MIT License (MIT)
=====================
Copyright (c) 2013-2018 bl contributors
----------------------------------
*bl contributors listed at <https://github.com/rvagg/bl#contributors>*
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This diff is collapsed. Click to expand it.
'use strict'
var DuplexStream = require('readable-stream').Duplex
, util = require('util')
, Buffer = require('safe-buffer').Buffer
function BufferList (callback) {
if (!(this instanceof BufferList))
return new BufferList(callback)
this._bufs = []
this.length = 0
if (typeof callback == 'function') {
this._callback = callback
var piper = function piper (err) {
if (this._callback) {
this._callback(err)
this._callback = null
}
}.bind(this)
this.on('pipe', function onPipe (src) {
src.on('error', piper)
})
this.on('unpipe', function onUnpipe (src) {
src.removeListener('error', piper)
})
} else {
this.append(callback)
}
DuplexStream.call(this)
}
util.inherits(BufferList, DuplexStream)
BufferList.prototype._offset = function _offset (offset) {
var tot = 0, i = 0, _t
if (offset === 0) return [ 0, 0 ]
for (; i < this._bufs.length; i++) {
_t = tot + this._bufs[i].length
if (offset < _t || i == this._bufs.length - 1) {
return [ i, offset - tot ]
}
tot = _t
}
}
BufferList.prototype._reverseOffset = function (blOffset) {
var bufferId = blOffset[0]
var offset = blOffset[1]
for (var i = 0; i < bufferId; i++) {
offset += this._bufs[i].length
}
return offset
}
BufferList.prototype.append = function append (buf) {
var i = 0
if (Buffer.isBuffer(buf)) {
this._appendBuffer(buf)
} else if (Array.isArray(buf)) {
for (; i < buf.length; i++)
this.append(buf[i])
} else if (buf instanceof BufferList) {
// unwrap argument into individual BufferLists
for (; i < buf._bufs.length; i++)
this.append(buf._bufs[i])
} else if (buf != null) {
// coerce number arguments to strings, since Buffer(number) does
// uninitialized memory allocation
if (typeof buf == 'number')
buf = buf.toString()
this._appendBuffer(Buffer.from(buf))
}
return this
}
BufferList.prototype._appendBuffer = function appendBuffer (buf) {
this._bufs.push(buf)
this.length += buf.length
}
BufferList.prototype._write = function _write (buf, encoding, callback) {
this._appendBuffer(buf)
if (typeof callback == 'function')
callback()
}
BufferList.prototype._read = function _read (size) {
if (!this.length)
return this.push(null)
size = Math.min(size, this.length)
this.push(this.slice(0, size))
this.consume(size)
}
BufferList.prototype.end = function end (chunk) {
DuplexStream.prototype.end.call(this, chunk)
if (this._callback) {
this._callback(null, this.slice())
this._callback = null
}
}
BufferList.prototype.get = function get (index) {
if (index > this.length || index < 0) {
return undefined
}
var offset = this._offset(index)
return this._bufs[offset[0]][offset[1]]
}
BufferList.prototype.slice = function slice (start, end) {
if (typeof start == 'number' && start < 0)
start += this.length
if (typeof end == 'number' && end < 0)
end += this.length
return this.copy(null, 0, start, end)
}
BufferList.prototype.copy = function copy (dst, dstStart, srcStart, srcEnd) {
if (typeof srcStart != 'number' || srcStart < 0)
srcStart = 0
if (typeof srcEnd != 'number' || srcEnd > this.length)
srcEnd = this.length
if (srcStart >= this.length)
return dst || Buffer.alloc(0)
if (srcEnd <= 0)
return dst || Buffer.alloc(0)
var copy = !!dst
, off = this._offset(srcStart)
, len = srcEnd - srcStart
, bytes = len
, bufoff = (copy && dstStart) || 0
, start = off[1]
, l
, i
// copy/slice everything
if (srcStart === 0 && srcEnd == this.length) {
if (!copy) { // slice, but full concat if multiple buffers
return this._bufs.length === 1
? this._bufs[0]
: Buffer.concat(this._bufs, this.length)
}
// copy, need to copy individual buffers
for (i = 0; i < this._bufs.length; i++) {
this._bufs[i].copy(dst, bufoff)
bufoff += this._bufs[i].length
}
return dst
}
// easy, cheap case where it's a subset of one of the buffers
if (bytes <= this._bufs[off[0]].length - start) {
return copy
? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes)
: this._bufs[off[0]].slice(start, start + bytes)
}
if (!copy) // a slice, we need something to copy in to
dst = Buffer.allocUnsafe(len)
for (i = off[0]; i < this._bufs.length; i++) {
l = this._bufs[i].length - start
if (bytes > l) {
this._bufs[i].copy(dst, bufoff, start)
bufoff += l
} else {
this._bufs[i].copy(dst, bufoff, start, start + bytes)
bufoff += l
break
}
bytes -= l
if (start)
start = 0
}
// safeguard so that we don't return uninitialized memory
if (dst.length > bufoff) return dst.slice(0, bufoff)
return dst
}
BufferList.prototype.shallowSlice = function shallowSlice (start, end) {
start = start || 0
end = typeof end !== 'number' ? this.length : end
if (start < 0)
start += this.length
if (end < 0)
end += this.length
if (start === end) {
return new BufferList()
}
var startOffset = this._offset(start)
, endOffset = this._offset(end)
, buffers = this._bufs.slice(startOffset[0], endOffset[0] + 1)
if (endOffset[1] == 0)
buffers.pop()
else
buffers[buffers.length-1] = buffers[buffers.length-1].slice(0, endOffset[1])
if (startOffset[1] != 0)
buffers[0] = buffers[0].slice(startOffset[1])
return new BufferList(buffers)
}
BufferList.prototype.toString = function toString (encoding, start, end) {
return this.slice(start, end).toString(encoding)
}
BufferList.prototype.consume = function consume (bytes) {
// first, normalize the argument, in accordance with how Buffer does it
bytes = Math.trunc(bytes)
// do nothing if not a positive number
if (Number.isNaN(bytes) || bytes <= 0) return this
while (this._bufs.length) {
if (bytes >= this._bufs[0].length) {
bytes -= this._bufs[0].length
this.length -= this._bufs[0].length
this._bufs.shift()
} else {
this._bufs[0] = this._bufs[0].slice(bytes)
this.length -= bytes
break
}
}
return this
}
BufferList.prototype.duplicate = function duplicate () {
var i = 0
, copy = new BufferList()
for (; i < this._bufs.length; i++)
copy.append(this._bufs[i])
return copy
}
BufferList.prototype.destroy = function destroy () {
this._bufs.length = 0
this.length = 0
this.push(null)
}
BufferList.prototype.indexOf = function (search, offset, encoding) {
if (encoding === undefined && typeof offset === 'string') {
encoding = offset
offset = undefined
}
if (typeof search === 'function' || Array.isArray(search)) {
throw new TypeError('The "value" argument must be one of type string, Buffer, BufferList, or Uint8Array.')
} else if (typeof search === 'number') {
search = Buffer.from([search])
} else if (typeof search === 'string') {
search = Buffer.from(search, encoding)
} else if (search instanceof BufferList) {
search = search.slice()
} else if (!Buffer.isBuffer(search)) {
search = Buffer.from(search)
}
offset = Number(offset || 0)
if (isNaN(offset)) {
offset = 0
}
if (offset < 0) {
offset = this.length + offset
}
if (offset < 0) {
offset = 0
}
if (search.length === 0) {
return offset > this.length ? this.length : offset
}
var blOffset = this._offset(offset)
var blIndex = blOffset[0] // index of which internal buffer we're working on
var buffOffset = blOffset[1] // offset of the internal buffer we're working on
// scan over each buffer
for (blIndex; blIndex < this._bufs.length; blIndex++) {
var buff = this._bufs[blIndex]
while(buffOffset < buff.length) {
var availableWindow = buff.length - buffOffset
if (availableWindow >= search.length) {
var nativeSearchResult = buff.indexOf(search, buffOffset)
if (nativeSearchResult !== -1) {
return this._reverseOffset([blIndex, nativeSearchResult])
}
buffOffset = buff.length - search.length + 1 // end of native search window
} else {
var revOffset = this._reverseOffset([blIndex, buffOffset])
if (this._match(revOffset, search)) {
return revOffset
}
buffOffset++
}
}
buffOffset = 0
}
return -1
}
BufferList.prototype._match = function(offset, search) {
if (this.length - offset < search.length) {
return false
}
for (var searchOffset = 0; searchOffset < search.length ; searchOffset++) {
if(this.get(offset + searchOffset) !== search[searchOffset]){
return false
}
}
return true
}
;(function () {
var methods = {
'readDoubleBE' : 8
, 'readDoubleLE' : 8
, 'readFloatBE' : 4
, 'readFloatLE' : 4
, 'readInt32BE' : 4
, 'readInt32LE' : 4
, 'readUInt32BE' : 4
, 'readUInt32LE' : 4
, 'readInt16BE' : 2
, 'readInt16LE' : 2
, 'readUInt16BE' : 2
, 'readUInt16LE' : 2
, 'readInt8' : 1
, 'readUInt8' : 1
, 'readIntBE' : null
, 'readIntLE' : null
, 'readUIntBE' : null
, 'readUIntLE' : null
}
for (var m in methods) {
(function (m) {
if (methods[m] === null) {
BufferList.prototype[m] = function (offset, byteLength) {
return this.slice(offset, offset + byteLength)[m](0, byteLength)
}
}
else {
BufferList.prototype[m] = function (offset) {
return this.slice(offset, offset + methods[m])[m](0)
}
}
}(m))
}
}())
module.exports = BufferList
{
"name": "bl",
"version": "2.2.1",
"description": "Buffer List: collect buffers and access with a standard readable Buffer interface, streamable too!",
"main": "bl.js",
"scripts": {
"test": "node test/test.js | faucet"
},
"repository": {
"type": "git",
"url": "https://github.com/rvagg/bl.git"
},
"homepage": "https://github.com/rvagg/bl",
"authors": [
"Rod Vagg <rod@vagg.org> (https://github.com/rvagg)",
"Matteo Collina <matteo.collina@gmail.com> (https://github.com/mcollina)",
"Jarett Cruger <jcrugzz@gmail.com> (https://github.com/jcrugzz)"
],
"keywords": [
"buffer",
"buffers",
"stream",
"awesomesauce"
],
"license": "MIT",
"dependencies": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
},
"devDependencies": {
"faucet": "0.0.1",
"hash_file": "~0.1.1",
"tape": "~4.9.0"
}
}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [1.1.6](https://github.com/mongodb/js-bson/compare/v1.1.5...v1.1.6) (2021-03-16)
### Bug Fixes
* Throw error on bigint usage and add helpers to Long ([#426](https://github.com/mongodb/js-bson/issues/426)) ([375f368](https://github.com/mongodb/js-bson/commit/375f368738807f2d41c7751e618fd09c8a1b94c9))
### [1.1.5](https://github.com/mongodb/js-bson/compare/v1.1.4...v1.1.5) (2020-08-10)
### Bug Fixes
* **object-id:** harden the duck-typing ([b526145](https://github.com/mongodb/js-bson/commit/b5261450c3bc4abb2e2fb19b5b1a7aba27982d44))
<a name="1.1.3"></a>
## [1.1.3](https://github.com/mongodb/js-bson/compare/v1.1.2...v1.1.3) (2019-11-09)
Reverts 1.1.2
<a name="1.1.2"></a>
## [1.1.2](https://github.com/mongodb/js-bson/compare/v1.1.1...v1.1.2) (2019-11-08)
### Bug Fixes
* **_bsontype:** only check bsontype if it is a prototype member. ([dd8a349](https://github.com/mongodb/js-bson/commit/dd8a349))
<a name="1.1.1"></a>
## [1.1.1](https://github.com/mongodb/js-bson/compare/v1.1.0...v1.1.1) (2019-03-08)
### Bug Fixes
* **object-id:** support 4.x->1.x interop for MinKey and ObjectId ([53419a5](https://github.com/mongodb/js-bson/commit/53419a5))
### Features
* replace new Buffer with modern versions ([24aefba](https://github.com/mongodb/js-bson/commit/24aefba))
<a name="1.1.0"></a>
# [1.1.0](https://github.com/mongodb/js-bson/compare/v1.0.9...v1.1.0) (2018-08-13)
### Bug Fixes
* **serializer:** do not use checkKeys for $clusterTime ([573e141](https://github.com/mongodb/js-bson/commit/573e141))
<a name="1.0.9"></a>
## [1.0.9](https://github.com/mongodb/js-bson/compare/v1.0.8...v1.0.9) (2018-06-07)
### Bug Fixes
* **serializer:** remove use of `const` ([5feb12f](https://github.com/mongodb/js-bson/commit/5feb12f))
<a name="1.0.7"></a>
## [1.0.7](https://github.com/mongodb/js-bson/compare/v1.0.6...v1.0.7) (2018-06-06)
### Bug Fixes
* **binary:** add type checking for buffer ([26b05b5](https://github.com/mongodb/js-bson/commit/26b05b5))
* **bson:** fix custom inspect property ([080323b](https://github.com/mongodb/js-bson/commit/080323b))
* **readme:** clarify documentation about deserialize methods ([20f764c](https://github.com/mongodb/js-bson/commit/20f764c))
* **serialization:** normalize function stringification ([1320c10](https://github.com/mongodb/js-bson/commit/1320c10))
<a name="1.0.6"></a>
## [1.0.6](https://github.com/mongodb/js-bson/compare/v1.0.5...v1.0.6) (2018-03-12)
### Features
* **serialization:** support arbitrary sizes for the internal serialization buffer ([abe97bc](https://github.com/mongodb/js-bson/commit/abe97bc))
<a name="1.0.5"></a>
## 1.0.5 (2018-02-26)
### Bug Fixes
* **decimal128:** add basic guard against REDOS attacks ([bd61c45](https://github.com/mongodb/js-bson/commit/bd61c45))
* **objectid:** if pid is 1, use random value ([e188ae6](https://github.com/mongodb/js-bson/commit/e188ae6))
1.0.4 2016-01-11
----------------
- #204 remove Buffer.from as it's partially broken in early 4.x.x. series of node releases.
1.0.3 2016-01-03
----------------
- Fixed toString for ObjectId so it will work with inspect.
1.0.2 2016-01-02
----------------
- Minor optimizations for ObjectID to use Buffer.from where available.
1.0.1 2016-12-06
----------------
- Reverse behavior for undefined to be serialized as NULL. MongoDB 3.4 does not allow for undefined comparisons.
1.0.0 2016-12-06
----------------
- Introduced new BSON API and documentation.
0.5.7 2016-11-18
-----------------
- NODE-848 BSON Regex flags must be alphabetically ordered.
0.5.6 2016-10-19
-----------------
- NODE-833, Detects cyclic dependencies in documents and throws error if one is found.
- Fix(deserializer): corrected the check for (size + index) comparison… (Issue #195, https://github.com/JoelParke).
0.5.5 2016-09-15
-----------------
- Added DBPointer up conversion to DBRef
0.5.4 2016-08-23
-----------------
- Added promoteValues flag (default to true) allowing user to specify if deserialization should be into wrapper classes only.
0.5.3 2016-07-11
-----------------
- Throw error if ObjectId is not a string or a buffer.
0.5.2 2016-07-11
-----------------
- All values encoded big-endian style for ObjectId.
0.5.1 2016-07-11
-----------------
- Fixed encoding/decoding issue in ObjectId timestamp generation.
- Removed BinaryParser dependency from the serializer/deserializer.
0.5.0 2016-07-05
-----------------
- Added Decimal128 type and extended test suite to include entire bson corpus.
0.4.23 2016-04-08
-----------------
- Allow for proper detection of ObjectId or objects that look like ObjectId, improving compatibility across third party libraries.
- Remove one package from dependency due to having been pulled from NPM.
0.4.22 2016-03-04
-----------------
- Fix "TypeError: data.copy is not a function" in Electron (Issue #170, https://github.com/kangas).
- Fixed issue with undefined type on deserializing.
0.4.21 2016-01-12
-----------------
- Minor optimizations to avoid non needed object creation.
0.4.20 2015-10-15
-----------------
- Added bower file to repository.
- Fixed browser pid sometimes set greater than 0xFFFF on browsers (Issue #155, https://github.com/rahatarmanahmed)
0.4.19 2015-10-15
-----------------
- Remove all support for bson-ext.
0.4.18 2015-10-15
-----------------
- ObjectID equality check should return boolean instead of throwing exception for invalid oid string #139
- add option for deserializing binary into Buffer object #116
0.4.17 2015-10-15
-----------------
- Validate regexp string for null bytes and throw if there is one.
0.4.16 2015-10-07
-----------------
- Fixed issue with return statement in Map.js.
0.4.15 2015-10-06
-----------------
- Exposed Map correctly via index.js file.
0.4.14 2015-10-06
-----------------
- Exposed Map correctly via bson.js file.
0.4.13 2015-10-06
-----------------
- Added ES6 Map type serialization as well as a polyfill for ES5.
0.4.12 2015-09-18
-----------------
- Made ignore undefined an optional parameter.
0.4.11 2015-08-06
-----------------
- Minor fix for invalid key checking.
0.4.10 2015-08-06
-----------------
- NODE-38 Added new BSONRegExp type to allow direct serialization to MongoDB type.
- Some performance improvements by in lining code.
0.4.9 2015-08-06
----------------
- Undefined fields are omitted from serialization in objects.
0.4.8 2015-07-14
----------------
- Fixed size validation to ensure we can deserialize from dumped files.
0.4.7 2015-06-26
----------------
- Added ability to instruct deserializer to return raw BSON buffers for named array fields.
- Minor deserialization optimization by moving inlined function out.
0.4.6 2015-06-17
----------------
- Fixed serializeWithBufferAndIndex bug.
0.4.5 2015-06-17
----------------
- Removed any references to the shared buffer to avoid non GC collectible bson instances.
0.4.4 2015-06-17
----------------
- Fixed rethrowing of error when not RangeError.
0.4.3 2015-06-17
----------------
- Start buffer at 64K and double as needed, meaning we keep a low memory profile until needed.
0.4.2 2015-06-16
----------------
- More fixes for corrupt Bson
0.4.1 2015-06-16
----------------
- More fixes for corrupt Bson
0.4.0 2015-06-16
----------------
- New JS serializer serializing into a single buffer then copying out the new buffer. Performance is similar to current C++ parser.
- Removed bson-ext extension dependency for now.
0.3.2 2015-03-27
----------------
- Removed node-gyp from install script in package.json.
0.3.1 2015-03-27
----------------
- Return pure js version on native() call if failed to initialize.
0.3.0 2015-03-26
----------------
- Pulled out all C++ code into bson-ext and made it an optional dependency.
0.2.21 2015-03-21
-----------------
- Updated Nan to 1.7.0 to support io.js and node 0.12.0
0.2.19 2015-02-16
-----------------
- Updated Nan to 1.6.2 to support io.js and node 0.12.0
0.2.18 2015-01-20
-----------------
- Updated Nan to 1.5.1 to support io.js
0.2.16 2014-12-17
-----------------
- Made pid cycle on 0xffff to avoid weird overflows on creation of ObjectID's
0.2.12 2014-08-24
-----------------
- Fixes for fortify review of c++ extension
- toBSON correctly allows returns of non objects
0.2.3 2013-10-01
----------------
- Drying of ObjectId code for generation of id (Issue #54, https://github.com/moredip)
- Fixed issue where corrupt CString's could cause endless loop
- Support for Node 0.11.X > (Issue #49, https://github.com/kkoopa)
0.1.4 2012-09-25
----------------
- Added precompiled c++ native extensions for win32 ia32 and x64
This diff is collapsed. Click to expand it.
# BSON parser
BSON is short for Bin­ary JSON and is the bin­ary-en­coded seri­al­iz­a­tion of JSON-like doc­u­ments. You can learn more about it in [the specification](http://bsonspec.org).
This browser version of the BSON parser is compiled using [webpack](https://webpack.js.org/) and the current version is pre-compiled in the `browser_build` directory.
This is the default BSON parser, however, there is a C++ Node.js addon version as well that does not support the browser. It can be found at [mongod-js/bson-ext](https://github.com/mongodb-js/bson-ext).
## Usage
To build a new version perform the following operations:
```
npm install
npm run build
```
A simple example of how to use BSON in the browser:
```html
<script src="./browser_build/bson.js"></script>
<script>
function start() {
// Get the Long type
var Long = BSON.Long;
// Create a bson parser instance
var bson = new BSON();
// Serialize document
var doc = { long: Long.fromNumber(100) }
// Serialize a document
var data = bson.serialize(doc)
// De serialize it again
var doc_2 = bson.deserialize(data)
}
</script>
```
A simple example of how to use BSON in `Node.js`:
```js
// Get BSON parser class
var BSON = require('bson')
// Get the Long type
var Long = BSON.Long;
// Create a bson parser instance
var bson = new BSON();
// Serialize document
var doc = { long: Long.fromNumber(100) }
// Serialize a document
var data = bson.serialize(doc)
console.log('data:', data)
// Deserialize the resulting Buffer
var doc_2 = bson.deserialize(data)
console.log('doc_2:', doc_2)
```
## Installation
`npm install bson`
## API
### BSON types
For all BSON types documentation, please refer to the following sources:
* [MongoDB BSON Type Reference](https://docs.mongodb.com/manual/reference/bson-types/)
* [BSON Spec](https://bsonspec.org/)
### BSON serialization and deserialiation
**`new BSON()`** - Creates a new BSON serializer/deserializer you can use to serialize and deserialize BSON.
#### BSON.serialize
The BSON `serialize` method takes a JavaScript object and an optional options object and returns a Node.js Buffer.
* `BSON.serialize(object, options)`
* @param {Object} object the JavaScript object to serialize.
* @param {Boolean} [options.checkKeys=false] the serializer will check if keys are valid.
* @param {Boolean} [options.serializeFunctions=false] serialize the JavaScript functions.
* @param {Boolean} [options.ignoreUndefined=true]
* @return {Buffer} returns a Buffer instance.
#### BSON.serializeWithBufferAndIndex
The BSON `serializeWithBufferAndIndex` method takes an object, a target buffer instance and an optional options object and returns the end serialization index in the final buffer.
* `BSON.serializeWithBufferAndIndex(object, buffer, options)`
* @param {Object} object the JavaScript object to serialize.
* @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object.
* @param {Boolean} [options.checkKeys=false] the serializer will check if keys are valid.
* @param {Boolean} [options.serializeFunctions=false] serialize the JavaScript functions.
* @param {Boolean} [options.ignoreUndefined=true] ignore undefined fields.
* @param {Number} [options.index=0] the index in the buffer where we wish to start serializing into.
* @return {Number} returns the index pointing to the last written byte in the buffer.
#### BSON.calculateObjectSize
The BSON `calculateObjectSize` method takes a JavaScript object and an optional options object and returns the size of the BSON object.
* `BSON.calculateObjectSize(object, options)`
* @param {Object} object the JavaScript object to serialize.
* @param {Boolean} [options.serializeFunctions=false] serialize the JavaScript functions.
* @param {Boolean} [options.ignoreUndefined=true]
* @return {Buffer} returns a Buffer instance.
#### BSON.deserialize
The BSON `deserialize` method takes a Node.js Buffer and an optional options object and returns a deserialized JavaScript object.
* `BSON.deserialize(buffer, options)`
* @param {Object} [options.evalFunctions=false] evaluate functions in the BSON document scoped to the object deserialized.
* @param {Object} [options.cacheFunctions=false] cache evaluated functions for reuse.
* @param {Object} [options.cacheFunctionsCrc32=false] use a crc32 code for caching, otherwise use the string of the function.
* @param {Object} [options.promoteLongs=true] when deserializing a Long will fit it into a Number if it's smaller than 53 bits
* @param {Object} [options.promoteBuffers=false] when deserializing a Binary will return it as a Node.js Buffer instance.
* @param {Object} [options.promoteValues=false] when deserializing will promote BSON values to their Node.js closest equivalent types.
* @param {Object} [options.fieldsAsRaw=null] allow to specify if there what fields we wish to return as unserialized raw buffer.
* @param {Object} [options.bsonRegExp=false] return BSON regular expressions as BSONRegExp instances.
* @return {Object} returns the deserialized Javascript Object.
#### BSON.deserializeStream
The BSON `deserializeStream` method takes a Node.js Buffer, `startIndex` and allow more control over deserialization of a Buffer containing concatenated BSON documents.
* `BSON.deserializeStream(buffer, startIndex, numberOfDocuments, documents, docStartIndex, options)`
* @param {Buffer} buffer the buffer containing the serialized set of BSON documents.
* @param {Number} startIndex the start index in the data Buffer where the deserialization is to start.
* @param {Number} numberOfDocuments number of documents to deserialize.
* @param {Array} documents an array where to store the deserialized documents.
* @param {Number} docStartIndex the index in the documents array from where to start inserting documents.
* @param {Object} [options.evalFunctions=false] evaluate functions in the BSON document scoped to the object deserialized.
* @param {Object} [options.cacheFunctions=false] cache evaluated functions for reuse.
* @param {Object} [options.cacheFunctionsCrc32=false] use a crc32 code for caching, otherwise use the string of the function.
* @param {Object} [options.promoteLongs=true] when deserializing a Long will fit it into a Number if it's smaller than 53 bits
* @param {Object} [options.promoteBuffers=false] when deserializing a Binary will return it as a Node.js Buffer instance.
* @param {Object} [options.promoteValues=false] when deserializing will promote BSON values to their Node.js closest equivalent types.
* @param {Object} [options.fieldsAsRaw=null] allow to specify if there what fields we wish to return as unserialized raw buffer.
* @param {Object} [options.bsonRegExp=false] return BSON regular expressions as BSONRegExp instances.
* @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents.
## FAQ
#### Why does `undefined` get converted to `null`?
The `undefined` BSON type has been [deprecated for many years](http://bsonspec.org/spec.html), so this library has dropped support for it. Use the `ignoreUndefined` option (for example, from the [driver](http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html#connect) ) to instead remove `undefined` keys.
#### How do I add custom serialization logic?
This library looks for `toBSON()` functions on every path, and calls the `toBSON()` function to get the value to serialize.
```javascript
var bson = new BSON();
class CustomSerialize {
toBSON() {
return 42;
}
}
const obj = { answer: new CustomSerialize() };
// "{ answer: 42 }"
console.log(bson.deserialize(bson.serialize(obj)));
```
{
"name": "bson",
"description": "A bson parser for node.js and the browser",
"keywords": [
"mongodb",
"bson",
"parser"
],
"author": "Christian Amor Kvalheim <christkv@gmail.com>",
"main": "./browser_build/bson.js",
"license": "Apache-2.0",
"moduleType": [
"globals",
"node"
],
"ignore": [
"**/.*",
"alternate_parsers",
"benchmarks",
"bower_components",
"node_modules",
"test",
"tools"
],
"version": "1.1.6"
}
This diff could not be displayed because it is too large.
{ "name" : "bson"
, "description" : "A bson parser for node.js and the browser"
, "main": "../"
, "directories" : { "lib" : "../lib/bson" }
, "engines" : { "node" : ">=0.6.0" }
, "licenses" : [ { "type" : "Apache License, Version 2.0"
, "url" : "http://www.apache.org/licenses/LICENSE-2.0" } ]
}
var BSON = require('./lib/bson/bson'),
Binary = require('./lib/bson/binary'),
Code = require('./lib/bson/code'),
DBRef = require('./lib/bson/db_ref'),
Decimal128 = require('./lib/bson/decimal128'),
Double = require('./lib/bson/double'),
Int32 = require('./lib/bson/int_32'),
Long = require('./lib/bson/long'),
Map = require('./lib/bson/map'),
MaxKey = require('./lib/bson/max_key'),
MinKey = require('./lib/bson/min_key'),
ObjectId = require('./lib/bson/objectid'),
BSONRegExp = require('./lib/bson/regexp'),
Symbol = require('./lib/bson/symbol'),
Timestamp = require('./lib/bson/timestamp');
// BSON MAX VALUES
BSON.BSON_INT32_MAX = 0x7fffffff;
BSON.BSON_INT32_MIN = -0x80000000;
BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1;
BSON.BSON_INT64_MIN = -Math.pow(2, 63);
// JS MAX PRECISE VALUES
BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double.
BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double.
// Add BSON types to function creation
BSON.Binary = Binary;
BSON.Code = Code;
BSON.DBRef = DBRef;
BSON.Decimal128 = Decimal128;
BSON.Double = Double;
BSON.Int32 = Int32;
BSON.Long = Long;
BSON.Map = Map;
BSON.MaxKey = MaxKey;
BSON.MinKey = MinKey;
BSON.ObjectId = ObjectId;
BSON.ObjectID = ObjectId;
BSON.BSONRegExp = BSONRegExp;
BSON.Symbol = Symbol;
BSON.Timestamp = Timestamp;
// Return the BSON
module.exports = BSON;
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
/**
* A class representation of the BSON Code type.
*
* @class
* @param {(string|function)} code a string or function.
* @param {Object} [scope] an optional scope for the function.
* @return {Code}
*/
var Code = function Code(code, scope) {
if (!(this instanceof Code)) return new Code(code, scope);
this._bsontype = 'Code';
this.code = code;
this.scope = scope;
};
/**
* @ignore
*/
Code.prototype.toJSON = function() {
return { scope: this.scope, code: this.code };
};
module.exports = Code;
module.exports.Code = Code;
/**
* A class representation of the BSON DBRef type.
*
* @class
* @param {string} namespace the collection name.
* @param {ObjectID} oid the reference ObjectID.
* @param {string} [db] optional db name, if omitted the reference is local to the current db.
* @return {DBRef}
*/
function DBRef(namespace, oid, db) {
if (!(this instanceof DBRef)) return new DBRef(namespace, oid, db);
this._bsontype = 'DBRef';
this.namespace = namespace;
this.oid = oid;
this.db = db;
}
/**
* @ignore
* @api private
*/
DBRef.prototype.toJSON = function() {
return {
$ref: this.namespace,
$id: this.oid,
$db: this.db == null ? '' : this.db
};
};
module.exports = DBRef;
module.exports.DBRef = DBRef;
This diff is collapsed. Click to expand it.
/**
* A class representation of the BSON Double type.
*
* @class
* @param {number} value the number we want to represent as a double.
* @return {Double}
*/
function Double(value) {
if (!(this instanceof Double)) return new Double(value);
this._bsontype = 'Double';
this.value = value;
}
/**
* Access the number value.
*
* @method
* @return {number} returns the wrapped double number.
*/
Double.prototype.valueOf = function() {
return this.value;
};
/**
* @ignore
*/
Double.prototype.toJSON = function() {
return this.value;
};
module.exports = Double;
module.exports.Double = Double;
// Copyright (c) 2008, Fair Oaks Labs, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//
// Modifications to writeIEEE754 to support negative zeroes made by Brian White
var readIEEE754 = function(buffer, offset, endian, mLen, nBytes) {
var e,
m,
bBE = endian === 'big',
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
nBits = -7,
i = bBE ? 0 : nBytes - 1,
d = bBE ? 1 : -1,
s = buffer[offset + i];
i += d;
e = s & ((1 << -nBits) - 1);
s >>= -nBits;
nBits += eLen;
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
m = e & ((1 << -nBits) - 1);
e >>= -nBits;
nBits += mLen;
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
if (e === 0) {
e = 1 - eBias;
} else if (e === eMax) {
return m ? NaN : (s ? -1 : 1) * Infinity;
} else {
m = m + Math.pow(2, mLen);
e = e - eBias;
}
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
};
var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) {
var e,
m,
c,
bBE = endian === 'big',
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0,
i = bBE ? nBytes - 1 : 0,
d = bBE ? -1 : 1,
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
value = Math.abs(value);
if (isNaN(value) || value === Infinity) {
m = isNaN(value) ? 1 : 0;
e = eMax;
} else {
e = Math.floor(Math.log(value) / Math.LN2);
if (value * (c = Math.pow(2, -e)) < 1) {
e--;
c *= 2;
}
if (e + eBias >= 1) {
value += rt / c;
} else {
value += rt * Math.pow(2, 1 - eBias);
}
if (value * c >= 2) {
e++;
c /= 2;
}
if (e + eBias >= eMax) {
m = 0;
e = eMax;
} else if (e + eBias >= 1) {
m = (value * c - 1) * Math.pow(2, mLen);
e = e + eBias;
} else {
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
e = 0;
}
}
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
e = (e << mLen) | m;
eLen += mLen;
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
buffer[offset + i - d] |= s * 128;
};
exports.readIEEE754 = readIEEE754;
exports.writeIEEE754 = writeIEEE754;
/**
* A class representation of a BSON Int32 type.
*
* @class
* @param {number} value the number we want to represent as an int32.
* @return {Int32}
*/
var Int32 = function(value) {
if (!(this instanceof Int32)) return new Int32(value);
this._bsontype = 'Int32';
this.value = value;
};
/**
* Access the number value.
*
* @method
* @return {number} returns the wrapped int32 number.
*/
Int32.prototype.valueOf = function() {
return this.value;
};
/**
* @ignore
*/
Int32.prototype.toJSON = function() {
return this.value;
};
module.exports = Int32;
module.exports.Int32 = Int32;
This diff is collapsed. Click to expand it.
'use strict';
// We have an ES6 Map available, return the native instance
if (typeof global.Map !== 'undefined') {
module.exports = global.Map;
module.exports.Map = global.Map;
} else {
// We will return a polyfill
var Map = function(array) {
this._keys = [];
this._values = {};
for (var i = 0; i < array.length; i++) {
if (array[i] == null) continue; // skip null and undefined
var entry = array[i];
var key = entry[0];
var value = entry[1];
// Add the key to the list of keys in order
this._keys.push(key);
// Add the key and value to the values dictionary with a point
// to the location in the ordered keys list
this._values[key] = { v: value, i: this._keys.length - 1 };
}
};
Map.prototype.clear = function() {
this._keys = [];
this._values = {};
};
Map.prototype.delete = function(key) {
var value = this._values[key];
if (value == null) return false;
// Delete entry
delete this._values[key];
// Remove the key from the ordered keys list
this._keys.splice(value.i, 1);
return true;
};
Map.prototype.entries = function() {
var self = this;
var index = 0;
return {
next: function() {
var key = self._keys[index++];
return {
value: key !== undefined ? [key, self._values[key].v] : undefined,
done: key !== undefined ? false : true
};
}
};
};
Map.prototype.forEach = function(callback, self) {
self = self || this;
for (var i = 0; i < this._keys.length; i++) {
var key = this._keys[i];
// Call the forEach callback
callback.call(self, this._values[key].v, key, self);
}
};
Map.prototype.get = function(key) {
return this._values[key] ? this._values[key].v : undefined;
};
Map.prototype.has = function(key) {
return this._values[key] != null;
};
Map.prototype.keys = function() {
var self = this;
var index = 0;
return {
next: function() {
var key = self._keys[index++];
return {
value: key !== undefined ? key : undefined,
done: key !== undefined ? false : true
};
}
};
};
Map.prototype.set = function(key, value) {
if (this._values[key]) {
this._values[key].v = value;
return this;
}
// Add the key to the list of keys in order
this._keys.push(key);
// Add the key and value to the values dictionary with a point
// to the location in the ordered keys list
this._values[key] = { v: value, i: this._keys.length - 1 };
return this;
};
Map.prototype.values = function() {
var self = this;
var index = 0;
return {
next: function() {
var key = self._keys[index++];
return {
value: key !== undefined ? self._values[key].v : undefined,
done: key !== undefined ? false : true
};
}
};
};
// Last ismaster
Object.defineProperty(Map.prototype, 'size', {
enumerable: true,
get: function() {
return this._keys.length;
}
});
module.exports = Map;
module.exports.Map = Map;
}
/**
* A class representation of the BSON MaxKey type.
*
* @class
* @return {MaxKey} A MaxKey instance
*/
function MaxKey() {
if (!(this instanceof MaxKey)) return new MaxKey();
this._bsontype = 'MaxKey';
}
module.exports = MaxKey;
module.exports.MaxKey = MaxKey;
/**
* A class representation of the BSON MinKey type.
*
* @class
* @return {MinKey} A MinKey instance
*/
function MinKey() {
if (!(this instanceof MinKey)) return new MinKey();
this._bsontype = 'MinKey';
}
module.exports = MinKey;
module.exports.MinKey = MinKey;
This diff is collapsed. Click to expand it.
'use strict';
var Long = require('../long').Long,
Double = require('../double').Double,
Timestamp = require('../timestamp').Timestamp,
ObjectID = require('../objectid').ObjectID,
Symbol = require('../symbol').Symbol,
BSONRegExp = require('../regexp').BSONRegExp,
Code = require('../code').Code,
Decimal128 = require('../decimal128'),
MinKey = require('../min_key').MinKey,
MaxKey = require('../max_key').MaxKey,
DBRef = require('../db_ref').DBRef,
Binary = require('../binary').Binary;
var normalizedFunctionString = require('./utils').normalizedFunctionString;
// To ensure that 0.4 of node works correctly
var isDate = function isDate(d) {
return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]';
};
var calculateObjectSize = function calculateObjectSize(
object,
serializeFunctions,
ignoreUndefined
) {
var totalLength = 4 + 1;
if (Array.isArray(object)) {
for (var i = 0; i < object.length; i++) {
totalLength += calculateElement(
i.toString(),
object[i],
serializeFunctions,
true,
ignoreUndefined
);
}
} else {
// If we have toBSON defined, override the current object
if (object.toBSON) {
object = object.toBSON();
}
// Calculate size
for (var key in object) {
totalLength += calculateElement(key, object[key], serializeFunctions, false, ignoreUndefined);
}
}
return totalLength;
};
/**
* @ignore
* @api private
*/
function calculateElement(name, value, serializeFunctions, isArray, ignoreUndefined) {
// If we have toBSON defined, override the current object
if (value && value.toBSON) {
value = value.toBSON();
}
switch (typeof value) {
case 'string':
return 1 + Buffer.byteLength(name, 'utf8') + 1 + 4 + Buffer.byteLength(value, 'utf8') + 1;
case 'number':
if (Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) {
if (value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) {
// 32 bit
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (4 + 1);
} else {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (8 + 1);
}
} else {
// 64 bit
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (8 + 1);
}
case 'undefined':
if (isArray || !ignoreUndefined)
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + 1;
return 0;
case 'boolean':
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (1 + 1);
case 'object':
if (
value == null ||
value instanceof MinKey ||
value instanceof MaxKey ||
value['_bsontype'] === 'MinKey' ||
value['_bsontype'] === 'MaxKey'
) {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + 1;
} else if (value instanceof ObjectID || value['_bsontype'] === 'ObjectID' || value['_bsontype'] === 'ObjectId') {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (12 + 1);
} else if (value instanceof Date || isDate(value)) {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (8 + 1);
} else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (1 + 4 + 1) + value.length
);
} else if (
value instanceof Long ||
value instanceof Double ||
value instanceof Timestamp ||
value['_bsontype'] === 'Long' ||
value['_bsontype'] === 'Double' ||
value['_bsontype'] === 'Timestamp'
) {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (8 + 1);
} else if (value instanceof Decimal128 || value['_bsontype'] === 'Decimal128') {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (16 + 1);
} else if (value instanceof Code || value['_bsontype'] === 'Code') {
// Calculate size depending on the availability of a scope
if (value.scope != null && Object.keys(value.scope).length > 0) {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
1 +
4 +
4 +
Buffer.byteLength(value.code.toString(), 'utf8') +
1 +
calculateObjectSize(value.scope, serializeFunctions, ignoreUndefined)
);
} else {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
1 +
4 +
Buffer.byteLength(value.code.toString(), 'utf8') +
1
);
}
} else if (value instanceof Binary || value['_bsontype'] === 'Binary') {
// Check what kind of subtype we have
if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY) {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
(value.position + 1 + 4 + 1 + 4)
);
} else {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (value.position + 1 + 4 + 1)
);
}
} else if (value instanceof Symbol || value['_bsontype'] === 'Symbol') {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
Buffer.byteLength(value.value, 'utf8') +
4 +
1 +
1
);
} else if (value instanceof DBRef || value['_bsontype'] === 'DBRef') {
// Set up correct object for serialization
var ordered_values = {
$ref: value.namespace,
$id: value.oid
};
// Add db reference if it exists
if (null != value.db) {
ordered_values['$db'] = value.db;
}
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
1 +
calculateObjectSize(ordered_values, serializeFunctions, ignoreUndefined)
);
} else if (
value instanceof RegExp ||
Object.prototype.toString.call(value) === '[object RegExp]'
) {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
1 +
Buffer.byteLength(value.source, 'utf8') +
1 +
(value.global ? 1 : 0) +
(value.ignoreCase ? 1 : 0) +
(value.multiline ? 1 : 0) +
1
);
} else if (value instanceof BSONRegExp || value['_bsontype'] === 'BSONRegExp') {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
1 +
Buffer.byteLength(value.pattern, 'utf8') +
1 +
Buffer.byteLength(value.options, 'utf8') +
1
);
} else {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
calculateObjectSize(value, serializeFunctions, ignoreUndefined) +
1
);
}
case 'function':
// WTF for 0.4.X where typeof /someregexp/ === 'function'
if (
value instanceof RegExp ||
Object.prototype.toString.call(value) === '[object RegExp]' ||
String.call(value) === '[object RegExp]'
) {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
1 +
Buffer.byteLength(value.source, 'utf8') +
1 +
(value.global ? 1 : 0) +
(value.ignoreCase ? 1 : 0) +
(value.multiline ? 1 : 0) +
1
);
} else {
if (serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
1 +
4 +
4 +
Buffer.byteLength(normalizedFunctionString(value), 'utf8') +
1 +
calculateObjectSize(value.scope, serializeFunctions, ignoreUndefined)
);
} else if (serializeFunctions) {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
1 +
4 +
Buffer.byteLength(normalizedFunctionString(value), 'utf8') +
1
);
}
}
}
return 0;
}
var BSON = {};
// BSON MAX VALUES
BSON.BSON_INT32_MAX = 0x7fffffff;
BSON.BSON_INT32_MIN = -0x80000000;
// JS MAX PRECISE VALUES
BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double.
BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double.
module.exports = calculateObjectSize;
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
'use strict';
/**
* Normalizes our expected stringified form of a function across versions of node
* @param {Function} fn The function to stringify
*/
function normalizedFunctionString(fn) {
return fn.toString().replace(/function *\(/, 'function (');
}
function newBuffer(item, encoding) {
return new Buffer(item, encoding);
}
function allocBuffer() {
return Buffer.alloc.apply(Buffer, arguments);
}
function toBuffer() {
return Buffer.from.apply(Buffer, arguments);
}
module.exports = {
normalizedFunctionString: normalizedFunctionString,
allocBuffer: typeof Buffer.alloc === 'function' ? allocBuffer : newBuffer,
toBuffer: typeof Buffer.from === 'function' ? toBuffer : newBuffer
};
/**
* A class representation of the BSON RegExp type.
*
* @class
* @return {BSONRegExp} A MinKey instance
*/
function BSONRegExp(pattern, options) {
if (!(this instanceof BSONRegExp)) return new BSONRegExp();
// Execute
this._bsontype = 'BSONRegExp';
this.pattern = pattern || '';
this.options = options || '';
// Validate options
for (var i = 0; i < this.options.length; i++) {
if (
!(
this.options[i] === 'i' ||
this.options[i] === 'm' ||
this.options[i] === 'x' ||
this.options[i] === 'l' ||
this.options[i] === 's' ||
this.options[i] === 'u'
)
) {
throw new Error('the regular expression options [' + this.options[i] + '] is not supported');
}
}
}
module.exports = BSONRegExp;
module.exports.BSONRegExp = BSONRegExp;
// Custom inspect property name / symbol.
var inspect = Buffer ? require('util').inspect.custom || 'inspect' : 'inspect';
/**
* A class representation of the BSON Symbol type.
*
* @class
* @deprecated
* @param {string} value the string representing the symbol.
* @return {Symbol}
*/
function Symbol(value) {
if (!(this instanceof Symbol)) return new Symbol(value);
this._bsontype = 'Symbol';
this.value = value;
}
/**
* Access the wrapped string value.
*
* @method
* @return {String} returns the wrapped string.
*/
Symbol.prototype.valueOf = function() {
return this.value;
};
/**
* @ignore
*/
Symbol.prototype.toString = function() {
return this.value;
};
/**
* @ignore
*/
Symbol.prototype[inspect] = function() {
return this.value;
};
/**
* @ignore
*/
Symbol.prototype.toJSON = function() {
return this.value;
};
module.exports = Symbol;
module.exports.Symbol = Symbol;
This diff is collapsed. Click to expand it.
{
"name": "bson",
"description": "A bson parser for node.js and the browser",
"keywords": [
"mongodb",
"bson",
"parser"
],
"files": [
"lib",
"index.js",
"browser_build",
"bower.json"
],
"version": "1.1.6",
"author": "Christian Amor Kvalheim <christkv@gmail.com>",
"contributors": [],
"repository": "mongodb/js-bson",
"bugs": {
"mail": "node-mongodb-native@googlegroups.com",
"url": "https://github.com/mongodb/js-bson/issues"
},
"devDependencies": {
"benchmark": "1.0.0",
"colors": "1.1.0",
"nodeunit": "0.9.0",
"babel-core": "^6.14.0",
"babel-loader": "^6.2.5",
"babel-polyfill": "^6.13.0",
"babel-preset-es2015": "^6.14.0",
"babel-preset-stage-0": "^6.5.0",
"babel-register": "^6.14.0",
"conventional-changelog-cli": "^1.3.5",
"standard-version": "^9.1.1",
"webpack": "^1.13.2",
"webpack-polyfills-plugin": "0.0.9"
},
"config": {
"native": false
},
"main": "./index",
"directories": {
"lib": "./lib/bson"
},
"engines": {
"node": ">=0.6.19"
},
"scripts": {
"test": "nodeunit ./test/node",
"build": "webpack --config ./webpack.dist.config.js",
"changelog": "conventional-changelog -p angular -i HISTORY.md -s",
"lint": "eslint lib test",
"format": "prettier --print-width 100 --tab-width 2 --single-quote --write 'test/**/*.js' 'lib/**/*.js'",
"release": "standard-version -i HISTORY.md"
},
"browser": "lib/bson/bson.js",
"license": "Apache-2.0"
}
Copyright Node.js contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
# core-util-is
The `util.is*` functions introduced in Node v0.12.
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(arg) {
if (Array.isArray) {
return Array.isArray(arg);
}
return objectToString(arg) === '[object Array]';
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return (objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
exports.isBuffer = require('buffer').Buffer.isBuffer;
function objectToString(o) {
return Object.prototype.toString.call(o);
}
{
"name": "core-util-is",
"version": "1.0.3",
"description": "The `util.is*` functions introduced in Node v0.12.",
"main": "lib/util.js",
"files": [
"lib"
],
"repository": {
"type": "git",
"url": "git://github.com/isaacs/core-util-is"
},
"keywords": [
"util",
"isBuffer",
"isArray",
"isNumber",
"isString",
"isRegExp",
"isThis",
"isThat",
"polyfill"
],
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"license": "MIT",
"bugs": {
"url": "https://github.com/isaacs/core-util-is/issues"
},
"scripts": {
"test": "tap test.js",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags"
},
"devDependencies": {
"tap": "^15.0.9"
}
}
## 1.5.1
- perf: minor performance tweak when growing queue size (#29)
## 1.5.0
- feat: adds capacity option for circular buffers (#27)
Copyright (c) 2018 Mike Diarmid (Salakar) <mike.diarmid@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this library except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
<p align="center">
<h1 align="center">Denque</h1>
</p>
<p align="center">
<a href="https://www.npmjs.com/package/denque"><img src="https://img.shields.io/npm/dm/denque.svg?style=flat-square" alt="NPM downloads"></a>
<a href="https://www.npmjs.com/package/denque"><img src="https://img.shields.io/npm/v/denque.svg?style=flat-square" alt="NPM version"></a>
<a href="https://github.com/invertase/denque/actions/workflows/testing.yam"><img src="https://github.com/invertase/denque/actions/workflows/testing.yaml/badge.svg" alt="Tests status"></a>
<a href="https://codecov.io/gh/invertase/denque"><img src="https://codecov.io/gh/invertase/denque/branch/master/graph/badge.svg?token=rn91iI4bSe" alt="Coverage"></a>
<a href="/LICENSE"><img src="https://img.shields.io/npm/l/denque.svg?style=flat-square" alt="License"></a>
<a href="https://twitter.com/invertaseio"><img src="https://img.shields.io/twitter/follow/invertaseio.svg?style=social&label=Follow" alt="Follow on Twitter"></a>
</p>
Denque is a well tested, extremely fast and lightweight [double-ended queue](http://en.wikipedia.org/wiki/Double-ended_queue)
implementation with zero dependencies and includes TypeScript types.
Double-ended queues can also be used as a:
- [Stack](http://en.wikipedia.org/wiki/Stack_\(abstract_data_type\))
- [Queue](http://en.wikipedia.org/wiki/Queue_\(data_structure\))
This implementation is currently the fastest available, even faster than `double-ended-queue`, see the [benchmarks](https://docs.page/invertase/denque/benchmarks).
Every queue operation is done at a constant `O(1)` - including random access from `.peekAt(index)`.
**Works on all node versions >= v0.10**
## Quick Start
Install the package:
```bash
npm install denque
```
Create and consume a queue:
```js
const Denque = require("denque");
const denque = new Denque([1,2,3,4]);
denque.shift(); // 1
denque.pop(); // 4
```
See the [API reference documentation](https://docs.page/invertase/denque/api) for more examples.
---
## Who's using it?
- [Kafka Node.js client](https://www.npmjs.com/package/kafka-node)
- [MariaDB Node.js client](https://www.npmjs.com/package/mariadb)
- [MongoDB Node.js client](https://www.npmjs.com/package/mongodb)
- [MySQL Node.js client](https://www.npmjs.com/package/mysql2)
- [Redis Node.js clients](https://www.npmjs.com/package/redis)
... and [many more](https://www.npmjs.com/browse/depended/denque).
---
## License
- See [LICENSE](/LICENSE)
---
<p align="center">
<a href="https://invertase.io/?utm_source=readme&utm_medium=footer&utm_campaign=docs.page">
<img width="75px" src="https://static.invertase.io/assets/invertase/invertase-rounded-avatar.png">
</a>
<p align="center">
Built and maintained by <a href="https://invertase.io/?utm_source=readme&utm_medium=footer&utm_campaign=denque">Invertase</a>.
</p>
</p>
declare class Denque<T = any> {
constructor();
constructor(array: T[]);
constructor(array: T[], options: IDenqueOptions);
push(item: T): number;
unshift(item: T): number;
pop(): T | undefined;
removeBack(): T | undefined;
shift(): T | undefined;
peekBack(): T | undefined;
peekFront(): T | undefined;
peekAt(index: number): T | undefined;
get(index: number): T | undefined;
remove(index: number, count: number): T[];
removeOne(index: number): T | undefined;
splice(index: number, count: number, ...item: T[]): T[] | undefined;
isEmpty(): boolean;
clear(): void;
toString(): string;
toArray(): T[];
length: number;
}
interface IDenqueOptions {
capacity?: number
}
export = Denque;
This diff is collapsed. Click to expand it.
{
"name": "denque",
"version": "1.5.1",
"description": "The fastest javascript implementation of a double-ended queue. Used by the official Redis, MongoDB, MariaDB & MySQL libraries for Node.js and many other libraries. Maintains compatability with deque.",
"main": "index.js",
"engines": {
"node": ">=0.10"
},
"keywords": [
"data-structure",
"data-structures",
"queue",
"double",
"end",
"ended",
"deque",
"denque",
"double-ended-queue"
],
"scripts": {
"test": "istanbul cover --report lcov _mocha && npm run typescript",
"coveralls": "cat ./coverage/lcov.info | coveralls",
"typescript": "tsc --project ./test/type/tsconfig.json",
"benchmark_thousand": "node benchmark/thousand",
"benchmark_2mil": "node benchmark/two_million",
"benchmark_splice": "node benchmark/splice",
"benchmark_remove": "node benchmark/remove",
"benchmark_removeOne": "node benchmark/removeOne"
},
"repository": {
"type": "git",
"url": "git+https://github.com/invertase/denque.git"
},
"license": "Apache-2.0",
"author": {
"name": "Invertase",
"email": "oss@invertase.io",
"url": "http://github.com/invertase/"
},
"contributors": [
"Mike Diarmid (Salakar) <mike@invertase.io>"
],
"bugs": {
"url": "https://github.com/invertase/denque/issues"
},
"homepage": "https://docs.page/invertase/denque",
"devDependencies": {
"benchmark": "^2.1.4",
"codecov": "^3.8.3",
"double-ended-queue": "^2.1.0-0",
"istanbul": "^0.4.5",
"mocha": "^3.5.3",
"typescript": "^3.4.1"
}
}
language: node_js
node_js:
- "0.8"
- "0.10"
test:
@node_modules/.bin/tape test.js
.PHONY: test
# isarray
`Array#isArray` for older browsers.
[![build status](https://secure.travis-ci.org/juliangruber/isarray.svg)](http://travis-ci.org/juliangruber/isarray)
[![downloads](https://img.shields.io/npm/dm/isarray.svg)](https://www.npmjs.org/package/isarray)
[![browser support](https://ci.testling.com/juliangruber/isarray.png)
](https://ci.testling.com/juliangruber/isarray)
## Usage
```js
var isArray = require('isarray');
console.log(isArray([])); // => true
console.log(isArray({})); // => false
```
## Installation
With [npm](http://npmjs.org) do
```bash
$ npm install isarray
```
Then bundle for the browser with
[browserify](https://github.com/substack/browserify).
With [component](http://component.io) do
```bash
$ component install juliangruber/isarray
```
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
"name" : "isarray",
"description" : "Array#isArray for older browsers",
"version" : "0.0.1",
"repository" : "juliangruber/isarray",
"homepage": "https://github.com/juliangruber/isarray",
"main" : "index.js",
"scripts" : [
"index.js"
],
"dependencies" : {},
"keywords": ["browser","isarray","array"],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT"
}
var toString = {}.toString;
module.exports = Array.isArray || function (arr) {
return toString.call(arr) == '[object Array]';
};
{
"name": "isarray",
"description": "Array#isArray for older browsers",
"version": "1.0.0",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/isarray.git"
},
"homepage": "https://github.com/juliangruber/isarray",
"main": "index.js",
"dependencies": {},
"devDependencies": {
"tape": "~2.13.4"
},
"keywords": [
"browser",
"isarray",
"array"
],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT",
"testling": {
"files": "test.js",
"browsers": [
"ie/8..latest",
"firefox/17..latest",
"firefox/nightly",
"chrome/22..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
},
"scripts": {
"test": "tape test.js"
}
}
var isArray = require('./');
var test = require('tape');
test('is array', function(t){
t.ok(isArray([]));
t.notOk(isArray({}));
t.notOk(isArray(null));
t.notOk(isArray(false));
var obj = {};
obj[0] = true;
t.notOk(isArray(obj));
var arr = [];
arr.foo = 'bar';
t.ok(isArray(arr));
t.end();
});
language: node_js
node_js:
- '4'
- '6'
The MIT License (MIT)
Copyright (c) 2017 Mathias Buus
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# memory-pager
Access memory using small fixed sized buffers instead of allocating a huge buffer.
Useful if you are implementing sparse data structures (such as large bitfield).
![travis](https://travis-ci.org/mafintosh/memory-pager.svg?branch=master)
```
npm install memory-pager
```
## Usage
``` js
var pager = require('paged-memory')
var pages = pager(1024) // use 1kb per page
var page = pages.get(10) // get page #10
console.log(page.offset) // 10240
console.log(page.buffer) // a blank 1kb buffer
```
## API
#### `var pages = pager(pageSize)`
Create a new pager. `pageSize` defaults to `1024`.
#### `var page = pages.get(pageNumber, [noAllocate])`
Get a page. The page will be allocated at first access.
Optionally you can set the `noAllocate` flag which will make the
method return undefined if no page has been allocated already
A page looks like this
``` js
{
offset: byteOffset,
buffer: bufferWithPageSize
}
```
#### `pages.set(pageNumber, buffer)`
Explicitly set the buffer for a page.
#### `pages.updated(page)`
Mark a page as updated.
#### `pages.lastUpdate()`
Get the last page that was updated.
#### `var buf = pages.toBuffer()`
Concat all pages allocated pages into a single buffer
## License
MIT
module.exports = Pager
function Pager (pageSize, opts) {
if (!(this instanceof Pager)) return new Pager(pageSize, opts)
this.length = 0
this.updates = []
this.path = new Uint16Array(4)
this.pages = new Array(32768)
this.maxPages = this.pages.length
this.level = 0
this.pageSize = pageSize || 1024
this.deduplicate = opts ? opts.deduplicate : null
this.zeros = this.deduplicate ? alloc(this.deduplicate.length) : null
}
Pager.prototype.updated = function (page) {
while (this.deduplicate && page.buffer[page.deduplicate] === this.deduplicate[page.deduplicate]) {
page.deduplicate++
if (page.deduplicate === this.deduplicate.length) {
page.deduplicate = 0
if (page.buffer.equals && page.buffer.equals(this.deduplicate)) page.buffer = this.deduplicate
break
}
}
if (page.updated || !this.updates) return
page.updated = true
this.updates.push(page)
}
Pager.prototype.lastUpdate = function () {
if (!this.updates || !this.updates.length) return null
var page = this.updates.pop()
page.updated = false
return page
}
Pager.prototype._array = function (i, noAllocate) {
if (i >= this.maxPages) {
if (noAllocate) return
grow(this, i)
}
factor(i, this.path)
var arr = this.pages
for (var j = this.level; j > 0; j--) {
var p = this.path[j]
var next = arr[p]
if (!next) {
if (noAllocate) return
next = arr[p] = new Array(32768)
}
arr = next
}
return arr
}
Pager.prototype.get = function (i, noAllocate) {
var arr = this._array(i, noAllocate)
var first = this.path[0]
var page = arr && arr[first]
if (!page && !noAllocate) {
page = arr[first] = new Page(i, alloc(this.pageSize))
if (i >= this.length) this.length = i + 1
}
if (page && page.buffer === this.deduplicate && this.deduplicate && !noAllocate) {
page.buffer = copy(page.buffer)
page.deduplicate = 0
}
return page
}
Pager.prototype.set = function (i, buf) {
var arr = this._array(i, false)
var first = this.path[0]
if (i >= this.length) this.length = i + 1
if (!buf || (this.zeros && buf.equals && buf.equals(this.zeros))) {
arr[first] = undefined
return
}
if (this.deduplicate && buf.equals && buf.equals(this.deduplicate)) {
buf = this.deduplicate
}
var page = arr[first]
var b = truncate(buf, this.pageSize)
if (page) page.buffer = b
else arr[first] = new Page(i, b)
}
Pager.prototype.toBuffer = function () {
var list = new Array(this.length)
var empty = alloc(this.pageSize)
var ptr = 0
while (ptr < list.length) {
var arr = this._array(ptr, true)
for (var i = 0; i < 32768 && ptr < list.length; i++) {
list[ptr++] = (arr && arr[i]) ? arr[i].buffer : empty
}
}
return Buffer.concat(list)
}
function grow (pager, index) {
while (pager.maxPages < index) {
var old = pager.pages
pager.pages = new Array(32768)
pager.pages[0] = old
pager.level++
pager.maxPages *= 32768
}
}
function truncate (buf, len) {
if (buf.length === len) return buf
if (buf.length > len) return buf.slice(0, len)
var cpy = alloc(len)
buf.copy(cpy)
return cpy
}
function alloc (size) {
if (Buffer.alloc) return Buffer.alloc(size)
var buf = new Buffer(size)
buf.fill(0)
return buf
}
function copy (buf) {
var cpy = Buffer.allocUnsafe ? Buffer.allocUnsafe(buf.length) : new Buffer(buf.length)
buf.copy(cpy)
return cpy
}
function Page (i, buf) {
this.offset = i * buf.length
this.buffer = buf
this.updated = false
this.deduplicate = 0
}
function factor (n, out) {
n = (n - (out[0] = (n & 32767))) / 32768
n = (n - (out[1] = (n & 32767))) / 32768
out[3] = ((n - (out[2] = (n & 32767))) / 32768) & 32767
}
{
"name": "memory-pager",
"version": "1.5.0",
"description": "Access memory using small fixed sized buffers",
"main": "index.js",
"dependencies": {},
"devDependencies": {
"standard": "^9.0.0",
"tape": "^4.6.3"
},
"scripts": {
"test": "standard && tape test.js"
},
"repository": {
"type": "git",
"url": "https://github.com/mafintosh/memory-pager.git"
},
"author": "Mathias Buus (@mafintosh)",
"license": "MIT",
"bugs": {
"url": "https://github.com/mafintosh/memory-pager/issues"
},
"homepage": "https://github.com/mafintosh/memory-pager"
}
var tape = require('tape')
var pager = require('./')
tape('get page', function (t) {
var pages = pager(1024)
var page = pages.get(0)
t.same(page.offset, 0)
t.same(page.buffer, Buffer.alloc(1024))
t.end()
})
tape('get page twice', function (t) {
var pages = pager(1024)
t.same(pages.length, 0)
var page = pages.get(0)
t.same(page.offset, 0)
t.same(page.buffer, Buffer.alloc(1024))
t.same(pages.length, 1)
var other = pages.get(0)
t.same(other, page)
t.end()
})
tape('get no mutable page', function (t) {
var pages = pager(1024)
t.ok(!pages.get(141, true))
t.ok(pages.get(141))
t.ok(pages.get(141, true))
t.end()
})
tape('get far out page', function (t) {
var pages = pager(1024)
var page = pages.get(1000000)
t.same(page.offset, 1000000 * 1024)
t.same(page.buffer, Buffer.alloc(1024))
t.same(pages.length, 1000000 + 1)
var other = pages.get(1)
t.same(other.offset, 1024)
t.same(other.buffer, Buffer.alloc(1024))
t.same(pages.length, 1000000 + 1)
t.ok(other !== page)
t.end()
})
tape('updates', function (t) {
var pages = pager(1024)
t.same(pages.lastUpdate(), null)
var page = pages.get(10)
page.buffer[42] = 1
pages.updated(page)
t.same(pages.lastUpdate(), page)
t.same(pages.lastUpdate(), null)
page.buffer[42] = 2
pages.updated(page)
pages.updated(page)
t.same(pages.lastUpdate(), page)
t.same(pages.lastUpdate(), null)
t.end()
})
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
'use strict';
// Core module
const core = require('./lib/core');
const Instrumentation = require('./lib/apm');
// Set up the connect function
const connect = require('./lib/mongo_client').connect;
// Expose error class
connect.MongoError = core.MongoError;
connect.MongoNetworkError = core.MongoNetworkError;
connect.MongoTimeoutError = core.MongoTimeoutError;
connect.MongoServerSelectionError = core.MongoServerSelectionError;
connect.MongoParseError = core.MongoParseError;
connect.MongoWriteConcernError = core.MongoWriteConcernError;
connect.MongoBulkWriteError = require('./lib/bulk/common').BulkWriteError;
connect.BulkWriteError = connect.MongoBulkWriteError;
// Actual driver classes exported
connect.Admin = require('./lib/admin');
connect.MongoClient = require('./lib/mongo_client');
connect.Db = require('./lib/db');
connect.Collection = require('./lib/collection');
connect.Server = require('./lib/topologies/server');
connect.ReplSet = require('./lib/topologies/replset');
connect.Mongos = require('./lib/topologies/mongos');
connect.ReadPreference = core.ReadPreference;
connect.GridStore = require('./lib/gridfs/grid_store');
connect.Chunk = require('./lib/gridfs/chunk');
connect.Logger = core.Logger;
connect.AggregationCursor = require('./lib/aggregation_cursor');
connect.CommandCursor = require('./lib/command_cursor');
connect.Cursor = require('./lib/cursor');
connect.GridFSBucket = require('./lib/gridfs-stream');
// Exported to be used in tests not to be used anywhere else
connect.CoreServer = core.Server;
connect.CoreConnection = core.Connection;
// BSON types exported
connect.Binary = core.BSON.Binary;
connect.Code = core.BSON.Code;
connect.Map = core.BSON.Map;
connect.DBRef = core.BSON.DBRef;
connect.Double = core.BSON.Double;
connect.Int32 = core.BSON.Int32;
connect.Long = core.BSON.Long;
connect.MinKey = core.BSON.MinKey;
connect.MaxKey = core.BSON.MaxKey;
connect.ObjectID = core.BSON.ObjectID;
connect.ObjectId = core.BSON.ObjectID;
connect.Symbol = core.BSON.Symbol;
connect.Timestamp = core.BSON.Timestamp;
connect.BSONRegExp = core.BSON.BSONRegExp;
connect.Decimal128 = core.BSON.Decimal128;
// Add connect method
connect.connect = connect;
// Set up the instrumentation method
connect.instrument = function(options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
const instrumentation = new Instrumentation();
instrumentation.instrument(connect.MongoClient, callback);
return instrumentation;
};
// Set our exports to be the connect function
module.exports = connect;
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
'use strict';
const EventEmitter = require('events').EventEmitter;
class Instrumentation extends EventEmitter {
constructor() {
super();
}
instrument(MongoClient, callback) {
// store a reference to the original functions
this.$MongoClient = MongoClient;
const $prototypeConnect = (this.$prototypeConnect = MongoClient.prototype.connect);
const instrumentation = this;
MongoClient.prototype.connect = function(callback) {
this.s.options.monitorCommands = true;
this.on('commandStarted', event => instrumentation.emit('started', event));
this.on('commandSucceeded', event => instrumentation.emit('succeeded', event));
this.on('commandFailed', event => instrumentation.emit('failed', event));
return $prototypeConnect.call(this, callback);
};
if (typeof callback === 'function') callback(null, this);
}
uninstrument() {
this.$MongoClient.prototype.connect = this.$prototypeConnect;
}
}
module.exports = Instrumentation;
{
"parserOptions": {
"ecmaVersion": 2018
}
}
'use strict';
// async function* asyncIterator() {
// while (true) {
// const value = await this.next();
// if (!value) {
// await this.close();
// return;
// }
// yield value;
// }
// }
// TODO: change this to the async generator function above
function asyncIterator() {
const cursor = this;
return {
next: function() {
return Promise.resolve()
.then(() => cursor.next())
.then(value => {
if (!value) {
return cursor.close().then(() => ({ value, done: true }));
}
return { value, done: false };
});
}
};
}
exports.asyncIterator = asyncIterator;
This diff is collapsed. Click to expand it.
'use strict';
const common = require('./common');
const BulkOperationBase = common.BulkOperationBase;
const Batch = common.Batch;
const bson = common.bson;
const utils = require('../utils');
const toError = utils.toError;
/**
* Add to internal list of Operations
*
* @ignore
* @param {OrderedBulkOperation} bulkOperation
* @param {number} docType number indicating the document type
* @param {object} document
* @return {OrderedBulkOperation}
*/
function addToOperationsList(bulkOperation, docType, document) {
// Get the bsonSize
const bsonSize = bson.calculateObjectSize(document, {
checkKeys: false,
// Since we don't know what the user selected for BSON options here,
// err on the safe side, and check the size with ignoreUndefined: false.
ignoreUndefined: false
});
// Throw error if the doc is bigger than the max BSON size
if (bsonSize >= bulkOperation.s.maxBsonObjectSize)
throw toError('document is larger than the maximum size ' + bulkOperation.s.maxBsonObjectSize);
// Create a new batch object if we don't have a current one
if (bulkOperation.s.currentBatch == null)
bulkOperation.s.currentBatch = new Batch(docType, bulkOperation.s.currentIndex);
const maxKeySize = bulkOperation.s.maxKeySize;
// Check if we need to create a new batch
if (
// New batch if we exceed the max batch op size
bulkOperation.s.currentBatchSize + 1 >= bulkOperation.s.maxWriteBatchSize ||
// New batch if we exceed the maxBatchSizeBytes. Only matters if batch already has a doc,
// since we can't sent an empty batch
(bulkOperation.s.currentBatchSize > 0 &&
bulkOperation.s.currentBatchSizeBytes + maxKeySize + bsonSize >=
bulkOperation.s.maxBatchSizeBytes) ||
// New batch if the new op does not have the same op type as the current batch
bulkOperation.s.currentBatch.batchType !== docType
) {
// Save the batch to the execution stack
bulkOperation.s.batches.push(bulkOperation.s.currentBatch);
// Create a new batch
bulkOperation.s.currentBatch = new Batch(docType, bulkOperation.s.currentIndex);
// Reset the current size trackers
bulkOperation.s.currentBatchSize = 0;
bulkOperation.s.currentBatchSizeBytes = 0;
}
if (docType === common.INSERT) {
bulkOperation.s.bulkResult.insertedIds.push({
index: bulkOperation.s.currentIndex,
_id: document._id
});
}
// We have an array of documents
if (Array.isArray(document)) {
throw toError('operation passed in cannot be an Array');
}
bulkOperation.s.currentBatch.originalIndexes.push(bulkOperation.s.currentIndex);
bulkOperation.s.currentBatch.operations.push(document);
bulkOperation.s.currentBatchSize += 1;
bulkOperation.s.currentBatchSizeBytes += maxKeySize + bsonSize;
bulkOperation.s.currentIndex += 1;
// Return bulkOperation
return bulkOperation;
}
/**
* Create a new OrderedBulkOperation instance (INTERNAL TYPE, do not instantiate directly)
* @class
* @extends BulkOperationBase
* @property {number} length Get the number of operations in the bulk.
* @return {OrderedBulkOperation} a OrderedBulkOperation instance.
*/
class OrderedBulkOperation extends BulkOperationBase {
constructor(topology, collection, options) {
options = options || {};
options = Object.assign(options, { addToOperationsList });
super(topology, collection, options, true);
}
}
/**
* Returns an unordered batch object
* @ignore
*/
function initializeOrderedBulkOp(topology, collection, options) {
return new OrderedBulkOperation(topology, collection, options);
}
initializeOrderedBulkOp.OrderedBulkOperation = OrderedBulkOperation;
module.exports = initializeOrderedBulkOp;
module.exports.Bulk = OrderedBulkOperation;
'use strict';
const common = require('./common');
const BulkOperationBase = common.BulkOperationBase;
const Batch = common.Batch;
const bson = common.bson;
const utils = require('../utils');
const toError = utils.toError;
/**
* Add to internal list of Operations
*
* @ignore
* @param {UnorderedBulkOperation} bulkOperation
* @param {number} docType number indicating the document type
* @param {object} document
* @return {UnorderedBulkOperation}
*/
function addToOperationsList(bulkOperation, docType, document) {
// Get the bsonSize
const bsonSize = bson.calculateObjectSize(document, {
checkKeys: false,
// Since we don't know what the user selected for BSON options here,
// err on the safe side, and check the size with ignoreUndefined: false.
ignoreUndefined: false
});
// Throw error if the doc is bigger than the max BSON size
if (bsonSize >= bulkOperation.s.maxBsonObjectSize)
throw toError('document is larger than the maximum size ' + bulkOperation.s.maxBsonObjectSize);
// Holds the current batch
bulkOperation.s.currentBatch = null;
// Get the right type of batch
if (docType === common.INSERT) {
bulkOperation.s.currentBatch = bulkOperation.s.currentInsertBatch;
} else if (docType === common.UPDATE) {
bulkOperation.s.currentBatch = bulkOperation.s.currentUpdateBatch;
} else if (docType === common.REMOVE) {
bulkOperation.s.currentBatch = bulkOperation.s.currentRemoveBatch;
}
const maxKeySize = bulkOperation.s.maxKeySize;
// Create a new batch object if we don't have a current one
if (bulkOperation.s.currentBatch == null)
bulkOperation.s.currentBatch = new Batch(docType, bulkOperation.s.currentIndex);
// Check if we need to create a new batch
if (
// New batch if we exceed the max batch op size
bulkOperation.s.currentBatch.size + 1 >= bulkOperation.s.maxWriteBatchSize ||
// New batch if we exceed the maxBatchSizeBytes. Only matters if batch already has a doc,
// since we can't sent an empty batch
(bulkOperation.s.currentBatch.size > 0 &&
bulkOperation.s.currentBatch.sizeBytes + maxKeySize + bsonSize >=
bulkOperation.s.maxBatchSizeBytes) ||
// New batch if the new op does not have the same op type as the current batch
bulkOperation.s.currentBatch.batchType !== docType
) {
// Save the batch to the execution stack
bulkOperation.s.batches.push(bulkOperation.s.currentBatch);
// Create a new batch
bulkOperation.s.currentBatch = new Batch(docType, bulkOperation.s.currentIndex);
}
// We have an array of documents
if (Array.isArray(document)) {
throw toError('operation passed in cannot be an Array');
}
bulkOperation.s.currentBatch.operations.push(document);
bulkOperation.s.currentBatch.originalIndexes.push(bulkOperation.s.currentIndex);
bulkOperation.s.currentIndex = bulkOperation.s.currentIndex + 1;
// Save back the current Batch to the right type
if (docType === common.INSERT) {
bulkOperation.s.currentInsertBatch = bulkOperation.s.currentBatch;
bulkOperation.s.bulkResult.insertedIds.push({
index: bulkOperation.s.bulkResult.insertedIds.length,
_id: document._id
});
} else if (docType === common.UPDATE) {
bulkOperation.s.currentUpdateBatch = bulkOperation.s.currentBatch;
} else if (docType === common.REMOVE) {
bulkOperation.s.currentRemoveBatch = bulkOperation.s.currentBatch;
}
// Update current batch size
bulkOperation.s.currentBatch.size += 1;
bulkOperation.s.currentBatch.sizeBytes += maxKeySize + bsonSize;
// Return bulkOperation
return bulkOperation;
}
/**
* Create a new UnorderedBulkOperation instance (INTERNAL TYPE, do not instantiate directly)
* @class
* @extends BulkOperationBase
* @property {number} length Get the number of operations in the bulk.
* @return {UnorderedBulkOperation} a UnorderedBulkOperation instance.
*/
class UnorderedBulkOperation extends BulkOperationBase {
constructor(topology, collection, options) {
options = options || {};
options = Object.assign(options, { addToOperationsList });
super(topology, collection, options, false);
}
handleWriteError(callback, writeResult) {
if (this.s.batches.length) {
return false;
}
return super.handleWriteError(callback, writeResult);
}
}
/**
* Returns an unordered batch object
* @ignore
*/
function initializeUnorderedBulkOp(topology, collection, options) {
return new UnorderedBulkOperation(topology, collection, options);
}
initializeUnorderedBulkOp.UnorderedBulkOperation = UnorderedBulkOperation;
module.exports = initializeUnorderedBulkOp;
module.exports.Bulk = UnorderedBulkOperation;
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
'use strict';
const MongoError = require('../core/error').MongoError;
/**
* An error indicating a connection pool is closed
*
* @property {string} address The address of the connection pool
* @extends MongoError
*/
class PoolClosedError extends MongoError {
constructor(pool) {
super('Attempted to check out a connection from closed connection pool');
this.name = 'MongoPoolClosedError';
this.address = pool.address;
}
}
/**
* An error thrown when a request to check out a connection times out
*
* @property {string} address The address of the connection pool
* @extends MongoError
*/
class WaitQueueTimeoutError extends MongoError {
constructor(pool) {
super('Timed out while checking out a connection from connection pool');
this.name = 'MongoWaitQueueTimeoutError';
this.address = pool.address;
}
}
module.exports = {
PoolClosedError,
WaitQueueTimeoutError
};
'use strict';
/**
* The base class for all monitoring events published from the connection pool
*
* @property {number} time A timestamp when the event was created
* @property {string} address The address (host/port pair) of the pool
*/
class ConnectionPoolMonitoringEvent {
constructor(pool) {
this.time = new Date();
this.address = pool.address;
}
}
/**
* An event published when a connection pool is created
*
* @property {Object} options The options used to create this connection pool
*/
class ConnectionPoolCreatedEvent extends ConnectionPoolMonitoringEvent {
constructor(pool) {
super(pool);
this.options = pool.options;
}
}
/**
* An event published when a connection pool is closed
*/
class ConnectionPoolClosedEvent extends ConnectionPoolMonitoringEvent {
constructor(pool) {
super(pool);
}
}
/**
* An event published when a connection pool creates a new connection
*
* @property {number} connectionId A monotonically increasing, per-pool id for the newly created connection
*/
class ConnectionCreatedEvent extends ConnectionPoolMonitoringEvent {
constructor(pool, connection) {
super(pool);
this.connectionId = connection.id;
}
}
/**
* An event published when a connection is ready for use
*
* @property {number} connectionId The id of the connection
*/
class ConnectionReadyEvent extends ConnectionPoolMonitoringEvent {
constructor(pool, connection) {
super(pool);
this.connectionId = connection.id;
}
}
/**
* An event published when a connection is closed
*
* @property {number} connectionId The id of the connection
* @property {string} reason The reason the connection was closed
*/
class ConnectionClosedEvent extends ConnectionPoolMonitoringEvent {
constructor(pool, connection, reason) {
super(pool);
this.connectionId = connection.id;
this.reason = reason || 'unknown';
}
}
/**
* An event published when a request to check a connection out begins
*/
class ConnectionCheckOutStartedEvent extends ConnectionPoolMonitoringEvent {
constructor(pool) {
super(pool);
}
}
/**
* An event published when a request to check a connection out fails
*
* @property {string} reason The reason the attempt to check out failed
*/
class ConnectionCheckOutFailedEvent extends ConnectionPoolMonitoringEvent {
constructor(pool, reason) {
super(pool);
this.reason = reason;
}
}
/**
* An event published when a connection is checked out of the connection pool
*
* @property {number} connectionId The id of the connection
*/
class ConnectionCheckedOutEvent extends ConnectionPoolMonitoringEvent {
constructor(pool, connection) {
super(pool);
this.connectionId = connection.id;
}
}
/**
* An event published when a connection is checked into the connection pool
*
* @property {number} connectionId The id of the connection
*/
class ConnectionCheckedInEvent extends ConnectionPoolMonitoringEvent {
constructor(pool, connection) {
super(pool);
this.connectionId = connection.id;
}
}
/**
* An event published when a connection pool is cleared
*/
class ConnectionPoolClearedEvent extends ConnectionPoolMonitoringEvent {
constructor(pool) {
super(pool);
}
}
const CMAP_EVENT_NAMES = [
'connectionPoolCreated',
'connectionPoolClosed',
'connectionCreated',
'connectionReady',
'connectionClosed',
'connectionCheckOutStarted',
'connectionCheckOutFailed',
'connectionCheckedOut',
'connectionCheckedIn',
'connectionPoolCleared'
];
module.exports = {
CMAP_EVENT_NAMES,
ConnectionPoolCreatedEvent,
ConnectionPoolClosedEvent,
ConnectionCreatedEvent,
ConnectionReadyEvent,
ConnectionClosedEvent,
ConnectionCheckOutStartedEvent,
ConnectionCheckOutFailedEvent,
ConnectionCheckedOutEvent,
ConnectionCheckedInEvent,
ConnectionPoolClearedEvent
};
'use strict';
const Duplex = require('stream').Duplex;
const BufferList = require('bl');
const MongoParseError = require('../core/error').MongoParseError;
const decompress = require('../core/wireprotocol/compression').decompress;
const Response = require('../core/connection/commands').Response;
const BinMsg = require('../core/connection/msg').BinMsg;
const MongoError = require('../core/error').MongoError;
const OP_COMPRESSED = require('../core/wireprotocol/shared').opcodes.OP_COMPRESSED;
const OP_MSG = require('../core/wireprotocol/shared').opcodes.OP_MSG;
const MESSAGE_HEADER_SIZE = require('../core/wireprotocol/shared').MESSAGE_HEADER_SIZE;
const COMPRESSION_DETAILS_SIZE = require('../core/wireprotocol/shared').COMPRESSION_DETAILS_SIZE;
const opcodes = require('../core/wireprotocol/shared').opcodes;
const compress = require('../core/wireprotocol/compression').compress;
const compressorIDs = require('../core/wireprotocol/compression').compressorIDs;
const uncompressibleCommands = require('../core/wireprotocol/compression').uncompressibleCommands;
const Msg = require('../core/connection/msg').Msg;
const kDefaultMaxBsonMessageSize = 1024 * 1024 * 16 * 4;
const kBuffer = Symbol('buffer');
/**
* A duplex stream that is capable of reading and writing raw wire protocol messages, with
* support for optional compression
*/
class MessageStream extends Duplex {
constructor(options) {
options = options || {};
super(options);
this.bson = options.bson;
this.maxBsonMessageSize = options.maxBsonMessageSize || kDefaultMaxBsonMessageSize;
this[kBuffer] = new BufferList();
}
_write(chunk, _, callback) {
const buffer = this[kBuffer];
buffer.append(chunk);
processIncomingData(this, callback);
}
_read(/* size */) {
// NOTE: This implementation is empty because we explicitly push data to be read
// when `writeMessage` is called.
return;
}
writeCommand(command, operationDescription) {
// TODO: agreed compressor should live in `StreamDescription`
const shouldCompress = operationDescription && !!operationDescription.agreedCompressor;
if (!shouldCompress || !canCompress(command)) {
const data = command.toBin();
this.push(Array.isArray(data) ? Buffer.concat(data) : data);
return;
}
// otherwise, compress the message
const concatenatedOriginalCommandBuffer = Buffer.concat(command.toBin());
const messageToBeCompressed = concatenatedOriginalCommandBuffer.slice(MESSAGE_HEADER_SIZE);
// Extract information needed for OP_COMPRESSED from the uncompressed message
const originalCommandOpCode = concatenatedOriginalCommandBuffer.readInt32LE(12);
// Compress the message body
compress({ options: operationDescription }, messageToBeCompressed, (err, compressedMessage) => {
if (err) {
operationDescription.cb(err, null);
return;
}
// Create the msgHeader of OP_COMPRESSED
const msgHeader = Buffer.alloc(MESSAGE_HEADER_SIZE);
msgHeader.writeInt32LE(
MESSAGE_HEADER_SIZE + COMPRESSION_DETAILS_SIZE + compressedMessage.length,
0
); // messageLength
msgHeader.writeInt32LE(command.requestId, 4); // requestID
msgHeader.writeInt32LE(0, 8); // responseTo (zero)
msgHeader.writeInt32LE(opcodes.OP_COMPRESSED, 12); // opCode
// Create the compression details of OP_COMPRESSED
const compressionDetails = Buffer.alloc(COMPRESSION_DETAILS_SIZE);
compressionDetails.writeInt32LE(originalCommandOpCode, 0); // originalOpcode
compressionDetails.writeInt32LE(messageToBeCompressed.length, 4); // Size of the uncompressed compressedMessage, excluding the MsgHeader
compressionDetails.writeUInt8(compressorIDs[operationDescription.agreedCompressor], 8); // compressorID
this.push(Buffer.concat([msgHeader, compressionDetails, compressedMessage]));
});
}
}
// Return whether a command contains an uncompressible command term
// Will return true if command contains no uncompressible command terms
function canCompress(command) {
const commandDoc = command instanceof Msg ? command.command : command.query;
const commandName = Object.keys(commandDoc)[0];
return !uncompressibleCommands.has(commandName);
}
function processIncomingData(stream, callback) {
const buffer = stream[kBuffer];
if (buffer.length < 4) {
callback();
return;
}
const sizeOfMessage = buffer.readInt32LE(0);
if (sizeOfMessage < 0) {
callback(new MongoParseError(`Invalid message size: ${sizeOfMessage}`));
return;
}
if (sizeOfMessage > stream.maxBsonMessageSize) {
callback(
new MongoParseError(
`Invalid message size: ${sizeOfMessage}, max allowed: ${stream.maxBsonMessageSize}`
)
);
return;
}
if (sizeOfMessage > buffer.length) {
callback();
return;
}
const message = buffer.slice(0, sizeOfMessage);
buffer.consume(sizeOfMessage);
const messageHeader = {
length: message.readInt32LE(0),
requestId: message.readInt32LE(4),
responseTo: message.readInt32LE(8),
opCode: message.readInt32LE(12)
};
let ResponseType = messageHeader.opCode === OP_MSG ? BinMsg : Response;
const responseOptions = stream.responseOptions;
if (messageHeader.opCode !== OP_COMPRESSED) {
const messageBody = message.slice(MESSAGE_HEADER_SIZE);
stream.emit(
'message',
new ResponseType(stream.bson, message, messageHeader, messageBody, responseOptions)
);
if (buffer.length >= 4) {
processIncomingData(stream, callback);
} else {
callback();
}
return;
}
messageHeader.fromCompressed = true;
messageHeader.opCode = message.readInt32LE(MESSAGE_HEADER_SIZE);
messageHeader.length = message.readInt32LE(MESSAGE_HEADER_SIZE + 4);
const compressorID = message[MESSAGE_HEADER_SIZE + 8];
const compressedBuffer = message.slice(MESSAGE_HEADER_SIZE + 9);
// recalculate based on wrapped opcode
ResponseType = messageHeader.opCode === OP_MSG ? BinMsg : Response;
decompress(compressorID, compressedBuffer, (err, messageBody) => {
if (err) {
callback(err);
return;
}
if (messageBody.length !== messageHeader.length) {
callback(
new MongoError(
'Decompressing a compressed message from the server failed. The message is corrupt.'
)
);
return;
}
stream.emit(
'message',
new ResponseType(stream.bson, message, messageHeader, messageBody, responseOptions)
);
if (buffer.length >= 4) {
processIncomingData(stream, callback);
} else {
callback();
}
});
}
module.exports = MessageStream;
'use strict';
const parseServerType = require('../core/sdam/server_description').parseServerType;
const RESPONSE_FIELDS = [
'minWireVersion',
'maxWireVersion',
'maxBsonObjectSize',
'maxMessageSizeBytes',
'maxWriteBatchSize',
'__nodejs_mock_server__'
];
class StreamDescription {
constructor(address, options) {
this.address = address;
this.type = parseServerType(null);
this.minWireVersion = undefined;
this.maxWireVersion = undefined;
this.maxBsonObjectSize = 16777216;
this.maxMessageSizeBytes = 48000000;
this.maxWriteBatchSize = 100000;
this.compressors =
options && options.compression && Array.isArray(options.compression.compressors)
? options.compression.compressors
: [];
}
receiveResponse(response) {
this.type = parseServerType(response);
RESPONSE_FIELDS.forEach(field => {
if (typeof response[field] !== 'undefined') {
this[field] = response[field];
}
});
if (response.compression) {
this.compressor = this.compressors.filter(c => response.compression.indexOf(c) !== -1)[0];
}
}
}
module.exports = {
StreamDescription
};
This diff could not be displayed because it is too large.
'use strict';
const ReadPreference = require('./core').ReadPreference;
const MongoError = require('./core').MongoError;
const Cursor = require('./cursor');
const CursorState = require('./core/cursor').CursorState;
/**
* @fileOverview The **CommandCursor** class is an internal class that embodies a
* generalized cursor based on a MongoDB command allowing for iteration over the
* results returned. It supports one by one document iteration, conversion to an
* array or can be iterated as a Node 0.10.X or higher stream
*
* **CommandCursor Cannot directly be instantiated**
* @example
* const MongoClient = require('mongodb').MongoClient;
* const test = require('assert');
* // Connection url
* const url = 'mongodb://localhost:27017';
* // Database Name
* const dbName = 'test';
* // Connect using MongoClient
* MongoClient.connect(url, function(err, client) {
* // Create a collection we want to drop later
* const col = client.db(dbName).collection('listCollectionsExample1');
* // Insert a bunch of documents
* col.insert([{a:1, b:1}
* , {a:2, b:2}, {a:3, b:3}
* , {a:4, b:4}], {w:1}, function(err, result) {
* test.equal(null, err);
* // List the database collections available
* db.listCollections().toArray(function(err, items) {
* test.equal(null, err);
* client.close();
* });
* });
* });
*/
/**
* Namespace provided by the browser.
* @external Readable
*/
/**
* Creates a new Command Cursor instance (INTERNAL TYPE, do not instantiate directly)
* @class CommandCursor
* @extends external:Readable
* @fires CommandCursor#data
* @fires CommandCursor#end
* @fires CommandCursor#close
* @fires CommandCursor#readable
* @return {CommandCursor} an CommandCursor instance.
*/
class CommandCursor extends Cursor {
constructor(topology, ns, cmd, options) {
super(topology, ns, cmd, options);
}
/**
* Set the ReadPreference for the cursor.
* @method
* @param {(string|ReadPreference)} readPreference The new read preference for the cursor.
* @throws {MongoError}
* @return {Cursor}
*/
setReadPreference(readPreference) {
if (this.s.state === CursorState.CLOSED || this.isDead()) {
throw MongoError.create({ message: 'Cursor is closed', driver: true });
}
if (this.s.state !== CursorState.INIT) {
throw MongoError.create({
message: 'cannot change cursor readPreference after cursor has been accessed',
driver: true
});
}
if (readPreference instanceof ReadPreference) {
this.options.readPreference = readPreference;
} else if (typeof readPreference === 'string') {
this.options.readPreference = new ReadPreference(readPreference);
} else {
throw new TypeError('Invalid read preference: ' + readPreference);
}
return this;
}
/**
* Set the batch size for the cursor.
* @method
* @param {number} value The number of documents to return per batch. See {@link https://docs.mongodb.com/manual/reference/command/find/|find command documentation}.
* @throws {MongoError}
* @return {CommandCursor}
*/
batchSize(value) {
if (this.s.state === CursorState.CLOSED || this.isDead()) {
throw MongoError.create({ message: 'Cursor is closed', driver: true });
}
if (typeof value !== 'number') {
throw MongoError.create({ message: 'batchSize requires an integer', driver: true });
}
if (this.cmd.cursor) {
this.cmd.cursor.batchSize = value;
}
this.setCursorBatchSize(value);
return this;
}
/**
* Add a maxTimeMS stage to the aggregation pipeline
* @method
* @param {number} value The state maxTimeMS value.
* @return {CommandCursor}
*/
maxTimeMS(value) {
if (this.topology.lastIsMaster().minWireVersion > 2) {
this.cmd.maxTimeMS = value;
}
return this;
}
/**
* Return the cursor logger
* @method
* @return {Logger} return the cursor logger
* @ignore
*/
getLogger() {
return this.logger;
}
}
// aliases
CommandCursor.prototype.get = CommandCursor.prototype.toArray;
/**
* CommandCursor stream data event, fired for each document in the cursor.
*
* @event CommandCursor#data
* @type {object}
*/
/**
* CommandCursor stream end event
*
* @event CommandCursor#end
* @type {null}
*/
/**
* CommandCursor stream close event
*
* @event CommandCursor#close
* @type {null}
*/
/**
* CommandCursor stream readable event
*
* @event CommandCursor#readable
* @type {null}
*/
/**
* Get the next available document from the cursor, returns null if no more documents are available.
* @function CommandCursor.prototype.next
* @param {CommandCursor~resultCallback} [callback] The result callback.
* @throws {MongoError}
* @return {Promise} returns Promise if no callback passed
*/
/**
* Check if there is any document still available in the cursor
* @function CommandCursor.prototype.hasNext
* @param {CommandCursor~resultCallback} [callback] The result callback.
* @throws {MongoError}
* @return {Promise} returns Promise if no callback passed
*/
/**
* The callback format for results
* @callback CommandCursor~toArrayResultCallback
* @param {MongoError} error An error instance representing the error during the execution.
* @param {object[]} documents All the documents the satisfy the cursor.
*/
/**
* Returns an array of documents. The caller is responsible for making sure that there
* is enough memory to store the results. Note that the array only contain partial
* results when this cursor had been previously accessed.
* @method CommandCursor.prototype.toArray
* @param {CommandCursor~toArrayResultCallback} [callback] The result callback.
* @throws {MongoError}
* @return {Promise} returns Promise if no callback passed
*/
/**
* The callback format for results
* @callback CommandCursor~resultCallback
* @param {MongoError} error An error instance representing the error during the execution.
* @param {(object|null)} result The result object if the command was executed successfully.
*/
/**
* Iterates over all the documents for this cursor. As with **{cursor.toArray}**,
* not all of the elements will be iterated if this cursor had been previously accessed.
* In that case, **{cursor.rewind}** can be used to reset the cursor. However, unlike
* **{cursor.toArray}**, the cursor will only hold a maximum of batch size elements
* at any given time if batch size is specified. Otherwise, the caller is responsible
* for making sure that the entire result can fit the memory.
* @method CommandCursor.prototype.each
* @param {CommandCursor~resultCallback} callback The result callback.
* @throws {MongoError}
* @return {null}
*/
/**
* Close the cursor, sending a KillCursor command and emitting close.
* @method CommandCursor.prototype.close
* @param {CommandCursor~resultCallback} [callback] The result callback.
* @return {Promise} returns Promise if no callback passed
*/
/**
* Is the cursor closed
* @method CommandCursor.prototype.isClosed
* @return {boolean}
*/
/**
* Clone the cursor
* @function CommandCursor.prototype.clone
* @return {CommandCursor}
*/
/**
* Resets the cursor
* @function CommandCursor.prototype.rewind
* @return {CommandCursor}
*/
/**
* The callback format for the forEach iterator method
* @callback CommandCursor~iteratorCallback
* @param {Object} doc An emitted document for the iterator
*/
/**
* The callback error format for the forEach iterator method
* @callback CommandCursor~endCallback
* @param {MongoError} error An error instance representing the error during the execution.
*/
/*
* Iterates over all the documents for this cursor using the iterator, callback pattern.
* @method CommandCursor.prototype.forEach
* @param {CommandCursor~iteratorCallback} iterator The iteration callback.
* @param {CommandCursor~endCallback} callback The end callback.
* @throws {MongoError}
* @return {null}
*/
module.exports = CommandCursor;
'use strict';
module.exports = {
SYSTEM_NAMESPACE_COLLECTION: 'system.namespaces',
SYSTEM_INDEX_COLLECTION: 'system.indexes',
SYSTEM_PROFILE_COLLECTION: 'system.profile',
SYSTEM_USER_COLLECTION: 'system.users',
SYSTEM_COMMAND_COLLECTION: '$cmd',
SYSTEM_JS_COLLECTION: 'system.js'
};
'use strict';
/**
* Context used during authentication
*
* @property {Connection} connection The connection to authenticate
* @property {MongoCredentials} credentials The credentials to use for authentication
* @property {object} options The options passed to the `connect` method
* @property {object?} response The response of the initial handshake
* @property {Buffer?} nonce A random nonce generated for use in an authentication conversation
*/
class AuthContext {
constructor(connection, credentials, options) {
this.connection = connection;
this.credentials = credentials;
this.options = options;
}
}
class AuthProvider {
constructor(bson) {
this.bson = bson;
}
/**
* Prepare the handshake document before the initial handshake.
*
* @param {object} handshakeDoc The document used for the initial handshake on a connection
* @param {AuthContext} authContext Context for authentication flow
* @param {function} callback
*/
prepare(handshakeDoc, context, callback) {
callback(undefined, handshakeDoc);
}
/**
* Authenticate
*
* @param {AuthContext} context A shared context for authentication flow
* @param {authResultCallback} callback The callback to return the result from the authentication
*/
auth(context, callback) {
callback(new TypeError('`auth` method must be overridden by subclass'));
}
}
/**
* This is a result from an authentication provider
*
* @callback authResultCallback
* @param {error} error An error object. Set to null if no error present
* @param {boolean} result The result of the authentication process
*/
module.exports = { AuthContext, AuthProvider };
'use strict';
const MongoCR = require('./mongocr');
const X509 = require('./x509');
const Plain = require('./plain');
const GSSAPI = require('./gssapi');
const ScramSHA1 = require('./scram').ScramSHA1;
const ScramSHA256 = require('./scram').ScramSHA256;
const MongoDBAWS = require('./mongodb_aws');
/**
* Returns the default authentication providers.
*
* @param {BSON} bson Bson definition
* @returns {Object} a mapping of auth names to auth types
*/
function defaultAuthProviders(bson) {
return {
'mongodb-aws': new MongoDBAWS(bson),
mongocr: new MongoCR(bson),
x509: new X509(bson),
plain: new Plain(bson),
gssapi: new GSSAPI(bson),
'scram-sha-1': new ScramSHA1(bson),
'scram-sha-256': new ScramSHA256(bson)
};
}
module.exports = { defaultAuthProviders };
'use strict';
const dns = require('dns');
const AuthProvider = require('./auth_provider').AuthProvider;
const retrieveKerberos = require('../utils').retrieveKerberos;
const MongoError = require('../error').MongoError;
let kerberos;
class GSSAPI extends AuthProvider {
auth(authContext, callback) {
const connection = authContext.connection;
const credentials = authContext.credentials;
if (credentials == null) return callback(new MongoError('credentials required'));
const username = credentials.username;
function externalCommand(command, cb) {
return connection.command('$external.$cmd', command, cb);
}
makeKerberosClient(authContext, (err, client) => {
if (err) return callback(err);
if (client == null) return callback(new MongoError('gssapi client missing'));
client.step('', (err, payload) => {
if (err) return callback(err);
externalCommand(saslStart(payload), (err, response) => {
if (err) return callback(err);
const result = response.result;
negotiate(client, 10, result.payload, (err, payload) => {
if (err) return callback(err);
externalCommand(saslContinue(payload, result.conversationId), (err, response) => {
if (err) return callback(err);
const result = response.result;
finalize(client, username, result.payload, (err, payload) => {
if (err) return callback(err);
externalCommand(
{
saslContinue: 1,
conversationId: result.conversationId,
payload
},
(err, result) => {
if (err) return callback(err);
callback(undefined, result);
}
);
});
});
});
});
});
});
}
}
module.exports = GSSAPI;
function makeKerberosClient(authContext, callback) {
const host = authContext.options.host;
const port = authContext.options.port;
const credentials = authContext.credentials;
if (!host || !port || !credentials) {
return callback(
new MongoError(
`Connection must specify: ${host ? 'host' : ''}, ${port ? 'port' : ''}, ${
credentials ? 'host' : 'credentials'
}.`
)
);
}
if (kerberos == null) {
try {
kerberos = retrieveKerberos();
} catch (e) {
return callback(e);
}
}
const username = credentials.username;
const password = credentials.password;
const mechanismProperties = credentials.mechanismProperties;
const serviceName =
mechanismProperties['gssapiservicename'] ||
mechanismProperties['gssapiServiceName'] ||
'mongodb';
performGssapiCanonicalizeHostName(host, mechanismProperties, (err, host) => {
if (err) return callback(err);
const initOptions = {};
if (password != null) {
Object.assign(initOptions, { user: username, password: password });
}
kerberos.initializeClient(
`${serviceName}${process.platform === 'win32' ? '/' : '@'}${host}`,
initOptions,
(err, client) => {
if (err) return callback(new MongoError(err));
callback(null, client);
}
);
});
}
function saslStart(payload) {
return {
saslStart: 1,
mechanism: 'GSSAPI',
payload,
autoAuthorize: 1
};
}
function saslContinue(payload, conversationId) {
return {
saslContinue: 1,
conversationId,
payload
};
}
function negotiate(client, retries, payload, callback) {
client.step(payload, (err, response) => {
// Retries exhausted, raise error
if (err && retries === 0) return callback(err);
// Adjust number of retries and call step again
if (err) return negotiate(client, retries - 1, payload, callback);
// Return the payload
callback(undefined, response || '');
});
}
function finalize(client, user, payload, callback) {
// GSS Client Unwrap
client.unwrap(payload, (err, response) => {
if (err) return callback(err);
// Wrap the response
client.wrap(response || '', { user }, (err, wrapped) => {
if (err) return callback(err);
// Return the payload
callback(undefined, wrapped);
});
});
}
function performGssapiCanonicalizeHostName(host, mechanismProperties, callback) {
const canonicalizeHostName =
typeof mechanismProperties.gssapiCanonicalizeHostName === 'boolean'
? mechanismProperties.gssapiCanonicalizeHostName
: false;
if (!canonicalizeHostName) return callback(undefined, host);
// Attempt to resolve the host name
dns.resolveCname(host, (err, r) => {
if (err) return callback(err);
// Get the first resolve host id
if (Array.isArray(r) && r.length > 0) {
return callback(undefined, r[0]);
}
callback(undefined, host);
});
}
'use strict';
// Resolves the default auth mechanism according to
// https://github.com/mongodb/specifications/blob/master/source/auth/auth.rst
function getDefaultAuthMechanism(ismaster) {
if (ismaster) {
// If ismaster contains saslSupportedMechs, use scram-sha-256
// if it is available, else scram-sha-1
if (Array.isArray(ismaster.saslSupportedMechs)) {
return ismaster.saslSupportedMechs.indexOf('SCRAM-SHA-256') >= 0
? 'scram-sha-256'
: 'scram-sha-1';
}
// Fallback to legacy selection method. If wire version >= 3, use scram-sha-1
if (ismaster.maxWireVersion >= 3) {
return 'scram-sha-1';
}
}
// Default for wireprotocol < 3
return 'mongocr';
}
/**
* A representation of the credentials used by MongoDB
* @class
* @property {string} mechanism The method used to authenticate
* @property {string} [username] The username used for authentication
* @property {string} [password] The password used for authentication
* @property {string} [source] The database that the user should authenticate against
* @property {object} [mechanismProperties] Special properties used by some types of auth mechanisms
*/
class MongoCredentials {
/**
* Creates a new MongoCredentials object
* @param {object} [options]
* @param {string} [options.username] The username used for authentication
* @param {string} [options.password] The password used for authentication
* @param {string} [options.source] The database that the user should authenticate against
* @param {string} [options.mechanism] The method used to authenticate
* @param {object} [options.mechanismProperties] Special properties used by some types of auth mechanisms
*/
constructor(options) {
options = options || {};
this.username = options.username;
this.password = options.password;
this.source = options.source || options.db;
this.mechanism = options.mechanism || 'default';
this.mechanismProperties = options.mechanismProperties || {};
if (this.mechanism.match(/MONGODB-AWS/i)) {
if (this.username == null && process.env.AWS_ACCESS_KEY_ID) {
this.username = process.env.AWS_ACCESS_KEY_ID;
}
if (this.password == null && process.env.AWS_SECRET_ACCESS_KEY) {
this.password = process.env.AWS_SECRET_ACCESS_KEY;
}
if (this.mechanismProperties.AWS_SESSION_TOKEN == null && process.env.AWS_SESSION_TOKEN) {
this.mechanismProperties.AWS_SESSION_TOKEN = process.env.AWS_SESSION_TOKEN;
}
}
Object.freeze(this.mechanismProperties);
Object.freeze(this);
}
/**
* Determines if two MongoCredentials objects are equivalent
* @param {MongoCredentials} other another MongoCredentials object
* @returns {boolean} true if the two objects are equal.
*/
equals(other) {
return (
this.mechanism === other.mechanism &&
this.username === other.username &&
this.password === other.password &&
this.source === other.source
);
}
/**
* If the authentication mechanism is set to "default", resolves the authMechanism
* based on the server version and server supported sasl mechanisms.
*
* @param {Object} [ismaster] An ismaster response from the server
* @returns {MongoCredentials}
*/
resolveAuthMechanism(ismaster) {
// If the mechanism is not "default", then it does not need to be resolved
if (this.mechanism.match(/DEFAULT/i)) {
return new MongoCredentials({
username: this.username,
password: this.password,
source: this.source,
mechanism: getDefaultAuthMechanism(ismaster),
mechanismProperties: this.mechanismProperties
});
}
return this;
}
}
module.exports = { MongoCredentials };
'use strict';
const crypto = require('crypto');
const AuthProvider = require('./auth_provider').AuthProvider;
class MongoCR extends AuthProvider {
auth(authContext, callback) {
const connection = authContext.connection;
const credentials = authContext.credentials;
const username = credentials.username;
const password = credentials.password;
const source = credentials.source;
connection.command(`${source}.$cmd`, { getnonce: 1 }, (err, result) => {
let nonce = null;
let key = null;
// Get nonce
if (err == null) {
const r = result.result;
nonce = r.nonce;
// Use node md5 generator
let md5 = crypto.createHash('md5');
// Generate keys used for authentication
md5.update(username + ':mongo:' + password, 'utf8');
const hash_password = md5.digest('hex');
// Final key
md5 = crypto.createHash('md5');
md5.update(nonce + username + hash_password, 'utf8');
key = md5.digest('hex');
}
const authenticateCommand = {
authenticate: 1,
user: username,
nonce,
key
};
connection.command(`${source}.$cmd`, authenticateCommand, callback);
});
}
}
module.exports = MongoCR;
'use strict';
const AuthProvider = require('./auth_provider').AuthProvider;
const MongoCredentials = require('./mongo_credentials').MongoCredentials;
const MongoError = require('../error').MongoError;
const crypto = require('crypto');
const http = require('http');
const maxWireVersion = require('../utils').maxWireVersion;
const url = require('url');
let aws4;
try {
aws4 = require('aws4');
} catch (e) {
// don't do anything;
}
const ASCII_N = 110;
const AWS_RELATIVE_URI = 'http://169.254.170.2';
const AWS_EC2_URI = 'http://169.254.169.254';
const AWS_EC2_PATH = '/latest/meta-data/iam/security-credentials';
class MongoDBAWS extends AuthProvider {
auth(authContext, callback) {
const connection = authContext.connection;
const credentials = authContext.credentials;
if (maxWireVersion(connection) < 9) {
callback(new MongoError('MONGODB-AWS authentication requires MongoDB version 4.4 or later'));
return;
}
if (aws4 == null) {
callback(
new MongoError(
'MONGODB-AWS authentication requires the `aws4` module, please install it as a dependency of your project'
)
);
return;
}
if (credentials.username == null) {
makeTempCredentials(credentials, (err, tempCredentials) => {
if (err) return callback(err);
authContext.credentials = tempCredentials;
this.auth(authContext, callback);
});
return;
}
const username = credentials.username;
const password = credentials.password;
const db = credentials.source;
const token = credentials.mechanismProperties.AWS_SESSION_TOKEN;
const bson = this.bson;
crypto.randomBytes(32, (err, nonce) => {
if (err) {
callback(err);
return;
}
const saslStart = {
saslStart: 1,
mechanism: 'MONGODB-AWS',
payload: bson.serialize({ r: nonce, p: ASCII_N })
};
connection.command(`${db}.$cmd`, saslStart, (err, result) => {
if (err) return callback(err);
const res = result.result;
const serverResponse = bson.deserialize(res.payload.buffer);
const host = serverResponse.h;
const serverNonce = serverResponse.s.buffer;
if (serverNonce.length !== 64) {
callback(
new MongoError(`Invalid server nonce length ${serverNonce.length}, expected 64`)
);
return;
}
if (serverNonce.compare(nonce, 0, nonce.length, 0, nonce.length) !== 0) {
callback(new MongoError('Server nonce does not begin with client nonce'));
return;
}
if (host.length < 1 || host.length > 255 || host.indexOf('..') !== -1) {
callback(new MongoError(`Server returned an invalid host: "${host}"`));
return;
}
const body = 'Action=GetCallerIdentity&Version=2011-06-15';
const options = aws4.sign(
{
method: 'POST',
host,
region: deriveRegion(serverResponse.h),
service: 'sts',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': body.length,
'X-MongoDB-Server-Nonce': serverNonce.toString('base64'),
'X-MongoDB-GS2-CB-Flag': 'n'
},
path: '/',
body
},
{
accessKeyId: username,
secretAccessKey: password,
token
}
);
const authorization = options.headers.Authorization;
const date = options.headers['X-Amz-Date'];
const payload = { a: authorization, d: date };
if (token) {
payload.t = token;
}
const saslContinue = {
saslContinue: 1,
conversationId: 1,
payload: bson.serialize(payload)
};
connection.command(`${db}.$cmd`, saslContinue, err => {
if (err) return callback(err);
callback();
});
});
});
}
}
function makeTempCredentials(credentials, callback) {
function done(creds) {
if (creds.AccessKeyId == null || creds.SecretAccessKey == null || creds.Token == null) {
callback(new MongoError('Could not obtain temporary MONGODB-AWS credentials'));
return;
}
callback(
undefined,
new MongoCredentials({
username: creds.AccessKeyId,
password: creds.SecretAccessKey,
source: credentials.source,
mechanism: 'MONGODB-AWS',
mechanismProperties: {
AWS_SESSION_TOKEN: creds.Token
}
})
);
}
// If the environment variable AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
// is set then drivers MUST assume that it was set by an AWS ECS agent
if (process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) {
request(
`${AWS_RELATIVE_URI}${process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI}`,
(err, res) => {
if (err) return callback(err);
done(res);
}
);
return;
}
// Otherwise assume we are on an EC2 instance
// get a token
request(
`${AWS_EC2_URI}/latest/api/token`,
{ method: 'PUT', json: false, headers: { 'X-aws-ec2-metadata-token-ttl-seconds': 30 } },
(err, token) => {
if (err) return callback(err);
// get role name
request(
`${AWS_EC2_URI}/${AWS_EC2_PATH}`,
{ json: false, headers: { 'X-aws-ec2-metadata-token': token } },
(err, roleName) => {
if (err) return callback(err);
// get temp credentials
request(
`${AWS_EC2_URI}/${AWS_EC2_PATH}/${roleName}`,
{ headers: { 'X-aws-ec2-metadata-token': token } },
(err, creds) => {
if (err) return callback(err);
done(creds);
}
);
}
);
}
);
}
function deriveRegion(host) {
const parts = host.split('.');
if (parts.length === 1 || parts[1] === 'amazonaws') {
return 'us-east-1';
}
return parts[1];
}
function request(uri, options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
options = Object.assign(
{
method: 'GET',
timeout: 10000,
json: true
},
url.parse(uri),
options
);
const req = http.request(options, res => {
res.setEncoding('utf8');
let data = '';
res.on('data', d => (data += d));
res.on('end', () => {
if (options.json === false) {
callback(undefined, data);
return;
}
try {
const parsed = JSON.parse(data);
callback(undefined, parsed);
} catch (err) {
callback(new MongoError(`Invalid JSON response: "${data}"`));
}
});
});
req.on('error', err => callback(err));
req.end();
}
module.exports = MongoDBAWS;
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
No preview for this file type
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.