Skip to main content

Main entries

@ekanos/harness/registry

Types and helpers for building your harness.config.ts. Server-safe.
interface
Your registry entry: slug, name, description, widgets, plus optional fixtures, tile, activationForm, definition, triggerMocks, live, oauth.
interface
One widget to render: id, title, component, plus optional width, isCollapsible, isPinnable, aiFooterEnabled, seeds.
interface
One recorded HTTP exchange: request (method + URL), response, status, headers.
interface
React-query cache seed: queryKey, and either data or error.
'default' | 'empty' | 'error'
The three fixture variants switchable from the toolbar.
interface
Live mode config: seeds (react-query keys that stay mocked in live mode), default ('live' to open in live mode until the toolbar is changed), egress (only for an entry with no definition), FetchProvider (deprecated; for composing an authenticated fetch once).
interface
Fixtures-mode mock context for triggers and actions: storage (account/user rows), secrets (account/admin tiers), fetchHandlers (dynamic or stateful responses).
string
Plausible UUID for accountId context.
string
Plausible UUID for sourceId context.
string
Plausible slug for account context.
readonly string[]
['default', 'empty', 'error'] — all valid variant names.
'fixtures' | 'live'
The two toolbar data modes.
function
Derive HarnessWidget[] from your definition to avoid duplication. The overrides map, keyed by widget id, supplies harness-only fields (width, seeds); an unknown key throws.
function
Erase the storage generic so your IntegrationDefinition<S> fits in the heterogeneous registry array.

@ekanos/harness/config

function
Identity function that exists for type inference. Also throws if a slug or widget id is not URL-safe, or if one is duplicated.

@ekanos/harness/app

Components and metadata mounted by the generated shell. The entry itself carries no 'use client' directive.
component
The client boundary of the whole harness; mounts the providers and the registry context. Props: integrations: HarnessIntegration[], children.
component
Landing page listing all integrations. Props: integrations: HarnessIntegration[].
Metadata
A Next.js Metadata object for the shell’s layout.

@ekanos/harness/routes

Client page components (the entry is 'use client') re-exported by the shell’s one-line route files, for example export { WidgetsPage as default } from '@ekanos/harness/routes';.
component
Wrapper for integration pages (/<slug>/). Renders tabs and nav.
component
Dashboard grid with all widgets.
component
Single widget in isolation at /<slug>/widgets/<widgetId>.
component
Marketplace tile, rendered in the catalogue grid.
component
Activation form and OAuth panel.
component
Webhooks, schedules, OAuth declaration, and Local OAuth panel.

@ekanos/harness/hooks

Hooks for code that only ever runs inside the harness (a debug banner, a dev-only branch), never a widget’s shipped data path. For activation data in widget code, prefer useActivationData() from @ekanos/sdk/hooks.
'fixtures' | 'live'
Returns the EFFECTIVE data mode (accounting for a missing live block or egress mismatch forcing fixtures).
unknown
Returns the activation data last submitted for this integration. Held in memory only, never written to localStorage, a fixture, or the registry; cleared on reload and on Disconnect.

@ekanos/harness/api

Server-only entry. Never import from a 'use client' module.
function
Returns { GET, POST, PUT } route handlers for the shell’s one API route. Serves oauth/{connect,callback,status}, storage, trigger, local-setup, and actions/<actionName> under /api/integrations/[slug]/. See Live Mode.
interface
{ GET: NextRouteHandler, POST: NextRouteHandler, PUT: NextRouteHandler }
type
(request: Request, context: { params: Promise<HarnessRouteParams> }) => Promise<Response>

@ekanos/harness/styles.css

Tailwind layer, design tokens, Font Awesome repairs, and @source globs covering the harness chrome.

@ekanos/harness/mocks/team-account-workspace

Stand-in for the host’s useTeamAccountWorkspace(). The generated next.config.mjs aliases @kit/team-accounts/hooks/use-team-account-workspace onto it, so unmodified widget source runs unchanged.

Data modes

DataMode

Exported from @ekanos/harness/registry. Returned by useHarnessDataMode() and passed as the mode prop to a live.FetchProvider.

Errors you will see

These are not exported by @ekanos/harness; match them by error.name.

NoRecordedResponseError

Thrown (as a rejected fetch) when a request has no matching fixture. Carries method and url (credentials redacted), and its message includes the fixture line to paste. See Fixtures.

MissingFixtureError

Thrown when a react-query query has neither a seed nor a queryFn of its own.

EgressDeniedError

From @ekanos/sdk/context. Thrown in live mode when a request targets an origin outside the declared egress. Carries origin, an optional reason, and code: 'EGRESS_DENIED'.

LiveActionNotConfirmedError

Thrown when a live-mode action’s confirmation prompt is declined. See Actions.

Handler context

Webhook, schedule, action, onActivate, and onTokens handlers receive the SDK’s IntegrationContext (exported as a type from @ekanos/sdk): accountId, accountSlug, userId, actor, sourceId, integration, timezone, storage, secrets, fetch, and logger. In fixtures mode it is a createMockContext() context; in live mode, the server-held live context.

TypeScript

The published package ships its types in dist/*.d.ts. To check your harness.config.ts, run npx tsc --noEmit in your project.