Skip to content

LibirSoft/AsenaExample

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

18 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

AsenaJS Example Project πŸš€

A comprehensive example application showcasing AsenaJS framework features through Todo and Chat applications with real-time WebSocket communication.

🎯 About AsenaJS

AsenaJS is a modern TypeScript framework for building scalable server-side applications with:

  • Decorator-based architecture - Clean, declarative code
  • Dependency Injection - Built-in IoC container
  • WebSocket support - First-class real-time communication
  • Database integration - Seamless ORM integration (Drizzle)
  • Type safety - Full TypeScript support throughout

✨ Features Demonstrated

Core AsenaJS Features

1. Dependency Injection

@Service()
export class TodoService {
  @Inject("TodoRepository")
  // @Inject(TodoRepository) you can use like that also
  private todoRepository: TodoRepository;
}

2. Decorator-based Routing

@Controller({ path: '/todos', middlewares: [AuthMiddleware] })
export class TodoController {
  @Get({ path: '/', description: 'Get all todos' })
  public async getTodos(context: Context) { }
}

3. Repository Pattern with Drizzle ORM

import {BunSQLDatabase} from "drizzle-orm/bun-sql";

@Repository({
  databaseService: 'DatabaseService',
  table: TodoSchema,
})
export class TodoRepository extends BaseRepository<TodoSchemaType, BunSQLDatabase> {
  public async getTodosByUserId(userId: string): Promise<Todo[]> {
    return await this.db!.select().from(TodoSchema);
  }
}

4. WebSocket Support

@WebSocket({ path: 'chat-room', middlewares: [WSAuthMiddleware] })
export class ChatWebSocket extends AsenaWebSocketService<{ user: User }> {
  @Inject("ChatService")
  private chatService: ChatService;
  
  public async onMessage(ws: Socket, message: Buffer | string) {
    // Real-time message handling
  }
}

5. Middleware System

@Middleware()
export class AuthMiddleware implements MiddlewareService {
  public async handle(context: Context, next: Next) {
    // Authentication logic
  }
}

6. Validation with Zod

@Middleware({ validator: true })
export class CreateTodoValidator extends ValidationService {
  public json() {
    return z.object({
      title: z.string(),
      description: z.string(),
      isCompleted: z.boolean(),
    });
  }
}

πŸ—οΈ Project Architecture

Clean Architecture Layers

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Controllers                 β”‚  ← REST & WebSocket endpoints
β”‚  @Controller, @WebSocket            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          Services                   β”‚  ← Business logic
β”‚          @Service                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚        Repositories                 β”‚  ← Data access
β”‚  @Repository (BaseRepository)       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      Database (Drizzle ORM)         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Project Structure

src/
β”œβ”€β”€ controller/          # REST & WebSocket controllers
β”‚   β”œβ”€β”€ TodoController.ts
β”‚   β”œβ”€β”€ ChatController.ts
β”‚   └── AuthController.ts
β”œβ”€β”€ core/
β”‚   β”œβ”€β”€ repository/      # @Repository classes
β”‚   β”‚   β”œβ”€β”€ TodoRepository.ts
β”‚   β”‚   └── ChatRepository.ts
β”‚   β”œβ”€β”€ service/         # @Service classes
β”‚   β”‚   β”œβ”€β”€ TodoService.ts
β”‚   β”‚   └── ChatService.ts
β”‚   └── schemas/         # Drizzle ORM schemas
β”‚       β”œβ”€β”€ User.ts
β”‚       β”œβ”€β”€ Todo.ts
β”‚       └── Chat.ts
β”œβ”€β”€ websocket/           # WebSocket handlers
β”‚   β”œβ”€β”€ ChatWebSocket.ts          # Authenticated
β”‚   └── NotificationWebSocket.ts  # Public
└── middleWare/
    β”œβ”€β”€ auth/            # Authentication
    └── validator/       # Request validation

πŸš€ Quick Start

1. Install Dependencies

bun install

2. Setup Database

# Create PostgreSQL database
psql -U postgres -c "CREATE DATABASE asenatest;"

# Generate migrations from schemas
bun run drizzle:generate

# Apply migrations
bun run drizzle:migrate

3. Start Server

bun run build:start

Server runs on http://localhost:3000

4. Test WebSockets

Open http://localhost:3000/websocket-test.html for interactive WebSocket testing.

πŸ“‹ API Examples

Todo API (with Authentication)

Create Todo:

POST /todos
Authorization: Cookie
{
  "title": "Learn AsenaJS",
  "description": "Study the framework",
  "isCompleted": false
}

Get All Todos:

GET /todos
Authorization: Cookie

Chat API (with Authentication)

Create Chat Room:

POST /chat/rooms
{
  "name": "General",
  "description": "Main chat room"
}

Send Message:

POST /chat/messages
{
  "content": "Hello, World!",
  "roomId": "room-uuid"
}

πŸ”Œ WebSocket Examples

1. Chat WebSocket (Authenticated)

// Requires authentication cookie
const chatWs = new WebSocket('ws://localhost:3000/chat-room');

chatWs.onopen = () => {
  // Join a room and send message
  chatWs.send(JSON.stringify({
    type: 'message',
    content: 'Hello everyone!',
    roomId: 'room-uuid'
  }));
};

chatWs.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('Received:', data);
};

2. Notification WebSocket (Public)

// No authentication required
const notifWs = new WebSocket('ws://localhost:3000/notifications');

notifWs.onopen = () => {
  // Subscribe to a channel
  notifWs.send(JSON.stringify({
    type: 'subscribe',
    channel: 'updates'
  }));
};

notifWs.onmessage = (event) => {
  const notification = JSON.parse(event.data);
  console.log('Notification:', notification);
};

πŸŽ“ Key AsenaJS Concepts

1. Dependency Injection

AsenaJS uses a powerful IoC container. Dependencies are automatically resolved:

@Service()
export class ChatService {
  @Inject(ChatRepository)  // Automatically injected
  private chatRepository: ChatRepository;
}

2. Decorator-based Configuration

Everything is configured through decorators:

  • @Controller() - Define REST controllers
  • @Service() - Define services
  • @Repository() - Define data repositories
  • @WebSocket() - Define WebSocket handlers
  • @Middleware() - Define middlewares
  • @Get(), @Post(), @Put(), @Delete() - Define routes

3. Middleware Chain

Middlewares can be applied at controller or route level:

@Controller({ 
  path: '/todos', 
  middlewares: [AuthMiddleware] // Applied to all routes
})
export class TodoController {
  @Post({ 
    path: '/', 
    validator: CreateTodoValidator // Route-specific
  })
  public async create(context: Context) { }
}

4. WebSocket with Authentication

WebSockets can use middlewares just like REST endpoints:

@WebSocket({ 
  path: 'chat-room', 
  middlewares: [WSAuthMiddleware] // Auth required
})
export class ChatWebSocket extends AsenaWebSocketService<{ user: User }> {
  public onMessage(ws: Socket<{ user: User }>, message: Buffer | string) {
    // User data available from ws.data.user
  }
}

5. Type-Safe Database Access

Using Drizzle ORM with AsenaJS:

@Repository({
  databaseService: 'DatabaseService',
  table: TodoSchema,
})
export class TodoRepository extends BaseRepository<TodoSchemaType> {
  // this.db is automatically injected and type-safe
  public async getTodos(): Promise<Todo[]> {
    return await this.db!.select().from(TodoSchema);
  }
}

🌟 Application Features

Todo Application

  • βœ… Full CRUD operations
  • βœ… User-specific todos
  • βœ… Authentication required
  • βœ… Request validation with Zod
  • βœ… UUID-based identification

Chat Application

REST API:

  • βœ… Create/list/delete chat rooms
  • βœ… Send/retrieve messages
  • βœ… Mark messages as read
  • βœ… User authorization

WebSocket (Authenticated):

  • βœ… Real-time messaging
  • βœ… Room-based communication
  • βœ… Message persistence
  • βœ… Typing indicators
  • βœ… Pub/Sub pattern

WebSocket (Public):

  • βœ… Public broadcast system
  • βœ… Channel subscriptions
  • βœ… Real-time notifications
  • βœ… No authentication needed

πŸ’Ύ Database

Using Drizzle ORM with automatic migrations:

// Define schema
export const TodoSchema = pgTable('todos', {
  id: uuid('id').primaryKey().defaultRandom(),
  title: text('title').notNull(),
  userId: uuid('user_id').references(() => UserSchema.id, { onDelete: 'cascade' }),
});
// Drizzle Kit generates migrations automatically
bun run drizzle:generate
bun run drizzle:migrate

Database Schema:

  • Users table (UUID primary keys)
  • Todos table (with foreign keys)
  • Chat rooms table
  • Messages table

πŸ§ͺ Testing

Interactive WebSocket Test Page: Visit http://localhost:3000/websocket-test.html to:

  • Test both WebSocket endpoints
  • Subscribe to channels
  • Send/receive messages
  • See real-time updates

πŸ“š Learn More

πŸ› οΈ Technologies

  • AsenaJS - Backend framework
  • TypeScript - Type safety
  • Drizzle ORM - Database toolkit
  • PostgreSQL - Database
  • Bun - JavaScript runtime
  • Hono - Web framework adapter
  • Zod - Schema validation

πŸ“ Notes

  • All IDs use UUID for scalability
  • WebSocket connections support authentication
  • Repository pattern with dependency injection
  • Clean separation of concerns
  • Full TypeScript type safety

Built with ❀️ using AsenaJS

This example demonstrates AsenaJS's powerful features for building modern, scalable applications with clean architecture and type safety.

About

Example project of asena framework usage

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published