bigcommerce-translations-admin-graphql-client
v0.3.0
Published
BigCommerce GraphQL client for translations app
Readme
BigCommerce Translations GraphQL Client
A TypeScript GraphQL client for BigCommerce's Admin API, specifically designed for managing translations and localized content.
Features
- 🌐 Product Localization
- Fetch and update product translations
- Support for all product fields (basic info, SEO, modifiers, options, etc.)
- Batch update capabilities
- 🧩 App Extensions Management
- CRUD operations for app extensions
- Support for all extension contexts (PANEL, BUTTON, FULL_PAGE)
- Automatic extension deduplication
- 🔄 Smart Request Handling
- Automatic rate limiting management
- Configurable retry logic
- Comprehensive error handling
- Query complexity tracking
- 📝 Detailed Logging
- Debug-level request/response logging
- Rate limit tracking
- Complexity monitoring
- Error tracing
- 🗂️ Category Localization
- Fetch category translations
- Update category translations
- Delete category translations
- Support for all translatable category fields
Installation
npm install bigcommerce-translations-admin-graphql-clientUsage
Basic Setup
import { createGraphQLClient } from 'bigcommerce-translations-admin-graphql-client';
const client = createGraphQLClient('your-access-token', 'store-hash');Advanced Configuration
import { GraphQLClient } from 'bigcommerce-translations-admin-graphql-client';
const client = new GraphQLClient({
accessToken: 'your-access-token',
storeHash: 'store-hash',
maxRetries: 3, // Optional: Default is 3
failOnLimitReached: false, // Optional: Default is false
complexity: {
onComplexityUpdate: (complexity) => {
// Monitor query complexity
console.log(`Query complexity: ${complexity}/10000`);
}
}
});API Reference
Product Localization
Fetching Product Translations
const productData = await client.getProductLocaleData({
pid: 'product-id',
channelId: 'channel-id',
availableLocales: [
{ code: 'en' },
{ code: 'es' },
{ code: 'fr' }
],
defaultLocale: 'en'
});Updating Product Translations
// Basic product information
const result = await client.updateProductLocaleData({
locale: 'es',
channelId: 123,
productId: 456,
productData: {
name: 'Producto Nuevo',
description: 'Descripción del producto',
pageTitle: 'Título de la página',
metaDescription: 'Meta descripción',
warranty: 'Garantía',
availabilityDescription: 'Disponibilidad',
searchKeywords: 'palabras clave',
preOrderMessage: 'Mensaje de pre-orden'
}
});
// With options and modifiers
const result = await client.updateProductLocaleData({
locale: 'es',
channelId: 123456,
productId: 789,
productData: {
name: 'Producto Nuevo',
// Options
options: {
'option-id-1': {
displayName: 'Color',
values: [
{ valueId: 'value-1', label: 'Rojo' },
{ valueId: 'value-2', label: 'Azul' }
],
removeValues: ['value-3'] // Remove this value's translation
}
},
// Modifiers
modifiers: {
'modifier-id-1': {
displayName: 'Texto personalizado',
defaultValue: 'Escriba aquí'
},
'modifier-id-2': {
displayName: 'Opciones',
values: [
{ valueId: 'value-1', label: 'Opción 1' },
{ valueId: 'value-2', label: 'Opción 2' }
]
}
},
// Custom fields
customFields: {
'custom-field-1': {
customFieldId: 'custom-field-1',
name: 'Campo personalizado',
value: 'Valor personalizado'
}
},
// Remove translations
remove: {
options: ['option-id-2'], // Remove all translations for this option
modifiers: ['modifier-id-3'], // Remove all translations for this modifier
customFields: ['custom-field-2'] // Remove all translations for this custom field
}
}
});Any fields that are undefined will be ignored. Empty strings will remove the translation override.
For advanced usage with more complex scenarios, you can still use the legacy format:
const result = await client.updateProductLocaleData({
input: {
productId: 'bc/store/product/123',
localeContext: {
channelId: 'bc/store/channel/456',
locale: 'es'
},
data: {
name: 'Producto',
description: 'Descripción'
}
},
// ... other mutation inputs
});getAllProducts(limit: number, cursor?: string)
Fetches all products with pagination support.
App Extensions
Listing Extensions
const extensions = await client.getAppExtensions();Creating an Extension
const newExtensionId = await client.createAppExtension({
context: 'PANEL',
model: 'PRODUCTS',
url: 'https://your-app.com/panel',
label: {
defaultValue: 'My Extension',
locales: [
{ value: 'Mi Extensión', localeCode: 'es' },
{ value: 'Mon Extension', localeCode: 'fr' }
]
}
});Updating an Extension
const updatedExtension = await client.updateAppExtension({
id: 'extension-id',
input: {
label: {
defaultValue: 'Updated Extension Name',
locales: [
{ value: 'Nombre Actualizado', localeCode: 'es' }
]
}
}
});Deleting an Extension
const deletedId = await client.deleteAppExtension('extension-id');App Extension Upsert
// Creates if doesn't exist, updates if exists, removes duplicates
const extensionId = await client.upsertAppExtension({
context: 'PANEL',
model: 'PRODUCTS',
url: 'https://your-app.com/panel',
label: {
defaultValue: 'My Extension'
}
});Category Localization
Fetching Category Translations
const categoryTranslations = await client.getCategoryTranslations({
channelId: 123,
locale: 'es'
});
// The response contains all translated fields for each category
console.log(categoryTranslations.edges.map(edge => ({
categoryId: edge.node.resourceId,
fields: edge.node.fields
})));Updating Category Translations
const updateResult = await client.updateCategoryTranslations({
channelId: 123456,
locale: 'es',
categories: [
{
categoryId: 456,
fields: [
{ fieldName: 'name', value: 'Categoría Nueva' },
{ fieldName: 'description', value: 'Descripción de la categoría' },
{ fieldName: 'page_title', value: 'Título de la página' },
{ fieldName: 'meta_description', value: 'Meta descripción' }
]
},
{
categoryId: 789,
fields: [
{ fieldName: 'name', value: 'Otra Categoría' },
{ fieldName: 'description', value: 'Descripción de otra categoría' }
]
}
]
});Deleting Category Translations
const deleteResult = await client.deleteCategoryTranslations({
channelId: 123456,
locale: 'es',
categories: [
{
categoryId: 456,
fields: ['name', 'description'] // Fields to remove translations for
},
{
categoryId: 789,
fields: ['name', 'page_title', 'meta_description']
}
]
});Error Handling
The client includes comprehensive error handling:
try {
const result = await client.getProductLocaleData({...});
} catch (error) {
if ('retryAfter' in error) {
// Rate limit error
console.log(`Rate limit reached. Retry after ${error.retryAfter} seconds`);
} else if ('errors' in error) {
// GraphQL error
console.log('GraphQL errors:', error.errors);
} else {
// Other error
console.error('Request failed:', error);
}
}Query Complexity
As of January 2025, BigCommerce's GraphQL API has a complexity limit of 10,000 per request. The client provides complexity monitoring to help you stay within this limit:
const client = new GraphQLClient({
// ... other config
complexity: {
onComplexityUpdate: (complexity) => {
// Monitor and log query complexity
console.log(`Query complexity: ${complexity}/10000`);
// Example: Alert on high complexity queries
if (complexity > 8000) {
console.warn('High complexity query detected');
}
}
}
});Tips for managing complexity:
- Limit collections to smaller page sizes (e.g.,
first:10instead offirst:50) - Reduce nested collection depths
- Request only needed fields
- Consider splitting large queries into smaller ones
Debugging
The client uses the debug package for detailed logging. Enable it by setting the DEBUG environment variable:
# Enable all logs
DEBUG=bigcommerce:graphql* npm start
# Enable specific logs
DEBUG=bigcommerce:graphql:request npm startDevelopment
# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Lint
npm run lintType Safety
The client is written in TypeScript and provides comprehensive type definitions for all operations. This includes:
- Request/response types for all operations
- Enum types for extension contexts and models
- Utility types for common patterns
Contributing
Contributions are welcome! Please read our contributing guidelines for details.
License
MIT
