Documentation
¶
Overview ¶
Package ygo is a pure-Go port of the Yjs CRDT framework.
ygo is binary-protocol compatible with the npm yjs package (V1 update encoding), allowing JavaScript clients to synchronize seamlessly with Go servers and vice versa.
Pure-Go means no CGO, so gomobile bind works for iOS/Android targets.
Status: pre-alpha. Public API is unstable.
See https://github.com/Deln0r/ygo for documentation and examples.
Example ¶
Example is the basic shape: create a document, edit a shared type inside a write transaction, and read the value back.
package main
import (
"fmt"
"github.com/Deln0r/ygo"
)
func main() {
doc := ygo.NewDoc()
settings := ygo.NewMap(doc, "settings")
txn := doc.WriteTxn()
settings.Set(txn, "theme", "dark")
settings.Set(txn, "fontSize", int64(14))
txn.Commit()
fmt.Println(settings.Get("theme"))
fmt.Println(settings.Get("fontSize"))
}
Output: dark 14
Example (Array) ¶
Example_array shows the shared Array: an ordered sequence you append to and read positionally.
package main
import (
"fmt"
"github.com/Deln0r/ygo"
)
func main() {
doc := ygo.NewDoc()
todo := ygo.NewArray(doc, "todo")
txn := doc.WriteTxn()
todo.Push(txn, "buy milk", "write code")
txn.Commit()
fmt.Println(todo.Len())
fmt.Println(todo.Get(0))
fmt.Println(todo.Get(1))
}
Output: 2 buy milk write code
Example (Sync) ¶
Example_sync shows the core CRDT property: two documents that never talked to each other each apply the other's update and converge on the same merged state, independent of order.
package main
import (
"fmt"
"github.com/Deln0r/ygo"
)
func main() {
// Peer A sets a title on its copy.
a := ygo.NewDoc()
am := ygo.NewMap(a, "doc")
wa := a.WriteTxn()
am.Set(wa, "title", "Hello")
wa.Commit()
// Peer B sets a different key on its own copy.
b := ygo.NewDoc()
bm := ygo.NewMap(b, "doc")
wb := b.WriteTxn()
bm.Set(wb, "author", "Ada")
wb.Commit()
// Exchange full-state updates and apply each to the other.
if err := ygo.ApplyUpdate(a, ygo.EncodeStateAsUpdate(b)); err != nil {
panic(err)
}
if err := ygo.ApplyUpdate(b, ygo.EncodeStateAsUpdate(a)); err != nil {
panic(err)
}
// Both converge to the same merged state.
fmt.Println(am.Get("title"), am.Get("author"))
fmt.Println(bm.Get("title"), bm.Get("author"))
}
Output: Hello Ada Hello Ada
Example (Text) ¶
Example_text shows the shared Text: a collaborative string edited by index. Inserts commute so concurrent edits converge.
package main
import (
"fmt"
"github.com/Deln0r/ygo"
)
func main() {
doc := ygo.NewDoc()
note := ygo.NewText(doc, "note")
txn := doc.WriteTxn()
_ = note.Insert(txn, 0, "world")
_ = note.Insert(txn, 0, "hello ")
txn.Commit()
fmt.Println(note.String())
}
Output: hello world
Example (Undo) ¶
Example_undo shows the built-in UndoManager: track a shared type, edit it, then step backward and forward through the edit history.
package main
import (
"fmt"
"github.com/Deln0r/ygo"
)
func main() {
doc := ygo.NewDoc()
m := ygo.NewMap(doc, "doc")
undo := ygo.NewUndoManager(doc, m)
txn := doc.WriteTxn()
m.Set(txn, "title", "draft")
txn.Commit()
fmt.Println(m.Get("title"))
undo.Undo()
fmt.Println(m.Has("title"))
undo.Redo()
fmt.Println(m.Get("title"))
}
Output: draft false draft
Index ¶
- Constants
- Variables
- func ApplyUpdate(d *Doc, raw []byte) error
- func ApplyUpdateV2(d *Doc, raw []byte) error
- func DiffUpdate(update, remoteSV []byte) ([]byte, error)
- func EncodeDiff(d *Doc, remoteSVBytes []byte) ([]byte, error)
- func EncodeDiffV2(d *Doc, remoteSVBytes []byte) ([]byte, error)
- func EncodeRelativePosition(rpos RelativePosition) ([]byte, error)
- func EncodeSnapshot(s Snapshot) []byte
- func EncodeStateAsUpdate(d *Doc) []byte
- func EncodeStateAsUpdateV2(d *Doc) []byte
- func EncodeStateVector(d *Doc) []byte
- func EncodeStateVectorFromUpdate(update []byte) ([]byte, error)
- func EqualSnapshots(a, b Snapshot) bool
- func HasPending(d *Doc) bool
- func MergeUpdates(updates [][]byte) ([]byte, error)
- func MergeUpdatesV2(updates [][]byte) ([]byte, error)
- func MissingSV(d *Doc) []byte
- type AbsolutePosition
- type Array
- type ArrayDeltaOp
- type ArrayEvent
- type Attrs
- type Awareness
- type Branch
- type ChunkKind
- type DeltaOp
- type Doc
- type KeyChange
- type Map
- type MapEvent
- type Options
- type RelativePosition
- type SharedType
- type Snapshot
- type SubdocsEvent
- type Text
- type TextEvent
- type Transaction
- type TransactionMut
- type UndoManager
- type UndoManagerOptions
- type UndoScope
- type XmlElement
- type XmlFragment
- type XmlText
Examples ¶
Constants ¶
const ( ChunkString = types.ChunkString ChunkEmbed = types.ChunkEmbed )
Text.Range emits chunks of either of these kinds.
const DefaultAwarenessTimeout = awareness.DefaultTimeout
DefaultAwarenessTimeout is the y-protocols convention for stale awareness-entry eviction (30 seconds). Pass to Awareness.SweepOutdated.
const MaxClientID = doc.MaxClientID
MaxClientID is the upper bound on Doc.ClientID values (2^53 - 1, matching JS Yjs's safe-integer range).
const Version = "0.0.0-dev"
Version is the current ygo version.
Variables ¶
var ErrSnapshotGC = errors.New("ygo: RestoreSnapshot requires the source Doc to have GC disabled (NewDocWithOptions with DisableGC: true)")
ErrSnapshotGC is returned by RestoreSnapshot when the source Doc has garbage collection enabled, which can discard content a snapshot needs to reconstruct.
Functions ¶
func ApplyUpdate ¶
ApplyUpdate decodes raw and integrates it into d. Items whose dependencies the local store has not yet seen queue in the per-doc pending buffer and drain automatically on subsequent ApplyUpdate calls that satisfy them.
Use HasPending / MissingSV to inspect the queue.
func ApplyUpdateV2 ¶
ApplyUpdateV2 decodes V2 wire bytes and integrates them into d. Pending-buffer semantics identical to ApplyUpdate (V1) — items missing causal dependencies queue silently and drain on subsequent ApplyUpdate / ApplyUpdateV2 calls.
V1 and V2 are NOT wire-interchangeable. Calling ApplyUpdateV2 on V1 bytes (or ApplyUpdate on V2 bytes) is undefined behaviour — either errors loudly or yields a semantically-wrong Update that fails integrate. Per the docs there is no autodetect; the caller must know which version they have via the surrounding transport metadata.
func DiffUpdate ¶ added in v1.13.0
DiffUpdate returns the part of a V1 update that a peer identified by remoteSV (a wire-encoded state vector, e.g. from EncodeStateVector or EncodeStateVectorFromUpdate) is missing. Mirrors yjs diffUpdate: trim a stored update before sending it to a peer that already has part of it.
It reconstructs the update's state and diffs against remoteSV, emitting whole blocks like EncodeDiff. A full update that ygo produces (EncodeStateAsUpdate / MergeUpdates) is self-contained and fully covered; a diff (from EncodeDiff) or a hand-crafted update whose block dependencies are absent drops those unresolved blocks.
func EncodeDiff ¶
EncodeDiff returns the wire-encoded V1 update covering the blocks d has that the remote (per remoteSVBytes) does not. A nil remoteSVBytes is treated as the empty SV — emit everything.
remoteSVBytes is the V1 wire-encoded form of the remote's state vector (the same shape EncodeStateVector produces).
func EncodeDiffV2 ¶
EncodeDiffV2 is the V2 analogue of EncodeDiff. State-vector argument shape is identical (still V1 wire-encoded SV); only the outgoing update bytes use the V2 column layout.
func EncodeRelativePosition ¶ added in v1.1.0
func EncodeRelativePosition(rpos RelativePosition) ([]byte, error)
EncodeRelativePosition serialises rpos to the yjs binary form (byte-compatible with Y.encodeRelativePosition). Errors only on a zero-value rpos with no anchor set.
func EncodeSnapshot ¶ added in v0.10.0
EncodeSnapshot returns the V1 wire encoding of s, byte-compatible with yjs `Y.encodeSnapshot`.
func EncodeStateAsUpdate ¶
EncodeStateAsUpdate returns the wire-encoded V1 update carrying the doc's full state. Apply to a fresh peer doc to bring it up to speed in one shot; same bytes interoperate with JS Yjs's Y.encodeStateAsUpdate.
func EncodeStateAsUpdateV2 ¶
EncodeStateAsUpdateV2 returns the wire-encoded V2 update carrying the doc's full state. V2 is the column-oriented alternative wire format used by Y.encodeStateAsUpdateV2 / Hocuspocus-V2 paths and some adopters' on-disk persistence layers (y-leveldb, y-indexeddb, SQLite/Postgres Hocuspocus adapters).
V1 and V2 are NOT wire-interchangeable — see ApplyUpdateV2.
func EncodeStateVector ¶
EncodeStateVector returns the wire-encoded V1 state vector of d. Sync-protocol callers send this to peers as "here's what I have; send me everything else."
func EncodeStateVectorFromUpdate ¶ added in v1.13.0
EncodeStateVectorFromUpdate computes the state vector a V1 update advances to, directly from the update bytes without reconstructing a document. Mirrors yjs encodeStateVectorFromUpdate: index or diff stored updates server-side without loading the full document into memory.
func EqualSnapshots ¶ added in v0.10.0
EqualSnapshots reports whether two snapshots are identical.
func HasPending ¶
HasPending reports whether d has any queued items awaiting causal dependencies.
func MergeUpdates ¶
MergeUpdates decodes every blob in updates in order, applies them to a fresh Doc, and returns a single V1 update blob equivalent to the merged state. Returns nil for an empty input.
Used by persistence layers for compaction (Flush) and by transports that want to batch-coalesce updates before sending.
func MergeUpdatesV2 ¶ added in v1.13.0
MergeUpdatesV2 is the V2 counterpart of MergeUpdates: it coalesces V2 update blobs into a single equivalent V2 update. Returns nil for an empty input. Like MergeUpdates it reconstructs then re-encodes, so blocks whose causal dependencies are absent across the merged set are dropped rather than preserved behind Skip blocks (as yjs mergeUpdatesV2 would); ygo-produced full updates are self-contained and unaffected.
func MissingSV ¶
MissingSV returns the wire-encoded V1 state vector identifying the clocks d needs to receive in order to drain its pending buffer. An empty result means the queue is empty.
Sync-protocol callers send this to peers as a re-fetch request: "I am stuck on items that need updates past this clock."
Types ¶
type AbsolutePosition ¶ added in v1.1.0
type AbsolutePosition = types.AbsolutePosition
AbsolutePosition is a resolved RelativePosition: the shared type's branch and the current numeric index within it.
func CreateAbsolutePositionFromRelativePosition ¶ added in v1.1.0
func CreateAbsolutePositionFromRelativePosition(d *Doc, rpos RelativePosition) (AbsolutePosition, bool)
CreateAbsolutePositionFromRelativePosition resolves rpos against the current state of d. ok is false when the anchor refers to state this replica has not yet seen or to a garbage-collected range.
Acquires the doc's locks internally; calling it while holding an open Transaction / TransactionMut on the same doc from the same goroutine deadlocks (Go RWMutex is not re-entrant).
type ArrayDeltaOp ¶ added in v1.2.0
type ArrayDeltaOp = types.ArrayDeltaOp
ArrayDeltaOp is one op of an array change delta: exactly one of Insert (values), Delete (count), or Retain (count) is set.
type ArrayEvent ¶ added in v1.2.0
type ArrayEvent = types.ArrayEvent
ArrayEvent is delivered to Array observers (Array.Observe) after a transaction that changed the array. Delta is the Quill-style change description. Semantic parity with yjs YArrayEvent.
type Attrs ¶
Attrs is the format-attribute map used by Text's rich-text API and DeltaOp. Keys are arbitrary strings; values are JSON-serializable scalars. A nil value clears the attribute on the affected range.
type Awareness ¶
Awareness tracks per-client ephemeral state (cursors, names, selections). Independent of any Doc; the local clientID is passed at construction. Embedders typically pair an Awareness with a Doc and use d.ClientID() as the awareness clientID.
func NewAwareness ¶
NewAwareness returns a fresh Awareness for the given local clientID. Use d.ClientID() to keep the awareness layer in sync with the doc.
type Branch ¶
Branch is the low-level shared-data container the types layer wraps. Most callers should use the typed constructors (NewMap, NewArray, NewText, NewXmlFragment) rather than building Branches directly. Re-exported here for advanced cases (custom shared-type implementations, observability code).
type DeltaOp ¶
DeltaOp is one Quill-style delta operation produced by Text.ToDelta and (future) consumed by Text.ApplyDelta.
type Doc ¶
Doc is a single CRDT replica — the local view of a collaborative document. Construct with NewDoc; mutate via WriteTxn; read via ReadTxn. See the doc-comment on the underlying type for the full concurrency contract.
func NewDoc ¶
func NewDoc() *Doc
NewDoc returns a fresh Doc with default options and a random client identifier.
func NewDocWithOptions ¶
NewDocWithOptions returns a fresh Doc with the given options.
func RestoreSnapshot ¶ added in v0.10.0
RestoreSnapshot reconstructs the document state that d had at the moment snap was taken, returning it as a new Doc. Byte-equivalent to yjs `Y.createDocFromSnapshot`.
d must have been created with GC disabled (ygo.NewDocWithOptions with DisableGC: true); otherwise deleted content the snapshot references may have been collected and RestoreSnapshot returns ErrSnapshotGC. The returned Doc also has GC disabled so it can itself be snapshotted.
The source Doc is not logically changed (the reconstruction may split blocks internally, which is transparent to readers).
type KeyChange ¶ added in v1.2.0
KeyChange describes one map key's change in a MapEvent: Action is "add", "update", or "delete"; OldValue is the prior value (nil for "add").
type Map ¶
Shared-type wrappers — re-exported from internal/types.
func NewMap ¶
NewMap, NewArray, NewText, NewXmlFragment return wrappers bound to the root branch with the given name in d. The branch is lazily created on first call; subsequent calls with the same name return wrappers pointing at the same underlying state.
Per-branch type discipline: a branch should be used as ONE type (Map OR Array OR Text OR XML). Mixing types on the same root branch produces undefined behaviour.
type MapEvent ¶ added in v1.2.0
MapEvent is delivered to Map observers (Map.Observe) after a transaction that changed the map, describing which keys changed and how. Byte-for-byte semantic parity with yjs YMapEvent.
type Options ¶
Options bundles per-Doc settings (deterministic ClientID, GC disable). The zero value is the recommended configuration.
type RelativePosition ¶ added in v1.1.0
type RelativePosition = types.RelativePosition
RelativePosition is a cursor/selection anchor attached to the document model rather than a numeric index, so it stays on the same logical character as concurrent edits land. Create one with CreateRelativePositionFromTypeIndex, ship it between peers with EncodeRelativePosition (byte-compatible with Y.encodeRelativePosition), and resolve it back to an index with CreateAbsolutePositionFromRelativePosition.
func CreateRelativePositionFromTypeIndex ¶ added in v1.1.0
func CreateRelativePositionFromTypeIndex(t SharedType, index uint64, assoc int64) (RelativePosition, error)
CreateRelativePositionFromTypeIndex anchors index within the shared type t (any wrapper: Map, Array, Text, Xml*). index counts UTF-16 code units for Text, elements for Array. assoc >= 0 sticks to the character after the position (default for cursors), assoc < 0 to the character before it.
func DecodeRelativePosition ¶ added in v1.1.0
func DecodeRelativePosition(buf []byte) (RelativePosition, error)
DecodeRelativePosition parses the yjs binary form.
type SharedType ¶ added in v1.1.0
type SharedType = UndoScope
SharedType is any shared-type wrapper (Map, Array, Text, XmlFragment, XmlElement, XmlText). Alias of UndoScope; both name the same one-method interface.
type Snapshot ¶ added in v0.10.0
Snapshot is a point-in-time marker of a document's history (the deleted ID ranges plus per-client clock heads as of the snapshot). Encode it with EncodeSnapshot for storage; reconstruct the document state it captured with RestoreSnapshot (see the Snapshot doc).
For time-travel to work, create the doc with GC disabled (ygo.NewDocWithOptions with DisableGC) so deleted content the snapshot references is retained.
func CreateSnapshot ¶ added in v0.10.0
CreateSnapshot captures the current state of d as a Snapshot. Byte-compatible with yjs `Y.snapshot(doc)`.
func DecodeSnapshot ¶ added in v0.10.0
DecodeSnapshot parses a V1 snapshot produced by EncodeSnapshot or yjs `Y.encodeSnapshot`.
type SubdocsEvent ¶ added in v1.0.0
type SubdocsEvent = doc.SubdocsEvent
SubdocsEvent carries the subdocument lifecycle changes of one transaction: GUIDs added, removed, and loaded. Observe with Doc.OnSubdocs.
type TextEvent ¶ added in v1.2.0
TextEvent is delivered to Text observers (Text.Observe) after a transaction that changed the text. Delta is the formatting-aware Quill-style change description. Semantic parity with yjs YTextEvent.
type Transaction ¶
type Transaction = doc.Transaction
Transaction is a read-only transaction holding the doc's read lock for its lifetime. Created by Doc.ReadTxn; released by Close.
type TransactionMut ¶
type TransactionMut = doc.TransactionMut
TransactionMut is a write transaction holding the doc's write lock. Created by Doc.WriteTxn; released by Commit.
type UndoManager ¶ added in v0.10.0
type UndoManager = undo.UndoManager
UndoManager records local mutations under a scope of shared types and reverses them with Undo / Redo. It subscribes to the doc's transaction lifecycle; close it with Close when no longer needed.
Scope is given as the typed wrappers themselves (a Map, Array, Text, or XML type). Only mutations under one of the scoped types, made by a tracked origin (local edits by default), are captured. Bursty edits within the capture-timeout window collapse into a single undo step.
m := ygo.NewMap(d, "settings") um := ygo.NewUndoManager(d, m) defer um.Close() // ... edits to m ... um.Undo() // reverts the last captured step
func NewUndoManager ¶ added in v0.10.0
func NewUndoManager(d *Doc, scope ...UndoScope) *UndoManager
NewUndoManager creates an UndoManager on d watching the given scope of shared types. At least one scope type is required.
um := ygo.NewUndoManager(d, myMap, myArray)
func NewUndoManagerWithOptions ¶ added in v0.10.0
func NewUndoManagerWithOptions(d *Doc, opts UndoManagerOptions, scope ...UndoScope) *UndoManager
NewUndoManagerWithOptions is NewUndoManager with explicit options.
type UndoManagerOptions ¶ added in v0.10.0
UndoManagerOptions configures an UndoManager. A zero value selects the defaults: 500 ms capture timeout, track local (nil) origin only.
type UndoScope ¶ added in v0.10.0
type UndoScope interface {
Branch() *Branch
}
UndoScope is anything an UndoManager can watch. Every shared-type wrapper (Map, Array, Text, XmlFragment, XmlElement, XmlText) satisfies it via its Branch method.
type XmlElement ¶
type XmlElement = types.XmlElement
Shared-type wrappers — re-exported from internal/types.
func NewXmlElement ¶
func NewXmlElement(d *Doc, name string) *XmlElement
NewXmlElement wraps a branch as an XmlElement. Typically used for root-level XML where the branch was constructed via d.Branch(name); nested elements should be constructed via XmlFragment.InsertXmlElement / XmlElement.InsertXmlElement which set TypeRef and Name automatically.
type XmlFragment ¶
type XmlFragment = types.XmlFragment
Shared-type wrappers — re-exported from internal/types.
func NewXmlFragment ¶
func NewXmlFragment(d *Doc, name string) *XmlFragment
Directories
¶
| Path | Synopsis |
|---|---|
|
Package benchmarks ports the dmonad/crdt-benchmarks B1-B4 workload suite to ygo.
|
Package benchmarks ports the dmonad/crdt-benchmarks B1-B4 workload suite to ygo. |
|
Package client is a Yjs sync provider over WebSocket: the Go equivalent of y-websocket's WebsocketProvider, compatible with yserve, Hocuspocus, and the reference y-websocket server.
|
Package client is a Yjs sync provider over WebSocket: the Go equivalent of y-websocket's WebsocketProvider, compatible with yserve, Hocuspocus, and the reference y-websocket server. |
|
cmd
|
|
|
gen-go-fixtures
command
gen-go-fixtures generates reverse-direction wire-format fixtures: Go encodes Doc state via EncodeStateAsUpdate (V1) and EncodeStateAsUpdateV2, captures the bytes + expected state, and writes them as JSON.
|
gen-go-fixtures generates reverse-direction wire-format fixtures: Go encodes Doc state via EncodeStateAsUpdate (V1) and EncodeStateAsUpdateV2, captures the bytes + expected state, and writes them as JSON. |
|
ygo-server
command
Command ygo-server is the legacy name of the stand-alone WebSocket sync server for ygo documents.
|
Command ygo-server is the legacy name of the stand-alone WebSocket sync server for ygo documents. |
|
yserve
command
Command yserve is a self-hosted Yjs sync server in a single static binary: a drop-in replacement for a Hocuspocus deployment with no Node runtime, no Redis, and no CGO.
|
Command yserve is a self-hosted Yjs sync server in a single static binary: a drop-in replacement for a Hocuspocus deployment with no Node runtime, no Redis, and no CGO. |
|
examples
|
|
|
collab-client
command
Command collab-client is a runnable example of the ygo Go-native sync client.
|
Command collab-client is a runnable example of the ygo Go-native sync client. |
|
collab-server
command
Command collab-server is a runnable example of embedding the ygo WebSocket sync server in your own Go backend and wiring its library-only extension points: connection lifecycle hooks, read-only viewers, an on-change side effect, first-load seeding, resource caps, and a live stats endpoint.
|
Command collab-server is a runnable example of embedding the ygo WebSocket sync server in your own Go backend and wiring its library-only extension points: connection lifecycle hooks, read-only viewers, an on-change side effect, first-load seeding, resource caps, and a live stats endpoint. |
|
offline-first
command
Command offline-first demonstrates the ygo client's offline-first persistence.
|
Command offline-first demonstrates the ygo client's offline-first persistence. |
|
Package gomobile is the bytes-in/bytes-out subset of the ygo API designed to survive `gomobile bind`.
|
Package gomobile is the bytes-in/bytes-out subset of the ygo API designed to survive `gomobile bind`. |
|
internal
|
|
|
awareness
Package awareness implements the y-protocols Awareness layer — the ephemeral, presence-style sibling of the document CRDT used to track per-client transient state like cursor positions, user names, and selection ranges.
|
Package awareness implements the y-protocols Awareness layer — the ephemeral, presence-style sibling of the document CRDT used to track per-client transient state like cursor positions, user names, and selection ranges. |
|
block
Package block defines the building blocks of a Yjs document.
|
Package block defines the building blocks of a Yjs document. |
|
doc
Package doc owns the Doc and Transaction types — the document container plus its mutation-lifecycle wrapper.
|
Package doc owns the Doc and Transaction types — the document container plus its mutation-lifecycle wrapper. |
|
encoding
Package encoding implements the V1 wire format yrs and JS Yjs use for state vectors, delete sets, and document updates.
|
Package encoding implements the V1 wire format yrs and JS Yjs use for state vectors, delete sets, and document updates. |
|
lib0
Package lib0 implements the binary encoding format used by Yjs.
|
Package lib0 implements the binary encoding format used by Yjs. |
|
store
Package store implements the per-client block storage that owns the memory for every Item in a Yjs document.
|
Package store implements the per-client block storage that owns the memory for every Item in a Yjs document. |
|
sync
Package sync implements the y-protocols/sync wire format and the Hocuspocus outer message envelope.
|
Package sync implements the y-protocols/sync wire format and the Hocuspocus outer message envelope. |
|
types
Package types holds the user-facing shared CRDT collection types: Map, Array, Text, XmlElement / XmlFragment / XmlText.
|
Package types holds the user-facing shared CRDT collection types: Map, Array, Text, XmlElement / XmlFragment / XmlText. |
|
undo
Package undo implements the Yjs UndoManager semantics in pure Go.
|
Package undo implements the Yjs UndoManager semantics in pure Go. |
|
utf16
Package utf16 provides UTF-16 code-unit length and offset helpers over Go's UTF-8 strings.
|
Package utf16 provides UTF-16 code-unit length and offset helpers over Go's UTF-8 strings. |
|
Package persist defines the storage contract for ygo documents and provides helpers that turn stored update logs back into live Docs.
|
Package persist defines the storage contract for ygo documents and provides helpers that turn stored update logs back into live Docs. |
|
sqlite
Package sqlite is the reference persist.Store implementation backed by modernc.org/sqlite.
|
Package sqlite is the reference persist.Store implementation backed by modernc.org/sqlite. |
|
Package server implements the y-websocket / Hocuspocus-compatible WebSocket sync server for ygo documents.
|
Package server implements the y-websocket / Hocuspocus-compatible WebSocket sync server for ygo documents. |