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

@vicaniddouglas/js_aide

v1.13.0

Published

A versatile collection of modular JavaScript utility helpers designed to streamline single-page application (SPA) development and general web programming tasks.

Readme

@vicaniddouglas/js_aide

A versatile collection of modular JavaScript utility helpers designed to streamline single-page application (SPA) development and general web programming tasks. This library provides a set of independent modules for common functionalities such as routing, input handling, validation, and more.

Description

@vicaniddouglas/js_aide bundles frequently needed JavaScript functionalities into a cohesive, easy-to-use package. Each module is designed to be independent, allowing you to import only what you need, reducing bundle size and improving application performance. From dynamic client-side routing to robust input validation and DOM manipulation, this library aims to accelerate your development workflow.

Features

🎮 Live Playground

Explore all library features—including the new Asynchronous Handshaking system—directly in our interactive sandbox.

Access via Repository:

  1. Clone the repository: git clone https://gitlab.com/vicaniddouglas/js_aide.git
  2. Open demo/index.html in any modern browser.

Access via NPM: If you have the package installed locally, you can run the playground using:

npm explore @vicaniddouglas/js_aide -- npm run serve:demo

Router

A modern, feature-rich client-side router for Single-Page Applications (SPAs).

  • History API-based navigation.
  • Supports dynamic route segments (e.g., /users/:id).
  • Automatic interception of internal <a> tags for seamless SPA navigation.
  • Configurable route guards (beforeNavigate) with support for redirects.
  • View lifecycle hooks (beforeEnter, beforeLeave) directly on DOM elements for managing view transitions and data loading.
  • Parses and exposes URL query parameters and hash fragments.
  • Efficient view toggling, only hiding the previously active view.

validator

A module offering various input validation utilities (e.g., email, number, custom regex).

inputHandlers

Utilities for enhanced DOM element interaction, such as restricting input to numbers, formatting number inputs, or providing custom select options.

requests

Helper functions for making HTTP requests (e.g., fetch wrappers for common patterns).

dates

Convenience functions for common date and time manipulation tasks.

fileManager

Utilities for browser-side file handling (e.g., file uploads, local storage, file type checks).

camera

Functions for interacting with device cameras, capturing images or video streams (requires browser API support).

figures

Utilities for number formatting, currency (including UGX defaults), and percentages.

dependencyManager

A robust manager for dynamically loading CDN-based libraries (like SheetJS or jsPDF) with retry logic and dependency tracking.

WebSocketClient

A professional-grade WebSocket client featuring automatic reconnection, heartbeat/health monitoring, and a built-in instance registry to prevent duplicate connections. Supports namespaces, rooms, and message acknowledgements.

Installation

Install the package via npm:

npm install @vicaniddouglas/js_aide

Or via yarn:

yarn add @vicaniddouglas/js_aide

Usage

Ensure your project is configured to use ES Modules (e.g., by adding "type": "module" to your project's package.json or using a bundler).

Importing Modules

You can import specific modules or all of them:

// Import specific modules
import { Router, validator } from "@vicaniddouglas/js_aide";

// Or import all, though generally not recommended for tree-shaking
// import * => JSAide from '@vicaniddouglas/js_aide';

Example: Using the Router

// main.js
import { Router } from "@vicaniddouglas/js_aide";

// Define your routes, mapping paths to DOM element IDs
const appRoutes = {
  "/": "home-view",
  "/products": "products-list-view",
  "/products/:id": "product-detail-view", // Dynamic segment
  "/profile": "user-profile-view",
};

const router = new Router(appRoutes, "/");

// --- Optional: Add a route guard ---
router.beforeNavigate = async (toPath, navigationContext) => {
  console.log(
    `Attempting to navigate from ${navigationContext.from} to ${toPath}`,
  );

  // Example: Protect the profile route
  if (toPath.startsWith("/profile")) {
    const isAuthenticated = await checkUserAuthentication(); // Your auth logic
    if (!isAuthenticated) {
      console.warn(
        "Access denied: User not authenticated. Redirecting to login.",
      );
      return "/login"; // Redirect to a login page
    }
  }
  return true; // Allow navigation
};

// --- Optional: Listen for navigation events ---
window.addEventListener("router:navigated", (event) => {
  const { path, pathname, params, query, hash } = event.detail;
  console.log(`Navigated to: ${path}`);
  console.log("Params:", params); // e.g., { id: '123' } for /products/123
  console.log("Query:", query); // e.g., { search: 'item' } for /search?search=item
  console.log("Hash:", hash); // e.g., '#section1' for /page#section1
});

// --- Example: Define view lifecycle hooks on your DOM elements ---
// Assuming you have a <div id="product-detail-view"> in your HTML
const productDetailView = document.getElementById("product-detail-view");
if (productDetailView) {
  productDetailView.beforeEnter = async (routeParams) => {
    console.log(`Entering product detail view for ID: ${routeParams.id}`);
    // Fetch product data based on routeParams.id
    const product = await fetchProductData(routeParams.id);
    // Render product details into the view
    renderProductDetails(productDetailView, product);
  };

  productDetailView.beforeLeave = () => {
    console.log("Leaving product detail view. Cleaning up...");
    // Dispose of any event listeners or resources specific to this view
    cleanupProductDetailResources();
  };
}

// Manually navigate (or click an <a> tag)
router.navigate("/products/123?utm_source=email#overview");

Example: Using the WebSocket Client

The WebSocketClient is designed to be "Zero-Touch," handling connection lifecycles and resource management automatically.

import { WebSocketClient, ConnectionEvent } from "@vicaniddouglas/js_aide";

// The constructor automatically reuses instances for the same URL (Registry Pattern)
const ws = new WebSocketClient("ws://localhost:8000");

// Listen for connection events
ws.on("open", () => {
    console.log("Connected to server!");
});

// Register a handler for a specific event
ws.onMessage("user_update", (data) => {
    console.log("Profile updated:", data);
});

ws.connect();

ws.send(event, data) vs ws.sendWithAck(event, data)

  1. ws.send(): A "fire and forget" method. It sends the data and returns immediately. Use this for non-critical updates like typing indicators.
  2. ws.sendWithAck(): Returns a Promise that resolves when the server confirms receipt. Use this for critical actions like saving a profile or processing a payment.
// Critical action with Acknowledgement
try {
    const response = await ws.sendWithAck("save_profile", { bio: "Hello world" });
    console.log("Profile saved successfully:", response);
} catch (error) {
    console.error("Failed to save profile (timed out):", error.message);
}

The Backend Contract (Implementing Acknowledgements)

To support sendWithAck(), your backend (e.g., Python/FastAPI, Node.js, Go) must follow the @vicaniddouglas framework standard:

  1. The client sends a message containing an id and ack: true.
  2. The server must respond with a message containing:
    • event: "ack"
    • id: The exact same ID sent by the client.
    • success: true or false.
    • data (optional): Any response data to return to the client.

Example Server Response (JSON):

{
  "event": "ack",
  "id": "1712065432123-0",
  "success": true,
  "data": { "status": "saved" }
}

Example: Using the Requests Module

The sendRequest function is a proactive HTTP client that standardizes all responses into a single dictionary format. It automatically handles error popups and callbacks, eliminating the need for try-catch blocks.

Standardized Response

Every call returns a Promise that always resolves to this structure:

{
  status: boolean, // true if Success, false if Error (Network or Business)
  log: string,    // Error message on failure, or "" on success
  data: any,       // The actual payload from the server
  httpCode: number // The raw HTTP status code
}

New Proactive Options

| Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | onSuccess | Function | null | Runs automatically if status is true. Strictly awaited. | | onError | Function | null | Runs automatically if status is false. Strictly awaited. | | showLoading | Function | null | Called with true/false. Strictly awaited. | | silent | Boolean | false | If true, disables the automatic Red Popup on error. |

Usage Patterns

1. The "Sequential Async Flow" (Awaiting Callbacks) Because sendRequest strictly awaits your callbacks, you can safely use async/await inside them without worrying about race conditions or premature page reloads.

import { sendRequest, popup } from "@vicaniddouglas/js_aide";

await sendRequest({
  endpoint: '/api/save',
  onSuccess: async (data) => {
    // This popup is BEAUTIFUL and BLOCKING.
    // sendRequest will NOT finish until the user clicks OK.
    await popup.success("Settings Saved!"); 
  }
});

// This reload is GUARANTEED to happen only after the popup is closed.
window.location.reload(); 

2. The "Fire and Forget" (Proactive Success) No need to check status if you only care about success. If it fails, the user gets a popup automatically.

import { sendRequest } from "@vicaniddouglas/js_aide";

sendRequest({
  endpoint: '/api/settings',
  onSuccess: (data) => console.log("Profile updated!", data)
});

2. The "Sequential Chain" (Linear Await) Since the promise never rejects, you can write linear logic without try-catch.

const res = await sendRequest({ endpoint: '/profile' });

if (res.status) {
   // Since status is true, we know data is safe to use
   const stats = await sendRequest({ endpoint: `/stats/${res.data.id}` });
   if (stats.status) render(stats.data);
}

3. Silent Background Tasks Use silent: true for background checks where a popup would be annoying.

sendRequest({
  endpoint: '/api/poll-notifications',
  silent: true,
  onSuccess: (count) => updateBadge(count)
});

Example: Using the Popup System

The popup module provides a Promise-based modal system for showing professional alerts. It is fully accessible (supports the Escape key) and highly customizable.

import { popup, icons } from "@vicaniddouglas/js_aide";

// Basic success alert (auto-closes in 2.5s)
await popup.success("Profile saved!");

Configuration Reference

Every popup method (.success(), .error(), .info()) accepts an optional options object as the second argument.

| Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | duration | Number | 2500ms - 4000ms | Time before the modal closes automatically. | | persistent| Boolean| false | If true, the modal will stay on screen until manually closed. | | closable | Boolean| true | If false, hides the close button and disables Esc/backdrop clicks. | | icon | String | Theme default | A custom SVG string to override the default icon. | | color | String | Theme default | A custom hex or CSS color for the icon and background tint. |

Common Usage Patterns

1. Sticky Info (Requires Acknowledgment)

await popup.info("Maintenance scheduled for midnight.", { persistent: true });

2. Process Lock (Interaction Block) Use this to prevent users from navigating away during critical operations.

// Shows a modal with no close buttons
popup.info("Deleting account data...", { persistent: true, closable: false });

await api.deleteAccount();
popup.close(); // Programmatically remove the modal
await popup.success("Account deleted.");

3. Custom Branding Override the icon and color to match specific visual needs.

popup.success("Photo Uploaded!", { 
  icon: icons.cameraIcon(),
  color: "#3b82f6" 
});

4. Asynchronous Handshaking (Zero-Alert)

The popup system provides replacements for native confirm() and prompt() that are fully asynchronous, themeable, and non-blocking in the developer's logic (via await).

Confirmation Dialogs Returns true on confirm, false on cancel/close.

const confirmed = await popup.confirm("Are you sure you want to delete this?");

if (confirmed) {
  await deleteRecord();
  await popup.success("Deleted!");
}

Data-Entry Prompts Returns the input value as a string on submit, or null if cancelled.

const name = await popup.prompt("Enter your display name:", {
  placeholder: "e.g., Douglas",
  inputType: "text" // Options: text, number, currency, password
});

if (name) {
  console.log("Hello", name);
}

| Prompt Option | Description | | :--- | :--- | | inputType | Controls input behavior (text, number, currency, password). | | defaultValue| Initial text inside the input. | | submitText | Text for the action button (default: "Submit"). | | cancelText | Text for the dismiss button (default: "Cancel"). |

Development

Running Tests

We use Vitest for unit testing. The library has over 80+ verified tests covering all core modules (Routing, Validation, WebSocket, Dates, etc.).

npm test

Building for Production

Generates minified ESM, IIFE, and CJS bundles in the dist folder using esbuild.

npm run build

License

This project is licensed under the MIT License.