mirror of
https://github.com/ash-project/ash_state_machine.git
synced 2024-09-19 12:53:20 +12:00
chore: fsm -> state_machine, event -> transition
This commit is contained in:
parent
6d0fa817a2
commit
06871a9977
15 changed files with 120 additions and 112 deletions
|
@ -1,8 +1,8 @@
|
||||||
spark_locals_without_parens = [
|
spark_locals_without_parens = [
|
||||||
default_initial_state: 1,
|
default_initial_state: 1,
|
||||||
deprecated_states: 1,
|
deprecated_states: 1,
|
||||||
event: 1,
|
transition: 1,
|
||||||
event: 2,
|
transition: 2,
|
||||||
from: 1,
|
from: 1,
|
||||||
initial_states: 1,
|
initial_states: 1,
|
||||||
state_attribute: 1,
|
state_attribute: 1,
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -20,7 +20,7 @@ erl_crash.dump
|
||||||
*.ez
|
*.ez
|
||||||
|
|
||||||
# Ignore package tarball (built via "mix hex.build").
|
# Ignore package tarball (built via "mix hex.build").
|
||||||
ash_fsm-*.tar
|
ash_state_machine-*.tar
|
||||||
|
|
||||||
# Temporary files, for example, from tests.
|
# Temporary files, for example, from tests.
|
||||||
/tmp/
|
/tmp/
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
# AshFsm
|
# AshStateMachine
|
||||||
|
|
||||||
**TODO: Add description**
|
**TODO: Add description**
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
||||||
by adding `ash_fsm` to your list of dependencies in `mix.exs`:
|
by adding `ash_state_machine` to your list of dependencies in `mix.exs`:
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
def deps do
|
def deps do
|
||||||
[
|
[
|
||||||
{:ash_fsm, "~> 0.1.0"}
|
{:ash_state_machine, "~> 0.1.0"}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
||||||
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
||||||
be found at <https://hexdocs.pm/ash_fsm>.
|
be found at <https://hexdocs.pm/ash_state_machine>.
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
defmodule AshFsm do
|
defmodule AshStateMachine do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Documentation for `AshFsm`.
|
Documentation for `AshStateMachine`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
defmodule Event do
|
defmodule Transition do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
The configuration for an event.
|
The configuration for an transition.
|
||||||
"""
|
"""
|
||||||
@type t :: %__MODULE__{
|
@type t :: %__MODULE__{
|
||||||
action: atom,
|
action: atom,
|
||||||
|
@ -16,15 +16,15 @@ defmodule AshFsm do
|
||||||
defstruct [:action, :from, :to]
|
defstruct [:action, :from, :to]
|
||||||
end
|
end
|
||||||
|
|
||||||
@event %Spark.Dsl.Entity{
|
@transition %Spark.Dsl.Entity{
|
||||||
name: :event,
|
name: :transition,
|
||||||
target: Event,
|
target: Transition,
|
||||||
args: [:action],
|
args: [:action],
|
||||||
identifier: :action,
|
identifier: :action,
|
||||||
schema: [
|
schema: [
|
||||||
action: [
|
action: [
|
||||||
type: :atom,
|
type: :atom,
|
||||||
doc: "The corresponding action that is invoked for the event."
|
doc: "The corresponding action that is invoked for the transition."
|
||||||
],
|
],
|
||||||
from: [
|
from: [
|
||||||
type: {:or, [{:list, :atom}, :atom]},
|
type: {:or, [{:list, :atom}, :atom]},
|
||||||
|
@ -39,23 +39,23 @@ defmodule AshFsm do
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@events %Spark.Dsl.Section{
|
@transitions %Spark.Dsl.Section{
|
||||||
name: :events,
|
name: :transitions,
|
||||||
entities: [
|
entities: [
|
||||||
@event
|
@transition
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@fsm %Spark.Dsl.Section{
|
@state_machine %Spark.Dsl.Section{
|
||||||
name: :fsm,
|
name: :state_machine,
|
||||||
schema: [
|
schema: [
|
||||||
deprecated_states: [
|
deprecated_states: [
|
||||||
type: {:list, :atom},
|
type: {:list, :atom},
|
||||||
doc: """
|
doc: """
|
||||||
A list of states that have been deprecated.
|
A list of states that have been deprecated.
|
||||||
The list of states is derived from the events normally.
|
The list of states is derived from the transitions normally.
|
||||||
Use this option to express that certain types should still
|
Use this option to express that certain types should still
|
||||||
be included even though no events go to/from that state anymore.
|
be included even though no transitions go to/from that state anymore.
|
||||||
"""
|
"""
|
||||||
],
|
],
|
||||||
state_attribute: [
|
state_attribute: [
|
||||||
|
@ -74,44 +74,46 @@ defmodule AshFsm do
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
sections: [
|
sections: [
|
||||||
@events
|
@transitions
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
use Spark.Dsl.Extension,
|
use Spark.Dsl.Extension,
|
||||||
sections: [@fsm],
|
sections: [@state_machine],
|
||||||
transformers: [
|
transformers: [
|
||||||
AshFsm.Transformers.FillInEventDefaults,
|
AshStateMachine.Transformers.FillInTransitionDefaults,
|
||||||
AshFsm.Transformers.AddState,
|
AshStateMachine.Transformers.AddState,
|
||||||
AshFsm.Transformers.EnsureStateSelected
|
AshStateMachine.Transformers.EnsureStateSelected
|
||||||
],
|
],
|
||||||
verifiers: [
|
verifiers: [
|
||||||
AshFsm.Verifiers.VerifyEventActions,
|
AshStateMachine.Verifiers.VerifyTransitionActions,
|
||||||
AshFsm.Verifiers.VerifyDefaultInitialState
|
AshStateMachine.Verifiers.VerifyDefaultInitialState
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
AshFsm.BuiltinChanges
|
AshStateMachine.BuiltinChanges
|
||||||
]
|
]
|
||||||
|
|
||||||
def transition_state(%{action_type: :update} = changeset, target) do
|
def transition_state(%{action_type: :update} = changeset, target) do
|
||||||
events = AshFsm.Info.fsm_events(changeset.resource, changeset.action.name)
|
transitions =
|
||||||
attribute = AshFsm.Info.fsm_state_attribute!(changeset.resource)
|
AshStateMachine.Info.state_machine_transitions(changeset.resource, changeset.action.name)
|
||||||
|
|
||||||
|
attribute = AshStateMachine.Info.state_machine_state_attribute!(changeset.resource)
|
||||||
old_state = Map.get(changeset.data, attribute)
|
old_state = Map.get(changeset.data, attribute)
|
||||||
|
|
||||||
case Enum.find(events, fn event ->
|
case Enum.find(transitions, fn transition ->
|
||||||
old_state in List.wrap(event.from) and target in List.wrap(event.to)
|
old_state in List.wrap(transition.from) and target in List.wrap(transition.to)
|
||||||
end) do
|
end) do
|
||||||
nil ->
|
nil ->
|
||||||
Ash.Changeset.add_error(
|
Ash.Changeset.add_error(
|
||||||
changeset,
|
changeset,
|
||||||
AshFsm.Errors.NoMatchingEvent.exception(
|
AshStateMachine.Errors.NoMatchingTransition.exception(
|
||||||
from: old_state,
|
from: old_state,
|
||||||
target: target,
|
target: target,
|
||||||
action: changeset.action.name
|
action: changeset.action.name
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
_event ->
|
_transition ->
|
||||||
Ash.Changeset.force_change_attribute(changeset, attribute, target)
|
Ash.Changeset.force_change_attribute(changeset, attribute, target)
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,12 +1,12 @@
|
||||||
defmodule AshFsm.BuiltinChanges do
|
defmodule AshStateMachine.BuiltinChanges do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Changes for working with AshFsm resources.
|
Changes for working with AshStateMachine resources.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Changes the state to the target state, validating the transition
|
Changes the state to the target state, validating the transition
|
||||||
"""
|
"""
|
||||||
def transition_state(target) do
|
def transition_state(target) do
|
||||||
{AshFsm.BuiltinChanges.TransitionState, target: target}
|
{AshStateMachine.BuiltinChanges.TransitionState, target: target}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule AshFsm.BuiltinChanges.TransitionState do
|
defmodule AshStateMachine.BuiltinChanges.TransitionState do
|
||||||
use Ash.Resource.Change
|
use Ash.Resource.Change
|
||||||
|
|
||||||
def change(changeset, opts, _) do
|
def change(changeset, opts, _) do
|
||||||
AshFsm.transition_state(changeset, opts[:target])
|
AshStateMachine.transition_state(changeset, opts[:target])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule AshFsm.Errors.NoMatchingEvent do
|
defmodule AshStateMachine.Errors.NoMatchingTransition do
|
||||||
@moduledoc "Used when a state change occurs in an action with no matching event"
|
@moduledoc "Used when a state change occurs in an action with no matching transition"
|
||||||
use Ash.Error.Exception
|
use Ash.Error.Exception
|
||||||
|
|
||||||
def_ash_error([:action, :target, :old_state], class: :invalid)
|
def_ash_error([:action, :target, :old_state], class: :invalid)
|
||||||
|
@ -7,11 +7,11 @@ defmodule AshFsm.Errors.NoMatchingEvent do
|
||||||
defimpl Ash.ErrorKind do
|
defimpl Ash.ErrorKind do
|
||||||
def id(_), do: Ash.UUID.generate()
|
def id(_), do: Ash.UUID.generate()
|
||||||
|
|
||||||
def code(_), do: "no_matching_event"
|
def code(_), do: "no_matching_transition"
|
||||||
|
|
||||||
def message(error) do
|
def message(error) do
|
||||||
"""
|
"""
|
||||||
Attempted to change state from #{error.old_state} to #{error.target} in action #{error.action}, but no matching event was configured.
|
Attempted to change state from #{error.old_state} to #{error.target} in action #{error.action}, but no matching transition was configured.
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
17
lib/info.ex
17
lib/info.ex
|
@ -1,15 +1,16 @@
|
||||||
defmodule AshFsm.Info do
|
defmodule AshStateMachine.Info do
|
||||||
use Spark.InfoGenerator, extension: AshFsm, sections: [:fsm]
|
use Spark.InfoGenerator, extension: AshStateMachine, sections: [:state_machine]
|
||||||
|
|
||||||
@spec fsm_events(Ash.Resource.record() | map(), name :: atom) :: list(AshFsm.Event.t())
|
@spec state_machine_transitions(Ash.Resource.record() | map(), name :: atom) ::
|
||||||
def fsm_events(resource_or_dsl, name) do
|
list(AshStateMachine.Transition.t())
|
||||||
|
def state_machine_transitions(resource_or_dsl, name) do
|
||||||
resource_or_dsl
|
resource_or_dsl
|
||||||
|> fsm_events()
|
|> state_machine_transitions()
|
||||||
|> Enum.filter(&(&1.action == name))
|
|> Enum.filter(&(&1.action == name))
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec fsm_all_states(Ash.Resource.record() | map()) :: list(atom)
|
@spec state_machine_all_states(Ash.Resource.record() | map()) :: list(atom)
|
||||||
def fsm_all_states(resource_or_dsl) do
|
def state_machine_all_states(resource_or_dsl) do
|
||||||
Spark.Dsl.Extension.get_persisted(resource_or_dsl, :all_fsm_states, [])
|
Spark.Dsl.Extension.get_persisted(resource_or_dsl, :all_state_machine_states, [])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule AshFsm.Transformers.AddState do
|
defmodule AshStateMachine.Transformers.AddState do
|
||||||
use Spark.Dsl.Transformer
|
use Spark.Dsl.Transformer
|
||||||
alias Spark.Dsl.Transformer
|
alias Spark.Dsl.Transformer
|
||||||
|
|
||||||
|
@ -6,19 +6,21 @@ defmodule AshFsm.Transformers.AddState do
|
||||||
|
|
||||||
def transform(dsl_state) do
|
def transform(dsl_state) do
|
||||||
deprecated_states =
|
deprecated_states =
|
||||||
case AshFsm.Info.fsm_deprecated_states(dsl_state) do
|
case AshStateMachine.Info.state_machine_deprecated_states(dsl_state) do
|
||||||
{:ok, value} -> value || []
|
{:ok, value} -> value || []
|
||||||
_ -> []
|
_ -> []
|
||||||
end
|
end
|
||||||
|
|
||||||
all_states = Enum.uniq(AshFsm.Info.fsm_all_states(dsl_state) ++ deprecated_states)
|
all_states =
|
||||||
attribute_name = AshFsm.Info.fsm_state_attribute!(dsl_state)
|
Enum.uniq(AshStateMachine.Info.state_machine_all_states(dsl_state) ++ deprecated_states)
|
||||||
|
|
||||||
|
attribute_name = AshStateMachine.Info.state_machine_state_attribute!(dsl_state)
|
||||||
module = Transformer.get_persisted(dsl_state, :module)
|
module = Transformer.get_persisted(dsl_state, :module)
|
||||||
|
|
||||||
case Ash.Resource.Info.attribute(dsl_state, attribute_name) do
|
case Ash.Resource.Info.attribute(dsl_state, attribute_name) do
|
||||||
nil ->
|
nil ->
|
||||||
default =
|
default =
|
||||||
case AshFsm.Info.fsm_default_initial_state(dsl_state) do
|
case AshStateMachine.Info.state_machine_default_initial_state(dsl_state) do
|
||||||
{:ok, value} ->
|
{:ok, value} ->
|
||||||
value
|
value
|
||||||
|
|
||||||
|
@ -42,7 +44,7 @@ defmodule AshFsm.Transformers.AddState do
|
||||||
{attribute.type, attribute.constraints}
|
{attribute.type, attribute.constraints}
|
||||||
end
|
end
|
||||||
|
|
||||||
case AshFsm.Info.fsm_default_initial_state(dsl_state) do
|
case AshStateMachine.Info.state_machine_default_initial_state(dsl_state) do
|
||||||
{:ok, default} ->
|
{:ok, default} ->
|
||||||
if attribute.default != default do
|
if attribute.default != default do
|
||||||
raise Spark.Error.DslError,
|
raise Spark.Error.DslError,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule AshFsm.Transformers.EnsureStateSelected do
|
defmodule AshStateMachine.Transformers.EnsureStateSelected do
|
||||||
use Spark.Dsl.Transformer
|
use Spark.Dsl.Transformer
|
||||||
|
|
||||||
def transform(dsl_state) do
|
def transform(dsl_state) do
|
||||||
|
@ -6,7 +6,7 @@ defmodule AshFsm.Transformers.EnsureStateSelected do
|
||||||
dsl_state,
|
dsl_state,
|
||||||
{Ash.Resource.Preparation.Build,
|
{Ash.Resource.Preparation.Build,
|
||||||
ensure_selected: [
|
ensure_selected: [
|
||||||
AshFsm.Info.fsm_state_attribute(dsl_state)
|
AshStateMachine.Info.state_machine_state_attribute(dsl_state)
|
||||||
]}
|
]}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
defmodule AshFsm.Transformers.FillInEventDefaults do
|
defmodule AshStateMachine.Transformers.FillInTransitionDefaults do
|
||||||
use Spark.Dsl.Transformer
|
use Spark.Dsl.Transformer
|
||||||
alias Spark.Dsl.Transformer
|
alias Spark.Dsl.Transformer
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
def transform(dsl_state) do
|
def transform(dsl_state) do
|
||||||
initial_states =
|
initial_states =
|
||||||
case AshFsm.Info.fsm_initial_states(dsl_state) do
|
case AshStateMachine.Info.state_machine_initial_states(dsl_state) do
|
||||||
{:ok, value} -> List.wrap(value)
|
{:ok, value} -> List.wrap(value)
|
||||||
_ -> []
|
_ -> []
|
||||||
end
|
end
|
||||||
|
@ -13,7 +13,7 @@ defmodule AshFsm.Transformers.FillInEventDefaults do
|
||||||
initial_states =
|
initial_states =
|
||||||
case initial_states do
|
case initial_states do
|
||||||
[] ->
|
[] ->
|
||||||
case AshFsm.Info.fsm_default_initial_state(dsl_state) do
|
case AshStateMachine.Info.state_machine_default_initial_state(dsl_state) do
|
||||||
{:ok, value} when not is_nil(value) ->
|
{:ok, value} when not is_nil(value) ->
|
||||||
[value]
|
[value]
|
||||||
|
|
||||||
|
@ -25,36 +25,36 @@ defmodule AshFsm.Transformers.FillInEventDefaults do
|
||||||
initial_states
|
initial_states
|
||||||
end
|
end
|
||||||
|
|
||||||
events =
|
transitions =
|
||||||
dsl_state
|
dsl_state
|
||||||
|> AshFsm.Info.fsm_events()
|
|> AshStateMachine.Info.state_machine_transitions()
|
||||||
|
|
||||||
all_states =
|
all_states =
|
||||||
events
|
transitions
|
||||||
|> Enum.flat_map(fn event ->
|
|> Enum.flat_map(fn transition ->
|
||||||
List.wrap(event.from) ++ List.wrap(event.to)
|
List.wrap(transition.from) ++ List.wrap(transition.to)
|
||||||
end)
|
end)
|
||||||
|> Enum.concat(List.wrap(initial_states))
|
|> Enum.concat(List.wrap(initial_states))
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
|
|
||||||
dsl_state =
|
dsl_state =
|
||||||
case AshFsm.Info.fsm_initial_states(dsl_state) do
|
case AshStateMachine.Info.state_machine_initial_states(dsl_state) do
|
||||||
{:ok, value} when not is_nil(value) and value != [] ->
|
{:ok, value} when not is_nil(value) and value != [] ->
|
||||||
dsl_state
|
dsl_state
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
Transformer.set_option(dsl_state, [:fsm], :initial_states, all_states)
|
Transformer.set_option(dsl_state, [:state_machine], :initial_states, all_states)
|
||||||
end
|
end
|
||||||
|
|
||||||
{:ok,
|
{:ok,
|
||||||
events
|
transitions
|
||||||
|> Enum.reduce(dsl_state, fn event, dsl_state ->
|
|> Enum.reduce(dsl_state, fn transition, dsl_state ->
|
||||||
Transformer.replace_entity(dsl_state, [:fsm], %{
|
Transformer.replace_entity(dsl_state, [:state_machine], %{
|
||||||
event
|
transition
|
||||||
| from: event.from || all_states,
|
| from: transition.from || all_states,
|
||||||
to: event.to || all_states
|
to: transition.to || all_states
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|> Transformer.persist(:all_fsm_states, all_states)}
|
|> Transformer.persist(:all_state_machine_states, all_states)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
defmodule AshFsm.Verifiers.VerifyDefaultInitialState do
|
defmodule AshStateMachine.Verifiers.VerifyDefaultInitialState do
|
||||||
use Spark.Dsl.Verifier
|
use Spark.Dsl.Verifier
|
||||||
|
|
||||||
def verify(dsl_state) do
|
def verify(dsl_state) do
|
||||||
module = Spark.Dsl.Verifier.get_persisted(dsl_state, :module)
|
module = Spark.Dsl.Verifier.get_persisted(dsl_state, :module)
|
||||||
|
|
||||||
attribute =
|
attribute =
|
||||||
Ash.Resource.Info.attribute(dsl_state, AshFsm.Info.fsm_state_attribute!(dsl_state))
|
Ash.Resource.Info.attribute(
|
||||||
|
dsl_state,
|
||||||
|
AshStateMachine.Info.state_machine_state_attribute!(dsl_state)
|
||||||
|
)
|
||||||
|
|
||||||
case AshFsm.Info.fsm_default_initial_state(dsl_state) do
|
case AshStateMachine.Info.state_machine_default_initial_state(dsl_state) do
|
||||||
{:ok, initial} when not is_nil(initial) ->
|
{:ok, initial} when not is_nil(initial) ->
|
||||||
initial_states = AshFsm.Info.fsm_initial_states!(dsl_state)
|
initial_states = AshStateMachine.Info.state_machine_initial_states!(dsl_state)
|
||||||
|
|
||||||
unless initial in initial_states do
|
unless initial in initial_states do
|
||||||
raise Spark.Error.DslError,
|
raise Spark.Error.DslError,
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
defmodule AshFsm.Verifiers.VerifyEventActions do
|
defmodule AshStateMachine.Verifiers.VerifyTransitionActions do
|
||||||
use Spark.Dsl.Verifier
|
use Spark.Dsl.Verifier
|
||||||
|
|
||||||
def verify(dsl_state) do
|
def verify(dsl_state) do
|
||||||
dsl_state
|
dsl_state
|
||||||
|> AshFsm.Info.fsm_events()
|
|> AshStateMachine.Info.state_machine_transitions()
|
||||||
|> Enum.each(fn event ->
|
|> Enum.each(fn transition ->
|
||||||
action = Ash.Resource.Info.action(dsl_state, event.action)
|
action = Ash.Resource.Info.action(dsl_state, transition.action)
|
||||||
|
|
||||||
unless action && action.type == :update do
|
unless action && action.type == :update do
|
||||||
raise Spark.Error.DslError,
|
raise Spark.Error.DslError,
|
||||||
module: Spark.Dsl.Verifier.get_persisted(dsl_state, :module),
|
module: Spark.Dsl.Verifier.get_persisted(dsl_state, :module),
|
||||||
path: [:fsm, :events, :event, event.action],
|
path: [:state_machine, :transitions, :transition, transition.action],
|
||||||
message: """
|
message: """
|
||||||
Event configured with action `:#{event.action}` but no such update action is defined.
|
Transition configured with action `:#{transition.action}` but no such update action is defined.
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
22
mix.exs
22
mix.exs
|
@ -1,4 +1,4 @@
|
||||||
defmodule AshFsm.MixProject do
|
defmodule AshStateMachine.MixProject do
|
||||||
use Mix.Project
|
use Mix.Project
|
||||||
|
|
||||||
@version "0.1.0"
|
@version "0.1.0"
|
||||||
|
@ -9,7 +9,7 @@ defmodule AshFsm.MixProject do
|
||||||
|
|
||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
app: :ash_fsm,
|
app: :ash_state_machine,
|
||||||
version: @version,
|
version: @version,
|
||||||
elixir: "~> 1.14",
|
elixir: "~> 1.14",
|
||||||
start_permanent: Mix.env() == :prod,
|
start_permanent: Mix.env() == :prod,
|
||||||
|
@ -20,19 +20,19 @@ defmodule AshFsm.MixProject do
|
||||||
dialyzer: [plt_add_apps: [:ash]],
|
dialyzer: [plt_add_apps: [:ash]],
|
||||||
docs: docs(),
|
docs: docs(),
|
||||||
description: @description,
|
description: @description,
|
||||||
source_url: "https://github.com/ash-project/ash_fsm",
|
source_url: "https://github.com/ash-project/ash_state_machine",
|
||||||
homepage_url: "https://github.com/ash-project/ash_fsm"
|
homepage_url: "https://github.com/ash-project/ash_state_machine"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
defp package do
|
defp package do
|
||||||
[
|
[
|
||||||
name: :ash_fsm,
|
name: :ash_state_machine,
|
||||||
licenses: ["MIT"],
|
licenses: ["MIT"],
|
||||||
files: ~w(lib .formatter.exs mix.exs README* LICENSE*
|
files: ~w(lib .formatter.exs mix.exs README* LICENSE*
|
||||||
CHANGELOG* documentation),
|
CHANGELOG* documentation),
|
||||||
links: %{
|
links: %{
|
||||||
GitHub: "https://github.com/ash-project/ash_fsm"
|
GitHub: "https://github.com/ash-project/ash_state_machine"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
@ -87,17 +87,17 @@ defmodule AshFsm.MixProject do
|
||||||
|
|
||||||
defp docs do
|
defp docs do
|
||||||
[
|
[
|
||||||
main: "AshFsm",
|
main: "AshStateMachine",
|
||||||
source_ref: "v#{@version}",
|
source_ref: "v#{@version}",
|
||||||
logo: "logos/small-logo.png",
|
logo: "logos/small-logo.png",
|
||||||
extra_section: "GUIDES",
|
extra_section: "GUIDES",
|
||||||
spark: [
|
spark: [
|
||||||
extensions: [
|
extensions: [
|
||||||
%{
|
%{
|
||||||
module: AshFsm,
|
module: AshStateMachine,
|
||||||
name: "AshFsm",
|
name: "AshStateMachine",
|
||||||
target: "Ash.Resource",
|
target: "Ash.Resource",
|
||||||
type: "Fsm Resource"
|
type: "StateMachine Resource"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
module: AshGraphql.Api,
|
module: AshGraphql.Api,
|
||||||
|
@ -147,7 +147,7 @@ defmodule AshFsm.MixProject do
|
||||||
sobelow: "sobelow --skip",
|
sobelow: "sobelow --skip",
|
||||||
credo: "credo --strict",
|
credo: "credo --strict",
|
||||||
docs: ["docs", "ash.replace_doc_links"],
|
docs: ["docs", "ash.replace_doc_links"],
|
||||||
"spark.formatter": "spark.formatter --extensions AshFsm"
|
"spark.formatter": "spark.formatter --extensions AshStateMachine"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
defmodule AshFsmTest do
|
defmodule AshStateMachineTest do
|
||||||
use ExUnit.Case
|
use ExUnit.Case
|
||||||
doctest AshFsm
|
doctest AshStateMachine
|
||||||
|
|
||||||
defmodule ThreeStates do
|
defmodule ThreeStates do
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
data_layer: Ash.DataLayer.Ets,
|
data_layer: Ash.DataLayer.Ets,
|
||||||
extensions: [AshFsm]
|
extensions: [AshStateMachine]
|
||||||
|
|
||||||
fsm do
|
state_machine do
|
||||||
default_initial_state :pending
|
default_initial_state :pending
|
||||||
|
|
||||||
events do
|
transitions do
|
||||||
event :begin, from: :pending, to: :executing
|
transition(:begin, from: :pending, to: :executing)
|
||||||
event :complete, from: :executing, to: :complete
|
transition(:complete, from: :executing, to: :complete)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ defmodule AshFsmTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
code_interface do
|
code_interface do
|
||||||
define_for AshFsmTest.Api
|
define_for AshStateMachineTest.Api
|
||||||
define :create
|
define :create
|
||||||
define :begin
|
define :begin
|
||||||
define :complete
|
define :complete
|
||||||
|
@ -54,7 +54,7 @@ defmodule AshFsmTest do
|
||||||
|
|
||||||
describe "transformers" do
|
describe "transformers" do
|
||||||
test "infers all states" do
|
test "infers all states" do
|
||||||
assert Enum.sort(AshFsm.Info.fsm_all_states(ThreeStates)) ==
|
assert Enum.sort(AshStateMachine.Info.state_machine_all_states(ThreeStates)) ==
|
||||||
Enum.sort([:executing, :pending, :complete])
|
Enum.sort([:executing, :pending, :complete])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -65,15 +65,15 @@ defmodule AshFsmTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it transitions to the appropriate state" do
|
test "it transitions to the appropriate state" do
|
||||||
fsm = ThreeStates.create!()
|
state_machine = ThreeStates.create!()
|
||||||
|
|
||||||
assert ThreeStates.begin!(fsm).state == :executing
|
assert ThreeStates.begin!(state_machine).state == :executing
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it transitions again to the appropriate state" do
|
test "it transitions again to the appropriate state" do
|
||||||
fsm = ThreeStates.create!() |> ThreeStates.begin!()
|
state_machine = ThreeStates.create!() |> ThreeStates.begin!()
|
||||||
|
|
||||||
assert ThreeStates.complete!(fsm).state == :complete
|
assert ThreeStates.complete!(state_machine).state == :complete
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
Loading…
Reference in a new issue