@zaplink/utils
v0.1.0
Published
Shared utilities for Zaplink SDK
Readme
@zaplink/utils
Shared utilities for the Zaplink JavaScript SDK ecosystem.
Installation
npm install @zaplink/utils
# or
pnpm add @zaplink/utils
# or
yarn add @zaplink/utilsFeatures
- Phone utilities - E.164 format validation and normalization
- Idempotency - Cryptographically secure key generation
- Problem Details - RFC 7807 error handling helpers
- WhatsApp Deep Links - Cross-platform WhatsApp link generation
- Header Parsing - Extract metadata from HTTP responses
Usage
Phone Utilities
import { isValidE164, normalizePhone, formatPhoneDisplay } from '@zaplink/utils';
// Validate E.164 format
isValidE164('+5215555555555'); // true
isValidE164('555-1234'); // false
// Normalize phone numbers
normalizePhone('(521) 555-555-5555'); // '+5215555555555'
normalizePhone('+1 (415) 555-2671'); // '+14155552671'
// Format for display
formatPhoneDisplay('+14155552671'); // '+1 (415) 555-2671'
formatPhoneDisplay('+5215555555555'); // '+52 555 555 5555'Idempotency Keys
import { generateIdempotencyKey, isValidIdempotencyKey } from '@zaplink/utils';
// Generate a secure random key
const key = generateIdempotencyKey();
// Example: 'Xy3kJ9mN8pQ2rV5wZ7bC4fG6hK1lM0nP3qS5tU7vX9yA2cD4eF6g'
// Validate keys
isValidIdempotencyKey(key); // true
isValidIdempotencyKey('too-short'); // false
// Create deterministic keys (use with caution)
const detKey = await createDeterministicKey('user-123', Date.now());Problem Details (RFC 7807)
import {
isProblem,
isProblemWithCode,
asProblem,
parseProblemFromResponse,
assertOk,
ProblemError,
} from '@zaplink/utils';
// Check if error is a Problem
try {
// ... some operation
} catch (error) {
if (isProblem(error)) {
console.error(`Error ${error.code}: ${error.title}`);
console.error(`Request ID: ${error.requestId}`);
}
}
// Check for specific error codes
if (isProblemWithCode(error, 'otp_invalid')) {
console.error('Invalid OTP provided');
}
// Parse from Response
const response = await fetch('...');
if (!response.ok) {
const problem = await parseProblemFromResponse(response);
throw new ProblemError(problem);
}
// Or use assertOk helper
await assertOk(response); // Throws ProblemError if not okWhatsApp Deep Links
import {
createWhatsAppDeepLink,
openWhatsApp,
detectPlatform,
isWhatsAppLikelyAvailable,
} from '@zaplink/utils';
// Create a WhatsApp deep link
const link = createWhatsAppDeepLink({
phone: '+5215555555555',
text: 'Hello from Zaplink!',
});
// Smart open (auto-detects platform)
openWhatsApp({
phone: '+5215555555555',
});
// Detect current platform
const platform = detectPlatform(); // 'web' | 'mobile' | 'ios' | 'android'
// Check availability
if (isWhatsAppLikelyAvailable()) {
console.log('WhatsApp is likely available');
}Header Parsing
import {
extractResponseMetadata,
parseRateLimitHeaders,
getRequestId,
parseRetryAfter,
isRetryable,
} from '@zaplink/utils';
const response = await fetch('...');
// Extract all metadata
const metadata = extractResponseMetadata(response.headers);
console.log(metadata);
// {
// requestId: 'req_abc123',
// apiVersion: '2025-10',
// rateLimit: { limit: 100, remaining: 99, reset: 1234567890 },
// retryAfter: 60
// }
// Get specific headers
const requestId = getRequestId(response.headers);
const retryAfter = parseRetryAfter(response.headers);
// Check if response is retryable
if (isRetryable(response)) {
const waitTime = parseRetryAfter(response.headers) || 5;
console.log(`Retry after ${waitTime} seconds`);
}API Reference
See TypeScript definitions for full API documentation.
License
MIT
