@bpinternal/integration-hub

中文文档
0.27.0发布于 2026/09/25AGPL-3.0TypeScriptES Module近 30 天下载 1.2万

Reusable Integration Hub for Botpress-style integration catalogs

原始使用文档
文档目录23 节
  1. Two ways to use this package
  2. UI only ( @bpinternal/integration-hub )
  3. UI + Botpress runtime ( @bpinternal/integration-hub/runtime…
  4. Quick start
  5. Install
  6. Option A: Drop-in screen (fastest)
  7. Option B: Hooks + UI components (more control)
  8. Option C: Mappers only (bring your own data layer)
  9. Option D: UI only (no Botpress client)
  10. API reference
  11. useIntegrationHub(options)
  12. useIntegrationDetails(options)
  13. BotpressIntegrationHub (composed screen)
  14. Mapper functions
  15. What this package does NOT include
  16. Customizing defaults
  17. UI components
  18. Styling requirements
  19. 1. Import package CSS
  20. 2. CSS custom properties
  21. 3. Container queries
  22. Build
  23. Publish

@bpinternal/integration-hub

React UI components and optional Botpress runtime hooks for building integration hub experiences.

Two ways to use this package

UI only (@bpinternal/integration-hub)

You provide your own data and wire your own API calls. The package gives you layout components, cards, grids, filters, and setup wizard shells. Use this when you have a non-Botpress backend or want full control over data fetching.

Required peers: react, react-dom, framer-motion, @base-ui/react, clsx, tailwind-merge, lucide-react

UI + Botpress runtime (@bpinternal/integration-hub/runtime)

You pass a @botpress/client instance and the package handles fetching integrations, mapping data to UI types, and executing install/uninstall/enable/disable mutations. Use this when your app already talks to the Botpress API.

Additional peers: @botpress/client, @tanstack/react-query

@botpress/client and @tanstack/react-query are marked as optional peer dependencies. They are only needed when importing from ./runtime. UI-only consumers do not need to install them.


Quick start

Install

pnpm add @bpinternal/integration-hub react react-dom framer-motion @base-ui/react clsx tailwind-merge lucide-react

If using the Botpress runtime:

pnpm add @botpress/client @tanstack/react-query

@bpinternal/integration-hub/runtime includes a built-in configuration form renderer backed by @bpinternal/static-zui-form.

If your app does not already provide Radix-style design tokens, import the package fallback theme:

import '@bpinternal/integration-hub/theme.css'

Option A: Drop-in screen (fastest)

A single component that handles everything — fetching, mapping, catalog, detail views, mutations.

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { BotpressIntegrationHub } from '@bpinternal/integration-hub/runtime'

const queryClient = new QueryClient()

export const IntegrationsPage = ({ client, workspaceId, botId }) => (
  <QueryClientProvider client={queryClient}>
    <BotpressIntegrationHub
      client={client}
      workspaceId={workspaceId}
      botId={botId}
      onInstall={(integration) => toast.success(`${integration.title} installed`)}
      onUninstall={(integration) => toast.success(`${integration.title} removed`)}
      onError={(error) => toast.error(error.message)}
    />
  </QueryClientProvider>
)

By default, BotpressIntegrationHub renders integration configuration fields using Static ZUI Form. Pass renderConfigurationForm only if you want to override this default behavior.

Option B: Hooks + UI components (more control)

Use the hooks for data/mutations but compose your own layout with the package's UI components.

import { useIntegrationHub, useIntegrationDetails } from '@bpinternal/integration-hub/runtime'
import {
  IntegrationHubBody,
  IntegrationGridCard,
  IntegrationInstalledList,
  IntegrationDetailsLayout,
  IntegrationCapabilitiesCards
} from '@bpinternal/integration-hub'

export const IntegrationsPage = ({ client, workspaceId, botId }) => {
  const [selectedId, setSelectedId] = useState(null)
  const [search, setSearch] = useState('')

  const hub = useIntegrationHub({ client, workspaceId, botId })
  const details = useIntegrationDetails({ client, workspaceId, botId, integrationId: selectedId })

  return (
    <IntegrationHubBody
      view="hub"
      searchInput={search}
      onSearchInputChange={setSearch}
      hubIntegrations={hub.integrations}
      sidebarIntegrations={hub.integrations}
      installedIntegrations={hub.installedIntegrations}
      isHubLoading={hub.isLoading}
      renderIntegrationCard={(integration) => (
        <IntegrationGridCard
          name={integration.title ?? integration.name}
          iconUrl={integration.iconUrl}
          installed={integration.installed}
          onClick={() => setSelectedId(integration.id)}
        />
      )}
      renderInstalledIntegrations={({ integrations, searchTerm, categoryOrder }) => (
        <IntegrationInstalledList
          integrations={integrations}
          searchTerm={searchTerm}
          categoryOrder={categoryOrder}
          onSelectIntegration={(i) => setSelectedId(i.id)}
        />
      )}
      renderIntegrationDetails={() => (
        <IntegrationDetailsLayout
          title={details.definition?.title ?? ''}
          iconUrl={details.definition?.iconUrl}
          onBack={() => setSelectedId(null)}
          onInstall={() => hub.install(selectedId)}
          isInstalled={Boolean(details.installedState)}
          isInstalling={hub.isInstalling}
        >
          <IntegrationCapabilitiesCards
            actionCards={details.capabilities.actionCards}
            eventCards={details.capabilities.eventCards}
          />
        </IntegrationDetailsLayout>
      )}
    />
  )
}

Option C: Mappers only (bring your own data layer)

Pure functions that convert @botpress/client types to the package's UI types. No React, no hooks. Use these if you already have your own React Query setup and just want to stop duplicating mapping logic.

import {
  toHubItem,
  toCapabilityCards,
  toConnectionMethods,
  getInstalledIntegrations,
  filterAndSortIntegrations
} from '@bpinternal/integration-hub/runtime'

// In your own React Query hook:
const integrations = await client.listPublicIntegrations({ version: 'latest' })
const bot = await client.getBot({ id: botId })

const installed = getInstalledIntegrations(bot.integrations)
const installedByName = new Map(installed.map((i) => [i.name, i]))

const hubItems = integrations.map((summary) => toHubItem({ summary, installedByName }))
const filtered = filterAndSortIntegrations({ integrations: hubItems, searchTerm: 'slack' })

Option D: UI only (no Botpress client)

Use the components with any data source. You handle all fetching and pass data as props.

import { IntegrationHubBody, IntegrationGridCard } from '@bpinternal/integration-hub'

const myIntegrations = [
  { id: '1', name: 'slack', title: 'Slack', description: 'Chat with Slack', iconUrl: '...' }
]

export const MyHub = () => (
  <IntegrationHubBody
    view="hub"
    searchInput={search}
    onSearchInputChange={setSearch}
    hubIntegrations={myIntegrations}
    sidebarIntegrations={myIntegrations}
    installedIntegrations={[]}
    renderIntegrationCard={(integration) => (
      <IntegrationGridCard name={integration.title} iconUrl={integration.iconUrl} />
    )}
    renderInstalledIntegrations={() => <div>No installed integrations</div>}
    renderIntegrationDetails={(id) => <div>Details for {id}</div>}
  />
)

API reference

useIntegrationHub(options)

Hook that fetches the integration catalog and bot state, and provides mutation functions.

Options:

ParamTypeDescription
clientClientA configured @botpress/client instance
workspaceIdstringWorkspace ID
botIdstringBot ID
categoryResolver?(integration) => string | nullOverride default category mapping
enabled?booleanDisable fetching (default true)

Returns:

FieldTypeDescription
integrationsBotpressIntegrationHubItem[]All public + private integrations with installed/enabled/hasUpdate computed
installedIntegrationsBotpressIntegrationHubItem[]Only integrations installed on the bot
isLoadingbooleanInitial load in progress
errorError | nullFetch error
install(id)(id: string) => Promise<void>Install integration on the bot
uninstall(id)(id: string) => Promise<void>Remove integration from the bot
enable(id)(id: string) => Promise<void>Enable installed integration
disable(id)(id: string) => Promise<void>Disable installed integration
upgrade(id)(id: string) => Promise<void>Upgrade integration to latest version
refresh()() => voidRe-fetch all data
isInstallingbooleanInstall mutation in progress
isUninstallingbooleanUninstall mutation in progress
isEnablingbooleanEnable mutation in progress
isDisablingbooleanDisable mutation in progress
isUpgradingbooleanUpgrade mutation in progress

useIntegrationDetails(options)

Hook that fetches a single integration's full definition, bot-installed state, and capabilities.

Options:

ParamTypeDescription
clientClientA configured @botpress/client instance
workspaceIdstringWorkspace ID
botIdstringBot ID
integrationIdstring | nullIntegration to load (null = disabled)
enabled?booleanDisable fetching (default true)

Returns:

FieldTypeDescription
definitionIntegration | nullFull integration definition (actions, events, channels, config schema)
installedStateBotpressInstalledIntegration | nullBot's installed state (enabled, config, webhookUrl) or null if not installed
capabilities.actionCardsIntegrationCapabilityCardItem[]Action cards ready for IntegrationCapabilitiesCards
capabilities.eventCardsIntegrationCapabilityCardItem[]Event cards
capabilities.channelCardsIntegrationCapabilityCardItem[]Channel cards
connectionMethodsIntegrationConnectionMethodOption[]Available connection methods (OAuth, named configs, sandbox)
selectedConnectionMethodstring | nullCurrently active connection method
isLoadingbooleanFetch in progress
errorError | nullFetch error
saveConfig(config)(config: Record<string, unknown>) => Promise<void>Save integration configuration
toggleEnabled()() => Promise<void>Toggle enabled/disabled state
setConnectionMethod(method)(method: string | null) => Promise<void>Switch connection method
refresh()() => voidRe-fetch details
isSavingConfigbooleanConfig save in progress
isTogglingEnabledbooleanToggle mutation in progress
isSettingConnectionMethodbooleanConnection method mutation in progress

BotpressIntegrationHub (composed screen)

Drop-in component that wires useIntegrationHub + useIntegrationDetails + all UI components. Manages view/search/selection/tab state internally.

Required props: client, workspaceId, botId

Optional overrides:

PropTypeDescription
initialView'hub' | 'installed'Starting view (default 'hub')
categoriesIntegrationHubCategory[]Override default categories
bannerSlidesIntegrationHubBannerSlide[]Override promotional banner content
bannerIconUrlstringBanner image URL
filterMenuLabelsPartial<IntegrationHubFilterMenuLabels>Override filter menu text
categoryResolver(integration) => string | nullCustom category mapping
disableInstallationbooleanHide install buttons
hasWriteAccessbooleanDisable mutation buttons when false
noResultsDocumentationLink{ href, label? }Link shown in empty search results
oauthTemplateDataRecord<string, unknown>Extra payload merged into client.runVrl when generating OAuth authorization URLs. If env is omitted, the runtime infers production for *.cloud API URLs and preview otherwise.

Render slots (for things the package cannot own):

SlotProps you receivePurpose
renderConfigurationForm{ definition, installedState, selectedConnectionMethod, onSave, isSaving }Override the default Static ZUI configuration form renderer.
renderConnectionsContent{ definition, installedState, connectionMethods, selectedConnectionMethod, onConnectionMethodChange }Override the default runtime connection UI (OAuth/manual flows).
renderDetailPanel{ definition, selectedCard, onClose }Render the side panel when a capability card is selected (e.g. schema viewer).

Callbacks:

CallbackTypeWhen it fires
onInstall(integration) => voidAfter successful install
onUninstall(integration) => voidAfter successful uninstall
onEnable(integration) => voidAfter successful enable
onDisable(integration) => voidAfter successful disable
onUpgrade(integration) => voidAfter successful upgrade
onError(error: Error) => voidOn any mutation error

Mapper functions

Pure functions (no React) exported from @bpinternal/integration-hub/runtime:

FunctionDescription
toHubItem({ summary, installedByName, categoryResolver? })Convert a @botpress/client integration summary + bot state into an IntegrationHubItem
toInstalledItem({ installedIntegration, summary?, categoryResolver? })Convert a bot's installed integration entry into an IntegrationHubItem
toCapabilityCards(definition)Extract actions, events, and channels from a full integration definition into card arrays
toConnectionMethods(definition)Extract available connection methods (OAuth, named configs, sandbox) from a definition
getInstalledIntegrations(botIntegrations)Convert the raw bot.integrations map into a typed array
findInstalledIntegration({ installedIntegrations, integrationId, integrationName? })Find a specific installed integration by ID or name
filterAndSortIntegrations({ integrations, searchTerm, visibility?, verification?, sortMethod? })Filter and sort hub items by search, visibility, verification status, and sort method
resolveCategory(integration, categoryResolver?)Resolve an integration's category with optional custom resolver
isOfficialWorkspace(handle)Check if a workspace handle is the official Botpress workspace
dedupeById(items)Remove duplicate items by ID

What this package does NOT include

These are the consumer's responsibility:

ThingWhyWhat to do
Auth / sessionEvery app handles auth differentlyCreate your own @botpress/client instance with your token and pass it to hooks
Custom OAuth UXThe package includes a default OAuth flow, but app-specific redirects and UX can varyUse oauthTemplateData or override with renderConnectionsContent / IntegrationOAuthButton
Custom config form behaviorThe package ships a Static ZUI default renderer, but apps may need custom controls/validation/UXProvide renderConfigurationForm only when overriding the default
Routing / URL syncToo framework-specific (React Router, TanStack Router, Next.js)Manage selectedIntegrationId and view state yourself and map to your router
Toast notificationsEvery app has its own toast systemUse onInstall, onUninstall, onError callbacks to trigger your toasts
Analytics / trackingApp-specific telemetryUse mutation callbacks (onInstall, onUninstall, onEnable, onDisable, onUpgrade) and your own UI-level tracking hooks
Feature flagsApp-specific gatingPass disableInstallation or hasWriteAccess booleans

Customizing defaults

The package ships with generic defaults. Override them for your product:

  • bannerSlides — promotional banner content (pass your own slides or an empty array to hide)
  • categories — integration categories with icons (defaults to 13 common categories)
  • filterMenuLabels — deep-merge with defaults to change labels like { verification: { official: 'Made by Botpress' } }
  • noResultsDocumentationLink — link shown when search has no results
  • formatGithubLabel on IntegrationSetupMetadataBar — custom GitHub URL display formatting
  • categoryResolver — function to override how integrations are assigned to categories

UI components

All exported from @bpinternal/integration-hub:

ComponentPurpose
IntegrationHubBodyFull hub page: category sidebar, search, banner carousel, responsive card grid, installed list, detail pane routing
IntegrationHubFilterMenuDropdown filter menu (visibility, verification, sort) with active filter pills
IntegrationGridCardIntegration card with icon, name, description, author, badges
IntegrationInstalledListSorted/filtered list of installed integrations with enabled/disabled status
IntegrationDetailsLayoutDetail page shell: back button, header, Install/Uninstall/Enable/Disable/Upgrade buttons, side panel slot
IntegrationSetupWizardLayoutSetup wizard: "setup mode" numbered steps and "configured mode" tabs
IntegrationSetupMetadataBarVersion, GitHub link, About button row
IntegrationConnectionMethodSelectorDropdown to pick connection method (OAuth, named config, sandbox)
IntegrationWebhookUrlFieldRead-only webhook URL with copy button and tooltip
IntegrationConfigurationSectionConfiguration wrapper with title, webhook field, blocked state, and children slot
IntegrationCapabilitiesCardsAction/event/channel capability card grid with selection state

Styling requirements

1. Import package CSS

The package ships precompiled component styles in theme.css. Import it once in your app entrypoint:

import '@bpinternal/integration-hub/theme.css'

You do not need to add @bpinternal/integration-hub to Tailwind content globs for runtime styles. Tailwind scanning of package source is only useful when developing against unpublished local source.

2. CSS custom properties

Components use Radix-style color tokens. Either use @radix-ui/themes or define these variables:

:root {
  --gray-1: #ffffff;
  --gray-2: #f8f9fa;
  --gray-3: #f1f3f5;
  --gray-5: #e1e5ea;
  --gray-6: #d0d7de;
  --gray-7: #bfc8d3;
  --gray-8: #9aa4b2;
  --gray-9: #7a8594;
  --gray-10: #6b7280;
  --gray-11: #4b5563;
  --gray-12: #111827;

  --gray-a2: rgba(17, 24, 39, 0.04);
  --gray-a3: rgba(17, 24, 39, 0.07);
  --gray-a4: rgba(17, 24, 39, 0.1);
  --gray-a5: rgba(17, 24, 39, 0.14);
  --gray-a6: rgba(17, 24, 39, 0.2);
  --gray-a8: rgba(17, 24, 39, 0.4);

  --blue-a2: rgba(37, 99, 235, 0.12);
  --blue-8: #3b82f6;
  --blue-11: #1d4ed8;

  --grass-3: #ecfdf3;
  --grass-5: #a7f3d0;
  --grass-10: #16a34a;

  --accent-9: #0ea5e9;
  --accent-11: #0284c7;
}

3. Container queries

IntegrationHubBody uses native CSS container queries for responsive grids. If you rebuild package styles from source in a Tailwind v3 app, add:

import containerQueries from '@tailwindcss/container-queries'
export default { plugins: [containerQueries] }

Build

pnpm --filter @bpinternal/integration-hub build
pnpm --filter @bpinternal/integration-hub type-check

Publish

pnpm --filter @bpinternal/integration-hub exec npm version patch
pnpm --filter @bpinternal/integration-hub exec npm publish --access public

prepack runs clean && build automatically before publish.

Note: Depending on options passed to the botpress client (x-multiple-integrations = true), the integrations from Botpress Cloud are keyed by their ALIAS, not their ID. For edits that intend to use the integration ID, make sure to explicitly use the .id parameter.

版本与发布记录

@bpinternal/integration-hub 共发布 51 个版本,首次发布于 2026/04/14;过去 12 个月发布了 51 个版本。

版本发布日期距今
0.27.0latest2026/09/251 个月前
0.26.12026/09/181 个月前
0.26.02026/08/122 个月前
0.25.92026/07/313 个月前
0.25.82026/06/194 个月前
0.25.72026/06/194 个月前

关于 @bpinternal/integration-hub 的常见问题

@bpinternal/integration-hub 是什么?

Reusable Integration Hub for Botpress-style integration catalogs

如何安装 @bpinternal/integration-hub?

在项目目录运行 npm install @bpinternal/integration-hub,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:clsx(>=2)、react(>=18)、react-dom(>=18)、lucide-react(>=0.466)、framer-motion(>=11)、@base-ui/react(>=1)、tailwind-merge(>=3)、@monaco-editor/react(>=4)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@bpinternal/integration-hub 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@bpinternal/integration-hub 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@bpinternal/integration-hub 可以商用吗?

@bpinternal/integration-hub 使用 AGPL-3.0 许可。最严格的 Copyleft:除分发外,通过网络向用户提供基于它的服务也需要开源对应源码。闭源 SaaS 使用前务必评估。以上为概括,不构成法律意见,请以许可原文为准。

@bpinternal/integration-hub 的下载量有多少?

根据 npm 官方下载统计,@bpinternal/integration-hub 在 2026/10/09 – 2026/11/07 这 30 天内被下载 12,048 次,日均约 402 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bpinternal/integration-hub 还在维护吗?

最新版本 0.27.0 发布于 2026/09/25(1 个月前);至今共发布 51 个版本,其中过去 12 个月发布了 51 个;首次发布于 2026/04/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。