I Foundations

The Prototype

A prototype supplies entity declarations, operations, and events that components inherit. Each component can extend the declarations or override implementations with its own behavior, while retaining exclusive ownership of its entities. Inherited operations run as endpoints of that component.

Applications can define prototypes for shared domain behavior, and prototypes can inherit from other prototypes. A component can choose a prototype or declare prototype: null to inherit none.

§The generic prototype

A component that declares an entity inherits Toa’s generic prototype by default; a component without an entity declaration inherits none by default. The generic prototype supplies system properties, common operations, and state-change events. For example, orders.observe reads an order even when the component has no observation implementation of its own.

The runtime maintains these properties alongside the entity’s business state:

PropertyMeaning
idThe entity’s identity.
CREATEDWhen it was created.
UPDATEDWhen its state was last written.
DELETEDWhen it was marked as deleted, or null while active.
VERSIONIts state revision, used for concurrency control.
REGIONThe rank of the region that last wrote its state.

Operations read the timestamps as milliseconds since the Unix epoch.

EndpointTypeBehaviour
transitTransitionMerges input into entity state and returns it.
observeObservationReturns one entity’s state.
assignAssignmentApplies input as a changeset.
enumerateObservationReturns a selected set of entities.
streamObservationReturns a stream of entity state.
ensureEffectReturns an entity, creating it from supplied state if it does not exist.
terminateAssignmentMarks an entity as deleted.

The prototype’s events announce changes to entity state so other components can react:

EventPublished when
createdA new entity is committed.
updatedAn existing entity is written, including when it is marked as deleted.
deletedThe committed entity state is marked as deleted.

§Refinement and forwarding

An inherited operation can be given a more specific contract without replacing its implementation. The generic transit operation, for example, merges input into entity state:

export function transition (input: Input, entry: State) {
  return Object.assign(entry, input)
}

A component can refine it to accept only an order total:

operations:
  transit:
    input:
      type: object
      properties:
        total: { type: integer, minimum: 0 }
      required: [total]
      additionalProperties: false

The runtime validates the input against this contract, then runs the inherited implementation. The component changes what the endpoint accepts, while retaining how it applies the change. This is a refinement of the declaration; overriding would replace the implementation itself.

Alternatively, forwarding exposes that implementation under a different endpoint with its own declaration:

operations:
  setTotal:
    forward: transit
    input:
      type: object
      properties:
        total: { type: integer, minimum: 0 }
      required: [total]
      additionalProperties: false

Here, orders.setTotal uses the inherited transition without a new function or a second operation call. The domain name and contract belong to setTotal; the implementation comes from transit.

The prototype marks transit as virtual: it supplies reusable behavior without exposing an endpoint by default. The first declaration exposes transit explicitly; the second exposes only setTotal.

Search
Search the documentation