This directory contains comprehensive documentation for all utility functions and shared functionality used throughout the TechDiary application.
Utilities are pure functions and shared helpers that provide common functionality across components, services, and other parts of the application. They are designed to be reusable, testable, and framework-agnostic where possible.
- fonts - Font configuration and Bengali typography support
- curry - Debounce utility for performance optimization
- getFileUrl - Multi-provider file URL generation and optimization
- markdoc-parser - Markdown parsing with custom components
- markdown-tags - React components for Markdoc integration
| Utility | Purpose | Key Features |
|---|---|---|
fonts |
Typography | Bengali font loading, Kohinoor Bangla variants |
curry |
Performance | Debounce with cancel/flush, TypeScript support |
getFileUrl |
Media | Multi-provider URLs, auto-optimization |
markdoc-parser |
Content | Markdown to React, custom tags |
markdown-tags |
Components | Interactive Markdoc components |
import { fontKohinoorBanglaRegular } from '@/utils/fonts';
<div className={fontKohinoorBanglaRegular.className}>
Bengali content with proper typography
</div>import { debounce } from '@/utils/curry';
const debouncedSearch = debounce(
(query: string) => performSearch(query),
{ delay: 300 }
);
// Use throughout component lifecycle
debouncedSearch('search term');
debouncedSearch.cancel(); // Cancel if neededimport getFileUrl from '@/utils/getFileUrl';
// Automatic provider detection and optimization
const optimizedUrl = getFileUrl({
provider: 'cloudinary',
key: 'image-public-id'
});import { markdocParser } from '@/utils/markdoc-parser';
const richContent = markdocParser(`
# Title
{% callout type="note" title="Important" %}
Custom content with interactive components
{% /callout %}
`);// Predictable input/output
export const processData = (input: DataType): ProcessedData => {
// No side effects
return transformedData;
};// Comprehensive TypeScript interfaces
export interface UtilityOptions {
required: string;
optional?: boolean;
}
export const utility = <T>(
input: T,
options: UtilityOptions
): ProcessedResult<T> => {
// Type-safe implementation
};// Graceful error handling with fallbacks
export const safeUtility = (input: unknown): Result => {
try {
return processInput(input);
} catch (error) {
console.warn('Utility error:', error);
return fallbackValue;
}
};// Configurable behavior
export const configurableUtil = (
input: Input,
config: Config = defaultConfig
): Output => {
return processWithConfig(input, { ...defaultConfig, ...config });
};- Utilities avoid memory leaks through proper cleanup
- Debounce functions include cancellation mechanisms
- Large data processing uses streaming where applicable
- Memoization for expensive calculations
- Lazy loading for heavy dependencies
- Tree-shaking friendly exports
// Tree-shakeable exports
export { specificUtility } from './specific-module';
// Avoid barrel exports for large utilities
// import { heavyUtil } from './heavy-utils'; // ❌
import { heavyUtil } from './heavy-utils/heavy-util'; // ✅describe('utilityFunction', () => {
it('handles valid input correctly', () => {
const result = utilityFunction(validInput);
expect(result).toEqual(expectedOutput);
});
it('handles edge cases gracefully', () => {
const result = utilityFunction(edgeCase);
expect(result).toBeDefined();
});
it('throws appropriate errors for invalid input', () => {
expect(() => utilityFunction(invalidInput)).toThrow();
});
});// Test utilities in realistic scenarios
describe('utility integration', () => {
it('works with real component data', () => {
const componentData = getTestComponentData();
const result = processComponentData(componentData);
expect(result).toMatchSnapshot();
});
});// Type-safe environment access
import { env } from '@/env';
export const getCloudinaryUrl = (publicId: string) => {
return `https://res.cloudinary.com/${env.CLOUDINARY_CLOUD_NAME}/image/upload/${publicId}`;
};// Multi-provider support with fallbacks
const providers = {
cloudinary: CloudinaryProvider,
r2: R2Provider,
local: LocalProvider
};
export const getProvider = (type: ProviderType) => {
return providers[type] || providers.local;
};// Utilities that respect current language
export const formatContent = (content: string, lang: Language) => {
const formatter = getFormatterForLanguage(lang);
return formatter.format(content);
};// Bengali text processing utilities
export const processBengaliText = (text: string): ProcessedText => {
return {
normalized: normalizeBengaliText(text),
wordCount: getBengaliWordCount(text),
readingTime: calculateBengaliReadingTime(text)
};
};// Sanitize user input before processing
export const sanitizeInput = (input: string): string => {
return DOMPurify.sanitize(input, {
ALLOWED_TAGS: ['p', 'br', 'strong', 'em'],
ALLOWED_ATTR: []
});
};// Validate URLs before processing
export const validateUrl = (url: string): boolean => {
try {
const parsed = new URL(url);
return ['http:', 'https:'].includes(parsed.protocol);
} catch {
return false;
}
};// Graceful degradation for browser features
export const supportsWebP = (): boolean => {
if (typeof window === 'undefined') return false;
const canvas = document.createElement('canvas');
return canvas.toDataURL('image/webp').indexOf('webp') > -1;
};// Conditional polyfill loading
export const ensureIntersectionObserver = async (): Promise<void> => {
if (!('IntersectionObserver' in window)) {
await import('intersection-observer');
}
};- Function Signature
// Clear, descriptive function signature
export const descriptiveUtilityName = (
primaryInput: PrimaryType,
options: UtilityOptions = {}
): ReturnType => {
// Implementation
};- Documentation Template
# UtilityName
## Overview
Brief description of utility purpose and use cases.
## API Reference
Function signatures, parameters, and return types.
## Usage Examples
Practical examples with common scenarios.
## Performance Notes
Performance characteristics and optimization tips.- Testing Requirements
- Unit tests for all code paths
- Edge case handling tests
- Performance benchmarks for critical utilities
- Browser compatibility tests where applicable
- Function is pure (no side effects)
- Comprehensive TypeScript typing
- Error handling implemented
- Performance optimized
- Browser compatibility considered
- Security implications reviewed
- Documentation complete
- Tests written and passing
- Components Documentation - Components that use these utilities
- Hooks Documentation - Custom hooks that may wrap utilities
- API Documentation - Server-side utility usage
- Performance Guide - Performance optimization strategies
When updating existing utilities, consider:
- Backward Compatibility
// Maintain old signature while adding new features
export const utility = (
input: Input,
optionsOrLegacyParam?: Options | LegacyType
): Output => {
// Handle both old and new signatures
const options = isLegacyParam(optionsOrLegacyParam)
? convertLegacyOptions(optionsOrLegacyParam)
: optionsOrLegacyParam || {};
// Implementation
};- Deprecation Strategy
// Clear deprecation warnings
export const oldUtility = (input: Input): Output => {
console.warn('oldUtility is deprecated. Use newUtility instead.');
return newUtility(input);
};- Migration Path Documentation
## Migration from v1 to v2
### Breaking Changes
- Function signature changed from `old(a, b)` to `new({ a, b })`
- Return type now includes additional metadata
### Migration Example
```typescript
// Old
const result = oldFunction(param1, param2);
// New
const result = newFunction({ param1, param2 });