dimah-formv0.6.1
Server

Integration

Create dimahForm(), mount its handler, and use form.api on the server.

@dimah-form/server creates one instance with an HTTP handler and an in-process api. Persistence is required; SQL is not.

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

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

export type Form = typeof form;

basePath must match createFormClient(). Use memoryAdapter() for tests and local development; choose SQL or a custom ResponseStore in Persistence.

Mount the handler

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);

Supported adapters are next, node, express, hono, fastify, elysia, and svelte-kit. Each receives the same form instance:

RuntimeImport
Express@dimah-form/server/expresstoExpressHandler
Hono@dimah-form/server/honotoHonoHandler
Fastify@dimah-form/server/fastifytoFastifyHandler
Elysia@dimah-form/server/elysiatoElysiaHandler
SvelteKit@dimah-form/server/svelte-kittoSvelteKitHandler
Node.js@dimah-form/server/nodetoNodeHandler

Express and Fastify must pass an unread request body to the adapter. Mount the dimah-form route before express.json() or configure Fastify so its JSON parser does not consume /api/form/* first.

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

const app = express();
app.all("/api/form/*", toExpressHandler(form));
app.use(express.json());

For an edge or Fetch runtime, forward the request directly:

export default {
  fetch(request: Request) {
    return form.handler(request);
  },
};

Call in process

form.api exposes the same operations as HTTP without a loopback request. Forward request headers when guard needs the caller's session.

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

export default async function SurveyPage({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;

  try {
    const snapshot = await form.api.getForm({
      query: { formId: slug },
      headers: await headers(),
    });
    return <Questionnaire form={snapshot} />;
  } catch (error) {
    if (isFormErrorCode(error, "UNKNOWN_FORM")) notFound();
    throw error;
  }
}

Route paths and request payloads are documented in Protocol. Put authorization and side effects in Security, not in an adapter.

Next

On this page