Vendure Plugin Configs
Framework for creating and sharing plugin configurations for Vendure-based storefronts. Plugin configs allow you to extend the Vendure SDK with new features, queries, and type-safe entity augmentations—only when you import the plugin.
Note: These plugin configurations only work if you have the corresponding Vendure plugins installed on your backend. The plugin configs provided here are client-side configurations that enable integration with existing Vendure plugins. If you need help setting up Vendure plugins or have questions about plugin compatibility, please contact the Haus Tech Team for more information.
Purpose
This library provides pre-configured plugin setups for the Vendure e-commerce platform, including badge management, campaign handling, elastic search integration, package size features, product popularity tracking, product variant specifications, and purchase order payment. It simplifies the integration of Vendure plugins with the Haus Storefront Components ecosystem. Plugin configs encapsulate feature functions, query/request extensions, and optional type augmentation for Vendure entities.
Features
- Plugin Management: Easy configuration and initialization of Vendure plugins
- Feature Toggles: Dynamic enabling/disabling of plugin features
- Query Updates: Automatic GraphQL query updates for plugin data
- Settings Management: Centralized plugin settings configuration
- Provider Integration: Support for custom providers and components
- Type Augmentation: Opt-in type extensions for Vendure entities (only active when plugin is imported)
- Pre-configured Plugins: Badge, Campaign, Elastic Search, Package Size, Related Products, Product Popularity, Product Variant Specifications, and Purchase Order Payment plugins
Installation
- npm
- Yarn
npm install @haus-storefront-react/vendure-plugin-configs
yarn add @haus-storefront-react/vendure-plugin-configs
Note: This is not a public package. Contact the Haus Tech Team for access.
API Reference
Products by SKU
Plugin config that adds productVariantsBySkus to the Vendure SDK, enabling lookup of product variants by SKU. Use with the Quick Order component to resolve identifiers (e.g. SKUs) to variant IDs before adding to the order.
Exports
| Export | Type | Description |
|---|---|---|
VendureProductsBySkuPlugin | VendurePluginConfig | Plugin config to add to DataProvider pluginConfigs |
quickOrderVariantSkuValidationStrategy | () => QuickOrderVariantValidationStrategy | Creates a validation strategy for QuickOrder CSV/Manual modes. Resolves SKUs to variant IDs via productVariantsBySkus. Use with QuickOrder.CSV.Root or QuickOrder.Manual.Root when the plugin is enabled. |
ProductVariantBySkuResult | type | Result type for productVariantsBySkus (variant IDs and error results) |
SdkWithProductsBySku | interface | SDK with productVariantsBySkus: (skus: string[]) => Promise<ProductVariantBySkuResult> |
ProductVariantSpecification
Key-value pair for product variant specifications (e.g. "Weight: 2.5 kg"). Matches the struct custom field defined by ProductVariantSpecificationsPlugin on the Vendure backend. Access via productVariant.customFields.specifications.
Interface
interface ProductVariantSpecification {
key: string
value: string
}
VendureProductVariantSpecificationsPlugin
Storefront plugin config for ProductVariantSpecificationsPlugin. Adds specifications (key-value pairs) to product variant queries. Add to pluginConfigs without calling init()—it has no features to configure.
VendurePluginConfig
The base class for all Vendure plugin configurations. Manages plugin state, features, query updates, requests, providers, and settings.
Signature
class VendurePluginConfig<
Features extends PluginFeatures = PluginFeatures,
R extends Record<string, (...args: any[]) => any> = Record<string, (...args: any[]) => any>,
S extends PluginSettings = PluginSettings,
T extends IGraphQLSDK = IGraphQLSDK
> implements IVendurePluginConfig<Features, R, S, T>
Constructor
constructor(config: VendurePluginConfigInput<Features, R, S>)
Constructor Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
config.name | string | Yes | The plugin name identifier |
config.enabled | boolean | No | Whether the plugin is enabled (default: true) |
config.enableFeatures | Partial<Record<keyof Features, boolean>> | Partial<Features> | No | Feature configuration object |
config.queryUpdates | BuilderQueryUpdates | Yes | GraphQL query field updates |
config.requests | R | No | Custom request methods |
config.providers | ProviderDataMap | No | Custom providers array |
config.settings | S | No | Plugin-specific settings |
Methods
| Method | Signature | Description |
|---|---|---|
init | (config: { enableFeatures?: Partial<Record<keyof Features, boolean>> | Partial<Features> | Array<keyof Features>; settings?: S }) => VendurePluginConfig<Features, R, S, T> | Initializes the plugin configuration with a specified set of features. Allows dynamically setting features that should be enabled. Returns the current instance enabling method chaining. |
setSdk | (sdk: T) => void | Sets the GraphQL SDK instance |
getSdk | () => T | Gets the GraphQL SDK instance |
getName | () => string | Gets the plugin name |
isEnabled | () => boolean | Checks if the plugin is enabled |
getEnabled | () => boolean | Gets the enabled state |
setEnabled | (enabled: boolean) => void | Sets the enabled state |
setEnableFeatures | (enableFeatures: Partial<Record<keyof Features, boolean>> | Partial<Features>) => void | Sets the enabled features |
getEnabledFeatures | () => Partial<Record<keyof Features, boolean>> | Gets the enabled features |
setQueryUpdates | (queryUpdates: BuilderQueryUpdates) => void | Sets the query updates |
getQueryUpdates | () => BuilderQueryUpdates | Gets the query updates |
setRequests | (requests: R) => void | Sets the custom requests |
getRequests | () => R | Gets the custom requests |
setProviders | (providers: ProviderDataMap) => void | Sets the custom providers |
getProviders | () => ProviderDataMap | Gets the custom providers array |
setSettings | (settings: S) => void | Sets the plugin settings |
getSettings | () => S | Gets the plugin settings |
onSdkReady | (sdk: T) => void | Promise<void> | Optional callback function that is called when the SDK is set. Use this to perform initialization that requires SDK access, such as dynamically building query updates based on SDK data. |
useRelatedProducts
React Query hook for loading related products for a product. The hook calls sdk.relatedProducts(input) and is enabled when input.id is present.
Signature
useRelatedProducts(input: RelatedProductsInput)
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
input | RelatedProductsInput | Yes | Request payload containing the source product id and optional filters |
RelatedProductsInput
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Product id used to load related products |
take | number | No | Maximum number of related products to return |
facetIds | string[] | No | Optional facet ids used to further filter related results |
VendureRelatedProductsPlugin
Pre-configured plugin that extends the product query with relatedProductIds and registers the relatedProducts(input) SDK request.
Adds to Product
| Field | Type | Description |
|---|---|---|
relatedProductIds | string[] | Related product ids returned on product data |
Adds to SDK
| Method | Signature | Description |
|---|---|---|
relatedProducts | (input: RelatedProductsInput) => Promise<Product[]> | Fetches related products for a product |
Basic Usage
Using a Pre-configured Plugin
- React
- React Native
import { VendureBadgePlugin } from '@haus-storefront-react/vendure-plugin-configs/badge'
import { DataProvider } from '@haus-storefront-react/core'
function App() {
return (
<DataProvider
provider='vendure'
options={{
apiUrl: 'https://your-vendure-instance.com/shop-api',
vendureToken: 'your-channel-token',
pluginConfigs: [
VendureBadgePlugin.init({
enableFeatures: ['showBadges'],
}),
],
}}
>
{/* Your app components */}
</DataProvider>
)
}
import { VendureBadgePlugin } from '@haus-storefront-react/vendure-plugin-configs/badge'
import { DataProvider } from '@haus-storefront-react/core'
function App() {
return (
<DataProvider
provider='vendure'
options={{
apiUrl: 'https://your-vendure-instance.com/shop-api',
vendureToken: 'your-channel-token',
pluginConfigs: [
VendureBadgePlugin.init({
enableFeatures: ['showBadges'],
}),
],
}}
>
{/* Your app components */}
</DataProvider>
)
}
Using Products by SKU with Quick Order
Add VendureProductsBySkuPlugin to your DataProvider and use quickOrderVariantSkuValidationStrategy() with Quick Order to resolve SKUs to variant IDs. The strategy uses the plugin's SDK internally (no need to pass the SDK).
- React
- React Native
import { VendureProductsBySkuPlugin, quickOrderVariantSkuValidationStrategy } from '@haus-storefront-react/vendure-plugin-configs/products-by-sku'
import { QuickOrder } from '@haus-storefront-react/quick-order'
import { DataProvider } from '@haus-storefront-react/core'
const skuStrategy = quickOrderVariantSkuValidationStrategy()
function App() {
return (
<DataProvider
provider='vendure'
options={{
apiUrl: 'https://your-vendure-instance.com/shop-api',
vendureToken: 'your-channel-token',
pluginConfigs: [VendureProductsBySkuPlugin],
}}
>
<QuickOrderPage />
</DataProvider>
)
}
function QuickOrderPage() {
return (
<QuickOrder.Root onSuccess={(r) => console.log(r)} onError={(e) => console.error(e)}>
{({ isLoading }) => (
<QuickOrder.Manual.Root validationStrategy={skuStrategy} initialRows={1}>
{({ rows, getValidRows }) => (
<>
{rows.map((row) => (
<QuickOrder.Manual.Row key={row.id} row={row}>
<div>
<QuickOrder.Manual.Row.IdentifierInput placeholder="SKU" />
<QuickOrder.Manual.Row.QuantityInput type="number" min={1} />
<QuickOrder.Manual.Row.RemoveButton>Remove</QuickOrder.Manual.Row.RemoveButton>
</div>
</QuickOrder.Manual.Row>
))}
<QuickOrder.Manual.AddRowButton>Add row</QuickOrder.Manual.AddRowButton>
<QuickOrder.Manual.SubmitButton>
{isLoading ? 'Adding...' : `Add ${getValidRows().length} item(s)`}
</QuickOrder.Manual.SubmitButton>
</>
)}
</QuickOrder.Manual.Root>
)}
</QuickOrder.Root>
)
}
import { VendureProductsBySkuPlugin, quickOrderVariantSkuValidationStrategy } from '@haus-storefront-react/vendure-plugin-configs/products-by-sku'
import { QuickOrder } from '@haus-storefront-react/quick-order'
import { DataProvider } from '@haus-storefront-react/core'
import { View, Text } from 'react-native'
const skuStrategy = quickOrderVariantSkuValidationStrategy()
function App() {
return (
<DataProvider
provider='vendure'
options={{
apiUrl: 'https://your-vendure-instance.com/shop-api',
vendureToken: 'your-channel-token',
pluginConfigs: [VendureProductsBySkuPlugin],
}}
>
<QuickOrderPage />
</DataProvider>
)
}
function QuickOrderPage() {
return (
<QuickOrder.Root onSuccess={(r) => console.log(r)} onError={(e) => console.error(e)}>
{({ isLoading }) => (
<QuickOrder.Manual.Root validationStrategy={skuStrategy} initialRows={1}>
{({ rows, getValidRows }) => (
<View>
{rows.map((row) => (
<QuickOrder.Manual.Row key={row.id} row={row}>
<View style={{ flexDirection: 'row' }}>
<QuickOrder.Manual.Row.IdentifierInput placeholder="SKU" />
<QuickOrder.Manual.Row.QuantityInput keyboardType="number-pad" />
<QuickOrder.Manual.Row.RemoveButton><Text>Remove</Text></QuickOrder.Manual.Row.RemoveButton>
</View>
</QuickOrder.Manual.Row>
))}
<QuickOrder.Manual.AddRowButton><Text>Add row</Text></QuickOrder.Manual.AddRowButton>
<QuickOrder.Manual.SubmitButton>
<Text>{isLoading ? 'Adding...' : `Add ${getValidRows().length} item(s)`}</Text>
</QuickOrder.Manual.SubmitButton>
</View>
)}
</QuickOrder.Manual.Root>
)}
</QuickOrder.Root>
)
}
Using Product Variant Specifications Plugin
The Product Variant Specifications plugin extends product variants with key-value specifications (e.g. "Weight: 2.5 kg"). Requires ProductVariantSpecificationsPlugin on the Vendure backend. Specifications are available at productVariant.customFields.specifications.
- React
- React Native
import { VendureProductVariantSpecificationsPlugin } from '@haus-storefront-react/vendure-plugin-configs/product-variant-specifications'
import { DataProvider } from '@haus-storefront-react/core'
function App() {
return (
<DataProvider
provider='vendure'
options={{
apiUrl: 'https://your-vendure-instance.com/shop-api',
vendureToken: 'your-channel-token',
pluginConfigs: [
VendureProductVariantSpecificationsPlugin,
],
}}
>
{/* Your app components */}
</DataProvider>
)
}
import { VendureProductVariantSpecificationsPlugin } from '@haus-storefront-react/vendure-plugin-configs/product-variant-specifications'
import { DataProvider } from '@haus-storefront-react/core'
function App() {
return (
<DataProvider
provider='vendure'
options={{
apiUrl: 'https://your-vendure-instance.com/shop-api',
vendureToken: 'your-channel-token',
pluginConfigs: [
VendureProductVariantSpecificationsPlugin,
],
}}
>
{/* Your app components */}
</DataProvider>
)
}
Accessing specifications in your components:
- React
- React Native
import type { ProductVariantSpecification } from '@haus-storefront-react/vendure-plugin-configs/product-variant-specifications'
import { Product } from '@haus-storefront-react/shared-types'
function VariantSpecs({ variant }: { variant: Product['variants'][number] }) {
const specs = variant?.customFields?.specifications as ProductVariantSpecification[] | undefined
if (!specs?.length) return null
return (
<dl>
{specs.map(({ key, value }) => (
<div key={key}>
<dt>{key}</dt>
<dd>{value}</dd>
</div>
))}
</dl>
)
}
import type { ProductVariantSpecification } from '@haus-storefront-react/vendure-plugin-configs/product-variant-specifications'
import { View, Text } from 'react-native'
import { Product } from '@haus-storefront-react/shared-types'
function VariantSpecs({ variant }: { variant: Product['variants'][number] }) {
const specs = variant?.customFields?.specifications as ProductVariantSpecification[] | undefined
if (!specs?.length) return null
return (
<View>
{specs.map(({ key, value }) => (
<View key={key}>
<Text>{key}: {value}</Text>
</View>
))}
</View>
)
}
Using ProductBadge Component
- React
- React Native
import { ProductBadge } from '@haus-storefront-react/vendure-plugin-configs/badge'
import { Product } from '@haus-storefront-react/shared-types'
function ProductCard({ product }: { product: Product }) {
return (
<div className='product-card'>
<img src={product.featuredAsset?.preview} alt={product.name} />
<ProductBadge.Root product={product}>
{({ groupedBadges }) => (
<ProductBadge.Group position='top-left'>
{({ badges }) => (
<>
{badges.map((badge) => (
<ProductBadge.Item key={badge.id}>
<ProductBadge.Image badge={badge} />
</ProductBadge.Item>
))}
</>
)}
</ProductBadge.Group>
)}
</ProductBadge.Root>
<h3>{product.name}</h3>
</div>
)
}
import { View, Image, Text } from 'react-native'
import { ProductBadge } from '@haus-storefront-react/vendure-plugin-configs/badge'
import { Product } from '@haus-storefront-react/shared-types'
function ProductCard({ product }: { product: Product }) {
return (
<View>
{product.featuredAsset?.preview && (
<Image source={{ uri: product.featuredAsset.preview }} />
)}
<ProductBadge.Root product={product}>
{({ groupedBadges }) => (
<ProductBadge.Group position='top-left'>
{({ badges }) => (
<>
{badges.map((badge) => (
<ProductBadge.Item key={badge.id}>
<ProductBadge.Image badge={badge} />
</ProductBadge.Item>
))}
</>
)}
</ProductBadge.Group>
)}
</ProductBadge.Root>
<Text>{product.name}</Text>
</View>
)
}
Using the Related Products Plugin
- React
- React Native
import { DataProvider } from '@haus-storefront-react/core'
import { VendureRelatedProductsPlugin } from '@haus-storefront-react/vendure-plugin-configs/related-products'
function App() {
return (
<DataProvider
provider='vendure'
options={{
apiUrl: 'https://your-vendure-instance.com/shop-api',
vendureToken: 'your-channel-token',
pluginConfigs: [VendureRelatedProductsPlugin.init({})],
}}
>
{/* Your app components */}
</DataProvider>
)
}
import { DataProvider } from '@haus-storefront-react/core'
import { VendureRelatedProductsPlugin } from '@haus-storefront-react/vendure-plugin-configs/related-products'
function App() {
return (
<DataProvider
provider='vendure'
options={{
apiUrl: 'https://your-vendure-instance.com/shop-api',
vendureToken: 'your-channel-token',
pluginConfigs: [VendureRelatedProductsPlugin.init({})],
}}
>
{/* Your app components */}
</DataProvider>
)
}
Loading Related Products
- React
- React Native
import { useRelatedProducts } from '@haus-storefront-react/vendure-plugin-configs/related-products'
function RelatedProducts({ productId }: { productId: string }) {
const { data: products, isLoading, error } = useRelatedProducts({
id: productId,
take: 4,
})
if (isLoading) return <p>Loading related products...</p>
if (error) return <p>Failed to load related products.</p>
if (!products?.length) return null
return (
<ul>
{products.map((product) => (
<li key={product.id}>{product.name}</li>
))}
</ul>
)
}
import { View, Text } from 'react-native'
import { useRelatedProducts } from '@haus-storefront-react/vendure-plugin-configs/related-products'
function RelatedProducts({ productId }: { productId: string }) {
const { data: products, isLoading, error } = useRelatedProducts({
id: productId,
take: 4,
})
if (isLoading) return <Text>Loading related products...</Text>
if (error) return <Text>Failed to load related products.</Text>
if (!products?.length) return null
return (
<View>
{products.map((product) => (
<Text key={product.id}>{product.name}</Text>
))}
</View>
)
}
Accessing relatedProductIds on Product Data
When VendureRelatedProductsPlugin is registered, the product query is extended with relatedProductIds, and the Product type is augmented accordingly.
import { Product } from '@haus-storefront-react/shared-types'
function ProductDebug({ product }: { product: Product }) {
return <pre>{JSON.stringify(product.relatedProductIds ?? [], null, 2)}</pre>
}
Advanced Usage
Dynamic Plugin Management
- React
- React Native
import { useState, useEffect } from 'react'
import { VendurePluginConfig } from '@haus-storefront-react/vendure-plugin-configs'
import { VendureBadgePlugin } from '@haus-storefront-react/vendure-plugin-configs/badge'
import { VendureCampaignPlugin } from '@haus-storefront-react/vendure-plugin-configs/campaign'
function PluginManager() {
const [plugins, setPlugins] = useState<VendurePluginConfig[]>([])
useEffect(() => {
const badgePlugin = VendureBadgePlugin.init({
enableFeatures: ['showBadges'],
})
const campaignPlugin = VendureCampaignPlugin.init({
enableFeatures: ['showCampaignPrices'],
})
setPlugins([badgePlugin, campaignPlugin])
}, [])
const togglePlugin = (pluginName: string) => {
setPlugins((prev) =>
prev.map((plugin) => {
if (plugin.getName() === pluginName) {
plugin.setEnabled(!plugin.isEnabled())
}
return plugin
}),
)
}
return (
<div className='plugin-manager'>
<h2>Plugin Management</h2>
{plugins.map((plugin) => (
<div key={plugin.getName()} className='plugin-item'>
<h3>{plugin.getName()}</h3>
<label>
<input
type='checkbox'
checked={plugin.isEnabled()}
onChange={() => togglePlugin(plugin.getName())}
/>
Enabled
</label>
</div>
))}
</div>
)
}
import { useState, useEffect } from 'react'
import { View, Text, Switch } from 'react-native'
import { VendurePluginConfig } from '@haus-storefront-react/vendure-plugin-configs'
import { VendureBadgePlugin } from '@haus-storefront-react/vendure-plugin-configs/badge'
import { VendureCampaignPlugin } from '@haus-storefront-react/vendure-plugin-configs/campaign'
function PluginManager() {
const [plugins, setPlugins] = useState<VendurePluginConfig[]>([])
useEffect(() => {
const badgePlugin = VendureBadgePlugin.init({
enableFeatures: ['showBadges'],
})
const campaignPlugin = VendureCampaignPlugin.init({
enableFeatures: ['showCampaignPrices'],
})
setPlugins([badgePlugin, campaignPlugin])
}, [])
const togglePlugin = (pluginName: string) => {
setPlugins((prev) =>
prev.map((plugin) => {
if (plugin.getName() === pluginName) {
plugin.setEnabled(!plugin.isEnabled())
}
return plugin
}),
)
}
return (
<View>
<Text>Plugin Management</Text>
{plugins.map((plugin) => (
<View key={plugin.getName()}>
<Text>{plugin.getName()}</Text>
<Switch
value={plugin.isEnabled()}
onValueChange={() => togglePlugin(plugin.getName())}
/>
</View>
))}
</View>
)
}
Custom Plugin with Requests and Settings
- React
- React Native
import { VendurePluginConfig } from '@haus-storefront-react/vendure-plugin-configs'
import { PaginatedList, ErrorResult } from '@haus-storefront-react/shared-types'
interface CustomFeatures {
processData: (props: { data: string }) => string
}
interface CustomRequests {
fetchCustomData: () => Promise<PaginatedList<any> | ErrorResult>
}
interface CustomSettings {
apiEndpoint: string
timeout: number
retries: number
}
const CustomPlugin = new VendurePluginConfig<
CustomFeatures,
CustomRequests,
CustomSettings
>({
name: 'custom',
enabled: true,
enableFeatures: {
processData: ({ data }) => `Processed: ${data}`,
},
queryUpdates: {
products: {
fields: ['id', 'name'],
},
},
requests: {
fetchCustomData: async () => {
const sdk = CustomPlugin.getSdk()
// Use SDK to fetch data
return {
items: [],
totalItems: 0,
}
},
},
settings: {
apiEndpoint: 'https://api.example.com',
timeout: 5000,
retries: 3,
},
// onSdkReady callback is called when SDK is set by DataProvider
// Use this to perform initialization that requires SDK access
onSdkReady: async (sdk) => {
// Example: Fetch custom fields from API and update query updates dynamically
// const customFields = await sdk.createRequest(...)
// CustomPlugin.setQueryUpdates({ ... })
// Example: Set up requests that depend on SDK after it's ready
// CustomPlugin.setRequests({ ... })
},
})
// Update settings dynamically
CustomPlugin.setSettings({
apiEndpoint: 'https://new-api.example.com',
timeout: 10000,
retries: 5,
})
import { VendurePluginConfig } from '@haus-storefront-react/vendure-plugin-configs'
import { PaginatedList, ErrorResult } from '@haus-storefront-react/shared-types'
interface CustomFeatures {
processData: (props: { data: string }) => string
}
interface CustomRequests {
fetchCustomData: () => Promise<PaginatedList<any> | ErrorResult>
}
interface CustomSettings {
apiEndpoint: string
timeout: number
retries: number
}
const CustomPlugin = new VendurePluginConfig<
CustomFeatures,
CustomRequests,
CustomSettings
>({
name: 'custom',
enabled: true,
enableFeatures: {
processData: ({ data }) => `Processed: ${data}`,
},
queryUpdates: {
products: {
fields: ['id', 'name'],
},
},
requests: {
fetchCustomData: async () => {
const sdk = CustomPlugin.getSdk()
// Use SDK to fetch data
return {
items: [],
totalItems: 0,
}
},
},
settings: {
apiEndpoint: 'https://api.example.com',
timeout: 5000,
retries: 3,
},
})
CustomPlugin.setSettings({
apiEndpoint: 'https://new-api.example.com',
timeout: 10000,
retries: 5,
})
Conditional Rendering with Plugin Features
- React
- React Native
import { ProductBadge } from '@haus-storefront-react/vendure-plugin-configs/badge'
import { Product } from '@haus-storefront-react/shared-types'
import { VendureBadgePlugin } from '@haus-storefront-react/vendure-plugin-configs/badge'
function ProductDisplay({ product }: { product: Product }) {
const badgePlugin = VendureBadgePlugin.init({
enableFeatures: ['showBadges'],
})
if (!badgePlugin.isEnabled()) {
return (
<div className='product'>
<img src={product.featuredAsset?.preview} alt={product.name} />
<h3>{product.name}</h3>
</div>
)
}
return (
<div className='product'>
<img src={product.featuredAsset?.preview} alt={product.name} />
{product.badges && product.badges.length > 0 && (
<ProductBadge.Root product={product}>
{({ groupedBadges, positions }) => (
<div className='badges'>
{positions.map((position) => (
<ProductBadge.Group key={position} position={position}>
{({ badges }) => (
<>
{badges.map((badge) => (
<ProductBadge.Item key={badge.id}>
<ProductBadge.Image badge={badge} />
</ProductBadge.Item>
))}
</>
)}
</ProductBadge.Group>
))}
</div>
)}
</ProductBadge.Root>
)}
<h3>{product.name}</h3>
</div>
)
}
import { View, Image, Text } from 'react-native'
import { ProductBadge } from '@haus-storefront-react/vendure-plugin-configs/badge'
import { Product } from '@haus-storefront-react/shared-types'
import { VendureBadgePlugin } from '@haus-storefront-react/vendure-plugin-configs/badge'
function ProductDisplay({ product }: { product: Product }) {
const badgePlugin = VendureBadgePlugin.init({
enableFeatures: ['showBadges'],
})
if (!badgePlugin.isEnabled()) {
return (
<View>
{product.featuredAsset?.preview && (
<Image source={{ uri: product.featuredAsset.preview }} />
)}
<Text>{product.name}</Text>
</View>
)
}
return (
<View>
{product.featuredAsset?.preview && (
<Image source={{ uri: product.featuredAsset.preview }} />
)}
{product.badges && product.badges.length > 0 && (
<ProductBadge.Root product={product}>
{({ groupedBadges, positions }) => (
<View>
{positions.map((position) => (
<ProductBadge.Group key={position} position={position}>
{({ badges }) => (
<>
{badges.map((badge) => (
<ProductBadge.Item key={badge.id}>
<ProductBadge.Image badge={badge} />
</ProductBadge.Item>
))}
</>
)}
</ProductBadge.Group>
))}
</View>
)}
</ProductBadge.Root>
)}
<Text>{product.name}</Text>
</View>
)
}
Using onSdkReady Callback
The onSdkReady callback is called automatically when the SDK is set by the DataProvider. Use this to perform initialization that requires SDK access, such as dynamically building query updates based on SDK data or setting up requests that depend on the SDK.
- React
- React Native
import { VendurePluginConfig } from '@haus-storefront-react/vendure-plugin-configs'
import type { BuilderQueryUpdates } from '@haus-storefront-react/shared-types'
// Example: Plugin that dynamically builds query updates based on custom fields
// from window.hausStorefront.customFields (loaded after plugin initialization)
const CustomFieldsPlugin = new VendurePluginConfig({
name: 'custom-fields',
queryUpdates: {}, // Empty initially, will be populated in onSdkReady
onSdkReady: async (sdk) => {
// Access window data that may not be available at plugin creation time
const customFields = window.hausStorefront?.customFields || {}
// Build query updates dynamically based on available custom fields
const queryUpdates: BuilderQueryUpdates = {}
if (customFields.Product?.length > 0) {
queryUpdates.product = {
fields: [
{ customFields: customFields.Product.map(f => f.name) }
]
}
}
// Update the plugin's query updates
CustomFieldsPlugin.setQueryUpdates(queryUpdates)
},
})
// Example: Plugin that fetches configuration from API and updates queries
const DynamicConfigPlugin = new VendurePluginConfig({
name: 'dynamic-config',
queryUpdates: {},
onSdkReady: async (sdk) => {
try {
// Fetch configuration from API using SDK
const config = await sdk.createRequest(
{
operation: 'getPluginConfig',
fields: ['customFields', 'enabledFeatures'],
},
{},
false
)
// Update query updates based on API response
if (config.data?.customFields) {
DynamicConfigPlugin.setQueryUpdates({
product: {
fields: config.data.customFields,
},
})
}
} catch (error) {
console.error('Failed to load plugin configuration:', error)
}
},
})
import { VendurePluginConfig } from '@haus-storefront-react/vendure-plugin-configs'
import AsyncStorage from '@react-native-async-storage/async-storage'
const CustomFieldsPlugin = new VendurePluginConfig({
name: 'custom-fields',
queryUpdates: {},
onSdkReady: async (sdk) => {
// Access async storage or other async data sources
const customFieldsJson = await AsyncStorage.getItem('customFields')
const customFields = customFieldsJson ? JSON.parse(customFieldsJson) : {}
// Build and set query updates dynamically
if (customFields.Product?.length > 0) {
CustomFieldsPlugin.setQueryUpdates({
product: {
fields: [
{ customFields: customFields.Product }
]
}
})
}
},
})
Made with ❤️ by Haus Tech Team