Utility Functions
Utility functions for the Hosted Components Service
Utility Functions
This page documents the various utility functions available in the library.
Tailwind Utilities
cn
A utility function that combines clsx and tailwind-merge for handling Tailwind CSS class names.
import { cn } from '@/lib/utils';
// Usage
cn('base-class', condition && 'conditional-class', 'another-class');Format Utilities
Card Number Formatting
import { formatCardNumber, unformatCardNumber } from '@/lib/utils';
// Format card number with spaces every 4 digits
formatCardNumber('4111111111111111'); // "4111 1111 1111 1111"
// Remove spaces from card number
unformatCardNumber('4111 1111 1111 1111'); // "4111111111111111"Expiry Date Formatting
import { formatExpiryDate, unformatExpiryDate } from '@/lib/utils';
// Format expiry date with slash
formatExpiryDate('1223'); // "12 / 23"
// Remove formatting from expiry date
unformatExpiryDate('12 / 23'); // "12/23"CSS Class Validation
validateClasses
Validates CSS class configurations against predefined rules.
import { validateClasses } from '@/lib/utils';
const classes = {
button: { 'background-color': 'blue' },
'button:hover': { 'background-color': 'darkblue' },
};
const validatedClasses = validateClasses(classes);convertToCssString
Converts validated class rules into a CSS string.
import { convertToCssString } from '@/lib/utils';
const cssString = convertToCssString(validatedClasses);Font Family Handler
import { handleFontFamily } from '@/lib/utils';
handleFontFamily('Roboto', (fontFamily) => {
// Handles loading Google Fonts and provides fallback
console.log(fontFamily); // "'Roboto', Arial, Helvetica, sans-serif"
});CSS Variables Validation
import { validateCSSVariables } from '@/lib/utils';
const variables = {
'--primary-color': '#007bff',
'--font-size': '16px',
};
const validatedVars = validateCSSVariables(variables);Environment Utilities
Environment Class
A centralized environment utility that provides consistent environment handling across all components.
import { Environment } from '@/lib/utils/environment';
// Get current environment
const env = Environment.getCurrentEnvironment(); // 'production' | 'staging' | 'develop' | 'sandbox'
// Check if production
const isProduction = Environment.isProduction(); // boolean
// Check if local/development
const isLocal = Environment.isLocal(); // boolean
// Get DataDog-specific environment mapping
const ddEnv = Environment.getDatadogEnvironment(); // Maps production -> sydney, others remain sameEnvironment Mappings:
production→ DataDog environment:sydneystaging→ DataDog environment:stagingdevelop/development→ DataDog environment:developsandbox→ DataDog environment:sandbox- Default fallback:
staging
devOnly
A utility function that redirects to the home page if the application is running in production mode.
import { devOnly } from '@/lib/utils';
// Usage in development-only routes
devOnly(); // Redirects to "/" if NODE_ENV is "production"Token Utilities
validateJWTToken
Validates JWT tokens by checking their format and expiration.
import { validateJWTToken } from '@/lib/utils';
const isValid = validateJWTToken('your.jwt.token');The function performs the following checks:
- Verifies the token has three parts separated by dots
- Validates base64url format for each part
- Checks token expiration if present
- Returns
trueif the token is valid,falseotherwise
Server Actions
Server Actions are async functions that are executed on the server-side. These functions can be used in both client and server components, and are specifically designed for creating, updating, or deleting data. For more information, see Next.js Server Actions documentation.
createCardToken
A server action function for creating a payment method token for card payments.
import { createCardToken } from '@/lib/utils';
// Usage
const response = await createCardToken(token, {
countryCode: 'US',
accountNumber: '4111111111111111',
expiryDate: '12/25',
accountHolderName: 'John Doe',
termAndConditionAgreed: true,
});API Utilities
apiRequest
A type-safe utility function for making HTTP requests with built-in error handling, response formatting, and enhanced logging.
import { apiRequest } from '@/lib/utils';
// Example GET request
const response = await apiRequest({
url: 'https://api.example.com/data',
method: 'GET',
token: 'your-auth-token', // Optional
});
// Example POST request with body
const response = await apiRequest({
url: 'https://api.example.com/data',
method: 'POST',
token: 'your-auth-token',
body: { key: 'value' },
});
// Type-safe response handling
interface UserData {
id: string;
name: string;
}
const response = await apiRequest<UserData>({
url: 'https://api.example.com/user',
method: 'GET',
});
// response.data will be typed as UserData | nullThe function handles:
- Automatic JSON parsing
- Error handling with detailed error information
- Authentication via Bearer token
- Type-safe responses
- Enhanced logging with structured DatadogLogger integration
- Security: Automatic token masking in logs
- Request/Response tracking for debugging and monitoring
Logging Utilities
DatadogLogger
The DatadogLogger utility provides structured logging with Datadog-compatible format, enhanced security features, and comprehensive tracking capabilities.
Core Features
- 🔐 Token Masking: Automatically masks sensitive tokens in logs
- 🎯 Context Management: Provides default contexts when none specified
- 📊 Payment Stage Tracking: Tracks different stages of payment processing
- 🌍 Environment Awareness: Adapts logging behavior based on environment
- ⚡ Production Safety: Filters sensitive data in production environments
Basic Usage
import { DatadogLogger } from '@/lib/utils/datadog-logger';
// Simple info logging
DatadogLogger.info('Operation completed successfully');
// Info with additional data
DatadogLogger.info('Payment processed', {
paymentId: 'payment-123',
amount: 100.0,
currency: 'USD',
});
// Warning logging
DatadogLogger.warn('Rate limit approaching', {
currentRequests: 95,
limit: 100,
timeWindow: '1m',
});
// Error logging
DatadogLogger.error('Payment validation failed', error, {
paymentId: 'payment-456',
validationStep: 'card_number',
});Enhanced Logging with Context and Token
// Enhanced logging with token masking and context
DatadogLogger.info(
'Payment method created',
{
paymentMethodId: 'pm-123',
paymentStage: 'payment_token_creation',
},
token, // Automatically masked in logs
{
countryCode: 'AU',
merchantId: 'merchant-123',
pageType: 'HPP 2.0',
}
);
// Context defaults - if no context provided, defaults to 'payment_method_embed'
DatadogLogger.debug('Processing payment', { amount: 100 }, token);Payment Stage Tracking
Track different stages of the payment process for better monitoring:
// Available payment stages
const paymentStages = {
initialization: 'initialization',
payment_method_selection: 'payment_method_selection',
form_validation: 'form_validation',
payment_token_creation: 'payment_token_creation',
customer_linking: 'customer_linking',
payment_token_creation_failed: 'payment_token_creation_failed',
};
// Usage
DatadogLogger.info(
'Form validation passed',
{
paymentStage: 'form_validation',
paymentMethodType: 'CARD',
},
token,
context
);Method Signatures
// All logging methods support enhanced parameters
static info(
message: string,
additionalData?: Record<string, unknown>,
token?: string | null,
context?: Record<string, unknown>
): void
static warn(
message: string,
additionalData?: Record<string, unknown>,
token?: string | null,
context?: Record<string, unknown>
): void
static error(
message: string,
error?: unknown,
additionalData?: Record<string, unknown>,
token?: string | null,
context?: Record<string, unknown>
): void
static debug(
message: string,
additionalData?: Record<string, unknown>,
token?: string | null,
context?: Record<string, unknown>
): voidSpecialized Logging Methods
// API request logging with automatic token masking
DatadogLogger.apiRequest(
'Payment API called',
{
url: '/api/payments',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: { amount: 100 },
},
token,
context
);
// API response logging
DatadogLogger.apiResponse(
'Payment API response',
{
status: 200,
data: { paymentId: 'payment-123' },
},
token,
context
);
// Database operation logging
DatadogLogger.database(
'User record created',
{
table: 'users',
operation: 'INSERT',
recordId: 'user-123',
},
token,
context
);
// Sensitive data logging (dev/staging only)
DatadogLogger.logSensitiveData(
'Payment details',
{
cardNumber: '4111111111111111',
expiryDate: '12/25',
},
token,
context
);Token Masking
The logger automatically masks tokens for security:
// Token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
// Logged as: "eyJhbG************ssw5c"
// Short tokens are completely masked
// Token: "abc123"
// Logged as: "***masked***"Environment-Specific Behavior
// Production environment
if (Environment.isProduction()) {
// - Debug logs are filtered out
// - Sensitive data is never logged
// - API request/response bodies are sanitized
// - Enhanced security measures
}
// Development/Staging environment
if (!Environment.isProduction()) {
// - All log levels available
// - Sensitive data can be logged with explicit methods
// - Full request/response logging
// - Enhanced debugging information
}Common Patterns
// ✅ Correct usage patterns
DatadogLogger.info('User authenticated successfully', { userId: 'user-123' });
DatadogLogger.error('Authentication failed');
DatadogLogger.error('Database query failed', dbError);
DatadogLogger.error('API request failed', apiError, { endpoint: '/api/payments' });
// Enhanced logging with context and token
DatadogLogger.info('Payment processing started', { paymentStage: 'initialization' }, token, {
merchantId: 'merchant-123',
countryCode: 'AU',
});
// ❌ Incorrect usage patterns
// Don't pass empty object as second parameter
DatadogLogger.error('Validation failed', {}); // Wrong!
// Don't pass additional data as second parameter when you mean to pass an error
DatadogLogger.error('Process failed', { step: 'validation' }); // Wrong!Log Structure
All logs follow a consistent Datadog-compatible structure:
{
"message": "Payment processed successfully",
"host": "aws/amplify",
"service": "hosted-component",
"env": "sydney", // or staging, develop, sandbox
"environment": "sydney,frontend", // or stage,frontend
"application": "hosted-component",
"timestamp": "2024-01-15T10:30:00.000Z",
"token": "eyJhbG************ssw5c", // masked
"context": "payment_method_embed", // or custom context
"paymentStage": "payment_token_creation",
"merchantId": "merchant-123",
"countryCode": "AU",
"pageType": "HPP 2.0"
}Production Safe Logger
For legacy compatibility, the ProductionSafeLogger is still available but now uses DatadogLogger internally:
import { ProductionSafeLogger } from '@/lib/utils/production-safe-logger';
// Basic logging (filtered in production)
ProductionSafeLogger.log('Debug information', { data: 'value' });
// Sensitive data logging (dev/staging only)
ProductionSafeLogger.logSensitiveData('Payment details', {
cardNumber: '4111111111111111',
});Best Practices
Logging Strategy
- Use structured logging: Always include relevant context in your logs
- Leverage payment stages: Track the user journey through payment processing
- Include tokens safely: Let the logger handle token masking automatically
- Provide meaningful contexts: Help with debugging and monitoring
- Use appropriate log levels: Info for normal operations, warn for potential issues, error for failures
// Good logging practice
DatadogLogger.info(
'Payment method selection changed',
{
paymentMethodType: 'CARD',
paymentStage: 'payment_method_selection',
},
token,
{
merchantId: 'merchant-123',
countryCode: 'AU',
pageType: 'HPP 2.0',
}
);Security Considerations
- Never log sensitive data in production
- Use
logSensitiveData()for development-only sensitive information - Tokens are automatically masked - no need to handle this manually
- Always check environment before logging sensitive information