Skip to content

Commit fd81341

Browse files
committed
docs: update
1 parent 27aa95b commit fd81341

File tree

3 files changed

+90
-111
lines changed

3 files changed

+90
-111
lines changed

AGENTS.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,14 @@
3838

3939
- Peer deps: Keep `loro-crdt` versions aligned with peer requirements.
4040
- Node/Tooling: Use Node 18+ and pnpm. Do not commit `dist/`; builds are produced by TypeScript (tsc).
41+
42+
## Public API (loro-mirror)
43+
44+
- `Mirror(options: MirrorOptions<S>)`
45+
- `doc` (required), `schema?`, `initialState?`, `validateUpdates?`, `throwOnValidationError?`, `debug?`, `checkStateConsistency?`, `inferOptions?`.
46+
- Methods: `getState()`, `setState(updater, options?)`, `subscribe(cb)`, `dispose()`, `checkStateConsistency()`, `getContainerIds()`.
47+
- `SetStateOptions` supports `{ tags?: string | string[] }`; subscriber metadata includes `{ direction: SyncDirection; tags?: string[] }`.
48+
- `schema(definition, options?)` plus builders: `.String()`, `.Number()`, `.Boolean()`, `.Ignore()`, `.LoroMap()`, `.LoroMapRecord()`, `.LoroList()`, `.LoroMovableList()`, `.LoroText()`, `.LoroTree()`.
49+
- Runtime helpers from the schema module: `validateSchema`, `getDefaultValue`, `createValueFromSchema`, and type guards such as `isContainerSchema`, `isLoroMapSchema`, `isLoroListSchema`, `isLoroMovableListSchema`, `isLoroTextSchema`, `isLoroTreeSchema`, `isRootSchemaType`, `isListLikeSchema`.
50+
- Types re-exported at the root: `MirrorOptions`, `SetStateOptions`, `UpdateMetadata`, `InferType`, `InferInputType`, `InferContainerOptions`, `SchemaType`, `ContainerSchemaType`, `RootSchemaType`, `LoroMapSchema`, `LoroListSchema`, `LoroMovableListSchema`, `LoroTextSchemaType`, `LoroTreeSchema`, `SchemaOptions`, `ChangeKinds`, `MapChangeKinds`, `ListChangeKinds`, `MovableListChangeKinds`, `TreeChangeKinds`, `TextChangeKinds`, `SubscriberCallback`, `SyncDirection`.
51+
- Utilities: `toNormalizedJson(doc)` for tree normalization. `$cid` is a reserved property injected into mirrored map values but there is no exported constant.

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ const mySchema = schema({ outline: schema.LoroTree(node) });
358358
- **`validateUpdates`**: boolean (default `true`) – validate new state against schema.
359359
- **`throwOnValidationError`**: boolean (default `false`) – throw on invalid updates.
360360
- **`debug`**: boolean (default `false`) – log diffs and applied changes.
361+
- **`checkStateConsistency`**: boolean (default `false`) – after each `setState`, assert the in-memory state equals the normalized `LoroDoc` snapshot.
361362
- **`inferOptions`**: `{ defaultLoroText?: boolean; defaultMovableList?: boolean }` – influence container-type inference when inserting containers from plain values.
362363

363364
- `getState(): State`: Returns the current in-memory state view.
@@ -368,11 +369,14 @@ const mySchema = schema({ outline: schema.LoroTree(node) });
368369
- **`direction`**: `SyncDirection``FROM_LORO` when changes came from the doc, `TO_LORO` when produced locally, `BIDIRECTIONAL` for manual/initial syncs.
369370
- **`tags`**: `string[] | undefined` – tags provided via `setState`.
370371
- `dispose()`: Unsubscribe internal listeners and clear subscribers.
372+
- `checkStateConsistency()`: Manually trigger the consistency assertion described above.
373+
- `getContainerIds()`: Returns the set of registered Loro container IDs (advanced debugging aid).
371374

372375
#### Notes
373376

374377
- **Lists and IDs**: If your list schema provides an `idSelector`, list updates use minimal add/remove/update/move operations; otherwise index-based diffs are applied.
375378
- **Container inference**: When schema is missing/ambiguous for a field, the mirror infers container types from values. `inferOptions.defaultLoroText` makes strings become `LoroText`; `inferOptions.defaultMovableList` makes arrays become `LoroMovableList`.
379+
- **Consistency checks**: Enabling `checkStateConsistency` (or calling the method directly) is useful while developing or writing tests; it throws if Mirror state diverges from the normalized document snapshot.
376380

377381
### Types
378382

api.md

Lines changed: 75 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,69 @@
1-
# Loro Mirror — API Reference
2-
3-
This is the complete API reference for the `loro-mirror` package. It covers the public classes, functions, types, and utilities exported from the package entry and includes practical tips for effective usage.
4-
5-
Contents
6-
7-
- Installation & Imports
1+
# Loro Mirror — API Reference
2+
3+
This is the complete API reference for the `loro-mirror` package. It covers the public classes, functions, types, and utilities exported from the package entry and includes practical tips for effective usage.
4+
5+
Contents
6+
7+
- Installation & Imports
88
- Core: Mirror
9-
- Schema Builder
10-
- Validation & Defaults
11-
- Utilities (Advanced)
12-
- Types & Constants
13-
- Tips & Recipes
14-
15-
## Installation & Imports
16-
17-
- Install: `npm install loro-mirror loro-crdt`
9+
- Schema Builder
10+
- Validation & Defaults
11+
- Utilities (Advanced)
12+
- Types & Constants
13+
- Tips & Recipes
14+
15+
## Installation & Imports
16+
17+
- Install: `npm install loro-mirror loro-crdt`
1818
- Import styles:
1919
- Named imports (recommended): `import { Mirror, schema } from "loro-mirror"`
20-
- Default (convenience bundle of `schema` + `core`): `import loroMirror from "loro-mirror"`
21-
20+
- Default (convenience bundle of `schema` + `core`): `import loroMirror from "loro-mirror"`
21+
2222
## Core: Mirror
23-
24-
### Mirror
25-
26-
- Constructor: `new Mirror(options)`
27-
- `options: MirrorOptions<S>`
28-
- `doc: LoroDoc` — the Loro document to sync with
29-
- `schema?: S` — root schema (enables validation, typed defaults)
23+
24+
### Mirror
25+
26+
- Constructor: `new Mirror(options)`
27+
- `options: MirrorOptions<S>`
28+
- `doc: LoroDoc` — the Loro document to sync with
29+
- `schema?: S` — root schema (enables validation, typed defaults)
3030
- `initialState?: Partial<InferInputType<S>>` — shallow overlay onto doc snapshot and schema defaults (does not write to Loro)
31-
- `validateUpdates?: boolean` (default `true`) — validate on `setState`
32-
- `throwOnValidationError?: boolean` (default `false`) — throw on schema validation errors
33-
- `debug?: boolean` — verbose logging to console for diagnostics
34-
- `checkStateConsistency?: boolean` (default `false`) — deep checks in-memory state equals normalized `doc` JSON after `setState`
35-
- `inferOptions?: { defaultLoroText?: boolean; defaultMovableList?: boolean }` — inference hints when no schema covers a field
36-
37-
- Methods
38-
- `getState(): InferType<S>` — returns the current mirror state (immutable snapshot)
31+
- `validateUpdates?: boolean` (default `true`) — validate on `setState`
32+
- `throwOnValidationError?: boolean` (default `false`) — throw on schema validation errors
33+
- `debug?: boolean` (default `false`) — verbose logging to console for diagnostics
34+
- `checkStateConsistency?: boolean` (default `false`) — verify after each `setState` that in-memory state matches the normalized `LoroDoc`
35+
- `inferOptions?: { defaultLoroText?: boolean; defaultMovableList?: boolean }` — inference hints when no schema covers a field
36+
37+
- Methods
38+
- `getState(): InferType<S>` — returns the current mirror state (immutable snapshot)
3939
- `setState(updater, options?): void`
4040
- Synchronous; the state, validation, and subscriber notifications all finish before `setState` returns.
41-
- `updater` supports both styles:
42-
- Mutate a draft: `(draft: InferType<S>) => void`
43-
- Return a new object: `(prev: Readonly<InferInputType<S>>) => InferInputType<S>`
44-
- Shallow partial: `Partial<InferInputType<S>>`
45-
- `options?: { tags?: string | string[] }` — tags surface in subscriber metadata
46-
- `subscribe((state, metadata) => void): () => void`
47-
- `metadata: { direction: SyncDirection; tags?: string[] }`
48-
- Returns an unsubscribe function
49-
- `dispose(): void` — removes all internal subscriptions and listeners
50-
- `checkStateConsistency(): void` — throws if `state` diverges from normalized `doc` JSON (use with `checkStateConsistency: true`)
51-
52-
- Behavior & Notes
53-
- Sync directions:
54-
- `FROM_LORO` — changes applied from the Loro document
55-
- `TO_LORO` — changes produced by `setState`
56-
- Mirror ignores events with origin `"to-loro"` to prevent feedback loops.
57-
- Initial state precedence: defaults (from schema) → `doc` snapshot (normalized) → hinted shapes from `initialState` (no writes to Loro).
58-
- Trees: mirror state uses `{ id: string; data: object; children: Node[] }`. Loro tree `meta` is normalized to `data`.
59-
- `$cid` on maps: Mirror injects a read‑only `$cid` field into every LoroMap shape in state. It equals the Loro container ID, is not written back to Loro, and is ignored by diffs.
60-
- Inference: with no schema, Mirror can infer containers from values; configure via `inferOptions`.
61-
62-
- Example
63-
64-
```ts
41+
- `updater` supports both styles:
42+
- Mutate a draft: `(draft: InferType<S>) => void`
43+
- Return a new object: `(prev: Readonly<InferInputType<S>>) => InferInputType<S>`
44+
- Shallow partial: `Partial<InferInputType<S>>`
45+
- `options?: { tags?: string | string[] }` — tags surface in subscriber metadata
46+
- `subscribe((state, metadata) => void): () => void`
47+
- `metadata: { direction: SyncDirection; tags?: string[] }`
48+
- Returns an unsubscribe function
49+
- `dispose(): void` — removes all internal subscriptions and listeners
50+
- `checkStateConsistency(): void` — manually triggers the consistency assertion described above
51+
- `getContainerIds(): ContainerID[]` — advanced helper that lists registered Loro container IDs for debugging
52+
53+
- Behavior & Notes
54+
- Sync directions:
55+
- `FROM_LORO` — changes applied from the Loro document
56+
- `TO_LORO` — changes produced by `setState`
57+
- `BIDIRECTIONAL` — manual/initial sync context
58+
- Mirror ignores events with origin `"to-loro"` to prevent feedback loops.
59+
- Initial state precedence: defaults (from schema) → `doc` snapshot (normalized) → hinted shapes from `initialState` (no writes to Loro).
60+
- Trees: mirror state uses `{ id: string; data: object; children: Node[] }`. Loro tree `meta` is normalized to `data`.
61+
- `$cid` on maps: Mirror injects a read-only `$cid` field into every LoroMap shape in state. It equals the Loro container ID, is not written back to Loro, and is ignored by diffs.
62+
- Inference: with no schema, Mirror can infer containers from values; configure via `inferOptions`.
63+
64+
#### Example
65+
66+
```ts
6567
import { Mirror, schema } from "loro-mirror";
6668
import { LoroDoc } from "loro-crdt";
6769

@@ -96,11 +98,11 @@
9698
- `definition: { [key: string]: ContainerSchemaType }`
9799
- `options?: SchemaOptions`
98100

99-
- Primitives
100-
- `schema.String<T = string>(options?)`
101-
- `schema.Number(options?)`
102-
- `schema.Boolean(options?)`
103-
- `schema.Ignore<T = unknown>(options?)` — present in state, ignored for Loro diffs/validation
101+
- Primitives
102+
- `schema.String<T = string>(options?)`
103+
- `schema.Number(options?)`
104+
- `schema.Boolean(options?)`
105+
- `schema.Ignore(options?)` — present in state, ignored for Loro diffs/validation
104106

105107
- Containers
106108
- `schema.LoroMap(definition)`
@@ -156,54 +158,17 @@
156158
- `createValueFromSchema(schema, value): InferType<S>`
157159
- Casts/wraps a value into the shape expected by a schema (primitives pass through).
158160

159-
## Utilities (Advanced)
160-
161-
The following helpers are exported for advanced use, tooling, or tests. Most apps do not need them directly.
162-
163-
- Equality & JSON
164-
- `deepEqual(a, b): boolean` — deep structural equality
165-
- `toNormalizedJson(doc: LoroDoc): unknown``doc.toJSON()` with tree `meta` normalized to `data`
166-
167-
- Path helpers
168-
- `getPathValue(obj, path: string[]): unknown` — read nested path
169-
- `setPathValue(obj, path: string[], value): void` — write nested path (mutates the object)
170-
171-
- Container detection & IDs
172-
- `valueIsContainer(v): { cid: string; value: unknown }` — check values from `doc.getDeepValueWithID()`
173-
- `valueIsContainerOfType(v, suffix: string): boolean` — e.g. `":Text"`, `":Map"`, `":List"`, `":MovableList"`
174-
- `containerIdToContainerType(id): ContainerType | undefined`
175-
- `getRootContainerByType(doc, key, type): Container`
176-
- `isTreeID(id: unknown): boolean` — test if a string looks like a Loro `TreeID` (e.g. `"0@1"`)
177-
178-
- Inference helpers
179-
- `schemaToContainerType(schema): ContainerType | undefined`
180-
- `tryInferContainerType(value, inferOptions?): ContainerType | undefined`
181-
- `inferContainerTypeFromValue(value, inferOptions?): "loro-map" | "loro-list" | "loro-text" | "loro-movable-list" | undefined`
182-
- `isValueOfContainerType(type, value): boolean`
183-
184-
- Guards & shapes
185-
- `isObject(v): v is Record<string, unknown>`
186-
- `isObjectLike(v): v is Record<string, unknown>`
187-
- `isArrayLike(v): v is unknown[]`
188-
- `isStringLike(v): v is string`
189-
- `isStateAndSchemaOfType(values, stateGuard, schemaGuard)` — generic narrow helper
190-
- Schema guards
191-
- `isContainerSchema(schema?): schema is ContainerSchemaType`
192-
- `isRootSchemaType(schema): schema is RootSchemaType`
193-
- `isLoroMapSchema(schema): schema is LoroMapSchema`
194-
- `isLoroListSchema(schema): schema is LoroListSchema`
195-
- `isListLikeSchema(schema): schema is LoroListSchema | LoroMovableListSchema`
196-
- `isLoroMovableListSchema(schema): schema is LoroMovableListSchema`
197-
- `isLoroTextSchema(schema): schema is LoroTextSchemaType`
198-
- `isLoroTreeSchema(schema): schema is LoroTreeSchema`
199-
200-
- Change helpers (primarily internal)
201-
- `insertChildToMap(containerId, key, value): Change` — produce a map change (container‑aware)
202-
- `tryUpdateToContainer(change, enable, schema?): Change` — upgrade an insert/set to a container operation based on schema/value
203-
204-
## Types & Constants
205-
206-
- `SyncDirection` — enum: `FROM_LORO`, `TO_LORO`, `BIDIRECTIONAL`
161+
## Utilities (Advanced)
162+
163+
Most applications will not need the low-level helpers below, but they are part of the published surface for tooling and testing.
164+
165+
- `toNormalizedJson(doc: LoroDoc): unknown` — returns `doc.toJSON()` with tree `meta` data normalized into `data` so it matches Mirror state.
166+
- Schema guards exported from `schema/validators`:
167+
- `isContainerSchema`, `isRootSchemaType`, `isLoroMapSchema`, `isLoroListSchema`, `isListLikeSchema`, `isLoroMovableListSchema`, `isLoroTextSchema`, `isLoroTreeSchema`
168+
169+
## Types & Constants
170+
171+
- `SyncDirection` — enum: `FROM_LORO`, `TO_LORO`, `BIDIRECTIONAL`
207172
- `MirrorOptions<S>` — constructor options for `Mirror`
208173
- `SetStateOptions``{ tags?: string | string[] }`
209174
- `UpdateMetadata``{ direction: SyncDirection; tags?: string[] }`
@@ -213,7 +178,6 @@
213178
- `SubscriberCallback<T>``(state: T, metadata: UpdateMetadata) => void`
214179
- Change types (advanced): `ChangeKinds`, `Change`, `MapChangeKinds`, `ListChangeKinds`, `MovableListChangeKinds`, `TreeChangeKinds`, `TextChangeKinds`
215180
- Schema types: `SchemaType`, `ContainerSchemaType`, `RootSchemaType`, `LoroMapSchema`, `LoroListSchema`, `LoroMovableListSchema`, `LoroTextSchemaType`, `LoroTreeSchema`, `SchemaOptions`, …
216-
- `CID_KEY` — the literal string `"$cid"` used by mirrored maps
217181

218182
## Tips & Recipes
219183

0 commit comments

Comments
 (0)