# Lambda Typed DI Pattern

This template demonstrates the object-based ties pattern for type-safe dependency injection in Lambda handlers.

## Key Features

- **Full Type Safety**: Complete TypeScript support with generics
- **Direct Access**: Dependencies available via `event.ties.serviceName`
- **IntelliSense**: Full autocompletion and error checking
- **Meaningful Keys**: Human-readable property names instead of hashes
- **Simple Handlers**: Direct async functions instead of factory functions

## Basic Usage

### 1. Define Your Handler with Typed Dependencies

```typescript
import { LambdaDefinition } from '@worktif/runtime';

// Define the shape of your dependencies
type MyHandlerTies = {
  userService: UserService;
  configService: ConfigService;
};

export const myHandler: LambdaDefinition<MyHandlerTies> = {
  id: 'my-handler',
  ties: {
    userService: UserService,
    configService: ConfigService
  },
  handler: async (event) => {
    // Direct access with full type safety
    const user = await event.ties.userService.getUser(event.pathParameters.id);
    const config = event.ties.configService.getConfig();
    
    return {
      statusCode: 200,
      body: JSON.stringify({ user, config })
    };
  },
  http: {
    method: 'GET',
    path: '/api/users/{id}'
  }
};
```

### 2. Register Your Services

```typescript
export class MyTies {
  // Object-based registration for type-safe access
  static register = {
    userService: {
      instance: UserService,
      dependencies: [],
    },
    configService: {
      instance: ConfigService,
      dependencies: [],
    },
  };
}
```

## Benefits Over Old Pattern

| Old Pattern | New Pattern |
|-------------|-------------|
| `ties: [UserService]` | `ties: { userService: UserService }` |
| `(deps) => async (event, context) => {}` | `async (event) => {}` |
| `(deps as any).userService` | `event.ties.userService` |
| No type safety | Full TypeScript generics |
| Hash-based keys | Meaningful property names |
| Manual type assertions | Automatic type inference |

## Examples in This Template

### Basic Handler (`src/handlers/example.handlers.ts`)
- Single service dependency
- Simple GET endpoint
- Error handling

### Multi-Service Handler (`src/handlers/example.handlers.ts`)
- Multiple service dependencies
- Demonstrates type safety with multiple services

### Service Registration (`src/ties/example.ties.ts`)
- Object-based registration pattern
- Backward compatibility support

## Migration from Old Pattern

If you have existing handlers using the old array-based pattern:

```typescript
// Old pattern (deprecated)
export const oldHandler: LambdaDefinition = {
  ties: [UserService],
  handler: (deps) => async (event, context) => {
    const userService = (deps as any).userService;
    // ...
  }
};

// New pattern (recommended)
type HandlerTies = { userService: UserService };
export const newHandler: LambdaDefinition<HandlerTies> = {
  ties: { userService: UserService },
  handler: async (event) => {
    const user = await event.ties.userService.getUser(id);
    // ...
  }
};
```

## Best Practices

1. **Define Ties Types**: Always create a type for your ties object
2. **Meaningful Names**: Use descriptive property names that match your service purpose
3. **Consistent Naming**: Keep property names consistent between ties definition and registration
4. **Type Safety**: Let TypeScript guide you - if it compiles, dependencies are correctly configured

## Common Patterns

### Single Service
```typescript
type SingleServiceTies = { myService: MyService };
```

### Multiple Services
```typescript
type MultiServiceTies = {
  userService: UserService;
  paymentService: PaymentService;
  notificationService: NotificationService;
};
```

### Service with Configuration
```typescript
type ServiceWithConfigTies = {
  dataService: DataService;
  configService: ConfigService;
  loggerService: LoggerService;
};
```

## Troubleshooting

**Issue**: `Property 'ties' does not exist on type 'APIGatewayProxyEvent'`
**Solution**: Use `LambdaDefinition<TiesType>` with your ties type generic

**Issue**: Dependencies are undefined in `event.ties`
**Solution**: Ensure property names in ties object match registration keys in ties class

**Issue**: No IntelliSense for `event.ties`
**Solution**: Define and use a proper ties type with `LambdaDefinition<TiesType>`

## Getting Started

1. Copy the example handlers and modify them for your use case
2. Create your service classes
3. Update the ties registration to include your services
4. Test your handlers to ensure dependencies are properly injected

The new pattern provides a much better developer experience with full type safety and cleaner code!
