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

aetherisyl

v0.2.0

Published

Aetherisyl browser SDK

Readme

Aetherisyl browser SDK

The official browser SDK for embedding an Aetherisyl verification widget.

Aetherisyl issues a short-lived, single-use token after the user completes the configured verification flow. Your application must send that token to its own backend, which then consumes it through the Aetherisyl API before allowing the protected operation.

Installation

pnpm add aetherisyl

The package is a modern ESM package with bundled TypeScript declarations and no runtime dependencies.

Browser integration

Add a mount point to the page:

<div id="aetherisyl-verification"></div>

Create one client for the environment and render a widget for each verification point:

import { createAetherisyl } from "aetherisyl";

const mountPoint = document.querySelector<HTMLElement>(
  "#aetherisyl-verification",
);

if (!mountPoint) {
  throw new Error("Aetherisyl mount point is missing.");
}

const client = createAetherisyl({
  apiBaseUrl: "https://api.example.com",
  widgetBaseUrl: "https://widget.example.com",
  debug: false,
});

const widget = client.render(mountPoint, {
  verificationPointId: "vp_...",
  async onSuccess(token) {
    // Send the token to your own backend with the protected business request.
    const response = await fetch("/api/register", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ token }),
    });

    if (!response.ok) {
      widget.reset();
    }
  },
  onExpired() {
    // The token can no longer be consumed. Ask the user to verify again.
    widget.reset();
  },
  onError(error) {
    console.error("Aetherisyl verification failed", error.code);
  },
});

onSuccess means that the browser challenge completed. It does not authorize the business operation by itself. Never trust a token without consuming it from your backend.

For an SPA, keep the returned widget handle and call destroy() when the component unmounts:

widget.destroy();

Server-side token consumption

Keep the verification-point secret on your backend. Never include an avs_... secret in browser code or public configuration.

Your backend must consume the token before completing the protected operation:

POST /v1/verifications/consume
Authorization: Bearer avs_...
Content-Type: application/json

{
  "token": "avt_...",
  "verificationPointId": "vp_...",
  "idempotencyKey": "your-stable-business-request-id"
}

Proceed only when the API returns a successful HTTP response with "success": true.

The idempotency key must be generated by your backend and remain stable across retries of the same business operation. Invalid, expired, already-consumed, or scope-mismatched tokens, as well as all other 4xx responses, must reject the operation. Only network failures, timeouts, and 5xx responses may use a deliberately configured fail-open policy.

API

createAetherisyl(options)

Creates a client and starts collecting privacy-reduced browser signals.

interface AetherisylOptions {
  apiBaseUrl: string;
  widgetBaseUrl: string;
  debug?: boolean;
}

Service URLs must be absolute HTTPS URLs. HTTP is accepted only for localhost, 127.0.0.1, and [::1] during local development.

client.render(element, options)

Mounts an isolated widget iframe into element.

interface RenderOptions {
  verificationPointId: string;
  evaluationBatchToken?: string;
  onSuccess(token: string): void;
  onExpired?(): void;
  onError?(error: AetherisylError): void;
}

verificationPointId belongs to each widget instance, not to the global client. Multiple independent widgets can be rendered on the same page.

evaluationBatchToken is reserved for Aetherisyl evaluation tooling. Normal production integrations should omit it.

Widget handle

interface AetherisylWidget {
  getToken(): string | null;
  reset(): void;
  destroy(): void;
}
  • getToken() returns the current unexpired token, or null.
  • reset() discards the current token and starts a new verification session.
  • destroy() closes the message channel and removes the widget iframe.

The SDK does not create hidden form fields or submit forms automatically.

Errors

onError receives an AetherisylError with a stable machine-readable code and a human-readable message. Configuration errors are thrown synchronously with the code invalid_configuration.

Content Security Policy

Allow the configured widget origin in frame-src. The SDK does not require blob:, unsafe-eval, or a cross-origin Worker:

Content-Security-Policy: default-src 'self'; script-src 'self'; frame-src https://widget.example.com; connect-src 'self'

All Aetherisyl network requests are made by the cross-origin widget. The host page SDK handles collection, mounting, and authenticated message passing.

Browser support

Aetherisyl targets the current and previous major versions of Chrome, Edge, Firefox, and Safari, including their corresponding iOS and Android browsers.

License

Apache-2.0