Introduction

Installation

StateFlow is designed to integrate seamlessly into modern TypeScript projects. This guide will walk you through installation, configuration, and your first setup.

Package Installation

StateFlow is available through npm and other package managers:

StateFlow requires TypeScript 4.5+ and Node.js 16+ for optimal compatibility.

Using npm

npm install @video/state-flow

Using yarn

yarn add @video/state-flow

Using pnpm

pnpm add @video/state-flow

TypeScript Configuration

StateFlow leverages advanced TypeScript features for type safety. Ensure your tsconfig.json includes these settings:

{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["ES2020", "DOM"],
    "strict": true,
    "exactOptionalPropertyTypes": true,
    "noUncheckedIndexedAccess": true,
    "moduleResolution": "node"
  }
}

Required Compiler Options

  • strict: true: Enables all strict type checking
  • exactOptionalPropertyTypes: true: Prevents undefined assignment to optional properties
  • noUncheckedIndexedAccess: true: Adds undefined to unchecked index signatures

Framework Integration

StateFlow works with any TypeScript application, but here are specific integration patterns for popular frameworks:

React Integration

StateFlow integrates naturally with React through custom hooks:

import { useState, useEffect } from 'react';
import { observe } from '@video/state-flow';
import type { MyApp } from './app-state';

function useStateFlow<T>(
  app: MyApp,
  states: StateVariant<T>[],
  compareFn?: (prev: T, curr: T) => boolean
) {
  const [state, setState] = useState<StateInstance<T> | null>(null);

  useEffect(() => {
    using observer = observe(app, states, setState, compareFn);
    return () => observer[Symbol.dispose]();
  }, [app, states, compareFn]);

  return state;
}

// Usage in component
function PlayerControls({ app }: { app: MyApp }) {
  const playbackState = useStateFlow(
    app, 
    [playbackState.playing, playbackState.paused],
    (prev, curr) => prev.position !== curr.position
  );

  if (!playbackState) return null;

  return (
    <button onClick={() => dispatch(app, signals.togglePlayback())}>
      {stateVar(playbackState) === 'playing' ? 'Pause' : 'Play'}
    </button>
  );
}

Vue Integration

Vue's reactivity system works well with StateFlow observers:

import { ref, onUnmounted } from 'vue';
import { observe } from '@video/state-flow';

export function useStateFlow<T>(
  app: MyApp,
  states: StateVariant<T>[]
) {
  const state = ref<StateInstance<T> | null>(null);

  const observer = observe(app, states, (newState) => {
    state.value = newState;
  });

  onUnmounted(() => {
    observer[Symbol.dispose]();
  });

  return state;
}

Angular Integration

Angular services provide a clean integration pattern:

import { Injectable, OnDestroy } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { observe } from '@video/state-flow';

@Injectable({
  providedIn: 'root'
})
export class StateFlowService implements OnDestroy {
  private observers: Array<{ [Symbol.dispose](): void }> = [];

  observeState<T>(
    app: MyApp,
    states: StateVariant<T>[]
  ): BehaviorSubject<StateInstance<T> | null> {
    const subject = new BehaviorSubject<StateInstance<T> | null>(null);
    
    const observer = observe(app, states, (state) => {
      subject.next(state);
    });
    
    this.observers.push(observer);
    return subject;
  }

  ngOnDestroy() {
    this.observers.forEach(observer => observer[Symbol.dispose]());
  }
}

Build Tool Configuration

Vite Setup

StateFlow works out-of-the-box with Vite. For optimal performance, consider these configurations:

// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    target: 'es2020'
  },
  optimizeDeps: {
    include: ['@video/state-flow']
  }
});

Webpack Configuration

For Webpack projects, ensure proper module resolution:

// webpack.config.js
module.exports = {
  resolve: {
    extensions: ['.ts', '.js']
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  }
};

Development Setup

ESLint Configuration

Enhance your development experience with these ESLint rules:

{
  "extends": ["@typescript-eslint/recommended"],
  "rules": {
    "@typescript-eslint/no-explicit-any": "error",
    "@typescript-eslint/prefer-readonly": "warn",
    "@typescript-eslint/explicit-function-return-type": "warn"
  }
}

IDE Integration

For VS Code, install the TypeScript extension and add these settings:

{
  "typescript.preferences.strictFunctionTypes": true,
  "typescript.preferences.strictNullChecks": true,
  "typescript.preferences.noImplicitAny": true
}

First Steps Checklist

Quick Start Checklist

  1. ✅ Install StateFlow package
  2. ✅ Configure TypeScript with strict mode
  3. ✅ Set up your first state definition
  4. ✅ Define signal handlers with defineFlow
  5. ✅ Initialize with applyFlow
  6. ✅ Test signal dispatch and state transitions
  7. ✅ Add observers for UI updates

Minimal Working Example

Here's a complete minimal setup to verify your installation:

// app.ts
import { 
  defineState, 
  defineSignal, 
  defineFlow, 
  applyFlow, 
  dispatch 
} from '@video/state-flow';

// 1. Define signals
const signals = {
  increment: defineSignal("increment")
};

// 2. Define state
const counterState = defineState<{ count: number }>()
  .name("counter")
  .signals(signals)
  .variant("active", true)
  .stringRepr(s => `count=${s.count}`)
  .build();

// 3. Define flow
defineFlow(counterState.active, {
  increment: (state) => ({ count: state.count + 1 })
});

// 4. Create application
const app = {
  counter: { count: 0 }
};

// 5. Apply flow
applyFlow(app, [counterState], () => {
  console.log('StateFlow initialized');
});

// 6. Test dispatch
await dispatch(app, signals.increment()).done();
console.log(app.counter); // "counter.active(count=1)"

Run this example to confirm StateFlow is working correctly in your environment.

Troubleshooting

Common Issues

TypeScript Errors: Ensure you're using TypeScript 4.5+ with strict mode enabled.

Module Resolution: If you encounter import errors, check that your bundler supports ES2020 modules.

Runtime Errors: Verify that all state variants have corresponding flow definitions before dispatching signals.

Getting Help

If you encounter issues not covered here:

  1. Check the Core Concepts for fundamental understanding
  2. Review the API Reference for detailed function signatures
  3. Examine the Architecture Guide for complex application patterns

Next Steps

Now that StateFlow is installed and configured, explore:

Previous
Core concepts