npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@entropy-tamer/reynard-core

v0.2.2

Published

Core utilities and modules for Reynard framework

Readme

reynard-core

The Foundation of the Reynard Framework 🦊

Core utilities, composables, and modules that power the entire Reynard ecosystem. This package provides the essential building blocks for reactive state management, security, HTTP clients, and comprehensive utility functions.

Architecture

graph TB
    subgraph "🦊 Reynard Core Framework"
        A[Core Index] --> B[Modules]
        A --> C[Composables]
        A --> D[Utils]
        A --> E[Clients]
        A --> F[Security]

        subgraph "🎯 Core Modules"
            B --> B1[Notification System]
            B --> B2[Notification Manager]
            B --> B3[Notification Factories]
            B --> B4[Notification Utils]
        end

        subgraph "⚡ SolidJS Composables"
            C --> C1[useNotifications]
            C --> C2[useLocalStorage]
            C --> C3[useMediaQuery]
            C --> C4[useDebounce]
            C --> C5[useThrottle]
            C --> C6[useClickOutside]
            C --> C7[useIntersectionObserver]
            C --> C8[useAsync]
            C --> C9[useEventListener]
            C --> C10[useViewportSize]
            C --> C11[useIdle]
            C --> C12[useGeolocation]
            C --> C13[useClipboard]
            C --> C14[useApiClient]
        end

        subgraph "🛠️ Utility Functions"
            D --> D1[Date Utils]
            D --> D2[Formatters]
            D --> D3[Language Utils]
            D --> D4[Validation]
            D --> D5[Async Utils]
            D --> D6[Package Exports]
            D --> D7[Optional i18n]
        end

        subgraph "🌐 HTTP Clients"
            E --> E1[API Client]
            E --> E2[HTTP Client]
            E --> E3[Health Monitoring]
            E --> E4[Error Handling]
        end

        subgraph "🛡️ Security Module"
            F --> F1[Crypto Utils]
            F --> F2[Input Validation]
            F --> F3[File Validation]
            F --> F4[Headers Security]
            F --> F5[XSS Protection]
            F --> F6[SQL Injection Prevention]
        end

        subgraph "🔧 Specialized Modules"
            G[Lazy Loading] --> G1[Package Export Registry]
            G --> G2[Dynamic Module Loading]
            H[HF Cache] --> H1[ML Model Caching]
            I[Image Utils] --> I1[Format Detection]
            J[Executor] --> J1[Task Management]
        end

        subgraph "🌍 Internationalization"
            K[Language Support] --> K1[Core Translations]
            K --> K2[Language Detection]
            K --> K3[Fallback Translations]
        end
    end

    subgraph "📦 External Dependencies"
        L[SolidJS] --> C
        M[Optional i18n] --> K
        N[Browser APIs] --> C1
        N --> C2
    end

    A -->|Exports| O[Framework Integration]
    B1 -->|Toast System| P[UI Components]
    C1 -->|Reactive State| Q[Application State]
    F1 -->|Security| R[Secure Operations]
    E1 -->|API Calls| S[Backend Services]

Data Flow

sequenceDiagram
    participant App as Application
    participant Core as Reynard Core
    participant Composable as Composables
    participant Security as Security Module
    participant Client as HTTP Client
    participant Backend as Backend API

    Note over App, Backend: Application Initialization
    App->>Core: Import Core Modules
    Core->>Security: Initialize Security Config
    Core->>Client: Setup HTTP Client

    Note over App, Backend: User Interaction Flow
    App->>Composable: useNotifications()
    Composable->>Core: Create Notification
    Core->>App: Toast Notification

    App->>Composable: useLocalStorage()
    Composable->>Core: Reactive Storage
    Core->>App: State Updates

    Note over App, Backend: API Communication
    App->>Composable: useApiClient()
    Composable->>Security: Validate Request
    Security->>Client: Secure HTTP Call
    Client->>Backend: API Request
    Backend-->>Client: Response
    Client-->>Composable: Typed Response
    Composable-->>App: Reactive Data

    Note over App, Backend: Security Validation
    App->>Security: validateInput()
    Security->>Security: XSS Protection
    Security->>Security: SQL Injection Check
    Security-->>App: Validation Result

Table of Contents

✨ Features

🎯 Core Composables

  • Notifications: Toast notification system with queue management and auto-dismiss
  • Local Storage: Reactive localStorage with cross-tab synchronization and type safety
  • Debouncing: Performance-optimized debounced values and callbacks
  • Throttling: Performance-optimized throttled values and callbacks with leading/trailing edge control
  • Click Outside: Detect clicks outside specified elements for dropdowns and modals
  • Intersection Observer: Reactive intersection observer for lazy loading and scroll-based animations
  • Async Operations: Comprehensive async state management with loading, error, and retry logic
  • Event Listeners: Reactive event listener management with automatic cleanup
  • Viewport Size: Reactive viewport dimensions tracking for responsive design
  • Idle Detection: User idle state detection with customizable timeout
  • Geolocation: Reactive geolocation API with position tracking and error handling
  • Clipboard: Reactive clipboard operations with read/write functionality
  • Media Queries: Responsive breakpoint detection with preference support
  • Optional Internationalization: Multi-language support when i18n package is available

🛡️ Security Module

  • Input Validation: Comprehensive validation for forms, files, and user input
  • XSS Protection: HTML sanitization and XSS prevention utilities
  • SQL Injection Prevention: SQL input validation and sanitization
  • File Security: Secure file upload validation and MIME type checking
  • Cryptographic Utilities: Secure random generation, hashing, and token management
  • Security Headers: CSP, HSTS, and other security header management
  • CSRF Protection: Token generation and validation

🌐 HTTP Clients

  • API Client: High-level API client with health monitoring and error handling
  • HTTP Client: Low-level HTTP client with retry logic and timeout management
  • Connection Management: Unified connection handling across the framework

🛠️ Utility Functions

  • Validation: Input validation, sanitization, and security utilities
  • Formatting: Date, number, currency, and file size formatting functions
  • Async Operations: Batch processing, concurrency control, retry logic, and polling
  • Language Detection: File type detection, language mapping, and syntax highlighting
  • Date Utilities: Comprehensive date manipulation and formatting
  • Performance: Timing utilities and performance monitoring
  • Type Safety: Comprehensive TypeScript definitions

🎨 Core Modules

  • Notification System: Toast notifications with auto-dismiss and queue management
  • Lazy Loading: Dynamic module loading and package export management
  • HuggingFace Cache: ML model caching and management utilities
  • Image Processing: Image format detection and processing utilities
  • Executor: Task execution and management system

📦 Installation

# Core package only (minimal dependencies)
pnpm install reynard-core solid-js

# With optional i18n support
pnpm install reynard-core reynard-i18n solid-js

# With connection management (recommended)
pnpm install reynard-core reynard-connection solid-js

🚀 Quick Start

Basic Notifications

import { createSignal } from "solid-js";
import { NotificationsProvider, createNotifications, useNotifications } from "reynard-core";

function App() {
  const notificationsModule = createNotifications();

  return (
    <NotificationsProvider value={notificationsModule}>
      <NotificationDemo />
    </NotificationsProvider>
  );
}

function NotificationDemo() {
  const { notify } = useNotifications();

  return (
    <div>
      <button onClick={() => notify("Hello World!", "success")}>Show Notification</button>
    </div>
  );
}

Security Validation

import { validateInput, sanitizeHTML, validateFileName, generateSecurePassword } from "reynard-core";

function SecurityDemo() {
  // Input validation
  const emailResult = validateInput("[email protected]", {
    type: "email",
    required: true,
  });

  // HTML sanitization
  const cleanHTML = sanitizeHTML('<script>alert("xss")</script><p>Safe content</p>');

  // File validation
  const fileResult = validateFileName("document.pdf", {
    allowedExtensions: [".pdf", ".doc", ".docx"],
    maxLength: 100,
  });

  // Secure password generation
  const password = generateSecurePassword(16, {
    includeUppercase: true,
    includeLowercase: true,
    includeNumbers: true,
    includeSymbols: true,
  });

  return (
    <div>
      <p>Email valid: {emailResult.isValid ? "Yes" : "No"}</p>
      <p>Clean HTML: {cleanHTML}</p>
      <p>File valid: {fileResult.isValid ? "Yes" : "No"}</p>
      <p>Generated password: {password}</p>
    </div>
  );
}

HTTP Client Usage

import { ApiClient, HTTPClient } from "reynard-core";

function ApiDemo() {
  // High-level API client
  const apiClient = new ApiClient({
    baseUrl: "https://api.example.com",
    apiKey: "your-api-key",
  });

  // Low-level HTTP client
  const httpClient = new HTTPClient({
    baseUrl: "https://api.example.com",
    timeout: 5000,
    retries: 3,
  });

  const fetchData = async () => {
    try {
      // Using API client
      const users = await apiClient.get("/users");

      // Using HTTP client
      const posts = await httpClient.get("/posts");

      return { users, posts };
    } catch (error) {
      console.error("API Error:", error);
    }
  };

  return <button onClick={fetchData}>Fetch Data</button>;
}

Notifications System

import { NotificationsProvider, createNotifications, useNotifications } from "reynard-core";

function App() {
  const notificationsModule = createNotifications();

  return (
    <NotificationsProvider value={notificationsModule}>
      <NotificationDemo />
    </NotificationsProvider>
  );
}

function NotificationDemo() {
  const { notify, dismiss, clear } = useNotifications();

  const showSuccess = () => notify("Operation completed!", "success");
  const showError = () => notify("Something went wrong!", "error");
  const showWarning = () => notify("Please check your input", "warning");

  return (
    <div>
      <button onClick={showSuccess}>Success</button>
      <button onClick={showError}>Error</button>
      <button onClick={showWarning}>Warning</button>
      <button onClick={clear}>Clear All</button>
    </div>
  );
}

Local Storage with Reactivity

import { useLocalStorage } from "reynard-core";

function SettingsComponent() {
  const [settings, setSettings] = useLocalStorage("app-settings", {
    language: "en",
    notifications: true,
  });

  const updateLanguage = (language: string) => {
    setSettings(prev => ({ ...prev, language }));
  };

  return (
    <div>
      <p>Current language: {settings().language}</p>
      <button onClick={() => updateLanguage("es")}>Switch to Spanish</button>
    </div>
  );
}

📚 API Reference

Composables

useNotifications()

Toast notification system with queue management and auto-dismiss.

const { notify, dismiss, clear, notifications } = useNotifications();

Methods:

  • notify(message, type?, options?): Show notification
  • dismiss(id): Dismiss specific notification
  • clear(): Clear all notifications

Types: "success" | "error" | "warning" | "info"

Example:

function NotificationDemo() {
  const { notify } = useNotifications();

  const handleSubmit = async () => {
    try {
      await submitForm();
      notify("Form submitted successfully!", "success");
    } catch (error) {
      notify("Failed to submit form", "error");
    }
  };

  return <button onClick={handleSubmit}>Submit</button>;
}

useMediaQuery(query)

Reactive media query detection for responsive design.

const isMobile = useMediaQuery("(max-width: 768px)");
const isDark = useMediaQuery("(prefers-color-scheme: dark)");

Example:

function ResponsiveComponent() {
  const isMobile = useMediaQuery("(max-width: 768px)");
  const isTablet = useMediaQuery("(max-width: 1024px)");

  return (
    <div>
      {isMobile() && <MobileLayout />}
      {isTablet() && !isMobile() && <TabletLayout />}
      {!isTablet() && <DesktopLayout />}
    </div>
  );
}

useLocalStorage<T>(key, options)

Reactive localStorage with type safety and cross-tab synchronization.

const [value, setValue] = useLocalStorage<T>(key, defaultValue, options);

Options:

  • defaultValue: Default value if key doesn't exist
  • serializer: Custom serialization functions
  • syncAcrossTabs: Enable cross-tab synchronization (default: true)

Example:

function UserPreferences() {
  const [preferences, setPreferences] = useLocalStorage("user-prefs", {
    darkMode: false,
    language: "en",
    fontSize: 16,
  });

  const toggleDarkMode = () => {
    setPreferences(prev => ({ ...prev, darkMode: !prev.darkMode }));
  };

  return (
    <div>
      <label>
        <input type="checkbox" checked={preferences().darkMode} onChange={toggleDarkMode} />
        Dark Mode
      </label>
    </div>
  );
}

useDebounce<T>(value, delay)

Debounced reactive values for performance optimization.

const debouncedValue = useDebounce(value, delay);

Example:

function SearchComponent() {
  const [searchTerm, setSearchTerm] = createSignal("");
  const debouncedSearchTerm = useDebounce(searchTerm, 300);

  createEffect(() => {
    if (debouncedSearchTerm()) {
      performSearch(debouncedSearchTerm());
    }
  });

  return <input value={searchTerm()} onInput={e => setSearchTerm(e.target.value)} placeholder="Search..." />;
}

useDebouncedCallback<TArgs>(callback, delay)

Debounced function calls to prevent excessive execution.

const debouncedCallback = useDebouncedCallback(callback, delay);

Example:

function AutoSaveComponent() {
  const [content, setContent] = createSignal("");
  const debouncedSave = useDebouncedCallback((text: string) => saveToServer(text), 1000);

  createEffect(() => {
    if (content()) {
      debouncedSave(content());
    }
  });

  return <textarea value={content()} onInput={e => setContent(e.target.value)} />;
}

useThrottle<T>(value, delay)

Throttled reactive values for performance optimization with leading/trailing edge control.

const throttledValue = useThrottle(value, delay);

Example:

function ScrollComponent() {
  const [scrollY, setScrollY] = createSignal(0);
  const throttledScrollY = useThrottle(scrollY, 100);

  createEffect(() => {
    const handleScroll = () => setScrollY(window.scrollY);
    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  });

  return <div>Scroll position: {throttledScrollY()}</div>;
}

useThrottledCallback<TArgs>(callback, delay)

Throttled function calls to prevent excessive execution with cancel and flush methods.

const throttledCallback = useThrottledCallback(callback, delay);

Example:

function SearchComponent() {
  const [query, setQuery] = createSignal("");
  const throttledSearch = useThrottledCallback((searchTerm: string) => {
    performSearch(searchTerm);
  }, 300);

  createEffect(() => {
    if (query()) {
      throttledSearch(query());
    }
  });

  return <input value={query()} onInput={e => setQuery(e.target.value)} />;
}

useClickOutside(options)

Detect clicks outside specified elements for dropdowns, modals, and popups.

const { isOutside, setTargetRef, targetRef } = useClickOutside(options);

Options:

  • enabled: Whether the click outside detection is enabled (default: true)
  • onOutsideClick: Callback when outside click is detected

Example:

function DropdownComponent() {
  const [isOpen, setIsOpen] = createSignal(false);
  const { setTargetRef } = useClickOutside({
    onOutsideClick: () => setIsOpen(false),
  });

  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen())}>Toggle Dropdown</button>
      {isOpen() && (
        <div ref={setTargetRef} class="dropdown">
          <p>Dropdown content</p>
        </div>
      )}
    </div>
  );
}

useIntersectionObserver(callback, options)

Reactive intersection observer for lazy loading, scroll-based animations, and visibility tracking.

const { isIntersecting, setTargetRef, targetRef } = useIntersectionObserver(callback, options);

Example:

function LazyImageComponent() {
  const [isVisible, setIsVisible] = createSignal(false);
  const { setTargetRef } = useIntersectionObserver(
    entries => {
      setIsVisible(entries[0].isIntersecting);
    },
    { threshold: 0.1 }
  );

  return (
    <div ref={setTargetRef}>
      {isVisible() ? <img src="lazy-image.jpg" alt="Lazy loaded image" /> : <div class="placeholder">Loading...</div>}
    </div>
  );
}

useAsync<T>(asyncFn, options)

Comprehensive async state management with loading, error, and retry logic.

const { data, isLoading, error, execute, reset, retry } = useAsync(asyncFn, options);

Options:

  • initialData: Initial data value
  • immediate: Execute immediately on mount (default: false)
  • retry: Retry configuration with count and delay
  • onSuccess: Success callback
  • onError: Error callback

Example:

function DataComponent() {
  const { data, isLoading, error, execute } = useAsync(
    async (id: string) => {
      const response = await fetch(`/api/users/${id}`);
      return response.json();
    },
    {
      retry: { count: 3, delay: 1000 },
      onError: err => console.error("Failed to fetch user:", err),
    }
  );

  const fetchUser = (id: string) => execute(id);

  return (
    <div>
      {isLoading() && <div>Loading...</div>}
      {error() && <div>Error: {error()?.message}</div>}
      {data() && <div>User: {data()?.name}</div>}
      <button onClick={() => fetchUser("123")}>Fetch User</button>
    </div>
  );
}

useEventListener<K>(eventName, handler, options)

Reactive event listener management with automatic cleanup.

const { isListening } = useEventListener(eventName, handler, options);

Options:

  • enabled: Whether the event listener is enabled (default: true)
  • passive: Use passive event listeners (default: false)
  • capture: Use capture phase (default: false)
  • once: Remove after first trigger (default: false)

Example:

function WindowResizeComponent() {
  const [windowSize, setWindowSize] = createSignal({ width: 0, height: 0 });

  const { isListening } = useEventListener("resize", () => {
    setWindowSize({
      width: window.innerWidth,
      height: window.innerHeight,
    });
  });

  return (
    <div>
      <p>Listening: {isListening() ? "Yes" : "No"}</p>
      <p>
        Size: {windowSize().width} x {windowSize().height}
      </p>
    </div>
  );
}

useViewportSize()

Reactive viewport dimensions tracking for responsive design.

const { width, height, size } = useViewportSize();

Example:

function ResponsiveComponent() {
  const { width, height, size } = useViewportSize();

  return (
    <div>
      <p>Width: {width()}</p>
      <p>Height: {height()}</p>
      <p>Size: {JSON.stringify(size())}</p>
    </div>
  );
}

useIdle(timeout)

User idle state detection with customizable timeout.

const { isIdle, idleTime, reset } = useIdle(timeout);

Example:

function IdleComponent() {
  const { isIdle, idleTime, reset } = useIdle(5000); // 5 seconds

  return (
    <div>
      <p>Status: {isIdle() ? "Idle" : "Active"}</p>
      <p>Idle time: {idleTime()}ms</p>
      <button onClick={reset}>Reset Timer</button>
    </div>
  );
}

useGeolocation(options)

Reactive geolocation API with position tracking and error handling.

const { position, error, isLoading, getCurrentPosition, watchPosition, stopWatching } = useGeolocation(options);

Options:

  • enabled: Whether geolocation is enabled (default: true)
  • watch: Watch position changes (default: false)
  • options: Position options (accuracy, timeout, etc.)
  • onPositionChange: Position change callback
  • onError: Error callback

Example:

function LocationComponent() {
  const { position, error, isLoading, getCurrentPosition } = useGeolocation({
    options: {
      enableHighAccuracy: true,
      timeout: 10000,
      maximumAge: 300000,
    },
  });

  return (
    <div>
      {isLoading() && <div>Getting location...</div>}
      {error() && <div>Error: {error()?.message}</div>}
      {position() && (
        <div>
          <p>Latitude: {position()?.latitude}</p>
          <p>Longitude: {position()?.longitude}</p>
        </div>
      )}
      <button onClick={getCurrentPosition}>Get Location</button>
    </div>
  );
}

useClipboard(options)

Reactive clipboard operations with read/write functionality.

const { clipboardText, isSupported, error, writeText, readText, copy } = useClipboard(options);

Options:

  • enabled: Whether clipboard tracking is enabled (default: true)
  • onClipboardChange: Callback when clipboard content changes

Example:

function ClipboardComponent() {
  const { clipboardText, isSupported, writeText, readText, copy } = useClipboard();

  const handleCopy = async () => {
    try {
      await copy("Hello, World!");
      console.log("Copied to clipboard");
    } catch (err) {
      console.error("Failed to copy:", err);
    }
  };

  const handleRead = async () => {
    try {
      await readText();
      console.log("Clipboard content:", clipboardText());
    } catch (err) {
      console.error("Failed to read clipboard:", err);
    }
  };

  return (
    <div>
      <p>Supported: {isSupported() ? "Yes" : "No"}</p>
      <p>Clipboard: {clipboardText()}</p>
      <button onClick={handleCopy}>Copy Text</button>
      <button onClick={handleRead}>Read Clipboard</button>
    </div>
  );
}

Security Functions

Input Validation

import { validateInput, validateEmail, validatePassword, validateURL, validatePhoneNumber } from "reynard-core";

// Comprehensive input validation
const result = validateInput("[email protected]", {
  type: "email",
  required: true,
  maxLength: 100,
});

// Email validation
const isValidEmail = validateEmail("[email protected]"); // true

// Password validation
const passwordStrength = validatePassword("MySecure123!", {
  minLength: 8,
  requireUppercase: true,
  requireLowercase: true,
  requireNumbers: true,
  requireSpecialChars: true,
});

// URL validation
const isValidUrl = validateURL("https://example.com"); // true

// Phone number validation
const isValidPhone = validatePhoneNumber("+1-555-123-4567"); // true

XSS Protection

import { sanitizeHTML, validateXSSInput, sanitizeXSSInput } from "reynard-core";

// HTML sanitization
const cleanHTML = sanitizeHTML('<script>alert("xss")</script><p>Safe content</p>');
// Returns: '<p>Safe content</p>'

// XSS validation
const xssResult = validateXSSInput('<img src="x" onerror="alert(1)">');
// Returns: { isValid: false, sanitized: '<img src="x">' }

// XSS sanitization
const sanitized = sanitizeXSSInput('<div onclick="alert(1)">Click me</div>');
// Returns: '<div>Click me</div>'

File Security

import { validateFileName, validateFileSize, validateMimeType, getSafeFilename } from "reynard-core";

// File name validation
const fileResult = validateFileName("document.pdf", {
  allowedExtensions: [".pdf", ".doc", ".docx"],
  maxLength: 100,
  allowHidden: false,
});

// File size validation
const sizeResult = validateFileSize(1024 * 1024, { maxSize: 10 * 1024 * 1024 }); // 1MB file, 10MB limit

// MIME type validation
const mimeResult = validateMimeType("application/pdf", {
  allowedTypes: ["application/pdf", "image/jpeg", "image/png"],
});

// Safe filename generation
const safeName = getSafeFilename("My Document (2024).pdf");
// Returns: "My_Document_2024_.pdf"

Cryptographic Utilities

import {
  generateSecurePassword,
  generateSecureString,
  generateSecureUUID,
  hashString,
  generateCSRFToken,
  validateCSRFToken,
} from "reynard-core";

// Secure password generation
const password = generateSecurePassword(16, {
  includeUppercase: true,
  includeLowercase: true,
  includeNumbers: true,
  includeSymbols: true,
});

// Secure string generation
const secureString = generateSecureString(32);

// UUID generation
const uuid = generateSecureUUID();

// String hashing
const hash = hashString("password", "sha256");

// CSRF token management
const csrfToken = generateCSRFToken();
const isValid = validateCSRFToken(csrfToken, "session-id");

Additional Utility Functions

import { validateEmail, validatePassword, sanitizeInput } from "reynard-core";

// Email validation
const isValidEmail = validateEmail("[email protected]"); // true

// Password validation
const passwordStrength = validatePassword("MySecure123!", {
  minLength: 8,
  requireUppercase: true,
  requireLowercase: true,
  requireNumbers: true,
  requireSpecialChars: true,
});

// Input sanitization
const cleanInput = sanitizeInput("<script>alert('xss')</script>"); // "alert('xss')"

Formatting Utilities

import { formatDate, formatNumber, formatCurrency } from "reynard-core";

// Date formatting
const formattedDate = formatDate(new Date(), "YYYY-MM-DD"); // "2024-01-15"
const relativeDate = formatDate(new Date(), "relative"); // "2 hours ago"

// Number formatting
const formattedNumber = formatNumber(1234.56, { decimals: 2 }); // "1,234.56"
const percentage = formatNumber(0.75, { style: "percent" }); // "75%"

// Currency formatting
const price = formatCurrency(99.99, "USD"); // "$99.99"
const euro = formatCurrency(89.5, "EUR"); // "€89.50"

Language Detection

import {
  detectLanguageFromExtension,
  detectLanguageFromContent,
  getLanguageInfo,
  getAllLanguages,
  getLanguagesByCategory,
} from "reynard-core";

// Detect language from file extension
const language = detectLanguageFromExtension("test.js"); // "javascript"

// Detect language from content
const contentLanguage = detectLanguageFromContent("def hello(): print('world')"); // "python"

// Get comprehensive language info
const info = getLanguageInfo("test.tsx");
// Returns: { monacoLanguage: "typescript", displayName: "TypeScript", isCode: true }

// Get all supported languages
const allLanguages = getAllLanguages();

// Get languages by category
const webLanguages = getLanguagesByCategory("web");
const programmingLanguages = getLanguagesByCategory("programming");

Async Utilities

import { batchExecute, mapWithConcurrency, retryWithBackoff, pollUntil, sleep, withTimeout, delay } from "reynard-core";

// Batch execution
const results = await batchExecute(
  [() => fetch("/api/users"), () => fetch("/api/posts"), () => fetch("/api/comments")],
  2
); // Process 2 at a time

// Concurrency control
const processedData = await mapWithConcurrency(
  items,
  async item => processItem(item),
  5 // Max 5 concurrent operations
);

// Retry with exponential backoff
const result = await retryWithBackoff(
  () => riskyOperation(),
  3, // Max 3 retries
  1000 // Base delay 1 second
);

// Polling
const data = await pollUntil(
  () => checkCondition(),
  1000, // Check every 1 second
  30000 // Timeout after 30 seconds
);

// Sleep utility
await sleep(1000); // Wait 1 second

// Timeout wrapper
const result = await withTimeout(
  fetch("/api/slow-endpoint"),
  5000, // 5 second timeout
  "Request timed out"
);

// Delay with value
const delayedValue = await delay("Hello", 1000); // Returns "Hello" after 1 second

Core Modules

import { createNotifications, NotificationsProvider } from "reynard-core";

// Create notifications module
const notificationsModule = createNotifications({
  maxNotifications: 5,
  defaultDuration: 5000,
  position: "top-right",
});

// Use in app
function App() {
  return (
    <NotificationsProvider value={notificationsModule}>
      <YourApp />
    </NotificationsProvider>
  );
}

🧪 Testing

Run the test suite:

pnpm test

🔧 Optional Dependencies

The core package is designed to work independently, but can be enhanced with optional packages:

  • reynard-i18n: Provides internationalization support with fallback to English strings
  • reynard-connection: Enhanced connection management (already included)

When optional dependencies are not available, the core package gracefully falls back to built-in functionality.

📦 Bundle Size

  • Core composables: ~15 kB (gzipped) - includes 13 composables
  • Security module: ~8 kB (gzipped)
  • HTTP clients: ~4 kB (gzipped)
  • Utility functions: ~12 kB (gzipped)
  • Language detection: ~3 kB (gzipped)
  • Async utilities: ~2 kB (gzipped)
  • Total: ~44 kB (gzipped)
  • With i18n: +~8 kB (gzipped)
  • With connection: +~5 kB (gzipped)

Modular Loading: The package supports tree-shaking, so you only include what you use. Individual modules can be imported separately:

// Import only what you need
import { useNotifications } from "reynard-core/composables";
import { validateInput } from "reynard-core/security";
import { formatDate } from "reynard-core/utils";

🎯 Feature Overview

Security-First Design

The core package prioritizes security with comprehensive validation, sanitization, and protection against common web vulnerabilities:

  • XSS Prevention: HTML sanitization and input validation
  • SQL Injection Protection: Parameterized query validation
  • File Upload Security: MIME type validation and filename sanitization
  • CSRF Protection: Token generation and validation
  • Cryptographic Utilities: Secure random generation and hashing

Performance Optimized

Built for performance with modern web standards:

  • Tree-shaking Support: Import only what you need
  • Lazy Loading: Dynamic module loading capabilities
  • Debounced Operations: Performance-optimized user interactions
  • Concurrent Processing: Batch operations and concurrency control
  • Memory Efficient: Minimal memory footprint

Developer Experience

Designed for excellent developer experience:

  • TypeScript First: Comprehensive type definitions
  • SolidJS Integration: Native reactive composables
  • Optional Dependencies: Graceful fallbacks when packages aren't available
  • Comprehensive Testing: 96+ tests covering all functionality with 100% pass rate
  • Clear Documentation: Extensive examples and API reference

Modular Architecture

Clean, modular design that scales:

  • Composables: Reusable reactive utilities
  • Security Module: Centralized security utilities
  • HTTP Clients: Unified API and HTTP client management
  • Utility Functions: Comprehensive utility library
  • Language Detection: File type and language detection
  • Async Utilities: Advanced async operation handling

🤝 Contributing

See the main Reynard repository for contribution guidelines.

Development Setup

# Clone the repository
git clone https://github.com/your-org/reynard.git
cd reynard/packages/core

# Install dependencies
pnpm install

# Run tests
pnpm test

# Build the package
pnpm build

# Run in development mode
pnpm dev

Built with ❤️ using SolidJS and modern web standards 🦊

The Reynard Core package provides the foundation for building secure, performant, and maintainable web applications with the cunning agility of a fox.