TypeORMのmigrationで作成されるテーブル名をカスタマイズする

# はじめに

TypeORM、素晴らしいんですが、作成したモデルを元にmigrationを掛けると残念なことになります。

例えば、
モデル名 `UserHoge` → 作成されるテーブル名 `user_hoge`
プロパティ名 `firstName` → 作成されるカラム名 `firstName`

なんでテーブルはスネークケース、カラムはキャメルケースで連結なんだ :sob: 

# こうあってほしい

### テーブル・カラム命名規約

Railsの規約がしっくり来るので、それ風にしたい。

- テーブル名: モデルのスネークケース複数形 `user_hoges`
- カラム名: スネークケース `first_name`

### コード

とは言っても、rubyと違って(Type|Java)Scriptの変数命名規約がキャメルケースなので、
コード上はキャメルケースで書きたい

- モデル名: キャメルケース単数 `UserHoge`
- プロパティ名: キャメルケース `firstName`


うまい方法はないかと探した結果、上記は2通りの方法で実現できそうです。

# [方法1] 個別でテーブル・カラム名を定義する

@Entityデコレーター、@Columnデコレーター共に、個別で名前を指定することができます。

```ts
@Entity('users') // これ！
export class User extends BaseEntity {
  @PrimaryGeneratedColumn()
  public id: number

  @Column({ name: 'first_name' }) // これ！
  public firstName: string = ''
}
```

これを元にmigrationを作成すると、指定した名前に応じたSQL文が発行されます。

これで、
「コード上はモデル名:`User` カラム名: `firstName`」
「DB上はテーブル名:`users` カラム名: `first_name`」

を実現できるわけですが、すべてのテーブル・カラムに個別に名前を付けていたのでは
ヌケモレが発生したとき大変なことになりますし、何より面倒くさいです。

# [方法2] 名前付けルールを設定する

ormconfigに独自の名前付けルールを設定する事で、個別に名前を設定しなくても
自動的にORM⇔DB間でいい感じに変換してくれるようになります。

### 1. 設定ファイルを作成 

ここでは`config/TypeOrmNamingStrategy.js`という名前で作ります。 

やっていることは、公式が用意してるDefaultNamingStrategyを継承して、
ルールを書き換えただけです。([念の為、デフォルトのルールはこちら](https://github.com/typeorm/typeorm/blob/a4dec02cc59d3219a29c7be0322af2253e1452dc/src/naming-strategy/DefaultNamingStrategy.ts))

自分はモデルから作るテーブルの他に、多対多のリレーションの中間テーブルの名前等も変えてます。
他にもOverrideしたい場合は、適宜。

```js

var DefaultNamingStrategy = require('typeorm').DefaultNamingStrategy
var snakeCase = require('typeorm/util/StringUtils').snakeCase
var pluralize = require('pluralize')

module.exports = class TypeOrmNamingStrategy extends DefaultNamingStrategy {
  tableName(className, customName) {
    return customName || pluralize(snakeCase(className))
  }

  columnName(propertyName, customName, embeddedPrefixes) {
    return snakeCase(embeddedPrefixes.join('_')) + (customName || snakeCase(propertyName))
  }

  relationName(propertyName) {
    return snakeCase(propertyName)
  }

  joinColumnName(relationName, referencedColumnName) {
    return snakeCase(pluralize.singular(relationName) + '_' + referencedColumnName)
  }

  joinTableName(firstTableName, secondTableName, firstPropertyName, secondPropertyName) {
    return snakeCase(firstTableName + '_' + secondTableName)
  }

  joinTableColumnName(tableName, propertyName, columnName) {
    return snakeCase(pluralize.singular(tableName) + '_' + (columnName || propertyName))
  }

  classTableInheritanceParentColumnName(parentTableName, parentTableIdPropertyName) {
    return snakeCase(pluralize.singular(parentTableName) + '_' + parentTableIdPropertyName)
  }
}

```

### 2. ormconfigを編集する

先程作ったカスタム名前付けルールのクラスを読み込むようにします。
設定内でクラスをインスタンス化しているため、ormconfig.jsonでは駄目です。
json拡張子を使っている人は、ormconfig.jsに変更してください。

```js:ormconfig.js
const TypeOrmNamingStrategy = require('./src/configs/TypeOrmNamingStrategy.js') // これ！

module.exports = {
  // 色々独自の設定
  type: 'postgres',
  host: process.env.DB_HOSTNAME,
  port: 5432,
  username: process.env.DB_USERNAME,
  password: process.env.DB_PASSWORD,
  ...
  namingStrategy: new TypeOrmNamingStrategy() // これ！！
}

```

### 3. いつも通りmigrationを当てる

カスタムルールに基づいた命名規則でmigrationが作られるようになります。