Module Development
Guide to creating new utility modules.
Creating a New Moduleβ
1. Choose Locationβ
Place your module in the appropriate utils/ subdirectory:
utils/
βββ formatting/ # Data formatters
βββ maps/ # Map functionality
βββ charts/ # Chart functionality
βββ state/ # State management
βββ files/ # File operations
βββ ui/ # UI components
βββ your-category/
2. Create Module Fileβ
// utils/formatting/formatPower.js
/**
* Power formatting utilities.
* @module formatPower
*/
/**
* Formats power value for display.
*
* @param {number} watts - Power in watts
* @param {Object} [options] - Formatting options
* @param {number} [options.decimals=0] - Decimal places
* @returns {string} Formatted power string
*
* @example
* formatPower(250); // "250 W"
* formatPower(1500); // "1.5 kW"
*/
export function formatPower(watts, options = {}) {
const { decimals = 0 } = options;
if (watts >= 1000) {
return `${(watts / 1000).toFixed(1)} kW`;
}
return `${watts.toFixed(decimals)} W`;
}
/**
* Converts power to watts per kilogram.
*
* @param {number} watts - Power in watts
* @param {number} weightKg - Weight in kilograms
* @returns {number} Watts per kilogram
*/
export function powerToWkg(watts, weightKg) {
if (weightKg <= 0) {
throw new Error('Weight must be positive');
}
return watts / weightKg;
}
3. Add Testsβ
// tests/unit/formatPower.test.js
import { describe, it, expect } from 'vitest';
import { formatPower, powerToWkg } from '../../utils/formatting/formatPower.js';
describe('formatPower', () => {
it('should format watts', () => {
expect(formatPower(250)).toBe('250 W');
});
it('should format kilowatts for large values', () => {
expect(formatPower(1500)).toBe('1.5 kW');
});
it('should handle zero', () => {
expect(formatPower(0)).toBe('0 W');
});
});
describe('powerToWkg', () => {
it('should calculate watts per kg', () => {
expect(powerToWkg(300, 75)).toBe(4);
});
it('should throw for zero weight', () => {
expect(() => powerToWkg(300, 0)).toThrow();
});
});
4. Export from Indexβ
If your category has an index file:
// utils/formatting/index.js
export { formatDistance } from './formatDistance.js';
export { formatDuration } from './formatDuration.js';
export { formatPower, powerToWkg } from './formatPower.js'; // Add
5. Import and Useβ
// In other modules
import { formatPower } from '../utils/formatting/formatPower.js';
// Or from index
import { formatPower } from '../utils/formatting/index.js';
Module Templateβ
/**
* [Module Description]
* @module [moduleName]
*/
// Constants
const DEFAULT_OPTIONS = {
// Default values
};
/**
* [Function description]
*
* @param {type} paramName - Parameter description
* @param {Object} [options] - Options object
* @returns {type} Return description
*
* @example
* // Usage example
*/
export function functionName(param, options = {}) {
// Merge options with defaults
const opts = { ...DEFAULT_OPTIONS, ...options };
// Validate inputs
if (!isValid(param)) {
throw new Error('Invalid parameter');
}
// Implementation
return result;
}
Best Practicesβ
Doβ
- β Single responsibility
- β Clear function names
- β Comprehensive JSDoc
- β Input validation
- β Error handling
- β Unit tests
Don'tβ
- β Side effects
- β Global state
- β Circular dependencies
- β DOM manipulation (in utility modules)
- β Console.log in production
Module Categoriesβ
Formatting Modulesβ
Transform data for display:
export function formatValue(value) {
// Transform to display string
return displayString;
}
Utility Modulesβ
General-purpose helpers:
export function calculateMetric(data) {
// Compute and return result
return result;
}
UI Modulesβ
Handle user interface:
export function setupComponent(element) {
// Attach event listeners
// Update DOM
}
Next: Testing β