{"id":41830409,"url":"https://github.com/cafjs/caf_fsm","last_synced_at":"2026-01-25T08:36:38.553Z","repository":{"id":57192671,"uuid":"433605356","full_name":"cafjs/caf_fsm","owner":"cafjs","description":"Caf.js plugin to implement finite state machines with xstate","archived":false,"fork":false,"pushed_at":"2023-04-18T22:34:07.000Z","size":22,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-26T14:54:38.273Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cafjs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-2.0.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-30T22:25:18.000Z","updated_at":"2021-12-16T09:24:23.000Z","dependencies_parsed_at":"2023-01-22T17:46:30.698Z","dependency_job_id":null,"html_url":"https://github.com/cafjs/caf_fsm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cafjs/caf_fsm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cafjs%2Fcaf_fsm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cafjs%2Fcaf_fsm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cafjs%2Fcaf_fsm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cafjs%2Fcaf_fsm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cafjs","download_url":"https://codeload.github.com/cafjs/caf_fsm/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cafjs%2Fcaf_fsm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28749603,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T08:31:04.260Z","status":"ssl_error","status_checked_at":"2026-01-25T08:30:28.859Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":[],"created_at":"2026-01-25T08:36:37.994Z","updated_at":"2026-01-25T08:36:38.546Z","avatar_url":"https://github.com/cafjs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Caf.js\n\nCo-design cloud assistants with your web app and IoT devices.\n\nSee https://www.cafjs.com\n\n## Create Finite State Machines (FSM) with xstate and Caf.js\n\n[![Build Status](https://github.com/cafjs/caf_fsm/actions/workflows/push.yml/badge.svg)](https://github.com/cafjs/caf_fsm/actions/workflows/push.yml)\n\nCaf.js plugin to integrate the great FSM library `@xstate/fsm` (see https://github.com/statelyai/xstate/tree/main/packages/xstate-fsm)\n\nWhen we combine state machines with our autonomous cloud assistants we make it easier to remotely control IoT devices, make them feel alive, or synchronize actions on hundreds of thousands of them across the world.\n\nAnd that's not all. The internal state of a cloud assistant is always externally consistent. If the server crashes and restarts, the recovered state is always what everybody expects.\n\nThis means that our state machines are also reliable, and we can count on them to, for example, safely orchestrate service API calls, or track the progress of a request in a sea of microservices.\n\nYou can learn more about external consistency in Caf.js [here](https://www.cafjslabs.com/orchestration)\n\n## API\n\nSee {@link module:caf_fsm/proxy_fsm} and the docs in https://xstate.js.org/docs/packages/xstate-fsm\n\nAn example that configures a traffic light state machine from https://github.com/cafjs/caf_hellofsm.git :\n\n```\n    async __ca_init__() {\n        ...\n        this.$.fsm.setCreateMachineMethod('__ca_createMachine__');\n        ...\n    },\n    async __ca_createMachine__() {\n        const updateImpl = (newLight) =\u003e {\n            this.state.light = newLight;\n            ...\n            this.$.pubsub.publish(this.state.myChannel, newLight);\n        };\n        const config = {\n            id: 'semaphore',\n            initial: LIGHTS.RED,\n            states: {\n                RED: {\n                    on: {\n                        TICK: {\n                            target: LIGHTS.GREEN,\n                            actions: () =\u003e updateImpl(LIGHTS.GREEN)\n                        }\n                    }\n                },\n                GREEN: {\n                    on: {\n                        TICK: {\n                            target: LIGHTS.YELLOW,\n                            actions: () =\u003e updateImpl(LIGHTS.YELLOW)\n                        }\n                    }\n                },\n                YELLOW: {\n                    on: {\n                        TICK: {\n                            target: LIGHTS.RED,\n                            actions: () =\u003e updateImpl(LIGHTS.RED)\n                        }\n                    }\n                }\n            }\n        };\n        return [null, {config}];\n    },\n    async __ca_pulse__() {\n        ...\n        await this.tick();\n        ...\n    },\n    async tick() {\n        await this.$.fsm.send(this, TICK);\n        return [null, this.state];\n    },\n```\n\nBy using `await` in `this.$.fsm.send` we force state transition actions to be part of the transaction processing the pulse request.\n\nBut this also means that the transition action `updateImpl()` cannot be an `async` function, to ensure it completes within the transaction (`xstate` does not internally `await` actions).\n\nThis is not a big concern because actions can always call transactional plugins, like `this.$.pubsub`, or modify CA state.\n\n## Configuration\n\n### ca.json\n\nSee {@link module:caf_fsm/plug_ca_fsm}\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcafjs%2Fcaf_fsm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcafjs%2Fcaf_fsm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcafjs%2Fcaf_fsm/lists"}