Public API for using custom data type parsers
See original GitHub issueHaving specific data types returned as custom types is a common use case. For example, while it makes sense for sequelize to return DECIMALs as strings by default to keep the dependencies small, any application that handles any kind of complex monetary values that need to be manipulated will likely want to use something like bignumber.js to handle those.
const user = await User.findOne();
user.balance instanceof BigNumber // true
await user.update({balance: user.balance.plus('5000000000.10')});
Currently, there are two methods, $stringify
(which is private?) and parse
. These partly sit on the base data types and then sometimes get overridden by the dialect data-types.
There should be a way to define a custom parser and stringifier for a data type that
- works with all dialects
- does not require to use private methods
- has an easy API (the user should not be concerned about the nature of the data types being static, classes and factory functions). #1498 Proposal
Allow to set two methods on each data type, parse
and stringify
. parse
at the moment is a static
method, because it needs to be set in the libraries before a model is defined. stringify()
is an instance method and can therefor access this.options
. NOTE: It would be nice if parse()
could be an instance method aswell for consistency. This may be changed before v4 is stable.
The internal parse and stringify methods will be renamed to _parse
and _stringify
to make them explicitely private. These may be overridden by dialects. They always first check for the presence of a parse
and/or stringify
function on the data type that may have been provided by the user and use it to convert the value.
The default implementation of parse()
and stringify()
always delegate to the dialect-specific data-types with .call()
/.apply()
. The dialect that should be used when stringifying is given as a dialect
option in the options
argument that some data types already accept. Data types are not replaced anymore at Model normalization with the dialect specific data types.
A user can choose to fallback to the default behaviour by calling super.stringify()
.
Sequelize.DECIMAL.parse = value => new BigNumber(value);
Sequelize.DECIMAL.stringify = value => value instanceof BigNumber ? value.toString() : value;
Interface:
stringify?: (value: any, options: { dialect: string}) => string;
parse?: (value: string, options: { dialect: string }) => any;
Questions about the current codebase
- why is
$stringify()
private, butparse()
not? No reason - why is
parse()
static, but$stringify()
an instance method? Parsers need to be set at connection-level before Model creation - why is there a second
stringify()
method? No reason - why is there no default implementation for
parse()
? E.g. why are there some data types that don’t have this method defined, and how is this handled No reason
ToDo
- Remove ParserStore #6473
- Don’t export closures in dialect data types
- Don’t patch BaseTypes with
types
property - just use dialect objects - Remove
DataType.extend
(we have inheritance for that and will use delegation anyway) - Remove
DataType.key
(we haveDataType.name
andDataType.prototype.toSql()
for that) - Introduce dialects/abstract/data-types.js (dialects need a base implementation that they can fallback to even when the user overrides parsers/stringifiers)
- Use method delegation
Issue Analytics
- State:
- Created 7 years ago
- Comments:15 (12 by maintainers)
any updates of this issues? I want to extend some datatypes properly.
Currently trying to figure out how to deal with DECIMAL being strings in Sequelize v4, really need something like this.