mongodb 6.5.0-dev.20240328.sha.458cf6d → 6.5.0-dev.20240403.sha.cb5903f

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.
package/lib/bson.js CHANGED
@@ -1,27 +1,38 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveBSONOptions = exports.pluckBSONSerializeOptions = exports.UUID = exports.Timestamp = exports.serialize = exports.ObjectId = exports.MinKey = exports.MaxKey = exports.Long = exports.Int32 = exports.EJSON = exports.Double = exports.deserialize = exports.Decimal128 = exports.DBRef = exports.Code = exports.calculateObjectSize = exports.BSONType = exports.BSONSymbol = exports.BSONRegExp = exports.BSON = exports.Binary = void 0;
4
- var bson_1 = require("bson");
5
- Object.defineProperty(exports, "Binary", { enumerable: true, get: function () { return bson_1.Binary; } });
6
- Object.defineProperty(exports, "BSON", { enumerable: true, get: function () { return bson_1.BSON; } });
7
- Object.defineProperty(exports, "BSONRegExp", { enumerable: true, get: function () { return bson_1.BSONRegExp; } });
8
- Object.defineProperty(exports, "BSONSymbol", { enumerable: true, get: function () { return bson_1.BSONSymbol; } });
9
- Object.defineProperty(exports, "BSONType", { enumerable: true, get: function () { return bson_1.BSONType; } });
10
- Object.defineProperty(exports, "calculateObjectSize", { enumerable: true, get: function () { return bson_1.calculateObjectSize; } });
11
- Object.defineProperty(exports, "Code", { enumerable: true, get: function () { return bson_1.Code; } });
12
- Object.defineProperty(exports, "DBRef", { enumerable: true, get: function () { return bson_1.DBRef; } });
13
- Object.defineProperty(exports, "Decimal128", { enumerable: true, get: function () { return bson_1.Decimal128; } });
14
- Object.defineProperty(exports, "deserialize", { enumerable: true, get: function () { return bson_1.deserialize; } });
15
- Object.defineProperty(exports, "Double", { enumerable: true, get: function () { return bson_1.Double; } });
16
- Object.defineProperty(exports, "EJSON", { enumerable: true, get: function () { return bson_1.EJSON; } });
17
- Object.defineProperty(exports, "Int32", { enumerable: true, get: function () { return bson_1.Int32; } });
18
- Object.defineProperty(exports, "Long", { enumerable: true, get: function () { return bson_1.Long; } });
19
- Object.defineProperty(exports, "MaxKey", { enumerable: true, get: function () { return bson_1.MaxKey; } });
20
- Object.defineProperty(exports, "MinKey", { enumerable: true, get: function () { return bson_1.MinKey; } });
21
- Object.defineProperty(exports, "ObjectId", { enumerable: true, get: function () { return bson_1.ObjectId; } });
22
- Object.defineProperty(exports, "serialize", { enumerable: true, get: function () { return bson_1.serialize; } });
23
- Object.defineProperty(exports, "Timestamp", { enumerable: true, get: function () { return bson_1.Timestamp; } });
24
- Object.defineProperty(exports, "UUID", { enumerable: true, get: function () { return bson_1.UUID; } });
3
+ exports.resolveBSONOptions = exports.pluckBSONSerializeOptions = exports.toUTF8 = exports.getBigInt64LE = exports.getFloat64LE = exports.getInt32LE = exports.parseToElementsToArray = exports.UUID = exports.Timestamp = exports.serialize = exports.ObjectId = exports.MinKey = exports.MaxKey = exports.Long = exports.Int32 = exports.EJSON = exports.Double = exports.deserialize = exports.Decimal128 = exports.DBRef = exports.Code = exports.calculateObjectSize = exports.BSONType = exports.BSONSymbol = exports.BSONRegExp = exports.BSONError = exports.BSON = exports.Binary = void 0;
4
+ const bson_1 = require("bson");
5
+ var bson_2 = require("bson");
6
+ Object.defineProperty(exports, "Binary", { enumerable: true, get: function () { return bson_2.Binary; } });
7
+ Object.defineProperty(exports, "BSON", { enumerable: true, get: function () { return bson_2.BSON; } });
8
+ Object.defineProperty(exports, "BSONError", { enumerable: true, get: function () { return bson_2.BSONError; } });
9
+ Object.defineProperty(exports, "BSONRegExp", { enumerable: true, get: function () { return bson_2.BSONRegExp; } });
10
+ Object.defineProperty(exports, "BSONSymbol", { enumerable: true, get: function () { return bson_2.BSONSymbol; } });
11
+ Object.defineProperty(exports, "BSONType", { enumerable: true, get: function () { return bson_2.BSONType; } });
12
+ Object.defineProperty(exports, "calculateObjectSize", { enumerable: true, get: function () { return bson_2.calculateObjectSize; } });
13
+ Object.defineProperty(exports, "Code", { enumerable: true, get: function () { return bson_2.Code; } });
14
+ Object.defineProperty(exports, "DBRef", { enumerable: true, get: function () { return bson_2.DBRef; } });
15
+ Object.defineProperty(exports, "Decimal128", { enumerable: true, get: function () { return bson_2.Decimal128; } });
16
+ Object.defineProperty(exports, "deserialize", { enumerable: true, get: function () { return bson_2.deserialize; } });
17
+ Object.defineProperty(exports, "Double", { enumerable: true, get: function () { return bson_2.Double; } });
18
+ Object.defineProperty(exports, "EJSON", { enumerable: true, get: function () { return bson_2.EJSON; } });
19
+ Object.defineProperty(exports, "Int32", { enumerable: true, get: function () { return bson_2.Int32; } });
20
+ Object.defineProperty(exports, "Long", { enumerable: true, get: function () { return bson_2.Long; } });
21
+ Object.defineProperty(exports, "MaxKey", { enumerable: true, get: function () { return bson_2.MaxKey; } });
22
+ Object.defineProperty(exports, "MinKey", { enumerable: true, get: function () { return bson_2.MinKey; } });
23
+ Object.defineProperty(exports, "ObjectId", { enumerable: true, get: function () { return bson_2.ObjectId; } });
24
+ Object.defineProperty(exports, "serialize", { enumerable: true, get: function () { return bson_2.serialize; } });
25
+ Object.defineProperty(exports, "Timestamp", { enumerable: true, get: function () { return bson_2.Timestamp; } });
26
+ Object.defineProperty(exports, "UUID", { enumerable: true, get: function () { return bson_2.UUID; } });
27
+ function parseToElementsToArray(bytes, offset) {
28
+ const res = bson_1.BSON.onDemand.parseToElements(bytes, offset);
29
+ return Array.isArray(res) ? res : [...res];
30
+ }
31
+ exports.parseToElementsToArray = parseToElementsToArray;
32
+ exports.getInt32LE = bson_1.BSON.onDemand.NumberUtils.getInt32LE;
33
+ exports.getFloat64LE = bson_1.BSON.onDemand.NumberUtils.getFloat64LE;
34
+ exports.getBigInt64LE = bson_1.BSON.onDemand.NumberUtils.getBigInt64LE;
35
+ exports.toUTF8 = bson_1.BSON.onDemand.ByteUtils.toUTF8;
25
36
  function pluckBSONSerializeOptions(options) {
26
37
  const { fieldsAsRaw, useBigInt64, promoteValues, promoteBuffers, promoteLongs, serializeFunctions, ignoreUndefined, bsonRegExp, raw, enableUtf8Validation } = options;
27
38
  return {
package/lib/bson.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bson.js","sourceRoot":"","sources":["../src/bson.ts"],"names":[],"mappings":";;;AAEA,6BAuBc;AAtBZ,8FAAA,MAAM,OAAA;AACN,4FAAA,IAAI,OAAA;AACJ,kGAAA,UAAU,OAAA;AACV,kGAAA,UAAU,OAAA;AACV,gGAAA,QAAQ,OAAA;AACR,2GAAA,mBAAmB,OAAA;AACnB,4FAAA,IAAI,OAAA;AACJ,6FAAA,KAAK,OAAA;AACL,kGAAA,UAAU,OAAA;AACV,mGAAA,WAAW,OAAA;AAEX,8FAAA,MAAM,OAAA;AACN,6FAAA,KAAK,OAAA;AAEL,6FAAA,KAAK,OAAA;AACL,4FAAA,IAAI,OAAA;AACJ,8FAAA,MAAM,OAAA;AACN,8FAAA,MAAM,OAAA;AACN,gGAAA,QAAQ,OAAA;AACR,iGAAA,SAAS,OAAA;AACT,iGAAA,SAAS,OAAA;AACT,4FAAA,IAAI,OAAA;AA4CN,SAAgB,yBAAyB,CAAC,OAA6B;IACrE,MAAM,EACJ,WAAW,EACX,WAAW,EACX,aAAa,EACb,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,UAAU,EACV,GAAG,EACH,oBAAoB,EACrB,GAAG,OAAO,CAAC;IACZ,OAAO;QACL,WAAW;QACX,WAAW;QACX,aAAa;QACb,cAAc;QACd,YAAY;QACZ,kBAAkB;QAClB,eAAe;QACf,UAAU;QACV,GAAG;QACH,oBAAoB;KACrB,CAAC;AACJ,CAAC;AAzBD,8DAyBC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAChC,OAA8B,EAC9B,MAA+C;IAE/C,MAAM,aAAa,GAAG,MAAM,EAAE,WAAW,CAAC;IAC1C,OAAO;QACL,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,aAAa,EAAE,GAAG,IAAI,KAAK;QAChD,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,aAAa,EAAE,WAAW,IAAI,KAAK;QACxE,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,aAAa,EAAE,YAAY,IAAI,IAAI;QAC1E,aAAa,EAAE,OAAO,EAAE,aAAa,IAAI,aAAa,EAAE,aAAa,IAAI,IAAI;QAC7E,cAAc,EAAE,OAAO,EAAE,cAAc,IAAI,aAAa,EAAE,cAAc,IAAI,KAAK;QACjF,eAAe,EAAE,OAAO,EAAE,eAAe,IAAI,aAAa,EAAE,eAAe,IAAI,KAAK;QACpF,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,UAAU,IAAI,KAAK;QACrE,kBAAkB,EAAE,OAAO,EAAE,kBAAkB,IAAI,aAAa,EAAE,kBAAkB,IAAI,KAAK;QAC7F,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,aAAa,EAAE,WAAW,IAAI,EAAE;QACrE,oBAAoB,EAClB,OAAO,EAAE,oBAAoB,IAAI,aAAa,EAAE,oBAAoB,IAAI,IAAI;KAC/E,CAAC;AACJ,CAAC;AAlBD,gDAkBC"}
1
+ {"version":3,"file":"bson.js","sourceRoot":"","sources":["../src/bson.ts"],"names":[],"mappings":";;;AACA,+BAA4B;AAE5B,6BAwBc;AAvBZ,8FAAA,MAAM,OAAA;AACN,4FAAA,IAAI,OAAA;AACJ,iGAAA,SAAS,OAAA;AACT,kGAAA,UAAU,OAAA;AACV,kGAAA,UAAU,OAAA;AACV,gGAAA,QAAQ,OAAA;AACR,2GAAA,mBAAmB,OAAA;AACnB,4FAAA,IAAI,OAAA;AACJ,6FAAA,KAAK,OAAA;AACL,kGAAA,UAAU,OAAA;AACV,mGAAA,WAAW,OAAA;AAEX,8FAAA,MAAM,OAAA;AACN,6FAAA,KAAK,OAAA;AAEL,6FAAA,KAAK,OAAA;AACL,4FAAA,IAAI,OAAA;AACJ,8FAAA,MAAM,OAAA;AACN,8FAAA,MAAM,OAAA;AACN,gGAAA,QAAQ,OAAA;AACR,iGAAA,SAAS,OAAA;AACT,iGAAA,SAAS,OAAA;AACT,4FAAA,IAAI,OAAA;AAKN,SAAgB,sBAAsB,CAAC,KAAiB,EAAE,MAAe;IACvE,MAAM,GAAG,GAAG,WAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACzD,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;AAC7C,CAAC;AAHD,wDAGC;AACY,QAAA,UAAU,GAAG,WAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC;AAClD,QAAA,YAAY,GAAG,WAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,YAAY,CAAC;AACtD,QAAA,aAAa,GAAG,WAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,aAAa,CAAC;AACxD,QAAA,MAAM,GAAG,WAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC;AA2CrD,SAAgB,yBAAyB,CAAC,OAA6B;IACrE,MAAM,EACJ,WAAW,EACX,WAAW,EACX,aAAa,EACb,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,UAAU,EACV,GAAG,EACH,oBAAoB,EACrB,GAAG,OAAO,CAAC;IACZ,OAAO;QACL,WAAW;QACX,WAAW;QACX,aAAa;QACb,cAAc;QACd,YAAY;QACZ,kBAAkB;QAClB,eAAe;QACf,UAAU;QACV,GAAG;QACH,oBAAoB;KACrB,CAAC;AACJ,CAAC;AAzBD,8DAyBC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAChC,OAA8B,EAC9B,MAA+C;IAE/C,MAAM,aAAa,GAAG,MAAM,EAAE,WAAW,CAAC;IAC1C,OAAO;QACL,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,aAAa,EAAE,GAAG,IAAI,KAAK;QAChD,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,aAAa,EAAE,WAAW,IAAI,KAAK;QACxE,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,aAAa,EAAE,YAAY,IAAI,IAAI;QAC1E,aAAa,EAAE,OAAO,EAAE,aAAa,IAAI,aAAa,EAAE,aAAa,IAAI,IAAI;QAC7E,cAAc,EAAE,OAAO,EAAE,cAAc,IAAI,aAAa,EAAE,cAAc,IAAI,KAAK;QACjF,eAAe,EAAE,OAAO,EAAE,eAAe,IAAI,aAAa,EAAE,eAAe,IAAI,KAAK;QACpF,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,UAAU,IAAI,KAAK;QACrE,kBAAkB,EAAE,OAAO,EAAE,kBAAkB,IAAI,aAAa,EAAE,kBAAkB,IAAI,KAAK;QAC7F,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,aAAa,EAAE,WAAW,IAAI,EAAE;QACrE,oBAAoB,EAClB,OAAO,EAAE,oBAAoB,IAAI,aAAa,EAAE,oBAAoB,IAAI,IAAI;KAC/E,CAAC;AACJ,CAAC;AAlBD,gDAkBC"}
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OnDemandDocument = void 0;
4
+ const bson_1 = require("../../../bson");
5
+ /** @internal */
6
+ class OnDemandDocument {
7
+ constructor(
8
+ /** BSON bytes, this document begins at offset */
9
+ bson,
10
+ /** The start of the document */
11
+ offset = 0,
12
+ /** If this is an embedded document, indicates if this was a BSON array */
13
+ isArray = false) {
14
+ this.bson = bson;
15
+ this.offset = offset;
16
+ this.isArray = isArray;
17
+ /**
18
+ * Maps JS strings to elements and jsValues for speeding up subsequent lookups.
19
+ * - If `false` then name does not exist in the BSON document
20
+ * - If `CachedBSONElement` instance name exists
21
+ * - If `cache[name].value == null` jsValue has not yet been parsed
22
+ * - Null/Undefined values do not get cached because they are zero-length values.
23
+ */
24
+ this.cache = Object.create(null);
25
+ /** Caches the index of elements that have been named */
26
+ this.indexFound = Object.create(null);
27
+ this.elements = (0, bson_1.parseToElementsToArray)(this.bson, offset);
28
+ }
29
+ /** Only supports basic latin strings */
30
+ isElementName(name, element) {
31
+ const nameLength = element[2 /* BSONElementOffset.nameLength */];
32
+ const nameOffset = element[1 /* BSONElementOffset.nameOffset */];
33
+ if (name.length !== nameLength)
34
+ return false;
35
+ for (let i = 0; i < name.length; i++) {
36
+ if (this.bson[nameOffset + i] !== name.charCodeAt(i))
37
+ return false;
38
+ }
39
+ return true;
40
+ }
41
+ /**
42
+ * Seeks into the elements array for an element matching the given name.
43
+ *
44
+ * @remarks
45
+ * Caching:
46
+ * - Caches the existence of a property making subsequent look ups for non-existent properties return immediately
47
+ * - Caches names mapped to elements to avoid reiterating the array and comparing the name again
48
+ * - Caches the index at which an element has been found to prevent rechecking against elements already determined to belong to another name
49
+ *
50
+ * @param name - a basic latin string name of a BSON element
51
+ * @returns
52
+ */
53
+ getElement(name) {
54
+ const cachedElement = this.cache[name];
55
+ if (cachedElement === false)
56
+ return null;
57
+ if (cachedElement != null) {
58
+ return cachedElement;
59
+ }
60
+ for (let index = 0; index < this.elements.length; index++) {
61
+ const element = this.elements[index];
62
+ // skip this element if it has already been associated with a name
63
+ if (!this.indexFound[index] && this.isElementName(name, element)) {
64
+ const cachedElement = { element, value: undefined };
65
+ this.cache[name] = cachedElement;
66
+ this.indexFound[index] = true;
67
+ return cachedElement;
68
+ }
69
+ }
70
+ this.cache[name] = false;
71
+ return null;
72
+ }
73
+ toJSValue(element, as) {
74
+ const type = element[0 /* BSONElementOffset.type */];
75
+ const offset = element[3 /* BSONElementOffset.offset */];
76
+ const length = element[4 /* BSONElementOffset.length */];
77
+ if (as !== type) {
78
+ return null;
79
+ }
80
+ switch (as) {
81
+ case bson_1.BSONType.null:
82
+ case bson_1.BSONType.undefined:
83
+ return null;
84
+ case bson_1.BSONType.double:
85
+ return (0, bson_1.getFloat64LE)(this.bson, offset);
86
+ case bson_1.BSONType.int:
87
+ return (0, bson_1.getInt32LE)(this.bson, offset);
88
+ case bson_1.BSONType.long:
89
+ return (0, bson_1.getBigInt64LE)(this.bson, offset);
90
+ case bson_1.BSONType.bool:
91
+ return Boolean(this.bson[offset]);
92
+ case bson_1.BSONType.objectId:
93
+ return new bson_1.ObjectId(this.bson.subarray(offset, offset + 12));
94
+ case bson_1.BSONType.timestamp:
95
+ return new bson_1.Timestamp((0, bson_1.getBigInt64LE)(this.bson, offset));
96
+ case bson_1.BSONType.string:
97
+ return (0, bson_1.toUTF8)(this.bson, offset + 4, offset + length - 1, false);
98
+ case bson_1.BSONType.binData: {
99
+ const totalBinarySize = (0, bson_1.getInt32LE)(this.bson, offset);
100
+ const subType = this.bson[offset + 4];
101
+ if (subType === 2) {
102
+ const subType2BinarySize = (0, bson_1.getInt32LE)(this.bson, offset + 1 + 4);
103
+ if (subType2BinarySize < 0)
104
+ throw new bson_1.BSONError('Negative binary type element size found for subtype 0x02');
105
+ if (subType2BinarySize > totalBinarySize - 4)
106
+ throw new bson_1.BSONError('Binary type with subtype 0x02 contains too long binary size');
107
+ if (subType2BinarySize < totalBinarySize - 4)
108
+ throw new bson_1.BSONError('Binary type with subtype 0x02 contains too short binary size');
109
+ return new bson_1.Binary(this.bson.subarray(offset + 1 + 4 + 4, offset + 1 + 4 + 4 + subType2BinarySize), 2);
110
+ }
111
+ return new bson_1.Binary(this.bson.subarray(offset + 1 + 4, offset + 1 + 4 + totalBinarySize), subType);
112
+ }
113
+ case bson_1.BSONType.date:
114
+ // Pretend this is correct.
115
+ return new Date(Number((0, bson_1.getBigInt64LE)(this.bson, offset)));
116
+ case bson_1.BSONType.object:
117
+ return new OnDemandDocument(this.bson, offset);
118
+ case bson_1.BSONType.array:
119
+ return new OnDemandDocument(this.bson, offset, true);
120
+ default:
121
+ throw new bson_1.BSONError(`Unsupported BSON type: ${as}`);
122
+ }
123
+ }
124
+ /**
125
+ * Checks for the existence of an element by name.
126
+ *
127
+ * @remarks
128
+ * Uses `getElement` with the expectation that will populate caches such that a `has` call
129
+ * followed by a `getElement` call will not repeat the cost paid by the first look up.
130
+ *
131
+ * @param name - element name
132
+ */
133
+ has(name) {
134
+ const cachedElement = this.cache[name];
135
+ if (cachedElement === false)
136
+ return false;
137
+ if (cachedElement != null)
138
+ return true;
139
+ return this.getElement(name) != null;
140
+ }
141
+ get(name, as, required) {
142
+ const element = this.getElement(name);
143
+ if (element == null) {
144
+ if (required === true) {
145
+ throw new bson_1.BSONError(`BSON element "${name}" is missing`);
146
+ }
147
+ else {
148
+ return null;
149
+ }
150
+ }
151
+ if (element.value == null) {
152
+ const value = this.toJSValue(element.element, as);
153
+ if (value == null) {
154
+ if (required === true) {
155
+ throw new bson_1.BSONError(`BSON element "${name}" is missing`);
156
+ }
157
+ else {
158
+ return null;
159
+ }
160
+ }
161
+ // It is important to never store null
162
+ element.value = value;
163
+ }
164
+ return element.value;
165
+ }
166
+ getNumber(name, required) {
167
+ const maybeBool = this.get(name, bson_1.BSONType.bool);
168
+ const bool = maybeBool == null ? null : maybeBool ? 1 : 0;
169
+ const maybeLong = this.get(name, bson_1.BSONType.long);
170
+ const long = maybeLong == null ? null : Number(maybeLong);
171
+ const result = bool ?? long ?? this.get(name, bson_1.BSONType.int) ?? this.get(name, bson_1.BSONType.double);
172
+ if (required === true && result == null) {
173
+ throw new bson_1.BSONError(`BSON element "${name}" is missing`);
174
+ }
175
+ return result;
176
+ }
177
+ /**
178
+ * Deserialize this object, DOES NOT cache result so avoid multiple invocations
179
+ * @param options - BSON deserialization options
180
+ */
181
+ toObject(options) {
182
+ return bson_1.BSON.deserialize(this.bson, {
183
+ ...options,
184
+ index: this.offset,
185
+ allowObjectSmallerThanBufferSize: true
186
+ });
187
+ }
188
+ /**
189
+ * Iterates through the elements of a document reviving them using the `as` BSONType.
190
+ *
191
+ * @param as - The type to revive all elements as
192
+ */
193
+ *valuesAs(as) {
194
+ if (!this.isArray) {
195
+ throw new bson_1.BSONError('Unexpected conversion of non-array value to array');
196
+ }
197
+ let counter = 0;
198
+ for (const element of this.elements) {
199
+ const value = this.toJSValue(element, as);
200
+ this.cache[counter] = { element, value };
201
+ yield value;
202
+ counter += 1;
203
+ }
204
+ }
205
+ }
206
+ exports.OnDemandDocument = OnDemandDocument;
207
+ //# sourceMappingURL=document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.js","sourceRoot":"","sources":["../../../../src/cmap/wire_protocol/on_demand/document.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "6.5.0-dev.20240328.sha.458cf6d",
3
+ "version": "6.5.0-dev.20240403.sha.cb5903f",
4
4
  "description": "The official MongoDB driver for Node.js",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@mongodb-js/saslprep": "^1.1.5",
29
- "bson": "^6.5.0",
29
+ "bson": "^6.6.0",
30
30
  "mongodb-connection-string-url": "^3.0.0"
31
31
  },
32
32
  "peerDependencies": {
package/src/bson.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import type { DeserializeOptions, SerializeOptions } from 'bson';
2
+ import { BSON } from 'bson';
2
3
 
3
4
  export {
4
5
  Binary,
5
6
  BSON,
7
+ BSONError,
6
8
  BSONRegExp,
7
9
  BSONSymbol,
8
10
  BSONType,
@@ -25,6 +27,17 @@ export {
25
27
  UUID
26
28
  } from 'bson';
27
29
 
30
+ export type BSONElement = BSON.OnDemand['BSONElement'];
31
+
32
+ export function parseToElementsToArray(bytes: Uint8Array, offset?: number): BSONElement[] {
33
+ const res = BSON.onDemand.parseToElements(bytes, offset);
34
+ return Array.isArray(res) ? res : [...res];
35
+ }
36
+ export const getInt32LE = BSON.onDemand.NumberUtils.getInt32LE;
37
+ export const getFloat64LE = BSON.onDemand.NumberUtils.getFloat64LE;
38
+ export const getBigInt64LE = BSON.onDemand.NumberUtils.getBigInt64LE;
39
+ export const toUTF8 = BSON.onDemand.ByteUtils.toUTF8;
40
+
28
41
  /**
29
42
  * BSON Serialization options.
30
43
  * @public
@@ -0,0 +1,322 @@
1
+ import {
2
+ Binary,
3
+ BSON,
4
+ type BSONElement,
5
+ BSONError,
6
+ type BSONSerializeOptions,
7
+ BSONType,
8
+ getBigInt64LE,
9
+ getFloat64LE,
10
+ getInt32LE,
11
+ ObjectId,
12
+ parseToElementsToArray,
13
+ Timestamp,
14
+ toUTF8
15
+ } from '../../../bson';
16
+
17
+ // eslint-disable-next-line no-restricted-syntax
18
+ const enum BSONElementOffset {
19
+ type = 0,
20
+ nameOffset = 1,
21
+ nameLength = 2,
22
+ offset = 3,
23
+ length = 4
24
+ }
25
+
26
+ export type JSTypeOf = {
27
+ [BSONType.null]: null;
28
+ [BSONType.undefined]: null;
29
+ [BSONType.double]: number;
30
+ [BSONType.int]: number;
31
+ [BSONType.long]: bigint;
32
+ [BSONType.timestamp]: Timestamp;
33
+ [BSONType.binData]: Binary;
34
+ [BSONType.bool]: boolean;
35
+ [BSONType.objectId]: ObjectId;
36
+ [BSONType.string]: string;
37
+ [BSONType.date]: Date;
38
+ [BSONType.object]: OnDemandDocument;
39
+ [BSONType.array]: OnDemandDocument;
40
+ };
41
+
42
+ /** @internal */
43
+ type CachedBSONElement = { element: BSONElement; value: any | undefined };
44
+
45
+ /** @internal */
46
+ export class OnDemandDocument {
47
+ /**
48
+ * Maps JS strings to elements and jsValues for speeding up subsequent lookups.
49
+ * - If `false` then name does not exist in the BSON document
50
+ * - If `CachedBSONElement` instance name exists
51
+ * - If `cache[name].value == null` jsValue has not yet been parsed
52
+ * - Null/Undefined values do not get cached because they are zero-length values.
53
+ */
54
+ private readonly cache: Record<string, CachedBSONElement | false | undefined> =
55
+ Object.create(null);
56
+ /** Caches the index of elements that have been named */
57
+ private readonly indexFound: Record<number, boolean> = Object.create(null);
58
+
59
+ /** All bson elements in this document */
60
+ private readonly elements: BSONElement[];
61
+
62
+ constructor(
63
+ /** BSON bytes, this document begins at offset */
64
+ protected readonly bson: Uint8Array,
65
+ /** The start of the document */
66
+ private readonly offset = 0,
67
+ /** If this is an embedded document, indicates if this was a BSON array */
68
+ public readonly isArray = false
69
+ ) {
70
+ this.elements = parseToElementsToArray(this.bson, offset);
71
+ }
72
+
73
+ /** Only supports basic latin strings */
74
+ private isElementName(name: string, element: BSONElement): boolean {
75
+ const nameLength = element[BSONElementOffset.nameLength];
76
+ const nameOffset = element[BSONElementOffset.nameOffset];
77
+
78
+ if (name.length !== nameLength) return false;
79
+
80
+ for (let i = 0; i < name.length; i++) {
81
+ if (this.bson[nameOffset + i] !== name.charCodeAt(i)) return false;
82
+ }
83
+
84
+ return true;
85
+ }
86
+
87
+ /**
88
+ * Seeks into the elements array for an element matching the given name.
89
+ *
90
+ * @remarks
91
+ * Caching:
92
+ * - Caches the existence of a property making subsequent look ups for non-existent properties return immediately
93
+ * - Caches names mapped to elements to avoid reiterating the array and comparing the name again
94
+ * - Caches the index at which an element has been found to prevent rechecking against elements already determined to belong to another name
95
+ *
96
+ * @param name - a basic latin string name of a BSON element
97
+ * @returns
98
+ */
99
+ private getElement(name: string): CachedBSONElement | null {
100
+ const cachedElement = this.cache[name];
101
+ if (cachedElement === false) return null;
102
+
103
+ if (cachedElement != null) {
104
+ return cachedElement;
105
+ }
106
+
107
+ for (let index = 0; index < this.elements.length; index++) {
108
+ const element = this.elements[index];
109
+
110
+ // skip this element if it has already been associated with a name
111
+ if (!this.indexFound[index] && this.isElementName(name, element)) {
112
+ const cachedElement = { element, value: undefined };
113
+ this.cache[name] = cachedElement;
114
+ this.indexFound[index] = true;
115
+ return cachedElement;
116
+ }
117
+ }
118
+
119
+ this.cache[name] = false;
120
+ return null;
121
+ }
122
+
123
+ /**
124
+ * Translates BSON bytes into a javascript value. Checking `as` against the BSON element's type
125
+ * this methods returns the small subset of BSON types that the driver needs to function.
126
+ *
127
+ * @remarks
128
+ * - BSONType.null and BSONType.undefined always return null
129
+ * - If the type requested does not match this returns null
130
+ *
131
+ * @param element - The element to revive to a javascript value
132
+ * @param as - A type byte expected to be returned
133
+ */
134
+ private toJSValue<T extends keyof JSTypeOf>(element: BSONElement, as: T): JSTypeOf[T];
135
+ private toJSValue(element: BSONElement, as: keyof JSTypeOf): any {
136
+ const type = element[BSONElementOffset.type];
137
+ const offset = element[BSONElementOffset.offset];
138
+ const length = element[BSONElementOffset.length];
139
+
140
+ if (as !== type) {
141
+ return null;
142
+ }
143
+
144
+ switch (as) {
145
+ case BSONType.null:
146
+ case BSONType.undefined:
147
+ return null;
148
+ case BSONType.double:
149
+ return getFloat64LE(this.bson, offset);
150
+ case BSONType.int:
151
+ return getInt32LE(this.bson, offset);
152
+ case BSONType.long:
153
+ return getBigInt64LE(this.bson, offset);
154
+ case BSONType.bool:
155
+ return Boolean(this.bson[offset]);
156
+ case BSONType.objectId:
157
+ return new ObjectId(this.bson.subarray(offset, offset + 12));
158
+ case BSONType.timestamp:
159
+ return new Timestamp(getBigInt64LE(this.bson, offset));
160
+ case BSONType.string:
161
+ return toUTF8(this.bson, offset + 4, offset + length - 1, false);
162
+ case BSONType.binData: {
163
+ const totalBinarySize = getInt32LE(this.bson, offset);
164
+ const subType = this.bson[offset + 4];
165
+
166
+ if (subType === 2) {
167
+ const subType2BinarySize = getInt32LE(this.bson, offset + 1 + 4);
168
+ if (subType2BinarySize < 0)
169
+ throw new BSONError('Negative binary type element size found for subtype 0x02');
170
+ if (subType2BinarySize > totalBinarySize - 4)
171
+ throw new BSONError('Binary type with subtype 0x02 contains too long binary size');
172
+ if (subType2BinarySize < totalBinarySize - 4)
173
+ throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
174
+ return new Binary(
175
+ this.bson.subarray(offset + 1 + 4 + 4, offset + 1 + 4 + 4 + subType2BinarySize),
176
+ 2
177
+ );
178
+ }
179
+
180
+ return new Binary(
181
+ this.bson.subarray(offset + 1 + 4, offset + 1 + 4 + totalBinarySize),
182
+ subType
183
+ );
184
+ }
185
+ case BSONType.date:
186
+ // Pretend this is correct.
187
+ return new Date(Number(getBigInt64LE(this.bson, offset)));
188
+
189
+ case BSONType.object:
190
+ return new OnDemandDocument(this.bson, offset);
191
+ case BSONType.array:
192
+ return new OnDemandDocument(this.bson, offset, true);
193
+
194
+ default:
195
+ throw new BSONError(`Unsupported BSON type: ${as}`);
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Checks for the existence of an element by name.
201
+ *
202
+ * @remarks
203
+ * Uses `getElement` with the expectation that will populate caches such that a `has` call
204
+ * followed by a `getElement` call will not repeat the cost paid by the first look up.
205
+ *
206
+ * @param name - element name
207
+ */
208
+ public has(name: string): boolean {
209
+ const cachedElement = this.cache[name];
210
+ if (cachedElement === false) return false;
211
+ if (cachedElement != null) return true;
212
+ return this.getElement(name) != null;
213
+ }
214
+
215
+ /**
216
+ * Turns BSON element with `name` into a javascript value.
217
+ *
218
+ * @typeParam T - must be one of the supported BSON types determined by `JSTypeOf` this will determine the return type of this function.
219
+ * @param name - the element name
220
+ * @param as - the bson type expected
221
+ * @param required - whether or not the element is expected to exist, if true this function will throw if it is not present
222
+ */
223
+ public get<const T extends keyof JSTypeOf>(
224
+ name: string,
225
+ as: T,
226
+ required?: false | undefined
227
+ ): JSTypeOf[T] | null;
228
+
229
+ /** `required` will make `get` throw if name does not exist or is null/undefined */
230
+ public get<const T extends keyof JSTypeOf>(name: string, as: T, required: true): JSTypeOf[T];
231
+
232
+ public get<const T extends keyof JSTypeOf>(
233
+ name: string,
234
+ as: T,
235
+ required?: boolean
236
+ ): JSTypeOf[T] | null {
237
+ const element = this.getElement(name);
238
+ if (element == null) {
239
+ if (required === true) {
240
+ throw new BSONError(`BSON element "${name}" is missing`);
241
+ } else {
242
+ return null;
243
+ }
244
+ }
245
+
246
+ if (element.value == null) {
247
+ const value = this.toJSValue(element.element, as);
248
+ if (value == null) {
249
+ if (required === true) {
250
+ throw new BSONError(`BSON element "${name}" is missing`);
251
+ } else {
252
+ return null;
253
+ }
254
+ }
255
+ // It is important to never store null
256
+ element.value = value;
257
+ }
258
+
259
+ return element.value;
260
+ }
261
+
262
+ /**
263
+ * Supports returning int, double, long, and bool as javascript numbers
264
+ *
265
+ * @remarks
266
+ * **NOTE:**
267
+ * - Use this _only_ when you believe the potential precision loss of an int64 is acceptable
268
+ * - This method does not cache the result as Longs or booleans would be stored incorrectly
269
+ *
270
+ * @param name - element name
271
+ * @param required - throws if name does not exist
272
+ */
273
+ public getNumber<const Req extends boolean = false>(
274
+ name: string,
275
+ required?: Req
276
+ ): Req extends true ? number : number | null;
277
+ public getNumber(name: string, required: boolean): number | null {
278
+ const maybeBool = this.get(name, BSONType.bool);
279
+ const bool = maybeBool == null ? null : maybeBool ? 1 : 0;
280
+
281
+ const maybeLong = this.get(name, BSONType.long);
282
+ const long = maybeLong == null ? null : Number(maybeLong);
283
+
284
+ const result = bool ?? long ?? this.get(name, BSONType.int) ?? this.get(name, BSONType.double);
285
+
286
+ if (required === true && result == null) {
287
+ throw new BSONError(`BSON element "${name}" is missing`);
288
+ }
289
+
290
+ return result;
291
+ }
292
+
293
+ /**
294
+ * Deserialize this object, DOES NOT cache result so avoid multiple invocations
295
+ * @param options - BSON deserialization options
296
+ */
297
+ public toObject(options?: BSONSerializeOptions): Record<string, any> {
298
+ return BSON.deserialize(this.bson, {
299
+ ...options,
300
+ index: this.offset,
301
+ allowObjectSmallerThanBufferSize: true
302
+ });
303
+ }
304
+
305
+ /**
306
+ * Iterates through the elements of a document reviving them using the `as` BSONType.
307
+ *
308
+ * @param as - The type to revive all elements as
309
+ */
310
+ public *valuesAs<const T extends keyof JSTypeOf>(as: T): Generator<JSTypeOf[T]> {
311
+ if (!this.isArray) {
312
+ throw new BSONError('Unexpected conversion of non-array value to array');
313
+ }
314
+ let counter = 0;
315
+ for (const element of this.elements) {
316
+ const value = this.toJSValue<T>(element, as);
317
+ this.cache[counter] = { element, value };
318
+ yield value;
319
+ counter += 1;
320
+ }
321
+ }
322
+ }