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を作成する
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を作成する
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を作成する
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を作成する
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
①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を作成する
<!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を修正する
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を作成する
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を作成する
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を作成する
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を編集する
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を作成する
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を作成する
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を作成する
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を修正する
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を修正する
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を修正する
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を修正する
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を修正する
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を修正する
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を修正する
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を修正する
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を修正する
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クローンを作成し、実践的にバックエンドを学ぼう