dimah-formv0.2.0

Configuration

Options for dimahForm(), createFormClient(), useFormResponse, and ResponseStore.

Options for the server instance, the React client, the fill hook, and a custom database adapter.


dimahForm(config)

The primary server instance initializer from @dimah-form/server. database is required. @dimah-form/db is not — memoryAdapter() ships in @dimah-form/server.

import { dimahForm } from "@dimah-form/server";

export const form = dimahForm({
  database: memoryAdapter(),
  forms: { ... },
  basePath: "/api/form",
});

Configuration Options

OptionTypeRequiredDefaultDescription
databaseResponseStoreYesPersistence adapter (memoryAdapter(), db(formDb) from @dimah-form/db, or a custom ResponseStore).
formsRecord<string, FormDefinitionInput>No{}Catalog of code-authored forms created with defineForm(). Feeds $Infer.
fieldTypesFieldTypeDefinition[]No[]Custom field type definitions created with defineFieldType().
basePathstringNo"/api/form"Base path prefix for HTTP route mounting.
guardDimahFormGuardNoundefinedSecurity callback executed before every query or mutation.
hooksDimahFormHooksNo{}Pre-write (onStart, onDraft, onSubmit) and post-write (afterSubmit, afterDraft, afterDelete) lifecycle hooks.
validateAnswersAnswersValidatorNoundefinedCustom cross-field validation function running on submit.
pluginsDimahFormPlugin[]No[]Server plugins created with definePlugin().
metaSchemaDimahFormMetaSchemaNoundefinedCustom Zod schemas for validating meta dictionaries on forms and fields.

createFormClient<T>(options)

Initializes the typed client runtime from @dimah-form/react.

import { createFormClient } from "@dimah-form/react";
import type { Form } from "@/lib/form";

export const formClient = createFormClient<Form>({
  basePath: "/api/form",
});

Configuration Options

OptionTypeDefaultDescription
basePathstring"/api/form"Relative URL path prefix matching the server's basePath.
baseURLstringundefinedAbsolute URL prefix (e.g., "https://api.example.com/api/form"). Overrides basePath.
credentialsRequestCredentials"same-origin"Fetch credentials policy (e.g. "include" for cross-origin cookies).
headersHeadersInit | (() => MaybePromise<HeadersInit>)undefinedStatic headers or dynamic header generator for auth tokens.
fieldTypesFieldTypeDefinition[][]Custom field types matching the server configuration.
pluginsDimahFormClientPlugin[][]Companion client plugins created with defineClientPlugin().
fetchtypeof fetchglobalThis.fetchCustom fetch implementation for SSR or testing harnesses.

useFormResponse(options)

Headless React hook for managing fill sessions.

Options

OptionTypeRequiredDescription
snapshotFormSnapshotYesForm definition snapshot (retrieved from server).
responseResponseRecordNoExisting response row to edit or view.
respondentIdstring | (() => string)NoUser identifier for draft ownership.
resumebooleanNoIf true, reconnects to the user's latest draft on first write.
autosaveboolean | { debounceMs?: number }NoEnables debounced background draft saving (default debounce: 600ms).
validate"submit" | "change"No"submit" (default) or "change" (real-time validation on edit).
onStarted(record: ResponseRecord) => voidNoCallback invoked after startResponse completes.
onSaved(record: ResponseRecord) => voidNoCallback invoked after saveDraft completes.
onSubmitted(record: ResponseRecord) => voidNoCallback invoked after submitResponse completes.
onReopened(record: ResponseRecord) => voidNoCallback invoked after reopenResponse completes.
onAbandoned(record: ResponseRecord) => voidNoCallback invoked after abandonResponse completes.

The ResponseStore Interface

Any database adapter passed to dimahForm({ database }) must satisfy the following interface:

interface ResponseStore {
  // Form Definitions
  getForm(idOrSlug: string): MaybePromise<FormSnapshot | undefined>;
  saveForm(
    form: FormSnapshot,
    options?: { expectedUpdatedAt?: string },
  ): MaybePromise<void>;
  deleteForm(id: string): MaybePromise<void>;
  listForms(query?: {
    status?: FormStatus;
    limit?: number;
    offset?: number;
  }): MaybePromise<{
    forms: FormSnapshot[];
    limit: number;
    offset: number;
    nextOffset: number | null;
  }>;

  // Response Sessions
  create(row: ResponseRecord): MaybePromise<void>;
  get(id: string): MaybePromise<ResponseRecord | undefined>;
  save(
    row: ResponseRecord,
    options?: { expectedUpdatedAt?: string },
  ): MaybePromise<void>;
  delete(id: string): MaybePromise<void>;
  listResponses(query?: ListResponsesQuery): MaybePromise<{
    responses: (ResponseRecord | ResponseSummary)[];
    limit: number;
    offset: number;
    nextOffset: number | null;
  }>;

  // Draft Helpers
  findLatestDraft(query: {
    formId: string;
    respondentId: string;
  }): MaybePromise<ResponseRecord | undefined>;
  getOrCreateDraft(row: ResponseRecord): MaybePromise<ResponseRecord>;
}

Next Steps

On this page