Skip to content

IndexedDbDatabase

Builds and opens typed IndexedDB databases from versioned schema migrations.

This module turns an IndexedDbVersion migration chain into an IndexedDbDatabase layer. The layer opens the browser database, runs any pending upgrade migrations, provides a query builder for the current schema, and exposes a rebuild effect that deletes and reopens the database. Migration transactions can create or delete object stores and indexes, and database failures are represented as IndexedDbDatabaseError values.

10 exports Added in v4.0.0 Source

Constructors

make

Added in v4.0.0 Source

Creates the initial IndexedDbSchema from a version and an initialization migration run during database upgrade.

Signature

declare function make<InitialVersion extends AnyWithProps, Error>(
  initialVersion: InitialVersion,
  init: (toQuery: Transaction<InitialVersion>) => Effect<void, Error>,
): IndexedDbSchema<never, InitialVersion, Error>;

Errors

ErrorReason type

Added in v4.0.0 Source

String union describing the failure categories for IndexedDB database opening, migration, and schema operations.

Signature

type ErrorReason =
  | "TransactionError"
  | "MissingTable"
  | "OpenError"
  | "UpgradeError"
  | "Aborted"
  | "Blocked"
  | "MissingIndex";

Tagged error for IndexedDB database operations, carrying a database error reason and the original cause.

Signature

declare class IndexedDbDatabaseError extends YieldableError<this> & {
  readonly _tag: "IndexedDbDatabaseError";
} & Readonly<{
  cause: unknown;
  reason: ErrorReason;
}> {
  constructor(args: {
    readonly cause: unknown;
    readonly reason: ErrorReason;
  });
  readonly "~@effect/platform-browser/IndexedDbDatabase/IndexedDbDatabaseError": "~@effect/platform-browser/IndexedDbDatabase/IndexedDbDatabaseError";
  readonly message: ErrorReason;
}

Models

Any interface

Added in v4.0.0 Source

Type-erased IndexedDB schema shape used when traversing schema migration chains.

Signature

interface Any {
  readonly layer: (
    databaseName: string,
  ) => Layer<IndexedDbDatabase, IndexedDbDatabaseError, IndexedDb>;
  readonly previous?: Any;
}

AnySchema type

Added in v4.0.0 Source

Type-erased IndexedDbSchema covering any source version, target version, and migration error type.

Signature

type AnySchema = IndexedDbSchema<IndexedDbVersion.AnyWithProps, IndexedDbVersion.AnyWithProps, any>;

IndexedDbSchema interface

Added in v4.0.0 Source

Describes an IndexedDB schema version and its migrations, and acts as an effect that yields a query builder for the target version.

Signature

interface IndexedDbSchema<
  in out FromVersion extends IndexedDbVersion.AnyWithProps,
  in out ToVersion extends IndexedDbVersion.AnyWithProps,
  out Error = never,
> extends Effect<IndexedDbQueryBuilder.IndexedDbQueryBuilder<ToVersion>, never, IndexedDbDatabase> {
  constructor(_: never);
  readonly add: <Version extends AnyWithProps, MigrationError>(
    version: Version,
    migrate: (
      fromQuery: Transaction<ToVersion>,
      toQuery: Transaction<Version>,
    ) => Effect<void, MigrationError>,
  ) => IndexedDbSchema<ToVersion, Version, Error | MigrationError>;
  readonly fromVersion: FromVersion;
  readonly getQueryBuilder: Effect<IndexedDbQueryBuilder<ToVersion>, never, IndexedDbDatabase>;
  readonly layer: (
    databaseName: string,
  ) => Layer<IndexedDbDatabase, IndexedDbDatabaseError, IndexedDb>;
  readonly migrate: [FromVersion] extends [never]
    ? (query: Transaction<ToVersion>) => Effect<void, Error>
    : (fromQuery: Transaction<FromVersion>, toQuery: Transaction<ToVersion>) => Effect<void, Error>;
  readonly previous: [FromVersion] extends [never]
    ? undefined
    : IndexedDbSchema<never, FromVersion, Error>;
  readonly version: ToVersion;
}

Transaction interface

Added in v4.0.0 Source

Query builder available during a database migration, extended with object-store and index management helpers for the active IDBTransaction.

Signature

interface Transaction<Source extends IndexedDbVersion.AnyWithProps = never> extends Omit<
  IndexedDbQueryBuilder.IndexedDbQueryBuilder<Source>,
  "transaction"
> {
  readonly createIndex: <Name extends string>(
    table: Name,
    indexName: IndexFromTable<
      Extract<
        Tables<Source>,
        {
          readonly tableName: Name;
        }
      >
    >,
    options?: IDBIndexParameters,
  ) => Effect<IDBIndex, IndexedDbDatabaseError>;
  readonly createObjectStore: <A extends string>(
    table: A,
  ) => Effect<IDBObjectStore, IndexedDbDatabaseError>;
  readonly deleteIndex: <Name extends string>(
    table: Name,
    indexName: IndexFromTable<
      Extract<
        Tables<Source>,
        {
          readonly tableName: Name;
        }
      >
    >,
  ) => Effect<void, IndexedDbDatabaseError>;
  readonly deleteObjectStore: <A extends string>(table: A) => Effect<void, IndexedDbDatabaseError>;
  readonly transaction: IDBTransaction;
}

Services

Service tag for an open IndexedDB database, its IDBKeyRange constructor, reactivity service, and rebuild effect.

When to use

Use when you need access to the live database service after an IndexedDbSchema layer has been provided, especially for rebuild or lower-level database primitives.

Details

database is a mutable reference to the current IDBDatabase. IDBKeyRange and reactivity are shared with query builders created from the schema.

Gotchas

rebuild closes and deletes the browser database, then reopens it and reruns migrations. Records not recreated by migrations are removed.

See

  • IndexedDb.IndexedDb for the lower-level browser IndexedDB primitives
  • make for creating a schema that provides this service as a layer

Signature

declare class IndexedDbDatabase extends Shape<"~@effect/platform-browser/IndexedDbDatabase", {
  readonly database: MutableRef<IDBDatabase>;
  readonly IDBKeyRange: {
    (): IDBKeyRange;
    prototype: IDBKeyRange;
    bound(lower: any, upper: any, lowerOpen?: boolean, upperOpen?: boolean): IDBKeyRange;
    lowerBound(lower: any, open?: boolean): IDBKeyRange;
    only(value: any): IDBKeyRange;
    upperBound(upper: any, open?: boolean): IDBKeyRange;
  };
  readonly reactivity: {
    readonly invalidate: (keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>) => Effect<void>;
    readonly invalidateUnsafe: (keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>) => void;
    readonly mutation: <A, E, R>(keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>, effect: Effect<A, E, R>) => Effect<A, E, R>;
    readonly query: <A, E, R>(keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>, effect: Effect<A, E, R>) => Effect<Dequeue<A, E>, never, R | Scope>;
    readonly registerUnsafe: (keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>, handler: () => void) => () => void;
    readonly stream: <A, E, R>(keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>, effect: Effect<A, E, R>) => Stream<A, E, Exclude<R, Scope>>;
    readonly withBatch: <A, E, R>(effect: Effect<A, E, R>) => Effect<A, E, R>;
  };
  readonly rebuild: Effect<void, IndexedDbDatabaseError>;
}, this> {
  constructor(_: never);
}

Utility Types

IndexFromTable type

Added in v4.0.0 Source

Extracts the string-literal index names defined by an IndexedDbTable.

Signature

type IndexFromTable<Table extends IndexedDbTable.AnyWithProps> =
  IsStringLiteral<Extract<keyof IndexedDbTable.Indexes<Table>, string>> extends true
    ? Extract<keyof IndexedDbTable.Indexes<Table>, string>
    : never;

IndexFromTableName type

Added in v4.0.0 Source

Extracts the valid index names for a table name within an IndexedDB version.

Signature

type IndexFromTableName<
  Version extends IndexedDbVersion.AnyWithProps,
  Table extends string,
> = IndexFromTable<IndexedDbTable.WithName<IndexedDbVersion.Tables<Version>, Table>>;