はじめに
前回の記事では、AdonisJSについての概要について説明しましたので、今回はMVC周りについて実際にコードを書きながら説明していきます。
各スターターキットの初期ディレクトリ構成
まず、AdonisJSでアプリケーションを作成する際にプロジェクトを作成することになります。
Web、API、Inertia、Slimのいずれかを選ぶことになりますので、それぞれについて説明していきます。
Web Starter Kit
サーバーレンダリングするWebアプリの作成をする場合は、こちらを選びます。
Edge.jsというテンプレートエンジン使用して、画面を作成します。
プロジェクトは以下を選択して作成します。
- 認証:セッション、アクセストークン、Basic認証のいずれか
- DB:Sqlite、PostgreSQL、Mysql、Microsoft SQL Serverのいずれか
ディレクトリ構成としては以下になっています。
tree -a -L 3 -I node_modules*
.
|-- .editorconfig
|-- .env # 環境変数設定
|-- .env.example
|-- .gitignore
|-- ace.js # aceコマンドの実行ファイル
|-- adonisrc.ts # adonisJSの設定ファイル。プロバイダーやコマンドエイリアスを登録
|-- app
| |-- exceptions # 例外周りのクラス
| | `-- handler.ts
| |-- middleware # ミドルウェア周りのクラス
| | |-- auth_middleware.ts
| | |-- container_bindings_middleware.ts
| | |-- guest_middleware.ts
| | `-- silent_auth_middleware.ts
| `-- models #モデル周りのクラス
| `-- user.ts
|-- bin # コマンド周り
| |-- console.ts
| |-- server.ts
| `-- test.ts
|-- config # 設定ファイル
| |-- app.ts
| |-- auth.ts # 認証設定
| |-- bodyparser.ts
| |-- database.ts # DB設定
| |-- hash.ts
| |-- logger.ts # ログ設定
| |-- session.ts # セッション設定
| |-- shield.ts # CSRFガード設定
| |-- static.ts # 静的ミドルウェアの構成
| `-- vite.ts
|-- database # データベース周り(マイグレーション、シード)
| `-- migrations
| `-- 1744190532347_create_users_table.ts
|-- eslint.config.js
|-- package-lock.json
|-- package.json
|-- resources # 静的ファイル
| |-- css
| | `-- app.css
| |-- js
| | `-- app.js
| `-- views
| `-- pages
|-- start # アプリケーションの初期スクリプト
| |-- env.ts
| |-- kernel.ts
| `-- routes.ts # ルーティング定義
|-- tests
| `-- bootstrap.ts
|-- tsconfig.json
`-- vite.config.ts
API starter kit
JSONでやり取りするAPIの作成をする場合はこちらを選びます。
ReactやVueなどでフロントエンドを構築する場合に、AdonisJSバックエンドを作成できます。
プロジェクトは以下を選択して作成します。
- 認証:セッション、アクセストークン、Basic認証のいずれか
- DB:Sqlite、PostgreSQL、Mysql、Microsoft SQL Serverのいずれか
ディレクトリ構成としては以下になっています。
基本的にWebと一緒ですが、config/やmiddlware/
に違いがあったり、resources/
がなかったりします。
tree -a -L 3 -I node_modules*
.
|-- .editorconfig
|-- .env
|-- .env.example
|-- .gitignore
|-- ace.js
|-- adonisrc.ts
|-- app
| |-- exceptions
| | `-- handler.ts
| |-- middleware
| | |-- auth_middleware.ts
| | |-- container_bindings_middleware.ts
| | |-- force_json_response_middleware.ts
| | |-- guest_middleware.ts
| | `-- silent_auth_middleware.ts
| `-- models
| `-- user.ts
|-- bin
| |-- console.ts
| |-- server.ts
| `-- test.ts
|-- config
| |-- app.ts
| |-- auth.ts
| |-- bodyparser.ts
| |-- cors.ts
| |-- database.ts
| |-- hash.ts
| |-- logger.ts
| `-- session.ts
|-- database
| `-- migrations
| `-- 1744189966356_create_users_table.ts
|-- eslint.config.js
|-- package-lock.json
|-- package.json
|-- start
| |-- env.ts
| |-- kernel.ts
| `-- routes.ts
|-- tests
| `-- bootstrap.ts
`-- tsconfig.json
Inertia starter kit
Inertiaは、SPAを構築する方法です。React・Vue・Solid・Svelteを使用して、アプリケーションのフロントエンドを構築できます。
以下を選択してプロジェクトを作成します。
- 認証:セッション、アクセストークン、Basic認証のいずれか
- DB:Sqlite、PostgreSQL、Mysql、Microsoft SQL Serverのいずれか
- フロントエンド:Vue3、React、Svelte、Solid.jsのいずれか
- サーバーサイドレンダリングするか
ディレクトリ構成としては以下になっています。
基本的にWebと一緒ですが、config/やresources/
に少し違いがあったり、inertia/
があったりします。
tree -a -L 3 -I node_modules*
.
|-- .editorconfig
|-- .env
|-- .env.example
|-- .gitignore
|-- ace.js
|-- adonisrc.ts
|-- app
| |-- exceptions
| | `-- handler.ts
| |-- middleware
| | |-- auth_middleware.ts
| | |-- container_bindings_middleware.ts
| | |-- guest_middleware.ts
| | `-- silent_auth_middleware.ts
| `-- models
| `-- user.ts
|-- bin
| |-- console.ts
| |-- server.ts
| `-- test.ts
|-- config
| |-- app.ts
| |-- auth.ts
| |-- bodyparser.ts
| |-- cors.ts
| |-- database.ts
| |-- hash.ts
| |-- inertia.ts # inertiaの設定
| |-- logger.ts
| |-- session.ts
| |-- shield.ts
| |-- static.ts
| `-- vite.ts
|-- database
| `-- migrations
| `-- 1744190205575_create_users_table.ts
|-- eslint.config.js
|-- inertia
| |-- app
| | `-- app.ts
| |-- css
| | `-- app.css
| |-- pages
| | |-- errors
| | `-- home.vue
| `-- tsconfig.json
|-- package-lock.json
|-- package.json
|-- resources
| `-- views
| `-- inertia_layout.edge
|-- start
| |-- env.ts
| |-- kernel.ts
| `-- routes.ts
|-- tests
| `-- bootstrap.ts
|-- tsconfig.json
`-- vite.config.ts
Slim starter kit
フレームワークのコア部分とデフォルトのフォルダ構造のみが付属しており、AdonisJSの最小限の機能のみ利用したい場合に使います。
tree -a -L 3 -I node_modules*
.
|-- .editorconfig
|-- .env
|-- .env.example
|-- .gitignore
|-- ace.js
|-- adonisrc.ts
|-- app
| |-- exceptions
| | `-- handler.ts
| `-- middleware
| `-- container_bindings_middleware.ts
|-- bin
| |-- console.ts
| |-- server.ts
| `-- test.ts
|-- config
| |-- app.ts
| |-- bodyparser.ts
| |-- hash.ts
| `-- logger.ts
|-- eslint.config.js
|-- package-lock.json
|-- package.json
|-- start
| |-- env.ts
| |-- kernel.ts
| `-- routes.ts
|-- tests
| `-- bootstrap.ts
`-- tsconfig.json
ここからは、実際に動かしながらやっていきます。
コントローラー
AdonisJSはMVCを採用しているので、まずはリクエストをModelとViewに捌くControllerから説明します。
コントローラーを作るために、2つのコマンドが用意されています。
- 1. クラス定義だけあるコントローラー
- 2. CRUD作成に必要なメソッドが定義されたコントローラー
【1. クラス定義だけあるコントローラー】を作るには、node ace make:controller <コントローラー名>
を実行します。
すると、controllers/
以下にコントローラークラスが作成されます。
// import type { HttpContext } from '@adonisjs/core/http'
export default class PostsController {
}
【2. CRUD作成に必要なメソッドが定義されたコントローラー】を作るには、node ace make:controller <コントローラー名> --resource
を実行します。
すると、CRUD用の7つのメソッドが定義されたusers_controller.ts
が作成されます。
import type { HttpContext } from '@adonisjs/core/http'
export default class UsersController {
/**
* 一覧取得用(GET)
*/
async index({}: HttpContext) {}
/**
* 新規登録の取得用(GET)
*/
async create({}: HttpContext) {}
/**
* 新規登録用(POST)
*/
async store({ request }: HttpContext) {}
/**
* 詳細取得用(GET)
*/
async show({ params }: HttpContext) {}
/**
* 編集の取得用(GET)
*/
async edit({ params }: HttpContext) {}
/**
* 更新用(PATCH/PUT)
*/
async update({ params, request }: HttpContext) {}
/**
* 削除用(DELETE)
*/
async destroy({ params }: HttpContext) {}
}
DI(依存性の注入)
DIをする場合は、以下のようにサービスクラスを作成して行います。
node ace make:service user
DONE: create app/services/user_service.ts
export class UserService {
// Your code here
}
import { inject } from '@adonisjs/core'
import UserService from '#services/user_service'
@inject()
export default class UsersController {
constructor(protected userService: UserService) {}
index() {
return this.userService.all()
}
}
ルーティング
さぁ、コントローラーを作成しましたが、このままだとリクエストがコントローラーまで届きませんので、ルーティングを設定しましょう。
ルーティングはstart/routes.ts
に記述します。
例えばpostコントローラーのstoreアクションを定義する場合は以下のようになります。
import router from '@adonisjs/core/services/router'
const PostsController = () => import('#controllers/posts_controller')
router.post('posts', [PostsController , 'store'])
リソースコントローラーと呼ばれるAPIのCRUD用のルートを作成する場合は、以下の1行だけでOKです。
import router from '@adonisjs/core/services/router'
const UsersController = () => import('#controllers/users_controller')
router.resource('users', UsersController)
では、ルートがちゃんと設定されているか確認してみます。
node ace list:routes
METHOD ROUTE ...................................................... HANDLER MIDDLEWARE
POST /posts ......................... #controllers/posts_controller.store
GET /users (users.index) ........... #controllers/users_controller.index
GET /users/create (users.create) .. #controllers/users_controller.create
POST /users (users.store) ........... #controllers/users_controller.store
GET /users/:id (users.show) ......... #controllers/users_controller.show
GET /users/:id/edit (users.edit) .... #controllers/users_controller.edit
PUT /users/:id (users.update) ..... #controllers/users_controller.update
PATCH /users/:id (users.update) ..... #controllers/users_controller.update
DELETE /users/:id (users.destroy) ... #controllers/users_controller.destroy
問題なく、設定されていそうですね
実行してみる
ルートが設定されたので、この段階で一度実行してみましょう。
posts_controllerにstoreアクションを追加します。
今回は疎通確認が出来ればいいので、json返すだけのメソッドにします。
import type { HttpContext } from '@adonisjs/core/http'
export default class PostsController {
/**
* Handle form submission for the create action
*/
async store({ request }: HttpContext) {
return {
'message': 'hello'
}
}
}
node ace serve --hmr
[ info ] starting HTTP server...
╭─────────────────────────────────────────────────╮
│ │
│ Server address: http://localhost:3333 │
│ Watch Mode: HMR │
│ Ready in: 1.33 s │
│ │
╰─────────────────────────────────────────────────╯
[01:55:09.980] INFO (20204): started HTTP server on localhost:3333
開発サーバが立ち上がったので、curlで実行してみます。
正常にjsonが返ってきましたね
curl -X POST http://localhost:3333/posts
{"message":"hello"}
モデル
レスポンスが返るになりましたが、実際はDBからデータを取得/登録することがほとんどです。
DBのテーブルを表すクラスがモデルになります。
AdonisJSでは、Lucid ORMというKnexベースで作られたActive RecordパターンのORMを利用します。
モデルクラスはnode ace make:model Post
というコマンドで作成できます。
import { DateTime } from 'luxon'
import { BaseModel, column } from '@adonisjs/lucid/orm'
export default class Post extends BaseModel {
@column({ isPrimary: true })
declare id: number
@column.dateTime({ autoCreate: true })
declare createdAt: DateTime
@column.dateTime({ autoCreate: true, autoUpdate: true })
declare updatedAt: DateTime
}
DB接続できるようにする
DB接続が必要なのでDockerでPostgreSQLコンテナを立ち上げてみます。
以下のファイルを作成してdocker compose up -d
を実行します。
version: '3.8'
services:
postgres:
image: postgres:15
container_name: postgres15
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: root
POSTGRES_DB: app
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
DBコンテナが立ち上がり、DBに接続できることが確認出来ました。
docker compsose up -d
docker compose exec postgres bash
psql -U root -d app
.envを確認して、DBの接続情報が一致していることを確認します。
TZ=UTC
PORT=3333
HOST=localhost
LOG_LEVEL=info
APP_KEY=Ald1bL-tkR8JQaiv1CdxHpd50JBUWLD7
NODE_ENV=development
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=root
DB_PASSWORD=root
DB_DATABASE=app
SESSION_DRIVER=cookie
テーブルの作成
次に、Postsテーブルを作成します!
モデル作成時に-m
を付けるとモデルクラスとマイグレーションクラスをまとめて作ることが出来ます。
node ace make:model -m Post
models/
以下にモデルクラスと、database/migrations/
以下にマイグレーションクラスが作成されます。
import { DateTime } from 'luxon'
import { BaseModel, column } from '@adonisjs/lucid/orm'
export default class Post extends BaseModel {
@column({ isPrimary: true })
declare id: number
@column.dateTime({ autoCreate: true })
declare createdAt: DateTime
@column.dateTime({ autoCreate: true, autoUpdate: true })
declare updatedAt: DateTime
}
import { BaseSchema } from '@adonisjs/lucid/schema'
export default class extends BaseSchema {
protected tableName = 'posts'
async up() {
this.schema.createTable(this.tableName, (table) => {
table.increments('id')
table.string('name') // 追加
table.timestamp('created_at')
table.timestamp('updated_at')
})
}
async down() {
this.schema.dropTable(this.tableName)
}
}
マイグレーションファイルが作れましたが、まだ実行されていないので、実行してみます。
node ace migration:status
┌────────────────────────────────────────────────────────┬───────────┬─────────┬───────────┐
│ Name │ Status │ Batch │ Message │
├────────────────────────────────────────────────────────┼───────────┼─────────┼───────────┤
│ database/migrations/1744189966356_create_users_table │ pending │ NA │ │
├────────────────────────────────────────────────────────┼───────────┼─────────┼───────────┤
│ database/migrations/1744340194247_create_posts_table │ pending │ NA │ │
└────────────────────────────────────────────────────────┴───────────┴─────────┴───────────┘
node ace migration:run
[ info ] Upgrading migrations version from "1" to "2"
❯ migrated database/migrations/1744189966356_create_users_table
❯ migrated database/migrations/1744340194247_create_posts_table
node ace migration:status
┌────────────────────────────────────────────────────────┬─────────────┬─────────┬───────────┐
│ Name │ Status │ Batch │ Message │
├────────────────────────────────────────────────────────┼─────────────┼─────────┼───────────┤
│ database/migrations/1744189966356_create_users_table │ completed │ 1 │ │
├────────────────────────────────────────────────────────┼─────────────┼─────────┼───────────┤
│ database/migrations/1744340194247_create_posts_table │ completed │ 1 │ │
└────────────────────────────────────────────────────────┴─────────────┴─────────┴───────────┘
データの投入
次にデータを入れたいので以下のコマンドを実行し、database/seeders
以下にシーダーファイルを作成します。
node ace make:seeder Post
DONE: create database/seeders/post_seeder.ts
作成したシードを修正します。
import { BaseSeeder } from '@adonisjs/lucid/seeders'
import db from '@adonisjs/lucid/services/db'
export default class extends BaseSeeder {
async run() {
// 既存のデータを削除
await db.from('posts').delete()
// 新しいデータを挿入
await db.table('posts').multiInsert([
{
name: 'post1',
created_at: new Date(),
updated_at: new Date(),
},
{
name: 'post2',
created_at: new Date(),
updated_at: new Date(),
},
{
name: 'post3',
created_at: new Date(),
updated_at: new Date(),
}
])
}
}
シードを実行し、データを登録します。
node ace db:seed
❯ completed database/seeders/post_seeder
データが入っていることを確認できます。
app=# select * from posts;
id | created_at | updated_at
----+----------------------------+----------------------------
1 | 2025-04-11 03:24:48.378+00 | 2025-04-11 03:24:48.378+00
2 | 2025-04-11 03:24:48.378+00 | 2025-04-11 03:24:48.378+00
3 | 2025-04-11 03:24:48.378+00 | 2025-04-11 03:24:48.378+00
(3 rows)
モデルとコントローラーの修正
では、モデルクラスとコントローラクラスを修正し、データの取得/登録が出来るようにしてみましょう。
import { DateTime } from 'luxon'
import { BaseModel, column } from '@adonisjs/lucid/orm'
interface CreateParams {
name: string
}
export default class Post extends BaseModel {
@column({ isPrimary: true })
declare id: number
@column()
declare name: string
@column.dateTime({ autoCreate: true })
declare createdAt: DateTime
@column.dateTime({ autoCreate: true, autoUpdate: true })
declare updatedAt: DateTime
static async index() {
const post = await this.all()
return { data: post }
}
static async register(params: CreateParams) {
const post = await this.create(params)
return { data: post }
}
}
import type { HttpContext } from '@adonisjs/core/http'
import Post from '#models/post'
export default class PostsController {
/**
* 一覧取得
*/
async index({ response }: HttpContext) {
const posts = await Post.index()
return response.status(200).json({
status: 'success',
data: posts
})
}
/**
* 新規登録
*/
async store({ request, response }: HttpContext) {
// リクエストボディからデータを取得
const data = request.only(['name'])
// 新規投稿を作成
const post = await Post.register(data)
return response.status(201).json({
status: 'success',
data: post
})
}
}
一覧取得のルートも追加します
import router from '@adonisjs/core/services/router'
const PostsController = () => import('#controllers/posts_controller')
const UsersController = () => import('#controllers/users_controller')
router.get('posts', [PostsController , 'index'])
router.post('posts', [PostsController , 'store'])
router.resource('users', UsersController)
最後にcurlでそれぞれ実行してみます。
curl -X GET http://localhost:3333/posts
{
"status": "success",
"data": {
"data": [
{
"id": 3,
"name": "post3",
"createdAt": "2025-04-11T04:58:20.938+00:00",
"updatedAt": "2025-04-11T04:58:20.938+00:00"
},
{
"id": 2,
"name": "post2",
"createdAt": "2025-04-11T04:58:20.938+00:00",
"updatedAt": "2025-04-11T04:58:20.938+00:00"
},
{
"id": 1,
"name": "post1",
"createdAt": "2025-04-11T04:58:20.938+00:00",
"updatedAt": "2025-04-11T04:58:20.938+00:00"
}
]
}
}
curl -X POST http://localhost:3333/posts \
-H "Content-Type: application/json" \
-d '{"name": "post4"}'
{
"status": "success",
"data": {
"data": {
"name": "post4",
"createdAt": "2025-04-11T05:02:16.432+00:00",
"updatedAt": "2025-04-11T05:02:16.432+00:00",
"id": 4
}
}
}
app=# select * from posts;
id | name | created_at | updated_at
----+-------+----------------------------+----------------------------
1 | post1 | 2025-04-11 05:02:12.186+00 | 2025-04-11 05:02:12.186+00
2 | post2 | 2025-04-11 05:02:12.186+00 | 2025-04-11 05:02:12.186+00
3 | post3 | 2025-04-11 05:02:12.186+00 | 2025-04-11 05:02:12.186+00
4 | post4 | 2025-04-11 05:02:16.432+00 | 2025-04-11 05:02:16.432+00
(4 rows)
一覧取得・登録が問題なく出来ましたね
バリデーション
登録が出来るようになりましたが、リクエスト値が正しいものなのかチェックしていないので、このままだとセキュリティ的によくないので、入力値チェックをするようにしましょう。
バリデーションクラスを以下のコマンドで作成します。
node ace make:validator post
create app/validators/post.ts
バリデーションルールとして、必須・1文字以上・255文字以内で設定します。
import vine from '@vinejs/vine'
/**
* Validates the post's creation action
*/
export const createPostValidator = vine.compile(
vine.object({
name: vine.string().minLength(1).maxLength(255),
})
)
コントローラーを修正し、登録処理する前にバリデーションを実行するようにします。
import type { HttpContext } from '@adonisjs/core/http'
import Post from '#models/post'
import {
createPostValidator,
} from '#validators/post'
export default class PostsController {
/**
* 一覧取得
*/
async index({ response }: HttpContext) {
const posts = await Post.index()
return response.status(200).json({
status: 'success',
data: posts
})
}
/**
* 新規登録
*/
async store({ request, response }: HttpContext) {
// リクエストボディからデータを取得
const data = request.only(['name'])
+ const payload = await createPostValidator.validate(data)
// 新規投稿を作成
const post = await Post.register(payload)
return response.status(201).json({
status: 'success',
data: post
})
}
}
nameをNULLにしてリクエストを実行すると、422エラーになることがわかります。
curl -X POST -i http://localhost:3333/posts -H "Content-Type: application/json" -d '{"name": null}'
HTTP/1.1 422 Unprocessable Entity
set-cookie: adonis-session=s%3AeyJtZXNzYWdlIjoicG90NG1xNmFwb3ZycHBxbjRmdmh4aDN1IiwicHVycG9zZSI6ImFkb25pcy1zZXNzaW9uIn0.UBRNklUSfWGm9RNah_DzIfOc8Pz-qd36CgbC4R5fIAE; Max-Age=7200; Path=/; HttpOnly; SameSite=Lax
x-request-id: vwz8cdv69284va07vttymqy6
content-length: 86
content-type: application/json; charset=utf-8
Date: Fri, 11 Apr 2025 08:26:02 GMT
Connection: keep-alive
Keep-Alive: timeout=5
{"errors":[{"message":"The name field is required","rule":"required","field":"name"}]}
ビュー
最後がMVCのViewになり、画面を構成する部分です。
今回はEdgeJS(テンプレートエンジン)を利用して試してみます。
以下のコマンドでviewファイルを作成し、以下のように修正します。
node ace make:view post
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>投稿一覧</h1>
{{-- テーブル形式での表示 --}}
<table>
<thead>
<tr>
<th>ID</th>
<th>名前</th>
</tr>
</thead>
<tbody>
@each(post in posts)
<tr>
<td>{{ post.id }}</td>
<td>{{ post.name }}</td>
</tr>
@else
<tr>
<td colspan="3">投稿がありません</td>
</tr>
@end
</tbody>
</table>
</body>
</html>
コントローラーを以下のように修正し、http://localhost:3333/posts
にアクセスすると、DBのデータが表示されるかと思います
import type { HttpContext } from '@adonisjs/core/http'
import Post from '#models/post'
export default class PostsController {
/**
* 一覧取得
*/
async index({ view }: HttpContext) {
const posts = await Post.index()
return view.render('post', {posts})
}
}
コマンド一覧
ここまでちょくちょく出てきたnode aceコマンドですが、ここで各コマンドについて紹介します。
node ace list
node ace serve --hmr
node ace build
node ace configure <パッケージ名>
# 例:node ace configure @adonisjs/lucid
node ace add <パッケージ名>
# 例:node ace add @adonisjs/lucid
# 以下2つを1コマンドで行えます
npm install <package-name>
node ace configure
node ace generate:key
node ace make:controller <コントローラー名>
# 例:node ace make:controller users
# リソースコントローラー(CRUD)の作成
node ace make:controller <コントローラー名> --resource
# 例:node ace make:controller users --resource
node ace make:middleware <ミドルウェア名>
# 例:node ace make:middleware bodyparser
node ace make:validator <バリデーションクラス名>
# 例:node ace make:validator user
node ace make:service <サービスクラス名>
# 例:node ace make:service invoice
node ace make:model <モデルクラス名>
例:node ace make:model User
# モデルと一緒にマイグレーションも作成
node ace make:model -m User
node ace make:seeder <シーダー名>
例:node ace make:seeder Post
node ace make:exception <例外クラス名>
# 例:node ace make:exception commandValidation
node ace make:command <コマンド名>
# 例:node ace make:command listRoutes
node ace make:test <テストファイル名> --suite=unit
# 例:node ace make:test user --suite=unit
# tests/unit/user.spec.ts
node ace list:routes
# シードの実行
node ace db:seed
# 全てのテーブルのトランケート
node ace db:truncate
# 全てのテーブルの削除
node ace db:wipe
# 全てのテーブル削除&マイグレーション実行
node ace migration:fresh
# 全てのマイグレーションのロールバック&実行
node ace migration:refresh
# 全てのマイグレーションのロールバック
node ace migration:reset
# 特定のマイグレーションのロールバック
node ace migration:rollback
# 未実行のマイグレーションの実行
node ace migration:run
# マイグレーションステータスの確認
node ace migration:status
その他
VsCode
みなさんVsCodeなどのIDEを利用して、開発しているとは思いますがAdonisJSにもvscode拡張があるので、開発する際は必ず入れるようにしましょう!
おわりに
今回はAdonisJSを実際に触りながら説明しました!
まだまだ知名度が低いですが、Laravelに慣れている方は導入がしやすいと思いますので、技術選定の参考にしていただければと思います。