The @paritydeals/js-sdk is a lightweight, plain TypeScript library designed for interacting with the ParityDeals entitlement service. It allows you to:

  • Fetch all feature entitlements for a specific organization and customer.
  • Cache these entitlements client-side for efficient and repeated access.
  • Check if a user has access to a particular feature.
  • Retrieve specific entitlement details, including boolean flags, numeric configurations, and metered usage data.
  • Manually refresh entitlement data from the server.
If you are using React, you can use the React SDK instead.

Installation

Install the SDK using your preferred package manager or include it directly via CDN.

npm install @paritydeals/js-sdk
# or
yarn add @paritydeals/js-sdk
# or
pnpm add @paritydeals/js-sdk

CDN Installation:

<script src="https://unpkg.com/@paritydeals/js-sdk/dist/paritydeals-sdk.umd.js"></script>

Basic Usage

Get started with the SDK in just a few lines of code.

import parityDealsSDK from '@paritydeals/js-sdk';

// Initialize the SDK
const pd = parityDealsSDK({
  customerId: "your-customer-id",
  accessToken: "your-access-token",
});

// Check if user has access to a feature
if (pd.hasAccess('premium-features')) {
  console.log("User has access to premium features!");
}

// Get specific entitlement details
const emailLimit = pd.getEntitlement('email-sends', 'metered');
if (emailLimit && emailLimit.hasAccess) {
  console.log(`Emails remaining: ${emailLimit.remaining}`);
}

API Reference

Complete documentation of all SDK methods and configuration options.

Initialization

Create and configure your SDK instance with the required parameters.

// Initialize the SDK
const pd = parityDealsSDK({
  customerId: "your-customer-id",
  accessToken: "your-access-token",
});

Options

OptionTypeDescription
customerIdstringUnique identifier for the customer
accessTokenstring-Authentication token for API requests
initializeAndFetchbooleantrueAutomatically fetch entitlements on initialization
onError(error: Error) => void-Error callback function

Core Methods

hasAccess(featureId: string): boolean

Check if the user has access to a specific feature.

if (pd.hasAccess('premium-features')) {
  // Show premium features
  showPremiumUI();
}

getEntitlement<T>(featureId: string, type: T['type']): T | null

Get detailed entitlement information for a specific feature.

// Boolean entitlement
const canUseAnalytics = pd.getEntitlement('analytics', 'boolean');
if (canUseAnalytics?.hasAccess) {
  enableAnalytics();
}

// Configurable entitlement
const storageLimit = pd.getEntitlement('storage-limit', 'customizable');
if (storageLimit?.hasAccess && storageLimit.configuration) {
  setStorageLimit(storageLimit.configuration);
}

// Metered entitlement
const emailQuota = pd.getEntitlement('email-sends', 'metered');
if (emailQuota?.hasAccess && emailQuota.remaining !== null && emailQuota.remaining > 0) {
  console.log(`Emails remaining: ${emailQuota.remaining}`);
}

getAllEntitlements(): EntitlementMap | null

Get all cached entitlements.

const allEntitlements = pd.getAllEntitlements();
if (allEntitlements) {
  Object.entries(allEntitlements).forEach(([featureId, entitlement]) => {
    console.log(`${featureId}: ${entitlement.hasAccess ? 'Access granted' : 'Access denied'}`);
  });
}

fetchAllEntitlements(forceRefresh?: boolean): Promise<EntitlementMap>

Manually fetch or refresh entitlements from the server.

// Fetch fresh data
try {
  const entitlements = await pd.fetchAllEntitlements(true);
  console.log('Entitlements refreshed:', entitlements);
} catch (error) {
  console.error('Failed to refresh entitlements:', error);
}

isLoading(): boolean

Check if entitlements are currently being fetched.

if (pd.isLoading()) {
  showLoadingSpinner();
} else {
  hideLoadingSpinner();
}

getLastError(): Error | null

Get the last error that occurred during entitlement fetching.

const lastError = pd.getLastError();
if (lastError) {
  console.error('Last SDK error:', lastError.message);
}

clearCache(): void

Clear the cached entitlements.

pd.clearCache();
// Next call to hasAccess or getEntitlement will trigger a new fetch

Entitlement Types

Different types of entitlements supported by the SDK.

interface MeteredEntitlement {
  featureId: string;
  featureType: "METER" | "BOOLEAN" | "CUSTOMIZABLE";
  hardLimit: boolean;
  hasAccess: boolean;
  currentUsage: number;
  usageLimit: number | null;
  remaining: number | null;
  resetAt?: string | null;
}

Examples

Real-world usage patterns and common implementation scenarios.

Feature Gating

Control access to features based on user entitlements.

// Simple feature gate
if (pd.hasAccess('beta-features')) {
  showBetaFeatures();
}

// Conditional rendering
const canUseAdvancedSearch = pd.hasAccess('advanced-search');
return (
  <div>
    <BasicSearch />
    {canUseAdvancedSearch && <AdvancedSearch />}
  </div>
);

Usage-Based Features

Implement usage limits and quota management.

const apiCalls = pd.getEntitlement('api-calls', 'metered');
if (apiCalls?.hasAccess) {
  if (apiCalls.remaining === null || apiCalls.remaining > 0) {
    // Allow API call
    makeApiCall();
  } else {
    // Show upgrade message
    showUpgradeMessage();
  }
}

Configuration-Based Features

Apply dynamic configuration based on user entitlements.

const teamSizeEntitlement = pd.getEntitlement('max-team-size', 'customizable');

if (teamSizeEntitlement?.hasAccess && teamSizeEntitlement.configuration) {
  const maxTeamSize = teamSizeEntitlement.configuration;

  if (currentTeam.length >= maxTeamSize) {
    showUpgradePrompt(); // or disable the "Add Member" button
  } else {
    enableTeamInvite();
  }
}

Error Handling

Robust error handling for production applications.

const pd = parityDealsSDK({
  customerId: "user123",
  accessToken: "token456",
  onError: (error) => {
    // Log to monitoring service
    logError('ParityDeals SDK Error', error);
    
    // Show user-friendly message
    showNotification('Unable to load feature settings', 'error');
  }
});

// Handle fetch errors
try {
  await pd.fetchAllEntitlements();
} catch (error) {
  console.error('Failed to load entitlements:', error);
  // Fallback to default behavior
  showDefaultFeatures();
}

Custom API Request Service

Integrate with your existing HTTP client or add custom logic.

// Custom API request function
async function customApiRequest<T>(config: ApiRequestConfig): Promise<ApiResponse<T>> {
  const response = await fetch(config.url, {
    method: config.method || 'GET',
    headers: {
      'Authorization': `Bearer ${config.accessToken}`,
      'Content-Type': 'application/json',
      ...config.headers
    },
    body: config.body ? JSON.stringify(config.body) : undefined
  });
  
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }
  
  return {
    status: response.status,
    statusText: response.statusText,
    data: await response.json()
  };
}

// Use custom API request
const pd = parityDealsSDK({
  customerId: "user123",
  accessToken: "token456"
}, customApiRequest);

TypeScript Support

Full TypeScript support with comprehensive type definitions.

The SDK is written in TypeScript and provides full type safety:

import parityDealsSDK, { 
  ParityDealsClientOptions, 
  EntitlementMap, 
  MeteredEntitlement 
} from '@paritydeals/js-sdk';

const options: ParityDealsClientOptions = {
  customerId: "user123",
  accessToken: "token456"
};

const pd = parityDealsSDK(options);

// Type-safe entitlement access
const emailQuota: MeteredEntitlement | null = pd.getEntitlement('emails', 'metered');

Advanced Configuration

Advanced options for customizing SDK behavior and API integration.

API Configuration

Configure API request behavior and retry logic.

const pd = parityDealsSDK({
  customerId: "user123",
  accessToken: "token456",
  apiConfig: {
    maxRetries: 5,
    timeout: 10000,
    backoffBaseDelay: 2000
  }
});

Custom Error Handling

Implement sophisticated error handling and recovery strategies.

const pd = parityDealsSDK({
  customerId: "user123",
  accessToken: "token456",
  onError: (error) => {
    // Send to error tracking service
    Sentry.captureException(error);
    
    // Retry logic
    if (error.message.includes('network')) {
      setTimeout(() => pd.fetchAllEntitlements(), 5000);
    }
  }
});

Advanced Options

Additional configuration options for specialized use cases.

Default values are:

const pd = parityDealsSDK({
  customerId: "",
  accessToken: "",
  apiUrl: "https://edge.api.paritydeals.com/api/v1",
  entitlementsPath: "entitlements/",
  apiConfig: {
    maxRetries: 3,
    timeout: 5000,
    backoffBaseDelay: 1000
  }
});
OptionTypeDescription
apiUrlstringBase URL for the API
entitlementsPathstringPath for fetching entitlements
apiConfig.maxRetriesnumberMaximum number of retries for API requests
apiConfig.timeoutnumberTimeout for API requests in milliseconds
apiConfig.backoffBaseDelaynumberBase delay for exponential backoff strategy