Adonisjs rest API crud setup
I will help you get started with Adonisjs by performing an API CRUD operation in this article. So, we are going to develop a simple Post module by using AdonisJs.
Firstly, we will install the Adonisjs version 5.
$ npm init adonis-ts-app crud
After successful installation Adonisjs version 5, run the following below command to start the application
You can purchase your hosting from Cloudsurph.com, Cloudsurph hosting is a reliable hosting option for business and personal projects. We offer insight and help on system configuration issues and code errors or bugs.
$ node ace serve --watch
Now, when you enter http://localhost:3333, you will see the Adonisjs front page.
Also, we have to need to install the @adonisjs/lucid package for database support.
$ npm i @adonisjs/lucid
When installing the package, we should configure the database that we are ready to use. My choice is MySQL
$ node ace configure @adonisjs/lucid
Now, based on the database selection, Adonisjs will automatically copy the environmental variables to the .env file like the following below.
MYSQL_HOST=localhost MYSQL_PORT=3306 MYSQL_USER=lucid MYSQL_PASSWORD= MYSQL_DB_NAME=lucid
So, now let’s create a migration and model file in Adonisjs, you can perform both with only a simple command.
$ node ace make:model Post -m
You can open the migration file under the database folder and add the necessary columns.
import BaseSchema from '@ioc:Adonis/Lucid/Schema' export default class Posts extends BaseSchema { protected tableName = 'posts' public async up() { this.schema.createTable(this.tableName, (table) => { table.increments('id') table.string('title', 255) table.text('content', 'long') table.specificType('status', 'tinyint(1)').unsigned().defaultTo(1); table.timestamp('created_at', { useTz: true }) table.timestamp('updated_at', { useTz: true }) }) } public async down() { this.schema.dropTable(this.tableName) } }
When the migration file is ready, then let’s check the migration status before you migrate.
$ node ace migration:status
You can see, that our migration file is pending, so we can go ahead and run the migration
$ node ace migration:run
Perfectly done! Now we have the table migrated and set up. Now we can focus on the model file.
import { DateTime } from 'luxon' import { BaseModel, column } from '@ioc:Adonis/Lucid/Orm' export default class Post extends BaseModel { @column({ isPrimary: true }) public id: number @column() public title: string @column() public content: string @column() public status: string @column.dateTime({ autoCreate: true }) public createdAt: DateTime @column.dateTime({ autoCreate: true, autoUpdate: true }) public updatedAt: DateTime }
So, here as you can see, we have to explicitly mention all the columns as properties on the model file, or else the typescript compiler would throw Property not exist on the Post model.
IF you want then buy a good, reliable, secure web hosting service from here: click here
Now we need to configure the necessary routes on the routes.ts file.
import Route from '@ioc:Adonis/Core/Route' Route.resource('posts', 'PostsController').apiOnly()
The above code will create all the post module routes for us. Kindly note, that I’ve added apiOnly() at the end of the line.
This means both CREATE and SHOW routes will be ignored.
So, now our routes, model, and migration files are ready, need to create a controller file.
$ node ace make:controller Post
export default class PostsController { }
Here we will add relevant methods to PostsController now
Listing
When we enter the route /posts on GET method, we should receive all the posts.
So, we need to add the index method on the PostsController and pull all the records from the Post model.
import Post from 'App/Models/Post' export default class PostsController { public async index({ response }) { const posts = await Post.all() return response.ok(posts) } }
Create
When we try to create a post by entering /posts on POST method, first we should validate whether we are receiving all the params from the client.
If not, then we have to validate the parameters and throw errors accordingly.
Adonisjs provides an easy inbuilt Validator which comes in handy for scenarios like this.
import Post from 'App/Models/Post' import { schema, rules } from '@ioc:Adonis/Core/Validator' export default class PostsController { public async index({ response }) { } public async store({ request, response }) { const postSchema = schema.create({ title: schema.string({ trim: true }, [ rules.maxLength(255) ]), content: schema.string({ escape: true }, [ rules.maxLength(1000) ]), }) const payload: any = await request.validate({ schema: postSchema }) const post: Post = await Post.create(payload) return response.ok(post) } }
Show
Now for retrieving a post resource, we’ve to enter the show API with the post identifier passed on the URL that is, /posts/1 on GET method.
import Post from 'App/Models/Post' import { schema, rules } from '@ioc:Adonis/Core/Validator' export default class PostsController { public async index({ response }) { } public async store({ request, response }) { } public async show({ params, response }) { const { id }: { id: Number } = params const post: any = await Post.find(id) if (!post) { return response.notFound({ message: 'Post not found' }) } return response.ok(post) } }
Update
When you need to update a post resource, we need two checks.
- Validate the input params
- Make sure the post resource exists on the database
Now, borrowing some of the code from store() and show() method, our update method will typically look like the following.
Here we can optimize the code by eliminating the code duplication of validation and post resource check but keeping them simple for now.
import Post from 'App/Models/Post' import { schema, rules } from '@ioc:Adonis/Core/Validator' export default class PostsController { public async index({ response }) { } public async store({ request, response }) { } public async show({ params, response }) { } public async update({ request, params, response }) { const postSchema = schema.create({ title: schema.string({ trim: true }, [ rules.maxLength(255) ]), content: schema.string({ escape: true }, [ rules.maxLength(1000) ]), }) const payload: any = await request.validate({ schema: postSchema }) const { id }: { id: Number } = params const post: any = await Post.find(id) if (!post) { return response.notFound({ message: 'Post not found' }) } post.title = payload.title post.content = payload.content await post.save() return response.ok(post) } }
Destroy
Now, Similar to the show() method, we’ve to first check the resource availability before we can delete the resource.
import Post from 'App/Models/Post' import { schema, rules } from '@ioc:Adonis/Core/Validator' export default class PostsController { public async index({ response }) { } public async store({ request, response }) { } public async show({ params, response }) { } public async update({ params, response }) { } public async destroy({ params, response }) { const { id }: { id: Number } = params const post: any = await Post.find(id) if (!post) { return response.notFound({ message: 'Post not found' }) } await post.delete() return response.ok({ message: 'Post deleted successfully.' }) } }
Finally, our PostsController will look like this below:
import Post from 'App/Models/Post' import { schema, rules } from '@ioc:Adonis/Core/Validator' export default class PostsController { public async index({ response }) { const posts = await Post.all() return response.ok(posts) } public async store({ request, response }) { const postSchema = schema.create({ title: schema.string({ trim: true }, [ rules.maxLength(255) ]), content: schema.string({ escape: true }, [ rules.maxLength(1000) ]), }) const payload: any = await request.validate({ schema: postSchema }) const post: Post = await Post.create(payload) return response.ok(post) } public async show({ params, response }) { const { id }: { id: Number } = params const post: any = await Post.find(id) if (!post) { return response.notFound({ message: 'Post not found' }) } return response.ok(post) } public async update({ request, params, response }) { const postSchema = schema.create({ title: schema.string({ trim: true }, [ rules.maxLength(255) ]), content: schema.string({ escape: true }, [ rules.maxLength(1000) ]), }) const payload: any = await request.validate({ schema: postSchema }) const { id }: { id: Number } = params const post: any = await Post.find(id) if (!post) { return response.notFound({ message: 'Post not found' }) } post.title = payload.title post.content = payload.content await post.save() return response.ok(post) } public async destroy({ params, response }) { const { id }: { id: Number } = params const post: any = await Post.find(id) if (!post) { return response.notFound({ message: 'Post not found' }) } await post.delete() return response.ok({ message: 'Post deleted successfully.' }) } }
That’s it for CRUD. Now we have got a fully functional Post module built on Adonisjs.
That’s it. If you enjoyed reading this article and have more questions please reach out to our support team via live chat or email and we would be glad to help you. we provide server hosting for all types of need and we can even get your server up and running with the service of your choice.