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-official/purchases

v1.0.0

Published

VibeCoding Purchases SDK for React Native and Expo apps

Readme

@vibecoding/purchases

A React Native and Expo SDK for VibeCoding's in-app purchase and subscription management system.

Features

  • ✅ Cross-platform support (iOS, Android, Web)
  • ✅ React Native and Expo compatibility (including Expo Go detection)
  • ✅ TypeScript support with full type definitions
  • ✅ React hooks for easy integration
  • ✅ Automatic receipt validation
  • ✅ Subscription management
  • ✅ Customer info synchronization
  • ✅ Error handling and retry logic
  • ✅ Platform-aware purchase handling
  • ✅ Expo IAP integration for development builds
  • ✅ Provider pattern for React applications

Installation

npm

npm install @vibecoding/purchases

yarn

yarn add @vibecoding/purchases

pnpm

pnpm add @vibecoding/purchases

Additional Dependencies

For React Native projects, you'll also need:

npm install react-native-iap

For Expo projects, you'll also need:

expo install expo-iap expo-constants

Quick Start

1. Using React Provider (Recommended)

import { VibeCodingPurchasesProvider, useVibeCodingPurchases } from '@vibecoding/purchases';

// Wrap your app with the provider
function App() {
  const config = {
    apiKey: "your-api-key",
    projectId: "your-project-id",
    environment: "production", // or 'development'
    baseUrl: "https://your-api-url.com" // optional
  };

  return (
    <VibeCodingPurchasesProvider
      config={config}
      appUserId="user-123" // optional, for automatic login
    >
      <YourAppContent />
    </VibeCodingPurchasesProvider>
  );
}

// Use the hook in your components
function SubscriptionScreen() {
  const {
    customerInfo,
    offerings,
    isLoading,
    error,
    purchasePackage,
    purchase, // simplified purchase by package ID
    hasEntitlement,
    login,
    logOut,
    canMakePurchases,
    isExpoGo
  } = useVibeCodingPurchases();

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

  const handleSimplePurchase = async (packageId) => {
    try {
      await purchase(packageId); // Purchase by package ID
      console.log('Purchase successful');
    } catch (error) {
      console.error('Purchase failed:', error);
    }
  };

  if (isLoading) {
    return <Text>Loading...</Text>;
  }

  if (isExpoGo) {
    return <Text>Purchases not supported in Expo Go. Use a development build.</Text>;
  }

  return (
    <View>
      <Text>Premium Active: {hasEntitlement('premium') ? 'Yes' : 'No'}</Text>
      <Text>Can Make Purchases: {canMakePurchases ? 'Yes' : 'No'}</Text>
      {offerings?.offerings.current && Object.values(offerings.offerings.current).map((offering) => (
        offering.availablePackages.map((pkg) => (
          <Button
            key={pkg.identifier}
            title={`Buy ${pkg.identifier} - ${pkg.product.price} ${pkg.product.currency}`}
            onPress={() => handlePurchase(pkg)}
          />
        ))
      ))}
    </View>
  );
}

2. Direct SDK Usage

import { VibeCodingPurchases } from "@vibecoding/purchases";

// Configure the SDK
const purchases = VibeCodingPurchases.configure({
  apiKey: "your-api-key",
  projectId: "your-project-id",
  environment: "production",
});

// Login a user
const { customerInfo, created } = await purchases.logIn("user-123");

// Get available offerings
const offerings = await purchases.getOfferings();

// Get customer info
const customerInfo = await purchases.getCustomerInfo();

// Make a purchase using static method
const result = await VibeCodingPurchases.purchase("monthly_premium");

// Check if user is anonymous
const isAnonymous = VibeCodingPurchases.isAnonymous();

// Get current user ID
const userId = VibeCodingPurchases.getUserId();

// Log out
await VibeCodingPurchases.logOut();

3. Initialize Method (Alternative)

import { VibeCodingPurchases } from "@vibecoding/purchases";

// Initialize with configuration and optional user
const purchases = await VibeCodingPurchases.initialize({
  apiKey: "your-api-key",
  projectId: "your-project-id",
  environment: "production",
  appUserId: "user-123", // optional
});

API Reference

Configuration

interface VibeCodingPurchasesConfiguration {
  apiKey: string;
  projectId: string;
  baseUrl?: string;
  environment?: "production" | "development";
}

Main Methods

Static Methods

VibeCodingPurchases.configure(config)

Configure the SDK with your API credentials. Returns a VibeCodingPurchases instance.

VibeCodingPurchases.initialize(config & { appUserId?: string })

Initialize the SDK with configuration and optional user login.

VibeCodingPurchases.isAnonymous()

Check if the current user is anonymous.

VibeCodingPurchases.getUserId()

Get the current app user ID.

VibeCodingPurchases.purchase(packageId)

Purchase a product by package ID (static convenience method).

VibeCodingPurchases.logOut()

Log out the current user (static method).

Instance Methods

purchases.logIn(appUserId)

Log in a specific user. Returns { customerInfo, created }.

purchases.getCustomerInfo()

Get current customer information and entitlements.

purchases.getOfferings(provider?)

Fetch available products and subscriptions. Optional provider parameter ("apple" | "google").

purchases.purchasePackage(package)

Purchase a product or subscription using a Package object.

purchases.restorePurchases()

Restore previous purchases (iOS primarily).

purchases.getCurrentAppUserId()

Get the current app user ID.

purchases.getCachedCustomerInfo()

Get cached customer information without making a network request.

purchases.isAnonymous()

Check if the current user is anonymous.

purchases.addCustomerInfoUpdateListener(listener)

Add a listener for customer info updates. Returns listener ID.

purchases.removeCustomerInfoUpdateListener(listenerId)

Remove a customer info update listener.

React Hooks

useVibeCodingPurchases()

Main hook providing access to purchases functionality.

const {
  // State
  customerInfo,
  offerings,
  isLoading,
  error,
  purchaseInProgress,
  userId,

  // Platform info
  isExpoGo,
  canMakePurchases,

  // Methods
  login,
  logOut,
  purchasePackage,
  purchase, // simplified purchase by package ID
  restorePurchases,
  getOfferings,
  refreshCustomerInfo,

  // Utility methods
  hasEntitlement,
  isPurchasing,
  isAnonymous,
} = useVibeCodingPurchases();

useEntitlement(entitlementId)

Hook for checking a specific entitlement.

const {
  isActive,
  productIdentifier,
  expirationDate,
  purchaseDate,
  identifier,
} = useEntitlement("premium");

useSubscriptionStatus()

Hook for subscription status information.

const { hasActiveSubscription, activeSubscriptions, allEntitlements } =
  useSubscriptionStatus();

Types

The SDK exports comprehensive TypeScript types:

  • CustomerInfo - Customer subscription and entitlement information
  • Offering - Available products grouped by offering
  • OfferingsResponse - Complete offerings response structure
  • Package - Individual purchasable package
  • Product - Product information (price, currency, identifier)
  • Entitlement - Individual entitlement with status and dates
  • LoginResponse - Response from login API call
  • PurchaseResponse - Response from purchase API call
  • VibeCodingPurchasesConfiguration - SDK configuration interface
  • VibeCodingPurchasesError - Custom error class
  • VibeCodingPurchasesErrorCode - Error code enum
  • UseVibeCodingPurchasesResult - Hook return type
  • ReactNativeIAPPurchase - React Native IAP purchase interface

Error Handling

The SDK includes comprehensive error handling:

import {
  VibeCodingPurchasesError,
  VibeCodingPurchasesErrorCode,
} from "@vibecoding/purchases";

try {
  await VibeCodingPurchases.purchase("monthly_premium");
} catch (error) {
  if (error instanceof VibeCodingPurchasesError) {
    switch (error.code) {
      case VibeCodingPurchasesErrorCode.PURCHASE_CANCELLED_ERROR:
        console.log("User cancelled the purchase");
        break;
      case VibeCodingPurchasesErrorCode.NETWORK_ERROR:
        console.log("Network error occurred");
        break;
      case VibeCodingPurchasesErrorCode.PLATFORM_NOT_SUPPORTED_ERROR:
        console.log("Platform not supported for purchases");
        break;
      case VibeCodingPurchasesErrorCode.USER_NOT_LOGGED_IN_ERROR:
        console.log("User needs to be logged in");
        break;
      case VibeCodingPurchasesErrorCode.CONFIGURATION_ERROR:
        console.log("SDK configuration error");
        break;
      case VibeCodingPurchasesErrorCode.PURCHASE_IN_PROGRESS_ERROR:
        console.log("Another purchase is already in progress");
        break;
      case VibeCodingPurchasesErrorCode.PRODUCT_NOT_AVAILABLE_ERROR:
        console.log("Product not available");
        break;
      // Handle other error codes...
    }
  }
}

Available Error Codes

  • UNKNOWN_ERROR - Unknown error occurred
  • PURCHASE_CANCELLED_ERROR - User cancelled the purchase
  • STORE_PROBLEM_ERROR - Store/platform error
  • NETWORK_ERROR - Network connectivity issue
  • INVALID_CREDENTIALS_ERROR - Invalid API credentials
  • INVALID_APP_USER_ID_ERROR - Invalid user ID provided
  • CONFIGURATION_ERROR - SDK configuration issue
  • USER_NOT_LOGGED_IN_ERROR - User needs to be logged in
  • RECEIPT_VALIDATION_ERROR - Receipt validation failed
  • PURCHASE_IN_PROGRESS_ERROR - Another purchase is in progress
  • PRODUCT_NOT_AVAILABLE_ERROR - Product not found or unavailable
  • PLATFORM_NOT_SUPPORTED_ERROR - Platform doesn't support purchases

Platform Support

  • iOS: Full support via App Store (uses expo-iap in Expo development builds)
  • Android: Full support via Google Play (uses expo-iap in Expo development builds)
  • Web: Limited support - redirects to web-based checkout (Stripe)
  • Expo Go: Not supported - displays helpful error messages and guidance
  • React Native: Full support with react-native-iap integration

Platform Detection

The SDK automatically detects the platform and adjusts behavior accordingly:

import {
  getPlatform,
  isExpo,
  isExpoGo,
  isReactNative,
} from "@vibecoding/purchases";

const platform = getPlatform(); // "ios" | "android" | "web"
const isExpoEnvironment = isExpo(); // boolean
const isRunningInExpoGo = isExpoGo(); // boolean
const isReactNativeApp = isReactNative(); // boolean

Advanced Usage

Direct API Client Access

For advanced use cases, you can access the API client directly:

import { VibeCodingPurchases } from "@vibecoding/purchases";

const purchases = VibeCodingPurchases.getSharedInstance();
const apiClient = purchases.apiClient;

// Make direct API calls
const customerInfo = await apiClient.getCustomerInfo("user-123");
const offerings = await apiClient.getOfferings("apple");
const loginResult = await apiClient.login("user-123");
const purchaseResult = await apiClient.processPurchase(
  "user-123",
  "product-id",
  "receipt-data",
  "transaction-id" // optional, iOS only
);

React Native Specific Exports

For React Native projects, there are additional convenience exports:

import {
  initializeVibeCodingPurchases,
  usePurchases, // alias for useVibeCodingPurchases
} from "@vibecoding/purchases/react-native";

// Initialize with React Native defaults
const purchases = await initializeVibeCodingPurchases(
  {
    apiKey: "your-key",
    projectId: "your-project",
  },
  "user-123" // optional auto-login
);

Convenience SDK Export

The SDK also exports a convenience object with static methods:

import { VibeCodingPurchasesSDK } from "@vibecoding/purchases";

// All static methods available
const purchases = VibeCodingPurchasesSDK.configure(config);
const instance = VibeCodingPurchasesSDK.getSharedInstance();
await VibeCodingPurchasesSDK.initialize(config);
const isAnon = VibeCodingPurchasesSDK.isAnonymous();
const userId = VibeCodingPurchasesSDK.getUserId();
await VibeCodingPurchasesSDK.purchase("package-id");
await VibeCodingPurchasesSDK.logOut();

Development

Building the Package

# Install dependencies
npm install

# Build the package
npm run build

# Watch for changes during development
npm run dev

Testing

npm test

Linting

npm run lint
npm run lint:fix

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For support, email [email protected] or create an issue in the GitHub repository.