8

I have a custom type in Postgres that I want to use in Sequelize. I've written code based on the example in the Sequelize docs, except for call to a function ("inherits") which I can't find in Sequelize or elsewhere. However, using sequelize.define to create a model with an attribute of this custom type throws an exception inside Sequelize. Is there an error in my code that stands out? Or is there another good example or tutorial for implementing a custom datatype? Also, what's up with the "inherits" function shown in the doc example -- are the docs leaving out an import/requires, or is that call erroneous?

Docs I'm following are here: http://docs.sequelizejs.com/manual/data-types.html#extending-datatypes

The type as defined in Postgres:

CREATE TYPE public.measurement AS
(
    unit text,
    value double precision
);

My test code in NodeJS:

const Sequelize = require('sequelize');

let dataTypes = Sequelize.DataTypes;

// Create class for custom datatype
class MEASUREMENT extends dataTypes.ABSTRACT {
    toSql() {
        console.log('MEASUREMENT toSql');
        return 'MEASUREMENT';
    }
    static parse(value) {
        console.log('MEASUREMENT parse value=', value);
        return value;
    }
};

// Set key
MEASUREMENT.prototype.key = 'MEASUREMENT';
MEASUREMENT.key = MEASUREMENT.prototype.key;

// Add to DataTypes
dataTypes.MEASUREMENT = MEASUREMENT;

// Add to Sequelize
Sequelize.MEASUREMENT = Sequelize.Utils.classToInvokable(MEASUREMENT);

let pgTypes = dataTypes.postgres;

// Map dialects
dataTypes.MEASUREMENT.types.postgres = ['MEASUREMENT']

pgTypes.MEASUREMENT = function MEASUREMENT() {
    if (!(this instanceof pgTypes.MEASUREMENT)) return new pgTypes.MEASUREMENT();
    DataTypes.MEASUREMENT.apply(this, arguments);
}

// inherits(pgTypes.MEASUREMENT, dataTypes.MEASUREMENT);
// Node throws a parse error. This is in the example in the Sequelize docs, however.

pgTypes.MEASUREMENT.parse = dataTypes.MEASUREMENT.parse;


// ------------------------------

const sequelize = new Sequelize('test', 'test', 'test', {
    host: 'localhost',
    dialect: 'postgres'
});

const Thing = sequelize.define('thing', {
    name: Sequelize.STRING,
    weight: Sequelize.MEASUREMENT
});

Call stack when run:

C:\Workspaces\nebula\server\node_modules\sequelize\lib\dialects\abstract\connection-manager.js:48
        if (dataType.types[this.dialectName]) {                                                                         
                          ^                                                                                             

TypeError: Cannot read property 'postgres' of undefined                                                                 
    at _.each.dataType (C:\Workspaces\nebula\server\node_modules\sequelize\lib\dialects\abstract\connection-manager.js:48:27)                                                                                                                   
    at C:\Workspaces\nebula\server\node_modules\lodash\lodash.js:4911:15                                                
    at baseForOwn (C:\Workspaces\nebula\server\node_modules\lodash\lodash.js:2996:24)                                   
    at C:\Workspaces\nebula\server\node_modules\lodash\lodash.js:4880:18                                                
    at Function.forEach (C:\Workspaces\nebula\server\node_modules\lodash\lodash.js:9344:14)                             
    at ConnectionManager.refreshTypeParser (C:\Workspaces\nebula\server\node_modules\sequelize\lib\dialects\abstract\connection-manager.js:46:7)                                                                                                
    at new ConnectionManager (C:\Workspaces\nebula\server\node_modules\sequelize\lib\dialects\postgres\connection-manager.js:23:10)                                                                                                             
    at new PostgresDialect (C:\Workspaces\nebula\server\node_modules\sequelize\lib\dialects\postgres\index.js:14:30)    
    at new Sequelize (C:\Workspaces\nebula\server\node_modules\sequelize\lib\sequelize.js:320:20)                       
    at Object.<anonymous> (C:\Workspaces\nebula\server\testsequelizecustom.js:58:19)                                    
    at Module._compile (internal/modules/cjs/loader.js:689:30)                                                          
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)                                            
    at Module.load (internal/modules/cjs/loader.js:599:32)                                                              
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)                                                            
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)                                                     
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)                                                  
    at startup (internal/bootstrap/node.js:279:19)                                                                      
    at bootstrapNodeJSCore (internal/bootstrap/node.js:752:3)                                                           
1
  • 1
    I agree the docs could be improved. This is how I got inherits to work: const util = require('util'); // Built-in Node package util.inherits(PgTypes.MEASUREMENT, DataTypes.MEASUREMENT); Commented Feb 24, 2021 at 23:02

1 Answer 1

5

To fix the error, we need to cause the property postgres on the object dataType.types to be defined.

Just under the line you already have:

pgTypes.MEASUREMENT.parse = dataTypes.MEASUREMENT.parse;

Add the following line, and the error should go away:

pgTypes.MEASUREMENT.types = {postgres:[‘MEASUREMENT’]};

You'll probably also need to add this line, to handle a related error (see below).

dataTypes.postgres.MEASUREMENT.key = ‘MEASUREMENT’;

The related error:

[...]/node_modules/sequelize/lib/dialects/postgres/connection-manager.js:36
if (dataType.key.toLowerCase() === 'range') {
                         ^
    
TypeError: Cannot read property 'toLowerCase' of undefined
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.