Package Exports
- @jean-michelet/workflow
- @jean-michelet/workflow/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@jean-michelet/workflow) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Workflow
If you've been programming for a while, you've likely encountered workflows. They represent the various states and transitions that an entity can go through in a system.
For example, let's say you're developing a blog and want to allow users to share posts. You'll need to establish some rules:
- When a user creates a post, does it start as a
draft
? - Can a post move directly from
draft
topublished
, or does it need to bemoderated
first? - You might allow deleting
draft
s, but shouldpublished
posts only bearchived
?
These kinds of questions can be tricky, and it's crucial to represent this logic clearly in your code.
Install
npm i @jean-michelet/workflow
Workflow class
The Workflow
class allows you to define transitions between different states. These transitions can be represented as simple state changes (Transition
) or as transitions with multiple origins (MultiOriginTransition
).
In this example, the post can move from draft
to published
:
import { Transition, Workflow } from "@jean-michelet/workflow";
const workflow = new Workflow();
workflow.addTransition("publish", new Transition("draft", "published"));
console.log(workflow.can("publish", "draft")); // true
console.log(workflow.can("publish", "published")); // false
Multi-Origin Transitions
A MultiOriginTransition
allows an entity to transition to a single target state from multiple states.
In this example, the post can move to the archived
state from either aborted
or completed
states:
import { MultiOriginTransition, Workflow } from "@jean-michelet/workflow";
const workflow = new Workflow();
workflow.addTransition(
"archive",
new MultiOriginTransition(["aborted", "completed"], "archived")
);
console.log(workflow.can("archive", "aborted")); // true
console.log(workflow.can("archive", "completed")); // true
ClassWorkflow class
The ClassWorkflow
allows you to check and apply transitions directly to an entity’s state property. It is particularly useful when working with classes and TypeScript.
Example
Suppose you have a Post
class with a status
property that tracks the state of the post:
import { ClassWorkflow, Transition } from "@jean-michelet/workflow";
class Post {
status = "draft";
}
const wf = new ClassWorkflow({
entity: Post,
stateProperty: "status",
});
wf.addTransition("publish", new Transition("draft", "published"));
const post = new Post();
if (wf.can("publish", post)) {
wf.apply("publish", post);
}
console.log(post.status); // Output: "published"
In this example, the ClassWorkflow
manages the state transitions of the Post
instance. The apply
method automatically updates the entity's status
property based on the defined transitions. If the transition isn't allowed, an error is thrown.
Handling unexpected states
Both Workflow
and ClassWorkflow
support a detectUnexpectedState
option. When enabled, this option throws an error if an entity is in an unexpected state that hasn't been accounted for in the transitions.
import { ClassWorkflow, Transition } from "@jean-michelet/workflow";
class Post {
status = "draft";
}
const wf = new ClassWorkflow({
entity: Post,
stateProperty: "status",
detectUnexpectedState: true,
});
wf.addTransition("publish", new Transition("draft", "published"));
const post = new Post();
post.status = "unknown";
wf.can("publish", post); // throw an error "The instance has an unexpected state 'unknown'"