dimah-formv0.2.0

Server

Create dimahForm(), mount HTTP adapters, and call form.api without a round trip.

@dimah-form/server is the Node / Edge engine: routing, snapshots, guards, and validation. Mount it on your framework, or call form.api in a server component with no extra HTTP hop.


Initializing dimahForm()

Create a centralized dimahForm() instance in your project:

lib/form.ts
import { dimahForm, memoryAdapter } from "@dimah-form/server";
import { forms } from "@/lib/forms";

export const form = dimahForm({
  database: memoryAdapter(), // or db(formDb) from @dimah-form/db
  forms,
  basePath: "/api/form", // Default base path
});

export type Form = typeof form;

database is required. A SQL database is not. memoryAdapter() is enough to run. For production SQL, see Database.


HTTP Framework Adapters

@dimah-form/server provides dedicated adapters for all major JavaScript backend frameworks:

Mount a catch-all route handler in the Next.js App Router:

app/api/form/[...all]/route.ts
import { toNextJsHandler } from "@dimah-form/server/next";
import { form } from "@/lib/form";

export const { GET, POST, PUT, PATCH, DELETE } = toNextJsHandler(form);

Direct Server API (form.api)

In addition to serving HTTP requests, dimahForm() provides a typed, internal API (form.api) that you can call directly in Next.js Server Actions, React Server Components, or backend services without any HTTP network overhead:

app/survey/[slug]/page.tsx
import { form } from "@/lib/form";
import { notFound } from "next/navigation";
import { headers } from "next/headers";
import { Questionnaire } from "@/components/questionnaire";

interface PageProps {
  params: Promise<{ slug: string }>;
}

export default async function SurveyPage({ params }: PageProps) {
  const { slug } = await params;

  // Direct server call — runs validation and security guards internally
  const snapshot = await form.api.getForm({
    query: { formId: slug },
    headers: await headers(), // Forwards session cookies/headers to guard
  });

  if (!snapshot) {
    notFound();
  }

  return <Questionnaire form={snapshot} />;
}

Available form.api Methods

MethodPayloadReturnsDescription
getForm{ query: { formId } }FormSnapshotRetrieves form definition by ID or slug.
listForms{ query?: { status?, limit?, offset? } }FormListReturns paginated list of forms.
saveForm{ body: FormSnapshot }FormSnapshotUpserts dynamic form in database.
deleteForm{ body: { formId } }{ ok: true }Deletes a dynamic form (must have no responses).
startResponse{ body: { formId, respondentId?, resume? } }ResponseRecordStarts response session and freezes snapshot.
getResponse{ query: { responseId } }ResponseRecordFetches a response record.
listResponses{ query?: ListResponsesQuery }ResponseListLists response summaries or full records.
saveDraft{ body: { responseId, answers, updatedAt? } }ResponseRecordPatches partial answers on an active draft.
submitResponse{ body: { responseId, answers?, updatedAt? } }ResponseRecordValidates visible answers and finalizes response.
abandonResponse{ body: { responseId, updatedAt? } }ResponseRecordMarks draft as abandoned.
reopenResponse{ body: { responseId, updatedAt? } }ResponseRecordUnlocks submitted/abandoned response back to draft.
deleteResponse{ body: { responseId } }{ ok: true }Deletes response record.

Next Steps

On this page