Forms
HTML form rendering with CSRF token injection, accessible labels, field-type dispatch, and shared-spec server-side validation.
b.forms.render(spec) emits a complete element with auto-escaped attributes, a hidden CSRF input, and per-field markup for text / email / password / number / checkbox / radio / textarea / select / hidden / submit. Every attribute value is forced through escapeAttribute so a hostile field name or value can't break out of the double-quoted attribute context.
b.forms.validate(spec, body) walks the same field spec the renderer accepts and returns { valid, errors, values } — coerced types, required-field checks, length bounds, regex pattern, enum membership. Sharing the spec is the point: the operator's "this is what the form looks like" and "this is what the form expects" stay in lock-step, eliminating the drift class where a field gets added to the renderer but not the validator.
CSRF tokens are 32-byte hex strings from b.crypto.generateToken; verifyCsrfToken is constant-time. The middleware in b.middleware.csrfProtect does the actual request-time gating — this module supplies the issue / verify primitives.
b.forms.generateCsrfToken() #
Returns a 32-byte (64 hex char) random token suitable for embedding in a hidden form field. Entropy comes from b.crypto.generateToken, which routes through Node's crypto.randomBytes. The token is opaque to the framework — operators store it in the session and compare via verifyCsrfToken on submit.
var token = b.forms.generateCsrfToken();
// → "8f3a1c4b...e7d9" (64 hex chars)
b.forms.verifyCsrfToken(submitted, expected) #
Constant-time comparison of a submitted token against the expected value. Returns false for any non-string input, mismatched length, or empty submitted token — never throws. Routes through b.crypto.timingSafeEqual so an attacker can't probe character positions via response-time differences.
var ok = b.forms.verifyCsrfToken(req.body.csrf, req.session.csrf);
// → true (when both strings are non-empty and byte-identical)
b.forms.escapeAttribute(value) #
Escapes a value for safe interpolation into a double-quoted HTML attribute context. Stricter than b.template.escapeHtml: also escapes backtick (some browsers parse ` ` as an attribute delimiter under quirks mode) and = (defense-in-depth for any unquoted-attribute slips). null / undefined become the empty string. Used internally by b.forms.render` for every attribute value; exported for operators rendering their own form fragments.
var safe = b.forms.escapeAttribute('a"bd');
// → "a"b<c>d"
b.forms.render(spec) #
Renders a complete element from a typed spec — method, action, fields, optional CSRF token. Each field's type selects the input widget (text / email / password / number / checkbox / radio / textarea / select / hidden / submit). All attribute values pass through escapeAttribute; spec.csrfToken (if present) is embedded as a hidden _csrf input. Throws when spec.action is missing / empty or spec.fields isn't an array.
var html = b.forms.render({
action: "/login",
method: "POST",
csrfToken: "8f3a1c4b...e7d9",
fields: [
{ type: "email", name: "email", label: "Email", required: true },
{ type: "password", name: "password", label: "Password", required: true },
{ type: "submit", name: "submit", value: "Sign in" },
],
});
// → ""
b.forms.validate(spec, body) #
Walks the same spec the renderer accepts and validates a submitted body. Per field: required-field check, type coercion (string / number / boolean / email / url), minlength / maxlength bounds, numeric min / max bounds, regex pattern, enum membership. Returns { valid: boolean, errors: { field: msg, ... }, values: { ... } }. The values object holds coerced values keyed by field name — route handlers consume result.values directly without re-parsing.
var result = b.forms.validate(
{ fields: [
{ type: "email", name: "email", required: true },
{ type: "number", name: "age", min: 1 },
] },
{ email: "ada@example.com", age: "37" }
);
// → { valid: true, errors: {}, values: { email: "ada@example.com", age: 37 } }
Last updated 2026-08-08T16:39:49.652Z by seeder.