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

@verse8/platform

v2.1.0

Published

Verse8 platform SDK — React hook + framework-agnostic browser API for VX Shop

Readme

@verse8/platform

Verse8 platform SDK — exposes the VX Shop to game clients through two surfaces:

  1. React hookuseVXShop (unchanged from v1.0.x).
  2. Framework-agnostic APIVXShop namespace, importable as ESM/CJS or loadable via <script> tag with window.VXShop.

Both surfaces share a single in-memory store: calling VXShop.refresh() from a vanilla page updates state observed by a mounted useVXShop hook, and vice versa.

Install

pnpm add @verse8/platform
# or
npm install @verse8/platform
# or
yarn add @verse8/platform

Script tag / CDN

<script src="https://unpkg.com/@verse8/platform/dist/index.global.js"></script>
<script>
  // window.VXShop is now available
  VXShop.init({ verseId: 'my-verse' });
  VXShop.subscribe(({ items, isLoading, error }) => {
    if (isLoading || error) return;
    renderShop(items);
  });
  document.getElementById('buy').onclick = () =>
    VXShop.buyItem('event-pack');
</script>

A jsdelivr field is also published; swap unpkg.com for cdn.jsdelivr.net/npm/... if preferred.

Quick start

React (existing)

import { useVXShop } from '@verse8/platform';
import { useEffect } from 'react';

function Shop() {
  const { items, getItem, buyItem, refresh, onClose } = useVXShop();

  useEffect(() => {
    const cancel = onClose(() => refresh());
    return cancel;
  }, [onClose, refresh]);

  return (
    <button onClick={() => buyItem('event-pack')}>
      Buy event pack — {getItem('event-pack')?.price ?? '...'}
    </button>
  );
}

Vanilla ESM

For pure vanilla use with no React installed, import from the /vanilla subpath — the default entry pulls in react at module load time because it re-exports useVXShop:

import { VXShop } from '@verse8/platform/vanilla';

VXShop.init({ verseId: 'my-verse' });

const unsub = VXShop.subscribe((state) => {
  if (state.error) console.error(state.error);
  if (!state.isLoading) updateUI(state.items);
});

document.getElementById('buy')!.onclick = () => {
  VXShop.buyItem('event-pack');
};

Named imports tree-shake too:

import { init, getItem, buyItem } from '@verse8/platform/vanilla';
init();
buyItem(getItem('event-pack')!.productId);

CommonJS

// Without React installed
const { VXShop } = require('@verse8/platform/vanilla');
VXShop.init();
console.log(VXShop.getItems());

// With React installed (also exposes useVXShop)
const { VXShop, useVXShop } = require('@verse8/platform');

<script> tag

<script src="https://unpkg.com/@verse8/platform/dist/index.global.js"></script>
<script>
  VXShop.init();
  VXShop.refresh().then(() => {
    console.log(VXShop.getItem('event-pack'));
  });
</script>

API

VXShop.init(opts?: VXShopInitOptions): void

Sets the shop parameters and (by default) triggers an initial refresh. Safe to call multiple times — the underlying fetch is throttled to 5 seconds, so rapid repeat init() calls coalesce into a single network request.

interface VXShopInitOptions {
  /** Override the verseId. Otherwise resolved from VITE_AGENT8_VERSE env or `verseId` query param. */
  verseId?: string;
  /** Override the account. Otherwise resolved from `account` query param or AGENT8_ACCOUNT env on Verse8 hosts. */
  account?: string;
  /** Set to false to skip the initial fetch. Default: true. */
  autoRefresh?: boolean;
}

Calling init is optional: every public function lazy-inits with defaults the first time it's invoked. Call init explicitly only to override verseId, account, or disable auto-refresh.

VXShop.getItem(productId): VXShopItem | undefined

Synchronous lookup against the current cache. Returns undefined until the first refresh() resolves.

VXShop.getItems(): VXShopItem[]

Snapshot of the current items array. Empty until the first fetch resolves.

VXShop.buyItem(productId): void

Posts an OPEN_VX_SHOP_DIALOG message to window.parent so the Verse8 host opens the payment dialog. Use onClose to observe the result.

VXShop.refresh(): Promise<void>

Re-fetches the item list. Throttled to 5 seconds — rapid repeat calls coalesce.

VXShop.onClose(cb): () => void

Registers a callback invoked when the payment dialog closes (with { purchased: boolean; productId: string; action: 'purchased' | 'closed' }). Returns an unsubscribe function.

VXShop.subscribe(listener): () => void

Registers a listener invoked on every state change with the current { items, isLoading, error }. Returns an unsubscribe function.

VXShop.getState(): VXShopState

Snapshot of current public state: { items, isLoading, error }.

useVXShop(options?): UseVXShopResult (React)

Returns:

| Property | Type | |---------------|------------------------------------------------------------| | items | VXShopItem[] | | isLoading | boolean | | error | string \| null | | getItem | (productId: string) => VXShopItem \| undefined | | buyItem | (productId: string) => void | | refresh | () => Promise<void> | | onClose | (cb: (payload) => void) => () => void |

Auto-refreshes on first mount. Backward-compatible with v1.0.x — no public-API changes.

Parameter resolution

Both surfaces resolve verseId and account from the same sources. Priority differs slightly by field:

verseId — explicit option → VITE_AGENT8_VERSE env (or NEXT_PUBLIC_AGENT8_VERSE on Next.js) → ?verseId= query parameter.

account — explicit option → ?account= query parameter → VITE_AGENT8_ACCOUNT env (only honored on agent8-games.verse8.io and agent8-container.* hostnames).

If either field cannot be resolved, the next refresh() records an error in state and subscribe listeners are notified.

Migration from v1.0.x

No breaking changes. The useVXShop hook's return shape, semantics, and auto-refresh trigger are byte-identical to v1.0.13. Just upgrade.

- "@verse8/platform": "^1.0.13"
+ "@verse8/platform": "^1.1.0"

License

UNLICENSED — Verse8 internal.