bson 4.1.0 → 4.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/HISTORY.md +48 -1
  2. package/README.md +7 -9
  3. package/bower.json +1 -1
  4. package/bson.d.ts +986 -0
  5. package/dist/bson.browser.esm.js +7811 -5011
  6. package/dist/bson.browser.esm.js.map +1 -0
  7. package/dist/bson.browser.umd.js +7862 -5099
  8. package/dist/bson.browser.umd.js.map +1 -0
  9. package/dist/bson.bundle.js +8723 -9228
  10. package/dist/bson.bundle.js.map +1 -0
  11. package/dist/bson.esm.js +5728 -4951
  12. package/dist/bson.esm.js.map +1 -0
  13. package/etc/prepare.js +19 -0
  14. package/lib/binary.js +218 -398
  15. package/lib/binary.js.map +1 -0
  16. package/lib/bson.js +201 -240
  17. package/lib/bson.js.map +1 -0
  18. package/lib/code.js +41 -41
  19. package/lib/code.js.map +1 -0
  20. package/lib/constants.js +78 -203
  21. package/lib/constants.js.map +1 -0
  22. package/lib/db_ref.js +88 -81
  23. package/lib/db_ref.js.map +1 -0
  24. package/lib/decimal128.js +667 -777
  25. package/lib/decimal128.js.map +1 -0
  26. package/lib/double.js +68 -70
  27. package/lib/double.js.map +1 -0
  28. package/lib/ensure_buffer.js +22 -18
  29. package/lib/ensure_buffer.js.map +1 -0
  30. package/lib/extended_json.js +310 -321
  31. package/lib/extended_json.js.map +1 -0
  32. package/lib/float_parser.js +98 -104
  33. package/lib/float_parser.js.map +1 -0
  34. package/lib/int_32.js +50 -49
  35. package/lib/int_32.js.map +1 -0
  36. package/lib/long.js +881 -16
  37. package/lib/long.js.map +1 -0
  38. package/lib/map.js +130 -122
  39. package/lib/map.js.map +1 -0
  40. package/lib/max_key.js +28 -25
  41. package/lib/max_key.js.map +1 -0
  42. package/lib/min_key.js +28 -25
  43. package/lib/min_key.js.map +1 -0
  44. package/lib/objectid.js +300 -410
  45. package/lib/objectid.js.map +1 -0
  46. package/lib/parser/calculate_size.js +188 -224
  47. package/lib/parser/calculate_size.js.map +1 -0
  48. package/lib/parser/deserializer.js +545 -621
  49. package/lib/parser/deserializer.js.map +1 -0
  50. package/lib/parser/serializer.js +798 -923
  51. package/lib/parser/serializer.js.map +1 -0
  52. package/lib/parser/utils.js +92 -30
  53. package/lib/parser/utils.js.map +1 -0
  54. package/lib/regexp.js +61 -74
  55. package/lib/regexp.js.map +1 -0
  56. package/lib/symbol.js +45 -58
  57. package/lib/symbol.js.map +1 -0
  58. package/lib/timestamp.js +91 -95
  59. package/lib/timestamp.js.map +1 -0
  60. package/lib/uuid.js +48 -0
  61. package/lib/uuid.js.map +1 -0
  62. package/lib/validate_utf8.js +41 -42
  63. package/lib/validate_utf8.js.map +1 -0
  64. package/package.json +53 -31
  65. package/src/binary.ts +272 -0
  66. package/src/bson.ts +326 -0
  67. package/src/code.ts +61 -0
  68. package/src/constants.ts +104 -0
  69. package/src/db_ref.ts +119 -0
  70. package/src/decimal128.ts +803 -0
  71. package/src/double.ts +87 -0
  72. package/src/ensure_buffer.ts +26 -0
  73. package/src/extended_json.ts +395 -0
  74. package/src/float_parser.ts +152 -0
  75. package/src/int_32.ts +66 -0
  76. package/src/long.ts +1002 -0
  77. package/src/map.ts +139 -0
  78. package/src/max_key.ts +37 -0
  79. package/src/min_key.ts +37 -0
  80. package/src/objectid.ts +379 -0
  81. package/src/parser/calculate_size.ts +230 -0
  82. package/src/parser/deserializer.ts +655 -0
  83. package/src/parser/serializer.ts +1069 -0
  84. package/src/parser/utils.ts +93 -0
  85. package/src/regexp.ts +94 -0
  86. package/src/symbol.ts +59 -0
  87. package/src/timestamp.ts +108 -0
  88. package/src/uuid.ts +57 -0
  89. package/src/validate_utf8.ts +47 -0
  90. package/lib/fnv1a.js +0 -48
@@ -0,0 +1,93 @@
1
+ import { Buffer } from 'buffer';
2
+
3
+ /**
4
+ * Normalizes our expected stringified form of a function across versions of node
5
+ * @param fn - The function to stringify
6
+ */
7
+ export function normalizedFunctionString(fn: Function): string {
8
+ return fn.toString().replace('function(', 'function (');
9
+ }
10
+
11
+ function insecureRandomBytes(size: number): Uint8Array {
12
+ const result = Buffer.alloc(size);
13
+ for (let i = 0; i < size; ++i) result[i] = Math.floor(Math.random() * 256);
14
+ return result;
15
+ }
16
+
17
+ /* We do not want to have to include DOM types just for this check */
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ declare let window: any;
20
+ declare let require: Function;
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ declare let global: any;
23
+ declare const self: unknown;
24
+
25
+ export let randomBytes = insecureRandomBytes;
26
+ if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {
27
+ randomBytes = size => window.crypto.getRandomValues(Buffer.alloc(size));
28
+ } else {
29
+ try {
30
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
31
+ randomBytes = require('crypto').randomBytes;
32
+ } catch (e) {
33
+ // keep the fallback
34
+ }
35
+
36
+ // NOTE: in transpiled cases the above require might return null/undefined
37
+ if (randomBytes == null) {
38
+ randomBytes = insecureRandomBytes;
39
+ }
40
+ }
41
+
42
+ export function isUint8Array(value: unknown): value is Uint8Array {
43
+ return Object.prototype.toString.call(value) === '[object Uint8Array]';
44
+ }
45
+
46
+ export function isBigInt64Array(value: unknown): value is BigInt64Array {
47
+ return Object.prototype.toString.call(value) === '[object BigInt64Array]';
48
+ }
49
+
50
+ export function isBigUInt64Array(value: unknown): value is BigUint64Array {
51
+ return Object.prototype.toString.call(value) === '[object BigUint64Array]';
52
+ }
53
+
54
+ /** Call to check if your environment has `Buffer` */
55
+ export function haveBuffer(): boolean {
56
+ return typeof global !== 'undefined' && typeof global.Buffer !== 'undefined';
57
+ }
58
+
59
+ /** Callable in any environment to check if value is a Buffer */
60
+ export function isBuffer(value: unknown): value is Buffer {
61
+ return typeof value === 'object' && value?.constructor?.name === 'Buffer';
62
+ }
63
+
64
+ // To ensure that 0.4 of node works correctly
65
+ export function isDate(d: unknown): d is Date {
66
+ return isObjectLike(d) && Object.prototype.toString.call(d) === '[object Date]';
67
+ }
68
+
69
+ /**
70
+ * @internal
71
+ * this is to solve the `'someKey' in x` problem where x is unknown.
72
+ * https://github.com/typescript-eslint/typescript-eslint/issues/1071#issuecomment-541955753
73
+ */
74
+ export function isObjectLike(candidate: unknown): candidate is Record<string, unknown> {
75
+ return typeof candidate === 'object' && candidate !== null;
76
+ }
77
+
78
+ declare let console: { warn(...message: unknown[]): void };
79
+ export function deprecate<T extends Function>(fn: T, message: string): T {
80
+ if (typeof window === 'undefined' && typeof self === 'undefined') {
81
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
82
+ return require('util').deprecate(fn, message);
83
+ }
84
+ let warned = false;
85
+ function deprecated(this: unknown, ...args: unknown[]) {
86
+ if (!warned) {
87
+ console.warn(message);
88
+ warned = true;
89
+ }
90
+ return fn.apply(this, ...args);
91
+ }
92
+ return (deprecated as unknown) as T;
93
+ }
package/src/regexp.ts ADDED
@@ -0,0 +1,94 @@
1
+ import type { EJSONOptions } from './extended_json';
2
+
3
+ function alphabetize(str: string): string {
4
+ return str.split('').sort().join('');
5
+ }
6
+
7
+ /** @public */
8
+ export interface BSONRegExpExtendedLegacy {
9
+ $regex: string | BSONRegExp;
10
+ $options: string;
11
+ }
12
+
13
+ /** @public */
14
+ export interface BSONRegExpExtended {
15
+ $regularExpression: {
16
+ pattern: string;
17
+ options: string;
18
+ };
19
+ }
20
+
21
+ /**
22
+ * A class representation of the BSON RegExp type.
23
+ * @public
24
+ */
25
+ export class BSONRegExp {
26
+ _bsontype!: 'BSONRegExp';
27
+
28
+ pattern!: string;
29
+ options!: string;
30
+ /**
31
+ * @param pattern - The regular expression pattern to match
32
+ * @param options - The regular expression options
33
+ */
34
+ constructor(pattern: string, options?: string) {
35
+ if (!(this instanceof BSONRegExp)) return new BSONRegExp(pattern, options);
36
+
37
+ this.pattern = pattern;
38
+ this.options = options ?? '';
39
+ // Execute
40
+ alphabetize(this.options);
41
+
42
+ // Validate options
43
+ for (let i = 0; i < this.options.length; i++) {
44
+ if (
45
+ !(
46
+ this.options[i] === 'i' ||
47
+ this.options[i] === 'm' ||
48
+ this.options[i] === 'x' ||
49
+ this.options[i] === 'l' ||
50
+ this.options[i] === 's' ||
51
+ this.options[i] === 'u'
52
+ )
53
+ ) {
54
+ throw new Error(`The regular expression option [${this.options[i]}] is not supported`);
55
+ }
56
+ }
57
+ }
58
+
59
+ static parseOptions(options?: string): string {
60
+ return options ? options.split('').sort().join('') : '';
61
+ }
62
+
63
+ /** @internal */
64
+ toExtendedJSON(options?: EJSONOptions): BSONRegExpExtendedLegacy | BSONRegExpExtended {
65
+ options = options || {};
66
+ if (options.legacy) {
67
+ return { $regex: this.pattern, $options: this.options };
68
+ }
69
+ return { $regularExpression: { pattern: this.pattern, options: this.options } };
70
+ }
71
+
72
+ /** @internal */
73
+ static fromExtendedJSON(doc: BSONRegExpExtendedLegacy | BSONRegExpExtended): BSONRegExp {
74
+ if ('$regex' in doc) {
75
+ if (typeof doc.$regex !== 'string') {
76
+ // This is for $regex query operators that have extended json values.
77
+ if (doc.$regex._bsontype === 'BSONRegExp') {
78
+ return (doc as unknown) as BSONRegExp;
79
+ }
80
+ } else {
81
+ return new BSONRegExp(doc.$regex, BSONRegExp.parseOptions(doc.$options));
82
+ }
83
+ }
84
+ if ('$regularExpression' in doc) {
85
+ return new BSONRegExp(
86
+ doc.$regularExpression.pattern,
87
+ BSONRegExp.parseOptions(doc.$regularExpression.options)
88
+ );
89
+ }
90
+ throw new TypeError(`Unexpected BSONRegExp EJSON object form: ${JSON.stringify(doc)}`);
91
+ }
92
+ }
93
+
94
+ Object.defineProperty(BSONRegExp.prototype, '_bsontype', { value: 'BSONRegExp' });
package/src/symbol.ts ADDED
@@ -0,0 +1,59 @@
1
+ /** @public */
2
+ export interface BSONSymbolExtended {
3
+ $symbol: string;
4
+ }
5
+
6
+ /**
7
+ * A class representation of the BSON Symbol type.
8
+ * @public
9
+ */
10
+ export class BSONSymbol {
11
+ _bsontype!: 'Symbol';
12
+
13
+ value!: string;
14
+ /**
15
+ * @param value - the string representing the symbol.
16
+ */
17
+ constructor(value: string) {
18
+ if (!(this instanceof BSONSymbol)) return new BSONSymbol(value);
19
+
20
+ this.value = value;
21
+ }
22
+
23
+ /** Access the wrapped string value. */
24
+ valueOf(): string {
25
+ return this.value;
26
+ }
27
+
28
+ /** @internal */
29
+ toString(): string {
30
+ return this.value;
31
+ }
32
+
33
+ /** @internal */
34
+ inspect(): string {
35
+ return `new BSONSymbol("${this.value}")`;
36
+ }
37
+
38
+ /** @internal */
39
+ toJSON(): string {
40
+ return this.value;
41
+ }
42
+
43
+ /** @internal */
44
+ toExtendedJSON(): BSONSymbolExtended {
45
+ return { $symbol: this.value };
46
+ }
47
+
48
+ /** @internal */
49
+ static fromExtendedJSON(doc: BSONSymbolExtended): BSONSymbol {
50
+ return new BSONSymbol(doc.$symbol);
51
+ }
52
+
53
+ /** @internal */
54
+ [Symbol.for('nodejs.util.inspect.custom')](): string {
55
+ return this.inspect();
56
+ }
57
+ }
58
+
59
+ Object.defineProperty(BSONSymbol.prototype, '_bsontype', { value: 'Symbol' });
@@ -0,0 +1,108 @@
1
+ import { Long } from './long';
2
+
3
+ /** @public */
4
+ export type TimestampOverrides = '_bsontype' | 'toExtendedJSON' | 'fromExtendedJSON' | 'inspect';
5
+ /** @public */
6
+ export type LongWithoutOverrides = new (low: number | Long, high?: number, unsigned?: boolean) => {
7
+ [P in Exclude<keyof Long, TimestampOverrides>]: Long[P];
8
+ };
9
+ /** @public */
10
+ export const LongWithoutOverridesClass: LongWithoutOverrides = (Long as unknown) as LongWithoutOverrides;
11
+
12
+ /** @public */
13
+ export interface TimestampExtended {
14
+ $timestamp: {
15
+ t: number;
16
+ i: number;
17
+ };
18
+ }
19
+
20
+ /** @public */
21
+ export class Timestamp extends LongWithoutOverridesClass {
22
+ _bsontype!: 'Timestamp';
23
+
24
+ static readonly MAX_VALUE = Long.MAX_UNSIGNED_VALUE;
25
+
26
+ /**
27
+ * @param low - A 64-bit Long representing the Timestamp.
28
+ */
29
+ constructor(low: Long);
30
+ /**
31
+ * @param low - the low (signed) 32 bits of the Timestamp.
32
+ * @param high - the high (signed) 32 bits of the Timestamp.
33
+ */
34
+ constructor(low: Long);
35
+ constructor(low: number, high: number);
36
+ constructor(low: number | Long, high?: number) {
37
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
38
+ ///@ts-expect-error
39
+ if (!(this instanceof Timestamp)) return new Timestamp(low, high);
40
+
41
+ if (Long.isLong(low)) {
42
+ super(low.low, low.high, true);
43
+ } else {
44
+ super(low, high, true);
45
+ }
46
+ Object.defineProperty(this, '_bsontype', {
47
+ value: 'Timestamp',
48
+ writable: false,
49
+ configurable: false,
50
+ enumerable: false
51
+ });
52
+ }
53
+
54
+ toJSON(): { $timestamp: string } {
55
+ return {
56
+ $timestamp: this.toString()
57
+ };
58
+ }
59
+
60
+ /** Returns a Timestamp represented by the given (32-bit) integer value. */
61
+ static fromInt(value: number): Timestamp {
62
+ return new Timestamp(Long.fromInt(value, true));
63
+ }
64
+
65
+ /** Returns a Timestamp representing the given number value, provided that it is a finite number. Otherwise, zero is returned. */
66
+ static fromNumber(value: number): Timestamp {
67
+ return new Timestamp(Long.fromNumber(value, true));
68
+ }
69
+
70
+ /**
71
+ * Returns a Timestamp for the given high and low bits. Each is assumed to use 32 bits.
72
+ *
73
+ * @param lowBits - the low 32-bits.
74
+ * @param highBits - the high 32-bits.
75
+ */
76
+ static fromBits(lowBits: number, highBits: number): Timestamp {
77
+ return new Timestamp(lowBits, highBits);
78
+ }
79
+
80
+ /**
81
+ * Returns a Timestamp from the given string, optionally using the given radix.
82
+ *
83
+ * @param str - the textual representation of the Timestamp.
84
+ * @param optRadix - the radix in which the text is written.
85
+ */
86
+ static fromString(str: string, optRadix: number): Timestamp {
87
+ return new Timestamp(Long.fromString(str, true, optRadix));
88
+ }
89
+
90
+ /** @internal */
91
+ toExtendedJSON(): TimestampExtended {
92
+ return { $timestamp: { t: this.high >>> 0, i: this.low >>> 0 } };
93
+ }
94
+
95
+ /** @internal */
96
+ static fromExtendedJSON(doc: TimestampExtended): Timestamp {
97
+ return new Timestamp(doc.$timestamp.i, doc.$timestamp.t);
98
+ }
99
+
100
+ /** @internal */
101
+ [Symbol.for('nodejs.util.inspect.custom')](): string {
102
+ return this.inspect();
103
+ }
104
+
105
+ inspect(): string {
106
+ return `new Timestamp(${this.getLowBits().toString()}, ${this.getHighBits().toString()})`;
107
+ }
108
+ }
package/src/uuid.ts ADDED
@@ -0,0 +1,57 @@
1
+ /**
2
+ * UUID regular expression pattern copied from `uuid` npm module.
3
+ * @see https://github.com/uuidjs/uuid/blob/master/src/regex.js
4
+ */
5
+ const UUID_RX = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
6
+
7
+ /** @public */
8
+ export interface UUIDExtended {
9
+ $uuid: string;
10
+ }
11
+
12
+ /**
13
+ * Parser function copied from `uuid` npm module.
14
+ * @see https://github.com/uuidjs/uuid/blob/master/src/parse.js
15
+ * @internal
16
+ */
17
+ export function parseUUID(uuid: string): Uint8Array {
18
+ if (typeof uuid !== 'string') {
19
+ throw new TypeError('Invalid type for UUID, expected string but got ' + typeof uuid);
20
+ }
21
+
22
+ if (!UUID_RX.test(uuid)) {
23
+ throw new TypeError('Invalid format for UUID: ' + uuid);
24
+ }
25
+
26
+ let v;
27
+ const arr = new Uint8Array(16);
28
+
29
+ // Parse ########-....-....-....-............
30
+ arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24;
31
+ arr[1] = (v >>> 16) & 0xff;
32
+ arr[2] = (v >>> 8) & 0xff;
33
+ arr[3] = v & 0xff;
34
+
35
+ // Parse ........-####-....-....-............
36
+ arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8;
37
+ arr[5] = v & 0xff;
38
+
39
+ // Parse ........-....-####-....-............
40
+ arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8;
41
+ arr[7] = v & 0xff;
42
+
43
+ // Parse ........-....-....-####-............
44
+ arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8;
45
+ arr[9] = v & 0xff;
46
+
47
+ // Parse ........-....-....-....-############
48
+ // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes)
49
+ arr[10] = ((v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000) & 0xff;
50
+ arr[11] = (v / 0x100000000) & 0xff;
51
+ arr[12] = (v >>> 24) & 0xff;
52
+ arr[13] = (v >>> 16) & 0xff;
53
+ arr[14] = (v >>> 8) & 0xff;
54
+ arr[15] = v & 0xff;
55
+
56
+ return arr;
57
+ }
@@ -0,0 +1,47 @@
1
+ const FIRST_BIT = 0x80;
2
+ const FIRST_TWO_BITS = 0xc0;
3
+ const FIRST_THREE_BITS = 0xe0;
4
+ const FIRST_FOUR_BITS = 0xf0;
5
+ const FIRST_FIVE_BITS = 0xf8;
6
+
7
+ const TWO_BIT_CHAR = 0xc0;
8
+ const THREE_BIT_CHAR = 0xe0;
9
+ const FOUR_BIT_CHAR = 0xf0;
10
+ const CONTINUING_CHAR = 0x80;
11
+
12
+ /**
13
+ * Determines if the passed in bytes are valid utf8
14
+ * @param bytes - An array of 8-bit bytes. Must be indexable and have length property
15
+ * @param start - The index to start validating
16
+ * @param end - The index to end validating
17
+ */
18
+ export function validateUtf8(
19
+ bytes: { [index: number]: number },
20
+ start: number,
21
+ end: number
22
+ ): boolean {
23
+ let continuation = 0;
24
+
25
+ for (let i = start; i < end; i += 1) {
26
+ const byte = bytes[i];
27
+
28
+ if (continuation) {
29
+ if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
30
+ return false;
31
+ }
32
+ continuation -= 1;
33
+ } else if (byte & FIRST_BIT) {
34
+ if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
35
+ continuation = 1;
36
+ } else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
37
+ continuation = 2;
38
+ } else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
39
+ continuation = 3;
40
+ } else {
41
+ return false;
42
+ }
43
+ }
44
+ }
45
+
46
+ return !continuation;
47
+ }
package/lib/fnv1a.js DELETED
@@ -1,48 +0,0 @@
1
- 'use strict';
2
-
3
- const Buffer = require('buffer').Buffer;
4
- const Long = require('./long');
5
-
6
- const MASK_8 = 0xff;
7
- const MASK_24 = 0xffffff;
8
- const MASK_32 = 0xffffffff;
9
-
10
- // See http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param for the definition of these parameters;
11
- const FNV_PRIME = new Long(16777619, 0);
12
- const OFFSET_BASIS = new Long(2166136261, 0);
13
- const FNV_MASK = new Long(MASK_32, 0);
14
-
15
- /**
16
- * Implementation of the FNV-1a hash for a 32-bit hash value
17
- * Algorithm can be found here: http://www.isthe.com/chongo/tech/comp/fnv/#FNV-1a
18
- * @ignore
19
- */
20
- function fnv1a32(input, encoding) {
21
- encoding = encoding || 'utf8';
22
- const octets = Buffer.from(input, encoding);
23
-
24
- let hash = OFFSET_BASIS;
25
- for (let i = 0; i < octets.length; i += 1) {
26
- hash = hash.xor(new Long(octets[i], 0));
27
- hash = hash.multiply(FNV_PRIME);
28
- hash = hash.and(FNV_MASK);
29
- }
30
- return hash.getLowBitsUnsigned();
31
- }
32
-
33
- /**
34
- * Implements FNV-1a to generate 32-bit hash, then uses xor-folding
35
- * to convert to a 24-bit hash. See here for more info:
36
- * http://www.isthe.com/chongo/tech/comp/fnv/#xor-fold
37
- * @ignore
38
- */
39
- function fnv1a24(input, encoding) {
40
- const _32bit = fnv1a32(input, encoding);
41
- const base = _32bit & MASK_24;
42
- const top = (_32bit >>> 24) & MASK_8;
43
- const final = (base ^ top) & MASK_24;
44
-
45
- return final;
46
- }
47
-
48
- module.exports = { fnv1a24, fnv1a32 };