{"id":37173288,"url":"https://github.com/zain-bahsarat/fsml","last_synced_at":"2026-01-14T20:15:16.687Z","repository":{"id":57575804,"uuid":"356060579","full_name":"zain-bahsarat/fsml","owner":"zain-bahsarat","description":"XML based finite statemachine in GO","archived":false,"fork":false,"pushed_at":"2021-04-13T20:31:32.000Z","size":34,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-06-20T06:30:48.073Z","etag":null,"topics":["finite-state-machine","fsm","go","golang","statemachine","xml","xml-schema"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zain-bahsarat.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-08T22:10:05.000Z","updated_at":"2021-04-13T20:31:34.000Z","dependencies_parsed_at":"2022-09-26T19:02:30.038Z","dependency_job_id":null,"html_url":"https://github.com/zain-bahsarat/fsml","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/zain-bahsarat/fsml","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zain-bahsarat%2Ffsml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zain-bahsarat%2Ffsml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zain-bahsarat%2Ffsml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zain-bahsarat%2Ffsml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zain-bahsarat","download_url":"https://codeload.github.com/zain-bahsarat/fsml/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zain-bahsarat%2Ffsml/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28434422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T18:57:19.464Z","status":"ssl_error","status_checked_at":"2026-01-14T18:52:48.501Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["finite-state-machine","fsm","go","golang","statemachine","xml","xml-schema"],"created_at":"2026-01-14T20:15:16.026Z","updated_at":"2026-01-14T20:15:16.672Z","avatar_url":"https://github.com/zain-bahsarat.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fsml ![Bulid Status](https://github.com/zain-bahsarat/fsml/actions/workflows/test.yml/badge.svg) [![Coverage Status](https://img.shields.io/coveralls/zain-bahsarat/fsml.svg)](https://coveralls.io/r/zain-bahsarat/fsml) [![Go Report Card](https://goreportcard.com/badge/zain-bahsarat/fsml)](https://goreportcard.com/report/zain-bahsarat/fsml)\n\n**FSML** is a XML based wrapper on top of https://github.com/looplab/fsm.\u003cbr\u003e\nIt provides the capabilities to define state machine of an entity in XML format and also supports features to handle error states and tasks execution on events and successful transition.\n\n## Installation\n\n```shell\n$ go get github.com/zain-bahsarat/fsml\n```\n\n## Usage\n\n```go\n    import (\n        \"fmt\"\n        \"strings\"\n\n        \"github.com/zain-bahsarat/fsml\"\n    )\n\n    // Every object which is passed to the statemachine has to implement\n    // `Stateful` interface otherwise it will throw error\n    // -------------------------------------\n    // type Stateful interface{\n    //     GetState() string\n    //     SetState(state string) error\n    // }\n    // -------------------------------------\n\n    // create an entity which implements stateful interface\n    type order struct {\n        state string\n        fsml.Stateful\n    }\n\n    func (o *order) SetState(state string) error {\n        o.state = state\n        return nil\n    }\n\n    func (o *order) GetState() string {\n        return o.state\n    }\n\n    func main() {\n        statemachineDef := getSimpleStatemachineDef()\n\n        reader := strings.NewReader(statemachineDef)\n        sm, err := fsml.New(reader)\n        if err != nil {\n            fmt.Printf(\"error= %+v\\n\", sm)\n        }\n\n        o := \u0026order{}\n        o.SetState(\"new\")\n\n        if err := sm.Trigger(\"DummyEvent\", o); err != nil {\n            fmt.Printf(\"error= %+v\\n\", err)\n        }\n\n        if !sm.Can(\"UndefinedEvent\", o) {\n            fmt.Printf(\"cannot trigger UndefinedEvent on %+v\\n\", o)\n        }\n\n    }\n\n    // state machine definition\n    func getSimpleStatemachineDef() string {\n        return `\u003cSchema\u003e\n                \u003cStates\u003e\n                    \u003cnew\u003e\n                        \u003cEvents\u003e\n                            \u003cDummyEvent targetState=\"pending\" errorState=\"error\"\u003e\u003c/DummyEvent\u003e\n                        \u003c/Events\u003e\n                    \u003c/new\u003e\n                    \u003cpending\u003e\u003c/pending\u003e\n                    \u003cerror\u003e\u003c/error\u003e\n                \u003c/States\u003e\n            \u003c/Schema\u003e`\n    }\n```\n\nHere is an example of state machine definition in xml format.\n\n```xml\n\u003cSchema\u003e\n    \u003cStates\u003e\n        \u003cnew\u003e\n            \u003cEvents\u003e\n                \u003cDummyEvent targetState=\"pending\" errorState=\"error\"\u003e\u003c/DummyEvent\u003e\n            \u003c/Events\u003e\n        \u003c/new\u003e\n        \u003cpending\u003e\u003c/pending\u003e\n        \u003cerror\u003e\u003c/error\u003e\n    \u003c/States\u003e\n\u003c/Schema\u003e\n```\n\nAbove statemachine has three states `new`, `pending` and `error` and event named `DummyEvent`\n\n## Schema Definition\n\n### Nodes\n\n- Schema `Root Node`\n- States `Container Node`\n  - All the state definitions will be inside this node\n- Events `Container Node`\n- Task\n- OnStateSet `Default Event`\n- OnAfterEvent `Default Event`\n- OnBeforeEvent `Default Event`\n\n### Default Events\n\nDefault events can used inside each state to define default behaviors when state is updated. you can also define global default events.\n\n```xml\n \u003cSchema\u003e\n    \u003cOnStateSet\u003e\u003c/OnStateSet\u003e\n    \u003cStates\u003e\n        \u003cnew\u003e\n            \u003cOnStateSet\u003e\u003c/OnStateSet\u003e\n            \u003cEvents\u003e\n                \u003cDummyEvent targetState=\"pending\" errorState=\"error\"\u003e\u003c/DummyEvent\u003e\n            \u003c/Events\u003e\n        \u003c/new\u003e\n        \u003cpending\u003e\u003c/pending\u003e\n        \u003cerror\u003e\u003c/error\u003e\n    \u003c/States\u003e\n\u003c/Schema\u003e\n```\n\n### Custom Events\n\nCustom events can be deined inside `Events` Node. There is an option to define `targetState`(required) and `errorState` which will take effect based on transition result\n\n### Tasks\n\n`Task` Node is defined inside Custom Event or Default Event when we want to execute some task on them. If all tasks defined inside event are executed successfully then state will be changed to `targetState` otherwise it will be `errorState`\n\nEvery task needs to implement `fsml.Task` interface to be accessible by statemachine. check `examples/tasks.go`\n\n```go\n    type task struct {}\n    func (t *task) Name() string {\n        return \"increment\"\n    }\n\n    func (t *task) Execute(i interface{}) error {\n        entity := i.(*item)\n        entity.count++\n\n        return nil\n    }\n\n    ......\n\n    statemachine.AddTask(\u0026task{})\n```\n\n```xml\n    \u003cnew\u003e\n        \u003cOnStateSet\u003e\u003c/OnStateSet\u003e\n        \u003cEvents\u003e\n            \u003cDummyEvent targetState=\"pending\" errorState=\"error\"\u003e\n                \u003cTask\u003eincrement\u003c/Task\u003e\n                \u003cTask\u003eincrement\u003c/Task\u003e\n            \u003c/DummyEvent\u003e\n        \u003c/Events\u003e\n    \u003c/new\u003e\n```\n\n---\n\n# License\n\nFSML is licensed under Apache License 2.0\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzain-bahsarat%2Ffsml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzain-bahsarat%2Ffsml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzain-bahsarat%2Ffsml/lists"}