@kyneta/yjs-schema 1.2.0 → 1.3.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 CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  } from "@kyneta/yjs-schema"
21
21
 
22
22
  // Define a schema
23
- const TodoDoc = Schema.doc({
23
+ const TodoDoc = Schema.struct({
24
24
  title: text(),
25
25
  items: Schema.list(
26
26
  Schema.struct({
@@ -105,7 +105,7 @@ importDelta(docB, delta!)
105
105
  import { bindYjs } from "@kyneta/yjs-schema"
106
106
  import { Schema, text } from "@kyneta/yjs-schema"
107
107
 
108
- const TodoDoc = bindYjs(Schema.doc({
108
+ const TodoDoc = bindYjs(Schema.struct({
109
109
  title: text(),
110
110
  items: Schema.list(Schema.struct({
111
111
  name: Schema.string(),
@@ -179,4 +179,4 @@ Because `yjs(doc)` returns a standard `Y.Doc`, the entire Yjs provider ecosystem
179
179
 
180
180
  ## License
181
181
 
182
- MIT
182
+ MIT
package/dist/index.d.ts CHANGED
@@ -1,173 +1,38 @@
1
- import { Version, Schema, Ref, SubstratePayload, SubstrateNamespace, CrdtStrategy, Path, ChangeBase, Op, Reader, Substrate, ReplicaFactory, SubstrateFactory, Segment } from '@kyneta/schema';
2
- export { Op, Ref, Schema, SubstratePayload, applyChanges, change, subscribe, subscribeNode } from '@kyneta/schema';
3
- import * as Y from 'yjs';
4
1
  export { Changeset } from '@kyneta/changefeed';
2
+ import { NativeMap, SubstrateNamespace, CrdtStrategy, Schema, Path, ChangeBase, Op, Reader, Version, Substrate, ReplicaFactory, SubstrateFactory, Segment } from '@kyneta/schema';
3
+ export { DocRef, NATIVE, Op, Ref, Schema, SubstratePayload, applyChanges, change, createDoc, createRef, exportEntirety, exportSince, merge, subscribe, subscribeNode, unwrap, version } from '@kyneta/schema';
4
+ import * as Y from 'yjs';
5
5
 
6
6
  /**
7
- * A Version wrapping a Yjs state vector.
8
- *
9
- * State vectors track the complete peer state which operations from
10
- * each client have been observed. This is the right abstraction for sync
11
- * diffing: `exportSince(version)` uses the state vector to compute the
12
- * minimal update payload via `Y.encodeStateAsUpdate(doc, sv)`.
13
- *
14
- * `serialize()` encodes to base64 for text-safe embedding.
15
- * `compare()` decodes both state vectors and performs standard
16
- * version-vector partial-order comparison over the client-clock maps.
7
+ * NativeMap for the Yjs CRDT substrate.
8
+ *
9
+ * Maps each schema kind to the corresponding Yjs shared type:
10
+ * - `root Y.Doc` (the document itself)
11
+ * - `text Y.Text`
12
+ * - `counter undefined` (Yjs has no counter type)
13
+ * - `list → Y.Array<unknown>`
14
+ * - `movableList → undefined` (Yjs has no movable list)
15
+ * - `struct Y.Map<unknown>` (Yjs uses maps for struct fields)
16
+ * - `map Y.Map<unknown>`
17
+ * - `tree → undefined` (Yjs has no tree type)
18
+ * - `set → undefined` (not yet supported)
19
+ * - `scalar → undefined` (no container; stored in parent map)
20
+ * - `sum → undefined` (no container; stored in parent map)
17
21
  */
18
- declare class YjsVersion implements Version {
19
- readonly sv: Uint8Array;
20
- constructor(sv: Uint8Array);
21
- /**
22
- * Serialize the state vector to a base64 string.
23
- *
24
- * The encoding is: raw state vector bytes → base64.
25
- * This is text-safe for embedding in HTML meta tags, URL parameters, etc.
26
- */
27
- serialize(): string;
28
- /**
29
- * Compare with another version using version-vector partial order.
30
- *
31
- * Decodes both state vectors via `Y.decodeStateVector()` to get
32
- * `Map<number, number>` (clientID → clock), then compares:
33
- *
34
- * - Collect the union of all client IDs from both maps.
35
- * - For each client, compare clocks (missing client = clock 0).
36
- * - If all clocks in `this` ≤ `other` and at least one strictly less → `"behind"`
37
- * - If all clocks in `this` ≥ `other` and at least one strictly greater → `"ahead"`
38
- * - If all clocks equal → `"equal"`
39
- * - Otherwise → `"concurrent"`
40
- *
41
- * Throws if `other` is not a `YjsVersion`.
42
- */
43
- compare(other: Version): "behind" | "equal" | "ahead" | "concurrent";
44
- /**
45
- * Greatest lower bound (lattice meet) of two Yjs versions.
46
- *
47
- * Decodes both state vectors, computes the component-wise minimum
48
- * via the shared `versionVectorMeet` utility, and encodes the result
49
- * back to a Yjs state vector.
50
- *
51
- * @throws If `other` is not a `YjsVersion`.
52
- */
53
- meet(other: Version): YjsVersion;
54
- /**
55
- * Parse a serialized YjsVersion string back into a YjsVersion.
56
- *
57
- * The inverse of `serialize()`: base64 → `Uint8Array`.
58
- */
59
- static parse(serialized: string): YjsVersion;
22
+ interface YjsNativeMap extends NativeMap {
23
+ readonly root: Y.Doc;
24
+ readonly text: Y.Text;
25
+ readonly counter: undefined;
26
+ readonly list: Y.Array<unknown>;
27
+ readonly movableList: undefined;
28
+ readonly struct: Y.Map<unknown>;
29
+ readonly map: Y.Map<unknown>;
30
+ readonly tree: undefined;
31
+ readonly set: undefined;
32
+ readonly scalar: undefined;
33
+ readonly sum: undefined;
60
34
  }
61
35
 
62
- /**
63
- * Create a live Yjs-backed document.
64
- *
65
- * **Form 1 — bring your own doc:**
66
- * ```ts
67
- * const yjsDoc = new Y.Doc()
68
- * const doc = createYjsDoc(mySchema, yjsDoc)
69
- * ```
70
- *
71
- * **Form 2 — fresh empty doc:**
72
- * ```ts
73
- * const doc = createYjsDoc(mySchema)
74
- *
75
- * // Apply initial content via change():
76
- * change(doc, d => {
77
- * d.title.insert(0, "Hello")
78
- * d.items.push({ name: "First item" })
79
- * })
80
- * ```
81
- *
82
- * Returns a full-stack `Ref<S>` — callable, navigable, writable,
83
- * transactable, and observable. Backed by a `YjsSubstrate` with
84
- * CRDT collaboration support.
85
- *
86
- * The returned ref observes **all** mutations to the underlying Y.Doc,
87
- * regardless of source (local kyneta writes, merge, external
88
- * `Y.applyUpdate()`, external raw Yjs API mutations).
89
- *
90
- * @param schema - The schema describing the document structure.
91
- * @param doc - Optional `Y.Doc` instance to wrap. If omitted, a fresh
92
- * empty Y.Doc is created with containers matching the schema.
93
- */
94
- type CreateYjsDoc = <S extends Schema>(schema: S, doc?: Y.Doc) => Ref<S>;
95
- declare const createYjsDoc: CreateYjsDoc;
96
- type CreateYjsDocFromEntirety = <S extends Schema>(schema: S, payload: SubstratePayload) => Ref<S>;
97
- /**
98
- * Reconstruct a live Yjs-backed document from a substrate entirety payload.
99
- *
100
- * The payload must have been produced by `exportEntirety()` on a
101
- * compatible document. This is the entry point for SSR hydration
102
- * and reconnection past log compaction.
103
- *
104
- * ```ts
105
- * const payload = exportEntirety(docA)
106
- * const docB = createYjsDocFromEntirety(MySchema, payload)
107
- * // docB has the same state as docA at the time of export
108
- * ```
109
- */
110
- declare const createYjsDocFromEntirety: CreateYjsDocFromEntirety;
111
-
112
- /**
113
- * Current version as a `YjsVersion` (wrapping a Yjs state vector).
114
- *
115
- * Use `.serialize()` to get a text-safe string for embedding in HTML
116
- * meta tags, URL parameters, etc.
117
- *
118
- * @param doc - A document created by `createYjsDoc` or `createYjsDocFromEntirety`.
119
- * @throws If `doc` was not created by `createYjsDoc` / `createYjsDocFromEntirety`.
120
- */
121
- declare function version(doc: object): YjsVersion;
122
- /**
123
- * Export the full substrate entirety — sufficient for a new peer to
124
- * reconstruct an equivalent document via `createYjsDocFromEntirety()`.
125
- *
126
- * Returns a binary `SubstratePayload` (Yjs state-as-update bytes).
127
- *
128
- * @param doc - A document created by `createYjsDoc` or `createYjsDocFromEntirety`.
129
- * @throws If `doc` was not created by `createYjsDoc` / `createYjsDocFromEntirety`.
130
- */
131
- declare function exportEntirety(doc: object): SubstratePayload;
132
- /**
133
- * Export a delta payload containing all changes since the given version.
134
- *
135
- * Returns a binary `SubstratePayload` (Yjs update bytes), or `null`
136
- * if the delta cannot be computed.
137
- *
138
- * ```ts
139
- * const v0 = version(docA)
140
- * change(docA, d => d.title.insert(0, "Hi"))
141
- * const delta = exportSince(docA, v0)
142
- * merge(docB, delta!)
143
- * ```
144
- *
145
- * @param doc - A document created by `createYjsDoc` or `createYjsDocFromEntirety`.
146
- * @param since - The version to diff from.
147
- * @throws If `doc` was not created by `createYjsDoc` / `createYjsDocFromEntirety`.
148
- */
149
- declare function exportSince(doc: object, since: YjsVersion): SubstratePayload | null;
150
- /**
151
- * Import a delta payload into a live document.
152
- *
153
- * The payload must have been produced by `exportSince()` or
154
- * `exportEntirety()` on a compatible document.
155
- *
156
- * After import, the changefeed fires for all subscribers — the event
157
- * bridge handles this automatically.
158
- *
159
- * ```ts
160
- * const delta = exportSince(docA, sinceVersion)
161
- * merge(docB, delta!, "sync")
162
- * ```
163
- *
164
- * @param doc - A document created by `createYjsDoc` or `createYjsDocFromEntirety`.
165
- * @param payload - The delta or entirety payload to merge.
166
- * @param origin - Optional provenance tag for the changeset.
167
- * @throws If `doc` was not created by `createYjsDoc` / `createYjsDocFromEntirety`.
168
- */
169
- declare function merge(doc: object, payload: SubstratePayload, origin?: string): void;
170
-
171
36
  /**
172
37
  * The Yjs CRDT substrate namespace.
173
38
  *
@@ -175,17 +40,15 @@ declare function merge(doc: object, payload: SubstratePayload, origin?: string):
175
40
  * - `yjs.bind(schema, "ephemeral")` — ephemeral/presence broadcast
176
41
  * - `yjs.replica()` — collaborative replication (default)
177
42
  * - `yjs.replica("ephemeral")` — ephemeral replication
178
- * - `yjs.unwrap(ref)` — access the underlying Y.Doc
179
43
  *
180
44
  * Strategy is constrained to `CrdtStrategy` (`"collaborative" | "ephemeral"`).
181
45
  * Passing `"authoritative"` is a compile error.
46
+ *
47
+ * To access the underlying Y.Doc, use `unwrap(ref)` from `@kyneta/schema`.
182
48
  */
183
49
  /** The closed set of capability tags that the Yjs substrate supports. */
184
50
  type YjsCaps = "text" | "json";
185
- declare const yjs: SubstrateNamespace<CrdtStrategy, YjsCaps> & {
186
- /** Access the underlying `Y.Doc` backing a ref. */
187
- unwrap(ref: object): Y.Doc;
188
- };
51
+ declare const yjs: SubstrateNamespace<CrdtStrategy, YjsCaps, YjsNativeMap>;
189
52
 
190
53
  /**
191
54
  * Apply a kyneta Change to the Yjs shared type tree imperatively.
@@ -260,6 +123,55 @@ declare function ensureContainers(doc: Y.Doc, schema: Schema, conditional?: bool
260
123
  */
261
124
  declare function yjsReader(doc: Y.Doc, schema: Schema): Reader;
262
125
 
126
+ /**
127
+ * A Version wrapping a Yjs state vector.
128
+ *
129
+ * State vectors track the complete peer state — which operations from
130
+ * each client have been observed. This is the right abstraction for sync
131
+ * diffing: `exportSince(version)` uses the state vector to compute the
132
+ * minimal update payload via `Y.encodeStateAsUpdate(doc, sv)`.
133
+ *
134
+ * `serialize()` encodes to base64 for text-safe embedding.
135
+ * `compare()` decodes both state vectors and performs standard
136
+ * version-vector partial-order comparison over the client-clock maps.
137
+ */
138
+ declare class YjsVersion implements Version {
139
+ readonly sv: Uint8Array;
140
+ constructor(sv: Uint8Array);
141
+ /**
142
+ * Serialize the state vector to a base64 string.
143
+ *
144
+ * The encoding is: raw state vector bytes → base64.
145
+ * This is text-safe for embedding in HTML meta tags, URL parameters, etc.
146
+ */
147
+ serialize(): string;
148
+ /**
149
+ * Compare with another version using version-vector partial order.
150
+ *
151
+ * Delegates to the shared `versionVectorCompare` utility after decoding
152
+ * both state vectors via `Y.decodeStateVector()`.
153
+ *
154
+ * @throws If `other` is not a `YjsVersion`.
155
+ */
156
+ compare(other: Version): "behind" | "equal" | "ahead" | "concurrent";
157
+ /**
158
+ * Greatest lower bound (lattice meet) of two Yjs versions.
159
+ *
160
+ * Decodes both state vectors, computes the component-wise minimum
161
+ * via the shared `versionVectorMeet` utility, and encodes the result
162
+ * back to a Yjs state vector.
163
+ *
164
+ * @throws If `other` is not a `YjsVersion`.
165
+ */
166
+ meet(other: Version): YjsVersion;
167
+ /**
168
+ * Parse a serialized YjsVersion string back into a YjsVersion.
169
+ *
170
+ * The inverse of `serialize()`: base64 → `Uint8Array`.
171
+ */
172
+ static parse(serialized: string): YjsVersion;
173
+ }
174
+
263
175
  /**
264
176
  * Creates a `Substrate<YjsVersion>` wrapping a user-provided Y.Doc.
265
177
  *
@@ -310,4 +222,4 @@ declare function stepIntoYjs(current: unknown, segment: Segment): unknown;
310
222
  */
311
223
  declare function resolveYjsType(rootMap: Y.Map<any>, rootSchema: Schema, path: Path): unknown;
312
224
 
313
- export { type YjsCaps, YjsVersion, applyChangeToYjs, createYjsDoc, createYjsDocFromEntirety, createYjsSubstrate, ensureContainers, eventsToOps, exportEntirety, exportSince, merge, resolveYjsType, stepIntoYjs, version, yjs, yjsReader, yjsReplicaFactory, yjsSubstrateFactory };
225
+ export { type YjsCaps, type YjsNativeMap, YjsVersion, applyChangeToYjs, createYjsSubstrate, ensureContainers, eventsToOps, resolveYjsType, stepIntoYjs, yjs, yjsReader, yjsReplicaFactory, yjsSubstrateFactory };