@livestore/adapter-expo 0.3.0-dev.36 → 0.3.0-dev.38
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/.tsbuildinfo +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -58
- package/dist/index.js.map +1 -1
- package/package.json +8 -6
- package/src/index.ts +66 -79
package/dist/index.d.ts
CHANGED
|
@@ -11,9 +11,9 @@ export type MakeDbOptions = {
|
|
|
11
11
|
*/
|
|
12
12
|
subDirectory?: string;
|
|
13
13
|
};
|
|
14
|
-
/** @default
|
|
14
|
+
/** @default android/ios id (see https://docs.expo.dev/versions/latest/sdk/application) */
|
|
15
15
|
clientId?: string;
|
|
16
|
-
/** @default '
|
|
16
|
+
/** @default 'static' */
|
|
17
17
|
sessionId?: string;
|
|
18
18
|
};
|
|
19
19
|
declare global {
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAEtB,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAEtB,OAAO,KAAK,EAAE,OAAO,EAA0D,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAkBrH,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,OAAO,CAAC,EAAE;QACR;;;;;WAKG;QACH,YAAY,CAAC,EAAE,MAAM,CAAA;KACtB,CAAA;IAED,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,aAAa,EAAE,OAAO,GAAG,SAAS,CAAA;CACvC;AAKD,eAAO,MAAM,oBAAoB,GAC9B,UAAS,aAAkB,KAAG,OAwE5B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,82 +1,65 @@
|
|
|
1
1
|
import './polyfill.js';
|
|
2
|
-
import { Devtools, liveStoreStorageFormatVersion, UnexpectedError } from '@livestore/common';
|
|
2
|
+
import { Devtools, liveStoreStorageFormatVersion, makeClientSession, UnexpectedError } from '@livestore/common';
|
|
3
3
|
import { Eventlog, LeaderThreadCtx, makeLeaderThreadLayer } from '@livestore/common/leader-thread';
|
|
4
4
|
import { LiveStoreEvent } from '@livestore/common/schema';
|
|
5
|
-
import
|
|
5
|
+
import { shouldNeverHappen } from '@livestore/utils';
|
|
6
6
|
import { Cause, Effect, FetchHttpClient, Fiber, Layer, Queue, Stream, SubscriptionRef } from '@livestore/utils/effect';
|
|
7
|
+
import * as Webmesh from '@livestore/webmesh';
|
|
8
|
+
import * as ExpoApplication from 'expo-application';
|
|
7
9
|
import * as SQLite from 'expo-sqlite';
|
|
10
|
+
import * as RN from 'react-native';
|
|
8
11
|
import { makeSqliteDb } from './make-sqlite-db.js';
|
|
9
12
|
import { makeShutdownChannel } from './shutdown-channel.js';
|
|
10
13
|
const IS_NEW_ARCH = globalThis.RN$Bridgeless === true;
|
|
11
14
|
// TODO refactor with leader-thread code from `@livestore/common/leader-thread`
|
|
12
|
-
export const makePersistedAdapter = (options = {}) => (
|
|
15
|
+
export const makePersistedAdapter = (options = {}) => (adapterArgs) => Effect.gen(function* () {
|
|
13
16
|
if (IS_NEW_ARCH === false) {
|
|
14
17
|
return yield* UnexpectedError.make({
|
|
15
18
|
cause: new Error('The LiveStore Expo adapter requires the new React Native architecture (aka Fabric). See https://docs.expo.dev/guides/new-architecture'),
|
|
16
19
|
});
|
|
17
20
|
}
|
|
18
|
-
const {
|
|
21
|
+
const { schema, shutdown, devtoolsEnabled, storeId, bootStatusQueue, syncPayload } = adapterArgs;
|
|
22
|
+
const { storage, clientId = yield* getDeviceId, sessionId = 'static', sync: syncOptions } = options;
|
|
19
23
|
yield* Queue.offer(bootStatusQueue, { stage: 'loading' });
|
|
20
24
|
const lockStatus = yield* SubscriptionRef.make('has-lock');
|
|
21
25
|
const shutdownChannel = yield* makeShutdownChannel(storeId);
|
|
22
26
|
yield* shutdownChannel.listen.pipe(Stream.flatten(), Stream.tap((error) => Effect.sync(() => shutdown(Cause.fail(error)))), Stream.runDrain, Effect.interruptible, Effect.tapCauseLogPretty, Effect.forkScoped);
|
|
23
|
-
const
|
|
24
|
-
? yield* DevtoolsExpo.makeExpoDevtoolsConnectedMeshNode({
|
|
25
|
-
nodeName: `expo-${storeId}-${clientId}-${sessionId}`,
|
|
26
|
-
target: `devtools-${storeId}-${clientId}-${sessionId}`,
|
|
27
|
-
})
|
|
28
|
-
: undefined;
|
|
27
|
+
const devtoolsUrl = getDevtoolsUrl();
|
|
29
28
|
const { leaderThread, initialSnapshot } = yield* makeLeaderThread({
|
|
30
29
|
storeId,
|
|
31
30
|
clientId,
|
|
32
|
-
sessionId,
|
|
33
31
|
schema,
|
|
34
32
|
makeSqliteDb,
|
|
35
33
|
syncOptions,
|
|
36
34
|
storage: storage ?? {},
|
|
37
35
|
devtoolsEnabled,
|
|
38
|
-
devtoolsWebmeshNode,
|
|
39
36
|
bootStatusQueue,
|
|
40
37
|
syncPayload,
|
|
38
|
+
devtoolsUrl,
|
|
41
39
|
});
|
|
42
40
|
const sqliteDb = yield* makeSqliteDb({ _tag: 'in-memory' });
|
|
43
41
|
sqliteDb.import(initialSnapshot);
|
|
44
|
-
const clientSession = {
|
|
45
|
-
|
|
42
|
+
const clientSession = yield* makeClientSession({
|
|
43
|
+
...adapterArgs,
|
|
46
44
|
lockStatus,
|
|
47
45
|
clientId,
|
|
48
46
|
sessionId,
|
|
49
47
|
leaderThread,
|
|
50
|
-
shutdown: () => Effect.dieMessage('TODO implement shutdown'),
|
|
51
48
|
sqliteDb,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
sessionId,
|
|
64
|
-
storeId,
|
|
65
|
-
schemaAlias: schema.devtools.alias,
|
|
66
|
-
}),
|
|
67
|
-
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped);
|
|
68
|
-
const storeDevtoolsChannel = yield* DevtoolsExpo.makeChannelForConnectedMeshNode({
|
|
69
|
-
target: `devtools-${storeId}-${clientId}-${sessionId}`,
|
|
70
|
-
node: devtoolsWebmeshNode,
|
|
71
|
-
schema: { listen: Devtools.ClientSession.MessageToApp, send: Devtools.ClientSession.MessageFromApp },
|
|
72
|
-
channelType: 'clientSession',
|
|
73
|
-
});
|
|
74
|
-
yield* connectDevtoolsToStore(storeDevtoolsChannel);
|
|
75
|
-
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped);
|
|
76
|
-
}
|
|
49
|
+
webmeshMode: 'proxy',
|
|
50
|
+
connectWebmeshNode: Effect.fnUntraced(function* ({ webmeshNode }) {
|
|
51
|
+
if (devtoolsEnabled) {
|
|
52
|
+
yield* Webmesh.connectViaWebSocket({
|
|
53
|
+
node: webmeshNode,
|
|
54
|
+
url: devtoolsUrl,
|
|
55
|
+
openTimeout: 50,
|
|
56
|
+
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped);
|
|
57
|
+
}
|
|
58
|
+
}),
|
|
59
|
+
});
|
|
77
60
|
return clientSession;
|
|
78
|
-
}).pipe(Effect.mapError((cause) => (cause._tag === 'LiveStore.UnexpectedError' ? cause : new UnexpectedError({ cause }))), Effect.tapCauseLogPretty);
|
|
79
|
-
const makeLeaderThread = ({ storeId, clientId,
|
|
61
|
+
}).pipe(Effect.mapError((cause) => (cause._tag === 'LiveStore.UnexpectedError' ? cause : new UnexpectedError({ cause }))), Effect.provide(FetchHttpClient.layer), Effect.tapCauseLogPretty);
|
|
62
|
+
const makeLeaderThread = ({ storeId, clientId, schema, makeSqliteDb, syncOptions, storage, devtoolsEnabled, bootStatusQueue: bootStatusQueueClientSession, syncPayload, devtoolsUrl, }) => Effect.gen(function* () {
|
|
80
63
|
const subDirectory = storage.subDirectory ? storage.subDirectory.replace(/\/$/, '') + '/' : '';
|
|
81
64
|
const pathJoin = (...paths) => paths.join('/').replaceAll(/\/+/g, '/');
|
|
82
65
|
const directory = pathJoin(SQLite.defaultDatabaseDirectory, subDirectory, storeId);
|
|
@@ -87,12 +70,11 @@ const makeLeaderThread = ({ storeId, clientId, sessionId, schema, makeSqliteDb,
|
|
|
87
70
|
const dbEventlog = yield* makeSqliteDb({ _tag: 'file', databaseName: dbEventlogPath, directory });
|
|
88
71
|
const devtoolsOptions = yield* makeDevtoolsOptions({
|
|
89
72
|
devtoolsEnabled,
|
|
73
|
+
devtoolsUrl,
|
|
90
74
|
dbState,
|
|
91
75
|
dbEventlog,
|
|
92
76
|
storeId,
|
|
93
77
|
clientId,
|
|
94
|
-
sessionId,
|
|
95
|
-
devtoolsWebmeshNode,
|
|
96
78
|
});
|
|
97
79
|
const layer = yield* Layer.memoize(makeLeaderThreadLayer({
|
|
98
80
|
clientId,
|
|
@@ -129,7 +111,7 @@ const makeLeaderThread = ({ storeId, clientId, sessionId, schema, makeSqliteDb,
|
|
|
129
111
|
return { leaderThread, initialSnapshot };
|
|
130
112
|
}).pipe(Effect.provide(layer));
|
|
131
113
|
});
|
|
132
|
-
const makeDevtoolsOptions = ({ devtoolsEnabled, dbState, dbEventlog, storeId, clientId,
|
|
114
|
+
const makeDevtoolsOptions = ({ devtoolsEnabled, devtoolsUrl, dbState, dbEventlog, storeId, clientId, }) => Effect.gen(function* () {
|
|
133
115
|
if (devtoolsEnabled === false) {
|
|
134
116
|
return {
|
|
135
117
|
enabled: false,
|
|
@@ -137,21 +119,37 @@ const makeDevtoolsOptions = ({ devtoolsEnabled, dbState, dbEventlog, storeId, cl
|
|
|
137
119
|
}
|
|
138
120
|
return {
|
|
139
121
|
enabled: true,
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
schema: { listen: Devtools.Leader.MessageToApp, send: Devtools.Leader.MessageFromApp },
|
|
145
|
-
channelType: 'leader',
|
|
146
|
-
});
|
|
147
|
-
return {
|
|
148
|
-
devtoolsWebChannel,
|
|
149
|
-
persistenceInfo: {
|
|
150
|
-
state: dbState.metadata.persistenceInfo,
|
|
151
|
-
eventlog: dbEventlog.metadata.persistenceInfo,
|
|
152
|
-
},
|
|
122
|
+
boot: Effect.gen(function* () {
|
|
123
|
+
const persistenceInfo = {
|
|
124
|
+
state: dbState.metadata.persistenceInfo,
|
|
125
|
+
eventlog: dbEventlog.metadata.persistenceInfo,
|
|
153
126
|
};
|
|
127
|
+
const node = yield* Webmesh.makeMeshNode(Devtools.makeNodeName.client.leader({ storeId, clientId }));
|
|
128
|
+
yield* Webmesh.connectViaWebSocket({
|
|
129
|
+
node,
|
|
130
|
+
url: devtoolsUrl,
|
|
131
|
+
openTimeout: 50,
|
|
132
|
+
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped);
|
|
133
|
+
return { node, persistenceInfo, mode: 'proxy' };
|
|
154
134
|
}),
|
|
155
135
|
};
|
|
156
136
|
});
|
|
137
|
+
const getDeviceId = Effect.gen(function* () {
|
|
138
|
+
if (RN.Platform.OS === 'android') {
|
|
139
|
+
return ExpoApplication.getAndroidId();
|
|
140
|
+
}
|
|
141
|
+
else if (RN.Platform.OS === 'ios') {
|
|
142
|
+
const iosId = yield* Effect.promise(() => ExpoApplication.getIosIdForVendorAsync());
|
|
143
|
+
if (iosId === null) {
|
|
144
|
+
return shouldNeverHappen('getDeviceId: iosId is null');
|
|
145
|
+
}
|
|
146
|
+
return iosId;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
return shouldNeverHappen(`getDeviceId: Unsupported platform: ${RN.Platform.OS}`);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
const getDevtoolsUrl = () => {
|
|
153
|
+
return process.env.EXPO_PUBLIC_LIVESTORE_DEVTOOLS_URL ?? `http://localhost:4242`;
|
|
154
|
+
};
|
|
157
155
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/adapter-expo",
|
|
3
|
-
"version": "0.3.0-dev.
|
|
3
|
+
"version": "0.3.0-dev.38",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
@@ -12,14 +12,15 @@
|
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@opentelemetry/api": "1.9.0",
|
|
15
|
-
"@livestore/
|
|
16
|
-
"@livestore/
|
|
17
|
-
"@livestore/utils": "0.3.0-dev.
|
|
18
|
-
"@livestore/webmesh": "0.3.0-dev.36"
|
|
15
|
+
"@livestore/common": "0.3.0-dev.38",
|
|
16
|
+
"@livestore/webmesh": "0.3.0-dev.38",
|
|
17
|
+
"@livestore/utils": "0.3.0-dev.38"
|
|
19
18
|
},
|
|
20
19
|
"devDependencies": {
|
|
20
|
+
"expo-application": "*",
|
|
21
21
|
"expo-file-system": "*",
|
|
22
|
-
"expo-sqlite": "^15.2.4"
|
|
22
|
+
"expo-sqlite": "^15.2.4",
|
|
23
|
+
"react-native": "0.79.0"
|
|
23
24
|
},
|
|
24
25
|
"files": [
|
|
25
26
|
"package.json",
|
|
@@ -27,6 +28,7 @@
|
|
|
27
28
|
"dist"
|
|
28
29
|
],
|
|
29
30
|
"peerDependencies": {
|
|
31
|
+
"expo-application": "*",
|
|
30
32
|
"expo-file-system": "*",
|
|
31
33
|
"expo-sqlite": "~15.2.4"
|
|
32
34
|
},
|
package/src/index.ts
CHANGED
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
import './polyfill.js'
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
BootStatus,
|
|
6
|
-
ClientSession,
|
|
7
|
-
ClientSessionLeaderThreadProxy,
|
|
8
|
-
LockStatus,
|
|
9
|
-
SyncOptions,
|
|
10
|
-
} from '@livestore/common'
|
|
11
|
-
import { Devtools, liveStoreStorageFormatVersion, UnexpectedError } from '@livestore/common'
|
|
3
|
+
import type { Adapter, BootStatus, ClientSessionLeaderThreadProxy, LockStatus, SyncOptions } from '@livestore/common'
|
|
4
|
+
import { Devtools, liveStoreStorageFormatVersion, makeClientSession, UnexpectedError } from '@livestore/common'
|
|
12
5
|
import type { DevtoolsOptions, LeaderSqliteDb } from '@livestore/common/leader-thread'
|
|
13
6
|
import { Eventlog, LeaderThreadCtx, makeLeaderThreadLayer } from '@livestore/common/leader-thread'
|
|
14
7
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
15
8
|
import { LiveStoreEvent } from '@livestore/common/schema'
|
|
16
|
-
import
|
|
9
|
+
import { shouldNeverHappen } from '@livestore/utils'
|
|
17
10
|
import type { Schema, Scope } from '@livestore/utils/effect'
|
|
18
11
|
import { Cause, Effect, FetchHttpClient, Fiber, Layer, Queue, Stream, SubscriptionRef } from '@livestore/utils/effect'
|
|
19
|
-
import
|
|
12
|
+
import * as Webmesh from '@livestore/webmesh'
|
|
13
|
+
import * as ExpoApplication from 'expo-application'
|
|
20
14
|
import * as SQLite from 'expo-sqlite'
|
|
15
|
+
import * as RN from 'react-native'
|
|
21
16
|
|
|
22
17
|
import type { MakeExpoSqliteDb } from './make-sqlite-db.js'
|
|
23
18
|
import { makeSqliteDb } from './make-sqlite-db.js'
|
|
@@ -35,9 +30,9 @@ export type MakeDbOptions = {
|
|
|
35
30
|
subDirectory?: string
|
|
36
31
|
}
|
|
37
32
|
// syncBackend?: TODO
|
|
38
|
-
/** @default
|
|
33
|
+
/** @default android/ios id (see https://docs.expo.dev/versions/latest/sdk/application) */
|
|
39
34
|
clientId?: string
|
|
40
|
-
/** @default '
|
|
35
|
+
/** @default 'static' */
|
|
41
36
|
sessionId?: string
|
|
42
37
|
}
|
|
43
38
|
|
|
@@ -51,7 +46,7 @@ const IS_NEW_ARCH = globalThis.RN$Bridgeless === true
|
|
|
51
46
|
// TODO refactor with leader-thread code from `@livestore/common/leader-thread`
|
|
52
47
|
export const makePersistedAdapter =
|
|
53
48
|
(options: MakeDbOptions = {}): Adapter =>
|
|
54
|
-
(
|
|
49
|
+
(adapterArgs) =>
|
|
55
50
|
Effect.gen(function* () {
|
|
56
51
|
if (IS_NEW_ARCH === false) {
|
|
57
52
|
return yield* UnexpectedError.make({
|
|
@@ -61,7 +56,9 @@ export const makePersistedAdapter =
|
|
|
61
56
|
})
|
|
62
57
|
}
|
|
63
58
|
|
|
64
|
-
const {
|
|
59
|
+
const { schema, shutdown, devtoolsEnabled, storeId, bootStatusQueue, syncPayload } = adapterArgs
|
|
60
|
+
|
|
61
|
+
const { storage, clientId = yield* getDeviceId, sessionId = 'static', sync: syncOptions } = options
|
|
65
62
|
|
|
66
63
|
yield* Queue.offer(bootStatusQueue, { stage: 'loading' })
|
|
67
64
|
|
|
@@ -78,90 +75,64 @@ export const makePersistedAdapter =
|
|
|
78
75
|
Effect.forkScoped,
|
|
79
76
|
)
|
|
80
77
|
|
|
81
|
-
const
|
|
82
|
-
? yield* DevtoolsExpo.makeExpoDevtoolsConnectedMeshNode({
|
|
83
|
-
nodeName: `expo-${storeId}-${clientId}-${sessionId}`,
|
|
84
|
-
target: `devtools-${storeId}-${clientId}-${sessionId}`,
|
|
85
|
-
})
|
|
86
|
-
: undefined
|
|
78
|
+
const devtoolsUrl = getDevtoolsUrl()
|
|
87
79
|
|
|
88
80
|
const { leaderThread, initialSnapshot } = yield* makeLeaderThread({
|
|
89
81
|
storeId,
|
|
90
82
|
clientId,
|
|
91
|
-
sessionId,
|
|
92
83
|
schema,
|
|
93
84
|
makeSqliteDb,
|
|
94
85
|
syncOptions,
|
|
95
86
|
storage: storage ?? {},
|
|
96
87
|
devtoolsEnabled,
|
|
97
|
-
devtoolsWebmeshNode,
|
|
98
88
|
bootStatusQueue,
|
|
99
89
|
syncPayload,
|
|
90
|
+
devtoolsUrl,
|
|
100
91
|
})
|
|
101
92
|
|
|
102
93
|
const sqliteDb = yield* makeSqliteDb({ _tag: 'in-memory' })
|
|
103
94
|
sqliteDb.import(initialSnapshot)
|
|
104
95
|
|
|
105
|
-
const clientSession = {
|
|
106
|
-
|
|
96
|
+
const clientSession = yield* makeClientSession({
|
|
97
|
+
...adapterArgs,
|
|
107
98
|
lockStatus,
|
|
108
99
|
clientId,
|
|
109
100
|
sessionId,
|
|
110
101
|
leaderThread,
|
|
111
|
-
shutdown: () => Effect.dieMessage('TODO implement shutdown'),
|
|
112
102
|
sqliteDb,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
sessionInfo: Devtools.SessionInfo.SessionInfo.make({
|
|
125
|
-
clientId,
|
|
126
|
-
sessionId,
|
|
127
|
-
storeId,
|
|
128
|
-
schemaAlias: schema.devtools.alias,
|
|
129
|
-
}),
|
|
130
|
-
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
|
|
131
|
-
|
|
132
|
-
const storeDevtoolsChannel = yield* DevtoolsExpo.makeChannelForConnectedMeshNode({
|
|
133
|
-
target: `devtools-${storeId}-${clientId}-${sessionId}`,
|
|
134
|
-
node: devtoolsWebmeshNode!,
|
|
135
|
-
schema: { listen: Devtools.ClientSession.MessageToApp, send: Devtools.ClientSession.MessageFromApp },
|
|
136
|
-
channelType: 'clientSession',
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
yield* connectDevtoolsToStore(storeDevtoolsChannel)
|
|
140
|
-
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
|
|
141
|
-
}
|
|
103
|
+
webmeshMode: 'proxy',
|
|
104
|
+
connectWebmeshNode: Effect.fnUntraced(function* ({ webmeshNode }) {
|
|
105
|
+
if (devtoolsEnabled) {
|
|
106
|
+
yield* Webmesh.connectViaWebSocket({
|
|
107
|
+
node: webmeshNode,
|
|
108
|
+
url: devtoolsUrl,
|
|
109
|
+
openTimeout: 50,
|
|
110
|
+
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
|
|
111
|
+
}
|
|
112
|
+
}),
|
|
113
|
+
})
|
|
142
114
|
|
|
143
115
|
return clientSession
|
|
144
116
|
}).pipe(
|
|
145
117
|
Effect.mapError((cause) => (cause._tag === 'LiveStore.UnexpectedError' ? cause : new UnexpectedError({ cause }))),
|
|
118
|
+
Effect.provide(FetchHttpClient.layer),
|
|
146
119
|
Effect.tapCauseLogPretty,
|
|
147
120
|
)
|
|
148
121
|
|
|
149
122
|
const makeLeaderThread = ({
|
|
150
123
|
storeId,
|
|
151
124
|
clientId,
|
|
152
|
-
sessionId,
|
|
153
125
|
schema,
|
|
154
126
|
makeSqliteDb,
|
|
155
127
|
syncOptions,
|
|
156
128
|
storage,
|
|
157
129
|
devtoolsEnabled,
|
|
158
|
-
devtoolsWebmeshNode,
|
|
159
130
|
bootStatusQueue: bootStatusQueueClientSession,
|
|
160
131
|
syncPayload,
|
|
132
|
+
devtoolsUrl,
|
|
161
133
|
}: {
|
|
162
134
|
storeId: string
|
|
163
135
|
clientId: string
|
|
164
|
-
sessionId: string
|
|
165
136
|
schema: LiveStoreSchema
|
|
166
137
|
makeSqliteDb: MakeExpoSqliteDb
|
|
167
138
|
syncOptions: SyncOptions | undefined
|
|
@@ -169,9 +140,9 @@ const makeLeaderThread = ({
|
|
|
169
140
|
subDirectory?: string
|
|
170
141
|
}
|
|
171
142
|
devtoolsEnabled: boolean
|
|
172
|
-
devtoolsWebmeshNode: MeshNode | undefined
|
|
173
143
|
bootStatusQueue: Queue.Queue<BootStatus>
|
|
174
144
|
syncPayload: Schema.JsonValue | undefined
|
|
145
|
+
devtoolsUrl: string
|
|
175
146
|
}) =>
|
|
176
147
|
Effect.gen(function* () {
|
|
177
148
|
const subDirectory = storage.subDirectory ? storage.subDirectory.replace(/\/$/, '') + '/' : ''
|
|
@@ -188,12 +159,11 @@ const makeLeaderThread = ({
|
|
|
188
159
|
|
|
189
160
|
const devtoolsOptions = yield* makeDevtoolsOptions({
|
|
190
161
|
devtoolsEnabled,
|
|
162
|
+
devtoolsUrl,
|
|
191
163
|
dbState,
|
|
192
164
|
dbEventlog,
|
|
193
165
|
storeId,
|
|
194
166
|
clientId,
|
|
195
|
-
sessionId,
|
|
196
|
-
devtoolsWebmeshNode,
|
|
197
167
|
})
|
|
198
168
|
|
|
199
169
|
const layer = yield* Layer.memoize(
|
|
@@ -263,20 +233,18 @@ const makeLeaderThread = ({
|
|
|
263
233
|
|
|
264
234
|
const makeDevtoolsOptions = ({
|
|
265
235
|
devtoolsEnabled,
|
|
236
|
+
devtoolsUrl,
|
|
266
237
|
dbState,
|
|
267
238
|
dbEventlog,
|
|
268
239
|
storeId,
|
|
269
240
|
clientId,
|
|
270
|
-
sessionId,
|
|
271
|
-
devtoolsWebmeshNode,
|
|
272
241
|
}: {
|
|
273
242
|
devtoolsEnabled: boolean
|
|
243
|
+
devtoolsUrl: string
|
|
274
244
|
dbState: LeaderSqliteDb
|
|
275
245
|
dbEventlog: LeaderSqliteDb
|
|
276
246
|
storeId: string
|
|
277
247
|
clientId: string
|
|
278
|
-
sessionId: string
|
|
279
|
-
devtoolsWebmeshNode: MeshNode | undefined
|
|
280
248
|
}): Effect.Effect<DevtoolsOptions, UnexpectedError, Scope.Scope> =>
|
|
281
249
|
Effect.gen(function* () {
|
|
282
250
|
if (devtoolsEnabled === false) {
|
|
@@ -287,21 +255,40 @@ const makeDevtoolsOptions = ({
|
|
|
287
255
|
|
|
288
256
|
return {
|
|
289
257
|
enabled: true,
|
|
290
|
-
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
schema: { listen: Devtools.Leader.MessageToApp, send: Devtools.Leader.MessageFromApp },
|
|
295
|
-
channelType: 'leader',
|
|
296
|
-
})
|
|
297
|
-
|
|
298
|
-
return {
|
|
299
|
-
devtoolsWebChannel,
|
|
300
|
-
persistenceInfo: {
|
|
301
|
-
state: dbState.metadata.persistenceInfo,
|
|
302
|
-
eventlog: dbEventlog.metadata.persistenceInfo,
|
|
303
|
-
},
|
|
258
|
+
boot: Effect.gen(function* () {
|
|
259
|
+
const persistenceInfo = {
|
|
260
|
+
state: dbState.metadata.persistenceInfo,
|
|
261
|
+
eventlog: dbEventlog.metadata.persistenceInfo,
|
|
304
262
|
}
|
|
263
|
+
|
|
264
|
+
const node = yield* Webmesh.makeMeshNode(Devtools.makeNodeName.client.leader({ storeId, clientId }))
|
|
265
|
+
|
|
266
|
+
yield* Webmesh.connectViaWebSocket({
|
|
267
|
+
node,
|
|
268
|
+
url: devtoolsUrl,
|
|
269
|
+
openTimeout: 50,
|
|
270
|
+
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
|
|
271
|
+
|
|
272
|
+
return { node, persistenceInfo, mode: 'proxy' }
|
|
305
273
|
}),
|
|
306
274
|
}
|
|
307
275
|
})
|
|
276
|
+
|
|
277
|
+
const getDeviceId = Effect.gen(function* () {
|
|
278
|
+
if (RN.Platform.OS === 'android') {
|
|
279
|
+
return ExpoApplication.getAndroidId()
|
|
280
|
+
} else if (RN.Platform.OS === 'ios') {
|
|
281
|
+
const iosId = yield* Effect.promise(() => ExpoApplication.getIosIdForVendorAsync())
|
|
282
|
+
if (iosId === null) {
|
|
283
|
+
return shouldNeverHappen('getDeviceId: iosId is null')
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return iosId
|
|
287
|
+
} else {
|
|
288
|
+
return shouldNeverHappen(`getDeviceId: Unsupported platform: ${RN.Platform.OS}`)
|
|
289
|
+
}
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
const getDevtoolsUrl = () => {
|
|
293
|
+
return process.env.EXPO_PUBLIC_LIVESTORE_DEVTOOLS_URL ?? `http://localhost:4242`
|
|
294
|
+
}
|