Nx Nestjs Mongodb Mongoose統合のセットアップ - 第2部
Nx Nest.js MongoDB Mongoose統合の第2部です。アプリケーションの効率性を高めるために、todosの生成、モジュールの作成、GraphQLモデル・リポジトリ・DTO・MongoDBスキーマの実装を行います。包括的な設定ガイドの続きにご期待ください。
はじめに
Nx、Nest.js、MongoDB、Mongoose統合のチュートリアルシリーズ第2部へようこそ。今回は、Nxを使ってfeature-sample-todosライブラリを生成する方法、モジュール・リゾルバー・サービスの作成方法、そしてMongoDBドキュメントスキーマの構築方法を解説します。さらに、sample-todos機能に関するGraphQLモデル、リポジトリ、DTOの実装や、サービスとリゾルバーの更新についても取り上げます。手順に従って、これらの技術をスムーズに統合し、アプリケーションのスケーラビリティと効率性を高めていきましょう。今後も、設定と統合の旅は続きます。お楽しみに。
Feature-Sample-Todosの生成
まず、Nxを使ってfeature-sample-todosライブラリを生成します。
npx nx generate @nx/js:library api-feature-sample-todos --directory=libs/api/mongoose/feature-sample-mongoose --importPath=@libs/api/mongoose/feature-sample-mongoose --tags=scope:api --bundler=swc
✔ Which unit test runner would you like to use? · jest
モジュール・リゾルバー・サービスの作成
次に、sample-todos機能用のモジュール、リゾルバー、サービスを作成します。
nx generate @nx/nest:module sample-todos --project=api-feature-sample-todos
nx generate @nx/nest:resolver sample-todos --project=api-feature-sample-todos
nx generate @nx/nest:service sample-todos --project=api-feature-sample-todos
ファイルが作成されたら、libフォルダに移動します。
MongoDBドキュメント(スキーマ)の作成
MongoDB用のドキュメント(スキーマ)を作成します。
libs/api/feature-sample-todos/src/lib/sample-todos/models/sample-todos.schema.ts
import { AbstractDocument } from '@libs/api/mongoose/shared';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
@Schema({ versionKey: false })
export class SampleTodoDocument extends AbstractDocument {
@Prop()
content!: string;
@Prop()
editing!: boolean;
@Prop()
completed!: boolean;
}
export const SampleTodoSchema = SchemaFactory.createForClass(SampleTodoDocument);
GraphQLモデルの作成
GraphQL用のモデルを作成します。
libs/api/feature-sample-todos/src/lib/sample-todos/models/sample-todos.model.ts
import { AbstractModel } from '@libs/api/mongoose/shared';
import { Field, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class SampleTodo extends AbstractModel {
@Field()
readonly content!: string;
@Field()
readonly editing!: boolean;
@Field()
readonly completed!: boolean;
}
リポジトリの作成
sample-todos用のリポジトリを作成します。
libs/api/feature-sample-todos/src/lib/sample-todos/sample-todos.repository.ts
import { AbstractRepository } from '@libs/api/mongoose/shared';
import { Injectable, Logger } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { SampleTodo } from './models/sample-todo.model';
import { SampleTodoDocument } from './models/sample-todo.schema';
@Injectable()
export class SampleTodosRepository extends AbstractRepository<SampleTodoDocument> {
protected readonly logger = new Logger(SampleTodosRepository.name);
constructor(
@InjectModel(SampleTodo.name)
SampleTodoModel: Model<SampleTodoDocument>
) {
super(SampleTodoModel);
}
}
DTOの作成
sample-todos用のDTOを作成します。
Args
libs/api/feature-sample-todos/src/lib/sample-todos/dto/args/get-sample-todos-args.dto.ts
import { ArgsType, Field } from '@nestjs/graphql';
import { IsNotEmpty, IsString } from 'class-validator';
@ArgsType()
export class GetSampleTodoArgs {
@Field()
@IsNotEmpty()
@IsString()
_id!: string;
}
Inputs
libs/api/feature-sample-todos/src/lib/sample-todos/dto/input/create-sample-todos-input.dto.ts
import { Field, InputType } from '@nestjs/graphql';
import { IsBoolean, IsString } from 'class-validator';
@InputType()
export class CreateSampleTodoInput {
@Field()
@IsString()
content!: string;
@Field()
@IsBoolean()
editing!: boolean;
@Field()
@IsBoolean()
completed!: boolean;
}
libs/api/feature-sample-todos/src/lib/sample-todos/dto/input/delete-sample-todos-input.dto.ts
import { Field, InputType } from '@nestjs/graphql';
import { IsNotEmpty, IsString } from 'class-validator';
@InputType()
export class DeleteSampleTodoInput {
@Field()
@IsNotEmpty()
@IsString()
_id!: string;
}
libs/api/feature-sample-todos/src/lib/sample-todos/dto/input/update-sample-todos-input.dto.ts
import { Field, InputType } from '@nestjs/graphql';
import { IsBoolean, IsNotEmpty, IsString } from 'class-validator';
@InputType()
export class UpdateSampleTodoInput {
@Field()
@IsNotEmpty()
@IsString()
_id!: string;
@Field()
@IsString()
content!: string;
@Field()
@IsBoolean()
editing!: boolean;
@Field()
@IsBoolean()
completed!: boolean;
}
サービスの更新
sample-todos用のサービスを更新します。
libs/api/feature-sample-todos/src/lib/sample-todos/sample-todos.service.ts
import { Injectable } from '@nestjs/common';
import { GetSampleTodoArgs } from './dto/args/get-sample-todo-args.dto';
import { CreateSampleTodoInput } from './dto/input/create-sample-todo-input.dto';
import { DeleteSampleTodoInput } from './dto/input/delete-sample-todo-input.dto';
import { UpdateSampleTodoInput } from './dto/input/update-sample-todo-input.dto';
import { SampleTodoDocument } from './models/sample-todo.schema';
import { SampleTodosRepository } from './sample-todos.repository';
@Injectable()
export class SampleTodosService {
constructor(private readonly SampleTodoRepository: SampleTodosRepository) {}
async createSampleTodo(createSampleTodoData: CreateSampleTodoInput) {
const SampleTodoDocument = await this.SampleTodoRepository.create({
...createSampleTodoData
});
return this.toModel(SampleTodoDocument);
}
async updateSampleTodo(updateSampleTodoData: UpdateSampleTodoInput) {
const SampleTodoDocument = await this.SampleTodoRepository.findOneAndUpdate(
{ _id: updateSampleTodoData._id },
updateSampleTodoData
);
return this.toModel(SampleTodoDocument);
}
async deleteSampleTodo(deleteSampleTodoData: DeleteSampleTodoInput) {
return await this.SampleTodoRepository.deleteOne({
_id: deleteSampleTodoData._id
});
}
async getSampleTodos() {
const SampleTodoDocument = await this.SampleTodoRepository.find({});
return SampleTodoDocument.map((todo) => this.toModel(todo));
}
async getSampleTodo(getSampleTodoArgs: GetSampleTodoArgs) {
const SampleTodoDocument = await this.SampleTodoRepository.findOne({
...getSampleTodoArgs
});
return this.toModel(SampleTodoDocument);
}
private toModel(SampleTodoDocument: SampleTodoDocument) {
return {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
_id: SampleTodoDocument._id.toHexString(),
...SampleTodoDocument
};
}
}
リゾルバーの更新
sample-todos用のリゾルバーを更新します。
libs/api/feature-sample-todos/src/lib/sample-todos/sample-todos.resolver.ts
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { GetSampleTodoArgs } from './dto/args/get-sample-todo-args.dto';
import { CreateSampleTodoInput } from './dto/input/create-sample-todo-input.dto';
import { DeleteSampleTodoInput } from './dto/input/delete-sample-todo-input.dto';
import { UpdateSampleTodoInput } from './dto/input/update-sample-todo-input.dto';
import { SampleTodo } from './models/sample-todo.model';
import { SampleTodosService } from './sample-todos.service';
@Resolver()
export class SampleTodosResolver {
constructor(private readonly SampleTodoService: SampleTodosService) {}
@Mutation(() => SampleTodo, { name: 'createSampleTodo' })
async createSampleTodo(
@Args('createSampleTodoData')
createSampleTodoData: CreateSampleTodoInput
) {
return await this.SampleTodoService.createSampleTodo(createSampleTodoData);
}
@Mutation(() => SampleTodo, { name: 'updateSampleTodo' })
async updateSampleTodo(
@Args('updateSampleTodoData')
updateSampleTodoData: UpdateSampleTodoInput
) {
return this.SampleTodoService.updateSampleTodo(updateSampleTodoData);
}
@Mutation(() => SampleTodo, { name: 'deleteSampleTodo', nullable: true })
async deleteSampleTodo(
@Args('deleteSampleTodoData')
deleteSampleTodoData: DeleteSampleTodoInput
) {
return this.SampleTodoService.deleteSampleTodo(deleteSampleTodoData);
}
@Query(() => [SampleTodo], { name: 'sampleTodos' })
async getSampleTodos() {
return this.SampleTodoService.getSampleTodos();
}
@Query(() => SampleTodo, { name: 'sampleTodo' })
async getSampleTodo(@Args() getSampleTodoArgs: GetSampleTodoArgs) {
return this.SampleTodoService.getSampleTodo(getSampleTodoArgs);
}
}
モジュールの更新
sample-todos用のモジュールを更新します。
libs/api/feature-sample-todos/src/lib/sample-todos/sample-todos.module.ts
- MongooseModuleを追加する。
- SampleMongooseTableRepositoryをprovidersに追加する。
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { SampleTodo } from './models/sample-todo.model';
import { SampleTodoSchema } from './models/sample-todo.schema';
import { SampleTodosRepository } from './sample-todos.repository';
import { SampleTodosResolver } from './sample-todos.resolver';
import { SampleTodosService } from './sample-todos.service';
@Module({
imports: [
MongooseModule.forFeature([
{
name: SampleTodo.name,
schema: SampleTodoSchema
}
])
],
providers: [SampleTodosResolver, SampleTodosService, SampleTodosRepository]
})
export class SampleTodosModule {}
app.module.tsの更新
apps/api/src/app/ディレクトリ内のapp.module.tsファイルを更新します。
- DatabaseModuleを追加する。
- SampleTodosModuleを追加する。
@Module({
imports: [
ServeStaticModule.forRoot({
rootPath: join(__dirname, '..', 'web/.next'),
exclude: ['/api/*', '/api/graphql']
}),
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
path: '/api/graphql',
autoSchemaFile: true
}),
// ---- Graphql ---- //
// When using Mongoose, the DatabaseModule is required.
DatabaseModule,
SampleTodosModule
],
controllers: [AppController],
providers: [AppService]
})
export class AppModule {}
Nx、Nest.js、MongoDB、Mongooseの設定と統合を継続し、堅牢な開発体験を築いていきますので、次の記事もお楽しみに。
関連コンテンツ
技術の記事をもっと見る →Nx Nestjs Mongodb Mongoose統合のセットアップ - 第3部
Nx Nest.js GraphQL統合の第3部です。パッケージのインストール、設定の更新、GraphQLクライアントの生成を通じてシームレスな統合を行い、データ管理とスケーラビリティを高めます。Nx、Nest.js、GraphQLの統合ガイドの完成、おめでとうございます!今後のチュートリアルもお楽しみに。
#nx#nestjs#mongodbNx Nestjs Mongodb Mongoose統合のセットアップ - 第1部
スケーラビリティと効率性を高めるための、Nx、Nest.js、MongoDB、Mongooseの統合ガイドです。手順に従ってスムーズに開発を進められます。
#nx#nestjs#mongodbNx NestJSからNext.js SSG(静的サイト生成)を配信する方法
モノレポツールNxを使って、Next.jsのSSG(静的サイト生成)で作成した静的サイトをNext.jsアプリケーションから配信する方法を解説します。この方法により、フロントエンドとバックエンドを1つのプロジェクトにまとめることができます。
#nx#nestjs#nextjs