fix(core): reject root-level primitives in initialState#83
Merged
Conversation
LoroDoc only stores container types (Map/List/MovableList/Text/Tree)
at the document root, but Mirror previously accepted root-level
primitives (e.g. `{ version: 0 }`) in initialState and silently kept
them in memory while never writing them to the doc. This caused
`mirror.getState()` to drift from `doc.toJSON()`.
Now reject primitives both at compile time (via a `RootInitialValue`
constraint on `initialState`) and at runtime (clear error pointing
users to wrap the value in a root LoroMap). `null`/`undefined` are
still accepted as "absent".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The jotai LoroMirrorAtomConfig and react UseLoroStoreOptions redeclare initialState with a looser type than MirrorOptions, which broke the build after the core constraint was tightened. Mirror the RootInitialValue intersection in both wrappers and re-export the type from loro-mirror so consumers can reuse it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Mirrorpreviously accepted root-level primitives ininitialState(e.g.{ version: 0 }) and silently kept them in memory while never persisting them to the doc — makingmirror.getState()drift fromdoc.toJSON().RootInitialValueconstraint oninitialState, and at runtime with a clear error that points users to wrap the value in a rootLoroMap(e.g. ametamap).null/undefinedat the root are still treated as "absent" and silently skipped.Repro (now fails fast)
Test plan
packages/core/tests/mirror.test.tscovering: bare number, bare boolean, primitive under a (mistyped) schema, and null/undefined skip-behavior.@ts-expect-errorto lock in the TypeScript rejection of root-levelnumber/boolean.🤖 Generated with Claude Code