Compare commits

...

15 Commits
v2.0.3 ... main

16 changed files with 496 additions and 50 deletions

4
.gitignore vendored
View File

@ -4,3 +4,7 @@ node_modules/
package-lock.json
dist/
# direnv
.envrc
.direnv/

View File

@ -1,6 +0,0 @@
{
"deno.enable": true,
"deno.lint": true,
"deno.unstable": false,
"tsserver.enable": false
}

58
Makefile Normal file
View File

@ -0,0 +1,58 @@
DENO := deno
COV := $(DENO) coverage cov_profile
FMT := $(DENO) fmt *.ts examples/*.ts
NPM_PUB := npm publish
D2 := wd2
DIAGRAMS := \
turnstile \
project
dev: fmt tests cov
ci: fmt-check tests-cov
tests: clean
$(DENO) test --coverage=cov_profile *.test.ts
tests-cov: tests
$(COV) --lcov > cov_profile/cov.lcov
cov:
$(COV)
fmt:
$(FMT)
fmt-check:
$(FMT) --check
build: clean | $(DIAGRAMS)
tsc && tsc -p tsconfig.cjs.json
clean:
@echo clean test coverage data
rm -rf cov_profile
@echo clean build target
rm -rf dist
@echo clean diagrams
rm -rf assets/*.svg
define d2rule
$(1)_args := $(D2) $$($(1)_theme_args) assets/$(1).d2 assets/$(1).svg
$(1): ; $$($(1)_args)
$(1)-w: ; $$($(1)_args) -w
endef
$(foreach d2name,$(DIAGRAMS),$(eval $(call d2rule,$(d2name))))
dry-pub:
$(NPM_PUB) --dry-run
pub:
$(NPM_PUB)
help:
cat Makefile

View File

@ -26,28 +26,23 @@ const sm = new StateMachineBuilder()
.build(locked);
```
You can find the full example in the [examples](./examples/) folder.
You can find more examples [here](./examples/README.md)
# Installation
## Deno
if you use the [Deno](https://deno.land), just add following to your
if you use the [Deno](https://deno.land), just add the following to your
`import_map.json`
```json
{
"imports": {
"it-fsm": "https://git.pleshevski.ru/pleshevskiy/it-fsm/src/commit/e3796c92639e3483a2a2a01a89912561561e796f/fsm.ts"
"it-fsm": "https://git.pleshevski.ru/pleshevskiy/it-fsm/raw/tag/v2.0.3/fsm.ts"
}
}
```
or you can use branch instead
`https://git.pleshevski.ru/pleshevskiy/paren/raw/branch/main/`
> **Note**: I recommend to use a specific commit instead of branch
## Node.js
If you use the Node.js or in a browser as ES module, you may need to install it

36
assets/project.d2 Normal file
View File

@ -0,0 +1,36 @@
# port: 43333
# layout: dagre
# theme: 101
# pad: 0
# sketch: true
direction: right
Project: {
pen: Pending {
shape: circle
width: 110
}
act: Active {
shape: circle
style.fill: "#9ae49a"
width: 110
}
com: Completed {
shape: circle
style.fill: "#eaea7e"
width: 110
}
arc: Archived {
shape: circle
style.fill: "#ff7e7e"
width: 110
}
pen -> act: Activate
pen -> arc: Archive
act -> com: Complete
arc -> pen: Restore
}

81
assets/project.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 313 KiB

26
assets/turnstile.d2 Normal file
View File

@ -0,0 +1,26 @@
# port: 43334
# layout: elk
# theme: 101
# pad: 0
# sketch: true
direction: right
Turnstile: {
l: Locked {
shape: circle
style.fill: "#fd7373"
width: 110
}
u: Unlocked {
shape: circle
style.fill: "#59c061"
width: 110
}
l -> l: push
u -> l: push
l -> u: coin
u -> u: coin
}

81
assets/turnstile.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 307 KiB

9
deno.lock Normal file
View File

@ -0,0 +1,9 @@
{
"version": "2",
"remote": {
"https://deno.land/std@0.165.0/fmt/colors.ts": "9e36a716611dcd2e4865adea9c4bec916b5c60caad4cdcdc630d4974e6bb8bd4",
"https://deno.land/std@0.165.0/testing/_diff.ts": "a23e7fc2b4d8daa3e158fa06856bedf5334ce2a2831e8bf9e509717f455adb2c",
"https://deno.land/std@0.165.0/testing/_format.ts": "cd11136e1797791045e639e9f0f4640d5b4166148796cad37e6ef75f7d7f3832",
"https://deno.land/std@0.165.0/testing/asserts.ts": "1e340c589853e82e0807629ba31a43c84ebdcdeca910c4a9705715dfdb0f5ce8"
}
}

27
examples/README.md Normal file
View File

@ -0,0 +1,27 @@
# Examples
## Turnstile
An example of a simple mechanism that can be modeled by a state machine is a
turnstile. A turnstile, used to control access to subways and amusement park
rides, is a gate with three rotating arms at waist height, one across the
entryway. Initially the arms are locked, blocking the entry, preventing patrons
from passing through. Depositing a coin or token in a slot on the turnstile
unlocks the arms, allowing a single customer to push through. After the customer
passes through, the arms are locked again until another coin is inserted.
![Turnstile diagram](https://git.pleshevski.ru/pleshevskiy/it-fsm/raw/branch/main/assets/turnstile.svg)
```sh
deno run ./examples/turnstile.ts
```
## Project
This is more complex example illustrate all features of this library
![Project diagram](https://git.pleshevski.ru/pleshevskiy/it-fsm/raw/branch/main/assets/project.svg)
```sh
deno run ./examples/project.ts
```

View File

@ -35,6 +35,7 @@ const smbProject = new StateMachineBuilder<
.withTransitions([
[ProjectStatus.Pending, [ProjectStatus.Active, ProjectStatus.Archived]],
[ProjectStatus.Active, [ProjectStatus.Completed]],
[ProjectStatus.Archived, [ProjectStatus.Pending]],
]);
async function main() {

141
flake.lock Normal file
View File

@ -0,0 +1,141 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1676283394,
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1676283394,
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1676518424,
"narHash": "sha256-OsJSBwl9Hayh/bmxDtUyxm2U6btaBHuLvviE9KpMmwQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a592a97fcedae7a06b8506623b25fd38a032ad13",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1676518424,
"narHash": "sha256-OsJSBwl9Hayh/bmxDtUyxm2U6btaBHuLvviE9KpMmwQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a592a97fcedae7a06b8506623b25fd38a032ad13",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1669261230,
"narHash": "sha256-AjddxRPd5y5jge77281P3O8+Cnafj842Xg59rwV4x+0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8e8b5f3b1e899bf5d250279578c0283705b8cdb4",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"wd2": "wd2"
}
},
"tools": {
"inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1676488781,
"narHash": "sha256-lP2UWGwangM1OSBOx0EFXOtnSBuyTJn3yza3Ujb9/C8=",
"ref": "refs/heads/main",
"rev": "5f07d4e256c1d8caefd52563737b1e3c023b5d35",
"revCount": 21,
"type": "git",
"url": "https://git.pleshevski.ru/mynix/tools"
},
"original": {
"type": "git",
"url": "https://git.pleshevski.ru/mynix/tools"
}
},
"wd2": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_2",
"tools": "tools"
},
"locked": {
"lastModified": 1676583860,
"narHash": "sha256-LuGEJMECOtqFJHw65ErtEDa7MnF5e+QmiGO583ZK9BE=",
"ref": "refs/heads/main",
"rev": "1e05739a5e39b982e3670997a3845ab9741f4ca1",
"revCount": 13,
"type": "git",
"url": "https://git.pleshevski.ru/pleshevskiy/wd2"
},
"original": {
"type": "git",
"url": "https://git.pleshevski.ru/pleshevskiy/wd2"
}
}
},
"root": "root",
"version": 7
}

24
flake.nix Normal file
View File

@ -0,0 +1,24 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
wd2.url = "git+https://git.pleshevski.ru/pleshevskiy/wd2";
};
outputs = { self, nixpkgs, flake-utils, wd2, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
in
{
devShells.default = pkgs.mkShell {
packages = with pkgs; [
d2 # to format .d2 files
wd2.packages.${system}.default
deno
nodejs-18_x
nodePackages.typescript
];
};
});
}

View File

@ -17,9 +17,9 @@
import {
assertEquals,
assertRejects,
assertThrows,
assertThrowsAsync,
} from "https://deno.land/std@0.105.0/testing/asserts.ts";
} from "https://deno.land/std@0.165.0/testing/asserts.ts";
import * as fsm from "./fsm.ts";
enum ProjectStatus {
@ -168,7 +168,7 @@ Deno.test("should throw error if transition to the state doesn't exist", () => {
const sm = new fsm.StateMachineBuilder()
.withStates(Object.values(ProjectStatus))
.build(ProjectStatus.Pending);
assertThrowsAsync(
assertRejects(
() => sm.tryChangeState(ProjectStatus.Active, null),
fsm.FsmError,
`cannot change state from "${ProjectStatus.Pending}" to "${ProjectStatus.Active}"`,
@ -195,7 +195,7 @@ Deno.test("should throw error if beforeExit action returns false", () => {
[ProjectStatus.Pending, [ProjectStatus.Active]],
])
.build(ProjectStatus.Pending);
assertThrowsAsync(
assertRejects(
() => sm.tryChangeState(ProjectStatus.Active, null),
fsm.FsmError,
`cannot change state from "${ProjectStatus.Pending}" to "${ProjectStatus.Active}"`,

View File

@ -1,25 +0,0 @@
DENO := deno
COV := $(DENO) coverage cov_profile
FMT := $(DENO) fmt *.ts examples/*.ts
dev: fmt tests cov
ci: fmt-check tests-cov
tests: clean
$(DENO) test --coverage=cov_profile *.test.ts
tests-cov: tests
$(COV) --lcov > cov_profile/cov.lcov
cov:
$(COV)
fmt:
$(FMT)
fmt-check:
$(FMT) --check
clean:
rm -rf cov_profile dist

View File

@ -4,10 +4,7 @@
"description": "Simple finite state machine for nodejs",
"readme": "README.md",
"scripts": {
"build": "tsc && tsc -p tsconfig.cjs.json",
"check": "tsc --noEmit && tsc -p tsconfig.cjs.json --noEmit",
"clean": "rm -rf ./dist",
"prepublishOnly": "npm run clean && npm run build"
"prepublishOnly": "make build"
},
"repository": {
"type": "git",
@ -28,9 +25,6 @@
"url": "https://github.com/pleshevskiy/it-fsm/issues"
},
"homepage": "https://git.pleshevski.ru/pleshevskiy/it-fsm#readme",
"devDependencies": {
"typescript": "^4.9.3"
},
"main": "./dist/cjs/fsm.js",
"module": "./dist/esm/fsm.js",
"types": "./dist/esm/fsm.d.ts",