sequelize-auto icon indicating copy to clipboard operation
sequelize-auto copied to clipboard

Using getAttributes to re-initialize models with customizations (getters/setters)

Open patricktyndall opened this issue 2 years ago • 0 comments

An idea for using sequelize-auto in scenarios where type-based customizations (getters/setters) are needed. Appreciate any feedback.

My app uses custom getters/setters so we can use integers to represent timestamptz columns (unix seconds). All timestamptzs are done this way.

As far as I can tell, there's no way to configure this globally for a specific column type in sequelize (or sequelize-auto). This is a blocker for adopting this lib.

So I've been looking for workarounds to achieve this so we can use sequelize-auto without breaking existing code:

  • I looked into hooks, but can't figure out a way to know the intended column type for each column.
  • Modify the initialized model's instance properties (I can at least delete something from fieldRawAttributesMap, but that seems like a risky approach)
  • I found the removeAttribute() method, which can be used to remove an attribute from an initialized model, but I don't see a corresponding addAttribute() (this would be a great solution)
  • Some mention of automated scripts here, but nothing actionable

One thing does come to mind: Using a custom initModels file, initialize a model from sequelize-auto, then call getAttributes on it to list the columns, then create a new model and loop through the columns to re-add them to my new model, but with type-based overrides.

  • Logging an attribute from getAttributes looks like this:
 {
   type: BOOLEAN {},
   allowNull: false,
   defaultValue: false,
   Model: restaurant,
   fieldName: 'is_dine_in_only',
   _modelAttribute: true,
   field: 'is_dine_in_only'
 }

This seems like enough info for me to create my own model with the necessary overrides. In other words, I just need sequelize-auto to be a "schema parsing" tool, and I can intercept its models to create my own with the generated schema info.

  • On this note: It would be great if sequelize-auto could simply generate the attributes, instead of model classes. All I need is the ability to programmatically modify the attributes, which I could do if they were exported from the generated model files. Instead, we have to initialize the model and then call getAttributes() on it.

Here are some concerns I have:

  • getAttributes is in the API so seemingly supported, but still it's deep in the docs
  • To identify the type of a column, I have to either compare with type.key to get a text representation (not a public API), or I can do type instanceof DataTypes.DATEONLY (this does work, but I'm also concerned it would break in future versions).
  • Supporting other sequelize constructs:
    • defaultValue is tricky. If it's a constant, I can just read from defaultValue. But if it's a LITERAL, I may need to use a private API to access the literal value.
    • allowNull is simple to read from / reuse
    • primaryKey is also simple
  • This means we need to initialize each model twice (once from sequelize-auto model, once after creating our new overridden model). Not sure how much overhead there is on that.
  • I don't use sync (so I don't care about references), but this approach would likely not work for those that do.

Can anyone critique this, or has anyone tried this approach?

patricktyndall avatar Sep 08 '23 16:09 patricktyndall