@cocreate/crdt 1.32.0 → 2.0.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/CONTRIBUTING.md CHANGED
@@ -1,19 +1,19 @@
1
1
  # Contributing to CoCreate-crdt
2
2
 
3
- This project is work of [many contributors](https://github.com/CoCreate-app/CoCreate-crdt/graphs/contributors).
4
- You're encouraged to submit [pull requests](https://github.com/CoCreate-app/CoCreate-crdt/pulls),
5
- [propose features and discuss issues](https://github.com/CoCreate-app/CoCreate-crdt/issues).
3
+ This project is work of [many contributors](https://github.com/CoCreateJS/crdt/graphs/contributors).
4
+ You're encouraged to submit [pull requests](https://github.com/CoCreateJS/crdt/pulls),
5
+ [propose features and discuss issues](https://github.com/CoCreateJS/crdt/issues).
6
6
 
7
7
  In the examples below, substitute your Github username for `contributor` in URLs.
8
8
 
9
9
  ## Fork the Project
10
10
 
11
- Fork the [project on Github](https://github.com/CoCreate-app/CoCreate-crdt) and check out your copy.
11
+ Fork the [project on Github](https://github.com/CoCreateJS/crdt) and check out your copy.
12
12
 
13
13
  ```
14
14
  git crdt https://github.com/contributor/CoCreate-crdt.git
15
15
  cd CoCreate-crdt
16
- git remote add upstream https://github.com/CoCreate-app/CoCreate-crdt.git
16
+ git remote add upstream https://github.com/CoCreateJS/crdt.git
17
17
  ```
18
18
 
19
19
  ## Create a Topic Branch
@@ -75,7 +75,7 @@ git push origin my-feature-branch
75
75
 
76
76
  ## Make a Pull Request
77
77
 
78
- Go to [https://github.com/CoCreate-app/CoCreate-crdt](https://github.com/CoCreate-app/CoCreate-crdt) and select your feature branch.
78
+ Go to [https://github.com/CoCreateJS/crdt](https://github.com/CoCreateJS/crdt) and select your feature branch.
79
79
  Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
80
80
 
81
81
  ## Rebase
package/README.md CHANGED
@@ -1,92 +1,180 @@
1
- # CoCreate-crdt
2
-
3
- CoCreate crdt Take it for a spin in our [playground!](https://cocreate.app/docs/crdt)
4
-
5
- ![minified](https://img.badgesize.io/https://cdn.cocreate.app/crdt/latest/CoCreate-crdt.min.js?style=flat-square&label=minified&color=orange)
6
- ![gzip](https://img.badgesize.io/https://cdn.cocreate.app/crdt/latest/CoCreate-crdt.min.js?compression=gzip&style=flat-square&label=gzip&color=yellow)
7
- ![brotli](https://img.badgesize.io/https://cdn.cocreate.app/crdt/latest/CoCreate-crdt.min.js?compression=brotli&style=flat-square&label=brotli)
8
- ![GitHub latest release](https://img.shields.io/github/v/release/CoCreate-app/CoCreate-crdt?style=flat-square)
9
- ![GitHub contributors](https://img.shields.io/github/contributors/CoCreate-app/CoCreate-crdt?style=flat-square)
10
- ![License](https://img.shields.io/static/v1?style=flat-square&label=license&message=AGPL-3.0&color=green)
11
- ![Hiring](https://img.shields.io/static/v1?style=flat-square&label=&message=Hiring&color=blueviolet)
12
-
13
- ![CoCreate-crdt](https://cdn.cocreate.app/docs/CoCreate-crdt.gif)
14
-
15
- ## [Docs & Demo](https://cocreate.app/docs/crdt)
16
-
17
- For a complete guide and working demo refer to the [doumentation](https://cocreate.app/docs/crdt)
18
-
19
- ## CDN
20
-
21
- ```html
22
- <script src="https://cdn.cocreate.app/crdt/latest/CoCreate-crdt.min.js"></script>
23
- ```
24
-
25
- ```html
26
- <script src="https://cdn.cocreate.app/crdt/latest/CoCreate-crdt.min.css"></script>
27
- ```
28
-
29
- ## NPM
30
-
31
- ```shell
32
- $ npm i @cocreate/crdt
33
- ```
34
-
35
- ## yarn
36
-
37
- ```shell
38
- $ yarn install @cocreate/crdt
39
- ```
40
-
41
- # Table of Contents
42
-
43
- - [Table of Contents](#table-of-contents)
44
- - [Announcements](#announcements)
45
- - [Roadmap](#roadmap)
46
- - [How to Contribute](#how-to-contribute)
47
- - [About](#about)
48
- - [License](#license)
49
-
50
- <a name="announcements"></a>
51
-
52
- # Announcements
53
-
54
- All updates to this library are documented in our [CHANGELOG](https://github.com/CoCreate-app/CoCreate-crdt/blob/master/CHANGELOG.md) and [releases](https://github.com/CoCreate-app/CoCreate-crdt/releases). You may also subscribe to email for releases and breaking changes.
55
-
56
- <a name="roadmap"></a>
57
-
58
- # Roadmap
59
-
60
- If you are interested in the future direction of this project, please take a look at our open [issues](https://github.com/CoCreate-app/CoCreate-crdt/issues) and [pull requests](https://github.com/CoCreate-app/CoCreate-crdt/pulls). We would love to hear your feedback.
61
-
62
- <a name="about"></a>
63
-
64
- # About
65
-
66
- CoCreate-crdt is guided and supported by the CoCreate Developer Experience Team.
67
-
68
- Please Email the Developer Experience Team [here](mailto:develop@cocreate.app) in case of any queries.
69
-
70
- CoCreate-crdt is maintained and funded by CoCreate. The names and logos for CoCreate are trademarks of CoCreate, LLC.
71
-
72
- <a name="contribute"></a>
73
-
74
- # How to Contribute
75
-
76
- We encourage contribution to our libraries (you might even score some nifty swag), please see our [CONTRIBUTING](https://github.com/CoCreate-app/CoCreate-crdt/blob/master/CONTRIBUTING.md) guide for details.
77
-
78
- We want this library to be community-driven, and CoCreate led. We need your help to realize this goal. To help make sure we are building the right things in the right order, we ask that you create [issues](https://github.com/CoCreate-app/CoCreate-crdt/issues) and [pull requests](https://github.com/CoCreate-app/CoCreate-crdt/pulls) or merely upvote or comment on existing issues or pull requests.
79
-
80
- We appreciate your continued support, thank you!
81
-
82
- <a name="license"></a>
83
-
84
- # License
85
-
86
- This software is dual-licensed under the GNU Affero General Public License version 3 (AGPLv3) and a commercial license.
87
-
88
- - **Open Source Use**: For open-source projects and non-commercial use, this software is available under the AGPLv3. The AGPLv3 allows you to freely use, modify, and distribute this software, provided that all modifications and derivative works are also licensed under the AGPLv3. For the full license text, see the [LICENSE file](https://github.com/CoCreate-app/CoCreate-crdt/blob/master/LICENSE).
89
-
90
- - **Commercial Use**: For-profit companies and individuals intending to use this software for commercial purposes must obtain a commercial license. The commercial license is available when you sign up for an API key on our [website](https://cocreate.app). This license permits proprietary use and modification of the software without the copyleft requirements of the AGPLv3. It is ideal for integrating this software into proprietary commercial products and applications.
91
-
92
- If you have not purchased a commercial license and intend to use this software for commercial purposes, you are required to sign up for an API key on our website.
1
+ # CoCreate-crdt
2
+
3
+ CoCreate crdt Take it for a spin in our [playground!](https://CoCreateJS.com/docs/crdt)
4
+
5
+ ![minified](https://img.badgesize.io/https://cdn.CoCreateJS.com/crdt/latest/CoCreate-crdt.min.js?style=flat-square&label=minified&color=orange)
6
+ ![gzip](https://img.badgesize.io/https://cdn.CoCreateJS.com/crdt/latest/CoCreate-crdt.min.js?compression=gzip&style=flat-square&label=gzip&color=yellow)
7
+ ![brotli](https://img.badgesize.io/https://cdn.CoCreateJS.com/crdt/latest/CoCreate-crdt.min.js?compression=brotli&style=flat-square&label=brotli)
8
+ ![GitHub latest release](https://img.shields.io/github/v/release/CoCreateJS/crdt?style=flat-square)
9
+ ![GitHub contributors](https://img.shields.io/github/contributors/CoCreateJS/crdt?style=flat-square)
10
+ ![License](https://img.shields.io/static/v1?style=flat-square&label=license&message=AGPL-3.0&color=green)
11
+ ![Hiring](https://img.shields.io/static/v1?style=flat-square&label=&message=Hiring&color=blueviolet)
12
+
13
+ ![CoCreate-crdt](https://cdn.CoCreateJS.com/docs/CoCreate-crdt.gif)
14
+
15
+ ## [Docs & Demo](https://CoCreateJS.com/docs/crdt)
16
+
17
+ For a complete guide and working demo refer to the [doumentation](https://CoCreateJS.com/docs/crdt)
18
+
19
+ ## CDN
20
+
21
+ ```html
22
+ <script src="https://cdn.CoCreateJS.com/crdt/latest/CoCreate-crdt.min.js"></script>
23
+ ```
24
+
25
+ ```html
26
+ <script src="https://cdn.CoCreateJS.com/crdt/latest/CoCreate-crdt.min.css"></script>
27
+ ```
28
+
29
+ ## NPM
30
+
31
+ ```shell
32
+ $ npm i @cocreate/crdt
33
+ ```
34
+
35
+ ## yarn
36
+
37
+ ```shell
38
+ $ yarn install @cocreate/crdt
39
+ ```
40
+
41
+ # Table of Contents
42
+
43
+ - [Table of Contents](#table-of-contents)
44
+ - [Announcements](#announcements)
45
+ - [Roadmap](#roadmap)
46
+ - [How to Contribute](#how-to-contribute)
47
+ - [About](#about)
48
+ - [License](#license)
49
+
50
+ <a name="announcements"></a>
51
+
52
+ # Announcements
53
+
54
+ All updates to this library are documented in our [CHANGELOG](https://github.com/CoCreateJS/crdt/blob/master/CHANGELOG.md) and [releases](https://github.com/CoCreateJS/crdt/releases). You may also subscribe to email for releases and breaking changes.
55
+
56
+ <a name="roadmap"></a>
57
+
58
+ # Roadmap
59
+
60
+ If you are interested in the future direction of this project, please take a look at our open [issues](https://github.com/CoCreateJS/crdt/issues) and [pull requests](https://github.com/CoCreateJS/crdt/pulls). We would love to hear your feedback.
61
+
62
+ <a name="about"></a>
63
+
64
+ # About
65
+
66
+ CoCreate-crdt is guided and supported by the CoCreate Developer Experience Team.
67
+
68
+ Please Email the Developer Experience Team [here](mailto:develop@CoCreateJS.com) in case of any queries.
69
+
70
+ CoCreate-crdt is maintained and funded by CoCreate. The names and logos for CoCreate are trademarks of CoCreate, LLC.
71
+
72
+ <a name="contribute"></a>
73
+
74
+ # How to Contribute
75
+
76
+ We encourage contribution to our libraries (you might even score some nifty swag), please see our [CONTRIBUTING](https://github.com/CoCreateJS/crdt/blob/master/CONTRIBUTING.md) guide for details.
77
+
78
+ We want this library to be community-driven, and CoCreate led. We need your help to realize this goal. To help make sure we are building the right things in the right order, we ask that you create [issues](https://github.com/CoCreateJS/crdt/issues) and [pull requests](https://github.com/CoCreateJS/crdt/pulls) or merely upvote or comment on existing issues or pull requests.
79
+
80
+ We appreciate your continued support, thank you!
81
+
82
+ <a name="license"></a>
83
+
84
+ # License
85
+
86
+ This software is dual-licensed under the GNU Affero General Public License version 3 (AGPLv3) and a commercial license.
87
+
88
+ - **Open Source Use**: For open-source projects and non-commercial use, this software is available under the AGPLv3. The AGPLv3 allows you to freely use, modify, and distribute this software, provided that all modifications and derivative works are also licensed under the AGPLv3. For the full license text, see the [LICENSE file](https://github.com/CoCreateJS/crdt/blob/master/LICENSE).
89
+
90
+ - **Commercial Use**: For-profit companies and individuals intending to use this software for commercial purposes must obtain a commercial license. The commercial license is available when you sign up for an API key on our [website](https://CoCreateJS.com). This license permits proprietary use and modification of the software without the copyleft requirements of the AGPLv3. It is ideal for integrating this software into proprietary commercial products and applications.
91
+
92
+ If you have not purchased a commercial license and intend to use this software for commercial purposes, you are required to sign up for an API key on our website.
93
+
94
+
95
+ ## Public API
96
+
97
+ Everyday text operations are `getText`, `updateText`, `replaceText`, `undoText`,
98
+ and `redoText`. Each receives an object containing `array`, `object`, and `key`.
99
+ `updateText` additionally accepts `start`, `length`, and `value`; `replaceText`
100
+ accepts the complete replacement `value`. `getText` initializes field state when
101
+ needed, so a separate initialization method is unnecessary.
102
+
103
+ Editor integration also uses `updateSelection`, `getSelection`, `getSelections`,
104
+ and `endRun` for presence, selection restoration, and typing boundaries.
105
+
106
+ The mutable registry, identifier construction, version reconstruction, and
107
+ snapshot maintenance stay internal. They are not part of the default public API.
108
+
109
+ ## Identity-based operation tracking
110
+
111
+ Run `npm test` for isolated operation-engine tests with mocked transport and
112
+ storage. New edits use operation format 2. The public `start`, `length`, and
113
+ `value` interface still accepts JavaScript UTF-16 offsets, but each outgoing edit
114
+ also captures:
115
+
116
+ - Stable identities for the exact characters being deleted (`targets`).
117
+ - The deleted text (`removedValue`).
118
+ - Left/right neighbor identities and neighboring character values.
119
+ - Stable identities for inserted characters, derived from operation ID and offset.
120
+
121
+ Replay uses an anchored sequence with retained deletion markers. Two clients
122
+ that both delete the same character therefore delete that identity twice, rather
123
+ than deleting the next surviving character. Character values and neighboring
124
+ text provide context, but are not used to guess which repeated character an
125
+ operation meant. Concurrent insertion runs have deterministic ordering and remain
126
+ contiguous. Operations whose anchor has not arrived remain pending in the sequence
127
+ until that anchor arrives.
128
+
129
+ Undo deletes only the characters created by its edit and removes only that edit's
130
+ deletion markers. Another user's deletions and insertions remain intact. Redo
131
+ inverts the undo operation. Text update events include the canonical `string`, a
132
+ splice against the current visible text, and the original identity `operation`.
133
+ Existing input/textarea consumers can therefore continue applying visible splices.
134
+
135
+ Snapshots retain character identities, deleted anchors, deletion markers and
136
+ processed operation IDs. Late identity edits can still target retained anchors.
137
+ Snapshot persistence appends a checkpoint rather than replacing the stored log,
138
+ so concurrent appends are not overwritten. Physical history/tombstone garbage
139
+ collection is not implemented; the server history remains append-only.
140
+
141
+ Simultaneous readers of the same uninitialized database field derive identical
142
+ baseline IDs from the field scope and text, using SHA-256 through Web Crypto.
143
+ Different initial field values still require application/server reconciliation.
144
+
145
+ ### Compatibility and limits
146
+
147
+ All actively collaborating clients must be updated together to use format 2.
148
+ Historical positional logs remain readable and are assigned deterministic
149
+ identities during replay. The original author intent of already recorded,
150
+ concurrent positional operations cannot be recovered after the fact. Old clients
151
+ will not correctly interpret identity-based deletes, restores, or snapshots.
152
+
153
+ Existing storage keys concatenate array/object/key; changing that format still
154
+ needs a migration to remove potential key collisions. Identity metadata is
155
+ retained for correctness and will grow with editing history. Large-document
156
+ performance and safe physical garbage collection need further work.
157
+
158
+ The tests cover concurrent deletes, repeated characters, concurrent insert/delete
159
+ and replacement, selective undo, out-of-order and duplicate delivery, bootstrap,
160
+ snapshot/reload, Unicode offsets and multi-writer convergence. They do not prove
161
+ every possible schedule or test production transport, browser rendering, cursor
162
+ mapping, authorization or persistence failure recovery. These changes do not
163
+ modify CoCreate-text's DOM rendering or wire Markdown to CRDT automatically.
164
+
165
+ ## Typing runs
166
+
167
+ See [the typing run contract](docs/operations.md). Concurrent runs at the same
168
+ anchor are ordered by persisted `clientId`, then by their first operation's ID
169
+ (`runId`) for runs from the same browser. No user ID, server election or new random
170
+ run identifier participates. Insertion anchors preserve deliberate placement in
171
+ already-observed content.
172
+
173
+ Consecutive insertion-only operations continue a run when the next position and
174
+ last character anchor both match. CRDT automatically ends it on a position break
175
+ or an incoming edit that shifts or interrupts the run. `endRun({ array, object,
176
+ key })` is optional for semantic boundaries without text operations, such as blur
177
+ or submit. The optional boolean flags `runBreak` and
178
+ `runEnd` establish boundaries on a particular edit. Run metadata persists with
179
+ operations and snapshots. Local editing requires Socket Client to have initialized
180
+ its `clientId` and `frameId`.
package/demo/index.html CHANGED
@@ -29,7 +29,7 @@
29
29
  '602c4dadb7fb6c9da35ca126', name: 'html', position: '0', length: 2 })
30
30
 
31
31
  <!--<script src="../dist/CoCreate-crdt.js"></script>-->
32
- <!-- <script src="https://CoCreate.app/dist/CoCreate.js" ></script> -->
33
- <script src="https://CoCreate.app/dist/CoCreate.js"></script>
32
+ <!-- <script src="https://CoCreateJS.com/dist/CoCreate.js" ></script> -->
33
+ <script src="https://CoCreateJS.com/dist/CoCreate.js"></script>
34
34
  </body>
35
35
  </html>
package/docs/index.html CHANGED
@@ -9,7 +9,7 @@
9
9
  rel="icon"
10
10
  type="image/png"
11
11
  sizes="32x32"
12
- href="https://cocreate.app/images/favicon.ico" />
12
+ href="https://CoCreateJS.com/images/favicon.ico" />
13
13
  <meta
14
14
  name="description"
15
15
  content="A simple HTML5 and pure javascript component. Easy configuration using HTML5 attributes or Javscript api and highly styleable." />
@@ -59,7 +59,7 @@
59
59
  share-width="500"
60
60
  share-media="https://via.placeholder.com/300/09f/fff.png">
61
61
  <a
62
- href="https://github.com/CoCreate-app/CoCreate-crdt"
62
+ href="https://github.com/CoCreateJS/CoCreate-crdt"
63
63
  target="_blank"
64
64
  class="margin-right:15px"
65
65
  ><i src="/assets/svg/github.svg"></i
@@ -103,7 +103,7 @@
103
103
  <pre
104
104
  class="margin-top:15px"><code class="language-javascript">npm install cocreate-crdt</code></pre>
105
105
  <p class="padding:10px_0px">Or you can use cdn link:</p>
106
- <pre><code class="language-javascript">https://cdn.cocreate.app/js/CoCreate-crdt.min.js</code></pre>
106
+ <pre><code class="language-javascript">https://cdn.CoCreateJS.com/js/CoCreate-crdt.min.js</code></pre>
107
107
 
108
108
  <h2
109
109
  class="border-bottom:1px_solid_lightgrey margin-top:20px padding:5px_0px">
@@ -247,6 +247,6 @@
247
247
  </div>
248
248
  </main>
249
249
 
250
- <script src="https://CoCreate.app/dist/CoCreate.js"></script>
250
+ <script src="https://CoCreateJS.com/dist/CoCreate.js"></script>
251
251
  </body>
252
252
  </html>
@@ -0,0 +1,159 @@
1
+ # Typing run contract (version 1)
2
+
3
+ This contract extends identity operation format 2. It requires no server-assigned
4
+ rank, extra browser identity, new database collection, or randomly generated run
5
+ identifier. All collaborating clients must use the same ordering implementation.
6
+
7
+ ## Identity and scope
8
+
9
+ The operation's `clientId` is the persisted browser identity supplied by the
10
+ initialized Socket Client. `frameId` identifies its existing page/frame context.
11
+ `user_id` remains useful author metadata but does not participate in ordering.
12
+ The local API rejects ordinary edits before client/frame identity is available;
13
+ it does not invent a fallback browser ID. Scope remains `array/object/key`.
14
+
15
+ ## Operation fields
16
+
17
+ | Field | Meaning |
18
+ | --- | --- |
19
+ | `id` | Unique operation ID; unchanged existing operation contract |
20
+ | `clientId` | Persisted Socket Client browser ID |
21
+ | `frameId` | Existing Socket Client frame ID |
22
+ | `runVersion` | `1` for this grouping contract |
23
+ | `runId` | ID of the first operation in this run |
24
+ | `runIndex` | Zero-based operation number within the run, not a character offset |
25
+ | `runLeft`, `runRight` | Character identities surrounding the initial run insertion |
26
+ | `left`, `right` | Character identities surrounding this individual operation |
27
+
28
+ Each inserted character still has its existing operation-ID/UTF-16-offset identity.
29
+ Runs are grouping metadata; they never replace character identities or deletion
30
+ markers. The server broadcasts and persists the fields with the operation. No
31
+ arrival-order lookup is needed to infer membership during replay.
32
+
33
+ ## Run boundaries
34
+
35
+ CRDT manages run boundaries from the edits it receives. Local tracking is scoped
36
+ to the field, client and frame. An insertion-only operation continues the previous
37
+ run when both its numeric `start` equals the previous insertion's end and its
38
+ left anchor equals the last character inserted by that run. Otherwise it starts
39
+ a new run using its own operation ID. Replacements start a new run; deletes, undo
40
+ and redo close the active run. A whole-value `replaceText` is a standalone run.
41
+
42
+ On a foreign edit, CRDT checks whether the expected next insertion position has
43
+ shifted, whether the last run character was removed, or whether the edit directly
44
+ inserts into or modifies the run. Any of these closes the active run, so the next
45
+ local insertion starts anew. Concurrent insertion elsewhere that leaves the run
46
+ and expected position intact does not end it.
47
+
48
+ No editor call is required to detect a changed insertion position or an incoming
49
+ edit that breaks sequential positioning. `endRun({ array, object, key })` remains
50
+ an optional semantic boundary for events with no text operation, such as blur,
51
+ submit or an explicit move away and back to the identical position. CRDT cannot
52
+ observe a cursor move with no accompanying edit. Boolean `runBreak: true` and
53
+ `runEnd: true` can also establish boundaries on an edit when the integration knows
54
+ its intent (for example a standalone paste). There is no idle timeout or heuristic
55
+ that assumes every multi-character input is a paste.
56
+
57
+ ```js
58
+ await crdt.updateText({ array, object, key, realtime: true, start: 0, value: 'H' });
59
+ await crdt.updateText({ array, object, key, realtime: true, start: 1, value: 'i' });
60
+ // These operations share the first operation's ID as runId, with indexes 0 and 1.
61
+ crdt.endRun({ array, object, key });
62
+ await crdt.updateText({ array, object, key, realtime: true, start: 2, value: '!' });
63
+ // This operation starts a new run with its own ID.
64
+ ```
65
+
66
+ Only `realtime: true` publishes an operation to other elements, the socket, or
67
+ storage. A private editor can provide a stable, editor-specific `scope` and
68
+ `initialValue` to keep its history in memory. It can also provide the originating
69
+ `element`; CRDT returns the update event with that element as its sole target.
70
+ The element reference is excluded from the history log and socket packet. Undo
71
+ and redo use the same scope. A Save action can publish the completed string with
72
+ a separate realtime `replaceText` call against the shared array/object/key.
73
+
74
+ ## Ordering
75
+
76
+ Character anchors determine document placement. For concurrent insertion branches
77
+ at the same anchor, compare `clientId` as case-sensitive code-unit strings,
78
+ ascending. For separate runs from the same browser, compare `runId` ascending.
79
+ Existing operation IDs resolve remaining ties. The rank is a comparison rule,
80
+ not an integer stored or recalculated from the connected participant list.
81
+
82
+ A continuation stays inside its run's branch. Explicit placement before content
83
+ an author already observed takes precedence over concurrent priority: a deliberate
84
+ insertion inside an existing run is allowed to split that run. Right-anchor
85
+ constraints establish that placement before concurrent branch ordering is applied.
86
+
87
+ Historical operations without run metadata retain their operation-ID ordering.
88
+ Snapshots retain the node client/run metadata and insertion boundaries, so replay
89
+ uses the same rule after compaction. Clients reconnecting do not rewrite previous
90
+ run membership; a new frame starts new local run tracking.
91
+
92
+ ## Validation coverage
93
+
94
+ Tests cover four concurrent character-by-character runs, reversed delivery,
95
+ multiple frames sharing one client, explicit/inferred boundaries, deliberate
96
+ insertions inside existing content and the existing identity/snapshot regressions.
97
+ Changed write positions and foreign interruptions are detected inside CRDT.
98
+ Optional non-writing editor actions can explicitly end a run; network and browser
99
+ integration testing remain separate work.
100
+
101
+ ## Selections and shared presence
102
+
103
+ Text and selection use the same `crdt` socket method and field scope. An optional
104
+ `selection` on `updateText` describes the **resulting** source selection after
105
+ that edit, with directional UTF-16 offsets:
106
+
107
+ ```js
108
+ await crdt.updateText({
109
+ array, object, key, realtime: true, start: 0, value: 'hello',
110
+ selection: { anchor: 5, head: 2 }
111
+ });
112
+ await crdt.updateSelection({ array, object, key, realtime: true, selection: { anchor: 2, head: 2 } });
113
+ await crdt.updateSelection({ array, object, key, realtime: true, selection: null }); // blur/hide
114
+ ```
115
+
116
+ Each endpoint becomes `{ left, right, affinity }`, where left and right are
117
+ stable neighboring character IDs (or null at a boundary). Default affinity is
118
+ `left`: a cursor stays immediately after its left neighbor when another writer
119
+ inserts into the same gap. Callers may also supply these endpoint references
120
+ with `affinity: 'right'` to stay before the right neighbor. Deleted neighbors
121
+ remain resolvable through tombstones. Unknown references wait until their text
122
+ arrives. Anchor/head preserve backward selections; they are not normalized away.
123
+
124
+ Editor adapters can supply a synchronous local `captureSelection()` callback
125
+ instead of numeric `selection`. CRDT calls it after dispatching the text update
126
+ so it reads the actual resulting editor selection. The callback never travels
127
+ on the socket or enters history. A callback failure does not stop broadcasting
128
+ or saving an already-applied text edit.
129
+
130
+ A text operation and its selection share one packet and history entry.
131
+ `updateSelection` sends `type: 'selection'` without a text operation ID, document
132
+ save, or undo entry. A changed position ends the local typing run; duplicate
133
+ positions are suppressed and metadata-only updates preserve the run. A per-frame
134
+ `selectionClock` prevents older packets from replacing a newer selection.
135
+ Selection-only updates are transient and are not restored from document history.
136
+ Optional `presence` carries display metadata such as userName and cursor colors.
137
+
138
+ `cocreate-crdt-selection` exposes `selection` references and a `resolved`
139
+ `{ anchor, head, start, end }` for the current source text (null for blur).
140
+ Known selections are resolved again after subsequent edits. Editor owns browser
141
+ selection capture and source-to-DOM mapping; its `cursors.js` renders remote
142
+ presence. CRDT owns transport for both text and presence. Editor surfaces do not
143
+ need the legacy Cursors package or Selection's former HTML-string position APIs.
144
+
145
+ For loaded fields, `updateSelection` anchors and caches the selection synchronously
146
+ before returning its Promise. `crdt.getSelection({array, object, key})` synchronously
147
+ returns the current local `{anchor, head, start, end}`, `undefined` before capture
148
+ or while references are unresolved, and `null` after clearing. Optional `clientId`
149
+ and `frameId` select another participant. Editor can restore the cached local
150
+ selection after a remote edit without rereading its source position from the DOM.
151
+
152
+ `crdt.getSelections({array, object, key})` returns current resolved presence entries
153
+ in the same shape as the selection event, including cleared entries. This lets a
154
+ newly bound editor display presence already known to CRDT. Returned anchor and
155
+ metadata objects are copied. One offset index per replayed sequence serves all
156
+ participants, including tombstone anchors.
157
+
158
+ Incoming presence requires a valid participant/frame and a positive safe-integer
159
+ clock. Invalid presence is ignored without dropping an accompanying text operation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/crdt",
3
- "version": "1.32.0",
3
+ "version": "2.0.0",
4
4
  "description": "CoCreate crdt",
5
5
  "author": "CoCreate LLC",
6
6
  "license": "AGPL-3.0",
@@ -10,28 +10,29 @@
10
10
  "scripts": {
11
11
  "start": "webpack --config webpack.config.js",
12
12
  "build": "webpack --mode=production --config webpack.config.js",
13
- "dev": "webpack --config webpack.config.js --watch"
13
+ "dev": "webpack --config webpack.config.js --watch",
14
+ "test": "node --test test/*.test.cjs"
14
15
  },
15
16
  "repository": {
16
17
  "type": "git",
17
- "url": "git+https://github.com/CoCreate-app/CoCreate-crdt.git"
18
+ "url": "git+https://github.com/CoCreateJS/crdt.git"
18
19
  },
19
20
  "bugs": {
20
- "url": "https://github.com/CoCreate-app/CoCreate-crdt/issues"
21
+ "url": "https://github.com/CoCreateJS/crdt/issues"
21
22
  },
22
- "homepage": "https://cocreate.app/docs/crdt",
23
+ "homepage": "https://CoCreateJS.com/docs/crdt",
23
24
  "funding": {
24
25
  "type": "GitHub Sponsors ❤",
25
- "url": "https://github.com/sponsors/CoCreate-app"
26
+ "url": "https://github.com/sponsors/CoCreateJS"
26
27
  },
27
28
  "main": "./src/index.js",
28
29
  "dependencies": {
29
- "@cocreate/crud-client": "^1.36.1",
30
- "@cocreate/local-storage": "^1.19.0",
31
- "@cocreate/utils": "^1.52.0"
30
+ "@cocreate/crud-client": "^1.37.0",
31
+ "@cocreate/local-storage": "^1.20.0",
32
+ "@cocreate/utils": "^1.54.0"
32
33
  },
33
34
  "devDependencies": {
34
- "@cocreate/webpack": "^1.8.0"
35
+ "@cocreate/webpack": "^1.9.0"
35
36
  },
36
37
  "allowScripts": {
37
38
  "@cocreate/actions@1.21.4": true,