Skip to content

Commit

Permalink
feat: add custom caster support for Decimal128
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Dec 13, 2018
1 parent aede9d1 commit 1a0d204
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 28 deletions.
36 changes: 36 additions & 0 deletions lib/cast/decimal128.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';

const Decimal128Type = require('../types/decimal128');
const assert = require('assert');

module.exports = function castDecimal128(value) {
if (value == null) {
return value;
}

if (typeof value === 'object' && typeof value.$numberDecimal === 'string') {
return Decimal128Type.fromString(value.$numberDecimal);
}

if (value instanceof Decimal128Type) {
return value;
}

if (typeof value === 'string') {
return Decimal128Type.fromString(value);
}

if (Buffer.isBuffer(value)) {
return new Decimal128Type(value);
}

if (typeof value === 'number') {
return Decimal128Type.fromString(String(value));
}

if (typeof value.valueOf === 'function' && typeof value.valueOf() === 'string') {
return Decimal128Type.fromString(value.valueOf());
}

assert.ok(false);
};
80 changes: 52 additions & 28 deletions lib/schema/decimal128.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
const SchemaType = require('../schematype');
const CastError = SchemaType.CastError;
const Decimal128Type = require('../types/decimal128');
const castDecimal128 = require('../cast/decimal128');
const utils = require('../utils');

let Document;

/**
Expand Down Expand Up @@ -37,6 +39,51 @@ Decimal128.schemaName = 'Decimal128';
Decimal128.prototype = Object.create(SchemaType.prototype);
Decimal128.prototype.constructor = Decimal128;

/*!
* ignore
*/

Decimal128._cast = castDecimal128;

/**
* Get/set the function used to cast arbitrary values to decimals.
*
* ####Example:
*
* // Make Mongoose only refuse to cast numbers as decimal128
* const original = mongoose.Schema.Types.Decimal128.cast();
* mongoose.Decimal128.cast(v => {
* assert.ok(typeof v !== 'number');
* return original(v);
* });
*
* // Or disable casting entirely
* mongoose.Decimal128.cast(false);
*
* @param {Function} [caster]
* @return {Function}
* @function get
* @static
* @api public
*/

Decimal128.cast = function cast(caster) {
if (arguments.length === 0) {
return this._cast;
}
if (caster === false) {
caster = v => {
if (v != null && !(v instanceof Decimal128Type)) {
throw new Error();
}
return v;
};
}
this._cast = caster;

return this._cast;
};

/*!
* ignore
*/
Expand Down Expand Up @@ -123,35 +170,12 @@ Decimal128.prototype.cast = function(value, doc, init) {
return ret;
}

if (value == null) {
return value;
const _castDecimal128 = this.constructor.cast();
try {
return _castDecimal128(value);
} catch (error) {
throw new CastError('Decimal128', value, this.path);
}

if (typeof value === 'object' && typeof value.$numberDecimal === 'string') {
return Decimal128Type.fromString(value.$numberDecimal);
}

if (value instanceof Decimal128Type) {
return value;
}

if (typeof value === 'string') {
return Decimal128Type.fromString(value);
}

if (Buffer.isBuffer(value)) {
return new Decimal128Type(value);
}

if (typeof value === 'number') {
return Decimal128Type.fromString(String(value));
}

if (typeof value.valueOf === 'function' && typeof value.valueOf() === 'string') {
return Decimal128Type.fromString(value.valueOf());
}

throw new CastError('Decimal128', value, this.path);
};

/*!
Expand Down
26 changes: 26 additions & 0 deletions test/schematype.cast.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ describe('SchemaType.cast() (gh-7045)', function() {
original.boolean = Schema.Types.Boolean.cast();
original.string = Schema.Types.String.cast();
original.date = Schema.Types.Date.cast();
original.decimal128 = Schema.Types.Decimal128.cast();
});

afterEach(function() {
Schema.ObjectId.cast(original.objectid);
Schema.Types.Boolean.cast(original.boolean);
Schema.Types.String.cast(original.string);
Schema.Types.Date.cast(original.date);
Schema.Types.Decimal128.cast(original.decimal128);
});

it('with inheritance', function() {
Expand Down Expand Up @@ -165,4 +167,28 @@ describe('SchemaType.cast() (gh-7045)', function() {
assert.throws(() => d.cast('2018-06-01'), /CastError/);
});
});

describe('decimal128', function() {
it('supports custom cast functions', function() {
Schema.Types.Decimal128.cast(v => {
assert.ok(typeof v !== 'number');
return original.date(v);
});

const d = new Schema.Types.Decimal128();
d.cast('1000'); // Should not throw

assert.throws(() => d.cast(1000), /CastError/);
});

it('supports disabling casting', function() {
Schema.Types.Decimal128.cast(false);

const d = new Schema.Types.Decimal128();
assert.throws(() => d.cast('1000'), /CastError/);
assert.throws(() => d.cast(1000), /CastError/);

d.cast(original.decimal128('1000')); // Should not throw
});
});
});

0 comments on commit 1a0d204

Please sign in to comment.