### Install @state-adapt/spaghetti-analyzer Source: https://state-adapt.github.io/api/spaghetti-analyzer/index Install the analyzer and core packages as development dependencies. ```sh npm install --save-dev @state-adapt/spaghetti-analyzer @state-adapt/spaghetti-core ``` -------------------------------- ### Install StateAdapt libraries Source: https://state-adapt.github.io/guide/angular/getting-started.html Install the core, RxJS, and Angular packages using npm. ```sh npm i -s @state-adapt/core npm i -s @state-adapt/rxjs npm i -s @state-adapt/angular ``` -------------------------------- ### Install StateAdapt packages Source: https://state-adapt.github.io/guide/svelte/getting-started.html Install the required npm packages: rxjs, @state-adapt/core, and @state-adapt/rxjs. ```sh npm i -s rxjs npm i -s @state-adapt/core npm i -s @state-adapt/rxjs ``` -------------------------------- ### Install StateAdapt dependencies Source: https://state-adapt.github.io/guide/react/getting-started.html Run these commands to install the core StateAdapt packages and RxJS. ```sh npm i -s rxjs npm i -s @state-adapt/core npm i -s @state-adapt/rxjs npm i -s @state-adapt/react ``` -------------------------------- ### Install StateAdapt packages Source: https://state-adapt.github.io/guide/solid/getting-started.html Install the required npm packages: rxjs, @state-adapt/core, and @state-adapt/rxjs. ```sh npm i -s rxjs npm i -s @state-adapt/core npm i -s @state-adapt/rxjs ``` -------------------------------- ### Configuration: apis option example for no-spaghetti Source: https://state-adapt.github.io/api/eslint-plugin-spaghetti/rules/no-spaghetti.html No description ```json { "rules": { "@state-adapt/spaghetti/no-spaghetti": [ "warn", { "apis": [ { "name": "Router.navigate", "methods": ["navigate"], "importSources": ["@app/router"], "penalty": 5 }, { "name": "Admin.log", "calls": ["console.log"], "penalty": 0 } ] } ] } } ``` -------------------------------- ### Auth Example with joinAdapters Source: https://state-adapt.github.io/api/core/src/joinAdapters Practical example of joinAdapters for an authentication state with username, password, and isLoggedIn slices. Shows usage with the update method and the resulting state object. ```tsx import { joinAdapters, createAdapter } from '@state-adapt/core'; interface AuthState { username: string | null; password: string | null; isLoggedIn: boolean; } const authAdapter = joinAdapters()({ username: createAdapter()({}), password: createAdapter()({}), isLoggedIn: createAdapter()({ login: () => true, logout: () => false, }), })(); // Usage const initialState = { username: null, password: null, isLoggedIn: false }; const newState = authAdapter.update(initialState, { username: 'bob', password: '1234', }); // { username: 'bob', password '1234', isLoggedIn: false } ``` -------------------------------- ### Multi-store shared derived state implementation Source: https://state-adapt.github.io/guide/react/examples/incremental-complexity.html A complete example showing the setup of an adapter, multiple stores, and a derived state component. ```tsx const nameAdapter = createAdapter()({ reverse: name => name.split('').reverse().join(''), selectors: { randomCase: name => name .split('') .map(c => (Math.random() > 0.5 ? c : c.toUpperCase())) .join(''), }, }); const onResetAll = source(); const name1Store = adapt('Bob', { adapter: nameAdapter, sources: { reset: onResetAll }, }); const name2Store = adapt('Kat', { adapter: nameAdapter, sources: { reset: onResetAll }, }); const deriveBobcat = derive(() => name1Store() === 'Bob' && name2Store() === 'Kat'); function MultiStoreSharedDerivedState() { const [name1, setName1] = useStore(name1Store); const [name2, setName2] = useStore(name2Store); const bobcat = useDerived(deriveBobcat); return ( <>

Hello {name1.state}!

Hello {name1.randomCase}!

Hello {name2.state}!

Hello {name2.randomCase}!

{bobcat &&

Hello, bobcat!

} ); } ``` -------------------------------- ### StateAdapt with adapter and shared source (final) Source: https://state-adapt.github.io/guide/angular/examples/incremental-complexity.html Complete TypeScript example with adapter, shared source, and two stores. ```ts export class NameComponent { nameAdapter = createAdapter()({ reverse: name => name.split('').reverse().join(''), selectors: { yelled: name => name.toUpperCase(), }, }); resetAll$ = source(); name1 = adapt('Bob', { adapter: this.nameAdapter, sources: { reset: this.resetAll$ }, }); name2 = adapt('Kat', { adapter: this.nameAdapter, sources: { reset: this.resetAll$ }, }); } ``` -------------------------------- ### joinAdapters() Source: https://state-adapt.github.io/api/core/src/joinAdapters Documentation for the joinAdapters function, including its signature, parameters, and usage examples. ```APIDOC ## joinAdapters() ### Description Creates a complex adapter from simpler adapters by combining their state change functions and selectors with namespaced names. The initial call returns a builder that can be chained with additional adapter entries, selectors, and reactions until a final empty call `()` produces the built adapter. ### Signature ```ts joinAdapters()(adapterEntries) => NewBlockAdder extends object ? S extends Selectors ? WithStateSelector> : WithStateSelector any>> : object, ReactionsWithoutSelectors & BasicAdapterMethods & WithUpdateReaction>> ``` ### Parameters - `ParentState` (type parameter) - The overall state shape that the joined adapter will manage. - `ExcludedProps` (type parameter) - Props to exclude from the adapter entries. - `adapterEntries` (object) - An object mapping state keys to simpler adapters (e.g., created with `createAdapter`). ### Returns A builder function that can be called with additional objects (selectors, reactions, etc.) and finally with `()` to get the final adapter. ### Example: Basic `joinAdapters` ```tsx import { joinAdapters, createAdapter } from '@state-adapt/core'; interface State { a: number; b: number; } const adapter = joinAdapters()({ a: createAdapter()({}), b: createAdapter()({ setTo0: state => 0, selectors: { negative: state => state * -1, }, }), })(); ``` ### Example: `joinAdapters` with `buildAdapters`-like syntax ```tsx import { joinAdapters, createAdapter } from '@state-adapt/core'; import { numberAdapter } from './number.adapter'; interface NumbersState { a: number; b: number; } const adapter = joinAdapters()({ a: numberAdapter, b: numberAdapter, })({ // Selectors total: s => s.a + s.b, })({ // Group reactions incrementAll: { a: numberAdapter.increment, b: numberAdapter.increment, }, })(([selectors, reactions]) => ({ // More reactions addBToA: state => ({ ...state, a: state.a + selectors.b(state) }), addAToB: state => ({ ...state, b: state.b + selectors.a(state) }), }))(); ``` ### Example: Auth ```tsx import { joinAdapters, createAdapter } from '@state-adapt/core'; interface AuthState { username: string | null; password: string | null; isLoggedIn: boolean; } const authAdapter = joinAdapters()({ username: createAdapter()({}), password: createAdapter()({}), isLoggedIn: createAdapter()({ login: () => true, logout: () => false, }), })(); // Usage const initialState = { username: null, password: null, isLoggedIn: false }; const newState = authAdapter.update(initialState, { username: 'bob', password: '1234', }); // { username: 'bob', password '1234', isLoggedIn: false } ``` ``` -------------------------------- ### Install ESLint plugin no-spaghetti and peer dependencies Source: https://state-adapt.github.io/guide/angular/getting-started.html Install the plugin and its peer dependencies for type-aware linting. ```sh npm install --save-dev @state-adapt/eslint-plugin-spaghetti @state-adapt/spaghetti-core @typescript-eslint/parser eslint ``` -------------------------------- ### Equivalent createAdapter Implementation Source: https://state-adapt.github.io/api/core/src/joinAdapters Equivalent manual implementation of the basic joinAdapters example using createAdapter directly. Shows the generated state change functions and selectors that joinAdapters would produce. ```tsx import { createAdapter } from '@state-adapt/core'; interface State { a: number; b: number; } const adapter = createAdapter()({ setA: (state, newA: number) => ({...state, a: newA}), resetA: (state, payload: void, initialState) => ({...state, a: initialState.a}), setBTo0: (state, payload: void) => ({...state, b: 0}), setB: (state, newB: number) => ({...state, b: newB}), resetB: (state, payload: void, initialState) => ({...state, b: initialState.b}), set: (state, newState: State) => newState, reset: (state, payload: void, initialState) => initialState, update: (state, newState: Partial) => ({...state, ...newState}), selectors: { a: state => state.a, b: state => state.b, bNegative: state => state.b * -1, state: state => state, }, }); ``` -------------------------------- ### Create dev.md with code conventions and API references Source: https://state-adapt.github.io/guide/angular/getting-started.html Alternative to skills: create a dev.md file to guide agents with code conventions and point to API references. ```markdown Always prefer declarative code and avoid imperative code. API references for @state-adapt packages are in node_modules/@state-adapt/*/skills/*/references ``` -------------------------------- ### adapt() Source: https://state-adapt.github.io/api/react/index/adapt Creates a React store from an initial state and a set of selectors/reactions. The returned store can be called as a function to get the current state, and selectors can be called as properties to get their current results. ```APIDOC ## adapt() ### Description Creates a React store from an initial state and a set of selectors/reactions. The returned store can be called as a function to get the current state, and selectors can be called as properties to get their current results. ### Signature `adapt(initialState, second): ReactStore` ### Type Parameters - **State** - The state type. - **S** - Extends `Selectors`. - **R** - Extends `ReactionsWithSelectors`. - **R2** - Extends `ReactionsWithSelectors`. - **ReturnedSources** - Defaults to `unknown`. ### Parameters - **initialState** (`InitialState`) - The initial state for the store. - **second** (`R & object & NotAdaptOptions | AdaptOptions`) - The selectors/reactions or adapt options. ### Returns `ReactStore` - A React store that can be called as a function to get the current state, and selectors can be called as properties to get their current results. ### Example ```ts import { stringAdapter } from '@state-adapt/core/adapters'; import { adapt } from '@state-adapt/react'; const name = adapt('John', stringAdapter); console.log(name()); // 'John' console.log(name.uppercase()); // 'JOHN' ``` ### Notes - See StateAdapt.adapt for the complete API. - See derive for composing these reads. ``` -------------------------------- ### Basic adapter implementation Source: https://state-adapt.github.io/api/core/src/Adapter An example of defining a basic adapter using the Adapter type, including state change functions and selectors. ```typescript import { Adapter } from '@state-adapt/core'; type State = number; const adapter = { set: (state: State, payload: State) => payload, reset: (state: State, payload: any, initialState: State) => initialState, selectors: { state: (state: State) => state, }, } satisfies Adapter; ``` -------------------------------- ### General command syntax examples detected by no-spaghetti Source: https://state-adapt.github.io/api/eslint-plugin-spaghetti/rules/no-spaghetti.html Shows the assignment, property mutation, increment, delete, and function-call patterns the rule detects as commands from syntax. ```ts status = 'ready'; // assignment user.name = 'Ada'; // property mutation count++; // increment delete cache.value; // delete save(); // function call with an ignored return value ``` -------------------------------- ### Using provideStore in AppModule for devtools setup without selectors Source: https://state-adapt.github.io/api/angular/index/provideStore Example of using provideStore in an Angular AppModule to configure devtools with actionSanitizer and stateSanitizer, and setting showSelectors to false. This provider is added to the providers array in the @NgModule decorator. ```typescript import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { actionSanitizer, stateSanitizer } from '@state-adapt/core'; import { provideStore } from '@state-adapt/angular'; import { AppComponent } from './app.component'; @NgModule({ imports: [BrowserModule], declarations: [AppComponent], providers: [ provideStore({ devtools: (window as any)?.__REDUX_DEVTOOLS_EXTENSION__?.({ actionSanitizer, stateSanitizer, }), showSelectors: false, }), ], }) export class AppModule {} ``` -------------------------------- ### Run Shopping Demo Source: https://state-adapt.github.io/guide/angular/examples/stackblitz-examples.html Command to execute the shopping catalog and cart demo application locally from the repository root. ```sh npm run demo:shopping ``` -------------------------------- ### Sum of Squared Numbers Imperative Example Source: https://state-adapt.github.io/guide/thinking-reactively/imperative-trap.html An example of imperative state modification using a loop and a delayed timeout mutation. ```typescript let squaredSum = 0; for (let i = 1; i <= 10; i++) { squaredSum += i ** 2; } setTimeout(() => { squaredSum = 100; }, 1000); ``` ```typescript let squaredSum = 0; for (let i = 1; i <= 10; i++) { squaredSum += i ** 2; } setTimeout(() => { squaredSum = 100; }, 1000); ``` -------------------------------- ### useAdapt(initialState, { adapter, sources, path }) Source: https://state-adapt.github.io/api/react/index/useAdapt Creates a store with an AdaptOptions object that can include an adapter, sources, and a state path. Sources allow the store to react to external events. ```APIDOC ## useAdapt(initialState, { adapter, sources, path }) ### Description Creates a store with an AdaptOptions object that can define an adapter, sources, and/or a state path. Sources allow the store to declaratively react to external events rather than being commanded by imperative callback functions. ### Signature `useAdapt(initialState: State, options: AdaptOptions): ProxyStoreTuple>` ### Parameters - **initialState** (`State`) - Required - The initial state for the store. - **options** (`AdaptOptions`) - Required - An object with optional `adapter`, `sources`, and `path` properties. - **adapter** (`Adapter`) - Optional - An adapter object with state change functions and selectors. - **sources** (`Source | Source[] | { [key: string]: Source | Source[] }`) - Optional - Sources that can be a single source, an array of sources, or an object mapping source names to sources. When a source emits, it triggers the store's `set` method with the payload. - **path** (`string`) - Optional - A state path for the store. ### Returns - **ProxyStoreTuple** - A tuple where the first element is a proxy object with selector results (including `state`), and the second element is a `setState` function with additional properties (e.g., custom state change functions and `reset`). ### Example ```tsx import { useAdapt } from '@state-adapt/react'; import { interval } from 'rxjs'; const onTick = interval(1000); export function MyComponent() { const [clock] = useAdapt(0, { adapter: { increment: state => state + 1, }, sources: onTick, // or [onTick], or { set: onTick }, or { set: [onTick] } path: 'clock', }); return
{clock.state}
; } ``` ### Sources There are 4 possible ways sources can be defined: 1. A source can be a single source or Observable<`State`>. When the source emits, it triggers the store's `set` method with the payload. 2. (Additional ways not fully described in the source text.) ``` -------------------------------- ### TypeScript example: createEntityState() Source: https://state-adapt.github.io/api/core/adapters/createEntityState Creates an empty normalized entity state for a Todo type. The example shows the import and usage, with the resulting state being { ids: [], entities: {} }. ```typescript import { createEntityState } from '@state-adapt/core/adapters'; type Todo = { id: string; text: string }; const initialState = createEntityState(); // { ids: [], entities: {} } ``` -------------------------------- ### adapt() Source: https://state-adapt.github.io/api/rxjs/index/StateAdapt Creates a store that will manage state while it has subscribers. Accepts an initial state and optionally an adapter, sources, and path. Returns an InitializedSmartStore with methods like set, reset, and state$. ```APIDOC ## adapt() ### Description Creates a store that will manage state while it has subscribers. Accepts an initial state and optionally an adapter, sources, and path. Returns an InitializedSmartStore with methods like set, reset, and state$. ### Method adapt ### Signature `adapt(initialState, second): InitializedSmartStore` ### Parameters - `initialState` (State) - Required - The initial state of the store. - `second` (Adapter | AdaptOptions) - Optional - Either a state Adapter object or an AdaptOptions object containing adapter, sources, and/or path. ### Usage Examples #### Example: initialState only ```typescript const name = adapt('John'); name.state$.subscribe(console.log); // logs 'John' name.set('Johnsh'); // logs 'Johnsh' name.reset(); // logs 'John' ``` #### Example: Using an adapter ```typescript const name = adapt('John', { concat: (state, payload: string) => state + payload, selectors: { length: state => state.length, }, }); name.state$.subscribe(console.log); // Logs 'John' name.length$.subscribe(console.log); // Logs 4 name.concat('sh'); // logs 'Johnsh' and 6 name.reset(); // logs 'John' and 4 ``` #### Example: Using AdaptOptions ```typescript const tick$ = interval(1000); const clock = adapt(0, { adapter: { increment: state => state + 1, }, sources: tick$, // or [tick$], or { set: tick$ }, or { set: [tick$] } path: 'clock', }); clock.state$.subscribe(console.log); // Logs 0, 1, 2, 3, etc. ``` ### Sources Sources allow the store to declaratively react to external events. There are 4 possible ways sources can be defined: 1. A single source or Observable - triggers the store's `set` method with the payload. 2. An array of sources or Observables - any emission triggers the store's `set` method. 3. An object with keys matching adapter state change function names, with a source or array of sources. 4. A function that takes a detached store and returns any of the above types. #### Example: Single source or observable ```typescript const nameChange$ = source(); const name = adapt('John', { sources: nameChange$, path: 'name', }); name.state$.subscribe(console.log); // Logs 'John' nameChange$.next('Johnsh'); // logs 'Johnsh' ``` #### Example: Array of sources or observables ```typescript const nameChange$ = source(); const nameChange2$ = source(); const name = adapt('John', { sources: [nameChange$, nameChange2$], path: 'name', }); name.state$.subscribe(console.log); // Logs 'John' nameChange$.next('Johnsh'); // logs 'Johnsh' nameChange2$.next('Johnsh2'); // logs 'Johnsh2' ``` #### Example: Object of sources or observables ```typescript const nameChange$ = source(); const nameReset$ = source(); const name = adapt('John', { sources: { set: nameChange$, reset: nameReset$, }, path: 'name', }); name.state$.subscribe(console.log); // Logs 'John' nameChange$.next('Johnsh'); // logs 'Johnsh' nameReset$.next(); // logs 'John' ``` ### Return Value Returns an `InitializedSmartStore` object with methods like `set`, `reset`, and a `state$` observable. The store manages state while it has subscribers and cleans up when it loses its last subscriber. ``` -------------------------------- ### Multi-store state selection with State Adapt Source: https://state-adapt.github.io/guide/solid/examples/incremental-complexity.html This example shows how to create an adapter with custom selectors and use it across two separate stores. It demonstrates triggering state changes and resetting both stores simultaneously using a shared source. ```tsx const nameAdapter = createAdapter()({ reverseName: (name) => name.split('').reverse().join(''), concatName: (name, anotherName: string) => `${name} ${anotherName}`, selectors: { yelledName: (name) => name.toUpperCase(), // Will be memoized }, }); const onResetBoth = source(); const onNameFromServer = timer(3000).pipe(map(() => 'Joel')); function MultiStoreSelectors() { const nameStore1 = adapt('Bob', { adapter: nameAdapter, sources: { set: onNameFromServer, // `set` is provided with all adapters reset: onResetBoth, // `reset` is provided with all adapters }, }); const name1 = fromAdapt(nameStore1); const nameStore2 = adapt('Bob', { adapter: nameAdapter, sources: { concatName: onNameFromServer, // Trigger a specific state reaction reset: onResetBoth, // `reset` is provided with all adapters }, }); const name2 = fromAdapt(nameStore2); const bothBobs = () => name1.state() === 'Bob' && name2.state() === 'Bob'; return ( <>

Hello {name1.yelledName()}!

Hello {name2.yelledName()}!

{bothBobs() &&

Hello Bobs!

} ); } ``` -------------------------------- ### Building an adapter with buildAdapter Source: https://state-adapt.github.io/api/core/src/buildAdapter Demonstrates the incremental construction of an adapter by chaining multiple configuration objects and finalizing with an empty call. ```typescript import { buildAdapter } from '@state-adapt/core'; import { numberAdapter } from './number.adapter'; const numberStringAdapter = buildAdapter()(numberAdapter)({ // Define more selectors })(([selectors, reactions]) => ({ // Define more state changes }))({ // Define grouped state changes })(); // End ``` -------------------------------- ### Using adapt() with stringAdapter Source: https://state-adapt.github.io/api/react/index/adapt Creates a store for a string initial value using the stringAdapter from @state-adapt/core/adapters. The store can be called as a function to get the current state, and selector properties like uppercase() can be called to get their current result. ```typescript import { stringAdapter } from '@state-adapt/core/adapters'; import { adapt } from '@state-adapt/react'; const name = adapt('John', stringAdapter); console.log(name()); // 'John' console.log(name.uppercase()); // 'JOHN' ``` -------------------------------- ### createStateAdapt(options?) Source: https://state-adapt.github.io/api/react/index/createStateAdapt Creates a StateAdapt instance with the provided configuration. Returns an object with adapt() and watch() methods. ```APIDOC ## createStateAdapt(options?) ### Description Creates a StateAdapt instance with the provided configuration. See ConfigureStateAdaptOptions for every available option. ### Parameters - **options** (ConfigureStateAdaptOptions) - Optional - Configuration options for the StateAdapt instance. ### Returns Returns an object with the following methods: - **adapt** - Creates a store using this StateAdapt instance. - **watch** - Watches a store path using this StateAdapt instance. ### Example ```ts // state-adapt.ts import { createStateAdapt } from '@state-adapt/react'; export const stateAdapt = createStateAdapt({ devtools: null }); export const { adapt, watch } = stateAdapt; ``` ### Notes - The package-level `adapt` and `watch` always use the default configuration (defaultStateAdapt). With a custom configuration, import them from your application's `state-adapt.ts` module and provide that same `stateAdapt` through AdaptContext. - Only combine stores created by the same instance. StateAdapt stops unsafe combinations with errors. ``` -------------------------------- ### Static JSX Declaration Source: https://state-adapt.github.io/guide/thinking-reactively/imperative-trap.html A simple example of static, non-reactive JSX content. ```tsx return

I WILL NEVER CHANGE!

; ``` -------------------------------- ### Run React Demo Locally Source: https://state-adapt.github.io/guide/react/examples/stackblitz-examples.html Command to execute the React demo application from the root of the StateAdapt repository. ```bash npm run demo:react ``` -------------------------------- ### Reactive JSX Declaration Source: https://state-adapt.github.io/guide/thinking-reactively/imperative-trap.html A reactive JSX example that updates based on the 'day' variable. ```tsx return

I WILL CHANGE ON {day}!

; ``` -------------------------------- ### Declarative Array Mapping Source: https://state-adapt.github.io/guide/thinking-reactively/imperative-trap.html An example of declarative programming where the variable is fully defined at the point of declaration. ```typescript const squared2 = [1, 2, 3].map(i => i ** 2); ``` -------------------------------- ### useAdapt Source: https://state-adapt.github.io/api/react/index/useAdapt Creates a smart store with the given initial state and options. If no path is provided, the store's path defaults to the result of calling getId. Stores need subscribers to activate and subscribe to their sources. ```APIDOC ## useAdapt ### Description Creates a smart store with the given initial state and options. If no path is provided, the store's path defaults to the result of calling getId. Stores need subscribers to activate and subscribe to their sources. ### Type Parameters - **State** - The state type. - **S** - Extends Selectors. - **R** - Extends ReactionsWithSelectors. - **ReturnedSources** - Defaults to unknown. ### Parameters - **initialState** (InitialState) - The initial state for the store. - **second** (R & object & NotAdaptOptions | AdaptOptions) - Either an options object or a combination of selectors and reactions. ### Returns - **ProxyStoreTuple>** - A tuple containing the store proxy and the initialized smart store. ``` -------------------------------- ### Derived events implementation Source: https://state-adapt.github.io/guide/react/examples/incremental-complexity.html A complete example demonstrating stores reacting to RxJS observables with delayed initialization. ```tsx const nameAdapter = createAdapter()({ reverse: name => name.split('').reverse().join(''), selectors: { randomCase: name => name .split('') .map(c => (Math.random() > 0.5 ? c : c.toUpperCase())) .join(''), }, }); const onResetAll = source(); const name1Store = adapt('Loading...', { adapter: nameAdapter, sources: { set: of('Bob').pipe(delay(3000)), reset: onResetAll, }, }); const name2Store = adapt('Loading...', { adapter: nameAdapter, sources: { set: of('Kat').pipe(delay(3000)), reset: onResetAll, }, }); const deriveBobcat = derive(() => name1Store() === 'Bob' && name2Store() === 'Kat'); function DerivedEvents() { const [name1, setName1] = useStore(name1Store); const [name2, setName2] = useStore(name2Store); const bobcat = useDerived(deriveBobcat); return ( <>

Hello {name1.state}!

Hello {name1.randomCase}!

Hello {name2.state}!

Hello {name2.randomCase}!

{bobcat &&

Hello, bobcat!

} ); } ``` -------------------------------- ### configureStateAdapt() Source: https://state-adapt.github.io/api/rxjs/index/configureStateAdapt Creates a new StateAdapt instance with the provided options. Returns an object with adapt and watch methods. ```APIDOC ## configureStateAdapt() ### Description Creates a new StateAdapt instance with the provided options. Returns an object with adapt and watch methods. ### Signature `configureStateAdapt(options?: ConfigureStateAdaptOptions): Pick, "adapt" | "watch">` ### Type Parameters - **Store** (extends `GlobalStore` = `GlobalStore`) - The type of the store used for integration. ### Parameters - **options** (`ConfigureStateAdaptOptions`, optional) - Configuration options for the StateAdapt instance. Can include: - `devtools` (any) - Redux DevTools extension instance. - `showSelectors` (boolean) - Whether to show selectors in DevTools. - `store` (GlobalStore) - A Redux-like store to integrate with. ### Returns `Pick, "adapt" | "watch">` - An object containing the `adapt` and `watch` methods. ### Examples #### Standalone with default options ```ts import { configureStateAdapt } from '@state-adapt/rxjs'; export const stateAdapt = configureStateAdapt(); export const { adapt, watch } = stateAdapt; ``` #### Standalone with DevTools ```ts import { actionSanitizer, stateSanitizer } from '@state-adapt/core'; import { configureStateAdapt } from '@state-adapt/rxjs'; export const stateAdapt = configureStateAdapt({ devtools: (window as any)?.__REDUX_DEVTOOLS_EXTENSION__?.({ actionSanitizer, stateSanitizer, }), showSelectors: false, }); export const { adapt, watch } = stateAdapt; ``` #### With another store ```ts import { configureStore } from '@reduxjs/toolkit'; import { configureStateAdapt } from '@state-adapt/rxjs'; import { reducer } from './reducer'; const store = configureStore({ reducer }); export const stateAdapt = configureStateAdapt({ store }); export const { adapt, watch } = stateAdapt; ``` ``` -------------------------------- ### Defining basic reactions with buildAdapter Source: https://state-adapt.github.io/api/core/src/buildAdapter Illustrates how to define reactions that utilize previously defined selectors to perform state changes. ```typescript import { buildAdapter } from '@state-adapt/core'; import { numberAdapter } from './number.adapter'; const numberStringAdapter = buildAdapter()(numberAdapter)({ negativeStr: s => s.negative.toString(), })(([selectors, reactions]) => ({ setToNegative: state => selectors.negative(state), }))(); ``` -------------------------------- ### Imperative Array Population Source: https://state-adapt.github.io/guide/thinking-reactively/imperative-trap.html A traditional example of imperative programming where an array is initialized empty and modified via a loop. ```typescript const squared = [] as number[]; for (let i = 1; i <= 3; i++) { squared.push(i ** 2); } ``` -------------------------------- ### Derive Double from Count Source: https://state-adapt.github.io/guide/thinking-reactively/the-reactivity-rule.html An example of deriving a value directly in the template to ensure it stays in sync with the source state. ```tsx

Double: {count * 2}

``` -------------------------------- ### joinAdapters with buildAdapter-like Syntax Source: https://state-adapt.github.io/api/core/src/joinAdapters Shows joinAdapters with buildAdapter-like chaining syntax: passing adapter entries, then selectors, then grouped reactions, then a function receiving selectors and reactions to add more reactions. Demonstrates how to reuse a numberAdapter for multiple slices. ```tsx import { joinAdapters, createAdapter } from '@state-adapt/core'; import { numberAdapter } from './number.adapter'; interface NumbersState { a: number; b: number; } const adapter = joinAdapters()({ a: numberAdapter, b: numberAdapter, })({ // Selectors total: s => s.a + s.b, })({ // Group reactions incrementAll: { a: numberAdapter.increment, b: numberAdapter.increment, }, })(([selectors, reactions]) => ({ // More reactions addBToA: state => ({ ...state, a: state.a + selectors.b(state) }), addAToB: state => ({ ...state, b: state.b + selectors.a(state) }), }))(); ``` -------------------------------- ### adapt(initialState, { adapter, sources, path }) - AdaptOptions Source: https://state-adapt.github.io/api/rxjs/index/StateAdapt Use AdaptOptions to define an adapter, sources, and a path. Sources allow the store to react to external events. The example uses an interval as a source to increment state. ```typescript const tick$ = interval(1000); const clock = adapt(0, { adapter: { increment: state => state + 1, }, sources: tick$, // or [tick$], or { set: tick$ }, or { set: [tick$] } path: 'clock', }); clock.state$.subscribe(console.log); // Logs 0, 1, 2, 3, etc. ``` -------------------------------- ### Define EntityState for a Todo collection Source: https://state-adapt.github.io/api/core/adapters/EntityState Example showing how to initialize an EntityState object with a specific Todo entity type. ```typescript import { EntityState } from '@state-adapt/core/adapters'; type Todo = { id: string; text: string }; const todos: EntityState = { ids: ['learn'], entities: { learn: { id: 'learn', text: 'Learn StateAdapt' } }, }; ``` -------------------------------- ### useAdapt(initialState, adapter) Source: https://state-adapt.github.io/api/react/index/useAdapt Creates a store with an adapter that defines custom state change functions and selectors. ```APIDOC ## useAdapt(initialState, adapter) ### Description Creates a store with an adapter object that customizes the state change functions and selectors. The adapter can define methods that become available on the `setState` function, and selectors that become properties on the selector results proxy. ### Signature `useAdapt(initialState: State, adapter: Adapter): ProxyStoreTuple>` ### Parameters - **initialState** (`State`) - Required - The initial state for the store. - **adapter** (`Adapter`) - Required - An adapter object with state change functions and selectors. ### Returns - **ProxyStoreTuple** - A tuple where the first element is a proxy object with selector results (including `state` and any custom selectors), and the second element is a `setState` function with additional properties (e.g., custom state change functions and `reset`). ### Example ```tsx import { useAdapt } from '@state-adapt/react'; export function MyComponent() { const [name, setName] = useAdapt('John', { concat: (state, payload: string) => state + payload, selectors: { length: state => state.length, }, }); return ( <>
{name.state}
{name.length}
); } ``` ``` -------------------------------- ### StateAdapt with derived events from RxJS Source: https://state-adapt.github.io/guide/angular/examples/incremental-complexity.html TypeScript example using RxJS observables as sources to set initial values after a delay. ```ts export class NameComponent { // ... name1 = adapt('Loading...', { adapter: this.nameAdapter, sources: { set: of('Bob').pipe(delay(3000)), // Any observable reset: this.resetAll$, }, }); name2 = adapt('Loading...', { adapter: this.nameAdapter, sources: { set: of('Kat').pipe(delay(3000)), // Any observable reset: this.resetAll$, }, }); } ``` -------------------------------- ### Create a small initial adapter object Source: https://state-adapt.github.io/api/core/src/createAdapter Shows how to define custom reactions and selectors for a simple number state. ```typescript import { createAdapter } from '@state-adapt/core'; const numberAdapter = createAdapter()({ add: (state, n: number) => state + n, subtract: (state, n: number) => state - n, selectors: { negative: state => state * -1, }, }); ``` -------------------------------- ### Add agent skills for StateAdapt packages Source: https://state-adapt.github.io/guide/angular/getting-started.html Use npx skills add to install the skill for each package's API reference. ```sh npx skills add ./node_modules/@state-adapt/core --skill state-adapt-core npx skills add ./node_modules/@state-adapt/rxjs --skill state-adapt-rxjs # etc ``` -------------------------------- ### Accessing loading state with watch() Source: https://state-adapt.github.io/api/rxjs/index/StateAdapt Example of using watch to access the loading state of an HTTP request without triggering the request itself. ```tsx watch('data', httpAdapter).loading$.subscribe(console.log); ``` -------------------------------- ### Run Counter Demo Source: https://state-adapt.github.io/guide/angular/examples/stackblitz-examples.html Command to execute the counter demo application locally from the repository root. ```sh npm run demo:counter ``` -------------------------------- ### Define derived state locally Source: https://state-adapt.github.io/guide/react/examples/incremental-complexity.html An example of calculating derived state directly within a component using the current state value. ```tsx const [name, setName] = useAdapt(nameStore); const randomCaseName = name.state .split('') .map(c => (Math.random() > 0.5 ? c : c.toUpperCase())) .join(''); // ... ``` -------------------------------- ### useAdapt(initialState) Source: https://state-adapt.github.io/api/react/index/useAdapt Creates a store with the given initial state and returns a tuple where the first element is a proxy object with selector results and the second is a setState function with a reset method. ```APIDOC ## useAdapt(initialState) ### Description Creates a store with the given initial state and returns a tuple `[selectorResults, setState]`. The `selectorResults` is a proxy object containing the state and any selectors. The `setState` function has a `reset` property that resets the store's state. ### Signature `useAdapt(initialState: State): ProxyStoreTuple>` ### Parameters - **initialState** (`State`) - Required - The initial state for the store. ### Returns - **ProxyStoreTuple** - A tuple where the first element is a proxy object with selector results (including `state`), and the second element is a `setState` function with additional properties (e.g., `reset`). ### Example ```tsx import { useAdapt } from '@state-adapt/react'; export function MyComponent() { const [name, setName] = useAdapt('John'); return ( <>
{name.state}
); } ``` ``` -------------------------------- ### StateAdapt with shared event source Source: https://state-adapt.github.io/guide/angular/examples/incremental-complexity.html TypeScript example showing two stores using a shared event source to reset both states. ```ts export class NameComponent { // ... resetAll$ = source(); // Shared event source name1 = adapt('Bob', this.nameAdapter); name1 = adapt('Bob', { adapter: this.nameAdapter, sources: { reset: this.resetAll$ }, // calls `reset` reducer (included) }); name2 = adapt('Kat', this.nameAdapter); name2 = adapt('Kat', { adapter: this.nameAdapter, sources: { reset: this.resetAll$ }, // calls `reset` reducer (included) }); } ``` -------------------------------- ### adapt(initialState, second?) Source: https://state-adapt.github.io/api/react/index/createStateAdapt Creates a store using this StateAdapt instance. Part of the object returned by createStateAdapt(). ```APIDOC ## adapt(initialState, second?) ### Description Creates a store using this StateAdapt instance. ### Type Parameters - **State** - The state type. - **S** - Extends Selectors. - **R** - Extends ReactionsWithSelectors. - **R2** - Extends ReactionsWithSelectors. - **ReturnedSources** - Defaults to unknown. ### Parameters - **initialState** (InitialState) - Required - The initial state for the store. - **second** (R & object & NotAdaptOptions | AdaptOptions) - Optional - Additional options or reactions. ### Returns ReactStore ### Example ```ts // counter.store.ts import { adapt } from './state-adapt'; export const countStore = adapt(5); ``` ``` -------------------------------- ### Create an empty initial adapter object Source: https://state-adapt.github.io/api/core/src/createAdapter Demonstrates initializing an adapter with no custom reactions or selectors using createAdapter. ```typescript import { createAdapter } from '@state-adapt/core'; const numberAdapter = createAdapter()({}); ``` -------------------------------- ### Define derived values outside components Source: https://state-adapt.github.io/api/react/index/derive Example showing how to define derived stores using derive() and consume them in a React component with useDerived(). ```tsx import { adapt, derive, useDerived } from '@state-adapt/react'; const priceStore = adapt(20); const quantityStore = adapt(3); const deriveSubtotal = derive(() => priceStore() * quantityStore()); const deriveTotal = derive(() => deriveSubtotal() + 5); function Total() { const total = useDerived(deriveTotal); return

Total: {total}

; } ```