Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ node_modules
dist
# Ignore TS incremental build info everywhere in the repo
*.tsbuildinfo
.DS_Store
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pnpm add loro-mirror loro-crdt

```typescript
import { LoroDoc } from "loro-crdt";
import { schema, createStore } from "loro-mirror";
import { Mirror, schema } from "loro-mirror";

// Define your schema
const todoSchema = schema({
Expand All @@ -51,16 +51,16 @@ const todoSchema = schema({

// Create a Loro document
const doc = new LoroDoc();
// Create a store
const store = createStore({
// Create a mirror
const mirror = new Mirror({
doc,
schema: todoSchema,
initialState: { todos: [] },
});

// Update the state (immutable update)
// Note: setState is async; await it in non-React code
await store.setState((s) => ({
await mirror.setState((s) => ({
...s,
todos: [
...s.todos,
Expand All @@ -72,7 +72,7 @@ await store.setState((s) => ({
}));

// Or: draft-style updates (mutate a draft)
await store.setState((state) => {
await mirror.setState((state) => {
state.todos.push({
text: "Learn Loro Mirror",
completed: false,
Expand All @@ -82,7 +82,7 @@ await store.setState((state) => {
});

// Subscribe to state changes
store.subscribe((state) => {
mirror.subscribe((state) => {
console.log("State updated:", state);
});
```
Expand Down
64 changes: 7 additions & 57 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Contents

- Installation & Imports
- Core: Mirror and Store
- Core: Mirror
- Schema Builder
- Validation & Defaults
- Utilities (Advanced)
Expand All @@ -15,11 +15,11 @@
## Installation & Imports

- Install: `npm install loro-mirror loro-crdt`
- Import styles:
- Named imports (recommended): `import { Mirror, createStore, schema } from "loro-mirror"`
- Import styles:
- Named imports (recommended): `import { Mirror, schema } from "loro-mirror"`
- Default (convenience bundle of `schema` + `core`): `import loroMirror from "loro-mirror"`

## Core: Mirror and Store
## Core: Mirror

### Mirror

Expand All @@ -31,8 +31,8 @@
- `validateUpdates?: boolean` (default `true`) — validate on `setState`
- `throwOnValidationError?: boolean` (default `false`) — throw on schema validation errors
- `debug?: boolean` — verbose logging to console for diagnostics
- `checkStateConsistency?: boolean` (default `false`) — deep checks in-memory state equals normalized `doc` JSON after `setState`
- `inferOptions?: { defaultLoroText?: boolean; defaultMovableList?: boolean }` — inference hints when no schema covers a field
- `checkStateConsistency?: boolean` (default `false`) — deep checks in-memory state equals normalized `doc` JSON after `setState`
- `inferOptions?: { defaultLoroText?: boolean; defaultMovableList?: boolean }` — inference hints when no schema covers a field

- Methods
- `getState(): InferType<S>` — returns the current mirror state (immutable snapshot)
Expand Down Expand Up @@ -87,56 +87,6 @@
unsub();
```

### Store

Convenience wrapper around `Mirror` with a minimal Redux‑like surface.

- `createStore(options): Store<S>`
- `options: CreateStoreOptions<S>`
- `doc: LoroDoc`
- `schema: S`
- `initialState?: Partial<InferInputType<S>>`
- `validateUpdates?: boolean`
- `throwOnValidationError?: boolean` (default `true`)
- `debug?: boolean`
- `checkStateConsistency?: boolean`
- Returns `Store<S>` with:
- `getState(): InferType<S>`
- `setState(updater): Promise<void>` — same updater shapes as Mirror; await in non-React code
- `subscribe(cb): () => void` (same metadata as Mirror)
- `getMirror(): Mirror<S>`
- `getLoro(): LoroDoc`

- `createReducer(handlers) -> (store) => dispatch(type, payload)`
- Define an object of handlers that mutate an Immer draft. The returned `dispatch` wires those actions to `store.setState`.

Example

```ts
import { createStore, createReducer, schema } from "loro-mirror";
import { LoroDoc } from "loro-crdt";

const s = schema({
todos: schema.LoroList(schema.LoroMap({ id: schema.String(), text: schema.String(), done: schema.Boolean({ defaultValue: false }) }), (t) => t.id),
});

const store = createStore({ doc: new LoroDoc(), schema: s });

const actions = {
add(state, { id, text }: { id: string; text: string }) {
state.todos.push({ id, text });
},
toggle(state, id: string) {
const item = state.todos.find((t) => t.id === id);
if (item) item.done = !item.done;
},
};

const dispatch = createReducer(actions)(store);

dispatch("add", { id: "a", text: "Task" });
dispatch("toggle", "a");
```

## Schema Builder

Expand Down Expand Up @@ -278,4 +228,4 @@

---

Questions or gaps? If you need deeper internals (diff pipelines, event application), explore the source under `src/core/` — but for most apps, `Mirror`, the schema builders, and `createStore` are all you need.
Questions or gaps? If you need deeper internals (diff pipelines, event application), explore the source under `src/core/` — but for most apps, `Mirror` and the schema builders are all you need.
21 changes: 5 additions & 16 deletions packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

## Quick Start

Define a schema and wire a store to a `LoroDoc`.
Define a schema and instantiate a `Mirror` with a `LoroDoc`.

```ts
import { createStore, schema } from "loro-mirror";
import { Mirror, schema } from "loro-mirror";
import { LoroDoc } from "loro-crdt";

const doc = new LoroDoc();
Expand All @@ -27,7 +27,7 @@ const appSchema = schema({
notes: schema.LoroText(),
});

const store = createStore({ doc, schema: appSchema });
const store = new Mirror({ doc, schema: appSchema });

// Read state
const state = store.getState();
Expand All @@ -53,8 +53,6 @@ const unsubscribe = store.subscribe((next, { direction }) => {
});
```

Tip: If you need direct access, `store.getMirror()` returns the underlying `Mirror`.

## Installation

```bash
Expand Down Expand Up @@ -92,15 +90,6 @@ Trees are advanced usage; see Advanced: Trees at the end.

Types: `SyncDirection`, `UpdateMetadata`, `SetStateOptions`.

### Store

- `createStore({ doc, schema, initialState?, validateUpdates?=true, throwOnValidationError?=true, debug?=false })`
- Returns: `{ getState, setState, subscribe, getMirror, getLoro }`

### Reducer Helper

- `createReducer(handlers) -> (store) => dispatch(type, payload)`
- Handlers get an Immer draft; call `dispatch("addTodo", { text })` etc.

### Schema Builder

Expand Down Expand Up @@ -143,9 +132,9 @@ Trees are for hierarchical data where each node has a `data` map. The state shap
```ts
const node = schema.LoroMap({ name: schema.String({ required: true }) });
const s = schema({ tree: schema.LoroTree(node) });
const store = createStore({ doc: new LoroDoc(), schema: s });
const mirror = new Mirror({ doc: new LoroDoc(), schema: s });

await store.setState((st) => {
await mirror.setState((st) => {
st.tree.push({ data: { name: "root" }, children: [] });
});
```
Expand Down
4 changes: 1 addition & 3 deletions packages/core/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@
* Core mirroring functionality for syncing application state with Loro CRDT
*/

export * from "./mirror";
export * from "./state";
export * from "./utils";
export { Mirror, toNormalizedJson } from "./mirror";
149 changes: 0 additions & 149 deletions packages/core/src/core/state.ts

This file was deleted.

3 changes: 1 addition & 2 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

// Re-export all public APIs
export * from "./schema";
export * from "./core";
export * from "./constants";
export { Mirror, toNormalizedJson } from "./core";

// Default export
import * as schema from "./schema";
Expand Down
Loading