@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
package/src/Sql.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// this file is generated by generateSql script
|
|
2
|
-
import { SqliteQuery } from "./Sqlite.js";
|
|
3
|
-
export const selectOwner: SqliteQuery = {
|
|
4
|
-
sql: `select "id", "mnemonic", "encryptionKey" from "evolu_owner"`,
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export const createMessageTable: SqliteQuery = {
|
|
8
|
-
sql: `create table "evolu_message" ("timestamp" blob primary key, "table" blob, "row" blob, "column" blob, "value" blob)`,
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const createMessageTableIndex: SqliteQuery = {
|
|
12
|
-
sql: `create index "index_evolu_message" on "evolu_message" ("table", "row", "column", "timestamp" desc)`,
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const createOwnerTable: SqliteQuery = {
|
|
16
|
-
sql: `create table "evolu_owner" ("id" blob, "mnemonic" blob, "encryptionKey" blob, "timestamp" blob, "merkleTree" blob)`,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const insertOwner: SqliteQuery = {
|
|
20
|
-
sql: `insert into "evolu_owner" ("id", "mnemonic", "encryptionKey", "timestamp", "merkleTree") values (?, ?, ?, ?, ?)`,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const selectOwnerTimestampAndMerkleTree: SqliteQuery = {
|
|
24
|
-
sql: `select "timestamp", "merkleTree" from "evolu_owner"`,
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const selectLastTimestampForTableRowColumn: SqliteQuery = {
|
|
28
|
-
sql: `select "timestamp" from "evolu_message" where "table" = ? and "row" = ? and "column" = ? order by "timestamp" desc limit ?`,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export const insertIntoMessagesIfNew: SqliteQuery = {
|
|
32
|
-
sql: `insert into "evolu_message" ("timestamp", "table", "row", "column", "value") values (?, ?, ?, ?, ?) on conflict do nothing`,
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export const updateOwnerTimestampAndMerkleTree: SqliteQuery = {
|
|
36
|
-
sql: `update "evolu_owner" set "merkleTree" = ?, "timestamp" = ?`,
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export const selectMessagesToSync: SqliteQuery = {
|
|
40
|
-
sql: `select * from "evolu_message" where "timestamp" >= ? order by "timestamp"`,
|
|
41
|
-
};
|
package/src/Sync.ts
DELETED
|
@@ -1,315 +0,0 @@
|
|
|
1
|
-
import * as Platform from "@effect/platform";
|
|
2
|
-
import * as S from "@effect/schema/Schema";
|
|
3
|
-
import { concatBytes } from "@noble/ciphers/utils";
|
|
4
|
-
import { BinaryReader, BinaryWriter } from "@protobuf-ts/runtime";
|
|
5
|
-
import * as Arr from "effect/Array";
|
|
6
|
-
import * as Context from "effect/Context";
|
|
7
|
-
import * as Deferred from "effect/Deferred";
|
|
8
|
-
import * as Effect from "effect/Effect";
|
|
9
|
-
import { absurd } from "effect/Function";
|
|
10
|
-
import * as Option from "effect/Option";
|
|
11
|
-
import * as Predicate from "effect/Predicate";
|
|
12
|
-
import { Config } from "./Config.js";
|
|
13
|
-
import {
|
|
14
|
-
MerkleTree,
|
|
15
|
-
Millis,
|
|
16
|
-
Timestamp,
|
|
17
|
-
TimestampString,
|
|
18
|
-
merkleTreeToString,
|
|
19
|
-
unsafeMerkleTreeFromString,
|
|
20
|
-
} from "./Crdt.js";
|
|
21
|
-
import { SecretBox } from "./Crypto.js";
|
|
22
|
-
import { Id } from "./Model.js";
|
|
23
|
-
import { Owner } from "./Owner.js";
|
|
24
|
-
import * as Protobuf from "./Protobuf.js";
|
|
25
|
-
import { JsonObjectOrArray, Value } from "./Sqlite.js";
|
|
26
|
-
|
|
27
|
-
export interface Sync {
|
|
28
|
-
readonly init: (owner: Owner) => Effect.Effect<void>;
|
|
29
|
-
readonly sync: (
|
|
30
|
-
syncData: SyncData,
|
|
31
|
-
) => Effect.Effect<SyncResult, SyncStateIsNotSynced, Config>;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export const Sync = Context.GenericTag<Sync>("Sync");
|
|
35
|
-
|
|
36
|
-
export interface SyncData {
|
|
37
|
-
merkleTree: MerkleTree;
|
|
38
|
-
timestamp: Timestamp;
|
|
39
|
-
messages?: ReadonlyArray<Message>;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface Message extends NewMessage {
|
|
43
|
-
readonly timestamp: TimestampString;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface NewMessage {
|
|
47
|
-
readonly table: string;
|
|
48
|
-
readonly row: Id;
|
|
49
|
-
readonly column: string;
|
|
50
|
-
readonly value: Value;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface SyncResult {
|
|
54
|
-
readonly messages: ReadonlyArray<Message>;
|
|
55
|
-
readonly merkleTree: MerkleTree;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* The SyncState type represents the various states that a synchronization
|
|
60
|
-
* process can be in.
|
|
61
|
-
*/
|
|
62
|
-
export type SyncState =
|
|
63
|
-
| SyncStateInitial
|
|
64
|
-
| SyncStateIsSyncing
|
|
65
|
-
| SyncStateIsSynced
|
|
66
|
-
| SyncStateIsNotSynced;
|
|
67
|
-
|
|
68
|
-
/** On app start, we need to find out whether the state is synced. */
|
|
69
|
-
export interface SyncStateInitial {
|
|
70
|
-
readonly _tag: "SyncStateInitial";
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// To preserve identity.
|
|
74
|
-
export const initialSyncState: SyncStateInitial = { _tag: "SyncStateInitial" };
|
|
75
|
-
|
|
76
|
-
export interface SyncStateIsSyncing {
|
|
77
|
-
readonly _tag: "SyncStateIsSyncing";
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export interface SyncStateIsSynced {
|
|
81
|
-
readonly _tag: "SyncStateIsSynced";
|
|
82
|
-
readonly time: Millis;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export interface SyncStateIsNotSynced {
|
|
86
|
-
readonly _tag: "SyncStateIsNotSynced";
|
|
87
|
-
readonly error: NetworkError | ServerError | PaymentRequiredError;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export interface NetworkError {
|
|
91
|
-
readonly _tag: "NetworkError";
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export interface ServerError {
|
|
95
|
-
readonly _tag: "ServerError";
|
|
96
|
-
readonly status: number;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export interface PaymentRequiredError {
|
|
100
|
-
readonly _tag: "PaymentRequiredError";
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export class SyncFactory extends Context.Tag("SyncFactory")<
|
|
104
|
-
SyncFactory,
|
|
105
|
-
{
|
|
106
|
-
readonly createSync: Effect.Effect<Sync, never, never>;
|
|
107
|
-
}
|
|
108
|
-
>() {}
|
|
109
|
-
|
|
110
|
-
export const createSync = Effect.gen(function* () {
|
|
111
|
-
const initContext = Context.empty().pipe(
|
|
112
|
-
Context.add(SecretBox, yield* SecretBox),
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
const afterInitContext =
|
|
116
|
-
yield* Deferred.make<Context.Context<SecretBox | Owner>>();
|
|
117
|
-
|
|
118
|
-
return Sync.of({
|
|
119
|
-
init: (owner) =>
|
|
120
|
-
Effect.logDebug(["Sync init", { owner }]).pipe(
|
|
121
|
-
Effect.tap(
|
|
122
|
-
Deferred.succeed(
|
|
123
|
-
afterInitContext,
|
|
124
|
-
initContext.pipe(Context.add(Owner, owner)),
|
|
125
|
-
),
|
|
126
|
-
),
|
|
127
|
-
),
|
|
128
|
-
sync: ({ merkleTree, timestamp, messages }) =>
|
|
129
|
-
Effect.gen(function* () {
|
|
130
|
-
yield* Effect.logDebug([
|
|
131
|
-
"Sync request",
|
|
132
|
-
{ merkleTree, timestamp, messages },
|
|
133
|
-
]);
|
|
134
|
-
const secretBox = yield* SecretBox;
|
|
135
|
-
const owner = yield* Owner;
|
|
136
|
-
const config = yield* Config;
|
|
137
|
-
|
|
138
|
-
return yield* Effect.forEach(
|
|
139
|
-
messages || [],
|
|
140
|
-
({ timestamp, ...newMessage }) =>
|
|
141
|
-
Effect.map(
|
|
142
|
-
secretBox.seal(
|
|
143
|
-
owner.encryptionKey,
|
|
144
|
-
newMessageToBinary(newMessage),
|
|
145
|
-
),
|
|
146
|
-
(content): Protobuf.EncryptedMessage => ({ timestamp, content }),
|
|
147
|
-
),
|
|
148
|
-
).pipe(
|
|
149
|
-
Effect.map((encrypedMessages) =>
|
|
150
|
-
Protobuf.SyncRequest.toBinary(
|
|
151
|
-
{
|
|
152
|
-
messages: encrypedMessages,
|
|
153
|
-
userId: owner.id,
|
|
154
|
-
nodeId: timestamp.node,
|
|
155
|
-
merkleTree: merkleTreeToString(merkleTree),
|
|
156
|
-
},
|
|
157
|
-
binaryWriteOptions,
|
|
158
|
-
),
|
|
159
|
-
),
|
|
160
|
-
Effect.flatMap((body) =>
|
|
161
|
-
Effect.gen(function* () {
|
|
162
|
-
const client = (yield* Platform.HttpClient.HttpClient).pipe(
|
|
163
|
-
Platform.HttpClient.filterStatusOk,
|
|
164
|
-
);
|
|
165
|
-
return yield* Platform.HttpClientRequest.post(
|
|
166
|
-
config.syncUrl,
|
|
167
|
-
).pipe(
|
|
168
|
-
Platform.HttpClientRequest.bodyUint8Array(
|
|
169
|
-
body,
|
|
170
|
-
"application/x-protobuf",
|
|
171
|
-
),
|
|
172
|
-
client.execute,
|
|
173
|
-
Effect.flatMap((response) => response.arrayBuffer),
|
|
174
|
-
Effect.scoped,
|
|
175
|
-
);
|
|
176
|
-
}).pipe(Effect.provide(Platform.FetchHttpClient.layer)),
|
|
177
|
-
),
|
|
178
|
-
Effect.map((buffer) =>
|
|
179
|
-
Protobuf.SyncResponse.fromBinary(
|
|
180
|
-
new Uint8Array(buffer),
|
|
181
|
-
binaryReadOptions,
|
|
182
|
-
),
|
|
183
|
-
),
|
|
184
|
-
Effect.flatMap((syncResponse) =>
|
|
185
|
-
Effect.forEach(syncResponse.messages, (encrypedMessage) =>
|
|
186
|
-
Effect.map(
|
|
187
|
-
secretBox.open(owner.encryptionKey, encrypedMessage.content),
|
|
188
|
-
(binary) => [binary, encrypedMessage.timestamp] as const,
|
|
189
|
-
),
|
|
190
|
-
).pipe(
|
|
191
|
-
Effect.map(
|
|
192
|
-
Arr.filterMap(([binary, timestamp]) =>
|
|
193
|
-
Option.map(
|
|
194
|
-
newMessageFromBinary(binary),
|
|
195
|
-
(newMessage): Message => ({ ...newMessage, timestamp }),
|
|
196
|
-
),
|
|
197
|
-
),
|
|
198
|
-
),
|
|
199
|
-
Effect.map((messages) => ({
|
|
200
|
-
messages,
|
|
201
|
-
merkleTree: unsafeMerkleTreeFromString(syncResponse.merkleTree),
|
|
202
|
-
})),
|
|
203
|
-
Effect.tap((response) =>
|
|
204
|
-
Effect.logDebug(["Sync response", response]),
|
|
205
|
-
),
|
|
206
|
-
),
|
|
207
|
-
),
|
|
208
|
-
Effect.catchTag("RequestError", () =>
|
|
209
|
-
Effect.fail<SyncStateIsNotSynced>({
|
|
210
|
-
_tag: "SyncStateIsNotSynced",
|
|
211
|
-
error: { _tag: "NetworkError" },
|
|
212
|
-
}),
|
|
213
|
-
),
|
|
214
|
-
Effect.catchTag("ResponseError", ({ response: { status } }) => {
|
|
215
|
-
switch (status) {
|
|
216
|
-
case 402:
|
|
217
|
-
return Effect.fail<SyncStateIsNotSynced>({
|
|
218
|
-
_tag: "SyncStateIsNotSynced",
|
|
219
|
-
error: { _tag: "PaymentRequiredError" },
|
|
220
|
-
});
|
|
221
|
-
default:
|
|
222
|
-
return Effect.fail<SyncStateIsNotSynced>({
|
|
223
|
-
_tag: "SyncStateIsNotSynced",
|
|
224
|
-
error: { _tag: "ServerError", status },
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
}),
|
|
228
|
-
);
|
|
229
|
-
}).pipe((effect) =>
|
|
230
|
-
Effect.flatMap(Deferred.await(afterInitContext), (context) =>
|
|
231
|
-
Effect.provide(effect, context),
|
|
232
|
-
),
|
|
233
|
-
),
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
const newMessageToBinary = ({ value, ...rest }: NewMessage): Uint8Array =>
|
|
238
|
-
concatBytes(
|
|
239
|
-
version1,
|
|
240
|
-
Protobuf.MessageContent.toBinary(
|
|
241
|
-
{ value: valueToProtobuf(value), ...rest },
|
|
242
|
-
binaryWriteOptions,
|
|
243
|
-
),
|
|
244
|
-
);
|
|
245
|
-
|
|
246
|
-
const version1 = new Uint8Array([0, 1]);
|
|
247
|
-
|
|
248
|
-
const valueToProtobuf = (value: Value): Protobuf.MessageContent["value"] => {
|
|
249
|
-
switch (typeof value) {
|
|
250
|
-
case "string":
|
|
251
|
-
return { oneofKind: "stringValue", stringValue: value };
|
|
252
|
-
case "number":
|
|
253
|
-
return {
|
|
254
|
-
oneofKind: "numberValue",
|
|
255
|
-
numberValue: S.encodeSync(S.NumberFromString)(value),
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
if (value == null) return { oneofKind: undefined };
|
|
259
|
-
if (Predicate.isUint8Array(value))
|
|
260
|
-
return { oneofKind: "bytesValue", bytesValue: value };
|
|
261
|
-
return { oneofKind: "jsonValue", jsonValue: JSON.stringify(value) };
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
// The 'protobuf-ts' uses TextEncoder, but polyfill fast-text-encoding
|
|
265
|
-
// doesn't support the fatal option.
|
|
266
|
-
// https://github.com/timostamm/protobuf-ts/issues/184#issuecomment-1658443836
|
|
267
|
-
const binaryWriteOptions = {
|
|
268
|
-
writerFactory: (): BinaryWriter =>
|
|
269
|
-
new BinaryWriter({
|
|
270
|
-
encode: (input: string): Uint8Array => new TextEncoder().encode(input),
|
|
271
|
-
}),
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
const binaryReadOptions = {
|
|
275
|
-
readerFactory: (bytes: Uint8Array): BinaryReader =>
|
|
276
|
-
new BinaryReader(bytes, {
|
|
277
|
-
decode: (input: Uint8Array): string => new TextDecoder().decode(input),
|
|
278
|
-
}),
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
const newMessageFromBinary = (
|
|
282
|
-
binary: Uint8Array,
|
|
283
|
-
): Option.Option<NewMessage> => {
|
|
284
|
-
if (!startsWithArray(binary, version1)) return Option.none();
|
|
285
|
-
const { value, ...content } = Protobuf.MessageContent.fromBinary(
|
|
286
|
-
binary.slice(version1.length),
|
|
287
|
-
binaryReadOptions,
|
|
288
|
-
);
|
|
289
|
-
return Option.some({ value: valueFromProtobuf(value), ...content });
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
const startsWithArray = (array: Uint8Array, prefix: Uint8Array): boolean => {
|
|
293
|
-
if (prefix.length > array.length) return false;
|
|
294
|
-
for (let i = 0; i < prefix.length; i++) {
|
|
295
|
-
if (array[i] !== prefix[i]) return false;
|
|
296
|
-
}
|
|
297
|
-
return true;
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
const valueFromProtobuf = (value: Protobuf.MessageContent["value"]): Value => {
|
|
301
|
-
switch (value.oneofKind) {
|
|
302
|
-
case "numberValue":
|
|
303
|
-
return S.decodeSync(S.NumberFromString)(value.numberValue);
|
|
304
|
-
case "stringValue":
|
|
305
|
-
return value.stringValue;
|
|
306
|
-
case "bytesValue":
|
|
307
|
-
return value.bytesValue;
|
|
308
|
-
case "jsonValue":
|
|
309
|
-
return JSON.parse(value.jsonValue) as JsonObjectOrArray;
|
|
310
|
-
case undefined:
|
|
311
|
-
return null;
|
|
312
|
-
default:
|
|
313
|
-
return absurd(value);
|
|
314
|
-
}
|
|
315
|
-
};
|