bson 4.7.0 → 5.0.0-alpha.1
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/bson.d.ts +207 -259
- package/lib/bson.bundle.js +4034 -0
- package/lib/bson.bundle.js.map +1 -0
- package/lib/bson.cjs +4029 -0
- package/lib/bson.cjs.map +1 -0
- package/lib/bson.mjs +4003 -0
- package/lib/bson.mjs.map +1 -0
- package/package.json +49 -62
- package/src/binary.ts +64 -53
- package/src/bson.ts +27 -108
- package/src/code.ts +25 -14
- package/src/constants.ts +33 -0
- package/src/db_ref.ts +14 -8
- package/src/decimal128.ts +32 -25
- package/src/double.ts +8 -5
- package/src/error.ts +0 -2
- package/src/extended_json.ts +148 -148
- package/src/index.ts +19 -0
- package/src/int_32.ts +8 -5
- package/src/long.ts +17 -16
- package/src/max_key.ts +8 -6
- package/src/min_key.ts +8 -6
- package/src/objectid.ts +42 -74
- package/src/parser/calculate_size.ts +39 -63
- package/src/parser/deserializer.ts +41 -112
- package/src/parser/serializer.ts +234 -341
- package/src/parser/utils.ts +1 -99
- package/src/regexp.ts +17 -5
- package/src/symbol.ts +9 -5
- package/src/timestamp.ts +63 -27
- package/src/utils/byte_utils.ts +61 -0
- package/src/utils/node_byte_utils.ts +141 -0
- package/src/utils/web_byte_utils.ts +190 -0
- package/src/uuid_utils.ts +15 -15
- package/bower.json +0 -26
- package/dist/bson.browser.esm.js +0 -7470
- package/dist/bson.browser.esm.js.map +0 -1
- package/dist/bson.browser.umd.js +0 -7537
- package/dist/bson.browser.umd.js.map +0 -1
- package/dist/bson.bundle.js +0 -7536
- package/dist/bson.bundle.js.map +0 -1
- package/dist/bson.esm.js +0 -5436
- package/dist/bson.esm.js.map +0 -1
- package/lib/binary.js +0 -426
- package/lib/binary.js.map +0 -1
- package/lib/bson.js +0 -251
- package/lib/bson.js.map +0 -1
- package/lib/code.js +0 -46
- package/lib/code.js.map +0 -1
- package/lib/constants.js +0 -82
- package/lib/constants.js.map +0 -1
- package/lib/db_ref.js +0 -97
- package/lib/db_ref.js.map +0 -1
- package/lib/decimal128.js +0 -669
- package/lib/decimal128.js.map +0 -1
- package/lib/double.js +0 -76
- package/lib/double.js.map +0 -1
- package/lib/ensure_buffer.js +0 -25
- package/lib/ensure_buffer.js.map +0 -1
- package/lib/error.js +0 -55
- package/lib/error.js.map +0 -1
- package/lib/extended_json.js +0 -390
- package/lib/extended_json.js.map +0 -1
- package/lib/int_32.js +0 -58
- package/lib/int_32.js.map +0 -1
- package/lib/long.js +0 -900
- package/lib/long.js.map +0 -1
- package/lib/map.js +0 -123
- package/lib/map.js.map +0 -1
- package/lib/max_key.js +0 -33
- package/lib/max_key.js.map +0 -1
- package/lib/min_key.js +0 -33
- package/lib/min_key.js.map +0 -1
- package/lib/objectid.js +0 -299
- package/lib/objectid.js.map +0 -1
- package/lib/parser/calculate_size.js +0 -194
- package/lib/parser/calculate_size.js.map +0 -1
- package/lib/parser/deserializer.js +0 -665
- package/lib/parser/deserializer.js.map +0 -1
- package/lib/parser/serializer.js +0 -867
- package/lib/parser/serializer.js.map +0 -1
- package/lib/parser/utils.js +0 -115
- package/lib/parser/utils.js.map +0 -1
- package/lib/regexp.js +0 -74
- package/lib/regexp.js.map +0 -1
- package/lib/symbol.js +0 -48
- package/lib/symbol.js.map +0 -1
- package/lib/timestamp.js +0 -102
- package/lib/timestamp.js.map +0 -1
- package/lib/utils/global.js +0 -18
- package/lib/utils/global.js.map +0 -1
- package/lib/uuid_utils.js +0 -35
- package/lib/uuid_utils.js.map +0 -1
- package/lib/validate_utf8.js +0 -47
- package/lib/validate_utf8.js.map +0 -1
- package/src/ensure_buffer.ts +0 -27
- package/src/map.ts +0 -119
- package/src/utils/global.ts +0 -22
package/src/parser/utils.ts
CHANGED
|
@@ -1,73 +1,3 @@
|
|
|
1
|
-
import { Buffer } from 'buffer';
|
|
2
|
-
import { getGlobal } from '../utils/global';
|
|
3
|
-
|
|
4
|
-
type RandomBytesFunction = (size: number) => Uint8Array;
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Normalizes our expected stringified form of a function across versions of node
|
|
8
|
-
* @param fn - The function to stringify
|
|
9
|
-
*/
|
|
10
|
-
export function normalizedFunctionString(fn: Function): string {
|
|
11
|
-
return fn.toString().replace('function(', 'function (');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function isReactNative() {
|
|
15
|
-
const g = getGlobal<{ navigator?: { product?: string } }>();
|
|
16
|
-
return typeof g.navigator === 'object' && g.navigator.product === 'ReactNative';
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const insecureRandomBytes: RandomBytesFunction = function insecureRandomBytes(size: number) {
|
|
20
|
-
const insecureWarning = isReactNative()
|
|
21
|
-
? 'BSON: For React Native please polyfill crypto.getRandomValues, e.g. using: https://www.npmjs.com/package/react-native-get-random-values.'
|
|
22
|
-
: 'BSON: No cryptographic implementation for random bytes present, falling back to a less secure implementation.';
|
|
23
|
-
console.warn(insecureWarning);
|
|
24
|
-
|
|
25
|
-
const result = Buffer.alloc(size);
|
|
26
|
-
for (let i = 0; i < size; ++i) result[i] = Math.floor(Math.random() * 256);
|
|
27
|
-
return result;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/* We do not want to have to include DOM types just for this check */
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
-
declare let window: any;
|
|
33
|
-
declare let require: Function;
|
|
34
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
|
-
declare let global: any;
|
|
36
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
|
-
declare let process: any; // Used by @rollup/plugin-replace
|
|
38
|
-
|
|
39
|
-
const detectRandomBytes = (): RandomBytesFunction => {
|
|
40
|
-
if (process.browser) {
|
|
41
|
-
if (typeof window !== 'undefined') {
|
|
42
|
-
// browser crypto implementation(s)
|
|
43
|
-
const target = window.crypto || window.msCrypto; // allow for IE11
|
|
44
|
-
if (target && target.getRandomValues) {
|
|
45
|
-
return size => target.getRandomValues(Buffer.alloc(size));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (typeof global !== 'undefined' && global.crypto && global.crypto.getRandomValues) {
|
|
50
|
-
// allow for RN packages such as https://www.npmjs.com/package/react-native-get-random-values to populate global
|
|
51
|
-
return size => global.crypto.getRandomValues(Buffer.alloc(size));
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return insecureRandomBytes;
|
|
55
|
-
} else {
|
|
56
|
-
let requiredRandomBytes: RandomBytesFunction | null | undefined;
|
|
57
|
-
try {
|
|
58
|
-
requiredRandomBytes = require('crypto').randomBytes;
|
|
59
|
-
} catch (e) {
|
|
60
|
-
// keep the fallback
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// NOTE: in transpiled cases the above require might return null/undefined
|
|
64
|
-
|
|
65
|
-
return requiredRandomBytes || insecureRandomBytes;
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export const randomBytes = detectRandomBytes();
|
|
70
|
-
|
|
71
1
|
export function isAnyArrayBuffer(value: unknown): value is ArrayBuffer {
|
|
72
2
|
return ['[object ArrayBuffer]', '[object SharedArrayBuffer]'].includes(
|
|
73
3
|
Object.prototype.toString.call(value)
|
|
@@ -94,34 +24,6 @@ export function isMap(d: unknown): d is Map<unknown, unknown> {
|
|
|
94
24
|
return Object.prototype.toString.call(d) === '[object Map]';
|
|
95
25
|
}
|
|
96
26
|
|
|
97
|
-
/** Call to check if your environment has `Buffer` */
|
|
98
|
-
export function haveBuffer(): boolean {
|
|
99
|
-
return typeof global !== 'undefined' && typeof global.Buffer !== 'undefined';
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// To ensure that 0.4 of node works correctly
|
|
103
27
|
export function isDate(d: unknown): d is Date {
|
|
104
|
-
return
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* @internal
|
|
109
|
-
* this is to solve the `'someKey' in x` problem where x is unknown.
|
|
110
|
-
* https://github.com/typescript-eslint/typescript-eslint/issues/1071#issuecomment-541955753
|
|
111
|
-
*/
|
|
112
|
-
export function isObjectLike(candidate: unknown): candidate is Record<string, unknown> {
|
|
113
|
-
return typeof candidate === 'object' && candidate !== null;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
declare let console: { warn(...message: unknown[]): void };
|
|
117
|
-
export function deprecate<T extends Function>(fn: T, message: string): T {
|
|
118
|
-
let warned = false;
|
|
119
|
-
function deprecated(this: unknown, ...args: unknown[]) {
|
|
120
|
-
if (!warned) {
|
|
121
|
-
console.warn(message);
|
|
122
|
-
warned = true;
|
|
123
|
-
}
|
|
124
|
-
return fn.apply(this, args);
|
|
125
|
-
}
|
|
126
|
-
return deprecated as unknown as T;
|
|
28
|
+
return Object.prototype.toString.call(d) === '[object Date]';
|
|
127
29
|
}
|
package/src/regexp.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BSON_MAJOR_VERSION } from './constants';
|
|
1
2
|
import { BSONError, BSONTypeError } from './error';
|
|
2
3
|
import type { EJSONOptions } from './extended_json';
|
|
3
4
|
|
|
@@ -25,7 +26,13 @@ export interface BSONRegExpExtended {
|
|
|
25
26
|
* @category BSONType
|
|
26
27
|
*/
|
|
27
28
|
export class BSONRegExp {
|
|
28
|
-
_bsontype
|
|
29
|
+
get _bsontype(): 'BSONRegExp' {
|
|
30
|
+
return 'BSONRegExp';
|
|
31
|
+
}
|
|
32
|
+
/** @internal */
|
|
33
|
+
get [Symbol.for('@@mdb.bson.version')](): BSON_MAJOR_VERSION {
|
|
34
|
+
return BSON_MAJOR_VERSION;
|
|
35
|
+
}
|
|
29
36
|
|
|
30
37
|
pattern!: string;
|
|
31
38
|
options!: string;
|
|
@@ -34,8 +41,6 @@ export class BSONRegExp {
|
|
|
34
41
|
* @param options - The regular expression options
|
|
35
42
|
*/
|
|
36
43
|
constructor(pattern: string, options?: string) {
|
|
37
|
-
if (!(this instanceof BSONRegExp)) return new BSONRegExp(pattern, options);
|
|
38
|
-
|
|
39
44
|
this.pattern = pattern;
|
|
40
45
|
this.options = alphabetize(options ?? '');
|
|
41
46
|
|
|
@@ -100,6 +105,13 @@ export class BSONRegExp {
|
|
|
100
105
|
}
|
|
101
106
|
throw new BSONTypeError(`Unexpected BSONRegExp EJSON object form: ${JSON.stringify(doc)}`);
|
|
102
107
|
}
|
|
103
|
-
}
|
|
104
108
|
|
|
105
|
-
|
|
109
|
+
/** @internal */
|
|
110
|
+
[Symbol.for('nodejs.util.inspect.custom')](): string {
|
|
111
|
+
return this.inspect();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
inspect(): string {
|
|
115
|
+
return `new BSONRegExp(${JSON.stringify(this.pattern)}, ${JSON.stringify(this.options)})`;
|
|
116
|
+
}
|
|
117
|
+
}
|
package/src/symbol.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { BSON_MAJOR_VERSION } from './constants';
|
|
2
|
+
|
|
1
3
|
/** @public */
|
|
2
4
|
export interface BSONSymbolExtended {
|
|
3
5
|
$symbol: string;
|
|
@@ -9,15 +11,19 @@ export interface BSONSymbolExtended {
|
|
|
9
11
|
* @category BSONType
|
|
10
12
|
*/
|
|
11
13
|
export class BSONSymbol {
|
|
12
|
-
_bsontype
|
|
14
|
+
get _bsontype(): 'BSONSymbol' {
|
|
15
|
+
return 'BSONSymbol';
|
|
16
|
+
}
|
|
17
|
+
/** @internal */
|
|
18
|
+
get [Symbol.for('@@mdb.bson.version')](): BSON_MAJOR_VERSION {
|
|
19
|
+
return BSON_MAJOR_VERSION;
|
|
20
|
+
}
|
|
13
21
|
|
|
14
22
|
value!: string;
|
|
15
23
|
/**
|
|
16
24
|
* @param value - the string representing the symbol.
|
|
17
25
|
*/
|
|
18
26
|
constructor(value: string) {
|
|
19
|
-
if (!(this instanceof BSONSymbol)) return new BSONSymbol(value);
|
|
20
|
-
|
|
21
27
|
this.value = value;
|
|
22
28
|
}
|
|
23
29
|
|
|
@@ -54,5 +60,3 @@ export class BSONSymbol {
|
|
|
54
60
|
return this.inspect();
|
|
55
61
|
}
|
|
56
62
|
}
|
|
57
|
-
|
|
58
|
-
Object.defineProperty(BSONSymbol.prototype, '_bsontype', { value: 'Symbol' });
|
package/src/timestamp.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import { BSON_MAJOR_VERSION } from './constants';
|
|
2
|
+
import { BSONError } from './error';
|
|
3
|
+
import type { Int32 } from './int_32';
|
|
1
4
|
import { Long } from './long';
|
|
2
|
-
import { isObjectLike } from './parser/utils';
|
|
3
5
|
|
|
4
6
|
/** @public */
|
|
5
7
|
export type TimestampOverrides = '_bsontype' | 'toExtendedJSON' | 'fromExtendedJSON' | 'inspect';
|
|
6
8
|
/** @public */
|
|
7
|
-
export type LongWithoutOverrides = new (
|
|
9
|
+
export type LongWithoutOverrides = new (
|
|
10
|
+
low: unknown,
|
|
11
|
+
high?: number | boolean,
|
|
12
|
+
unsigned?: boolean
|
|
13
|
+
) => {
|
|
8
14
|
[P in Exclude<keyof Long, TimestampOverrides>]: Long[P];
|
|
9
15
|
};
|
|
10
16
|
/** @public */
|
|
@@ -24,42 +30,65 @@ export interface TimestampExtended {
|
|
|
24
30
|
* @category BSONType
|
|
25
31
|
* */
|
|
26
32
|
export class Timestamp extends LongWithoutOverridesClass {
|
|
27
|
-
_bsontype
|
|
33
|
+
get _bsontype(): 'Timestamp' {
|
|
34
|
+
return 'Timestamp';
|
|
35
|
+
}
|
|
36
|
+
/** @internal */
|
|
37
|
+
get [Symbol.for('@@mdb.bson.version')](): BSON_MAJOR_VERSION {
|
|
38
|
+
return BSON_MAJOR_VERSION;
|
|
39
|
+
}
|
|
28
40
|
|
|
29
41
|
static readonly MAX_VALUE = Long.MAX_UNSIGNED_VALUE;
|
|
30
42
|
|
|
31
43
|
/**
|
|
32
|
-
* @param
|
|
44
|
+
* @param int - A 64-bit bigint representing the Timestamp.
|
|
45
|
+
*/
|
|
46
|
+
constructor(int: bigint);
|
|
47
|
+
/**
|
|
48
|
+
* @param long - A 64-bit Long representing the Timestamp.
|
|
33
49
|
*/
|
|
34
50
|
constructor(long: Long);
|
|
35
51
|
/**
|
|
36
52
|
* @param value - A pair of two values indicating timestamp and increment.
|
|
37
53
|
*/
|
|
38
54
|
constructor(value: { t: number; i: number });
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
constructor(low: number | Long | { t: number; i: number }, high?: number) {
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
47
|
-
// @ts-expect-error
|
|
48
|
-
if (!(this instanceof Timestamp)) return new Timestamp(low, high);
|
|
49
|
-
|
|
50
|
-
if (Long.isLong(low)) {
|
|
55
|
+
constructor(low?: bigint | Long | { t: number | Int32; i: number | Int32 }) {
|
|
56
|
+
if (low == null) {
|
|
57
|
+
super(0, 0, true);
|
|
58
|
+
} else if (typeof low === 'bigint') {
|
|
59
|
+
super(low, true);
|
|
60
|
+
} else if (Long.isLong(low)) {
|
|
51
61
|
super(low.low, low.high, true);
|
|
52
|
-
} else if (
|
|
53
|
-
|
|
62
|
+
} else if (typeof low === 'object' && 't' in low && 'i' in low) {
|
|
63
|
+
if (typeof low.t !== 'number' && (typeof low.t !== 'object' || low.t._bsontype !== 'Int32')) {
|
|
64
|
+
throw new BSONError('Timestamp constructed from { t, i } must provide t as a number');
|
|
65
|
+
}
|
|
66
|
+
if (typeof low.i !== 'number' && (typeof low.i !== 'object' || low.i._bsontype !== 'Int32')) {
|
|
67
|
+
throw new BSONError('Timestamp constructed from { t, i } must provide i as a number');
|
|
68
|
+
}
|
|
69
|
+
if (low.t < 0) {
|
|
70
|
+
throw new BSONError('Timestamp constructed from { t, i } must provide a positive t');
|
|
71
|
+
}
|
|
72
|
+
if (low.i < 0) {
|
|
73
|
+
throw new BSONError('Timestamp constructed from { t, i } must provide a positive i');
|
|
74
|
+
}
|
|
75
|
+
if (low.t > 0xffff_ffff) {
|
|
76
|
+
throw new BSONError(
|
|
77
|
+
'Timestamp constructed from { t, i } must provide t equal or less than uint32 max'
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
if (low.i > 0xffff_ffff) {
|
|
81
|
+
throw new BSONError(
|
|
82
|
+
'Timestamp constructed from { t, i } must provide i equal or less than uint32 max'
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
super(low.i.valueOf(), low.t.valueOf(), true);
|
|
54
87
|
} else {
|
|
55
|
-
|
|
88
|
+
throw new BSONError(
|
|
89
|
+
'A Timestamp can only be constructed with: bigint, Long, or { t: number; i: number }'
|
|
90
|
+
);
|
|
56
91
|
}
|
|
57
|
-
Object.defineProperty(this, '_bsontype', {
|
|
58
|
-
value: 'Timestamp',
|
|
59
|
-
writable: false,
|
|
60
|
-
configurable: false,
|
|
61
|
-
enumerable: false
|
|
62
|
-
});
|
|
63
92
|
}
|
|
64
93
|
|
|
65
94
|
toJSON(): { $timestamp: string } {
|
|
@@ -85,7 +114,7 @@ export class Timestamp extends LongWithoutOverridesClass {
|
|
|
85
114
|
* @param highBits - the high 32-bits.
|
|
86
115
|
*/
|
|
87
116
|
static fromBits(lowBits: number, highBits: number): Timestamp {
|
|
88
|
-
return new Timestamp(lowBits, highBits);
|
|
117
|
+
return new Timestamp({ i: lowBits, t: highBits });
|
|
89
118
|
}
|
|
90
119
|
|
|
91
120
|
/**
|
|
@@ -105,7 +134,14 @@ export class Timestamp extends LongWithoutOverridesClass {
|
|
|
105
134
|
|
|
106
135
|
/** @internal */
|
|
107
136
|
static fromExtendedJSON(doc: TimestampExtended): Timestamp {
|
|
108
|
-
|
|
137
|
+
// The Long check is necessary because extended JSON has different behavior given the size of the input number
|
|
138
|
+
const i = Long.isLong(doc.$timestamp.i)
|
|
139
|
+
? doc.$timestamp.i.getLowBitsUnsigned() // Need to fetch the least significant 32 bits
|
|
140
|
+
: doc.$timestamp.i;
|
|
141
|
+
const t = Long.isLong(doc.$timestamp.t)
|
|
142
|
+
? doc.$timestamp.t.getLowBitsUnsigned() // Need to fetch the least significant 32 bits
|
|
143
|
+
: doc.$timestamp.t;
|
|
144
|
+
return new Timestamp({ t, i });
|
|
109
145
|
}
|
|
110
146
|
|
|
111
147
|
/** @internal */
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { nodeJsByteUtils } from './node_byte_utils';
|
|
2
|
+
import { webByteUtils } from './web_byte_utils';
|
|
3
|
+
|
|
4
|
+
/** @internal */
|
|
5
|
+
export type ByteUtils = {
|
|
6
|
+
/** Transforms the input to an instance of Buffer if running on node, otherwise Uint8Array */
|
|
7
|
+
toLocalBufferType(buffer: Uint8Array | ArrayBufferView | ArrayBuffer): Uint8Array;
|
|
8
|
+
/** Create empty space of size */
|
|
9
|
+
allocate: (size: number) => Uint8Array;
|
|
10
|
+
/** Check if two Uint8Arrays are deep equal */
|
|
11
|
+
equals: (a: Uint8Array, b: Uint8Array) => boolean;
|
|
12
|
+
/** Check if two Uint8Arrays are deep equal */
|
|
13
|
+
fromNumberArray: (array: number[]) => Uint8Array;
|
|
14
|
+
/** Create a Uint8Array from a base64 string */
|
|
15
|
+
fromBase64: (base64: string) => Uint8Array;
|
|
16
|
+
/** Create a base64 string from bytes */
|
|
17
|
+
toBase64: (buffer: Uint8Array) => string;
|
|
18
|
+
/** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
|
|
19
|
+
fromISO88591: (codePoints: string) => Uint8Array;
|
|
20
|
+
/** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
|
|
21
|
+
toISO88591: (buffer: Uint8Array) => string;
|
|
22
|
+
/** Create a Uint8Array from a hex string */
|
|
23
|
+
fromHex: (hex: string) => Uint8Array;
|
|
24
|
+
/** Create a hex string from bytes */
|
|
25
|
+
toHex: (buffer: Uint8Array) => string;
|
|
26
|
+
/** Create a Uint8Array containing utf8 code units from a string */
|
|
27
|
+
fromUTF8: (text: string) => Uint8Array;
|
|
28
|
+
/** Create a string from utf8 code units */
|
|
29
|
+
toUTF8: (buffer: Uint8Array) => string;
|
|
30
|
+
/** Get the utf8 code unit count from a string if it were to be transformed to utf8 */
|
|
31
|
+
utf8ByteLength: (input: string) => number;
|
|
32
|
+
/** Encode UTF8 bytes generated from `source` string into `destination` at byteOffset. Returns the number of bytes encoded. */
|
|
33
|
+
encodeUTF8Into(destination: Uint8Array, source: string, byteOffset: number): number;
|
|
34
|
+
/** Generate a Uint8Array filled with random bytes with byteLength */
|
|
35
|
+
randomBytes(byteLength: number): Uint8Array;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
declare const Buffer: { new (): unknown; prototype?: { _isBuffer?: boolean } } | undefined;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Check that a global Buffer exists that is a function and
|
|
42
|
+
* does not have a '_isBuffer' property defined on the prototype
|
|
43
|
+
* (this is to prevent using the npm buffer)
|
|
44
|
+
*/
|
|
45
|
+
const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuffer !== true;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* This is the only ByteUtils that should be used across the rest of the BSON library.
|
|
49
|
+
*
|
|
50
|
+
* The type annotation is important here, it asserts that each of the platform specific
|
|
51
|
+
* utils implementations are compatible with the common one.
|
|
52
|
+
*
|
|
53
|
+
* @internal
|
|
54
|
+
*/
|
|
55
|
+
export const ByteUtils: ByteUtils = hasGlobalBuffer ? nodeJsByteUtils : webByteUtils;
|
|
56
|
+
|
|
57
|
+
export class BSONDataView extends DataView {
|
|
58
|
+
static fromUint8Array(input: Uint8Array) {
|
|
59
|
+
return new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { BSONError } from '../error';
|
|
2
|
+
|
|
3
|
+
type NodeJsEncoding = 'base64' | 'hex' | 'utf8' | 'binary';
|
|
4
|
+
type NodeJsBuffer = ArrayBufferView &
|
|
5
|
+
Uint8Array & {
|
|
6
|
+
write(string: string, offset: number, length: undefined, encoding: 'utf8'): number;
|
|
7
|
+
copy(target: Uint8Array, targetStart: number, sourceStart: number, sourceEnd: number): number;
|
|
8
|
+
toString: (this: Uint8Array, encoding: NodeJsEncoding) => string;
|
|
9
|
+
equals: (this: Uint8Array, other: Uint8Array) => boolean;
|
|
10
|
+
};
|
|
11
|
+
type NodeJsBufferConstructor = Omit<Uint8ArrayConstructor, 'from'> & {
|
|
12
|
+
alloc: (size: number) => NodeJsBuffer;
|
|
13
|
+
from(array: number[]): NodeJsBuffer;
|
|
14
|
+
from(array: Uint8Array): NodeJsBuffer;
|
|
15
|
+
from(array: ArrayBuffer): NodeJsBuffer;
|
|
16
|
+
from(array: ArrayBuffer, byteOffset: number, byteLength: number): NodeJsBuffer;
|
|
17
|
+
from(base64: string, encoding: NodeJsEncoding): NodeJsBuffer;
|
|
18
|
+
byteLength(input: string, encoding: 'utf8'): number;
|
|
19
|
+
isBuffer(value: unknown): value is NodeJsBuffer;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// This can be nullish, but we gate the nodejs functions on being exported whether or not this exists
|
|
23
|
+
// Node.js global
|
|
24
|
+
declare const Buffer: NodeJsBufferConstructor;
|
|
25
|
+
declare const require: (mod: 'node:crypto') => { randomBytes: (byteLength: number) => Uint8Array };
|
|
26
|
+
|
|
27
|
+
/** @internal */
|
|
28
|
+
export function nodejsMathRandomBytes(byteLength: number) {
|
|
29
|
+
return nodeJsByteUtils.fromNumberArray(
|
|
30
|
+
Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256))
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @internal
|
|
36
|
+
* WARNING: REQUIRE WILL BE REWRITTEN
|
|
37
|
+
*
|
|
38
|
+
* This code is carefully used by require_rewriter.mjs any modifications must be reflected in the plugin.
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* "crypto" is the only dependency BSON needs. This presents a problem for creating a bundle of the BSON library
|
|
42
|
+
* in an es module format that can be used both on the browser and in Node.js. In Node.js when BSON is imported as
|
|
43
|
+
* an es module, there will be no global require function defined, making the code below fallback to the much less desireable math.random bytes.
|
|
44
|
+
* In order to make our es module bundle work as expected on Node.js we need to change this `require()` to a dynamic import, and the dynamic
|
|
45
|
+
* import must be top-level awaited since es modules are async. So we rely on a custom rollup plugin to seek out the following lines of code
|
|
46
|
+
* and replace `require` with `await import` and the IIFE line (`nodejsRandomBytes = (() => { ... })()`) with `nodejsRandomBytes = await (async () => { ... })()`
|
|
47
|
+
* when generating an es module bundle.
|
|
48
|
+
*/
|
|
49
|
+
const nodejsRandomBytes: (byteLength: number) => Uint8Array = (() => {
|
|
50
|
+
try {
|
|
51
|
+
return require('node:crypto').randomBytes;
|
|
52
|
+
} catch {
|
|
53
|
+
return nodejsMathRandomBytes;
|
|
54
|
+
}
|
|
55
|
+
})();
|
|
56
|
+
|
|
57
|
+
/** @internal */
|
|
58
|
+
export const nodeJsByteUtils = {
|
|
59
|
+
toLocalBufferType(potentialBuffer: Uint8Array | NodeJsBuffer | ArrayBuffer): NodeJsBuffer {
|
|
60
|
+
if (Buffer.isBuffer(potentialBuffer)) {
|
|
61
|
+
return potentialBuffer;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (ArrayBuffer.isView(potentialBuffer)) {
|
|
65
|
+
return Buffer.from(
|
|
66
|
+
potentialBuffer.buffer,
|
|
67
|
+
potentialBuffer.byteOffset,
|
|
68
|
+
potentialBuffer.byteLength
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const stringTag =
|
|
73
|
+
potentialBuffer?.[Symbol.toStringTag] ?? Object.prototype.toString.call(potentialBuffer);
|
|
74
|
+
if (
|
|
75
|
+
stringTag === 'ArrayBuffer' ||
|
|
76
|
+
stringTag === 'SharedArrayBuffer' ||
|
|
77
|
+
stringTag === '[object ArrayBuffer]' ||
|
|
78
|
+
stringTag === '[object SharedArrayBuffer]'
|
|
79
|
+
) {
|
|
80
|
+
return Buffer.from(potentialBuffer);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
throw new BSONError(`Cannot create Buffer from ${String(potentialBuffer)}`);
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
allocate(size: number): NodeJsBuffer {
|
|
87
|
+
return Buffer.alloc(size);
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
equals(a: Uint8Array, b: Uint8Array): boolean {
|
|
91
|
+
return nodeJsByteUtils.toLocalBufferType(a).equals(b);
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
fromNumberArray(array: number[]): NodeJsBuffer {
|
|
95
|
+
return Buffer.from(array);
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
fromBase64(base64: string): NodeJsBuffer {
|
|
99
|
+
return Buffer.from(base64, 'base64');
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
toBase64(buffer: Uint8Array): string {
|
|
103
|
+
return nodeJsByteUtils.toLocalBufferType(buffer).toString('base64');
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
/** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
|
|
107
|
+
fromISO88591(codePoints: string): NodeJsBuffer {
|
|
108
|
+
return Buffer.from(codePoints, 'binary');
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
/** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
|
|
112
|
+
toISO88591(buffer: Uint8Array): string {
|
|
113
|
+
return nodeJsByteUtils.toLocalBufferType(buffer).toString('binary');
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
fromHex(hex: string): NodeJsBuffer {
|
|
117
|
+
return Buffer.from(hex, 'hex');
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
toHex(buffer: Uint8Array): string {
|
|
121
|
+
return nodeJsByteUtils.toLocalBufferType(buffer).toString('hex');
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
fromUTF8(text: string): NodeJsBuffer {
|
|
125
|
+
return Buffer.from(text, 'utf8');
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
toUTF8(buffer: Uint8Array): string {
|
|
129
|
+
return nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8');
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
utf8ByteLength(input: string): number {
|
|
133
|
+
return Buffer.byteLength(input, 'utf8');
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
encodeUTF8Into(buffer: Uint8Array, source: string, byteOffset: number): number {
|
|
137
|
+
return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
randomBytes: nodejsRandomBytes
|
|
141
|
+
};
|