@evolu/common 1.0.17 → 2.0.1
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 +7 -7
- package/dist/src/Config.d.ts +4 -6
- package/dist/src/Config.d.ts.map +1 -1
- package/dist/src/Config.js +1 -1
- package/dist/src/Crdt.d.ts +15 -9
- package/dist/src/Crdt.d.ts.map +1 -1
- package/dist/src/Crdt.js +15 -14
- package/dist/src/Crypto.d.ts +7 -13
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +7 -9
- package/dist/src/Db.d.ts +36 -70
- package/dist/src/Db.d.ts.map +1 -1
- package/dist/src/Db.js +45 -51
- package/dist/src/DbWorker.d.ts +13 -14
- package/dist/src/DbWorker.d.ts.map +1 -1
- package/dist/src/DbWorker.js +56 -57
- package/dist/src/Diff.d.ts +3 -1
- package/dist/src/Diff.d.ts.map +1 -1
- package/dist/src/Diff.js +3 -7
- package/dist/src/{Errors.d.ts → ErrorStore.d.ts} +14 -7
- package/dist/src/ErrorStore.d.ts.map +1 -0
- package/dist/src/{Errors.js → ErrorStore.js} +2 -0
- package/dist/src/Evolu.d.ts +316 -58
- package/dist/src/Evolu.d.ts.map +1 -1
- package/dist/src/Evolu.js +199 -185
- package/dist/src/Model.d.ts +47 -57
- package/dist/src/Model.d.ts.map +1 -1
- package/dist/src/Model.js +30 -35
- package/dist/src/OnCompletes.d.ts +11 -0
- package/dist/src/OnCompletes.d.ts.map +1 -0
- package/dist/src/OnCompletes.js +21 -0
- package/dist/src/Owner.d.ts +31 -0
- package/dist/src/Owner.d.ts.map +1 -0
- package/dist/src/Owner.js +20 -0
- package/dist/src/Platform.d.ts +16 -12
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +18 -12
- package/dist/src/Protobuf.d.ts +25 -73
- package/dist/src/Protobuf.d.ts.map +1 -1
- package/dist/src/Protobuf.js +4 -12
- package/dist/src/Public.d.ts +5 -3
- package/dist/src/Public.d.ts.map +1 -1
- package/dist/src/Public.js +1 -0
- package/dist/src/Sqlite.d.ts +8 -11
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +7 -7
- package/dist/src/Store.d.ts +6 -5
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +21 -16
- package/dist/src/SyncWorker.d.ts +8 -2
- package/dist/src/SyncWorker.d.ts.map +1 -1
- package/dist/src/SyncWorker.js +12 -19
- package/dist/src/index.d.ts +6 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -2
- package/package.json +23 -13
- package/src/Config.ts +7 -7
- package/src/Crdt.ts +29 -26
- package/src/Crypto.ts +14 -19
- package/src/Db.ts +113 -166
- package/src/DbWorker.ts +110 -140
- package/src/Diff.ts +5 -7
- package/src/{Errors.ts → ErrorStore.ts} +17 -8
- package/src/Evolu.ts +682 -442
- package/src/Model.ts +60 -85
- package/src/OnCompletes.ts +46 -0
- package/src/Owner.ts +65 -0
- package/src/Platform.ts +38 -25
- package/src/Protobuf.ts +25 -73
- package/src/Public.ts +5 -3
- package/src/Sqlite.ts +13 -24
- package/src/Store.ts +36 -24
- package/src/SyncWorker.ts +30 -38
- package/src/index.ts +6 -2
- package/dist/src/Errors.d.ts.map +0 -1
package/src/Sqlite.ts
CHANGED
|
@@ -1,45 +1,37 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Context, Effect, Predicate, ReadonlyRecord } from "effect";
|
|
2
2
|
|
|
3
3
|
export interface Sqlite {
|
|
4
4
|
readonly exec: (
|
|
5
|
-
arg: string |
|
|
5
|
+
arg: string | SqliteQuery,
|
|
6
6
|
) => Effect.Effect<never, never, ExecResult>;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export const Sqlite = Context.Tag<Sqlite>(
|
|
9
|
+
export const Sqlite = Context.Tag<Sqlite>();
|
|
10
10
|
|
|
11
|
-
export interface
|
|
11
|
+
export interface SqliteQuery {
|
|
12
12
|
readonly sql: string;
|
|
13
|
-
readonly parameters:
|
|
13
|
+
readonly parameters: Value[];
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export type Value = SqliteValue | JsonObjectOrArray;
|
|
17
|
-
|
|
18
17
|
export type SqliteValue = null | string | number | Uint8Array;
|
|
19
|
-
export type SqliteRow = Record<string, SqliteValue>;
|
|
20
|
-
|
|
21
18
|
export type JsonObjectOrArray = JsonObject | JsonArray;
|
|
22
|
-
|
|
23
19
|
type JsonObject = ReadonlyRecord.ReadonlyRecord<Json>;
|
|
24
20
|
type JsonArray = ReadonlyArray<Json>;
|
|
25
21
|
type Json = string | number | boolean | null | JsonObject | JsonArray;
|
|
26
22
|
|
|
27
23
|
interface ExecResult {
|
|
28
|
-
readonly rows:
|
|
24
|
+
readonly rows: SqliteRow[];
|
|
29
25
|
readonly changes: number;
|
|
30
26
|
}
|
|
31
27
|
|
|
32
|
-
export type
|
|
33
|
-
Value | Row | ReadonlyArray<Row>
|
|
34
|
-
>;
|
|
35
|
-
|
|
36
|
-
export type Query = string & Brand.Brand<"Query">;
|
|
28
|
+
export type SqliteRow = Record<string, SqliteValue>;
|
|
37
29
|
|
|
38
30
|
export const isJsonObjectOrArray: Predicate.Refinement<
|
|
39
31
|
Value,
|
|
40
32
|
JsonObjectOrArray
|
|
41
33
|
> = (value): value is JsonObjectOrArray =>
|
|
42
|
-
value !== null && typeof value === "object" && !(value
|
|
34
|
+
value !== null && typeof value === "object" && !Predicate.isUint8Array(value);
|
|
43
35
|
|
|
44
36
|
export const valuesToSqliteValues = (
|
|
45
37
|
values: ReadonlyArray<Value>,
|
|
@@ -48,15 +40,13 @@ export const valuesToSqliteValues = (
|
|
|
48
40
|
isJsonObjectOrArray(value) ? JSON.stringify(value) : value,
|
|
49
41
|
);
|
|
50
42
|
|
|
51
|
-
export const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
JSON.parse(s) as QueryObject;
|
|
43
|
+
export const ensureSqliteQuery = (arg: string | SqliteQuery): SqliteQuery => {
|
|
44
|
+
if (typeof arg !== "string") return arg;
|
|
45
|
+
return { sql: arg, parameters: [] };
|
|
46
|
+
};
|
|
56
47
|
|
|
57
|
-
export const
|
|
48
|
+
export const maybeParseJson = (rows: SqliteRow[]): SqliteRow[] =>
|
|
58
49
|
parseArray(rows);
|
|
59
|
-
};
|
|
60
50
|
|
|
61
51
|
const parseArray = <T>(a: T[]): T[] => {
|
|
62
52
|
for (let i = 0; i < a.length; ++i) a[i] = parse(a[i]) as T;
|
|
@@ -67,7 +57,6 @@ const parse = (o: unknown): unknown => {
|
|
|
67
57
|
if (Predicate.isString(o)) return parseString(o);
|
|
68
58
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
69
59
|
if (Array.isArray(o)) return parseArray(o);
|
|
70
|
-
// Predicate.isReadonlyRecord
|
|
71
60
|
if (typeof o === "object" && o !== null && !Predicate.isUint8Array(o))
|
|
72
61
|
return parseObject(o as Record<string, unknown>);
|
|
73
62
|
return o;
|
package/src/Store.ts
CHANGED
|
@@ -1,32 +1,44 @@
|
|
|
1
|
-
|
|
1
|
+
import { Effect } from "effect";
|
|
2
2
|
|
|
3
|
-
export type
|
|
3
|
+
export type Listener = () => void;
|
|
4
|
+
|
|
5
|
+
export type Unsubscribe = () => void;
|
|
4
6
|
|
|
5
7
|
export interface Store<T> {
|
|
6
|
-
|
|
7
|
-
readonly
|
|
8
|
+
// No Effect API because of React useSyncExternalStore
|
|
9
|
+
readonly subscribe: (listener: Listener) => Unsubscribe;
|
|
8
10
|
readonly getState: () => T;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const makeStore = <T>(initialState: T): Store<T> => {
|
|
12
|
-
let currentState = initialState;
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
// Effect API because it's a side-effect.
|
|
13
|
+
readonly setState: (state: T) => Effect.Effect<never, never, void>;
|
|
14
|
+
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
export const makeStore = <T>(
|
|
17
|
+
initialState: T,
|
|
18
|
+
): Effect.Effect<never, never, Store<T>> =>
|
|
19
|
+
Effect.sync(() => {
|
|
20
|
+
const listeners = new Set<Listener>();
|
|
21
|
+
let currentState = initialState;
|
|
22
|
+
|
|
23
|
+
const store: Store<T> = {
|
|
24
|
+
subscribe(listener) {
|
|
25
|
+
listeners.add(listener);
|
|
26
|
+
return () => {
|
|
27
|
+
listeners.delete(listener);
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
getState() {
|
|
32
|
+
return currentState;
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
setState: (state) =>
|
|
36
|
+
Effect.sync(() => {
|
|
37
|
+
if (state === currentState) return;
|
|
38
|
+
currentState = state;
|
|
39
|
+
listeners.forEach((listener) => listener());
|
|
40
|
+
}),
|
|
20
41
|
};
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const setState: Store<T>["setState"] = (state: T) => {
|
|
24
|
-
if (state === currentState) return;
|
|
25
|
-
currentState = state;
|
|
26
|
-
listeners.forEach((listener) => listener());
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const getState: Store<T>["getState"] = () => currentState;
|
|
30
42
|
|
|
31
|
-
|
|
32
|
-
};
|
|
43
|
+
return store;
|
|
44
|
+
});
|
package/src/SyncWorker.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
Equivalence,
|
|
7
7
|
Function,
|
|
8
8
|
Layer,
|
|
9
|
+
Match,
|
|
9
10
|
Option,
|
|
10
11
|
Predicate,
|
|
11
12
|
ReadonlyArray,
|
|
@@ -21,9 +22,9 @@ import {
|
|
|
21
22
|
unsafeMerkleTreeFromString,
|
|
22
23
|
} from "./Crdt.js";
|
|
23
24
|
import { SecretBox } from "./Crypto.js";
|
|
24
|
-
import {
|
|
25
|
-
import { UnexpectedError, makeUnexpectedError } from "./Errors.js";
|
|
25
|
+
import { UnexpectedError, makeUnexpectedError } from "./ErrorStore.js";
|
|
26
26
|
import { Id } from "./Model.js";
|
|
27
|
+
import { Owner } from "./Owner.js";
|
|
27
28
|
import { Fetch, SyncLock } from "./Platform.js";
|
|
28
29
|
import {
|
|
29
30
|
EncryptedMessage,
|
|
@@ -38,13 +39,11 @@ export interface SyncWorker {
|
|
|
38
39
|
onMessage: (output: SyncWorkerOutput) => void;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
export const SyncWorker = Context.Tag<SyncWorker>(
|
|
42
|
+
export const SyncWorker = Context.Tag<SyncWorker>();
|
|
42
43
|
|
|
43
44
|
export type SyncWorkerPostMessage = SyncWorker["postMessage"];
|
|
44
45
|
|
|
45
|
-
export const SyncWorkerPostMessage = Context.Tag<SyncWorkerPostMessage>(
|
|
46
|
-
"evolu/SyncWorkerPostMessage",
|
|
47
|
-
);
|
|
46
|
+
export const SyncWorkerPostMessage = Context.Tag<SyncWorkerPostMessage>();
|
|
48
47
|
|
|
49
48
|
export type SyncWorkerInput =
|
|
50
49
|
| SyncWorkerInputSync
|
|
@@ -86,9 +85,7 @@ interface SyncWorkerInputSyncCompleted {
|
|
|
86
85
|
|
|
87
86
|
type SyncWorkerOnMessage = SyncWorker["onMessage"];
|
|
88
87
|
|
|
89
|
-
const SyncWorkerOnMessage = Context.Tag<SyncWorkerOnMessage>(
|
|
90
|
-
"evolu/SyncWorkerOnMessage",
|
|
91
|
-
);
|
|
88
|
+
const SyncWorkerOnMessage = Context.Tag<SyncWorkerOnMessage>();
|
|
92
89
|
|
|
93
90
|
export type SyncWorkerOutput =
|
|
94
91
|
| UnexpectedError
|
|
@@ -103,6 +100,12 @@ export type SyncWorkerOutputSyncResponse = {
|
|
|
103
100
|
readonly syncLoopCount: number;
|
|
104
101
|
};
|
|
105
102
|
|
|
103
|
+
/**
|
|
104
|
+
* The SyncState type represents the various states that a synchronization
|
|
105
|
+
* process can be in. Evolu apps should not bother users with an "unsynced"
|
|
106
|
+
* state. Instead, they should warn users if data have not been synced for too
|
|
107
|
+
* long (a week, for example).
|
|
108
|
+
*/
|
|
106
109
|
export type SyncState =
|
|
107
110
|
| SyncStateInitial
|
|
108
111
|
| SyncStateIsSyncing
|
|
@@ -319,8 +322,6 @@ export const SyncWorkerLive = Layer.effect(
|
|
|
319
322
|
SyncWorker,
|
|
320
323
|
Effect.gen(function* (_) {
|
|
321
324
|
const syncLock = yield* _(SyncLock);
|
|
322
|
-
const fetch = yield* _(Fetch);
|
|
323
|
-
const secretBox = yield* _(SecretBox);
|
|
324
325
|
|
|
325
326
|
const onError = (
|
|
326
327
|
error: UnexpectedError,
|
|
@@ -329,35 +330,26 @@ export const SyncWorkerLive = Layer.effect(
|
|
|
329
330
|
syncWorker.onMessage(error);
|
|
330
331
|
});
|
|
331
332
|
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
void
|
|
338
|
-
> => {
|
|
339
|
-
switch (input._tag) {
|
|
340
|
-
case "sync":
|
|
341
|
-
return sync(input);
|
|
342
|
-
case "syncCompleted":
|
|
343
|
-
return syncLock.release;
|
|
344
|
-
}
|
|
345
|
-
};
|
|
346
|
-
|
|
347
|
-
const postMessage: SyncWorker["postMessage"] = (input) => {
|
|
348
|
-
void mapInputToEffect(input).pipe(
|
|
349
|
-
Effect.catchAllDefect(makeUnexpectedError),
|
|
350
|
-
Effect.catchAll(onError),
|
|
351
|
-
Effect.provideService(SyncLock, syncLock),
|
|
352
|
-
Effect.provideService(Fetch, fetch),
|
|
353
|
-
Effect.provideService(SecretBox, secretBox),
|
|
354
|
-
Effect.provideService(SyncWorkerOnMessage, syncWorker.onMessage),
|
|
355
|
-
Effect.runPromise,
|
|
356
|
-
);
|
|
357
|
-
};
|
|
333
|
+
const context = Context.empty().pipe(
|
|
334
|
+
Context.add(SyncLock, syncLock),
|
|
335
|
+
Context.add(Fetch, yield* _(Fetch)),
|
|
336
|
+
Context.add(SecretBox, yield* _(SecretBox)),
|
|
337
|
+
);
|
|
358
338
|
|
|
359
339
|
const syncWorker: SyncWorker = {
|
|
360
|
-
postMessage
|
|
340
|
+
postMessage: (input) => {
|
|
341
|
+
Match.value(input).pipe(
|
|
342
|
+
Match.tagsExhaustive({
|
|
343
|
+
sync,
|
|
344
|
+
syncCompleted: () => syncLock.release,
|
|
345
|
+
}),
|
|
346
|
+
Effect.catchAllDefect(makeUnexpectedError),
|
|
347
|
+
Effect.catchAll(onError),
|
|
348
|
+
Effect.provide(context),
|
|
349
|
+
Effect.provideService(SyncWorkerOnMessage, syncWorker.onMessage),
|
|
350
|
+
Effect.runPromise,
|
|
351
|
+
);
|
|
352
|
+
},
|
|
361
353
|
onMessage: Function.constVoid,
|
|
362
354
|
};
|
|
363
355
|
|
package/src/index.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
export { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
|
2
1
|
export * from "./Config.js";
|
|
3
2
|
export * from "./Crdt.js";
|
|
4
3
|
export * from "./Crypto.js";
|
|
5
4
|
export * from "./Db.js";
|
|
6
5
|
export * from "./DbWorker.js";
|
|
7
|
-
export * from "./
|
|
6
|
+
export * from "./Diff.js";
|
|
7
|
+
export * from "./ErrorStore.js";
|
|
8
8
|
export * from "./Evolu.js";
|
|
9
9
|
export * from "./Model.js";
|
|
10
|
+
export * from "./Murmurhash.js";
|
|
11
|
+
export * from "./OnCompletes.js";
|
|
12
|
+
export * from "./Owner.js";
|
|
10
13
|
export * from "./Platform.js";
|
|
11
14
|
export * from "./Protobuf.js";
|
|
15
|
+
export * from "./Public.js";
|
|
12
16
|
export * from "./Sqlite.js";
|
|
13
17
|
export * from "./Store.js";
|
|
14
18
|
export * from "./SyncWorker.js";
|
package/dist/src/Errors.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Errors.d.ts","sourceRoot":"","sources":["../../src/Errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,cAAc,CAAC;AAE1D;;;;GAIG;AACH,UAAU,iBAAiB;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;CACnC;AAED,eAAO,MAAM,mBAAmB,UACvB,OAAO,KACb,aAAa,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,CAU7C,CAAC"}
|