npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@avleon/core

v0.0.45

Published

avleon core

Readme

Avleon

npm version Build

⚠️ WARNING

🚧 This project is in active development.

Overview

Avleon is a powerful, TypeScript-based web framework built on top of Fastify, designed to simplify API development with a focus on decorators, dependency injection, and OpenAPI documentation. It provides a robust set of tools for building scalable, maintainable web applications with minimal boilerplate code.

Table of Contents

Features

  • Decorator-based API Development: Define controllers, routes, and middleware using TypeScript decorators
  • Dependency Injection: Built-in DI system using TypeDI for service management
  • OpenAPI/Swagger Integration: Automatic API documentation generation with support for both Swagger UI and Scalar
  • Validation: Request validation with support for class-validator and custom validation rules
  • Middleware System: Flexible middleware architecture for request processing
  • Response Handling: Standardized response formats with HTTP status codes
  • File Upload: Built-in support for multipart file uploads with file validation
  • Authentication & Authorization: Middleware for securing your API endpoints
  • Database Integration: Support for TypeORM for database operations
  • Queue System: Background job processing capabilities
  • Environment Configuration: Environment variable management
  • Logging: Integrated logging with Pino
  • Testing: Built-in testing utilities for API endpoints

Installation

npx @avleon/cli new myapp
# or
yarn dlx @avleon/cli new myapp
# or
pnpm dlx @avleon/cli new myapp

Quick Start

Minimal

import { Avleon } from "@avleon/core";

const app = Avleon.createApplication();
app.mapGet("/", () => "Hello, Avleon");
app.run(); // or app.run(3000);

Controller Based

import { Avleon, ApiController, Get, Results } from "@avleon/core";

// Define a controller
@ApiController
class HelloController {
  @Get()
  sayHello() {
    return "Hello, Avleon!";
  }
}

// Create and start the application
const app = Avleon.createApplication();
app.useControllers([HelloController]);
app.run();

Core Concepts

Application Creation

Avleon provides a builder pattern for creating applications:

import { Avleon } from "@avleon/core";

// Create an application
const app = Avleon.createApplication();

// Configure and run the application
app.useCors();
app.useControllers([UserController]);
// For auto register controller `app.useControllers({auto:true});`

app.run(); // or app.run(port)

Controllers

Controllers are the entry points for your API requests. They are defined using the @ApiController decorator:

@ApiController("/users")
class UserController {
  // Route handlers go here
}

Route Methods

Define HTTP methods using decorators:

@Get('/')
async getUsers() {
  // Handle GET request
}

@Post('/')
async createUser(@Body() user: UserDto) {
  // Handle POST request
}

@Put('/:id')
async updateUser(@Param('id') id: string, @Body() user: UserDto) {
  // Handle PUT request
}

@Delete('/:id')
async deleteUser(@Param('id') id: string) {
  // Handle DELETE request
}

Parameter Decorators

Extract data from requests using parameter decorators:

@Get('/:id')
async getUser(
  @Param('id') id: string,
  @Query('include') include: string,
  @Header('authorization') token: string,
  @Body() data: UserDto
) {
  // Access route parameters, query strings, headers, and request body
}

Error Handling

Return standardized responses using the HttpResponse and HttpExceptions class:

@Get('/:id')
async getUser(@Param('id') id: string) {
  const user = await this.userService.findById(id);

  if (!user) {
    throw HttpExceptions.NotFound('User not found');
  }

  return HttpResponse.Ok(user);
}

Middleware

Create and apply middleware for cross-cutting concerns:

@Middleware
class LoggingMiddleware extends AppMiddleware {
  async invoke(req: IRequest) {
    console.log(`Request: ${req.method} ${req.url}`);
    return req;
  }
}

@UseMiddleware(LoggingMiddleware)
@ApiController("/users")
class UserController {
  // Controller methods
}

You can also apply middleware to specific routes:

@ApiController("/users")
class UserController {
  @UseMiddleware(LoggingMiddleware)
  @Get("/")
  async getUsers() {
    // Only this route will use the LoggingMiddleware
  }
}

Authentication & Authorization

Secure your API with authentication and authorization:

import { CanAuthorize } from "@avleon/core";

@CanAuthorize
class JwtAuthorization extends AuthorizeMiddleware {
  authorize(roles: string[]) {
    return async (req: IRequest) => {
      // Implement JWT authentication logic
      return req;
    };
  }
}

Now register the authrization class to our app by useAuthorization function;

app.useAuthorization(JwtAuthorization);

Then you have access the AuthUser on class lavel or method lavel depending on how you use the @Authorized() decorator.

// admin.controller.ts
@Authorized()
@ApiController("/admin")
class AdminController {
  // Protected controller methods

  // protected controller has access to AuthUser in each route method
  @Get()
  async account(@AuthUser() user: User) {
    ///
  }
}

// Or protect specific routes with roles
@ApiController("/admin")
class AdminController {
  @Authorized({
    roles: ["admin"],
  })
  @Get("/")
  async adminDashboard() {
    // Only users with 'admin' role can access this
  }
}

Validation

Validate request data using class-validator:

class UserDto {
  @IsString()
  @IsNotEmpty()
  name: string;

  @IsEmail()
  email: string;

  @IsNumber()
  @Min(0)
  @Max(120)
  age: number;
}

@Post('/')
async createUser(@Body() user: UserDto) {
  // User data is automatically validated
  return user;
}

You can also use custom validation rules:

class UserDto {
  @Validate({
    type: "string",
    required: true,
    message: "Name is required",
  })
  name: string;

  @Validate({
    type: "number",
    min: 0,
    max: 120,
    message: "Age must be between 0 and 120",
  })
  age: number;
}

OpenAPI Documentation

Generate API documentation automatically:


app.useOpenApi({
    info: {
      title: "User API",
      version: "1.0.0",
      description: "API for managing users",
    },
    servers: [
      {
        url: "http://localhost:3000",
        description: "Development server",
      },
    ],
  });

You can also customize the OpenAPI UI:

app.useOpenApi(OpenApiConfig, (config) => {
  // Modify the OpenAPI configuration
  config.info.title = "Custom API Title";
  return config;
});

Advanced Features

Database Integration

1. Knex

const app = Avleon.createApplication();
app.useKnex({
  client: 'mysql',
  connection: {
    host: '127.0.0.1',
    port: 3306,
    user: 'your_database_user',
    password: 'your_database_password',
    database: 'myapp_test',
  },
})

or using config class

@AppConfig
export class KnexConfig implements IConfig {
  // config method is mendatory
  // config method has access to environment variables by default
  config(env: Environment) {
    return {
      client: 'mysql',
      connection: {
        host: env.get("DB_HOST") || '127.0.0.1',
        port: env.get("DB_PORT") || 3306,
        user: env.get("DB_USER")|| 'your_database_user',
        password: env.get("DB_PASS") || 'your_database_password',
        database: env.get("DB_NAME") || 'myapp_test',
      },
    };
  }
}

// now we can register it with our app

app.useKenx(KnexConfig)

Exmaple uses

import { DB, AppService } from "@avleon/core";

@AppService
export class UsersService{
  constructor(
    private readonly db: DB
  ){}

  async findAll(){
    const result = await this.db.client.select("*").from("users");
    return result;
  }
}

2. Typeorm

Connect to databases using TypeORM:

const app = Avleon.createApplication();
app.useDataSource({
  type: "postgres",
  host: "localhost",
  port: 5432,
  username: "postgres",
  password: "password",
  database: "avleon",
  entities: [User],
  synchronize: true,
});

Or use the config class:

// datasource.config.ts
import { AppConfig, IConfig } from "@avleon/core";

@AppConfig
export class DataSourceConfig implements IConfig {
  // config method is mendatory
  // config method has access to environment variables by default
  config(env: Environment) {
    return {
      type: env.get("type") || "postgres",
      host: "localhost",
      port: 5432,
      username: "postgres",
      password: "password",
      database: "avleon",
      entities: [User],
      synchronize: true,
    };
  }
}
// app.ts
const app = Avleon.createApplication();
app.useDataSource(DataSourceConfig);
// ... other impments

Now in your Controller or Injected service use can use like this

import { AppService, InjectRepository } from "@avleon/core";
import { Repository } from "typeorm";
import { User } from "model_path";

@AppService
export class UserService {
  constructor(
    @InjectRepository(User)
    private readonly _userRepository: Repository<User>,
  ) {}

  async findAll() {
    const users = await this._userRepository.find();
    return users;
  }
}

File Uploads & File Storage

Handle file uploads with multipart support:

// Configure multipart file uploads
app.useMultipart({
  destination: path.join(process.cwd(), 'public/uploads'),
  limits: {
    fileSize: 5 * 1024 * 1024 // 5MB
  }
});
// In your controller
import {FileStorage} from '@avleon/core';

//inject FileStorage into constructor
constructor(
  private readonly fileStorage: FileStorage
){}

@OpenApi({
  description: "Uploading single file"
  body:{
    type:"object",
    properties:{
      file:{
        type:"string",
        format:"binary"
      }
    },
    required:["file"]
  }
})
@Post('/upload')
async uploadSingleFile(@UploadFile('file') file: MultipartFile) {
  // Process uploaded file
  const result = await this.fileStorage.save(file);
  // or with new name 
  //  const result = await this.fileStorage.save(file, {as:newname.ext});
  // result
  // {
  //  uploadPath:"/uplaod",
  //  staticPath: "/static/"
  //}
  return result;
}

Static Files

Serve static files:

import path from 'path';


app.useStaticFiles({
  path: path.join(process.cwd(), "public"),
  prefix: "/static/",
});

Configuration

Coming soon...

Route Mapping

Avleon provides several methods for mapping routes in your application:

mapGet

The mapGet method is used to define GET routes in your application. It takes a path string and a handler function as parameters.

app.mapGet("/users", async (req, res) => {
  // Handle GET request to /users
  return { users: [] };
});

mapPost

The mapPost method is used to define POST routes in your application. It takes a path string and a handler function as parameters.

app.mapPost("/users", async (req, res) => {
  // Handle POST request to /users
  const userData = req.body;
  // Process user data
  return { success: true };
});

mapPut

The mapPut method is used to define PUT routes in your application. It takes a path string and a handler function as parameters.

app.mapPut("/users/:id", async (req, res) => {
  // Handle PUT request to /users/:id
  const userId = req.params.id;
  const userData = req.body;
  // Update user data
  return { success: true };
});

mapDelete

The mapDelete method is used to define DELETE routes in your application. It takes a path string and a handler function as parameters.

app.mapDelete("/users/:id", async (req, res) => {
  // Handle DELETE request to /users/:id
  const userId = req.params.id;
  // Delete user
  return { success: true };
});

Add openapi and middleware support for inline route

Each of these methods returns a route object that can be used to add middleware or Swagger documentation to the route.

app
  .mapGet("/users", async (req, res) => {
    // Handler function
  })
  .useMiddleware([AuthMiddleware])
  .useOpenApi({
    summary: "Get all users",
    description: "Retrieves a list of all users",
    tags: ["users"],
    response: {
      200: {
        description: "Successful response",
        content: {
          "application/json": {
            schema: {
              type: "array",
              items: {
                type: "object",
                properties: {
                  id: { type: "string" },
                  name: { type: "string" },
                },
              },
            },
          },
        },
      },
    },
  });

Websocket Intregation (Socket.io)

app.useSocketIO({
  cors:{origin:"*"}
})

Now in controller or service use EventDispatcher

export class UserService{
  constructor(
    private readonly dispatcher: EventDispatcher
  )

  async create(){
    ...rest code

    await this.dispatcher.dispatch("users:notifications",{created:true, userId: newUser.Id})
  }
  
}

Testing

Test your API endpoints with the built-in testing utilities:

Coming soon...

License

ISC

Author

Tareq Hossain - GitHub