Skip to content

Commit

Permalink
Merge pull request #15054 from mongodb-js/NODE-6503/int32-schemaType
Browse files Browse the repository at this point in the history
feat(NODE-6503): Add Int32 to SchemaType
  • Loading branch information
vkarpov15 authored Dec 5, 2024
2 parents e927dd2 + 9dcada3 commit 6d8a0f2
Show file tree
Hide file tree
Showing 13 changed files with 923 additions and 30 deletions.
1 change: 1 addition & 0 deletions docs/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ The permitted SchemaTypes are:
* [Decimal128](api/mongoose.html#mongoose_Mongoose-Decimal128)
* [Map](schematypes.html#maps)
* [UUID](schematypes.html#uuid)
* [Int32](schematypes.html#int32)

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

Expand Down
40 changes: 40 additions & 0 deletions docs/schematypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Check out [Mongoose's plugins search](http://plugins.mongoosejs.io) to find plug
* [Schema](#schemas)
* [UUID](#uuid)
* [BigInt](#bigint)
* [Int32](#int32)

### Example

Expand All @@ -68,6 +69,7 @@ const schema = new Schema({
mixed: Schema.Types.Mixed,
_someId: Schema.Types.ObjectId,
decimal: Schema.Types.Decimal128,
int32bit: Schema.Types.Int32,
array: [],
ofString: [String],
ofNumber: [Number],
Expand Down Expand Up @@ -647,6 +649,44 @@ const question = new Question({ answer: 42n });
typeof question.answer; // 'bigint'
```

### Int32 {#int32}

Mongoose supports 32-bit integers as a SchemaType.
Int32s are stored as [32-bit integers in MongoDB (BSON type "int")](https://www.mongodb.com/docs/manual/reference/bson-types/).

```javascript
const studentsSchema = new Schema({
id: Int32
});
const Student = mongoose.model('Student', schema);

const student = new Student({ id: 1339 });
typeof student.id; // 'number'
```

There are several types of values that will be successfully cast to a Number.

```javascript
new Student({ id: '15' }).id; // 15 as a Int32
new Student({ id: true }).id; // 1 as a Int32
new Student({ id: false }).id; // 0 as a Int32
new Student({ id: { valueOf: () => 83 } }).id; // 83 as a Int32
new Student({ id: '' }).id; // null as a Int32
```

If you pass an object with a `valueOf()` function that returns a Number, Mongoose will
call it and assign the returned value to the path.

The values `null` and `undefined` are not cast.

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:

* NaN
* strings that cast to NaN
* objects that don't have a `valueOf()` function
* a decimal that must be rounded to be an integer
* an input that represents a value outside the bounds of an 32-bit integer

## Getters {#getters}

Getters are like virtuals for paths defined in your schema. For example,
Expand Down
36 changes: 36 additions & 0 deletions lib/cast/int32.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';

const isBsonType = require('../helpers/isBsonType');
const assert = require('assert');

/**
* Given a value, cast it to a Int32, or throw an `Error` if the value
* cannot be casted. `null` and `undefined` are considered valid.
*
* @param {Any} value
* @return {Number}
* @throws {Error} if `value` does not represent an integer, or is outside the bounds of an 32-bit integer.
* @api private
*/

module.exports = function castInt32(val) {
if (val == null) {
return val;
}
if (val === '') {
return null;
}

const coercedVal = isBsonType(val, 'Long') ? val.toNumber() : Number(val);

const INT32_MAX = 0x7FFFFFFF;
const INT32_MIN = -0x80000000;

if (coercedVal === (coercedVal | 0) &&
coercedVal >= INT32_MIN &&
coercedVal <= INT32_MAX
) {
return coercedVal;
}
assert.ok(false);
};
2 changes: 2 additions & 0 deletions lib/mongoose.js
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,7 @@ Mongoose.prototype.VirtualType = VirtualType;
* - [ObjectId](https://mongoosejs.com/docs/schematypes.html#objectids)
* - [Map](https://mongoosejs.com/docs/schematypes.html#maps)
* - [Subdocument](https://mongoosejs.com/docs/schematypes.html#schemas)
* - [Int32](https://mongoosejs.com/docs/schematypes.html#int32)
*
* Using this exposed access to the `ObjectId` type, we can construct ids on demand.
*
Expand Down Expand Up @@ -1138,6 +1139,7 @@ Mongoose.prototype.syncIndexes = function(options) {

Mongoose.prototype.Decimal128 = SchemaTypes.Decimal128;


/**
* The Mongoose Mixed [SchemaType](https://mongoosejs.com/docs/schematypes.html). Used for
* declaring paths in your schema that Mongoose's change tracking, casting,
Expand Down
1 change: 1 addition & 0 deletions lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -2892,6 +2892,7 @@ module.exports = exports = Schema;
* - [Mixed](https://mongoosejs.com/docs/schematypes.html#mixed)
* - [UUID](https://mongoosejs.com/docs/schematypes.html#uuid)
* - [BigInt](https://mongoosejs.com/docs/schematypes.html#bigint)
* - [Int32](https://mongoosejs.com/docs/schematypes.html#int32)
*
* Using this exposed access to the `Mixed` SchemaType, we can use them in our schema.
*
Expand Down
4 changes: 2 additions & 2 deletions lib/schema/bigint.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ SchemaBigInt.setters = [];
SchemaBigInt.get = SchemaType.get;

/**
* Get/set the function used to cast arbitrary values to booleans.
* Get/set the function used to cast arbitrary values to bigints.
*
* #### Example:
*
* // Make Mongoose cast empty string '' to false.
* const original = mongoose.Schema.BigInt.cast();
* const original = mongoose.Schema.Types.BigInt.cast();
* mongoose.Schema.BigInt.cast(v => {
* if (v === '') {
* return false;
Expand Down
1 change: 1 addition & 0 deletions lib/schema/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ exports.ObjectId = require('./objectId');
exports.String = require('./string');
exports.Subdocument = require('./subdocument');
exports.UUID = require('./uuid');
exports.Int32 = require('./int32');

// alias

Expand Down
Loading

0 comments on commit 6d8a0f2

Please sign in to comment.