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

@bzbs/react-providers

v3.0.0

Published

A collection of React Context Provider for Buzzebees apps

Downloads

520

Readme

@bzbs/react-providers

Version: 2.7.8 | License: ISC | Author: Buzzebees Co., Ltd. Repository: Azure DevOps

A collection of React state management providers and Zustand stores for Buzzebees loyalty/reward apps. This package is the implementation layer on top of @bzbs/react-api-client, wrapping API calls with React-friendly state, actions, and side-effects (analytics, token management, event broadcasting).

⚠️ Important: The Context API layer (/providers, ./context export) is deprecated. All new development must use the Zustand stores (@bzbs/react-providers/zustand). The Context API docs are retained for migration reference only.


Table of Contents


Installation

npm install @bzbs/react-providers

Peer dependencies:

npm install react react-dom axios

Also required (provides BzbsService):

npm install @bzbs/react-api-client

Architecture Overview

@bzbs/react-providers
├── Zustand Stores    ← Recommended: import from '@bzbs/react-providers/zustand'
├── Context Providers ← DEPRECATED: import from '@bzbs/react-providers/context'
├── Service Utilities ← HTTP interceptors, URL helpers, event emitter
├── Analytics Utils   ← Matomo tracking wrappers
├── Locale Utils      ← Locale → LCID mapping
└── Constants         ← Campaign types, point types

Dependencies flow:

@bzbs/react-api-client (BzbsService)
    ↓
useBuzzebeesAppStore  ← Central config store
    ↓
useAuthStore, useUserStore, useCartStore, ...  ← Feature stores

All feature stores read bzbsService from useBuzzebeesAppStore to make API calls. You must call useBuzzebeesAppStore.getState().configure(...) (or use individual setters) before using any other store.


Quick Start (Zustand)

import axios from 'axios';
import { BzbsService } from '@bzbs/react-api-client';
import {
  useBuzzebeesAppStore,
  addDefaultHeaderInterceptor,
  useAuthStore,
} from '@bzbs/react-providers/zustand';

// 1. Create an Axios instance
const axiosClient = axios.create({
  headers: {
    'Content-Type': 'application/json',
    'App-Id': 'YOUR_APP_ID',
    'Ocp-Apim-Subscription-Key': 'YOUR_SUBSCRIPTION_KEY',
  },
});

// 2. Create the BzbsService instance
const bzbsService = new BzbsService(axiosClient, 'https://api.buzzebees.com');

// 3. Define token persistence functions
const tokenFunctions = {
  getToken: async () => localStorage.getItem('bzbs_token'),
  setToken: (token: string) => localStorage.setItem('bzbs_token', token),
  removeToken: () => localStorage.removeItem('bzbs_token'),
};

// 4. Attach auth/header interceptors
addDefaultHeaderInterceptor(
  axiosClient,
  'YOUR_APP_ID',
  'YOUR_SUBSCRIPTION_KEY',
  tokenFunctions,
  '1.0'
);

// 5. Configure the central app store (call this once at app startup)
useBuzzebeesAppStore.getState().configure({
  appId: 'YOUR_APP_ID',
  appName: 'your-app',
  bzbsService,
  tokenFunctions,
  tokenType: 'jwt',
  urls: {
    webCallback: 'https://yourapp.com/callback',
    cart: 'https://cart.buzzebees.com',
  },
  config: {
    defaultDashboardConfig: 'main',
    defaultDashboardMode: 'main',
    defaultMenuConfig: 'default',
    defaultCampaignConfig: 'default',
  },
});

// 6. Use stores in components
function LoginScreen() {
  const { isLoading, isLoggedIn, actions } = useAuthStore();

  const handleLogin = async () => {
    const result = await actions.loginWithUsernamePassword('[email protected]', 'password');
    if (result.type === 'success') {
      console.log('Logged in!');
    }
  };

  return <button onClick={handleLogin} disabled={isLoading}>Login</button>;
}

Package Exports

| Import Path | Contents | |---|---| | @bzbs/react-providers | Everything: all providers, stores, utils, constants, services | | @bzbs/react-providers/zustand | Zustand stores + utils + constants + services (recommended) | | @bzbs/react-providers/context | Context providers + utils + constants + services (deprecated) |


Zustand Stores Reference

All stores are available from @bzbs/react-providers/zustand.


useBuzzebeesAppStore

Central configuration store. Must be configured before any other store is used.

import { useBuzzebeesAppStore } from '@bzbs/react-providers/zustand';

State:

type BuzzebeesAppState = {
  appId: string;
  appName: string;
  bzbsService: BzbsService | null;
  uuid: string;
  macAddress: string;
  clientVersion: string;
  os: string;
  platform: string;
  fcmToken: string;
  deviceNotificationEnabled: boolean;
  urls: { webCallback: string; cart: string };
  tokenFunctions: TokenFunctions | null;
  tokenType: AuthTokenType;          // 'jwt' | 'auth_token'
  config: {
    defaultDashboardConfig: string;
    defaultDashboardMode: 'main' | 'sub';
    defaultMenuConfig: string;
    defaultCampaignConfig: string;
  };
};

Actions:

type BuzzebeesAppActions = {
  // Bulk configure — call this once at app startup
  configure(config: {
    appId: string;
    appName: string;
    bzbsService: BzbsService;
    tokenFunctions: TokenFunctions;
    tokenType?: AuthTokenType;
    uuid?: string;
    macAddress?: string;
    clientVersion?: string;
    os?: string;
    platform?: string;
    fcmToken?: string;
    deviceNotificationEnabled?: boolean;
    urls: { webCallback: string; cart: string };
    config?: {
      defaultDashboardConfig?: string;
      defaultDashboardMode?: 'main' | 'sub';
      defaultMenuConfig?: string;
      defaultCampaignConfig?: string;
    };
  }): void;

  // Individual setters
  setAppId(appId: string): void;
  setAppName(appName: string): void;
  setBzbsService(service: BzbsService): void;
  setUuid(uuid: string): void;
  setMacAddress(macAddress: string): void;
  setClientVersion(clientVersion: string): void;
  setOs(os: string): void;
  setPlatform(platform: string): void;
  setFcmToken(fcmToken: string): void;
  setDeviceNotificationEnabled(enabled: boolean): void;
  setUrls(urls: { webCallback: string; cart: string }): void;
  setTokenType(tokenType: AuthTokenType): void;
  setTokenFunctions(tokenFunctions: TokenFunctions): void;
};

Usage:

// Access state in a component
const { appId, bzbsService } = useBuzzebeesAppStore();

// Access state outside React (e.g., service files)
const state = useBuzzebeesAppStore.getState();

useAuthStore

Manages the full authentication lifecycle: login, logout, OTP, token validation.

import { useAuthStore } from '@bzbs/react-providers/zustand';

State:

type AuthState = {
  isInitialized: boolean;
  versionData: Version | null;
  rawVersionData: unknown | null;
  data: LoginResponse | ResumeResponse | null;
  isLoading: boolean;
  isLoadingToken: boolean;
  error: ErrorResponse | null;
  token: string | null;
  isLoggedIn: boolean;
};

Actions:

type AuthActions = {
  // State setters
  setIsLoading(value: boolean): void;
  setIsLoadingToken(value: boolean): void;
  setError(value: unknown): void;

  // Check persisted token and restore session
  checkLoggedIn(): Promise<void>;

  // Login methods — all return ServiceResponse<LoginResponse>
  loginWithUsernamePassword(username: string, password: string): Promise<ServiceResponse<LoginResponse>>;
  loginWithGoogle(token: string): Promise<ServiceResponse<LoginResponse>>;
  loginWithFacebook(token: string): Promise<ServiceResponse<LoginResponse>>;
  loginWithApple(token: string, refreshToken: string): Promise<ServiceResponse<LoginResponse>>;
  loginWithUUID(): Promise<ServiceResponse<LoginResponse>>;
  loginWithOtp(otp: string, refCode: string, contact: string): Promise<ServiceResponse<LoginResponse>>;

  // Password management
  forgetPassword(contact: string, type: 'email' | 'contact_number'): Promise<ServiceResponse<ForgetPasswordResponse>>;
  resetPassword(contact: string, otp: string, refCode: string, password: string): Promise<ServiceResponse<StatusResponse>>;

  // OTP
  sendOtp(contact: string, channel: string): Promise<ServiceResponse<OtpResponse>>;
  validateOtp(otp: string, refCode: string, contact: string, channel: string, type: 'email' | 'contact_number'): Promise<ServiceResponse<ValidateOtpResponse>>;
  confirmOtp(otp: string, refCode: string, contact: string): Promise<ServiceResponse<ConfirmOtpResponse>>;

  // Apple Sign-In
  appleToken(authorizationCode: string, idToken: string): Promise<ServiceResponse<AppleToken>>;

  // Session management
  logout(): Promise<ServiceResponse<unknown>>;
  resume(clientVersion: string): Promise<ServiceResponse<ResumeResponse>>;
  version(clientVersion: string): Promise<ServiceResponse<Version>>;
  clear(): void;
};

Example:

const { isLoggedIn, isLoading, token, actions } = useAuthStore();

// Login
const res = await actions.loginWithUsernamePassword('[email protected]', 'secret');
if (res.type === 'success') { /* navigate to home */ }

// Check token on app start
useEffect(() => {
  actions.checkLoggedIn();
}, []);

// Logout
await actions.logout();

Note: After a successful login, useAuthStore automatically calls useUserStore.getState().fetchUser() and fires analytics events.


useUserStore

Manages the authenticated user's profile, points, badges, cart count, and traces.

import { useUserStore } from '@bzbs/react-providers/zustand';

State:

type UserState = {
  user: ProfileResponse | null;
  points: number;
  recentPoints: UpdatedPoints | null;
  expiringPoints: UpdatedPoints[];
  recentBadge: unknown | null;
  recentTrace: unknown | null;
  cartCount: number;
  isLoading: boolean;
  error: ErrorResponse | null;
  badgeList: unknown[];
  traceList: unknown[];
};

Actions:

type UserActions = {
  fetchUser(): Promise<ServiceResponse<ProfileResponse>>;
  fetchPoint(): Promise<void>;
  fetchExpiringPoints(): Promise<void>;
  fetchCartCount(): Promise<void>;

  editUser(params: UpdateProfileParams): Promise<ServiceResponse<ProfileResponse>>;
  changePassword(oldPassword: string, newPassword: string): Promise<ServiceResponse<unknown>>;
  changeContactNumber(contactNumber: string, otp: string, refCode: string): Promise<ServiceResponse<unknown>>;
  changeAvatar(file: File | Blob): Promise<ServiceResponse<unknown>>;
  deleteUser(): Promise<ServiceResponse<unknown>>;

  consumeRecentPoints(): void;
  consumeRecentBadge(): void;
  consumeRecentTrace(): void;

  setupEventListeners(): void;
  cleanupEventListeners(): void;

  setError(value: unknown): void;
  clear(): void;
};

type UpdateProfileParams = {
  firstName?: string;
  lastName?: string;
  email?: string;
  birthDate?: string;
  gender?: string;
  // ... additional profile fields from @bzbs/react-api-client
};

useCartStore

Fetches and tracks the number of items in the user's cart.

import { useCartStore } from '@bzbs/react-providers/zustand';

State:

type CartState = {
  count: number;
  isLoading: boolean;
  error: ErrorResponse | null;
};

Actions:

type CartActions = {
  fetchCount(): Promise<ServiceResponse<CartCountResponse>>;
  clear(): void;
};

useLocaleStore

Manages the app locale used for API requests.

import { useLocaleStore, EN, TH } from '@bzbs/react-providers/zustand';

State:

type LocaleState = {
  appLocale: AppLocale;
  locale: string;      // e.g. 'en', 'th'
  localeId: number;    // LCID e.g. 1033, 1054
};

type AppLocale = {
  locale: string;
  localeId: number;
};

Constants:

const EN: AppLocale = { locale: 'en', localeId: 1033 };
const TH: AppLocale = { locale: 'th', localeId: 1054 };

Actions:

type LocaleActions = {
  // Accepts an AppLocale object or a locale string like 'en', 'th-TH', 'en-US'
  setAppLocale(locale: AppLocale | string): void;
};

Example:

const { locale, localeId } = useLocaleStore();

// Set by locale string (resolves via findBestLocaleFromString)
useLocaleStore.getState().setAppLocale('th');

// Set by full AppLocale object
useLocaleStore.getState().setAppLocale(TH);

useAnalyticsStore

Manages Matomo analytics tracking.

import { useAnalyticsStore } from '@bzbs/react-providers/zustand';

State:

type AnalyticsState = {
  isInitialized: boolean;
  isEnabled: boolean;
  siteId: number;
  urlBase: string;
  trackerUrl: string | undefined;
  userId: string | undefined;
  disabled: boolean;
  log: boolean;
  matomoInstance: MatomoTracker | null;
  presetUserInfo: UserInfo | undefined;
};

Actions:

type AnalyticsActions = {
  initialize(config: {
    siteId: number;
    urlBase: string;
    trackerUrl?: string;
    userId?: string;
    disabled?: boolean;
    log?: boolean;
  }): void;

  setEnabled(enabled: boolean): void;
  setPresetUserInfo(userInfo: UserInfo): void;
  clearPresetUserInfo(): void;

  trackAppStart(userInfo?: UserInfo): Promise<void>;
  trackEvent(params: {
    action: string;
    name?: string;
    category?: string;
    value?: number;
    campaign?: string;
    userInfo?: UserInfo;
  }): Promise<void>;
  trackScreenView(params: { name: string; userInfo?: UserInfo }): Promise<void>;
  trackAction(params: { name: string; userInfo?: UserInfo }): Promise<void>;
  trackSiteSearch(params: {
    keyword: string;
    category?: string;
    count?: number;
    userInfo?: UserInfo;
  }): Promise<void>;
  trackLink(params: { link: string; userInfo?: UserInfo }): Promise<void>;
  trackDownload(params: { download: string; userInfo?: UserInfo }): Promise<void>;

  setUserId(userId: string | null): void;
  setCustomDimension(id: number, value: string): void;
  reset(): void;
};

useAlertStore

Manages alert/dialog display state.

import { useAlertStore } from '@bzbs/react-providers/zustand';

State:

type AlertState = {
  isOpen: boolean;
  request: AlertRequest | null;
};

type AlertRequest = {
  title?: string;
  message: string;
  confirmLabel?: string;
  onConfirm?: () => void;
};

Actions:

type AlertActions = {
  show(request: AlertRequest): void;
  hide(): void;
};

useConfirmStore

Manages confirmation dialog state.

import { useConfirmStore } from '@bzbs/react-providers/zustand';

State:

type ConfirmState = {
  isOpen: boolean;
  request: ConfirmRequest | null;
};

type ConfirmRequest = {
  title?: string;
  message: string;
  confirmLabel?: string;
  cancelLabel?: string;
  onConfirm?: () => void;
  onCancel?: () => void;
};

Actions:

type ConfirmActions = {
  show(request: ConfirmRequest): void;
  hide(): void;
};

usePopupStore

Manages popup/modal display state.

import { usePopupStore } from '@bzbs/react-providers/zustand';

State:

type PopupState = {
  isOpen: boolean;
  request: PopupRequest | null;
};

type PopupRequest = {
  content: React.ReactNode;
  onClose?: () => void;
};

Actions:

type PopupActions = {
  show(request: PopupRequest): void;
  hide(): void;
};

useLoadingIndicatorStore

Manages a global loading indicator with named loading keys.

import { useLoadingIndicatorStore, useLoading } from '@bzbs/react-providers/zustand';

State:

type LoadingIndicatorState = {
  loadingKeys: string[];
  isLoading: boolean;
};

Actions:

type LoadingIndicatorActions = {
  show(key?: string): void;
  hide(key?: string): void;
  clear(): void;
};

useLoading hook: A convenience hook for reading the current loading state.


useNotificationStore

Manages user notification list and unread count.

import { useNotificationStore } from '@bzbs/react-providers/zustand';

Wraps notificationApi from @bzbs/react-api-client. Actions include fetching notifications, marking as read, and clearing state.


useMaintenanceStore

Manages app maintenance mode state.

import { useMaintenanceStore } from '@bzbs/react-providers/zustand';

Fetches maintenance configuration from the API and exposes isMaintenance: boolean and maintenanceData.


useConsentStore

Manages user consent preferences (marketing, data sharing, etc.).

import { useConsentStore } from '@bzbs/react-providers/zustand';

Wraps consentApi from @bzbs/react-api-client. Exposes consent state and update actions.


useRegistrationStore

Manages user registration flow state.

import { useRegistrationStore } from '@bzbs/react-providers/zustand';

Wraps registrationApi. Handles multi-step registration: form data, OTP verification, and account creation.


useAddressStore

Manages user address book.

import { useAddressStore } from '@bzbs/react-providers/zustand';

Wraps addressApi. CRUD operations for user addresses.


useZipCodeStore

Fetches postal/zip code data for address forms.

import { useZipCodeStore } from '@bzbs/react-providers/zustand';

createCampaignsStore

Factory that creates a scoped campaigns list store. Use when you need multiple independent campaign list instances.

import { createCampaignsStore } from '@bzbs/react-providers/zustand';

const useMyCampaignsStore = createCampaignsStore();

Wraps campaignApi.getCampaigns(). Supports pagination, filtering, and config-based loading.


createCampaignDetailStore

Factory that creates a scoped campaign detail store.

import { createCampaignDetailStore } from '@bzbs/react-providers/zustand';

const useCampaignDetailStore = createCampaignDetailStore();

Wraps campaignApi.getCampaignDetail().


createCategoriesStore

Factory that creates a scoped categories/menu store.

import { createCategoriesStore } from '@bzbs/react-providers/zustand';

const useCategoriesStore = createCategoriesStore();

createDashboardStore

Factory that creates a scoped dashboard configuration store.

import { createDashboardStore } from '@bzbs/react-providers/zustand';

const useDashboardStore = createDashboardStore();

createPointLogStore

Factory that creates a scoped point history store.

import { createPointLogStore } from '@bzbs/react-providers/zustand';

const usePointLogStore = createPointLogStore();

Wraps pointLogApi. Supports pagination.


createPurchaseStore

Factory that creates a scoped purchase history store.

import { createPurchaseStore } from '@bzbs/react-providers/zustand';

const usePurchaseStore = createPurchaseStore();

useCouponStore

Manages user coupon list and coupon operations.

import { useCouponStore } from '@bzbs/react-providers/zustand';

createFavoriteCampaignsStore

Factory that creates a scoped favorites store.

import { createFavoriteCampaignsStore } from '@bzbs/react-providers/zustand';

const useFavoriteCampaignsStore = createFavoriteCampaignsStore();

TokenFunctions Interface

A required interface for token persistence. You provide your own implementation based on your storage mechanism.

type TokenFunctions = {
  getToken: () => Promise<string | null>;
  setToken: (token: string) => void;
  removeToken: () => void;
};

Example implementations:

// Web (localStorage)
const tokenFunctions: TokenFunctions = {
  getToken: async () => localStorage.getItem('auth_token'),
  setToken: (token) => localStorage.setItem('auth_token', token),
  removeToken: () => localStorage.removeItem('auth_token'),
};

// React Native (AsyncStorage)
import AsyncStorage from '@react-native-async-storage/async-storage';
const tokenFunctions: TokenFunctions = {
  getToken: () => AsyncStorage.getItem('auth_token'),
  setToken: (token) => AsyncStorage.setItem('auth_token', token),
  removeToken: () => AsyncStorage.removeItem('auth_token'),
};

// In-memory (testing / SSR)
let _token: string | null = null;
const tokenFunctions: TokenFunctions = {
  getToken: async () => _token,
  setToken: (token) => { _token = token; },
  removeToken: () => { _token = null; },
};

Service Utilities

Exported from @bzbs/react-providers/zustand (and the default export).


addDefaultHeaderInterceptor

Attaches request and response interceptors to an Axios instance. Call this once after creating your Axios instance and before passing it to BzbsService.

import { addDefaultHeaderInterceptor } from '@bzbs/react-providers/zustand';

addDefaultHeaderInterceptor(
  axiosInstance: AxiosInstance,
  appId: string,
  subscriptionKey: string,
  tokenFunctions: TokenFunctions,
  apiVersion: string,
  corelationIdGenerator?: () => string   // optional, defaults to uuidv7()
): void

What it does:

| Direction | Action | |---|---| | Request | Adds App-Id, Ocp-Apim-Subscription-Key, api-version, X-Corelation-Id headers | | Request | Adds Authorization: Bearer <token> (JWT) or Authorization: token <token> | | Response | Normalises both new-style ({ Success, Data }) and old-style ({ error, ... }) responses | | Response | Emits get_points event if response contains buzzebees.points | | Response | Emits get_badges event if response contains buzzebees.badges | | Response | Emits session_expired event on error code 1905 or 2076 |


addBlake2OtpSignatureInterceptor

Adds BLAKE2b OTP signature headers to requests matching specified URL paths.

import { addBlake2OtpSignatureInterceptor } from '@bzbs/react-providers/zustand';

addBlake2OtpSignatureInterceptor(
  axiosInstance: AxiosInstance,
  paths: string[],              // URL path substrings to match (e.g. ['/otp/send'])
  encoder: TextEncoder,
  getCurrentDateTime?: () => Date  // optional, defaults to () => new Date()
): void

When a matching request includes app_id, contact_number, and channel params, the interceptor adds:

  • OTP-Signature: BLAKE2b hex of appId|contactNumber|channel|datetime
  • Timestamp: Unix timestamp (seconds)

Utility Functions

import {
  avatarUrl,
  largeImage,
  fetchImage,
  interfaceWebsite,
  createInterfaceToken,
  createCartUrl,
  generateBlake2bSignatureHex,
  generateShortLivedId,
  getOtpSignatureHeaders,
} from '@bzbs/react-providers/zustand';

| Function | Signature | Description | |---|---|---| | avatarUrl | (baseUrl, appId, userId, token) => string | Builds a profile picture URL with cache-busting timestamp | | largeImage | (url) => string | Transforms a standard image URL to its large variant | | fetchImage | (axiosClient, imageUrl) => Promise<Blob \| undefined> | Downloads an image as a Blob | | interfaceWebsite | (url, token?, returnUrl?, params?) => string | Builds an interface website URL with obfuscated token | | createInterfaceToken | (token) => string | Obfuscates a token by rearranging first/last characters | | createCartUrl | (cartUrl, appName, accessKey, params?) => string | Builds a cart landing URL with access key | | generateBlake2bSignatureHex | (data, key, encoder) => string | Generates a BLAKE2b hex signature | | generateShortLivedId | () => string | Generates a random short-lived ID string | | getOtpSignatureHeaders | ({ appId, contactNumber, channel, encoder, now? }) => object | Returns { 'OTP-Signature': string, Timestamp: number } |


eventEmitter

A global Emittery instance for cross-component communication. The addDefaultHeaderInterceptor automatically fires events on it.

import { eventEmitter } from '@bzbs/react-providers/zustand';

// Listen for points update (response contains buzzebees.points)
eventEmitter.on('get_points', (data) => {
  console.log('New points:', data.points);
});

// Listen for badges update
eventEmitter.on('get_badges', (badges) => {
  console.log('New badges:', badges);
});

// Listen for session expiry (error code 1905 or 2076)
eventEmitter.on('session_expired', (error) => {
  // Redirect to login, clear token, etc.
  useAuthStore.getState().clear();
});

useUserStore internally calls setupEventListeners() to subscribe to get_points and get_badges and update its state. Call cleanupEventListeners() on unmount.


Analytics Utilities

import {
  analytics,
  trackCommonEvents,
  useAnalytics,
  usePageTracking,
  useAnalyticsState,
  initializeAnalytics,
  withPageTracking,
} from '@bzbs/react-providers/zustand';

trackCommonEvents

Pre-built Matomo event calls for common Buzzebees actions. All functions are async and no-op if analytics is not initialized.

await trackCommonEvents.loginSuccess(userInfo?)
await trackCommonEvents.registerSuccess(userInfo?)
await trackCommonEvents.viewCampaign(userInfo?)
await trackCommonEvents.redeemSuccess(campaignId: string, userInfo?)
await trackCommonEvents.unconsentSuccess(userInfo?)
await trackCommonEvents.buttonClick(buttonName: string, category?: string, userInfo?)
await trackCommonEvents.formSubmit(formName: string, success?: boolean, userInfo?)
await trackCommonEvents.search(keyword: string, resultCount?: number, category?: string, userInfo?)
await trackCommonEvents.purchase(amount: number, currency?: string, productName?: string, userInfo?)
await trackCommonEvents.userRegistration(method?: string, userInfo?)
await trackCommonEvents.userLogin(method?: string, userInfo?)
await trackCommonEvents.error(errorType: string, errorMessage?: string, userInfo?)
await trackCommonEvents.custom(name: string, category: string, label?: string, value?: number, userInfo?)

analytics (global object)

For use outside React components (service files, event handlers, etc.).

analytics.init({ siteId: 1, urlBase: 'https://matomo.example.com' })
analytics.trackEvent({ action, name?, category?, value?, campaign?, userInfo? })
analytics.trackScreenView(name: string, userInfo?)
analytics.trackAppStart(userInfo?)
analytics.trackSiteSearch(keyword: string, category?, count?, userInfo?)
analytics.trackLink(link: string, userInfo?)
analytics.trackDownload(download: string, userInfo?)
analytics.setUserId(userId: string | null)
analytics.setCustomDimension(id: number, value: string)
analytics.setPresetUserInfo(userInfo: UserInfo)
analytics.clearPresetUserInfo()
analytics.setEnabled(enabled: boolean)
analytics.reset()

useAnalytics Hook

React hook that returns analytics functions from the current context.

const {
  isInitialized,
  isEnabled,
  trackEvent,
  trackScreenView,
  trackAction,
  trackAppStart,
  trackSiteSearch,
  trackLink,
  trackDownload,
  setUserId,
  setCustomDimension,
  setEnabled,
  setPresetUserInfo,
  clearPresetUserInfo,
} = useAnalytics();

usePageTracking hook — automatically tracks screen view on mount:

usePageTracking(
  pageName?: string,
  dependencies?: unknown[],
  customUserInfo?: UserInfo
): void

withPageTracking HOC:

const TrackedComponent = withPageTracking(MyComponent, 'Home Screen');

Locale Utilities

import { findBestLocaleFromString, localeToLCIDMap } from '@bzbs/react-providers/zustand';

findBestLocaleFromString(value: string): { locale: string; localeId: number }

Resolves a locale string to an AppLocale object with LCID. Supports:

  • Exact match: 'th-TH'{ locale: 'th-TH', localeId: 1054 }
  • Partial match: 'th' → finds first key starting with 'th'
  • Throws Error if no match found

localeToLCIDMap — Object mapping 200+ locale strings (BCP 47) to Windows LCID numbers.

Common mappings:

| Locale | LCID | |---|---| | en-US | 1033 | | th-TH | 1054 | | zh-CN | 2052 | | zh-TW | 1028 | | ja-JP | 1041 | | ko-KR | 1042 | | ms-MY | 1086 | | id-ID | 1057 | | vi-VN | 1066 |


Constants

import { campaignType, campaignPointType, campaignInterfaceType } from '@bzbs/react-providers/zustand';

campaignType

Maps campaign type names to numeric IDs used by the Buzzebees API.

const campaignType = {
  draw: 0,
  free: 1,
  deal: 2,
  buy: 3,
  bid: 4,
  ads: 5,
  install: 6,
  booking: 7,
  interface: 8,
  event: 9,
  media: 10,
  ewalletTopUp: 11,
  ewalletRedeem: 12,
  ewalletTransfer: 13,
  ewalletBanking: 14,
  autofeed: 15,
  news: 16,
  reservation: 17,
  ewalletBuy: 18,
  pointRedemption: 19,
  donate: 20,
  pointFree: 21,
  voucher: 22,
  encrypt: 23,
  encryptRedeem: 24,
  giftCard: 25,
  verifyCode: 26,
  subscription: 27,
  fillCode: 28,
  subscriptionFood: 29,
  buyEVoucher: 30,
  uploadReceipt: 31,
  payWithPoints: 32,
  marketPlacePrivilege: 33,
  topup2C2P: 34,
  directTopup2C2P: 35,
};

Usage:

if (campaign.campaign_type === campaignType.voucher) {
  // Handle voucher campaign
}

campaignPointType

const campaignPointType = {
  use: 'use',   // campaign costs points
  get: 'get',   // campaign rewards points
};

campaignInterfaceType

const campaignInterfaceType = {
  web: 'web',
  survey: 'survey',
  surveyApprove: 'surveyapprove',
};

Types Reference

import type {
  TokenFunctions,
  AuthTokenType,
  AppLocale,
  MatomoConfig,
  LoginResponseHandler,
  ErrorResponseHandler,
  // Store types
  BuzzebeesAppState,
  BuzzebeesAppActions,
  BuzzebeesAppStore,
  AuthState,
  AuthActions,
  AuthStore,
  UserState,
  UserActions,
  UserStore,
  CartState,
  CartActions,
  CartStore,
  LocaleState,
  LocaleActions,
  LocaleStore,
  AlertState,
  AlertActions,
  AlertStore,
  AlertRequest,
  ConfirmState,
  ConfirmActions,
  ConfirmStore,
  ConfirmRequest,
  PopupState,
  PopupActions,
  PopupStore,
  PopupRequest,
  LoadingIndicatorState,
  LoadingIndicatorActions,
  LoadingIndicatorStore,
  UpdateProfileParams,
} from '@bzbs/react-providers/zustand';

| Type | Description | |---|---| | TokenFunctions | Token persistence interface (getToken/setToken/removeToken) | | AuthTokenType | 'jwt' \| 'auth_token' — token format stored after login | | AppLocale | { locale: string; localeId: number } | | MatomoConfig | Matomo tracker configuration (siteId, urlBase, trackerUrl?, userId?, disabled?, log?) | | LoginResponseHandler | (response: LoginResponse) => void | | ErrorResponseHandler | (error: ErrorResponse) => void | | UpdateProfileParams | Parameters for useUserStore().editUser() |

All API response types (LoginResponse, ProfileResponse, ErrorResponse, etc.) are re-exported from @bzbs/react-api-client. See react-api-client.md for the full models reference.


Deprecated: Context API

⚠️ The Context API layer is deprecated. Do not use it in new code. Use Zustand stores instead.


DefaultMainAppProvider

(Deprecated) A composite provider that wraps the entire app with all context providers nested in order.

// DEPRECATED — use useBuzzebeesAppStore.getState().configure() instead
import { DefaultMainAppProvider } from '@bzbs/react-providers/context';

Props:

type DefaultMainAppProviderProps = {
  appId: string;
  appName: string;
  bzbsService: BzbsService;
  urls: { webCallback: string; cart: string };
  tokenFunctions: TokenFunctions;
  defaultDashboardConfig: string;
  defaultDashboardMode: 'main' | 'sub';
  defaultMenuConfig: string;
  defaultCampaignConfig: string;
  language: string;
  matomoConfig?: MatomoConfig;
  children: React.ReactNode;
};

Provider nesting order (outer → inner):

  1. BuzzebeesServiceProvider
  2. AnalyticsProvider
  3. AppLocaleProvider
  4. LoadingProvider
  5. PopupProvider
  6. MaintenanceProvider
  7. AuthProvider
  8. RegisterProvider
  9. UserProvider
  10. PointLogProvider
  11. ConsentProvider
  12. NotificationProvider
  13. AddressProvider
  14. ZipCodeProvider
  15. CartProvider
  16. DashboardProvider
  17. CategoriesProvider
  18. CampaignProvider

Context Providers Table

(Deprecated) All context providers and their Zustand equivalents.

| Provider | Hook | Zustand Equivalent | |---|---|---| | BuzzebeesServiceProvider | useBuzzebeesServiceContext() | useBuzzebeesAppStore | | AuthProvider | useAuthContext() | useAuthStore | | UserProvider | useUserContext() | useUserStore | | CartProvider | useCartContext() | useCartStore | | CampaignsProvider | useCampaignsContext() | createCampaignsStore() | | CampaignDetailProvider | useCampaignDetailContext() | createCampaignDetailStore() | | CategoriesProvider | useCategoriesContext() | createCategoriesStore() | | CouponProvider | useCouponContext() | useCouponStore | | AlertProvider | useAlertContext() | useAlertStore | | ConfirmProvider | useConfirmContext() | useConfirmStore | | PopupProvider | usePopupContext() | usePopupStore | | LoadingProvider | useLoadingContext() / useLoading() | useLoadingIndicatorStore / useLoading | | NotificationProvider | useNotificationContext() | useNotificationStore | | AnalyticsProvider | useAnalyticsContext() | useAnalyticsStore | | AppLocaleProvider | useAppLocaleContext() | useLocaleStore | | ConsentProvider | useConsentContext() | useConsentStore | | MaintenanceProvider | useMaintenanceContext() | useMaintenanceStore | | RegistrationProvider | useRegistrationContext() | useRegistrationStore | | AddressProvider | useAddressContext() | useAddressStore | | ZipCodeProvider | useZipCodeContext() | useZipCodeStore | | DashboardProvider | useDashboardContext() | createDashboardStore() | | PointLogProvider | usePointLogContext() | createPointLogStore() | | PurchaseProvider | usePurchaseContext() | createPurchaseStore() |


Relationship to @bzbs/react-api-client

@bzbs/react-providers is the stateful wrapper around @bzbs/react-api-client. The relationship:

@bzbs/react-api-client          @bzbs/react-providers
────────────────────────        ──────────────────────────────
BzbsService                 →   Passed into useBuzzebeesAppStore
authenticateApi             →   useAuthStore
profileApi                  →   useUserStore
cartApi                     →   useCartStore
campaignApi                 →   createCampaignsStore / createCampaignDetailStore
categoryApi                 →   createCategoriesStore
couponApi                   →   useCouponStore
notificationApi             →   useNotificationStore
historyApi                  →   createPurchaseStore
registrationApi             →   useRegistrationStore
addressApi                  →   useAddressStore
badgeApi                    →   useUserStore (badges)
consentApi                  →   useConsentStore
dashboardApi                →   createDashboardStore
pointLogApi                 →   createPointLogStore

To create a BzbsService instance, refer to react-api-client.md.


Development Commands

# Build all entry points (dist/)
npm run build

# Run tests with coverage
npm test

# Format source files
npm run format

# Upgrade @bzbs/react-api-client to latest
npm run update:client

# Publish — patch version bump
npm run patch

# Publish — minor version bump
npm run minor

# Publish — major version bump
npm run major

Build output (three entry points, each with CJS + ESM + types):

| Entry point | CJS | ESM | Types | |---|---|---|---| | src/index.ts | dist/index.js | dist/index.mjs | dist/index.d.ts | | context.ts | dist/context.js | dist/context.mjs | dist/context.d.ts | | zustand.ts | dist/zustand.js | dist/zustand.mjs | dist/zustand.d.ts |