Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@xstate/fsm

Package Overview
Dependencies
Maintainers
3
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@xstate/fsm - npm Package Compare versions

Comparing version 1.6.2 to 1.6.3

dist/index.d.ts.map

6

CHANGELOG.md
# @xstate/fsm
## 1.6.3
### Patch Changes
- [#2474](https://github.com/davidkpiano/xstate/pull/2474) Thanks [@annaghi](https://github.com/annaghi)! - Use CommonJS files as `package.json#main` (instead of UMD files) as this plays better with native ESM loader in node (and by extension fixes compatibility issues with projects like [SvelteKit](https://kit.svelte.dev/)).
## 1.6.2

@@ -4,0 +10,0 @@

0

lib/index.d.ts

@@ -0,0 +0,0 @@ import { StateMachine, EventObject, Typestate, InterpreterStatus } from './types';

32

lib/index.js

@@ -1,3 +0,7 @@

import { InterpreterStatus } from './types';
export { InterpreterStatus };
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var types = require('./types.js');
const INIT_EVENT = { type: 'xstate.init' };

@@ -8,3 +12,3 @@ const ASSIGN_ACTION = 'xstate.assign';

}
export function assign(assignment) {
function assign(assignment) {
return {

@@ -74,3 +78,3 @@ type: ASSIGN_ACTION,

}
export function createMachine(fsmConfig, options = {}) {
function createMachine(fsmConfig, options = {}) {
if (!IS_PRODUCTION) {

@@ -144,5 +148,5 @@ Object.keys(fsmConfig.states).forEach((state) => {

const executeStateActions = (state, event) => state.actions.forEach(({ exec }) => exec && exec(state.context, event));
export function interpret(machine) {
function interpret(machine) {
let state = machine.initialState;
let status = InterpreterStatus.NotStarted;
let status = types.InterpreterStatus.NotStarted;
const listeners = new Set();

@@ -152,3 +156,3 @@ const service = {

send: (event) => {
if (status !== InterpreterStatus.Running) {
if (status !== types.InterpreterStatus.Running) {
return;

@@ -184,3 +188,3 @@ }

}
status = InterpreterStatus.Running;
status = types.InterpreterStatus.Running;
executeStateActions(state, INIT_EVENT);

@@ -190,3 +194,3 @@ return service;

stop: () => {
status = InterpreterStatus.Stopped;
status = types.InterpreterStatus.Stopped;
listeners.clear();

@@ -204,1 +208,11 @@ return service;

}
Object.defineProperty(exports, 'InterpreterStatus', {
enumerable: true,
get: function () {
return types.InterpreterStatus;
}
});
exports.assign = assign;
exports.createMachine = createMachine;
exports.interpret = interpret;

@@ -0,0 +0,0 @@ export declare enum InterpreterStatus {

@@ -1,2 +0,5 @@

export var InterpreterStatus;
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
(function (InterpreterStatus) {

@@ -6,2 +9,2 @@ InterpreterStatus[InterpreterStatus["NotStarted"] = 0] = "NotStarted";

InterpreterStatus[InterpreterStatus["Stopped"] = 2] = "Stopped";
})(InterpreterStatus || (InterpreterStatus = {}));
})(exports.InterpreterStatus || (exports.InterpreterStatus = {}));
{
"name": "@xstate/fsm",
"version": "1.6.2",
"version": "1.6.3",
"description": "XState for finite state machines",

@@ -20,3 +20,3 @@ "keywords": [

"license": "MIT",
"main": "dist/xstate.fsm.js",
"main": "lib/index.js",
"types": "lib/index.d.ts",

@@ -26,4 +26,3 @@ "module": "es/index.js",

"files": [
"dist/**/*.js",
"dist/**/*.d.ts",
"dist",
"lib/**/*.js",

@@ -39,3 +38,3 @@ "lib/**/*.d.ts",

"scripts": {
"clean": "rm -rf dist lib tsconfig.tsbuildinfo",
"clean": "rm -rf lib es dist tsconfig.tsbuildinfo",
"build": "rollup -c",

@@ -57,4 +56,4 @@ "test": "jest",

"ts-jest": "^26.5.6",
"typescript": "^4.3.5"
"typescript": "^4.5.2"
}
}

@@ -14,7 +14,10 @@ # @xstate/fsm

This package contains a minimal, 1kb implementation of [XState](https://github.com/davidkpiano/xstate) for **finite state machines**.
This package contains a minimal, 1kb implementation of [XState](https://github.com/statelyai/xstate) for **finite state machines**.
- [Read the full documentation in the XState docs](https://xstate.js.org/docs/packages/xstate-fsm/).
- [Read our contribution guidelines](https://github.com/statelyai/xstate/blob/main/CONTRIBUTING.md).
## Features
| | **@xstate/fsm** | [XState](https://github.com/davidkpiano/xstate) |
| | **@xstate/fsm** | [XState](https://github.com/statelyai/xstate) |
| --------------------------- | :-------------: | :---------------------------------------------: |

@@ -50,7 +53,7 @@ | Finite states | ✅ | ✅ |

If you want to use statechart features such as nested states, parallel states, history states, activities, invoked services, delayed transitions, transient transitions, etc. please use [`XState`](https://github.com/davidkpiano/xstate).
If you want to use statechart features such as nested states, parallel states, history states, activities, invoked services, delayed transitions, transient transitions, etc. please use [`XState`](https://github.com/statelyai/xstate).
## Super quick start
## Quick start
**Installation**
### Installation

@@ -61,3 +64,3 @@ ```bash

**Usage (machine):**
### Usage (machine)

@@ -85,3 +88,3 @@ ```js

**Usage (service):**
### Usage (service)

@@ -103,327 +106,1 @@ ```js

```
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Super quick start](#super-quick-start)
- [API](#api)
- [`createMachine(config)`](#createmachineconfig)
- [Machine config](#machine-config)
- [State config](#state-config)
- [Transition config](#transition-config)
- [Machine options](#machine-options)
- [Action config](#action-config)
- [`machine.initialState`](#machineinitialstate)
- [`machine.transition(state, event)`](#machinetransitionstate-event)
- [State](#state)
- [`interpret(machine)`](#interpretmachine)
- [`service.subscribe(stateListener)`](#servicesubscribestatelistener)
- [`service.send(event)`](#servicesendevent)
- [`service.start()`](#servicestart)
- [`service.stop()`](#servicestop)
- [TypeScript](#typescript)
- [Example](#example)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## API
### `createMachine(config, options)`
Creates a new finite state machine from the config.
| Argument | Type | Description |
| --------- | ------------------ | ------------------------------------------- |
| `config` | object (see below) | The config object for creating the machine. |
| `options` | object (see below) | The optional options object. |
**Returns:**
A `Machine`, which provides:
- `machine.initialState`: the machine's resolved initial state
- `machine.transition(state, event)`: a pure transition function that returns the next state given the current `state` and `event`
The machine config has this schema:
### Machine config
- `id` (string) - an identifier for the type of machine this is. Useful for debugging.
- `initial` (string) - the key of the initial state.
- `states` (object) - an object mapping state names (keys) to [states](#state-config)
### State config
- `on` (object) - an object mapping event types (keys) to [transitions](#transition-config)
### Transition config
String syntax:
- (string) - the state name to transition to.
- Same as `{ target: stateName }`
Object syntax:
- `target?` (string) - the state name to transition to.
- `actions?` (Action | Action[]) - the [action(s)](#action-config) to execute when this transition is taken.
- `cond?` (Guard) - the condition (predicate function) to test. If it returns `true`, the transition will be taken.
### Machine options
- `actions?` (object) - a lookup object for your string actions.
### Action config
Function syntax:
- (function) - the action function to execute. Resolves to `{ type: actionFn.name, exec: actionFn }` and the function takes the following arguments:
1. `context` (any) - the machine's current `context`.
2. `event` (object) - the event that caused the action to be executed.
Object syntax:
- `type` (string) - the action type.
- `exec?` (function) - the action function to execute.
String syntax:
- (string) - the action type.
- By default it resolves to `{ type: actionType, exec: undefined }`. It can resolve to resolved function or resolved object action **if** the action can be looked up in the `options.actions` object.
<details>
<summary>Why use a string or object for defining actions?</summary>
Using the string or object syntax is useful for handling actions in a custom way, rather than baking in the implementation details to your machine:
```js
const nextState = machine.transition();
nextState.actions.forEach((action) => {
if (action.type === 'focus') {
}
});
```
</details>
### `machine.initialState`
The resolved initial state of the `machine`.
### `machine.transition(state, event)`
A pure transition function that returns the next state given the current `state` and `event`.
The state can be a `string` state name, or a `State` object (the return type of `machine.transition(...)`).
| Argument | Type | Description |
| -------- | ----------------------------------- | ---------------------------------------------------------------- |
| `state` | `string` or `State` object | The current state to transition from |
| `event` | `string` or `{ type: string, ... }` | The event that transitions the current `state` to the next state |
**Returns:**
A `State` object, which represents the next state.
**Example:**
```js
const yellowState = machine.transition('green', 'TIMER');
const redState = machine.transition(yellowState, 'TIMER');
const greenState = machine.transition(yellowState, { type: 'TIMER' });
// => { value: 'green', ... }
```
### State
An object that represents the state of a machine with the following schema:
- `value` (string) - the finite state value
- `context` (object) - the extended state (context)
- `actions` (array) - an array of action objects representing the side-effects (actions) to be executed
- `changed` (boolean) - whether this state is changed from the previous state (`true` if the `state.value` and `state.context` are the same, and there are no side-effects)
- `matches(value)` (boolean) - whether this state's value matches (i.e., is equal to) the `value`. This is useful for typestate checking.
### `interpret(machine)`
Creates an instance of an interpreted machine, also known as a **service**. This is a stateful representation of the running machine, which you can subscribe to, send events to, start, and stop.
Actions will also be executed by the interpreter.
| Argument | Type | Description |
| --------- | ------------ | ------------------------------ |
| `machine` | StateMachine | The machine to be interpreted. |
**Example:**
```js
import { createMachine, interpret } from '@xstate/fsm';
const machine = createMachine({});
const service = interpret(machine);
const subscription = service.subscribe((state) => {
console.log(state);
});
service.start();
service.send('SOME_EVENT');
service.send({ type: 'ANOTHER_EVENT' });
subscription.unsubscribe();
service.stop();
```
### `service.subscribe(stateListener)`
A service (created from `interpret(machine)`) can be subscribed to via the `.subscribe(...)` method. The subscription will be notified of all state changes (including the initial state) and can be unsubscribed.
| Argument | Type | Description |
| --------------- | ----------------- | ----------------------------------------------------------------------------------------------- |
| `stateListener` | `(state) => void` | The listener that is called with the interpreted machine's current `state` whenever it changes. |
**Returns:**
A subscription object with an `unsubscribe` method.
### `service.send(event)`
Sends an `event` to the interpreted machine. The event can be a string (e.g., `"EVENT"`) or an object with a `type` property (e.g., `{ type: "EVENT" }`).
| Argument | Type | Description |
| -------- | ----------------------------------- | ------------------------------------------------ |
| `event` | `string` or `{ type: string, ... }` | The event to be sent to the interpreted machine. |
### `service.start()`
Starts the interpreted machine.
Events sent to the interpreted machine will not trigger any transitions until the service is started. All listeners (via `service.subscribe(listener)`) will receive the `machine.initialState`.
### `service.stop()`
Stops the interpreted machine.
Events sent to a stopped service will no longer trigger any transitions. All listeners (via `service.subscribe(listener)`) will be unsubscribed.
## TypeScript
A machine can be strictly typed by passing in 3 generic types:
- `TContext` - the machine's `context`
- `TEvent` - all events that the machine accepts
- `TState` - all states that the machine can be in
The `TContext` type should be an `object` that represents all possible combined types of `state.context`.
The `TEvent` type should be the union of all event objects that the machine can accept, where each event object has a `{ type: string }` property, as well as any other properties that may be present.
The `TState` type should be the union of all typestates (value and contexts) that the machine can be in, where each typestate has:
- `value` (string) - the value (name) of the state
- `context` (object) - an object that extends `TContext` and narrows the shape of the context to what it should be in this state.
**Example:**
```ts
interface User {
name: string;
}
interface UserContext {
user?: User;
error?: string;
}
type UserEvent =
| { type: 'FETCH'; id: string }
| { type: 'RESOLVE'; user: User }
| { type: 'REJECT'; error: string };
type UserState =
| {
value: 'idle';
context: UserContext & {
user: undefined;
error: undefined;
};
}
| {
value: 'loading';
context: UserContext;
}
| {
value: 'success';
context: UserContext & { user: User; error: undefined };
}
| {
value: 'failure';
context: UserContext & { user: undefined; error: string };
};
const userMachine = createMachine<UserContext, UserEvent, UserState>({
/* ... */
});
const userService = interpret(userMachine);
userService.subscribe((state) => {
if (state.matches('success')) {
// from UserState, `user` will be defined
state.context.user.name;
}
});
```
## Example
```js
import { createMachine, assign, interpret } from '@xstate/fsm';
const lightMachine = createMachine({
id: 'light',
initial: 'green',
context: { redLights: 0 },
states: {
green: {
on: {
TIMER: 'yellow'
}
},
yellow: {
on: {
TIMER: {
target: 'red',
actions: () => console.log('Going to red!')
}
}
},
red: {
entry: assign({ redLights: (ctx) => ctx.redLights + 1 }),
on: {
TIMER: 'green'
}
}
}
});
const lightService = interpret(lightMachine);
lightService.subscribe((state) => {
console.log(state);
});
lightService.start();
lightService.send('TIMER');
lightService.send('TIMER');
// => logs {
// value: 'red',
// context: { redLights: 1 },
// actions: [],
// changed: true
// }
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc