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 🙏

© 2025 – Pkg Stats / Ryan Hefner

buymeua-api-fe

v0.19.1

Published

TypeScript/JavaScript client for BuyMeUA API with RTK Query integration.

Readme

Buymeua API Frontend

TypeScript/JavaScript client for BuyMeUA API with RTK Query integration.

npm version License: ISC

🚀 Installation

npm install buymeua-api-fe @reduxjs/toolkit react-redux
# or
yarn add buymeua-api-fe @reduxjs/toolkit react-redux
# or
pnpm add buymeua-api-fe @reduxjs/toolkit react-redux

📖 Quick Start

Table of Contents

1. Configure API and Setup Redux Store

import { configureStore } from '@reduxjs/toolkit';
import { configureBuymeuaApi, Session } from 'buymeua-api-fe';

// Configure API before store setup
const buymeuaApi = configureBuymeuaApi({
  baseUrl: 'https://api.buymeua.com/',
  prepareHeaders: (headers) => {
    headers.set('Accept', 'application/json');
    headers.set('Content-Type', 'application/json');

    headers.set('X-SESSION', Session.Dropshipper);

    const token = localStorage.getItem('auth-token');
    if (token) {
      headers.set('Authorization', `Bearer ${token}`);
    }
  },
  onUnauthorized: (args, api, extraOptions) => {
    // Handle 401 errors with full request context
    console.log('Unauthorized request:', args);
    localStorage.removeItem('auth-token');
    window.location.href = '/login';
  },
});

// Setup Redux store
export const store = configureStore({
  reducer: {
    [buymeuaApi.reducerPath]: buymeuaApi.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(buymeuaApi.middleware),
});

2. Usage in React Components

import React from 'react';
import { useGetProductsInfiniteQuery } from 'buymeua-api-fe';

function ProductList() {
  const { data, isLoading, error, fetchNextPage, hasNextPage } = useGetProductsInfiniteQuery({
    per_page: 20,
    core_filter: 'phone'
  });

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error loading products</div>;

  return (
    <div>
      {data?.pages.map((page, pageIndex) => (
        <div key={pageIndex}>
          {page.data.map((product) => (
            <div key={product.id}>{product.name}</div>
          ))}
        </div>
      ))}
      {hasNextPage && (
        <button onClick={() => fetchNextPage()}>Load More</button>
      )}
    </div>
  );
}

📚 API Reference

Configuration

configureBuymeuaApi(config: ApiConfig)

Configures the global API client.

Parameters:

  • config.baseUrl - Base API URL
  • config.prepareHeaders - Function to prepare headers (receives Headers object and API context)
  • config.onUnauthorized - Optional callback for handling 401 errors (receives args, api, extraOptions for context)

Returns: Configured API instance ready for Redux store setup

Products

// Get products list with infinite scroll
const { data, fetchNextPage, hasNextPage } = useGetProductsInfiniteQuery({
  per_page?: number;
  core_filter?: string;
  filter_has_special?: boolean | null;
  order_by?: string | string[];
  category_filter?: number[];
  option_value_filter?: {
    option_value_ids: number[];
    warehouse_ids: number[];
  };
  attribute_filter?: {
    attribute_ids: number[];
    attribute_values: `${number}:$${number}`[];
  };
  filter_customer_id?: number;
  filter_has_customer_id?: boolean;
  filter_advertised?: boolean;
  filter_product_ids?: number[];
  filter_exclude_product_ids?: number[];
  price_from?: number;
  price_to?: number;
  retail_price_from?: number;
  retail_price_to?: number;
  margin_from?: number;
  margin_to?: number;
  only_in_root_category?: boolean;
  price_type?: string;
});

// Get products by QR code
const { data, fetchNextPage, hasNextPage } = useGetProductsByQrInfiniteQuery({
  'filter[barcode]'?: string;
  'filter[product_id]'?: number;
  core_filter?: string;
  per_page?: number;
});

// Get single product by ID
const { data } = useGetProductQuery({ product: number });

// Get product statistics
const { data } = useGetProductStatisticsQuery({ product: number });

// Get bestsellers
const { data } = useGetBestSellersQuery({
  best_seller_days_filter?: number;
  filter_customer_id?: number;
  filter_has_suppliers?: boolean;
  category_filter?: number[];
});

// Get product details
const { data } = useGetProductDetailsQuery({ product: number });

// Get product attributes for filtering
const { data } = useGetProductAttributesQuery({
  search?: string;
  product_id?: number;
  category_id?: number;
  attribute_ids?: number[];
  option_value_filter?: {
    option_value_ids?: number[];
    warehouse_ids?: number[];
  };
  attribute_filter?: {
    attribute_ids?: number[];
    attribute_values?: `${number}:${string}`[];
  };
});

// Get product options for filtering
const { data } = useGetProductOptionsQuery({
  search?: string;
  product_id?: number;
  category_id?: number;
  option_id?: number;
  option_value_ids?: number[];
  warehouse_ids?: number[];
  attribute_filter?: {
    attribute_ids?: number[];
    attribute_values?: `${number}:${string}`[];
  };
});

// Get supplier products with infinite scroll
const { data, fetchNextPage, hasNextPage } = useGetSupplierProductsInfiniteQuery({
  core_filter?: string;
  category_filter?: number[];
  buyme_category_filter?: number[];
  filter_buyme_category_set_main_category?: boolean;
  filter_customer_id?: number;
  filter_advertised?: boolean;
  only_in_root_category?: boolean;
  option_value_filter?: {
    option_value_ids?: number[];
    warehouse_ids?: number[];
  };
  price_from?: number;
  price_to?: number;
  per_page?: number;
  price_type?: 'price' | 'price_drop';
});

// Get supplier product details
const { data } = useGetSupplierProductDetailsQuery({ id: number });

Cart

// Get cart count
const { data } = useGetCartCountQuery();

// Get cart merchants
const { data, fetchNextPage, hasNextPage } = useGetCartMerchantsInfiniteQuery({
  per_page?: number;
});

// Get cart merchant items
const { data, fetchNextPage, hasNextPage } = useGetCartMerchantItemsInfiniteQuery({
  merchant_id: number;
  per_page?: number;
});

// Add item to cart
const [addToCart] = useAddToCartMutation();
await addToCart({
  product_type: string;
  product_id: number;
  product_option_value_id: number;
  quantity: number;
  warehouse_id: number | null; // only for buyme products
});

// Remove item from cart
const [removeFromCart] = useRemoveItemFromCartMutation();
await removeFromCart({
  cart_item_id: number;
  merchantId: number;
  quantity: number;
});

// Remove entire merchant from cart
const [removeMerchant] = useRemoveMerchantFromCartMutation();
await removeMerchant({ merchant_id: number });

// Update cart item quantity
const [updateQuantity] = useUpdateCartItemQuantityMutation();
await updateQuantity({
  cart_item_option_value_id: number;
  quantity: number;
  type: 'increase' | 'decrease';
  merchantId: number;
  optionIndex: number;
});

// Toggle gift package
const [toggleGift] = useToggleGiftPackageMutation();
await toggleGift({
  gift_package: boolean;
  merchantId: number;
});

Authentication

// Sign in with phone number
const [signIn] = useSignInMutation();
await signIn({
  telephone: string;
});

// Confirm verification code
const [confirmCode] = useConfirmCodeMutation();
await confirmCode({
  telephone: string;
  code: string;
});

// Sign up
const [signUp] = useSignUpMutation();
await signUp({
  telephone: string;
  firstname: string;
  lastname: string;
  term: 1;
});

// Register as guest
const [registerGuest] = useRegisterGuestMutation();
const { data } = await registerGuest(); // Returns Customer with token

// Logout
const [logout] = useLogoutMutation();
await logout();

Customer Account

// Save customer settings
const [saveSettings] = useSaveCustomerSettingsMutation();
await saveSettings({
  firstname: string;
  lastname: string;
  middlename: string;
  iban: string;
  card_fio: string;
  ederpou: string;
  avatar: string;
  email?: string;
});

// Delete customer account
const [deleteAccount] = useDeleteCustomerAccountMutation();
await deleteAccount();

Categories

// Get categories tree (full hierarchy)
const { data } = useGetCategoriesQuery({
  search?: string;
  filter_parent_id?: number;
  filter_with_products?: boolean;
  filter_with_supplier_products?: boolean;
  filter_prepared_for_site?: boolean;
});

// Build category breadcrumbs
import { useCategoryBreadcrumbs } from 'buymeua-api-fe';
const { breadcrumbs, isLoading } = useCategoryBreadcrumbs(categoryId);
// Returns array of categories from root to current

// Get supplier categories
const { data, fetchNextPage, hasNextPage } = useGetSupplierCategoriesInfiniteQuery({
  customer: number;
  parent_id?: number;
  per_page?: number;
});

// Get Buyme categories
const { data, fetchNextPage, hasNextPage } = useGetBuymeCategoriesInfiniteQuery({
  search?: string;
  parent_id?: number;
  customer_id?: number;
  per_page?: number;
});

Favorites

// Get favorite count
const { data } = useGetFavoriteCountQuery();

// Get favorite merchants
const { data, fetchNextPage, hasNextPage } = useGetFavoriteMerchantsInfiniteQuery({
  per_page?: number;
});

// Get favorite merchant items
const { data, fetchNextPage, hasNextPage } = useGetFavoriteMerchantItemsInfiniteQuery({
  merchant_id: number;
});

// Add to favorites
const [addToFavorite] = useAddFavoriteMerchantItemMutation();
await addToFavorite({
  product_type: string;
  product_id: number;
  optimisticUpdate?: {
    product: BaseProduct; // For optimistic UI updates
  };
});

// Remove from favorites
const [removeFromFavorite] = useDeleteFavoriteMerchantItemMutation();
await removeFromFavorite({
  product_type: string;
  product_id: number;
  optimisticUpdate?: {
    product: BaseProduct; // For optimistic UI updates
  };
});

Chat

// Get chat list
const { data, fetchNextPage, hasNextPage } = useGetChatsInfiniteQuery({
  per_page?: number;
});

// Get chat info
const { data } = useGetChatInfoQuery({
  customerChatThread: number;
});

// Get chat messages
const { data, fetchNextPage, hasNextPage } = useGetChatInfiniteQuery({
  customerChatThreadId: number;
  per_page?: number;
});

// Get single chat message
const { data } = useGetChatMessageQuery({
  customerChatThreadId: number;
  customerChatId: number;
});

// Create chat
const [createChat] = useCreateChatMutation();
await createChat({
  customer_id: number;
  supplier_id: number | null;
  admin_id: number | null;
});

// Send message
const [sendMessage] = useSendChatMessageMutation();
await sendMessage({
  customerChatThreadId: number;
  message: string;
  medias: File[];
});

// Update message
const [updateMessage] = useUpdateChatMessageMutation();
await updateMessage({
  customerChatThreadId: number;
  customerChatId: number;
  message: string;
  medias: File[];
});

// Mark messages as read
const [markAsRead] = useMarkChatMessagesAsReadMutation();
await markAsRead({
  customerChatThreadId: number;
  chats: number[]; // Message IDs
});

// Delete chat
const [deleteChat] = useDeleteChatMutation();
await deleteChat({
  customerChatThread: number;
  customer_id: number;
});

// Delete message
const [deleteMessage] = useDeleteChatMessageMutation();
await deleteMessage({
  customerChatThread: number;
  chat: number; // Message ID
});

// Resend message
const [resendMessage] = useResendChatMessageMutation();
await resendMessage({
  customerChatThreadId: number;
  customerChatId: number;
  message: string;
  medias: File[];
});

Notifications

// Get notifications
const { data, fetchNextPage, hasNextPage } = useGetNotificationsInfiniteQuery({
  per_page?: number;
  'filter[type]'?: string;
  'filter[event]'?: string;
  'filter[date_from]'?: string;
  'filter[date_to]'?: string;
});

// Get single notification
const { data } = useGetNotificationQuery({
  notification: number;
});

// Get notifications count
const { data } = useGetNotificationsCountQuery();

// Get new suppliers count
const { data } = useGetNewSuppliersCountQuery();

// Mark all as read
const [markAllAsRead] = useMarkAllNotificationsAsReadMutation();
await markAllAsRead();

// Mark single notification as read
const [markAsRead] = useMarkNotificationAsReadMutation();
await markAsRead({ notification: number });

// Delete all notifications
const [deleteAll] = useDeleteAllNotificationsMutation();
await deleteAll();

// Delete single notification
const [deleteNotification] = useDeleteNotificationMutation();
await deleteNotification({ notification: number });

Stories

// Get stories
const { data, fetchNextPage, hasNextPage } = useGetStoriesInfiniteQuery({
  sort_type?: 'created_at' | 'views_count' | 'sort_order' | 'viewed_order';
  sort_direction?: 'asc' | 'desc';
  per_page?: number;
});

// Increase story views
const [increaseViews] = useIncreaseStoryViewsMutation();
await increaseViews({ story: number });

Suppliers

// Get suppliers list
const { data, fetchNextPage, hasNextPage } = useGetSuppliersInfiniteQuery({
  per_page?: number;
  search?: string;
  filter_buyme_category_ids?: number[];
});

// Get supplier info
const { data } = useGetSupplierInfoQuery({
  customer: number;
});

// Get supplier articles
const { data, fetchNextPage, hasNextPage } = useGetSupplierArticlesInfiniteQuery({
  customer: number;
  per_page?: number;
  'filter[id]'?: number;
  'filter[translations.title]'?: string;
  'filter[translations.content]'?: string;
  'filter[date_from]'?: string;
  'filter[date_to]'?: string;
});

// Get supplier reviews
const { data, fetchNextPage, hasNextPage } = useGetSupplierReviewsInfiniteQuery({
  supplier_id: number;
  per_page?: number;
  rating?: number;
  has_reply?: boolean;
  date_from?: string;
  date_to?: string;
  sort_by?: 'rating' | 'created_at';
  sort_direction?: 'asc' | 'desc';
});

// Get supplier rating
const { data } = useGetSupplierRatingQuery({
  supplier_id: number;
});

// Add supplier review
const [addReview] = useAddSupplierReviewMutation();
await addReview({
  supplier_id: number;
  rating: number;
  text: string;
});

// Reply to supplier review
const [replyToReview] = useReplyToSupplierReviewMutation();
await replyToReview({
  review_id: number;
  reply_text: string;
});

// Mark supplier as old
const [markAsOld] = useMarkSupplierAsOldMutation();
await markAsOld({ supplier: number });

Nova Poshta

// Get Nova Poshta cities
const { data, fetchNextPage, hasNextPage } = useGetNovaposhtaCitiesInfiniteQuery({
  search?: string;
  area?: string;
  settlement_type?: string;
  is_branch?: boolean;
  per_page?: number;
});

// Get Nova Poshta streets
const { data, fetchNextPage, hasNextPage } = useGetNovaposhtaStreetsInfiniteQuery({
  search?: string;
  city_ref: string;
  streets_type?: string;
  per_page?: number;
});

// Get Nova Poshta warehouses
const { data, fetchNextPage, hasNextPage } = useGetNovaposhtaWarehousesInfiniteQuery({
  search?: string;
  city_ref: string;
  type?: string;
  per_page?: number;
});

Orders

// Check telephone number (blacklist, duplicates)
const { data } = useCheckTelephoneQuery({
  telephone: string;
});

// Get delivery methods for merchant
const { data } = useGetDeliveryMethodsQuery({
  merchant_id: number;
});

// Get payment methods for merchant
const { data } = useGetPaymentMethodsQuery({
  merchant_id: number;
  custom_ttn?: string;
  delivery_method_code?: string;
});

// Create order
const [createOrder] = useCreateOrderMutation();
await createOrder({
  merchant_id: number;
  payment_method_code: string;
  delivery_method_code?: string;
  custom_ttn?: string;
  firstname?: string;
  lastname?: string;
  middlename?: string;
  telephone?: string;
  email?: string;
  comment?: string;
  city_ref?: string;
  warehouse_ref?: string;
  shipping_street_id?: number;
  shipping_house?: string;
  shipping_flat?: string;
  country_id?: number;
  city?: string;
  address?: string;
  total_pay?: number;
  custom_customer_id?: number;
  category_order_id?: number;
  ad_platform_page_id?: number;
  ad_new_client?: boolean;
});

Referrals

// Get referral statistics
const { data, fetchNextPage, hasNextPage } = useGetReferralStatisticsInfiniteQuery({
  date_from?: string;
  date_to?: string;
  per_page?: number;
});

// Get referral transactions
const { data, fetchNextPage, hasNextPage } = useGetReferralTransactionsInfiniteQuery({
  referral_id: number;
  date_from?: string;
  date_to?: string;
  per_page?: number;
});

// Track referral visit
const [trackVisit] = useTrackReferralVisitMutation();
await trackVisit({
  referral_id: number;
});

Ads

// Get ad pages
const { data } = useGetAdPagesQuery({
  platform_id: number;
});

// Get ad platforms
const { data, fetchNextPage, hasNextPage } = useGetAdPlatformsInfiniteQuery({
  per_page?: number;
});

Countries

// Get countries list
const { data, fetchNextPage, hasNextPage } = useGetCountriesInfiniteQuery({
  search?: string;
  per_page?: number;
});

Store

// Get store information
const { data } = useGetStoreInfoQuery({
  store: number;
});

// Get store articles/informations
const { data } = useGetStoreArticlesQuery({
  store: number;
});

📋 TypeScript Types

The library is fully typed with TypeScript. Main types:

interface ApiConfig {
  baseUrl: string;
  prepareHeaders?: (
    headers: Headers,
    api: {
      getState: () => unknown;
      extra: unknown;
      endpoint: string;
      type: 'query' | 'mutation';
      forced?: boolean;
    } & {
      arg: unknown;
      extraOptions: unknown;
    },
  ) => Headers | void | Promise<void>;
  onUnauthorized?: (
    args: string | FetchArgs,
    api: BaseQueryApi,
    extraOptions: unknown,
  ) => void;
}

enum Session {
  Dropshipper = 'dropshipper',
  Supplier = 'supplier',
  Retail = 'retail',
}

interface PaginatedResponse {
  meta: {
    current_page: number;
    last_page: number;
    per_page: number;
    total: number;
    from: number;
    to: number;
  };
  links: {
    first: string;
    last: string;
    prev: string | null;
    next: string | null;
  };
}

📄 License

ISC License - see the LICENSE file for details.