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

@hyve-sdk/js

v2.4.0

Published

Hyve SDK - TypeScript wrapper for Hyve game server integration

Readme

@hyve-sdk/js

TypeScript SDK for integrating games with the Hyve platform. Provides authentication, telemetry, persistent storage, ads, billing, and native bridge capabilities.

Installation

pnpm add @hyve-sdk/js

Quick Start

import { HyveClient } from "@hyve-sdk/js";

// Authentication is automatic — the SDK reads hyve-access and game-id from the URL
const client = new HyveClient();

console.log("User ID:", client.getUserId());
console.log("Game ID:", client.getGameId());
console.log("Authenticated:", client.isUserAuthenticated());

The SDK reads authentication from URL parameters automatically during construction:

https://your-game.com?hyve-access=eyJhbGci...&game-id=my-game

Environment detection happens automatically from the parent page URL (games run in iframes):

  • Dev: marvin.dev.hyve.gg or dev.hyve.gg
  • Prod: marvin.hyve.gg or hyve.gg
  • Override with isDev in config for local testing only

React Integration

Import from @hyve-sdk/js/react for the React provider and hook:

import { HyveSdkProvider, useHyveSdk } from "@hyve-sdk/js/react";

function App() {
  return (
    <HyveSdkProvider config={{ isDev: true }}>
      <Game />
    </HyveSdkProvider>
  );
}

function Game() {
  const sdk = useHyveSdk();

  const handleScore = () => {
    sdk.sendTelemetry("game", "player", "score_submitted", null, null, { score: 1000 });
  };

  return <button onClick={handleScore}>Submit Score</button>;
}

You can also pass a pre-created client:

const client = new HyveClient({ isDev: true });

<HyveSdkProvider client={client}>
  <App />
</HyveSdkProvider>

Telemetry

await client.sendTelemetry(
  "game",        // location
  "player",      // category
  "action",      // action
  "combat",      // sub-category (optional)
  "attack",      // sub-action (optional)
  {              // event details (optional)
    damage: 100,
    targetId: "enemy-123",
  }
);

Requires a valid hyve-access JWT and game-id in the URL.

Persistent Game Data

Save and retrieve game data with either cloud (default) or local storage:

// Save a value
await client.saveGameData("player_level", 5);
await client.saveGameData("settings", { volume: 0.8, fullscreen: true });

// Get a value
const item = await client.getGameData("player_level");
console.log(item?.value); // 5

// Batch save
await client.batchSaveGameData([
  { key: "coins", value: 1200 },
  { key: "lives", value: 3 },
]);

// Batch get
const items = await client.getMultipleGameData(["coins", "lives"]);

// Delete
await client.deleteGameData("temp_key");
await client.deleteMultipleGameData(["key1", "key2"]);

Storage Modes

// Set mode at construction
const client = new HyveClient({ storageMode: "local" });

// Or override per-call
await client.saveGameData("key", "value", "local");
await client.getGameData("key", "cloud");

// Change mode at runtime
client.configureStorage("cloud");
console.log(client.getStorageMode()); // "cloud"

| Mode | Description | |------|-------------| | cloud | Synced to backend API (default) | | local | Browser localStorage, device-only |

Ads

Ads are disabled by default and must be explicitly configured.

const client = new HyveClient({
  ads: {
    enabled: true,
    onBeforeAd: (type) => game.pause(),
    onAfterAd: (type) => game.resume(),
    onRewardEarned: () => { player.coins += 100; },
  },
});

const result = await client.showAd("rewarded");
if (result.success) {
  console.log("User watched the ad");
}

await client.showAd("interstitial");  // between levels
await client.showAd("preroll");       // game start

| Ad Type | Use Case | |---------|----------| | rewarded | User watches full ad for a reward | | interstitial | Between levels or game screens | | preroll | Before the game starts |

The SDK automatically routes ad calls through the appropriate platform SDK (CrazyGames, Playgama, or the default Google H5 Ads SDK) based on the current domain.

Platform Integrations

CrazyGames

When running on CrazyGames, the SDK auto-initializes the CrazyGames SDK and routes ads through it. Use these additional lifecycle methods:

// Call when gameplay begins (required by CrazyGames policy)
await client.gameplayStart();

// Call when gameplay stops (paused, died, menu, etc.)
await client.gameplayStop();

// Trigger a celebration effect on the CrazyGames website
await client.happytime();

Playgama

When running on Playgama, the SDK auto-initializes the Playgama Bridge and routes ads through it. No additional setup required.

Billing

Billing supports web (Stripe) and native (In-App Purchases) — platform is detected automatically.

const client = new HyveClient({
  billing: {
    stripePublishableKey: "pk_live_...",
  },
});

if (client.isBillingAvailable()) {
  client.onPurchaseComplete((result) => {
    console.log("Purchase successful:", result.transactionId);
  });

  client.onPurchaseError((result) => {
    console.error("Purchase failed:", result.error?.message);
  });

  const products = await client.getBillingProducts();
  await client.purchaseProduct("price_1234");
}

For web, add a container element for the Stripe checkout UI:

<div id="stripe-checkout-element"></div>

| Platform | Payment Method | Detection | |----------|---------------|-----------| | Web | Stripe Embedded Checkout | Default | | Native iOS/Android | In-App Purchases | ReactNativeWebView in window |

Native Bridge

Type-safe bidirectional communication between your web game and a React Native WebView host.

import { NativeBridge } from "@hyve-sdk/js";

if (NativeBridge.isNativeContext()) {
  NativeBridge.initialize();

  // Listen for IAP availability
  NativeBridge.on("IAP_AVAILABILITY_RESULT", (payload) => {
    if (payload.available) {
      console.log("IAP available on:", payload.platform);
    }
  });
  NativeBridge.checkIAPAvailability();

  // Request push notification permission
  NativeBridge.on("PUSH_PERMISSION_GRANTED", (payload) => {
    console.log("Token:", payload?.token);
  });
  NativeBridge.requestNotificationPermission();

  // Send/receive custom messages
  NativeBridge.send("GAME_EVENT", { action: "level_complete", level: 3 });
  NativeBridge.on("CUSTOM_RESPONSE", (payload) => {
    console.log("Received:", payload);
  });
}

NativeBridge API

| Method | Description | |--------|-------------| | isNativeContext() | Check if running in React Native WebView | | initialize() | Start the message listener | | send(type, payload?) | Send a message to the native app | | on(type, handler) | Register a message handler | | off(type) | Remove a message handler | | clearHandlers() | Remove all handlers | | checkIAPAvailability() | Request IAP availability from native | | requestNotificationPermission() | Request push notification permission |

Logger

import { logger } from "@hyve-sdk/js";

logger.debug("Debug info", { data: "value" });
logger.info("Informational message");
logger.warn("Warning message");
logger.error("Error message", error);

// Namespaced child logger
const gameLogger = logger.child("Game");
gameLogger.info("Game started");
// Output: [Hyve SDK] [Game] [INFO] [timestamp] Game started

Override log level in the browser:

localStorage.setItem("HYVE_SDK_LOG_LEVEL", "error,warn");

API Reference

HyveClient Config

new HyveClient(config?: {
  isDev?: boolean;             // Override env detection (local testing only)
  apiBaseUrl?: string;         // Override API base URL
  storageMode?: "cloud" | "local";
  ads?: AdConfig;
  billing?: BillingConfig;
})

Authentication

| Method | Returns | Description | |--------|---------|-------------| | getUserId() | string \| null | Authenticated user ID | | getGameId() | string \| null | Game ID from URL or JWT | | getSessionId() | string | Unique session ID | | getJwtToken() | string \| null | Raw JWT string | | isUserAuthenticated() | boolean | Whether a user ID was extracted | | hasJwtToken() | boolean | Whether a JWT is present | | logout() | void | Clear auth state | | reset() | void | Clear auth and generate new session ID |

API

| Method | Returns | Description | |--------|---------|-------------| | callApi<T>(endpoint, options?) | Promise<T> | Authenticated fetch to the Hyve API | | getInventory() | Promise<Inventory> | Get user inventory | | getInventoryItem(itemId) | Promise<InventoryItem> | Get a specific inventory item |

Telemetry

| Method | Returns | Description | |--------|---------|-------------| | sendTelemetry(location, category, action, subCategory?, subAction?, details?) | Promise<boolean> | Send an analytics event | | updateTelemetryConfig(config) | void | Update telemetry settings at runtime |

Storage

| Method | Returns | Description | |--------|---------|-------------| | saveGameData(key, value, storage?) | Promise<SaveGameDataResponse> | Save a single value | | batchSaveGameData(items, storage?) | Promise<SaveGameDataResponse> | Save multiple values | | getGameData(key, storage?) | Promise<GameDataItem \| null> | Get a single value | | getMultipleGameData(keys, storage?) | Promise<GameDataItem[]> | Get multiple values | | deleteGameData(key, storage?) | Promise<boolean> | Delete a single value | | deleteMultipleGameData(keys, storage?) | Promise<number> | Delete multiple values | | configureStorage(mode) | void | Set default storage mode | | getStorageMode() | "cloud" \| "local" | Get current storage mode |

Ads

| Method | Returns | Description | |--------|---------|-------------| | configureAds(config) | void | Configure the ads service | | showAd(type) | Promise<AdResult> | Show an ad | | areAdsReady() | boolean | Check if ads have initialized | | gameplayStart() | Promise<void> | Notify gameplay started (CrazyGames) | | gameplayStop() | Promise<void> | Notify gameplay stopped (CrazyGames) | | happytime() | Promise<void> | Trigger celebration effect (CrazyGames) |

Billing

| Method | Returns | Description | |--------|---------|-------------| | getBillingPlatform() | BillingPlatform | "web" | "native" | "unknown" | | isBillingAvailable() | boolean | Check if billing is ready | | getBillingProducts() | Promise<BillingProduct[]> | Fetch available products | | purchaseProduct(productId, options?) | Promise<PurchaseResult> | Initiate a purchase | | onPurchaseComplete(callback) | void | Register purchase success handler | | onPurchaseError(callback) | void | Register purchase error handler | | unmountBillingCheckout() | void | Clean up Stripe checkout UI |

Build Output

| Format | File | Use | |--------|------|-----| | CJS | dist/index.js | Node.js / bundler | | ESM | dist/index.mjs | Bundler (tree-shakeable) | | CJS (React) | dist/react.js | React integration | | ESM (React) | dist/react.mjs | React integration (tree-shakeable) |

Development

pnpm run check-types   # Type check
pnpm run lint          # Lint
pnpm run build         # Build

License

MIT