@kyneta/yjs-schema 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -25
- package/dist/index.d.ts +185 -86
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1159 -860
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/__tests__/bind-constraints.test.ts +39 -30
- package/src/__tests__/bind-yjs.test.ts +53 -16
- package/src/__tests__/position.test.ts +376 -0
- package/src/__tests__/structural-merge.test.ts +111 -54
- package/src/__tests__/substrate.test.ts +18 -0
- package/src/__tests__/version.test.ts +87 -0
- package/src/bind-yjs.ts +44 -37
- package/src/change-mapping.ts +219 -25
- package/src/index.ts +3 -1
- package/src/populate.ts +59 -12
- package/src/position.ts +45 -0
- package/src/reader.ts +62 -6
- package/src/substrate.ts +99 -11
- package/src/version.ts +135 -33
- package/src/yjs-resolve.ts +59 -12
package/README.md
CHANGED
|
@@ -8,19 +8,20 @@ Wraps a `Y.Doc` with schema-aware typed reads, writes, versioning, and export/im
|
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
10
|
import {
|
|
11
|
-
|
|
11
|
+
createDoc,
|
|
12
12
|
change,
|
|
13
13
|
subscribe,
|
|
14
14
|
Schema,
|
|
15
15
|
text,
|
|
16
|
+
yjs,
|
|
16
17
|
version,
|
|
17
18
|
exportSnapshot,
|
|
18
19
|
exportSince,
|
|
19
20
|
importDelta,
|
|
20
21
|
} from "@kyneta/yjs-schema"
|
|
21
22
|
|
|
22
|
-
// Define a schema
|
|
23
|
-
const TodoDoc = Schema.struct({
|
|
23
|
+
// Define a schema and bind to Yjs substrate
|
|
24
|
+
const TodoDoc = yjs.bind(Schema.struct({
|
|
24
25
|
title: text(),
|
|
25
26
|
items: Schema.list(
|
|
26
27
|
Schema.struct({
|
|
@@ -28,10 +29,10 @@ const TodoDoc = Schema.struct({
|
|
|
28
29
|
done: Schema.boolean(),
|
|
29
30
|
}),
|
|
30
31
|
),
|
|
31
|
-
})
|
|
32
|
+
}))
|
|
32
33
|
|
|
33
34
|
// Create a document with optional seed values
|
|
34
|
-
const doc =
|
|
35
|
+
const doc = createDoc(TodoDoc, {
|
|
35
36
|
title: "My Todos",
|
|
36
37
|
items: [{ name: "Buy milk", done: false }],
|
|
37
38
|
})
|
|
@@ -66,16 +67,16 @@ subscribe(doc, (changeset) => {
|
|
|
66
67
|
|
|
67
68
|
### Unsupported
|
|
68
69
|
|
|
69
|
-
- **`Schema.
|
|
70
|
-
- **`Schema.
|
|
71
|
-
- **`Schema.
|
|
70
|
+
- **`Schema.counter()`** — Yjs has no native counter type. Use `Schema.number()` with `ReplaceChange` instead. Attempting to use a counter annotation will throw at construction time.
|
|
71
|
+
- **`Schema.movableList()`** — Yjs has no native movable list. Will throw at construction time.
|
|
72
|
+
- **`Schema.tree()`** — Yjs has no native tree type. Will throw at construction time.
|
|
72
73
|
|
|
73
74
|
## Sync
|
|
74
75
|
|
|
75
76
|
```ts
|
|
76
77
|
import {
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
createDoc,
|
|
79
|
+
yjs,
|
|
79
80
|
version,
|
|
80
81
|
exportSnapshot,
|
|
81
82
|
exportSince,
|
|
@@ -83,12 +84,14 @@ import {
|
|
|
83
84
|
change,
|
|
84
85
|
} from "@kyneta/yjs-schema"
|
|
85
86
|
|
|
87
|
+
const MyDoc = yjs.bind(MySchema)
|
|
88
|
+
|
|
86
89
|
// Peer A creates a doc
|
|
87
|
-
const docA =
|
|
90
|
+
const docA = createDoc(MyDoc, { title: "Draft" })
|
|
88
91
|
|
|
89
92
|
// Peer B bootstraps from a full snapshot
|
|
90
93
|
const snapshot = exportSnapshot(docA)
|
|
91
|
-
const docB =
|
|
94
|
+
const docB = createDoc(MyDoc, snapshot)
|
|
92
95
|
|
|
93
96
|
// After mutations on A, sync incrementally
|
|
94
97
|
const vBefore = version(docB)
|
|
@@ -102,10 +105,10 @@ importDelta(docB, delta!)
|
|
|
102
105
|
## Exchange Integration
|
|
103
106
|
|
|
104
107
|
```ts
|
|
105
|
-
import {
|
|
108
|
+
import { yjs } from "@kyneta/yjs-schema"
|
|
106
109
|
import { Schema, text } from "@kyneta/yjs-schema"
|
|
107
110
|
|
|
108
|
-
const TodoDoc =
|
|
111
|
+
const TodoDoc = yjs.bind(Schema.struct({
|
|
109
112
|
title: text(),
|
|
110
113
|
items: Schema.list(Schema.struct({
|
|
111
114
|
name: Schema.string(),
|
|
@@ -117,16 +120,17 @@ const TodoDoc = bindYjs(Schema.struct({
|
|
|
117
120
|
const doc = exchange.get("my-todos", TodoDoc)
|
|
118
121
|
```
|
|
119
122
|
|
|
120
|
-
`
|
|
123
|
+
`yjs.bind()` produces a `BoundSchema` with the collaborative `SyncProtocol`, which the exchange uses for bidirectional CRDT sync.
|
|
121
124
|
|
|
122
125
|
## Escape Hatch
|
|
123
126
|
|
|
124
127
|
Access the underlying `Y.Doc` for direct Yjs API usage:
|
|
125
128
|
|
|
126
129
|
```ts
|
|
127
|
-
import { yjs } from "@kyneta/yjs-schema"
|
|
130
|
+
import { yjs, createDoc } from "@kyneta/yjs-schema"
|
|
128
131
|
|
|
129
|
-
const
|
|
132
|
+
const MyDoc = yjs.bind(MySchema)
|
|
133
|
+
const doc = createDoc(MyDoc)
|
|
130
134
|
const yjsDoc = yjs(doc)
|
|
131
135
|
|
|
132
136
|
// Use with Yjs ecosystem
|
|
@@ -152,28 +156,27 @@ Because `yjs(doc)` returns a standard `Y.Doc`, the entire Yjs provider ecosystem
|
|
|
152
156
|
|
|
153
157
|
| Export | Description |
|
|
154
158
|
|---|---|
|
|
155
|
-
| `
|
|
156
|
-
| `createYjsDocFromSnapshot(schema, payload)` | Reconstruct from snapshot |
|
|
159
|
+
| `createDoc(schema, docOrSeed?)` | Create a live Yjs-backed document *(re-exported from `@kyneta/schema`)* |
|
|
157
160
|
| `version(doc)` | Current `YjsVersion` |
|
|
158
|
-
| `
|
|
161
|
+
| `exportEntirety(doc)` | Full state as `SubstratePayload` |
|
|
159
162
|
| `exportSince(doc, since)` | Delta since version |
|
|
160
|
-
| `
|
|
163
|
+
| `merge(doc, payload, origin?)` | Apply delta from peer |
|
|
161
164
|
| `change(doc, fn)` | Transactional mutation |
|
|
162
165
|
| `subscribe(doc, callback)` | Observe changes |
|
|
163
|
-
| `
|
|
166
|
+
| `yjs.bind(schema)` | Bind schema for exchange use |
|
|
164
167
|
| `yjs(ref)` | Escape hatch → `Y.Doc` |
|
|
165
|
-
| `text()` | `Schema.
|
|
168
|
+
| `text()` | `Schema.text()` convenience — collaborative text schema kind |
|
|
166
169
|
|
|
167
170
|
### Low-level primitives (power users)
|
|
168
171
|
|
|
169
172
|
| Export | Description |
|
|
170
173
|
|---|---|
|
|
171
174
|
| `YjsVersion` | Version class wrapping Yjs state vectors |
|
|
172
|
-
| `
|
|
175
|
+
| `yjsReader(doc, schema)` | Live `StoreReader` over Yjs types |
|
|
173
176
|
| `resolveYjsType(rootMap, schema, path)` | Path resolution |
|
|
174
177
|
| `applyChangeToYjs(rootMap, schema, path, change)` | kyneta → Yjs |
|
|
175
178
|
| `eventsToOps(events)` | Yjs → kyneta |
|
|
176
|
-
| `
|
|
179
|
+
| `ensureContainers(doc, schema, seed)` | Root container population |
|
|
177
180
|
| `createYjsSubstrate(doc, schema)` | Low-level substrate construction |
|
|
178
181
|
| `yjsSubstrateFactory` | `SubstrateFactory<YjsVersion>` |
|
|
179
182
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import
|
|
1
|
+
import { BindingTarget, ChangeBase, DocRef, Instruction, NATIVE, NativeMap, Op, Op as Op$1, Path, Position, Reader, Ref, ReplicaFactory, Schema, Schema as Schema$1, SchemaBinding, Segment, Side, Substrate, SubstrateFactory, SubstratePayload, Version, applyChanges, change, createDoc, createRef, exportEntirety, exportSince, merge, subscribe, subscribeNode, unwrap, version } from "@kyneta/schema";
|
|
2
|
+
import * as Y from "yjs";
|
|
3
|
+
import { Doc } from "yjs";
|
|
4
|
+
import { Changeset } from "@kyneta/changefeed";
|
|
5
5
|
|
|
6
|
+
//#region src/native-map.d.ts
|
|
6
7
|
/**
|
|
7
8
|
* NativeMap for the Yjs CRDT substrate.
|
|
8
9
|
*
|
|
@@ -20,36 +21,41 @@ import * as Y from 'yjs';
|
|
|
20
21
|
* - `sum → undefined` (no container; stored in parent map)
|
|
21
22
|
*/
|
|
22
23
|
interface YjsNativeMap extends NativeMap {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
readonly root: Y.Doc;
|
|
25
|
+
readonly text: Y.Text;
|
|
26
|
+
readonly counter: undefined;
|
|
27
|
+
readonly list: Y.Array<unknown>;
|
|
28
|
+
readonly movableList: undefined;
|
|
29
|
+
readonly struct: Y.Map<unknown>;
|
|
30
|
+
readonly map: Y.Map<unknown>;
|
|
31
|
+
readonly tree: undefined;
|
|
32
|
+
readonly set: undefined;
|
|
33
|
+
readonly scalar: undefined;
|
|
34
|
+
readonly sum: undefined;
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/bind-yjs.d.ts
|
|
38
|
+
/**
|
|
39
|
+
* Yjs composition-law tags — the set of concurrent composition laws
|
|
40
|
+
* that the Yjs substrate faithfully implements.
|
|
41
|
+
*/
|
|
42
|
+
type YjsLaws = "lww" | "positional-ot" | "lww-per-key" | "lww-tag-replaced";
|
|
36
43
|
/**
|
|
37
|
-
* The Yjs CRDT
|
|
44
|
+
* The Yjs CRDT binding target.
|
|
38
45
|
*
|
|
39
|
-
* - `yjs.bind(schema)` — collaborative sync
|
|
40
|
-
* - `yjs.
|
|
41
|
-
* - `yjs.replica()` — collaborative replication (default)
|
|
42
|
-
* - `yjs.replica("ephemeral")` — ephemeral replication
|
|
46
|
+
* - `yjs.bind(schema)` — bind a schema to Yjs with collaborative sync
|
|
47
|
+
* - `yjs.replica()` — create a collaborative replica
|
|
43
48
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
49
|
+
* Laws are constrained to `YjsLaws` — schemas requiring composition laws
|
|
50
|
+
* outside this set (e.g. `"additive"` from `Schema.counter()`,
|
|
51
|
+
* `"positional-ot-move"` from `Schema.movableList()`) are rejected at
|
|
52
|
+
* compile time.
|
|
46
53
|
*
|
|
47
54
|
* To access the underlying Y.Doc, use `unwrap(ref)` from `@kyneta/schema`.
|
|
48
55
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
declare const yjs: BindingTarget<YjsLaws, YjsNativeMap>;
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/change-mapping.d.ts
|
|
53
59
|
/**
|
|
54
60
|
* Apply a kyneta Change to the Yjs shared type tree imperatively.
|
|
55
61
|
*
|
|
@@ -62,7 +68,7 @@ declare const yjs: SubstrateNamespace<CrdtStrategy, YjsCaps, YjsNativeMap>;
|
|
|
62
68
|
* @param path - The path to the target
|
|
63
69
|
* @param change - The kyneta Change to apply
|
|
64
70
|
*/
|
|
65
|
-
declare function applyChangeToYjs(rootMap: Y.Map<any>, rootSchema: Schema, path: Path, change: ChangeBase): void;
|
|
71
|
+
declare function applyChangeToYjs(rootMap: Y.Map<any>, rootSchema: Schema$1, path: Path, change: ChangeBase, binding?: SchemaBinding): void;
|
|
66
72
|
/**
|
|
67
73
|
* Convert `observeDeep` events into kyneta `Op[]` for changefeed delivery.
|
|
68
74
|
*
|
|
@@ -76,8 +82,9 @@ declare function applyChangeToYjs(rootMap: Y.Map<any>, rootSchema: Schema, path:
|
|
|
76
82
|
*
|
|
77
83
|
* @param events - The events from the `observeDeep` callback
|
|
78
84
|
*/
|
|
79
|
-
declare function eventsToOps(events: Y.YEvent<any>[], schema: Schema): Op[];
|
|
80
|
-
|
|
85
|
+
declare function eventsToOps(events: Y.YEvent<any>[], schema: Schema$1, binding?: SchemaBinding): Op$1[];
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/populate.d.ts
|
|
81
88
|
/**
|
|
82
89
|
* Ensure that a Y.Doc's root map contains the correct Yjs shared types
|
|
83
90
|
* matching the schema structure.
|
|
@@ -100,13 +107,35 @@ declare function eventsToOps(events: Y.YEvent<any>[], schema: Schema): Op[];
|
|
|
100
107
|
* then restores the caller's clientID. This produces byte-identical
|
|
101
108
|
* structural ops across all peers, enabling Yjs deduplication on merge.
|
|
102
109
|
*
|
|
110
|
+
* **Identity-keying:** When a `binding` is provided, each root field's
|
|
111
|
+
* key in the root Y.Map is the identity hash from `binding.forward`
|
|
112
|
+
* instead of the field name. Nested product fields are similarly keyed
|
|
113
|
+
* via `ensureMapContainers`.
|
|
114
|
+
*
|
|
103
115
|
* @param doc - The Y.Doc to prepare
|
|
104
116
|
* @param schema - The root document schema (a ProductSchema)
|
|
105
117
|
* @param conditional - If true, skip fields that already exist in the root map.
|
|
106
118
|
* Context: jj:smmulzkm (two-phase substrate construction)
|
|
119
|
+
* @param binding - Optional SchemaBinding for identity-keyed containers.
|
|
107
120
|
*/
|
|
108
|
-
declare function ensureContainers(doc: Y.Doc, schema: Schema, conditional?: boolean): void;
|
|
109
|
-
|
|
121
|
+
declare function ensureContainers(doc: Y.Doc, schema: Schema$1, conditional?: boolean, binding?: SchemaBinding): void;
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/position.d.ts
|
|
124
|
+
/** Map kyneta Side to Yjs assoc. Left → -1 (left-sticky), Right → 0 (right-sticky). */
|
|
125
|
+
declare function toYjsAssoc(side: Side): number;
|
|
126
|
+
/** Map Yjs assoc to kyneta Side. Negative → left, non-negative → right. */
|
|
127
|
+
declare function fromYjsAssoc(assoc: number): Side;
|
|
128
|
+
declare class YjsPosition implements Position {
|
|
129
|
+
private readonly rpos;
|
|
130
|
+
private readonly doc;
|
|
131
|
+
readonly side: Side;
|
|
132
|
+
constructor(rpos: Y.RelativePosition, doc: Y.Doc);
|
|
133
|
+
resolve(): number | null;
|
|
134
|
+
encode(): Uint8Array;
|
|
135
|
+
transform(_instructions: readonly Instruction[]): void;
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/reader.d.ts
|
|
110
139
|
/**
|
|
111
140
|
* Creates a Reader that navigates the Yjs shared type tree live,
|
|
112
141
|
* using the schema as a type witness to determine navigation at each
|
|
@@ -120,58 +149,106 @@ declare function ensureContainers(doc: Y.Doc, schema: Schema, conditional?: bool
|
|
|
120
149
|
*
|
|
121
150
|
* @param doc - The Y.Doc to read from.
|
|
122
151
|
* @param schema - The root schema for the document.
|
|
152
|
+
* @param binding - Optional SchemaBinding for identity-keyed navigation.
|
|
123
153
|
*/
|
|
124
|
-
declare function yjsReader(doc: Y.Doc, schema: Schema): Reader;
|
|
125
|
-
|
|
154
|
+
declare function yjsReader(doc: Y.Doc, schema: Schema$1, binding?: SchemaBinding): Reader;
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/version.d.ts
|
|
126
157
|
/**
|
|
127
|
-
* A Version wrapping a Yjs state vector.
|
|
158
|
+
* A Version wrapping a Yjs snapshot (state vector + delete set).
|
|
128
159
|
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* minimal update payload via `Y.encodeStateAsUpdate(doc, sv)`.
|
|
160
|
+
* The state vector tracks which insertions from each client have been
|
|
161
|
+
* observed. The delete set tracks which of those items have been
|
|
162
|
+
* tombstoned. Together they fully describe a Yjs document's state.
|
|
133
163
|
*
|
|
134
|
-
* `
|
|
135
|
-
* `
|
|
136
|
-
*
|
|
164
|
+
* - `sv` is used by `exportSince()` to compute the minimal update payload
|
|
165
|
+
* via `Y.encodeStateAsUpdate(doc, sv)`.
|
|
166
|
+
* - `snapshotBytes` is the encoded Yjs `Snapshot` (SV + delete set),
|
|
167
|
+
* used for equality comparison: two documents are "equal" only when
|
|
168
|
+
* both their inserts and deletes match.
|
|
169
|
+
*
|
|
170
|
+
* `compare()` first performs standard version-vector partial-order
|
|
171
|
+
* comparison on the state vectors. If the SVs are equal, it falls
|
|
172
|
+
* through to a byte-level comparison of the snapshot bytes — if they
|
|
173
|
+
* differ (same inserts, different deletes), the result is "concurrent",
|
|
174
|
+
* ensuring the sync protocol pushes the divergent deletes.
|
|
137
175
|
*/
|
|
138
176
|
declare class YjsVersion implements Version {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
177
|
+
/** Encoded state vector — used by exportSince(). */
|
|
178
|
+
readonly sv: Uint8Array;
|
|
179
|
+
/**
|
|
180
|
+
* Encoded Yjs snapshot (state vector + delete set) — used for equality
|
|
181
|
+
* comparison. Two documents are "equal" only if both their inserts
|
|
182
|
+
* (state vector) and deletes (delete set) match.
|
|
183
|
+
*/
|
|
184
|
+
readonly snapshotBytes: Uint8Array;
|
|
185
|
+
constructor(sv: Uint8Array, snapshotBytes?: Uint8Array);
|
|
186
|
+
/**
|
|
187
|
+
* Construct a version from a live `Y.Doc` by snapshotting its full state.
|
|
188
|
+
*
|
|
189
|
+
* Walks the struct store to derive the delete set — O(n) in the number
|
|
190
|
+
* of items. Use {@link fromDeleteSet} for the incremental path.
|
|
191
|
+
*/
|
|
192
|
+
static fromDoc(doc: Doc): YjsVersion;
|
|
193
|
+
/**
|
|
194
|
+
* Construct a version from a `Y.Doc`'s state vector and an externally
|
|
195
|
+
* maintained delete set — the incremental path that avoids a struct
|
|
196
|
+
* store walk.
|
|
197
|
+
*
|
|
198
|
+
* @param doc The live Y.Doc (for the state vector).
|
|
199
|
+
* @param ds An accumulated delete set, kept in sync by merging
|
|
200
|
+
* `transaction.deleteSet` on each transaction.
|
|
201
|
+
*/
|
|
202
|
+
static fromDeleteSet(doc: Doc, ds: ReturnType<typeof Y.createDeleteSet>): YjsVersion;
|
|
203
|
+
/**
|
|
204
|
+
* Serialize to a text-safe string.
|
|
205
|
+
*
|
|
206
|
+
* Format: `base64(sv) + "." + base64(snapshotBytes)`.
|
|
207
|
+
* The "." separator is unambiguous since base64 never contains ".".
|
|
208
|
+
*/
|
|
209
|
+
serialize(): string;
|
|
210
|
+
/**
|
|
211
|
+
* Compare with another version using version-vector partial order,
|
|
212
|
+
* extended with delete-set equality checking.
|
|
213
|
+
*
|
|
214
|
+
* 1. Decode both state vectors and compare via `versionVectorCompare`.
|
|
215
|
+
* 2. If the SV comparison yields anything other than "equal", return it.
|
|
216
|
+
* 3. If the SVs are equal, compare snapshot bytes for byte equality.
|
|
217
|
+
* If they differ (same inserts, different deletes), return "concurrent"
|
|
218
|
+
* — both sides may have tombstones the other lacks.
|
|
219
|
+
* 4. "equal" is returned only when BOTH the state vector AND the
|
|
220
|
+
* delete set match.
|
|
221
|
+
*
|
|
222
|
+
* @throws If `other` is not a `YjsVersion`.
|
|
223
|
+
*/
|
|
224
|
+
compare(other: Version): "behind" | "equal" | "ahead" | "concurrent";
|
|
225
|
+
/**
|
|
226
|
+
* Greatest lower bound (lattice meet) of two Yjs versions.
|
|
227
|
+
*
|
|
228
|
+
* Decodes both state vectors, computes the component-wise minimum
|
|
229
|
+
* via `versionVectorMeet`, and encodes the result back to a Yjs
|
|
230
|
+
* state vector.
|
|
231
|
+
*
|
|
232
|
+
* The meet snapshot uses the meet SV with no delete-set information
|
|
233
|
+
* (conservative lower bound). meet() feeds into advance(), which Yjs
|
|
234
|
+
* does not support incrementally, so this is safe.
|
|
235
|
+
*
|
|
236
|
+
* @throws If `other` is not a `YjsVersion`.
|
|
237
|
+
*/
|
|
238
|
+
meet(other: Version): YjsVersion;
|
|
239
|
+
/**
|
|
240
|
+
* Parse a serialized YjsVersion string back into a YjsVersion.
|
|
241
|
+
*
|
|
242
|
+
* New format: `base64(sv) + "." + base64(snapshotBytes)`.
|
|
243
|
+
* Legacy format (no "."): `base64(sv)` only — constructed with
|
|
244
|
+
* `snapshotBytes` equal to the SV bytes. When compared against a
|
|
245
|
+
* new-format version with matching SVs, the differing snapshot bytes
|
|
246
|
+
* yield "concurrent", triggering a safe redundant sync push.
|
|
247
|
+
*/
|
|
248
|
+
static parse(serialized: string): YjsVersion;
|
|
173
249
|
}
|
|
174
|
-
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/substrate.d.ts
|
|
175
252
|
/**
|
|
176
253
|
* Creates a `Substrate<YjsVersion>` wrapping a user-provided Y.Doc.
|
|
177
254
|
*
|
|
@@ -189,37 +266,59 @@ declare class YjsVersion implements Version {
|
|
|
189
266
|
* @param doc - The Y.Doc to wrap. The substrate does NOT own the doc;
|
|
190
267
|
* the caller is responsible for its lifecycle.
|
|
191
268
|
* @param schema - The root schema for the document.
|
|
269
|
+
* @param binding - Optional SchemaBinding for identity-keyed containers.
|
|
192
270
|
*/
|
|
193
|
-
declare function createYjsSubstrate(doc: Y.Doc, schema: Schema): Substrate<YjsVersion>;
|
|
271
|
+
declare function createYjsSubstrate(doc: Y.Doc, schema: Schema$1, binding?: SchemaBinding): Substrate<YjsVersion>;
|
|
194
272
|
declare const yjsReplicaFactory: ReplicaFactory<YjsVersion>;
|
|
195
273
|
declare const yjsSubstrateFactory: SubstrateFactory<YjsVersion>;
|
|
196
|
-
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region src/yjs-resolve.d.ts
|
|
197
276
|
/**
|
|
198
277
|
* Navigate one step deeper into the Yjs shared type tree.
|
|
199
278
|
*
|
|
200
279
|
* Uses `instanceof` for runtime type discrimination:
|
|
201
|
-
* - `Y.Map` → `.get(key)`
|
|
280
|
+
* - `Y.Map` → `.get(key)` — uses the identity hash when provided
|
|
202
281
|
* - `Y.Array` → `.get(index)`
|
|
203
282
|
* - `Y.Text` → terminal (cannot step further)
|
|
204
283
|
* - Plain value → terminal (return `undefined`)
|
|
205
284
|
*
|
|
206
285
|
* @param current - The current position (a Yjs shared type or plain value)
|
|
207
286
|
* @param segment - The path segment to follow
|
|
287
|
+
* @param identity - Optional identity hash to use instead of the segment's resolved value
|
|
208
288
|
*/
|
|
209
|
-
declare function stepIntoYjs(current: unknown, segment: Segment): unknown;
|
|
289
|
+
declare function stepIntoYjs(current: unknown, segment: Segment, identity?: string): unknown;
|
|
290
|
+
/**
|
|
291
|
+
* Result of resolving a Yjs shared type at a path.
|
|
292
|
+
*
|
|
293
|
+
* Includes both the resolved Yjs value and the schema at that position,
|
|
294
|
+
* enabling callers to distinguish between schema kinds that map to the
|
|
295
|
+
* same Yjs type (e.g. "text" vs "richtext" both use Y.Text).
|
|
296
|
+
*/
|
|
297
|
+
interface ResolvedYjs {
|
|
298
|
+
readonly resolved: unknown;
|
|
299
|
+
readonly schema: Schema$1;
|
|
300
|
+
}
|
|
210
301
|
/**
|
|
211
302
|
* Resolve a Yjs shared type (or plain value) at the given path.
|
|
212
303
|
*
|
|
213
304
|
* Left-folds over path segments using `advanceSchema` for pure schema
|
|
214
305
|
* descent and `stepIntoYjs` for Yjs-specific navigation.
|
|
215
306
|
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
307
|
+
* When a `binding` is provided, each step computes the absolute schema
|
|
308
|
+
* path and looks up the identity hash from `binding.forward`. This
|
|
309
|
+
* identity hash is used instead of the field name at every product-field
|
|
310
|
+
* boundary (root and nested).
|
|
311
|
+
*
|
|
312
|
+
* Returns both the Yjs shared type (or plain value) and the schema at
|
|
313
|
+
* the terminal position. For an empty path, returns the root map and
|
|
314
|
+
* root schema.
|
|
218
315
|
*
|
|
219
316
|
* @param rootMap - The root `Y.Map` obtained via `doc.getMap("root")`
|
|
220
317
|
* @param rootSchema - The root document schema
|
|
221
318
|
* @param path - The path to resolve
|
|
319
|
+
* @param binding - Optional SchemaBinding for identity-keyed navigation.
|
|
222
320
|
*/
|
|
223
|
-
declare function resolveYjsType(rootMap: Y.Map<any>, rootSchema: Schema, path: Path):
|
|
224
|
-
|
|
225
|
-
export { type
|
|
321
|
+
declare function resolveYjsType(rootMap: Y.Map<any>, rootSchema: Schema$1, path: Path, binding?: SchemaBinding): ResolvedYjs;
|
|
322
|
+
//#endregion
|
|
323
|
+
export { type Changeset, type DocRef, NATIVE, type Op, type Ref, Schema, type SubstratePayload, type YjsLaws, type YjsNativeMap, YjsPosition, YjsVersion, applyChangeToYjs, applyChanges, change, createDoc, createRef, createYjsSubstrate, ensureContainers, eventsToOps, exportEntirety, exportSince, fromYjsAssoc, merge, resolveYjsType, stepIntoYjs, subscribe, subscribeNode, toYjsAssoc, unwrap, version, yjs, yjsReader, yjsReplicaFactory, yjsSubstrateFactory };
|
|
324
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/native-map.ts","../src/bind-yjs.ts","../src/change-mapping.ts","../src/populate.ts","../src/position.ts","../src/reader.ts","../src/version.ts","../src/substrate.ts","../src/yjs-resolve.ts"],"mappings":"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"}
|