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

helpdesk-app-framework-sdk

v1.0.16

Published

The HelpDesk App Framework (BAF) SDK is a JavaScript library that simplifies cross-frame communication between iframed apps and the HelpDesk App Framework.

Readme

HelpDesk App Framework SDK

The HelpDesk App Framework (BAF) SDK is a JavaScript library that simplifies cross-frame communication between iframed apps and the HelpDesk App Framework, enabling seamless integration of custom applications into the HelpDesk helpdesk platform.

Overview

The BAF SDK provides a unified interface for:

  • Data Access: Retrieve and update ticket, contact, and chat information
  • Event Handling: Listen to and respond to platform events
  • Cross-Frame Communication: Safely communicate between iframes and the host
  • API Requests: Make secure HTTP requests through HelpDesk proxy
  • App Instances: Manage app instances and multi-instance scenarios
  • Context & Metadata: Access runtime context and app metadata

Getting Started

Installation

npm install helpdesk_app_framework_sdk

Basic Usage

<script src="path/to/baf_sdk.min.js"></script>
<script>
  const client = BAFClient.init((context) => {
    console.log('App initialized!');
    console.log('User:', context.user.name);
  });
</script>

Or as an ES Module

import BAFClient from 'helpdesk_app_framework_sdk';

const client = BAFClient.init((context) => {
  console.log('App initialized!');
});

Core Concepts

Client Initialization

Initialize the SDK when your app loads:

const client = BAFClient.init((context) => {
  // Called when app is registered and ready
  console.log('Module:', context.module);        // ticket, contact, chat, etc.
  console.log('Object ID:', context.objectId);   // Current object being viewed
  console.log('User:', context.user.name);       // Current user information
});

The init() function returns a Client instance that provides access to all APIs.

API Reference

Context API

Access runtime environment information through the context object.

// Get organization details
client.context.getOrgId();
client.context.getOrgName();

// Get brand information
client.context.getBrandId();
client.context.getBrandName();

// Get current module and object
client.context.getModule();      // 'ticket', 'contact', 'chat', etc.
client.context.getObjectId();    // ID of current object

// Get user information
client.context.getUser();        // Full user object
client.context.getUserId();
client.context.getUserEmail();
client.context.getUserName();
client.context.getUserTimezone();

// Get plan information
const plan = client.context.getPlan();
console.log(plan.id, plan.name);

Metadata API

Access app and installation metadata through the metadata object.

// Get app information
client.metadata.getAppId();
client.metadata.getAppName();
client.metadata.getVersion();

// Get installation details
client.metadata.getInstallationId();
client.metadata.getInstallDate();

// Check permissions
if (client.metadata.hasReadAccess()) {
  // App has read permission
}

if (client.metadata.hasWriteAccess()) {
  // App has write permission
}

// Check status
client.metadata.isActive();
client.metadata.isEnabled();

// Get locations
const locations = client.metadata.getLocations();
console.log(locations); // ['desk.ticket.view.rightpanel', ...]

// Check if location is supported
if (client.metadata.isLocationSupported('desk.ticket.view.rightpanel')) {
  // Location is supported
}

Data API (get/set)

Retrieve and update data from the platform context.

Get Data

// Get single data point
client.get('ticket.subject').then(data => {
  console.log(data['ticket.subject']);
});

// Get multiple data points
client.get(['ticket.subject', 'ticket.description']).then(data => {
  console.log(data['ticket.subject']);
  console.log(data['ticket.description']);
});

// Error handling
client.get('ticket.id')
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

Set Data

// Update single field
client.set('ticket.subject', 'Updated Subject')
  .then(() => console.log('Updated!'))
  .catch(error => console.error('Error:', error));

// Set structured data
client.set('ticket.customFields', {
  field1: 'value1',
  field2: 'value2'
});

Event Handling (on/off)

Listen to platform events and react to changes.

// Listen for ticket updates
client.on('ticket.updated', (ticket) => {
  console.log('Ticket updated:', ticket);
});

// Listen for custom events
client.on('contact.selected', (contact) => {
  console.log('Contact selected:', contact);
});

// Remove specific listener
const handler = (ticket) => console.log(ticket);
client.on('ticket.updated', handler);
client.off('ticket.updated', handler);

// Remove all listeners for an event
client.off('ticket.updated');

Invoke Actions (invoke)

Execute platform-exposed methods.

// Open a modal
client.invoke('modal.open', {
  title: 'Confirm Action',
  message: 'Are you sure?',
  buttons: ['Yes', 'No']
}).then(result => {
  console.log('User clicked:', result);
});

// Show notification
client.invoke('notification.show', {
  type: 'success',
  message: 'Operation completed'
});

// Navigate to view
client.invoke('navigation.goto', {
  view: 'ticket',
  id: '12345'
});

Custom Events (trigger)

Emit custom events to communicate with other parts of the system.

// Emit custom event
client.trigger('custom.dataUpdated', {
  status: 'success',
  recordId: '12345'
});

// Listen for your own events
client.on('custom.dataUpdated', (data) => {
  console.log('Data updated:', data);
});

Capability Check (has)

Check if a specific capability or data path is available.

// Check if a custom field exists
client.has('ticket.custom_field_123').then(exists => {
  if (exists) {
    console.log('Custom field is available');
  }
});

// Check if a capability is available
client.has('capability.updateTicket').then(available => {
  if (available) {
    console.log('Can update tickets');
  }
});

Request API (Secure Proxy)

Make HTTP requests securely through the HelpDesk proxy.

Important: Storage and resources APIs are not available in Zendesk-compatible mode.

// Basic GET request
client.request.get('https://api.example.com/data')
  .then(response => console.log(response.data))
  .catch(error => console.error(error));

// POST request with data
client.request.post('https://api.example.com/tickets', {
  subject: 'New Ticket',
  priority: 'high'
}).then(response => console.log('Created:', response.data));

// Using full request method
client.request.request({
  url: 'https://api.example.com/users',
  method: 'GET',
  headers: {
    'Authorization': 'Bearer {{setting.api_key}}'  // Secure setting placeholder
  },
  params: {
    status: 'active',
    limit: 20
  },
  timeout: 30000,
  autoRetry: true,
  maxRetry: 3
}).then(response => {
  console.log('Status:', response.status);
  console.log('Data:', response.data);
});

// PUT request
client.request.put('https://api.example.com/tickets/123', {
  status: 'resolved'
});

// DELETE request
client.request.delete('https://api.example.com/tickets/123');

// PATCH request
client.request.patch('https://api.example.com/tickets/123', {
  priority: 'low'
});

Request Options

| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | url | string | Yes | - | Full URL of API endpoint | | method | string | Yes | - | HTTP method (GET, POST, PUT, DELETE, PATCH) | | headers | object | No | {} | HTTP headers | | params | object | No | - | Query parameters | | body | object/string | No | - | Request payload (POST/PUT/PATCH) | | timeout | number | No | 15000 | Timeout in ms (max 30000) | | autoRetry | boolean | No | true | Auto-retry on 429/5xx | | maxRetry | number | No | 3 | Max retry attempts | | retryDelay | number | No | 1000 | Delay between retries (ms) |

Request Limitations

  • Maximum request payload: 100 KB
  • Maximum response size: 6 MB
  • Default timeout: 15 seconds (configurable up to 30 seconds)
  • Rate limit: 50 requests per minute per app per account
  • Binary file upload/download: Not supported

Instance API

Manage app instances (for multi-instance widgets).

// Get current instance
const currentInstance = client.instance.current();
console.log('Instance ID:', currentInstance.getId());

// Get specific instance
const instance = client.instance.get('instance-id-123');

// Get all active instances
const allInstances = client.instance.all();
allInstances.forEach(inst => {
  console.log(inst.getId());
});

// Create new instance
client.instance.create({
  widgets: ['widget1', 'widget2']
}).then(instance => {
  console.log('Created instance:', instance.getId());
});

// Send message to other instances
client.instance.send(['instance-1', 'instance-2'], 'update-channel', {
  type: 'refresh',
  data: newData
});

// Receive messages from other instances
client.instance.receive('update-channel', (message) => {
  console.log('Received message:', message);
});

// Resize widget
client.instance.resize(500);  // Set height to 500px

// Close current instance
client.instance.close();

Widget Locations

Apps can be placed in specific locations in the HelpDesk UI:

| Location | Area | Description | |----------|------|-------------| | desk.menu.left | Left Sidebar | Full-screen app in left menu | | desk.ticket.view.rightpanel | Right Panel (Ticket View) | Contextual panel on ticket page | | desk.contact.view.rightpanel | Right Panel (Contact View) | Contextual panel on contact page | | desk.contactgroup.view.rightpanel | Right Panel (Contact Group View) | Contextual panel on contact group page | | desk.chat.view.rightpanel | Right Panel (Chat View) | Contextual panel on chat page | | desk.cti.widget | Bottom-Left | CTI widget in bottom-left corner |

Manifest Configuration

Your app requires a manifest.json file:

{
  "name": "My HelpDesk App",
  "version": "1.0.0",
  "frameworkVersion": "1.0.0",
  "product": "HelpDesk",
  "developer": {
    "name": "John Doe",
    "contactEmail": "[email protected]",
    "supportEmail": "[email protected]",
    "websiteUrl": "https://myapp.com",
    "privacyUrl": "https://myapp.com/privacy",
    "termsOfUseUrl": "https://myapp.com/terms"
  },
  "widgets": [
    {
      "name": "Ticket Widget",
      "location": "desk.ticket.view.rightpanel",
      "url": "widgets/ticket/index.html"
    }
  ],
  "trustedDomains": [
    "https://api.example.com",
    "https://cdn.example.com"
  ],
  "settings": {
    "enablePermission": true,
    "enableReadPermission": true,
    "enableWritePermission": false,
    "fields": [
      {
        "key": "api_key",
        "label": "API Key",
        "type": "text",
        "required": true,
        "secure": true
      }
    ]
  },
  "internalAuth": {
    "authType": "oauth",
    "clientId": "your-client-id",
    "clientSecret": "your-client-secret",
    "authorizeUri": "https://auth.example.com/oauth/authorize",
    "accessTokenUri": "https://auth.example.com/oauth/token",
    "redirectUri": "https://myapp.com/oauth/callback",
    "scopes": ["read", "write"]
  }
}

Security Best Practices

  1. Never expose sensitive data in client code

    • Use secure: true in manifest for sensitive settings
    • Reference settings as {{setting.key}} in API requests
    • Platform replaces values server-side
  2. Validate all data

    • Validate user input before API calls
    • Check response data types and values
    • Handle errors gracefully
  3. Use trusted domains

    • Only add domains to trustedDomains that you control
    • Verify HTTPS certificates for external APIs
  4. Handle permissions

    • Check metadata.hasReadAccess() and metadata.hasWriteAccess()
    • Gracefully degrade functionality for limited permissions

Error Handling

// Handle promise errors
client.get('ticket.id')
  .then(data => console.log(data))
  .catch(error => {
    console.error('Error:', error.message);
    // Show user-friendly error message
  });

// Try-catch with async/await
async function fetchTicketData() {
  try {
    const data = await client.get('ticket.id');
    console.log(data);
  } catch (error) {
    console.error('Failed to fetch ticket:', error);
  }
}

Development

Build

npm install
npm run build

Development Build

npm run build:dev
npm run server    # Serve at http://localhost:9001

Testing

npm test

Linting

npm run lint

Limitations & Compatibility

  • Storage API: Not available (use secure settings or your own backend)
  • Resources API: Not available (resources are managed via manifest)
  • Binary transfers: Not supported via request proxy
  • CORS: Handled by proxy (no direct CORS in app code)
  • Maximum payload: 100 KB requests, 6 MB responses
  • Rate limiting: 50 requests/minute per app per account

Examples

Complete Ticket Widget

import BAFClient from 'helpdesk_app_framework_sdk';

const client = BAFClient.init(async (context) => {
  console.log('App loaded for:', context.module);
  
  try {
    // Get ticket data
    const data = await client.get([
      'ticket.subject',
      'ticket.description',
      'ticket.status',
      'ticket.requester.email'
    ]);
    
    console.log('Ticket:', data);
    
    // Listen for updates
    client.on('ticket.updated', (ticket) => {
      console.log('Ticket updated:', ticket);
    });
    
    // Listen for status changes
    client.on('ticket.statusChanged', (status) => {
      console.log('New status:', status);
    });
    
  } catch (error) {
    console.error('Error loading ticket:', error);
  }
});

API Integration Example

// Make secure API request with auth
client.request.post('https://api.partner.com/sync', {
  ticketId: ticketData.id,
  subject: ticketData.subject,
  description: ticketData.description
}, {
  headers: {
    'Authorization': 'Bearer {{setting.partner_api_key}}',
    'X-App-Version': '1.0.0'
  },
  timeout: 30000,
  autoRetry: true
}).then(response => {
  console.log('Sync successful:', response.data);
}).catch(error => {
  console.error('Sync failed:', error);
});

Support

For issues, questions, or feature requests, please contact [email protected] or visit https://www.helpdesk.com/developer

License

Licensed under the Apache License, Version 2.0. See LICENSE file for details.

Copyright © 2026 HelpDesk