@livestore/adapter-expo 0.3.0-dev.18 → 0.3.0-dev.21
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 +15 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +133 -151
- package/dist/index.js.map +1 -1
- package/dist/make-sqlite-db.d.ts +20 -0
- package/dist/make-sqlite-db.d.ts.map +1 -0
- package/dist/make-sqlite-db.js +164 -0
- package/dist/make-sqlite-db.js.map +1 -0
- package/dist/shutdown-channel.d.ts +3 -0
- package/dist/shutdown-channel.d.ts.map +1 -0
- package/dist/shutdown-channel.js +8 -0
- package/dist/shutdown-channel.js.map +1 -0
- package/package.json +11 -6
- package/src/index.ts +253 -223
- package/src/make-sqlite-db.ts +201 -0
- package/src/shutdown-channel.ts +9 -0
- package/tsconfig.json +6 -1
- package/dist/common.d.ts +0 -13
- package/dist/common.d.ts.map +0 -1
- package/dist/common.js +0 -100
- package/dist/common.js.map +0 -1
- package/dist/devtools.d.ts +0 -22
- package/dist/devtools.d.ts.map +0 -1
- package/dist/devtools.js +0 -177
- package/dist/devtools.js.map +0 -1
- package/src/common.ts +0 -115
- package/src/devtools.ts +0 -292
package/src/common.ts
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import type { PreparedStatement, SqliteDb } from '@livestore/common'
|
|
2
|
-
import { base64, shouldNeverHappen } from '@livestore/utils'
|
|
3
|
-
import { Effect } from '@livestore/utils/effect'
|
|
4
|
-
import * as ExpoFS from 'expo-file-system'
|
|
5
|
-
import type * as SQLite from 'expo-sqlite'
|
|
6
|
-
|
|
7
|
-
export const makeSqliteDb = (db: SQLite.SQLiteDatabase): SqliteDb => {
|
|
8
|
-
const stmts: PreparedStatement[] = []
|
|
9
|
-
|
|
10
|
-
const sqliteDb: SqliteDb<any> = {
|
|
11
|
-
metadata: { fileName: db.databasePath },
|
|
12
|
-
_tag: 'SqliteDb',
|
|
13
|
-
prepare: (queryStr) => {
|
|
14
|
-
try {
|
|
15
|
-
const dbStmt = db.prepareSync(queryStr)
|
|
16
|
-
const stmt = {
|
|
17
|
-
execute: (bindValues) => {
|
|
18
|
-
// console.log('execute', queryStr, bindValues)
|
|
19
|
-
const res = dbStmt.executeSync(bindValues ?? ([] as any))
|
|
20
|
-
res.resetSync()
|
|
21
|
-
return () => res.changes
|
|
22
|
-
},
|
|
23
|
-
select: (bindValues) => {
|
|
24
|
-
const res = dbStmt.executeSync(bindValues ?? ([] as any))
|
|
25
|
-
try {
|
|
26
|
-
return res.getAllSync() as any
|
|
27
|
-
} finally {
|
|
28
|
-
res.resetSync()
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
finalize: () => dbStmt.finalizeSync(),
|
|
32
|
-
sql: queryStr,
|
|
33
|
-
} satisfies PreparedStatement
|
|
34
|
-
stmts.push(stmt)
|
|
35
|
-
return stmt
|
|
36
|
-
} catch (e) {
|
|
37
|
-
console.error(`Error preparing statement: ${queryStr}`, e)
|
|
38
|
-
return shouldNeverHappen(`Error preparing statement: ${queryStr}`)
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
execute: (queryStr, bindValues) => {
|
|
42
|
-
const stmt = db.prepareSync(queryStr)
|
|
43
|
-
try {
|
|
44
|
-
const res = stmt.executeSync(bindValues ?? ([] as any))
|
|
45
|
-
return () => res.changes
|
|
46
|
-
} finally {
|
|
47
|
-
stmt.finalizeSync()
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
export: () => {
|
|
51
|
-
return db.serializeSync()
|
|
52
|
-
},
|
|
53
|
-
select: (queryStr, bindValues) => {
|
|
54
|
-
const stmt = sqliteDb.prepare(queryStr)
|
|
55
|
-
const res = stmt.select(bindValues)
|
|
56
|
-
stmt.finalize()
|
|
57
|
-
return res as any
|
|
58
|
-
},
|
|
59
|
-
// TODO
|
|
60
|
-
destroy: () => {},
|
|
61
|
-
close: () => {
|
|
62
|
-
for (const stmt of stmts) {
|
|
63
|
-
stmt.finalize()
|
|
64
|
-
}
|
|
65
|
-
return db.closeSync()
|
|
66
|
-
},
|
|
67
|
-
import: () => {
|
|
68
|
-
throw new Error('Not implemented')
|
|
69
|
-
// TODO properly implement this as it seems to require importing to a temporary in-memory db,
|
|
70
|
-
// save it to a file, and then reopen the DB from that file? (see `overwriteDbFile` below)
|
|
71
|
-
},
|
|
72
|
-
session: () => {
|
|
73
|
-
return {
|
|
74
|
-
changeset: () => new Uint8Array(),
|
|
75
|
-
finish: () => {},
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
makeChangeset: (data) => {
|
|
79
|
-
return {
|
|
80
|
-
invert: () => {
|
|
81
|
-
return sqliteDb.makeChangeset(data)
|
|
82
|
-
},
|
|
83
|
-
apply: () => {
|
|
84
|
-
// TODO
|
|
85
|
-
},
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
} satisfies SqliteDb
|
|
89
|
-
|
|
90
|
-
return sqliteDb
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export type DbPairRef = {
|
|
94
|
-
current:
|
|
95
|
-
| {
|
|
96
|
-
db: SQLite.SQLiteDatabase
|
|
97
|
-
sqliteDb: SqliteDb
|
|
98
|
-
}
|
|
99
|
-
| undefined
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export const getDbFilePath = (dbName: string) => {
|
|
103
|
-
return `${ExpoFS.documentDirectory}SQLite/${dbName}`
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export const overwriteDbFile = (dbName: string, data: Uint8Array) =>
|
|
107
|
-
Effect.gen(function* () {
|
|
108
|
-
const path = getDbFilePath(dbName)
|
|
109
|
-
|
|
110
|
-
yield* Effect.promise(() => ExpoFS.deleteAsync(path, { idempotent: true }))
|
|
111
|
-
|
|
112
|
-
// TODO avoid converting to string once the ExpoFS API supports binary data
|
|
113
|
-
const b64String = base64.encode(data)
|
|
114
|
-
yield* Effect.promise(() => ExpoFS.writeAsStringAsync(path, b64String, { encoding: ExpoFS.EncodingType.Base64 }))
|
|
115
|
-
})
|
package/src/devtools.ts
DELETED
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
import type { ClientSession, ConnectDevtoolsToStore } from '@livestore/common'
|
|
3
|
-
import {
|
|
4
|
-
Devtools,
|
|
5
|
-
IntentionalShutdownCause,
|
|
6
|
-
liveStoreVersion,
|
|
7
|
-
MUTATION_LOG_META_TABLE,
|
|
8
|
-
SCHEMA_META_TABLE,
|
|
9
|
-
SCHEMA_MUTATIONS_META_TABLE,
|
|
10
|
-
UnexpectedError,
|
|
11
|
-
} from '@livestore/common'
|
|
12
|
-
import type { PullQueueItem } from '@livestore/common/leader-thread'
|
|
13
|
-
import type { LiveStoreSchema, MutationEvent } from '@livestore/common/schema'
|
|
14
|
-
import { makeExpoDevtoolsChannel } from '@livestore/devtools-expo-common/web-channel'
|
|
15
|
-
import type { ParseResult, Scope } from '@livestore/utils/effect'
|
|
16
|
-
import { Cause, Effect, Queue, Schema, Stream, SubscriptionRef, WebChannel } from '@livestore/utils/effect'
|
|
17
|
-
import * as SQLite from 'expo-sqlite'
|
|
18
|
-
|
|
19
|
-
import type { DbPairRef } from './common.js'
|
|
20
|
-
import { makeSqliteDb, overwriteDbFile } from './common.js'
|
|
21
|
-
|
|
22
|
-
export type BootedDevtools = {
|
|
23
|
-
onMutation: ({
|
|
24
|
-
mutationEventEncoded,
|
|
25
|
-
}: {
|
|
26
|
-
mutationEventEncoded: MutationEvent.AnyEncoded
|
|
27
|
-
}) => Effect.Effect<void, UnexpectedError, never>
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const bootDevtools = ({
|
|
31
|
-
connectDevtoolsToStore,
|
|
32
|
-
clientSession,
|
|
33
|
-
schema,
|
|
34
|
-
shutdown,
|
|
35
|
-
dbRef,
|
|
36
|
-
dbMutationLogRef,
|
|
37
|
-
incomingSyncMutationsQueue,
|
|
38
|
-
}: {
|
|
39
|
-
connectDevtoolsToStore: ConnectDevtoolsToStore
|
|
40
|
-
clientSession: ClientSession
|
|
41
|
-
schema: LiveStoreSchema
|
|
42
|
-
dbRef: DbPairRef
|
|
43
|
-
dbMutationLogRef: DbPairRef
|
|
44
|
-
shutdown: (cause: Cause.Cause<UnexpectedError | IntentionalShutdownCause>) => void
|
|
45
|
-
incomingSyncMutationsQueue: Queue.Queue<PullQueueItem>
|
|
46
|
-
}): Effect.Effect<BootedDevtools, UnexpectedError | ParseResult.ParseError, Scope.Scope> =>
|
|
47
|
-
Effect.gen(function* () {
|
|
48
|
-
const appHostId = 'expo'
|
|
49
|
-
const isLeader = true
|
|
50
|
-
|
|
51
|
-
const expoDevtoolsChannel = yield* makeExpoDevtoolsChannel({
|
|
52
|
-
listenSchema: Schema.Union(Devtools.MessageToApp, Devtools.MessageToApp),
|
|
53
|
-
sendSchema: Schema.Union(Devtools.MessageFromApp, Devtools.MessageFromApp),
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
const isConnected = yield* SubscriptionRef.make(false)
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Used to forward messages from `expoDevtoolsChannel` to a "filtered" `storeDevtoolsChannel`
|
|
60
|
-
* which is expected by the `connectDevtoolsToStore` function.
|
|
61
|
-
*/
|
|
62
|
-
const storeDevtoolsChannelProxy = yield* WebChannel.queueChannelProxy({
|
|
63
|
-
schema: { listen: Devtools.MessageToApp, send: Devtools.MessageFromApp },
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
yield* storeDevtoolsChannelProxy.sendQueue.pipe(
|
|
67
|
-
Stream.fromQueue,
|
|
68
|
-
Stream.tap((msg) => expoDevtoolsChannel.send(msg)),
|
|
69
|
-
Stream.runDrain,
|
|
70
|
-
Effect.forkScoped,
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
const getDatabaseName = (db: DbPairRef) =>
|
|
74
|
-
db.current!.db.databasePath.slice(db.current!.db.databasePath.lastIndexOf('/') + 1)
|
|
75
|
-
|
|
76
|
-
yield* expoDevtoolsChannel.listen.pipe(
|
|
77
|
-
Stream.flatten(),
|
|
78
|
-
Stream.tap((decodedEvent) =>
|
|
79
|
-
Effect.gen(function* () {
|
|
80
|
-
if (Schema.is(Devtools.MessageToApp)(decodedEvent)) {
|
|
81
|
-
yield* storeDevtoolsChannelProxy.listenQueue.pipe(Queue.offer(decodedEvent))
|
|
82
|
-
return
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// if (decodedEvent._tag === 'LSD.DevtoolsReady') {
|
|
86
|
-
// if ((yield* isConnected.get) === false) {
|
|
87
|
-
// // yield* expoDevtoolsChannel.send(Devtools.AppHostReady.make({ appHostId, liveStoreVersion, isLeader }))
|
|
88
|
-
// }
|
|
89
|
-
|
|
90
|
-
// return
|
|
91
|
-
// }
|
|
92
|
-
|
|
93
|
-
// if (decodedEvent._tag === 'LSD.DevtoolsConnected') {
|
|
94
|
-
// if (yield* isConnected.get) {
|
|
95
|
-
// console.warn('devtools already connected')
|
|
96
|
-
// return
|
|
97
|
-
// }
|
|
98
|
-
|
|
99
|
-
// yield* connectDevtoolsToStore(storeDevtoolsChannelProxy.webChannel).pipe(
|
|
100
|
-
// Effect.tapCauseLogPretty,
|
|
101
|
-
// Effect.forkScoped,
|
|
102
|
-
// )
|
|
103
|
-
|
|
104
|
-
// yield* SubscriptionRef.set(isConnected, true)
|
|
105
|
-
// return
|
|
106
|
-
// }
|
|
107
|
-
|
|
108
|
-
// if (decodedEvent._tag === 'LSD.Disconnect') {
|
|
109
|
-
// yield* SubscriptionRef.set(isConnected, false)
|
|
110
|
-
|
|
111
|
-
// // yield* disconnect
|
|
112
|
-
|
|
113
|
-
// // TODO is there a better place for this?
|
|
114
|
-
// yield* expoDevtoolsChannel.send(Devtools.AppHostReady.make({ appHostId, liveStoreVersion, isLeader }))
|
|
115
|
-
|
|
116
|
-
// return
|
|
117
|
-
// }
|
|
118
|
-
|
|
119
|
-
const { requestId } = decodedEvent
|
|
120
|
-
const reqPayload = { requestId, appHostId, liveStoreVersion }
|
|
121
|
-
|
|
122
|
-
switch (decodedEvent._tag) {
|
|
123
|
-
case 'LSD.Ping': {
|
|
124
|
-
yield* expoDevtoolsChannel.send(Devtools.Pong.make({ ...reqPayload }))
|
|
125
|
-
return
|
|
126
|
-
}
|
|
127
|
-
case 'LSD.Leader.SnapshotReq': {
|
|
128
|
-
const data = yield* clientSession.leaderThread.export
|
|
129
|
-
|
|
130
|
-
yield* expoDevtoolsChannel.send(Devtools.SnapshotRes.make({ snapshot: data!, ...reqPayload }))
|
|
131
|
-
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
case 'LSD.Leader.LoadDatabaseFileReq': {
|
|
135
|
-
const { data } = decodedEvent
|
|
136
|
-
|
|
137
|
-
let tableNames: Set<string>
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
const tmpExpoDb = SQLite.deserializeDatabaseSync(data)
|
|
141
|
-
const tmpDb = makeSqliteDb(tmpExpoDb)
|
|
142
|
-
const tableNameResults = tmpDb.select<{ name: string }>(
|
|
143
|
-
`select name from sqlite_master where type = 'table'`,
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
tableNames = new Set(tableNameResults.map((_) => _.name))
|
|
147
|
-
|
|
148
|
-
tmpExpoDb.closeSync()
|
|
149
|
-
} catch (e) {
|
|
150
|
-
yield* expoDevtoolsChannel.send(
|
|
151
|
-
Devtools.LoadDatabaseFileRes.make({ ...reqPayload, status: 'unsupported-file' }),
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
console.error(e)
|
|
155
|
-
|
|
156
|
-
return
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (tableNames.has(MUTATION_LOG_META_TABLE)) {
|
|
160
|
-
// yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
|
|
161
|
-
|
|
162
|
-
dbMutationLogRef.current!.db.closeSync()
|
|
163
|
-
|
|
164
|
-
yield* overwriteDbFile(getDatabaseName(dbMutationLogRef), data)
|
|
165
|
-
|
|
166
|
-
dbMutationLogRef.current = undefined
|
|
167
|
-
|
|
168
|
-
dbRef.current!.db.closeSync()
|
|
169
|
-
SQLite.deleteDatabaseSync(getDatabaseName(dbRef))
|
|
170
|
-
} else if (tableNames.has(SCHEMA_META_TABLE) && tableNames.has(SCHEMA_MUTATIONS_META_TABLE)) {
|
|
171
|
-
// yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
|
|
172
|
-
|
|
173
|
-
// yield* db.import(data)
|
|
174
|
-
|
|
175
|
-
dbRef.current!.db.closeSync()
|
|
176
|
-
|
|
177
|
-
yield* overwriteDbFile(getDatabaseName(dbRef), data)
|
|
178
|
-
} else {
|
|
179
|
-
yield* expoDevtoolsChannel.send(
|
|
180
|
-
Devtools.LoadDatabaseFileRes.make({ ...reqPayload, status: 'unsupported-database' }),
|
|
181
|
-
)
|
|
182
|
-
return
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
yield* expoDevtoolsChannel.send(Devtools.LoadDatabaseFileRes.make({ ...reqPayload, status: 'ok' }))
|
|
186
|
-
|
|
187
|
-
yield* shutdown(Cause.fail(IntentionalShutdownCause.make({ reason: 'devtools-import' })))
|
|
188
|
-
|
|
189
|
-
return
|
|
190
|
-
}
|
|
191
|
-
case 'LSD.Leader.ResetAllDataReq': {
|
|
192
|
-
const { mode } = decodedEvent
|
|
193
|
-
|
|
194
|
-
dbRef.current!.db.closeSync()
|
|
195
|
-
SQLite.deleteDatabaseSync(getDatabaseName(dbRef))
|
|
196
|
-
|
|
197
|
-
if (mode === 'all-data') {
|
|
198
|
-
dbMutationLogRef.current!.db.closeSync()
|
|
199
|
-
SQLite.deleteDatabaseSync(getDatabaseName(dbMutationLogRef))
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
yield* expoDevtoolsChannel.send(Devtools.ResetAllDataRes.make({ ...reqPayload }))
|
|
203
|
-
|
|
204
|
-
yield* shutdown(Cause.fail(IntentionalShutdownCause.make({ reason: 'devtools-reset' })))
|
|
205
|
-
|
|
206
|
-
return
|
|
207
|
-
}
|
|
208
|
-
case 'LSD.Leader.DatabaseFileInfoReq': {
|
|
209
|
-
const dbSizeQuery = `SELECT page_count * page_size as size FROM pragma_page_count(), pragma_page_size();`
|
|
210
|
-
const dbFileSize = dbRef.current!.db.prepareSync(dbSizeQuery).executeSync<any>().getFirstSync()!
|
|
211
|
-
.size as number
|
|
212
|
-
const mutationLogFileSize = dbMutationLogRef
|
|
213
|
-
.current!.db.prepareSync(dbSizeQuery)
|
|
214
|
-
.executeSync<any>()
|
|
215
|
-
.getFirstSync()!.size as number
|
|
216
|
-
|
|
217
|
-
yield* expoDevtoolsChannel.send(
|
|
218
|
-
Devtools.DatabaseFileInfoRes.make({
|
|
219
|
-
readModel: { fileSize: dbFileSize, persistenceInfo: { fileName: 'livestore.db' } },
|
|
220
|
-
mutationLog: {
|
|
221
|
-
fileSize: mutationLogFileSize,
|
|
222
|
-
persistenceInfo: { fileName: 'livestore-mutationlog.db' },
|
|
223
|
-
},
|
|
224
|
-
...reqPayload,
|
|
225
|
-
}),
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
return
|
|
229
|
-
}
|
|
230
|
-
case 'LSD.Leader.MutationLogReq': {
|
|
231
|
-
const mutationLog = yield* clientSession.leaderThread.getMutationLogData
|
|
232
|
-
|
|
233
|
-
yield* expoDevtoolsChannel.send(Devtools.MutationLogRes.make({ mutationLog, ...reqPayload }))
|
|
234
|
-
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
case 'LSD.Leader.RunMutationReq': {
|
|
238
|
-
const { mutationEventEncoded: mutationEventEncoded_ } = decodedEvent
|
|
239
|
-
const mutationDef = schema.mutations.get(mutationEventEncoded_.mutation)!
|
|
240
|
-
// const nextMutationEventIdPair = clientSession.mutations.nextMutationEventIdPair({
|
|
241
|
-
// clientOnly: mutationDef.options.clientOnly,
|
|
242
|
-
// })
|
|
243
|
-
|
|
244
|
-
// const mutationEventEncoded = new MutationEvent.EncodedWithMeta({
|
|
245
|
-
// ...mutationEventEncoded_,
|
|
246
|
-
// // ...nextMutationEventIdPair,
|
|
247
|
-
// })
|
|
248
|
-
|
|
249
|
-
// const mutationEventDecoded = yield* Schema.decode(mutationEventSchema)(mutationEventEncoded)
|
|
250
|
-
// yield* Queue.offer(incomingSyncMutationsQueue, {
|
|
251
|
-
// payload: { _tag: 'upstream-advance', newEvents: [mutationEventEncoded] },
|
|
252
|
-
// remaining: 0,
|
|
253
|
-
// })
|
|
254
|
-
|
|
255
|
-
// const mutationDef =
|
|
256
|
-
// schema.mutations.get(mutationEventEncoded.mutation) ??
|
|
257
|
-
// shouldNeverHappen(`Unknown mutation: ${mutationEventEncoded.mutation}`)
|
|
258
|
-
|
|
259
|
-
// yield* clientSession.mutations.push([mutationEventEncoded])
|
|
260
|
-
|
|
261
|
-
yield* expoDevtoolsChannel.send(Devtools.RunMutationRes.make({ ...reqPayload }))
|
|
262
|
-
|
|
263
|
-
return
|
|
264
|
-
}
|
|
265
|
-
case 'LSD.Leader.SyncingInfoReq': {
|
|
266
|
-
const syncingInfo = Devtools.SyncingInfo.make({
|
|
267
|
-
enabled: false,
|
|
268
|
-
metadata: {},
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
yield* expoDevtoolsChannel.send(Devtools.SyncingInfoRes.make({ syncingInfo, ...reqPayload }))
|
|
272
|
-
|
|
273
|
-
return
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}),
|
|
277
|
-
),
|
|
278
|
-
Stream.runDrain,
|
|
279
|
-
Effect.tapCauseLogPretty,
|
|
280
|
-
Effect.forkScoped,
|
|
281
|
-
)
|
|
282
|
-
// yield* expoDevtoolsChannel.send(Devtools.AppHostReady.make({ appHostId, isLeader, liveStoreVersion }))
|
|
283
|
-
|
|
284
|
-
const onMutation = ({ mutationEventEncoded }: { mutationEventEncoded: MutationEvent.AnyEncoded }) =>
|
|
285
|
-
expoDevtoolsChannel
|
|
286
|
-
.send(Devtools.MutationBroadcast.make({ mutationEventEncoded, liveStoreVersion }))
|
|
287
|
-
.pipe(UnexpectedError.mapToUnexpectedError)
|
|
288
|
-
|
|
289
|
-
return {
|
|
290
|
-
onMutation,
|
|
291
|
-
}
|
|
292
|
-
}).pipe(Effect.withSpan('@livestore/adapter-expo:bootDevtools'))
|