formular

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 23, 2026 License: CC0-1.0 Imports: 6 Imported by: 0

README

formular

Formular is a JSON message DSL for backend-owned dynamic menus and forms that can be rendered by GUI, TUI, CLI, MCP, web, or other frontends.

JavaScript frontend

The npm package entry point is a single dependency-free browser file:

import { FormularMenu } from "@asciimoth/formular-menu";

const menu = new FormularMenu("root", "settings", (message) => {
  console.log("frontend message", message);
});

Run the local WASM demo:

pnpm install
pnpm run demo

The demo renders two independent frontends and a Go WASM backend connected by one merged JSON message channel.

Documentation

Overview

Package formular defines wire types for the Formular JSON menu and form protocol.

Index

Constants

View Source
const (
	MessageMenuSnapshot        = "menu.snapshot"
	MessageBlockSnapshot       = "block.snapshot"
	MessageBlockDelete         = "block.delete"
	MessageFieldStatus         = "field.status"
	MessageAutocompleteHints   = "autocomplete.hints"
	MessageFieldUpdate         = "field.update"
	MessageFieldValidate       = "field.validate"
	MessageFormApply           = "form.apply"
	MessageButtonPress         = "button.press"
	MessageAutocompleteRequest = "autocomplete.request"
)

Message type constants used in Formular JSON envelopes.

View Source
const (
	ItemHeader      = "header"
	ItemLabel       = "label"
	ItemProgressbar = "progressbar"
	ItemLogs        = "logs"
	ItemButton      = "button"
	ItemField       = "field"
)

Item type constants used by menu and array element content.

View Source
const (
	FieldText     = "text"
	FieldInt      = "int"
	FieldFloat    = "float"
	FieldFile     = "file"
	FieldCheckbox = "checkbox"
	FieldRadio    = "radio"
	FieldRange    = "range"
	FieldArray    = "array"
)

Field kind constants supported by the base DSL.

View Source
const (
	TextPlain    = "plain"
	TextMarkdown = "markdown"
	TextCode     = "code"
)

Text format constants for label rendering.

View Source
const (
	LogTrace = "trace"
	LogDebug = "debug"
	LogInfo  = "info"
	LogWarn  = "warn"
	LogError = "error"
	LogPanic = "panic"
)

Log level constants for logs item rendering.

View Source
const (
	StatusUnset = "unset"
	StatusOK    = "ok"
	StatusWarn  = "warn"
	StatusError = "error"
)

Validation status constants set by a backend.

Variables

This section is empty.

Functions

func IsValidationError

func IsValidationError(err error) bool

IsValidationError reports whether err contains one or more Formular validation errors.

Types

type ArrayElement

type ArrayElement struct {
	// ID is unique within the owning array field.
	ID string `json:"id"`
	// Template names the template this element is based on.
	Template string `json:"template"`
	// Items is the element snapshot after backend defaults and status are applied.
	Items []Item `json:"items"`
	// Copyable declares optional text for a frontend copy action.
	Copyable *Copyable `json:"copyable,omitempty"`
}

ArrayElement is one concrete element inside an array field.

func (ArrayElement) Copy

func (e ArrayElement) Copy() ArrayElement

Copy returns a deep copy of e.

func (ArrayElement) Validate

func (e ArrayElement) Validate() error

Validate returns an error if e is not a valid array element.

type ArrayElementValue

type ArrayElementValue struct {
	// ID identifies the existing or frontend-created element.
	ID string `json:"id"`
	// Template names the template this value follows.
	Template string `json:"template"`
	// Values contains field values for this element.
	Values map[string]any `json:"values"`
}

ArrayElementValue is the wire value shape used when sending array field values.

func (ArrayElementValue) Copy

Copy returns a deep copy of v.

func (ArrayElementValue) Validate

func (v ArrayElementValue) Validate() error

Validate returns an error if v is not a valid array element value.

type ArrayTemplate

type ArrayTemplate struct {
	// Name is unique within the owning array field.
	Name string `json:"name"`
	// Label is optional display text for template selection.
	Label string `json:"label,omitempty"`
	// Items are labels, buttons, and fields allowed in elements of this template.
	Items []Item `json:"items"`
}

ArrayTemplate defines one allowed element shape for an array field.

func (ArrayTemplate) Copy

func (t ArrayTemplate) Copy() ArrayTemplate

Copy returns a deep copy of t.

func (ArrayTemplate) Validate

func (t ArrayTemplate) Validate() error

Validate returns an error if t is not a valid array template.

type Autocomplete

type Autocomplete struct {
	// Enabled permits frontend autocomplete.request messages.
	Enabled bool `json:"enabled,omitempty"`
	// Tag is an application-defined completion namespace or hint.
	Tag string `json:"tag,omitempty"`
}

Autocomplete configures frontend completion behavior for a field.

func (Autocomplete) Copy

func (a Autocomplete) Copy() Autocomplete

Copy returns a deep copy of a.

func (Autocomplete) Validate

func (a Autocomplete) Validate() error

Validate returns an error if a is not a valid autocomplete configuration.

type AutocompleteHintsMessage

type AutocompleteHintsMessage struct {
	MessageBase
	// Field identifies the text field the hints belong to.
	Field FieldRef `json:"field"`
	// Prefix is the input prefix the backend used to compute hints.
	Prefix string `json:"prefix"`
	// Hints contains complete candidate values, not suffixes.
	Hints []string `json:"hints"`
}

AutocompleteHintsMessage is sent by a backend with possible completions.

func (AutocompleteHintsMessage) Copy

Copy returns a deep copy of m.

func (AutocompleteHintsMessage) Validate

func (m AutocompleteHintsMessage) Validate() error

Validate returns an error if m is not a valid autocomplete hints message.

type AutocompleteRequestMessage

type AutocompleteRequestMessage struct {
	MessageBase
	// Field identifies the focused field being completed.
	Field FieldRef `json:"field"`
	// Prefix is the current text input prefix.
	Prefix string `json:"prefix"`
}

AutocompleteRequestMessage is sent by a frontend to request completions.

func (AutocompleteRequestMessage) Copy

Copy returns a deep copy of m.

func (AutocompleteRequestMessage) Validate

func (m AutocompleteRequestMessage) Validate() error

Validate returns an error if m is not a valid autocomplete request message.

type Block

type Block struct {
	// ID is unique within one menu.
	ID string `json:"id"`
	// Order controls frontend display ordering.
	Order int `json:"order"`
	// Generation changes when block structure or item configuration changes.
	Generation uint64 `json:"generation"`
	// Form marks the block as applied as a whole instead of realtime field updates.
	Form bool `json:"form"`
	// Inactive disables all user input for the block.
	Inactive bool `json:"inactive,omitempty"`
	// Collapsible tells the frontend to expose collapse controls.
	Collapsible bool `json:"collapsible,omitempty"`
	// Collapsed is the initial collapsed state unless force-updated.
	Collapsed bool `json:"collapsed,omitempty"`
	// Copyable declares optional text for a frontend copy action.
	Copyable *Copyable `json:"copyable,omitempty"`
	// Items are headers, labels, fields, and buttons in display order.
	Items []Item `json:"items"`
}

Block is a backend-defined menu section with independent generation.

func (Block) Copy

func (b Block) Copy() Block

Copy returns a deep copy of b.

func (Block) Validate

func (b Block) Validate() error

Validate returns an error if b is not a valid block.

type BlockDeleteMessage

type BlockDeleteMessage struct {
	MessageBase
	// BlockID identifies the block to remove.
	BlockID string `json:"blockId"`
}

BlockDeleteMessage is sent by a backend to remove one block.

func (BlockDeleteMessage) Copy

Copy returns a deep copy of m.

func (BlockDeleteMessage) Validate

func (m BlockDeleteMessage) Validate() error

Validate returns an error if m is not a valid block delete message.

type BlockSnapshotMessage

type BlockSnapshotMessage struct {
	MessageBase
	// Block is the full current snapshot of the addressed block.
	Block Block `json:"block"`
}

BlockSnapshotMessage is sent by a backend to create or replace one block.

func (BlockSnapshotMessage) Copy

Copy returns a deep copy of m.

func (BlockSnapshotMessage) Validate

func (m BlockSnapshotMessage) Validate() error

Validate returns an error if m is not a valid block snapshot message.

type ButtonPressMessage

type ButtonPressMessage struct {
	MessageBase
	// BlockID identifies the block that owns the button.
	BlockID string `json:"blockId"`
	// ElementPath identifies a nested array element button when present.
	ElementPath []ElementPathSegment `json:"elementPath,omitempty"`
	// ButtonID identifies the button inside the block or element.
	ButtonID string `json:"buttonId"`
}

ButtonPressMessage is sent by a frontend when a declared button is pressed.

func (ButtonPressMessage) Copy

Copy returns a deep copy of m.

func (ButtonPressMessage) Validate

func (m ButtonPressMessage) Validate() error

Validate returns an error if m is not a valid button press message.

type Copyable

type Copyable struct {
	// Text is placed on the system clipboard by frontend copy controls.
	Text string `json:"text"`
}

Copyable contains clipboard text for copyable blocks or array elements.

func (Copyable) Copy

func (c Copyable) Copy() Copyable

Copy returns a deep copy of c.

func (Copyable) Validate

func (c Copyable) Validate() error

Validate returns an error if c is not a valid copyable descriptor.

type ElementPathSegment

type ElementPathSegment struct {
	// ArrayFieldID identifies the array field containing the element.
	ArrayFieldID string `json:"arrayFieldId"`
	// ElementID identifies the array element inside ArrayFieldID.
	ElementID string `json:"elementId"`
}

ElementPathSegment identifies one array element nesting step.

func (ElementPathSegment) Copy

Copy returns a deep copy of s.

func (ElementPathSegment) Validate

func (s ElementPathSegment) Validate() error

Validate returns an error if s is not a valid element path segment.

type Field

type Field struct {
	// Kind selects the base input widget and value shape.
	Kind string `json:"kind"`
	// Value is the backend-provided default or current value.
	Value any `json:"value,omitempty"`
	// Placeholder is optional empty-state text for text-like inputs.
	Placeholder string `json:"placeholder,omitempty"`
	// Readonly prevents direct user editing when true.
	Readonly bool `json:"readonly,omitempty"`
	// Required means frontend apply is blocked while the value is empty.
	Required bool `json:"required,omitempty"`
	// Validation means frontend should send field.validate messages for changes.
	Validation bool `json:"validate,omitempty"`
	// Status is a backend-provided validation state.
	Status string `json:"status,omitempty"`
	// StatusText is optional explanatory text for Status.
	StatusText string `json:"statusText,omitempty"`
	// Secret requests hidden text entry.
	Secret bool `json:"secret,omitempty"`
	// Multiline allows newline-preserving text input.
	Multiline bool `json:"multiline,omitempty"`
	// Subtype refines text fields, for example email or filepath.
	Subtype string `json:"subtype,omitempty"`
	// Autocomplete configures optional completion requests for text fields.
	Autocomplete *Autocomplete `json:"autocomplete,omitempty"`
	// AllowedValues enumerates values the frontend may offer as choices.
	AllowedValues []any `json:"allowedValues,omitempty"`
	// Min is the optional numeric minimum for int, float, or range fields.
	Min *float64 `json:"min,omitempty"`
	// Max is the optional numeric maximum for int, float, or range fields.
	Max *float64 `json:"max,omitempty"`
	// Fraction is the optional number of fractional digits for floats.
	Fraction *uint `json:"fraction,omitempty"`
	// MaxBytes limits base64 file payload size before encoding.
	MaxBytes *uint64 `json:"maxBytes,omitempty"`
	// Accept lists MIME types accepted by file inputs.
	Accept []string `json:"accept,omitempty"`
	// Templates declares allowed element templates for array fields.
	Templates []ArrayTemplate `json:"templates,omitempty"`
	// Elements is the current array field element snapshot.
	Elements []ArrayElement `json:"elements,omitempty"`
}

Field contains input configuration for an Item with type field.

func (Field) Copy

func (f Field) Copy() Field

Copy returns a deep copy of f.

func (Field) Validate

func (f Field) Validate() error

Validate returns an error if f is not a valid field.

type FieldRef

type FieldRef struct {
	// BlockID identifies the owning top-level block.
	BlockID string `json:"blockId"`
	// FieldID identifies the final field being addressed.
	FieldID string `json:"fieldId"`
	// ElementPath identifies nested array element ownership when present.
	ElementPath []ElementPathSegment `json:"elementPath,omitempty"`
}

FieldRef identifies a top-level or nested field in frontend messages.

func (FieldRef) Copy

func (r FieldRef) Copy() FieldRef

Copy returns a deep copy of r.

func (FieldRef) Validate

func (r FieldRef) Validate() error

Validate returns an error if r is not a valid field reference.

type FieldStatusMessage

type FieldStatusMessage struct {
	MessageBase
	// Field identifies the top-level or nested field being updated.
	Field FieldRef `json:"field"`
	// Status is the backend validation state to display.
	Status string `json:"status"`
	// StatusText is optional explanatory text for the status.
	StatusText string `json:"statusText,omitempty"`
	// Readonly optionally changes whether the field accepts user input.
	Readonly *bool `json:"readonly,omitempty"`
}

FieldStatusMessage is sent by a backend to update a field status or readonly flag.

func (FieldStatusMessage) Copy

Copy returns a deep copy of m.

func (FieldStatusMessage) Validate

func (m FieldStatusMessage) Validate() error

Validate returns an error if m is not a valid field status message.

type FieldUpdateMessage

type FieldUpdateMessage struct {
	MessageBase
	// Field identifies the field whose value changed.
	Field FieldRef `json:"field"`
	// Value is the current field value after frontend normalization.
	Value any `json:"value"`
}

FieldUpdateMessage is sent by a frontend for realtime field changes.

func (FieldUpdateMessage) Copy

Copy returns a deep copy of m.

func (FieldUpdateMessage) Validate

func (m FieldUpdateMessage) Validate() error

Validate returns an error if m is not a valid field update message.

type FieldValidateMessage

type FieldValidateMessage struct {
	MessageBase
	// Field identifies the field to validate.
	Field FieldRef `json:"field"`
	// Value is the current candidate field value.
	Value any `json:"value"`
}

FieldValidateMessage is sent by a frontend to request backend validation.

func (FieldValidateMessage) Copy

Copy returns a deep copy of m.

func (FieldValidateMessage) Validate

func (m FieldValidateMessage) Validate() error

Validate returns an error if m is not a valid field validate message.

type FieldValue

type FieldValue struct {
	// FieldID identifies the value owner.
	FieldID string `json:"fieldId"`
	// Value is the current field value.
	Value any `json:"value"`
}

FieldValue is a named field value used by clients that prefer ordered lists.

func (FieldValue) Copy

func (v FieldValue) Copy() FieldValue

Copy returns a deep copy of v.

func (FieldValue) Validate

func (v FieldValue) Validate() error

Validate returns an error if v is not a valid field value.

type FormApplyMessage

type FormApplyMessage struct {
	MessageBase
	// BlockID identifies the form block being applied.
	BlockID string `json:"blockId"`
	// Values contains all current field values in the block.
	Values map[string]any `json:"values"`
}

FormApplyMessage is sent by a frontend when a form block is applied.

func (FormApplyMessage) Copy

Copy returns a deep copy of m.

func (FormApplyMessage) Validate

func (m FormApplyMessage) Validate() error

Validate returns an error if m is not a valid form apply message.

type Item

type Item struct {
	// Type is one of header, label, progressbar, logs, button, or field.
	Type string `json:"type"`
	// ID is unique inside its owning block or array element.
	ID string `json:"id"`
	// Label is the user-facing caption for fields and buttons.
	Label string `json:"label,omitempty"`
	// Text is the user-facing body for labels and headers.
	Text string `json:"text,omitempty"`
	// Format controls label rendering for plain text, markdown, or code.
	Format string `json:"format,omitempty"`
	// Syntax optionally names a code syntax for highlighted labels.
	Syntax string `json:"syntax,omitempty"`
	// Help is an optional plaintext hint attached to the item.
	Help string `json:"help,omitempty"`
	// Progress is the percentage shown by progressbar items, from 0 to 100.
	Progress *uint `json:"progress,omitempty"`
	// Logs contains lines shown by logs items.
	Logs []LogLine `json:"logs,omitempty"`
	// Inactive disables a button.
	Inactive bool `json:"inactive,omitempty"`
	// Field contains field-specific configuration when Type is field.
	*Field `json:",omitempty"`
}

Item is a discriminated menu content item.

func (Item) Copy

func (i Item) Copy() Item

Copy returns a deep copy of i.

func (Item) Validate

func (i Item) Validate() error

Validate returns an error if i is not a valid item.

type LogLine

type LogLine struct {
	// Level controls the colored prefix shown before Text.
	Level string `json:"level"`
	// Text is the line body.
	Text string `json:"text"`
}

LogLine is one rendered line in a logs item.

func (LogLine) Copy

func (l LogLine) Copy() LogLine

Copy returns a deep copy of l.

func (LogLine) Validate

func (l LogLine) Validate() error

Validate returns an error if l is not a valid log line.

type MenuSnapshotMessage struct {
	MessageBase
	// Force tells the frontend to discard remembered state and reinitialize.
	Force bool `json:"force,omitempty"`
	// Blocks is the complete block list for this menu snapshot.
	Blocks []Block `json:"blocks"`
}

MenuSnapshotMessage is sent by a backend to initialize or replace a menu.

Copy returns a deep copy of m.

func (m MenuSnapshotMessage) Validate() error

Validate returns an error if m is not a valid menu snapshot message.

type MessageBase

type MessageBase struct {
	// Type identifies the concrete message shape.
	Type string `json:"type"`
	// MenuID identifies the menu instance the message belongs to.
	MenuID string `json:"menuId"`
	// MenuGeneration is the backend-assigned menu structure generation.
	MenuGeneration uint64 `json:"menuGeneration,omitempty"`
	// BlockGeneration is the backend-assigned block structure generation.
	BlockGeneration uint64 `json:"blockGeneration,omitempty"`
}

MessageBase contains fields common to all Formular protocol messages.

func (MessageBase) Copy

func (m MessageBase) Copy() MessageBase

Copy returns a deep copy of m.

func (MessageBase) Validate

func (m MessageBase) Validate() error

Validate returns an error if m is not a valid message base.

type ValidationError

type ValidationError struct {
	// Path identifies the invalid field or value.
	Path string
	// Message describes the validation failure.
	Message string
}

ValidationError describes one invalid field in a Formular structure.

func (ValidationError) Copy

Copy returns a deep copy of e.

func (ValidationError) Error

func (e ValidationError) Error() string

Error returns a human-readable validation error.

func (ValidationError) Validate

func (e ValidationError) Validate() error

Validate returns an error if e is not a valid validation error.

type ValidationErrors

type ValidationErrors []ValidationError

ValidationErrors is a collection of validation failures.

func (ValidationErrors) Error

func (e ValidationErrors) Error() string

Error returns all validation failures as one string.

func (ValidationErrors) Unwrap

func (e ValidationErrors) Unwrap() []error

Unwrap returns the validation failures for errors.Join-style inspection.

Directories

Path Synopsis
demo
backend command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL