FS FormScript

Integrations

A FormScript document can reach out. It can declare a source to fetch data from and an action to submit to, and §11 makes one rule about both:

An action or a source is data, not code (Spec-11.1). The runtime owns transport, auth and serialisation; the document contributes values.

That is the whole integration model. A document says what to call and with what; it never says how. The host owns how.

What a document may declare

§8.7 is the complete list. There is no headers, no auth, no target and no body format — and there is deliberately no place to put them.

Property Applies to Meaning
url action, source Required. The request URL expression
method action, source HTTP method. "GET" for a source, "POST" for an action
when action, source The guard expression
params source An object expression of query parameters
body action The request body expression
timeout action, source Milliseconds
retry action The retry count
cache source The cache lifetime
type source The declared result type
conflict action The replay conflict policy. skip by default

A document that declares params on an action is rejected by the analyzer: params belongs to a source.

The body of an action is $form.output — the projected output document — unless the action declares its own body (Spec-11.4).

What the host must supply

The runtime never opens a socket and never reads a clock by itself. These are the interfaces a host provides.

The host supplies It is Where it is used
Transport send(request) → response. The network the runtime does not own every source and action
Clock now() and sleep(ms). The time, and the wait a backoff needs timeouts, retry, the transaction timestamp
A durable store somewhere to keep unsent submissions the offline queue (Spec-11.9)
The source's status and value idle | pending | ready | error, and the value when it is ready a field whose options come from a source (Spec-11.7)
The action's status idle | pending | success | error so a form can branch on it
$env and $user the environment and the person $env.locale, $env.user.*
A locale and a text catalogue the locale, and a function that resolves a message key §12 internationalisation

Because a host supplies the transport and the clock, a test can supply its own and nothing in the runtime package ever touches the network.

How a value becomes a parameter

The mapping is what makes a source or an action well-behaved when a field has not been answered.

The value What is sent
a value bound — the parameter is sent
absent (null or unknown) bound to an empty value: asked, not answered (Spec-4.35)
inapplicable omitted: not asked (Spec-8.3)
the error value the mapping fails and the request is not built (E-EVAL-07)

An array is sent as repeated fields of the same name.

What the specification deliberately leaves out

No transport beyond HTTP verbs, no authentication scheme, no serialisation format for a body other than the output document, no database, no API convention, no message broker, no vendor. §1.4 says the language does not specify a layout system, and §11 says the same about the network: a FormScript document is not tied to any of it.

That is what makes an integration cheap. The host already has a transport, a store and a session; the document only has to name a URL and a guard.

What is wired up today

Integration What it is
The command line npm run formscript -- lint | run | ast | conformance | errors | level | spec-lint. It runs a document, a transaction script and the suites
The playground the reference implementation compiled to the browser. It runs a form in the page and shows the output document
Server-side rendering a form rendered to HTML and read back from a POST, with no JavaScript at all — see server rendering
The corpus 232 real forms from FHIR and XForms, converted and run — see the corpus
The CI gates the specification lint, the colour gate, the contrast gate, the tutorial gate, the documents gate, the property suite and the conformance suite

See also