@ebitex/forms-sdk
v0.4.92
Published
Fetch and render ebitex Forms in your own application.
Readme
@ebitex/forms-sdk
Fetch and render ebitex Forms in your own application.
Two entry points, split deliberately:
@ebitex/forms-sdk— fetches a form definition and validates a submission against it. No React dependency, so a server-only consumer never pulls one in.@ebitex/forms-sdk/react— the rendering components. Imports React as apeerDependency(never bundled), so it never conflicts with your own app's copy.
Your organization's API key is server-side only. Fetch the form definition with
createFormsClient on your server or in a build step, then pass the result to <EbitexForm> —
which never receives the key itself, only the already-fetched definition.
Install
npm install @ebitex/forms-sdkQuick start
// Server-side (a route handler, a loader, a build step — never in a browser bundle)
import { createFormsClient } from '@ebitex/forms-sdk'
const client = createFormsClient({ apiKey: process.env.EBITEX_FORMS_API_KEY! })
const form = await client.getForm('contact-us')// Client-side — `form` is whatever getForm(...) returned above, passed down as a prop
import { EbitexForm } from '@ebitex/forms-sdk/react'
import '@ebitex/forms-sdk/styles.css'
function ContactPage({ form }: { form: SdkForm }) {
return <EbitexForm form={form} onSubmitted={() => console.log('done')} />
}<EbitexForm> posts directly to the form's own public submissionUrl — the same anonymous
endpoint ebitex's own hosted page and iframe embed use — so it never needs your API key either.
Multi-step forms save progress as the respondent advances.
Errors
getForm throws FormsApiError for a non-2xx response, carrying status, the parsed body, and
requestId: the request's reference, from the X-Request-Id response header or an unhandled
500's body (null when a proxy answered and the request never reached ebitex). The message ends
[request <id>] when there is one. Log it, and quote it to support.
Rendering nodes yourself
If you're not using <EbitexForm> — building a custom renderer, or validating a submission
server-side without a browser involved — collectDataFields/resolveVariant/
isFieldComparisonSatisfied/isAllOfSatisfied/isSatisfied are the same evaluators it uses
internally, exported so a second, independently-written implementation never has a chance to drift
from the real one.
A form's content tree (SdkForm.actions, each FormStep.nodes) is FormNode[]: a Fieldset or
Row groups other nodes; a field type (InputField/TextareaField/NumberField/ChoiceField/
ButtonField) is a leaf; a VariantNode shows at most one of its branches (first whose when
is satisfied) or its fallback, based on the respondent's own answers so far.
interface VariantNode {
nodeType: 'Variant'
branches: VariantBranch[]
/** Always an array — empty means "nothing" rather than `null`. */
fallback: FormNode[]
}
interface VariantBranch {
when: VariantPredicate
/** May hold more than one node — not capped at one. */
nodes: FormNode[]
}
type VariantPredicate = FieldComparisonPredicate | AllOfPredicate
interface FieldComparisonPredicate {
kind: 'FieldComparison'
field: string // a submissionKey answered *earlier* in the form
operator: 'Equals' | 'NotEquals' | 'IsEmpty' | 'IsNotEmpty'
value?: string // present for Equals/NotEquals, absent otherwise
}
/** AND-combination of two or more FieldComparisonPredicates — every one must be satisfied. */
interface AllOfPredicate {
kind: 'AllOf'
predicates: FieldComparisonPredicate[]
}import { resolveVariant, isSatisfied } from '@ebitex/forms-sdk'
// Which of a Variant's branches (or its fallback) the respondent currently sees, given their
// answers so far — returns that branch's/fallback's own node list, possibly empty.
const visibleNodes = resolveVariant(variantNode, currentAnswers)
// Evaluating one branch's own `when` directly, regardless of which predicate kind it is.
const branchApplies = isSatisfied(someBranch.when, currentAnswers)A field's answer is submitted under its own submissionKey — not necessarily its name: a field
placed by reference to one you've reused across forms is keyed by that shared field's own external
id instead. Always read/write SubmissionData by submissionKey.
Validating a submission
import { validateSubmission } from '@ebitex/forms-sdk'
const errors = validateSubmission(form, submittedData, { requireAll: true })<EbitexForm> calls this itself for inline feedback before every request; the server is always the
final authority regardless — a client-side pass is for a good respondent experience, not enforcement.
Versioning
This package's public wire shape mirrors ebitex's own Forms API responses directly (see
SdkForm/FormNode above) — a breaking shape change on the server ships as a new minor version
here (pre-1.0), not a patch. Pin a specific version if that matters to your build.
Full guide: developers.ebitex.io.
