npm package: @lafken/main
Description: Lafken core engine - orchestrate AWS serverless infrastructure using decorators with automatic CDKTN code generation
Author: Aníbal Jorquera
Latest version: 0.10.6

# @lafken/main

Core entry point for a Lafken serverless application. `@lafken/main` initializes the AWS provider, orchestrates resolvers and modules, and synthesizes the resulting Terraform configuration through CDKTN. It provides `createApp` to bootstrap the application and `createModule` to organize resources into logical groups.

## Installation

```bash
npm install @lafken/main
```

## Getting Started

Create an application with resolvers and modules, then let Lafken generate all the infrastructure:

```typescript
import { createApp, createModule } from '@lafken/main';
import { ApiResolver } from '@lafken/api/resolver';
import { QueueResolver } from '@lafken/queue/resolver';

// 1. Define modules that group related resources
const userModule = createModule({
  name: 'users',
  resources: [UserApi, UserQueue],
});

const billingModule = createModule({
  name: 'billing',
  resources: [InvoiceSchedule],
});

// 2. Create the application
await createApp({
  name: 'my-app',
  modules: [userModule, billingModule],
  resolvers: [
    new ApiResolver({ restApi: { name: 'my-api' } }),
    new QueueResolver(),
  ],
});
```

## Features

### createApp

`createApp` is the main entry point. It initializes the AWS stack, runs all resolver lifecycle hooks (`beforeCreate` → `create` → `afterCreate`), and synthesizes the Terraform output:

```typescript
await createApp({
  name: 'my-app',
  modules: [userModule, billingModule],
  resolvers: [new ApiResolver(), new QueueResolver()],
  globalConfig: {
    lambda: {
      memory: 512,
      timeout: 30,
      runtime: 22,
      services: ['dynamodb', 's3', 'sqs'],
    },
    tags: {
      environment: 'production',
      team: 'platform',
    },
  },
  awsProviderConfig: {
    region: 'us-east-1',
    profile: 'my-aws-profile',
  },
  s3Backend: {
    bucket: 'my-terraform-state',
    key: 'app/terraform.tfstate',
    region: 'us-east-1',
  },
  extend: async (scope) => {
    // Add custom CDKTN constructs after all resolvers finish
  },
});
```

#### Application Options

| Option              | Type                | Required | Description                                               |
| ------------------- | ------------------- | -------- | --------------------------------------------------------- |
| `name`              | `string`            | Yes      | Application name, used as the stack identifier             |
| `modules`           | `StackModule[]`     | Yes      | Modules created with `createModule`                        |
| `resolvers`         | `ResolverType[]`    | Yes      | Resolvers that process decorated resources                 |
| `globalConfig`      | `GlobalConfig`      | No       | Shared Lambda and tag settings for all resources           |
| `awsProviderConfig` | `AwsProviderConfig` | No       | AWS provider settings (region, profile, etc.)              |
| `s3Backend`         | `S3BackendConfig`   | No       | Remote S3 backend for Terraform state                      |
| `extend`            | `(scope) => void`   | No       | Callback invoked after all resolvers finish                |

### createModule

`createModule` groups related resources into a logical unit with its own scope, IAM role, and configuration. Each resource inside the module is processed by the matching resolver based on its decorator type:

```typescript
const orderModule = createModule({
  name: 'orders',
  resources: [OrderApi, OrderQueue, OrderSchedule],
  globalConfig: {
    lambda: {
      memory: 256,
      timeout: 15,
      services: ['dynamodb', 'sqs'],
    },
    tags: {
      domain: 'orders',
    },
  },
});
```

#### Module Options

| Option         | Type              | Required | Description                                           |
| -------------- | ----------------- | -------- | ----------------------------------------------------- |
| `name`         | `string`          | Yes      | Module name, used as scope and tag identifier          |
| `resources`    | `ClassResource[]` | Yes      | Decorated classes to be processed by resolvers         |
| `globalConfig` | `GlobalConfig`    | No       | Lambda and tag settings scoped to this module          |

### Global Configuration

Global configuration applies default settings to all Lambda functions and resources. Values cascade from application to module to individual resource, with more specific settings taking precedence:

```
App globalConfig → Module globalConfig → Resource-level config
```

#### Lambda Configuration

| Option        | Type             | Description                                               |
| ------------- | ---------------- | --------------------------------------------------------- |
| `memory`      | `number`         | Memory allocation in MB                                   |
| `timeout`     | `number`         | Execution timeout in seconds                              |
| `runtime`     | `20 \| 22 \| 24` | Node.js runtime version                                   |
| `services`    | `Services[]`     | AWS services the Lambda can access (creates IAM role)     |
| `enableTrace` | `boolean`        | Enable AWS X-Ray tracing                                  |
| `env`         | `EnvironmentValue` | Environment variables for Lambda functions              |

#### Available Services

Services define which AWS resources the Lambda IAM role can access:

| Service         | Description                      |
| --------------- | -------------------------------- |
| `dynamodb`      | Amazon DynamoDB                  |
| `s3`            | Amazon S3                        |
| `lambda`        | AWS Lambda                       |
| `cloudwatch`    | Amazon CloudWatch Logs           |
| `sqs`           | Amazon SQS                       |
| `state_machine` | AWS Step Functions               |
| `kms`           | AWS KMS                          |
| `ssm`           | AWS Systems Manager Parameter Store |
| `event`         | Amazon EventBridge               |

For fine-grained control, specify individual permissions:

```typescript
services: [
  'cloudwatch',
  { type: 'dynamodb', permissions: ['Query', 'GetItem'] },
  { type: 's3', permissions: ['GetObject'], resources: ['arn:aws:s3:::my-bucket/*'] },
  { type: 'custom', serviceName: 'ses', permissions: ['SendEmail'] },
]
```

#### Tags

Tags are applied automatically to all taggable resources. Module-level tags merge with app-level tags, and resource-specific tags take highest precedence:

```typescript
// App-level tags
globalConfig: {
  tags: {
    environment: 'production',
    project: 'my-app',
  },
}

// Module-level tags (merged with app tags)
globalConfig: {
  tags: {
    domain: 'orders',
  },
}
```

Lafken also adds automatic tags: `lafken:app` with the app name and `lafken:module` with the module name.

### S3 Backend

Store Terraform state remotely in an S3 bucket for team collaboration and state locking:

```typescript
await createApp({
  name: 'my-app',
  s3Backend: {
    bucket: 'terraform-state-bucket',
    key: 'apps/my-app/terraform.tfstate',
    region: 'us-east-1',
    dynamodbTable: 'terraform-locks',
  },
});
```

### Extending the Application

The `extend` callback runs after all resolvers have finished processing. Use it to add custom infrastructure that is not covered by the standard resolvers:

```typescript
await createApp({
  name: 'my-app',
  modules: [userModule],
  resolvers: [new ApiResolver()],
  extend: async (scope) => {
    // Add any CDKTN construct directly to the stack
  },
});
```