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.
*
* @example
* formatPower(250); // "250 W"
* formatPower(1500); // "1.5 kW"
*
* @param {number} watts - Power in watts
* @param {Object} [options] - Formatting options
* @param {number} [options.decimals=0] - Decimal places. Default is `0`
*
* @returns {string} Formatted power string
*/
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 {undefined} moduleName
*/
// Constants
const DEFAULT_OPTIONS = {
// Default values
};
/**
* [Function description]
*
* @example
* // Usage example
*
* @param {type} paramName - Parameter description
* @param {Object} [options] - Options object
*
* @returns {type} Return description
*/
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 β