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 🙏

© 2025 – Pkg Stats / Ryan Hefner

neverbroken

v3.2.0

Published

Semantic DOM selector library with built-in fallbacks. Use meaningful names instead of fragile CSS selectors!

Readme

neverbroken

Semantic DOM selector library with built-in fallbacks. Use meaningful names instead of fragile CSS selectors - works instantly!

Installation

npm install neverbroken

Quick Start

// Multiple import styles - works instantly, no setup required!

// Option 1: Class-based (purist-friendly)
import NeverBroken from 'neverbroken';
const nb = NeverBroken.create();

// Option 2: Short instance (pragmatic)
import { nb } from 'neverbroken';

// Option 3: Factory function
import { createNeverBroken } from 'neverbroken';
const nb = createNeverBroken();

// Option 4: Document augmentation (optional)
import 'neverbroken/augment';
// Ready to use immediately!

// Use semantic selectors that work instantly
const submitButton = nb.submitButton();  // Note: call as function
const userAvatar = nb.user.avatar();
const loginForm = nb.forms.login();

Two Main Use Cases

🎯 Script Injection (Primary Purpose)

For automating external websites by injecting scripts:

// Injected into target website
const nb = NeverBroken.create({ debug: true });
const loginButton = nb.submitButton();  // Finds login button on target site
loginButton.click();                    // Automate the external site

🏠 Self-DOM Usage (Your Own App)

For testing or automating your own application:

// In your own Svelte/React/Vue app
const nb = NeverBroken.create({ debug: true });

// Scan your DOM to discover available selectors
const available = nb.scan();
console.table(available);  // Shows what NeverBroken can find

// Add custom mappings for your components
nb.addComponentMapping('myButton', '.my-custom-btn-class');
nb.addComponentMapping('userCard', '[data-testid="user-card"]');

// Now use your custom semantic names
const button = nb.myButton();
const card = nb.userCard();

API Reference

Import Styles (Pick Your Preference)

// 🎓 JavaScript Purist Style
import NeverBroken from 'neverbroken';
const nb = new NeverBroken();
// or
const nb = NeverBroken.create();

// 🚀 Pragmatic Style
import { nb, createNeverBroken } from 'neverbroken';
const selector = createNeverBroken();

// 📖 Document Augmentation Style
import 'neverbroken/augment';
const button = document.nb.submitButton;
// or
const button = document.neverbroken.submitButton;
const element = document.nbQuerySelector('userAvatar');

// 🔗 Legacy Compatibility
import { neverbroken } from 'neverbroken';
// Ready to use immediately!

Multiple Syntax Options

// Using any instance (nb, selector, document.nb, etc.):

// Option 1: Familiar DOM API (easy migration)
const avatar = nb.querySelector('userAvatar');
const buttons = nb.querySelectorAll('submitButton');

// Option 2: Clean semantic properties
const avatar = nb.userAvatar;
const submitBtn = nb.submitButton;

// Option 3: Nested semantic organization  
const avatar = nb.user.avatar;
const submitBtn = nb.form.submitButton;
const closeBtn = nb.modal.closeButton;

// Option 4: Fluent/chainable API
const modal = nb.find('modalDialog')
  .waitFor(1000)
  .withAttribute('open')
  .first();

Configuration

// Optional configuration (works instantly without any config!)
nb.configure({
  fallbackStrategy: 'graceful',   // 'graceful' or 'strict'
  cacheTimeout: 5000,             // Cache timeout in ms
  debug: true                     // Enable debug logging
});

// Or configure during creation
const nb = NeverBroken.create({
  debug: process.env.NODE_ENV === 'development',
  fallbackStrategy: 'graceful'
});

Convenience Methods

// Direct element interaction (works with any instance)
nb.submitButton.click();
nb.searchInput.focus();
nb.emailInput.value('[email protected]');

// Async resolution for dynamic content
const element = await nb.userAvatar.async();

// Document augmentation style (both work)
document.nb.submitButton.click();
document.neverbroken.submitButton.click();
const modal = await document.nbFind('modal').first();

TypeScript Support

// Extend with your app-specific selectors
declare module 'neverbroken' {
  interface NeverBrokenSelectors {
    myCustomButton: ElementGetter<HTMLButtonElement>;
    myApp: {
      header: ElementGetter<HTMLElement>;
      sidebar: ElementGetter<HTMLElement>;
    };
  }
}

// Full type safety and autocomplete
const button: HTMLButtonElement = nb.myCustomButton;
const header: HTMLElement = nb.myApp.header;

How It Works

  1. Semantic Mapping - Use meaningful names instead of fragile CSS selectors
  2. Built-in Fallbacks - Smart built-in mapping for common UI elements
  3. Smart Caching - Intelligent caching with TTL for optimal performance
  4. Instant Use - Works immediately without any configuration or API keys
  5. Extensible - Add your own semantic mappings for custom elements

Common Semantic Selectors

Forms

  • submitButton, cancelButton, closeButton
  • emailInput, passwordInput, searchInput
  • loginForm, registerForm, contactForm

Navigation

  • navigationMenu, headerLogo, userMenu, cartIcon
  • breadcrumbs, searchInput

Content

  • mainContent, sidebar, footer
  • modal, modalContent, modalOverlay

User Elements

  • userAvatar, userName, userProfile, userSettings

Advanced Features

Built-in Semantic Mappings

NeverBroken includes smart built-in mappings for common UI patterns:

// These work instantly out of the box
const button = nb.submitButton;        // → button[type="submit"]
const input = nb.emailInput;          // → input[type="email"]
const avatar = nb.userAvatar;         // → .avatar, .user-avatar, .profile-picture

Self-DOM Utilities

Perfect for testing and automating your own applications:

Scan Your DOM

// Discover available selectors in your app
const available = nb.scan({
  includeClasses: true,
  includeIds: true,
  includeDataAttributes: true,
  maxResults: 20
});

console.table(available);
// Shows: type, selector, suggested semantic name, element, text

Custom Component Mappings

// Add mappings for your specific components
nb.addComponentMapping('myButton', '.my-custom-button-class');
nb.addComponentMapping('userCard', '[data-testid="user-card"]');
nb.addComponentMapping('navMenu', '#navigation-menu');

// Batch add multiple mappings
nb.addComponentMappings({
  'submitBtn': '.submit-button',
  'cancelBtn': '.cancel-button', 
  'userProfile': '[data-user-profile]'
});

// Now use your semantic names
const button = nb.myButton();
const card = nb.userCard();

Smart Error Messages

When NeverBroken can't find elements in self-DOM usage, it provides helpful suggestions:

// Enable debug mode for helpful error messages
const nb = NeverBroken.create({ debug: true });

// If this fails, you'll get suggestions
const missing = nb.nonExistentButton();

// Console output:
// [NeverBroken] Self-DOM Warning: Could not find element for 'nonExistentButton'
// [NeverBroken] Suggestions for self-DOM usage:
// 1. Add custom mapping: nb.addComponentMapping('nonExistentButton', 'your-selector')
// 2. Scan your DOM: nb.scan() to discover available selectors
// 3. Use data attributes: <div data-automation="nonExistentButton">...</div>
// 4. Similar selectors found: ['.existing-button', '#submit-btn']

Fallback Strategies

nb.configure({
  fallbackStrategy: 'graceful' // Uses semantic name as CSS selector if no mapping found
  // fallbackStrategy: 'strict'  // Throws error if no mapping found
});

Examples

E-commerce Site

const addToCart = nb.product.addToCartButton;
const priceDisplay = nb.product.price;
const cartCounter = nb.navigation.cartCounter;

Form Handling

const email = nb.forms.login.emailInput;
const password = nb.forms.login.passwordInput;
const submit = nb.forms.login.submitButton;

submit.click();

Modal Interactions

const confirmDialog = nb.modal;
const confirmBtn = nb.modal.confirmButton;
const cancelBtn = nb.modal.cancelButton;

Migration from Standard DOM Selectors

// Before
const button = document.querySelector('.btn-primary.submit-form');
const inputs = document.querySelectorAll('input[type="text"]');

// After (any style works)  
const button = nb.submitButton;
const inputs = nb.textInputs;

// Or with document augmentation (both work)
const button = document.nb.submitButton;
const button = document.neverbroken.submitButton;
const inputs = document.nb.textInputs;

Why These Import Styles?

We provide multiple import patterns to respect different JavaScript philosophies:

🎓 Purist-Friendly (NeverBroken class)

  • ✅ Follows PascalCase class conventions
  • ✅ Clear factory pattern with .create()
  • ✅ No global pollution
  • ✅ Explicit instantiation

🚀 Pragmatic ({ nb } instance)

  • ✅ Short, easy to type
  • ✅ Ready to use immediately
  • ✅ No ceremony, just results
  • ✅ Similar to jQuery $

📖 Document Augmentation (opt-in)

  • ✅ Familiar document.* pattern
  • ✅ Non-invasive (requires explicit import)
  • ✅ Both document.nb and document.neverbroken available
  • ✅ Zero naming conflicts
  • ✅ Works with existing codebases

🔗 Legacy Compatibility (neverbroken)

  • ✅ Maintains backward compatibility
  • ✅ Smooth migration path
  • ✅ No breaking changes

License

Proprietary - See LICENSE.txt for full terms