신동해

Add MongoDB lib, Update server.js

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