Objection.js: do we have any method to generate migration file now from model?

Created on 24 Oct 2017  路  4Comments  路  Source: Vincit/objection.js

migration generation can be done by knex, do we have any method to generate migration file now from model?

Most helpful comment

Heyo @njleonzhang and other Objection.js peeps! We're working on a (WIP) cool migration project called schwifty-migration that addresses migration file generation.

Right now with this lib you can only use schwifty models (they have a Joi schema). Right now schwifty-migration is pretty specific to our own usage, but in the future we will add support for models with Objection's default JSON schema.

schwifty-migration manages changes for:

  • Adding new models
  • Adding and removing columns from an existing model
  • Changing the datatype of an existing column

It does NOT manage:

  • Removing models
  • Changing a column or table's name

As it's meant for writing migrations during development -- those features may or may not make it into future versions.

Just lettin' you know we're working on it!

All 4 comments

Heyo @njleonzhang and other Objection.js peeps! We're working on a (WIP) cool migration project called schwifty-migration that addresses migration file generation.

Right now with this lib you can only use schwifty models (they have a Joi schema). Right now schwifty-migration is pretty specific to our own usage, but in the future we will add support for models with Objection's default JSON schema.

schwifty-migration manages changes for:

  • Adding new models
  • Adding and removing columns from an existing model
  • Changing the datatype of an existing column

It does NOT manage:

  • Removing models
  • Changing a column or table's name

As it's meant for writing migrations during development -- those features may or may not make it into future versions.

Just lettin' you know we're working on it!

There's no such method in objection core and I don't think there should be. I think @wswoodruff and his team is your best shot right now 馃槃

Tnx for your effort. wait for new migration tool. 馃憤

I agree it should be kept out of core.

Some thoughts on a plugin implementation:

You should maintain a "squashed" latest migration inside your models.

There should be a migration function taking knex as a param, inside the model file.

There would be two functions, because if you are adding references, you need the table you are referencing to have been created first, and we don't want to have to worry about ordering our model migrations. Call them migrate and migrateAfter.

You could generate these migrations in separate properties (say generatedMigrate), and then the user could:

a. use the generated ones by a simple reference from latestMigration.
b. copy-paste from the generated ones into their custom one.
c. easily compare them against their custom latestMigration.

Then you would custom write your alter tables and add them to knex-migrate files. (Doing this in an automated way is too much effort and would be problematic if it wasn't perfect.)

There would be a tool to run the migrate functions together, then in a separate stage run the migrateAfter.

Then to verify your "squashed" schema:

  • create a database from scratch from your migration files
  • create a database from the squashed migrations
  • diff the databases (pg_dump -s)
import {Model} from 'objection'

class Person extends Model {
  static jsonSchema = {
    properties: {id: {type: 'string'}},
  }

  static relationMappings = {
    parent: {
      relation: Model.BelongsToOneRelation,
      modelClass: Person,
      join: {
        from: 'Person.parentId',
        to: 'Person.id',
      },
    },
  }

  static migrate = async knex => {
    knex.raw('CREATE SCHEMA IF NOT EXISTS foo')
    knex.raw('ALTER DATABASE SET search_path = public,foo')
    knex.createTable('foo.Person', (table) => {
      table.increments('id').primary()
    })
  }

  static migrateAfter = async knex => {
    await Person.generatedMigrateAfter(knex)
  }

  ////////////////////////////////////////////////////////////////////////////////

  // Generated from jsonSchema.
  static generatedMigrate = async knex => {
    knex.raw('CREATE SCHEMA IF NOT EXISTS foo')
    knex.raw('ALTER DATABASE SET search_path = public,foo')
    knex.createTable('foo.Person', (table) => {
      table.increments('id').primary()
    })
  }

  static generatedMigrateAfter = async knex => {
    knex.alterTable('Person', (table) => {
      table.foreign('parentId')
        .references('id')
        .inTable('Person')
    })
  }

}

NOTE: No down migration needed, because this migration is the first.

Why maintain migrations/ and "squashed migrations"?

This is a good question, and I am not so sure about it. What I can think of though is:

  • Faster testing. Avoid running time consuming data migration logic when setting up. Avoid redundant alter table commands.
  • Enourages recreating databases often rather than keeping an old dev database around. Quickly create new databases for each test run.
  • More convenient to visualise your table's schema - data types, references, etc.

I guess you could also pg_dump -s after running your migrations to visualize the schema, and this could negate a lot of the advantages I mentioned - except you are now tied to a specific dialect. Instead of having the current schema in knex.migrate style, you could just add comments to your models like https://github.com/ctran/annotate_models does.

Exporting postgres schema as json: https://github.com/tjwebb/pg-json-schema-export

Another option is to look at the pg_attribute system catalog.


Lots of tools floating around that diff dbs and output DDL like https://github.com/joncrlsn/pgdiff and https://www.postgrescompare.com/.


Maybe its better to put the generated migrations in a separate file...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

apronin83 picture apronin83  路  3Comments

AhmadRaza786 picture AhmadRaza786  路  3Comments

Gustav0ar picture Gustav0ar  路  4Comments

haywirez picture haywirez  路  3Comments

chen7david picture chen7david  路  3Comments