@evolu/common 5.1.4 → 5.2.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/dist/src/Crypto.d.ts +14 -11
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +14 -4
- package/dist/src/Db.d.ts +3 -3
- package/dist/src/Db.d.ts.map +1 -1
- package/dist/src/Db.js +4 -4
- package/dist/src/Evolu.d.ts +26 -5
- package/dist/src/Evolu.d.ts.map +1 -1
- package/dist/src/Evolu.js +16 -9
- package/dist/src/Owner.d.ts +2 -2
- package/dist/src/Owner.d.ts.map +1 -1
- package/dist/src/Owner.js +3 -4
- package/dist/src/Public.d.ts +1 -0
- package/dist/src/Public.d.ts.map +1 -1
- package/dist/src/Public.js +1 -0
- package/package.json +1 -1
- package/src/Crypto.ts +31 -32
- package/src/Db.ts +16 -14
- package/src/Evolu.ts +54 -15
- package/src/Owner.ts +9 -7
- package/src/Public.ts +1 -0
package/dist/src/Crypto.d.ts
CHANGED
|
@@ -4,17 +4,6 @@ import * as Context from "effect/Context";
|
|
|
4
4
|
import * as Effect from "effect/Effect";
|
|
5
5
|
import * as Layer from "effect/Layer";
|
|
6
6
|
import { Id } from "./Model.js";
|
|
7
|
-
declare const Bip39_base: Context.TagClass<Bip39, "Bip39", {
|
|
8
|
-
readonly make: Effect.Effect<Mnemonic>;
|
|
9
|
-
readonly toSeed: (mnemonic: Mnemonic) => Effect.Effect<Uint8Array>;
|
|
10
|
-
readonly parse: (mnemonic: string) => Effect.Effect<Mnemonic, InvalidMnemonicError>;
|
|
11
|
-
}>;
|
|
12
|
-
export declare class Bip39 extends Bip39_base {
|
|
13
|
-
}
|
|
14
|
-
export interface InvalidMnemonicError {
|
|
15
|
-
readonly _tag: "InvalidMnemonicError";
|
|
16
|
-
}
|
|
17
|
-
export declare const validateMnemonicToEffect: (validateMnemonic: (mnemonic: string, wordlist: string[]) => boolean) => (mnemonic: string, wordlist: string[]) => Effect.Effect<Mnemonic, InvalidMnemonicError, never>;
|
|
18
7
|
/**
|
|
19
8
|
* Mnemonic is a password generated by Evolu in BIP39 format.
|
|
20
9
|
*
|
|
@@ -23,6 +12,20 @@ export declare const validateMnemonicToEffect: (validateMnemonic: (mnemonic: str
|
|
|
23
12
|
* provide a human-readable way of storing a private key.
|
|
24
13
|
*/
|
|
25
14
|
export type Mnemonic = string & Brand.Brand<"Mnemonic">;
|
|
15
|
+
/**
|
|
16
|
+
* Mnemonic is a password generated by Evolu in BIP39 format.
|
|
17
|
+
*
|
|
18
|
+
* A mnemonic, also known as a "seed phrase," is a set of 12 words in a specific
|
|
19
|
+
* order chosen from a predefined list. The purpose of the BIP39 mnemonic is to
|
|
20
|
+
* provide a human-readable way of storing a private key.
|
|
21
|
+
*/
|
|
22
|
+
export declare const createMnemonic: () => Mnemonic;
|
|
23
|
+
/** Parse a string to {@link Mnemonic}. */
|
|
24
|
+
export declare const parseMnemonic: (mnemonic: string) => Effect.Effect<Mnemonic, InvalidMnemonicError>;
|
|
25
|
+
export interface InvalidMnemonicError {
|
|
26
|
+
readonly _tag: "InvalidMnemonicError";
|
|
27
|
+
}
|
|
28
|
+
export declare const mnemonicToSeed: (mnemonic: Mnemonic) => Uint8Array;
|
|
26
29
|
declare const NanoIdGenerator_base: Context.TagClass<NanoIdGenerator, "NanoIdGenerator", {
|
|
27
30
|
readonly nanoid: Effect.Effect<NanoId>;
|
|
28
31
|
readonly nodeId: Effect.Effect<NodeId>;
|
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,OAAO,KAAK,CAAC,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"Crypto.d.ts","sourceRoot":"","sources":["../../src/Crypto.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,uBAAuB,CAAC;AAQ3C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAEhC;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,QAAO,QACiB,CAAC;AAEpD,0CAA0C;AAC1C,eAAO,MAAM,aAAa,aACd,MAAM,KACf,OAAO,MAAM,CAAC,QAAQ,EAAE,oBAAoB,CAO9C,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;CACvC;AAED,eAAO,MAAM,cAAc,aAAc,QAAQ,KAAG,UAChB,CAAC;;qBAKhB,OAAO,MAAM,CAAC,MAAM,CAAC;qBACrB,OAAO,MAAM,CAAC,MAAM,CAAC;oBACtB,OAAO,MAAM,CAAC,EAAE,CAAC;;AALrC,qBAAa,eAAgB,SAAQ,oBAOlC;CAAG;AAEN,eAAO,MAAM,yBAAyB,mBACpB,CACd,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,KAC7B,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,UAClC,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,MAAM,KAChC,MAAM,KAAK,CAAC,eAAe,EAAE,KAAK,EAAE,KAAK,CAU3C,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAEpD,eAAO,MAAM,MAAM,8DAGlB,CAAC;AACF,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAC;AAIxC,eAAO,MAAM,YAAY,SACjB,UAAU,QACV,cAAc,MAAM,CAAC,KAC1B,OAAO,MAAM,CAAC,UAAU,CAWvB,CAAC;;mBAKc,CACb,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,UAAU,KAClB,OAAO,MAAM,CAAC,UAAU,CAAC;mBAEf,CACb,GAAG,EAAE,UAAU,EACf,UAAU,EAAE,UAAU,KACnB,OAAO,MAAM,CAAC,UAAU,CAAC;;AAXlC,qBAAa,SAAU,SAAQ,cAa5B;IACD,MAAM,CAAC,IAAI,uCAgBT;CACH"}
|
package/dist/src/Crypto.js
CHANGED
|
@@ -4,19 +4,29 @@ import { concatBytes } from "@noble/ciphers/utils";
|
|
|
4
4
|
import { hmac } from "@noble/hashes/hmac";
|
|
5
5
|
import { sha512 } from "@noble/hashes/sha512";
|
|
6
6
|
import { randomBytes } from "@noble/hashes/utils";
|
|
7
|
+
import * as bip39 from "@scure/bip39";
|
|
8
|
+
import { wordlist } from "@scure/bip39/wordlists/english";
|
|
7
9
|
import * as Context from "effect/Context";
|
|
8
10
|
import * as Effect from "effect/Effect";
|
|
9
11
|
import * as Layer from "effect/Layer";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Mnemonic is a password generated by Evolu in BIP39 format.
|
|
14
|
+
*
|
|
15
|
+
* A mnemonic, also known as a "seed phrase," is a set of 12 words in a specific
|
|
16
|
+
* order chosen from a predefined list. The purpose of the BIP39 mnemonic is to
|
|
17
|
+
* provide a human-readable way of storing a private key.
|
|
18
|
+
*/
|
|
19
|
+
export const createMnemonic = () => bip39.generateMnemonic(wordlist, 128);
|
|
20
|
+
/** Parse a string to {@link Mnemonic}. */
|
|
21
|
+
export const parseMnemonic = (mnemonic) => {
|
|
13
22
|
const mnemonicTrimmed = mnemonic.trim();
|
|
14
|
-
return validateMnemonic(mnemonicTrimmed, wordlist)
|
|
23
|
+
return bip39.validateMnemonic(mnemonicTrimmed, wordlist)
|
|
15
24
|
? Effect.succeed(mnemonicTrimmed)
|
|
16
25
|
: Effect.fail({
|
|
17
26
|
_tag: "InvalidMnemonicError",
|
|
18
27
|
});
|
|
19
28
|
};
|
|
29
|
+
export const mnemonicToSeed = (mnemonic) => bip39.mnemonicToSeedSync(mnemonic);
|
|
20
30
|
export class NanoIdGenerator extends Context.Tag("NanoIdGenerator")() {
|
|
21
31
|
}
|
|
22
32
|
export const createNanoIdGeneratorLive = (customAlphabet, nanoid) => {
|
package/dist/src/Db.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import * as Record from "effect/Record";
|
|
|
6
6
|
import * as Kysely from "kysely";
|
|
7
7
|
import { Config } from "./Config.js";
|
|
8
8
|
import { Millis, Time, TimestampCounterOverflowError, TimestampDriftError, TimestampTimeOutOfRangeError } from "./Crdt.js";
|
|
9
|
-
import {
|
|
9
|
+
import { Mnemonic, NanoIdGenerator } from "./Crypto.js";
|
|
10
10
|
import { QueryPatches } from "./Diff.js";
|
|
11
11
|
import { EvoluError } from "./Error.js";
|
|
12
12
|
import { Id } from "./Model.js";
|
|
@@ -15,7 +15,7 @@ import { SyncLock } from "./Platform.js";
|
|
|
15
15
|
import { Sqlite, SqliteExecResult, SqliteFactory, SqliteQuery, Value } from "./Sqlite.js";
|
|
16
16
|
import { NewMessage, SyncFactory, SyncState } from "./Sync.js";
|
|
17
17
|
export interface Db {
|
|
18
|
-
readonly init: (schema: DbSchema, initialData: ReadonlyArray<Mutation>, onError: Callbacks["onError"], onSyncStateChange: Callbacks["onSyncStateChange"], onReceive: Callbacks["onReceive"]) => Effect.Effect<Owner, NotSupportedPlatformError | TimestampTimeOutOfRangeError | TimestampDriftError | TimestampCounterOverflowError, Config>;
|
|
18
|
+
readonly init: (schema: DbSchema, initialData: ReadonlyArray<Mutation>, onError: Callbacks["onError"], onSyncStateChange: Callbacks["onSyncStateChange"], onReceive: Callbacks["onReceive"], mnemonic: Mnemonic | undefined) => Effect.Effect<Owner, NotSupportedPlatformError | TimestampTimeOutOfRangeError | TimestampDriftError | TimestampCounterOverflowError, Config>;
|
|
19
19
|
readonly loadQueries: (queries: ReadonlyArray<Query>) => Effect.Effect<ReadonlyArray<QueryPatches>>;
|
|
20
20
|
readonly mutate: (mutations: ReadonlyArray<Mutation>, queriesToRefresh: ReadonlyArray<Query>) => Effect.Effect<ReadonlyArray<QueryPatches>, TimestampTimeOutOfRangeError | TimestampDriftError | TimestampCounterOverflowError, Config>;
|
|
21
21
|
readonly resetOwner: () => Effect.Effect<void>;
|
|
@@ -62,7 +62,7 @@ declare const DbFactory_base: Context.TagClass<DbFactory, "DbFactory", {
|
|
|
62
62
|
}>;
|
|
63
63
|
export declare class DbFactory extends DbFactory_base {
|
|
64
64
|
}
|
|
65
|
-
export declare const createDb: Effect.Effect<Db, never, SqliteFactory |
|
|
65
|
+
export declare const createDb: Effect.Effect<Db, never, SqliteFactory | NanoIdGenerator | Time | SyncFactory | SyncLock>;
|
|
66
66
|
export interface Callbacks {
|
|
67
67
|
readonly onError: (error: EvoluError) => void;
|
|
68
68
|
readonly onSyncStateChange: (state: SyncState) => void;
|
package/dist/src/Db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Db.d.ts","sourceRoot":"","sources":["../../src/Db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,uBAAuB,CAAC;AAE3C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAE1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAKxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAKxC,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAEL,MAAM,EACN,IAAI,EAEJ,6BAA6B,EAC7B,mBAAmB,EAEnB,4BAA4B,EAW7B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"Db.d.ts","sourceRoot":"","sources":["../../src/Db.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Db.js
CHANGED
|
@@ -12,7 +12,7 @@ import * as Schedule from "effect/Schedule";
|
|
|
12
12
|
import * as String from "effect/String";
|
|
13
13
|
import * as SynchronizedRef from "effect/SynchronizedRef";
|
|
14
14
|
import { Time, diffMerkleTrees, initialMerkleTree, insertIntoMerkleTree, makeInitialTimestamp, makeSyncTimestamp, merkleTreeToString, receiveTimestamp, sendTimestamp, timestampToString, unsafeTimestampFromString, } from "./Crdt.js";
|
|
15
|
-
import {
|
|
15
|
+
import { NanoIdGenerator } from "./Crypto.js";
|
|
16
16
|
import { makePatches } from "./Diff.js";
|
|
17
17
|
import { ensureTransferableError, makeUnexpectedError, } from "./Error.js";
|
|
18
18
|
import { cast } from "./Model.js";
|
|
@@ -30,19 +30,19 @@ export class DbFactory extends Context.Tag("DbFactory")() {
|
|
|
30
30
|
export const createDb = Effect.gen(function* () {
|
|
31
31
|
const { createSqlite } = yield* SqliteFactory;
|
|
32
32
|
const { createSync } = yield* SyncFactory;
|
|
33
|
-
const initContext = Context.empty().pipe(Context.add(
|
|
33
|
+
const initContext = Context.empty().pipe(Context.add(NanoIdGenerator, yield* NanoIdGenerator), Context.add(Time, yield* Time), Context.add(SyncLock, yield* SyncLock));
|
|
34
34
|
const afterInitContext = yield* Deferred.make();
|
|
35
35
|
const afterInit = (options) => (effect) => Effect.flatMap(Deferred.await(afterInitContext), (context) => Effect.flatMap(Sqlite, (sqlite) => sqlite.transaction(options.transaction)(effect)).pipe(Effect.provide(context)));
|
|
36
36
|
const queryRowsRef = yield* SynchronizedRef.make(new Map());
|
|
37
37
|
const db = {
|
|
38
|
-
init: (schema, initialData, onError, onSyncStateChange, onReceive) => Effect.gen(function* () {
|
|
38
|
+
init: (schema, initialData, onError, onSyncStateChange, onReceive, mnemonic) => Effect.gen(function* () {
|
|
39
39
|
yield* Effect.logDebug(["Db init", { schema }]);
|
|
40
40
|
const sqlite = yield* createSqlite;
|
|
41
41
|
const contextWithSqlite = Context.add(initContext, Sqlite, sqlite);
|
|
42
42
|
const owner = yield* getSchema.pipe(Effect.tap(ensureSchema(schema)), Effect.flatMap((currentSchema) => {
|
|
43
43
|
if (currentSchema.tables.map((t) => t.name).includes("evolu_owner"))
|
|
44
44
|
return readOwner;
|
|
45
|
-
return createOwner().pipe(Effect.tap(applyMutations(initialData)));
|
|
45
|
+
return createOwner(mnemonic).pipe(Effect.tap(applyMutations(initialData)));
|
|
46
46
|
}), sqlite.transaction("exclusive"), Effect.provide(contextWithSqlite));
|
|
47
47
|
const sync = yield* createSync.pipe(Effect.provide(initContext));
|
|
48
48
|
yield* sync.init(owner);
|
package/dist/src/Evolu.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import * as Layer from "effect/Layer";
|
|
|
5
5
|
import * as Record from "effect/Record";
|
|
6
6
|
import * as Kysely from "kysely";
|
|
7
7
|
import { Config } from "./Config.js";
|
|
8
|
+
import { TimestampString } from "./Crdt.js";
|
|
8
9
|
import { Mnemonic, NanoIdGenerator } from "./Crypto.js";
|
|
9
10
|
import { DbFactory, DbSchema, Index, Queries, Query, QueryResult, QueryResultsPromisesFromQueries, Row } from "./Db.js";
|
|
10
11
|
import { EvoluError } from "./Error.js";
|
|
@@ -14,7 +15,6 @@ import { AppState } from "./Platform.js";
|
|
|
14
15
|
import { SqliteQueryOptions, Value } from "./Sqlite.js";
|
|
15
16
|
import { Listener, Unsubscribe } from "./Store.js";
|
|
16
17
|
import { SyncState } from "./Sync.js";
|
|
17
|
-
import { TimestampString } from "./Crdt.js";
|
|
18
18
|
/**
|
|
19
19
|
* The Evolu interface provides a type-safe SQL query building and state
|
|
20
20
|
* management defined by a database schema. It leverages Kysely for creating SQL
|
|
@@ -280,10 +280,25 @@ export interface Evolu<T extends EvoluSchema = EvoluSchema> {
|
|
|
280
280
|
* Delete {@link Owner} and all their data from the current device. After the
|
|
281
281
|
* deletion, Evolu will purge the application state. For browsers, this will
|
|
282
282
|
* reload all tabs using Evolu. For native apps, it will restart the app.
|
|
283
|
+
*
|
|
284
|
+
* Reloading can be turned off via options if you want to provide a different
|
|
285
|
+
* UX.
|
|
286
|
+
*/
|
|
287
|
+
readonly resetOwner: (options?: {
|
|
288
|
+
readonly reload: boolean;
|
|
289
|
+
}) => Promise<void>;
|
|
290
|
+
/**
|
|
291
|
+
* Restore {@link Owner} with all their synced data. It uses {@link resetOwner},
|
|
292
|
+
* so be careful.
|
|
283
293
|
*/
|
|
284
|
-
readonly
|
|
285
|
-
|
|
286
|
-
|
|
294
|
+
readonly restoreOwner: (mnemonic: Mnemonic, options?: {
|
|
295
|
+
readonly reload: boolean;
|
|
296
|
+
}) => Promise<void>;
|
|
297
|
+
/**
|
|
298
|
+
* Reload the app in a platform-specific way. For browsers, this will reload
|
|
299
|
+
* all tabs using Evolu. For native apps, it will restart the app.
|
|
300
|
+
*/
|
|
301
|
+
readonly reloadApp: () => void;
|
|
287
302
|
/**
|
|
288
303
|
* Ensure tables and columns defined in {@link EvoluSchema} exist in the
|
|
289
304
|
* database.
|
|
@@ -359,7 +374,7 @@ export declare class EvoluFactory extends EvoluFactory_base {
|
|
|
359
374
|
}
|
|
360
375
|
export interface EvoluConfig<T extends EvoluSchema = EvoluSchema> extends Config {
|
|
361
376
|
/**
|
|
362
|
-
* Use the `indexes`
|
|
377
|
+
* Use the `indexes` option to define SQLite indexes.
|
|
363
378
|
*
|
|
364
379
|
* Table and column names are not typed because Kysely doesn't support it.
|
|
365
380
|
*
|
|
@@ -377,6 +392,12 @@ export interface EvoluConfig<T extends EvoluSchema = EvoluSchema> extends Config
|
|
|
377
392
|
indexes: ReadonlyArray<Index>;
|
|
378
393
|
/** Use this option to create initial data (fixtures). */
|
|
379
394
|
initialData: (evolu: EvoluForInitialData<T>) => void;
|
|
395
|
+
/**
|
|
396
|
+
* Use this option to create Evolu with the specified mnemonic. If omitted,
|
|
397
|
+
* the mnemonic will be autogenerated. That should be the default behavior
|
|
398
|
+
* until special UX requirements are needed (e.g., multitenancy).
|
|
399
|
+
*/
|
|
400
|
+
mnemonic: Mnemonic;
|
|
380
401
|
}
|
|
381
402
|
interface EvoluForInitialData<T extends EvoluSchema = EvoluSchema> {
|
|
382
403
|
create: Mutate<T, "create">;
|
package/dist/src/Evolu.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../src/Evolu.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,uBAAuB,CAAC;AAG3C,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAKtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,MAAM,EAAgC,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EACL,SAAS,EACT,QAAQ,EACR,KAAK,EAEL,OAAO,EACP,KAAK,EACL,WAAW,EACX,+BAA+B,EAE/B,GAAG,EAMJ,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,UAAU,EAAuB,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAa,MAAM,eAAe,CAAC;AACpD,OAAO,EAEL,kBAAkB,EAClB,KAAK,EAEN,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAa,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAoB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../src/Evolu.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Evolu.js
CHANGED
|
@@ -27,7 +27,7 @@ EvoluFactory.Common = Layer.effect(EvoluFactory, Effect.gen(function* () {
|
|
|
27
27
|
// For hot/live reloading and future Evolu dynamic import.
|
|
28
28
|
const instances = new Map();
|
|
29
29
|
return EvoluFactory.of({
|
|
30
|
-
createEvolu: (schema, { indexes, initialData, ...config } = {}) => {
|
|
30
|
+
createEvolu: (schema, { indexes, initialData, mnemonic, ...config } = {}) => {
|
|
31
31
|
const runtime = createRuntime(config);
|
|
32
32
|
const name = config?.name || defaultConfig.name;
|
|
33
33
|
const dbSchema = {
|
|
@@ -36,7 +36,7 @@ EvoluFactory.Common = Layer.effect(EvoluFactory, Effect.gen(function* () {
|
|
|
36
36
|
};
|
|
37
37
|
let evolu = instances.get(name);
|
|
38
38
|
if (evolu == null) {
|
|
39
|
-
evolu = createEvolu(dbSchema, runtime, initialData).pipe(Effect.provide(context), runtime.runSync);
|
|
39
|
+
evolu = createEvolu(dbSchema, runtime, initialData, mnemonic).pipe(Effect.provide(context), runtime.runSync);
|
|
40
40
|
instances.set(name, evolu);
|
|
41
41
|
}
|
|
42
42
|
else {
|
|
@@ -62,7 +62,7 @@ const getPropertySignatures = (schema) => {
|
|
|
62
62
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
63
63
|
return out;
|
|
64
64
|
};
|
|
65
|
-
const createEvolu = (schema, runtime, initialData) => Effect.gen(function* () {
|
|
65
|
+
const createEvolu = (schema, runtime, initialData, mnemonic) => Effect.gen(function* () {
|
|
66
66
|
yield* Effect.logTrace("EvoluFactory createEvolu");
|
|
67
67
|
const config = yield* Config;
|
|
68
68
|
const dbFactory = yield* DbFactory;
|
|
@@ -100,7 +100,7 @@ const createEvolu = (schema, runtime, initialData) => Effect.gen(function* () {
|
|
|
100
100
|
const sync = ({ refreshQueries }) => () => {
|
|
101
101
|
Effect.flatMap(db.sync(refreshQueries ? [...subscribedQueries.keys()] : []), handlePatches()).pipe(runFork);
|
|
102
102
|
};
|
|
103
|
-
db.init(schema, initialDataAsMutations, handleDbError, handleSyncStateChange, handleDbReceive).pipe(Effect.tap(sync({ refreshQueries: false })), Effect.flatMap(ownerStore.setState), Effect.catchTag("NotSupportedPlatformError", () => Effect.void), // no-op
|
|
103
|
+
db.init(schema, initialDataAsMutations, handleDbError, handleSyncStateChange, handleDbReceive, mnemonic).pipe(Effect.tap(sync({ refreshQueries: false })), Effect.flatMap(ownerStore.setState), Effect.catchTag("NotSupportedPlatformError", () => Effect.void), // no-op
|
|
104
104
|
runFork);
|
|
105
105
|
const appStateReset = yield* appState.init({
|
|
106
106
|
onRequestSync: sync({ refreshQueries: true }),
|
|
@@ -252,11 +252,18 @@ const createEvolu = (schema, runtime, initialData) => Effect.gen(function* () {
|
|
|
252
252
|
create: mutate,
|
|
253
253
|
update: mutate,
|
|
254
254
|
createOrUpdate: mutate,
|
|
255
|
-
resetOwner: () => {
|
|
256
|
-
db.resetOwner()
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
255
|
+
resetOwner: (options) => Effect.gen(function* () {
|
|
256
|
+
yield* db.resetOwner();
|
|
257
|
+
if (options?.reload !== false)
|
|
258
|
+
yield* appStateReset.reset;
|
|
259
|
+
}).pipe(runPromise),
|
|
260
|
+
restoreOwner: (mnemonic, options) => Effect.gen(function* () {
|
|
261
|
+
yield* db.restoreOwner(schema, mnemonic);
|
|
262
|
+
if (options?.reload !== false)
|
|
263
|
+
yield* appStateReset.reset;
|
|
264
|
+
}).pipe(runPromise),
|
|
265
|
+
reloadApp: () => {
|
|
266
|
+
appStateReset.reset.pipe(runFork);
|
|
260
267
|
},
|
|
261
268
|
ensureSchema: (schema) => {
|
|
262
269
|
db.ensureSchema(schema).pipe(runFork);
|
package/dist/src/Owner.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Brand from "effect/Brand";
|
|
2
2
|
import * as Context from "effect/Context";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
|
-
import {
|
|
4
|
+
import { Mnemonic } from "./Crypto.js";
|
|
5
5
|
import { Id } from "./Model.js";
|
|
6
6
|
/**
|
|
7
7
|
* The Owner represents the Evolu database owner, a user. Instead of traditional
|
|
@@ -29,5 +29,5 @@ export declare const Owner: Context.Tag<Owner, Owner>;
|
|
|
29
29
|
* {@link Mnemonic}.
|
|
30
30
|
*/
|
|
31
31
|
export type OwnerId = Id & Brand.Brand<"Owner">;
|
|
32
|
-
export declare const makeOwner: (mnemonic?: Mnemonic) => Effect.Effect<Owner
|
|
32
|
+
export declare const makeOwner: (mnemonic?: Mnemonic) => Effect.Effect<Owner>;
|
|
33
33
|
//# sourceMappingURL=Owner.d.ts.map
|
package/dist/src/Owner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Owner.d.ts","sourceRoot":"","sources":["../../src/Owner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,
|
|
1
|
+
{"version":3,"file":"Owner.d.ts","sourceRoot":"","sources":["../../src/Owner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EACL,QAAQ,EAIT,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAEhC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,KAAK;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE5B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IAErB,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC;CACpC;AAED,eAAO,MAAM,KAAK,2BAAqC,CAAC;AAExD;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAEhD,eAAO,MAAM,SAAS,cAAe,QAAQ,KAAG,OAAO,MAAM,CAAC,KAAK,CAoB/D,CAAC"}
|
package/dist/src/Owner.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import * as Context from "effect/Context";
|
|
2
2
|
import * as Effect from "effect/Effect";
|
|
3
|
-
import {
|
|
3
|
+
import { createMnemonic, mnemonicToSeed, slip21Derive, } from "./Crypto.js";
|
|
4
4
|
export const Owner = Context.GenericTag("Owner");
|
|
5
5
|
export const makeOwner = (mnemonic) => Effect.gen(function* (_) {
|
|
6
|
-
const bip39 = yield* Bip39;
|
|
7
6
|
if (mnemonic == null)
|
|
8
|
-
mnemonic =
|
|
9
|
-
const seed =
|
|
7
|
+
mnemonic = createMnemonic();
|
|
8
|
+
const seed = mnemonicToSeed(mnemonic);
|
|
10
9
|
const id = yield* Effect.map(slip21Derive(seed, ["Evolu", "Owner Id"]), (key) => {
|
|
11
10
|
// convert key to nanoid
|
|
12
11
|
let id = "";
|
package/dist/src/Public.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { sql } from "kysely";
|
|
|
2
2
|
export type { NotNull } from "kysely";
|
|
3
3
|
export { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
|
4
4
|
export type { Timestamp, TimestampError } from "./Crdt.js";
|
|
5
|
+
export { createMnemonic, parseMnemonic } from "./Crypto.js";
|
|
5
6
|
export type { InvalidMnemonicError, Mnemonic } from "./Crypto.js";
|
|
6
7
|
export type { ExtractRow, QueryResult } from "./Db.js";
|
|
7
8
|
export * from "./Error.js";
|
package/dist/src/Public.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Public.d.ts","sourceRoot":"","sources":["../../src/Public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,YAAY,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3D,YAAY,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACvD,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"Public.d.ts","sourceRoot":"","sources":["../../src/Public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,YAAY,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5D,YAAY,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACvD,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/src/Public.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { sql } from "kysely";
|
|
2
2
|
export { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
|
3
|
+
export { createMnemonic, parseMnemonic } from "./Crypto.js";
|
|
3
4
|
export * from "./Error.js";
|
|
4
5
|
export { createIndexes } from "./Evolu.js";
|
|
5
6
|
export * from "./Model.js";
|
package/package.json
CHANGED
package/src/Crypto.ts
CHANGED
|
@@ -4,44 +4,14 @@ import { concatBytes } from "@noble/ciphers/utils";
|
|
|
4
4
|
import { hmac } from "@noble/hashes/hmac";
|
|
5
5
|
import { sha512 } from "@noble/hashes/sha512";
|
|
6
6
|
import { randomBytes } from "@noble/hashes/utils";
|
|
7
|
+
import * as bip39 from "@scure/bip39";
|
|
8
|
+
import { wordlist } from "@scure/bip39/wordlists/english";
|
|
7
9
|
import * as Brand from "effect/Brand";
|
|
8
10
|
import * as Context from "effect/Context";
|
|
9
11
|
import * as Effect from "effect/Effect";
|
|
10
12
|
import * as Layer from "effect/Layer";
|
|
11
|
-
|
|
12
13
|
import { Id } from "./Model.js";
|
|
13
14
|
|
|
14
|
-
export class Bip39 extends Context.Tag("Bip39")<
|
|
15
|
-
Bip39,
|
|
16
|
-
{
|
|
17
|
-
readonly make: Effect.Effect<Mnemonic>;
|
|
18
|
-
|
|
19
|
-
readonly toSeed: (mnemonic: Mnemonic) => Effect.Effect<Uint8Array>;
|
|
20
|
-
|
|
21
|
-
readonly parse: (
|
|
22
|
-
mnemonic: string,
|
|
23
|
-
) => Effect.Effect<Mnemonic, InvalidMnemonicError>;
|
|
24
|
-
}
|
|
25
|
-
>() {}
|
|
26
|
-
|
|
27
|
-
export interface InvalidMnemonicError {
|
|
28
|
-
readonly _tag: "InvalidMnemonicError";
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export const validateMnemonicToEffect =
|
|
32
|
-
(validateMnemonic: (mnemonic: string, wordlist: string[]) => boolean) =>
|
|
33
|
-
(
|
|
34
|
-
mnemonic: string,
|
|
35
|
-
wordlist: string[],
|
|
36
|
-
): Effect.Effect<Mnemonic, InvalidMnemonicError, never> => {
|
|
37
|
-
const mnemonicTrimmed = mnemonic.trim();
|
|
38
|
-
return validateMnemonic(mnemonicTrimmed, wordlist)
|
|
39
|
-
? Effect.succeed(mnemonicTrimmed as Mnemonic)
|
|
40
|
-
: Effect.fail<InvalidMnemonicError>({
|
|
41
|
-
_tag: "InvalidMnemonicError",
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
|
-
|
|
45
15
|
/**
|
|
46
16
|
* Mnemonic is a password generated by Evolu in BIP39 format.
|
|
47
17
|
*
|
|
@@ -51,6 +21,35 @@ export const validateMnemonicToEffect =
|
|
|
51
21
|
*/
|
|
52
22
|
export type Mnemonic = string & Brand.Brand<"Mnemonic">;
|
|
53
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Mnemonic is a password generated by Evolu in BIP39 format.
|
|
26
|
+
*
|
|
27
|
+
* A mnemonic, also known as a "seed phrase," is a set of 12 words in a specific
|
|
28
|
+
* order chosen from a predefined list. The purpose of the BIP39 mnemonic is to
|
|
29
|
+
* provide a human-readable way of storing a private key.
|
|
30
|
+
*/
|
|
31
|
+
export const createMnemonic = (): Mnemonic =>
|
|
32
|
+
bip39.generateMnemonic(wordlist, 128) as Mnemonic;
|
|
33
|
+
|
|
34
|
+
/** Parse a string to {@link Mnemonic}. */
|
|
35
|
+
export const parseMnemonic = (
|
|
36
|
+
mnemonic: string,
|
|
37
|
+
): Effect.Effect<Mnemonic, InvalidMnemonicError> => {
|
|
38
|
+
const mnemonicTrimmed = mnemonic.trim();
|
|
39
|
+
return bip39.validateMnemonic(mnemonicTrimmed, wordlist)
|
|
40
|
+
? Effect.succeed(mnemonicTrimmed as Mnemonic)
|
|
41
|
+
: Effect.fail<InvalidMnemonicError>({
|
|
42
|
+
_tag: "InvalidMnemonicError",
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export interface InvalidMnemonicError {
|
|
47
|
+
readonly _tag: "InvalidMnemonicError";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const mnemonicToSeed = (mnemonic: Mnemonic): Uint8Array =>
|
|
51
|
+
bip39.mnemonicToSeedSync(mnemonic);
|
|
52
|
+
|
|
54
53
|
export class NanoIdGenerator extends Context.Tag("NanoIdGenerator")<
|
|
55
54
|
NanoIdGenerator,
|
|
56
55
|
{
|
package/src/Db.ts
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
timestampToString,
|
|
37
37
|
unsafeTimestampFromString,
|
|
38
38
|
} from "./Crdt.js";
|
|
39
|
-
import {
|
|
39
|
+
import { Mnemonic, NanoIdGenerator } from "./Crypto.js";
|
|
40
40
|
import { QueryPatches, makePatches } from "./Diff.js";
|
|
41
41
|
import {
|
|
42
42
|
EvoluError,
|
|
@@ -77,6 +77,7 @@ export interface Db {
|
|
|
77
77
|
onError: Callbacks["onError"],
|
|
78
78
|
onSyncStateChange: Callbacks["onSyncStateChange"],
|
|
79
79
|
onReceive: Callbacks["onReceive"],
|
|
80
|
+
mnemonic: Mnemonic | undefined,
|
|
80
81
|
) => Effect.Effect<
|
|
81
82
|
Owner,
|
|
82
83
|
| NotSupportedPlatformError
|
|
@@ -174,13 +175,12 @@ export class DbFactory extends Context.Tag("DbFactory")<
|
|
|
174
175
|
export const createDb: Effect.Effect<
|
|
175
176
|
Db,
|
|
176
177
|
never,
|
|
177
|
-
SqliteFactory |
|
|
178
|
+
SqliteFactory | NanoIdGenerator | Time | SyncFactory | SyncLock
|
|
178
179
|
> = Effect.gen(function* () {
|
|
179
180
|
const { createSqlite } = yield* SqliteFactory;
|
|
180
181
|
const { createSync } = yield* SyncFactory;
|
|
181
182
|
|
|
182
183
|
const initContext = Context.empty().pipe(
|
|
183
|
-
Context.add(Bip39, yield* Bip39),
|
|
184
184
|
Context.add(NanoIdGenerator, yield* NanoIdGenerator),
|
|
185
185
|
Context.add(Time, yield* Time),
|
|
186
186
|
Context.add(SyncLock, yield* SyncLock),
|
|
@@ -189,14 +189,7 @@ export const createDb: Effect.Effect<
|
|
|
189
189
|
const afterInitContext =
|
|
190
190
|
yield* Deferred.make<
|
|
191
191
|
Context.Context<
|
|
192
|
-
|
|
|
193
|
-
| NanoIdGenerator
|
|
194
|
-
| Time
|
|
195
|
-
| SyncLock
|
|
196
|
-
| Sqlite
|
|
197
|
-
| Owner
|
|
198
|
-
| Sync
|
|
199
|
-
| Callbacks
|
|
192
|
+
NanoIdGenerator | Time | SyncLock | Sqlite | Owner | Sync | Callbacks
|
|
200
193
|
>
|
|
201
194
|
>();
|
|
202
195
|
|
|
@@ -212,7 +205,14 @@ export const createDb: Effect.Effect<
|
|
|
212
205
|
const queryRowsRef = yield* SynchronizedRef.make<QueryRowsMap>(new Map());
|
|
213
206
|
|
|
214
207
|
const db: Db = {
|
|
215
|
-
init: (
|
|
208
|
+
init: (
|
|
209
|
+
schema,
|
|
210
|
+
initialData,
|
|
211
|
+
onError,
|
|
212
|
+
onSyncStateChange,
|
|
213
|
+
onReceive,
|
|
214
|
+
mnemonic,
|
|
215
|
+
) =>
|
|
216
216
|
Effect.gen(function* () {
|
|
217
217
|
yield* Effect.logDebug(["Db init", { schema }]);
|
|
218
218
|
const sqlite = yield* createSqlite;
|
|
@@ -222,7 +222,9 @@ export const createDb: Effect.Effect<
|
|
|
222
222
|
Effect.flatMap((currentSchema) => {
|
|
223
223
|
if (currentSchema.tables.map((t) => t.name).includes("evolu_owner"))
|
|
224
224
|
return readOwner;
|
|
225
|
-
return createOwner().pipe(
|
|
225
|
+
return createOwner(mnemonic).pipe(
|
|
226
|
+
Effect.tap(applyMutations(initialData)),
|
|
227
|
+
);
|
|
226
228
|
}),
|
|
227
229
|
sqlite.transaction("exclusive"),
|
|
228
230
|
Effect.provide(contextWithSqlite),
|
|
@@ -526,7 +528,7 @@ const readOwner = Effect.logTrace("Db readOwner").pipe(
|
|
|
526
528
|
),
|
|
527
529
|
);
|
|
528
530
|
|
|
529
|
-
const createOwner = (mnemonic
|
|
531
|
+
const createOwner = (mnemonic: Mnemonic | undefined) =>
|
|
530
532
|
Effect.logTrace("Db createOwner").pipe(
|
|
531
533
|
Effect.zipRight(
|
|
532
534
|
Effect.all([makeOwner(mnemonic), Sqlite, makeInitialTimestamp]),
|
package/src/Evolu.ts
CHANGED
|
@@ -13,6 +13,7 @@ import * as Predicate from "effect/Predicate";
|
|
|
13
13
|
import * as Record from "effect/Record";
|
|
14
14
|
import * as Kysely from "kysely";
|
|
15
15
|
import { Config, createRuntime, defaultConfig } from "./Config.js";
|
|
16
|
+
import { TimestampString } from "./Crdt.js";
|
|
16
17
|
import { Mnemonic, NanoIdGenerator } from "./Crypto.js";
|
|
17
18
|
import {
|
|
18
19
|
DbFactory,
|
|
@@ -44,7 +45,6 @@ import {
|
|
|
44
45
|
} from "./Sqlite.js";
|
|
45
46
|
import { Listener, Unsubscribe, makeStore } from "./Store.js";
|
|
46
47
|
import { SyncState, initialSyncState } from "./Sync.js";
|
|
47
|
-
import { TimestampString } from "./Crdt.js";
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* The Evolu interface provides a type-safe SQL query building and state
|
|
@@ -341,11 +341,30 @@ export interface Evolu<T extends EvoluSchema = EvoluSchema> {
|
|
|
341
341
|
* Delete {@link Owner} and all their data from the current device. After the
|
|
342
342
|
* deletion, Evolu will purge the application state. For browsers, this will
|
|
343
343
|
* reload all tabs using Evolu. For native apps, it will restart the app.
|
|
344
|
+
*
|
|
345
|
+
* Reloading can be turned off via options if you want to provide a different
|
|
346
|
+
* UX.
|
|
347
|
+
*/
|
|
348
|
+
readonly resetOwner: (options?: {
|
|
349
|
+
readonly reload: boolean;
|
|
350
|
+
}) => Promise<void>;
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Restore {@link Owner} with all their synced data. It uses {@link resetOwner},
|
|
354
|
+
* so be careful.
|
|
344
355
|
*/
|
|
345
|
-
readonly
|
|
356
|
+
readonly restoreOwner: (
|
|
357
|
+
mnemonic: Mnemonic,
|
|
358
|
+
options?: {
|
|
359
|
+
readonly reload: boolean;
|
|
360
|
+
},
|
|
361
|
+
) => Promise<void>;
|
|
346
362
|
|
|
347
|
-
/**
|
|
348
|
-
|
|
363
|
+
/**
|
|
364
|
+
* Reload the app in a platform-specific way. For browsers, this will reload
|
|
365
|
+
* all tabs using Evolu. For native apps, it will restart the app.
|
|
366
|
+
*/
|
|
367
|
+
readonly reloadApp: () => void;
|
|
349
368
|
|
|
350
369
|
/**
|
|
351
370
|
* Ensure tables and columns defined in {@link EvoluSchema} exist in the
|
|
@@ -485,7 +504,12 @@ export class EvoluFactory extends Context.Tag("EvoluFactory")<
|
|
|
485
504
|
return EvoluFactory.of({
|
|
486
505
|
createEvolu: <T extends EvoluSchema, I>(
|
|
487
506
|
schema: S.Schema<T, I>,
|
|
488
|
-
{
|
|
507
|
+
{
|
|
508
|
+
indexes,
|
|
509
|
+
initialData,
|
|
510
|
+
mnemonic,
|
|
511
|
+
...config
|
|
512
|
+
}: Partial<EvoluConfig<T>> = {},
|
|
489
513
|
): Evolu<T> => {
|
|
490
514
|
const runtime = createRuntime(config);
|
|
491
515
|
const name = config?.name || defaultConfig.name;
|
|
@@ -499,6 +523,7 @@ export class EvoluFactory extends Context.Tag("EvoluFactory")<
|
|
|
499
523
|
dbSchema,
|
|
500
524
|
runtime,
|
|
501
525
|
initialData as EvoluConfig["initialData"],
|
|
526
|
+
mnemonic,
|
|
502
527
|
).pipe(Effect.provide(context), runtime.runSync);
|
|
503
528
|
instances.set(name, evolu);
|
|
504
529
|
} else {
|
|
@@ -514,7 +539,7 @@ export class EvoluFactory extends Context.Tag("EvoluFactory")<
|
|
|
514
539
|
export interface EvoluConfig<T extends EvoluSchema = EvoluSchema>
|
|
515
540
|
extends Config {
|
|
516
541
|
/**
|
|
517
|
-
* Use the `indexes`
|
|
542
|
+
* Use the `indexes` option to define SQLite indexes.
|
|
518
543
|
*
|
|
519
544
|
* Table and column names are not typed because Kysely doesn't support it.
|
|
520
545
|
*
|
|
@@ -533,6 +558,13 @@ export interface EvoluConfig<T extends EvoluSchema = EvoluSchema>
|
|
|
533
558
|
|
|
534
559
|
/** Use this option to create initial data (fixtures). */
|
|
535
560
|
initialData: (evolu: EvoluForInitialData<T>) => void;
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Use this option to create Evolu with the specified mnemonic. If omitted,
|
|
564
|
+
* the mnemonic will be autogenerated. That should be the default behavior
|
|
565
|
+
* until special UX requirements are needed (e.g., multitenancy).
|
|
566
|
+
*/
|
|
567
|
+
mnemonic: Mnemonic;
|
|
536
568
|
}
|
|
537
569
|
|
|
538
570
|
const schemaToTables = (schema: S.Schema<any>) =>
|
|
@@ -565,7 +597,8 @@ const getPropertySignatures = <I extends { [K in keyof A]: any }, A>(
|
|
|
565
597
|
const createEvolu = (
|
|
566
598
|
schema: DbSchema,
|
|
567
599
|
runtime: ManagedRuntime.ManagedRuntime<Config, never>,
|
|
568
|
-
initialData
|
|
600
|
+
initialData: EvoluConfig["initialData"],
|
|
601
|
+
mnemonic: Mnemonic | undefined,
|
|
569
602
|
) =>
|
|
570
603
|
Effect.gen(function* () {
|
|
571
604
|
yield* Effect.logTrace("EvoluFactory createEvolu");
|
|
@@ -640,6 +673,7 @@ const createEvolu = (
|
|
|
640
673
|
handleDbError,
|
|
641
674
|
handleSyncStateChange,
|
|
642
675
|
handleDbReceive,
|
|
676
|
+
mnemonic,
|
|
643
677
|
).pipe(
|
|
644
678
|
Effect.tap(sync({ refreshQueries: false })),
|
|
645
679
|
Effect.flatMap(ownerStore.setState),
|
|
@@ -861,15 +895,20 @@ const createEvolu = (
|
|
|
861
895
|
update: mutate,
|
|
862
896
|
createOrUpdate: mutate as Mutate<EvoluSchema, "createOrUpdate">,
|
|
863
897
|
|
|
864
|
-
resetOwner: () =>
|
|
865
|
-
|
|
866
|
-
|
|
898
|
+
resetOwner: (options) =>
|
|
899
|
+
Effect.gen(function* () {
|
|
900
|
+
yield* db.resetOwner();
|
|
901
|
+
if (options?.reload !== false) yield* appStateReset.reset;
|
|
902
|
+
}).pipe(runPromise),
|
|
867
903
|
|
|
868
|
-
restoreOwner: (mnemonic) =>
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
)
|
|
904
|
+
restoreOwner: (mnemonic, options) =>
|
|
905
|
+
Effect.gen(function* () {
|
|
906
|
+
yield* db.restoreOwner(schema, mnemonic);
|
|
907
|
+
if (options?.reload !== false) yield* appStateReset.reset;
|
|
908
|
+
}).pipe(runPromise),
|
|
909
|
+
|
|
910
|
+
reloadApp: () => {
|
|
911
|
+
appStateReset.reset.pipe(runFork);
|
|
873
912
|
},
|
|
874
913
|
|
|
875
914
|
ensureSchema: (schema) => {
|
package/src/Owner.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import * as Brand from "effect/Brand";
|
|
2
2
|
import * as Context from "effect/Context";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
Mnemonic,
|
|
6
|
+
createMnemonic,
|
|
7
|
+
mnemonicToSeed,
|
|
8
|
+
slip21Derive,
|
|
9
|
+
} from "./Crypto.js";
|
|
5
10
|
import { Id } from "./Model.js";
|
|
6
11
|
|
|
7
12
|
/**
|
|
@@ -35,13 +40,10 @@ export const Owner = Context.GenericTag<Owner>("Owner");
|
|
|
35
40
|
*/
|
|
36
41
|
export type OwnerId = Id & Brand.Brand<"Owner">;
|
|
37
42
|
|
|
38
|
-
export const makeOwner = (
|
|
39
|
-
mnemonic?: Mnemonic,
|
|
40
|
-
): Effect.Effect<Owner, never, Bip39> =>
|
|
43
|
+
export const makeOwner = (mnemonic?: Mnemonic): Effect.Effect<Owner> =>
|
|
41
44
|
Effect.gen(function* (_) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const seed = yield* bip39.toSeed(mnemonic);
|
|
45
|
+
if (mnemonic == null) mnemonic = createMnemonic();
|
|
46
|
+
const seed = mnemonicToSeed(mnemonic);
|
|
45
47
|
const id = yield* Effect.map(
|
|
46
48
|
slip21Derive(seed, ["Evolu", "Owner Id"]),
|
|
47
49
|
(key) => {
|
package/src/Public.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { sql } from "kysely";
|
|
|
2
2
|
export type { NotNull } from "kysely";
|
|
3
3
|
export { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
|
4
4
|
export type { Timestamp, TimestampError } from "./Crdt.js";
|
|
5
|
+
export { createMnemonic, parseMnemonic } from "./Crypto.js";
|
|
5
6
|
export type { InvalidMnemonicError, Mnemonic } from "./Crypto.js";
|
|
6
7
|
export type { ExtractRow, QueryResult } from "./Db.js";
|
|
7
8
|
export * from "./Error.js";
|