@evolu/react-native 1.0.8 → 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 +12 -0
- package/dist/PlatformLive.d.ts +2 -2
- package/dist/PlatformLive.d.ts.map +1 -1
- package/dist/PlatformLive.js +32 -35
- package/dist/SqliteLive.d.ts.map +1 -1
- package/dist/SqliteLive.js +5 -5
- package/dist/index.d.ts +34 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -8
- package/package.json +15 -15
- package/src/PlatformLive.ts +33 -39
- package/src/SqliteLive.ts +11 -6
- package/src/index.ts +73 -27
package/README.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
1
|
# Evolu for React Native
|
|
2
2
|
|
|
3
3
|
[Evolu](https://github.com/evoluhq/evolu) for [React Native](https://reactnative.dev/).
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
For detailed information and usage examples, please visit [evolu.dev](https://www.evolu.dev).
|
|
8
|
+
|
|
9
|
+
## Community
|
|
10
|
+
|
|
11
|
+
The Evolu community is on [GitHub Discussions](https://github.com/evoluhq/evolu/discussions), where you can ask questions and voice ideas.
|
|
12
|
+
|
|
13
|
+
To chat with other community members, you can join the [Evolu Discord](https://discord.gg/2J8yyyyxtZ).
|
|
14
|
+
|
|
15
|
+
[](https://twitter.com/evoluhq)
|
package/dist/PlatformLive.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AppState, Bip39, FlushSync,
|
|
1
|
+
import { AppState, Bip39, FlushSync, PlatformName, SyncLock } from "@evolu/common";
|
|
2
2
|
import { Layer } from "effect";
|
|
3
|
-
export declare const
|
|
3
|
+
export declare const PlatformNameLive: Layer.Layer<never, never, PlatformName>;
|
|
4
4
|
export declare const FlushSyncLive: Layer.Layer<never, never, FlushSync>;
|
|
5
5
|
export declare const SyncLockLive: Layer.Layer<never, never, SyncLock>;
|
|
6
6
|
export declare const AppStateLive: Layer.Layer<never, never, AppState>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlatformLive.d.ts","sourceRoot":"","sources":["../src/PlatformLive.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,KAAK,EACL,SAAS,EAGT,
|
|
1
|
+
{"version":3,"file":"PlatformLive.d.ts","sourceRoot":"","sources":["../src/PlatformLive.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,KAAK,EACL,SAAS,EAGT,YAAY,EACZ,QAAQ,EACT,MAAM,eAAe,CAAC;AAQvB,OAAO,EAAoB,KAAK,EAAE,MAAM,QAAQ,CAAC;AAIjD,eAAO,MAAM,gBAAgB,yCAA8C,CAAC;AAE5E,eAAO,MAAM,aAAa,sCAA+C,CAAC;AAE1E,eAAO,MAAM,YAAY,qCAexB,CAAC;AAEF,eAAO,MAAM,YAAY,qCA8BxB,CAAC;AAEF,eAAO,MAAM,SAAS,kCAYrB,CAAC"}
|
package/dist/PlatformLive.js
CHANGED
|
@@ -1,53 +1,50 @@
|
|
|
1
|
-
import { AppState, Bip39, FlushSync,
|
|
1
|
+
import { AppState, Bip39, FlushSync, PlatformName, SyncLock, } from "@evolu/common";
|
|
2
2
|
import NetInfo from "@react-native-community/netinfo";
|
|
3
3
|
import { generateMnemonic, mnemonicToSeed, validateMnemonic, } from "@scure/bip39";
|
|
4
4
|
import { wordlist } from "@scure/bip39/wordlists/english";
|
|
5
5
|
import { Effect, Function, Layer } from "effect";
|
|
6
6
|
import { reloadAsync } from "expo-updates";
|
|
7
7
|
import { DevSettings, AppState as ReactNativeAppState } from "react-native";
|
|
8
|
-
export const
|
|
9
|
-
name: "react-native",
|
|
10
|
-
});
|
|
8
|
+
export const PlatformNameLive = Layer.succeed(PlatformName, "react-native");
|
|
11
9
|
export const FlushSyncLive = Layer.succeed(FlushSync, Function.constVoid);
|
|
12
10
|
export const SyncLockLive = Layer.effect(SyncLock, Effect.sync(() => {
|
|
13
|
-
let
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
let hasSyncLock = false;
|
|
12
|
+
return SyncLock.of({
|
|
13
|
+
acquire: Effect.sync(() => {
|
|
14
|
+
if (hasSyncLock)
|
|
15
|
+
return false;
|
|
16
|
+
hasSyncLock = true;
|
|
17
|
+
return true;
|
|
18
|
+
}),
|
|
19
|
+
release: Effect.sync(() => {
|
|
20
|
+
hasSyncLock = false;
|
|
21
|
+
}),
|
|
19
22
|
});
|
|
20
|
-
const release = Effect.sync(() => {
|
|
21
|
-
hasLock = false;
|
|
22
|
-
});
|
|
23
|
-
return { acquire, release };
|
|
24
23
|
}));
|
|
25
|
-
export const AppStateLive = Layer.
|
|
26
|
-
|
|
27
|
-
let
|
|
28
|
-
ReactNativeAppState.addEventListener("change", (
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
export const AppStateLive = Layer.succeed(AppState, AppState.of({
|
|
25
|
+
init: ({ onFocus, onReconnect }) => {
|
|
26
|
+
let appStateStatus = ReactNativeAppState.currentState;
|
|
27
|
+
ReactNativeAppState.addEventListener("change", (current) => {
|
|
28
|
+
if (appStateStatus.match(/inactive|background/) && current === "active")
|
|
29
|
+
onFocus();
|
|
30
|
+
appStateStatus = current;
|
|
32
31
|
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
callback();
|
|
41
|
-
state = nextState;
|
|
32
|
+
let netInfoState = null;
|
|
33
|
+
NetInfo.addEventListener((current) => {
|
|
34
|
+
if (netInfoState?.isInternetReachable === false &&
|
|
35
|
+
current.isConnected &&
|
|
36
|
+
current.isInternetReachable)
|
|
37
|
+
onReconnect();
|
|
38
|
+
netInfoState = current;
|
|
42
39
|
});
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
onReconnect();
|
|
41
|
+
},
|
|
42
|
+
reset: Effect.sync(() => {
|
|
45
43
|
if (process.env.NODE_ENV === "development")
|
|
46
44
|
DevSettings.reload();
|
|
47
45
|
else
|
|
48
|
-
|
|
49
|
-
})
|
|
50
|
-
return AppState.of({ onFocus, onReconnect, reset });
|
|
46
|
+
reloadAsync();
|
|
47
|
+
}),
|
|
51
48
|
}));
|
|
52
49
|
export const Bip39Live = Layer.succeed(Bip39, Bip39.of({
|
|
53
50
|
make: Effect.sync(() => generateMnemonic(wordlist, 128)),
|
package/dist/SqliteLive.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqliteLive.d.ts","sourceRoot":"","sources":["../src/SqliteLive.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"SqliteLive.d.ts","sourceRoot":"","sources":["../src/SqliteLive.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAIP,MAAM,eAAe,CAAC;AACvB,OAAO,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAC;AA2BvC,eAAO,MAAM,UAAU,mCAAkC,CAAC"}
|
package/dist/SqliteLive.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { Sqlite,
|
|
1
|
+
import { Sqlite, ensureSqliteQuery, maybeParseJson, valuesToSqliteValues, } from "@evolu/common";
|
|
2
2
|
import { Effect, Layer } from "effect";
|
|
3
3
|
import * as SQLite from "expo-sqlite";
|
|
4
4
|
const db = SQLite.openDatabase("evolu1.db");
|
|
5
5
|
const exec = (arg) => Effect.gen(function* (_) {
|
|
6
|
-
const
|
|
6
|
+
const sqliteQuery = ensureSqliteQuery(arg);
|
|
7
7
|
const query = {
|
|
8
|
-
sql:
|
|
9
|
-
args:
|
|
8
|
+
sql: sqliteQuery.sql,
|
|
9
|
+
args: valuesToSqliteValues(sqliteQuery.parameters),
|
|
10
10
|
};
|
|
11
11
|
const { rows, rowsAffected } = yield* _(Effect.promise(() => db
|
|
12
12
|
.execAsync([query], false)
|
|
@@ -16,7 +16,7 @@ const exec = (arg) => Effect.gen(function* (_) {
|
|
|
16
16
|
throw result.error;
|
|
17
17
|
return result;
|
|
18
18
|
})));
|
|
19
|
-
|
|
19
|
+
maybeParseJson(rows);
|
|
20
20
|
return { rows, changes: rowsAffected };
|
|
21
21
|
});
|
|
22
22
|
export const SqliteLive = Layer.succeed(Sqlite, { exec });
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
1
|
+
import { Config, InvalidMnemonicError, Mnemonic, Schema } from "@evolu/common";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
export { Id, NonEmptyString1000, PositiveInt, SqliteBoolean, SqliteDate, String, String1000, canUseDom, cast, id, } from "@evolu/common";
|
|
4
|
+
export type { EvoluError, InvalidMnemonicError, Mnemonic, Owner, OwnerId, SyncState, Timestamp, TimestampError, UnexpectedError, } from "@evolu/common";
|
|
5
|
+
export { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
|
6
|
+
/**
|
|
7
|
+
* Create Evolu for React Native.
|
|
8
|
+
*
|
|
9
|
+
* ### Example
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* import * as S from "@effect/schema/Schema";
|
|
13
|
+
* import * as Evolu from "@evolu/react-native";
|
|
14
|
+
*
|
|
15
|
+
* const TodoId = Evolu.id("Todo");
|
|
16
|
+
* type TodoId = S.Schema.To<typeof TodoId>;
|
|
17
|
+
*
|
|
18
|
+
* const TodoTable = S.struct({
|
|
19
|
+
* id: TodoId,
|
|
20
|
+
* title: Evolu.NonEmptyString1000,
|
|
21
|
+
* });
|
|
22
|
+
* type TodoTable = S.Schema.To<typeof TodoTable>;
|
|
23
|
+
*
|
|
24
|
+
* const Database = S.struct({
|
|
25
|
+
* todo: TodoTable,
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* const { useEvolu, useEvoluError, useQuery, useOwner } =
|
|
29
|
+
* Evolu.create(Database);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare const create: <From, To extends Schema>(schema: import("@effect/schema/Schema").Schema<From, To>, config?: Partial<Config> | undefined) => import("@evolu/common-react").EvoluReact<To>;
|
|
33
|
+
/** Parse a string to {@link Mnemonic}. */
|
|
34
|
+
export declare const parseMnemonic: (mnemonic: string) => Effect.Effect<never, InvalidMnemonicError, Mnemonic>;
|
|
4
35
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EAKN,oBAAoB,EACpB,QAAQ,EAER,MAAM,EAGP,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,MAAM,EAAS,MAAM,QAAQ,CAAC;AAYvC,OAAO,EACL,EAAE,EACF,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,UAAU,EACV,MAAM,EACN,UAAU,EACV,SAAS,EACT,IAAI,EACJ,EAAE,GACH,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,UAAU,EACV,oBAAoB,EACpB,QAAQ,EACR,KAAK,EACL,OAAO,EACP,SAAS,EACT,SAAS,EACT,cAAc,EACd,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAetE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,MAAM,2KAGlB,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,aAAa,EAAE,CAC1B,QAAQ,EAAE,MAAM,KACb,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,oBAAoB,EAAE,QAAQ,CAGjD,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,41 @@
|
|
|
1
|
-
import { DbWorkerLive, FetchLive, NanoIdLive, SecretBoxLive, SyncWorkerLive, } from "@evolu/common";
|
|
2
|
-
import {
|
|
3
|
-
import { Layer } from "effect";
|
|
4
|
-
import { AppStateLive, Bip39Live, FlushSyncLive,
|
|
1
|
+
import { Bip39, DbWorkerLive, EvoluCommonLive, FetchLive, NanoIdLive, SecretBoxLive, SyncWorkerLive, } from "@evolu/common";
|
|
2
|
+
import { EvoluReactLive, makeCreateEvoluReact } from "@evolu/common-react";
|
|
3
|
+
import { Effect, Layer } from "effect";
|
|
4
|
+
import { AppStateLive, Bip39Live, FlushSyncLive, SyncLockLive, } from "./PlatformLive.js";
|
|
5
5
|
import { SqliteLive } from "./SqliteLive.js";
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
|
|
9
|
-
export
|
|
6
|
+
// export * from "@evolu/common/public" isn't working in RN for some reason,
|
|
7
|
+
// so we have to export manually.
|
|
8
|
+
// TODO: Recheck after RN 0.73 release.
|
|
9
|
+
export { Id, NonEmptyString1000, PositiveInt, SqliteBoolean, SqliteDate, String, String1000, canUseDom, cast, id, } from "@evolu/common";
|
|
10
|
+
export { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
|
11
|
+
/** Evolu for native platform. */
|
|
12
|
+
const EvoluNativeLive = EvoluCommonLive.pipe(Layer.provide(Layer.mergeAll(FlushSyncLive, AppStateLive, DbWorkerLive)), Layer.provide(Layer.mergeAll(Bip39Live, NanoIdLive, SqliteLive, SyncWorkerLive)), Layer.provide(Layer.mergeAll(SecretBoxLive, SyncLockLive, FetchLive)));
|
|
13
|
+
/**
|
|
14
|
+
* Create Evolu for React Native.
|
|
15
|
+
*
|
|
16
|
+
* ### Example
|
|
17
|
+
*
|
|
18
|
+
* ```ts
|
|
19
|
+
* import * as S from "@effect/schema/Schema";
|
|
20
|
+
* import * as Evolu from "@evolu/react-native";
|
|
21
|
+
*
|
|
22
|
+
* const TodoId = Evolu.id("Todo");
|
|
23
|
+
* type TodoId = S.Schema.To<typeof TodoId>;
|
|
24
|
+
*
|
|
25
|
+
* const TodoTable = S.struct({
|
|
26
|
+
* id: TodoId,
|
|
27
|
+
* title: Evolu.NonEmptyString1000,
|
|
28
|
+
* });
|
|
29
|
+
* type TodoTable = S.Schema.To<typeof TodoTable>;
|
|
30
|
+
*
|
|
31
|
+
* const Database = S.struct({
|
|
32
|
+
* todo: TodoTable,
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* const { useEvolu, useEvoluError, useQuery, useOwner } =
|
|
36
|
+
* Evolu.create(Database);
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export const create = EvoluReactLive.pipe(Layer.provide(EvoluNativeLive), makeCreateEvoluReact);
|
|
40
|
+
/** Parse a string to {@link Mnemonic}. */
|
|
41
|
+
export const parseMnemonic = Bip39.pipe(Effect.provide(Bip39Live), Effect.runSync).parse;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evolu/react-native",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Evolu for React Native",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"evolu",
|
|
@@ -31,24 +31,24 @@
|
|
|
31
31
|
"README.md"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"expo-updates": "^0.18.
|
|
34
|
+
"expo-updates": "^0.18.17"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"eslint": "^8.
|
|
38
|
-
"expo": "^49.0.
|
|
39
|
-
"expo-sqlite": "~11.
|
|
37
|
+
"eslint": "^8.54.0",
|
|
38
|
+
"expo": "^49.0.21",
|
|
39
|
+
"expo-sqlite": "~11.3.3",
|
|
40
40
|
"react-native": "^0.72.6",
|
|
41
|
-
"typescript": "^5.
|
|
41
|
+
"typescript": "^5.3.2",
|
|
42
42
|
"vitest": "^0.34.6",
|
|
43
|
-
"@evolu/common": "
|
|
44
|
-
"@evolu/common-react": "
|
|
43
|
+
"@evolu/common": "2.0.5",
|
|
44
|
+
"@evolu/common-react": "2.0.2",
|
|
45
45
|
"@evolu/tsconfig": "0.0.2",
|
|
46
|
-
"eslint-config-evolu": "0.0
|
|
46
|
+
"eslint-config-evolu": "1.0.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"@evolu/common-react": "^
|
|
50
|
-
"expo": "^49.0.
|
|
51
|
-
"expo-sqlite": "~11.
|
|
49
|
+
"@evolu/common-react": "^2.0.2",
|
|
50
|
+
"expo": "^49.0.20",
|
|
51
|
+
"expo-sqlite": "~11.3.3",
|
|
52
52
|
"react-native": "^0.72.4"
|
|
53
53
|
},
|
|
54
54
|
"publishConfig": {
|
|
@@ -57,12 +57,12 @@
|
|
|
57
57
|
"engines": {
|
|
58
58
|
"node": ">=18.16"
|
|
59
59
|
},
|
|
60
|
-
"sideEffects":
|
|
60
|
+
"sideEffects": [],
|
|
61
61
|
"scripts": {
|
|
62
62
|
"dev": "tsc --watch",
|
|
63
63
|
"build": "rm -rf dist && tsc",
|
|
64
|
-
"lint": "
|
|
65
|
-
"clean": "rm -rf .turbo
|
|
64
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
65
|
+
"clean": "rm -rf .turbo node_modules dist",
|
|
66
66
|
"format": "prettier --write \"src/*.{ts,tsx,md}\""
|
|
67
67
|
}
|
|
68
68
|
}
|
package/src/PlatformLive.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
FlushSync,
|
|
5
5
|
InvalidMnemonicError,
|
|
6
6
|
Mnemonic,
|
|
7
|
-
|
|
7
|
+
PlatformName,
|
|
8
8
|
SyncLock,
|
|
9
9
|
} from "@evolu/common";
|
|
10
10
|
import NetInfo, { NetInfoState } from "@react-native-community/netinfo";
|
|
@@ -18,62 +18,56 @@ import { Effect, Function, Layer } from "effect";
|
|
|
18
18
|
import { reloadAsync } from "expo-updates";
|
|
19
19
|
import { DevSettings, AppState as ReactNativeAppState } from "react-native";
|
|
20
20
|
|
|
21
|
-
export const
|
|
22
|
-
name: "react-native",
|
|
23
|
-
});
|
|
21
|
+
export const PlatformNameLive = Layer.succeed(PlatformName, "react-native");
|
|
24
22
|
|
|
25
23
|
export const FlushSyncLive = Layer.succeed(FlushSync, Function.constVoid);
|
|
26
24
|
|
|
27
25
|
export const SyncLockLive = Layer.effect(
|
|
28
26
|
SyncLock,
|
|
29
27
|
Effect.sync(() => {
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
let hasSyncLock = false;
|
|
29
|
+
return SyncLock.of({
|
|
30
|
+
acquire: Effect.sync(() => {
|
|
31
|
+
if (hasSyncLock) return false;
|
|
32
|
+
hasSyncLock = true;
|
|
33
|
+
return true;
|
|
34
|
+
}),
|
|
35
|
+
release: Effect.sync(() => {
|
|
36
|
+
hasSyncLock = false;
|
|
37
|
+
}),
|
|
40
38
|
});
|
|
41
|
-
|
|
42
|
-
return { acquire, release };
|
|
43
39
|
}),
|
|
44
40
|
);
|
|
45
41
|
|
|
46
|
-
export const AppStateLive = Layer.
|
|
42
|
+
export const AppStateLive = Layer.succeed(
|
|
47
43
|
AppState,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
let
|
|
51
|
-
ReactNativeAppState.addEventListener("change", (
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
44
|
+
AppState.of({
|
|
45
|
+
init: ({ onFocus, onReconnect }) => {
|
|
46
|
+
let appStateStatus = ReactNativeAppState.currentState;
|
|
47
|
+
ReactNativeAppState.addEventListener("change", (current): void => {
|
|
48
|
+
if (appStateStatus.match(/inactive|background/) && current === "active")
|
|
49
|
+
onFocus();
|
|
50
|
+
appStateStatus = current;
|
|
55
51
|
});
|
|
56
|
-
};
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
NetInfo.addEventListener((nextState) => {
|
|
53
|
+
let netInfoState: NetInfoState | null = null;
|
|
54
|
+
NetInfo.addEventListener((current) => {
|
|
61
55
|
if (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
56
|
+
netInfoState?.isInternetReachable === false &&
|
|
57
|
+
current.isConnected &&
|
|
58
|
+
current.isInternetReachable
|
|
65
59
|
)
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
onReconnect();
|
|
61
|
+
netInfoState = current;
|
|
68
62
|
});
|
|
69
|
-
};
|
|
70
63
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
else void reloadAsync();
|
|
74
|
-
});
|
|
64
|
+
onReconnect();
|
|
65
|
+
},
|
|
75
66
|
|
|
76
|
-
|
|
67
|
+
reset: Effect.sync(() => {
|
|
68
|
+
if (process.env.NODE_ENV === "development") DevSettings.reload();
|
|
69
|
+
else reloadAsync();
|
|
70
|
+
}),
|
|
77
71
|
}),
|
|
78
72
|
);
|
|
79
73
|
|
package/src/SqliteLive.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Sqlite,
|
|
3
|
+
ensureSqliteQuery,
|
|
4
|
+
maybeParseJson,
|
|
5
|
+
valuesToSqliteValues,
|
|
6
|
+
} from "@evolu/common";
|
|
2
7
|
import { Effect, Layer } from "effect";
|
|
3
8
|
import * as SQLite from "expo-sqlite";
|
|
4
9
|
|
|
@@ -6,10 +11,10 @@ const db = SQLite.openDatabase("evolu1.db");
|
|
|
6
11
|
|
|
7
12
|
const exec: Sqlite["exec"] = (arg) =>
|
|
8
13
|
Effect.gen(function* (_) {
|
|
9
|
-
const
|
|
10
|
-
const query
|
|
11
|
-
sql:
|
|
12
|
-
args:
|
|
14
|
+
const sqliteQuery = ensureSqliteQuery(arg);
|
|
15
|
+
const query = {
|
|
16
|
+
sql: sqliteQuery.sql,
|
|
17
|
+
args: valuesToSqliteValues(sqliteQuery.parameters),
|
|
13
18
|
};
|
|
14
19
|
const { rows, rowsAffected } = yield* _(
|
|
15
20
|
Effect.promise(() =>
|
|
@@ -22,7 +27,7 @@ const exec: Sqlite["exec"] = (arg) =>
|
|
|
22
27
|
}),
|
|
23
28
|
),
|
|
24
29
|
);
|
|
25
|
-
|
|
30
|
+
maybeParseJson(rows);
|
|
26
31
|
return { rows, changes: rowsAffected };
|
|
27
32
|
});
|
|
28
33
|
|
package/src/index.ts
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Bip39,
|
|
3
|
+
Config,
|
|
2
4
|
DbWorkerLive,
|
|
5
|
+
Evolu,
|
|
6
|
+
EvoluCommonLive,
|
|
3
7
|
FetchLive,
|
|
8
|
+
InvalidMnemonicError,
|
|
9
|
+
Mnemonic,
|
|
4
10
|
NanoIdLive,
|
|
11
|
+
Schema,
|
|
5
12
|
SecretBoxLive,
|
|
6
13
|
SyncWorkerLive,
|
|
7
14
|
} from "@evolu/common";
|
|
8
|
-
import {
|
|
9
|
-
import { Layer } from "effect";
|
|
15
|
+
import { EvoluReactLive, makeCreateEvoluReact } from "@evolu/common-react";
|
|
16
|
+
import { Effect, Layer } from "effect";
|
|
10
17
|
import {
|
|
11
18
|
AppStateLive,
|
|
12
19
|
Bip39Live,
|
|
13
20
|
FlushSyncLive,
|
|
14
|
-
PlatformLive,
|
|
15
21
|
SyncLockLive,
|
|
16
22
|
} from "./PlatformLive.js";
|
|
17
23
|
import { SqliteLive } from "./SqliteLive.js";
|
|
18
24
|
|
|
19
|
-
//
|
|
20
|
-
//
|
|
25
|
+
// export * from "@evolu/common/public" isn't working in RN for some reason,
|
|
26
|
+
// so we have to export manually.
|
|
27
|
+
// TODO: Recheck after RN 0.73 release.
|
|
21
28
|
export {
|
|
22
29
|
Id,
|
|
23
30
|
NonEmptyString1000,
|
|
24
|
-
Owner,
|
|
25
31
|
PositiveInt,
|
|
26
32
|
SqliteBoolean,
|
|
27
33
|
SqliteDate,
|
|
@@ -30,28 +36,68 @@ export {
|
|
|
30
36
|
canUseDom,
|
|
31
37
|
cast,
|
|
32
38
|
id,
|
|
33
|
-
jsonArrayFrom,
|
|
34
|
-
jsonObjectFrom,
|
|
35
39
|
} from "@evolu/common";
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
export type {
|
|
41
|
+
EvoluError,
|
|
42
|
+
InvalidMnemonicError,
|
|
43
|
+
Mnemonic,
|
|
44
|
+
Owner,
|
|
45
|
+
OwnerId,
|
|
46
|
+
SyncState,
|
|
47
|
+
Timestamp,
|
|
48
|
+
TimestampError,
|
|
49
|
+
UnexpectedError,
|
|
50
|
+
} from "@evolu/common";
|
|
51
|
+
export { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
|
38
52
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
Layer.mergeAll(SyncLockLive, FetchLive, SecretBoxLive),
|
|
49
|
-
),
|
|
50
|
-
),
|
|
53
|
+
/** Evolu for native platform. */
|
|
54
|
+
const EvoluNativeLive: Layer.Layer<
|
|
55
|
+
Config,
|
|
56
|
+
never,
|
|
57
|
+
Evolu<Schema>
|
|
58
|
+
> = EvoluCommonLive.pipe(
|
|
59
|
+
Layer.provide(Layer.mergeAll(FlushSyncLive, AppStateLive, DbWorkerLive)),
|
|
60
|
+
Layer.provide(
|
|
61
|
+
Layer.mergeAll(Bip39Live, NanoIdLive, SqliteLive, SyncWorkerLive),
|
|
51
62
|
),
|
|
52
|
-
Layer.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
63
|
+
Layer.provide(Layer.mergeAll(SecretBoxLive, SyncLockLive, FetchLive)),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Create Evolu for React Native.
|
|
68
|
+
*
|
|
69
|
+
* ### Example
|
|
70
|
+
*
|
|
71
|
+
* ```ts
|
|
72
|
+
* import * as S from "@effect/schema/Schema";
|
|
73
|
+
* import * as Evolu from "@evolu/react-native";
|
|
74
|
+
*
|
|
75
|
+
* const TodoId = Evolu.id("Todo");
|
|
76
|
+
* type TodoId = S.Schema.To<typeof TodoId>;
|
|
77
|
+
*
|
|
78
|
+
* const TodoTable = S.struct({
|
|
79
|
+
* id: TodoId,
|
|
80
|
+
* title: Evolu.NonEmptyString1000,
|
|
81
|
+
* });
|
|
82
|
+
* type TodoTable = S.Schema.To<typeof TodoTable>;
|
|
83
|
+
*
|
|
84
|
+
* const Database = S.struct({
|
|
85
|
+
* todo: TodoTable,
|
|
86
|
+
* });
|
|
87
|
+
*
|
|
88
|
+
* const { useEvolu, useEvoluError, useQuery, useOwner } =
|
|
89
|
+
* Evolu.create(Database);
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export const create = EvoluReactLive.pipe(
|
|
93
|
+
Layer.provide(EvoluNativeLive),
|
|
94
|
+
makeCreateEvoluReact,
|
|
57
95
|
);
|
|
96
|
+
|
|
97
|
+
/** Parse a string to {@link Mnemonic}. */
|
|
98
|
+
export const parseMnemonic: (
|
|
99
|
+
mnemonic: string,
|
|
100
|
+
) => Effect.Effect<never, InvalidMnemonicError, Mnemonic> = Bip39.pipe(
|
|
101
|
+
Effect.provide(Bip39Live),
|
|
102
|
+
Effect.runSync,
|
|
103
|
+
).parse;
|