formular

package module
v0.3.5 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2026 License: CC0-1.0 Imports: 8 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. It also supports backend-requested one-shot yes/no, selection, and captcha dialogs through asynchronous messages.

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.

License

Files in this repository are distributed under the CC0 license.

CC0
To the extent possible under law, ASCIIMoth has waived all copyright and related or neighboring rights to formular.

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"
	MessageDialogCreate        = "dialog.create"
	MessageFieldUpdate         = "field.update"
	MessageFieldValidate       = "field.validate"
	MessageFormApply           = "form.apply"
	MessageButtonPress         = "button.press"
	MessageAutocompleteRequest = "autocomplete.request"
	MessageDialogResponse      = "dialog.response"
)

Message type constants used in Formular JSON envelopes.

View Source
const (
	DialogKindYesNo     = "yesno"
	DialogKindSelection = "selection"
	DialogKindCaptcha   = "captcha"
)

Dialog kind constants supported by the base protocol.

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.

View Source
const (
	StateOperatorEquals    = "equals"
	StateOperatorNotEquals = "notEquals"
	StateOperatorEmpty     = "empty"
	StateOperatorNotEmpty  = "notEmpty"
)

State condition operator constants used by frontend item state rules.

Variables

This section is empty.

Functions

func ArrayElementBoolValue added in v0.3.1

func ArrayElementBoolValue(v any, fieldID string) (bool, bool)

ArrayElementBoolValue returns one boolean field value from an array element.

func ArrayElementFieldValue added in v0.3.1

func ArrayElementFieldValue(v any, fieldID string) (any, bool)

ArrayElementFieldValue returns one field value from an array element value.

func ArrayElementIntValue added in v0.3.1

func ArrayElementIntValue(v any, fieldID string) (int, bool)

ArrayElementIntValue returns one integer field value from an array element.

func ArrayElementStringValue added in v0.3.1

func ArrayElementStringValue(v any, fieldID string) (string, bool)

ArrayElementStringValue returns one string field value from an array element.

func BoolValue added in v0.3.1

func BoolValue(v any) (bool, bool)

BoolValue decodes a Formular scalar value as a bool.

Only concrete booleans are accepted. Failed conversions return false, false.

func DialogSelectionValuesFromAny added in v0.3.3

func DialogSelectionValuesFromAny(v any) ([]string, bool)

DialogSelectionValuesFromAny decodes a single-selection or multiple-selection dialog result.

A string becomes a one-item result. String slices and JSON-decoded arrays of strings are copied into the returned slice. Other values return nil, false.

func DispatchDialogMessage added in v0.3.3

func DispatchDialogMessage(msg Message, h DialogHandler) (handled bool, err error)

DispatchDialogMessage routes a frontend dialog.response message.

It returns handled=false for messages with a different menu or dialog ID, for unsupported message types, and for malformed JSON-like inputs. A matching response is handled even when OnResponse is nil.

func DispatchFormMessage added in v0.3.1

func DispatchFormMessage(msg Message, h FormHandler) (handled bool, err error)

DispatchFormMessage routes a frontend form message to a FormHandler.

It returns handled=false for messages with a different menu or block, for unsupported message types, and for malformed JSON-like inputs. Matching messages are handled even when the corresponding callback is nil.

func FloatValue added in v0.3.1

func FloatValue(v any) (float64, bool)

FloatValue decodes a Formular scalar value as a finite float64.

Go integer and floating-point numeric types, plus json.Number, are accepted. Failed conversions return 0, false.

func IntValue added in v0.3.1

func IntValue(v any) (int, bool)

IntValue decodes a Formular scalar value as an int.

Signed and unsigned integer types are accepted when they fit in int. json.Number and floating-point values are accepted only when finite and exactly whole-numbered. Failed conversions return 0, false.

func IsValidationError

func IsValidationError(err error) bool

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

func StringValue added in v0.3.1

func StringValue(v any) (string, bool)

StringValue decodes a Formular scalar value as a string.

Only concrete strings are accepted. Failed conversions return "", false.

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 InstantiateArrayTemplate added in v0.3.1

func InstantiateArrayTemplate(template ArrayTemplate, id string, values map[string]any) ArrayElement

InstantiateArrayTemplate copies an array template into a concrete element and overlays field values by item ID.

Unspecified fields keep their template defaults. The template is not mutated.

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 ArrayElementValueFromAny added in v0.3.1

func ArrayElementValueFromAny(v any) (ArrayElementValue, bool)

ArrayElementValueFromAny decodes a single array element value from typed or JSON-like data.

The canonical ArrayElementValue shape is accepted directly. Map-shaped values must contain non-empty string "id" and "template" fields. Missing "values" is treated as an empty value map; malformed input returns false.

func ArrayElementValuesFromAny added in v0.3.1

func ArrayElementValuesFromAny(v any) ([]ArrayElementValue, bool)

ArrayElementValuesFromAny decodes one or more array element values.

It accepts []ArrayElementValue, []any, and other slice/array values whose elements individually decode with ArrayElementValueFromAny. Passing a single element value returns a one-element slice.

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 AutocompleteHints added in v0.3.1

func AutocompleteHints(menuID string, menuGen uint64, ref FieldRef, prefix string, hints []string) AutocompleteHintsMessage

AutocompleteHints constructs an autocomplete.hints message for one field.

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 BlockSnapshot added in v0.3.1

func BlockSnapshot(menuID string, menuGen, blockGen uint64, block Block) BlockSnapshotMessage

BlockSnapshot constructs a block.snapshot message for one block.

menuGen is the containing menu generation. blockGen is copied into the message envelope; the block's own Generation field is left unchanged so callers retain explicit control of the block snapshot identity.

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 Choice added in v0.3.1

type Choice struct {
	// Value is the protocol value placed in the radio field's allowedValues.
	Value string
	// Label is optional caller-owned display metadata and is not serialized by
	// the core protocol today.
	Label string
}

Choice describes one radio field choice.

The current Formular protocol transmits allowed radio values but does not carry separate display labels for each value. Label is retained for future callers that want to keep local choice metadata near the builder call.

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 Dialog added in v0.3.3

type Dialog struct {
	// ID is unique among pending dialogs for one menu.
	ID string `json:"id"`
	// Kind is yesno, selection, or captcha.
	Kind string `json:"kind"`
	// Title is the user-facing modal heading.
	Title string `json:"title"`
	// Text is optional plain text shown before the input controls.
	Text string `json:"text,omitempty"`
	// Options contains the allowed results for a selection dialog.
	Options []DialogOption `json:"options,omitempty"`
	// Multiple permits more than one result in a selection dialog.
	Multiple bool `json:"multiple,omitempty"`
	// Resources contains base64-encoded content displayed by the dialog.
	Resources []DialogResource `json:"resources,omitempty"`
	// Placeholder is optional empty-state text for captcha input.
	Placeholder string `json:"placeholder,omitempty"`
	// YesLabel replaces the default Yes button label for a yes/no dialog.
	YesLabel string `json:"yesLabel,omitempty"`
	// NoLabel replaces the default No button label for a yes/no dialog.
	NoLabel string `json:"noLabel,omitempty"`
	// SubmitLabel replaces the default Submit button label.
	SubmitLabel string `json:"submitLabel,omitempty"`
	// CancelLabel replaces the default Cancel button label.
	CancelLabel string `json:"cancelLabel,omitempty"`
}

Dialog describes one backend-requested modal interaction.

func CaptchaDialog added in v0.3.3

func CaptchaDialog(id, title, text string, image DialogResource) Dialog

CaptchaDialog constructs a captcha dialog description with one image.

func SelectionDialog added in v0.3.3

func SelectionDialog(id, title, text string, options ...DialogOption) Dialog

SelectionDialog constructs a single-selection dialog description.

func YesNoDialog added in v0.3.3

func YesNoDialog(id, title, text string) Dialog

YesNoDialog constructs a yes/no dialog description.

func (Dialog) Copy added in v0.3.3

func (d Dialog) Copy() Dialog

Copy returns a deep copy of d.

func (Dialog) Validate added in v0.3.3

func (d Dialog) Validate() error

Validate returns an error if d is not a valid dialog description.

type DialogCreateMessage added in v0.3.3

type DialogCreateMessage struct {
	MessageBase
	// Dialog describes the modal interaction and any attached resources.
	Dialog Dialog `json:"dialog"`
}

DialogCreateMessage is sent by a backend to request one modal interaction.

A frontend sends at most one dialog.response for this message. Resources are part of Dialog and therefore travel in the same message as their use.

func DialogCreate added in v0.3.3

func DialogCreate(menuID string, menuGen uint64, dialog Dialog) DialogCreateMessage

DialogCreate constructs a dialog.create message.

The dialog and all attached resources are copied before they are stored in the message.

func (DialogCreateMessage) Copy added in v0.3.3

Copy returns a deep copy of m.

func (DialogCreateMessage) Validate added in v0.3.3

func (m DialogCreateMessage) Validate() error

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

type DialogHandler added in v0.3.3

type DialogHandler struct {
	// MenuID filters messages by menuId when non-empty.
	MenuID string
	// DialogID filters messages by dialogId when non-empty.
	DialogID string

	// OnResponse receives the dialog ID and result. A nil result means that the
	// user canceled the dialog.
	OnResponse func(dialogID string, value any) error
}

DialogHandler contains an optional callback for one-shot dialog responses.

type DialogOption added in v0.3.3

type DialogOption struct {
	// Value is the stable backend-facing result.
	Value string `json:"value"`
	// Label is the user-facing option text.
	Label string `json:"label"`
	// Selected marks an initial selection.
	Selected bool `json:"selected,omitempty"`
}

DialogOption is one result that a selection dialog can return.

func (DialogOption) Copy added in v0.3.3

func (o DialogOption) Copy() DialogOption

Copy returns a deep copy of o.

func (DialogOption) Validate added in v0.3.3

func (o DialogOption) Validate() error

Validate returns an error if o is not a valid dialog option.

type DialogResource added in v0.3.3

type DialogResource struct {
	// ID identifies the resource inside this dialog.
	ID string `json:"id"`
	// MIMEType identifies the decoded content type.
	MIMEType string `json:"mimeType"`
	// Data is the resource bytes encoded as standard base64 text.
	Data string `json:"data"`
	// Alt is optional alternative text for visual content.
	Alt string `json:"alt,omitempty"`
}

DialogResource is content attached directly to a dialog.create message.

func DialogResourceFromBytes added in v0.3.3

func DialogResourceFromBytes(id, mimeType, alt string, data []byte) DialogResource

DialogResourceFromBytes constructs an attached resource from raw bytes.

func (DialogResource) Copy added in v0.3.3

func (r DialogResource) Copy() DialogResource

Copy returns a deep copy of r.

func (DialogResource) Validate added in v0.3.3

func (r DialogResource) Validate() error

Validate returns an error if r is not a valid attached dialog resource.

type DialogResponseMessage added in v0.3.3

type DialogResponseMessage struct {
	MessageBase
	// DialogID correlates this response with a dialog.create message.
	DialogID string `json:"dialogId"`
	// Value is the user result, or nil when the user cancels the dialog.
	Value any `json:"value"`
}

DialogResponseMessage is sent by a frontend when a one-shot dialog ends.

Value is bool for a yes/no dialog, string or []string for a selection, string for a captcha, and nil when the user cancels the dialog.

func (DialogResponseMessage) Copy added in v0.3.3

Copy returns a deep copy of m.

func (DialogResponseMessage) Validate added in v0.3.3

func (m DialogResponseMessage) Validate() error

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

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"`
	// Selector names a frontend-provided set of text values to offer as choices.
	Selector string `json:"selector,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"`
	// Copyable declares optional text for a frontend copy action.
	Copyable *Copyable `json:"copyable,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 FieldOption added in v0.3.1

type FieldOption = func(*Item)

FieldOption mutates a field item produced by the field builders in this file.

The option receives the full item so it can set item-level metadata such as Help as well as field-level metadata. Field-only options are no-ops when used with non-field builders such as Button.

var Multiline FieldOption = func(item *Item) {
	withField(item, func(field *Field) {
		field.Multiline = true
	})
}

Multiline allows newline-preserving entry for text fields.

var Readonly FieldOption = func(item *Item) {
	withField(item, func(field *Field) {
		field.Readonly = true
	})
}

Readonly marks a field as display-only.

var Required FieldOption = func(item *Item) {
	withField(item, func(field *Field) {
		field.Required = true
	})
}

Required marks a field as required for frontend form apply.

var Secret FieldOption = func(item *Item) {
	withField(item, func(field *Field) {
		field.Secret = true
	})
}

Secret requests hidden entry for text fields.

var Validation FieldOption = func(item *Item) {
	withField(item, func(field *Field) {
		field.Validation = true
	})
}

Validation enables frontend field.validate messages for a field.

func AllowedValues added in v0.3.1

func AllowedValues(values ...any) FieldOption

AllowedValues sets the protocol allowedValues list for text, int, float, or radio fields. Values are deep-copied before being stored on the field.

func AutocompleteConfig added in v0.3.1

func AutocompleteConfig(config Autocomplete) FieldOption

AutocompleteConfig sets text-field autocomplete behavior.

The name avoids colliding with the Autocomplete struct type.

func Placeholder added in v0.3.1

func Placeholder(text string) FieldOption

Placeholder sets placeholder text for a field.

func Selector added in v0.3.2

func Selector(name string) FieldOption

Selector sets the name of a frontend-provided set of text values.

A selector lets the frontend supply choices that are not known to the backend, such as the names of users known to the local application.

func Status added in v0.3.1

func Status(status string) FieldOption

Status sets the backend validation status shown for a field.

func StatusText added in v0.3.1

func StatusText(text string) FieldOption

StatusText sets explanatory text for a field status.

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 FieldStatusFromError added in v0.3.1

func FieldStatusFromError(menuID string, menuGen, blockGen uint64, ref FieldRef, err error) FieldStatusMessage

FieldStatusFromError constructs a field.status message from a Go error.

A nil error produces an ok status. A non-nil error produces an error status with err.Error() as StatusText.

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 FormHandler added in v0.3.1

type FormHandler struct {
	// MenuID filters messages by menuId when non-empty.
	MenuID string
	// BlockID filters messages by blockId when non-empty.
	BlockID string

	// OnApply receives each field value from a matching form.apply message.
	OnApply func(fieldID string, value any) error
	// OnValidate receives the field value from a matching field.validate message.
	OnValidate func(fieldID string, value any) error
	// OnUpdate receives the field value from a matching field.update message.
	OnUpdate func(fieldID string, value any) error
}

FormHandler contains optional callbacks for frontend form messages routed to one menu and block.

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"`
	// StateConditions declares frontend-only visibility and readonly rules.
	StateConditions *StateConditions `json:"stateConditions,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 Button added in v0.3.1

func Button(id, label string, opts ...ItemOption) Item

Button constructs a button item.

func CheckboxField added in v0.3.1

func CheckboxField(id, label string, value bool, opts ...FieldOption) Item

CheckboxField constructs a checkbox field item.

func FloatField added in v0.3.1

func FloatField(id, label string, value float64, opts ...FieldOption) Item

FloatField constructs a floating-point field item.

func IntField added in v0.3.1

func IntField(id, label string, value int, opts ...FieldOption) Item

IntField constructs an integer field item.

func Logs added in v0.3.1

func Logs(id, label string, lines []LogLine) Item

Logs constructs a logs display item.

func MultilineTextField added in v0.3.1

func MultilineTextField(id, label, value string, opts ...FieldOption) Item

MultilineTextField constructs a text field item that preserves newlines.

func PlainLabel added in v0.3.1

func PlainLabel(id, text string) Item

PlainLabel constructs a plain text label item.

func RadioField added in v0.3.1

func RadioField(id, label string, value string, options []Choice, opts ...FieldOption) Item

RadioField constructs a radio field item from string choices.

func ReadonlyTextField added in v0.3.1

func ReadonlyTextField(id, label, value string, opts ...FieldOption) Item

ReadonlyTextField constructs a readonly text field item.

func SecretTextField added in v0.3.1

func SecretTextField(id, label, value string, opts ...FieldOption) Item

SecretTextField constructs a text field item that requests hidden entry.

func TextField added in v0.3.1

func TextField(id, label, value string, opts ...FieldOption) Item

TextField constructs a text field 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 ItemOption added in v0.3.1

type ItemOption = func(*Item)

ItemOption mutates an item produced by item builders such as Button.

func Help added in v0.3.1

func Help(text string) ItemOption

Help sets plaintext help on any item.

func ReadonlyWhen added in v0.3.4

func ReadonlyWhen(condition StateCondition) ItemOption

ReadonlyWhen disables an interactive item while condition is true.

A static field Readonly flag, button Inactive flag, or inactive block still disables the item when this condition is false.

func VisibleWhen added in v0.3.4

func VisibleWhen(condition StateCondition) ItemOption

VisibleWhen makes an item visible only while condition is true.

The browser evaluates the condition from its current local field values. It does not need a backend round trip.

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.

func ForcedMenuSnapshot added in v0.3.1

func ForcedMenuSnapshot(menuID string, generation uint64, blocks ...Block) MenuSnapshotMessage

ForcedMenuSnapshot constructs a menu.snapshot message that requests a full frontend refresh, including local state that ordinary snapshots may preserve.

func MenuSnapshot(menuID string, generation uint64, blocks ...Block) MenuSnapshotMessage

MenuSnapshot constructs a complete menu.snapshot message.

The blocks are deep-copied so callers can continue mutating local menu definitions after constructing the outbound message.

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 MenuSnapshotState struct {
	// contains filtered or unexported fields
}

MenuSnapshotState keeps the latest menu.snapshot-equivalent state for menus.

It is intended for frontends and middleware that forward Formular messages and need to serve a newly connected frontend from locally cached menu state. It applies only messages that affect the observable menu snapshot. Ephemeral messages such as autocomplete and dialog messages are ignored.

func NewMenuSnapshotState added in v0.2.0

func NewMenuSnapshotState() *MenuSnapshotState

NewMenuSnapshotState creates an empty menu snapshot state cache.

func (s *MenuSnapshotState) Apply(message any) bool

Apply applies one typed Formular message or map-shaped decoded JSON message.

func (s *MenuSnapshotState) ApplyJSON(data []byte) (bool, error)

ApplyJSON decodes and applies one Formular message.

func (s *MenuSnapshotState) ForceSnapshot(menuID string) (MenuSnapshotMessage, bool)

ForceSnapshot returns the cached snapshot with Force set for frontend reloads.

func (s *MenuSnapshotState) ForceSnapshots() []MenuSnapshotMessage

ForceSnapshots returns all cached snapshots sorted by menu id with Force set.

func (s *MenuSnapshotState) Snapshot(menuID string) (MenuSnapshotMessage, bool)

Snapshot returns the cached snapshot for one menu.

func (s *MenuSnapshotState) Snapshots() []MenuSnapshotMessage

Snapshots returns all cached snapshots sorted by menu id.

type Message added in v0.3.1

type Message = any

Message is any decoded Formular protocol message.

Dispatch helpers accept typed message structs, pointers to those structs, JSON bytes, json.RawMessage, and map-shaped decoded JSON values.

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 StateCondition added in v0.3.4

type StateCondition struct {
	// Source identifies the field value used by a comparison condition.
	Source *StateConditionSource `json:"source,omitempty"`
	// Operator is equals, notEquals, empty, or notEmpty for a comparison.
	Operator string `json:"operator,omitempty"`
	// Value is the expected string, number, or Boolean for equality operators.
	Value any `json:"value,omitempty"`
	// All is true when every child condition is true.
	All []StateCondition `json:"all,omitempty"`
	// Any is true when at least one child condition is true.
	Any []StateCondition `json:"any,omitempty"`
	// Not negates one child condition.
	Not *StateCondition `json:"not,omitempty"`
}

StateCondition is one value comparison or a Boolean combination of other conditions. Exactly one of Source, All, Any, or Not must define a condition.

func AllStateConditions added in v0.3.4

func AllStateConditions(conditions ...StateCondition) StateCondition

AllStateConditions constructs a condition that requires every child.

func AnyStateConditions added in v0.3.4

func AnyStateConditions(conditions ...StateCondition) StateCondition

AnyStateConditions constructs a condition that requires at least one child.

func FieldEmpty added in v0.3.4

func FieldEmpty(fieldID string) StateCondition

FieldEmpty tests whether a field in the current scope has an empty value.

func FieldEquals added in v0.3.4

func FieldEquals(fieldID string, value any) StateCondition

FieldEquals tests a field in the target item's current scope for equality.

func FieldNotEmpty added in v0.3.4

func FieldNotEmpty(fieldID string) StateCondition

FieldNotEmpty tests whether a field in the current scope has a non-empty value.

func FieldNotEquals added in v0.3.4

func FieldNotEquals(fieldID string, value any) StateCondition

FieldNotEquals tests a field in the current scope for inequality.

func NotStateCondition added in v0.3.4

func NotStateCondition(condition StateCondition) StateCondition

NotStateCondition constructs a condition that negates its child.

func StateValueCondition added in v0.3.4

func StateValueCondition(source StateConditionSource, operator string, value any) StateCondition

StateValueCondition constructs a field value comparison condition.

Equals and notEquals require a string, number, or Boolean value. Empty and notEmpty ignore value, so callers should pass nil for those operators.

func (StateCondition) Copy added in v0.3.4

func (c StateCondition) Copy() StateCondition

Copy returns a deep copy of c.

func (StateCondition) Validate added in v0.3.4

func (c StateCondition) Validate() error

Validate returns an error if c is not a valid item state condition.

type StateConditionSource added in v0.3.4

type StateConditionSource struct {
	// BlockID selects a top-level field in another block when it is set. When it
	// is empty, FieldID resolves in the target item's current scope.
	BlockID string `json:"blockId,omitempty"`
	// FieldID identifies the source field.
	FieldID string `json:"fieldId"`
}

StateConditionSource identifies a field whose current frontend value is used by a state condition.

func StateBlockFieldSource added in v0.3.4

func StateBlockFieldSource(blockID, fieldID string) StateConditionSource

StateBlockFieldSource selects a top-level field in a specified block.

func StateFieldSource added in v0.3.4

func StateFieldSource(fieldID string) StateConditionSource

StateFieldSource selects a field in the target item's current scope.

For a top-level item, the scope is its block. For an item in an array element, the scope is that element.

func (StateConditionSource) Copy added in v0.3.4

Copy returns a deep copy of s.

func (StateConditionSource) Validate added in v0.3.4

func (s StateConditionSource) Validate() error

Validate returns an error if s is not a valid state condition source.

type StateConditions added in v0.3.4

type StateConditions struct {
	// Visible controls whether the frontend renders the item as visible.
	Visible *StateCondition `json:"visible,omitempty"`
	// Readonly controls whether the frontend permits interaction with the item.
	Readonly *StateCondition `json:"readonly,omitempty"`
}

StateConditions controls item state from current frontend field values.

Visible is evaluated directly: a true result shows the item and a false result hides it. Readonly disables interactive items when it is true.

func (StateConditions) Copy added in v0.3.4

Copy returns a deep copy of s.

func (StateConditions) Validate added in v0.3.4

func (s StateConditions) Validate() error

Validate returns an error if s is not a valid item state condition set.

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