LoginSignup
35
34

More than 1 year has passed since last update.

Express + TypeScript + MongoDBでCRUD操作

Last updated at Posted at 2020-06-20

はじめに

Expressは、Node.jsのWebアプリケーションでもっとも利用されているフレームワークです。Expressは、HTTPによるWeb上の相互作用とNode.jsプラットフォームの中間に位置するので、ある種のミドルウェアと言えます。
Expressを利用して、MVCモデルのアプリケーションを開発してみます。

データベースにはMongoDBを利用します。MondoDBはドキュメント型のNoSQLであり、JSONの構造をそのままデータとして保存することができます。
MongoDBは以下のような特徴を持ちます。

  • トランザクションを持っていないが、データの読み書きはRDBよりも早い
  • スキーマがない
  • クエリはJavaScriptで行う
  • SQLのGROUP BYのような集約クエリを持っている

さらに、今回TypeScriptを導入してみます。
TypeScriptの型定義により、より安全なコードとエディタのインテリセンスによる開発体験の向上を狙います。

開発環境の構築

さっそく初めていきますが、まずはコードが動く最小限のところから初めます。

適当な場所でディレクトリを作成して移動しましょう。

mkdir express-ts
cd express-ts

npm init -yでプロジェクトルートにpackage.jsonを設置します。

{
  "name": "express-ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

expressをインストールします。


npm i express 

TypeScriptや型定義、TypeScriptコードのままExpressサーバーを実行するためのts-node-devをインストールします。

npm i -D typescript @types/node @types/express ts-node-dev

サーバーを起動するためのnpm scriptをpackage.jsonに記述しておきましょう。

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "serve": "ts-node-dev src/main.ts"
  },

最終的にpackage.jsonは次のようになります。

{
  "name": "express-ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "serve": "ts-node-dev src/main.ts"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "@types/express": "^4.17.6",
    "@types/node": "^14.0.13",
    "ts-node-dev": "^1.0.0-pre.44",
    "typescript": "^3.9.5"
  }
}

最後に、tsconfig.jsontsc --initで生成します。

生成できたら、"moduleResolution": "node"のコメントを外します。

{
  "compilerOptions": {
    "target": "es5" ,
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true ,
    "forceConsistentCasingInFileNames": true
  }
}

簡単なExpressサーバー

これで環境構築は終了です。ちゃんと動くか試しに簡単な「Hello」と出力するサーバを構築してみます。

srcフォルダを作成し、その中にmain.tsというファイルを作成してください。

src/main.ts
import Express from 'express'

const app = Express()
const port = 3000

app.get('/', (req, res) => {
  const data = { message: 'Hello' }
  res.send(data)
})

app.listen(port, () => {
  console.log('server start')
})

Expressモジュールには、Webサーバー機能を組み込んだクラスが含まれています。そのExpressアプリケーションを実体化したものを慣例的にappという変数に代入して使用します。

app.get()はGETリクエストを処理します。第一引数でパスを受け取り、第二引数でコールバックをうけとります。

npm run serveでアプリケーションを実行して、http://localhost:3000へアクセスしましょう。メッセージがレスポンスとして帰ってきているはずです。

ルーティングを設定する

サーバーからのレスポンスを受け取ることができたので、ルーティングを設定しましょう。

srcフォルダの下にroutesフォルダを作成し、index.tsファイルを配置します。
router/index.tsはすべてのルートをまとめるファイルです。

src/routes/index.ts
import Express from 'express'
import userRoutes from './userRoutes'
import homeRoutes from './homeRoutes'

const router = Express.Router()

router.use('/users', userRoutes)
router.use('/', homeRoutes)

export default router

Express.Router()はルーティングに関する機能を提供します。
router.use()で名前空間を追加します。
/usersというプレフィックがついたルートは、すべてuserRoutesモジュールのルートを利用します。

routesフォルダ配下にuserRoutes.tsファイルを作成して、/usersルートを作成します。

src/routes/userRoutes.ts

import Express from 'express'
import usersController from '../controllers/usersController'

const router = Express.Router()

router.get('/', usersController.index)

export default router

router.get('/', usersController.index)のルートは、/users/へGETリクエストを送ったときに処理されます。

ここでは、実際処理は直接コールバックを記述するのではなく、usersControllerに任せます。コントローラーは、ビューとモデルを結びつけ。リクエストを受信した時、適切なレスポンスを返します。

srcフォルダの下にcontrollersフォルダを作成し、usersController.tsを作成します。

src/controllers/usersController.ts

import Express from 'express'

export default {
  index: (req: Express.Request, res: Express.Response) => {
    res.send('<h1>User index</h1>')
  },
}

今はまだ簡単なレスポンスを返すだけです。型指定のためにexpressをインポートしています。

homeRoutes.tshomeController.tsも同じように作成します。

src/routes/homeRoutes.ts
import Express from 'express'
import homeController from '../controllers/homeController'

const router = Express.Router()

router.get('/', homeController.index)

export default router

src/controllers/homeController.ts
import Express from 'express'

export default {
  index: (req: Express.Request, res: Express.Response) => {
    res.send('<h1>Top Page</h1>')
  },
}

最後に、main.tsで作成したルーティングを使用するように編集します。

import Express from 'express'
import router from './routes'

const app = Express()
const port = 3000

app.use('/', router)

app.listen(port, () => {
  console.log('server start')
})

http://localhost:3000/http://localhost:3000/usersをそれぞれ訪れて、正しくルーティングが行われているか確認してみましょう。

スクリーンショット 20200613 21.14.32.png

スクリーンショット 20200613 21.14.48.png

ビューを作成する

静的ファイルを設定する

ルーティングを作成したところで、ルーティングとビューを接続してみましょう。
まずは、静的ファイルを使用するフォルダを作成します。

ここでは、srcフォルダにpublicフォルダを配置して、その中にimagescssjsフォルダを作成します。

そうしたら、src/main.tsファイル内でapp.use(Express.static('public'))と記述し、Expressに静的ファイルの置き場を教えます。

src/main.ts
import Express from 'express'
import router from './routes'

const app = Express()
const port = 3000

app.use(Express.static(__dirname + '/public'))
app.use('/', router)

app.listen(port, () => {
  console.log('server start')
})

public/cssにはBootstrapをダウンロードして、bootstrap.cssというファイル名で保存しておきます。

テンプレートエンジンを使用する

通常のHTMLファイルの代わりに、EJSと呼ばれるテンプレートエンジンを使用します。

EJSJavaScriptのテンプレートエンジンの一つで、動的に変数を受け渡したり、共通のレイアウトファイルを設定したり、再利用できるパーシャルを利用することができます。

まずは、EJSテンプレートパッケージをインストールします。

npm i express-ejs-layouts ejs

express-ejs-layoutsの型定義もインストールします。

npm i -D @types/express-ejs-layouts

さらに、main.tsでテンプレートエンジンとしてEJSを利用することを伝えます。

src/main.ts

import Express from 'express'
import path from 'path'
import router from './routes'
import layouts from 'express-ejs-layouts'

const app = Express()
const port = 3000

app.set('view engine', 'ejs')
app.set('views', path.resolve(__dirname, 'views'))
app.use(layouts)
app.use(Express.static(__dirname + '/public'))
app.use('/', router)

app.listen(port, () => {
  console.log('server start')
})

ejsファイルの作成

srcフォルダにviewsフォルダを作成し、layout.ejsファイルを作成します。
.ejsはEJSの拡張子です。

src/views/layout.ejs

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=0.8, maximum-scale=1">
  <title>Express </title>
  <link rel="stylesheet" href="/css/bootstrap.css">
</head>

<body>
  <header>
    <div id="nav">
      <div class="col-sm nav-align">
        <h1 id="title">Express</h1>
      </div>
      <div class="col-sm nav-align">
        <a href="/">
          <span class="button">Home</span>
        </a>
        <a href="/users">
          <span class="button">Users</span>
        </a>
      </div>
    </div>
  </header>

  <div class="container">
    <%- body %>
  </div>

  <footer>
    footer
  </footer>
</body>

</html>

レイアウトファイルには、<head>タグと全ページ共通であるヘッダーとフッターを配置します。
ボディ部分は、<%- body %>と記述されているところに描画されます。

ついで、usersフォルダを作成し、index.ejsを作成します。/usersにリクエストが送られたときに描画するビューを作成します。

src/views/users/index.ejs
<h1>ユーザー一覧</h1>
<table class="table">
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
    </tr>
  </thead>
  <tbody>
    <% users.forEach(user => { %>
      <tr>
        <td>
          <%= user.name %>
        </td>
        <td><%= user.email %></td>
      </tr>
    <% }) %>
  </tbody>
</table>

<% %>で囲まれている部分は、JavaScriptとして解釈されます。
コントローラーから渡されたデータを使用することができるので、受け取ったusers変数をforEachでループして個々のユーザーデータを表示しています。

コントローラーに戻り、データを渡してみましょう。

src/controllers/usersController.ts

import Express from 'express'
import * as User from '../models/userModel'

export default {
  index: (req: Express.Request, res: Express.Response) => {
    const users = User.find()
    res.render('users/index', { users })
  ,
}

res.render()の第一引数にviewsフォルダからみたパスを、第二引数にビューへ渡す変数をオブジェクトで渡します。

受け渡すデータはモデルから取得します。

srcフォルダ下にmodelsフォルダを作成し、userModel.tsファイルを作成します。

src/models/userModel.ts

type Sex = '' | ''

interface User {
  name: String
  email: String
  sex: Sex
  age: Number
}

const users: Array<User> = [
  {
    name: 'ユーザー1',
    email: 'user1@example.com',
    sex: '',
    age: 19,
  },
  {
    name: 'ユーザー2',
    email: 'user2@example.com',
    sex: '',
    age: 22,
  },
  {
    name: 'ユーザー3',
    email: 'user3@example.com',
    sex: '',
    age: 33,
  },
]

export function find(): Array<User> {
  return users
}

とりあえず、適当なダミーデータを用意しておきます。
Userモデルのfind()関数を実行すると、ユーザーデータを取得できます。

それでは、http://localhost:3000/usersを見てみましょう。
ユーザー一覧が表示されているはずです。

スクリーンショット 20200613 23.17.01.png

MongoDBでユーザーのCRUD操作

とりあえず、ユーザー一覧を表示させるところまで進みました。
しかし、予め用意していたデータのみしか表示できないのはあまりにも不便なため、MongoDBを導入してデータの永続化ができるようにします。

最終的には、CRUD操作ができるようにルートを作成します。

MondoDBのインストール

次のコマンドを実行して、MongoDBをインストールします。
ここではHomebrewを使用してインストールしています。

brew tap mongodb/brew
brew install mongodb-community@4.2

以下のコマンドで起動します。

brew services start mongodb-community@4.2

Mongooseをインストールして、Node.jsアプリケーションに接続

Mongooseは、アプリケーションでMongoDBを使いやすくしてくれるためのODM(オブジェクトとドキュメントを対応させるためのツール)です。ORMと似たようなものです。

MongoDBは、本来はスキーマはありませんが、実際にアプリケーションを運営するうえでスキーマがあったほうがよいでしょう。Mongooseはドキュメントをモデル化してスキーマの構築を手助けしてくれます。

次のコマンドでインストールします。

npm i mongoose

型定義もインストールいしましょう。

npm i @types/mongoose

インストールが完了したら、main.tsで次のように接続します。

src/main.ts

import Express from 'express'
import path from 'path'
import router from './routes'
import layouts from 'express-ejs-layouts'
import mongoose from 'mongoose'

mongoose.connect('mongodb://localhost:27017/test_db', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
})

mongoose.Promise = global.Promise

const app = Express()
const port = 3000

app.set('view engine', 'ejs')
app.set('views', path.resolve(__dirname, 'views'))
app.use(layouts)
app.use(Express.static(__dirname + '/public'))
app.use('/', router)

app.listen(port, () => {
  console.log('server start')
})

mongodb://localhost:27017/はMongoDBのローカルの接続先です。その後にデータベース名をしていします。このデータベース名は存在しなければ自動で作成してくれます。

その後、MonngooseでPromiseを使用するためにmongoose.Promise = global.Promiseで代入しています。

ユーザーモデルを構築する

Monngoseを使用して、ユーザースキーマモデルを構築します。
models/userModel.tsに実装します。

src/models/userModel.ts

import mongoose, { Schema, Document } from 'mongoose'

type Sex = '' | ''

export interface UserDoc extends Document {
  firstName: String
  lastName: String
  email: String
  age: Number
  sex: Sex
}

const userSchema: Schema = new Schema(
  {
    firstName: {
      type: String,
      trim: true,
      required: true,
    },
    lastName: {
      type: String,
      trim: true,
      required: true,
    },
    email: {
      type: String,
      required: true,
      unique: true,
    },
    age: {
      type: Number,
      required: true,
    },
    sex: {
      type: String,
      required: true,
      enum: ['', '']
    },
  },
  {
    timestamps: true,
  }
)

userSchema.virtual('fullName').get(function(this: User) {
  return `${this.firstName} ${this.lastName}`
})

export default mongoose.model<User>('User', userSchema)

TypeScriptでスキーマを構築するためには、スキーマとは別にDocumentを継承したインターフェースをを作成する必要があります。

mongoose.Schemaが提供するコンストラクタにパラメータを渡すことでスキーマを構築することができます。
スキーマでは型定義だけでなく、requireduniqueなどのオプションも使用可能です。
timestamsオプションを設定すると、自動でcreated_atupdated_atフィールドを設定してくれます。

mongoose.Schemaメソッドのvirtualはデータベースが提供しない仮想のフィールドを使用することができます。
この例ではユーザーのフルネームを返し、fullNameというプロパティでアクセスできます。

最後に、mongoose.model()にスキーマを渡して、モデルが作成されます。
このとき、ジェネリクスで呼び出すようにします。

ユーザー一覧の修正

モデルをmongooseで構築するように修正したので、コントローラーの実装も修正します。

src/controllers/userController.ts

import Express from 'express'
import User from '../models/userModel'

export default {
  index: async (
    req: Express.Request,
    res: Express.Response,
    next: Express.NextFunction
  ) => {
    try {
      const users = await User.find({}).exce()
      res.locals.users = users
      next()
    } catch (err) {
      next(err)
    }
  },
  indexView: (req: Express.Request, res: Express.Response) => {
    res.render('users/index')
  },
}

データベースへの接続は失敗することがあるので、index()はミドルウェア関数として実装します。
ミドルウェアはリクエスト(req)、レスポンス(res)と次のミドルウェアの呼び出し関数(next)を受け取る関数でリクエストに処理を挟むことができます。
ミドルウェアで例えばロギングをしたり、認証をしたあとに、next()を呼び出すことで、次のミドルウェア関数へ処理を渡します。

ミドルウェア関数では、確実にnext()を呼ばなければいけないことに注意してください。さもないと、無限ループに陥りスタックオーバーフローが発生します。

try/catch構文で処理をし、エラーは発生した場合にはnext()にエラーを渡しミドルウェア関数でエラーは発生したことを伝えます。

ルーティングも次のように修正します。

src/routes/userRoutes.ts

import Express from 'express'
import usersController from '../controllers/usersController'

const router = Express.Router()

router.get('/', usersController.index, usersController.indexView)

export default router

データを入れて確認

MongoDBにデータを入れてみて表示を確認してみましょう。

MongoDBのGUI操作には、MongoDB compassが便利です。

ローカルに接続し、データベースとテーブルを選んでインサートします。

スクリーンショット 20200614 14.27.52.png

スクリーンショット 20200614 14.28.10.png

投入したユーザーデータが表示されました。

スクリーンショット 20200614 14.30.37.png

ユーザーの作成

フォームの作成

アプリケーションから新規ユーザーを作成できるように、作成フォームを作りましょう。
views/usersフォルダの下に、new.ejsというファイルを作成します。

src/views/users

<div class="data-form">
  <form class="form-signin" action="/users/create" method="POST">
    <h2>Create a new user:</h2>
    <label for="inputFirstName">First Name</label>
    <input class="form-control" type="text" name="first" id="inputFirstName" placeholder="First" autofocus required>
    <label for="inputLastName">Last Name</label>
    <input class="form-control" type="text" name="last" id="inputLastName" placeholder="Last" required>
    <label for="inputEmail">Email Address</label>
    <input class="form-control" type="email" name="email" id="inputEmail" placeholder="Email" required>
    <label for="inputAge">age</label>
    <input class="form-control" type="text" name="age" id="inputAge" placeholder="Age" required>
    <label for="inputSex">sex</label>
    <select name="sex" id="inputSex" class="form-control">
      <option value="男"></option>
      <option value="女"></option>
    </select>
    <br /><button class="btn btn-lg btn-primary btn-block" type="submit">Create</button>
  </form>
</div>

コントローラーとルーティングも追加します。

src/controllers/userController.ts

import Express from 'express'
import User from '../models/userModel'

export default {
  index: async (
    req: Express.Request,
    res: Express.Response,
    next: Express.NextFunction
  ) => {
    try {
      const users = await User.find({}).exec()
      res.locals.users = users
      next()
    } catch (err) {
      next(err)
    }
  },
  indexView: (req: Express.Request, res: Express.Response) => {
    res.render('users/index')
  },
  new: (req: Express.Request, res: Express.Response) => {
    res.render('users/new')
  },
}

src/routes/userRoutes.ts

import Express from 'express'
import usersController from '../controllers/usersController'

const router = Express.Router()

router.get('/', usersController.index, usersController.indexView)
router.get('/new', usersController.new)

export default router

users/newにアクセスして確認します。

スクリーンショット 20200614 14.54.08.png

リクエストを受け取れるようにする

Expressでリクエストパラメータを受け取れるようにするために、main.tsに次のように追記します。

import bodyParser from 'body-parser'

app.use(
  bodyParser.urlencoded({
    extended: true,
  })
)

createアクション

実際にリクエストパラメータを受け取りデータベースに保存するcreateアクションを実装します。
リクエストパラメータはres.bodyから受け取ることができます。

src/controllers/usersController.ts

import Express from 'express'
import User, { UserDoc } from '../models/userModel'

export default {
  index: async (
    req: Express.Request,
    res: Express.Response,
    next: Express.NextFunction
  ) => {
    try {
      const users = await User.find({}).exec()
      res.locals.users = users
      next()
    } catch (err) {
      next(err)
    }
  },
  indexView: (req: Express.Request, res: Express.Response) => {
    res.render('users/index')
  },
  new: (req: Express.Request, res: Express.Response) => {
    res.render('users/new')
  },
  create: async (
    req: Express.Request,
    res: Express.Response,
    next: Express.NextFunction
  ) => {
    const userParams = req.body as UserDoc
    try {
      await User.create(userParams)
      res.locals.redirect = '/users'
      next()
    } catch (err) {
      next(err)
    }
  },
  redirectView: (
    req: Express.Request,
    res: Express.Response,
    next: Express.NextFunction
  ) => {
    const redirect = res.locals.redirect
    if (redirect) {
      res.redirect(redirect)
    } else {
      next()
    }
  },
}

ドキュメントの作成は、create()メソッドを使用します。
ユーザーの作成に成功したらredirectViewアクションへ渡します。

ルーティングを追記しましょう。

scr/routes/userRoutes.ts

import Express from 'express'
import usersController from '../controllers/usersController'

const router = Express.Router()

router.get('/', usersController.index, usersController.indexView)
router.get('/new', usersController.new)
router.post('/create', usersController.create, usersController.redirectView)

export default router

ユーザーデータを読み出して更新

次は、updateアクションを作成します。edit.ejsファイルを作成します。
作成用のフォームとよく似ていますが、初期値としてユーザーのデータを埋め込みます。

src/views/users/edit.ejs
<div class="data-form">
  <form class="form-signin" action="<%= `/users/${user._id}/update?_method=PUT` %>" method="post">
    <h2 class="form-signin-heading">Edit User</h2>
    <label for="inputFirstName">First Name</label>
    <input type="text" name="first" id="inputFirstName" class="form-control" placeholder="First"
      value="<%= user.firstName %>" autofocus>
    <label for="inputLastName">Last Name</label>
    <input type="text" name="last" id="inputLastName" value="<%= user.lastName %>" class="form-control"
      placeholder="Last">
    <label for="inputPassword">Password</label>
    <input type="email" name="email" id="inputEmail" placeholder="Email" value="<%= user.email %>" class="form-control"
      required>
    <label for="inputAge">Age</label>
    <input type="text" name="age" id="inputAge" value="<%= user.age %>" class="form-control" placeholder="Age" required>
    <select name="sex" id="inputSex" class="form-control">
      <option value="男"></option>
      <option value="女"></option>
    </select>
    <br>
    <button class="btn btn-lg btn-primary btn-block" type="submit">Update</button>
  </form>
</div>

更新フォームへのパスはusers/:id/editです。ルーティングにコロン(:)を使うと動的にルーティングさせることができます。

index.ejsから更新フォームへアクセスできるようにしておきましょう。

src/views/users/index.ejs
<td>
  <a href="<%= `/users/${user._id}.edit` %>">Edit</a>
</td>

さて、更新のリクエストを送信するときには、PUTリクエストを送信できるようにしたいです。
しかし。HTMLフォームがサポートしているリクエストはGETとPOSTだけだのでこのままでは実現できません。

そのため、HTTPリクエストを書き換えるパッケージを使用します。

npm i method-override
npm i -D @types/method-override

main.tsにmethod-overrideを使うように追記します。

src/main.ts

import methodOverride from 'method-override'

app.use(methodOverride('_method', {
  methods: ['POST', 'GET']
}))

method-overrideは、URLに_methodというクエリパラメータを見つけたら、そのパラメータの値として指定されたメソッドを使ってそのリクエストを解釈します。
フォームのアクションパスに、?_method=PUTを加えれば、それはPUTリクエストとして解釈されます。

editアクションを作成

コントローラーにeditアクションを作成しましょう。

req.params.idからユーザーのID受け取り、findById()`メソッドでデータベースから特定のユーザーを捜索します。
ユーザーが見つからない場合には、エラーを送出します。

また、res.localsオブジェクトに代入した値はビューで変数として使用することができます。

src/controllers/userController.ts

edit: async (
    req: Express.Request,
    res: Express.Response,
    next: Express.NextFunction
  ) => {
    const userId: string = req.params.id
    try {
      const user = await User.findById(userId)
      res.locals.user = user
      next()
    } catch (err) {
      next(err)
    }
  },
  editView: (req: Express.Request, res: Express.Response) => {
    res.render('users/edit')
  },

updateアクション

updateアクションも作成しましょう。
findByIdAdUpdate()メソッドを使用すれば、ユーザーをIDで見つけたあとに更新することができます。

src/controllers/userController.ts

update: async (
    req: Express.Request,
    res: Express.Response,
    next: Express.NextFunction
  ) => {
    const userId: string = req.params.id
    const userParams = req.body as UserDoc

    try {
      await User.findByIdAndUpdate(userId, {
        $set: userParams,
      })
      res.locals.redirect = '/users'
      next()
    } catch (err) {
      next(err)
    }
  },

ルーティングに、editとupdateを追加しましょう。
updateアクションはPUTリクエストを受け取ります。

src/routes/userRoutes.ts

router.get('/:id/edit', usersController.edit, usersController.editView)
router.put('/:id/update', usersController.update, usersController.redirectView)

ユーザーを削除する

最後に、deleteアクションを作成しましょう。
ユーザーを削除するために、ビューは作成しません。
インデックスページに削除のために動線を用意します。

src/views/users/index.ejs

<td>
  <a 
    href="<%= `users/${user._id}/delete?_method=DELETE` %>"
    onclick="return confirm('本当にこのユーザーを削除しますか?')"
  >
    DELETE
  </a>
</td>

deleteアクション

ユーザーを削除するためのdeleteアクションをコントローラーに追加します。

特定のユーザーを削除するためにfindByIdAndRemoveを呼び出します。

src/controllers/userController.ts

delete: async (
    req: Express.Request,
    res: Express.Response,
    next: Express.NextFunction
  ) => {
    const userId: string = req.params.id

    try {
      await User.findByIdAndRemove(userId)
      res.locals.redirect = '/users/'
      next()
    } catch (err) {
      next(err)
    }
  },

今までの流れと同じく、ユーザの削除に成功したら次のミドルウェア関数を呼び出し、失敗したらエラーを渡します。

最後に、ルーティングに追加しましょう。

src/routes/userRoutes.ts

router.delete('/:id/delete', usersController.delete, usersController.redirectView)

これで、基本的なCRUD操作は完了です。

参考

入門Node.jsプログラミング
実践TypeScript
Strongly typed models with Mongoose and TypeScript

35
34
7

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
35
34