AngularやNestJSのモジュール定義をする際、たくさんのクラスをインポートして、ProviderやImportに登録する場合があると思う。フォルダ構成次第だが、これを楽をする方法がある。
フォルダ構成
一般的かは分からないが、コントローラ・エンティティ・サービスごとにフォルダを分け、それぞれのindex.ts
の中で同種のクラス定義をまとめてexportするフォルダ構成にしてみる。
各フォルダのindex.ts
は以下のようになる。
export * from './location.controller';
export * from './item.controller';
モジュール定義
上記のフォルダ構成の場合、import * as Services from './services'
と書いただけで、Services
はItemService
, LocationService
というメンバに、それぞれのクラス定義=Function型が格納される(ソースは省略)。これを、ToArray
関数により配列化すれば、モジュール定義に使用することができる。
対象のエンティティやサービスが増えても、コードを変える必要がなくなるので少し楽ができる。
また、エンティティの配列は後で使いたいので、モジュールの静的メンバとして持っておく。
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import * as Services from './services';
import * as Entities from './entities';
import * as Controllers from './controllers';
function ToArray( obj: Object ) {
return Object.keys( obj ).map( key => obj[key] );
}
const EntityArray = ToArray( Entities );
@Module( {
imports: [ TypeOrmModule.forFeature( EntityArray ) ],
providers: ToArray( Services ),
controllers: ToArray( Controllers ),
} )
export class InventryModule {
static readonly Entities = EntityArray;
}
ToArrayの元ネタ: Javascript, Converting an Object to an Array of Objects.
データベースの定義に使う
NestJSのTypeOrmModuleでは、forRootにてデータベースで扱うエンティティを指定する必要がある。[ワイルドカード付きのファイルパスで指定することもできる]
(https://qiita.com/stm32p103/items/4cb0f352042cd856a12e)が、先ほど用意した`InventryModule.Entities`静的メンバを使えば以下のように書ける。これなら、ファイルを移動しても影響がないはず。
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { InventryModule } from './inventry';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot( {
type: 'sqlite',
database: 'db/sqlite.db',
synchronize: true,
entities: [ ...InventryModule.Entities ]
} ), InventryModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}