# Basic Usage
After you installed nuxt-neo
package and added there are some required options you must set.
# Creating your API
Create a new folder on your project, lets assume ~/api
.
{
modules: [
['nuxt-neo', {
directory: __dirname + '/api'
}]
]
}
// or alternatively:
{
modules: [
'nuxt-neo'
],
nuxtNeo: {
directory: __dirname + '/api'
}
}
Then lets create a new file, for example, ~/api/todos.js
and export a new class:
import Todos from '<your_todos_data_provider>'
class TodosController {
// Required: This will be the action to route mapper.
static ROUTES = {
allAction: {
path: '/', // your route will be /api/todos'/'
verb: 'GET'
},
getAction: {
path: '/:id', // your route will be /api/todos/:id - route paths are express-like
verb: 'GET'
},
createAction: {
path: '/', // your route will be /api/todos'/'
verb: 'POST'
},
};
// Everytime this class instantiates, request object will be injected into the construtor params.
constructor(request) {
this.request = request;
}
async allAction() {
const todos = await Todos.fetchAll();
return {
total: todos.length,
items: todos
}
}
// An object is passed to all actions, with the route params, query string and body.
async getAction({params}) {
const todo = await Todos.fetchById(params.id);
return todo;
}
// An object is passed to all actions, with the route params, query string and body.
async createAction({params, query, body}) {
return await Todos.create(body.title, body.content);
}
}
export default TodosController;
Now if you call your server at: GET http://<your_local_host>:<your_local_port>/api/todos
,
it will return a response with 200
status code and the given structure:
{
total: '<number_of_todos>',
items: [
{
title: '<rand_title>',
content: '<rand_content>'
}
// ...
]
}
# Accessing your API in your Vue Pages
First you need to create your client-side http request handler:
{
modules: [
['nuxt-neo', {
clientSideApiHandler: '~/api_handler' // since its client-side we can use alias resolver '~'
}]
]
}
Lets create our handler now (e.g we using axios to take care of this for us):
// file: ~/api_handler
import axios from 'axios';
// path is the relative path of the route
// verb is the method type
// {query, body, params} are the given payload to send
// {prefix} are api options (prefix is the api prefix, e.g: '/api')
export default (path, verb, {query, body}, {prefix}) => {
return axios({
baseURL: `http://${process.env.HOST}:${process.env.PORT}${prefix || ''}`,
timeout: 10000,
url: path,
method: verb.toLowerCase(),
data: body,
params: query
}).then(({data}) => data);
};
NOTE: You must return exactly what the controller action + successHandler
return,
to keep the data uniform.
Now lets connect our api with our page. Using the power of asyncData
and/or fetch
special
properties for server-side fetching on vue.js pages, we can simply do this:
<template>
<div class="index-page">
<div class="current-todo" v-if="currentTodo">
Current todo is: {{currentTodo.title}}
</div>
<div v-for="todo in todos.items">
{{todo.title}}
<button @click="handleClick(todo.id)">Click for details</button>
</div>
</div>
</template>
<script>
export default {
asyncData: async ({app}) => ({todos: await app.$api.todos.allAction()}),
methods: {
async handleClick(id) {
this.currentTodo = await this.$api.todos.getAction({params: {id}});
}
}
}
</script>
$api
is injected into all Vue instances (including root), sinceasyncData
doesn't havethis
property.- If
asyncData
is called on server-side, it will go directly to your controller action code. If its called on client-side it uses yourclientSideApiHandler
to handle the api request. - When calling an
action
(e.g:todos.allActions
), it accepts an object as param:
{
// the route params, same as express
params: {id: 1},
// the request body (in server side is server directly as JSON,
// in client side its your api handler that should define which encode type to use)
body: {foo: true},
// the url query string (in server side is server directly as JSON,
// in client side its your api handler that should assemble to url query string (axios does that out-of-the-box)
query: {bar: true}
}
# Extending the Typescript API interface
If your project is written in Typescript or uses JSDoc annotations to enable type-checking, you can extend the Api
interface to make Typescript aware of the apis that you've created and enable type-safety and improve the UX during development.
For example, for the example apis that we've created before on this page, you would extend the interface this way:
declare module 'nuxt-neo' {
declare type Todo = any; // For of the sake of the example the type is not strictly defined
interface Api {
todos: {
allAction(): Promise<{ total: number, items: Todo[] }>;
getAction(args: { params: { id: number } }): Promise<Todo | null>;
createAction(args: { body: { title: string, content: string } }): Promise<Todo>;
}
}
}