Skip to content

Commit 6d8a0f2

Browse files
authored
Merge pull request #15054 from mongodb-js/NODE-6503/int32-schemaType
feat(NODE-6503): Add Int32 to SchemaType
2 parents e927dd2 + 9dcada3 commit 6d8a0f2

File tree

13 files changed

+923
-30
lines changed

13 files changed

+923
-30
lines changed

docs/guide.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ The permitted SchemaTypes are:
8080
* [Decimal128](api/mongoose.html#mongoose_Mongoose-Decimal128)
8181
* [Map](schematypes.html#maps)
8282
* [UUID](schematypes.html#uuid)
83+
* [Int32](schematypes.html#int32)
8384

8485
Read more about [SchemaTypes here](schematypes.html).
8586

docs/schematypes.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Check out [Mongoose's plugins search](http://plugins.mongoosejs.io) to find plug
5555
* [Schema](#schemas)
5656
* [UUID](#uuid)
5757
* [BigInt](#bigint)
58+
* [Int32](#int32)
5859

5960
### Example
6061

@@ -68,6 +69,7 @@ const schema = new Schema({
6869
mixed: Schema.Types.Mixed,
6970
_someId: Schema.Types.ObjectId,
7071
decimal: Schema.Types.Decimal128,
72+
int32bit: Schema.Types.Int32,
7173
array: [],
7274
ofString: [String],
7375
ofNumber: [Number],
@@ -647,6 +649,44 @@ const question = new Question({ answer: 42n });
647649
typeof question.answer; // 'bigint'
648650
```
649651

652+
### Int32 {#int32}
653+
654+
Mongoose supports 32-bit integers as a SchemaType.
655+
Int32s are stored as [32-bit integers in MongoDB (BSON type "int")](https://www.mongodb.com/docs/manual/reference/bson-types/).
656+
657+
```javascript
658+
const studentsSchema = new Schema({
659+
id: Int32
660+
});
661+
const Student = mongoose.model('Student', schema);
662+
663+
const student = new Student({ id: 1339 });
664+
typeof student.id; // 'number'
665+
```
666+
667+
There are several types of values that will be successfully cast to a Number.
668+
669+
```javascript
670+
new Student({ id: '15' }).id; // 15 as a Int32
671+
new Student({ id: true }).id; // 1 as a Int32
672+
new Student({ id: false }).id; // 0 as a Int32
673+
new Student({ id: { valueOf: () => 83 } }).id; // 83 as a Int32
674+
new Student({ id: '' }).id; // null as a Int32
675+
```
676+
677+
If you pass an object with a `valueOf()` function that returns a Number, Mongoose will
678+
call it and assign the returned value to the path.
679+
680+
The values `null` and `undefined` are not cast.
681+
682+
The following inputs will result will all result in a [CastError](validation.html#cast-errors) once validated, meaning that it will not throw on initialization, only when validated:
683+
684+
* NaN
685+
* strings that cast to NaN
686+
* objects that don't have a `valueOf()` function
687+
* a decimal that must be rounded to be an integer
688+
* an input that represents a value outside the bounds of an 32-bit integer
689+
650690
## Getters {#getters}
651691

652692
Getters are like virtuals for paths defined in your schema. For example,

lib/cast/int32.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
3+
const isBsonType = require('../helpers/isBsonType');
4+
const assert = require('assert');
5+
6+
/**
7+
* Given a value, cast it to a Int32, or throw an `Error` if the value
8+
* cannot be casted. `null` and `undefined` are considered valid.
9+
*
10+
* @param {Any} value
11+
* @return {Number}
12+
* @throws {Error} if `value` does not represent an integer, or is outside the bounds of an 32-bit integer.
13+
* @api private
14+
*/
15+
16+
module.exports = function castInt32(val) {
17+
if (val == null) {
18+
return val;
19+
}
20+
if (val === '') {
21+
return null;
22+
}
23+
24+
const coercedVal = isBsonType(val, 'Long') ? val.toNumber() : Number(val);
25+
26+
const INT32_MAX = 0x7FFFFFFF;
27+
const INT32_MIN = -0x80000000;
28+
29+
if (coercedVal === (coercedVal | 0) &&
30+
coercedVal >= INT32_MIN &&
31+
coercedVal <= INT32_MAX
32+
) {
33+
return coercedVal;
34+
}
35+
assert.ok(false);
36+
};

lib/mongoose.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,7 @@ Mongoose.prototype.VirtualType = VirtualType;
987987
* - [ObjectId](https://mongoosejs.com/docs/schematypes.html#objectids)
988988
* - [Map](https://mongoosejs.com/docs/schematypes.html#maps)
989989
* - [Subdocument](https://mongoosejs.com/docs/schematypes.html#schemas)
990+
* - [Int32](https://mongoosejs.com/docs/schematypes.html#int32)
990991
*
991992
* Using this exposed access to the `ObjectId` type, we can construct ids on demand.
992993
*
@@ -1138,6 +1139,7 @@ Mongoose.prototype.syncIndexes = function(options) {
11381139

11391140
Mongoose.prototype.Decimal128 = SchemaTypes.Decimal128;
11401141

1142+
11411143
/**
11421144
* The Mongoose Mixed [SchemaType](https://mongoosejs.com/docs/schematypes.html). Used for
11431145
* declaring paths in your schema that Mongoose's change tracking, casting,

lib/schema.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2892,6 +2892,7 @@ module.exports = exports = Schema;
28922892
* - [Mixed](https://mongoosejs.com/docs/schematypes.html#mixed)
28932893
* - [UUID](https://mongoosejs.com/docs/schematypes.html#uuid)
28942894
* - [BigInt](https://mongoosejs.com/docs/schematypes.html#bigint)
2895+
* - [Int32](https://mongoosejs.com/docs/schematypes.html#int32)
28952896
*
28962897
* Using this exposed access to the `Mixed` SchemaType, we can use them in our schema.
28972898
*

lib/schema/bigint.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@ SchemaBigInt.setters = [];
8181
SchemaBigInt.get = SchemaType.get;
8282

8383
/**
84-
* Get/set the function used to cast arbitrary values to booleans.
84+
* Get/set the function used to cast arbitrary values to bigints.
8585
*
8686
* #### Example:
8787
*
8888
* // Make Mongoose cast empty string '' to false.
89-
* const original = mongoose.Schema.BigInt.cast();
89+
* const original = mongoose.Schema.Types.BigInt.cast();
9090
* mongoose.Schema.BigInt.cast(v => {
9191
* if (v === '') {
9292
* return false;

lib/schema/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ exports.ObjectId = require('./objectId');
1919
exports.String = require('./string');
2020
exports.Subdocument = require('./subdocument');
2121
exports.UUID = require('./uuid');
22+
exports.Int32 = require('./int32');
2223

2324
// alias
2425

0 commit comments

Comments
 (0)