🎪 Demo & Explanation of Acai-TS
📚 Examples Repository
Don't like reading documentation? Check out our working examples:
Working Examples
All examples are located in the examples directory of this repository.
- APIGateway with Decorators - Full decorator-based routing example
- APIGateway with Pattern Routing - Convention over configuration example
- DynamoDB Streams - Process DynamoDB stream events
- S3 Events - Process S3 bucket events
- SQS Messages - Process SQS queue messages
🚀 Quick Start Tutorial
1️⃣ Install Acai-TS
| npm install acai-ts reflect-metadata
|
2️⃣ Create Your First Endpoint
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | import 'reflect-metadata';
import { Router, BaseEndpoint, Response, Request } from 'acai-ts';
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
// File: src/handlers/hello.ts
export class HelloEndpoint extends BaseEndpoint {
async get(request: Request, response: Response): Promise<Response> {
response.body = { message: 'Hello, World!' };
return response;
}
}
export const handler = async (
event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
const router = new Router({
basePath: '/api/v1',
routesPath: './src/handlers/**/*.ts'
});
return await router.route(event);
};
|
3️⃣ Add Schema Validation
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | // File: src/handlers/users.ts
import { BaseEndpoint, Validate, Response, Request } from 'acai-ts';
export class UsersEndpoint extends BaseEndpoint {
@Validate({ requiredBody: 'CreateUserRequest' })
async post(request: Request, response: Response): Promise<Response> {
// request.body is already validated against your OpenAPI schema
response.body = {
id: '123',
...request.body
};
return response;
}
}
|
4️⃣ Add Middleware
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | // File: src/handlers/profile.ts
import { BaseEndpoint, Before, Response, Request } from 'acai-ts';
const authMiddleware = async (request: Request, response: Response) => {
if (!request.headers.authorization) {
response.code = 401;
response.setError('auth', 'Unauthorized');
}
};
export class ProfileEndpoint extends BaseEndpoint {
@Before(authMiddleware)
async get(request: Request, response: Response): Promise<Response> {
response.body = { user: 'profile data' };
return response;
}
}
|
💡 Key Concepts
🎆 Happy Path Programming
Acai-TS embraces Happy Path Programming - validation happens upfront, so your business logic runs cleanly:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | // ❌ Without Acai-TS: Defensive coding everywhere
export const handler = async (event: any) => {
try {
if (!event.body) throw new Error('No body');
const body = JSON.parse(event.body);
if (!body.email) throw new Error('Email required');
// Finally, business logic...
} catch (error) {
return { statusCode: 400, body: JSON.stringify({ error }) };
}
};
// ✅ With Acai-TS: Validation handled, focus on logic
export class CreateUserEndpoint extends BaseEndpoint {
@Validate({ requiredBody: 'CreateUserRequest' })
async post(request: Request, response: Response): Promise<Response> {
// Body is already validated - just write business logic!
const user = await this.userService.create(request.body);
response.body = user;
return response;
}
}
|
📘 TypeScript First
Full type safety throughout:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | interface User {
id: string;
email: string;
name: string;
}
// File: src/handlers/users/{id}.ts
export class UserEndpoint extends BaseEndpoint {
async get(request: Request, response: Response): Promise<Response> {
const userId: string = request.pathParameters.id;
const user: User = await this.userRepo.findById(userId);
response.body = user; // Fully typed!
return response;
}
}
|
📍 Next Steps