mobx-keystone-yjs
Version:
Yjs bindings for mobx-keystone
52 lines (47 loc) • 1.91 kB
text/typescript
import * as Y from "yjs"
import { failure } from "../utils/error"
import { getOrCreateYjsCollectionAtom } from "../utils/getOrCreateYjsCollectionAtom"
/**
* Resolves a path within a Yjs object structure.
* Returns the Yjs container at the specified path.
*
* When a Y.Text is encountered during path resolution (either at the start
* or mid-path), it is returned immediately since Y.Text doesn't support
* nested path traversal.
*
* @param yjsObject The root Yjs object
* @param path Array of keys/indices to traverse
* @returns The Yjs container at the path, or Y.Text if encountered during traversal
*/
export function resolveYjsPath(
yjsObject: Y.Map<unknown> | Y.Array<unknown> | Y.Text,
path: readonly (string | number)[]
): unknown {
let currentYjsObject: unknown = yjsObject
let i = -1
for (const pathPart of path) {
i++
// If we encounter a Y.Text during path resolution, return it immediately.
// Y.Text objects don't support nested path traversal, and their updates
// are handled separately by YjsTextModel's own synchronization mechanism.
if (currentYjsObject instanceof Y.Text) {
return currentYjsObject
}
if (currentYjsObject instanceof Y.Map) {
getOrCreateYjsCollectionAtom(currentYjsObject).reportObserved()
const key = String(pathPart)
currentYjsObject = currentYjsObject.get(key)
} else if (currentYjsObject instanceof Y.Array) {
getOrCreateYjsCollectionAtom(currentYjsObject).reportObserved()
const key = Number(pathPart)
currentYjsObject = currentYjsObject.get(key)
} else {
throw failure(
`Y.Map or Y.Array was expected at path ${JSON.stringify(
path.slice(0, i)
)} in order to resolve path ${JSON.stringify(path)}, but got ${currentYjsObject} instead`
)
}
}
return currentYjsObject
}