{"id":15683978,"url":"https://github.com/perry-mitchell/mini-state-machine","last_synced_at":"2025-05-07T15:06:06.723Z","repository":{"id":57297670,"uuid":"156764244","full_name":"perry-mitchell/mini-state-machine","owner":"perry-mitchell","description":"A tiny finite state machine","archived":false,"fork":false,"pushed_at":"2023-08-09T11:01:37.000Z","size":962,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-07T15:05:44.343Z","etag":null,"topics":["finite-state-machine","fsm","state-machine","state-management","stateful","transitions"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/perry-mitchell.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-08T20:23:21.000Z","updated_at":"2024-07-12T20:00:35.000Z","dependencies_parsed_at":"2025-03-12T05:00:40.615Z","dependency_job_id":null,"html_url":"https://github.com/perry-mitchell/mini-state-machine","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perry-mitchell%2Fmini-state-machine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perry-mitchell%2Fmini-state-machine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perry-mitchell%2Fmini-state-machine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perry-mitchell%2Fmini-state-machine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/perry-mitchell","download_url":"https://codeload.github.com/perry-mitchell/mini-state-machine/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252902614,"owners_count":21822261,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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","state-machine","state-management","stateful","transitions"],"created_at":"2024-10-03T17:09:24.243Z","updated_at":"2025-05-07T15:06:06.675Z","avatar_url":"https://github.com/perry-mitchell.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mini-State-Machine\n\u003e A tiny Finite State Machine\n\n![Tests status](https://github.com/perry-mitchell/mini-state-machine/actions/workflows/test.yml/badge.svg) [![npm version](https://badge.fury.io/js/mini-state-machine.svg)](https://www.npmjs.com/package/mini-state-machine)\n\n## About\n\nState machines are extremely useful pieces of functionality that ensure some state of a custom system. Using state machines (or _Finite State Machines_) allows you to define states for a system and all possible transitions between those states, ensuring the system follows only a certain amount of paths between states. An attempt to deviate from the allowed paths will always result in an error (as well as the initial state being preserved).\n\nState machines such as this one can help you map out your states and transition pathways:\n\n![State machine visualisation](mini-state-machine.jpg)\n\nSuch a diagram can easily be modelled as a state machine using this library:\n\n```typescript\nimport { createStateMachine } from \"mini-state-machine\";\n\ncreateStateMachine({\n    initial: \"idle\",\n    transitions: [\n        { name: \"prepare\", from: \"idle\", to: \"hidden\" },\n        { name: \"show\", from: \"hidden\", to: \"shown\" },\n        { name: \"hide\", from: \"shown\", to: \"hidden\" }\n    ]\n});\n```\n\n### Why\n\nExisting solutions were a bit too bloated for my use case - I needed a small and functional state machine with asynchronous transitions. Mini-State-Machine is my take on the bare minimum. If you have suggestions on how I could make it smaller, please create an issue!\n\nCurrently the NodeJS version is **less than 5kb minified!**\n\n### Usage\n\nUsage is simple: Create a state machine instance and you're ready to go!\n\n```typescript\nimport { createStateMachine } from \"mini-state-machine\";\n\nconst sm = createStateMachine({\n    initial: \"hidden\",\n    transitions: [\n        { name: \"show\", from: \"hidden\", to: \"shown\" },\n        { name: \"load\", from \"shown\", to: \"loaded\" },\n        { name: \"hide\", from: \"*\", to: \"hidden\" }\n    ]\n});\n\nawait sm.transition(\"show\");\nsm.state; // \"shown\"\n\nawait sm.transition(\"show\"); // Exception: No path for this transition\n```\n\nEvent handlers can be attached so each transition can be watched using callbacks. Transitions can be **cancelled** in the `\"before\"` and `\"leave\"` callback types by either returning `false` or throwing an error (or rejecting a `Promise`).\n\n```typescript\nsm.on(\"before\", \"show\", () =\u003e {\n    if (someTest()) {\n        // cancel show\n        return false;\n    }\n});\n\nsm.on(\"leave\", \"hidden\", () =\u003e {\n    throw new Error(\"Some error\");\n    // or\n    return Promise.reject(new Error(\"Some error\"));\n});\n```\n\n_By throwing an error, the original `transition()` call will be rejected with that error._\n\nThe methods `off(type, stateOrTransitionName, callback)` and `once(type, stateOrTransitionName, callback)` are also available and function like normal event emitter properties. `on()` and `once` also return an Object that contains a `remove` property method, which removes the listener when called.\n\nYou can also listen to all events by using an asterisk:\n\n```typescript\nsm.on(\"after\", \"*\", event =\u003e {\n    // 'event' :\n    // {\n    //     from: \"state1\",\n    //     to: \"state2\",\n    //     transition: \"doSomething\"\n    // }\n});\n```\n\nCheck out the [API documentation](API.md) for more information.\n\n#### Checking State\n\nYou can check the current state by using `sm.state`. For convenience you can also use `sm.is(\"someState\")`.\n\nYou can also check whether a transition is possible by calling `sm.can(\"show\")`, or if it is impossible by calling `sm.cannot(\"hide\")`.\n\n#### History\n\nYou can get the entire history of the state machine by calling `sm.getHistory()`. This method is expensive as it clones (using JSON) the entire history collection before returning it.\n\nEach history item will conform to the following structure:\n\n| Property      | Type          | Description                                           |\n|---------------|---------------|-------------------------------------------------------|\n| tsStart       | Number        | The timestamp at which the transition started.        |\n| tsEnd         | Number        | The timestamp at which the transition ended.          |\n| state         | String        | The state that was set at the end of the transition.  |\n| previous      | String        | The previous state before the transition.             |\n| transition    | String        | The transition name.                                  |\n\n#### Event Lifecycle\n\nThe events for a transition occur in the following order:\n\n * **before** _transition_ (cancelable)\n * **leave** _state_ (cancelable)\n * **enter** _state_\n * **after** _transition_\n\nReturning a `Promise` in any of these delays the transition. The callbacks for before, leave, enter and after events are called serially, which means that a failure or delay in one will affect the following callbacks (a failure meaning that they will not be called at all).\n\nThe exact time at which the state is changed is between **leave-state** and **enter-state**, and once the enter-state procedure has been started it is already to late to cancel the transition.\n\n## Installation\n\nRun the following to install:\n\n```\nnpm install mini-state-machine --save\n```\n\n_This library supports **NodeJS 16** as a minimum compatible version_.\n\nThis package is in **ESM** module. It needs to be bundled with a tool like _Webpack_ before being used in the browser.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fperry-mitchell%2Fmini-state-machine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fperry-mitchell%2Fmini-state-machine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fperry-mitchell%2Fmini-state-machine/lists"}