@evolu/common 5.4.8 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -34
- package/dist/src/Array.d.ts +17 -0
- package/dist/src/Array.d.ts.map +1 -0
- package/dist/src/Array.js +12 -0
- package/dist/src/Assert.d.ts +68 -0
- package/dist/src/Assert.d.ts.map +1 -0
- package/dist/src/Assert.js +77 -0
- package/dist/src/BigInt.d.ts +20 -0
- package/dist/src/BigInt.d.ts.map +1 -0
- package/dist/src/BigInt.js +18 -0
- package/dist/src/Buffer.d.ts +92 -0
- package/dist/src/Buffer.d.ts.map +1 -0
- package/dist/src/Buffer.js +62 -0
- package/dist/src/Callbacks.d.ts +20 -0
- package/dist/src/Callbacks.d.ts.map +1 -0
- package/dist/src/Callbacks.js +18 -0
- package/dist/src/Console.d.ts +78 -0
- package/dist/src/Console.d.ts.map +1 -0
- package/dist/src/Console.js +103 -0
- package/dist/src/Crypto.d.ts +72 -39
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +89 -54
- package/dist/src/Eq.d.ts +97 -0
- package/dist/src/Eq.d.ts.map +1 -0
- package/dist/src/Eq.js +167 -0
- package/dist/src/Error.d.ts +14 -10
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +43 -11
- package/dist/src/Evolu/Config.d.ts +69 -0
- package/dist/src/Evolu/Config.d.ts.map +1 -0
- package/dist/src/Evolu/Config.js +9 -0
- package/dist/src/Evolu/Db.d.ts +126 -0
- package/dist/src/Evolu/Db.d.ts.map +1 -0
- package/dist/src/Evolu/Db.js +774 -0
- package/dist/src/Evolu/Diff.d.ts +43 -0
- package/dist/src/Evolu/Diff.d.ts.map +1 -0
- package/dist/src/Evolu/Diff.js +95 -0
- package/dist/src/Evolu/Evolu.d.ts +334 -0
- package/dist/src/Evolu/Evolu.d.ts.map +1 -0
- package/dist/src/Evolu/Evolu.js +434 -0
- package/dist/src/Evolu/Internal.d.ts +26 -0
- package/dist/src/Evolu/Internal.d.ts.map +1 -0
- package/dist/src/Evolu/Internal.js +25 -0
- package/dist/src/Evolu/Kysely.d.ts +6 -0
- package/dist/src/Evolu/Kysely.d.ts.map +1 -0
- package/dist/src/Evolu/Kysely.js +21 -0
- package/dist/src/Evolu/Owner.d.ts +155 -0
- package/dist/src/Evolu/Owner.d.ts.map +1 -0
- package/dist/src/Evolu/Owner.js +126 -0
- package/dist/src/Evolu/Platform.d.ts +23 -0
- package/dist/src/Evolu/Platform.d.ts.map +1 -0
- package/dist/src/Evolu/Platform.js +1 -0
- package/dist/src/Evolu/Protocol.d.ts +401 -0
- package/dist/src/Evolu/Protocol.d.ts.map +1 -0
- package/dist/src/Evolu/Protocol.js +1151 -0
- package/dist/src/Evolu/Public.d.ts +18 -0
- package/dist/src/Evolu/Public.d.ts.map +1 -0
- package/dist/src/Evolu/Public.js +11 -0
- package/dist/src/Evolu/PublicKysely.d.ts +148 -0
- package/dist/src/Evolu/PublicKysely.d.ts.map +1 -0
- package/dist/src/Evolu/PublicKysely.js +185 -0
- package/dist/src/Evolu/Query.d.ts +63 -0
- package/dist/src/Evolu/Query.d.ts.map +1 -0
- package/dist/src/Evolu/Query.js +61 -0
- package/dist/src/Evolu/Relay.d.ts +13 -0
- package/dist/src/Evolu/Relay.d.ts.map +1 -0
- package/dist/src/Evolu/Relay.js +109 -0
- package/dist/src/Evolu/Schema.d.ts +201 -0
- package/dist/src/Evolu/Schema.d.ts.map +1 -0
- package/dist/src/Evolu/Schema.js +150 -0
- package/dist/src/Evolu/Storage.d.ts +49 -0
- package/dist/src/Evolu/Storage.d.ts.map +1 -0
- package/dist/src/Evolu/Storage.js +1111 -0
- package/dist/src/Evolu/Sync.d.ts +59 -0
- package/dist/src/Evolu/Sync.d.ts.map +1 -0
- package/dist/src/Evolu/Sync.js +29 -0
- package/dist/src/Evolu/Timestamp.d.ts +106 -0
- package/dist/src/Evolu/Timestamp.d.ts.map +1 -0
- package/dist/src/Evolu/Timestamp.js +179 -0
- package/dist/src/Function.d.ts +54 -0
- package/dist/src/Function.d.ts.map +1 -0
- package/dist/src/Function.js +38 -0
- package/dist/src/ManyToManyMap.d.ts +26 -0
- package/dist/src/ManyToManyMap.d.ts.map +1 -0
- package/dist/src/ManyToManyMap.js +92 -0
- package/dist/src/NanoId.d.ts +27 -0
- package/dist/src/NanoId.d.ts.map +1 -0
- package/dist/src/NanoId.js +6 -0
- package/dist/src/Number.d.ts +42 -0
- package/dist/src/Number.d.ts.map +1 -0
- package/dist/src/Number.js +55 -0
- package/dist/src/Object.d.ts +35 -0
- package/dist/src/Object.d.ts.map +1 -0
- package/dist/src/Object.js +36 -0
- package/dist/src/Order.d.ts +90 -0
- package/dist/src/Order.d.ts.map +1 -0
- package/dist/src/Order.js +85 -0
- package/dist/src/Promise.d.ts +180 -0
- package/dist/src/Promise.d.ts.map +1 -0
- package/dist/src/Promise.js +176 -0
- package/dist/src/Random.d.ts +52 -0
- package/dist/src/Random.d.ts.map +1 -0
- package/dist/src/Random.js +29 -0
- package/dist/src/Ref.d.ts +40 -0
- package/dist/src/Ref.d.ts.map +1 -0
- package/dist/src/Ref.js +13 -0
- package/dist/src/Result.d.ts +421 -0
- package/dist/src/Result.d.ts.map +1 -0
- package/dist/src/Result.js +357 -0
- package/dist/src/Skiplist.d.ts +23 -0
- package/dist/src/Skiplist.d.ts.map +1 -0
- package/dist/src/Skiplist.js +58 -0
- package/dist/src/Sqlite.d.ts +116 -52
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +183 -67
- package/dist/src/Store.d.ts +45 -8
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +33 -17
- package/dist/src/String.d.ts +2 -0
- package/dist/src/String.d.ts.map +1 -0
- package/dist/src/String.js +14 -0
- package/dist/src/Time.d.ts +20 -0
- package/dist/src/Time.d.ts.map +1 -0
- package/dist/src/Time.js +25 -0
- package/dist/src/Type.d.ts +1937 -0
- package/dist/src/Type.d.ts.map +1 -0
- package/dist/src/Type.js +2002 -0
- package/dist/src/Types.d.ts +188 -0
- package/dist/src/Types.d.ts.map +1 -0
- package/dist/src/Types.js +6 -0
- package/dist/src/WebSocket.d.ts +112 -0
- package/dist/src/WebSocket.d.ts.map +1 -0
- package/dist/src/WebSocket.js +139 -0
- package/dist/src/Worker.d.ts +44 -0
- package/dist/src/Worker.d.ts.map +1 -0
- package/dist/src/Worker.js +66 -0
- package/dist/src/index.d.ts +24 -11
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +24 -11
- package/package.json +29 -38
- package/src/Array.ts +39 -0
- package/src/Assert.ts +116 -0
- package/src/BigInt.ts +29 -0
- package/src/Buffer.ts +175 -0
- package/src/Callbacks.ts +43 -0
- package/src/Console.ts +159 -0
- package/src/Crypto.ts +169 -115
- package/src/Eq.ts +204 -0
- package/src/Error.ts +57 -20
- package/src/Evolu/Config.ts +83 -0
- package/src/Evolu/Db.ts +1275 -0
- package/src/Evolu/Diff.ts +142 -0
- package/src/Evolu/Evolu.ts +947 -0
- package/src/Evolu/Internal.ts +26 -0
- package/src/Evolu/Kysely.ts +38 -0
- package/src/Evolu/Owner.ts +296 -0
- package/src/Evolu/Platform.ts +27 -0
- package/src/Evolu/Protocol.ts +1857 -0
- package/src/Evolu/Public.ts +43 -0
- package/src/Evolu/PublicKysely.ts +240 -0
- package/src/Evolu/Query.ts +167 -0
- package/src/Evolu/Relay.ts +142 -0
- package/src/Evolu/Schema.ts +417 -0
- package/src/Evolu/Storage.ts +1281 -0
- package/src/Evolu/Sync.ts +105 -0
- package/src/Evolu/Timestamp.ts +311 -0
- package/src/Function.ts +58 -0
- package/src/ManyToManyMap.ts +140 -0
- package/src/NanoId.ts +39 -0
- package/src/Number.ts +90 -0
- package/src/Object.ts +64 -0
- package/src/Order.ts +113 -0
- package/src/Promise.ts +295 -0
- package/src/Random.ts +68 -0
- package/src/Ref.ts +63 -0
- package/src/Result.ts +453 -0
- package/src/Skiplist.ts +102 -0
- package/src/Sqlite.ts +366 -153
- package/src/Store.ts +79 -36
- package/src/String.ts +10 -0
- package/src/Time.ts +36 -0
- package/src/Type.ts +3978 -0
- package/src/Types.ts +209 -0
- package/src/WebSocket.ts +273 -0
- package/src/Worker.ts +129 -0
- package/src/index.ts +24 -11
- package/dist/src/Config.d.ts +0 -56
- package/dist/src/Config.d.ts.map +0 -1
- package/dist/src/Config.js +0 -39
- package/dist/src/Crdt.d.ts +0 -89
- package/dist/src/Crdt.d.ts.map +0 -1
- package/dist/src/Crdt.js +0 -181
- package/dist/src/Db.d.ts +0 -107
- package/dist/src/Db.d.ts.map +0 -1
- package/dist/src/Db.js +0 -443
- package/dist/src/Diff.d.ts +0 -27
- package/dist/src/Diff.d.ts.map +0 -1
- package/dist/src/Diff.js +0 -84
- package/dist/src/Evolu.d.ts +0 -426
- package/dist/src/Evolu.d.ts.map +0 -1
- package/dist/src/Evolu.js +0 -333
- package/dist/src/Model.d.ts +0 -141
- package/dist/src/Model.d.ts.map +0 -1
- package/dist/src/Model.js +0 -125
- package/dist/src/Murmurhash.d.ts +0 -2
- package/dist/src/Murmurhash.d.ts.map +0 -1
- package/dist/src/Murmurhash.js +0 -60
- package/dist/src/Owner.d.ts +0 -33
- package/dist/src/Owner.d.ts.map +0 -1
- package/dist/src/Owner.js +0 -26
- package/dist/src/Platform.d.ts +0 -37
- package/dist/src/Platform.d.ts.map +0 -1
- package/dist/src/Platform.js +0 -11
- package/dist/src/Protobuf.d.ts +0 -81
- package/dist/src/Protobuf.d.ts.map +0 -1
- package/dist/src/Protobuf.js +0 -92
- package/dist/src/Public.d.ts +0 -13
- package/dist/src/Public.d.ts.map +0 -1
- package/dist/src/Public.js +0 -6
- package/dist/src/Socket.d.ts +0 -8
- package/dist/src/Socket.d.ts.map +0 -1
- package/dist/src/Socket.js +0 -51
- package/dist/src/Sql.d.ts +0 -12
- package/dist/src/Sql.d.ts.map +0 -1
- package/dist/src/Sql.js +0 -30
- package/dist/src/Sync.d.ts +0 -70
- package/dist/src/Sync.d.ts.map +0 -1
- package/dist/src/Sync.js +0 -127
- package/src/Config.ts +0 -119
- package/src/Crdt.ts +0 -361
- package/src/Db.ts +0 -955
- package/src/Diff.ts +0 -114
- package/src/Evolu.ts +0 -1016
- package/src/Model.ts +0 -233
- package/src/Murmurhash.ts +0 -70
- package/src/Owner.ts +0 -69
- package/src/Platform.ts +0 -47
- package/src/Protobuf.ts +0 -155
- package/src/Public.ts +0 -12
- package/src/Socket.ts +0 -83
- package/src/Sql.ts +0 -41
- package/src/Sync.ts +0 -315
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🛠️
|
|
3
|
+
*
|
|
4
|
+
* ### Example
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { Evolu } from "@evolu/common/evolu";
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export * from "./Config.js";
|
|
14
|
+
export * from "./Db.js";
|
|
15
|
+
export * from "./Diff.js";
|
|
16
|
+
export * from "./Evolu.js";
|
|
17
|
+
export * from "./Kysely.js";
|
|
18
|
+
export * from "./Owner.js";
|
|
19
|
+
export * from "./Platform.js";
|
|
20
|
+
export * from "./Protocol.js";
|
|
21
|
+
export * from "./Query.js";
|
|
22
|
+
export * from "./Relay.js";
|
|
23
|
+
export * from "./Schema.js";
|
|
24
|
+
export * from "./Storage.js";
|
|
25
|
+
export * from "./Sync.js";
|
|
26
|
+
export * from "./Timestamp.js";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CreateIndexBuilder,
|
|
3
|
+
DummyDriver,
|
|
4
|
+
Kysely,
|
|
5
|
+
SqliteAdapter,
|
|
6
|
+
SqliteQueryCompiler,
|
|
7
|
+
} from "kysely";
|
|
8
|
+
import { DbIndex } from "./Db.js";
|
|
9
|
+
|
|
10
|
+
// https://kysely.dev/docs/recipes/splitting-query-building-and-execution
|
|
11
|
+
export const kysely = new Kysely({
|
|
12
|
+
dialect: {
|
|
13
|
+
createAdapter: () => new SqliteAdapter(),
|
|
14
|
+
createDriver: () => new DummyDriver(),
|
|
15
|
+
createIntrospector() {
|
|
16
|
+
throw new Error("Not implemeneted");
|
|
17
|
+
},
|
|
18
|
+
createQueryCompiler: () => new SqliteQueryCompiler(),
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export type DbIndexesBuilder = (
|
|
23
|
+
create: (indexName: string) => CreateIndexBuilder,
|
|
24
|
+
) => ReadonlyArray<CreateIndexBuilder<any>>;
|
|
25
|
+
|
|
26
|
+
const createIndex = kysely.schema.createIndex.bind(kysely.schema);
|
|
27
|
+
|
|
28
|
+
export const createIndexes = (
|
|
29
|
+
indexes?: DbIndexesBuilder,
|
|
30
|
+
): ReadonlyArray<DbIndex> => {
|
|
31
|
+
if (!indexes) return [];
|
|
32
|
+
return indexes(createIndex).map(
|
|
33
|
+
(index): DbIndex => ({
|
|
34
|
+
name: index.toOperationNode().name.name,
|
|
35
|
+
sql: index.compile().sql,
|
|
36
|
+
}),
|
|
37
|
+
);
|
|
38
|
+
};
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { assert } from "../Assert.js";
|
|
2
|
+
import {
|
|
3
|
+
createEncryptionKey,
|
|
4
|
+
CreateMnemonicDep,
|
|
5
|
+
CreateRandomBytesDep,
|
|
6
|
+
createSlip21,
|
|
7
|
+
createSlip21Id,
|
|
8
|
+
EncryptionKey,
|
|
9
|
+
MnemonicSeed,
|
|
10
|
+
mnemonicToMnemonicSeed,
|
|
11
|
+
} from "../Crypto.js";
|
|
12
|
+
import { NanoIdLibDep } from "../NanoId.js";
|
|
13
|
+
import { TimeDep } from "../Time.js";
|
|
14
|
+
import {
|
|
15
|
+
Base64Url,
|
|
16
|
+
brand,
|
|
17
|
+
DateIso,
|
|
18
|
+
DateIsoString,
|
|
19
|
+
Id,
|
|
20
|
+
length,
|
|
21
|
+
Mnemonic,
|
|
22
|
+
NonNegativeInt,
|
|
23
|
+
Uint8Array,
|
|
24
|
+
} from "../Type.js";
|
|
25
|
+
import {
|
|
26
|
+
createInitialTimestamp,
|
|
27
|
+
TimestampString,
|
|
28
|
+
timestampToTimestampString,
|
|
29
|
+
} from "./Timestamp.js";
|
|
30
|
+
|
|
31
|
+
// TODO: Clean API
|
|
32
|
+
// - createOwner should be createAppOwner
|
|
33
|
+
// - Docs mention WriteKey is optional but it's required in Owner.
|
|
34
|
+
// - For Protocol, we need only ownerId, encryptionKey, and writeKey.
|
|
35
|
+
// - Not sure whether we need JSDoc for this module, and we don't
|
|
36
|
+
// use modules for Evolu internal API yet.
|
|
37
|
+
// It's not single responsibility API.
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* `Owner` is an entity in Evolu that owns data, meaning it is locally stored on
|
|
41
|
+
* a device under the user’s control. Data can be personal private, peer-to-peer
|
|
42
|
+
* shared, or aggregated from multiple owners.
|
|
43
|
+
*
|
|
44
|
+
* An owner has a {@link Mnemonic} from which {@link OwnerId} and
|
|
45
|
+
* {@link EncryptionKey} are deterministically derived using SLIP-21, and an
|
|
46
|
+
* optional {@link WriteKey} that, when present, enables writing to the Evolu
|
|
47
|
+
* Relay or peers. The {@link WriteKey} can be rotated.
|
|
48
|
+
*
|
|
49
|
+
* Variants include {@link AppOwner}, {@link ShardOwner}, {@link SharedOwner}, and
|
|
50
|
+
* {@link SharedReadonlyOwner}, each with specific roles and properties detailed
|
|
51
|
+
* in their respective definitions.
|
|
52
|
+
*
|
|
53
|
+
* Public-key cryptography isn’t included here as it belongs to data and varies
|
|
54
|
+
* by use case. An Evolu app without collaboration doesn’t need it, while a
|
|
55
|
+
* Nostr-like app can leverage Nostr NIPs, or a super-safe app can use
|
|
56
|
+
* post-quantum cryptography.
|
|
57
|
+
*/
|
|
58
|
+
export interface Owner {
|
|
59
|
+
readonly mnemonic: Mnemonic;
|
|
60
|
+
readonly createdAt: DateIsoString;
|
|
61
|
+
readonly id: OwnerId;
|
|
62
|
+
readonly encryptionKey: EncryptionKey;
|
|
63
|
+
readonly writeKey: WriteKey;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface OwnerWithWriteAccess {
|
|
67
|
+
readonly id: OwnerId;
|
|
68
|
+
readonly encryptionKey: EncryptionKey;
|
|
69
|
+
readonly writeKey: WriteKey;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The unique identifier of {@link Owner} derived from the {@link Mnemonic}.
|
|
74
|
+
*
|
|
75
|
+
* This branded {@link Id} type, generated by {@link createSlip21Id}, is a
|
|
76
|
+
* 21-character {@link Base64Url} string (126 bits of entropy), providing a
|
|
77
|
+
* compact, shareable, and secure identifier for UI use, tied to the owner's
|
|
78
|
+
* mnemonic and derivation path.
|
|
79
|
+
*/
|
|
80
|
+
export const OwnerId = brand("OwnerId", Id);
|
|
81
|
+
export type OwnerId = typeof OwnerId.Type;
|
|
82
|
+
|
|
83
|
+
export const writeKeyLength = 16 as NonNegativeInt;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* A secure token proving the initiator can write changes. Derived from a
|
|
87
|
+
* mnemonic or randomly generated. It's rotatable.
|
|
88
|
+
*/
|
|
89
|
+
export const WriteKey = brand("WriteKey", length(writeKeyLength)(Uint8Array));
|
|
90
|
+
export type WriteKey = typeof WriteKey.Type;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The root owner of an Evolu app, created from a mnemonic safely generated on a
|
|
94
|
+
* device when the app is initialized or restored on another device using an
|
|
95
|
+
* existing mnemonic. It manages the app's core data, including the storage of
|
|
96
|
+
* other owners' mnemonics in an encrypted app table. Its `writeKey` is
|
|
97
|
+
* deterministic and rotatable. Never share the AppOwner mnemonic with anyone.
|
|
98
|
+
*/
|
|
99
|
+
export interface AppOwner extends Owner {
|
|
100
|
+
readonly type: "AppOwner";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Used to shard data within an app for partial or deferred sync. Created in the
|
|
105
|
+
* Evolu `initialData` function or dynamically as needed. Its mnemonic is stored
|
|
106
|
+
* in an app table (encrypted by `AppOwner`) and synced between devices. Its
|
|
107
|
+
* `writeKey` is deterministic and rotatable, enabling selective syncing of data
|
|
108
|
+
* subsets. Not intended for sharing outside the app.
|
|
109
|
+
*
|
|
110
|
+
* This type omits `id`, `encryptionKey`, and `createdAt` as they are derived by
|
|
111
|
+
* Evolu from the `mnemonic`, reducing storage overhead.
|
|
112
|
+
*/
|
|
113
|
+
export interface ShardOwner {
|
|
114
|
+
readonly type: "ShardOwner";
|
|
115
|
+
readonly mnemonic: Mnemonic;
|
|
116
|
+
readonly writeKey: WriteKey;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Used to share data among one or more users, enabling collaboration or
|
|
121
|
+
* controlled access. Its `writeKey` is random (not derived from the mnemonic,
|
|
122
|
+
* stored alongside it in the app table) and rotatable, ensuring it cannot be
|
|
123
|
+
* regenerated by others if shared. Share the `mnemonic` alone for read-only
|
|
124
|
+
* access (as `SharedReadonlyOwner`) or share SharedOwner itself for write
|
|
125
|
+
* access.
|
|
126
|
+
*
|
|
127
|
+
* This type omits `id`, `encryptionKey`, and `createdAt` as they are derived by
|
|
128
|
+
* Evolu from the `mnemonic`, reducing storage overhead.
|
|
129
|
+
*/
|
|
130
|
+
export interface SharedOwner {
|
|
131
|
+
readonly type: "SharedOwner";
|
|
132
|
+
readonly mnemonic: Mnemonic;
|
|
133
|
+
readonly writeKey: WriteKey;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Used for sharing data that can only be read, such as with followers or peers
|
|
138
|
+
* in a read-only sync scenario. It lacks a `writeKey`, containing only the
|
|
139
|
+
* `mnemonic` from which `id` and `encryptionKey` are derived by Evolu.
|
|
140
|
+
* Typically derived from a `SharedOwner` by sharing its `mnemonic` without the
|
|
141
|
+
* `writeKey`.
|
|
142
|
+
*/
|
|
143
|
+
export interface SharedReadonlyOwner {
|
|
144
|
+
readonly type: "SharedReadonlyOwner";
|
|
145
|
+
readonly mnemonic: Mnemonic;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Creates an {@link AppOwner}, optionally from an existing mnemonic to restore
|
|
150
|
+
* it on another device; otherwise, generates a new mnemonic.
|
|
151
|
+
*/
|
|
152
|
+
export const createAppOwner =
|
|
153
|
+
(deps: TimeDep & CreateRandomBytesDep & CreateMnemonicDep) =>
|
|
154
|
+
(mnemonic = deps.createMnemonic()): AppOwner => {
|
|
155
|
+
const owner = createOwner(deps)(mnemonic);
|
|
156
|
+
return { type: "AppOwner", ...owner };
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Creates a {@link ShardOwner} for sharding app data with a freshly generated
|
|
161
|
+
* mnemonic. Unlike {@link createAppOwner}, it doesn’t accept an existing
|
|
162
|
+
* mnemonic because ShardOwner mnemonics are always generated and restored
|
|
163
|
+
* automatically via database sync.
|
|
164
|
+
*/
|
|
165
|
+
export const createShardOwner = (
|
|
166
|
+
deps: TimeDep & CreateRandomBytesDep & CreateMnemonicDep,
|
|
167
|
+
): ShardOwner => {
|
|
168
|
+
const owner = createOwner(deps)();
|
|
169
|
+
return {
|
|
170
|
+
type: "ShardOwner",
|
|
171
|
+
mnemonic: owner.mnemonic,
|
|
172
|
+
writeKey: owner.writeKey,
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Creates a fresh {@link SharedOwner} for sharing data with write access. Takes
|
|
178
|
+
* no arguments as both `mnemonic` and rotatable `writeKey` are newly generated;
|
|
179
|
+
* when shared, recipients use the provided `mnemonic` and `writeKey` directly
|
|
180
|
+
* as a {@link SharedOwner} without needing to recreate it.
|
|
181
|
+
*/
|
|
182
|
+
export const createSharedOwner = (
|
|
183
|
+
deps: CreateRandomBytesDep & CreateMnemonicDep,
|
|
184
|
+
): SharedOwner => {
|
|
185
|
+
const mnemonic = deps.createMnemonic();
|
|
186
|
+
const writeKey = createWriteKey(deps)(); // Random, no seed
|
|
187
|
+
return {
|
|
188
|
+
type: "SharedOwner",
|
|
189
|
+
mnemonic,
|
|
190
|
+
writeKey,
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Creates a {@link SharedReadonlyOwner} from a {@link SharedOwner} for read-only
|
|
196
|
+
* data sharing. Extracts the `mnemonic` from the provided {@link SharedOwner},
|
|
197
|
+
* omitting its `writeKey` to ensure read-only access.
|
|
198
|
+
*/
|
|
199
|
+
export const createSharedReadonlyOwner = (
|
|
200
|
+
sharedOwner: SharedOwner,
|
|
201
|
+
): SharedReadonlyOwner => {
|
|
202
|
+
return {
|
|
203
|
+
type: "SharedReadonlyOwner",
|
|
204
|
+
mnemonic: sharedOwner.mnemonic,
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/** Creates an {@link Owner} with optional `mnemonic` and `writeKey`. */
|
|
209
|
+
export const createOwner =
|
|
210
|
+
(deps: TimeDep & CreateRandomBytesDep & CreateMnemonicDep) =>
|
|
211
|
+
(mnemonic = deps.createMnemonic(), writeKey?: WriteKey): Owner => {
|
|
212
|
+
const seed = mnemonicToMnemonicSeed(mnemonic);
|
|
213
|
+
|
|
214
|
+
const id = createSlip21Id(seed, ["Evolu", "Owner Id"]) as OwnerId;
|
|
215
|
+
const encryptionKey = createEncryptionKey(seed);
|
|
216
|
+
|
|
217
|
+
const createdAt = DateIso.fromParent(new Date(deps.time.now()));
|
|
218
|
+
assert(createdAt.ok, "Invalid DateIso: bad system clock");
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
mnemonic,
|
|
222
|
+
createdAt: createdAt.value,
|
|
223
|
+
id,
|
|
224
|
+
encryptionKey,
|
|
225
|
+
writeKey: writeKey ?? createWriteKey(deps)(seed),
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
export const createWriteKey =
|
|
230
|
+
(deps: CreateRandomBytesDep) =>
|
|
231
|
+
(seed?: MnemonicSeed): WriteKey => {
|
|
232
|
+
const key = seed
|
|
233
|
+
? createSlip21(seed, ["Evolu", "Write Key"]).slice(0, 16)
|
|
234
|
+
: deps.createRandomBytes(16);
|
|
235
|
+
|
|
236
|
+
const writeKey = WriteKey.from(key);
|
|
237
|
+
assert(writeKey.ok, "Ensure valid WriteKey");
|
|
238
|
+
|
|
239
|
+
return writeKey.value;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* An `OwnerRow` represents a row in the `evolu_owner` table, based on an
|
|
244
|
+
* {@link Owner} with an added `timestamp` ({@link TimestampString}) for CRDT
|
|
245
|
+
* sync. It supports all {@link Owner} variants with an optional `writeKey`; use
|
|
246
|
+
* {@link createOwnerRow} to align it with a specific {@link Owner}.
|
|
247
|
+
*/
|
|
248
|
+
export type OwnerRow = Omit<Owner, "writeKey"> & {
|
|
249
|
+
readonly writeKey: WriteKey | null;
|
|
250
|
+
readonly timestamp: TimestampString;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Creates an {@link OwnerRow} from any {@link Owner} variant for the
|
|
255
|
+
* `evolu_owner` table, adding a `timestamp` ({@link TimestampString}) for CRDT
|
|
256
|
+
* sync.
|
|
257
|
+
*/
|
|
258
|
+
export const createOwnerRow =
|
|
259
|
+
(deps: TimeDep & CreateRandomBytesDep & CreateMnemonicDep & NanoIdLibDep) =>
|
|
260
|
+
(
|
|
261
|
+
owner: AppOwner | ShardOwner | SharedOwner | SharedReadonlyOwner,
|
|
262
|
+
): OwnerRow => {
|
|
263
|
+
const timestamp = timestampToTimestampString(createInitialTimestamp(deps));
|
|
264
|
+
switch (owner.type) {
|
|
265
|
+
case "AppOwner": {
|
|
266
|
+
const { type, ...rest } = owner;
|
|
267
|
+
return { ...rest, timestamp };
|
|
268
|
+
}
|
|
269
|
+
case "ShardOwner":
|
|
270
|
+
case "SharedOwner":
|
|
271
|
+
return {
|
|
272
|
+
...createOwner(deps)(owner.mnemonic, owner.writeKey),
|
|
273
|
+
timestamp,
|
|
274
|
+
};
|
|
275
|
+
case "SharedReadonlyOwner":
|
|
276
|
+
return {
|
|
277
|
+
...createOwner(deps)(owner.mnemonic),
|
|
278
|
+
writeKey: null,
|
|
279
|
+
timestamp,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Rotates the {@link WriteKey} for an {@link AppOwner}, {@link ShardOwner}, or
|
|
286
|
+
* {@link SharedOwner}, returning a new instance with the updated key.
|
|
287
|
+
*/
|
|
288
|
+
export const rotateWriteKey = <T extends AppOwner | ShardOwner | SharedOwner>(
|
|
289
|
+
owner: T,
|
|
290
|
+
newWriteKey: WriteKey,
|
|
291
|
+
): T => {
|
|
292
|
+
return {
|
|
293
|
+
...owner,
|
|
294
|
+
writeKey: newWriteKey,
|
|
295
|
+
} as T;
|
|
296
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Config } from "./Config.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* FlushSync is for libraries like React to flush updates synchronously inside
|
|
5
|
+
* the provided callback to ensure the DOM is updated immediately.
|
|
6
|
+
*
|
|
7
|
+
* For example, with React, when we want to focus on an element rendered as a
|
|
8
|
+
* result of a mutation, Evolu ensures all DOM changes are flushed synchronously
|
|
9
|
+
* if an onComplete callback is used.
|
|
10
|
+
*
|
|
11
|
+
* https://react.dev/reference/react-dom/flushSync
|
|
12
|
+
*/
|
|
13
|
+
export type FlushSync = (callback: () => void) => void;
|
|
14
|
+
|
|
15
|
+
export interface FlushSyncDep {
|
|
16
|
+
readonly flushSync: FlushSync;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface AppState {
|
|
20
|
+
readonly reset: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type CreateAppState = (config: Config) => AppState;
|
|
24
|
+
|
|
25
|
+
export interface CreateAppStateDep {
|
|
26
|
+
readonly createAppState: CreateAppState;
|
|
27
|
+
}
|