@livestore/adapter-web 0.4.0-dev.8 → 0.4.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/README.md +5 -5
- package/dist/.tsbuildinfo +1 -1
- package/dist/in-memory/in-memory-adapter.d.ts +49 -5
- package/dist/in-memory/in-memory-adapter.d.ts.map +1 -1
- package/dist/in-memory/in-memory-adapter.js +77 -20
- package/dist/in-memory/in-memory-adapter.js.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/single-tab/mod.d.ts +15 -0
- package/dist/single-tab/mod.d.ts.map +1 -0
- package/dist/single-tab/mod.js +15 -0
- package/dist/single-tab/mod.js.map +1 -0
- package/dist/single-tab/single-tab-adapter.d.ts +108 -0
- package/dist/single-tab/single-tab-adapter.d.ts.map +1 -0
- package/dist/single-tab/single-tab-adapter.js +271 -0
- package/dist/single-tab/single-tab-adapter.js.map +1 -0
- package/dist/web-worker/client-session/client-session-devtools.d.ts +2 -2
- package/dist/web-worker/client-session/client-session-devtools.d.ts.map +1 -1
- package/dist/web-worker/client-session/client-session-devtools.js +20 -9
- package/dist/web-worker/client-session/client-session-devtools.js.map +1 -1
- package/dist/web-worker/client-session/persisted-adapter.d.ts +18 -0
- package/dist/web-worker/client-session/persisted-adapter.d.ts.map +1 -1
- package/dist/web-worker/client-session/persisted-adapter.js +141 -67
- package/dist/web-worker/client-session/persisted-adapter.js.map +1 -1
- package/dist/web-worker/client-session/sqlite-loader.d.ts +2 -0
- package/dist/web-worker/client-session/sqlite-loader.d.ts.map +1 -0
- package/dist/web-worker/client-session/sqlite-loader.js +16 -0
- package/dist/web-worker/client-session/sqlite-loader.js.map +1 -0
- package/dist/web-worker/common/persisted-sqlite.d.ts +13 -20
- package/dist/web-worker/common/persisted-sqlite.d.ts.map +1 -1
- package/dist/web-worker/common/persisted-sqlite.js +95 -102
- package/dist/web-worker/common/persisted-sqlite.js.map +1 -1
- package/dist/web-worker/common/shutdown-channel.d.ts +3 -2
- package/dist/web-worker/common/shutdown-channel.d.ts.map +1 -1
- package/dist/web-worker/common/shutdown-channel.js +2 -2
- package/dist/web-worker/common/shutdown-channel.js.map +1 -1
- package/dist/web-worker/common/worker-disconnect-channel.d.ts +2 -6
- package/dist/web-worker/common/worker-disconnect-channel.d.ts.map +1 -1
- package/dist/web-worker/common/worker-disconnect-channel.js +3 -2
- package/dist/web-worker/common/worker-disconnect-channel.js.map +1 -1
- package/dist/web-worker/common/worker-schema.d.ts +152 -58
- package/dist/web-worker/common/worker-schema.d.ts.map +1 -1
- package/dist/web-worker/common/worker-schema.js +55 -37
- package/dist/web-worker/common/worker-schema.js.map +1 -1
- package/dist/web-worker/leader-worker/make-leader-worker.d.ts +5 -3
- package/dist/web-worker/leader-worker/make-leader-worker.d.ts.map +1 -1
- package/dist/web-worker/leader-worker/make-leader-worker.js +99 -38
- package/dist/web-worker/leader-worker/make-leader-worker.js.map +1 -1
- package/dist/web-worker/shared-worker/make-shared-worker.d.ts +2 -1
- package/dist/web-worker/shared-worker/make-shared-worker.d.ts.map +1 -1
- package/dist/web-worker/shared-worker/make-shared-worker.js +62 -52
- package/dist/web-worker/shared-worker/make-shared-worker.js.map +1 -1
- package/package.json +56 -18
- package/src/in-memory/in-memory-adapter.ts +92 -26
- package/src/index.ts +15 -1
- package/src/single-tab/mod.ts +15 -0
- package/src/single-tab/single-tab-adapter.ts +499 -0
- package/src/web-worker/ambient.d.ts +7 -24
- package/src/web-worker/client-session/client-session-devtools.ts +32 -18
- package/src/web-worker/client-session/persisted-adapter.ts +199 -103
- package/src/web-worker/client-session/sqlite-loader.ts +19 -0
- package/src/web-worker/common/persisted-sqlite.ts +215 -170
- package/src/web-worker/common/shutdown-channel.ts +10 -3
- package/src/web-worker/common/worker-disconnect-channel.ts +10 -3
- package/src/web-worker/common/worker-schema.ts +78 -38
- package/src/web-worker/leader-worker/make-leader-worker.ts +149 -71
- package/src/web-worker/shared-worker/make-shared-worker.ts +78 -90
- package/dist/opfs-utils.d.ts +0 -5
- package/dist/opfs-utils.d.ts.map +0 -1
- package/dist/opfs-utils.js +0 -43
- package/dist/opfs-utils.js.map +0 -1
- package/src/opfs-utils.ts +0 -61
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
import { Devtools,
|
|
1
|
+
import { Devtools, isWorkerTransportError, LogConfig, liveStoreVersion, UnknownError } from '@livestore/common'
|
|
2
2
|
import * as DevtoolsWeb from '@livestore/devtools-web-common/web-channel'
|
|
3
3
|
import * as WebmeshWorker from '@livestore/devtools-web-common/worker'
|
|
4
4
|
import { isDevEnv, isNotUndefined, LS_DEV } from '@livestore/utils'
|
|
5
5
|
import {
|
|
6
|
-
BrowserWorker,
|
|
7
|
-
BrowserWorkerRunner,
|
|
8
6
|
Deferred,
|
|
9
7
|
Effect,
|
|
10
8
|
Exit,
|
|
11
9
|
FetchHttpClient,
|
|
12
10
|
identity,
|
|
13
11
|
Layer,
|
|
14
|
-
|
|
15
|
-
LogLevel,
|
|
16
|
-
ParseResult,
|
|
12
|
+
Option,
|
|
17
13
|
Ref,
|
|
18
14
|
Schema,
|
|
19
15
|
Scope,
|
|
@@ -21,9 +17,9 @@ import {
|
|
|
21
17
|
SubscriptionRef,
|
|
22
18
|
TaskTracing,
|
|
23
19
|
Worker,
|
|
24
|
-
WorkerError,
|
|
25
20
|
WorkerRunner,
|
|
26
21
|
} from '@livestore/utils/effect'
|
|
22
|
+
import { BrowserWorker, BrowserWorkerRunner } from '@livestore/utils/effect/browser'
|
|
27
23
|
|
|
28
24
|
import { makeShutdownChannel } from '../common/shutdown-channel.ts'
|
|
29
25
|
import * as WorkerSchema from '../common/worker-schema.ts'
|
|
@@ -42,15 +38,16 @@ navigator.locks.request(
|
|
|
42
38
|
async () => new Promise(() => {}),
|
|
43
39
|
)
|
|
44
40
|
|
|
45
|
-
if (isDevEnv()) {
|
|
41
|
+
if (isDevEnv() === true) {
|
|
46
42
|
globalThis.__debugLiveStoreUtils = {
|
|
47
43
|
blobUrl: (buffer: Uint8Array<ArrayBuffer>) =>
|
|
48
44
|
URL.createObjectURL(new Blob([buffer], { type: 'application/octet-stream' })),
|
|
49
|
-
runSync: (effect: Effect.Effect<
|
|
50
|
-
runFork: (effect: Effect.Effect<
|
|
45
|
+
runSync: <A, E>(effect: Effect.Effect<A, E>) => Effect.runSync(effect),
|
|
46
|
+
runFork: <A, E>(effect: Effect.Effect<A, E>) => Effect.runFork(effect),
|
|
51
47
|
}
|
|
52
48
|
}
|
|
53
49
|
|
|
50
|
+
// @effect-diagnostics-next-line anyUnknownInErrorContext:off -- `SerializedRunner.Handlers` uses `any` in the R channel, propagating as `unknown` in `HandlersContext`
|
|
54
51
|
const makeWorkerRunner = Effect.gen(function* () {
|
|
55
52
|
const leaderWorkerContextSubRef = yield* SubscriptionRef.make<
|
|
56
53
|
| {
|
|
@@ -60,22 +57,18 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
60
57
|
| undefined
|
|
61
58
|
>(undefined)
|
|
62
59
|
|
|
63
|
-
const initialMessagePayloadDeferredRef = yield* Deferred.make<
|
|
64
|
-
typeof WorkerSchema.SharedWorkerInitialMessagePayloadFromClientSession.Type
|
|
65
|
-
>().pipe(Effect.andThen(Ref.make))
|
|
66
|
-
|
|
67
60
|
const waitForWorker = SubscriptionRef.waitUntil(leaderWorkerContextSubRef, isNotUndefined).pipe(
|
|
68
61
|
Effect.map((_) => _.worker),
|
|
69
62
|
)
|
|
70
63
|
|
|
71
|
-
const forwardRequest = <
|
|
72
|
-
req:
|
|
73
|
-
):
|
|
74
|
-
|
|
75
|
-
: never =>
|
|
64
|
+
const forwardRequest = <A, I, E, EI, R>(
|
|
65
|
+
req: WorkerSchema.LeaderWorkerInnerRequest & Schema.WithResult<A, I, E, EI, R>,
|
|
66
|
+
): Effect.Effect<A, E, R> =>
|
|
67
|
+
// Forward the request to the active worker and convert transport errors to defects.
|
|
76
68
|
waitForWorker.pipe(
|
|
77
69
|
// Effect.logBefore(`forwardRequest: ${req._tag}`),
|
|
78
|
-
Effect.andThen((worker) => worker.executeEffect(req)
|
|
70
|
+
Effect.andThen((worker) => worker.executeEffect(req)),
|
|
71
|
+
Effect.catchIf(isWorkerTransportError, (e) => Effect.die(e)),
|
|
79
72
|
// Effect.tap((_) => Effect.log(`forwardRequest: ${req._tag}`, _)),
|
|
80
73
|
// Effect.tapError((cause) => Effect.logError(`forwardRequest err: ${req._tag}`, cause)),
|
|
81
74
|
Effect.interruptible,
|
|
@@ -83,27 +76,18 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
83
76
|
label: `@livestore/adapter-web:shared-worker:forwardRequest:${req._tag}`,
|
|
84
77
|
duration: 500,
|
|
85
78
|
}),
|
|
86
|
-
Effect.mapError((cause) =>
|
|
87
|
-
Schema.is(UnexpectedError)(cause)
|
|
88
|
-
? cause
|
|
89
|
-
: ParseResult.isParseError(cause) || Schema.is(WorkerError.WorkerError)(cause)
|
|
90
|
-
? new UnexpectedError({ cause })
|
|
91
|
-
: cause,
|
|
92
|
-
),
|
|
93
|
-
Effect.catchAllDefect((cause) => new UnexpectedError({ cause })),
|
|
94
79
|
Effect.tapCauseLogPretty,
|
|
95
|
-
)
|
|
80
|
+
)
|
|
96
81
|
|
|
97
|
-
const forwardRequestStream = <
|
|
98
|
-
req:
|
|
99
|
-
):
|
|
100
|
-
? Stream.Stream<A, UnexpectedError, never>
|
|
101
|
-
: never =>
|
|
82
|
+
const forwardRequestStream = <A, I, E, EI, R>(
|
|
83
|
+
req: WorkerSchema.LeaderWorkerInnerRequest & Schema.WithResult<A, I, E, EI, R>,
|
|
84
|
+
): Stream.Stream<A, E, R> =>
|
|
102
85
|
Effect.gen(function* () {
|
|
103
86
|
yield* Effect.logDebug(`forwardRequestStream: ${req._tag}`)
|
|
104
87
|
const { worker, scope } = yield* SubscriptionRef.waitUntil(leaderWorkerContextSubRef, isNotUndefined)
|
|
105
|
-
const stream = worker.execute(req)
|
|
106
|
-
|
|
88
|
+
const stream = worker.execute(req).pipe(
|
|
89
|
+
Stream.refineOrDie((e) => isWorkerTransportError(e) === true ? Option.none() : Option.some(e)),
|
|
90
|
+
)
|
|
107
91
|
// It seems the request stream is not automatically interrupted when the scope shuts down
|
|
108
92
|
// so we need to manually interrupt it when the scope shuts down
|
|
109
93
|
const shutdownDeferred = yield* Deferred.make<void>()
|
|
@@ -118,12 +102,10 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
118
102
|
return Stream.merge(stream, scopeShutdownStream, { haltStrategy: 'either' })
|
|
119
103
|
}).pipe(
|
|
120
104
|
Effect.interruptible,
|
|
121
|
-
UnexpectedError.mapToUnexpectedError,
|
|
122
105
|
Effect.tapCauseLogPretty,
|
|
123
106
|
Stream.unwrap,
|
|
124
107
|
Stream.ensuring(Effect.logDebug(`shutting down stream for ${req._tag}`)),
|
|
125
|
-
|
|
126
|
-
) as any
|
|
108
|
+
)
|
|
127
109
|
|
|
128
110
|
const resetCurrentWorkerCtx = Effect.gen(function* () {
|
|
129
111
|
const prevWorker = yield* SubscriptionRef.get(leaderWorkerContextSubRef)
|
|
@@ -142,62 +124,60 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
142
124
|
}
|
|
143
125
|
}).pipe(Effect.withSpan('@livestore/adapter-web:shared-worker:resetCurrentWorkerCtx'))
|
|
144
126
|
|
|
145
|
-
// const devtoolsWebBridge = yield* makeDevtoolsWebBridge
|
|
146
|
-
|
|
147
127
|
const reset = Effect.gen(function* () {
|
|
148
128
|
yield* Effect.logDebug('reset')
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
yield* Ref.set(initialMessagePayloadDeferredRef, initialMessagePayloadDeferred)
|
|
153
|
-
|
|
129
|
+
// Clear cached invariants so a fresh configuration can be accepted after shutdown
|
|
130
|
+
yield* Ref.set(invariantsRef, undefined)
|
|
131
|
+
// Tear down current leader worker context
|
|
154
132
|
yield* resetCurrentWorkerCtx
|
|
155
|
-
// yield* devtoolsWebBridge.reset
|
|
156
133
|
})
|
|
157
134
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const messageSchema = WorkerSchema.LeaderWorkerInnerInitialMessage.pipe(
|
|
170
|
-
Schema.omit('devtoolsEnabled', 'debugInstanceId'),
|
|
171
|
-
)
|
|
172
|
-
const isEqual = Schema.equivalence(messageSchema)
|
|
173
|
-
if (isEqual(initialMessage, previousInitialMessage.initialMessage) === false) {
|
|
174
|
-
const diff = Schema.debugDiff(messageSchema)(previousInitialMessage.initialMessage, initialMessage)
|
|
135
|
+
// Cache first-applied invariants to enforce stability across leader transitions
|
|
136
|
+
const InvariantsSchema = Schema.Struct({
|
|
137
|
+
storeId: Schema.String,
|
|
138
|
+
storageOptions: WorkerSchema.StorageType,
|
|
139
|
+
syncPayloadEncoded: Schema.UndefinedOr(Schema.JsonValue),
|
|
140
|
+
liveStoreVersion: Schema.Literal(liveStoreVersion),
|
|
141
|
+
devtoolsEnabled: Schema.Boolean,
|
|
142
|
+
})
|
|
143
|
+
type Invariants = typeof InvariantsSchema.Type
|
|
144
|
+
const invariantsRef = yield* Ref.make<Invariants | undefined>(undefined)
|
|
145
|
+
const sameInvariants = Schema.equivalence(InvariantsSchema)
|
|
175
146
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
payload: {
|
|
179
|
-
diff,
|
|
180
|
-
previousInitialMessage: previousInitialMessage.initialMessage,
|
|
181
|
-
newInitialMessage: initialMessage,
|
|
182
|
-
},
|
|
183
|
-
})
|
|
184
|
-
}
|
|
185
|
-
} else {
|
|
186
|
-
yield* Deferred.succeed(initialMessagePayloadDeferred, message.payload)
|
|
187
|
-
}
|
|
188
|
-
}),
|
|
147
|
+
// @effect-diagnostics-next-line anyUnknownInErrorContext:off -- `SerializedRunner.Handlers` uses `any` in the R channel
|
|
148
|
+
return WorkerRunner.layerSerialized(WorkerSchema.SharedWorkerRequest, {
|
|
189
149
|
// Whenever the client session leader changes (and thus creates a new leader thread), the new client session leader
|
|
190
150
|
// sends a new MessagePort to the shared worker which proxies messages to the new leader thread.
|
|
191
|
-
UpdateMessagePort: ({ port }) =>
|
|
151
|
+
UpdateMessagePort: ({ port, initial, liveStoreVersion: clientLiveStoreVersion }) =>
|
|
192
152
|
Effect.gen(function* () {
|
|
193
|
-
|
|
153
|
+
// Enforce invariants: storeId, storageOptions, syncPayloadEncoded, liveStoreVersion must remain stable
|
|
154
|
+
const invariants: Invariants = {
|
|
155
|
+
storeId: initial.storeId,
|
|
156
|
+
storageOptions: initial.storageOptions,
|
|
157
|
+
syncPayloadEncoded: initial.syncPayloadEncoded,
|
|
158
|
+
liveStoreVersion: clientLiveStoreVersion,
|
|
159
|
+
devtoolsEnabled: initial.devtoolsEnabled,
|
|
160
|
+
}
|
|
161
|
+
const prev = yield* Ref.get(invariantsRef)
|
|
162
|
+
// Early return on mismatch to keep happy path linear
|
|
163
|
+
if (prev !== undefined && sameInvariants(prev, invariants) === false) {
|
|
164
|
+
const diff = Schema.debugDiff(InvariantsSchema)(prev, invariants)
|
|
165
|
+
return yield* new UnknownError({
|
|
166
|
+
cause: 'Store invariants changed across leader transitions',
|
|
167
|
+
payload: { diff, previous: prev, next: invariants },
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
// First writer records invariants
|
|
171
|
+
if (prev === undefined) {
|
|
172
|
+
yield* Ref.set(invariantsRef, invariants)
|
|
173
|
+
}
|
|
194
174
|
|
|
195
175
|
yield* resetCurrentWorkerCtx
|
|
196
176
|
|
|
197
177
|
const scope = yield* Scope.make()
|
|
198
178
|
|
|
199
179
|
yield* Effect.gen(function* () {
|
|
200
|
-
const shutdownChannel = yield* makeShutdownChannel(
|
|
180
|
+
const shutdownChannel = yield* makeShutdownChannel(initial.storeId)
|
|
201
181
|
|
|
202
182
|
yield* shutdownChannel.listen.pipe(
|
|
203
183
|
Stream.flatten(),
|
|
@@ -212,7 +192,7 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
212
192
|
const worker = yield* Worker.makePoolSerialized<WorkerSchema.LeaderWorkerInnerRequest>({
|
|
213
193
|
size: 1,
|
|
214
194
|
concurrency: 100,
|
|
215
|
-
initialMessage: () =>
|
|
195
|
+
initialMessage: () => initial,
|
|
216
196
|
}).pipe(
|
|
217
197
|
Effect.provide(workerLayer),
|
|
218
198
|
Effect.withSpan('@livestore/adapter-web:shared-worker:makeWorkerProxyFromPort'),
|
|
@@ -220,7 +200,7 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
220
200
|
|
|
221
201
|
// Prepare the web mesh connection for leader worker to be able to connect to the devtools
|
|
222
202
|
const { node } = yield* WebmeshWorker.CacheService
|
|
223
|
-
const { storeId, clientId } =
|
|
203
|
+
const { storeId, clientId } = initial
|
|
224
204
|
|
|
225
205
|
yield* DevtoolsWeb.connectViaWorker({
|
|
226
206
|
node,
|
|
@@ -232,7 +212,6 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
232
212
|
}).pipe(Effect.tapCauseLogPretty, Scope.extend(scope), Effect.forkIn(scope))
|
|
233
213
|
}).pipe(
|
|
234
214
|
Effect.withSpan('@livestore/adapter-web:shared-worker:updateMessagePort'),
|
|
235
|
-
UnexpectedError.mapToUnexpectedError,
|
|
236
215
|
Effect.tapCauseLogPretty,
|
|
237
216
|
),
|
|
238
217
|
|
|
@@ -240,12 +219,16 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
240
219
|
BootStatusStream: forwardRequestStream,
|
|
241
220
|
PushToLeader: forwardRequest,
|
|
242
221
|
PullStream: forwardRequestStream,
|
|
222
|
+
StreamEvents: forwardRequestStream,
|
|
243
223
|
Export: forwardRequest,
|
|
244
224
|
GetRecreateSnapshot: forwardRequest,
|
|
245
225
|
ExportEventlog: forwardRequest,
|
|
246
226
|
Setup: forwardRequest,
|
|
247
227
|
GetLeaderSyncState: forwardRequest,
|
|
228
|
+
SyncStateStream: forwardRequestStream,
|
|
248
229
|
GetLeaderHead: forwardRequest,
|
|
230
|
+
GetNetworkStatus: forwardRequest,
|
|
231
|
+
NetworkStatusStream: forwardRequestStream,
|
|
249
232
|
Shutdown: forwardRequest,
|
|
250
233
|
ExtraDevtoolsMessage: forwardRequest,
|
|
251
234
|
|
|
@@ -254,7 +237,13 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
254
237
|
})
|
|
255
238
|
}).pipe(Layer.unwrapScoped)
|
|
256
239
|
|
|
257
|
-
export const makeWorker = () => {
|
|
240
|
+
export const makeWorker = (options?: LogConfig.WithLoggerOptions): void => {
|
|
241
|
+
const runtimeLayer = Layer.mergeAll(
|
|
242
|
+
FetchHttpClient.layer,
|
|
243
|
+
WebmeshWorker.CacheService.layer({ nodeName: DevtoolsWeb.makeNodeName.sharedWorker({ storeId }) }),
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
// @effect-diagnostics-next-line anyUnknownInErrorContext:off -- propagated from `makeWorkerRunner`
|
|
258
247
|
makeWorkerRunner.pipe(
|
|
259
248
|
Layer.provide(BrowserWorkerRunner.layer),
|
|
260
249
|
// WorkerRunner.launch,
|
|
@@ -262,13 +251,12 @@ export const makeWorker = () => {
|
|
|
262
251
|
Effect.scoped,
|
|
263
252
|
Effect.tapCauseLogPretty,
|
|
264
253
|
Effect.annotateLogs({ thread: self.name }),
|
|
265
|
-
Effect.provide(
|
|
266
|
-
|
|
267
|
-
Effect.provide(WebmeshWorker.CacheService.layer({ nodeName: DevtoolsWeb.makeNodeName.sharedWorker({ storeId }) })),
|
|
268
|
-
LS_DEV ? TaskTracing.withAsyncTaggingTracing((name) => (console as any).createTask(name)) : identity,
|
|
254
|
+
Effect.provide(runtimeLayer),
|
|
255
|
+
LS_DEV === true ? TaskTracing.withAsyncTaggingTracing((name) => (console as any).createTask(name)) : identity,
|
|
269
256
|
// TODO remove type-cast (currently needed to silence a tsc bug)
|
|
270
|
-
|
|
271
|
-
|
|
257
|
+
// @effect-diagnostics-next-line anyUnknownInErrorContext:off -- TSC bug workaround; the cast uses `any` as an intermediate
|
|
258
|
+
(_) => _ as any as Effect.Effect<void>,
|
|
259
|
+
LogConfig.withLoggerConfig(options, { threadName: self.name }),
|
|
272
260
|
Effect.runFork,
|
|
273
261
|
)
|
|
274
262
|
}
|
package/dist/opfs-utils.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export declare const rootHandlePromise: Promise<FileSystemDirectoryHandle>;
|
|
2
|
-
export declare const getDirHandle: (absDirPath: string | undefined) => Promise<FileSystemDirectoryHandle>;
|
|
3
|
-
export declare const printTree: (directoryHandle_?: FileSystemDirectoryHandle | Promise<FileSystemDirectoryHandle>, depth?: number, prefix?: string) => Promise<void>;
|
|
4
|
-
export declare const deleteAll: (directoryHandle: FileSystemDirectoryHandle) => Promise<void>;
|
|
5
|
-
//# sourceMappingURL=opfs-utils.d.ts.map
|
package/dist/opfs-utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"opfs-utils.d.ts","sourceRoot":"","sources":["../src/opfs-utils.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,iBAAiB,oCAYQ,CAAA;AAEtC,eAAO,MAAM,YAAY,GAAU,YAAY,MAAM,GAAG,SAAS,uCAWhE,CAAA;AAED,eAAO,MAAM,SAAS,GACpB,mBAAkB,yBAAyB,GAAG,OAAO,CAAC,yBAAyB,CAAqB,EACpG,QAAO,MAAiC,EACxC,eAAW,KACV,OAAO,CAAC,IAAI,CAgBd,CAAA;AAED,eAAO,MAAM,SAAS,GAAU,iBAAiB,yBAAyB,kBAMzE,CAAA"}
|
package/dist/opfs-utils.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// NOTE we're already firing off this promise call here since we'll need it anyway and need it cached
|
|
2
|
-
import { prettyBytes } from '@livestore/utils';
|
|
3
|
-
// To improve LiveStore compatibility with e.g. Node.js we're guarding for `navigator` / `navigator.storage` to be defined.
|
|
4
|
-
export const rootHandlePromise = typeof navigator === 'undefined' || navigator.storage === undefined
|
|
5
|
-
? // We're using a proxy here to make the promise reject lazy
|
|
6
|
-
new Proxy({}, {
|
|
7
|
-
get: () => Promise.reject(new Error(`Can't get OPFS root handle in this environment as navigator.storage is undefined`)),
|
|
8
|
-
})
|
|
9
|
-
: navigator.storage.getDirectory();
|
|
10
|
-
export const getDirHandle = async (absDirPath) => {
|
|
11
|
-
const rootHandle = await rootHandlePromise;
|
|
12
|
-
if (absDirPath === undefined)
|
|
13
|
-
return rootHandle;
|
|
14
|
-
let dirHandle = rootHandle;
|
|
15
|
-
const directoryStack = absDirPath?.split('/').filter(Boolean);
|
|
16
|
-
while (directoryStack.length > 0) {
|
|
17
|
-
dirHandle = await dirHandle.getDirectoryHandle(directoryStack.shift());
|
|
18
|
-
}
|
|
19
|
-
return dirHandle;
|
|
20
|
-
};
|
|
21
|
-
export const printTree = async (directoryHandle_ = rootHandlePromise, depth = Number.POSITIVE_INFINITY, prefix = '') => {
|
|
22
|
-
if (depth < 0)
|
|
23
|
-
return;
|
|
24
|
-
const directoryHandle = await directoryHandle_;
|
|
25
|
-
const entries = directoryHandle.values();
|
|
26
|
-
for await (const entry of entries) {
|
|
27
|
-
const isDirectory = entry.kind === 'directory';
|
|
28
|
-
const size = entry.kind === 'file' ? await entry.getFile().then((file) => prettyBytes(file.size)) : undefined;
|
|
29
|
-
console.log(`${prefix}${isDirectory ? '📁' : '📄'} ${entry.name} ${size ? `(${size})` : ''}`);
|
|
30
|
-
if (isDirectory) {
|
|
31
|
-
const nestedDirectoryHandle = await directoryHandle.getDirectoryHandle(entry.name);
|
|
32
|
-
await printTree(nestedDirectoryHandle, depth - 1, `${prefix} `);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
export const deleteAll = async (directoryHandle) => {
|
|
37
|
-
if (directoryHandle.kind !== 'directory')
|
|
38
|
-
return;
|
|
39
|
-
for await (const entryName of directoryHandle.keys()) {
|
|
40
|
-
await directoryHandle.removeEntry(entryName, { recursive: true });
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
//# sourceMappingURL=opfs-utils.js.map
|
package/dist/opfs-utils.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"opfs-utils.js","sourceRoot":"","sources":["../src/opfs-utils.ts"],"names":[],"mappings":"AAAA,qGAAqG;AAErG,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,2HAA2H;AAC3H,MAAM,CAAC,MAAM,iBAAiB,GAC5B,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,OAAO,KAAK,SAAS;IACjE,CAAC,CAAC,2DAA2D;QAC1D,IAAI,KAAK,CACR,EAAE,EACF;YACE,GAAG,EAAE,GAAG,EAAE,CACR,OAAO,CAAC,MAAM,CACZ,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAC9F;SACJ,CACQ;IACb,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,CAAA;AAEtC,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,UAA8B,EAAE,EAAE;IACnE,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAA;IAC1C,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,UAAU,CAAA;IAE/C,IAAI,SAAS,GAAG,UAAU,CAAA;IAC1B,MAAM,cAAc,GAAG,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC7D,OAAO,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,SAAS,GAAG,MAAM,SAAS,CAAC,kBAAkB,CAAC,cAAc,CAAC,KAAK,EAAG,CAAC,CAAA;IACzE,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAC5B,mBAAmF,iBAAiB,EACpG,QAAgB,MAAM,CAAC,iBAAiB,EACxC,MAAM,GAAG,EAAE,EACI,EAAE;IACjB,IAAI,KAAK,GAAG,CAAC;QAAE,OAAM;IAErB,MAAM,eAAe,GAAG,MAAM,gBAAgB,CAAA;IAC9C,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,CAAA;IAExC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAClC,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,KAAK,WAAW,CAAA;QAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAC7G,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAE7F,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,qBAAqB,GAAG,MAAM,eAAe,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAClF,MAAM,SAAS,CAAC,qBAAqB,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,MAAM,IAAI,CAAC,CAAA;QAClE,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,eAA0C,EAAE,EAAE;IAC5E,IAAI,eAAe,CAAC,IAAI,KAAK,WAAW;QAAE,OAAM;IAEhD,IAAI,KAAK,EAAE,MAAM,SAAS,IAAI,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC;QACrD,MAAM,eAAe,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACnE,CAAC;AACH,CAAC,CAAA"}
|
package/src/opfs-utils.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
// NOTE we're already firing off this promise call here since we'll need it anyway and need it cached
|
|
2
|
-
|
|
3
|
-
import { prettyBytes } from '@livestore/utils'
|
|
4
|
-
|
|
5
|
-
// To improve LiveStore compatibility with e.g. Node.js we're guarding for `navigator` / `navigator.storage` to be defined.
|
|
6
|
-
export const rootHandlePromise =
|
|
7
|
-
typeof navigator === 'undefined' || navigator.storage === undefined
|
|
8
|
-
? // We're using a proxy here to make the promise reject lazy
|
|
9
|
-
(new Proxy(
|
|
10
|
-
{},
|
|
11
|
-
{
|
|
12
|
-
get: () =>
|
|
13
|
-
Promise.reject(
|
|
14
|
-
new Error(`Can't get OPFS root handle in this environment as navigator.storage is undefined`),
|
|
15
|
-
),
|
|
16
|
-
},
|
|
17
|
-
) as never)
|
|
18
|
-
: navigator.storage.getDirectory()
|
|
19
|
-
|
|
20
|
-
export const getDirHandle = async (absDirPath: string | undefined) => {
|
|
21
|
-
const rootHandle = await rootHandlePromise
|
|
22
|
-
if (absDirPath === undefined) return rootHandle
|
|
23
|
-
|
|
24
|
-
let dirHandle = rootHandle
|
|
25
|
-
const directoryStack = absDirPath?.split('/').filter(Boolean)
|
|
26
|
-
while (directoryStack.length > 0) {
|
|
27
|
-
dirHandle = await dirHandle.getDirectoryHandle(directoryStack.shift()!)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return dirHandle
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const printTree = async (
|
|
34
|
-
directoryHandle_: FileSystemDirectoryHandle | Promise<FileSystemDirectoryHandle> = rootHandlePromise,
|
|
35
|
-
depth: number = Number.POSITIVE_INFINITY,
|
|
36
|
-
prefix = '',
|
|
37
|
-
): Promise<void> => {
|
|
38
|
-
if (depth < 0) return
|
|
39
|
-
|
|
40
|
-
const directoryHandle = await directoryHandle_
|
|
41
|
-
const entries = directoryHandle.values()
|
|
42
|
-
|
|
43
|
-
for await (const entry of entries) {
|
|
44
|
-
const isDirectory = entry.kind === 'directory'
|
|
45
|
-
const size = entry.kind === 'file' ? await entry.getFile().then((file) => prettyBytes(file.size)) : undefined
|
|
46
|
-
console.log(`${prefix}${isDirectory ? '📁' : '📄'} ${entry.name} ${size ? `(${size})` : ''}`)
|
|
47
|
-
|
|
48
|
-
if (isDirectory) {
|
|
49
|
-
const nestedDirectoryHandle = await directoryHandle.getDirectoryHandle(entry.name)
|
|
50
|
-
await printTree(nestedDirectoryHandle, depth - 1, `${prefix} `)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export const deleteAll = async (directoryHandle: FileSystemDirectoryHandle) => {
|
|
56
|
-
if (directoryHandle.kind !== 'directory') return
|
|
57
|
-
|
|
58
|
-
for await (const entryName of directoryHandle.keys()) {
|
|
59
|
-
await directoryHandle.removeEntry(entryName, { recursive: true })
|
|
60
|
-
}
|
|
61
|
-
}
|