SuzukiTakamasa / CryptoFunds

0 stars 0 forks source link

To Do アプリ #2

Open SuzukiTakamasa opened 3 months ago

SuzukiTakamasa commented 3 months ago

入力プロンプト

以下の技術スタックを使用したTo Doアプリのサンプルコードを必要な環境構築の手順も含めて出力してください。
言語: TypeScript
ライブラリ・フレームワーク: React/Next.js/NestJS
データベース: PostgreSQL
アーキテクチャ: クリーンアーキテクチャ、マルチテナントアーキテクチャ(RLS採用)

1. 環境構築

必要なツール Node.js (v14以上) PostgreSQL (v12以上) Docker (オプショナル)

1.1 Node.jsとnpmのインストール

公式サイトからインストールします: https://nodejs.org/

1.2 PostgreSQLのインストール

公式サイトからインストールします: https://www.postgresql.org/download/

1.3 NestJS CLIのインストール

npm install -g @nestjs/cli

2. フロントエンド: Next.jsのセットアップ

2.1 プロジェクトの作成

npx create-next-app@latest todo-app --typescript

2.2 依存関係のインストール

React QueryやAxiosなどの依存ライブラリをインストールします。

cd todo-app
npm install axios react-query

2.3 フォルダ構成

以下のようなフォルダ構成を作成します。

todo-app/
  ├── components/
  ├── pages/
  ├── services/
  ├── styles/
  ├── utils/
  ├── ... (その他のディレクトリ)

2.4 サンプルコード

pages/index.tsx

tsx

import React from 'react'
import { useQuery } from 'react-query'
import axios from 'axios'

const fetchTodos = async () => {
  const { data } = await axios.get('/api/todos')
  return data
}

const Home: React.FC = () => {
  const { data, error, isLoading } = useQuery('todos', fetchTodos)

  if (isLoading) return <div>Loading...</div>
  if (error) return <div>Error!</div>

  return (
    <div>
      <h1>To Do List</h1>
      <ul>
        {data.map((todo: { id: number, title: string }) => (
          <li key={todo.id}>{todo.title}</li>
        ))}
      </ul>
    </div>
  )
}

export default Home

3. バックエンド: NestJSのセットアップ

3.1 プロジェクトの作成

nest new todo-api
cd todo-api

3.2 依存関係のインストール PostgreSQLドライバ、およびTypeORMをインストールします。

npm install @nestjs/typeorm typeorm pg

3.3 フォルダ構成

以下のようなフォルダ構成を作成します。

todo-api/
  ├── src/
      ├── modules/
      ├── entities/
      ├── repositories/
      ├── ...

3.4 サンプルコード

src/app.module.ts

TypeScript

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule } from '@nestjs/config';
import { TodoModule } from './modules/todo.module';

@Module({
  imports: [
    ConfigModule.forRoot(),
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: process.env.DB_HOST,
      port: Number(process.env.DB_PORT),
      username: process.env.DB_USER,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_NAME,
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true, 
    }),
    TodoModule,
  ],
})
export class AppModule {}

src/modules/todo.module.ts

TypeScript

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TodoService } from './todo.service';
import { TodoController } from './todo.controller';
import { Todo } from '../entities/todo.entity';

@Module({
  imports: [TypeOrmModule.forFeature([Todo])],
  providers: [TodoService],
  controllers: [TodoController],
})
export class TodoModule {}
src/entities/todo.entity.ts

TypeScript

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Todo {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  title: string;

  @Column({ default: false })
  completed: boolean;
}
src/modules/todo.service.ts

TypeScript

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Todo } from '../entities/todo.entity';

@Injectable()
export class TodoService {
  constructor(
    @InjectRepository(Todo)
    private readonly todoRepository: Repository<Todo>
  ) {}

  findAll(): Promise<Todo[]> {
    return this.todoRepository.find();
  }
}
src/modules/todo.controller.ts

TypeScript

import { Controller, Get } from '@nestjs/common';
import { TodoService } from './todo.service';
import { Todo } from '../entities/todo.entity';

@Controller('todos')
export class TodoController {
  constructor(private readonly todoService: TodoService) {}

  @Get()
  async findAll(): Promise<Todo[]> {
    return this.todoService.findAll();
  }
}

4. データベース設定(RLSの設定)

4.1 PostgreSQLの設定

PostgreSQLの設定データベースやユーザーを作成します。例として、todosデータベースを作成します。

sql

CREATE DATABASE todos;
CREATE USER todo_user WITH ENCRYPTED PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE todos TO todo_user;
次に、RLS (行レベルセキュリティ) を有効にします。

sql

-- 多分野のテーブル作成
CREATE TABLE todos (
  id SERIAL PRIMARY KEY,
  title VARCHAR(255) NOT NULL,
  completed BOOLEAN DEFAULT false,
  tenant_id INT NOT NULL
);

-- テナントIDでRLSのポリシーを設定
ALTER TABLE todos ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation_policy ON todos
USING (tenant_id = current_setting('myapp.current_tenant')::int);
RLSが有効な状態で、特定のテナントのみがそのテナントデータにアクセスできるようにします。

4.2 環境変数の設定

.env ファイルを作成し、設定を追加します

DB_HOST=localhost
DB_PORT=5432
DB_USER=todo_user
DB_PASSWORD=password
DB_NAME=todos
SuzukiTakamasa commented 3 months ago

メモ: バックエンドのバリデーションにはZodを使用することにする