@lafken/common
@lafken/common is the core utility package for the Lafken framework. It provides the decorator factory functions, metadata reflection utilities, and shared types that power every @lafken/* package. If a Lafken package defines a decorator or reads infrastructure metadata, it depends on @lafken/common.
Installation
pnpm add @lafken/common
Overview
Lafken uses TypeScript decorators to declare infrastructure. This package provides the factories that create those decorators and the utilities that read the metadata they produce:
| Factory | Level | Purpose |
|---|---|---|
createResourceDecorator |
Class | Mark a class as a deployable resource |
createLambdaDecorator |
Method | Mark a method as a Lambda handler |
createEventDecorator |
Param | Bind a method parameter to the Lambda event |
createFieldDecorator |
Prop | Describe a typed field inside a payload class |
createPayloadDecorator |
Class | Define a named payload schema |
Decorator Factories
createResourceDecorator
Creates a class-level decorator that marks a class as an infrastructure resource. The factory automatically captures the resource name, the file path and folder (used for Lambda bundling), and any custom metadata you define.
import { createResourceDecorator } from '@lafken/common';
export const RESOURCE_TYPE = 'MY_SERVICE' as const;
export interface MyServiceProps {
name?: string;
retryCount?: number;
}
export const MyService = createResourceDecorator<MyServiceProps>({
type: RESOURCE_TYPE,
callerFileIndex: 5, // Stack-trace index to resolve caller file
getMetadata: (props) => ({ // Optional — transform props before storing
...props,
retryCount: props.retryCount ?? 3,
}),
});
Usage:
@MyService({ name: 'notifications', retryCount: 5 })
export class NotificationService { ... }
Captured metadata (ResourceMetadata):
| Field | Description |
|---|---|
type |
Resolver identifier (MY_SERVICE) |
name |
Explicit name or the class name |
foldername |
Directory of the decorated file |
filename |
File name (without .js extension) |
originalName |
Original class name (for asset naming) |
minify |
Whether to minify the bundle (true) |
createLambdaDecorator
Creates a method-level decorator that registers a method as a Lambda handler. It stores handler metadata and rewrites the method descriptor so the framework can inject arguments (@Event, @Context) at runtime.
import { createLambdaDecorator } from '@lafken/common';
import type { LambdaMetadata } from '@lafken/common';
export interface PublishProps {
name: string;
lambda?: LambdaProps;
}
export interface PublishMetadata extends PublishProps {
name: string;
}
export const Publish = (props: PublishProps) =>
createLambdaDecorator<PublishProps, PublishMetadata>({
getLambdaMetadata: (props, methodName) => ({
...props,
name: methodName,
}),
})(props);
Usage:
class NotificationService {
@Publish({ name: 'send-email' })
sendEmail(@Event() event: EmailPayload) {
// handler logic
}
}
LambdaProps — Optional Lambda-level configuration available through the lambda property:
| Property | Type | Description |
|---|---|---|
timeout |
number |
Execution timeout in seconds |
memory |
number |
Memory allocation in MB |
runtime |
24 | 22 | 20 |
Node.js runtime version |
services |
ServicesValues |
IAM service permissions |
env |
EnvironmentValue |
Environment variables (static or dynamic) |
tags |
Record<string, string> |
Resource tags |
enableTrace |
boolean |
Enable AWS X-Ray tracing |
createEventDecorator
Creates a parameter-level decorator that binds a method parameter to the incoming Lambda event. It works with createFieldDecorator to map typed payload classes onto the raw event.
import { createEventDecorator } from '@lafken/common';
export const Event = createEventDecorator({
prefix: 'my-service',
enableInLambdaInvocation: false, // Only capture metadata during build
});
Usage:
class NotificationService {
@Publish({ name: 'send-email' })
sendEmail(@Event(EmailPayload) event: EmailPayload) { ... }
}
Context
A built-in parameter decorator that injects the Lambda execution context:
import { Context } from '@lafken/common';
class MyService {
@Handler()
process(@Event(Input) event: Input, @Context() ctx: any) {
console.log(ctx.functionName);
}
}
createFieldDecorator
Creates a property-level decorator that describes a typed field inside a payload class. The field metadata is collected by resolvers to build event schemas (e.g., Step Functions input/output, API request bodies).
Supported types: String, Number, Boolean, nested classes, and arrays.
import { createFieldDecorator } from '@lafken/common';
export const Field = createFieldDecorator({
prefix: 'my-service',
getMetadata: () => ({}),
});
Usage:
class Address {
@Field()
street: string;
@Field()
city: string;
}
class UserPayload {
@Field({ name: 'user_name' }) // Rename the field in the schema
name: string;
@Field()
age: number;
@Field({ type: Address }) // Nested object
address: Address;
@Field({ type: [String] }) // Array of primitives
tags: string[];
}
createPayloadDecorator
Creates a class-level decorator that gives a payload class a name and optional metadata. This identity is used when resolvers reference the payload in generated infrastructure.
import { createPayloadDecorator } from '@lafken/common';
export const Payload = createPayloadDecorator({
prefix: 'my-service',
createUniqueId: true, // Append a counter if names collide
});
Usage:
@Payload({ name: 'CreateUserInput' })
class CreateUserInput {
@Field()
email: string;
}
Metadata Utilities
Resolvers use these functions to read the metadata produced by the decorators above.
getResourceMetadata
Returns the ResourceMetadata stored on a class by createResourceDecorator:
import { getResourceMetadata } from '@lafken/common';
const metadata = getResourceMetadata(NotificationService);
// { type: 'MY_SERVICE', name: 'notifications', foldername: '...', ... }
getResourceHandlerMetadata
Returns an array of handler metadata stored by createLambdaDecorator:
import { getResourceHandlerMetadata } from '@lafken/common';
const handlers = getResourceHandlerMetadata<PublishMetadata>(NotificationService);
// [{ name: 'sendEmail', ... }]
getMetadataByKey / getMetadataPrototypeByKey
Low-level helpers to read any Reflect metadata by key from a class or its prototype:
import { getMetadataByKey, getMetadataPrototypeByKey } from '@lafken/common';
const payload = getMetadataByKey<PayloadMetadata>(MyClass, 'my-service:lafken:payload');
const fields = getMetadataPrototypeByKey<FieldMetadata[]>(MyClass, 'my-service:lafken:field');
Build Environment
Decorators only capture metadata when the build environment flag is set. This prevents metadata side-effects during normal runtime execution.
isBuildEnvironment()— Returnstruewhen theLAFKEN_CONTEXTenvironment variable equalsBUILD.enableBuildEnvVariable()— Sets the flag. Required in tests before declaring any decorated class.
import { enableBuildEnvVariable } from '@lafken/common';
describe('My resolver', () => {
enableBuildEnvVariable();
@MyService({ name: 'test' })
class TestResource { ... }
it('should capture metadata', () => {
const meta = getResourceMetadata(TestResource);
expect(meta.name).toBe('test');
});
});
String Utilities
General-purpose string helpers used throughout the framework:
| Function | Description | Example |
|---|---|---|
capitalize(str) |
Uppercase first letter | 'hello' → 'Hello' |
kebabCase(str) |
Convert to kebab-case | 'MyService' → 'my-service' |
cleanString(str) |
Remove non-alphanumeric characters | 'a-b_c' → 'abc' |
cleanAndCapitalize(str) |
Clean + capitalize each word | 'my-service' → 'MyService' |
cleanTemplateString(str) |
Trim + collapse multiline strings into one line | — |
Shared Types
Services & Permissions
The Services type provides typed IAM permission declarations for Lambda handlers:
import type { Services } from '@lafken/common';
// Shorthand — grants full service access
const services: Services[] = ['dynamodb', 's3'];
// Fine-grained — specific actions and resources
const services: Services[] = [
{ type: 'dynamodb', permissions: ['GetItem', 'PutItem'] },
{ type: 's3', permissions: ['GetObject'], resources: ['arn:aws:s3:::my-bucket/*'] },
{ type: 'custom', serviceName: 'ses', permissions: ['SendEmail'] },
];
Supported service types: dynamodb, s3, lambda, cloudwatch, sqs, state_machine, kms, ssm, event, and custom.
Environment Variables
import type { EnvironmentValue } from '@lafken/common';
// Static values
const env: EnvironmentValue = { TABLE_NAME: 'users' };
// Dynamic values — resolved at deploy time via resource references
const env: EnvironmentValue = ({ getResourceValue }) => ({
TABLE_ARN: getResourceValue('dynamo::users-table', 'arn'),
});
Duration
import type { Duration } from '@lafken/common';
const timeout: Duration = 30; // seconds
const ttl: Duration = { type: 'days', duration: 7 }; // 7 days
Type-Safe Resource References
The package provides augmentable interfaces that enable type-safe resource names across modules. Packages extend these interfaces so that getResourceValue calls are validated at compile time:
// In your lafken-types.d.ts
declare module '@lafken/common' {
interface ModulesAvailable {
core: {
Queue: { 'email-queue': string };
};
}
interface DynamoTableAvailable {
'users-table': string;
}
}
API Reference
Decorator Factories
| Export | Description |
|---|---|
createResourceDecorator |
Factory for class-level resource decorators |
createLambdaDecorator |
Factory for method-level handler decorators |
createEventDecorator |
Factory for parameter-level event binding |
createFieldDecorator |
Factory for property-level field metadata |
createPayloadDecorator |
Factory for class-level payload naming |
Context |
Parameter decorator for Lambda context |
Metadata Readers
| Export | Description |
|---|---|
getResourceMetadata |
Read class resource metadata |
getResourceHandlerMetadata |
Read method handler metadata |
getMetadataByKey |
Read metadata by key from a class |
getMetadataPrototypeByKey |
Read metadata by key from a prototype |
Utilities
| Export | Description |
|---|---|
enableBuildEnvVariable |
Enable build mode for decorator capture |
isBuildEnvironment |
Check if build mode is active |
getCallerFileName |
Resolve the caller file from the stack |
capitalize |
Capitalize a string |
kebabCase |
Convert to kebab-case |
cleanString |
Strip non-alphanumeric characters |
cleanAndCapitalize |
Clean and capitalize each word |
cleanTemplateString |
Collapse multiline string to one line |
Constants
| Export | Description |
|---|---|
LAFKEN_CONTEXT |
Environment variable name |
LAFKEN_CONTEXT_VALUE |
Expected value for build mode |
Key Types
| Export | Description |
|---|---|
ResourceProps |
Base props for resource decorators |
ResourceMetadata |
Metadata shape stored by resource decorators |
LambdaProps |
Lambda configuration (timeout, memory, runtime, ...) |
LambdaMetadata |
Metadata shape for handler methods |
FieldMetadata |
Discriminated union of field types |
PayloadMetadata |
Metadata shape for payload classes |
Services |
IAM permission declaration type |
ServicesValues |
Array or function returning Services[] |
EnvironmentValue |
Static or dynamic environment variables |
Duration |
Seconds or { type, duration } object |
ClassResource |
Generic class constructor type |
GetResourceValue |
Callback type for cross-resource references |
DeepPartial<T> |
Recursive partial type utility |
License
MIT