Typed machines
States and events are enums, and an illegal assembly does not compile.
Document workflow
This is the machine Document Workflow runs. InReview and Approval are composites: all[InReview] cancels to Draft, and all[Approval] abandons to Cancelled.
Install
libraryDependencies += "rocks.earlyeffect" %% "mechanoid" % "0.8.0"
libraryDependencies += "dev.zio" %% "zio" % "2.1.26"
libraryDependencies += "rocks.earlyeffect" %%% "mechanoid" % "0.8.0"
libraryDependencies += "dev.zio" %%% "zio" % "2.1.26"
libraryDependencies += "rocks.earlyeffect" %%% "mechanoid-web" % "0.8.0"
libraryDependencies += "rocks.earlyeffect" %% "mechanoid-postgres" % "0.8.0"
Machine.apply
Machine.apply is the public constructor. Citing that method expands the inline macro, which rejects a placeholder assembly, so the panel is mechanoid.machine.Machine, cut after apply.
object Machine:
/** Create a Machine from a validated Assembly.
*
* This is the ONLY public way to create a Machine. The assembly must be created via the `assembly` or `assemblyAll`
* macros, which perform compile-time validation of transitions.
*
* @tparam S
* The state type (must have Finite instance)
* @tparam E
* The event type (must have Finite instance)
* @param assembly
* A validated assembly created via `assembly()` or `assemblyAll()`
* @return
* A runnable Machine
*
* @example
* {{{
* import mechanoid.Mechanoid.*
*
* // Using assembly()
* val machine = Machine(assembly[State, Event](
* Idle via Start to Running,
* Running via Stop to Idle,
* ))
*
* // Using assemblyAll with block syntax
* val machine2 = Machine(assemblyAll[State, Event]:
* Idle via Start to Running
* Running via Stop to Idle
* )
* }}}
*/
inline def apply[S, E](inline assembly: Assembly[S, E])(using
inline finiteS: Finite[S],
inline finiteE: Finite[E],
): Machine[S, E] =
${ MachineMacros.applyImpl[S, E]('assembly, 'finiteS, 'finiteE) }…