Scoring
Compute Likert totals, keying, bands, and missing-item policies from snapshots.
@dimah-form/scoring computes named scores from a response definition snapshot
and its answers. It never writes scores into answers and adds no tables.
npm i @dimah-form/scoringimport { scoringPlugin } from "@dimah-form/scoring";
import { createDefineForm } from "@dimah-form/server";
export const plugins = [scoringPlugin()] as const;
export const defineScoredForm = createDefineForm({ plugins });import { dimahForm } from "@dimah-form/server";
import { plugins } from "@/lib/form-plugins";
import { forms } from "@/lib/forms";
export const form = dimahForm({
database,
forms,
plugins,
});For browser-side previews and typed plugin endpoints, add the matching
scoringClientPlugin() from @dimah-form/scoring/client. Server plugins are
not inferred by createFormClient. Authorize getResponseScores as you would
any other admin operation.
import { scoringClientPlugin } from "@dimah-form/scoring/client";
import { createFormClient } from "@dimah-form/react";
import type { Form } from "@/lib/form";
const plugins = [scoringClientPlugin()] as const;
export const formClient = createFormClient<Form, typeof plugins>({ plugins });Use the root entry on the server, /client in browser bundles, and
@dimah-form/scoring/document in isomorphic packages that need document
readers without loading the server plugin.
Author a score
There is no likert field type. Use select, multiSelect, number, or
boolean, then configure scoring in meta.scoring.
import { defineScoredForm } from "@/lib/form-plugins";
const likert = [
{ value: "0", label: "Not at all", meta: { scoring: { points: 0 } } },
{ value: "1", label: "Several days", meta: { scoring: { points: 1 } } },
{ value: "2", label: "More than half", meta: { scoring: { points: 2 } } },
{ value: "3", label: "Nearly every day", meta: { scoring: { points: 3 } } },
];
export const gad7 = defineScoredForm({
title: "GAD-7",
meta: {
scoring: {
variables: [{ id: "gad7", label: "GAD-7", min: 0, max: 21 }],
bands: [
{ variable: "gad7", from: 0, to: 4, label: "Minimal" },
{ variable: "gad7", from: 5, to: 9, label: "Mild" },
{ variable: "gad7", from: 10, to: 14, label: "Moderate" },
{ variable: "gad7", from: 15, to: 21, label: "Severe" },
],
},
},
fields: [
{
id: "q1",
type: "select",
options: likert,
meta: { scoring: { variable: "gad7" } },
},
// Add q2 through q7 with the same mapping.
],
});option.points contributes to a field's variable. Use option.add when one
choice contributes to one or more variables; never mix it with points.
reverse works for select, number, and boolean, not multiSelect.
import type {
ScoringAdd,
ScoringBand,
ScoringFieldMeta,
ScoringFormMeta,
ScoringFormula,
ScoringPluginOptions,
ScoringVariable,
} from "@dimah-form/scoring";ScoringPluginOptions
Prop
Type
ScoringFormMeta
Prop
Type
ScoringVariable
Prop
Type
ScoringBand
Prop
Type
ScoringFormula
Prop
Type
ScoringFieldMeta
Prop
Type
ScoringAdd
Likert options use { points } on option.meta.scoring instead. Never mix points and add.
Prop
Type
Read results
import { scoreResponse } from "@dimah-form/scoring/client";
const preview = scoreResponse(session.snapshot, session.answers);
const stored = await form.api.getResponseScores({ query: { responseId } });Compute with the session snapshot or stored response.definition, never a
later live form.
import type { ScoreResult } from "@dimah-form/scoring";Prop
Type
Missing items default to "incomplete". Set a variable's missing policy to
"zero" or "omit" when the instrument requires it. Bands are labels;
formulas support sums of distinct variables only.
onScore runs after submit persistence. It may project scores to your own
database, but should not mutate response.answers.