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

@koia-ai/koia-eshop-sdk

v1.0.16

Published

A configurable React context provider for e-commerce functionality with cart management, discount codes, order processing, and API client for product management

Downloads

5

Readme

Koia Eshop SDK

A configurable React context provider for e-commerce functionality with cart management, discount codes, order processing, and API client for product management.

Features

  • 🛒 Cart Management: Add, remove, and manage cart items
  • 🏷️ Discount Codes: Configurable discount code system
  • 💾 Persistence: Automatic localStorage persistence
  • 🔧 Configurable: Customizable API endpoints and storage keys
  • 📦 TypeScript: Full TypeScript support
  • 🎯 Framework Agnostic: Works with any React setup
  • 🌐 API Client: Built-in client for product management and API calls

Installation

npm install @koia-ai/koia-eshop-sdk

or

yarn add @koia-ai/koia-eshop-sdk

Quick Start

React Context Provider (Cart Management)

import { EshopProvider, useEshop } from '@koia-ai/koia-eshop-sdk';

// Configure your eshop
const config = {
  discountCodes: {
    'SAVE10': 10,
    'SAVE20': 20,
    'FREESHIP': 0 // Special code for free shipping
  },
  apiEndpoint: '/api/orders',
  storageKeys: {
    cart: 'my-cart',
    discountCode: 'my-discount',
    discountPercentage: 'my-discount-percentage'
  }
};

function App() {
  return (
    <EshopProvider config={config}>
      <YourApp />
    </EshopProvider>
  );
}

function ProductComponent() {
  const { addToCart } = useEshop();
  
  const handleAddToCart = () => {
    addToCart({
      id: 'product-1',
      name: 'Awesome Product',
      price: 29.99,
      quantity: 1
    });
  };

  return (
    <button onClick={handleAddToCart}>
      Add to Cart
    </button>
  );
}

API Client (Product Management)

import { useEshopClient } from '@koia-ai/koia-eshop-sdk';

function ProductList() {
  const eshop = useEshopClient(supabaseUrl, supabaseKey, baseUrl);
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(false);

  const fetchProducts = async (organizationId: string) => {
    setLoading(true);
    const { data, error } = await eshop.getProducts(organizationId);
    
    if (error) {
      console.error('Failed to fetch products:', error);
    } else {
      setProducts(data || []);
    }
    setLoading(false);
  };

  useEffect(() => {
    fetchProducts('your-organization-id');
  }, []);

  return (
    <div>
      {loading ? (
        <p>Loading products...</p>
      ) : (
        products.map(product => (
          <div key={product.id}>
            <h3>{product.name}</h3>
            <p>{product.description}</p>
            <p>${product.price}</p>
          </div>
        ))
      )}
    </div>
  );
}

Configuration

EshopConfig Interface

interface EshopConfig {
  discountCodes?: Record<string, number>; // Discount code -> percentage
  apiEndpoint?: string; // API endpoint for order creation
  storageKeys?: {
    cart?: string; // localStorage key for cart
    discountCode?: string; // localStorage key for discount code
    discountPercentage?: string; // localStorage key for discount percentage
  };
}

Default Configuration

const defaultConfig: EshopConfig = {
  discountCodes: {},
  apiEndpoint: '/api/orders',
  storageKeys: {
    cart: 'cart',
    discountCode: 'discountCode',
    discountPercentage: 'discountPercentage'
  }
};

API Reference

EshopProvider

The main context provider component.

<EshopProvider config={config}>
  {children}
</EshopProvider>

Props:

  • children: React children components
  • config: Optional configuration object

useEshop Hook

Returns the eshop context with all available methods and state.

const {
  cart,
  addToCart,
  removeFromCart,
  removeOneFromCart,
  clearCart,
  applyDiscountCode,
  removeDiscountCode,
  discountCode,
  discountPercentage,
  subtotal,
  total,
  shippingCost,
  setShippingCost,
  finalizeOrder
} = useEshop();

EshopClient

Client class for making API calls with authentication.

const eshop = useEshopClient(supabaseUrl, supabaseKey, baseUrl);

// Set authentication token
eshop.setAccessToken('your-access-token');

// Fetch products
const { data: products, error } = await eshop.getProducts(organizationId);

// Make custom API requests
const { data, error } = await eshop.makeRequest('/api/custom-endpoint');

useEshopClient Hook

Hook to create and manage an EshopClient instance.

const client = useEshopClient(supabaseUrl, supabaseKey, baseUrl);

Cart Management

Adding Items

const { addToCart } = useEshop();

addToCart({
  id: 'product-1',
  name: 'Product Name',
  price: 29.99,
  quantity: 2
});

Removing Items

const { removeFromCart, removeOneFromCart } = useEshop();

// Remove all quantities of an item
removeFromCart('product-1');

// Remove one quantity of an item
removeOneFromCart('product-1');

Clearing Cart

const { clearCart } = useEshop();

clearCart(); // Clears cart and resets discount information

Product Management

Fetching Products

const eshop = useEshopClient(supabaseUrl, supabaseKey, baseUrl);

const { data: products, error } = await eshop.getProducts(organizationId);

if (error) {
  console.error('Failed to fetch products:', error);
} else {
  console.log('Products:', products);
}

Authentication

const eshop = useEshopClient(supabaseUrl, supabaseKey, baseUrl);

// Set access token for authenticated requests
eshop.setAccessToken('your-access-token');

// Clear access token
eshop.clearAccessToken();

Discount Codes

Applying Discount Codes

const { applyDiscountCode } = useEshop();

const handleApplyCode = (code: string) => {
  const isValid = applyDiscountCode(code);
  if (isValid) {
    console.log('Discount applied!');
  } else {
    console.log('Invalid discount code');
  }
};

Removing Discount Codes

const { removeDiscountCode } = useEshop();

removeDiscountCode(); // Removes current discount code

Order Processing

Finalizing Orders

const { finalizeOrder } = useEshop();

const handleCheckout = async () => {
  try {
    const customerInfo = {
      name: 'John Doe',
      email: '[email protected]',
      address: '123 Main St'
    };

    const result = await finalizeOrder(customerInfo);
    console.log('Order created:', result.order);
  } catch (error) {
    console.error('Order failed:', error);
  }
};

State Values

Cart Information

const { cart, subtotal, total, shippingCost } = useEshop();

// cart: Array of CartItem objects
// subtotal: Sum of all items before discount and shipping
// total: Final total including discount and shipping
// shippingCost: Current shipping cost

Discount Information

const { discountCode, discountPercentage } = useEshop();

// discountCode: Current applied discount code (string | null)
// discountPercentage: Current discount percentage (number)

Complete Example

import React, { useState, useEffect } from 'react';
import { EshopProvider, useEshop, useEshopClient } from '@koia-ai/koia-eshop-sdk';

const config = {
  discountCodes: {
    'SAVE10': 10,
    'SAVE20': 20
  },
  apiEndpoint: '/api/orders'
};

function ProductList() {
  const eshop = useEshopClient(supabaseUrl, supabaseKey, baseUrl);
  const { addToCart } = useEshop();
  const [products, setProducts] = useState([]);

  useEffect(() => {
    const fetchProducts = async () => {
      const { data, error } = await eshop.getProducts('your-org-id');
      if (!error && data) {
        setProducts(data);
      }
    };
    fetchProducts();
  }, []);

  return (
    <div>
      {products.map(product => (
        <div key={product.id}>
          <h3>{product.name}</h3>
          <p>{product.description}</p>
          <p>${product.price}</p>
          <button onClick={() => addToCart({
            id: product.id,
            name: product.name,
            price: product.price,
            quantity: 1
          })}>
            Add to Cart
          </button>
        </div>
      ))}
    </div>
  );
}

function CartComponent() {
  const { 
    cart, 
    addToCart, 
    removeFromCart, 
    subtotal, 
    total,
    applyDiscountCode,
    discountCode 
  } = useEshop();
  
  const [discountInput, setDiscountInput] = useState('');

  const handleApplyDiscount = () => {
    const success = applyDiscountCode(discountInput);
    if (success) {
      setDiscountInput('');
    }
  };

  return (
    <div>
      <h2>Shopping Cart</h2>
      
      {cart.map(item => (
        <div key={item.id}>
          <span>{item.name}</span>
          <span>${item.price} x {item.quantity}</span>
          <button onClick={() => removeFromCart(item.id)}>Remove</button>
        </div>
      ))}
      
      <div>
        <p>Subtotal: ${subtotal}</p>
        <p>Total: ${total}</p>
        {discountCode && <p>Discount: {discountCode}</p>}
      </div>
      
      <div>
        <input
          value={discountInput}
          onChange={(e) => setDiscountInput(e.target.value)}
          placeholder="Enter discount code"
        />
        <button onClick={handleApplyDiscount}>Apply</button>
      </div>
    </div>
  );
}

function App() {
  return (
    <EshopProvider config={config}>
      <ProductList />
      <CartComponent />
    </EshopProvider>
  );
}

Types

CartItem

interface CartItem {
  id: string;
  name: string;
  price: number;
  quantity: number;
}

Product

interface Product {
  id: string;
  name: string;
  description: string;
  price: number;
  organization_id: string;
  created_at: string;
  updated_at: string;
  organizations: {
    id: string;
    name: string;
    slug: string;
  };
}

EshopContextType

interface EshopContextType {
  cart: CartItem[];
  addToCart: (item: CartItem) => void;
  removeFromCart: (id: string) => void;
  removeOneFromCart: (id: string) => void;
  clearCart: () => void;
  applyDiscountCode: (code: string) => boolean;
  removeDiscountCode: () => void;
  discountCode: string | null;
  discountPercentage: number;
  subtotal: number;
  total: number;
  shippingCost: number;
  setShippingCost: (cost: number) => void;
  finalizeOrder: (customerInfo: any) => Promise<{ order: any }>;
}

ApiResponse

interface ApiResponse<T> {
  data?: T;
  error?: string;
}

Error Handling

The useEshop hook will throw an error if used outside of an EshopProvider:

try {
  const { cart } = useEshop();
} catch (error) {
  console.error('useEshop must be used within an EshopProvider');
}

API calls return consistent error format:

const { data, error } = await eshop.getProducts(organizationId);

if (error) {
  console.error('API Error:', error);
} else {
  console.log('Products:', data);
}

Browser Support

This package uses localStorage for persistence, which is supported in all modern browsers. For older browsers, consider using a polyfill.

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.