Examples
Real-world examples and use cases for Lopos utility functions.
Examples
Use Cases
Practical
Example Categories
Form Validation
Validate user input with flexible testing
Configuration Management
Merge and manage application configs
Event Handling
Throttle events for better performance
Data Processing
Safe cloning and manipulation
Date Operations
Parse and format dates flexibly
Form Validation System
Build a comprehensive form validation system using Lopos test functions.
const { test, lopif } = require("lopos");
class FormValidator {
constructor() {
this.errors = [];
}
validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return lopif(
test("regexTest", email, emailRegex),
() => true,
() => {
this.errors.push("Invalid email format");
return false;
}
);
}
validatePassword(password) {
const validations = [
{
test: () => test("lengthGreaterThan", password, 7),
message: "Password must be at least 8 characters"
},
{
test: () => test("regexTest", password, /[A-Z]/),
message: "Password must contain uppercase letter"
},
{
test: () => test("regexTest", password, /[0-9]/),
message: "Password must contain a number"
}
];
return validations.every(validation =>
lopif(
validation.test(),
() => true,
() => {
this.errors.push(validation.message);
return false;
}
)
);
}
validateAge(age) {
return lopif(
test("inRange", parseInt(age), [13, 120]),
() => true,
() => {
this.errors.push("Age must be between 13 and 120");
return false;
}
);
}
validateForm(formData) {
this.errors = [];
const isEmailValid = this.validateEmail(formData.email);
const isPasswordValid = this.validatePassword(formData.password);
const isAgeValid = this.validateAge(formData.age);
return {
isValid: isEmailValid && isPasswordValid && isAgeValid,
errors: this.errors
};
}
}
// Usage
const validator = new FormValidator();
const result = validator.validateForm({
email: "user@example.com",
password: "SecurePass123",
age: "25"
});
console.log(result.isValid); // true or false
console.log(result.errors); // Array of error messagesConfiguration Management
Manage application configurations with environment-specific overrides.
const { deepMerge, test } = require("lopos");
class ConfigManager {
constructor() {
this.defaultConfig = {
server: {
port: 3000,
host: "localhost",
ssl: false
},
database: {
host: "localhost",
port: 5432,
pool: {
min: 2,
max: 10
}
},
cache: {
ttl: 3600,
maxSize: 1000
},
logging: {
level: "info",
format: "json"
}
};
}
loadConfig(environment = "development") {
const envConfigs = {
development: {
server: { port: 3001 },
logging: { level: "debug" }
},
production: {
server: {
port: 80,
ssl: true,
host: "0.0.0.0"
},
database: {
pool: { min: 5, max: 50 }
},
cache: {
ttl: 7200,
maxSize: 10000
},
logging: { level: "error" }
},
testing: {
database: {
host: "test-db",
pool: { min: 1, max: 5 }
},
cache: { ttl: 60 }
}
};
const envConfig = envConfigs[environment] || {};
return deepMerge(this.defaultConfig, envConfig);
}
validateConfig(config) {
const validations = [
test("isType", config.server.port, "number"),
test("inRange", config.server.port, [1, 65535]),
test("contains", ["info", "debug", "warn", "error"], config.logging.level),
test("greaterThan", config.database.pool.max, config.database.pool.min)
];
return validations.every(Boolean);
}
getConfig(environment, userOverrides = {}) {
let config = this.loadConfig(environment);
if (Object.keys(userOverrides).length > 0) {
config = deepMerge(config, userOverrides);
}
if (!this.validateConfig(config)) {
throw new Error("Invalid configuration");
}
return config;
}
}
// Usage
const configManager = new ConfigManager();
// Development config
const devConfig = configManager.getConfig("development");
// Production with custom overrides
const prodConfig = configManager.getConfig("production", {
server: { port: 8080 },
database: { host: "prod-db.example.com" }
});
console.log("Dev port:", devConfig.server.port); // 3001
console.log("Prod port:", prodConfig.server.port); // 8080Performance-Optimized Event Handling
Create responsive UIs with throttled event handlers and smart state management.
const { advancedThrottle, test, lopif } = require("lopos");
class UIController {
constructor() {
this.state = {
scrollPosition: 0,
windowWidth: window.innerWidth,
searchQuery: "",
isScrolling: false
};
this.setupEventHandlers();
}
setupEventHandlers() {
// Throttled scroll handler
this.handleScroll = advancedThrottle(() => {
const scrollTop = window.pageYOffset;
this.state.scrollPosition = scrollTop;
// Update navigation visibility
lopif(
test("greaterThan", scrollTop, 100),
() => this.showFloatingNav(),
() => this.hideFloatingNav()
);
// Update scroll indicator
this.updateScrollIndicator(scrollTop);
}, 16, { leading: true, trailing: true }); // ~60fps
// Throttled resize handler
this.handleResize = advancedThrottle(() => {
const newWidth = window.innerWidth;
const oldWidth = this.state.windowWidth;
this.state.windowWidth = newWidth;
// Trigger layout changes only if significant resize
lopif(
test("greaterThan", Math.abs(newWidth - oldWidth), 100),
() => this.handleLayoutChange(newWidth),
() => console.log("Minor resize, ignoring")
);
}, 250, { leading: false, trailing: true });
// Throttled search with debounce-like behavior
this.handleSearch = advancedThrottle((query) => {
lopif(
test("lengthGreaterThan", query.trim(), 2),
() => this.performSearch(query),
() => this.clearSearchResults()
);
}, 300, { leading: false, trailing: true });
// Attach event listeners
window.addEventListener('scroll', this.handleScroll);
window.addEventListener('resize', this.handleResize);
}
showFloatingNav() {
const nav = document.getElementById('floating-nav');
if (nav) nav.classList.add('visible');
}
hideFloatingNav() {
const nav = document.getElementById('floating-nav');
if (nav) nav.classList.remove('visible');
}
updateScrollIndicator(scrollTop) {
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
const progress = (scrollTop / docHeight) * 100;
const indicator = document.getElementById('scroll-indicator');
if (indicator) {
indicator.style.width = `${Math.min(progress, 100)}%`;
}
}
handleLayoutChange(width) {
lopif(
test("lessThan", width, 768),
() => this.enableMobileLayout(),
() => this.enableDesktopLayout()
);
}
enableMobileLayout() {
document.body.classList.add('mobile-layout');
document.body.classList.remove('desktop-layout');
}
enableDesktopLayout() {
document.body.classList.add('desktop-layout');
document.body.classList.remove('mobile-layout');
}
performSearch(query) {
console.log(`Searching for: ${query}`);
// Implement actual search logic
}
clearSearchResults() {
console.log("Clearing search results");
// Clear search results
}
// Cleanup method
destroy() {
this.handleScroll.cancel();
this.handleResize.cancel();
this.handleSearch.cancel();
window.removeEventListener('scroll', this.handleScroll);
window.removeEventListener('resize', this.handleResize);
}
}
// Usage
const uiController = new UIController();
// Search input handler
const searchInput = document.getElementById('search');
if (searchInput) {
searchInput.addEventListener('input', (e) => {
uiController.handleSearch(e.target.value);
});
}
// Cleanup on page unload
window.addEventListener('beforeunload', () => {
uiController.destroy();
});Safe Data Processing Pipeline
Process and transform data safely with cloning and validation.
const { deepClone, test, lopif, deepMerge } = require("lopos");
class DataProcessor {
constructor() {
this.processors = new Map();
this.cache = new Map();
}
// Register data transformation functions
registerProcessor(name, processorFn, validator = null) {
this.processors.set(name, { fn: processorFn, validator });
}
// Safe data transformation with validation
processData(data, processorName, options = {}) {
const processor = this.processors.get(processorName);
return lopif(
test("isType", processor, "object"),
() => {
// Clone data to prevent mutation
const clonedData = deepClone(data);
// Validate input if validator exists
const isValid = lopif(
test("isType", processor.validator, "function"),
() => processor.validator(clonedData),
() => true // No validator, assume valid
);
return lopif(
isValid,
() => {
try {
const result = processor.fn(clonedData, options);
// Cache result if caching is enabled
lopif(
options.cache === true,
() => this.cacheResult(processorName, data, result),
() => null
);
return result;
} catch (error) {
console.error(`Processing failed for ${processorName}:`, error);
return { error: error.message, originalData: clonedData };
}
},
() => ({ error: "Invalid input data", originalData: clonedData })
);
},
() => ({ error: `Processor '${processorName}' not found` })
);
}
cacheResult(processorName, input, result) {
const cacheKey = `${processorName}_${JSON.stringify(input)}`;
this.cache.set(cacheKey, {
result,
timestamp: Date.now()
});
}
// Batch processing with error handling
processBatch(dataArray, processorName, options = {}) {
return dataArray.map((item, index) => {
const result = this.processData(item, processorName, options);
return lopif(
test("containsKeys", result, ["error"]),
() => ({ index, error: result.error, item }),
() => ({ index, success: true, result, item })
);
});
}
// Pipeline processing
processPipeline(data, processorNames, options = {}) {
return processorNames.reduce((currentData, processorName) => {
return lopif(
test("containsKeys", currentData, ["error"]),
() => currentData, // Stop pipeline on error
() => this.processData(currentData, processorName, options)
);
}, data);
}
}
// Example processors
const dataProcessor = new DataProcessor();
// User data normalization
dataProcessor.registerProcessor(
'normalizeUser',
(user) => ({
id: user.id,
name: (user.firstName + ' ' + user.lastName).trim(),
email: user.email.toLowerCase(),
age: parseInt(user.age),
createdAt: new Date(user.createdAt),
preferences: deepMerge({
theme: 'light',
notifications: true
}, user.preferences || {})
}),
(user) => test("containsKeys", user, ["id", "firstName", "email"])
);
// Data aggregation
dataProcessor.registerProcessor(
'aggregateStats',
(users) => ({
total: users.length,
averageAge: users.reduce((sum, u) => sum + u.age, 0) / users.length,
emailDomains: [...new Set(users.map(u => u.email.split('@')[1]))],
ageGroups: {
young: users.filter(u => u.age < 25).length,
adult: users.filter(u => u.age >= 25 && u.age < 65).length,
senior: users.filter(u => u.age >= 65).length
}
}),
(users) => test("isArray", users) && users.length > 0
);
// Usage examples
const userData = [
{
id: 1,
firstName: "John",
lastName: "Doe",
email: "JOHN@EXAMPLE.COM",
age: "30",
createdAt: "2023-01-01",
preferences: { theme: "dark" }
},
{
id: 2,
firstName: "Jane",
lastName: "Smith",
email: "jane@test.org",
age: "25",
createdAt: "2023-02-01"
}
];
// Single user processing
const normalizedUser = dataProcessor.processData(userData[0], 'normalizeUser');
console.log(normalizedUser);
// Batch processing
const batchResults = dataProcessor.processBatch(userData, 'normalizeUser');
console.log(batchResults);
// Pipeline processing
const pipelineResult = dataProcessor.processPipeline(
userData,
['normalizeUser', 'aggregateStats'],
{ cache: true }
);
console.log(pipelineResult);Advanced Date Operations
Handle complex date scenarios with flexible parsing and formatting.
const { flexibleDate, test, lopif } = require("lopos");
class DateManager {
constructor(defaultTimezone = "local") {
this.defaultTimezone = defaultTimezone;
this.dateFormats = {
short: (date) => date.toLocaleDateString(),
long: (date) => date.toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
}),
time: (date) => date.toLocaleTimeString(),
iso: (date) => date.toISOString(),
relative: true
};
}
// Parse various date inputs
parseDate(input, options = {}) {
const config = {
timezone: this.defaultTimezone,
fallback: null,
strict: false,
...options
};
return flexibleDate(input, config);
}
// Format date with multiple options
formatDate(input, format = "short", options = {}) {
const date = this.parseDate(input, options);
return lopif(
test("equals", date, null),
() => "Invalid Date",
() => {
const formatFn = this.dateFormats[format];
return lopif(
test("isType", formatFn, "function"),
() => formatFn(new Date(date)),
() => flexibleDate(input, {
format: format === "relative" ? undefined : format,
relative: format === "relative",
...options
})
);
}
);
}
// Calculate date ranges
getDateRange(startDate, endDate, options = {}) {
const start = this.parseDate(startDate);
const end = this.parseDate(endDate);
return lopif(
test("equals", start, null) || test("equals", end, null),
() => ({ error: "Invalid date range" }),
() => {
const startTime = new Date(start).getTime();
const endTime = new Date(end).getTime();
const diffMs = endTime - startTime;
return {
start: this.formatDate(start, options.format || "iso"),
end: this.formatDate(end, options.format || "iso"),
duration: {
milliseconds: diffMs,
seconds: Math.floor(diffMs / 1000),
minutes: Math.floor(diffMs / (1000 * 60)),
hours: Math.floor(diffMs / (1000 * 60 * 60)),
days: Math.floor(diffMs / (1000 * 60 * 60 * 24))
},
isValid: diffMs >= 0
};
}
);
}
// Business day calculations
addBusinessDays(startDate, days) {
const date = new Date(this.parseDate(startDate));
let addedDays = 0;
while (addedDays < days) {
date.setDate(date.getDate() + 1);
// Skip weekends (Saturday = 6, Sunday = 0)
lopif(
test("contains", [0, 6], date.getDay()),
() => null, // Weekend, don't count
() => addedDays++ // Weekday, count it
);
}
return this.formatDate(date, "iso");
}
// Event scheduling
scheduleEvent(eventDate, reminderDays = [7, 1]) {
const event = this.parseDate(eventDate);
return lopif(
test("equals", event, null),
() => ({ error: "Invalid event date" }),
() => {
const eventTime = new Date(event).getTime();
const now = Date.now();
return {
event: {
date: this.formatDate(event, "long"),
time: this.formatDate(event, "time"),
relative: this.formatDate(event, "relative")
},
reminders: reminderDays.map(days => {
const reminderDate = flexibleDate(event, {
adjustDays: -days,
format: "iso"
});
return {
days: days,
date: this.formatDate(reminderDate, "long"),
isPast: new Date(reminderDate).getTime() < now
};
}),
status: lopif(
test("lessThan", eventTime, now),
() => "past",
() => lopif(
test("lessThan", eventTime - now, 24 * 60 * 60 * 1000),
() => "today",
() => "upcoming"
)
)
};
}
);
}
// Time zone conversion
convertTimezone(date, fromTz, toTz) {
const baseDate = this.parseDate(date, { timezone: fromTz });
return lopif(
test("equals", baseDate, null),
() => "Invalid Date",
() => this.formatDate(baseDate, "iso", { timezone: toTz })
);
}
}
// Usage examples
const dateManager = new DateManager("utc");
// Parse various formats
console.log(dateManager.parseDate("2023-12-25")); // ISO string
console.log(dateManager.parseDate("December 25, 2023")); // Natural language
console.log(dateManager.parseDate(1703462400000)); // Timestamp
// Format dates
console.log(dateManager.formatDate("2023-12-25", "long"));
console.log(dateManager.formatDate("2023-12-25", "relative"));
// Date range calculations
const range = dateManager.getDateRange("2023-01-01", "2023-12-31");
console.log(`Duration: ${range.duration.days} days`);
// Business days
const businessDate = dateManager.addBusinessDays("2023-12-22", 5);
console.log("5 business days later:", businessDate);
// Event scheduling
const eventSchedule = dateManager.scheduleEvent("2024-01-15T10:00:00Z", [7, 3, 1]);
console.log("Event schedule:", eventSchedule);
// Timezone conversion
const converted = dateManager.convertTimezone(
"2023-12-25T12:00:00Z",
"utc",
"+0300"
);
console.log("Converted time:", converted);More Examples
Explore more examples and use cases in the individual function documentation: