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

@villagehq/widget-sdk

v0.0.9

Published

A type‑safe, embeddable JavaScript widget for Village integrations, including a built‑in events SDK.

Readme

📦 Village Widget

A type‑safe, embeddable JavaScript widget for Village integrations, including a built‑in events SDK.


Table of Contents

  1. Installation
  2. Quick Start
  3. Authentication
  4. Usage
  5. Module Usage (ES6)
  6. Development
  7. API Reference
  8. Available Events

Installation

NPM/Yarn

npm install @villagehq/widget-sdk
# or
yarn add @villagehq/widget-sdk

CDN (Script Tag)

<script src="https://unpkg.com/@villagehq/widget-sdk/dist/village-widget.js"></script>

ES6 Module

import Village from '@villagehq/widget-sdk';

Quick Start

// Initialize the SDK
Village.init('YOUR_PARTNER_KEY');

// Authenticate with token
const authResult = await Village.authorize('your-auth-token', 'yourdomain.com');
if (authResult.ok) {
  console.log('Authenticated successfully!');
}

Authentication

Token-based Authentication

For applications with existing authentication systems:

// Basic token authentication
const result = await Village.authorize(authToken, 'yourdomain.com');

// With automatic token refresh
const result = await Village.authorize(
  authToken, 
  'yourdomain.com',
  async () => {
    // Your token refresh logic
    const newToken = await refreshAuthToken();
    return newToken;
  }
);

User Reference Authentication

For backwards compatibility with the identify system:

// Identify user with reference ID
await Village.authorize('user-123', { 
  email: '[email protected]',
  name: 'John Doe' 
});

// Or use the legacy identify method
await Village.identify('user-123', {
  email: '[email protected]',
  name: 'John Doe'
});

Browser Extension Support

The SDK is fully CSP-compliant for Chrome and Firefox extensions:

// manifest.json (Chrome Extension Manifest V3)
{
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'"
  },
  "host_permissions": ["https://yourdomain.com/*"]
}

// In your extension popup or content script
import Village from '@villagehq/widget-sdk';

Village.init('YOUR_PARTNER_KEY');
const result = await Village.authorize(token, 'yourdomain.com');

Usage

Initializing the SDK

// Basic initialization
Village.init('YOUR_PARTNER_KEY');

// With configuration
Village.init('YOUR_PARTNER_KEY', {
  paths_cta: [],  // Custom CTAs (see below)
  // other config options
});

Custom CTAs

// external callback function
function alertUser() {
  alert('This alert comes from an external callback!');
}

Village.init('YOUR_PUBLIC_KEY', {
  paths_cta: [
    {
      label: 'Save to CRM',
      // inline callback function
      callback() {
        // your save logic here
        alert('Record saved to CRM!');
      },
      // simple style example
      style: {
        backgroundColor: '#007bff',
        color: '#fff'
      }
    },
    {
      label: 'Alert me',
      callback: alertUser,
      style: {
        backgroundColor: '#dc3545',
        color: '#fff'
      }
    }
  ]
});

Listening to Events

// Listen for widget ready
Village.on('village.widget.ready', (data) => {
  console.log('Widget is ready!', data);
});

// Listen for CTA clicks
Village.on('village.path.cta.clicked', ({ index, cta, context }) => {
  console.log('CTA clicked:', cta.label, context);
});

// Listen for OAuth success
Village.on('village.oauth.success', ({ token }) => {
  console.log('OAuth successful, token received');
});

// Listen for paths CTA updates
Village.on('village.paths_cta.updated', (updatedCTAs) => {
  console.log('CTAs updated:', updatedCTAs);
});

Module Usage (ES6)

For modern JavaScript applications and bundlers:

// Import the module
import Village from '@villagehq/widget-sdk';

// Initialize
Village.init('YOUR_PARTNER_KEY');

// Use async/await for authentication
async function authenticate() {
  try {
    const result = await Village.authorize(token, 'yourdomain.com');
    if (result.ok) {
      console.log('Authentication successful!');
    } else {
      console.error('Authentication failed:', result.reason);
    }
  } catch (error) {
    console.error('Error during authentication:', error);
  }
}

// Dynamic CTA management
Village.updatePathsCTA([
  { label: 'Action 1', callback: () => console.log('Action 1') },
  { label: 'Action 2', callback: () => console.log('Action 2') }
]);

// Add single CTA on the fly
Village.addPathCTA({
  label: 'New Action',
  callback: (payload) => {
    console.log('New action clicked', payload);
  }
});

Development

npm install
npm run dev             # Watch mode (builds to development folder)
npm run build           # Production build
npm run build:staging   # Staging build
npm run lint            # ESLint
npm run format          # Prettier
npm run test            # Vitest
npm run check:bundle    # Build + JS syntax check

API Reference

Core Methods

Village.init(partnerKey, config?)

Initialize the Village SDK with your partner key.

Parameters:

  • partnerKey (string, required): Your Village partner key
  • config (object, optional): Configuration options
    • paths_cta: Array of CTA objects

Returns: Village instance


Village.authorize(token, domain, refreshCallback?)

Authenticate a user with token or user reference.

Parameters:

  • token (string): Auth token
  • domain (string): Domain for token auth
  • refreshCallback (function, optional): Async function to refresh token when expired

Returns: Promise

{
  ok: boolean,
  status: 'authorized' | 'unauthorized',
  domain?: string,
  reason?: string
}

Village.identify(userReference, details?)

Legacy method for user identification (backwards compatibility).

Parameters:

  • userReference (string): Unique user identifier
  • details (object, optional): User details (email, name, etc.)

Returns: Promise


Village.logout()

Log out the current user and clear authentication.


Village.on(event, callback)

Subscribe to Village events.

Parameters:

  • event (string): Event name
  • callback (function): Event handler

Village.emit(event, data)

Emit custom events.

Parameters:

  • event (string): Event name
  • data (any): Event data

Village.updatePathsCTA(ctaList)

Replace the entire CTA list.

Parameters:

  • ctaList (array): Array of CTA objects

Village.addPathCTA(cta)

Add a single CTA to the existing list.

Parameters:

  • cta (object): CTA object with label and callback

Available Events

| Event | Description | Payload | |-----------------------------|------------------------------------------------|------------------------------| | village.widget.ready | Widget has initialized | void | | village.path.cta.clicked | User clicked a configured CTA | { index, cta, context } | | village.paths_cta.updated | CTA list was dynamically updated | PathCTA[] | | village.user.synced | User graph sync completed | { userId, syncedAt } | | village.oauth.success | OAuth flow succeeded with token | { token } | | village.oauth.error | OAuth flow failed | { error } | | village.widget.error | Internal widget error | { message, source, details } |