> ## Documentation Index
> Fetch the complete documentation index at: https://stratasync.blode.md/llms.txt
> Use this file to discover all available pages before exploring further.

# @stratasync/mobx

Implements `ReactivityAdapter` using MobX. Makes synced model properties observable so components re-render when data changes.

## What it provides

- **`mobxReactivityAdapter`**: a pre-configured singleton implementing `ReactivityAdapter` with MobX observables, computed values, reactions, and batched updates
- **`createMobXReactivity`**: a factory function returning the same adapter (useful for explicit instantiation)
- **MobX helpers**: dirty tracking, relation helpers, and model utilities
- **Core re-exports**: model decorators and base classes from `@stratasync/core` (see [Re-exported core APIs](#re-exported-core-apis))

## Installation

```bash
npm install @stratasync/mobx mobx
```

### Peer dependencies

| Package | Version  |
| ------- | -------- |
| `mobx`  | `^6.0.0` |

## Usage

Pass the adapter when creating the sync client.

```ts
import { createSyncClient } from "@stratasync/client";
import { mobxReactivityAdapter } from "@stratasync/mobx";

const client = createSyncClient({
  reactivity: mobxReactivityAdapter,
  // ... storage, transport
});
```

All decorated model properties become MobX observables:

- `autorun`, `reaction`, `when` track reads and re-execute on changes
- Components wrapped with `observer()` re-render on observed changes
- Sync engine batch updates run inside `runInAction`

## API reference

### mobxReactivityAdapter

Singleton `ReactivityAdapter` implementation.

```ts
import { mobxReactivityAdapter } from "@stratasync/mobx";
```

The adapter implements these methods:

| Method                            | MobX Implementation               | Description                                                      |
| --------------------------------- | --------------------------------- | ---------------------------------------------------------------- |
| `createBox(initialValue)`         | `observable` + `makeObservable`   | Creates a reactive boxed value.                                  |
| `createMap(entries)`              | `observable.map`                  | Creates a reactive key-value map.                                |
| `createArray(items)`              | `observable.array`                | Creates a reactive array.                                        |
| `makeObservable(target)`          | `observable(target)`              | Makes a plain object deeply observable.                          |
| `batch(fn)`                       | `runInAction(fn)`                 | Batches multiple updates into a single reaction cycle.           |
| `runInAction(fn)`                 | `runInAction(fn)`                 | Runs a function inside a MobX action.                            |
| `reaction(expr, effect, options)` | `reaction(expr, effect, options)` | Creates a reaction that tracks an expression and runs an effect. |
| `computed(getter)`                | `computed(getter)`                | Creates a MobX computed value.                                   |

### createMobXReactivity

Factory that returns the `mobxReactivityAdapter` singleton. Both approaches are equivalent:

```ts
import { createMobXReactivity, mobxReactivityAdapter } from "@stratasync/mobx";

// These are the same object
const adapter1 = mobxReactivityAdapter;
const adapter2 = createMobXReactivity();
// adapter1 === adapter2
```

**Signature:** `createMobXReactivity(): ReactivityAdapter`

### ReactivityAdapter interface

From `@stratasync/core`:

```ts
interface ReactivityAdapter {
  createBox<T>(initialValue: T, options?: ObservableOptions): ObservableBox<T>;
  createMap<K, V>(
    entries?: Iterable<[K, V]>,
    options?: ObservableOptions
  ): ObservableMap<K, V>;
  createArray<T>(items?: T[], options?: ObservableOptions): ObservableArray<T>;
  makeObservable<T extends object>(target: T, options?: ObservableOptions): T;
  batch(fn: () => void): void;
  runInAction<T>(fn: () => T): T;
  reaction<T>(
    expression: () => T,
    effect: (value: T) => void,
    options?: ReactionOptions
  ): DisposeFn;
  computed<T>(getter: () => T, options?: ObservableOptions): { get(): T };
}
```

## Re-exported core APIs

Import decorators and base classes directly from `@stratasync/mobx`:

```ts
import {
  BackReference,
  Model,
  ClientModel,
  OneToMany,
  Property,
  Reference,
  ReferenceArray,
  mobxReactivityAdapter,
} from "@stratasync/mobx";
```

Define models and configure reactivity from a single import:

```ts
import {
  Model,
  ClientModel,
  Property,
  createDirtyTracker,
  computedReference,
  mobxReactivityAdapter,
} from "@stratasync/mobx";

@ClientModel("Task")
class Task extends Model {
  @Property() title!: string;
  @Property() description!: string;
  @Property() priority!: number;
}
```

Additional root exports:

```ts
import {
  cloneModelData,
  computedCollection,
  computedReference,
  createDirtyTracker,
  diffModels,
  getDirtyTracker,
  initMobXObservability,
  isModelDirty,
  toPlainObject,
} from "@stratasync/mobx";
```

## How it works

All model property storage uses MobX observables, so any `autorun`, `reaction`, `computed`, or `observer` that reads a property gets notified on change. Sync updates are wrapped in `runInAction` for batching.

## Architecture role

Bridges `@stratasync/core` with MobX.

```
sync-core (defines ReactivityAdapter interface)
  ^-- sync-mobx (implements ReactivityAdapter with MobX)
        ^-- sync-client (uses adapter for observable state)
```

The sync system is reactivity-agnostic: the same interface works with other state libraries.