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

vibecoding-purchases

v1.1.2

Published

VibeCoding Purchases SDK for React Native and Expo apps

Readme

VibeCoding Purchases SDK

A comprehensive purchases SDK for React Native and web applications that integrates with your VibeCoding backend API.

Features

  • ✅ Anonymous user system with automatic linking
  • ✅ Cross-platform support (iOS, Android, Web)
  • ✅ Native mobile payments (Apple App Store, Google Play)
  • ✅ Subscription management
  • ✅ Purchase restoration
  • ✅ React hooks for easy integration
  • ✅ TypeScript support

Installation

npm install vibecoding-purchases
# or
yarn add vibecoding-purchases

Quick Start

1. Configure the SDK

The SDK works in multiple environments with different capabilities:

For Expo Go (Development)

import { VibeCodingPurchases } from "vibecoding-purchases";

// Basic configuration for Expo Go - no native purchases
const purchases = VibeCodingPurchases.configure({
  projectId: "your-project-id",
  apiKey: "your-api-key",
  baseUrl: "https://your-api.com",
  environment: "development", // or 'production'
});

// Will work for: user management, offerings, customer info
// Won't work: native purchases (will throw helpful errors)

For Development Builds (Native Features)

import { VibeCodingPurchases } from "vibecoding-purchases";
import { useIAP } from "expo-iap";

// With expo-iap for full native purchase support
const expoIAPResult = useIAP();
const purchases = VibeCodingPurchases.configure(
  {
    projectId: "your-project-id",
    apiKey: "your-api-key",
    baseUrl: "https://your-api.com",
    environment: "production",
  },
  expoIAPResult // Optional - enables native purchases & restore
);

// Will work: everything including native purchases and restore

For Web/React (Future Stripe Support)

import { VibeCodingPurchases } from "vibecoding-purchases";

// Web configuration - Stripe integration planned
const purchases = VibeCodingPurchases.configure({
  projectId: "your-project-id",
  apiKey: "your-api-key",
  baseUrl: "https://your-api.com",
  environment: "production",
});

// Currently works: user management, offerings, customer info
// Coming soon: Stripe checkout sessions

2. Anonymous User System

The SDK automatically handles anonymous users. When a user first opens your app, they get an anonymous ID:

// This will create an anonymous user automatically
const result = await purchases.logIn();
console.log(result.customerInfo.originalAppUserId); // "$AnonymousUser:abc123..."

3. User Login with Account Linking

When a user logs in, their anonymous purchases are automatically transferred:

// Login with a real user ID - anonymous purchases will be linked
const result = await purchases.logIn("user123");
console.log("Purchases transferred:", result.created);

4. Get Available Offerings

const offerings = await purchases.getOfferings();
const currentOffering = offerings.offerings.all["main"];
const packages = currentOffering?.availablePackages || [];

5. Make a Purchase (React Native)

// For React Native apps, use the hook for native purchases
import { useVibeCodingPurchases } from 'vibecoding-purchases';

function PurchaseButton({ package: pkg }) {
  const { purchasePackage, loading } = useVibeCodingPurchases();

  const handlePurchase = async () => {
    try {
      const result = await purchasePackage(pkg);
      console.log('Purchase successful:', result.customerInfo);
    } catch (error) {
      console.error('Purchase failed:', error);
    }
  };

  return (
    <button onClick={handlePurchase} disabled={loading}>
      {loading ? 'Processing...' : `Buy for ${pkg.product.price}`}
    </button>
  );
}

API Endpoints

Your backend now supports these endpoints:

User Management

POST /api/purchases/login

Creates/authenticates user with automatic anonymous user handling.

{
  "app_user_id": "user123",
  "project_id": "your-project-id"
}

POST /api/purchases/link-alias

Links anonymous user to identified user.

{
  "old_id": "$AnonymousUser:abc123",
  "new_id": "user123",
  "project_id": "your-project-id"
}

Purchase & Subscription

GET /api/purchases/{PROJECT_ID}/offerings

Fetches available packages and offerings for the project.

GET /api/purchases/customer/{APP_USER_ID}

Gets customer subscription info and entitlements.

POST /api/purchases/purchase

Validates native purchase receipts.

{
  "app_user_id": "user123",
  "product_id": "premium_monthly",
  "transaction_receipt": "base64-receipt-data",
  "apple_transaction_id": "1000000123456789" // for iOS
}

POST /api/purchases/{PROJECT_ID}/payment-sheet

Creates payment sheet for web (currently deprecated - use native mobile payments).

Native Restore via SDK

Purchases are restored automatically through the native platform integration (expo-iap). No separate API call needed - the SDK handles this internally.

Subscription Management

Subscription management is handled through the native platform stores (App Store/Google Play). Users manage subscriptions directly in their device settings.

Anonymous User System Details

How It Works

  1. First Launch: User gets an anonymous ID like $AnonymousUser:abc123def456
  2. Anonymous Purchases: User can make purchases while anonymous
  3. User Login: When user logs in with real ID, anonymous purchases are transferred
  4. Security: If stored ID is custom but no custom ID provided, resets to new anonymous ID

Storage Functions

import { VibeCodingPurchasesStorage } from "vibecoding-purchases";

// Generate anonymous ID
const anonymousId = VibeCodingPurchasesStorage.generateAnonymousId();
// Returns: "$AnonymousUser:abc123def456"

// Check if ID is anonymous
const isAnon = VibeCodingPurchasesStorage.isAnonymousUserId(userId);

// Core user management
const result = await VibeCodingPurchasesStorage.getOrCreateUserId(
  customUserId, // null for anonymous, string for login
  projectId,
  environment
);

// Storage operations
await VibeCodingPurchasesStorage.setUserId(userId, projectId);
const userId = await VibeCodingPurchasesStorage.getUserId(projectId);
await VibeCodingPurchasesStorage.clearUserId(projectId);

React Integration

Provider Setup

Choose the setup that matches your environment:

Expo Go Setup (Development)

import { VibeCodingPurchasesProvider } from "vibecoding-purchases";

function App() {
  return (
    <VibeCodingPurchasesProvider
      config={{
        projectId: "your-project-id",
        apiKey: "your-api-key",
        environment: "development",
      }}
      // No expoIAPResult needed - will work for basic features
    >
      <YourApp />
    </VibeCodingPurchasesProvider>
  );
}

Development Build Setup (Full Features)

import { VibeCodingPurchasesProvider } from "vibecoding-purchases";
import { useIAP } from "expo-iap";

function App() {
  const expoIAPResult = useIAP(); // Enable native purchases
  
  return (
    <VibeCodingPurchasesProvider
      config={{
        projectId: "your-project-id",
        apiKey: "your-api-key",
        environment: "production",
      }}
      expoIAPResult={expoIAPResult} // Enables native purchases & restore
    >
      <YourApp />
    </VibeCodingPurchasesProvider>
  );
}

Using Hooks

The hook automatically detects your environment and enables appropriate features:

import { useVibeCodingPurchases, useEntitlement } from "vibecoding-purchases";

function PremiumFeature() {
  const {
    customerInfo,
    offerings,
    purchasePackage,
    restorePurchases,
    isLoading,
    canMakePurchases, // false in Expo Go, true in dev builds
    isExpoGo, // true if running in Expo Go
    error,
  } = useVibeCodingPurchases();

  const isPremium = useEntitlement("premium");

  if (isPremium) {
    return <PremiumContent />;
  }

  return (
    <div>
      <h2>Upgrade to Premium</h2>
      
      {/* Show appropriate UI based on platform */}
      {isExpoGo && (
        <p>💡 Native purchases require a development build. Showing demo pricing.</p>
      )}
      
      {offerings?.all?.["main"]?.availablePackages.map((pkg) => (
        <button
          key={pkg.identifier}
          onClick={() => purchasePackage(pkg)}
          disabled={isLoading || !canMakePurchases}
        >
          {pkg.product.identifier} - ${pkg.product.price}
          {!canMakePurchases && " (Dev Build Required)"}
        </button>
      ))}

      {canMakePurchases && (
        <button onClick={restorePurchases} disabled={isLoading}>
          Restore Purchases
        </button>
      )}
      
      {error && <p style={{color: 'red'}}>Error: {error.message}</p>}
    </div>
  );
}

Restore Purchases

The SDK provides different restore behavior based on platform:

Native Platforms (iOS/Android)

When expo-iap is configured, restorePurchases() performs a full transaction history sync:

// Syncs all purchase history from device with backend
const customerInfo = await purchases.restorePurchases();

What happens:

  1. Queries native store (App Store/Google Play) for all purchase history
  2. Extracts transaction IDs from purchase receipts
  3. Sends transaction data to backend for validation
  4. Updates customer info with restored purchases
  5. Clears any pending transactions

Web Platform

On web, restorePurchases() simply refreshes customer info (no native transactions exist):

// Just refreshes customer info from backend
const customerInfo = await purchases.restorePurchases();

Using with React Hooks

const { restorePurchases, isLoading, error } = useVibeCodingPurchases({
  config,
  expoIAPResult: useIAP(), // Required for native restore
});

const handleRestore = async () => {
  try {
    await restorePurchases();
    console.log("Purchases restored successfully");
  } catch (err) {
    console.error("Restore failed:", err);
  }
};

Error Handling

import {
  VibeCodingPurchasesError,
  VibeCodingPurchasesErrorCode,
} from "vibecoding-purchases";

try {
  await purchases.logIn("user123");
} catch (error) {
  if (error instanceof VibeCodingPurchasesError) {
    switch (error.code) {
      case VibeCodingPurchasesErrorCode.NETWORK_ERROR:
        console.log("Network issue, try again");
        break;
      case VibeCodingPurchasesErrorCode.INVALID_CREDENTIALS_ERROR:
        console.log("Invalid API credentials");
        break;
      case VibeCodingPurchasesErrorCode.USER_NOT_LOGGED_IN_ERROR:
        console.log("User needs to log in first");
        break;
    }
  }
}

Platform Support

| Platform | User Management | Offerings | Native Purchases | Restore | |----------|----------------|-----------|------------------|---------| | Expo Go | ✅ | ✅ | ❌ | ❌ | | iOS Dev Build | ✅ | ✅ | ✅ (App Store) | ✅ | | Android Dev Build | ✅ | ✅ | ✅ (Google Play) | ✅ | | Web | ✅ | ✅ | 🚧 (Stripe planned) | 🚧 |

Key Notes:

  • Expo Go: Perfect for development - shows pricing, handles users, won't crash on purchase attempts
  • Development Builds: Full native functionality with expo-iap
  • Web: Basic functionality now, Stripe integration coming soon
  • expo-iap is optional: SDK works without it, just disables native features gracefully

Security Features

  • Automatic anonymous user reset if security mismatch detected
  • Server-side receipt validation
  • Project-scoped API keys
  • Environment-specific configurations

Migration from Other SDKs

If you're migrating from RevenueCat or similar:

  1. The CustomerInfo structure is compatible
  2. Anonymous user system works automatically
  3. Entitlements are based on your product configuration
  4. Use the same product IDs from your app store configuration

License

MIT License - see LICENSE file for details.