@effect/platform-browser 4.0.0-beta.5 → 4.0.0-beta.51
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/BrowserHttpClient.d.ts +3 -3
- package/dist/BrowserHttpClient.d.ts.map +1 -1
- package/dist/BrowserHttpClient.js +11 -6
- package/dist/BrowserHttpClient.js.map +1 -1
- package/dist/BrowserPersistence.d.ts +17 -0
- package/dist/BrowserPersistence.d.ts.map +1 -0
- package/dist/BrowserPersistence.js +187 -0
- package/dist/BrowserPersistence.js.map +1 -0
- package/dist/BrowserWorkerRunner.js +1 -1
- package/dist/BrowserWorkerRunner.js.map +1 -1
- package/dist/Clipboard.d.ts +6 -3
- package/dist/Clipboard.d.ts.map +1 -1
- package/dist/Clipboard.js +2 -2
- package/dist/Clipboard.js.map +1 -1
- package/dist/Geolocation.d.ts +6 -6
- package/dist/Geolocation.d.ts.map +1 -1
- package/dist/Geolocation.js +2 -2
- package/dist/Geolocation.js.map +1 -1
- package/dist/IndexedDb.d.ts +50 -0
- package/dist/IndexedDb.d.ts.map +1 -0
- package/dist/IndexedDb.js +65 -0
- package/dist/IndexedDb.js.map +1 -0
- package/dist/IndexedDbDatabase.d.ts +105 -0
- package/dist/IndexedDbDatabase.d.ts.map +1 -0
- package/dist/IndexedDbDatabase.js +321 -0
- package/dist/IndexedDbDatabase.js.map +1 -0
- package/dist/IndexedDbQueryBuilder.d.ts +342 -0
- package/dist/IndexedDbQueryBuilder.d.ts.map +1 -0
- package/dist/IndexedDbQueryBuilder.js +869 -0
- package/dist/IndexedDbQueryBuilder.js.map +1 -0
- package/dist/IndexedDbTable.d.ts +109 -0
- package/dist/IndexedDbTable.d.ts.map +1 -0
- package/dist/IndexedDbTable.js +38 -0
- package/dist/IndexedDbTable.js.map +1 -0
- package/dist/IndexedDbVersion.d.ts +50 -0
- package/dist/IndexedDbVersion.d.ts.map +1 -0
- package/dist/IndexedDbVersion.js +23 -0
- package/dist/IndexedDbVersion.js.map +1 -0
- package/dist/Permissions.d.ts +8 -5
- package/dist/Permissions.d.ts.map +1 -1
- package/dist/Permissions.js +2 -2
- package/dist/Permissions.js.map +1 -1
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/BrowserHttpClient.ts +17 -10
- package/src/BrowserPersistence.ts +306 -0
- package/src/BrowserWorkerRunner.ts +1 -1
- package/src/Clipboard.ts +2 -2
- package/src/Geolocation.ts +2 -2
- package/src/IndexedDb.ts +97 -0
- package/src/IndexedDbDatabase.ts +631 -0
- package/src/IndexedDbQueryBuilder.ts +1890 -0
- package/src/IndexedDbTable.ts +203 -0
- package/src/IndexedDbVersion.ts +89 -0
- package/src/Permissions.ts +2 -2
- package/src/index.ts +30 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import type * as Arr from "effect/Array"
|
|
5
|
+
import * as Clock from "effect/Clock"
|
|
6
|
+
import type * as Duration from "effect/Duration"
|
|
7
|
+
import * as Effect from "effect/Effect"
|
|
8
|
+
import * as Layer from "effect/Layer"
|
|
9
|
+
import * as Persistence from "effect/unstable/persistence/Persistence"
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @since 1.0.0
|
|
13
|
+
* @category layers
|
|
14
|
+
*/
|
|
15
|
+
export const layerBackingIndexedDb = (options?: {
|
|
16
|
+
readonly database?: string | undefined
|
|
17
|
+
}): Layer.Layer<Persistence.BackingPersistence> =>
|
|
18
|
+
Layer.effect(Persistence.BackingPersistence)(Effect.gen(function*() {
|
|
19
|
+
const db = yield* Effect.acquireRelease(
|
|
20
|
+
openDatabase(options?.database ?? defaultDatabase),
|
|
21
|
+
(db) => Effect.sync(() => db.close())
|
|
22
|
+
).pipe(Effect.orDie)
|
|
23
|
+
|
|
24
|
+
return Persistence.BackingPersistence.of({
|
|
25
|
+
make: Effect.fnUntraced(function*(storeId) {
|
|
26
|
+
const clock = yield* Clock.Clock
|
|
27
|
+
return {
|
|
28
|
+
get: (key) => get(db, clock, storeId, key),
|
|
29
|
+
getMany: (keys) => getMany(db, clock, storeId, keys),
|
|
30
|
+
set: (key, value, ttl) => set(db, clock, storeId, key, value, ttl),
|
|
31
|
+
setMany: (entries) => setMany(db, clock, storeId, entries),
|
|
32
|
+
remove: (key) => remove(db, storeId, key),
|
|
33
|
+
clear: clear(db, storeId)
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
}))
|
|
38
|
+
|
|
39
|
+
const defaultDatabase = "effect_persistence"
|
|
40
|
+
const databaseVersion = 1
|
|
41
|
+
const entriesStoreName = "entries"
|
|
42
|
+
const storeIdIndexName = "storeId"
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @since 1.0.0
|
|
46
|
+
* @category layers
|
|
47
|
+
*/
|
|
48
|
+
export const layerIndexedDb = (options?: {
|
|
49
|
+
readonly database?: string | undefined
|
|
50
|
+
}): Layer.Layer<Persistence.Persistence> =>
|
|
51
|
+
Persistence.layer.pipe(
|
|
52
|
+
Layer.provide(layerBackingIndexedDb(options))
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
const openDatabase = (database: string): Effect.Effect<IDBDatabase, Persistence.PersistenceError> =>
|
|
56
|
+
Effect.gen(function*() {
|
|
57
|
+
const openRequest = yield* Effect.try({
|
|
58
|
+
try: () => globalThis.indexedDB.open(database, databaseVersion),
|
|
59
|
+
catch: (cause) =>
|
|
60
|
+
new Persistence.PersistenceError({
|
|
61
|
+
message: "Failed to open backing store database",
|
|
62
|
+
cause
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
openRequest.onupgradeneeded = () => {
|
|
67
|
+
const db = openRequest.result
|
|
68
|
+
const entries = db.objectStoreNames.contains(entriesStoreName)
|
|
69
|
+
? openRequest.transaction?.objectStore(entriesStoreName)
|
|
70
|
+
: db.createObjectStore(entriesStoreName, { keyPath: ["storeId", "id"] })
|
|
71
|
+
if (entries && !entries.indexNames.contains(storeIdIndexName)) {
|
|
72
|
+
entries.createIndex(storeIdIndexName, storeIdIndexName, { unique: false })
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return yield* idbRequest("Failed to open backing store database", () => openRequest)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
interface EntryRow {
|
|
80
|
+
readonly storeId: string
|
|
81
|
+
readonly id: string
|
|
82
|
+
readonly value: object
|
|
83
|
+
readonly expires: number | null
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const isExpired = (row: EntryRow, now: number): boolean => row.expires !== null && row.expires <= now
|
|
87
|
+
|
|
88
|
+
const get = (
|
|
89
|
+
db: IDBDatabase,
|
|
90
|
+
clock: Clock.Clock,
|
|
91
|
+
storeId: string,
|
|
92
|
+
key: string
|
|
93
|
+
): Effect.Effect<object | undefined, Persistence.PersistenceError> =>
|
|
94
|
+
withEntriesTransaction<object | undefined>(
|
|
95
|
+
db,
|
|
96
|
+
"readwrite",
|
|
97
|
+
`Failed to get key ${key} from backing store`,
|
|
98
|
+
(
|
|
99
|
+
entries,
|
|
100
|
+
setResult,
|
|
101
|
+
fail
|
|
102
|
+
) => {
|
|
103
|
+
const now = clock.currentTimeMillisUnsafe()
|
|
104
|
+
const id: [string, string] = [storeId, key]
|
|
105
|
+
const request = entries.get(id)
|
|
106
|
+
request.onerror = () => fail(request.error)
|
|
107
|
+
request.onsuccess = () => {
|
|
108
|
+
const row = request.result as EntryRow | undefined
|
|
109
|
+
if (!row || !isExpired(row, now)) {
|
|
110
|
+
setResult(row?.value)
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const deleteRequest = entries.delete(id)
|
|
115
|
+
deleteRequest.onerror = () => fail(deleteRequest.error)
|
|
116
|
+
deleteRequest.onsuccess = () => setResult(undefined)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
const getMany = (
|
|
122
|
+
db: IDBDatabase,
|
|
123
|
+
clock: Clock.Clock,
|
|
124
|
+
storeId: string,
|
|
125
|
+
keys: Arr.NonEmptyArray<string>
|
|
126
|
+
): Effect.Effect<Arr.NonEmptyArray<object | undefined>, Persistence.PersistenceError> =>
|
|
127
|
+
withEntriesTransaction(
|
|
128
|
+
db,
|
|
129
|
+
"readwrite",
|
|
130
|
+
"Failed to getMany from backing store",
|
|
131
|
+
(entries, setResult, fail) => {
|
|
132
|
+
const now = clock.currentTimeMillisUnsafe()
|
|
133
|
+
const results = new Array<object | undefined>(keys.length)
|
|
134
|
+
setResult(results as any)
|
|
135
|
+
|
|
136
|
+
for (let i = 0; i < keys.length; i++) {
|
|
137
|
+
const key = keys[i]
|
|
138
|
+
const keyPath = [storeId, key]
|
|
139
|
+
const request = entries.get(keyPath)
|
|
140
|
+
request.onerror = () => fail(request.error)
|
|
141
|
+
request.onsuccess = () => {
|
|
142
|
+
const row = request.result as EntryRow | undefined
|
|
143
|
+
if (!row) return
|
|
144
|
+
else if (!isExpired(row, now)) {
|
|
145
|
+
results[i] = row.value
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
const deleteRequest = entries.delete(keyPath)
|
|
149
|
+
deleteRequest.onerror = () => fail(deleteRequest.error)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
const set = (
|
|
156
|
+
db: IDBDatabase,
|
|
157
|
+
clock: Clock.Clock,
|
|
158
|
+
storeId: string,
|
|
159
|
+
key: string,
|
|
160
|
+
value: object,
|
|
161
|
+
ttl: Duration.Duration | undefined
|
|
162
|
+
): Effect.Effect<void, Persistence.PersistenceError> =>
|
|
163
|
+
withEntriesTransaction(
|
|
164
|
+
db,
|
|
165
|
+
"readwrite",
|
|
166
|
+
`Failed to set key ${key} in backing store`,
|
|
167
|
+
(entries, setResult, fail) => {
|
|
168
|
+
const request = entries.put(
|
|
169
|
+
{
|
|
170
|
+
storeId,
|
|
171
|
+
id: key,
|
|
172
|
+
value,
|
|
173
|
+
expires: Persistence.unsafeTtlToExpires(clock, ttl)
|
|
174
|
+
} satisfies EntryRow
|
|
175
|
+
)
|
|
176
|
+
request.onerror = () => fail(request.error)
|
|
177
|
+
request.onsuccess = () => setResult(undefined)
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
const setMany = (
|
|
182
|
+
db: IDBDatabase,
|
|
183
|
+
clock: Clock.Clock,
|
|
184
|
+
storeId: string,
|
|
185
|
+
entries: Arr.NonEmptyArray<readonly [key: string, value: object, ttl: Duration.Duration | undefined]>
|
|
186
|
+
): Effect.Effect<void, Persistence.PersistenceError> =>
|
|
187
|
+
withEntriesTransaction(
|
|
188
|
+
db,
|
|
189
|
+
"readwrite",
|
|
190
|
+
"Failed to setMany in backing store",
|
|
191
|
+
(store, setResult, fail) => {
|
|
192
|
+
for (const [key, value, ttl] of entries) {
|
|
193
|
+
const request = store.put(
|
|
194
|
+
{
|
|
195
|
+
storeId,
|
|
196
|
+
id: key,
|
|
197
|
+
value,
|
|
198
|
+
expires: Persistence.unsafeTtlToExpires(clock, ttl)
|
|
199
|
+
} satisfies EntryRow
|
|
200
|
+
)
|
|
201
|
+
request.onerror = () => fail(request.error)
|
|
202
|
+
request.onsuccess = () => setResult(undefined)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
const remove = (
|
|
208
|
+
db: IDBDatabase,
|
|
209
|
+
storeId: string,
|
|
210
|
+
key: string
|
|
211
|
+
): Effect.Effect<void, Persistence.PersistenceError> =>
|
|
212
|
+
withEntriesTransaction(
|
|
213
|
+
db,
|
|
214
|
+
"readwrite",
|
|
215
|
+
`Failed to remove key ${key} from backing store`,
|
|
216
|
+
(entries, setResult, fail) => {
|
|
217
|
+
const request = entries.delete([storeId, key])
|
|
218
|
+
request.onerror = () => fail(request.error)
|
|
219
|
+
request.onsuccess = () => setResult(undefined)
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
const clear = (db: IDBDatabase, storeId: string): Effect.Effect<void, Persistence.PersistenceError> =>
|
|
224
|
+
withEntriesTransaction(db, "readwrite", "Failed to clear backing store", (entries, setResult, fail) => {
|
|
225
|
+
const index = entries.index(storeIdIndexName)
|
|
226
|
+
const cursorRequest = index.openCursor(storeId)
|
|
227
|
+
cursorRequest.onerror = () => fail(cursorRequest.error)
|
|
228
|
+
cursorRequest.onsuccess = () => {
|
|
229
|
+
const cursor = cursorRequest.result
|
|
230
|
+
if (!cursor) {
|
|
231
|
+
setResult(undefined)
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
const deleteRequest = cursor.delete()
|
|
235
|
+
deleteRequest.onerror = () => fail(deleteRequest.error)
|
|
236
|
+
deleteRequest.onsuccess = () => cursor.continue()
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
const withEntriesTransaction = <A>(
|
|
241
|
+
db: IDBDatabase,
|
|
242
|
+
mode: IDBTransactionMode,
|
|
243
|
+
message: string,
|
|
244
|
+
run: (
|
|
245
|
+
entries: IDBObjectStore,
|
|
246
|
+
onResult: (result: A) => void,
|
|
247
|
+
fail: (cause: unknown) => void
|
|
248
|
+
) => void
|
|
249
|
+
): Effect.Effect<A, Persistence.PersistenceError> =>
|
|
250
|
+
Effect.callback<A, Persistence.PersistenceError>((resume) => {
|
|
251
|
+
const tx = db.transaction(entriesStoreName, mode)
|
|
252
|
+
const entries = tx.objectStore(entriesStoreName)
|
|
253
|
+
|
|
254
|
+
let result: A | undefined
|
|
255
|
+
let setResult = false
|
|
256
|
+
let done = false
|
|
257
|
+
|
|
258
|
+
const fail = (cause: unknown) => {
|
|
259
|
+
if (!done) {
|
|
260
|
+
done = true
|
|
261
|
+
tx.abort()
|
|
262
|
+
}
|
|
263
|
+
resume(Effect.fail(new Persistence.PersistenceError({ message, cause })))
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
tx.oncomplete = () => {
|
|
267
|
+
done = true
|
|
268
|
+
if (setResult) resume(Effect.succeed(result!))
|
|
269
|
+
}
|
|
270
|
+
tx.onerror = () => {
|
|
271
|
+
done = true
|
|
272
|
+
fail(tx.error)
|
|
273
|
+
}
|
|
274
|
+
tx.onabort = () => {
|
|
275
|
+
done = true
|
|
276
|
+
fail(tx.error)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
run(entries, (next) => {
|
|
280
|
+
if (done) return resume(Effect.succeed(next))
|
|
281
|
+
setResult = true
|
|
282
|
+
result = next
|
|
283
|
+
}, fail)
|
|
284
|
+
|
|
285
|
+
return Effect.sync(() => {
|
|
286
|
+
tx.abort()
|
|
287
|
+
})
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
const idbRequest = <A>(
|
|
291
|
+
message: string,
|
|
292
|
+
evaluate: () => IDBRequest<A>
|
|
293
|
+
): Effect.Effect<A, Persistence.PersistenceError> =>
|
|
294
|
+
Effect.callback<A, Persistence.PersistenceError>((resume) => {
|
|
295
|
+
const request = evaluate()
|
|
296
|
+
const fail = (cause: unknown) => {
|
|
297
|
+
resume(Effect.fail(new Persistence.PersistenceError({ message, cause })))
|
|
298
|
+
}
|
|
299
|
+
if (request.readyState === "done") {
|
|
300
|
+
resume(Effect.succeed(request.result))
|
|
301
|
+
}
|
|
302
|
+
request.onsuccess = () => {
|
|
303
|
+
resume(Effect.succeed(request.result))
|
|
304
|
+
}
|
|
305
|
+
request.onerror = () => fail(request.error)
|
|
306
|
+
})
|
|
@@ -44,7 +44,7 @@ export const make = (self: MessagePort | Window): WorkerRunner.WorkerRunnerPlatf
|
|
|
44
44
|
Effect.scopedWith(Effect.fnUntraced(function*(scope) {
|
|
45
45
|
const closeLatch = Deferred.makeUnsafe<void, WorkerError>()
|
|
46
46
|
const trackFiber = Fiber.runIn(scope)
|
|
47
|
-
const services = yield* Effect.
|
|
47
|
+
const services = yield* Effect.context<R>()
|
|
48
48
|
const runFork = Effect.runForkWith(services)
|
|
49
49
|
const onExit = (exit: Exit.Exit<any, E>) => {
|
|
50
50
|
if (exit._tag === "Failure" && !Cause.hasInterruptsOnly(exit.cause)) {
|
package/src/Clipboard.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @since 1.0.0
|
|
3
3
|
*/
|
|
4
|
+
import * as Context from "effect/Context"
|
|
4
5
|
import * as Data from "effect/Data"
|
|
5
6
|
import * as Effect from "effect/Effect"
|
|
6
7
|
import * as Layer from "effect/Layer"
|
|
7
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
8
8
|
|
|
9
9
|
const TypeId = "~@effect/platform-browser/Clipboard"
|
|
10
10
|
const ErrorTypeId = "~@effect/platform-browser/Clipboard/ClipboardError"
|
|
@@ -38,7 +38,7 @@ export class ClipboardError extends Data.TaggedError("ClipboardError")<{
|
|
|
38
38
|
* @since 1.0.0
|
|
39
39
|
* @category Service
|
|
40
40
|
*/
|
|
41
|
-
export const Clipboard:
|
|
41
|
+
export const Clipboard: Context.Service<Clipboard, Clipboard> = Context.Service<Clipboard>(TypeId)
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* @since 1.0.0
|
package/src/Geolocation.ts
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* @since 1.0.0
|
|
3
3
|
*/
|
|
4
4
|
import * as Cause from "effect/Cause"
|
|
5
|
+
import * as Context from "effect/Context"
|
|
5
6
|
import * as Data from "effect/Data"
|
|
6
7
|
import * as Effect from "effect/Effect"
|
|
7
8
|
import * as Layer from "effect/Layer"
|
|
8
9
|
import * as Queue from "effect/Queue"
|
|
9
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
10
10
|
import * as Stream from "effect/Stream"
|
|
11
11
|
|
|
12
12
|
const TypeId = "~@effect/platform-browser/Geolocation"
|
|
@@ -34,7 +34,7 @@ export interface Geolocation {
|
|
|
34
34
|
* @since 1.0.0
|
|
35
35
|
* @category Service
|
|
36
36
|
*/
|
|
37
|
-
export const Geolocation:
|
|
37
|
+
export const Geolocation: Context.Service<Geolocation, Geolocation> = Context.Service<Geolocation>(TypeId)
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* @since 1.0.0
|
package/src/IndexedDb.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 4.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Config from "effect/Config"
|
|
5
|
+
import * as Context from "effect/Context"
|
|
6
|
+
import * as Effect from "effect/Effect"
|
|
7
|
+
import * as Layer from "effect/Layer"
|
|
8
|
+
import * as Schema from "effect/Schema"
|
|
9
|
+
import * as SchemaIssue from "effect/SchemaIssue"
|
|
10
|
+
|
|
11
|
+
const TypeId = "~@effect/platform-browser/IndexedDb"
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @since 4.0.0
|
|
15
|
+
* @category models
|
|
16
|
+
*/
|
|
17
|
+
export interface IndexedDb {
|
|
18
|
+
readonly [TypeId]: typeof TypeId
|
|
19
|
+
readonly indexedDB: globalThis.IDBFactory
|
|
20
|
+
readonly IDBKeyRange: typeof globalThis.IDBKeyRange
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @since 4.0.0
|
|
25
|
+
* @category tag
|
|
26
|
+
*/
|
|
27
|
+
export const IndexedDb: Context.Service<IndexedDb, IndexedDb> = Context.Service<IndexedDb, IndexedDb>(TypeId)
|
|
28
|
+
|
|
29
|
+
/** @internal */
|
|
30
|
+
const IDBFlatKey = Schema.Union([
|
|
31
|
+
Schema.String,
|
|
32
|
+
Schema.Number.check(Schema.makeFilter((input) => !Number.isNaN(input))),
|
|
33
|
+
Schema.DateValid,
|
|
34
|
+
Schema.declare(
|
|
35
|
+
(input): input is BufferSource =>
|
|
36
|
+
input instanceof ArrayBuffer ||
|
|
37
|
+
(ArrayBuffer.isView(input) && input.buffer instanceof ArrayBuffer)
|
|
38
|
+
)
|
|
39
|
+
])
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Schema for `IDBValidKey` (`number | string | Date | BufferSource | IDBValidKey[]`).
|
|
43
|
+
*
|
|
44
|
+
* @since 4.0.0
|
|
45
|
+
* @category schemas
|
|
46
|
+
*/
|
|
47
|
+
export const IDBValidKey = Schema.Union([IDBFlatKey, Schema.Array(IDBFlatKey)])
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Schema for `autoIncrement` key path (`number`).
|
|
51
|
+
*
|
|
52
|
+
* @since 4.0.0
|
|
53
|
+
* @category schemas
|
|
54
|
+
*/
|
|
55
|
+
export const AutoIncrement = Schema.Int.check(
|
|
56
|
+
Schema.isBetween({ minimum: 1, maximum: 2 ** 53 })
|
|
57
|
+
).annotate({
|
|
58
|
+
identifier: "AutoIncrement",
|
|
59
|
+
title: "autoIncrement",
|
|
60
|
+
description: "Defines a valid autoIncrement key path for the IndexedDb table"
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @since 4.0.0
|
|
65
|
+
* @category constructor
|
|
66
|
+
*/
|
|
67
|
+
export const make = (impl: Omit<IndexedDb, typeof TypeId>): IndexedDb => IndexedDb.of({ [TypeId]: TypeId, ...impl })
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Instance of IndexedDb from the `window` object.
|
|
71
|
+
*
|
|
72
|
+
* @since 4.0.0
|
|
73
|
+
* @category constructors
|
|
74
|
+
*/
|
|
75
|
+
export const layerWindow: Layer.Layer<IndexedDb, Config.ConfigError> = Layer.effect(
|
|
76
|
+
IndexedDb,
|
|
77
|
+
Effect.suspend(() => {
|
|
78
|
+
if (window.indexedDB && window.IDBKeyRange) {
|
|
79
|
+
return Effect.succeed(
|
|
80
|
+
make({
|
|
81
|
+
indexedDB: window.indexedDB,
|
|
82
|
+
IDBKeyRange: window.IDBKeyRange
|
|
83
|
+
})
|
|
84
|
+
)
|
|
85
|
+
} else {
|
|
86
|
+
return Effect.fail(
|
|
87
|
+
new Config.ConfigError(
|
|
88
|
+
new Schema.SchemaError(
|
|
89
|
+
new SchemaIssue.MissingKey({
|
|
90
|
+
messageMissingKey: "window.indexedDB is not available"
|
|
91
|
+
})
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
)
|