(options?: {
readonly database?: string
})
| 356 | * @category indexed db |
| 357 | */ |
| 358 | export const makeIndexedDb = (options?: { |
| 359 | readonly database?: string |
| 360 | }): Effect.Effect<typeof EventJournal.Service, EventJournalError, Scope> => |
| 361 | Effect.gen(function*() { |
| 362 | const database = options?.database ?? "effect_event_journal" |
| 363 | const openRequest = indexedDB.open(database, 1) |
| 364 | openRequest.onupgradeneeded = () => { |
| 365 | const db = openRequest.result |
| 366 | |
| 367 | const entries = db.createObjectStore("entries", { keyPath: "id" }) |
| 368 | entries.createIndex("id", "id", { unique: true }) |
| 369 | entries.createIndex("event", "event") |
| 370 | |
| 371 | const remotes = db.createObjectStore("remotes", { keyPath: ["remoteId", "entryId"] }) |
| 372 | remotes.createIndex("id", ["remoteId", "entryId"], { unique: true }) |
| 373 | remotes.createIndex("sequence", ["remoteId", "sequence"], { unique: true }) |
| 374 | |
| 375 | const remoteEntryId = db.createObjectStore("remoteEntryId", { keyPath: ["remoteId"] }) |
| 376 | remoteEntryId.createIndex("id", "remoteId", { unique: true }) |
| 377 | } |
| 378 | const db = yield* Effect.acquireRelease( |
| 379 | idbReq("open", () => openRequest), |
| 380 | (db) => Effect.sync(() => db.close()) |
| 381 | ) |
| 382 | |
| 383 | const pubsub = yield* PubSub.unbounded<Entry>() |
| 384 | |
| 385 | return EventJournal.of({ |
| 386 | entries: idbReq( |
| 387 | "entries", |
| 388 | () => |
| 389 | db.transaction("entries", "readonly") |
| 390 | .objectStore("entries") |
| 391 | .index("id") |
| 392 | .getAll() |
| 393 | ).pipe( |
| 394 | Effect.flatMap((_) => |
| 395 | decodeEntryIdbArray(_).pipe( |
| 396 | Effect.mapError((cause) => new EventJournalError({ method: "entries", cause })) |
| 397 | ) |
| 398 | ) |
| 399 | ), |
| 400 | write: ({ effect, event, payload, primaryKey }) => |
| 401 | Effect.uninterruptibleMask((restore) => { |
| 402 | const entry = new Entry({ |
| 403 | id: makeEntryId(), |
| 404 | event, |
| 405 | primaryKey, |
| 406 | payload |
| 407 | }, { disableValidation: true }) |
| 408 | return restore(effect(entry)).pipe( |
| 409 | Effect.zipLeft(idbReq( |
| 410 | "write", |
| 411 | () => |
| 412 | db |
| 413 | .transaction("entries", "readwrite") |
| 414 | .objectStore("entries") |
| 415 | .put(encodeEntryIdb(entry)) |
no test coverage detected