1.2.16 • Published 5 months ago

kenai v1.2.16

Weekly downloads
-
License
MIT
Repository
-
Last release
5 months ago

Table of content

Installation

npm install kenai

First steps

Before we start using the decorators, we need to configure Kenai as a Fastify plugin. Below are the plugin configuration options:

OptionDescriptionMandatory
routersUsed to define new routes from this endpointYes
zodCustomParserDefine a custom parser for Zod errorsNo
redisDefines the Redis configuration for routes with cacheNo
controllerParametersDefines the parameters for the controller class, such as the server itselfNo
bufferRedisDataDefine if Redis data should be stored in a buffer, this helps to save memory spaceNo

Example of how to configure the plugin:

import MainRouter from './routers/';
import { KenaiPlugin } from 'kenai';
import fastify from 'fastify';

const app = fastify({ ignoreTrailingSlash: true });

app.register(KenaiPlugin, { mainRoute: MainRouter });

app.listen({ port: 3000 }, (err, address) => {
    if (err) throw err;
    console.log(`Server listening at ${address}`);
});

Decorators

Router

This decorator is responsible for creating routes in Fastify, allowing you to define middlewares, new routes, and controllers in a single call.

External routes defined inside the decorator body are automatically integrated, dynamically associating their URLs with the 'child' routes and this also applies to middlewares.

Configuration options:

OptionDescriptionMandatory
routersUsed to define new routes from this endpointYes
middlewaresResponsible for adding middleware to routes for validationNo
controllersResponsible for adding controllers to routesYes

Below is an example of how to create a route:

import { Router, Get } from 'kenai';

@Router('/hello-world')
export default class MainRouter {
    @Get()
    helloWorld() {
        return 'Hello World!';
    }
}

Creating external routes and controllers:

Controllers are defined using the Methods decorators

import { Router, Get } from 'kenai';

class HelloWorldController {
    @Get()
    helloWorld() {
        return 'Hello World!';
    }
}

// External route but interconnected, final url: /v1/hello-world
@Router('/hello-world', {
    controllers: [HelloWorldController]
});
class HelloWorldRouter {}

@Router('/v1', {
    routers: [HelloWorldRouter],
})
export default class MainRouter {}

Middlewares

The middlewares are responsible for validating the requests, being invoked before the main processing and executed afterwards.

Example of how to create a middleware:

You can add more than one middleware, just separate them with a comma.

function ContentTypeValidator(request, reply, done) {
    if (request.headers['Content-Type'] !== 'application/json')
        throw new Error('Não aceito esse tipo de conteúdo');

    return done();
}

@Router('/')
class MainRouter {
    @Middleware(ContentTypeValidator)
    @Get()
    helloWorld() {
        return 'Hello World!';
    }
}

BodySchema

This decorator is responsible for validating all data sent to the request body, using Zod as a validation schema.

OptionDescriptionRequired
schemaDefines the validation schema using zodYes
omitUnknownKeysDefines whether the validator should remove keys that do not exist in the schemaNo

Example of how to use BodySchema:

import { BodySchema, Post } from 'kenai';
import { z } from 'zod';

class MainRouter {
    @BodySchema(z.object({ name: z.string().min(1) }))
    @Post()
    run(request) {}
}

QuerySchema

This decorator is responsible for validating all data sent in the request URL, using Zod as a validation schema.

The schema created in zod must have all properties as optional, otherwise it will create errors for values that were not informed.

OptionDescriptionRequired
schemaDefines the validation schema using zodYes
omitUnknownKeysDefines whether the validator should remove keys that do not exist in the schemaNo

Example of how to use QuerySchema:

import { QuerySchema, Get } from 'kenai';
import { z } from 'zod';

class MainRouter {
    @QuerySchema(z.object({ name: z.string().min(1).optional() }))
    @Get()
    run(request) {}
}

ParamsSchema

This decorator is responsible for validating all parameters passed in the Url of the request, using the Zod as a validation schema.

OptionDescriptionRequired
schemaDefines the validation schema using zodYes

Example of how to use the ParamsSchema:

import { ParamsSchema, Get } from 'kenai';
import { z } from 'zod';

class MainRouter {
    @ParamsSchema(z.object({ name: z.string().min(1) }))
    @Get()
    run(request) {}
}

Returns

This decorator defines all possible returns of the request, defining the status and body of the response using Zod as validation for the output.

OptionDescriptionRequired
statusDefines the status of the responseYes
schemaDefines the validation schema using zodNo

Example of how to use Returns:

import { Returns, Get } from 'kenai';
import { z } from 'zod';

class MainRouter {
    @Returns(200, z.object({ name: z.string().min(1) }))
    @Returns(201)
    @Get()
    run() {
        return { name: 'Kenai' };
    }
}

Methods

The methods are responsible for creating the route controllers.

All methods accept the same parameters:

OptionDescriptionRequired
pathDefines the route pathYes
fastifyRouteOptionsDefines Fastify route optionsNo

Get

This decorator is responsible for creating a controller for a GET route.

Example of how to use Get:

import { Get } from 'kenai';

class MainRouter {
    @Get('/hello-world')
    helloWorld() {
        return 'Hello World!';
    }
}

Post

This decorator is responsible for creating a controller for a POST route.

Example of how to use Post:

import { Post } from 'kenai';

class MainRouter {
    @Post('/hello-world')
    helloWorld() {
        return 'Hello World!';
    }
}

Put

This decorator is responsible for creating a controller for a PUT route.

Example of how to use Put:

import { Put } from 'kenai';

class MainRouter {
    @Put('/hello-world')
    helloWorld() {
        return 'Hello World!';
    }
}

Patch

This decorator is responsible for creating a controller for a PATCH route.

Example of how to use Patch:

import { Patch } from 'kenai';

class MainRouter {
    @Patch('/hello-world')
    helloWorld() {
        return 'Hello World!';
    }
}

Delete

This decorator is responsible for creating a controller for a DELETE route.

Example of how to use Delete:

import { Delete } from 'kenai';

class MainRouter {
    @Delete('/hello-world')
    helloWorld() {
        return 'Hello World!';
    }
}

Params

The 'params' are responsible for creating custom parameters in the route handler.

All 'params' accept these same parameters:

OptionDescriptionMandatory
keyName of some value that can be obtained in that objectYes

Reply

This decorator returns the entire response body.

Example of how to use Reply:

import { Reply, Post } from 'kenai';

class MainRouter {
    @Post('/hello-world')
    helloWorld(@Reply() reply: FastifyReply) {
        return reply.code(401).send('Unauthorized');
    }
}

// Getting values within the request body

class MainRouter {
    @Post('/hello-world')
    helloWorld(@Reply('statusCode') statusCode: number) {
        return statusCode;
    }
}

Request

This decorator returns the entire request object.

Example of how to use Request:

import { Request, Post } from 'kenai';

class MainRouter {
    @Post('/hello-world')
    helloWorld(@Request() request: FastifyRequest) {
        return request;
    }
}

// Getting values within the request body

class MainRouter {
    @Post('/hello-world')
    helloWorld(@Request('body') body: any) {
        return body;
    }
}

Params

This decorator returns all parameters of the request.

Example of how to use the Params:

import { Params, Post } from 'kenai';

class MainRouter {
    @Post('/hello-world/:name')
    helloWorld(@Params() params: Record<string, string>) {
        return params;
    }
}

Body

This decorator returns the entire request body.

Example of how to use Body:

import { Body, Post } from 'kenai';

class MainRouter {
    @Post('/hello-world')
    helloWorld(@Body() body: any) {
        return body;
    }
}

Query

This decorator returns all query parameters of the request.

Example of how to use the Query:

import { Query, Post } from 'kenai';

class MainRouter {
    @Post('/hello-world')
    helloWorld(@Query() query: Record<string, string>) {
        return query;
    }
}

Headers

This decorator returns all request headers.

Example of how to use the Headers:

import { Headers, Post } from 'kenai';

class MainRouter {
    @Post('/hello-world')
    helloWorld(@Headers() headers: Record<string, string>) {
        return headers;
    }
}

Cache

Cache

This decorator allows you to store the result of a route in cache. This means that, when a request is made to this route, the results are stored in the cache and reused in the next request, thus saving response time.

To enable the caching system, you must establish a connection with Redis in the Kenai configuration options (Plugin).

OptionDescriptionRequired
timeTime in seconds that the result will be stored in cacheYes

Example of how to use the Cache:

import { Cache, Get } from 'kenai';

class MainRouter {
    @Get('/hello-world')
    @Cache(60)
    helloWorld() {
        return 'Hello World!';
    }
}

Cache.InvalidateOnUpdate

This decorator allows you to invalidate the cache of a route whenever the stored content is updated. This means that, when calling the route, the corresponding cache will be automatically invalidated, ensuring that the next request returns updated data.

For example, I have a route that fetches all users from the database and another that updates a specific user. When I update a user, I want the cache to be invalidated so that I can have the updated data in the next request.

Example of how to use the Cache.InvalidateOnUpdate:

import { Cache, Get } from 'kenai';

class MainRouter {
    @Post('/hello-world')
    @Cache.InvalidateOnUpdate()
    helloWorld() {
        return 'Hello World!';
    }
}

OpenAPI

The decorators in this category are responsible for describing routes, automatically generating documentation with Swagger from these descriptions.

Decorators such as BodySchema, ParamsSchema, QuerySchema, and Returns accept Zod as a validation schema. This allows you to define detailed descriptions for values using the describe function, or create complete specifications with the zod-to-openapi package.

Description

This decorator defines a description about the route.

OptionDescriptionRequired
descriptionDescribes the routeYes

Example of how to use the Description:

import { Description, Get } from 'kenai';

class MainRouter {
    @Get('/hello-world')
    @Description('Hello World!')
    helloWorld() {
        return 'Hello World!';
    }
}

Summary

This decorator defines a summary about the route.

OptionDescriptionRequired
summaryRoute summaryYes

Example of how to use the Summary:

import { Summary, Get } from 'kenai';

class MainRouter {
    @Get('/hello-world')
    @Summary('Hello World!')
    helloWorld() {
        return 'Hello World!';
    }
}

Tags

This decorator defines tags for the route. Tags are very useful for organizing routes into logical categories, making the API documentation easier to understand and navigate.

OptionDescriptionRequired
tagsRoute tagsYes

Example of how to use the Tags:

import { Tags, Get } from 'kenai';

class MainRouter {
    @Get('/hello-world')
    @Tags('Hello World')
    helloWorld() {
        return 'Hello World!';
    }
}

Consumes

This decorator defines which types of content can be sent in the request. It is useful for specifying if the route only accepts application/json, for example.

OptionDescriptionRequired
consumesAccepted content typesYes

Example of how to use the Consumes:

import { Consumes, Post } from 'kenai';

class MainRouter {
    @Post('/hello-world')
    @Consumes(['application/json'])
    helloWorld() {
        return 'Hello World!';
    }
}

Security

This decorator defines which securities should be used to protect the route. It is useful for specifying if the route needs authentication, for example.

OptionDescriptionRequired
securityRoute securitiesYes

Example of how to use the Security:

import { Security, Post } from 'kenai';

class MainRouter {
    @Post('/hello-world')
    @Security({ apiKey: [] })
    helloWorld() {
        return 'Hello World!';
    }
}

OperationId

This decorator defines the name of an operation. It is useful for defining different names for operations in the same controller.

OptionDescriptionRequired
operationIdOperation nameYes

Example of how to use the OperationId:

import { OperationId, Get } from 'kenai';

class MainRouter {
    @Get('/hello-world')
    @OperationId('helloWorld')
    helloWorld() {
        return 'Hello World!';
    }
}

Deprecated

This decorator defines if the route is deprecated. It is useful for marking routes that should not be used in production.

Example of how to use the Deprecated:

import { Deprecated, Get } from 'kenai';

class MainRouter {
    @Get('/hello-world')
    @Deprecated
    helloWorld() {
        return 'Hello World!';
    }
}

Hide

This decorator defines if the route should be hidden. It is useful for marking routes that should not be displayed in the API documentation.

Example of how to use the Hide:

import { Hide, Get } from 'kenai';

class MainRouter {
    @Get('/hello-world')
    @Hide
    helloWorld() {
        return 'Hello World!';
    }
}

Extra

createParamsDecorator

Use this function to create decorators for route parameters. For example:

OptionDescriptionRequired
pathInitial path where the parameter will be obtainedYes
keyProperty name that you want to obtainNo
import { createParamsDecorator, Get } from 'kenai';

const Session = (key?: string) => createParamsDecorator('request/session', key);
// Or
const IP = createParamsDecorator('request/ip');

export class MainRouter {
    @Get('/')
    run(@Session() session: any, @IP ip: string) {
        return { session, ip };
    }
}
1.2.12

8 months ago

1.2.13

8 months ago

1.2.10

8 months ago

1.2.11

8 months ago

1.2.16

5 months ago

1.2.14

8 months ago

1.2.15

8 months ago

1.2.9

8 months ago

1.2.8

8 months ago

1.2.7

8 months ago

1.2.6

8 months ago

1.2.5

8 months ago

1.2.0

8 months ago

1.1.9

8 months ago

1.2.4

8 months ago

1.2.3

8 months ago

1.2.2

8 months ago

1.2.1

8 months ago

1.1.1

8 months ago

1.1.0

8 months ago

1.0.8-dev.20241013

8 months ago

1.1.8

8 months ago

1.0.9

8 months ago

1.1.7

8 months ago

1.0.8

8 months ago

1.1.6

8 months ago

1.0.7

9 months ago

1.1.5

8 months ago

1.1.4

8 months ago

1.1.3

8 months ago

1.1.2

8 months ago

1.0.8-dev.20241019

8 months ago

1.0.6

1 year ago

1.0.5

1 year ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago