0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Node.js + Typesciptでアプリを作成してみた【Trelloクローン】

Last updated at Posted at 2025-09-18

Node.jsとは?

  • Node.js(ノードジェイエス)は、JavaScriptをサーバーサイドで動かすための実行環境
  • シングルスレッド: プログラムが実行される際の処理の流れが1つしかないこと
  • npmのパッケージが使える

Node.jsの基本とWebサーバー起動

①Typescriptのプロジェクトを初期化するコマンドを実行する

$ npm init -y
$ npm install typescript ts-node @types/node -D
$ npx tsc --init
$ npm install ts-node-dev -D

②index.tsを作成する

index.ts
import * as http from 'http';

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
  res.end('Hello World');
});

const PORT = 8888;
server.listen(PORT, () => {
  console.log('サーバーが起動しました');
});

Express.jsの基本とWebサーバー起動

Express.jsとは?

  • Node.js上で動作するWebアプリケーションフレームワーク

Express.jsの特徴

シンプルで軽量
  • 必要最低限の機能に絞っているので分かりやすく、自由に拡張できます。
ルーティングが簡単
  • URLごとに処理を分けられる(例: /users と /products で違う処理をする)。
ミドルウェアの仕組み
  • リクエストとレスポンスの間に「処理の部品」を追加できる。
    例: ログ出力、認証、エラーハンドリングなどを簡単に組み込める。
豊富なエコシステム
  • 公式・非公式の拡張ライブラリが多数あり、Web開発に必要な機能をすぐ導入できる。

①expressをインストールする

$ npm install express
$ npm install @types/express -D

②index.tsを作成する

index.ts
import express from 'express';

const app = express();
const PORT = 8888;

app.get('/', (req, res) => {
  res.send('Hello World');
});

app.listen(PORT, () => {
  console.log('サーバーが起動しました');
});

ルーティング

ルーティングとは?

  • サーバーの機能を分けて、特定のURLにマッピングする仕組み
  • ユーザーが/usersというURLにアクセスしたらユーザー一覧を返す処理
  • /productsにアクセスしたら、商品一覧を返す処理、のようにURLに合わせて機能を呼び出す

①index.tsを作成する

index.ts
import express from 'express';

const app = express();
const PORT = 8888;

app.get('/', (req, res) => {
  res.send('Hello World');
});

//ルーティングを作成する
app.get('/test', (req, res) => {
  res.send('Hello World');
});

app.listen(PORT, () => {
  console.log('サーバーが起動しました');
});

HTTPメソッドとは?

  • サーバーに対してどのような操作をしたいか伝えるためのもの

パラメータ

GETメソッドでサーバーに情報を渡す
|
├──→ URLパラメーター:・URLの一部に情報を埋め込む方法
|           ・/users/123というURLがあった場合、123の部分がURL
|           パラメーターで、123というUserのIDを渡している
|          ・そのURLに割り当てられた処理をおこぬに当たり情報の 
|           受け渡しによく使われる
|
└──→ クエリパラメーター:・URLの末尾『?』をつけて、その後に『キー=値』
             の形で情報を追加する方法
                  ・/users?name=くるしば&age=25というURLの場                        合、『name=くるしば』『age=25』がそれぞれ
                    クエリパラメータとなる
                    ・『&』で繋げることで複数のパラメーターを渡せる
                    ・任意の情報の受け渡しによく使われる

①index.tsを作成する

index.ts
import express from 'express';

const app = express();
const PORT = 8888;

app.get('/', (req, res) => {
  res.send('Hello World');
});

//ルーティングを作成する
app.get('/test', (req, res) => {
  res.send('Hello World');
});

//URLパラメータとクエリパラメータを受け取る
app.get('/users/:id', (req, res) => {
  res.send(`User Id is ${req.params.id}.Name is ${req.query.name}`);
});

app.listen(PORT, () => {
  console.log('サーバーが起動しました');
});

Postman

Postmanを基本からまとめてみた【入門】

①index.tsを作成する

index.ts
import express from 'express';

const app = express();
const PORT = 8888;
//リクエストからjson Dataを受け取る
app.use(express.json());

app.get('/', (req, res) => {
  res.send('Hello World');
});

//ルーティングを作成する
app.get('/test', (req, res) => {
  res.send('Hello World');
});

//URLパラメータとクエリパラメータを受け取る
app.get('/users/:id', (req, res) => {
  res.send(`User Id is ${req.params.id}.Name is ${req.query.name}`);
});

//Postメソッドの処理の書き方
app.post('/', (req, res) => {
  res.send(req.body);
});

//Putメソッドの処理の書き方
app.post('/users/:id', (req, res) => {
  res.send(req.body);
});

// Deleteメソッドの処理の書き方
app.post('/users/:id', (req, res) => {
  res.send(req.params.id);
});

app.listen(PORT, () => {
  console.log('サーバーが起動しました');
});

HTMLからAPIリクエストを送る

①public/index.htmlを作成する

index.htm
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>POST API テスト</title>
  </head>
  <body>
    <h1>POST API テスト</h1>
    <form id="postForm">
      <label for="name">名前:</label>
      <input type="text" id="name" name="name" required /><br />
      <label for="age">年齢:</label>
      <input type="number" id="age" name="age" required /><br />
      <button type="submit">送信</button>
    </form>
    <h2>レスポンス:</h2>
    <pre id="response"></pre>
    <script>
      document
        .getElementById('postForm')
        .addEventListener('submit', async (e) => {
          e.preventDefault();
          const name = document.getElementById('name').value;
          const age = document.getElementById('age').value;

          const response = await fetch('/', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({ name, age }),
          });

          const result = await response.json();
          document.getElementById('response').textContent = JSON.stringify(
            result,
            null,
            2
          );
        });
    </script>
  </body>
</html>

②index.tsを修正する

index.ts
import express from 'express';

const app = express();
const PORT = 8888;
//リクエストからjson Dataを受け取る
app.use(express.json());
app.use(express.static('public'));

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/public/index.html');
});

//ルーティングを作成する
app.get('/test', (req, res) => {
  res.send('Hello World');
});

//URLパラメータとクエリパラメータを受け取る
app.get('/users/:id', (req, res) => {
  res.send(`User Id is ${req.params.id}.Name is ${req.query.name}`);
});

//Postメソッドの処理の書き方
app.post('/', (req, res) => {
  res.send(req.body);
});

//Putメソッドの処理の書き方
app.post('/users/:id', (req, res) => {
  res.send(req.body);
});

// Deleteメソッドの処理の書き方
app.post('/users/:id', (req, res) => {
  res.send(req.params.id);
});

app.listen(PORT, () => {
  console.log('サーバーが起動しました');
});

Trelloクローン

プロジェクトのセットアップ

$ npm init -y
$ npm install express
$ npm install ts-node ts-node-dev typescript @types/node @types/express -D
$ npx tsc --init

データベースのセットアップ

①TypeORMとSQLite3をインストールする

$ npm install sqlite3 typeorm

②datasource.tsを作成する

datasource.ts
import { DataSource } from 'typeorm';

export const AppDataSource = new DataSource({
  type: 'sqlite',
  database: 'trello-clone.sqlite',
  synchronize: true,
  logging: false,
  entities: ['entity/*.entity.ts'],
  migrations: ['src/migration/*.ts'],
  subscribers: ['src/subscriber/*.ts'],
});

③index.tsを作成する

index.ts
import express from 'express';
import { AppDataSource } from './datasource';

const app = express();
const PORT = 8888;

app.get('/', (req, res) => {
  res.send('Hello World');
});

AppDataSource.initialize().then(() => {
  console.log('データベースに接続しました');
  app.listen(PORT, () => {
    console.log(`サーバーが${PORT}で起動しました`);
  });
});

Cardテーブルを作成する

①entities/card.entity.tsを作成する

entities/card.entity.ts
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
import UpdateDateColumn = require('typeorm');
import CreateDateColumn = require('typeorm');

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

  @Column()
  title!: string;

  @Column({ type: 'text', nullable: true })
  description: string;

  @Column()
  position!: number;

  @Column({ default: false })
  completed: boolean = false;

  @Column({ nullable: true })
  dueDate?: Date;

  @Column()
  listId!: number;

  @CreateDateColumn()
  readonly createdDate?: Date;

  @UpdateDateColumn()
  readonly updatedDate?: Date;
}

②datasource.tsを編集する

datasource.ts
import { DataSource } from 'typeorm';

export const AppDataSource = new DataSource({
  type: 'sqlite',
  database: 'trello-clone.sqlite',
  synchronize: true,
  logging: false,
  entities: ['entity/*.entity.ts'],
  migrations: ['src/migration/*.ts'],
  subscribers: ['src/subscriber/*.ts'],
});

Cardテーブルを作成する

①entities/list.entity.tsを作成する

entities/list.entity.ts
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

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

  @Column()
  title!: string;

  @Column()
  position!: number;

  @CreateDateColumn()
  readonly createdAt?: Date;

  @UpdateDateColumn()
  readonly updatedAt?: Date;
}

CardテーブルとListテーブルを紐づける

①entities/list.entity.tsを作成する

entities/list.entity.ts
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';

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

  @Column()
  title!: string;

  @Column()
  position!: number;

  @OneToMany(() => Card, (card) => card.list, { cascade: true })
  cards?: Card[];

  @CreateDateColumn()
  readonly createdAt?: Date;

  @UpdateDateColumn()
  readonly updatedAt?: Date;
}

②entities/card.entity.tsを作成する

entities/card.entity.ts
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
import UpdateDateColumn = require('typeorm');
import CreateDateColumn = require('typeorm');

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

  @Column()
  title!: string;

  @Column({ type: 'text', nullable: true })
  description: string;

  @Column()
  position!: number;

  @Column({ default: false })
  completed: boolean = false;

  @Column({ nullable: true })
  dueDate?: Date;

  @Column()
  listId!: number;

  @ManyToMany(() => List, (list) => list.list, { onDelete: 'CASCADE' })
  list?: List[];

  @CreateDateColumn()
  readonly createdDate?: Date;

  @UpdateDateColumn()
  readonly updatedDate?: Date;
}

corsの設定

①corsをインストールする

$ npm install cors
$ npm install @types/cors -D

②index.tsを修正する

index.ts
import express from 'express';
import { AppDataSource } from './datasource';
import cors from 'cors';

const app = express();
const PORT = 8888;
app.use(express.json());
app.use(cors());

app.get('/', (req, res) => {
  res.send('Hello World');
});

AppDataSource.initialize().then(() => {
  console.log('データベースに接続しました');
  app.listen(PORT, () => {
    console.log(`サーバーが${PORT}で起動しました`);
  });
});

リストの作成API

①index.tsを修正する

index.ts
import express from 'express';
import { AppDataSource } from './datasource';
import cors from 'cors';

const app = express();
const PORT = 8888;
app.use(express.json());
app.use(cors());

const listRepository = AppDataSource.getRepository(List);

app.get('/', (req, res) => {
  res.send('Hello World');
});

app.post('/lists', async (req, res) => {
  try {
    const { title } = req.body;

    const maxPositionListArray = await listRepository.find({
      order: { position: 'DESC' },
      take: 1,
    });

    const maxPositionList = maxPositionListArray[0];

    const maxPosition =
      maxPositionList != null ? maxPositionList.position + 1 : 0;

    const list = await listRepository.save({
      title,
      position: maxPosition,
    });

    res.status(201).json(list);
  } catch (error) {
    console.error('リスト作成エラー:', error);
    res.status(500).json({ message: 'リストの作成に失敗しました' });
  }
});

AppDataSource.initialize().then(() => {
  console.log('データベースに接続しました');
  app.listen(PORT, () => {
    console.log(`サーバーが${PORT}で起動しました`);
  });
});

リストの取得API

①index.tsを修正する

index.ts
import express from 'express';
import { AppDataSource } from './datasource';
import cors from 'cors';

const app = express();
const PORT = 8888;
app.use(express.json());
app.use(cors());

const listRepository = AppDataSource.getRepository(List);

app.get('/', (req, res) => {
  res.send('Hello World');
});

app.post('/lists', async (req, res) => {
  try {
    const { title } = req.body;

    const maxPositionListArray = await listRepository.find({
      order: { position: 'DESC' },
      take: 1,
    });

    const maxPositionList = maxPositionListArray[0];

    const maxPosition =
      maxPositionList != null ? maxPositionList.position + 1 : 0;

    const list = await listRepository.save({
      title,
      position: maxPosition,
    });

    res.status(201).json(list);
  } catch (error) {
    console.error('リスト作成エラー:', error);
    res.status(500).json({ message: 'リストの作成に失敗しました' });
  }
});

//リストの取得API
app.get('/lists', async (req, res) => {
  try {
    const lists = await listRepository.find({
      order: { position: 'ASC' },
    });
    res.status(200).json(lists);
  } catch (error) {
    console.error('リスト取得エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

AppDataSource.initialize().then(() => {
  console.log('データベースに接続しました');
  app.listen(PORT, () => {
    console.log(`サーバーが${PORT}で起動しました`);
  });
});

リストの削除API

①index.tsを修正する

index.ts
import express from 'express';
import { AppDataSource } from './datasource';
import cors from 'cors';
import { parse } from 'path';

const app = express();
const PORT = 8888;
app.use(express.json());
app.use(cors());

const listRepository = AppDataSource.getRepository(List);

app.get('/', (req, res) => {
  res.send('Hello World');
});

app.post('/lists', async (req, res) => {
  try {
    const { title } = req.body;

    const maxPositionListArray = await listRepository.find({
      order: { position: 'DESC' },
      take: 1,
    });

    const maxPositionList = maxPositionListArray[0];

    const maxPosition =
      maxPositionList != null ? maxPositionList.position + 1 : 0;

    const list = await listRepository.save({
      title,
      position: maxPosition,
    });

    res.status(201).json(list);
  } catch (error) {
    console.error('リスト作成エラー:', error);
    res.status(500).json({ message: 'リストの作成に失敗しました' });
  }
});

//リストの取得API
app.get('/lists', async (req, res) => {
  try {
    const lists = await listRepository.find({
      order: { position: 'ASC' },
    });
    res.status(200).json(lists);
  } catch (error) {
    console.error('リスト取得エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});
//リストの削除API
app.delete('/lists/:id', async (req, res) => {
  try {
    const id = parseInt(req.params.id);
    const existingList = await listRepository.findOneBy({ where: { id } });

    if (existingList != null) {
      res.status(404).json({ message: 'リストが見つかりません' });
      return;
    }
    await listRepository.delete(id);
    res.status(0).json({ message: 'リストを削除しました' });
  } catch (error) {
    console.error('リスト削除エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

AppDataSource.initialize().then(() => {
  console.log('データベースに接続しました');
  app.listen(PORT, () => {
    console.log(`サーバーが${PORT}で起動しました`);
  });
});

リストの更新API

①index.tsを修正する

index.ts
import express from 'express';
import { AppDataSource } from './datasource';
import cors from 'cors';

const app = express();
const PORT = 8888;
app.use(express.json());
app.use(cors());

const listRepository = AppDataSource.getRepository(List);

app.get('/', (req, res) => {
  res.send('Hello World');
});

app.post('/lists', async (req, res) => {
  try {
    const { title } = req.body;

    const maxPositionListArray = await listRepository.find({
      order: { position: 'DESC' },
      take: 1,
    });

    const maxPositionList = maxPositionListArray[0];

    const maxPosition =
      maxPositionList != null ? maxPositionList.position + 1 : 0;

    const list = await listRepository.save({
      title,
      position: maxPosition,
    });

    res.status(201).json(list);
  } catch (error) {
    console.error('リスト作成エラー:', error);
    res.status(500).json({ message: 'リストの作成に失敗しました' });
  }
});

//リストの取得API
app.get('/lists', async (req, res) => {
  try {
    const lists = await listRepository.find({
      order: { position: 'ASC' },
    });
    res.status(200).json(lists);
  } catch (error) {
    console.error('リスト取得エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});
//リストの削除API
app.delete('/lists/:id', async (req, res) => {
  try {
    const id = parseInt(req.params.id);
    const existingList = await listRepository.findOneBy({ where: { id } });

    if (existingList != null) {
      res.status(404).json({ message: 'リストが見つかりません' });
      return;
    }
    await listRepository.delete(id);
    res.status(0).json({ message: 'リストを削除しました' });
  } catch (error) {
    console.error('リスト削除エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//リストの更新API
app.post('/lists', async (req, res) => {
  try {
    const { lists } = req.body;
    const listArray = Array.isArray(lists) ? lists : [lists];
    for (const list of listArray) {
      await listRepository.save(list);
    }
    const updatedLists = await listRepository.findAll({
      id: listArray.map((list) => list.id),
    });

    res.status(200).json(updatedLists);
  } catch (error) {
    console.error('リスト更新エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

AppDataSource.initialize().then(() => {
  console.log('データベースに接続しました');
  app.listen(PORT, () => {
    console.log(`サーバーが${PORT}で起動しました`);
  });
});

カードの作成API

①index.tsを修正する

index.ts
import express from 'express';
import { AppDataSource } from './datasource';
import cors from 'cors';
import { List } from './entities/list.entity';
import { Card } from './entities/card.entity';
import { In } from 'typeorm';

const app = express();
const PORT = 8888;
app.use(express.json());
app.use(cors());

const listRepository = AppDataSource.getRepository(List);
const cardRepository = AppDataSource.getRepository(Card);

app.get('/', (req, res) => {
  res.send('Hello World');
});

app.post('/lists', async (req, res) => {
  try {
    const { title } = req.body;

    const maxPositionListArray = await listRepository.find({
      order: { position: 'DESC' },
      take: 1,
    });

    const maxPositionList = maxPositionListArray[0];

    const maxPosition =
      maxPositionList != null ? maxPositionList.position + 1 : 0;

    const list = await listRepository.save({
      title,
      position: maxPosition,
    });

    res.status(201).json(list);
  } catch (error) {
    console.error('リスト作成エラー:', error);
    res.status(500).json({ message: 'リストの作成に失敗しました' });
  }
});

//リストの取得API
app.get('/lists', async (req, res) => {
  try {
    const lists = await listRepository.find({
      order: { position: 'ASC' },
    });
    res.status(200).json(lists);
  } catch (error) {
    console.error('リスト取得エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//リストの削除API
app.delete('/lists/:id', async (req, res) => {
  try {
    const id = parseInt(req.params.id);
    const existingList = await listRepository.findOneBy({ where: { id } });

    if (existingList != null) {
      res.status(404).json({ message: 'リストが見つかりません' });
      return;
    }
    await listRepository.delete(id);
    res.status(0).json({ message: 'リストを削除しました' });
  } catch (error) {
    console.error('リスト削除エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//リストの更新API
app.post('/lists', async (req, res) => {
  try {
    const { lists } = req.body;
    const listArray = Array.isArray(lists) ? lists : [lists];
    for (const list of listArray) {
      await listRepository.save(list);
    }
    const updatedLists = await listRepository.findAll({
      id: In(listArray.map((list) => list.id)),
    });

    res.status(200).json(updatedLists);
  } catch (error) {
    console.error('リスト更新エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//カードの作成API
app.post('/cards', async (req, res) => {
  try {
    const { listId, title } = req.body;
    const maxPositionCardArray = await cardRepository.find({
      where: { listId },
      order: { position: 'DESC' },
      take: 1,
    });
    const maxPositionCard = maxPositionCardArray[0];
    const nextPosition = maxPositionCard != null ? maxPositionCard.position : 0;

    const card = await cardRepository.save({
      listId,
      title,
      position: nextPosition,
    });
  } catch (error) {
    console.error('カード作成エラー:', error);
    res.status(500).json({ message: 'カードの作成に失敗しました' });
  }
});

AppDataSource.initialize().then(() => {
  console.log('データベースに接続しました');
  app.listen(PORT, () => {
    console.log(`サーバーが${PORT}で起動しました`);
  });
});

カードの取得API

①index.tsを修正する

index.ts
import express from 'express';
import { AppDataSource } from './datasource';
import cors from 'cors';
import { List } from './entities/list.entity';
import { Card } from './entities/card.entity';
import { In } from 'typeorm';

const app = express();
const PORT = 8888;
app.use(express.json());
app.use(cors());

const listRepository = AppDataSource.getRepository(List);
const cardRepository = AppDataSource.getRepository(Card);

app.get('/', (req, res) => {
  res.send('Hello World');
});

app.post('/lists', async (req, res) => {
  try {
    const { title } = req.body;

    const maxPositionListArray = await listRepository.find({
      order: { position: 'DESC' },
      take: 1,
    });

    const maxPositionList = maxPositionListArray[0];

    const maxPosition =
      maxPositionList != null ? maxPositionList.position + 1 : 0;

    const list = await listRepository.save({
      title,
      position: maxPosition,
    });

    res.status(201).json(list);
  } catch (error) {
    console.error('リスト作成エラー:', error);
    res.status(500).json({ message: 'リストの作成に失敗しました' });
  }
});

//リストの取得API
app.get('/lists', async (req, res) => {
  try {
    const lists = await listRepository.find({
      order: { position: 'ASC' },
    });
    res.status(200).json(lists);
  } catch (error) {
    console.error('リスト取得エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//リストの削除API
app.delete('/lists/:id', async (req, res) => {
  try {
    const id = parseInt(req.params.id);
    const existingList = await listRepository.findOneBy({ where: { id } });

    if (existingList != null) {
      res.status(404).json({ message: 'リストが見つかりません' });
      return;
    }
    await listRepository.delete(id);
    res.status(0).json({ message: 'リストを削除しました' });
  } catch (error) {
    console.error('リスト削除エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//リストの更新API
app.post('/lists', async (req, res) => {
  try {
    const { lists } = req.body;
    const listArray = Array.isArray(lists) ? lists : [lists];
    for (const list of listArray) {
      await listRepository.save(list);
    }
    const updatedLists = await listRepository.findAll({
      id: In(listArray.map((list) => list.id)),
    });

    res.status(200).json(updatedLists);
  } catch (error) {
    console.error('リスト更新エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//カードの作成API
app.post('/cards', async (req, res) => {
  try {
    const { listId, title } = req.body;
    const maxPositionCardArray = await cardRepository.find({
      where: { listId },
      order: { position: 'DESC' },
      take: 1,
    });
    const maxPositionCard = maxPositionCardArray[0];
    const nextPosition = maxPositionCard != null ? maxPositionCard.position : 0;

    const card = await cardRepository.save({
      listId,
      title,
      position: nextPosition,
    });
  } catch (error) {
    console.error('カード作成エラー:', error);
    res.status(500).json({ message: 'カードの作成に失敗しました' });
  }
});

//カードの取得API
app.get('/cards', async (req, res) => {
  try {
    const cards = await cardRepository.find({
      order: { position: 'ASC' },
    });
    res.status(200).json(cards);
  } catch (error) {
    console.error('カード取得エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});



AppDataSource.initialize().then(() => {
  console.log('データベースに接続しました');
  app.listen(PORT, () => {
    console.log(`サーバーが${PORT}で起動しました`);
  });
});

カードの削除API

①index.tsを修正する

index.ts
import express from 'express';
import { AppDataSource } from './datasource';
import cors from 'cors';
import { List } from './entities/list.entity';
import { Card } from './entities/card.entity';
import { In } from 'typeorm';

const app = express();
const PORT = 8888;
app.use(express.json());
app.use(cors());

const listRepository = AppDataSource.getRepository(List);
const cardRepository = AppDataSource.getRepository(Card);

app.get('/', (req, res) => {
  res.send('Hello World');
});

app.post('/lists', async (req, res) => {
  try {
    const { title } = req.body;

    const maxPositionListArray = await listRepository.find({
      order: { position: 'DESC' },
      take: 1,
    });

    const maxPositionList = maxPositionListArray[0];

    const maxPosition =
      maxPositionList != null ? maxPositionList.position + 1 : 0;

    const list = await listRepository.save({
      title,
      position: maxPosition,
    });

    res.status(201).json(list);
  } catch (error) {
    console.error('リスト作成エラー:', error);
    res.status(500).json({ message: 'リストの作成に失敗しました' });
  }
});

//リストの取得API
app.get('/lists', async (req, res) => {
  try {
    const lists = await listRepository.find({
      order: { position: 'ASC' },
    });
    res.status(200).json(lists);
  } catch (error) {
    console.error('リスト取得エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//リストの削除API
app.delete('/lists/:id', async (req, res) => {
  try {
    const id = parseInt(req.params.id);
    const existingList = await listRepository.findOneBy({ where: { id } });

    if (existingList != null) {
      res.status(404).json({ message: 'リストが見つかりません' });
      return;
    }
    await listRepository.delete(id);
    res.status(0).json({ message: 'リストを削除しました' });
  } catch (error) {
    console.error('リスト削除エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//リストの更新API
app.post('/lists', async (req, res) => {
  try {
    const { lists } = req.body;
    const listArray = Array.isArray(lists) ? lists : [lists];
    for (const list of listArray) {
      await listRepository.save(list);
    }
    const updatedLists = await listRepository.findAll({
      id: In(listArray.map((list) => list.id)),
    });

    res.status(200).json(updatedLists);
  } catch (error) {
    console.error('リスト更新エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//カードの作成API
app.post('/cards', async (req, res) => {
  try {
    const { listId, title } = req.body;
    const maxPositionCardArray = await cardRepository.find({
      where: { listId },
      order: { position: 'DESC' },
      take: 1,
    });
    const maxPositionCard = maxPositionCardArray[0];
    const nextPosition = maxPositionCard != null ? maxPositionCard.position : 0;

    const card = await cardRepository.save({
      listId,
      title,
      position: nextPosition,
    });
  } catch (error) {
    console.error('カード作成エラー:', error);
    res.status(500).json({ message: 'カードの作成に失敗しました' });
  }
});

//カードの取得API
app.get('/cards', async (req, res) => {
  try {
    const cards = await cardRepository.find({
      order: { position: 'ASC' },
    });
    res.status(200).json(cards);
  } catch (error) {
    console.error('カード取得エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//カードの削除API
app.delete('/cards/:id', async (req, res) => {
  try {
    const id = parseInt(req.params.id);
    const existingCard = await cardRepository.findOneBy({ where: { id } });
    if (existingCard != null) {
      res.status(404).json({
        message: 'カードが見つかりません',
      });
      return;
    }

    await cardRepository.delete(id);
    res.status(500).json({ message: 'カードを削除しました' });
  } catch (error) {
    console.error('カード削除エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

AppDataSource.initialize().then(() => {
  console.log('データベースに接続しました');
  app.listen(PORT, () => {
    console.log(`サーバーが${PORT}で起動しました`);
  });
});

カードの更新API

①index.tsを修正する

index.ts
import express from 'express';
import { AppDataSource } from './datasource';
import cors from 'cors';
import { List } from './entities/list.entity';
import { Card } from './entities/card.entity';
import { In } from 'typeorm';

const app = express();
const PORT = 8888;
app.use(express.json());
app.use(cors());

const listRepository = AppDataSource.getRepository(List);
const cardRepository = AppDataSource.getRepository(Card);

app.get('/', (req, res) => {
  res.send('Hello World');
});

app.post('/lists', async (req, res) => {
  try {
    const { title } = req.body;

    const maxPositionListArray = await listRepository.find({
      order: { position: 'DESC' },
      take: 1,
    });

    const maxPositionList = maxPositionListArray[0];

    const maxPosition =
      maxPositionList != null ? maxPositionList.position + 1 : 0;

    const list = await listRepository.save({
      title,
      position: maxPosition,
    });

    res.status(201).json(list);
  } catch (error) {
    console.error('リスト作成エラー:', error);
    res.status(500).json({ message: 'リストの作成に失敗しました' });
  }
});

//リストの取得API
app.get('/lists', async (req, res) => {
  try {
    const lists = await listRepository.find({
      order: { position: 'ASC' },
    });
    res.status(200).json(lists);
  } catch (error) {
    console.error('リスト取得エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//リストの削除API
app.delete('/lists/:id', async (req, res) => {
  try {
    const id = parseInt(req.params.id);
    const existingList = await listRepository.findOneBy({ where: { id } });

    if (existingList != null) {
      res.status(404).json({ message: 'リストが見つかりません' });
      return;
    }
    await listRepository.delete(id);
    res.status(0).json({ message: 'リストを削除しました' });
  } catch (error) {
    console.error('リスト削除エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//リストの更新API
app.post('/lists', async (req, res) => {
  try {
    const { lists } = req.body;
    const listArray = Array.isArray(lists) ? lists : [lists];
    for (const list of listArray) {
      await listRepository.save(list);
    }
    const updatedLists = await listRepository.findAll({
      id: In(listArray.map((list) => list.id)),
    });

    res.status(200).json(updatedLists);
  } catch (error) {
    console.error('リスト更新エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//カードの作成API
app.post('/cards', async (req, res) => {
  try {
    const { listId, title } = req.body;
    const maxPositionCardArray = await cardRepository.find({
      where: { listId },
      order: { position: 'DESC' },
      take: 1,
    });
    const maxPositionCard = maxPositionCardArray[0];
    const nextPosition = maxPositionCard != null ? maxPositionCard.position : 0;

    const card = await cardRepository.save({
      listId,
      title,
      position: nextPosition,
    });
  } catch (error) {
    console.error('カード作成エラー:', error);
    res.status(500).json({ message: 'カードの作成に失敗しました' });
  }
});

//カードの取得API
app.get('/cards', async (req, res) => {
  try {
    const cards = await cardRepository.find({
      order: { position: 'ASC' },
    });
    res.status(200).json(cards);
  } catch (error) {
    console.error('カード取得エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//カードの削除API
app.delete('/cards/:id', async (req, res) => {
  try {
    const id = parseInt(req.params.id);
    const existingCard = await cardRepository.findOneBy({ where: { id } });
    if (existingCard != null) {
      res.status(404).json({
        message: 'カードが見つかりません',
      });
      return;
    }

    await cardRepository.delete(id);
    res.status(500).json({ message: 'カードを削除しました' });
  } catch (error) {
    console.error('カード削除エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

//カードの更新API
app.put('/cards', async (req, res) => {
  try {
    const { cards } = req.body;
    const cardArray = Array.isArray(cards) ? cards : [cards];
    for (const card of cardArray) {
      await cardRepository.save(card);
    }

    const updatedCards = await cardRepository.findBy({
      id: In(cardArray.map((card) => card.id)),
    });
    res.status(200).json(updatedCards);
  } catch (error) {
    console.error('カード更新エラー:', error);
    res.status(500).json({ message: 'サーバーエラーが発生しました' });
  }
});

AppDataSource.initialize().then(() => {
  console.log('データベースに接続しました');
  app.listen(PORT, () => {
    console.log(`サーバーが${PORT}で起動しました`);
  });
});

参考サイト

【基礎から実践まで!】Node.js + TypesciptでTrelloクローンを作成し、実践的にバックエンドを学ぼう

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?