Lafken
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.
Key Features
- 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
Getting Started
Installation
Create a new Lafken project:
npm create lafken@latest
Or install in an existing TypeScript project:
npm install @lafken/main @lafken/api @lafken/common
System Requirements
- Node.js >= 20.19
- pnpm >= 10.20.0
- TypeScript >= 5.0
Core Concepts
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)
5-Minute Example
Here's a complete serverless API:
1. Define Your Resource
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}!`
};
}
}
2. Create a Module
import { createModule } from '@lafken/main';
export const helloModule = createModule({
name: 'hello-module',
resources: [HelloApi],
});
3. Create Your App
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
Advanced Features
Environment Variables
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, getSSMValue }) => ({
// 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: getSSMValue('/my-app/api-key')
}),
}
})
getUser() { /* ... */ }
}
Type-Safe Resource References
Enable TypeScript autocomplete for your infrastructure:
Create lafken-types.d.ts in your project root and extend the two interfaces from @lafken/common:
SharedResourceNames— resources defined and owned by your applicationSharedReferenceResources— resources from external stacks that your app references
declare module '@lafken/common' {
// Resources defined in this application
interface SharedResourceNames {
api: 'my-api';
'api-authorizer': 'cognito-auth' | 'custom-auth';
lambda: 'my-function';
queue: 'my-queue';
bucket: 'my-bucket';
dynamo: 'my-table';
'state-machine': 'my-workflow';
'user-pool': 'my-user-pool';
'user-pool-client': 'my-user-pool-client';
}
// Resources from external stacks referenced by this application
interface SharedReferenceResources {
dynamo: 'shared-table';
queue: 'shared-queue';
'user-pool': 'shared-user-pool';
'state-machine': 'shared-workflow';
'event-bus': 'shared-event-bus';
'event-rule': 'shared-event-rule';
schedule: 'shared-schedule';
lambda: 'shared-function';
}
}
export {};
Each key is a resource scope, and the value is a union of valid resource names for that scope. Only include the scopes your application actually uses.
Now you get full autocomplete:
getResourceValue('dynamo::my-table', 'arn') // ✓ TypeScript knows this is valid
getResourceValue('dynamo::invalid', 'arn') // ✗ TypeScript error
Creating Custom Resolvers
Extend 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 */ }
}
Complete Package Documentation
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
Contributing
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
Security
Found a security vulnerability? Please report it responsibly via SECURITY.md. Do not open public issues for security vulnerabilities.
License
MIT License - see LICENSE file for details.
Need Help?
- 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!