mirror of
https://github.com/loro-dev/loro.git
synced 2024-11-24 12:20:06 +00:00
Refactor: merge two js packages (#532)
* feat: make vitest tests pass * chore: update readme & add deno test for web bundle * chore: bump version to 1.0.8-alpha.0 * chore: bump loro-crdt version * fix: build script export init method from loro-wasm/web * chore: bump version * chore: specify which files to include for npm publish * refactor: rename loro-js to loro-js-test * refactor: remove the old loro-js folder * fix: build scripts * chore: 1.0.8-alpha.3 * chore: add release info
This commit is contained in:
parent
e2be56b0c2
commit
62a3a93552
55 changed files with 1604 additions and 4024 deletions
|
@ -3,12 +3,7 @@
|
||||||
"changelog": "@changesets/changelog-git",
|
"changelog": "@changesets/changelog-git",
|
||||||
"commit": false,
|
"commit": false,
|
||||||
"fixed": [],
|
"fixed": [],
|
||||||
"linked": [
|
"linked": [],
|
||||||
[
|
|
||||||
"loro-wasm",
|
|
||||||
"loro-crdt"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"access": "public",
|
"access": "public",
|
||||||
"baseBranch": "main",
|
"baseBranch": "main",
|
||||||
"updateInternalDependencies": "patch",
|
"updateInternalDependencies": "patch",
|
||||||
|
|
5
.changeset/wise-balloons-sniff.md
Normal file
5
.changeset/wise-balloons-sniff.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"loro-crdt": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Merge two js packages
|
|
@ -11,9 +11,9 @@ src/
|
||||||
wasm-size/
|
wasm-size/
|
||||||
web-test/
|
web-test/
|
||||||
pkg/
|
pkg/
|
||||||
web/
|
|
||||||
scripts/
|
scripts/
|
||||||
.cargo/
|
.cargo/
|
||||||
CHANGELOG.md
|
|
||||||
Cargo.toml
|
Cargo.toml
|
||||||
deno.lock
|
deno.lock
|
||||||
|
rollup.config.mjs
|
||||||
|
tsconfig.json
|
||||||
|
|
|
@ -1,5 +1,29 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 1.0.8-alpha.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Fix build for bundler
|
||||||
|
|
||||||
|
## 1.0.8-alpha.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Fix build script for web target
|
||||||
|
|
||||||
|
## 1.0.8-alpha.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Include the build for web
|
||||||
|
|
||||||
|
## 1.0.8-alpha.0
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Refactor simplify js binding
|
||||||
|
|
||||||
## 1.0.7
|
## 1.0.7
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
|
@ -38,11 +38,11 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
https://github.com/loro-dev/loro/assets/18425020/fe246c47-a120-44b3-91d4-1e7232a5b4ac
|
<h4 align="center">
|
||||||
|
✨ Loro 1.0 is out! Read the <a href="https://loro.dev/blog/v1.0">announcement</a>.
|
||||||
|
</h4>
|
||||||
|
|
||||||
Loro is a [CRDTs(Conflict-free Replicated Data Types)](https://crdt.tech/) library that makes building [local-first apps][local-first] easier. It is currently available for JavaScript (via WASM) and Rust developers.
|
Loro is a [CRDTs(Conflict-free Replicated Data Types)](https://crdt.tech/) library that makes building [local-first apps][local-first] easier. It is currently available for JavaScript (via WASM) and Rust developers.
|
||||||
|
|
||||||
Explore our vision in our blog: [**✨ Reimagine State Management with CRDTs**](https://loro.dev/blog/loro-now-open-source).
|
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
|
@ -65,10 +65,13 @@ Explore our vision in our blog: [**✨ Reimagine State Management with CRDTs**](
|
||||||
|
|
||||||
**Advanced Features in Loro**
|
**Advanced Features in Loro**
|
||||||
|
|
||||||
- 📖 Preserve Editing History in a [Replayable Event Graph](https://loro.dev/docs/advanced/replayable_event_graph)
|
|
||||||
- ⏱️ Fast [Time Travel](https://loro.dev/docs/tutorial/time_travel) Through History
|
- ⏱️ Fast [Time Travel](https://loro.dev/docs/tutorial/time_travel) Through History
|
||||||
|
- 🏛️ [Version Control with Real-Time Collaboration](https://loro.dev/blog/v1.0#version-control)
|
||||||
|
- 📦 [Shallow Snapshot](https://loro.dev/docs/advanced/shallow_snapshot) that Works like Git Shallow Clone
|
||||||
|
|
||||||
https://github.com/loro-dev/loro/assets/18425020/ec2d20a3-3d8c-4483-a601-b200243c9792
|
|
||||||
|
> In this example, we demonstrate importing an entire Loro codebase into a Loro-powered
|
||||||
|
> version controller, preserving the complete Git DAG history while enabling fast version switching.
|
||||||
|
|
||||||
# Example
|
# Example
|
||||||
|
|
||||||
|
@ -76,48 +79,50 @@ https://github.com/loro-dev/loro/assets/18425020/ec2d20a3-3d8c-4483-a601-b200243
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { expect, test } from 'vitest';
|
import { expect, test } from 'vitest';
|
||||||
import { Loro, LoroList } from 'loro-crdt';
|
import { LoroDoc, LoroList } from 'loro-crdt';
|
||||||
|
|
||||||
/**
|
test('sync example', () => {
|
||||||
* Demonstrates synchronization of two documents with two rounds of exchanges.
|
/**
|
||||||
*/
|
* Demonstrates synchronization of two documents with two rounds of exchanges.
|
||||||
// Initialize document A
|
*/
|
||||||
const docA = new Loro();
|
// Initialize document A
|
||||||
const listA: LoroList = docA.getList('list');
|
const docA = new LoroDoc();
|
||||||
listA.insert(0, 'A');
|
const listA: LoroList = docA.getList('list');
|
||||||
listA.insert(1, 'B');
|
listA.insert(0, 'A');
|
||||||
listA.insert(2, 'C');
|
listA.insert(1, 'B');
|
||||||
|
listA.insert(2, 'C');
|
||||||
|
|
||||||
// Export the state of document A as a byte array
|
// Export the state of document A as a byte array
|
||||||
const bytes: Uint8Array = docA.exportFrom();
|
const bytes: Uint8Array = docA.export({ mode: 'update' });
|
||||||
|
|
||||||
// Simulate sending `bytes` across the network to another peer, B
|
// Simulate sending `bytes` across the network to another peer, B
|
||||||
const docB = new Loro();
|
const docB = new LoroDoc();
|
||||||
// Peer B imports the updates from A
|
// Peer B imports the updates from A
|
||||||
docB.import(bytes);
|
docB.import(bytes);
|
||||||
|
|
||||||
// Verify that B's state matches A's state
|
// Verify that B's state matches A's state
|
||||||
expect(docB.toJSON()).toStrictEqual({
|
expect(docB.toJSON()).toStrictEqual({
|
||||||
list: ['A', 'B', 'C'],
|
list: ['A', 'B', 'C'],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get the current operation log version of document B
|
// Get the current operation log version of document B
|
||||||
const version = docB.oplogVersion();
|
const version = docB.oplogVersion();
|
||||||
|
|
||||||
// Simulate editing at B: delete item 'B'
|
// Simulate editing at B: delete item 'B'
|
||||||
const listB: LoroList = docB.getList('list');
|
const listB: LoroList = docB.getList('list');
|
||||||
listB.delete(1, 1);
|
listB.delete(1, 1);
|
||||||
|
|
||||||
// Export the updates from B since the last synchronization point
|
// Export the updates from B since the last synchronization point
|
||||||
const bytesB: Uint8Array = docB.exportFrom(version);
|
const bytesB: Uint8Array = docB.export({ mode: 'update', from: version });
|
||||||
|
|
||||||
// Simulate sending `bytesB` back across the network to A
|
// Simulate sending `bytesB` back across the network to A
|
||||||
// A imports the updates from B
|
// A imports the updates from B
|
||||||
docA.import(bytesB);
|
docA.import(bytesB);
|
||||||
|
|
||||||
// Verify that the list at A now matches the list at B after merging
|
// Verify that the list at A now matches the list at B after merging
|
||||||
expect(docA.toJSON()).toStrictEqual({
|
expect(docA.toJSON()).toStrictEqual({
|
||||||
list: ['A', 'C'],
|
list: ['A', 'C'],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -126,9 +131,9 @@ expect(docA.toJSON()).toStrictEqual({
|
||||||
Loro draws inspiration from the innovative work of the following projects and individuals:
|
Loro draws inspiration from the innovative work of the following projects and individuals:
|
||||||
|
|
||||||
- [Ink & Switch](https://inkandswitch.com/): The principles of Local-first Software have greatly influenced this project. The [Peritext](https://www.inkandswitch.com/peritext/) project has also shaped our approach to rich text CRDTs.
|
- [Ink & Switch](https://inkandswitch.com/): The principles of Local-first Software have greatly influenced this project. The [Peritext](https://www.inkandswitch.com/peritext/) project has also shaped our approach to rich text CRDTs.
|
||||||
- [Diamond-types](https://github.com/josephg/diamond-types): The [Replayable Event Graph (REG)](https://loro.dev/docs/advanced/replayable_event_graph) algorithm from @josephg has been adapted to reduce the computation and space usage of CRDTs.
|
- [Diamond-types](https://github.com/josephg/diamond-types): The [Event Graph Walker (Eg-walker)](https://loro.dev/docs/advanced/event_graph_walker) algorithm from @josephg has been adapted to reduce the computation and space usage of CRDTs.
|
||||||
- [Automerge](https://github.com/automerge/automerge): Their use of columnar encoding for CRDTs has informed our strategies for efficient data encoding.
|
- [Automerge](https://github.com/automerge/automerge): Their use of columnar encoding for CRDTs has informed our strategies for efficient data encoding.
|
||||||
- [Yjs](https://github.com/yjs/yjs): We have incorporated a similar algorithm for effectively merging collaborative editing operations, thanks to their pioneering works.
|
- [Yjs](https://github.com/yjs/yjs): We have incorporated a similar algorithm for effectively merging collaborative editing operations, thanks to their pioneering work.
|
||||||
- [Matthew Weidner](https://mattweidner.com/): His work on the [Fugue](https://arxiv.org/abs/2305.00583) algorithm has been invaluable, enhancing our text editing capabilities.
|
- [Matthew Weidner](https://mattweidner.com/): His work on the [Fugue](https://arxiv.org/abs/2305.00583) algorithm has been invaluable, enhancing our text editing capabilities.
|
||||||
- [Martin Kleppmann](https://martin.kleppmann.com/): His work on CRDTs has significantly influenced our comprehension of the field.
|
- [Martin Kleppmann](https://martin.kleppmann.com/): His work on CRDTs has significantly influenced our comprehension of the field.
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
{
|
{
|
||||||
"version": "3",
|
"version": "4",
|
||||||
"redirects": {
|
"redirects": {
|
||||||
"https://deno.land/std/archive/mod.ts": "https://deno.land/std@0.224.0/archive/mod.ts",
|
"https://deno.land/std/archive/mod.ts": "https://deno.land/std@0.224.0/archive/mod.ts",
|
||||||
"https://deno.land/std/encoding/base64.ts": "https://deno.land/std@0.224.0/encoding/base64.ts",
|
"https://deno.land/std/encoding/base64.ts": "https://deno.land/std@0.224.0/encoding/base64.ts",
|
||||||
|
"https://deno.land/std/fs/mod.ts": "https://deno.land/std@0.224.0/fs/mod.ts",
|
||||||
"https://x.nest.land/std@0.73.0/path/mod.ts": "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/mod.ts"
|
"https://x.nest.land/std@0.73.0/path/mod.ts": "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/mod.ts"
|
||||||
},
|
},
|
||||||
"remote": {
|
"remote": {
|
||||||
|
@ -100,11 +101,73 @@
|
||||||
"https://deno.land/std@0.224.0/bytes/copy.ts": "08d85062240a7223e6ec4e2af193ad1a50c59a43f0d86ac3a7b16f3e0d77c028",
|
"https://deno.land/std@0.224.0/bytes/copy.ts": "08d85062240a7223e6ec4e2af193ad1a50c59a43f0d86ac3a7b16f3e0d77c028",
|
||||||
"https://deno.land/std@0.224.0/encoding/_util.ts": "beacef316c1255da9bc8e95afb1fa56ed69baef919c88dc06ae6cb7a6103d376",
|
"https://deno.land/std@0.224.0/encoding/_util.ts": "beacef316c1255da9bc8e95afb1fa56ed69baef919c88dc06ae6cb7a6103d376",
|
||||||
"https://deno.land/std@0.224.0/encoding/base64.ts": "dd59695391584c8ffc5a296ba82bcdba6dd8a84d41a6a539fbee8e5075286eaf",
|
"https://deno.land/std@0.224.0/encoding/base64.ts": "dd59695391584c8ffc5a296ba82bcdba6dd8a84d41a6a539fbee8e5075286eaf",
|
||||||
|
"https://deno.land/std@0.224.0/fs/_create_walk_entry.ts": "5d9d2aaec05bcf09a06748b1684224d33eba7a4de24cf4cf5599991ca6b5b412",
|
||||||
|
"https://deno.land/std@0.224.0/fs/_get_file_info_type.ts": "da7bec18a7661dba360a1db475b826b18977582ce6fc9b25f3d4ee0403fe8cbd",
|
||||||
|
"https://deno.land/std@0.224.0/fs/_is_same_path.ts": "709c95868345fea051c58b9e96af95cff94e6ae98dfcff2b66dee0c212c4221f",
|
||||||
|
"https://deno.land/std@0.224.0/fs/_is_subdir.ts": "c68b309d46cc8568ed83c000f608a61bbdba0943b7524e7a30f9e450cf67eecd",
|
||||||
|
"https://deno.land/std@0.224.0/fs/_to_path_string.ts": "29bfc9c6c112254961d75cbf6ba814d6de5349767818eb93090cecfa9665591e",
|
||||||
|
"https://deno.land/std@0.224.0/fs/copy.ts": "7ab12a16adb65d155d4943c88081ca16ce3b0b5acada64c1ce93800653678039",
|
||||||
|
"https://deno.land/std@0.224.0/fs/empty_dir.ts": "e400e96e1d2c8c558a5a1712063bd43939e00619c1d1cc29959babc6f1639418",
|
||||||
|
"https://deno.land/std@0.224.0/fs/ensure_dir.ts": "51a6279016c65d2985f8803c848e2888e206d1b510686a509fa7cc34ce59d29f",
|
||||||
|
"https://deno.land/std@0.224.0/fs/ensure_file.ts": "67608cf550529f3d4aa1f8b6b36bf817bdc40b14487bf8f60e61cbf68f507cf3",
|
||||||
|
"https://deno.land/std@0.224.0/fs/ensure_link.ts": "5c98503ebfa9cc05e2f2efaa30e91e60b4dd5b43ebbda82f435c0a5c6e3ffa01",
|
||||||
|
"https://deno.land/std@0.224.0/fs/ensure_symlink.ts": "cafe904cebacb9a761977d6dbf5e3af938be946a723bb394080b9a52714fafe4",
|
||||||
|
"https://deno.land/std@0.224.0/fs/eol.ts": "18c4ac009d0318504c285879eb7f47942643f13619e0ff070a0edc59353306bd",
|
||||||
|
"https://deno.land/std@0.224.0/fs/exists.ts": "3d38cb7dcbca3cf313be343a7b8af18a87bddb4b5ca1bd2314be12d06533b50f",
|
||||||
|
"https://deno.land/std@0.224.0/fs/expand_glob.ts": "2e428d90acc6676b2aa7b5c78ef48f30641b13f1fe658e7976c9064fb4b05309",
|
||||||
|
"https://deno.land/std@0.224.0/fs/mod.ts": "c25e6802cbf27f3050f60b26b00c2d8dba1cb7fcdafe34c66006a7473b7b34d4",
|
||||||
|
"https://deno.land/std@0.224.0/fs/move.ts": "ca205d848908d7f217353bc5c623627b1333490b8b5d3ef4cab600a700c9bd8f",
|
||||||
|
"https://deno.land/std@0.224.0/fs/walk.ts": "cddf87d2705c0163bff5d7767291f05b0f46ba10b8b28f227c3849cace08d303",
|
||||||
"https://deno.land/std@0.224.0/io/_constants.ts": "3c7ad4695832e6e4a32e35f218c70376b62bc78621ef069a4a0a3d55739f8856",
|
"https://deno.land/std@0.224.0/io/_constants.ts": "3c7ad4695832e6e4a32e35f218c70376b62bc78621ef069a4a0a3d55739f8856",
|
||||||
"https://deno.land/std@0.224.0/io/buf_reader.ts": "aa6d589e567c964c8ba1f582648f3feac45e88ab2e3d2cc2c9f84fd73c05d051",
|
"https://deno.land/std@0.224.0/io/buf_reader.ts": "aa6d589e567c964c8ba1f582648f3feac45e88ab2e3d2cc2c9f84fd73c05d051",
|
||||||
"https://deno.land/std@0.224.0/io/buffer.ts": "4d1f805f350433e418002accec798bc6c33ce18f614afa65f987c202d7b2234e",
|
"https://deno.land/std@0.224.0/io/buffer.ts": "4d1f805f350433e418002accec798bc6c33ce18f614afa65f987c202d7b2234e",
|
||||||
"https://deno.land/std@0.224.0/io/multi_reader.ts": "dd8f06d50adec0e1befb92a1d354fcf28733a4b1669b23bf534ace161ce61b1c",
|
"https://deno.land/std@0.224.0/io/multi_reader.ts": "dd8f06d50adec0e1befb92a1d354fcf28733a4b1669b23bf534ace161ce61b1c",
|
||||||
"https://deno.land/std@0.224.0/io/read_all.ts": "876c1cb20adea15349c72afc86cecd3573335845ae778967aefb5e55fe5a8a4a",
|
"https://deno.land/std@0.224.0/io/read_all.ts": "876c1cb20adea15349c72afc86cecd3573335845ae778967aefb5e55fe5a8a4a",
|
||||||
|
"https://deno.land/std@0.224.0/path/_common/assert_path.ts": "dbdd757a465b690b2cc72fc5fb7698c51507dec6bfafce4ca500c46b76ff7bd8",
|
||||||
|
"https://deno.land/std@0.224.0/path/_common/basename.ts": "569744855bc8445f3a56087fd2aed56bdad39da971a8d92b138c9913aecc5fa2",
|
||||||
|
"https://deno.land/std@0.224.0/path/_common/constants.ts": "dc5f8057159f4b48cd304eb3027e42f1148cf4df1fb4240774d3492b5d12ac0c",
|
||||||
|
"https://deno.land/std@0.224.0/path/_common/dirname.ts": "684df4aa71a04bbcc346c692c8485594fc8a90b9408dfbc26ff32cf3e0c98cc8",
|
||||||
|
"https://deno.land/std@0.224.0/path/_common/from_file_url.ts": "d672bdeebc11bf80e99bf266f886c70963107bdd31134c4e249eef51133ceccf",
|
||||||
|
"https://deno.land/std@0.224.0/path/_common/glob_to_reg_exp.ts": "6cac16d5c2dc23af7d66348a7ce430e5de4e70b0eede074bdbcf4903f4374d8d",
|
||||||
|
"https://deno.land/std@0.224.0/path/_common/normalize.ts": "684df4aa71a04bbcc346c692c8485594fc8a90b9408dfbc26ff32cf3e0c98cc8",
|
||||||
|
"https://deno.land/std@0.224.0/path/_common/normalize_string.ts": "33edef773c2a8e242761f731adeb2bd6d683e9c69e4e3d0092985bede74f4ac3",
|
||||||
|
"https://deno.land/std@0.224.0/path/_common/strip_trailing_separators.ts": "7024a93447efcdcfeaa9339a98fa63ef9d53de363f1fbe9858970f1bba02655a",
|
||||||
|
"https://deno.land/std@0.224.0/path/_os.ts": "8fb9b90fb6b753bd8c77cfd8a33c2ff6c5f5bc185f50de8ca4ac6a05710b2c15",
|
||||||
|
"https://deno.land/std@0.224.0/path/basename.ts": "7ee495c2d1ee516ffff48fb9a93267ba928b5a3486b550be73071bc14f8cc63e",
|
||||||
|
"https://deno.land/std@0.224.0/path/constants.ts": "0c206169ca104938ede9da48ac952de288f23343304a1c3cb6ec7625e7325f36",
|
||||||
|
"https://deno.land/std@0.224.0/path/dirname.ts": "85bd955bf31d62c9aafdd7ff561c4b5fb587d11a9a5a45e2b01aedffa4238a7c",
|
||||||
|
"https://deno.land/std@0.224.0/path/from_file_url.ts": "911833ae4fd10a1c84f6271f36151ab785955849117dc48c6e43b929504ee069",
|
||||||
|
"https://deno.land/std@0.224.0/path/glob_to_regexp.ts": "7f30f0a21439cadfdae1be1bf370880b415e676097fda584a63ce319053b5972",
|
||||||
|
"https://deno.land/std@0.224.0/path/is_absolute.ts": "4791afc8bfd0c87f0526eaa616b0d16e7b3ab6a65b62942e50eac68de4ef67d7",
|
||||||
|
"https://deno.land/std@0.224.0/path/is_glob.ts": "a65f6195d3058c3050ab905705891b412ff942a292bcbaa1a807a74439a14141",
|
||||||
|
"https://deno.land/std@0.224.0/path/join.ts": "ae2ec5ca44c7e84a235fd532e4a0116bfb1f2368b394db1c4fb75e3c0f26a33a",
|
||||||
|
"https://deno.land/std@0.224.0/path/join_globs.ts": "5b3bf248b93247194f94fa6947b612ab9d3abd571ca8386cf7789038545e54a0",
|
||||||
|
"https://deno.land/std@0.224.0/path/normalize.ts": "4155743ccceeed319b350c1e62e931600272fad8ad00c417b91df093867a8352",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/_util.ts": "1e3937da30f080bfc99fe45d7ed23c47dd8585c5e473b2d771380d3a6937cf9d",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/basename.ts": "d2fa5fbbb1c5a3ab8b9326458a8d4ceac77580961b3739cd5bfd1d3541a3e5f0",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/constants.ts": "93481efb98cdffa4c719c22a0182b994e5a6aed3047e1962f6c2c75b7592bef1",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/dirname.ts": "76cd348ffe92345711409f88d4d8561d8645353ac215c8e9c80140069bf42f00",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/from_file_url.ts": "951aee3a2c46fd0ed488899d024c6352b59154c70552e90885ed0c2ab699bc40",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/glob_to_regexp.ts": "76f012fcdb22c04b633f536c0b9644d100861bea36e9da56a94b9c589a742e8f",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/is_absolute.ts": "cebe561ad0ae294f0ce0365a1879dcfca8abd872821519b4fcc8d8967f888ede",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/join.ts": "7fc2cb3716aa1b863e990baf30b101d768db479e70b7313b4866a088db016f63",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/join_globs.ts": "a9475b44645feddceb484ee0498e456f4add112e181cb94042cdc6d47d1cdd25",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/normalize.ts": "baeb49816a8299f90a0237d214cef46f00ba3e95c0d2ceb74205a6a584b58a91",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/normalize_glob.ts": "9c87a829b6c0f445d03b3ecadc14492e2864c3ebb966f4cea41e98326e4435c6",
|
||||||
|
"https://deno.land/std@0.224.0/path/posix/resolve.ts": "08b699cfeee10cb6857ccab38fa4b2ec703b0ea33e8e69964f29d02a2d5257cf",
|
||||||
|
"https://deno.land/std@0.224.0/path/resolve.ts": "a6f977bdb4272e79d8d0ed4333e3d71367cc3926acf15ac271f1d059c8494d8d",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/_util.ts": "d5f47363e5293fced22c984550d5e70e98e266cc3f31769e1710511803d04808",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/basename.ts": "6bbc57bac9df2cec43288c8c5334919418d784243a00bc10de67d392ab36d660",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/constants.ts": "5afaac0a1f67b68b0a380a4ef391bf59feb55856aa8c60dfc01bd3b6abb813f5",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/dirname.ts": "33e421be5a5558a1346a48e74c330b8e560be7424ed7684ea03c12c21b627bc9",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/from_file_url.ts": "ced2d587b6dff18f963f269d745c4a599cf82b0c4007356bd957cb4cb52efc01",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/glob_to_regexp.ts": "e45f1f89bf3fc36f94ab7b3b9d0026729829fabc486c77f414caebef3b7304f8",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/is_absolute.ts": "4a8f6853f8598cf91a835f41abed42112cebab09478b072e4beb00ec81f8ca8a",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/join.ts": "8d03530ab89195185103b7da9dfc6327af13eabdcd44c7c63e42e27808f50ecf",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/join_globs.ts": "a9475b44645feddceb484ee0498e456f4add112e181cb94042cdc6d47d1cdd25",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/normalize.ts": "78126170ab917f0ca355a9af9e65ad6bfa5be14d574c5fb09bb1920f52577780",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/normalize_glob.ts": "9c87a829b6c0f445d03b3ecadc14492e2864c3ebb966f4cea41e98326e4435c6",
|
||||||
|
"https://deno.land/std@0.224.0/path/windows/resolve.ts": "8dae1dadfed9d46ff46cc337c9525c0c7d959fb400a6308f34595c45bdca1972",
|
||||||
"https://deno.land/x/compress@v0.4.5/deps.ts": "096395daebc7ed8a18f0484e4ffcc3a7f70e50946735f7df9611a7fcfd8272cc",
|
"https://deno.land/x/compress@v0.4.5/deps.ts": "096395daebc7ed8a18f0484e4ffcc3a7f70e50946735f7df9611a7fcfd8272cc",
|
||||||
"https://deno.land/x/compress@v0.4.5/gzip/gzip.ts": "4bf22e9cd3368332928324dd9443ef72cabd05e9234e5a37dd7b3517d50e945e",
|
"https://deno.land/x/compress@v0.4.5/gzip/gzip.ts": "4bf22e9cd3368332928324dd9443ef72cabd05e9234e5a37dd7b3517d50e945e",
|
||||||
"https://deno.land/x/compress@v0.4.5/gzip/gzip_file.ts": "b044ec0df4266c084baa033a4ab5394882e44a86d09d5616636467dcb39c671d",
|
"https://deno.land/x/compress@v0.4.5/gzip/gzip_file.ts": "b044ec0df4266c084baa033a4ab5394882e44a86d09d5616636467dcb39c671d",
|
||||||
|
@ -147,8 +210,25 @@
|
||||||
"workspace": {
|
"workspace": {
|
||||||
"packageJson": {
|
"packageJson": {
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
"npm:@rollup/plugin-alias@^5.1.1",
|
||||||
|
"npm:@rollup/plugin-node-resolve@^15.0.1",
|
||||||
|
"npm:@rollup/plugin-typescript@^12.1.1",
|
||||||
|
"npm:@typescript-eslint/parser@^6.2.0",
|
||||||
|
"npm:@vitest/ui@^1.0.4",
|
||||||
|
"npm:esbuild@~0.18.20",
|
||||||
|
"npm:eslint@^8.46.0",
|
||||||
|
"npm:loro-crdt@0.16.0",
|
||||||
|
"npm:loro-crdt@1.0.0-alpha.4",
|
||||||
|
"npm:prettier@3",
|
||||||
|
"npm:rollup-plugin-dts@^5.3.0",
|
||||||
|
"npm:rollup-plugin-esbuild@5",
|
||||||
|
"npm:rollup@^3.20.1",
|
||||||
|
"npm:tslib@^2.8.0",
|
||||||
|
"npm:typescript@^5.6.3",
|
||||||
"npm:vite-plugin-top-level-await@^1.2.2",
|
"npm:vite-plugin-top-level-await@^1.2.2",
|
||||||
"npm:vite-plugin-wasm@^3.1.0"
|
"npm:vite-plugin-wasm@^3.1.0",
|
||||||
|
"npm:vite@^4.2.1",
|
||||||
|
"npm:vitest@^1.4.0"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3
crates/loro-wasm/deno_tests/.vscode/settings.json
vendored
Normal file
3
crates/loro-wasm/deno_tests/.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"deno.enable": true
|
||||||
|
}
|
10
crates/loro-wasm/deno_tests/basic.test.ts
Normal file
10
crates/loro-wasm/deno_tests/basic.test.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import init, { initSync, LoroDoc } from "../web/loro_wasm.js";
|
||||||
|
import { expect } from "npm:expect";
|
||||||
|
|
||||||
|
await init();
|
||||||
|
|
||||||
|
Deno.test("basic", () => {
|
||||||
|
const doc = new LoroDoc();
|
||||||
|
doc.getText("text").insert(0, "Hello, world!");
|
||||||
|
expect(doc.getText("text").toString()).toBe("Hello, world!");
|
||||||
|
});
|
3
crates/loro-wasm/deno_tests/deno.json
Normal file
3
crates/loro-wasm/deno_tests/deno.json
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"nodeModulesDir": "auto"
|
||||||
|
}
|
240
crates/loro-wasm/deno_tests/deno.lock
Normal file
240
crates/loro-wasm/deno_tests/deno.lock
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
{
|
||||||
|
"version": "4",
|
||||||
|
"specifiers": {
|
||||||
|
"npm:expect@*": "29.7.0"
|
||||||
|
},
|
||||||
|
"npm": {
|
||||||
|
"@babel/code-frame@7.26.0": {
|
||||||
|
"integrity": "sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==",
|
||||||
|
"dependencies": [
|
||||||
|
"@babel/helper-validator-identifier",
|
||||||
|
"js-tokens",
|
||||||
|
"picocolors"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@babel/helper-validator-identifier@7.25.9": {
|
||||||
|
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="
|
||||||
|
},
|
||||||
|
"@jest/expect-utils@29.7.0": {
|
||||||
|
"integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
|
||||||
|
"dependencies": [
|
||||||
|
"jest-get-type"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@jest/schemas@29.6.3": {
|
||||||
|
"integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
|
||||||
|
"dependencies": [
|
||||||
|
"@sinclair/typebox"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@jest/types@29.6.3": {
|
||||||
|
"integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
|
||||||
|
"dependencies": [
|
||||||
|
"@jest/schemas",
|
||||||
|
"@types/istanbul-lib-coverage",
|
||||||
|
"@types/istanbul-reports",
|
||||||
|
"@types/node",
|
||||||
|
"@types/yargs",
|
||||||
|
"chalk"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@sinclair/typebox@0.27.8": {
|
||||||
|
"integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA=="
|
||||||
|
},
|
||||||
|
"@types/istanbul-lib-coverage@2.0.6": {
|
||||||
|
"integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="
|
||||||
|
},
|
||||||
|
"@types/istanbul-lib-report@3.0.3": {
|
||||||
|
"integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
|
||||||
|
"dependencies": [
|
||||||
|
"@types/istanbul-lib-coverage"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@types/istanbul-reports@3.0.4": {
|
||||||
|
"integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
|
||||||
|
"dependencies": [
|
||||||
|
"@types/istanbul-lib-report"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@types/node@22.5.4": {
|
||||||
|
"integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
|
||||||
|
"dependencies": [
|
||||||
|
"undici-types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@types/stack-utils@2.0.3": {
|
||||||
|
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
|
||||||
|
},
|
||||||
|
"@types/yargs-parser@21.0.3": {
|
||||||
|
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="
|
||||||
|
},
|
||||||
|
"@types/yargs@17.0.33": {
|
||||||
|
"integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
|
||||||
|
"dependencies": [
|
||||||
|
"@types/yargs-parser"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ansi-styles@4.3.0": {
|
||||||
|
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||||
|
"dependencies": [
|
||||||
|
"color-convert"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ansi-styles@5.2.0": {
|
||||||
|
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="
|
||||||
|
},
|
||||||
|
"braces@3.0.3": {
|
||||||
|
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||||
|
"dependencies": [
|
||||||
|
"fill-range"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"chalk@4.1.2": {
|
||||||
|
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||||
|
"dependencies": [
|
||||||
|
"ansi-styles@4.3.0",
|
||||||
|
"supports-color"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ci-info@3.9.0": {
|
||||||
|
"integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="
|
||||||
|
},
|
||||||
|
"color-convert@2.0.1": {
|
||||||
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||||
|
"dependencies": [
|
||||||
|
"color-name"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"color-name@1.1.4": {
|
||||||
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||||
|
},
|
||||||
|
"diff-sequences@29.6.3": {
|
||||||
|
"integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q=="
|
||||||
|
},
|
||||||
|
"escape-string-regexp@2.0.0": {
|
||||||
|
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="
|
||||||
|
},
|
||||||
|
"expect@29.7.0": {
|
||||||
|
"integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
|
||||||
|
"dependencies": [
|
||||||
|
"@jest/expect-utils",
|
||||||
|
"jest-get-type",
|
||||||
|
"jest-matcher-utils",
|
||||||
|
"jest-message-util",
|
||||||
|
"jest-util"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fill-range@7.1.1": {
|
||||||
|
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||||
|
"dependencies": [
|
||||||
|
"to-regex-range"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"graceful-fs@4.2.11": {
|
||||||
|
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
|
||||||
|
},
|
||||||
|
"has-flag@4.0.0": {
|
||||||
|
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
|
||||||
|
},
|
||||||
|
"is-number@7.0.0": {
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
|
||||||
|
},
|
||||||
|
"jest-diff@29.7.0": {
|
||||||
|
"integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
|
||||||
|
"dependencies": [
|
||||||
|
"chalk",
|
||||||
|
"diff-sequences",
|
||||||
|
"jest-get-type",
|
||||||
|
"pretty-format"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"jest-get-type@29.6.3": {
|
||||||
|
"integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw=="
|
||||||
|
},
|
||||||
|
"jest-matcher-utils@29.7.0": {
|
||||||
|
"integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
|
||||||
|
"dependencies": [
|
||||||
|
"chalk",
|
||||||
|
"jest-diff",
|
||||||
|
"jest-get-type",
|
||||||
|
"pretty-format"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"jest-message-util@29.7.0": {
|
||||||
|
"integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
|
||||||
|
"dependencies": [
|
||||||
|
"@babel/code-frame",
|
||||||
|
"@jest/types",
|
||||||
|
"@types/stack-utils",
|
||||||
|
"chalk",
|
||||||
|
"graceful-fs",
|
||||||
|
"micromatch",
|
||||||
|
"pretty-format",
|
||||||
|
"slash",
|
||||||
|
"stack-utils"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"jest-util@29.7.0": {
|
||||||
|
"integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
|
||||||
|
"dependencies": [
|
||||||
|
"@jest/types",
|
||||||
|
"@types/node",
|
||||||
|
"chalk",
|
||||||
|
"ci-info",
|
||||||
|
"graceful-fs",
|
||||||
|
"picomatch"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"js-tokens@4.0.0": {
|
||||||
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||||
|
},
|
||||||
|
"micromatch@4.0.8": {
|
||||||
|
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||||
|
"dependencies": [
|
||||||
|
"braces",
|
||||||
|
"picomatch"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"picocolors@1.1.1": {
|
||||||
|
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
||||||
|
},
|
||||||
|
"picomatch@2.3.1": {
|
||||||
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
||||||
|
},
|
||||||
|
"pretty-format@29.7.0": {
|
||||||
|
"integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
|
||||||
|
"dependencies": [
|
||||||
|
"@jest/schemas",
|
||||||
|
"ansi-styles@5.2.0",
|
||||||
|
"react-is"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"react-is@18.3.1": {
|
||||||
|
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
|
||||||
|
},
|
||||||
|
"slash@3.0.0": {
|
||||||
|
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="
|
||||||
|
},
|
||||||
|
"stack-utils@2.0.6": {
|
||||||
|
"integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
|
||||||
|
"dependencies": [
|
||||||
|
"escape-string-regexp"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"supports-color@7.2.0": {
|
||||||
|
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||||
|
"dependencies": [
|
||||||
|
"has-flag"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"to-regex-range@5.0.1": {
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dependencies": [
|
||||||
|
"is-number"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"undici-types@6.19.8": {
|
||||||
|
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
215
crates/loro-wasm/index.ts
Normal file
215
crates/loro-wasm/index.ts
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
export * from "loro-wasm";
|
||||||
|
export type * from "loro-wasm";
|
||||||
|
import {
|
||||||
|
AwarenessWasm,
|
||||||
|
PeerID,
|
||||||
|
Container,
|
||||||
|
ContainerID,
|
||||||
|
ContainerType,
|
||||||
|
LoroCounter,
|
||||||
|
LoroDoc,
|
||||||
|
LoroList,
|
||||||
|
LoroMap,
|
||||||
|
LoroText,
|
||||||
|
LoroTree,
|
||||||
|
OpId,
|
||||||
|
Value,
|
||||||
|
AwarenessListener,
|
||||||
|
} from "loro-wasm";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Please use LoroDoc
|
||||||
|
*/
|
||||||
|
export class Loro extends LoroDoc { }
|
||||||
|
|
||||||
|
const CONTAINER_TYPES = [
|
||||||
|
"Map",
|
||||||
|
"Text",
|
||||||
|
"List",
|
||||||
|
"Tree",
|
||||||
|
"MovableList",
|
||||||
|
"Counter",
|
||||||
|
];
|
||||||
|
|
||||||
|
export function isContainerId(s: string): s is ContainerID {
|
||||||
|
return s.startsWith("cid:");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether the value is a container.
|
||||||
|
*
|
||||||
|
* # Example
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const map = doc.getMap("map");
|
||||||
|
* const list = doc.getList("list");
|
||||||
|
* const text = doc.getText("text");
|
||||||
|
* isContainer(map); // true
|
||||||
|
* isContainer(list); // true
|
||||||
|
* isContainer(text); // true
|
||||||
|
* isContainer(123); // false
|
||||||
|
* isContainer("123"); // false
|
||||||
|
* isContainer({}); // false
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function isContainer(value: any): value is Container {
|
||||||
|
if (typeof value !== "object" || value == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const p = Object.getPrototypeOf(value);
|
||||||
|
if (p == null || typeof p !== "object" || typeof p["kind"] !== "function") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CONTAINER_TYPES.includes(value.kind());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Get the type of a value that may be a container.
|
||||||
|
*
|
||||||
|
* # Example
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const map = doc.getMap("map");
|
||||||
|
* const list = doc.getList("list");
|
||||||
|
* const text = doc.getText("text");
|
||||||
|
* getType(map); // "Map"
|
||||||
|
* getType(list); // "List"
|
||||||
|
* getType(text); // "Text"
|
||||||
|
* getType(123); // "Json"
|
||||||
|
* getType("123"); // "Json"
|
||||||
|
* getType({}); // "Json"
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function getType<T>(
|
||||||
|
value: T,
|
||||||
|
): T extends LoroText ? "Text"
|
||||||
|
: T extends LoroMap<any> ? "Map"
|
||||||
|
: T extends LoroTree<any> ? "Tree"
|
||||||
|
: T extends LoroList<any> ? "List"
|
||||||
|
: T extends LoroCounter ? "Counter"
|
||||||
|
: "Json" {
|
||||||
|
if (isContainer(value)) {
|
||||||
|
return value.kind() as unknown as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Json" as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function newContainerID(id: OpId, type: ContainerType): ContainerID {
|
||||||
|
return `cid:${id.counter}@${id.peer}:${type}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function newRootContainerID(
|
||||||
|
name: string,
|
||||||
|
type: ContainerType,
|
||||||
|
): ContainerID {
|
||||||
|
return `cid:root-${name}:${type}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Awareness is a structure that allows to track the ephemeral state of the peers.
|
||||||
|
*
|
||||||
|
* If we don't receive a state update from a peer within the timeout, we will remove their state.
|
||||||
|
* The timeout is in milliseconds. This can be used to handle the off-line state of a peer.
|
||||||
|
*/
|
||||||
|
export class Awareness<T extends Value = Value> {
|
||||||
|
inner: AwarenessWasm<T>;
|
||||||
|
private peer: PeerID;
|
||||||
|
private timer: number | undefined;
|
||||||
|
private timeout: number;
|
||||||
|
private listeners: Set<AwarenessListener> = new Set();
|
||||||
|
constructor(peer: PeerID, timeout: number = 30000) {
|
||||||
|
this.inner = new AwarenessWasm(peer, timeout);
|
||||||
|
this.peer = peer;
|
||||||
|
this.timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(bytes: Uint8Array, origin = "remote") {
|
||||||
|
const { updated, added } = this.inner.apply(bytes);
|
||||||
|
this.listeners.forEach((listener) => {
|
||||||
|
listener({ updated, added, removed: [] }, origin);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.startTimerIfNotEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
setLocalState(state: T) {
|
||||||
|
const wasEmpty = this.inner.getState(this.peer) == null;
|
||||||
|
this.inner.setLocalState(state);
|
||||||
|
if (wasEmpty) {
|
||||||
|
this.listeners.forEach((listener) => {
|
||||||
|
listener(
|
||||||
|
{ updated: [], added: [this.inner.peer()], removed: [] },
|
||||||
|
"local",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.listeners.forEach((listener) => {
|
||||||
|
listener(
|
||||||
|
{ updated: [this.inner.peer()], added: [], removed: [] },
|
||||||
|
"local",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.startTimerIfNotEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
getLocalState(): T | undefined {
|
||||||
|
return this.inner.getState(this.peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllStates(): Record<PeerID, T> {
|
||||||
|
return this.inner.getAllStates();
|
||||||
|
}
|
||||||
|
|
||||||
|
encode(peers: PeerID[]): Uint8Array {
|
||||||
|
return this.inner.encode(peers);
|
||||||
|
}
|
||||||
|
|
||||||
|
encodeAll(): Uint8Array {
|
||||||
|
return this.inner.encodeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
addListener(listener: AwarenessListener) {
|
||||||
|
this.listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeListener(listener: AwarenessListener) {
|
||||||
|
this.listeners.delete(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
peers(): PeerID[] {
|
||||||
|
return this.inner.peers();
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
this.listeners.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private startTimerIfNotEmpty() {
|
||||||
|
if (this.inner.isEmpty() || this.timer != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
const removed = this.inner.removeOutdated();
|
||||||
|
if (removed.length > 0) {
|
||||||
|
this.listeners.forEach((listener) => {
|
||||||
|
listener({ updated: [], added: [], removed }, "timeout");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.inner.isEmpty()) {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
this.timer = undefined;
|
||||||
|
}
|
||||||
|
}, this.timeout / 2) as unknown as number;
|
||||||
|
}
|
||||||
|
}
|
79
crates/loro-wasm/package-lock.json
generated
79
crates/loro-wasm/package-lock.json
generated
|
@ -1,79 +0,0 @@
|
||||||
{
|
|
||||||
"name": "loro-wasm",
|
|
||||||
"version": "0.4.1",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"name": "loro-wasm",
|
|
||||||
"version": "0.4.1",
|
|
||||||
"license": "ISC",
|
|
||||||
"devDependencies": {
|
|
||||||
"vite-plugin-top-level-await": "^1.2.2",
|
|
||||||
"vite-plugin-wasm": "^3.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"../../node_modules/.pnpm/vite-plugin-top-level-await@1.3.0_vite@4.5.0/node_modules/vite-plugin-top-level-await": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@rollup/plugin-virtual": "^3.0.1",
|
|
||||||
"@swc/core": "^1.3.10",
|
|
||||||
"uuid": "^9.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/jest": "^29.2.0",
|
|
||||||
"@types/uuid": "^9.0.0",
|
|
||||||
"cz-conventional-changelog": "^3.3.0",
|
|
||||||
"esbuild": "^0.15.12",
|
|
||||||
"jest": "^29.2.1",
|
|
||||||
"jest-extended": "^3.1.0",
|
|
||||||
"prettier": "^2.7.1",
|
|
||||||
"ts-jest": "^29.0.3",
|
|
||||||
"typescript": "^4.8.4",
|
|
||||||
"vite": "^3.1.8"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"vite": ">=2.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"../../node_modules/.pnpm/vite-plugin-wasm@3.2.2_vite@4.5.0/node_modules/vite-plugin-wasm": {
|
|
||||||
"version": "3.2.2",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/preset-env": "^7.20.2",
|
|
||||||
"@jest/types": "^28.1.3",
|
|
||||||
"@jsona/openapi": "^0.2.5",
|
|
||||||
"@syntect/wasm": "^0.0.4",
|
|
||||||
"@types/express": "^4.17.13",
|
|
||||||
"@types/jest": "^28.1.5",
|
|
||||||
"cross-env": "^7.0.3",
|
|
||||||
"cz-conventional-changelog": "^3.3.0",
|
|
||||||
"esbuild": "^0.15.12",
|
|
||||||
"express": "^4.18.1",
|
|
||||||
"jest": "^28.1.3",
|
|
||||||
"jest-extended": "^3.0.1",
|
|
||||||
"playwright": "^1.23.3",
|
|
||||||
"prettier": "^2.7.1",
|
|
||||||
"terser": "^5.14.2",
|
|
||||||
"ts-jest": "^28.0.7",
|
|
||||||
"typescript": "^4.7.4",
|
|
||||||
"vite": "^4.1.4",
|
|
||||||
"wait-port": "^1.0.4"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"vite": "^2 || ^3 || ^4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/vite-plugin-top-level-await": {
|
|
||||||
"resolved": "../../node_modules/.pnpm/vite-plugin-top-level-await@1.3.0_vite@4.5.0/node_modules/vite-plugin-top-level-await",
|
|
||||||
"link": true
|
|
||||||
},
|
|
||||||
"node_modules/vite-plugin-wasm": {
|
|
||||||
"resolved": "../../node_modules/.pnpm/vite-plugin-wasm@3.2.2_vite@4.5.0/node_modules/vite-plugin-wasm",
|
|
||||||
"link": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "loro-wasm",
|
"name": "loro-crdt",
|
||||||
"version": "1.0.7",
|
"version": "1.0.8-alpha.3",
|
||||||
"description": "Loro CRDTs is a high-performance CRDT framework that makes your app state synchronized, collaborative and maintainable effortlessly.",
|
"description": "Loro CRDTs is a high-performance CRDT framework that makes your app state synchronized, collaborative and maintainable effortlessly.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"crdt",
|
"crdt",
|
||||||
|
@ -14,17 +14,45 @@
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/loro-dev/loro.git"
|
"url": "git+https://github.com/loro-dev/loro.git"
|
||||||
},
|
},
|
||||||
"main": "nodejs/loro_wasm.js",
|
"main": "nodejs/index.js",
|
||||||
"module": "bundler/loro_wasm.js",
|
"module": "bundler/index.js",
|
||||||
|
"types": "bundler/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"./bundler",
|
||||||
|
"./nodejs",
|
||||||
|
"./web",
|
||||||
|
"CHANGELOG.md",
|
||||||
|
"README.md",
|
||||||
|
"LICENSE",
|
||||||
|
"package.json"
|
||||||
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"release": "deno run -A ./scripts/build.ts release",
|
"build-dev": "deno run -A ./scripts/build.ts dev && rollup -c && deno run -A ./scripts/post-rollup.ts && npm run test",
|
||||||
"dev": "deno run -A ./scripts/build.ts dev"
|
"build-release": "deno run -A ./scripts/build.ts release && rollup -c && deno run -A ./scripts/post-rollup.ts && npm run test",
|
||||||
|
"test": "node --expose-gc ./node_modules/vitest/vitest.mjs run && npx tsc --noEmit && cd ./deno_tests && deno test -A"
|
||||||
},
|
},
|
||||||
"homepage": "https://loro.dev",
|
"homepage": "https://loro.dev",
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-alias": "^5.1.1",
|
||||||
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||||
|
"@rollup/plugin-typescript": "^12.1.1",
|
||||||
|
"rollup": "^3.20.1",
|
||||||
|
"tslib": "^2.8.0",
|
||||||
|
"typescript": "^5.6.3",
|
||||||
"vite-plugin-top-level-await": "^1.2.2",
|
"vite-plugin-top-level-await": "^1.2.2",
|
||||||
"vite-plugin-wasm": "^3.1.0"
|
"vite-plugin-wasm": "^3.1.0",
|
||||||
|
"@typescript-eslint/parser": "^6.2.0",
|
||||||
|
"@vitest/ui": "^1.0.4",
|
||||||
|
"esbuild": "^0.18.20",
|
||||||
|
"eslint": "^8.46.0",
|
||||||
|
"loro-crdt-old": "npm:loro-crdt@=0.16.0",
|
||||||
|
"loro-crdt-alpha-4": "npm:loro-crdt@=1.0.0-alpha.4",
|
||||||
|
"prettier": "^3.0.0",
|
||||||
|
"rollup-plugin-dts": "^5.3.0",
|
||||||
|
"rollup-plugin-esbuild": "^5.0.0",
|
||||||
|
"vite": "^4.2.1",
|
||||||
|
"vitest": "^1.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
38
crates/loro-wasm/rollup.config.mjs
Normal file
38
crates/loro-wasm/rollup.config.mjs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import typescript from '@rollup/plugin-typescript';
|
||||||
|
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
||||||
|
const createConfig = (format, tsTarget, outputDir) => ({
|
||||||
|
input: {
|
||||||
|
'index': 'index.ts',
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
dir: outputDir,
|
||||||
|
format: format,
|
||||||
|
sourcemap: true,
|
||||||
|
entryFileNames: '[name].js',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
typescript({
|
||||||
|
tsconfig: 'tsconfig.json',
|
||||||
|
compilerOptions: {
|
||||||
|
target: tsTarget,
|
||||||
|
declaration: true,
|
||||||
|
outDir: outputDir,
|
||||||
|
},
|
||||||
|
exclude: ['tests/**/*']
|
||||||
|
}),
|
||||||
|
nodeResolve()
|
||||||
|
],
|
||||||
|
external: [/loro_wasm/]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create different bundle configurations
|
||||||
|
export default [
|
||||||
|
// CommonJS for Node.js
|
||||||
|
createConfig('cjs', 'ES2020', 'nodejs'),
|
||||||
|
|
||||||
|
// ESM for Web
|
||||||
|
createConfig('es', 'ES2020', 'web'),
|
||||||
|
|
||||||
|
// ESM for bundler
|
||||||
|
createConfig('es', 'ES2020', 'bundler'),
|
||||||
|
];
|
|
@ -12,7 +12,7 @@ if (Deno.args[0] == "release") {
|
||||||
profile = "release";
|
profile = "release";
|
||||||
profileDir = "release";
|
profileDir = "release";
|
||||||
}
|
}
|
||||||
const TARGETS = ["bundler", "nodejs"];
|
const TARGETS = ["bundler", "nodejs", "web"];
|
||||||
const startTime = performance.now();
|
const startTime = performance.now();
|
||||||
const LoroWasmDir = path.resolve(__dirname, "..");
|
const LoroWasmDir = path.resolve(__dirname, "..");
|
||||||
|
|
||||||
|
|
57
crates/loro-wasm/scripts/post-rollup.ts
Normal file
57
crates/loro-wasm/scripts/post-rollup.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { walk } from "https://deno.land/std/fs/mod.ts";
|
||||||
|
|
||||||
|
const DIRS_TO_SCAN = ["./nodejs", "./bundler", "./web"];
|
||||||
|
const FILES_TO_PROCESS = ["index.js", "index.d.ts"];
|
||||||
|
|
||||||
|
async function replaceInFile(filePath: string) {
|
||||||
|
try {
|
||||||
|
let content = await Deno.readTextFile(filePath);
|
||||||
|
|
||||||
|
// Replace various import/require patterns for 'loro-wasm'
|
||||||
|
const isWebIndexJs = filePath.includes("web") && filePath.endsWith("index.js");
|
||||||
|
const target = isWebIndexJs ? "./loro_wasm.js" : "./loro_wasm";
|
||||||
|
|
||||||
|
content = content.replace(
|
||||||
|
/from ["']loro-wasm["']/g,
|
||||||
|
`from "${target}"`
|
||||||
|
);
|
||||||
|
content = content.replace(
|
||||||
|
/require\(["']loro-wasm["']\)/g,
|
||||||
|
`require("${target}")`
|
||||||
|
);
|
||||||
|
content = content.replace(
|
||||||
|
/import\(["']loro-wasm["']\)/g,
|
||||||
|
`import("${target}")`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isWebIndexJs) {
|
||||||
|
content = `export { default } from "./loro_wasm.js";\n${content}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Deno.writeTextFile(filePath, content);
|
||||||
|
console.log(`✓ Processed: ${filePath}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error processing ${filePath}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
for (const dir of DIRS_TO_SCAN) {
|
||||||
|
try {
|
||||||
|
for await (const entry of walk(dir, {
|
||||||
|
includeDirs: false,
|
||||||
|
match: [/index\.(js|d\.ts)$/],
|
||||||
|
})) {
|
||||||
|
if (FILES_TO_PROCESS.includes(entry.name)) {
|
||||||
|
await replaceInFile(entry.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error scanning directory ${dir}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (import.meta.main) {
|
||||||
|
main();
|
||||||
|
}
|
|
@ -1354,6 +1354,7 @@ impl LoroDoc {
|
||||||
/// sub();
|
/// sub();
|
||||||
/// ```
|
/// ```
|
||||||
// TODO: convert event and event sub config
|
// TODO: convert event and event sub config
|
||||||
|
#[wasm_bindgen(skip_typescript)]
|
||||||
pub fn subscribe(&self, f: js_sys::Function) -> JsValue {
|
pub fn subscribe(&self, f: js_sys::Function) -> JsValue {
|
||||||
let observer = observer::Observer::new(f);
|
let observer = observer::Observer::new(f);
|
||||||
let doc = self.0.clone();
|
let doc = self.0.clone();
|
||||||
|
@ -2060,6 +2061,7 @@ impl LoroText {
|
||||||
/// - `doc.checkout(version)` is called.
|
/// - `doc.checkout(version)` is called.
|
||||||
///
|
///
|
||||||
/// returns a subscription callback, which can be used to unsubscribe.
|
/// returns a subscription callback, which can be used to unsubscribe.
|
||||||
|
#[wasm_bindgen(skip_typescript)]
|
||||||
pub fn subscribe(&self, f: js_sys::Function) -> JsResult<JsValue> {
|
pub fn subscribe(&self, f: js_sys::Function) -> JsResult<JsValue> {
|
||||||
let observer = observer::Observer::new(f);
|
let observer = observer::Observer::new(f);
|
||||||
let doc = self
|
let doc = self
|
||||||
|
@ -2419,6 +2421,7 @@ impl LoroMap {
|
||||||
/// map.set("foo", "bar");
|
/// map.set("foo", "bar");
|
||||||
/// doc.commit();
|
/// doc.commit();
|
||||||
/// ```
|
/// ```
|
||||||
|
#[wasm_bindgen(skip_typescript)]
|
||||||
pub fn subscribe(&self, f: js_sys::Function) -> JsResult<JsValue> {
|
pub fn subscribe(&self, f: js_sys::Function) -> JsResult<JsValue> {
|
||||||
let observer = observer::Observer::new(f);
|
let observer = observer::Observer::new(f);
|
||||||
let doc = self
|
let doc = self
|
||||||
|
@ -2696,6 +2699,7 @@ impl LoroList {
|
||||||
/// list.insert(0, 100);
|
/// list.insert(0, 100);
|
||||||
/// doc.commit();
|
/// doc.commit();
|
||||||
/// ```
|
/// ```
|
||||||
|
#[wasm_bindgen(skip_typescript)]
|
||||||
pub fn subscribe(&self, f: js_sys::Function) -> JsResult<JsValue> {
|
pub fn subscribe(&self, f: js_sys::Function) -> JsResult<JsValue> {
|
||||||
let observer = observer::Observer::new(f);
|
let observer = observer::Observer::new(f);
|
||||||
let doc = self
|
let doc = self
|
||||||
|
@ -3016,6 +3020,7 @@ impl LoroMovableList {
|
||||||
/// list.insert(0, 100);
|
/// list.insert(0, 100);
|
||||||
/// doc.commit();
|
/// doc.commit();
|
||||||
/// ```
|
/// ```
|
||||||
|
#[wasm_bindgen(skip_typescript)]
|
||||||
pub fn subscribe(&self, f: js_sys::Function) -> JsResult<JsValue> {
|
pub fn subscribe(&self, f: js_sys::Function) -> JsResult<JsValue> {
|
||||||
let observer = observer::Observer::new(f);
|
let observer = observer::Observer::new(f);
|
||||||
let loro = self
|
let loro = self
|
||||||
|
@ -3707,6 +3712,7 @@ impl LoroTree {
|
||||||
/// const node = root.createNode();
|
/// const node = root.createNode();
|
||||||
/// doc.commit();
|
/// doc.commit();
|
||||||
/// ```
|
/// ```
|
||||||
|
#[wasm_bindgen(skip_typescript)]
|
||||||
pub fn subscribe(&self, f: js_sys::Function) -> JsResult<JsValue> {
|
pub fn subscribe(&self, f: js_sys::Function) -> JsResult<JsValue> {
|
||||||
let observer = observer::Observer::new(f);
|
let observer = observer::Observer::new(f);
|
||||||
let doc = self
|
let doc = self
|
||||||
|
@ -4889,4 +4895,540 @@ export type ImportStatus = {
|
||||||
success: Map<PeerID, CounterSpan>,
|
success: Map<PeerID, CounterSpan>,
|
||||||
pending: Map<PeerID, CounterSpan> | null
|
pending: Map<PeerID, CounterSpan> | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Frontiers = OpId[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a path to identify the exact location of an event's target.
|
||||||
|
* The path is composed of numbers (e.g., indices of a list container) strings
|
||||||
|
* (e.g., keys of a map container) and TreeID (the node of a tree container),
|
||||||
|
* indicating the absolute position of the event's source within a loro document.
|
||||||
|
*/
|
||||||
|
export type Path = (number | string | TreeID)[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A batch of events that created by a single `import`/`transaction`/`checkout`.
|
||||||
|
*
|
||||||
|
* @prop by - How the event is triggered.
|
||||||
|
* @prop origin - (Optional) Provides information about the origin of the event.
|
||||||
|
* @prop diff - Contains the differential information related to the event.
|
||||||
|
* @prop target - Identifies the container ID of the event's target.
|
||||||
|
* @prop path - Specifies the absolute path of the event's emitter, which can be an index of a list container or a key of a map container.
|
||||||
|
*/
|
||||||
|
export interface LoroEventBatch {
|
||||||
|
/**
|
||||||
|
* How the event is triggered.
|
||||||
|
*
|
||||||
|
* - `local`: The event is triggered by a local transaction.
|
||||||
|
* - `import`: The event is triggered by an import operation.
|
||||||
|
* - `checkout`: The event is triggered by a checkout operation.
|
||||||
|
*/
|
||||||
|
by: "local" | "import" | "checkout";
|
||||||
|
origin?: string;
|
||||||
|
/**
|
||||||
|
* The container ID of the current event receiver.
|
||||||
|
* It's undefined if the subscriber is on the root document.
|
||||||
|
*/
|
||||||
|
currentTarget?: ContainerID;
|
||||||
|
events: LoroEvent[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The concrete event of Loro.
|
||||||
|
*/
|
||||||
|
export interface LoroEvent {
|
||||||
|
/**
|
||||||
|
* The container ID of the event's target.
|
||||||
|
*/
|
||||||
|
target: ContainerID;
|
||||||
|
diff: Diff;
|
||||||
|
/**
|
||||||
|
* The absolute path of the event's emitter, which can be an index of a list container or a key of a map container.
|
||||||
|
*/
|
||||||
|
path: Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ListDiff = {
|
||||||
|
type: "list";
|
||||||
|
diff: Delta<(Value | Container)[]>[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TextDiff = {
|
||||||
|
type: "text";
|
||||||
|
diff: Delta<string>[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MapDiff = {
|
||||||
|
type: "map";
|
||||||
|
updated: Record<string, Value | Container | undefined>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TreeDiffItem =
|
||||||
|
| {
|
||||||
|
target: TreeID;
|
||||||
|
action: "create";
|
||||||
|
parent: TreeID | undefined;
|
||||||
|
index: number;
|
||||||
|
fractionalIndex: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
target: TreeID;
|
||||||
|
action: "delete";
|
||||||
|
oldParent: TreeID | undefined;
|
||||||
|
oldIndex: number;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
target: TreeID;
|
||||||
|
action: "move";
|
||||||
|
parent: TreeID | undefined;
|
||||||
|
index: number;
|
||||||
|
fractionalIndex: string;
|
||||||
|
oldParent: TreeID | undefined;
|
||||||
|
oldIndex: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TreeDiff = {
|
||||||
|
type: "tree";
|
||||||
|
diff: TreeDiffItem[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CounterDiff = {
|
||||||
|
type: "counter";
|
||||||
|
increment: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Diff = ListDiff | TextDiff | MapDiff | TreeDiff | CounterDiff;
|
||||||
|
export type Subscription = () => void;
|
||||||
|
type NonNullableType<T> = Exclude<T, null | undefined>;
|
||||||
|
export type AwarenessListener = (
|
||||||
|
arg: { updated: PeerID[]; added: PeerID[]; removed: PeerID[] },
|
||||||
|
origin: "local" | "timeout" | "remote" | string,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
|
||||||
|
interface Listener {
|
||||||
|
(event: LoroEventBatch): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LoroDoc {
|
||||||
|
subscribe(listener: Listener): Subscription;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UndoManager {
|
||||||
|
/**
|
||||||
|
* Set the callback function that is called when an undo/redo step is pushed.
|
||||||
|
* The function can return a meta data value that will be attached to the given stack item.
|
||||||
|
*
|
||||||
|
* @param listener - The callback function.
|
||||||
|
*/
|
||||||
|
setOnPush(listener?: UndoConfig["onPush"]): void;
|
||||||
|
/**
|
||||||
|
* Set the callback function that is called when an undo/redo step is popped.
|
||||||
|
* The function will have a meta data value that was attached to the given stack item when `onPush` was called.
|
||||||
|
*
|
||||||
|
* @param listener - The callback function.
|
||||||
|
*/
|
||||||
|
setOnPop(listener?: UndoConfig["onPop"]): void;
|
||||||
|
}
|
||||||
|
interface LoroDoc<T extends Record<string, Container> = Record<string, Container>> {
|
||||||
|
/**
|
||||||
|
* Get a LoroMap by container id
|
||||||
|
*
|
||||||
|
* The object returned is a new js object each time because it need to cross
|
||||||
|
* the WASM boundary.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const map = doc.getMap("map");
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
getMap<Key extends keyof T | ContainerID>(name: Key): T[Key] extends LoroMap ? T[Key] : LoroMap;
|
||||||
|
/**
|
||||||
|
* Get a LoroList by container id
|
||||||
|
*
|
||||||
|
* The object returned is a new js object each time because it need to cross
|
||||||
|
* the WASM boundary.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getList("list");
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
getList<Key extends keyof T | ContainerID>(name: Key): T[Key] extends LoroList ? T[Key] : LoroList;
|
||||||
|
/**
|
||||||
|
* Get a LoroMovableList by container id
|
||||||
|
*
|
||||||
|
* The object returned is a new js object each time because it need to cross
|
||||||
|
* the WASM boundary.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getList("list");
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
getMovableList<Key extends keyof T | ContainerID>(name: Key): T[Key] extends LoroMovableList ? T[Key] : LoroMovableList;
|
||||||
|
/**
|
||||||
|
* Get a LoroTree by container id
|
||||||
|
*
|
||||||
|
* The object returned is a new js object each time because it need to cross
|
||||||
|
* the WASM boundary.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const tree = doc.getTree("tree");
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
getTree<Key extends keyof T | ContainerID>(name: Key): T[Key] extends LoroTree ? T[Key] : LoroTree;
|
||||||
|
getText(key: string | ContainerID): LoroText;
|
||||||
|
}
|
||||||
|
interface LoroList<T = unknown> {
|
||||||
|
new(): LoroList<T>;
|
||||||
|
/**
|
||||||
|
* Get elements of the list. If the value is a child container, the corresponding
|
||||||
|
* `Container` will be returned.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc, LoroText } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getList("list");
|
||||||
|
* list.insert(0, 100);
|
||||||
|
* list.insert(1, "foo");
|
||||||
|
* list.insert(2, true);
|
||||||
|
* list.insertContainer(3, new LoroText());
|
||||||
|
* console.log(list.value); // [100, "foo", true, LoroText];
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
toArray(): T[];
|
||||||
|
/**
|
||||||
|
* Insert a container at the index.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc, LoroText } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getList("list");
|
||||||
|
* list.insert(0, 100);
|
||||||
|
* const text = list.insertContainer(1, new LoroText());
|
||||||
|
* text.insert(0, "Hello");
|
||||||
|
* console.log(list.toJSON()); // [100, "Hello"];
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
insertContainer<C extends Container>(pos: number, child: C): T extends C ? T : C;
|
||||||
|
/**
|
||||||
|
* Get the value at the index. If the value is a container, the corresponding handler will be returned.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getList("list");
|
||||||
|
* list.insert(0, 100);
|
||||||
|
* console.log(list.get(0)); // 100
|
||||||
|
* console.log(list.get(1)); // undefined
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
get(index: number): T;
|
||||||
|
/**
|
||||||
|
* Insert a value at index.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getList("list");
|
||||||
|
* list.insert(0, 100);
|
||||||
|
* list.insert(1, "foo");
|
||||||
|
* list.insert(2, true);
|
||||||
|
* console.log(list.value); // [100, "foo", true];
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
insert<V extends T>(pos: number, value: Exclude<V, Container>): void;
|
||||||
|
delete(pos: number, len: number): void;
|
||||||
|
push<V extends T>(value: Exclude<V, Container>): void;
|
||||||
|
subscribe(listener: Listener): Subscription;
|
||||||
|
getAttached(): undefined | LoroList<T>;
|
||||||
|
}
|
||||||
|
interface LoroMovableList<T = unknown> {
|
||||||
|
new(): LoroMovableList<T>;
|
||||||
|
/**
|
||||||
|
* Get elements of the list. If the value is a child container, the corresponding
|
||||||
|
* `Container` will be returned.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc, LoroText } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getMovableList("list");
|
||||||
|
* list.insert(0, 100);
|
||||||
|
* list.insert(1, "foo");
|
||||||
|
* list.insert(2, true);
|
||||||
|
* list.insertContainer(3, new LoroText());
|
||||||
|
* console.log(list.value); // [100, "foo", true, LoroText];
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
toArray(): T[];
|
||||||
|
/**
|
||||||
|
* Insert a container at the index.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc, LoroText } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getMovableList("list");
|
||||||
|
* list.insert(0, 100);
|
||||||
|
* const text = list.insertContainer(1, new LoroText());
|
||||||
|
* text.insert(0, "Hello");
|
||||||
|
* console.log(list.toJSON()); // [100, "Hello"];
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
insertContainer<C extends Container>(pos: number, child: C): T extends C ? T : C;
|
||||||
|
/**
|
||||||
|
* Get the value at the index. If the value is a container, the corresponding handler will be returned.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getMovableList("list");
|
||||||
|
* list.insert(0, 100);
|
||||||
|
* console.log(list.get(0)); // 100
|
||||||
|
* console.log(list.get(1)); // undefined
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
get(index: number): T;
|
||||||
|
/**
|
||||||
|
* Insert a value at index.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getMovableList("list");
|
||||||
|
* list.insert(0, 100);
|
||||||
|
* list.insert(1, "foo");
|
||||||
|
* list.insert(2, true);
|
||||||
|
* console.log(list.value); // [100, "foo", true];
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
insert<V extends T>(pos: number, value: Exclude<V, Container>): void;
|
||||||
|
delete(pos: number, len: number): void;
|
||||||
|
push<V extends T>(value: Exclude<V, Container>): void;
|
||||||
|
subscribe(listener: Listener): Subscription;
|
||||||
|
getAttached(): undefined | LoroMovableList<T>;
|
||||||
|
/**
|
||||||
|
* Set the value at the given position.
|
||||||
|
*
|
||||||
|
* It's different from `delete` + `insert` that it will replace the value at the position.
|
||||||
|
*
|
||||||
|
* For example, if you have a list `[1, 2, 3]`, and you call `set(1, 100)`, the list will be `[1, 100, 3]`.
|
||||||
|
* If concurrently someone call `set(1, 200)`, the list will be `[1, 200, 3]` or `[1, 100, 3]`.
|
||||||
|
*
|
||||||
|
* But if you use `delete` + `insert` to simulate the set operation, they may create redundant operations
|
||||||
|
* and the final result will be `[1, 100, 200, 3]` or `[1, 200, 100, 3]`.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getMovableList("list");
|
||||||
|
* list.insert(0, 100);
|
||||||
|
* list.insert(1, "foo");
|
||||||
|
* list.insert(2, true);
|
||||||
|
* list.set(1, "bar");
|
||||||
|
* console.log(list.value); // [100, "bar", true];
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
set<V extends T>(pos: number, value: Exclude<V, Container>): void;
|
||||||
|
/**
|
||||||
|
* Set a container at the index.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc, LoroText } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const list = doc.getMovableList("list");
|
||||||
|
* list.insert(0, 100);
|
||||||
|
* const text = list.setContainer(0, new LoroText());
|
||||||
|
* text.insert(0, "Hello");
|
||||||
|
* console.log(list.toJSON()); // ["Hello"];
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
setContainer<C extends Container>(pos: number, child: C): T extends C ? T : C;
|
||||||
|
}
|
||||||
|
interface LoroMap<T extends Record<string, unknown> = Record<string, unknown>> {
|
||||||
|
new(): LoroMap<T>;
|
||||||
|
/**
|
||||||
|
* Get the value of the key. If the value is a child container, the corresponding
|
||||||
|
* `Container` will be returned.
|
||||||
|
*
|
||||||
|
* The object returned is a new js object each time because it need to cross
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const map = doc.getMap("map");
|
||||||
|
* map.set("foo", "bar");
|
||||||
|
* const bar = map.get("foo");
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
getOrCreateContainer<C extends Container>(key: string, child: C): C;
|
||||||
|
/**
|
||||||
|
* Set the key with a container.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc, LoroText, LoroList } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const map = doc.getMap("map");
|
||||||
|
* map.set("foo", "bar");
|
||||||
|
* const text = map.setContainer("text", new LoroText());
|
||||||
|
* const list = map.setContainer("list", new LoroList());
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
setContainer<C extends Container, Key extends keyof T>(key: Key, child: C): NonNullableType<T[Key]> extends C ? NonNullableType<T[Key]> : C;
|
||||||
|
/**
|
||||||
|
* Get the value of the key. If the value is a child container, the corresponding
|
||||||
|
* `Container` will be returned.
|
||||||
|
*
|
||||||
|
* The object/value returned is a new js object/value each time because it need to cross
|
||||||
|
* the WASM boundary.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const map = doc.getMap("map");
|
||||||
|
* map.set("foo", "bar");
|
||||||
|
* const bar = map.get("foo");
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
get<Key extends keyof T>(key: Key): T[Key];
|
||||||
|
/**
|
||||||
|
* Set the key with the value.
|
||||||
|
*
|
||||||
|
* If the value of the key is exist, the old value will be updated.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const map = doc.getMap("map");
|
||||||
|
* map.set("foo", "bar");
|
||||||
|
* map.set("foo", "baz");
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
set<Key extends keyof T, V extends T[Key]>(key: Key, value: Exclude<V, Container>): void;
|
||||||
|
delete(key: string): void;
|
||||||
|
subscribe(listener: Listener): Subscription;
|
||||||
|
}
|
||||||
|
interface LoroText {
|
||||||
|
new(): LoroText;
|
||||||
|
insert(pos: number, text: string): void;
|
||||||
|
delete(pos: number, len: number): void;
|
||||||
|
subscribe(listener: Listener): Subscription;
|
||||||
|
}
|
||||||
|
interface LoroTree<T extends Record<string, unknown> = Record<string, unknown>> {
|
||||||
|
new(): LoroTree<T>;
|
||||||
|
/**
|
||||||
|
* Create a new tree node as the child of parent and return a `LoroTreeNode` instance.
|
||||||
|
* If the parent is undefined, the tree node will be a root node.
|
||||||
|
*
|
||||||
|
* If the index is not provided, the new node will be appended to the end.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* const doc = new LoroDoc();
|
||||||
|
* const tree = doc.getTree("tree");
|
||||||
|
* const root = tree.createNode();
|
||||||
|
* const node = tree.createNode(undefined, 0);
|
||||||
|
*
|
||||||
|
* // undefined
|
||||||
|
* // / \
|
||||||
|
* // node root
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
createNode(parent?: TreeID, index?: number): LoroTreeNode<T>;
|
||||||
|
move(target: TreeID, parent?: TreeID, index?: number): void;
|
||||||
|
delete(target: TreeID): void;
|
||||||
|
has(target: TreeID): boolean;
|
||||||
|
/**
|
||||||
|
* Get LoroTreeNode by the TreeID.
|
||||||
|
*/
|
||||||
|
getNodeByID(target: TreeID): LoroTreeNode<T>;
|
||||||
|
subscribe(listener: Listener): Subscription;
|
||||||
|
}
|
||||||
|
interface LoroTreeNode<T extends Record<string, unknown> = Record<string, unknown>> {
|
||||||
|
/**
|
||||||
|
* Get the associated metadata map container of a tree node.
|
||||||
|
*/
|
||||||
|
readonly data: LoroMap<T>;
|
||||||
|
/**
|
||||||
|
* Create a new node as the child of the current node and
|
||||||
|
* return an instance of `LoroTreeNode`.
|
||||||
|
*
|
||||||
|
* If the index is not provided, the new node will be appended to the end.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* import { LoroDoc } from "loro-crdt";
|
||||||
|
*
|
||||||
|
* let doc = new LoroDoc();
|
||||||
|
* let tree = doc.getTree("tree");
|
||||||
|
* let root = tree.createNode();
|
||||||
|
* let node = root.createNode();
|
||||||
|
* let node2 = root.createNode(0);
|
||||||
|
* // root
|
||||||
|
* // / \
|
||||||
|
* // node2 node
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
createNode(index?: number): LoroTreeNode<T>;
|
||||||
|
move(parent?: LoroTreeNode<T>, index?: number): void;
|
||||||
|
parent(): LoroTreeNode<T> | undefined;
|
||||||
|
/**
|
||||||
|
* Get the children of this node.
|
||||||
|
*
|
||||||
|
* The objects returned are new js objects each time because they need to cross
|
||||||
|
* the WASM boundary.
|
||||||
|
*/
|
||||||
|
children(): Array<LoroTreeNode<T>> | undefined;
|
||||||
|
}
|
||||||
|
interface AwarenessWasm<T extends Value = Value> {
|
||||||
|
getState(peer: PeerID): T | undefined;
|
||||||
|
getTimestamp(peer: PeerID): number | undefined;
|
||||||
|
getAllStates(): Record<PeerID, T>;
|
||||||
|
setLocalState(value: T): void;
|
||||||
|
removeOutdated(): PeerID[];
|
||||||
|
}
|
||||||
|
|
||||||
"#;
|
"#;
|
||||||
|
|
|
@ -5,8 +5,8 @@ import {
|
||||||
Cursor,
|
Cursor,
|
||||||
PeerID,
|
PeerID,
|
||||||
setDebug,
|
setDebug,
|
||||||
} from "../src/index";
|
} from "../bundler/index";
|
||||||
import { AwarenessListener } from "../src/awareness";
|
import { AwarenessListener } from "../bundler/index";
|
||||||
|
|
||||||
describe("Awareness", () => {
|
describe("Awareness", () => {
|
||||||
it("setLocalRecord", () => {
|
it("setLocalRecord", () => {
|
|
@ -15,8 +15,7 @@ import {
|
||||||
Frontiers,
|
Frontiers,
|
||||||
encodeFrontiers,
|
encodeFrontiers,
|
||||||
decodeFrontiers,
|
decodeFrontiers,
|
||||||
} from "../src";
|
} from "../bundler/index";
|
||||||
import { m } from "vitest/dist/reporters-yx5ZTtEV";
|
|
||||||
|
|
||||||
it("basic example", () => {
|
it("basic example", () => {
|
||||||
const doc = new LoroDoc();
|
const doc = new LoroDoc();
|
||||||
|
@ -654,4 +653,4 @@ it("json path", () => {
|
||||||
const result = doc.JSONPath(path);
|
const result = doc.JSONPath(path);
|
||||||
expect(result.length).toBe(1);
|
expect(result.length).toBe(1);
|
||||||
expect(result).toStrictEqual(["1984"])
|
expect(result).toStrictEqual(["1984"])
|
||||||
})
|
})
|
|
@ -1,5 +1,5 @@
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { LoroDoc } from "../src";
|
import { LoroDoc } from "../bundler/index";
|
||||||
|
|
||||||
describe("Checkout", () => {
|
describe("Checkout", () => {
|
||||||
it("simple checkout", async () => {
|
it("simple checkout", async () => {
|
|
@ -10,7 +10,7 @@ import {
|
||||||
LoroText,
|
LoroText,
|
||||||
MapDiff,
|
MapDiff,
|
||||||
TextDiff,
|
TextDiff,
|
||||||
} from "../src";
|
} from "../bundler/index";
|
||||||
|
|
||||||
import * as OLD from "loro-crdt-old";
|
import * as OLD from "loro-crdt-old";
|
||||||
|
|
||||||
|
@ -29,12 +29,14 @@ describe("compatibility", () => {
|
||||||
// t.createNode(node.id, 0);
|
// t.createNode(node.id, 0);
|
||||||
const bytes = docA.exportFrom();
|
const bytes = docA.exportFrom();
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
const docB = new OLD.Loro();
|
const docB = new OLD.Loro();
|
||||||
docB.import(bytes);
|
docB.import(bytes);
|
||||||
expect(docA.toJSON()).toStrictEqual(docB.toJSON());
|
expect(docA.toJSON()).toStrictEqual(docB.toJSON());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("basic forward compatibility on exportSnapshot", () => {
|
it("basic forward compatibility on exportSnapshot", () => {
|
||||||
|
// @ts-ignore
|
||||||
const docA = new Loro();
|
const docA = new Loro();
|
||||||
docA.getText("text").insert(0, "123");
|
docA.getText("text").insert(0, "123");
|
||||||
docA.getMap("map").set("key", 123);
|
docA.getMap("map").set("key", 123);
|
||||||
|
@ -46,12 +48,14 @@ describe("compatibility", () => {
|
||||||
// t.createNode(node.id, 0);
|
// t.createNode(node.id, 0);
|
||||||
const bytes = docA.exportSnapshot();
|
const bytes = docA.exportSnapshot();
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
const docB = new OLD.Loro();
|
const docB = new OLD.Loro();
|
||||||
docB.import(bytes);
|
docB.import(bytes);
|
||||||
expect(docA.toJSON()).toStrictEqual(docB.toJSON());
|
expect(docA.toJSON()).toStrictEqual(docB.toJSON());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("basic backward compatibility on exportSnapshot", () => {
|
it("basic backward compatibility on exportSnapshot", () => {
|
||||||
|
// @ts-ignore
|
||||||
const docA = new OLD.Loro();
|
const docA = new OLD.Loro();
|
||||||
docA.getText("text").insert(0, "123");
|
docA.getText("text").insert(0, "123");
|
||||||
docA.getMap("map").set("key", 123);
|
docA.getMap("map").set("key", 123);
|
||||||
|
@ -69,13 +73,14 @@ describe("compatibility", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("basic backward compatibility on exportSnapshot", () => {
|
it("basic backward compatibility on exportSnapshot", () => {
|
||||||
|
// @ts-ignore
|
||||||
const docA = new OLD.Loro();
|
const docA = new OLD.Loro();
|
||||||
docA.getText("text").insert(0, "123");
|
docA.getText("text").insert(0, "123");
|
||||||
docA.getMap("map").set("key", 123);
|
docA.getMap("map").set("key", 123);
|
||||||
docA.getMap("map").set("key", "123");
|
docA.getMap("map").set("key", "123");
|
||||||
docA.getList("list").insert(0, 1);
|
docA.getList("list").insert(0, 1);
|
||||||
docA.getList("list").insert(0, "1");
|
docA.getList("list").insert(0, "1");
|
||||||
|
|
||||||
// const t = docA.getTree("tree");
|
// const t = docA.getTree("tree");
|
||||||
// const node = t.createNode();
|
// const node = t.createNode();
|
||||||
// t.createNode(node.id);
|
// t.createNode(node.id);
|
|
@ -1,5 +1,5 @@
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { CounterDiff, LoroDoc } from "../src";
|
import { CounterDiff, LoroDoc } from "../bundler/index";
|
||||||
|
|
||||||
function oneMs(): Promise<void> {
|
function oneMs(): Promise<void> {
|
||||||
return new Promise((r) => setTimeout(r));
|
return new Promise((r) => setTimeout(r));
|
||||||
|
@ -15,13 +15,13 @@ describe("counter", () => {
|
||||||
expect(counter.value).toBe(2);
|
expect(counter.value).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("encode", async () => {
|
it("encode", async () => {
|
||||||
const doc = new LoroDoc();
|
const doc = new LoroDoc();
|
||||||
const counter = doc.getCounter("counter");
|
const counter = doc.getCounter("counter");
|
||||||
counter.increment(1);
|
counter.increment(1);
|
||||||
counter.increment(2);
|
counter.increment(2);
|
||||||
counter.decrement(4);
|
counter.decrement(4);
|
||||||
|
|
||||||
const updates = doc.exportFrom();
|
const updates = doc.exportFrom();
|
||||||
const snapshot = doc.exportSnapshot();
|
const snapshot = doc.exportSnapshot();
|
||||||
const json = doc.exportJsonUpdates();
|
const json = doc.exportJsonUpdates();
|
|
@ -12,7 +12,7 @@ import {
|
||||||
MapDiff,
|
MapDiff,
|
||||||
TextDiff,
|
TextDiff,
|
||||||
UndoManager,
|
UndoManager,
|
||||||
} from "../src";
|
} from "../bundler/index";
|
||||||
|
|
||||||
describe("detached editing", () => {
|
describe("detached editing", () => {
|
||||||
it("basic tests", async () => {
|
it("basic tests", async () => {
|
|
@ -11,7 +11,7 @@ import {
|
||||||
LoroText,
|
LoroText,
|
||||||
MapDiff,
|
MapDiff,
|
||||||
TextDiff,
|
TextDiff,
|
||||||
} from "../src";
|
} from "../bundler/index";
|
||||||
|
|
||||||
describe("event", () => {
|
describe("event", () => {
|
||||||
it("target", async () => {
|
it("target", async () => {
|
|
@ -8,7 +8,7 @@ import {
|
||||||
LoroMap,
|
LoroMap,
|
||||||
LoroText,
|
LoroText,
|
||||||
LoroTree,
|
LoroTree,
|
||||||
} from "../src";
|
} from "../bundler/index";
|
||||||
|
|
||||||
describe("gc", () => {
|
describe("gc", () => {
|
||||||
it("should export gc snapshot", () => {
|
it("should export gc snapshot", () => {
|
|
@ -1,7 +1,6 @@
|
||||||
import { describe, expect, expectTypeOf, it } from "vitest";
|
import { it } from "vitest";
|
||||||
import { LoroDoc } from "../src";
|
import { LoroDoc } from "../bundler/index";
|
||||||
import { Container, LoroText, OpId } from "../src";
|
import { LoroText, OpId } from "../bundler/index";
|
||||||
import { setDebug } from "loro-wasm";
|
|
||||||
|
|
||||||
it("#211", () => {
|
it("#211", () => {
|
||||||
const loro1 = new LoroDoc();
|
const loro1 = new LoroDoc();
|
|
@ -3,7 +3,7 @@ import {
|
||||||
LoroDoc,
|
LoroDoc,
|
||||||
LoroMap,
|
LoroMap,
|
||||||
TextOp,
|
TextOp,
|
||||||
} from "../src";
|
} from "../bundler/index";
|
||||||
|
|
||||||
it("json encoding", () => {
|
it("json encoding", () => {
|
||||||
const doc = new LoroDoc();
|
const doc = new LoroDoc();
|
|
@ -1,5 +1,5 @@
|
||||||
import { assert, describe, expect, it } from "vitest";
|
import { assert, describe, expect, it } from "vitest";
|
||||||
import { LoroDoc, LoroList, LoroMap, LoroText, VersionVector } from "../src";
|
import { LoroDoc, LoroList, LoroMap, LoroText, VersionVector } from "../bundler/index";
|
||||||
import { expectTypeOf } from "vitest";
|
import { expectTypeOf } from "vitest";
|
||||||
|
|
||||||
function assertEquals(a: any, b: any) {
|
function assertEquals(a: any, b: any) {
|
||||||
|
@ -29,7 +29,7 @@ describe("transaction", () => {
|
||||||
const loro = new LoroDoc();
|
const loro = new LoroDoc();
|
||||||
const text = loro.getText("text");
|
const text = loro.getText("text");
|
||||||
let count = 0;
|
let count = 0;
|
||||||
const sub = loro.subscribe((event: { origin: string }) => {
|
const sub = loro.subscribe((event) => {
|
||||||
count += 1;
|
count += 1;
|
||||||
sub();
|
sub();
|
||||||
assertEquals(event.origin, "origin");
|
assertEquals(event.origin, "origin");
|
|
@ -8,7 +8,7 @@ import {
|
||||||
LoroMovableList,
|
LoroMovableList,
|
||||||
LoroText,
|
LoroText,
|
||||||
TextDiff,
|
TextDiff,
|
||||||
} from "../src";
|
} from "../bundler/index";
|
||||||
|
|
||||||
describe("movable list", () => {
|
describe("movable list", () => {
|
||||||
it("should work like list", () => {
|
it("should work like list", () => {
|
|
@ -1,6 +1,5 @@
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { Delta, LoroDoc, TextDiff } from "../src";
|
import { Delta, LoroDoc, TextDiff, Cursor, OpId } from "../bundler/index";
|
||||||
import { Cursor, OpId, PeerID, setDebug } from "loro-wasm";
|
|
||||||
|
|
||||||
describe("richtext", () => {
|
describe("richtext", () => {
|
||||||
it("mark", () => {
|
it("mark", () => {
|
||||||
|
@ -298,7 +297,7 @@ describe("richtext", () => {
|
||||||
]);
|
]);
|
||||||
text.deleteUtf8(3, 4);
|
text.deleteUtf8(3, 4);
|
||||||
expect(text.toDelta()).toStrictEqual([
|
expect(text.toDelta()).toStrictEqual([
|
||||||
{ insert: "你b"},
|
{ insert: "你b" },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -336,7 +335,7 @@ describe("richtext", () => {
|
||||||
const text = doc.getText('t');
|
const text = doc.getText('t');
|
||||||
text.insert(0, "你好");
|
text.insert(0, "你好");
|
||||||
let str = "";
|
let str = "";
|
||||||
text.iter((s : string)=>{
|
text.iter((s: string) => {
|
||||||
str = str + s;
|
str = str + s;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
|
@ -1,5 +1,5 @@
|
||||||
import { assert, describe, expect, it } from "vitest";
|
import { assert, describe, expect, it } from "vitest";
|
||||||
import { LoroDoc, LoroTree, LoroTreeNode, TreeDiff } from "../src";
|
import { LoroDoc, LoroTree, LoroTreeNode, TreeDiff } from "../bundler/index";
|
||||||
|
|
||||||
function assertEquals(a: any, b: any) {
|
function assertEquals(a: any, b: any) {
|
||||||
expect(a).toStrictEqual(b);
|
expect(a).toStrictEqual(b);
|
|
@ -7,7 +7,7 @@ import {
|
||||||
LoroTree,
|
LoroTree,
|
||||||
PeerID,
|
PeerID,
|
||||||
Value,
|
Value,
|
||||||
} from "../src";
|
} from "../bundler/index";
|
||||||
import { expect, expectTypeOf, test } from "vitest";
|
import { expect, expectTypeOf, test } from "vitest";
|
||||||
|
|
||||||
test("Container should not match Value", () => {
|
test("Container should not match Value", () => {
|
|
@ -1,4 +1,4 @@
|
||||||
import { Cursor, LoroDoc, UndoManager } from "../src";
|
import { Cursor, LoroDoc, UndoManager } from "../bundler/index";
|
||||||
import { describe, expect, test } from "vitest";
|
import { describe, expect, test } from "vitest";
|
||||||
|
|
||||||
describe("undo", () => {
|
describe("undo", () => {
|
|
@ -5,7 +5,7 @@ import {
|
||||||
LoroMap,
|
LoroMap,
|
||||||
OpId,
|
OpId,
|
||||||
VersionVector,
|
VersionVector,
|
||||||
} from "../src";
|
} from "../bundler/index";
|
||||||
|
|
||||||
describe("Frontiers", () => {
|
describe("Frontiers", () => {
|
||||||
it("two clients", () => {
|
it("two clients", () => {
|
116
crates/loro-wasm/tsconfig.json
Normal file
116
crates/loro-wasm/tsconfig.json
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||||
|
/* Projects */
|
||||||
|
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||||
|
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||||
|
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||||
|
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||||
|
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||||
|
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||||
|
/* Language and Environment */
|
||||||
|
"target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||||
|
"lib": [
|
||||||
|
"ES2016",
|
||||||
|
"DOM"
|
||||||
|
], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||||
|
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||||
|
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
||||||
|
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||||
|
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||||
|
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||||
|
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||||
|
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||||
|
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||||
|
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||||
|
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||||
|
/* Modules */
|
||||||
|
"module": "ESNext" /* Specify what module code is generated. */,
|
||||||
|
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||||
|
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||||
|
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||||
|
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||||
|
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||||
|
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||||
|
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||||
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||||
|
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
|
||||||
|
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
|
||||||
|
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
|
||||||
|
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
|
||||||
|
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||||
|
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
|
||||||
|
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||||
|
/* JavaScript Support */
|
||||||
|
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||||
|
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||||
|
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||||
|
/* Emit */
|
||||||
|
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||||
|
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||||
|
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||||
|
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||||
|
"inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||||
|
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||||
|
// "outDir": "./dist" /* Specify an output folder for all emitted files. */,
|
||||||
|
// "removeComments": true, /* Disable emitting comments. */
|
||||||
|
"noEmit": false /* Disable emitting files from a compilation. */,
|
||||||
|
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||||
|
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||||
|
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||||
|
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||||
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
|
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||||
|
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||||
|
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||||
|
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||||
|
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||||
|
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||||
|
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||||
|
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||||
|
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||||
|
/* Interop Constraints */
|
||||||
|
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||||
|
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
|
||||||
|
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||||
|
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
|
||||||
|
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||||
|
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
||||||
|
/* Type Checking */
|
||||||
|
"strict": true /* Enable all strict type-checking options. */,
|
||||||
|
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||||
|
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||||
|
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||||
|
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||||
|
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||||
|
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||||
|
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||||
|
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||||
|
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||||
|
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||||
|
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||||
|
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||||
|
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||||
|
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||||
|
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||||
|
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||||
|
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||||
|
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||||
|
/* Completeness */
|
||||||
|
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||||
|
"skipLibCheck": true, /* Skip type checking all .d.ts files. */
|
||||||
|
"paths": {
|
||||||
|
"loro-wasm": [
|
||||||
|
"./nodejs/loro_wasm.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"dist",
|
||||||
|
"deno",
|
||||||
|
"scripts",
|
||||||
|
"deno_tests",
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
|
@ -6,7 +6,8 @@ export default defineConfig({
|
||||||
test: {
|
test: {
|
||||||
exclude: [
|
exclude: [
|
||||||
...configDefaults.exclude,
|
...configDefaults.exclude,
|
||||||
"deno/*"
|
"deno/*",
|
||||||
|
"deno_tests/*"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
});
|
});
|
3
loro-js/.gitignore
vendored
3
loro-js/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
||||||
node_modules/
|
|
||||||
dist/
|
|
||||||
docs/
|
|
|
@ -1,10 +0,0 @@
|
||||||
tests/
|
|
||||||
.vscode/
|
|
||||||
deno/
|
|
||||||
src/
|
|
||||||
node_modules/
|
|
||||||
pnpm-lock.yaml
|
|
||||||
rollup.config.mjs
|
|
||||||
tsconfig.json
|
|
||||||
vite.config.ts
|
|
||||||
CHANGELOG.md
|
|
8
loro-js/.vscode/settings.json
vendored
8
loro-js/.vscode/settings.json
vendored
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"deno.enable": false,
|
|
||||||
"editor.defaultFormatter": "vscode.typescript-language-features",
|
|
||||||
"editor.formatOnSave": true,
|
|
||||||
"[typescript]": {
|
|
||||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
|
||||||
}
|
|
||||||
}
|
|
1399
loro-js/CHANGELOG.md
1399
loro-js/CHANGELOG.md
File diff suppressed because it is too large
Load diff
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2023 Loro
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -1,138 +0,0 @@
|
||||||
<p align="center">
|
|
||||||
<a href="https://loro.dev">
|
|
||||||
<picture>
|
|
||||||
<img src="./docs/Loro.svg" width="200"/>
|
|
||||||
</picture>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<h1 align="center">
|
|
||||||
<a href="https://loro.dev" alt="loro-site">Loro</a>
|
|
||||||
</h1>
|
|
||||||
<p align="center">
|
|
||||||
<b>Reimagine state management with CRDTs 🦜</b><br/>
|
|
||||||
Make your app state synchronized and collaborative effortlessly.
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://trendshift.io/repositories/4964" target="_blank"><img src="https://trendshift.io/api/badge/repositories/4964" alt="loro-dev%2Floro | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://loro.dev/docs">
|
|
||||||
<b>Documentation</b>
|
|
||||||
</a>
|
|
||||||
|
|
|
||||||
<a href="https://loro.dev/docs/tutorial/get_started">
|
|
||||||
<b>Getting Started</b>
|
|
||||||
</a>
|
|
||||||
|
|
|
||||||
<a href="https://docs.rs/loro">
|
|
||||||
<b>Rust Doc</b>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
|
||||||
<a aria-label="X" href="https://x.com/loro_dev" target="_blank">
|
|
||||||
<img alt="" src="https://img.shields.io/badge/Twitter-black?style=for-the-badge&logo=Twitter">
|
|
||||||
</a>
|
|
||||||
<a aria-label="Discord-Link" href="https://discord.gg/tUsBSVfqzf" target="_blank">
|
|
||||||
<img alt="" src="https://img.shields.io/badge/Discord-black?style=for-the-badge&logo=discord">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
https://github.com/loro-dev/loro/assets/18425020/fe246c47-a120-44b3-91d4-1e7232a5b4ac
|
|
||||||
|
|
||||||
Loro is a [CRDTs(Conflict-free Replicated Data Types)](https://crdt.tech/) library that makes building [local-first apps][local-first] easier. It is currently available for JavaScript (via WASM) and Rust developers.
|
|
||||||
|
|
||||||
Explore our vision in our blog: [**✨ Reimagine State Management with CRDTs**](https://loro.dev/blog/loro-now-open-source).
|
|
||||||
|
|
||||||
# Features
|
|
||||||
|
|
||||||
**Basic Features Provided by CRDTs**
|
|
||||||
|
|
||||||
- P2P Synchronization
|
|
||||||
- Automatic Merging
|
|
||||||
- Local Availability
|
|
||||||
- Scalability
|
|
||||||
- Delta Updates
|
|
||||||
|
|
||||||
**Supported CRDT Algorithms**
|
|
||||||
|
|
||||||
- 📝 Text Editing with [Fugue]
|
|
||||||
- 📙 [Peritext-like Rich Text CRDT](https://loro.dev/blog/loro-richtext)
|
|
||||||
- 🌲 [Moveable Tree](https://loro.dev/docs/tutorial/tree)
|
|
||||||
- 🚗 [Moveable List](https://loro.dev/docs/tutorial/list)
|
|
||||||
- 🗺️ [Last-Write-Wins Map](https://loro.dev/docs/tutorial/map)
|
|
||||||
- 🔄 [Replayable Event Graph](https://loro.dev/docs/advanced/replayable_event_graph)
|
|
||||||
|
|
||||||
**Advanced Features in Loro**
|
|
||||||
|
|
||||||
- 📖 Preserve Editing History in a [Replayable Event Graph](https://loro.dev/docs/advanced/replayable_event_graph)
|
|
||||||
- ⏱️ Fast [Time Travel](https://loro.dev/docs/tutorial/time_travel) Through History
|
|
||||||
|
|
||||||
https://github.com/loro-dev/loro/assets/18425020/ec2d20a3-3d8c-4483-a601-b200243c9792
|
|
||||||
|
|
||||||
# Example
|
|
||||||
|
|
||||||
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/edit/loro-basic-test?file=test%2Floro-sync.test.ts)
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { expect, test } from 'vitest';
|
|
||||||
import { Loro, LoroList } from 'loro-crdt';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Demonstrates synchronization of two documents with two rounds of exchanges.
|
|
||||||
*/
|
|
||||||
// Initialize document A
|
|
||||||
const docA = new Loro();
|
|
||||||
const listA: LoroList = docA.getList('list');
|
|
||||||
listA.insert(0, 'A');
|
|
||||||
listA.insert(1, 'B');
|
|
||||||
listA.insert(2, 'C');
|
|
||||||
|
|
||||||
// Export the state of document A as a byte array
|
|
||||||
const bytes: Uint8Array = docA.exportFrom();
|
|
||||||
|
|
||||||
// Simulate sending `bytes` across the network to another peer, B
|
|
||||||
const docB = new Loro();
|
|
||||||
// Peer B imports the updates from A
|
|
||||||
docB.import(bytes);
|
|
||||||
|
|
||||||
// Verify that B's state matches A's state
|
|
||||||
expect(docB.toJSON()).toStrictEqual({
|
|
||||||
list: ['A', 'B', 'C'],
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get the current operation log version of document B
|
|
||||||
const version = docB.oplogVersion();
|
|
||||||
|
|
||||||
// Simulate editing at B: delete item 'B'
|
|
||||||
const listB: LoroList = docB.getList('list');
|
|
||||||
listB.delete(1, 1);
|
|
||||||
|
|
||||||
// Export the updates from B since the last synchronization point
|
|
||||||
const bytesB: Uint8Array = docB.exportFrom(version);
|
|
||||||
|
|
||||||
// Simulate sending `bytesB` back across the network to A
|
|
||||||
// A imports the updates from B
|
|
||||||
docA.import(bytesB);
|
|
||||||
|
|
||||||
// Verify that the list at A now matches the list at B after merging
|
|
||||||
expect(docA.toJSON()).toStrictEqual({
|
|
||||||
list: ['A', 'C'],
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
# Credits
|
|
||||||
|
|
||||||
Loro draws inspiration from the innovative work of the following projects and individuals:
|
|
||||||
|
|
||||||
- [Ink & Switch](https://inkandswitch.com/): The principles of Local-first Software have greatly influenced this project. The [Peritext](https://www.inkandswitch.com/peritext/) project has also shaped our approach to rich text CRDTs.
|
|
||||||
- [Diamond-types](https://github.com/josephg/diamond-types): The [Replayable Event Graph (REG)](https://loro.dev/docs/advanced/replayable_event_graph) algorithm from @josephg has been adapted to reduce the computation and space usage of CRDTs.
|
|
||||||
- [Automerge](https://github.com/automerge/automerge): Their use of columnar encoding for CRDTs has informed our strategies for efficient data encoding.
|
|
||||||
- [Yjs](https://github.com/yjs/yjs): We have incorporated a similar algorithm for effectively merging collaborative editing operations, thanks to their pioneering works.
|
|
||||||
- [Matthew Weidner](https://mattweidner.com/): His work on the [Fugue](https://arxiv.org/abs/2305.00583) algorithm has been invaluable, enhancing our text editing capabilities.
|
|
||||||
- [Martin Kleppmann](https://martin.kleppmann.com/): His work on CRDTs has significantly influenced our comprehension of the field.
|
|
||||||
|
|
||||||
|
|
||||||
[local-first]: https://www.inkandswitch.com/local-first/
|
|
||||||
[Fugue]: https://arxiv.org/abs/2305.00583
|
|
||||||
[Peritext]: https://www.inkandswitch.com/peritext/
|
|
3
loro-js/deno/.vscode/settings.json
vendored
3
loro-js/deno/.vscode/settings.json
vendored
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"deno.enable": true
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@loro/loro",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"exports": "./mod.ts"
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export * from "npm:loro-crdt@0.14.2";
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { Loro } from "./mod.ts";
|
|
||||||
import { expect } from 'npm:expect'
|
|
||||||
|
|
||||||
Deno.test("test", () => {
|
|
||||||
const doc = new Loro();
|
|
||||||
const text = doc.getText("text");
|
|
||||||
text.insert(0, "123")
|
|
||||||
expect(text.toString()).toEqual("123");
|
|
||||||
text.insert(0, "123")
|
|
||||||
expect(text.toString()).toEqual("123123");
|
|
||||||
const docB = Loro.fromSnapshot(doc.exportSnapshot());
|
|
||||||
expect(docB.getText('text').toString()).toEqual("123123");
|
|
||||||
})
|
|
|
@ -1,49 +0,0 @@
|
||||||
{
|
|
||||||
"name": "loro-crdt",
|
|
||||||
"version": "1.0.7",
|
|
||||||
"description": "Loro CRDTs is a high-performance CRDT framework that makes your app state synchronized, collaborative and maintainable effortlessly.",
|
|
||||||
"keywords": [
|
|
||||||
"crdt",
|
|
||||||
"CRDTs",
|
|
||||||
"realtime",
|
|
||||||
"collaboration",
|
|
||||||
"sync",
|
|
||||||
"p2p"
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/loro-dev/loro.git"
|
|
||||||
},
|
|
||||||
"main": "dist/loro.js",
|
|
||||||
"module": "dist/loro.mjs",
|
|
||||||
"typings": "dist/loro.d.ts",
|
|
||||||
"scripts": {
|
|
||||||
"build": "rollup -c",
|
|
||||||
"watch": "rollup -c -w",
|
|
||||||
"test": "node --expose-gc ./node_modules/vitest/vitest.mjs run && npx tsc --noEmit",
|
|
||||||
"prepublish": "pnpm run build"
|
|
||||||
},
|
|
||||||
"author": "Loro",
|
|
||||||
"homepage": "https://loro.dev",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"loro-wasm": "workspace:*"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
||||||
"@typescript-eslint/parser": "^6.2.0",
|
|
||||||
"@vitest/ui": "^1.0.4",
|
|
||||||
"esbuild": "^0.18.20",
|
|
||||||
"eslint": "^8.46.0",
|
|
||||||
"loro-crdt-old": "npm:loro-crdt@=0.16.0",
|
|
||||||
"loro-crdt-alpha-4": "npm:loro-crdt@=1.0.0-alpha.4",
|
|
||||||
"prettier": "^3.0.0",
|
|
||||||
"rollup": "^3.20.1",
|
|
||||||
"rollup-plugin-dts": "^5.3.0",
|
|
||||||
"rollup-plugin-esbuild": "^5.0.0",
|
|
||||||
"typescript": "^5.0.2",
|
|
||||||
"vite": "^4.2.1",
|
|
||||||
"vite-plugin-wasm": "^3.2.2",
|
|
||||||
"vitest": "^1.4.0"
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,37 +0,0 @@
|
||||||
import { defineConfig } from "rollup";
|
|
||||||
import dts from "rollup-plugin-dts";
|
|
||||||
import esbuild from "rollup-plugin-esbuild";
|
|
||||||
import packageJson from "./package.json" assert { type: "json" };
|
|
||||||
|
|
||||||
const name = packageJson.main.replace(/\.js$/, "");
|
|
||||||
|
|
||||||
const bundle = (config) => ({
|
|
||||||
...config,
|
|
||||||
input: "src/index.ts",
|
|
||||||
external: (id) => !/^[./]/.test(id),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default defineConfig([
|
|
||||||
bundle({
|
|
||||||
plugins: [esbuild()],
|
|
||||||
output: [
|
|
||||||
{
|
|
||||||
file: `${name}.js`,
|
|
||||||
format: "cjs",
|
|
||||||
sourcemap: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
file: `${name}.mjs`,
|
|
||||||
format: "es",
|
|
||||||
sourcemap: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
bundle({
|
|
||||||
plugins: [dts()],
|
|
||||||
output: {
|
|
||||||
file: `${name}.d.ts`,
|
|
||||||
format: "es",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]);
|
|
|
@ -1,108 +0,0 @@
|
||||||
import { AwarenessWasm, PeerID, Value } from "loro-wasm";
|
|
||||||
|
|
||||||
export type AwarenessListener = (
|
|
||||||
arg: { updated: PeerID[]; added: PeerID[]; removed: PeerID[] },
|
|
||||||
origin: "local" | "timeout" | "remote" | string,
|
|
||||||
) => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Awareness is a structure that allows to track the ephemeral state of the peers.
|
|
||||||
*
|
|
||||||
* If we don't receive a state update from a peer within the timeout, we will remove their state.
|
|
||||||
* The timeout is in milliseconds. This can be used to handle the off-line state of a peer.
|
|
||||||
*/
|
|
||||||
export class Awareness<T extends Value = Value> {
|
|
||||||
inner: AwarenessWasm<T>;
|
|
||||||
private peer: PeerID;
|
|
||||||
private timer: number | undefined;
|
|
||||||
private timeout: number;
|
|
||||||
private listeners: Set<AwarenessListener> = new Set();
|
|
||||||
constructor(peer: PeerID, timeout: number = 30000) {
|
|
||||||
this.inner = new AwarenessWasm(peer, timeout);
|
|
||||||
this.peer = peer;
|
|
||||||
this.timeout = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply(bytes: Uint8Array, origin = "remote") {
|
|
||||||
const { updated, added } = this.inner.apply(bytes);
|
|
||||||
this.listeners.forEach((listener) => {
|
|
||||||
listener({ updated, added, removed: [] }, origin);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.startTimerIfNotEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
setLocalState(state: T) {
|
|
||||||
const wasEmpty = this.inner.getState(this.peer) == null;
|
|
||||||
this.inner.setLocalState(state);
|
|
||||||
if (wasEmpty) {
|
|
||||||
this.listeners.forEach((listener) => {
|
|
||||||
listener(
|
|
||||||
{ updated: [], added: [this.inner.peer()], removed: [] },
|
|
||||||
"local",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.listeners.forEach((listener) => {
|
|
||||||
listener(
|
|
||||||
{ updated: [this.inner.peer()], added: [], removed: [] },
|
|
||||||
"local",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.startTimerIfNotEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
getLocalState(): T | undefined {
|
|
||||||
return this.inner.getState(this.peer);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAllStates(): Record<PeerID, T> {
|
|
||||||
return this.inner.getAllStates();
|
|
||||||
}
|
|
||||||
|
|
||||||
encode(peers: PeerID[]): Uint8Array {
|
|
||||||
return this.inner.encode(peers);
|
|
||||||
}
|
|
||||||
|
|
||||||
encodeAll(): Uint8Array {
|
|
||||||
return this.inner.encodeAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
addListener(listener: AwarenessListener) {
|
|
||||||
this.listeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeListener(listener: AwarenessListener) {
|
|
||||||
this.listeners.delete(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
peers(): PeerID[] {
|
|
||||||
return this.inner.peers();
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy() {
|
|
||||||
clearInterval(this.timer);
|
|
||||||
this.listeners.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private startTimerIfNotEmpty() {
|
|
||||||
if (this.inner.isEmpty() || this.timer != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.timer = setInterval(() => {
|
|
||||||
const removed = this.inner.removeOutdated();
|
|
||||||
if (removed.length > 0) {
|
|
||||||
this.listeners.forEach((listener) => {
|
|
||||||
listener({ updated: [], added: [], removed }, "timeout");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (this.inner.isEmpty()) {
|
|
||||||
clearInterval(this.timer);
|
|
||||||
this.timer = undefined;
|
|
||||||
}
|
|
||||||
}, this.timeout / 2) as unknown as number;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,681 +0,0 @@
|
||||||
export * from "loro-wasm";
|
|
||||||
export type * from "loro-wasm";
|
|
||||||
import {
|
|
||||||
Container,
|
|
||||||
ContainerID,
|
|
||||||
ContainerType,
|
|
||||||
Delta,
|
|
||||||
LoroCounter,
|
|
||||||
LoroDoc,
|
|
||||||
LoroList,
|
|
||||||
LoroMap,
|
|
||||||
LoroText,
|
|
||||||
LoroTree,
|
|
||||||
OpId,
|
|
||||||
TreeID,
|
|
||||||
Value,
|
|
||||||
} from "loro-wasm";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Please use LoroDoc
|
|
||||||
*/
|
|
||||||
export class Loro extends LoroDoc {}
|
|
||||||
export { Awareness } from "./awareness";
|
|
||||||
|
|
||||||
export type Frontiers = OpId[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a path to identify the exact location of an event's target.
|
|
||||||
* The path is composed of numbers (e.g., indices of a list container) strings
|
|
||||||
* (e.g., keys of a map container) and TreeID (the node of a tree container),
|
|
||||||
* indicating the absolute position of the event's source within a loro document.
|
|
||||||
*/
|
|
||||||
export type Path = (number | string | TreeID)[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A batch of events that created by a single `import`/`transaction`/`checkout`.
|
|
||||||
*
|
|
||||||
* @prop by - How the event is triggered.
|
|
||||||
* @prop origin - (Optional) Provides information about the origin of the event.
|
|
||||||
* @prop diff - Contains the differential information related to the event.
|
|
||||||
* @prop target - Identifies the container ID of the event's target.
|
|
||||||
* @prop path - Specifies the absolute path of the event's emitter, which can be an index of a list container or a key of a map container.
|
|
||||||
*/
|
|
||||||
export interface LoroEventBatch {
|
|
||||||
/**
|
|
||||||
* How the event is triggered.
|
|
||||||
*
|
|
||||||
* - `local`: The event is triggered by a local transaction.
|
|
||||||
* - `import`: The event is triggered by an import operation.
|
|
||||||
* - `checkout`: The event is triggered by a checkout operation.
|
|
||||||
*/
|
|
||||||
by: "local" | "import" | "checkout";
|
|
||||||
origin?: string;
|
|
||||||
/**
|
|
||||||
* The container ID of the current event receiver.
|
|
||||||
* It's undefined if the subscriber is on the root document.
|
|
||||||
*/
|
|
||||||
currentTarget?: ContainerID;
|
|
||||||
events: LoroEvent[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The concrete event of Loro.
|
|
||||||
*/
|
|
||||||
export interface LoroEvent {
|
|
||||||
/**
|
|
||||||
* The container ID of the event's target.
|
|
||||||
*/
|
|
||||||
target: ContainerID;
|
|
||||||
diff: Diff;
|
|
||||||
/**
|
|
||||||
* The absolute path of the event's emitter, which can be an index of a list container or a key of a map container.
|
|
||||||
*/
|
|
||||||
path: Path;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ListDiff = {
|
|
||||||
type: "list";
|
|
||||||
diff: Delta<(Value | Container)[]>[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TextDiff = {
|
|
||||||
type: "text";
|
|
||||||
diff: Delta<string>[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type MapDiff = {
|
|
||||||
type: "map";
|
|
||||||
updated: Record<string, Value | Container | undefined>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TreeDiffItem =
|
|
||||||
| {
|
|
||||||
target: TreeID;
|
|
||||||
action: "create";
|
|
||||||
parent: TreeID | undefined;
|
|
||||||
index: number;
|
|
||||||
fractionalIndex: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
target: TreeID;
|
|
||||||
action: "delete";
|
|
||||||
oldParent: TreeID | undefined;
|
|
||||||
oldIndex: number;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
target: TreeID;
|
|
||||||
action: "move";
|
|
||||||
parent: TreeID | undefined;
|
|
||||||
index: number;
|
|
||||||
fractionalIndex: string;
|
|
||||||
oldParent: TreeID | undefined;
|
|
||||||
oldIndex: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TreeDiff = {
|
|
||||||
type: "tree";
|
|
||||||
diff: TreeDiffItem[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CounterDiff = {
|
|
||||||
type: "counter";
|
|
||||||
increment: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Diff = ListDiff | TextDiff | MapDiff | TreeDiff | CounterDiff;
|
|
||||||
|
|
||||||
interface Listener {
|
|
||||||
(event: LoroEventBatch): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CONTAINER_TYPES = [
|
|
||||||
"Map",
|
|
||||||
"Text",
|
|
||||||
"List",
|
|
||||||
"Tree",
|
|
||||||
"MovableList",
|
|
||||||
"Counter",
|
|
||||||
];
|
|
||||||
|
|
||||||
export function isContainerId(s: string): s is ContainerID {
|
|
||||||
return s.startsWith("cid:");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the value is a container.
|
|
||||||
*
|
|
||||||
* # Example
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const map = doc.getMap("map");
|
|
||||||
* const list = doc.getList("list");
|
|
||||||
* const text = doc.getText("text");
|
|
||||||
* isContainer(map); // true
|
|
||||||
* isContainer(list); // true
|
|
||||||
* isContainer(text); // true
|
|
||||||
* isContainer(123); // false
|
|
||||||
* isContainer("123"); // false
|
|
||||||
* isContainer({}); // false
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export function isContainer(value: any): value is Container {
|
|
||||||
if (typeof value !== "object" || value == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const p = Object.getPrototypeOf(value);
|
|
||||||
if (p == null || typeof p !== "object" || typeof p["kind"] !== "function") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CONTAINER_TYPES.includes(value.kind());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the type of a value that may be a container.
|
|
||||||
*
|
|
||||||
* # Example
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const map = doc.getMap("map");
|
|
||||||
* const list = doc.getList("list");
|
|
||||||
* const text = doc.getText("text");
|
|
||||||
* getType(map); // "Map"
|
|
||||||
* getType(list); // "List"
|
|
||||||
* getType(text); // "Text"
|
|
||||||
* getType(123); // "Json"
|
|
||||||
* getType("123"); // "Json"
|
|
||||||
* getType({}); // "Json"
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export function getType<T>(
|
|
||||||
value: T,
|
|
||||||
): T extends LoroText ? "Text"
|
|
||||||
: T extends LoroMap<any> ? "Map"
|
|
||||||
: T extends LoroTree<any> ? "Tree"
|
|
||||||
: T extends LoroList<any> ? "List"
|
|
||||||
: T extends LoroCounter ? "Counter"
|
|
||||||
: "Json" {
|
|
||||||
if (isContainer(value)) {
|
|
||||||
return value.kind() as unknown as any;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Json" as any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Subscription = () => void;
|
|
||||||
declare module "loro-wasm" {
|
|
||||||
interface LoroDoc {
|
|
||||||
subscribe(listener: Listener): Subscription;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UndoManager {
|
|
||||||
/**
|
|
||||||
* Set the callback function that is called when an undo/redo step is pushed.
|
|
||||||
* The function can return a meta data value that will be attached to the given stack item.
|
|
||||||
*
|
|
||||||
* @param listener - The callback function.
|
|
||||||
*/
|
|
||||||
setOnPush(listener?: UndoConfig["onPush"]): void;
|
|
||||||
/**
|
|
||||||
* Set the callback function that is called when an undo/redo step is popped.
|
|
||||||
* The function will have a meta data value that was attached to the given stack item when `onPush` was called.
|
|
||||||
*
|
|
||||||
* @param listener - The callback function.
|
|
||||||
*/
|
|
||||||
setOnPop(listener?: UndoConfig["onPop"]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LoroDoc<
|
|
||||||
T extends Record<string, Container> = Record<string, Container>,
|
|
||||||
> {
|
|
||||||
/**
|
|
||||||
* Get a LoroMap by container id
|
|
||||||
*
|
|
||||||
* The object returned is a new js object each time because it need to cross
|
|
||||||
* the WASM boundary.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const map = doc.getMap("map");
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
getMap<Key extends keyof T | ContainerID>(
|
|
||||||
name: Key,
|
|
||||||
): T[Key] extends LoroMap ? T[Key] : LoroMap;
|
|
||||||
/**
|
|
||||||
* Get a LoroList by container id
|
|
||||||
*
|
|
||||||
* The object returned is a new js object each time because it need to cross
|
|
||||||
* the WASM boundary.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getList("list");
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
getList<Key extends keyof T | ContainerID>(
|
|
||||||
name: Key,
|
|
||||||
): T[Key] extends LoroList ? T[Key] : LoroList;
|
|
||||||
/**
|
|
||||||
* Get a LoroMovableList by container id
|
|
||||||
*
|
|
||||||
* The object returned is a new js object each time because it need to cross
|
|
||||||
* the WASM boundary.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getList("list");
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
getMovableList<Key extends keyof T | ContainerID>(
|
|
||||||
name: Key,
|
|
||||||
): T[Key] extends LoroMovableList ? T[Key] : LoroMovableList;
|
|
||||||
/**
|
|
||||||
* Get a LoroTree by container id
|
|
||||||
*
|
|
||||||
* The object returned is a new js object each time because it need to cross
|
|
||||||
* the WASM boundary.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const tree = doc.getTree("tree");
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
getTree<Key extends keyof T | ContainerID>(
|
|
||||||
name: Key,
|
|
||||||
): T[Key] extends LoroTree ? T[Key] : LoroTree;
|
|
||||||
getText(key: string | ContainerID): LoroText;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LoroList<T = unknown> {
|
|
||||||
new (): LoroList<T>;
|
|
||||||
/**
|
|
||||||
* Get elements of the list. If the value is a child container, the corresponding
|
|
||||||
* `Container` will be returned.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getList("list");
|
|
||||||
* list.insert(0, 100);
|
|
||||||
* list.insert(1, "foo");
|
|
||||||
* list.insert(2, true);
|
|
||||||
* list.insertContainer(3, new LoroText());
|
|
||||||
* console.log(list.value); // [100, "foo", true, LoroText];
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
toArray(): T[];
|
|
||||||
/**
|
|
||||||
* Insert a container at the index.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getList("list");
|
|
||||||
* list.insert(0, 100);
|
|
||||||
* const text = list.insertContainer(1, new LoroText());
|
|
||||||
* text.insert(0, "Hello");
|
|
||||||
* console.log(list.toJSON()); // [100, "Hello"];
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
insertContainer<C extends Container>(
|
|
||||||
pos: number,
|
|
||||||
child: C,
|
|
||||||
): T extends C ? T : C;
|
|
||||||
/**
|
|
||||||
* Get the value at the index. If the value is a container, the corresponding handler will be returned.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getList("list");
|
|
||||||
* list.insert(0, 100);
|
|
||||||
* console.log(list.get(0)); // 100
|
|
||||||
* console.log(list.get(1)); // undefined
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
get(index: number): T;
|
|
||||||
/**
|
|
||||||
* Insert a value at index.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getList("list");
|
|
||||||
* list.insert(0, 100);
|
|
||||||
* list.insert(1, "foo");
|
|
||||||
* list.insert(2, true);
|
|
||||||
* console.log(list.value); // [100, "foo", true];
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
insert<V extends T>(pos: number, value: Exclude<V, Container>): void;
|
|
||||||
delete(pos: number, len: number): void;
|
|
||||||
push<V extends T>(value: Exclude<V, Container>): void;
|
|
||||||
subscribe(listener: Listener): Subscription;
|
|
||||||
getAttached(): undefined | LoroList<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LoroMovableList<T = unknown> {
|
|
||||||
new (): LoroMovableList<T>;
|
|
||||||
/**
|
|
||||||
* Get elements of the list. If the value is a child container, the corresponding
|
|
||||||
* `Container` will be returned.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getMovableList("list");
|
|
||||||
* list.insert(0, 100);
|
|
||||||
* list.insert(1, "foo");
|
|
||||||
* list.insert(2, true);
|
|
||||||
* list.insertContainer(3, new LoroText());
|
|
||||||
* console.log(list.value); // [100, "foo", true, LoroText];
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
toArray(): T[];
|
|
||||||
/**
|
|
||||||
* Insert a container at the index.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getMovableList("list");
|
|
||||||
* list.insert(0, 100);
|
|
||||||
* const text = list.insertContainer(1, new LoroText());
|
|
||||||
* text.insert(0, "Hello");
|
|
||||||
* console.log(list.toJSON()); // [100, "Hello"];
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
insertContainer<C extends Container>(
|
|
||||||
pos: number,
|
|
||||||
child: C,
|
|
||||||
): T extends C ? T : C;
|
|
||||||
/**
|
|
||||||
* Get the value at the index. If the value is a container, the corresponding handler will be returned.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getMovableList("list");
|
|
||||||
* list.insert(0, 100);
|
|
||||||
* console.log(list.get(0)); // 100
|
|
||||||
* console.log(list.get(1)); // undefined
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
get(index: number): T;
|
|
||||||
/**
|
|
||||||
* Insert a value at index.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getMovableList("list");
|
|
||||||
* list.insert(0, 100);
|
|
||||||
* list.insert(1, "foo");
|
|
||||||
* list.insert(2, true);
|
|
||||||
* console.log(list.value); // [100, "foo", true];
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
insert<V extends T>(pos: number, value: Exclude<V, Container>): void;
|
|
||||||
delete(pos: number, len: number): void;
|
|
||||||
push<V extends T>(value: Exclude<V, Container>): void;
|
|
||||||
subscribe(listener: Listener): Subscription;
|
|
||||||
getAttached(): undefined | LoroMovableList<T>;
|
|
||||||
/**
|
|
||||||
* Set the value at the given position.
|
|
||||||
*
|
|
||||||
* It's different from `delete` + `insert` that it will replace the value at the position.
|
|
||||||
*
|
|
||||||
* For example, if you have a list `[1, 2, 3]`, and you call `set(1, 100)`, the list will be `[1, 100, 3]`.
|
|
||||||
* If concurrently someone call `set(1, 200)`, the list will be `[1, 200, 3]` or `[1, 100, 3]`.
|
|
||||||
*
|
|
||||||
* But if you use `delete` + `insert` to simulate the set operation, they may create redundant operations
|
|
||||||
* and the final result will be `[1, 100, 200, 3]` or `[1, 200, 100, 3]`.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getMovableList("list");
|
|
||||||
* list.insert(0, 100);
|
|
||||||
* list.insert(1, "foo");
|
|
||||||
* list.insert(2, true);
|
|
||||||
* list.set(1, "bar");
|
|
||||||
* console.log(list.value); // [100, "bar", true];
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
set<V extends T>(pos: number, value: Exclude<V, Container>): void;
|
|
||||||
/**
|
|
||||||
* Set a container at the index.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const list = doc.getMovableList("list");
|
|
||||||
* list.insert(0, 100);
|
|
||||||
* const text = list.setContainer(0, new LoroText());
|
|
||||||
* text.insert(0, "Hello");
|
|
||||||
* console.log(list.toJSON()); // ["Hello"];
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
setContainer<C extends Container>(
|
|
||||||
pos: number,
|
|
||||||
child: C,
|
|
||||||
): T extends C ? T : C;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LoroMap<
|
|
||||||
T extends Record<string, unknown> = Record<string, unknown>,
|
|
||||||
> {
|
|
||||||
new (): LoroMap<T>;
|
|
||||||
/**
|
|
||||||
* Get the value of the key. If the value is a child container, the corresponding
|
|
||||||
* `Container` will be returned.
|
|
||||||
*
|
|
||||||
* The object returned is a new js object each time because it need to cross
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const map = doc.getMap("map");
|
|
||||||
* map.set("foo", "bar");
|
|
||||||
* const bar = map.get("foo");
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
getOrCreateContainer<C extends Container>(key: string, child: C): C;
|
|
||||||
/**
|
|
||||||
* Set the key with a container.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc, LoroText, LoroList } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const map = doc.getMap("map");
|
|
||||||
* map.set("foo", "bar");
|
|
||||||
* const text = map.setContainer("text", new LoroText());
|
|
||||||
* const list = map.setContainer("list", new LoroList());
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
setContainer<C extends Container, Key extends keyof T>(
|
|
||||||
key: Key,
|
|
||||||
child: C,
|
|
||||||
): NonNullableType<T[Key]> extends C ? NonNullableType<T[Key]> : C;
|
|
||||||
/**
|
|
||||||
* Get the value of the key. If the value is a child container, the corresponding
|
|
||||||
* `Container` will be returned.
|
|
||||||
*
|
|
||||||
* The object/value returned is a new js object/value each time because it need to cross
|
|
||||||
* the WASM boundary.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const map = doc.getMap("map");
|
|
||||||
* map.set("foo", "bar");
|
|
||||||
* const bar = map.get("foo");
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
get<Key extends keyof T>(key: Key): T[Key];
|
|
||||||
/**
|
|
||||||
* Set the key with the value.
|
|
||||||
*
|
|
||||||
* If the value of the key is exist, the old value will be updated.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const map = doc.getMap("map");
|
|
||||||
* map.set("foo", "bar");
|
|
||||||
* map.set("foo", "baz");
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
set<Key extends keyof T, V extends T[Key]>(
|
|
||||||
key: Key,
|
|
||||||
value: Exclude<V, Container>,
|
|
||||||
): void;
|
|
||||||
delete(key: string): void;
|
|
||||||
subscribe(listener: Listener): Subscription;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LoroText {
|
|
||||||
new (): LoroText;
|
|
||||||
insert(pos: number, text: string): void;
|
|
||||||
delete(pos: number, len: number): void;
|
|
||||||
subscribe(listener: Listener): Subscription;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LoroTree<
|
|
||||||
T extends Record<string, unknown> = Record<string, unknown>,
|
|
||||||
> {
|
|
||||||
new (): LoroTree<T>;
|
|
||||||
/**
|
|
||||||
* Create a new tree node as the child of parent and return a `LoroTreeNode` instance.
|
|
||||||
* If the parent is undefined, the tree node will be a root node.
|
|
||||||
*
|
|
||||||
* If the index is not provided, the new node will be appended to the end.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* const doc = new LoroDoc();
|
|
||||||
* const tree = doc.getTree("tree");
|
|
||||||
* const root = tree.createNode();
|
|
||||||
* const node = tree.createNode(undefined, 0);
|
|
||||||
*
|
|
||||||
* // undefined
|
|
||||||
* // / \
|
|
||||||
* // node root
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
createNode(parent?: TreeID, index?: number): LoroTreeNode<T>;
|
|
||||||
move(target: TreeID, parent?: TreeID, index?: number): void;
|
|
||||||
delete(target: TreeID): void;
|
|
||||||
has(target: TreeID): boolean;
|
|
||||||
/**
|
|
||||||
* Get LoroTreeNode by the TreeID.
|
|
||||||
*/
|
|
||||||
getNodeByID(target: TreeID): LoroTreeNode<T>;
|
|
||||||
subscribe(listener: Listener): Subscription;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LoroTreeNode<
|
|
||||||
T extends Record<string, unknown> = Record<string, unknown>,
|
|
||||||
> {
|
|
||||||
/**
|
|
||||||
* Get the associated metadata map container of a tree node.
|
|
||||||
*/
|
|
||||||
readonly data: LoroMap<T>;
|
|
||||||
/**
|
|
||||||
* Create a new node as the child of the current node and
|
|
||||||
* return an instance of `LoroTreeNode`.
|
|
||||||
*
|
|
||||||
* If the index is not provided, the new node will be appended to the end.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```typescript
|
|
||||||
* import { LoroDoc } from "loro-crdt";
|
|
||||||
*
|
|
||||||
* let doc = new LoroDoc();
|
|
||||||
* let tree = doc.getTree("tree");
|
|
||||||
* let root = tree.createNode();
|
|
||||||
* let node = root.createNode();
|
|
||||||
* let node2 = root.createNode(0);
|
|
||||||
* // root
|
|
||||||
* // / \
|
|
||||||
* // node2 node
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
createNode(index?: number): LoroTreeNode<T>;
|
|
||||||
move(parent?: LoroTreeNode<T>, index?: number): void;
|
|
||||||
parent(): LoroTreeNode<T> | undefined;
|
|
||||||
/**
|
|
||||||
* Get the children of this node.
|
|
||||||
*
|
|
||||||
* The objects returned are new js objects each time because they need to cross
|
|
||||||
* the WASM boundary.
|
|
||||||
*/
|
|
||||||
children(): Array<LoroTreeNode<T>> | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AwarenessWasm<T extends Value = Value> {
|
|
||||||
getState(peer: PeerID): T | undefined;
|
|
||||||
getTimestamp(peer: PeerID): number | undefined;
|
|
||||||
getAllStates(): Record<PeerID, T>;
|
|
||||||
setLocalState(value: T): void;
|
|
||||||
removeOutdated(): PeerID[];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type NonNullableType<T> = Exclude<T, null | undefined>;
|
|
||||||
|
|
||||||
export function newContainerID(id: OpId, type: ContainerType): ContainerID {
|
|
||||||
return `cid:${id.counter}@${id.peer}:${type}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function newRootContainerID(
|
|
||||||
name: string,
|
|
||||||
type: ContainerType,
|
|
||||||
): ContainerID {
|
|
||||||
return `cid:root-${name}:${type}`;
|
|
||||||
}
|
|
|
@ -1,106 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
|
||||||
/* Projects */
|
|
||||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
|
||||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
|
||||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
|
||||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
|
||||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
|
||||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
|
||||||
/* Language and Environment */
|
|
||||||
"target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
|
||||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
|
||||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
|
||||||
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
|
||||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
|
||||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
|
||||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
|
||||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
|
||||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
|
||||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
|
||||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
|
||||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
|
||||||
/* Modules */
|
|
||||||
"module": "commonjs" /* Specify what module code is generated. */,
|
|
||||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
|
||||||
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
|
|
||||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
|
||||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
|
||||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
|
||||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
|
||||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
|
||||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
|
||||||
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
|
|
||||||
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
|
|
||||||
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
|
|
||||||
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
|
|
||||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
|
||||||
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
|
|
||||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
|
||||||
/* JavaScript Support */
|
|
||||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
|
||||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
|
||||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
|
||||||
/* Emit */
|
|
||||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
|
||||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
|
||||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
|
||||||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
|
||||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
|
||||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
|
||||||
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
|
|
||||||
// "removeComments": true, /* Disable emitting comments. */
|
|
||||||
"noEmit": true /* Disable emitting files from a compilation. */,
|
|
||||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
|
||||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
|
||||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
|
||||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
|
||||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
|
||||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
|
||||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
|
||||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
|
||||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
|
||||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
|
||||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
|
||||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
|
||||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
|
||||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
|
||||||
/* Interop Constraints */
|
|
||||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
|
||||||
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
|
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
|
||||||
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
|
|
||||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
|
||||||
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
|
||||||
/* Type Checking */
|
|
||||||
"strict": true /* Enable all strict type-checking options. */,
|
|
||||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
|
||||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
|
||||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
|
||||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
|
||||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
|
||||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
|
||||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
|
||||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
|
||||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
|
||||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
|
||||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
|
||||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
|
||||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
|
||||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
|
||||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
|
||||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
|
||||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
|
||||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
|
||||||
/* Completeness */
|
|
||||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
|
||||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"node_modules",
|
|
||||||
"dist",
|
|
||||||
"deno"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -9,9 +9,9 @@
|
||||||
"build": "cargo build",
|
"build": "cargo build",
|
||||||
"test": "cargo nextest run --features=test_utils,jsonpath --no-fail-fast && cargo test --doc",
|
"test": "cargo nextest run --features=test_utils,jsonpath --no-fail-fast && cargo test --doc",
|
||||||
"test-all": "pnpm test && pnpm test-wasm",
|
"test-all": "pnpm test && pnpm test-wasm",
|
||||||
"test-wasm": "cd crates/loro-wasm && deno task dev && cd ../../loro-js && pnpm i && pnpm run test",
|
"test-wasm": "cd crates/loro-wasm && pnpm i && pnpm build-dev",
|
||||||
"coverage": "mkdir -p coverage && cargo llvm-cov nextest --features test_utils,jsonpath --lcov > coverage/lcov-nextest.info && cargo llvm-cov report",
|
"coverage": "mkdir -p coverage && cargo llvm-cov nextest --features test_utils,jsonpath --lcov > coverage/lcov-nextest.info && cargo llvm-cov report",
|
||||||
"release-wasm": "cd crates/loro-wasm && deno task release && cd ../../loro-js && pnpm i && pnpm build && pnpm run test",
|
"release-wasm": "cd crates/loro-wasm && pnpm i && pnpm build-release",
|
||||||
"check": "cargo clippy --all-features -- -Dwarnings",
|
"check": "cargo clippy --all-features -- -Dwarnings",
|
||||||
"run-fuzz-corpus": "cd crates/fuzz && cargo +nightly fuzz run all -- -max_total_time=1",
|
"run-fuzz-corpus": "cd crates/fuzz && cargo +nightly fuzz run all -- -max_total_time=1",
|
||||||
"fix": "cargo clippy --fix --features=test_utils",
|
"fix": "cargo clippy --fix --features=test_utils",
|
||||||
|
|
221
pnpm-lock.yaml
221
pnpm-lock.yaml
|
@ -17,62 +17,18 @@ importers:
|
||||||
|
|
||||||
crates/loro-wasm:
|
crates/loro-wasm:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
vite-plugin-top-level-await:
|
'@rollup/plugin-alias':
|
||||||
specifier: ^1.2.2
|
specifier: ^5.1.1
|
||||||
version: 1.4.1(vite@4.5.3)
|
version: 5.1.1(rollup@3.29.4)
|
||||||
vite-plugin-wasm:
|
|
||||||
specifier: ^3.1.0
|
|
||||||
version: 3.3.0(vite@4.5.3)
|
|
||||||
|
|
||||||
examples/loro-quill:
|
|
||||||
dependencies:
|
|
||||||
is-equal:
|
|
||||||
specifier: ^1.6.4
|
|
||||||
version: 1.7.0
|
|
||||||
loro-crdt:
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../../loro-js
|
|
||||||
quill:
|
|
||||||
specifier: ^1.3.7
|
|
||||||
version: 1.3.7
|
|
||||||
vue:
|
|
||||||
specifier: ^3.2.47
|
|
||||||
version: 3.4.27(typescript@5.4.5)
|
|
||||||
devDependencies:
|
|
||||||
'@types/quill':
|
|
||||||
specifier: ^1.3.7
|
|
||||||
version: 1.3.10
|
|
||||||
'@vitejs/plugin-vue':
|
|
||||||
specifier: ^4.1.0
|
|
||||||
version: 4.6.2(vite@4.5.3)(vue@3.4.27)
|
|
||||||
typescript:
|
|
||||||
specifier: ^5.2.0
|
|
||||||
version: 5.4.5
|
|
||||||
vite:
|
|
||||||
specifier: ^4.3.2
|
|
||||||
version: 4.5.3
|
|
||||||
vite-plugin-top-level-await:
|
|
||||||
specifier: ^1.3.0
|
|
||||||
version: 1.4.1(vite@4.5.3)
|
|
||||||
vite-plugin-wasm:
|
|
||||||
specifier: ^3.2.2
|
|
||||||
version: 3.3.0(vite@4.5.3)
|
|
||||||
vue-tsc:
|
|
||||||
specifier: ^1.4.2
|
|
||||||
version: 1.8.27(typescript@5.4.5)
|
|
||||||
|
|
||||||
loro-js:
|
|
||||||
dependencies:
|
|
||||||
loro-wasm:
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../crates/loro-wasm
|
|
||||||
devDependencies:
|
|
||||||
'@rollup/plugin-node-resolve':
|
'@rollup/plugin-node-resolve':
|
||||||
specifier: ^15.0.1
|
specifier: ^15.0.1
|
||||||
version: 15.2.3(rollup@3.29.4)
|
version: 15.2.3(rollup@3.29.4)
|
||||||
|
'@rollup/plugin-typescript':
|
||||||
|
specifier: ^12.1.1
|
||||||
|
version: 12.1.1(rollup@3.29.4)(tslib@2.8.0)(typescript@5.6.3)
|
||||||
'@typescript-eslint/parser':
|
'@typescript-eslint/parser':
|
||||||
specifier: ^6.2.0
|
specifier: ^6.2.0
|
||||||
version: 6.21.0(eslint@8.57.0)(typescript@5.4.5)
|
version: 6.21.0(eslint@8.57.0)(typescript@5.6.3)
|
||||||
'@vitest/ui':
|
'@vitest/ui':
|
||||||
specifier: ^1.0.4
|
specifier: ^1.0.4
|
||||||
version: 1.6.0(vitest@1.6.0)
|
version: 1.6.0(vitest@1.6.0)
|
||||||
|
@ -96,23 +52,66 @@ importers:
|
||||||
version: 3.29.4
|
version: 3.29.4
|
||||||
rollup-plugin-dts:
|
rollup-plugin-dts:
|
||||||
specifier: ^5.3.0
|
specifier: ^5.3.0
|
||||||
version: 5.3.1(rollup@3.29.4)(typescript@5.4.5)
|
version: 5.3.1(rollup@3.29.4)(typescript@5.6.3)
|
||||||
rollup-plugin-esbuild:
|
rollup-plugin-esbuild:
|
||||||
specifier: ^5.0.0
|
specifier: ^5.0.0
|
||||||
version: 5.0.0(esbuild@0.18.20)(rollup@3.29.4)
|
version: 5.0.0(esbuild@0.18.20)(rollup@3.29.4)
|
||||||
|
tslib:
|
||||||
|
specifier: ^2.8.0
|
||||||
|
version: 2.8.0
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.0.2
|
specifier: ^5.6.3
|
||||||
version: 5.4.5
|
version: 5.6.3
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.2.1
|
specifier: ^4.2.1
|
||||||
version: 4.5.3
|
version: 4.5.3
|
||||||
|
vite-plugin-top-level-await:
|
||||||
|
specifier: ^1.2.2
|
||||||
|
version: 1.4.1(rollup@3.29.4)(vite@4.5.3)
|
||||||
vite-plugin-wasm:
|
vite-plugin-wasm:
|
||||||
specifier: ^3.2.2
|
specifier: ^3.1.0
|
||||||
version: 3.3.0(vite@4.5.3)
|
version: 3.3.0(vite@4.5.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^1.4.0
|
specifier: ^1.4.0
|
||||||
version: 1.6.0(@vitest/ui@1.6.0)
|
version: 1.6.0(@vitest/ui@1.6.0)
|
||||||
|
|
||||||
|
examples/loro-quill:
|
||||||
|
dependencies:
|
||||||
|
is-equal:
|
||||||
|
specifier: ^1.6.4
|
||||||
|
version: 1.7.0
|
||||||
|
loro-crdt:
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../crates/loro-wasm
|
||||||
|
quill:
|
||||||
|
specifier: ^1.3.7
|
||||||
|
version: 1.3.7
|
||||||
|
vue:
|
||||||
|
specifier: ^3.2.47
|
||||||
|
version: 3.4.27(typescript@5.4.5)
|
||||||
|
devDependencies:
|
||||||
|
'@types/quill':
|
||||||
|
specifier: ^1.3.7
|
||||||
|
version: 1.3.10
|
||||||
|
'@vitejs/plugin-vue':
|
||||||
|
specifier: ^4.1.0
|
||||||
|
version: 4.6.2(vite@4.5.3)(vue@3.4.27(typescript@5.4.5))
|
||||||
|
typescript:
|
||||||
|
specifier: ^5.2.0
|
||||||
|
version: 5.4.5
|
||||||
|
vite:
|
||||||
|
specifier: ^4.3.2
|
||||||
|
version: 4.5.3
|
||||||
|
vite-plugin-top-level-await:
|
||||||
|
specifier: ^1.3.0
|
||||||
|
version: 1.4.1(rollup@4.17.2)(vite@4.5.3)
|
||||||
|
vite-plugin-wasm:
|
||||||
|
specifier: ^3.2.2
|
||||||
|
version: 3.3.0(vite@4.5.3)
|
||||||
|
vue-tsc:
|
||||||
|
specifier: ^1.4.2
|
||||||
|
version: 1.8.27(typescript@5.4.5)
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
'@babel/code-frame@7.24.2':
|
'@babel/code-frame@7.24.2':
|
||||||
|
@ -487,6 +486,7 @@ packages:
|
||||||
'@humanwhocodes/config-array@0.11.14':
|
'@humanwhocodes/config-array@0.11.14':
|
||||||
resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
|
resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
|
||||||
engines: {node: '>=10.10.0'}
|
engines: {node: '>=10.10.0'}
|
||||||
|
deprecated: Use @eslint/config-array instead
|
||||||
|
|
||||||
'@humanwhocodes/module-importer@1.0.1':
|
'@humanwhocodes/module-importer@1.0.1':
|
||||||
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
|
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
|
||||||
|
@ -494,6 +494,7 @@ packages:
|
||||||
|
|
||||||
'@humanwhocodes/object-schema@2.0.3':
|
'@humanwhocodes/object-schema@2.0.3':
|
||||||
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
|
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
|
||||||
|
deprecated: Use @eslint/object-schema instead
|
||||||
|
|
||||||
'@jest/schemas@29.6.3':
|
'@jest/schemas@29.6.3':
|
||||||
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
|
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
|
||||||
|
@ -523,6 +524,15 @@ packages:
|
||||||
'@polka/url@1.0.0-next.25':
|
'@polka/url@1.0.0-next.25':
|
||||||
resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==}
|
resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==}
|
||||||
|
|
||||||
|
'@rollup/plugin-alias@5.1.1':
|
||||||
|
resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
rollup:
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@rollup/plugin-node-resolve@15.2.3':
|
'@rollup/plugin-node-resolve@15.2.3':
|
||||||
resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==}
|
resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
@ -532,6 +542,19 @@ packages:
|
||||||
rollup:
|
rollup:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@rollup/plugin-typescript@12.1.1':
|
||||||
|
resolution: {integrity: sha512-t7O653DpfB5MbFrqPe/VcKFFkvRuFNp9qId3xq4Eth5xlyymzxNpye2z8Hrl0RIMuXTSr5GGcFpkdlMeacUiFQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
rollup: ^2.14.0||^3.0.0||^4.0.0
|
||||||
|
tslib: '*'
|
||||||
|
typescript: '>=3.7.0'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
rollup:
|
||||||
|
optional: true
|
||||||
|
tslib:
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@rollup/plugin-virtual@3.0.2':
|
'@rollup/plugin-virtual@3.0.2':
|
||||||
resolution: {integrity: sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==}
|
resolution: {integrity: sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
@ -1186,6 +1209,7 @@ packages:
|
||||||
eslint@8.57.0:
|
eslint@8.57.0:
|
||||||
resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==}
|
resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
espree@9.6.1:
|
espree@9.6.1:
|
||||||
|
@ -1342,6 +1366,7 @@ packages:
|
||||||
|
|
||||||
glob@7.2.3:
|
glob@7.2.3:
|
||||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||||
|
deprecated: Glob versions prior to v9 are no longer supported
|
||||||
|
|
||||||
globals@13.24.0:
|
globals@13.24.0:
|
||||||
resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
|
resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
|
||||||
|
@ -1437,6 +1462,7 @@ packages:
|
||||||
|
|
||||||
inflight@1.0.6:
|
inflight@1.0.6:
|
||||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
||||||
|
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
|
||||||
|
|
||||||
inherits@2.0.4:
|
inherits@2.0.4:
|
||||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||||
|
@ -2008,6 +2034,7 @@ packages:
|
||||||
|
|
||||||
rimraf@3.0.2:
|
rimraf@3.0.2:
|
||||||
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
|
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
|
||||||
|
deprecated: Rimraf versions prior to v4 are no longer supported
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
rollup-plugin-dts@5.3.1:
|
rollup-plugin-dts@5.3.1:
|
||||||
|
@ -2240,6 +2267,9 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.2.0'
|
typescript: '>=4.2.0'
|
||||||
|
|
||||||
|
tslib@2.8.0:
|
||||||
|
resolution: {integrity: sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==}
|
||||||
|
|
||||||
tty-table@4.2.3:
|
tty-table@4.2.3:
|
||||||
resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==}
|
resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==}
|
||||||
engines: {node: '>=8.0.0'}
|
engines: {node: '>=8.0.0'}
|
||||||
|
@ -2290,6 +2320,11 @@ packages:
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
typescript@5.6.3:
|
||||||
|
resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
|
||||||
|
engines: {node: '>=14.17'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
ufo@1.5.3:
|
ufo@1.5.3:
|
||||||
resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==}
|
resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==}
|
||||||
|
|
||||||
|
@ -2897,6 +2932,10 @@ snapshots:
|
||||||
|
|
||||||
'@polka/url@1.0.0-next.25': {}
|
'@polka/url@1.0.0-next.25': {}
|
||||||
|
|
||||||
|
'@rollup/plugin-alias@5.1.1(rollup@3.29.4)':
|
||||||
|
optionalDependencies:
|
||||||
|
rollup: 3.29.4
|
||||||
|
|
||||||
'@rollup/plugin-node-resolve@15.2.3(rollup@3.29.4)':
|
'@rollup/plugin-node-resolve@15.2.3(rollup@3.29.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rollup/pluginutils': 5.1.0(rollup@3.29.4)
|
'@rollup/pluginutils': 5.1.0(rollup@3.29.4)
|
||||||
|
@ -2905,15 +2944,32 @@ snapshots:
|
||||||
is-builtin-module: 3.2.1
|
is-builtin-module: 3.2.1
|
||||||
is-module: 1.0.0
|
is-module: 1.0.0
|
||||||
resolve: 1.22.8
|
resolve: 1.22.8
|
||||||
|
optionalDependencies:
|
||||||
rollup: 3.29.4
|
rollup: 3.29.4
|
||||||
|
|
||||||
'@rollup/plugin-virtual@3.0.2': {}
|
'@rollup/plugin-typescript@12.1.1(rollup@3.29.4)(tslib@2.8.0)(typescript@5.6.3)':
|
||||||
|
dependencies:
|
||||||
|
'@rollup/pluginutils': 5.1.0(rollup@3.29.4)
|
||||||
|
resolve: 1.22.8
|
||||||
|
typescript: 5.6.3
|
||||||
|
optionalDependencies:
|
||||||
|
rollup: 3.29.4
|
||||||
|
tslib: 2.8.0
|
||||||
|
|
||||||
|
'@rollup/plugin-virtual@3.0.2(rollup@3.29.4)':
|
||||||
|
optionalDependencies:
|
||||||
|
rollup: 3.29.4
|
||||||
|
|
||||||
|
'@rollup/plugin-virtual@3.0.2(rollup@4.17.2)':
|
||||||
|
optionalDependencies:
|
||||||
|
rollup: 4.17.2
|
||||||
|
|
||||||
'@rollup/pluginutils@5.1.0(rollup@3.29.4)':
|
'@rollup/pluginutils@5.1.0(rollup@3.29.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.5
|
'@types/estree': 1.0.5
|
||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
|
optionalDependencies:
|
||||||
rollup: 3.29.4
|
rollup: 3.29.4
|
||||||
|
|
||||||
'@rollup/rollup-android-arm-eabi@4.17.2':
|
'@rollup/rollup-android-arm-eabi@4.17.2':
|
||||||
|
@ -3034,15 +3090,16 @@ snapshots:
|
||||||
|
|
||||||
'@types/semver@7.5.8': {}
|
'@types/semver@7.5.8': {}
|
||||||
|
|
||||||
'@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5)':
|
'@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.6.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/scope-manager': 6.21.0
|
'@typescript-eslint/scope-manager': 6.21.0
|
||||||
'@typescript-eslint/types': 6.21.0
|
'@typescript-eslint/types': 6.21.0
|
||||||
'@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.5)
|
'@typescript-eslint/typescript-estree': 6.21.0(typescript@5.6.3)
|
||||||
'@typescript-eslint/visitor-keys': 6.21.0
|
'@typescript-eslint/visitor-keys': 6.21.0
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
typescript: 5.4.5
|
optionalDependencies:
|
||||||
|
typescript: 5.6.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
@ -3053,7 +3110,7 @@ snapshots:
|
||||||
|
|
||||||
'@typescript-eslint/types@6.21.0': {}
|
'@typescript-eslint/types@6.21.0': {}
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@6.21.0(typescript@5.4.5)':
|
'@typescript-eslint/typescript-estree@6.21.0(typescript@5.6.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 6.21.0
|
'@typescript-eslint/types': 6.21.0
|
||||||
'@typescript-eslint/visitor-keys': 6.21.0
|
'@typescript-eslint/visitor-keys': 6.21.0
|
||||||
|
@ -3062,8 +3119,9 @@ snapshots:
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
minimatch: 9.0.3
|
minimatch: 9.0.3
|
||||||
semver: 7.6.2
|
semver: 7.6.2
|
||||||
ts-api-utils: 1.3.0(typescript@5.4.5)
|
ts-api-utils: 1.3.0(typescript@5.6.3)
|
||||||
typescript: 5.4.5
|
optionalDependencies:
|
||||||
|
typescript: 5.6.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
@ -3074,7 +3132,7 @@ snapshots:
|
||||||
|
|
||||||
'@ungap/structured-clone@1.2.0': {}
|
'@ungap/structured-clone@1.2.0': {}
|
||||||
|
|
||||||
'@vitejs/plugin-vue@4.6.2(vite@4.5.3)(vue@3.4.27)':
|
'@vitejs/plugin-vue@4.6.2(vite@4.5.3)(vue@3.4.27(typescript@5.4.5))':
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 4.5.3
|
vite: 4.5.3
|
||||||
vue: 3.4.27(typescript@5.4.5)
|
vue: 3.4.27(typescript@5.4.5)
|
||||||
|
@ -3172,8 +3230,9 @@ snapshots:
|
||||||
minimatch: 9.0.4
|
minimatch: 9.0.4
|
||||||
muggle-string: 0.3.1
|
muggle-string: 0.3.1
|
||||||
path-browserify: 1.0.1
|
path-browserify: 1.0.1
|
||||||
typescript: 5.4.5
|
|
||||||
vue-template-compiler: 2.7.16
|
vue-template-compiler: 2.7.16
|
||||||
|
optionalDependencies:
|
||||||
|
typescript: 5.4.5
|
||||||
|
|
||||||
'@vue/reactivity@3.4.27':
|
'@vue/reactivity@3.4.27':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -3190,7 +3249,7 @@ snapshots:
|
||||||
'@vue/shared': 3.4.27
|
'@vue/shared': 3.4.27
|
||||||
csstype: 3.1.3
|
csstype: 3.1.3
|
||||||
|
|
||||||
'@vue/server-renderer@3.4.27(vue@3.4.27)':
|
'@vue/server-renderer@3.4.27(vue@3.4.27(typescript@5.4.5))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/compiler-ssr': 3.4.27
|
'@vue/compiler-ssr': 3.4.27
|
||||||
'@vue/shared': 3.4.27
|
'@vue/shared': 3.4.27
|
||||||
|
@ -4509,11 +4568,11 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
glob: 7.2.3
|
glob: 7.2.3
|
||||||
|
|
||||||
rollup-plugin-dts@5.3.1(rollup@3.29.4)(typescript@5.4.5):
|
rollup-plugin-dts@5.3.1(rollup@3.29.4)(typescript@5.6.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
magic-string: 0.30.10
|
magic-string: 0.30.10
|
||||||
rollup: 3.29.4
|
rollup: 3.29.4
|
||||||
typescript: 5.4.5
|
typescript: 5.6.3
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@babel/code-frame': 7.24.2
|
'@babel/code-frame': 7.24.2
|
||||||
|
|
||||||
|
@ -4750,9 +4809,11 @@ snapshots:
|
||||||
|
|
||||||
trim-newlines@3.0.1: {}
|
trim-newlines@3.0.1: {}
|
||||||
|
|
||||||
ts-api-utils@1.3.0(typescript@5.4.5):
|
ts-api-utils@1.3.0(typescript@5.6.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
typescript: 5.4.5
|
typescript: 5.6.3
|
||||||
|
|
||||||
|
tslib@2.8.0: {}
|
||||||
|
|
||||||
tty-table@4.2.3:
|
tty-table@4.2.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -4812,6 +4873,8 @@ snapshots:
|
||||||
|
|
||||||
typescript@5.4.5: {}
|
typescript@5.4.5: {}
|
||||||
|
|
||||||
|
typescript@5.6.3: {}
|
||||||
|
|
||||||
ufo@1.5.3: {}
|
ufo@1.5.3: {}
|
||||||
|
|
||||||
unbox-primitive@1.0.2:
|
unbox-primitive@1.0.2:
|
||||||
|
@ -4851,9 +4914,19 @@ snapshots:
|
||||||
- supports-color
|
- supports-color
|
||||||
- terser
|
- terser
|
||||||
|
|
||||||
vite-plugin-top-level-await@1.4.1(vite@4.5.3):
|
vite-plugin-top-level-await@1.4.1(rollup@3.29.4)(vite@4.5.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rollup/plugin-virtual': 3.0.2
|
'@rollup/plugin-virtual': 3.0.2(rollup@3.29.4)
|
||||||
|
'@swc/core': 1.5.5
|
||||||
|
uuid: 9.0.1
|
||||||
|
vite: 4.5.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@swc/helpers'
|
||||||
|
- rollup
|
||||||
|
|
||||||
|
vite-plugin-top-level-await@1.4.1(rollup@4.17.2)(vite@4.5.3):
|
||||||
|
dependencies:
|
||||||
|
'@rollup/plugin-virtual': 3.0.2(rollup@4.17.2)
|
||||||
'@swc/core': 1.5.5
|
'@swc/core': 1.5.5
|
||||||
uuid: 9.0.1
|
uuid: 9.0.1
|
||||||
vite: 4.5.3
|
vite: 4.5.3
|
||||||
|
@ -4887,7 +4960,6 @@ snapshots:
|
||||||
'@vitest/runner': 1.6.0
|
'@vitest/runner': 1.6.0
|
||||||
'@vitest/snapshot': 1.6.0
|
'@vitest/snapshot': 1.6.0
|
||||||
'@vitest/spy': 1.6.0
|
'@vitest/spy': 1.6.0
|
||||||
'@vitest/ui': 1.6.0(vitest@1.6.0)
|
|
||||||
'@vitest/utils': 1.6.0
|
'@vitest/utils': 1.6.0
|
||||||
acorn-walk: 8.3.2
|
acorn-walk: 8.3.2
|
||||||
chai: 4.4.1
|
chai: 4.4.1
|
||||||
|
@ -4904,6 +4976,8 @@ snapshots:
|
||||||
vite: 5.2.11
|
vite: 5.2.11
|
||||||
vite-node: 1.6.0
|
vite-node: 1.6.0
|
||||||
why-is-node-running: 2.2.2
|
why-is-node-running: 2.2.2
|
||||||
|
optionalDependencies:
|
||||||
|
'@vitest/ui': 1.6.0(vitest@1.6.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- less
|
- less
|
||||||
- lightningcss
|
- lightningcss
|
||||||
|
@ -4930,8 +5004,9 @@ snapshots:
|
||||||
'@vue/compiler-dom': 3.4.27
|
'@vue/compiler-dom': 3.4.27
|
||||||
'@vue/compiler-sfc': 3.4.27
|
'@vue/compiler-sfc': 3.4.27
|
||||||
'@vue/runtime-dom': 3.4.27
|
'@vue/runtime-dom': 3.4.27
|
||||||
'@vue/server-renderer': 3.4.27(vue@3.4.27)
|
'@vue/server-renderer': 3.4.27(vue@3.4.27(typescript@5.4.5))
|
||||||
'@vue/shared': 3.4.27
|
'@vue/shared': 3.4.27
|
||||||
|
optionalDependencies:
|
||||||
typescript: 5.4.5
|
typescript: 5.4.5
|
||||||
|
|
||||||
wcwidth@1.0.1:
|
wcwidth@1.0.1:
|
||||||
|
|
Loading…
Reference in a new issue