or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-utilities.mddata-structures.mddevelopment-utilities.mddom-styling.mdfunctional-programming.mdindex.mdnetwork-fetch.mdperformance-crypto.mdtext-unicode.mduser-agent-browser.md
tile.json

development-utilities.mddocs/

Development Utilities

Development aids including assertion utilities, error handling, debugging tools, and data type utilities.

Capabilities

Assertion Utilities

Runtime assertion and validation utilities for development and debugging.

const invariant = require('fbjs/lib/invariant');
const warning = require('fbjs/lib/warning');

/**
 * Assertion utility that throws error if condition is false
 * Supports sprintf-style formatting with %s placeholders
 * @param condition - Condition to assert (truthy values pass)
 * @param format - Error message format string with %s placeholders
 * @param args - Values to substitute into format string
 * @throws Error with formatted message if condition is false
 */
function invariant(condition: any, format: string, ...args: Array<any>): void;

/**
 * Development warning utility (no-op in production builds)
 * Logs warning to console if condition is false
 * @param condition - Condition to check (false triggers warning)
 * @param format - Warning message format string with %s placeholders
 * @param args - Values to substitute into format string
 */
function warning(condition: boolean, format: string, ...args: Array<any>): void;

Usage Examples:

const invariant = require('fbjs/lib/invariant');
const warning = require('fbjs/lib/warning');

// Basic assertions
function processUser(user) {
  invariant(user, 'User object is required');
  invariant(user.id, 'User must have an ID');
  invariant(typeof user.name === 'string', 'User name must be a string');
  
  // Process user...
}

// Assertions with formatted messages
function transfer(fromAccount, toAccount, amount) {
  invariant(fromAccount, 'Source account is required');
  invariant(toAccount, 'Destination account is required');
  invariant(amount > 0, 'Transfer amount must be positive, got %s', amount);
  invariant(fromAccount.balance >= amount, 
    'Insufficient funds: need %s, have %s', amount, fromAccount.balance);
  
  // Perform transfer...
}

// Array validation
function processArray(items) {
  invariant(Array.isArray(items), 'Expected array, got %s', typeof items);
  invariant(items.length > 0, 'Array cannot be empty');
  
  items.forEach((item, index) => {
    invariant(item != null, 'Item at index %s cannot be null', index);
  });
}

// API parameter validation
function createUser(userData) {
  invariant(userData, 'User data is required');
  invariant(userData.email, 'Email is required');
  invariant(userData.email.includes('@'), 'Invalid email format: %s', userData.email);
  
  warning(userData.name, 'User name not provided, using email as display name');
  warning(userData.phone, 'Phone number not provided');
  
  return {
    id: generateId(),
    email: userData.email,
    name: userData.name || userData.email,
    phone: userData.phone || null
  };
}

// State validation
class Counter {
  constructor(initialValue = 0) {
    invariant(typeof initialValue === 'number', 
      'Initial value must be a number, got %s', typeof initialValue);
    this.value = initialValue;
  }
  
  increment(step = 1) {
    invariant(typeof step === 'number', 'Step must be a number');
    invariant(step > 0, 'Step must be positive, got %s', step);
    
    this.value += step;
    warning(this.value <= 1000, 'Counter value is getting large: %s', this.value);
  }
  
  decrement(step = 1) {
    invariant(typeof step === 'number', 'Step must be a number');
    invariant(step > 0, 'Step must be positive, got %s', step);
    invariant(this.value >= step, 'Cannot decrement below zero: %s - %s', this.value, step);
    
    this.value -= step;
  }
}

// Configuration validation
function initializeApp(config) {
  invariant(config, 'Configuration object is required');
  invariant(config.apiUrl, 'API URL is required');
  invariant(typeof config.timeout === 'number', 
    'Timeout must be a number, got %s', typeof config.timeout);
  
  warning(config.timeout >= 5000, 
    'Timeout is very short (%s ms), consider increasing it', config.timeout);
  warning(config.apiUrl.startsWith('https://'), 
    'API URL should use HTTPS: %s', config.apiUrl);
  
  // Initialize app with validated config
}

// Error boundaries with detailed messages
function parseJSON(jsonString) {
  invariant(typeof jsonString === 'string', 
    'JSON input must be string, got %s', typeof jsonString);
  invariant(jsonString.length > 0, 'JSON string cannot be empty');
  
  try {
    return JSON.parse(jsonString);
  } catch (error) {
    invariant(false, 'Invalid JSON: %s', error.message);
  }
}

Type Checking Utilities

Utilities for runtime type checking and null safety.

const nullthrows = require('fbjs/lib/nullthrows');

/**
 * Throws error if value is null or undefined, returns value otherwise
 * Provides type narrowing in TypeScript/Flow
 * @param value - Value to check for null/undefined
 * @param message - Optional error message
 * @returns The value if not null/undefined
 * @throws Error if value is null or undefined
 */
function nullthrows<T>(value: ?T, message?: string): T;

Usage Examples:

const nullthrows = require('fbjs/lib/nullthrows');

// Basic null checking
function processElement(elementId) {
  const element = document.getElementById(elementId);
  const safeElement = nullthrows(element, `Element not found: ${elementId}`);
  
  // Now we know element is not null
  safeElement.addEventListener('click', handleClick);
  return safeElement;
}

// API response validation
function processUserData(response) {
  const user = nullthrows(response.user, 'User data missing from response');
  const profile = nullthrows(user.profile, 'User profile missing');
  
  return {
    id: nullthrows(user.id, 'User ID missing'),
    name: nullthrows(profile.name, 'Profile name missing'),
    email: nullthrows(profile.email, 'Profile email missing')
  };
}

// Array processing with null safety
function processItems(items) {
  return items.map((item, index) => {
    const safeItem = nullthrows(item, `Item at index ${index} is null`);
    return {
      id: nullthrows(safeItem.id, `Item ${index} missing ID`),
      name: nullthrows(safeItem.name, `Item ${index} missing name`)
    };
  });
}

// Optional chaining alternative
function getNestedValue(obj) {
  const level1 = nullthrows(obj.level1, 'Level 1 missing');
  const level2 = nullthrows(level1.level2, 'Level 2 missing');
  return nullthrows(level2.value, 'Final value missing');
}

// Function parameter validation
function calculateArea(shape) {
  const width = nullthrows(shape.width, 'Shape width is required');
  const height = nullthrows(shape.height, 'Shape height is required');
  
  return width * height;
}

// Configuration validation
function loadConfig(configData) {
  return {
    apiKey: nullthrows(configData.apiKey, 'API key is required'),
    baseUrl: nullthrows(configData.baseUrl, 'Base URL is required'),
    timeout: configData.timeout || 5000, // Optional with default
    retries: configData.retries || 3      // Optional with default
  };
}

Key Mirror Utilities

Utilities for creating objects where keys equal their values, useful for constants and enums.

const keyMirror = require('fbjs/lib/keyMirror');
const keyMirrorRecursive = require('fbjs/lib/keyMirrorRecursive');
const keyOf = require('fbjs/lib/keyOf');

/**
 * Creates object where keys equal their values
 * Useful for creating constant enums that are minification-safe
 * Validates that input is an object and not an array using invariant
 * @param obj - Object with keys to mirror (values are ignored)
 * @returns Object where each key equals its string value
 * @throws Error if obj is not an object or is an array
 */
function keyMirror<T: {}>(obj: T): $ObjMapi<T, <K>(K) => K>;

/**
 * Recursive version of keyMirror for nested objects
 * @param obj - Object with nested structure to mirror
 * @returns Object with mirrored keys at all levels
 */
function keyMirrorRecursive(obj: Object): Object;

/**
 * Gets minification-safe property key name
 * Useful for accessing object properties in a way that survives minification
 * @param oneKeyObj - Object with single property
 * @returns String key name
 */
function keyOf(oneKeyObj: Object): string;

Usage Examples:

const keyMirror = require('fbjs/lib/keyMirror');
const keyMirrorRecursive = require('fbjs/lib/keyMirrorRecursive');
const keyOf = require('fbjs/lib/keyOf');

// Basic enum creation
const ActionTypes = keyMirror({
  USER_LOGIN: null,
  USER_LOGOUT: null,
  LOAD_DATA: null,
  SAVE_DATA: null,
  SHOW_ERROR: null
});

console.log(ActionTypes);
// {
//   USER_LOGIN: 'USER_LOGIN',
//   USER_LOGOUT: 'USER_LOGOUT',
//   LOAD_DATA: 'LOAD_DATA',
//   SAVE_DATA: 'SAVE_DATA',
//   SHOW_ERROR: 'SHOW_ERROR'
// }

// Error handling - keyMirror validates input with invariant
try {
  const invalidEnum = keyMirror(['not', 'an', 'object']); // Throws Error
} catch (error) {
  console.error('keyMirror failed:', error.message);
  // Output: "keyMirror(...): Argument must be an object."
}

try {
  const arrayEnum = keyMirror([1, 2, 3]); // Throws Error - arrays not allowed
} catch (error) {
  console.error('keyMirror failed:', error.message);
  // Output: "keyMirror(...): Argument must be an object."
}

// Safe keyMirror wrapper
function safeKeyMirror(obj, defaultValue = {}) {
  try {
    if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
      console.warn('Invalid input for keyMirror, using default');
      return defaultValue;
    }
    return keyMirror(obj);
  } catch (error) {
    console.error('keyMirror error:', error.message);
    return defaultValue;
  }
}

// Usage in Redux actions
function loginUser(credentials) {
  return {
    type: ActionTypes.USER_LOGIN,
    payload: credentials
  };
}

// API endpoints enum
const API_ENDPOINTS = keyMirror({
  USERS: null,
  PRODUCTS: null,
  ORDERS: null,
  ANALYTICS: null
});

function makeRequest(endpoint, data) {
  const url = `https://api.example.com/${endpoint.toLowerCase()}`;
  // Safe to use endpoint as it equals its string value
}

// Status constants
const Status = keyMirror({
  PENDING: null,
  SUCCESS: null,
  ERROR: null,
  CANCELLED: null
});

class AsyncOperation {
  constructor() {
    this.status = Status.PENDING;
  }
  
  complete() {
    this.status = Status.SUCCESS;
  }
  
  fail() {
    this.status = Status.ERROR;
  }
}

// Recursive mirroring for nested constants
const CONFIG_KEYS = keyMirrorRecursive({
  API: {
    BASE_URL: null,
    TIMEOUT: null,
    RETRIES: null
  },
  UI: {
    THEME: null,
    LANGUAGE: null,
    ANIMATIONS: {
      DURATION: null,
      EASING: null
    }
  },
  FEATURES: {
    ANALYTICS: null,
    NOTIFICATIONS: null
  }
});

console.log(CONFIG_KEYS);
// {
//   API: {
//     BASE_URL: 'BASE_URL',
//     TIMEOUT: 'TIMEOUT', 
//     RETRIES: 'RETRIES'
//   },
//   UI: {
//     THEME: 'THEME',
//     LANGUAGE: 'LANGUAGE',
//     ANIMATIONS: {
//       DURATION: 'DURATION',
//       EASING: 'EASING'
//     }
//   },
//   FEATURES: {
//     ANALYTICS: 'ANALYTICS',
//     NOTIFICATIONS: 'NOTIFICATIONS'
//   }
// }

// Minification-safe property access
const user = { name: 'Alice', age: 30, email: 'alice@example.com' };

// Instead of 'name' (which gets minified)
const nameKey = keyOf({ name: null }); // 'name'
const userName = user[nameKey];

// Safer for property validation
function validateUser(user) {
  const requiredFields = [
    keyOf({ name: null }),
    keyOf({ email: null }),
    keyOf({ age: null })
  ];
  
  requiredFields.forEach(field => {
    if (!user[field]) {
      throw new Error(`Missing required field: ${field}`);
    }
  });
}

// Form field names
const FORM_FIELDS = keyMirror({
  USERNAME: null,
  PASSWORD: null,
  EMAIL: null,
  CONFIRM_PASSWORD: null
});

function createForm() {
  return {
    [FORM_FIELDS.USERNAME]: '',
    [FORM_FIELDS.PASSWORD]: '',
    [FORM_FIELDS.EMAIL]: '',
    [FORM_FIELDS.CONFIRM_PASSWORD]: ''
  };
}

// Event types for event emitter
const EVENTS = keyMirror({
  CONNECT: null,
  DISCONNECT: null,
  MESSAGE: null,
  ERROR: null,
  RECONNECT: null
});

class EventEmitter {
  constructor() {
    this.listeners = {};
  }
  
  on(event, callback) {
    // Event names are guaranteed to be strings
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(callback);
  }
  
  emit(event, data) {
    if (this.listeners[event]) {
      this.listeners[event].forEach(callback => callback(data));
    }
  }
}

// Usage
const emitter = new EventEmitter();
emitter.on(EVENTS.CONNECT, () => console.log('Connected'));
emitter.emit(EVENTS.CONNECT);

Path and Phone Number Utilities

Utilities for object property access and phone number validation.

const getByPath = require('fbjs/lib/getByPath');
const isInternationalPhoneNumber = require('fbjs/lib/isInternationalPhoneNumber');

/**
 * Gets nested property by dot-notation path string
 * @param object - Object to traverse
 * @param path - Dot-notation path (e.g., 'user.profile.name')
 * @returns Value at path or undefined if path doesn't exist
 */
function getByPath(object: Object, path: string): any;

/**
 * Validates international phone number format
 * @param number - Phone number string to validate
 * @returns True if number appears to be valid international format
 */
function isInternationalPhoneNumber(number: string): boolean;

Usage Examples:

const getByPath = require('fbjs/lib/getByPath');
const isInternationalPhoneNumber = require('fbjs/lib/isInternationalPhoneNumber');

// Nested object property access
const user = {
  id: 123,
  profile: {
    personal: {
      name: 'Alice Johnson',
      age: 30
    },
    contact: {
      email: 'alice@example.com',
      phone: '+1-555-123-4567',
      address: {
        street: '123 Main St',
        city: 'Springfield',
        country: 'USA'
      }
    }
  },
  preferences: {
    theme: 'dark',
    notifications: {
      email: true,
      sms: false,
      push: true
    }
  }
};

// Get nested values safely
const name = getByPath(user, 'profile.personal.name'); // 'Alice Johnson'
const email = getByPath(user, 'profile.contact.email'); // 'alice@example.com'
const city = getByPath(user, 'profile.contact.address.city'); // 'Springfield'
const theme = getByPath(user, 'preferences.theme'); // 'dark'

// Handle missing paths gracefully
const missing = getByPath(user, 'profile.social.twitter'); // undefined
const invalid = getByPath(user, 'invalid.path.here'); // undefined

// Dynamic path building
function getUserProperty(user, category, field) {
  const path = `profile.${category}.${field}`;
  return getByPath(user, path);
}

const userEmail = getUserProperty(user, 'contact', 'email');
const userAge = getUserProperty(user, 'personal', 'age');

// Form data extraction
const formPaths = [
  'profile.personal.name',
  'profile.contact.email',
  'profile.contact.phone',
  'preferences.notifications.email'
];

const formData = {};
formPaths.forEach(path => {
  const value = getByPath(user, path);
  if (value !== undefined) {
    formData[path] = value;
  }
});

// Configuration access
const config = {
  api: {
    endpoints: {
      users: '/api/users',
      products: '/api/products'
    },
    timeout: 5000,
    retries: 3
  },
  ui: {
    theme: {
      primary: '#007bff',
      secondary: '#6c757d'
    }
  }
};

const usersEndpoint = getByPath(config, 'api.endpoints.users');
const primaryColor = getByPath(config, 'ui.theme.primary');

// Phone number validation
const phoneNumbers = [
  '+1-555-123-4567',    // US format
  '+44-20-7946-0958',   // UK format  
  '+33-1-23-45-67-89',  // France format
  '+81-3-1234-5678',    // Japan format
  '555-123-4567',       // Invalid (no country code)
  '+1234567890123456',  // Invalid (too long)
  'not-a-phone'         // Invalid (not a number)
];

phoneNumbers.forEach(number => {
  const isValid = isInternationalPhoneNumber(number);
  console.log(`${number}: ${isValid ? 'Valid' : 'Invalid'}`);
});

// User registration validation
function validateRegistration(userData) {
  const errors = [];
  
  const name = getByPath(userData, 'personal.name');
  if (!name) {
    errors.push('Name is required');
  }
  
  const email = getByPath(userData, 'contact.email');
  if (!email || !email.includes('@')) {
    errors.push('Valid email is required');
  }
  
  const phone = getByPath(userData, 'contact.phone');
  if (phone && !isInternationalPhoneNumber(phone)) {
    errors.push('Phone number must be in international format');
  }
  
  return {
    isValid: errors.length === 0,
    errors: errors
  };
}

// API response processing
function processAPIResponse(response) {
  return {
    id: getByPath(response, 'data.user.id'),
    name: getByPath(response, 'data.user.profile.displayName'),
    avatar: getByPath(response, 'data.user.profile.avatar.url'),
    isActive: getByPath(response, 'data.user.status.isActive'),
    lastLogin: getByPath(response, 'data.user.activity.lastLoginDate'),
    permissions: getByPath(response, 'data.user.permissions') || []
  };
}

// Settings management
class Settings {
  constructor(data) {
    this.data = data;
  }
  
  get(path, defaultValue = null) {
    const value = getByPath(this.data, path);
    return value !== undefined ? value : defaultValue;
  }
  
  set(path, value) {
    // Simple path setting (would need more complex logic for real implementation)
    const keys = path.split('.');
    let current = this.data;
    
    for (let i = 0; i < keys.length - 1; i++) {
      if (!current[keys[i]]) {
        current[keys[i]] = {};
      }
      current = current[keys[i]];
    }
    
    current[keys[keys.length - 1]] = value;
  }
}

Missing forks Utilities

Additional configuration and utility modules from Facebook's fork implementations.

const SiteData = require('fbjs/lib/SiteData');
const TokenizeUtil = require('fbjs/lib/TokenizeUtil');
const URI = require('fbjs/lib/URI');
const cssVar = require('fbjs/lib/cssVar');

/**
 * Site configuration data object
 * @type Object with site-specific configuration
 */
const SiteData: {
  is_rtl: boolean;  // Whether site uses right-to-left text direction
};

/**
 * Text tokenization utilities
 * @returns Punctuation regex pattern for tokenization
 */
function TokenizeUtil.getPunctuation(): string;

/**
 * Simple URI wrapper class
 * @constructor
 * @param uri - URI string to parse
 */
class URI {
  constructor(uri: string);
  toString(): string;
}

/**
 * CSS variable utility
 * Gets CSS variable value by name from fbjs-css-vars
 * @param name - CSS variable name
 * @returns CSS variable value
 * @throws Error via invariant if variable not found
 */
function cssVar(name: string): string;

/**
 * Development warning utility (from __forks__)
 * Logs warning to console if condition is false (no-op in production)
 * @param condition - Condition to check (false triggers warning)
 * @param format - Warning message format string with %s placeholders
 * @param args - Values to substitute into format string
 */
function warning(condition: boolean, format: string, ...args: Array<any>): void;

Usage Examples:

const SiteData = require('fbjs/lib/SiteData');
const TokenizeUtil = require('fbjs/lib/TokenizeUtil');
const URI = require('fbjs/lib/URI');
const cssVar = require('fbjs/lib/cssVar');
const warning = require('fbjs/lib/warning');

// Site configuration
if (SiteData.is_rtl) {
  document.body.dir = 'rtl';
  document.body.style.textAlign = 'right';
}

// Text tokenization
const punctuationPattern = TokenizeUtil.getPunctuation();
const tokenizer = new RegExp(punctuationPattern, 'g');
const tokens = text.split(tokenizer).filter(token => token.trim());

// URI handling
const uri = new URI('https://example.com/path?query=value#fragment');
const uriString = uri.toString(); // 'https://example.com/path?query=value#fragment'

// CSS variables
try {
  const primaryColor = cssVar('primary-color');
  element.style.color = primaryColor;
} catch (error) {
  console.error('CSS variable not found:', error.message);
}

// Development warnings
function validateUser(user) {
  warning(user.name, 'User name is missing, using ID as fallback');
  warning(user.email, 'User email not provided, notifications disabled');
  
  return {
    id: user.id,
    name: user.name || `User ${user.id}`,
    email: user.email || null
  };
}

Error Handling Utilities

Development error handling and event listener utilities.

const ErrorUtils = require('fbjs/lib/ErrorUtils');
const EventListener = require('fbjs/lib/EventListener');

/**
 * Error handling utilities for development and production
 */
const ErrorUtils: {
  /**
   * Global error handler registration
   * @param handler - Function to handle uncaught errors
   */
  setGlobalHandler(handler: (error: Error, isFatal: boolean) => void): void;
  
  /**
   * Reports error to error handling system
   * @param error - Error object or message
   * @param isFatal - Whether error is fatal to application
   */
  reportError(error: Error | string, isFatal?: boolean): void;
  
  /**
   * Wraps function to catch and report errors
   * @param fn - Function to wrap
   * @param context - Optional context for error reporting
   * @returns Wrapped function that catches errors
   */
  guard(fn: Function, context?: string): Function;
  
  /**
   * Creates error boundary for React-like error handling
   * @param component - Component or function to protect
   * @param fallback - Fallback to use when error occurs
   * @returns Protected component
   */
  applyWithGuard(component: Function, fallback?: Function): Function;
};

/**
 * Cross-browser event listener utilities
 */
const EventListener: {
  /**
   * Adds event listener with cross-browser compatibility
   * @param target - DOM element or event target
   * @param eventType - Event type string
   * @param listener - Event handler function
   * @param capture - Whether to use capture phase
   * @returns Object with remove() method
   */
  listen(
    target: EventTarget, 
    eventType: string, 
    listener: (event: Event) => void, 
    capture?: boolean
  ): { remove(): void };
  
  /**
   * Adds one-time event listener
   * @param target - DOM element or event target
   * @param eventType - Event type string
   * @param listener - Event handler function
   * @returns Object with remove() method
   */
  once(
    target: EventTarget,
    eventType: string,
    listener: (event: Event) => void
  ): { remove(): void };
  
  /**
   * Captures events during capture phase
   * @param target - DOM element or event target
   * @param eventType - Event type string
   * @param listener - Event handler function
   * @returns Object with remove() method
   */
  capture(
    target: EventTarget,
    eventType: string,
    listener: (event: Event) => void
  ): { remove(): void };
};

Usage Examples:

const ErrorUtils = require('fbjs/lib/ErrorUtils');
const EventListener = require('fbjs/lib/EventListener');

// Global error handling setup
ErrorUtils.setGlobalHandler((error, isFatal) => {
  console.error('Global error caught:', error);
  
  // Send to error reporting service
  if (typeof window !== 'undefined' && window.errorReportingService) {
    window.errorReportingService.report({
      message: error.message,
      stack: error.stack,
      isFatal: isFatal,
      timestamp: Date.now(),
      userAgent: navigator.userAgent,
      url: window.location.href
    });
  }
});

// Function wrapping for error safety
const safeAsyncFunction = ErrorUtils.guard(async function(userId) {
  const response = await fetch(`/api/users/${userId}`);
  const userData = await response.json();
  return userData;
}, 'user-data-fetch');

// Event listener management
class ComponentManager {
  constructor(element) {
    this.element = element;
    this.listeners = [];
  }
  
  addListener(eventType, handler) {
    const listener = EventListener.listen(this.element, eventType, handler);
    this.listeners.push(listener);
    return listener;
  }
  
  addOneTimeListener(eventType, handler) {
    const listener = EventListener.once(this.element, eventType, handler);
    this.listeners.push(listener);
    return listener;
  }
  
  destroy() {
    // Clean up all listeners
    this.listeners.forEach(listener => listener.remove());
    this.listeners = [];
  }
}

// Error boundary pattern
function createErrorBoundary(render, fallback) {
  return ErrorUtils.applyWithGuard(render, fallback || function(error) {
    return `<div class="error">Something went wrong: ${error.message}</div>`;
  });
}

// Safe API calls with error reporting
async function safeApiCall(endpoint, options = {}) {
  try {
    const response = await fetch(endpoint, options);
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    
    return await response.json();
  } catch (error) {
    ErrorUtils.reportError(error, false);
    throw error; // Re-throw for caller to handle
  }
}

// Form validation with error handling
const safeFormValidator = ErrorUtils.guard(function(formData) {
  const errors = [];
  
  if (!formData.email) {
    errors.push('Email is required');
  } else if (!formData.email.includes('@')) {
    errors.push('Invalid email format');
  }
  
  if (!formData.password) {
    errors.push('Password is required');
  } else if (formData.password.length < 8) {
    errors.push('Password must be at least 8 characters');
  }
  
  return {
    isValid: errors.length === 0,
    errors: errors
  };
}, 'form-validation');

// Event handling with cleanup
function setupPageEvents() {
  const cleanupCallbacks = [];
  
  // Navigation events
  const navListener = EventListener.listen(document, 'click', (event) => {
    if (event.target.matches('[data-nav]')) {
      event.preventDefault();
      const target = event.target.getAttribute('data-nav');
      navigateTo(target);
    }
  });
  cleanupCallbacks.push(() => navListener.remove());
  
  // Form submission
  const formListener = EventListener.listen(document, 'submit', (event) => {
    if (event.target.matches('form[data-ajax]')) {
      event.preventDefault();
      handleAjaxForm(event.target);
    }
  });
  cleanupCallbacks.push(() => formListener.remove());
  
  // Keyboard shortcuts
  const keyListener = EventListener.listen(document, 'keydown', (event) => {
    if (event.ctrlKey && event.key === 's') {
      event.preventDefault();
      saveCurrentState();
    }
  });
  cleanupCallbacks.push(() => keyListener.remove());
  
  // Return cleanup function
  return function cleanup() {
    cleanupCallbacks.forEach(fn => fn());
  };
}

// Error monitoring for critical sections
function monitorCriticalSection(name, fn) {
  return ErrorUtils.guard(function(...args) {
    const startTime = performance.now();
    
    try {
      const result = fn.apply(this, args);
      
      // If it's a promise, handle async errors
      if (result && typeof result.then === 'function') {
        return result.catch(error => {
          ErrorUtils.reportError(new Error(`Critical section '${name}' failed: ${error.message}`), true);
          throw error;
        });
      }
      
      return result;
    } catch (error) {
      const duration = performance.now() - startTime;
      ErrorUtils.reportError(new Error(`Critical section '${name}' failed after ${duration}ms: ${error.message}`), true);
      throw error;
    }
  }, `critical-${name}`);
}