@evolu/common 6.0.1-preview.0 → 6.0.1-preview.10
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/dist/src/Assert.d.ts +6 -3
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +6 -3
- package/dist/src/Crypto.d.ts +11 -0
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Evolu/Config.d.ts +17 -4
- package/dist/src/Evolu/Config.d.ts.map +1 -1
- package/dist/src/Evolu/Config.js +1 -1
- package/dist/src/Evolu/Db.d.ts +21 -13
- package/dist/src/Evolu/Db.d.ts.map +1 -1
- package/dist/src/Evolu/Db.js +81 -64
- package/dist/src/Evolu/Evolu.d.ts +6 -6
- package/dist/src/Evolu/Evolu.d.ts.map +1 -1
- package/dist/src/Evolu/Evolu.js +19 -24
- package/dist/src/Evolu/Owner.d.ts +6 -1
- package/dist/src/Evolu/Owner.d.ts.map +1 -1
- package/dist/src/Evolu/Owner.js +5 -0
- package/dist/src/Evolu/Protocol.d.ts +134 -64
- package/dist/src/Evolu/Protocol.d.ts.map +1 -1
- package/dist/src/Evolu/Protocol.js +227 -77
- package/dist/src/Evolu/Relay.d.ts +3 -1
- package/dist/src/Evolu/Relay.d.ts.map +1 -1
- package/dist/src/Evolu/Relay.js +39 -3
- package/dist/src/Evolu/Schema.d.ts +24 -40
- package/dist/src/Evolu/Schema.d.ts.map +1 -1
- package/dist/src/Evolu/Schema.js +13 -72
- package/dist/src/Evolu/Storage.d.ts +1 -0
- package/dist/src/Evolu/Storage.d.ts.map +1 -1
- package/dist/src/Evolu/Storage.js +10 -0
- package/package.json +3 -3
- package/src/Assert.ts +6 -3
- package/src/Crypto.ts +13 -0
- package/src/Evolu/Config.ts +19 -5
- package/src/Evolu/Db.ts +92 -76
- package/src/Evolu/Evolu.ts +38 -35
- package/src/Evolu/Owner.ts +7 -1
- package/src/Evolu/Protocol.ts +276 -110
- package/src/Evolu/Relay.ts +45 -4
- package/src/Evolu/Schema.ts +102 -130
- package/src/Evolu/Storage.ts +12 -0
package/dist/src/Assert.d.ts
CHANGED
|
@@ -16,9 +16,12 @@
|
|
|
16
16
|
* assert(true, "true is not true"); // no-op
|
|
17
17
|
* assert(false, "true is not true"); // throws Error
|
|
18
18
|
*
|
|
19
|
-
* const
|
|
20
|
-
* //
|
|
21
|
-
* assert(
|
|
19
|
+
* const length = buffer.getLength();
|
|
20
|
+
* // We know length is logically non-negative, but TypeScript doesn't
|
|
21
|
+
* assert(
|
|
22
|
+
* NonNegativeInt.is(length),
|
|
23
|
+
* "buffer length should be non-negative",
|
|
24
|
+
* );
|
|
22
25
|
* ```
|
|
23
26
|
*/
|
|
24
27
|
export declare const assert: (condition: unknown, message: string) => asserts condition;
|
package/dist/src/Assert.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Assert.d.ts","sourceRoot":"","sources":["../../src/Assert.ts"],"names":[],"mappings":"AAgBA
|
|
1
|
+
{"version":3,"file":"Assert.d.ts","sourceRoot":"","sources":["../../src/Assert.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,MAAM,EAAE,CACnB,SAAS,EAAE,OAAO,EAClB,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC,SAIZ,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,EAAE,CAAC,CAAC,EAClC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,EACb,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAKlC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,2BAA2B,EAAE,CAAC,CAAC,EAC1C,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,EACrB,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAK3C,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,CAO3E"}
|
package/dist/src/Assert.js
CHANGED
|
@@ -16,9 +16,12 @@
|
|
|
16
16
|
* assert(true, "true is not true"); // no-op
|
|
17
17
|
* assert(false, "true is not true"); // throws Error
|
|
18
18
|
*
|
|
19
|
-
* const
|
|
20
|
-
* //
|
|
21
|
-
* assert(
|
|
19
|
+
* const length = buffer.getLength();
|
|
20
|
+
* // We know length is logically non-negative, but TypeScript doesn't
|
|
21
|
+
* assert(
|
|
22
|
+
* NonNegativeInt.is(length),
|
|
23
|
+
* "buffer length should be non-negative",
|
|
24
|
+
* );
|
|
22
25
|
* ```
|
|
23
26
|
*/
|
|
24
27
|
export const assert = (condition, message) => {
|
package/dist/src/Crypto.d.ts
CHANGED
|
@@ -79,4 +79,15 @@ export declare const padmePaddedLength: (length: NonNegativeInt) => NonNegativeI
|
|
|
79
79
|
* {@link padmePaddedLength}.
|
|
80
80
|
*/
|
|
81
81
|
export declare const padmePaddingLength: (length: NonNegativeInt) => NonNegativeInt;
|
|
82
|
+
/**
|
|
83
|
+
* Performs a timing-safe comparison of two Uint8Arrays. Returns true if they
|
|
84
|
+
* are equal, false otherwise. Takes constant time regardless of where the
|
|
85
|
+
* arrays differ.
|
|
86
|
+
*
|
|
87
|
+
* @see https://nodejs.org/api/crypto.html#cryptotimingsafeequala-b
|
|
88
|
+
*/
|
|
89
|
+
export type TimingSafeEqual = (a: Uint8Array, b: Uint8Array) => boolean;
|
|
90
|
+
export interface TimingSafeEqualDep {
|
|
91
|
+
readonly timingSafeEqual: TimingSafeEqual;
|
|
92
|
+
}
|
|
82
93
|
//# sourceMappingURL=Crypto.d.ts.map
|
package/dist/src/Crypto.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Crypto.d.ts","sourceRoot":"","sources":["../../src/Crypto.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,EAAc,MAAM,EAAW,MAAM,aAAa,CAAC;AAC1D,OAAO,EAEL,EAAE,EAEF,QAAQ,EACR,cAAc,EAEf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,yDAAyD;AACzD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG,CAAC,WAAW,CAAC,EAAE,MAAM,KAAK,WAAW,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;CAC/C;AAED,oFAAoF;AACpF,eAAO,MAAM,iBAAiB,EAAE,iBACS,CAAC;AAE1C,MAAM,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC;AAE5C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;CACzC;AAED,eAAO,MAAM,qBAAqB,EAAE,cACe,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;AAE9D,eAAO,MAAM,sBAAsB,GAAI,UAAU,QAAQ,KAAG,YACR,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,YAAY,EAClB,MAAM,aAAa,CAAC,MAAM,CAAC,KAC1B,UAUF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,YAAY,EAClB,MAAM,aAAa,CAAC,MAAM,CAAC,KAC1B,EAUF,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,aAAa,8fAAiD,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAC;AAEtD,eAAO,MAAM,mBAAmB,GAAI,MAAM,YAAY,KAAG,aACS,CAAC;AAEnE,8BAA8B;AAC9B,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IAErC,QAAQ,CAAC,OAAO,EAAE,CAChB,SAAS,EAAE,UAAU,EACrB,aAAa,EAAE,aAAa,KACzB;QACH,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;QAC3B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;KACjC,CAAC;IAEF,QAAQ,CAAC,OAAO,EAAE,CAChB,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,UAAU,KACd,MAAM,CAAC,UAAU,EAAE,2BAA2B,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;CAC3C;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,6BAA6B,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAChC,MAAM,oBAAoB,KACzB,eAyBF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,cAAc,KAAG,cAO1D,CAAC;AAEF;;;GAGG;AAEH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,cAAc,KAAG,cAE3D,CAAC"}
|
|
1
|
+
{"version":3,"file":"Crypto.d.ts","sourceRoot":"","sources":["../../src/Crypto.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,EAAc,MAAM,EAAW,MAAM,aAAa,CAAC;AAC1D,OAAO,EAEL,EAAE,EAEF,QAAQ,EACR,cAAc,EAEf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,yDAAyD;AACzD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG,CAAC,WAAW,CAAC,EAAE,MAAM,KAAK,WAAW,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;CAC/C;AAED,oFAAoF;AACpF,eAAO,MAAM,iBAAiB,EAAE,iBACS,CAAC;AAE1C,MAAM,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC;AAE5C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;CACzC;AAED,eAAO,MAAM,qBAAqB,EAAE,cACe,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;AAE9D,eAAO,MAAM,sBAAsB,GAAI,UAAU,QAAQ,KAAG,YACR,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,YAAY,EAClB,MAAM,aAAa,CAAC,MAAM,CAAC,KAC1B,UAUF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,YAAY,EAClB,MAAM,aAAa,CAAC,MAAM,CAAC,KAC1B,EAUF,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,aAAa,8fAAiD,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAC;AAEtD,eAAO,MAAM,mBAAmB,GAAI,MAAM,YAAY,KAAG,aACS,CAAC;AAEnE,8BAA8B;AAC9B,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IAErC,QAAQ,CAAC,OAAO,EAAE,CAChB,SAAS,EAAE,UAAU,EACrB,aAAa,EAAE,aAAa,KACzB;QACH,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;QAC3B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;KACjC,CAAC;IAEF,QAAQ,CAAC,OAAO,EAAE,CAChB,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,UAAU,KACd,MAAM,CAAC,UAAU,EAAE,2BAA2B,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;CAC3C;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,6BAA6B,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAChC,MAAM,oBAAoB,KACzB,eAyBF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,cAAc,KAAG,cAO1D,CAAC;AAEF;;;GAGG;AAEH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,cAAc,KAAG,cAE3D,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,KAAK,OAAO,CAAC;AAExE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;CAC3C"}
|
|
@@ -3,9 +3,12 @@ import { Mnemonic, SimpleName } from "../Type.js";
|
|
|
3
3
|
import type { DbIndexesBuilder } from "./Kysely.js";
|
|
4
4
|
export interface Config extends ConsoleConfig {
|
|
5
5
|
/**
|
|
6
|
-
* The name of Evolu
|
|
7
|
-
* instances concurrently.
|
|
8
|
-
*
|
|
6
|
+
* The name of the Evolu instance. Evolu is multitenant - it can run multiple
|
|
7
|
+
* instances concurrently. Each instance must have a unique name.
|
|
8
|
+
*
|
|
9
|
+
* The instance name is used as the SQLite database filename for persistent
|
|
10
|
+
* storage, ensuring that database files are separated and invisible to each
|
|
11
|
+
* other.
|
|
9
12
|
*
|
|
10
13
|
* The default value is: `Evolu`.
|
|
11
14
|
*
|
|
@@ -19,7 +22,7 @@ export interface Config extends ConsoleConfig {
|
|
|
19
22
|
/**
|
|
20
23
|
* URL for Evolu sync and backup server.
|
|
21
24
|
*
|
|
22
|
-
* The default value is `
|
|
25
|
+
* The default value is `wss://free.evoluhq.com`.
|
|
23
26
|
*/
|
|
24
27
|
readonly syncUrl: string;
|
|
25
28
|
/**
|
|
@@ -61,6 +64,16 @@ export interface Config extends ConsoleConfig {
|
|
|
61
64
|
* until special UX requirements are needed (e.g., multitenancy).
|
|
62
65
|
*/
|
|
63
66
|
readonly mnemonic?: Mnemonic;
|
|
67
|
+
/**
|
|
68
|
+
* Use in-memory SQLite database instead of persistent storage. Useful for
|
|
69
|
+
* testing or temporary data that doesn't need persistence.
|
|
70
|
+
*
|
|
71
|
+
* In-memory databases exist only in RAM and are completely destroyed when
|
|
72
|
+
* the process ends, making them forensically safe for sensitive data.
|
|
73
|
+
*
|
|
74
|
+
* The default value is: `false`.
|
|
75
|
+
*/
|
|
76
|
+
readonly inMemory?: boolean;
|
|
64
77
|
}
|
|
65
78
|
export interface ConfigDep {
|
|
66
79
|
readonly config: Config;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Config.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,MAAO,SAAQ,aAAa;IAC3C
|
|
1
|
+
{"version":3,"file":"Config.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,MAAO,SAAQ,aAAa;IAC3C;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAEpC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAE7B;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,aAAa,EAAE,MAM3B,CAAC"}
|
package/dist/src/Evolu/Config.js
CHANGED
|
@@ -2,7 +2,7 @@ import { getOrThrow } from "../Result.js";
|
|
|
2
2
|
import { SimpleName } from "../Type.js";
|
|
3
3
|
export const defaultConfig = {
|
|
4
4
|
name: getOrThrow(SimpleName.fromParent("Evolu")),
|
|
5
|
-
syncUrl: "
|
|
5
|
+
syncUrl: "wss://free.evoluhq.com",
|
|
6
6
|
reloadUrl: "/",
|
|
7
7
|
maxDrift: 5 * 60 * 1000,
|
|
8
8
|
enableLogging: false,
|
package/dist/src/Evolu/Db.d.ts
CHANGED
|
@@ -14,24 +14,32 @@ import { Worker } from "../Worker.js";
|
|
|
14
14
|
import { Config } from "./Config.js";
|
|
15
15
|
import { QueryPatches } from "./Diff.js";
|
|
16
16
|
import { AppOwner, OwnerRow } from "./Owner.js";
|
|
17
|
-
import {
|
|
17
|
+
import { BinaryOwnerId, CrdtMessage, DbChange, ProtocolError, Storage } from "./Protocol.js";
|
|
18
18
|
import { Query } from "./Query.js";
|
|
19
19
|
import { SqliteStorageBase } from "./Storage.js";
|
|
20
20
|
import { CreateSyncDep } from "./Sync.js";
|
|
21
21
|
import { Timestamp, TimestampError } from "./Timestamp.js";
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
export
|
|
27
|
-
readonly name: Base64Url256;
|
|
28
|
-
readonly columns: ReadonlyArray<Base64Url256>;
|
|
29
|
-
}
|
|
22
|
+
export declare const DbTable: import("../Type.js").ObjectType<{
|
|
23
|
+
name: import("../Type.js").BrandType<import("../Type.js").Type<"Brand", string & import("../Types.js").Brand<"Base64Url">, string, import("../Type.js").RegexError<"Base64Url">, string, import("../Type.js").StringError>, "MaxLength256", import("../Type.js").MaxLengthError<256>, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">>;
|
|
24
|
+
columns: import("../Type.js").ArrayType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", string & import("../Types.js").Brand<"Base64Url">, string, import("../Type.js").RegexError<"Base64Url">, string, import("../Type.js").StringError>, "MaxLength256", import("../Type.js").MaxLengthError<256>, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">>>;
|
|
25
|
+
}>;
|
|
26
|
+
export type DbTable = typeof DbTable.Type;
|
|
30
27
|
export declare const DbIndex: import("../Type.js").ObjectType<{
|
|
31
28
|
name: import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
32
29
|
sql: import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
33
30
|
}>;
|
|
34
31
|
export type DbIndex = typeof DbIndex.Type;
|
|
32
|
+
export declare const DbSchema: import("../Type.js").ObjectType<{
|
|
33
|
+
tables: import("../Type.js").ArrayType<import("../Type.js").ObjectType<{
|
|
34
|
+
name: import("../Type.js").BrandType<import("../Type.js").Type<"Brand", string & import("../Types.js").Brand<"Base64Url">, string, import("../Type.js").RegexError<"Base64Url">, string, import("../Type.js").StringError>, "MaxLength256", import("../Type.js").MaxLengthError<256>, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">>;
|
|
35
|
+
columns: import("../Type.js").ArrayType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", string & import("../Types.js").Brand<"Base64Url">, string, import("../Type.js").RegexError<"Base64Url">, string, import("../Type.js").StringError>, "MaxLength256", import("../Type.js").MaxLengthError<256>, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">>>;
|
|
36
|
+
}>>;
|
|
37
|
+
indexes: import("../Type.js").ArrayType<import("../Type.js").ObjectType<{
|
|
38
|
+
name: import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
39
|
+
sql: import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
40
|
+
}>>;
|
|
41
|
+
}>;
|
|
42
|
+
export type DbSchema = typeof DbSchema.Type;
|
|
35
43
|
export type DbWorker = Worker<DbWorkerInput, DbWorkerOutput>;
|
|
36
44
|
export type CreateDbWorker = (name: SimpleName) => DbWorker;
|
|
37
45
|
export interface CreateDbWorkerDep {
|
|
@@ -105,14 +113,14 @@ export declare const getDbSchema: (deps: SqliteDep) => ({ allIndexes }?: {
|
|
|
105
113
|
}) => Result<DbSchema, SqliteError>;
|
|
106
114
|
export interface DbSnapshot {
|
|
107
115
|
readonly schema: DbSchema;
|
|
108
|
-
readonly
|
|
109
|
-
rows: ReadonlyArray<SqliteRow>;
|
|
116
|
+
readonly tables: Array<{
|
|
110
117
|
name: string;
|
|
118
|
+
rows: ReadonlyArray<SqliteRow>;
|
|
111
119
|
}>;
|
|
112
120
|
}
|
|
113
|
-
export declare const getDbSnapshot: (deps: SqliteDep) =>
|
|
121
|
+
export declare const getDbSnapshot: (deps: SqliteDep) => DbSnapshot;
|
|
114
122
|
export declare const createAppTable: (tableName: string, columns: ReadonlyArray<string>) => SafeSql;
|
|
115
|
-
export declare const applyMessageToTimestampAndHistoryTables: (deps: SqliteDep &
|
|
123
|
+
export declare const applyMessageToTimestampAndHistoryTables: (deps: SqliteDep & ClientStorageDep) => (ownerId: BinaryOwnerId, message: CrdtMessage) => Result<void, SqliteError>;
|
|
116
124
|
export declare const maybeMigrateToVersion0: (deps: SqliteDep) => (schema: DbSchema) => Result<{
|
|
117
125
|
readonly messages: ReadonlyArray<CrdtMessage>;
|
|
118
126
|
readonly mnemonic: Mnemonic;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Db.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Db.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,qBAAqB,EACtB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EAEpB,2BAA2B,EAE5B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAa,GAAG,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAW,MAAM,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAEL,qBAAqB,EAErB,OAAO,EAEP,SAAS,EACT,WAAW,EAEX,SAAS,EAEV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,
|
|
1
|
+
{"version":3,"file":"Db.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Db.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Evolu/Db.js
CHANGED
|
@@ -7,15 +7,23 @@ import { objectToEntries } from "../Object.js";
|
|
|
7
7
|
import { createRef } from "../Ref.js";
|
|
8
8
|
import { err, ok } from "../Result.js";
|
|
9
9
|
import { createSqlite, explainSqliteQueryPlan, sql, } from "../Sqlite.js";
|
|
10
|
-
import { object, String } from "../Type.js";
|
|
10
|
+
import { array, object, String } from "../Type.js";
|
|
11
11
|
import { createInitializedWorker, } from "../Worker.js";
|
|
12
12
|
import { makePatches } from "./Diff.js";
|
|
13
13
|
import { createAppOwner, createOwnerRow, } from "./Owner.js";
|
|
14
|
-
import { applyProtocolMessageAsClient, binaryIdToId, createProtocolMessageForSync, createProtocolMessageFromCrdtMessages, decryptAndDecodeDbChange, encodeAndEncryptDbChange, idToBinaryId, ownerIdToBinaryOwnerId, protocolVersion, } from "./Protocol.js";
|
|
14
|
+
import { applyProtocolMessageAsClient, Base64Url256, binaryIdToId, createProtocolMessageForSync, createProtocolMessageFromCrdtMessages, decryptAndDecodeDbChange, encodeAndEncryptDbChange, idToBinaryId, ownerIdToBinaryOwnerId, protocolVersion, } from "./Protocol.js";
|
|
15
15
|
import { createQueryRowsCache, deserializeQuery, emptyRows, } from "./Query.js";
|
|
16
16
|
import { createSqliteStorageBase, } from "./Storage.js";
|
|
17
17
|
import { Millis, receiveTimestamp, sendTimestamp, timestampStringToTimestamp, timestampToBinaryTimestamp, timestampToTimestampString, } from "./Timestamp.js";
|
|
18
|
+
export const DbTable = object({
|
|
19
|
+
name: Base64Url256,
|
|
20
|
+
columns: array(Base64Url256),
|
|
21
|
+
});
|
|
18
22
|
export const DbIndex = object({ name: String, sql: String });
|
|
23
|
+
export const DbSchema = object({
|
|
24
|
+
tables: array(DbTable),
|
|
25
|
+
indexes: array(DbIndex),
|
|
26
|
+
});
|
|
19
27
|
export const createDbWorkerForPlatform = (platformDeps) => {
|
|
20
28
|
const tabQueryRowsCacheMap = new Map();
|
|
21
29
|
const getQueryRowsCache = (tabId) => {
|
|
@@ -29,7 +37,7 @@ export const createDbWorkerForPlatform = (platformDeps) => {
|
|
|
29
37
|
return createInitializedWorker({
|
|
30
38
|
init: async (initMessage, postMessage, safeHandler) => {
|
|
31
39
|
platformDeps.console.enabled = initMessage.config.enableLogging ?? false;
|
|
32
|
-
const sqliteResult = await createSqlite(platformDeps)(initMessage.config.name);
|
|
40
|
+
const sqliteResult = await createSqlite(platformDeps)(initMessage.config.name, { memory: initMessage.config.inMemory ?? false });
|
|
33
41
|
if (!sqliteResult.ok) {
|
|
34
42
|
postMessage({ type: "onError", error: sqliteResult.error });
|
|
35
43
|
return null;
|
|
@@ -232,7 +240,6 @@ export const createDbWorkerForPlatform = (platformDeps) => {
|
|
|
232
240
|
onCompleteId: message.onCompleteId,
|
|
233
241
|
reload: message.reload,
|
|
234
242
|
});
|
|
235
|
-
deps.sqlite[Symbol.dispose]();
|
|
236
243
|
break;
|
|
237
244
|
}
|
|
238
245
|
case "ensureDbSchema": {
|
|
@@ -324,24 +331,22 @@ export const getDbSchema = (deps) => ({ allIndexes = false } = {}) => {
|
|
|
324
331
|
return ok({ tables, indexes });
|
|
325
332
|
};
|
|
326
333
|
const indexesAreEqual = (self, that) => self.name === that.name && self.sql === that.sql;
|
|
327
|
-
// TODO: Move
|
|
334
|
+
// TODO: Move to test helpers.
|
|
328
335
|
export const getDbSnapshot = (deps) => {
|
|
329
336
|
const schema = getDbSchema(deps)({ allIndexes: true });
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const rows = [];
|
|
337
|
+
assert(schema.ok, "bug");
|
|
338
|
+
const tables = [];
|
|
333
339
|
for (const table of schema.value.tables) {
|
|
334
340
|
const result = deps.sqlite.exec(sql `
|
|
335
341
|
select * from ${sql.identifier(table.name)};
|
|
336
342
|
`);
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
rows.push({
|
|
340
|
-
rows: result.value.rows,
|
|
343
|
+
assert(result.ok, "bug");
|
|
344
|
+
tables.push({
|
|
341
345
|
name: table.name,
|
|
346
|
+
rows: result.value.rows,
|
|
342
347
|
});
|
|
343
348
|
}
|
|
344
|
-
return
|
|
349
|
+
return { schema: schema.value, tables };
|
|
345
350
|
};
|
|
346
351
|
const ensureDbSchema = (deps) => (newSchema, currentSchema, options) => {
|
|
347
352
|
const queries = [];
|
|
@@ -434,39 +439,37 @@ const initializeDb = (deps) => (mnemonic) => {
|
|
|
434
439
|
values ('protocolVersion', ${protocolVersion});
|
|
435
440
|
`,
|
|
436
441
|
/**
|
|
437
|
-
* The History table stores all values per timestamp, table,
|
|
438
|
-
* column
|
|
439
|
-
*
|
|
440
|
-
*
|
|
441
|
-
*
|
|
442
|
-
* and DbChange to leverage a covering index. Hence, every value change
|
|
443
|
-
* has its timestamp, table, row, and column. In the future, we will
|
|
444
|
-
* rethink that and store history more efficiently.
|
|
445
|
-
*
|
|
446
|
-
* There is no need to use `OwnerId` on the client, because timestamps
|
|
447
|
-
* (which include a `NodeId`) are globally unique. The relay needs
|
|
448
|
-
* `OwnerId` because it hosts multiple apps/owners, but client storage
|
|
449
|
-
* represents one DB, and even when it hosts multiple owners, their
|
|
450
|
-
* timestamps remain unique.
|
|
442
|
+
* The History table stores all values per ownerId, timestamp, table, id,
|
|
443
|
+
* and column for conflict-free merging using last-write-win CRDT.
|
|
444
|
+
* Denormalizes Timestamp and DbChange for covering index performance.
|
|
445
|
+
* Time travel is available when last-write-win isn't desired. Future
|
|
446
|
+
* optimization will store history more efficiently.
|
|
451
447
|
*/
|
|
452
448
|
sql `
|
|
453
449
|
create table evolu_history (
|
|
454
|
-
"
|
|
450
|
+
"ownerId" blob not null,
|
|
455
451
|
"table" text not null,
|
|
456
|
-
"
|
|
452
|
+
"id" blob not null,
|
|
457
453
|
"column" text not null,
|
|
454
|
+
"timestamp" blob not null,
|
|
458
455
|
"value" any
|
|
459
456
|
)
|
|
460
457
|
strict;
|
|
461
458
|
`,
|
|
459
|
+
// Index for reading database changes by owner and timestamp.
|
|
460
|
+
// Timestamp always corresponds to a DbChange.
|
|
462
461
|
sql `
|
|
463
|
-
create index
|
|
462
|
+
create index evolu_history_ownerId_timestamp on evolu_history (
|
|
463
|
+
"ownerId",
|
|
464
|
+
"timestamp"
|
|
465
|
+
);
|
|
464
466
|
`,
|
|
465
467
|
sql `
|
|
466
|
-
create unique index
|
|
467
|
-
"
|
|
468
|
-
"column",
|
|
468
|
+
create unique index evolu_history_ownerId_table_id_column_timestampDesc on evolu_history (
|
|
469
|
+
"ownerId",
|
|
469
470
|
"table",
|
|
471
|
+
"id",
|
|
472
|
+
"column",
|
|
470
473
|
"timestamp" desc
|
|
471
474
|
);
|
|
472
475
|
`,
|
|
@@ -490,7 +493,14 @@ const initializeDb = (deps) => (mnemonic) => {
|
|
|
490
493
|
const ownerRow = createOwnerRow(deps)(appOwner);
|
|
491
494
|
const result = deps.sqlite.exec(sql `
|
|
492
495
|
insert into evolu_owner
|
|
493
|
-
(
|
|
496
|
+
(
|
|
497
|
+
"mnemonic",
|
|
498
|
+
"id",
|
|
499
|
+
"encryptionKey",
|
|
500
|
+
"createdAt",
|
|
501
|
+
"writeKey",
|
|
502
|
+
"timestamp"
|
|
503
|
+
)
|
|
494
504
|
values
|
|
495
505
|
(
|
|
496
506
|
${ownerRow.mnemonic},
|
|
@@ -523,16 +533,15 @@ const applyChanges = (deps) => (changes, onChange) => {
|
|
|
523
533
|
assertNonEmptyReadonlyArray(messages);
|
|
524
534
|
return ok(messages);
|
|
525
535
|
};
|
|
526
|
-
const applyMessages = (deps) => (messages, lastTimestamp
|
|
536
|
+
const applyMessages = (deps) => (messages, lastTimestamp) => {
|
|
537
|
+
const ownerId = ownerIdToBinaryOwnerId(deps.ownerRowRef.get().id);
|
|
527
538
|
for (const message of messages) {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
if (!apply2.ok)
|
|
535
|
-
return apply2;
|
|
539
|
+
const result1 = applyMessageToAppTable(deps)(ownerId, message);
|
|
540
|
+
if (!result1.ok)
|
|
541
|
+
return result1;
|
|
542
|
+
const result2 = applyMessageToTimestampAndHistoryTables(deps)(ownerId, message);
|
|
543
|
+
if (!result2.ok)
|
|
544
|
+
return result2;
|
|
536
545
|
}
|
|
537
546
|
const timestamp = timestampToTimestampString(lastTimestamp);
|
|
538
547
|
deps.ownerRowRef.modify((owner) => ({ ...owner, timestamp }));
|
|
@@ -543,44 +552,44 @@ const applyMessages = (deps) => (messages, lastTimestamp, options = {}) => {
|
|
|
543
552
|
return saveTimestamp;
|
|
544
553
|
return ok();
|
|
545
554
|
};
|
|
546
|
-
const applyMessageToAppTable = (deps) => (message) => {
|
|
555
|
+
const applyMessageToAppTable = (deps) => (ownerId, message) => {
|
|
547
556
|
const date = new Date(message.timestamp.millis).toISOString();
|
|
548
557
|
const timestamp = timestampToBinaryTimestamp(message.timestamp);
|
|
549
558
|
for (const [column, value] of objectToEntries(message.change.values)) {
|
|
550
559
|
const result = deps.sqlite.exec(sql.prepared `
|
|
551
560
|
with
|
|
552
561
|
lastTimestamp as (
|
|
553
|
-
select timestamp
|
|
562
|
+
select "timestamp"
|
|
554
563
|
from evolu_history
|
|
555
564
|
where
|
|
556
|
-
"
|
|
557
|
-
and "column" = ${column}
|
|
565
|
+
"ownerId" = ${ownerId}
|
|
558
566
|
and "table" = ${message.change.table}
|
|
559
|
-
|
|
567
|
+
and "id" = ${message.change.id}
|
|
568
|
+
and "column" = ${column}
|
|
569
|
+
order by "timestamp" desc
|
|
560
570
|
limit 1
|
|
561
571
|
)
|
|
562
572
|
insert into ${sql.identifier(message.change.table)}
|
|
563
573
|
("id", ${sql.identifier(column)}, createdAt, updatedAt)
|
|
564
574
|
select ${message.change.id}, ${value}, ${date}, ${date}
|
|
565
575
|
where
|
|
566
|
-
(select timestamp from lastTimestamp) is null
|
|
567
|
-
or (select timestamp from lastTimestamp) < ${timestamp}
|
|
576
|
+
(select "timestamp" from lastTimestamp) is null
|
|
577
|
+
or (select "timestamp" from lastTimestamp) < ${timestamp}
|
|
568
578
|
on conflict ("id") do update
|
|
569
579
|
set
|
|
570
580
|
${sql.identifier(column)} = ${value},
|
|
571
581
|
updatedAt = ${date}
|
|
572
582
|
where
|
|
573
|
-
(select timestamp from lastTimestamp) is null
|
|
574
|
-
or (select timestamp from lastTimestamp) < ${timestamp};
|
|
583
|
+
(select "timestamp" from lastTimestamp) is null
|
|
584
|
+
or (select "timestamp" from lastTimestamp) < ${timestamp};
|
|
575
585
|
`);
|
|
576
586
|
if (!result.ok)
|
|
577
587
|
return result;
|
|
578
588
|
}
|
|
579
589
|
return ok();
|
|
580
590
|
};
|
|
581
|
-
export const applyMessageToTimestampAndHistoryTables = (deps) => (message) => {
|
|
591
|
+
export const applyMessageToTimestampAndHistoryTables = (deps) => (ownerId, message) => {
|
|
582
592
|
const timestamp = timestampToBinaryTimestamp(message.timestamp);
|
|
583
|
-
const ownerId = ownerIdToBinaryOwnerId(deps.ownerRowRef.get().id);
|
|
584
593
|
const id = idToBinaryId(message.change.id);
|
|
585
594
|
const result = deps.storage.insertTimestamp(ownerId, timestamp);
|
|
586
595
|
if (!result.ok)
|
|
@@ -588,9 +597,16 @@ export const applyMessageToTimestampAndHistoryTables = (deps) => (message) => {
|
|
|
588
597
|
for (const [column, value] of Object.entries(message.change.values)) {
|
|
589
598
|
const result = deps.sqlite.exec(sql.prepared `
|
|
590
599
|
insert into evolu_history
|
|
591
|
-
("
|
|
600
|
+
("ownerId", "table", "id", "column", "value", "timestamp")
|
|
592
601
|
values
|
|
593
|
-
(
|
|
602
|
+
(
|
|
603
|
+
${ownerId},
|
|
604
|
+
${message.change.table},
|
|
605
|
+
${id},
|
|
606
|
+
${column},
|
|
607
|
+
${value},
|
|
608
|
+
${timestamp}
|
|
609
|
+
)
|
|
594
610
|
on conflict do nothing;
|
|
595
611
|
`);
|
|
596
612
|
if (!result.ok)
|
|
@@ -631,7 +647,7 @@ export const maybeMigrateToVersion0 = (deps) => (schema) => {
|
|
|
631
647
|
if (!mnemonicAndLastTimestamp.ok)
|
|
632
648
|
return mnemonicAndLastTimestamp;
|
|
633
649
|
const messagesRows = deps.sqlite.exec(sql `
|
|
634
|
-
select "timestamp", "table", "
|
|
650
|
+
select "timestamp", "table", "id", "column", "value" from evolu_message;
|
|
635
651
|
`);
|
|
636
652
|
if (!messagesRows.ok)
|
|
637
653
|
return messagesRows;
|
|
@@ -646,7 +662,7 @@ export const maybeMigrateToVersion0 = (deps) => (schema) => {
|
|
|
646
662
|
const messages = messagesRows.value.rows.map((message) => ({
|
|
647
663
|
timestamp: timestampStringToTimestamp(message.timestamp),
|
|
648
664
|
change: {
|
|
649
|
-
id: message.
|
|
665
|
+
id: message.id,
|
|
650
666
|
table: message.table,
|
|
651
667
|
values: { [message.column]: message.value },
|
|
652
668
|
},
|
|
@@ -704,6 +720,7 @@ const createClientStorage = (deps) => (options) => {
|
|
|
704
720
|
const storage = {
|
|
705
721
|
...sqliteStorageBase.value,
|
|
706
722
|
validateWriteKey: constFalse,
|
|
723
|
+
setWriteKey: constFalse,
|
|
707
724
|
writeMessages: (_ownerId, messages) => {
|
|
708
725
|
// TODO: Get owner by _ownerId when we support more.
|
|
709
726
|
const owner = deps.ownerRowRef.get();
|
|
@@ -742,11 +759,11 @@ const createClientStorage = (deps) => (options) => {
|
|
|
742
759
|
deps.postMessage({ type: "onReceive" });
|
|
743
760
|
return true;
|
|
744
761
|
},
|
|
745
|
-
readDbChange: (
|
|
762
|
+
readDbChange: (ownerId, timestamp) => {
|
|
746
763
|
const result = deps.sqlite.exec(sql `
|
|
747
|
-
select "table", "
|
|
764
|
+
select "table", "id", "column", "value"
|
|
748
765
|
from evolu_history
|
|
749
|
-
where "timestamp" = ${timestamp};
|
|
766
|
+
where "ownerId" = ${ownerId} and "timestamp" = ${timestamp};
|
|
750
767
|
`);
|
|
751
768
|
if (!result.ok) {
|
|
752
769
|
deps.postMessage({ type: "onError", error: result.error });
|
|
@@ -754,16 +771,16 @@ const createClientStorage = (deps) => (options) => {
|
|
|
754
771
|
}
|
|
755
772
|
const { rows } = result.value;
|
|
756
773
|
assert(rows.length > 0, "Rows must not be empty");
|
|
757
|
-
const { table,
|
|
774
|
+
const { table, id } = rows[0];
|
|
758
775
|
const values = {};
|
|
759
776
|
for (const r of rows) {
|
|
760
777
|
assert(r.table === table, "All rows must have the same table");
|
|
761
|
-
assert(eqArrayNumber(r.
|
|
778
|
+
assert(eqArrayNumber(r.id, id), "All rows must have the same Id");
|
|
762
779
|
values[r.column] = r.value;
|
|
763
780
|
}
|
|
764
781
|
const change = {
|
|
765
782
|
table: rows[0].table,
|
|
766
|
-
id: binaryIdToId(rows[0].
|
|
783
|
+
id: binaryIdToId(rows[0].id),
|
|
767
784
|
values,
|
|
768
785
|
};
|
|
769
786
|
const { encryptionKey } = deps.ownerRowRef.get();
|
|
@@ -12,7 +12,7 @@ import { AppOwner } from "./Owner.js";
|
|
|
12
12
|
import { CreateAppStateDep, FlushSyncDep } from "./Platform.js";
|
|
13
13
|
import { ProtocolError, ProtocolUnsupportedVersionError } from "./Protocol.js";
|
|
14
14
|
import { Queries, QueriesToQueryRowsPromises, Query, QueryRows, Row } from "./Query.js";
|
|
15
|
-
import { CreateQuery, EvoluSchema, Mutation } from "./Schema.js";
|
|
15
|
+
import { CreateQuery, EvoluSchema, Mutation, ValidateSchema } from "./Schema.js";
|
|
16
16
|
import { SyncState } from "./Sync.js";
|
|
17
17
|
import { TimestampError } from "./Timestamp.js";
|
|
18
18
|
export interface Evolu<S extends EvoluSchema = EvoluSchema> {
|
|
@@ -40,7 +40,7 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> {
|
|
|
40
40
|
* All this function does is compile the Kysely query and serialize it into a
|
|
41
41
|
* unique string. Both operations are fast and cheap.
|
|
42
42
|
*
|
|
43
|
-
* For mutations, use {@link Evolu
|
|
43
|
+
* For mutations, use {@link Evolu#insert} and {@link Evolu#update}.
|
|
44
44
|
*
|
|
45
45
|
* ### Example
|
|
46
46
|
*
|
|
@@ -62,7 +62,7 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> {
|
|
|
62
62
|
* A returned promise always resolves successfully because there is no reason
|
|
63
63
|
* why loading should fail. All data are local, and the query is typed. A
|
|
64
64
|
* serious unexpected Evolu error shall be handled with
|
|
65
|
-
* {@link Evolu
|
|
65
|
+
* {@link Evolu#subscribeError}.
|
|
66
66
|
*
|
|
67
67
|
* Loading is batched, and returned promises are cached, so there is no need
|
|
68
68
|
* for an additional cache. Evolu's internal cache is invalidated on
|
|
@@ -95,7 +95,7 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> {
|
|
|
95
95
|
* If you are curious why Evolu does not do that for all queries by default,
|
|
96
96
|
* the answer is simple: performance. Tracking changes is costly and
|
|
97
97
|
* meaningful only for visible (hence subscribed) queries anyway. To subscribe
|
|
98
|
-
* to a query, use {@link Evolu
|
|
98
|
+
* to a query, use {@link Evolu#subscribeQuery}.
|
|
99
99
|
*
|
|
100
100
|
* ### Example
|
|
101
101
|
*
|
|
@@ -237,7 +237,7 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> {
|
|
|
237
237
|
}) => Promise<void>;
|
|
238
238
|
/**
|
|
239
239
|
* Restore {@link AppOwner} with all their synced data. It uses
|
|
240
|
-
* {@link Evolu
|
|
240
|
+
* {@link Evolu#resetAppOwner}, so be careful.
|
|
241
241
|
*/
|
|
242
242
|
readonly restoreAppOwner: (mnemonic: Mnemonic, options?: {
|
|
243
243
|
readonly reload?: boolean;
|
|
@@ -329,6 +329,6 @@ export interface EvoluForInitialData<S extends EvoluSchema = EvoluSchema> {
|
|
|
329
329
|
* const evolu = createEvolu(evoluReactDeps)(Schema);
|
|
330
330
|
* ```
|
|
331
331
|
*/
|
|
332
|
-
export declare const createEvolu: (deps: EvoluDeps) => <S extends EvoluSchema>(schema: S
|
|
332
|
+
export declare const createEvolu: (deps: EvoluDeps) => <S extends EvoluSchema>(schema: ValidateSchema<S> extends never ? S : ValidateSchema<S>, partialConfig?: Partial<EvoluConfigWithInitialData<S>>) => Evolu<S>;
|
|
333
333
|
export declare const createNamespaceName: (config: Config) => (name: string) => string;
|
|
334
334
|
//# sourceMappingURL=Evolu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Evolu.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAA0B,WAAW,EAAe,MAAM,cAAc,CAAC;AAChF,OAAO,EAAe,cAAc,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAML,QAAQ,EAET,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAEL,aAAa,EACb,+BAA+B,EAChC,MAAM,eAAe,CAAC;AACvB,OAAO,EAGL,OAAO,EACP,0BAA0B,EAC1B,KAAK,EACL,SAAS,EAET,GAAG,EAGJ,MAAM,YAAY,CAAC;AACpB,OAAO,
|
|
1
|
+
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Evolu.ts"],"names":[],"mappings":"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"}
|