CI Hex.pm Version Hex Downloads Hex Docs License

Block document model, one-way SCXML compiler, and LiveView editor components for composing Statifier statecharts from typed blocks.

Pre-1.0. Until statifier_blocks reaches v1.0, its public surface may change between minor releases, sometimes drastically: a release may rename modules, callbacks, table columns, telemetry events or error vocabulary with no compatibility shim. Every such change is recorded in CHANGELOG.md under a bold Breaking heading that says what to do about it. Pinning to an exact minor - ~> X.Y.0 - is the recommended way to consume the package until 1.0.

Why a block layer

Statecharts are the right execution model for long-running workflows, and SCXML is the right interchange format for them - but neither is something a non-engineer will author by hand. This package is the authoring layer:

  • A block document model. A document is a tree of typed blocks, each with a declared shape rather than free-form XML. The document, not the chart, is what people edit and you store, one revision per saved edit.
  • A one-way SCXML compiler. A document compiles to an SCXML chart that Statifier runs, with a provenance map that points a running position back at the block that produced it. Nothing decompiles a chart into blocks.
  • LiveView editor components. The components a host embeds so people can compose, rearrange and validate a document in a browser.

Blocks are typed and host-pluggable: a host registers the block types its own domain needs, and the compiler and editor work off that palette rather than off a closed built-in vocabulary.

Installation

def deps do
  [
    {:statifier_blocks, "~> 0.44.0"}
  ]
end

Two dependencies are optional and neither is added for you: phoenix_live_view, without which no editor module compiles at all, and statifier_ui, which an :expression field uses for its expression editor when it resolves. See How to embed the editor in a LiveView host.

Basic usage

A visitor becomes a library patron through a few screens. Declare one step of your own, put it after a core.invoke step that names your check of the visitor's details, and compile the document to a chart:

defmodule MyApp.Blocks.SendWelcome do
  @moduledoc "myapp.send_welcome: sends the new patron a welcome message."
  use StatifierBlocks.InvokeStep,
    invoke_type: "myapp:send_welcome",
    palette: %{label: "Send welcome", group: "Registration"}
end

alias StatifierBlocks.{Block, Compiler, Document, Palette}

palette = Palette.from_modules([{"myapp.send_welcome", MyApp.Blocks.SendWelcome}], core: true)

document =
  Document.new(
    Block.new("core.sequence",
      id: "blk_root",
      slots: %{
        "body" => [
          Block.new("core.invoke",
            id: "blk_check_details",
            config: %{"invoke_type" => "myapp:check_details"}
          ),
          Block.new("myapp.send_welcome", id: "blk_send_welcome")
        ]
      }
    ),
    id: "bdoc_patron_registration"
  )

{:ok, compiled} = Compiler.compile(document, palette)

compiled.invoke_types
#=> ["myapp:check_details", "myapp:send_welcome"]

compiled.scxml =~ ~s(<invoke type="myapp:send_welcome"/>)
#=> true

compiled.scxml is a chart Statifier runs as-is; your host runs the two invoke types it names. How to build a block document and compile it to a chart walks the same path with a branch, a declared datamodel and the provenance map.

Documentation

Compatibility

  • Elixir ~> 1.18.
  • Statifier ~> 2.2, statifier_datamodel ~> 0.4 and predicator ~> 9.4 and >= 9.4.1.
  • phoenix_live_view ~> 1.0 is optional; without it no editor module compiles, and the rest of the package compiles and runs. statifier_ui ~> 0.9 is optional too; with it an :expression field gets its expression editor.
  • Pre-1.0: pin an exact minor (~> 0.44.0) until 1.0, and read the CHANGELOG's Breaking headings when you move it.

License

MIT - see LICENSE.

One file is not: assets/vendor/elk.bundled.js, elkjs 0.9.3 vendored unmodified for the Map hook, is under the Eclipse Public License 2.0, and its licence text ships beside it as assets/vendor/elkjs-LICENSE.md.