Skip to content

Commit

Permalink
feat: add make migration command
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Jan 12, 2020
1 parent 26d1e4c commit 56efe6e
Show file tree
Hide file tree
Showing 8 changed files with 435 additions and 3 deletions.
150 changes: 150 additions & 0 deletions commands/MakeMigration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* @adonisjs/lucid
*
* (c) Harminder Virk <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

import { join } from 'path'
import camelCase from 'camelcase'
import snakeCase from 'snake-case'
import { inject } from '@adonisjs/fold'
import { BaseCommand, args, flags } from '@adonisjs/ace'
import { DatabaseContract } from '@ioc:Adonis/Lucid/Database'
import { ApplicationContract } from '@ioc:Adonis/Core/Application'

@inject([null, 'Adonis/Lucid/Database'])
export default class MakeMigration extends BaseCommand {
public static commandName = 'make:migration'
public static description = 'Make a new migration file'

/**
* The name of the migration file. We use this to create the migration
* file and generate the table name
*/
@args.string({ description: 'Name of the migration file' })
public name: string

/**
* Choose a custom pre-defined connection. Otherwise, we use the
* default connection
*/
@flags.string({ description: 'Define a custom database connection for the migration' })
public connection: string

/**
* Pre select migration directory. If this is defined, we will ignore the paths
* defined inside the config.
*/
@flags.string({ description: 'Pre-select a migration directory' })
public folder: string

/**
* Custom table name for creating a new table
*/
@flags.string({ description: 'Define the table name for creating a new table' })
public create: string

/**
* Custom table name for altering an existing table
*/
@flags.string({ description: 'Define the table name for altering an existing table' })
public table: string

/**
* This command loads the application, since we need the runtime
* to find the migration directories for a given connection
*/
public static settings = {
loadApp: true,
}

constructor (app: ApplicationContract, private _db: DatabaseContract) {
super(app)
}

/**
* Returns the directory for creating the migration file
*/
private async _getDirectory (migrationPaths?: string[]): Promise<string> {
if (this.folder) {
return this.folder
}

let directories = migrationPaths && migrationPaths.length ? migrationPaths : ['database/migrations']
if (directories.length === 1) {
return directories[0]
}

return this.prompt.choice('Select the migrations folder', directories, { name: 'folder' })
}

public async handle () {
const connection = this._db.getRawConnection(this.connection || this._db.primaryConnectionName)

/**
* Ensure the define connection name does exists in the
* config file
*/
if (!connection) {
this.logger.error(
`${this.connection} is not a valid connection name. Double check config/database file`,
)
return
}

/**
* Not allowed together, hence we must notify the user about the same
*/
if (this.table && this.create) {
this.logger.warn('--table and --create cannot be used together. Ignoring --create')
}

/**
* The folder for creating the schema file
*/
const folder = await this._getDirectory((connection.config.migrations || {}).paths)

/**
* Using the user defined table name or an empty string. We can attempt to
* build the table name from the migration file name, but let's do that
* later.
*/
const tableName = this.table || this.create || ''

/**
* Template stub
*/
const stub = join(
__dirname,
'..',
'templates',
this.table ? 'migration-alter.txt' : 'migration-make.txt',
)

/**
* Prepend timestamp to keep schema files in the order they
* have been created
*/
const prefix = `${new Date().getTime()}_`

this
.generator
.addFile(this.name, { pattern: 'snakecase', form: 'plural', prefix })
.stub(stub)
.destinationDir(folder)
.appRoot(this.application.cliCwd || this.application.appRoot)
.apply({
toClassName (filename: string) {
return camelCase(tableName || filename.replace(prefix, ''), { pascalCase: true })
},
toTableName (filename: string) {
return tableName || snakeCase(filename.replace(prefix, ''))
},
})

await this.generator.run()
}
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"@poppinss/utils": "^2.1.0",
"camelcase": "^5.3.1",
"knex": "^0.20.2",
"knex-dynamic-connection": "^1.0.1",
"knex-dynamic-connection": "^1.0.2",
"pluralize": "^8.0.0",
"snake-case": "^2.1.0",
"ts-essentials": "^3.0.5"
Expand All @@ -54,7 +54,7 @@
"@adonisjs/core": "2.x.x"
},
"devDependencies": {
"@adonisjs/ace": "^6.7.2",
"@adonisjs/ace": "^6.7.3",
"@adonisjs/fold": "^6.2.3",
"@adonisjs/mrm-preset": "^2.1.0",
"@adonisjs/sink": "^2.4.0",
Expand Down
15 changes: 15 additions & 0 deletions templates/migration-alter.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import BaseSchema from '@ioc:Adonis/Lucid/Schema'

export default class ${toClassName(filename)} extends BaseSchema {
protected $tableName = '${toTableName(filename)}'

public async up () {
this.schema.table(this.$tableName, (table) => {
})
}

public async down () {
this.schema.table(this.$tableName, (table) => {
})
}
}
16 changes: 16 additions & 0 deletions templates/migration-make.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import BaseSchema from '@ioc:Adonis/Lucid/Schema'

export default class ${toClassName(filename)} extends BaseSchema {
protected $tableName = '${toTableName(filename)}'

public async up () {
this.schema.createTable(this.$tableName, (table) => {
table.increments('id')
table.timestamps()
})
}

public async down () {
this.schema.dropTable(this.$tableName)
}
}
7 changes: 7 additions & 0 deletions test-helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,10 @@ export function getBaseSchema () {
export function getMigrator (db: DatabaseContract, app: ApplicationContract, config: MigratorOptions) {
return new Migrator(db, app, config) as unknown as MigratorContract
}

/**
* Split string to an array using cross platform new lines
*/
export function toNewlineArray (contents: string): string[] {
return contents.split(/\r?\n/)
}
Binary file added test-helpers/tmp/db.sqlite
Binary file not shown.
Loading

0 comments on commit 56efe6e

Please sign in to comment.