A TypeScript framework for building serverless applications on AWS using decorators.
Lafken simplifies AWS infrastructure by letting you define resources with decorators in your TypeScript code. Focus on your application logic while Lafken automatically generates and manages all the infrastructure using Terraform.
Lafken leverages cdk-terrain to transform application code into Terraform-based infrastructure.
If you find Lafken useful, please consider supporting the cdk-terrain project. Your support helps us grow the ecosystem and continue building better tools together.
- Decorator-Based: Define infrastructure with familiar TypeScript decorators
- Type-Safe: Full TypeScript support with autocomplete for resources
- Zero Configuration: Start building immediately with sensible defaults
- Modular: Organize resources into logical modules
- Extensible: Create custom resolvers for additional AWS services
- Infrastructure as Code: Infrastructure is version-controlled TypeScript code
Create a new Lafken project:
npm create lafken@latestOr install in an existing TypeScript project:
npm install @lafken/main @lafken/api @lafken/common- Node.js >= 20.19
- pnpm >= 10.20.0
- TypeScript >= 5.0
Lafken works through three key components:
- Decorators: Mark your classes and methods to define infrastructure (
@Api,@Get,@Queue, etc.) - Modules: Group related resources together with shared configuration
- App: Register modules and resolvers to generate your infrastructure
Here's the flow:
TypeScript Code (with decorators)
β
Module (groups resources)
β
App + Resolvers (processes decorators)
β
Terraform Configuration (generated automatically)
Here's a complete serverless API:
import { Api, Get, ApiRequest, PathParam } from '@lafken/api/main';
@ApiRequest()
export class HelloRequestEvent {
@PathParam()
name: number;
}
@Api({
path: '/hello'
})
export class HelloApi {
@Get({
path: '/{name}'
})
greet(@Event(HelloRequestEvent) event: HelloRequestEvent) {
return {
message: `Hello, ${event.name}!`
};
}
}import { createModule } from '@lafken/main';
export const helloModule = createModule({
name: 'hello-module',
resources: [HelloApi],
});import { createApp } from '@lafken/main';
import { ApiResolver } from '@lafken/api/resolver';
createApp({
name: 'hello-app',
resolvers: [new ApiResolver()],
modules: [helloModule],
});That's it! Lafken generates all the AWS infrastructure:
- API Gateway REST API
- Lambda function
- IAM roles with least-privilege permissions
- Terraform configuration
Define environment variables for your Lambda functions with support for static and dynamic values:
@Api({ path: '/users' })
export class UserApi {
@Get({
path: '/{id}',
lambda: {
env: ({ getResourceValue }) => ({
// Static value
APP_NAME: 'my-app',
// Environment variable
DEBUG: process.env.DEBUG || 'false',
// Dynamic reference to another resource
TABLE_NAME: getResourceValue('dynamo::users', 'name'),
// AWS Systems Manager Parameter Store
API_KEY: 'SSM::STRING::/my-app/api-key'
}),
}
})
getUser() { /* ... */ }
}Enable TypeScript autocomplete for your infrastructure:
Create lafken-types.d.ts in your project root:
declare module '@lafken/common' {
// Register application modules
interface ModulesAvailable {
// Module name
greeting: {
// STATE MACHINE resources within the module
StateMachine: {
// Resource name mapped to a boolean flag
GreetingStepFunction: true;
};
// QUEUE resources within the module
Queue: {
'greeting-standard-queue': true;
};
};
}
// bucket
interface BucketAvailable {
'lafken-example-documents': true;
}
// api
interface ApiRestAvailable {
UserApi: true;
}
interface DynamoTableAvailable {
users: true;
}
}
export {};Now you get full autocomplete:
getResourceValue('dynamo::users', 'arn') // β TypeScript knows this is valid
getResourceValue('dynamo::invalid', 'arn') // β TypeScript errorExtend Lafken with your own AWS services:
import { ResolverType } from '@lafken/resolver';
export class MyServiceResolver implements ResolverType {
async beforeCreate(scope) { /* Shared resources */ }
async create(module, resource) { /* Process resource */ }
async afterCreate(scope) { /* Configure integrations */ }
}Lafken is organized into focused packages. Here's what each does:
| Package | Purpose |
|---|---|
| @lafken/main | Core engine - create apps and modules |
| @lafken/api | REST APIs with API Gateway |
| @lafken/queue | SQS queues and message processing |
| @lafken/event | EventBridge event buses |
| @lafken/schedule | Scheduled Lambda functions |
| @lafken/state-machine | Step Functions workflows |
| @lafken/bucket | S3 bucket management |
| @lafken/dynamo | DynamoDB tables |
| @lafken/auth | Cognito authentication |
| @lafken/resolver | Base utilities for creating resolvers |
| @lafken/common | Decorators and type utilities |
View full documentation for each package:
- Main Module - Application setup and configuration
- API Module - Create REST APIs
- Queue Module - SQS queues and workers
- Event Module - EventBridge event buses
- Schedule Module - Scheduled tasks
- State Machine Module - Step Functions
- Bucket Module - S3 buckets
- Dynamo Module - DynamoDB tables
- Auth Module - Cognito setup
- Resolver Module - Create custom resolvers
- Common Module - Utilities and decorators
We welcome contributions! Here are some ways to help:
- Report Bugs: Use the bug report template
- Suggest Features: Use the feature request template
- Improve Docs: Open a documentation issue
- Submit Code: Read our Contributing Guide
Found a security vulnerability? Please report it responsibly via SECURITY.md. Do not open public issues for security vulnerabilities.
MIT License - see LICENSE file for details.
- GitHub Discussions: Ask questions and share ideas
- GitHub Issues: Report bugs or request features
- Code of Conduct: Please review our CODE_OF_CONDUCT.md
Happy building with Lafken! π