Skip to main content

Helper Functions

The framework provides various helper functions for common operations.

Key Helpers

Functions for working with DynamoDB keys.

addSortKeyVersion(sk: string, version: number): string

Adds a version suffix to a sort key.

import { addSortKeyVersion } from '@mbc-cqrs-serverless/core';

const versionedSk = addSortKeyVersion('CAT#001', 1);
// Result: 'CAT#001@1'

getSortKeyVersion(sk: string): number

Extracts the version number from a sort key. Returns VERSION_LATEST if no version suffix exists.

import { getSortKeyVersion } from '@mbc-cqrs-serverless/core';

const version = getSortKeyVersion('CAT#001@3');
// Result: 3

const latestVersion = getSortKeyVersion('CAT#001');
// Result: VERSION_LATEST (-1)

removeSortKeyVersion(sk: string): string

Removes the version suffix from a sort key.

import { removeSortKeyVersion } from '@mbc-cqrs-serverless/core';

const sk = removeSortKeyVersion('CAT#001@3');
// Result: 'CAT#001'

generateId(pk: string, sk: string): string

Generates a unique ID by combining partition key and sort key (without version).

import { generateId } from '@mbc-cqrs-serverless/core';

const id = generateId('TENANT#mbc', 'CAT#001@3');
// Result: 'TENANT#mbc#CAT#001'

sortKeyBaseFromId(pk: string, itemId: string): string | undefined

The inverse of generateId: extracts the base sort key from a composite ID. Returns undefined if the ID does not start with the given partition key.

import { sortKeyBaseFromId } from '@mbc-cqrs-serverless/core';

const skBase = sortKeyBaseFromId('TENANT#mbc', 'TENANT#mbc#CAT#001');
// Result: 'CAT#001'

parseTwoSegmentPkSkFromId(itemId: string): { pk: string; skBase: string } | undefined

Splits a composite ID back into its partition key and base sort key, assuming the partition key has two segments (type and tenant code). Returns undefined if the ID has fewer than three segments.

import { parseTwoSegmentPkSkFromId } from '@mbc-cqrs-serverless/core';

const result = parseTwoSegmentPkSkFromId('TENANT#mbc#CAT#001');
// result.pk is 'TENANT#mbc' and result.skBase is 'CAT#001'

getTenantCode(pk: string): string | undefined

Extracts the tenant code from a partition key.

import { getTenantCode } from '@mbc-cqrs-serverless/core';

const tenantCode = getTenantCode('TENANT#mbc');
// Result: 'mbc'

masterPk(tenantCode?: string): string

Generates a partition key for master data.

import { masterPk } from '@mbc-cqrs-serverless/core';

const pk = masterPk('mbc');
// Result: 'MASTER#mbc'

const commonPk = masterPk();
// Result: 'MASTER#single' (DEFAULT_TENANT_CODE)

seqPk(tenantCode?: string): string

Generates a partition key for sequences.

import { seqPk } from '@mbc-cqrs-serverless/core';

const pk = seqPk('mbc');
// Result: 'SEQ#mbc'

ttlSk(tableName: string): string

Generates a TTL sort key for a table. Used to identify TTL-related records.

import { ttlSk } from '@mbc-cqrs-serverless/core';

const sk = ttlSk('my-table');
// Result: 'TTL#my-table'

S3 Attribute Helpers

Functions for working with S3 URI attributes.

isS3AttributeKey(attributes: any): boolean

Checks if an attribute value is an S3 URI.

import { isS3AttributeKey } from '@mbc-cqrs-serverless/core';

const isS3 = isS3AttributeKey('s3://my-bucket/path/to/file.pdf');
// Result: true

const isNotS3 = isS3AttributeKey('regular string');
// Result: false

toS3AttributeKey(bucket: string, key: string): string

Creates an S3 URI from bucket and key.

import { toS3AttributeKey } from '@mbc-cqrs-serverless/core';

const s3Uri = toS3AttributeKey('my-bucket', 'path/to/file.pdf');
// Result: 's3://my-bucket/path/to/file.pdf'

parseS3AttributeKey(s3Uri: string): { bucket: string; key: string }

Parses an S3 URI into bucket and key components.

import { parseS3AttributeKey } from '@mbc-cqrs-serverless/core';

const { bucket, key } = parseS3AttributeKey('s3://my-bucket/path/to/file.pdf');
// bucket: 'my-bucket', key: 'path/to/file.pdf'

Context Helpers

Functions for working with invocation context and user information.

getUserContext(ctx: IInvoke | ExecutionContext): UserContext

Extracts user context from the invocation context. Returns userId, tenantCode, and tenantRole.

import { getUserContext } from '@mbc-cqrs-serverless/core';

const userContext = getUserContext(invokeContext);
// Returns: { userId: '...', tenantCode: 'mbc', tenantRole: 'admin' }

extractInvokeContext(ctx?: ExecutionContext): IInvoke

Extracts the invocation context from a NestJS execution context. Supports both Lambda and local development environments.

import { extractInvokeContext } from '@mbc-cqrs-serverless/core';

@Get()
async getItem(@Req() request: Request) {
const ctx = extractInvokeContext(this.executionContext);
// Use ctx for further operations
}

getAuthorizerClaims(ctx: IInvoke): JwtClaims

Extracts JWT claims from the authorizer in the invocation context.

import { getAuthorizerClaims } from '@mbc-cqrs-serverless/core';

const claims = getAuthorizerClaims(invokeContext);
// Returns JWT claims including sub, email, custom:tenant, etc.

UserContext Class

class UserContext {
userId: string; // User's unique identifier (sub claim)
tenantCode: string; // Current tenant code
tenantRole: string; // User's role in the current tenant

constructor(partial: Partial<UserContext>);
}

JwtClaims Interface

interface JwtClaims {
sub: string; // User's unique identifier
iss: string; // Token issuer URL
username?: string; // Username
'cognito:groups'?: string[]; // Cognito user groups
'cognito:username': string; // Cognito username
origin_jti?: string; // Original JWT ID
client_id?: string; // OAuth client ID
scope?: string; // OAuth scopes
aud: string; // Token audience
event_id: string; // Cognito event ID
token_use: string; // Token type (access/id)
auth_time: number; // Authentication timestamp
name: string; // User's name
'custom:tenant'?: string; // User's default tenant code
'custom:roles'?: string; // JSON array of tenant roles
exp: number; // Expiration timestamp
email: string; // User's email address
email_verified?: boolean; // Email verification status
iat: number; // Issued at timestamp
jti: string; // JWT ID
}

DateTime Helpers

Functions for working with dates and ISO strings.

toISOString(date: Date): string | undefined

Converts a Date to ISO string format. Returns undefined if date is null/undefined.

import { toISOString } from '@mbc-cqrs-serverless/core';

const isoString = toISOString(new Date('2024-01-15T10:30:00Z'));
// Result: '2024-01-15T10:30:00.000Z'

toISOStringWithTimezone(date: Date): string | undefined

Converts a Date to ISO string format with timezone offset. Returns undefined if date is null/undefined.

import { toISOStringWithTimezone } from '@mbc-cqrs-serverless/core';

const isoString = toISOStringWithTimezone(new Date('2024-01-15T10:30:00'));
// Result: '2024-01-15T10:30:00+09:00' (in JST timezone)

isISOString(val: string): boolean

Checks if a string is a valid ISO date string.

import { isISOString } from '@mbc-cqrs-serverless/core';

isISOString('2024-01-15T10:30:00.000Z'); // true
isISOString('2024-01-15'); // false
isISOString('invalid'); // false

isISOStringWithTimezone(val: string): boolean

Checks if a string is a valid ISO date string with timezone.

import { isISOStringWithTimezone } from '@mbc-cqrs-serverless/core';

isISOStringWithTimezone('2024-01-15T10:30:00+09:00'); // true
isISOStringWithTimezone('2024-01-15T10:30:00.000Z'); // false

Event-Type Helpers

Functions for working with AWS event source ARNs.

getEventTypeFromArn(source: string): string | null

Extracts the event type from an AWS ARN. Returns 'sqs', 'sns', 'dynamodb', 'event-bridge', or null.

import { getEventTypeFromArn } from '@mbc-cqrs-serverless/core';

const eventType = getEventTypeFromArn('arn:aws:dynamodb:ap-northeast-1:123456789:table/my-table/stream/...');
// Result: 'dynamodb'

const sqsType = getEventTypeFromArn('arn:aws:sqs:ap-northeast-1:123456789:my-queue');
// Result: 'sqs'

getResourceNameFromArn(source: string): string

Extracts the resource name from an AWS ARN.

import { getResourceNameFromArn } from '@mbc-cqrs-serverless/core';

const tableName = getResourceNameFromArn('arn:aws:dynamodb:ap-northeast-1:123456789:table/my-table/stream/...');
// Result: 'my-table'

const queueName = getResourceNameFromArn('arn:aws:sqs:ap-northeast-1:123456789:my-queue');
// Result: 'my-queue'

Object Helpers

Functions for working with objects.

isObject(item: any): boolean

Checks if the value is a plain object (not array, not null).

import { isObject } from '@mbc-cqrs-serverless/core';

isObject({ key: 'value' }); // true
isObject([1, 2, 3]); // false
isObject(null); // false
isObject('string'); // false

mergeDeep(target: any, ...sources: any[]): any

Deep merges objects without mutating the original objects.

import { mergeDeep } from '@mbc-cqrs-serverless/core';

const result = mergeDeep(
{ a: 1, b: { c: 2 } },
{ b: { d: 3 }, e: 4 }
);
// Result: { a: 1, b: { c: 2, d: 3 }, e: 4 }

objectBytes(obj: any): number

Calculates the byte size of a JSON-serialized object.

import { objectBytes } from '@mbc-cqrs-serverless/core';

const size = objectBytes({ name: 'test', value: 123 });
// Result: byte size of JSON string

pickKeys(obj: any, keys: string[]): object

Creates a new object with only the specified keys.

import { pickKeys } from '@mbc-cqrs-serverless/core';

const result = pickKeys({ a: 1, b: 2, c: 3 }, ['a', 'c']);
// Result: { a: 1, c: 3 }

omitKeys(obj: any, keys: string[]): object

Creates a new object without the specified keys.

import { omitKeys } from '@mbc-cqrs-serverless/core';

const result = omitKeys({ a: 1, b: 2, c: 3 }, ['b']);
// Result: { a: 1, c: 3 }

Serializer Helpers

Functions for converting between internal DynamoDB structure and external flat structure.

SerializerOptions Interface

interface SerializerOptions {
keepAttributes?: boolean; // Reserved for future use
flattenDepth?: number; // Reserved for future use
}
note

The SerializerOptions interface is defined for future extensibility but is not currently used by the function. The function always flattens attributes to the top level.

serializeToExternal<T extends CommandEntity | DataEntity>(item: T | null | undefined, options?: SerializerOptions): Record<string, any> | null

Converts internal DynamoDB entity to external flat structure. Flattens the attributes object into the root level. Returns null if input is null or undefined.

import { serializeToExternal } from '@mbc-cqrs-serverless/core';

const entity = {
pk: 'TENANT#mbc',
sk: 'CAT#001',
id: 'TENANT#mbc#CAT#001',
code: '001',
name: 'Category 1',
version: 1,
tenantCode: 'mbc',
type: 'CAT',
isDeleted: false,
attributes: { color: 'red', size: 'large' }
};

const external = serializeToExternal(entity);
// Result:
// {
// id: 'TENANT#mbc#CAT#001',
// pk: 'TENANT#mbc',
// sk: 'CAT#001',
// code: '001',
// name: 'Category 1',
// version: 1,
// tenantCode: 'mbc',
// type: 'CAT',
// isDeleted: false,
// color: 'red', // Flattened from attributes
// size: 'large' // Flattened from attributes
// }

deserializeToInternal<T extends CommandEntity | DataEntity>(data: Record<string, any> | null | undefined, EntityClass: new () => T): T | null

Converts external flat structure back to internal DynamoDB entity structure. Returns null if input is null or undefined.

import { deserializeToInternal, DataEntity } from '@mbc-cqrs-serverless/core';

const external = {
id: 'TENANT#mbc#CAT#001',
name: 'Category 1',
color: 'red',
size: 'large'
};

const entity = deserializeToInternal(external, DataEntity);
// Result: DataEntity with pk, sk, name, and attributes: { color, size }

Source Helper

Function for generating command source identifiers.

getCommandSource(moduleName: string, controllerName: string, method: string): string

Generates a standardized source string for commands.

import { getCommandSource } from '@mbc-cqrs-serverless/core';

const source = getCommandSource('CatalogModule', 'CatalogController', 'create');
// Result: '[CatalogModule]:CatalogController.create'

Constants

IS_LAMBDA_RUNNING: boolean

A constant that indicates whether the code is running in an AWS Lambda environment.

import { IS_LAMBDA_RUNNING } from '@mbc-cqrs-serverless/core';

if (IS_LAMBDA_RUNNING) {
// Lambda-specific logic
} else {
// Local development logic
}