src/app/core/database/database.ts

Description

An implementation of this abstract class provides functions for direct database access. This interface is an extension of the PouchDB API.

PLEASE NOTE: Direct access to the Database layer is rarely necessary, and you should probably use EntityMapperService instead. Database is not an Angular Service and has to be accessed through the DatabaseResolverService.

Relationships

Used by

Depends on

No results matching.

Index

Methods

Constructor

constructor(dbName: string)
Parameters :
Name Type Optional
dbName string No

Methods

Abstract allDocs
allDocs(options?: GetAllOptions)

Load all documents (matching the given PouchDB options) from the database.

Normally you should rather use "getAll()" or another well typed method of this class instead of passing PouchDB specific options here because that will make your code tightly coupled with PouchDB rather than any other database provider.

Parameters :
Name Type Optional Description
options GetAllOptions Yes

PouchDB options object as in the normal PouchDB library

Returns : Promise<any>
Abstract changes
changes()
Abstract destroy
destroy()

Closes all open connections to the database base and destroys it (clearing all data)

Returns : Promise<any>
Abstract find
find(prefix: string, query: any, page?: { limit?: number; bookmark?: string }, sort?: { prop?: string; dir?: "asc" | "desc" })

Uses the PouchDB-find plugin https://github.com/apache/pouchdb/tree/master/packages/node_modules/pouchdb-find This supports querying using the Mango Query Language https://pouchdb.com/guides/mango-queries.html#query-language There might be differences in queries between a local PouchDB and the CouchDB.

Pagination uses an opaque bookmark cursor rather than skip: passing the bookmark returned by a previous call continues right after those results. Unlike skip, this also works correctly when the remote CouchDB applies permission filtering to the query (see https://github.com/Aam-Digital/replication-backend/pull/330). A bookmark is forward-only - it cannot be used to jump backwards - so callers that need to revisit earlier pages must cache them themselves.

Parameters :
Name Type Optional Description
prefix string No

of the entity to be queried

query any No

the Mango Query Language query

page { limit?: number; bookmark?: string } Yes

additional pagination options

sort { prop?: string; dir?: "asc" | "desc" } Yes

additional sorting options

Returns : Promise<{ docs: any[]; bookmark?: string }>
Abstract get
get(id: string, options?: GetOptions)

Load a single document by id from the database.

Parameters :
Name Type Optional Description
id string No

The primary key of the document to be loaded

options GetOptions Yes

Optional options for the database engine (PouchDB)

Returns : Promise<any>
getAll
getAll(prefix: string)

Load all documents (with the given prefix) from the database.

Parameters :
Name Type Optional Default value Description
prefix string No ""

The string prefix of document ids that should be retrieved

Returns : Promise<Array<any>>
Abstract init
init(dbName?: string)

Initialize the database fully after its initial creation, e.g. once user details are available.

Parameters :
Name Type Optional Description
dbName string Yes

A special database name, if different from the default name passed in the constructor

Returns : any
Abstract isEmpty
isEmpty()
Returns : Promise<boolean>

true if there are no documents in the database

Abstract isInitialized
isInitialized()

Whether the database is already initialized and ready for use.

Returns : boolean
purge
purge(_id: string)

Permanently remove a document from the local database without syncing the deletion to the server.

Unlike remove, purge leaves no tombstone and does not affect the remote database. Throws if not supported by the current implementation.

Parameters :
Name Type Optional
_id string No
Returns : Promise<boolean>
Abstract put
put(object: any, forceUpdate?: boolean)

Save a document to the database.

Parameters :
Name Type Optional Description
object any No

The document to be saved

forceUpdate boolean Yes

(Optional) Whether conflicts should be ignored and an existing conflicting document forcefully overwritten.

Returns : Promise<any>
Abstract putAll
putAll(objects: any[], forceUpdate?: boolean)

Save a bunch of documents at once to the database

Parameters :
Name Type Optional Description
objects any[] No

The documents to be saved

forceUpdate boolean Yes

(Optional) Whether conflicts should be ignored and existing conflicting documents forcefully overwritten.

Returns : Promise<any[]>

array holding success responses or errors depending on the success of the operation

Abstract query
query(fun: any, options?: QueryOptions)

Query data from the database based on a more complex, indexed request.

This is directly calling the PouchDB implementation of this function. Also see the documentation there: https://pouchdb.com/api.html#query_database

Parameters :
Name Type Optional Description
fun any No

The name of a previously saved database index

options QueryOptions Yes

Additional options for the query, like a key. See the PouchDB docs for details.

Returns : Promise<any>
Abstract remove
remove(object: any)

Delete a document from the database

Parameters :
Name Type Optional Description
object any No

The document to be deleted (usually this object must at least contain the _id and _rev)

Returns : Promise<any>
Async removeAll
removeAll<T>(shouldDelete: (doc: T) => void)
Type parameters :
  • T

Delete all documents of the database matching the given filter.

Note that getAll() also returns the database's own "_design/..." index documents, so a filter that does not exclude them deletes the indices as well. They are only recreated when the app starts up again (see DatabaseIndexingService), so only delete them if the calling code reloads the app or restores the documents immediately afterwards.

Example :
   Pass a specialized document type if the filter reads fields other than `_id`.
Parameters :
Name Type Optional Description
shouldDelete function No

filter deciding for each document whether it is deleted. Pass a specialized document type if the filter reads fields other than _id.

Returns : Promise<number>

the number of deleted documents

Abstract reset
reset()

Closes open connections and un-initializes the database (without deleting persisted data, see destroy() for that)

Returns : Promise<any>
Abstract saveDatabaseIndex
saveDatabaseIndex(designDoc: any)

Create a database index to query() certain data more efficiently in the future.

Also see the PouchDB documentation regarding indices and queries: https://pouchdb.com/api.html#query_database

Parameters :
Name Type Optional Description
designDoc any No

The PouchDB style design document for the map/reduce query

Returns : Promise<any>
supportsFind
supportsFind()

Whether find (bookmark-based pagination) is supported by this implementation. Callers should fall back to loading all docs otherwise.

Returns : boolean
import { Observable } from "rxjs";

/**
 * An implementation of this abstract class provides functions for direct database access.
 * This interface is an extension of the [PouchDB API](https://pouchdb.com/api.html).
 *
 * PLEASE NOTE:
 * Direct access to the Database layer is rarely necessary, and you should probably use EntityMapperService instead.
 * Database is not an Angular Service and has to be accessed through the DatabaseResolverService.
 */
export abstract class Database {
  constructor(protected dbName: string) {}

  /**
   * Initialize the database fully after its initial creation,
   * e.g. once user details are available.
   * @param dbName A special database name, if different from the default name passed in the constructor
   */
  abstract init(dbName?: string);

  /**
   * Whether the database is already initialized and ready for use.
   */
  abstract isInitialized(): boolean;

  /**
   * Load a single document by id from the database.
   * @param id The primary key of the document to be loaded
   * @param options Optional options for the database engine (PouchDB)
   */
  abstract get(id: string, options?: GetOptions): Promise<any>;

  /**
   * Load all documents (matching the given PouchDB options) from the database.
   *
   * Normally you should rather use "getAll()" or another well typed method of this class
   * instead of passing PouchDB specific options here
   * because that will make your code tightly coupled with PouchDB rather than any other database provider.
   *
   * @param options PouchDB options object as in the normal PouchDB library
   */
  abstract allDocs(options?: GetAllOptions): Promise<any>;

  /**
   * Save a document to the database.
   * @param object The document to be saved
   * @param forceUpdate (Optional) Whether conflicts should be ignored and an existing conflicting document forcefully overwritten.
   */
  abstract put(object: any, forceUpdate?: boolean): Promise<any>;

  /**
   * Save a bunch of documents at once to the database
   * @param objects The documents to be saved
   * @param forceUpdate (Optional) Whether conflicts should be ignored and existing conflicting documents forcefully overwritten.
   * @returns array holding success responses or errors depending on the success of the operation
   */
  abstract putAll(objects: any[], forceUpdate?: boolean): Promise<any[]>;

  /**
   * Delete a document from the database
   * @param object The document to be deleted (usually this object must at least contain the _id and _rev)
   */
  abstract remove(object: any): Promise<any>;

  /**
   * Permanently remove a document from the local database without syncing the deletion to the server.
   *
   * Unlike {@link remove}, purge leaves no tombstone and does not affect the remote database.
   * Throws if not supported by the current implementation.
   *
   * @param id The document ID to purge
   */
  purge(_id: string): Promise<boolean> {
    throw new Error("purge() is not supported by this database implementation");
  }

  /**
   * Whether {@link find} (bookmark-based pagination) is supported by this implementation.
   * Callers should fall back to loading all docs otherwise.
   */
  supportsFind(): boolean {
    return false;
  }

  /**
   * Uses the PouchDB-find plugin {@link https://github.com/apache/pouchdb/tree/master/packages/node_modules/pouchdb-find}
   * This supports querying using the Mango Query Language {@link https://pouchdb.com/guides/mango-queries.html#query-language}
   * There might be differences in queries between a local PouchDB and the CouchDB.
   *
   * Pagination uses an opaque `bookmark` cursor rather than `skip`: passing the
   * `bookmark` returned by a previous call continues right after those
   * results. Unlike `skip`, this also works correctly when the remote CouchDB
   * applies permission filtering to the query (see
   * {@link https://github.com/Aam-Digital/replication-backend/pull/330}).
   * A bookmark is forward-only - it cannot be used to jump backwards - so
   * callers that need to revisit earlier pages must cache them themselves.
   *
   * @param prefix of the entity to be queried
   * @param query the Mango Query Language query
   * @param page additional pagination options
   * @param sort additional sorting options
   */
  abstract find(
    prefix: string,
    query: any,
    page?: { limit?: number; bookmark?: string },
    sort?: { prop?: string; dir?: "asc" | "desc" },
  ): Promise<{ docs: any[]; bookmark?: string }>;

  /**
   * Query data from the database based on a more complex, indexed request.
   *
   * This is directly calling the PouchDB implementation of this function.
   * Also see the documentation there: {@link https://pouchdb.com/api.html#query_database}
   *
   * @param fun The name of a previously saved database index
   * @param options Additional options for the query, like a `key`. See the PouchDB docs for details.
   */
  abstract query(fun: any, options?: QueryOptions): Promise<any>;

  /**
   * Create a database index to `query()` certain data more efficiently in the future.
   *
   * Also see the PouchDB documentation regarding indices and queries: {@link https://pouchdb.com/api.html#query_database}
   *
   * @param designDoc The PouchDB style design document for the map/reduce query
   */
  abstract saveDatabaseIndex(designDoc: any): Promise<any>;

  /**
   * Load all documents (with the given prefix) from the database.
   * @param prefix The string prefix of document ids that should be retrieved
   */
  getAll(prefix = ""): Promise<Array<any>> {
    return this.allDocs({
      include_docs: true,
      startkey: prefix,
      endkey: prefix + "\ufff0",
    });
  }

  /**
   * Delete all documents of the database matching the given filter.
   *
   * Note that `getAll()` also returns the database's own "_design/..." index
   * documents, so a filter that does not exclude them deletes the indices as well.
   * They are only recreated when the app starts up again
   * (see {@link DatabaseIndexingService}), so only delete them if the calling code
   * reloads the app or restores the documents immediately afterwards.
   *
   * @param shouldDelete filter deciding for each document whether it is deleted.
   *        Pass a specialized document type if the filter reads fields other than `_id`.
   * @returns the number of deleted documents
   */
  async removeAll<T extends { _id: string }>(
    shouldDelete: (doc: T) => boolean,
  ): Promise<number> {
    const allDocs: T[] = await this.getAll();
    const docsToDelete = allDocs.filter(shouldDelete);
    for (const doc of docsToDelete) {
      await this.remove(doc);
    }
    return docsToDelete.length;
  }

  /**
   * @returns true if there are no documents in the database
   */
  abstract isEmpty(): Promise<boolean>;

  /**
   * Closes open connections and un-initializes the database
   * (without deleting persisted data, see destroy() for that)
   */
  abstract reset(): Promise<any>;

  /**
   * Closes all open connections to the database base and destroys it (clearing all data)
   */
  abstract destroy(): Promise<any>;

  abstract changes(): Observable<DatabaseDocChange>;
}

/**
 * Based upon PouchDb changes feed format.
 */
export interface DatabaseDocChange {
  _id: string;
  _rev: string;
  _deleted?: boolean;

  [key: string]: any;
}

/**
 * Basic query options supported by {@link Database}.
 *
 * also see https://pouchdb.com/guides/queries.html
 */
export type QueryOptions = PouchDB.Query.Options<any, any>;

/**
 * Basic database read options supported by {@link Database}.
 *
 * also see https://pouchdb.com/api.html#fetch_document
 */
export type GetAllOptions =
  | PouchDB.Core.AllDocsWithKeyOptions
  | PouchDB.Core.AllDocsWithKeysOptions
  | PouchDB.Core.AllDocsWithinRangeOptions
  | PouchDB.Core.AllDocsOptions;

/**
 * Basic database read options supported by {@link Database}.
 *
 * also see https://pouchdb.com/api.html#fetch_document
 */
export type GetOptions = PouchDB.Core.GetOptions;

results matching ""

    No results matching ""