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

@basetime/a2w-webview-ts

v0.2.4

Published

SDK for webview apps running inside the Addtowallet scanner.

Readme

a2w-webview-ts

SDK for webview apps running inside the Addtowallet scanner.

See the standard example in examples/standard. See the SPA example in examples/spa.

Installation

npm install @basetime/a2w-webview-ts

Usage

import { WebApp } from '@basetime/a2w-webview-ts';

const webApp = new WebApp();

// Check if the app is embedded in the atw scanner webview.
if (!webApp.isEmbedded) {
  throw new Error('This app is not embedded in the atw scanner webview.');
}

// Listen for scan events from the scanner.
webApp.on('scan', ({ payload }) => {
  console.log(payload);

  const isApple = payload.device.model.toLowerCase().includes('iphone');
  console.log(`Using ${isApple ? 'iPhone' : 'Android'}`);

  // Check the password if one as set in the Addtowallet app.
  if (payload.password !== '123434) {
    throw new Error('Invalid password.');
  }

  // Notify the scanner that the webview is ready. (Not currently used.)
  webApp.send('ready');

  // Wait 5 seconds before navigating to the standby screen.
  setTimeout(() => {
    webApp.send('navigate', { url: '/' });
  }, 5000);
});

// Triggered when the scanner is on the home screen.
webApp.on('standby', ({ payload }) => {
  console.log(payload);
  console.log('The scanner is in standby mode.');

  // Override these settings in the scanner app.
  // They remain overridden until the `force` flag is
  // used by the backend.
  webApp.send('settings', {
    pin: '1234',
    webviewStandbyUrl: 'https://example.com/standby',
  });
});

// Triggered when an error is encountered in the scanner. For example,
webApp.on('error', ({ payload }) => {
  console.log(payload.errorCode);
  console.log(payload.errorMessage);
});

Alternatively, you import the WebApp class directly from the CDN:

<script type="module">
  import WebApp from 'https://cdn.addtowallet.io/js/webview/v0.2.3/WebApp.js';

  const webApp = new WebApp();

  // Listen for scan events from the scanner.
  webApp.on('scan', ({ payload }) => {
    console.log(payload);
  });

  // Listen for standby events from the scanner.
  webApp.on('standby', ({ payload }) => {
    console.log('The scanner is in standby mode.');
  });

  // Listen for error events from the scanner.
  webApp.on('error', ({ payload }) => {
    console.log('There has been an error.');
  });
</script>

React

If your embedded app is built with React, the SDK ships a small set of hooks under the optional /react subpath. React is declared as an optional peer dependency, so non-React consumers don't pay any bundle cost and don't need to install it.

npm install @basetime/a2w-webview-ts react
import { useEvent, useWebApp } from '@basetime/a2w-webview-ts/react';

export function ScanScreen() {
  useEvent('scan', ({ payload }) => {
    if (!payload.found) {
      return;
    }
    console.log('Scanned pass:', payload.pass);
  });

  useEvent('standby', () => {
    console.log('Scanner is idle');
  });

  // `useWebApp` is only needed if you want to call `send`, check
  // `isEmbedded`, or otherwise access the instance directly.
  const webApp = useWebApp();
  if (!webApp.isEmbedded) {
    return <p>Open this app inside the atw scanner.</p>;
  }

  return <p>Waiting for a scan…</p>;
}

Using the wildcard listener, we can listen to all events and navigate to the appropriate screen based on the event.

import React, { useState } from 'react';
import { useEvent, useWebApp } from '@basetime/a2w-webview-ts/react';
import { ScanScreen, StandbyScreen, ErrorScreen } from './screens';

export function App() {
  const [page, setPage] = useState<'scan' | 'standby' | 'error'>('scan');

  useEvent('*', ({ action, payload }) => {
    if (action === 'scan') {
      setPage('scan');
    } else if (action === 'standby') {
      setPage('standby');
    } else if (action === 'error') {
      setPage('error');
    }
  });

  if (page === 'scan') {
    return <ScanScreen />;
  } else if (page === 'standby') {
    return <StandbyScreen />;
  } else if (page === 'error') {
    return <ErrorScreen />;
  }

  return <p>Waiting for a scan…</p>;
}

Available hooks:

  • useEvent(event, callback) subscribes to an event for the lifetime of the component. The callback is captured in a ref, so passing an inline arrow function does not cause the listener to re-subscribe on every render.
  • useWebApp() returns a stable WebApp instance for cases where you need to call send, inspect isEmbedded, or otherwise interact with the scanner imperatively.

Events

The scanner communicates with your embedded app through a small set of events. Inbound events (scan, standby, error) are dispatched by the scanner and consumed via webApp.on(...). Outbound events (navigate, settings) are sent from your app back to the scanner via webApp.send(...).

All inbound event callbacks receive a message object of the shape { action, payload }, where action is the event name and payload is the event-specific data described below.

Wildcard listener

Pass '*' as the event name to subscribe to every built-in event in a single call. The callback fires once per event with the actual action (e.g. 'scan'), so it's a convenient way to log, debug, or proxy all scanner traffic without registering a handler per event:

const off = webApp.on('*', ({ action, payload }) => {
  console.log('scanner event:', action, payload);
});

// Later, to unsubscribe:
off();
// or equivalently:
webApp.off('*', callback);

The wildcard covers the SDK's built-in AppEvents keys (scan, standby, error, navigate, ready, settings); custom event names added via a typed WebApp<E> are not included.

The same wildcard works in the React hook:

import { useEvent } from '@basetime/a2w-webview-ts/react';

useEvent('*', ({ action, payload }) => {
  console.log('scanner event:', action, payload);
});

scan

Triggered by the scanner each time it processes a pass scan, regardless of whether the pass was found. Use this event to validate the pass, run any business logic against the campaign, and optionally drive the scanner to a new screen using the navigate event.

webApp.on('scan', ({ payload }) => {
  if (!payload.found) {
    console.warn('Pass not recognized');
    return;
  }

  console.log('Scanned pass:', payload.pass);
});

payload (ScanPayload) properties:

  • scanner (string): The ID of the scanner that produced the event.
  • location (string): The device location as "latitude,longitude".
  • found (boolean): Whether the scanned pass was found in the system.
  • pass (Pass): The full pass object, including its associated campaign.
  • tags (string[]): The tags associated with the scanner.
  • password (string): The password configured in the Addtowallet app, if any. Useful for authenticating the request inside your handler.
  • settings (Record<string, any>): Additional scanner settings.
  • webviewHeight (number): The height of the scanner webview in pixels.
  • webviewWidth (number): The width of the scanner webview in pixels.
  • device (ScannerDeviceInfo): Information about the device:
    • manufacturer (string | null): e.g. "Apple", "Google", "xiaomi".
    • model (string | null): e.g. "iPhone XS Max", "Pixel 2".
    • osVersion (string | null): e.g. "12.3.1", "11.0".
    • deviceName (string | null): The user-assigned device name, e.g. "Vivian's iPhone XS". May be null if unavailable.

standby

Triggered when the scanner is sitting on its home / standby screen. This is a good place to push per-device configuration overrides via the settings event, or to render an idle UI in your embedded webview.

webApp.on('standby', ({ payload }) => {
  console.log('Scanner', payload.scanner, 'is idle');
});

payload (StandbyPayload) properties:

  • scanner (string): The ID of the scanner.
  • location (string): The device location as "latitude,longitude".
  • password (string): The password configured in the Addtowallet app, if any.
  • settings (Record<string, any>): Additional scanner settings.
  • webviewHeight (number): The height of the scanner webview in pixels.
  • webviewWidth (number): The width of the scanner webview in pixels.
  • device (ScannerDeviceInfo): Device information (see scan above).

error

Triggered whenever the scanner encounters a recoverable error, such as a missing pass or campaign. Use this event to surface a user-friendly error state inside your webview.

webApp.on('error', ({ payload }) => {
  console.error(`[${payload.errorCode}] ${payload.errorMessage}`);
});

payload (ErrorPayload) properties:

  • scanner (string): The ID of the scanner.
  • location (string): The device location as "latitude,longitude".
  • password (string): The password configured in the Addtowallet app, if any.
  • settings (Record<string, any>): Additional scanner settings.
  • webviewHeight (number): The height of the scanner webview in pixels.
  • webviewWidth (number): The width of the scanner webview in pixels.
  • device (ScannerDeviceInfo): Device information (see scan above).
  • errorCode (number): A numeric representation of the error, e.g. 404.
  • errorMessage (string): A human-readable description of the error, e.g. "Campaign not found".

navigate

Sent from your app to the scanner to instruct it to navigate one of its webviews to a new URL. Commonly used after handling a scan event to return the scanner to its standby screen or to advance to a custom flow.

webApp.send('navigate', { url: '/' });

payload (NavigatePayload) properties:

  • url (string): The URL (or path) the scanner should navigate to.

ready

Sent from your app to the scanner to notify it that the webview is ready.

webApp.send('ready');

settings

Sent from your app to override scanner settings at runtime. Overrides provided this way persist on the device until the backend pushes a new settings payload with the force flag. Only the fields you provide are updated; everything else is left untouched.

webApp.send('settings', {
  pin: '1234',
  webviewStandbyUrl: 'https://example.com/standby',
});

payload is a Partial<Settings> object. Supported fields:

  • baseUrl (string): The base URL of the API.
  • pin (string): The PIN that unlocks the scanner's settings screen.
  • brandColor (string): The brand color used by the scanner UI.
  • brandLogoUrl (string): The URL of the brand logo.
  • tags (string[]): The tags associated with the scanner.
  • webviewSpaUrl (string): The URL displayed in the SPA webview.
  • webviewScanUrl (string): The URL displayed in the scan webview.
  • webviewStandbyUrl (string): The URL displayed in the standby webview.
  • webviewErrorUrl (string): The URL displayed in the error webview.
  • webviewPassword (string): The password required to access the webview.
  • isKioskMode (boolean): Whether to hide the scan button on the home screen.
  • debugWebviews (boolean): Whether to enable debug mode for webviews.
  • logLevel ('debug' | 'info' | 'error'): Minimum log severity. debug logs everything; info logs info and errors; error logs only errors.
  • additionalSettings (Record<string, any>): Arbitrary additional settings.