ACTION_STATUSES
re-export| Package | @formscript/runtime |
|---|---|
| Specification | 4.10, 8.7, 11, 11.1, 11.2, 11.3 |
| Depends on | ast, decimal, errors, evaluator, types |
@formscript/runtime
Remote data and actions, per §11
of the specification: action (§11.1), source (§11.2) and offline behaviour
(§11.3).
An action or a source is data, not code (Spec-11.1): the runtime owns transport, auth and serialisation, and the document contributes values. This package models the declarations, builds the requests, and drives the transport the host supplies.
The declarations
import { readActionProperties, resolveAction } from '@formscript/runtime';
const properties = readActionProperties(actionStatement);
const action = resolveAction(properties, { url: 'https://api.example.com/applications' });
action.method; // 'POST' — the default of §8.7
action.conflict; // 'skip' — the default of Spec-11.10
readActionProperties and readSourceProperties read the document-level
properties of an action or a source block and keep the expressions that
need evaluation (url, params, body, when). resolveAction and
resolveSource turn them into the runtime declarations.
The request
buildSourceRequest and buildActionRequest are pure: they take a
declaration and the evaluated values, and they return a request description.
No network, no clock, no randomness.
const built = buildSourceRequest(source, { params: { region: 'GB' } });
built.request.method; // 'GET'
built.request.url; // 'https://api.example.com/countries?region=GB'
The body of an action is $form.output — the projected output document
(§4.10) — unless the action declares its own body (Spec-11.4).
The parameter mapping
| Mapped value | Outcome |
|---|---|
| a value | bound; the parameter is sent |
absent (null, 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 (Spec-6.3, E-EVAL-07) |
An array is sent as repeated fields of the same name.
Running an action
import { executeAction } from '@formscript/runtime';
const execution = await executeAction(action, { transport, clock });
execution.status; // 'idle' | 'pending' | 'success' | 'error' (Spec-11.2)
The status is a normal derived value, so a form can branch on it
(match $submit_application.status). ActionStatusStore holds the status of
every action for a host that wants to read it.
retry uses exponential backoff with jitter and is capped at the declared
value; a 4xx response is never retried (Spec-11.3).
Resolving a source
import { SourceResolver } from '@formscript/runtime';
const resolver = new SourceResolver({ transport, clock, sources });
resolver.status('countries'); // 'idle' — nothing is fetched until it is referenced (Spec-11.5)
await resolver.resolve('countries');
resolver.status('countries'); // 'ready' — the source produced its value (Spec-6.3)
A source is lazily evaluated and cached (Spec-11.5). Its cache lifetime is
none, 5m, 1h, 24h, 7d or an explicit duration (Spec-11.6); an
explicit duration is calendar-relative (Spec-3.12). A field whose options
come from a source renders in a pending state until the source resolves
(Spec-11.7).
Offline behaviour
import { OfflineQueue } from '@formscript/runtime';
const queue = new OfflineQueue(store, clock);
await queue.enqueue(action, request);
const outcomes = await queue.replay(transport);
A runtime operating offline must preserve unsent submissions in a durable
queue and replay them on reconnect, in submission order (Spec-11.9). The store
is the host's, because durability is the host's business. Each submission
follows the conflict policy of its action (Spec-11.10): retry sends it
again, skip leaves it alone, and fail stops the replay. The default is
skip, so an action that declares no policy is never re-sent. Every outcome is
reported, so a replay is never silent.
The host interfaces
interface Transport {
send(request: TransportRequest): Promise<TransportResponse>;
}
interface Clock {
now(): number;
sleep(ms: number): Promise<void>;
}
Transport is the network the runtime does not own (Spec-11.1). Clock
supplies the time and the wait the backoff needs (Spec-11.3). A test supplies
its own, which is why nothing in this package opens a socket.
Judgement calls
- The action's request target is its
url. §8.7 gives an action aurl, amethod, abody, awhen, atimeout, aretryand aconflict, and notargetand noparams:paramsbelongs tosource. The model accepts a host-supplied parameter map and headers on both declarations, and a document that declaresparamson an action is reported by the analyzer asE-PROP-02. - The parameter mapping is an extension by analogy. §11.1 states no mapping rules, so the rules above extend the two absences of the language: an absent value is asked-but-not-answered (Spec-4.35) and an inapplicable value is not-asked (Spec-8.3).
- The retry cap is a cap on the number of retries. "retry MUST use
exponential backoff with jitter and MUST cap at the declared value"
(Spec-11.3) is read as: at most
retryretries, soretry + 1attempts. - The backoff shape is not specified. The first delay is 1000 ms, the delay doubles with every attempt, and the jitter is half the exponential delay. The source of the jitter is injected, so a test is deterministic.
- The headers are the host's. §8.7 lists no
headersproperty and Spec-11.1 gives auth to the runtime, so the headers of a declaration are host-supplied rather than document-declared. The runtime addscontent-type: application/jsonwhen it sends a body and the host has not set one. - The source status has its own vocabulary. Spec-6.3 names it:
idle | pending | ready | error. A source that has produced its value isready, which is whatfieldReadAfterSourcetests for; the runtime declares the vocabulary itself, because the engine declares the same one and the dependency must not run from the engine to the runtime (Spec-6.3, Spec-11.7). - A failed source leaves the field unknown. The diagnostic is
E-IO-01("source fetch failed"). The field keeps its content, so it readsnull(Spec-5.8); it does not become inapplicable, because the question was asked, and it does not take the error value, which would poison the data plane (Spec-5.3). - A source that fails is not retried. Spec-11.3 gives the retry policy to actions only.
- The queue removes a skipped submission and keeps a failed one. A
skipsubmission is deliberately not sent, so it leaves the queue; afailsubmission stays queued and stops the replay, so that the submission order of Spec-11.9 is preserved.
Ambiguities in the specification
- Spec-11.3's "MUST cap at the declared value" does not say whether the cap is on the number of retries or on the delay.
- Spec-11.10 does not say how a runtime reports an action whose conflict policy
was not chosen explicitly. The runtime records it as
conflictDeclaredand leaves the reporting to the host.
Two ambiguities that earlier revisions of this package listed here have been
repaired in the specification itself: §11.3 now says what an unreachable
source does (Spec-11.11), and Spec-11.10 now states the default conflict
policy and that it MUST NOT be retry.
Public API
74 exported symbols.
ActionDeclaration
interface
A resolved `action` declaration; the runtime owns transport, auth and serialisation (Spec-11.1).
ActionExecution
interfaceActionExecutionOptions
interfaceActionProperties
interface
The document-level properties of an action, before evaluation (Spec-11.1).
ActionResolution
interface
The values a host has evaluated for a declaration.
ActionState
interfaceActionStatus
type
The status of an action (Spec-11.2); a normal derived value a form can branch on.
ActionStatusStore
re-exportbuildActionRequest
re-exportbuildRequest
re-exportbuildSourceRequest
re-exportcacheDurationMs
function
The lifetime of a cache policy in milliseconds; an explicit duration is calendar-relative (Spec-3.12).
CachePolicy
type
The cache lifetimes of §11.6: the five named values, or an explicit duration.
canRetry
function
Whether the action may be tried again; a 4xx response is never retried (Spec-11.3).
Clock
interface
The clock the host must supply.
CONFLICT_POLICIES
constConflictPolicy
type
The replay conflict policies of §11.3.
DEFAULT_ACTION_METHOD
const
The default method of an action (§8.7).
DEFAULT_CACHE_POLICY
const
The default cache lifetime of a source (§8.7).
DEFAULT_CONFLICT_POLICY
const
The default replay conflict policy of an action (Spec-11.10).
DEFAULT_SOURCE_METHOD
const
The default method of a source (§8.7).
Duration
interface
Duration literals (§3.6): `30d`, `6mo`, `2y`, `PT30M`; calendar-relative (Spec-3.12).
durationMs
function
The length of a duration literal in milliseconds; `undefined` when invalid.
durationMsOf
function
The length of a duration in milliseconds, measured from `from` (Spec-3.12).
EnqueueResult
typeexecuteAction
function
Runs an action; the status moves `idle` → `pending` → `success` or `error` (Spec-11.2).
fieldReadAfterSource
re-exportHTTP_METHODS
constHttpMethod
type
The HTTP methods a request may use (§8.7).
isActionStatus
re-exportisCachePolicy
functionisClientErrorStatus
re-exportisConflictPolicy
functionisHttpMethod
functionisSourceStatus
re-exportisSuccessStatus
re-exportmapParameter
re-exportmapParameters
re-exportMappedParameter
interfaceNAMED_CACHE_POLICIES
constOfflineQueue
re-exportOfflineStore
interface
The durable storage of the queue; a runtime operating offline must preserve submissions (Spec-11.9).
ParameterMap
type
The evaluated values of the parameters of a request (§8.7).
ParameterReason
type
Why a parameter was omitted or failed.
ParameterState
type
What happened to one parameter of a request.
parseDuration
function
Parses a duration literal; `undefined` when the text is not one.
QueuedSubmission
interface
A submission that has not reached the server yet.
QueueFullError
re-exportreadActionProperties
function
Reads the properties of an `action` block (§8.7, §11.1).
readSourceProperties
function
Reads the properties of a `source` block (§8.7, §11.2).
ReplayOutcome
interfaceReplayOutcomeKind
typeRequestBuildResult
typeRequestDescription
interface
A request the runtime is about to send. The transport is the host's.
RequestOptions
interface
The values a host supplies when it asks for a request.
resolveAction
function
Builds the runtime declaration of an action from its properties (§11.1).
resolveSource
function
Builds the runtime declaration of a source from its properties (§11.2).
RETRY_BASE_DELAY_MS
const
The first delay of the exponential backoff of Spec-11.3.
retryDelayMs
function
The delay before the next attempt: exponential backoff with jitter (Spec-11.3).
serializeBody
re-exportSOURCE_STATUSES
re-exportSourceDeclaration
interface
A resolved `source` declaration (§11.2).
SourceFetchResult
interfaceSourceProperties
interface
The document-level properties of a source, before evaluation (§11.2).
SourceResolution
interfaceSourceResolver
re-exportSourceResolverOptions
interfaceSourceState
interfaceSourceStatus
type
The status of a source (Spec-6.3); a resolved source is `ready`.
Transport
interface
The transport the host must supply; the runtime owns the request, never the network (Spec-11.1).
TransportRequest
interface
The request the runtime hands to the host's transport.
TransportResponse
interface
What the host's transport reports back.
TransportTimeoutError
re-export