diff --git a/.eslintignore b/.eslintignore index ececb37e..f2aaa561 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,5 @@ dist/ node_modules/ docs/ types/ +lib/ +*.d.ts diff --git a/rollup.config.js b/rollup.config.js index 01edfe57..63fc3b08 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -10,7 +10,7 @@ const tsConfig = { checkJs: false, strict: true, alwaysStrict: true, - target: 'ES2017', + target: 'es5', module: 'commonjs', moduleResolution: 'node', lib: ['ES2017', 'ES2020.BigInt', 'ES2017.TypedArrays'], diff --git a/src/binary.ts b/src/binary.ts index 6fd898b8..1699fb65 100644 --- a/src/binary.ts +++ b/src/binary.ts @@ -50,15 +50,17 @@ export class Binary { /** User BSON type */ static readonly SUBTYPE_USER_DEFINED = 128; - buffer: Buffer; - sub_type: number; - position: number; + buffer!: Buffer; + sub_type!: number; + position!: number; /** * @param buffer - a buffer object containing the binary data. * @param subType - the option binary type. */ constructor(buffer?: string | BinarySequence, subType?: number) { + if (!(this instanceof Binary)) return new Binary(buffer, subType); + if ( !(buffer == null) && !(typeof buffer === 'string') && diff --git a/src/code.ts b/src/code.ts index 603722c8..47d1c851 100644 --- a/src/code.ts +++ b/src/code.ts @@ -13,13 +13,15 @@ export interface CodeExtended { export class Code { _bsontype!: 'Code'; - code: string | Function; + code!: string | Function; scope?: Document; /** * @param code - a string or function. * @param scope - an optional scope for the function. */ constructor(code: string | Function, scope?: Document) { + if (!(this instanceof Code)) return new Code(code, scope); + this.code = code; this.scope = scope; } diff --git a/src/db_ref.ts b/src/db_ref.ts index 7556c9d2..a4a0e51e 100644 --- a/src/db_ref.ts +++ b/src/db_ref.ts @@ -22,10 +22,10 @@ export function isDBRefLike(value: unknown): value is DBRefLike { export class DBRef { _bsontype!: 'DBRef'; - collection: string; - oid: ObjectId; + collection!: string; + oid!: ObjectId; db?: string; - fields: Document; + fields!: Document; /** * @param collection - the collection name. @@ -33,6 +33,8 @@ export class DBRef { * @param db - optional db name, if omitted the reference is local to the current db. */ constructor(collection: string, oid: ObjectId, db?: string, fields?: Document) { + if (!(this instanceof DBRef)) return new DBRef(collection, oid, db, fields); + // check if namespace has been provided const parts = collection.split('.'); if (parts.length === 2) { diff --git a/src/decimal128.ts b/src/decimal128.ts index 8ba4c30d..f798cbf9 100644 --- a/src/decimal128.ts +++ b/src/decimal128.ts @@ -165,10 +165,12 @@ export interface Decimal128Extended { export class Decimal128 { _bsontype!: 'Decimal128'; - readonly bytes: Buffer; + readonly bytes!: Buffer; /** @param bytes - a buffer containing the raw Decimal128 bytes in little endian order */ constructor(bytes: Buffer) { + if (!(this instanceof Decimal128)) return new Decimal128(bytes); + this.bytes = bytes; } diff --git a/src/double.ts b/src/double.ts index becdc9df..f55543cb 100644 --- a/src/double.ts +++ b/src/double.ts @@ -12,13 +12,15 @@ export interface DoubleExtended { export class Double { _bsontype!: 'Double'; - value: number; + value!: number; /** * Create a Double type * * @param value - the number we want to represent as a double. */ constructor(value: number) { + if (!(this instanceof Double)) return new Double(value); + if ((value as unknown) instanceof Number) { value = value.valueOf(); } diff --git a/src/int_32.ts b/src/int_32.ts index b3041530..887def2d 100644 --- a/src/int_32.ts +++ b/src/int_32.ts @@ -12,13 +12,15 @@ export interface Int32Extended { export class Int32 { _bsontype!: 'Int32'; - value: number; + value!: number; /** * Create an Int32 type * * @param value - the number we want to represent as an int32. */ constructor(value: number | string) { + if (!(this instanceof Int32)) return new Int32(value); + if ((value as unknown) instanceof Number) { value = value.valueOf(); } diff --git a/src/long.ts b/src/long.ts index 3887c3c4..afd5005a 100644 --- a/src/long.ts +++ b/src/long.ts @@ -82,17 +82,17 @@ export class Long { /** * The high 32 bits as a signed value. */ - high: number; + high!: number; /** * The low 32 bits as a signed value. */ - low: number; + low!: number; /** * Whether unsigned or not. */ - unsigned: boolean; + unsigned!: boolean; /** * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers. @@ -102,6 +102,8 @@ export class Long { * @param unsigned - Whether unsigned or not, defaults to signed */ constructor(low = 0, high = 0, unsigned?: boolean) { + if (!(this instanceof Long)) return new Long(low, high, unsigned); + this.low = low | 0; this.high = high | 0; this.unsigned = !!unsigned; diff --git a/src/max_key.ts b/src/max_key.ts index 49f8288c..fcfc5bec 100644 --- a/src/max_key.ts +++ b/src/max_key.ts @@ -10,6 +10,10 @@ export interface MaxKeyExtended { export class MaxKey { _bsontype!: 'MaxKey'; + constructor() { + if (!(this instanceof MaxKey)) return new MaxKey(); + } + /** @internal */ toExtendedJSON(): MaxKeyExtended { return { $maxKey: 1 }; diff --git a/src/min_key.ts b/src/min_key.ts index 79ee2091..f1647fcb 100644 --- a/src/min_key.ts +++ b/src/min_key.ts @@ -10,6 +10,10 @@ export interface MinKeyExtended { export class MinKey { _bsontype!: 'MinKey'; + constructor() { + if (!(this instanceof MinKey)) return new MinKey(); + } + /** @internal */ toExtendedJSON(): MinKeyExtended { return { $minKey: 1 }; diff --git a/src/objectid.ts b/src/objectid.ts index 9495bf1e..bdc89ca4 100644 --- a/src/objectid.ts +++ b/src/objectid.ts @@ -57,6 +57,8 @@ export class ObjectId { * @param id - Can be a 24 character hex string, 12 byte binary Buffer, or a number. */ constructor(id?: string | Buffer | number | ObjectIdLike | ObjectId) { + if (!(this instanceof ObjectId)) return new ObjectId(id); + // Duck-typing to support ObjectId from different npm packages if (id instanceof ObjectId) { this[kId] = id.id; diff --git a/src/regexp.ts b/src/regexp.ts index 35f3921e..4225f136 100644 --- a/src/regexp.ts +++ b/src/regexp.ts @@ -25,13 +25,15 @@ export interface BSONRegExpExtended { export class BSONRegExp { _bsontype!: 'BSONRegExp'; - pattern: string; - options: string; + pattern!: string; + options!: string; /** * @param pattern - The regular expression pattern to match * @param options - The regular expression options */ constructor(pattern: string, options?: string) { + if (!(this instanceof BSONRegExp)) return new BSONRegExp(pattern, options); + this.pattern = pattern; this.options = options ?? ''; // Execute diff --git a/src/symbol.ts b/src/symbol.ts index 15d3da8f..8dcb2419 100644 --- a/src/symbol.ts +++ b/src/symbol.ts @@ -10,11 +10,13 @@ export interface BSONSymbolExtended { export class BSONSymbol { _bsontype!: 'Symbol'; - value: string; + value!: string; /** * @param value - the string representing the symbol. */ constructor(value: string) { + if (!(this instanceof BSONSymbol)) return new BSONSymbol(value); + this.value = value; } diff --git a/src/timestamp.ts b/src/timestamp.ts index a280f78c..d20b6b5f 100644 --- a/src/timestamp.ts +++ b/src/timestamp.ts @@ -31,8 +31,13 @@ export class Timestamp extends LongWithoutOverridesClass { * @param low - the low (signed) 32 bits of the Timestamp. * @param high - the high (signed) 32 bits of the Timestamp. */ + constructor(low: Long); constructor(low: number, high: number); constructor(low: number | Long, high?: number) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + ///@ts-expect-error + if (!(this instanceof Timestamp)) return new Timestamp(low, high); + if (Long.isLong(low)) { super(low.low, low.high, true); } else { diff --git a/test/node/bson_types_construction_tests.js b/test/node/bson_types_construction_tests.js new file mode 100644 index 00000000..ad7507ed --- /dev/null +++ b/test/node/bson_types_construction_tests.js @@ -0,0 +1,35 @@ +'use strict'; +const BSON = require('../register-bson'); + +describe('Constructing BSON types', function () { + it('with new keyword should work', function () { + const oid = new BSON.ObjectId(); + new BSON.DBRef('test', oid); + new BSON.BSONRegExp('aaa'); + new BSON.BSONSymbol('aaa'); + new BSON.Binary('aaa'); + new BSON.Code(function () {}); + new BSON.Decimal128('aaa'); + new BSON.Double(2.3); + new BSON.Int32(1); + new BSON.Long(0, 0); + new BSON.Timestamp(0, 0); + new BSON.MaxKey(); + new BSON.MinKey(); + }); + it('as a function call should work', function () { + const oid = BSON.ObjectId(); + BSON.DBRef('test', oid); + BSON.BSONRegExp('aaa'); + BSON.BSONSymbol('aaa'); + BSON.Binary('aaa'); + BSON.Code(function () {}); + BSON.Decimal128('aaa'); + BSON.Double(2.3); + BSON.Int32(1); + BSON.Long(0, 0); + BSON.Timestamp(0, 0); + BSON.MaxKey(); + BSON.MinKey(); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index a03db31b..096316bd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ "checkJs": false, "strict": true, "alwaysStrict": true, - "target": "ES2017", + "target": "es5", "module": "commonjs", "moduleResolution": "node", "lib": [