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

@bmsuisse/app-native

v0.5.0

Published

Web app side of the BMS app: typed calls to window.BMSNative (chrome, toast, share, scan, widgets, Live Activities, approvals, native forms and content) with browser fallbacks.

Readme

@bmsuisse/app-native

Web app side of the BMS app: typed calls to window.BMSNative, which the app injects into every web app — with browser fallbacks, so the same page also runs outside the app. No dependencies, no React required.

Backend counterpart: bmsdna-app-native (Python). Detailed guides per topic: docs/, for native forms and content native-surfaces-guide.md.

Installation

npm install @bmsuisse/app-native
# or
bun add @bmsuisse/app-native

Examples

import {
  isNativeApp,
  can,
  on,
  setChrome,
  toast,
  haptic,
  share,
  biometricConfirm,
  scanBarcode,
  scanBarcodes,
  scanText,
  setWidgets,
  getAccessToken,
  navigate,
  addReminder,
  saveContact,
  callPhone,
  toIsoWithOffset,
  canShowNativeForms,
  isNativeSurfaceUnsupported,
  showForm,
  showContent,
} from '@bmsuisse/app-native'

// Is the page running in the app? Does it have a given capability?
if (isNativeApp() && can('customChrome')) {
  setChrome({
    scope: 'route',
    menu: [{ items: [{ id: 'new-order', label: 'New order', icon: 'plus' }] }],
    actionButtons: [{ id: 'search', icon: 'magnifyingglass' }],
  })
}

// Taps in the native menu — instead of setting window.onNativeMenuSelect yourself
const off = on('menuSelect', (id) => navigate(`/${id}`))

// Feedback
toast('Saved', 'success')
haptic('success')

// Share: app → native share sheet, browser → Web Share API / clipboard
await share({ title: 'Order 123', url: location.href })

// Face ID before a critical action (UX only, no proof for the backend)
const { ok } = await biometricConfirm('Approve order?')

// Scan a barcode; the result arrives as an event
on('barcodeScanned', (value) => lookup(value))
await scanBarcode()

// Or let the promise carry the result: several codes, or text from a label
// (docs/scan-guide.md). Keep a way to type the value in.
const codes = await scanBarcodes({ formats: ['ean13', 'qr'], max: 20 })
const serial = await scanText({ pattern: '[A-Z]{2}-\d{4,}' })

// Widgets on the native dashboard
await setWidgets([{ id: 'open-orders', kind: 'kpi', title: 'Open', data: { value: 12 } }])

// Entra token of the app's sign-in. Only needed where the browser cannot set a
// header (WebSocket, EventSource, …): fetch/XHR to your own backend get it automatically.
const session = await getAccessToken()
if (session.ok) socket.send(JSON.stringify({ token: session.token }))

// Other apps on the iPhone: route, reminder, contact, phone call
await navigate({ destination: { name: 'Müller AG', address: 'Industriestrasse 5, 4600 Olten' } })
await addReminder({ title: 'Call Mr. Meier back', due: toIsoWithOffset(new Date(2026, 9, 2, 9)) })
await saveContact({ givenName: 'Anna', organization: 'Müller AG', phones: ['+41 44 000 00 00'] })
await callPhone({ number: '+41 44 000 00 00' })

// Native form (an iOS sheet). The form stays open until your handler settles:
// `{ fieldErrors }` or a thrown error marks fields and lets the user correct.
if (canShowNativeForms()) {
  const res = await showForm(
    {
      id: 'new-customer',
      title: 'New customer',
      fields: [
        { id: 'name', type: 'text', label: 'Company name', required: true },
        { id: 'email', type: 'email', label: 'Email', required: true },
        { id: 'card', type: 'photo', label: 'Business card', max: 1 },
      ],
    },
    { onSubmit: async (values) => await api.createCustomer(values) }
  )
  if (!res.ok && isNativeSurfaceUnsupported(res)) openWebForm() // old app, no capability
} else {
  openWebForm()
}

// Native content: info with blocks and buttons
const shown = await showContent({
  title: 'Miller Ltd',
  blocks: [
    { type: 'facts', items: [{ label: 'Phone', value: '+41 44 000 00 00', kind: 'phone' }] },
  ],
  actions: [{ id: 'new-order', label: 'New order', style: 'primary' }],
})

Behavior outside the app

| Function | Browser | | ----------------------------------------------------------------- | --------------------------------------------------------------------------------- | | toast, haptic, setBadge, setChrome | does nothing | | share | Web Share API, otherwise clipboard ('copied') | | openExternal | new tab | | biometricConfirm | { ok: true } (web flow continues) | | navigate | route in Google Maps in a new tab | | callPhone | tel: link | | showForm, showContent, closeSurface | { ok: false, error: 'unavailable' } — keep your web UI (canShowNativeForms()) | | all others (setWidgets, startLiveActivity, scanDocument, …) | { ok: false, error: 'unavailable' } |

Responses and errors

Calls with a response return { ok: true, … } or { ok: false, error }. Common errors: capability (the app has not granted the capability to the web app), invalid, cancelled, unavailable, notConfigured; for getAccessToken also forbidden and notSignedIn; for the device actions also denied; for showForm/showContent also forbidden, busy and tooLarge. An app that predates a call answers unknownAction: treat it like unavailable. can(capability) saves unnecessary calls, but the app always checks on its own.

Overview

| Area | Functions | Capability | | --------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | | Detection | isNativeApp, nativeInfo, can | – | | Events | on('menuSelect' \| 'actionButtonTap' \| 'bottomBarTap' \| 'barcodeScanned' \| 'barcodesScanned' \| 'textScanned', …) | – | | Chrome | setChrome, centerProminentEntry | customChrome, customBottomBar | | Feedback | toast, haptic, setBadge | – | | System | share, openExternal, biometricConfirm | – | | Camera | scanDocument, scanBarcode, scanBarcodes, scanText, canScan (guide) | camera | | Widgets | setWidgets, updateWidget, removeWidgets, refreshWidgets | dashboardWidgets | | Live Activities | startLiveActivity, updateLiveActivity, endLiveActivity, getLiveActivities | liveActivities | | Approvals | refreshApprovals | approvals | | Sign-in | getAccessToken | identity | | Other apps | navigate, callPhone, addReminder, saveContact, toIsoWithOffset | deviceApps (reminder, contact) | | Native forms | showForm, canShowNativeForms, formLimitWarnings | nativeForms (+ camera for camera fields) | | Native content | showContent, canShowNativeContent, contentLimitWarnings | nativeContent (+ deviceApps for saveContact/addReminder steps) | | Surfaces | closeSurface, surfaceResult, isNativeSurfaceUnsupported, on('surfaceAction', …), onSurfaceAction | nativeForms or nativeContent | | Testing | sendTestNotification | notifications | | Raw access | call, post, send | – |

License

MIT