import { isImmutableString } from "./proxies.js"; export { isImmutableString, isCounter } from "./proxies.js"; import { type AutomergeValue, type Cursor, type CursorPosition, type Mark, type MarkSet, type MarkRange, type MarkValue, type MoveCursor, type Doc, type PatchCallback, type Patch } from "./types.js"; export { type AutomergeValue, type Cursor, Counter, type Doc, Int, Uint, Float64, type Mark, type MarkSet, type MarkRange, type MarkValue, type MoveCursor, type Patch, type PatchCallback, type ScalarValue, type PatchInfo, type PatchSource, } from "./types.js"; import type { Automerge, API as WasmAPI, Actor as ActorId, Prop, ObjID, Change, ChangeMetadata, DecodedChange, DiffOptions, Heads, MaterializeValue, JsSyncState, SyncMessage, Span, DecodedSyncMessage, UpdateSpansConfig } from "./wasm_types.js"; export type { ChangeMetadata, PutPatch, DelPatch, DiffOptions, SpliceTextPatch, InsertPatch, IncPatch, Span, SyncMessage, UpdateSpansConfig, } from "./wasm_types.js"; /** @hidden **/ type API = WasmAPI; declare const _SyncStateSymbol: unique symbol; /** * An opaque type tracking the state of sync with a remote peer */ type SyncState = JsSyncState & { /** @hidden */ _opaque: typeof _SyncStateSymbol; }; import { type ChangeToEncode } from "./low_level.js"; export { initializeWasm, initializeBase64Wasm, wasmInitialized, isWasmInitialized, } from "./low_level.js"; import { ImmutableString } from "./immutable_string.js"; export { ImmutableString } from "./immutable_string.js"; export { applyPatch, applyPatches } from "./apply_patches.js"; /** Options passed to {@link change}, and {@link emptyChange} * @typeParam T - The type of value contained in the document */ export type ChangeOptions = { /** A message which describes the changes */ message?: string; /** * The unix timestamp (in seconds) of the change (purely advisory, not used in conflict resolution). * When omitted it defaults to the current timestamp. When set to `undefined` no timestamp is used. */ time?: number | undefined; /** A callback which will be called to notify the caller of any changes to the document */ patchCallback?: PatchCallback; }; /** Options passed to {@link loadIncremental}, {@link applyChanges}, and {@link receiveSyncMessage} * @typeParam T - The type of value contained in the document */ export type ApplyOptions = { patchCallback?: PatchCallback; }; /** * A List is an extended Array that adds the two helper methods `deleteAt` and `insertAt`. */ export interface List extends Array { insertAt(index: number, ...args: T[]): List; deleteAt(index: number, numDelete?: number): List; } /** * Function for use in {@link change} which inserts values into a list at a given index * @param list * @param index * @param values */ export declare function insertAt(list: T[], index: number, ...values: T[]): void; /** * Function for use in {@link change} which deletes values from a list at a given index * @param list * @param index * @param numDelete */ export declare function deleteAt(list: T[], index: number, numDelete?: number): void; /** * Function which is called by {@link change} when making changes to a `Doc` * @typeParam T - The type of value contained in the document * * This function may mutate `doc` */ export type ChangeFn = (doc: T) => void; /** @hidden **/ export interface State { change: DecodedChange; snapshot: T; } /** @hidden **/ export declare function use(api: API): void; /** * Options to be passed to {@link init} or {@link load} * @typeParam T - The type of the value the document contains */ export type InitOptions = { /** The actor ID to use for this document, a random one will be generated if `null` is passed */ actor?: ActorId; freeze?: boolean; /** A callback which will be called with the initial patch once the document has finished loading */ patchCallback?: PatchCallback; /** @hidden */ unchecked?: boolean; /** Allow loading a document with missing changes */ allowMissingChanges?: boolean; /** @hidden */ convertImmutableStringsToText?: boolean; }; /** @hidden */ export declare function getBackend(doc: Doc): Automerge; export declare function getChangesSince(state: Doc, heads: Heads): Change[]; export declare function getChangesMetaSince(state: Doc, heads: Heads): ChangeMetadata[]; /** * Create a new automerge document * * @typeParam T - The type of value contained in the document. This will be the * type that is passed to the change closure in {@link change} * @param _opts - Either an actorId or an {@link InitOptions} (which may * contain an actorId). If this is null the document will be initialised with a * random actor ID */ export declare function init(_opts?: ActorId | InitOptions): Doc; /** * Make an immutable view of an automerge document as at `heads` * * @remarks * The document returned from this function cannot be passed to {@link change}. * This is because it shares the same underlying memory as `doc`, but it is * consequently a very cheap copy. * * Note that this function will throw an error if any of the hashes in `heads` * are not in the document. * * @typeParam T - The type of the value contained in the document * @param doc - The document to create a view of * @param heads - The hashes of the heads to create a view at */ export declare function view(doc: Doc, heads: Heads): Doc; /** * Make a full writable copy of an automerge document * * @remarks * Unlike {@link view} this function makes a full copy of the memory backing * the document and can thus be passed to {@link change}. It also generates a * new actor ID so that changes made in the new document do not create duplicate * sequence numbers with respect to the old document. If you need control over * the actor ID which is generated you can pass the actor ID as the second * argument * * @typeParam T - The type of the value contained in the document * @param doc - The document to clone * @param _opts - Either an actor ID to use for the new doc or an {@link InitOptions} */ export declare function clone(doc: Doc, _opts?: ActorId | InitOptions): Doc; /** Explicity free the memory backing a document. Note that this is note * necessary in environments which support * [`FinalizationRegistry`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry) */ export declare function free(doc: Doc): void; /** * Create an automerge document from a POJO * * @param initialState - The initial state which will be copied into the document * @typeParam T - The type of the value passed to `from` _and_ the type the resulting document will contain * @typeParam actor - The actor ID of the resulting document, if this is null a random actor ID will be used * * @example * ``` * const doc = automerge.from({ * tasks: [ * {description: "feed dogs", done: false} * ] * }) * ``` */ export declare function from>(initialState: T | Doc, _opts?: ActorId | InitOptions): Doc; /** * Update the contents of an automerge document * @typeParam T - The type of the value contained in the document * @param doc - The document to update * @param options - Either a message, an {@link ChangeOptions}, or a {@link ChangeFn} * @param callback - A `ChangeFn` to be used if `options` was a `string` * * Note that if the second argument is a function it will be used as the `ChangeFn` regardless of what the third argument is. * * @example A simple change * ``` * let doc1 = automerge.init() * doc1 = automerge.change(doc1, d => { * d.key = "value" * }) * assert.equal(doc1.key, "value") * ``` * * @example A change with a message * * ``` * doc1 = automerge.change(doc1, "add another value", d => { * d.key2 = "value2" * }) * ``` * * @example A change with a message and a timestamp * * ``` * doc1 = automerge.change(doc1, {message: "add another value", time: 1640995200}, d => { * d.key2 = "value2" * }) * ``` * * @example responding to a patch callback * ``` * let patchedPath * let patchCallback = patch => { * patchedPath = patch.path * } * doc1 = automerge.change(doc1, {message: "add another value", time: 1640995200, patchCallback}, d => { * d.key2 = "value2" * }) * assert.equal(patchedPath, ["key2"]) * ``` */ export declare function change(doc: Doc, options: string | ChangeOptions | ChangeFn, callback?: ChangeFn): Doc; /** * The type returned from {@link changeAt} */ export type ChangeAtResult = { /** The updated document **/ newDoc: Doc; /** * The heads resulting from the change * * @remarks * Note that this is _not_ the same as the heads of `newDoc`. The newly created * change will be added to the history of `newDoc` as if it was _concurrent_ * with whatever the heads of the document were at the time of the change. * This means that `newHeads` will be the same as the heads of a fork of * `newDoc` at the given heads to which the change was applied. * * This field will be `null` if no change was made */ newHeads: Heads | null; }; /** * Make a change to the document as it was at a particular point in history * @typeParam T - The type of the value contained in the document * @param doc - The document to update * @param scope - The heads representing the point in history to make the change * @param options - Either a message or a {@link ChangeOptions} for the new change * @param callback - A `ChangeFn` to be used if `options` was a `string` * * @remarks * This function is similar to {@link change} but allows you to make changes to * the document as if it were at a particular point in time. To understand this * imagine a document created with the following history: * * ```ts * let doc = automerge.from({..}) * doc = automerge.change(doc, () => {...}) * * const heads = automerge.getHeads(doc) * * // fork the document make a change * let fork = automerge.fork(doc) * fork = automerge.change(fork, () => {...}) * const headsOnFork = automerge.getHeads(fork) * * // make a change on the original doc * doc = automerge.change(doc, () => {...}) * const headsOnOriginal = automerge.getHeads(doc) * * // now merge the changes back to the original document * doc = automerge.merge(doc, fork) * * // The heads of the document will now be (headsOnFork, headsOnOriginal) * ``` * * {@link ChangeAt} produces an equivalent history, but without having to * create a fork of the document. In particular the `newHeads` field of the * returned {@link ChangeAtResult} will be the same as `headsOnFork`. * * Why would you want this? It's typically used in conjunction with {@link diff} * to reconcile state which is managed concurrently with the document. For * example, if you have a text editor component which the user is modifying * and you can't send the changes to the document synchronously you might follow * a workflow like this: * * * On initialization save the current heads of the document in the text editor state * * Every time the user makes a change record the change in the text editor state * * Now from time to time reconcile the editor state and the document * * Load the last saved heads from the text editor state, call them `oldHeads` * * Apply all the unreconciled changes to the document using `changeAt(doc, oldHeads, ...)` * * Get the diff from the resulting document to the current document using {@link diff} * passing the {@link ChangeAtResult.newHeads} as the `before` argument and the * heads of the entire document as the `after` argument. * * Apply the diff to the text editor state * * Save the current heads of the document in the text editor state */ export declare function changeAt(doc: Doc, scope: Heads, options: string | ChangeOptions | ChangeFn, callback?: ChangeFn): ChangeAtResult; /** * Make a change to a document which does not modify the document * * @param doc - The doc to add the empty change to * @param options - Either a message or a {@link ChangeOptions} for the new change * * Why would you want to do this? One reason might be that you have merged * changes from some other peers and you want to generate a change which * depends on those merged changes so that you can sign the new change with all * of the merged changes as part of the new change. */ export declare function emptyChange(doc: Doc, options: string | ChangeOptions | void): Doc; /** * Load an automerge document from a compressed document produce by {@link save} * * @typeParam T - The type of the value which is contained in the document. * Note that no validation is done to make sure this type is in * fact the type of the contained value so be a bit careful * @param data - The compressed document * @param _opts - Either an actor ID or some {@link InitOptions}, if the actor * ID is null a random actor ID will be created * * Note that `load` will throw an error if passed incomplete content (for * example if you are receiving content over the network and don't know if you * have the complete document yet). If you need to handle incomplete content use * {@link init} followed by {@link loadIncremental}. */ export declare function load(data: Uint8Array, _opts?: ActorId | InitOptions): Doc; /** * Load changes produced by {@link saveIncremental}, or partial changes * * @typeParam T - The type of the value which is contained in the document. * Note that no validation is done to make sure this type is in * fact the type of the contained value so be a bit careful * @param data - The compressedchanges * @param opts - an {@link ApplyOptions} * * This function is useful when staying up to date with a connected peer. * Perhaps the other end sent you a full compresed document which you loaded * with {@link load} and they're sending you the result of * {@link getLastLocalChange} every time they make a change. * * Note that this function will succesfully load the results of {@link save} as * well as {@link getLastLocalChange} or any other incremental change. */ export declare function loadIncremental(doc: Doc, data: Uint8Array, opts?: ApplyOptions): Doc; /** * Create binary save data to be appended to a save file or fed into {@link loadIncremental} * * @typeParam T - The type of the value which is contained in the document. * Note that no validation is done to make sure this type is in * fact the type of the contained value so be a bit careful * * This function is useful for incrementally saving state. The data can be appended to a * automerge save file, or passed to a document replicating its state. * */ export declare function saveIncremental(doc: Doc): Uint8Array; /** * Export the contents of a document to a compressed format * * @param doc - The doc to save * * The returned bytes can be passed to {@link load} or {@link loadIncremental} */ export declare function save(doc: Doc): Uint8Array; /** * Merge `remote` into `local` * @typeParam T - The type of values contained in each document * @param local - The document to merge changes into * @param remote - The document to merge changes from * * @returns - The merged document * * Often when you are merging documents you will also need to clone them. Both * arguments to `merge` are frozen after the call so you can no longer call * mutating methods (such as {@link change}) on them. The symtom of this will be * an error which says "Attempting to change an out of date document". To * overcome this call {@link clone} on the argument before passing it to {@link * merge}. */ export declare function merge(local: Doc, remote: Doc): Doc; /** * Get the actor ID associated with the document */ export declare function getActorId(doc: Doc): ActorId; /** * The type of conflicts for particular key or index * * Maps and sequences in automerge can contain conflicting values for a * particular key or index. In this case {@link getConflicts} can be used to * obtain a `Conflicts` representing the multiple values present for the property * * A `Conflicts` is a map from a unique (per property or index) key to one of * the possible conflicting values for the given property. */ type Conflicts = { [key: string]: AutomergeValue; }; /** * Get the conflicts associated with a property * * The values of properties in a map in automerge can be conflicted if there * are concurrent "put" operations to the same key. Automerge chooses one value * arbitrarily (but deterministically, any two nodes who have the same set of * changes will choose the same value) from the set of conflicting values to * present as the value of the key. * * Sometimes you may want to examine these conflicts, in this case you can use * {@link getConflicts} to get the conflicts for the key. * * @example * ``` * import * as automerge from "@automerge/automerge" * * type Profile = { * pets: Array<{name: string, type: string}> * } * * let doc1 = automerge.init("aaaa") * doc1 = automerge.change(doc1, d => { * d.pets = [{name: "Lassie", type: "dog"}] * }) * let doc2 = automerge.init("bbbb") * doc2 = automerge.merge(doc2, automerge.clone(doc1)) * * doc2 = automerge.change(doc2, d => { * d.pets[0].name = "Beethoven" * }) * * doc1 = automerge.change(doc1, d => { * d.pets[0].name = "Babe" * }) * * const doc3 = automerge.merge(doc1, doc2) * * // Note that here we pass `doc3.pets`, not `doc3` * let conflicts = automerge.getConflicts(doc3.pets[0], "name") * * // The two conflicting values are the keys of the conflicts object * assert.deepEqual(Object.values(conflicts), ["Babe", Beethoven"]) * ``` */ export declare function getConflicts(doc: Doc, prop: Prop): Conflicts | undefined; /** * Get the binary representation of the last change which was made to this doc * * This is most useful when staying in sync with other peers, every time you * make a change locally via {@link change} you immediately call {@link * getLastLocalChange} and send the result over the network to other peers. */ export declare function getLastLocalChange(doc: Doc): Change | undefined; /** * Return the object ID of an arbitrary javascript value * * This is useful to determine if something is actually an automerge document, * if `doc` is not an automerge document this will return null. */ export declare function getObjectId(doc: any, prop?: Prop): ObjID | null; /** * Get the changes which are in `newState` but not in `oldState`. The returned * changes can be loaded in `oldState` via {@link applyChanges}. * * Note that this will crash if there are changes in `oldState` which are not in `newState`. */ export declare function getChanges(oldState: Doc, newState: Doc): Change[]; /** * Get all the changes in a document * * This is different to {@link save} because the output is an array of changes * which can be individually applied via {@link applyChanges}` * */ export declare function getAllChanges(doc: Doc): Change[]; /** * Apply changes received from another document * * `doc` will be updated to reflect the `changes`. If there are changes which * we do not have dependencies for yet those will be stored in the document and * applied when the depended on changes arrive. * * You can use the {@link ApplyOptions} to pass a patchcallback which will be * informed of any changes which occur as a result of applying the changes * */ export declare function applyChanges(doc: Doc, changes: Change[], opts?: ApplyOptions): [Doc]; /** @hidden */ export declare function getHistory(doc: Doc): State[]; /** * Create a set of patches representing the change from one set of heads to another * * If either of the heads are missing from the document the returned set of patches will be empty */ export declare function diff(doc: Doc, before: Heads, after: Heads): Patch[]; /** * Create a set of patches representing the change from one set of heads to another at a given path * @experimental * @param doc - The document to update * @param path - path of the object to diff * @param before - before Heads for the diff * @param after - after Heads for the diff * @param opts - Options is { recursive: bool } to diff sub objects as well. Default is true * * This is an experimental API */ export declare function diffPath(doc: Doc, path: Prop[], before: Heads, after: Heads, opts?: DiffOptions): Patch[]; /** @hidden */ export declare function equals(val1: unknown, val2: unknown): boolean; /** * encode a {@link SyncState} into binary to send over the network * * @group sync * */ export declare function encodeSyncState(state: SyncState): Uint8Array; /** * Decode some binary data into a {@link SyncState} * * @group sync */ export declare function decodeSyncState(state: Uint8Array): SyncState; /** * Generate a sync message to send to the peer represented by `inState` * @param doc - The doc to generate messages about * @param inState - The {@link SyncState} representing the peer we are talking to * * @group sync * * @returns An array of `[newSyncState, syncMessage | null]` where * `newSyncState` should replace `inState` and `syncMessage` should be sent to * the peer if it is not null. If `syncMessage` is null then we are up to date. */ export declare function generateSyncMessage(doc: Doc, inState: SyncState): [SyncState, SyncMessage | null]; /** * Update a document and our sync state on receiving a sync message * * @group sync * * @param doc - The doc the sync message is about * @param inState - The {@link SyncState} for the peer we are communicating with * @param message - The message which was received * @param opts - Any {@link ApplyOption}s, used for passing a * {@link PatchCallback} which will be informed of any changes * in `doc` which occur because of the received sync message. * * @returns An array of `[newDoc, newSyncState, null]` where * `newDoc` is the updated state of `doc`, `newSyncState` should replace * `inState`. * * @remarks Note that this function has three return values for legacy reasons. * The third value used to be a sync message to send back but this is now * always null and you should instead call `generateSyncMessage` after calling * `receiveSyncMessage` to see if there are new messages to send. */ export declare function receiveSyncMessage(doc: Doc, inState: SyncState, message: SyncMessage, opts?: ApplyOptions): [Doc, SyncState, null]; /** * Check whether the replica represented by `remoteState` has all our changes * * @param doc - The doc to check whether the remote has changes for * @param remoteState - The {@link SyncState} representing the peer we are talking to * * @group sync * * @returns true if the remote has all of our changes */ export declare function hasOurChanges(doc: Doc, remoteState: SyncState): boolean; /** * Create a new, blank {@link SyncState} * * When communicating with a peer for the first time use this to generate a new * {@link SyncState} for them * * @group sync */ export declare function initSyncState(): SyncState; /** @hidden */ export declare function encodeChange(change: ChangeToEncode): Change; /** @hidden */ export declare function decodeChange(data: Change): DecodedChange; /** @hidden */ export declare function encodeSyncMessage(message: DecodedSyncMessage): SyncMessage; /** @hidden */ export declare function decodeSyncMessage(message: SyncMessage): DecodedSyncMessage; /** * Get any changes in `doc` which are not dependencies of `heads` */ export declare function getMissingDeps(doc: Doc, heads: Heads): Heads; /** * Get the hashes of the heads of this document */ export declare function getHeads(doc: Doc): Heads; /** @hidden */ export declare function dump(doc: Doc): void; /** @hidden */ export declare function toJS(doc: Doc): T; export declare function isAutomerge(doc: unknown): boolean; export declare function saveSince(doc: Doc, heads: Heads): Uint8Array; /** * Returns true if the document has all of the given heads somewhere in its history */ export declare function hasHeads(doc: Doc, heads: Heads): boolean; export type { API, SyncState, ActorId, Conflicts, Prop, Change, ObjID, DecodedChange, DecodedSyncMessage, Heads, MaterializeValue, }; /** * @hidden */ export declare function topoHistoryTraversal(doc: Doc): string[]; /** * Decode a change hash into the details of this change * * This should be considered a semi-stable API. We try not to change the * encoding in backwards incompatible ways but we won't bump a major version if * we do have to change it */ export declare function inspectChange(doc: Doc, changeHash: string): DecodedChange | null; /** * Return some internal statistics about the document */ export declare function stats(doc: Doc): { numChanges: number; numOps: number; numActors: number; /** @deprecated Use `releaseInfo().wasm.cargoPackageName` instead */ cargoPackageName: string; /** @deprecated Use `releaseInfo().wasm.cargoPackageVersion` instead */ cargoPackageVersion: string; /** @deprecated Use `releaseInfo().wasm.rustcVersion` instead */ rustcVersion: string; }; export type JsReleaseInfo = { gitHead: string; }; export type WasmReleaseInfo = { gitHead: string; cargoPackageName: string; cargoPackageVersion: string; rustcVersion: string; }; export type ReleaseInfo = { js: JsReleaseInfo; wasm: WasmReleaseInfo | null; }; /** * Get release information about the automerge library. * * Returns metadata about both the JavaScript wrapper and the WebAssembly * module, including git commit hashes. If js.gitHead !== wasm.gitHead, * the JS and WASM were built from different commits. * * If the WASM module has not been initialized, wasm will be null. */ export declare function releaseInfo(): ReleaseInfo; /** * Modify a string * * @typeParam T - The type of the value contained in the document * @param doc - The document to modify * @param path - The path to the string to modify * @param index - The position (as a {@link Cursor} or index) to edit. * If a cursor is used then the edit happens such that the cursor will * now point to the end of the newText, so you can continue to reuse * the same cursor for multiple calls to splice. * @param del - The number of code units to delete, a positive number * deletes N characters after the cursor, a negative number deletes * N characters before the cursor. * @param newText - The string to insert (if any). */ export declare function splice(doc: Doc, path: Prop[], index: number | Cursor, del: number, newText?: string): void; /** * Update the value of a string * * @typeParam T - The type of the value contained in the document * @param doc - The document to modify * @param path - The path to the string to modify * @param newText - The new text to update the value to * * @remarks * This will calculate a diff between the current value and the new value and * then convert that diff into calls to {@link splice}. This will produce results * which don't merge as well as directly capturing the user input actions, but * sometimes it's not possible to capture user input and this is the best you * can do. * * This is an experimental API and may change in the future. * * @beta */ export declare function updateText(doc: Doc, path: Prop[], newText: string): void; /** * Return the text + block markers at a given path * * @remarks * Rich text in automerge is represented as a sequence of characters with block * markers appearing inline with the text, and inline formatting spans overlaid * on the whole sequence. Block markers are normal automerge maps, but they are * only visible via either the {@link block} function or the {@link spans} * function. This function returns the current state of the spans */ export declare function spans(doc: Doc, path: Prop[]): Span[]; /** * Get the block marker at the given index */ export declare function block(doc: Doc, path: Prop[], index: number | Cursor): { [key: string]: MaterializeValue; } | null; /** * Insert a new block marker at the given index */ export declare function splitBlock(doc: Doc, path: Prop[], index: number | Cursor, block: { [key: string]: MaterializeValue; }): void; /** * Delete the block marker at the given index */ export declare function joinBlock(doc: Doc, path: Prop[], index: number | Cursor): void; /** * Update the block marker at the given index */ export declare function updateBlock(doc: Doc, path: Prop[], index: number | Cursor, block: { [key: string]: MaterializeValue; }): void; /** * Update the spans at the given path * * @remarks * Like {@link updateText} this will diff `newSpans` against the current state * of the text at `path` and perform a reasonably minimal number of operations * required to update the spans to the new state. * * When updating spans, we need to know what to set the "expand" behavior of * newly created marks to. By default we set it to "both", meaning that the * spans will expand on either, but this can be overridden by passing * `{ defaultExpand: ""}` as the final `config` parameter. You * can also pass `{perMarkExpand: {"": ""}` to * set the expand configuration for specific marks where it should be * different from the default. */ export declare function updateSpans(doc: Doc, path: Prop[], newSpans: Span[], config?: UpdateSpansConfig): void; /** * Returns a cursor for the given position in a string. * * @remarks * A cursor represents a relative position, "before character X", * rather than an absolute position. As the document is edited, the * cursor remains stable relative to its context, just as you'd expect * from a cursor in a concurrent text editor. * * The string representation is shareable, and so you can use this both * to edit the document yourself (using {@link splice}) or to share multiple * collaborator's current cursor positions over the network. * * The cursor's `position` can be an index in the string, `'start'` or `'end'`. * - `'start'` ensures this cursor always resolves to `0` * - `'end'` ensures this cursor always resolves to `string.length` * * Start cursors can be created by passing any negative number in `position`. * * End cursors can be created by passing a number `>= string.length` in `position`. * * `move` determines the position the cursor resolves to if the character at * `index` is removed: * - `'after'` causes the cursor to resolve towards `string.length` * - `'before'` causes the cursor to resolve towards `0` * * `move` is `'after'` by default. * * @typeParam T - The type of the value contained in the document * @param doc - The document * @param path - The path to the string * @param position - The position of the cursor, either an index, `'start'` or `'end'` * @param move - The direction the cursor should resolve to, defaults to 'after' */ export declare function getCursor(doc: Doc, path: Prop[], position: CursorPosition, move?: MoveCursor): Cursor; /** * Returns the current index of the cursor. * * @typeParam T - The type of the value contained in the document * * @param doc - The document * @param path - The path to the string * @param index - The cursor */ export declare function getCursorPosition(doc: Doc, path: Prop[], cursor: Cursor): number; export declare function mark(doc: Doc, path: Prop[], range: MarkRange, name: string, value: MarkValue): void; export declare function unmark(doc: Doc, path: Prop[], range: MarkRange, name: string): void; export declare function marks(doc: Doc, path: Prop[]): Mark[]; export declare function marksAt(doc: Doc, path: Prop[], index: number): MarkSet; /** * @deprecated This method has been renamed to {@link isImmutableString} */ export declare const isRawString: typeof isImmutableString; /** * @deprecated This type has been renamed to {@link ImmutableString} */ export declare const RawString: typeof ImmutableString; /** * EXPERIMENTAL: save a bundle of changes from a document to an encoded form * @experimental * @param doc - The document containing the changes to save * @param hashes - The hashes of the changes to save to a bundle * @returns */ export declare function saveBundle(doc: Doc, hashes: string[]): Uint8Array; /** * EXPERIMENTAL: Load a bundle of changes to examine them * @experimental * @param bundle - The encoded bundle to read */ export declare function readBundle(bundle: Uint8Array): { changes: DecodedChange[]; deps: Heads; };