UNPKG

pip-services3-data-node

Version:
256 lines (225 loc) 10.2 kB
/** @module persistence */ /** @hidden */ let _ = require('lodash'); import { IIdentifiable } from 'pip-services3-commons-node'; import { AnyValueMap } from 'pip-services3-commons-node'; import { ObjectWriter } from 'pip-services3-commons-node'; import { IdGenerator } from 'pip-services3-commons-node'; import { MemoryPersistence } from './MemoryPersistence'; import { IWriter } from '../IWriter'; import { IGetter } from '../IGetter'; import { ISetter } from '../ISetter'; import { ILoader } from '../ILoader'; import { ISaver } from '../ISaver'; /** * Abstract persistence component that stores data in memory * and implements a number of CRUD operations over data items with unique ids. * The data items must implement [[https://pip-services3-node.github.io/pip-services3-commons-node/interfaces/data.iidentifiable.html IIdentifiable interface]]. * * In basic scenarios child classes shall only override [[getPageByFilter]], * [[getListByFilter]] or [[deleteByFilter]] operations with specific filter function. * All other operations can be used out of the box. * * In complex scenarios child classes can implement additional operations by * accessing cached items via this._items property and calling [[save]] method * on updates. * * @see [[MemoryPersistence]] * * ### References ### * * - <code>\*:logger:\*:\*:1.0</code> (optional) [[https://pip-services3-node.github.io/pip-services3-components-node/interfaces/log.ilogger.html ILogger]] components to pass log messages * * ### Examples ### * * class MyMemoryPersistence extends IdentifiableMemoryPersistence<MyData, string> { * * private composeFilter(filter: FilterParams): any { * filter = filter || new FilterParams(); * let name = filter.getAsNullableString("name"); * return (item) => { * if (name != null && item.name != name) * return false; * return true; * }; * } * * public getPageByFilter(correlationId: string, filter: FilterParams, paging: PagingParams, * callback: (err: any, page: DataPage<MyData>) => void): void { * super.getPageByFilter(correlationId, this.composeFilter(filter), paging, null, null, callback); * } * * } * * let persistence = new MyMemoryPersistence(); * * persistence.create("123", { id: "1", name: "ABC" }, (err, item) => { * persistence.getPageByFilter( * "123", * FilterParams.fromTuples("name", "ABC"), * null, * (err, page) => { * console.log(page.data); // Result: { id: "1", name: "ABC" } * * persistence.deleteById("123", "1", (err, item) => { * ... * }); * } * ) * }); */ export class IdentifiableMemoryPersistence<T extends IIdentifiable<K>, K> extends MemoryPersistence<T> implements IWriter<T, K>, IGetter<T, K>, ISetter<T> { /** * Creates a new instance of the persistence. * * @param loader (optional) a loader to load items from external datasource. * @param saver (optional) a saver to save items to external datasource. */ public constructor(loader?: ILoader<T>, saver?: ISaver<T>) { super(loader, saver); } /** * Gets a list of data items retrieved by given unique ids. * * @param correlationId (optional) transaction id to trace execution through call chain. * @param ids ids of data items to be retrieved * @param callback callback function that receives a data list or error. */ public getListByIds(correlationId: string, ids: K[], callback: (err: any, items: T[]) => void): void { let filter = (item: T) => { return _.indexOf(ids, item.id) >= 0; } this.getListByFilter(correlationId, filter, null, null, callback); } /** * Gets a data item by its unique id. * * @param correlationId (optional) transaction id to trace execution through call chain. * @param id an id of data item to be retrieved. * @param callback callback function that receives data item or error. */ public getOneById(correlationId: string, id: K, callback: (err: any, item: T) => void): void { let items = this._items.filter((x) => {return x.id == id;}); let item = items.length > 0 ? items[0] : null; if (item != null) this._logger.trace(correlationId, "Retrieved item %s", id); else this._logger.trace(correlationId, "Cannot find item by %s", id); callback(null, item); } /** * Creates a data item. * * @param correlation_id (optional) transaction id to trace execution through call chain. * @param item an item to be created. * @param callback (optional) callback function that receives created item or error. */ public create(correlationId: string, item: T, callback?: (err: any, item: T) => void): void { if (item.id == null) { item = _.clone(item); ObjectWriter.setProperty(item, "id", IdGenerator.nextLong()); } super.create(correlationId, item, callback); } /** * Sets a data item. If the data item exists it updates it, * otherwise it create a new data item. * * @param correlation_id (optional) transaction id to trace execution through call chain. * @param item a item to be set. * @param callback (optional) callback function that receives updated item or error. */ public set(correlationId: string, item: T, callback?: (err: any, item: T) => void): void { item = _.clone(item); if (item.id == null) ObjectWriter.setProperty(item, "id", IdGenerator.nextLong()); let index = this._items.map((x) => { return x.id; }).indexOf(item.id); if (index < 0) this._items.push(item); else this._items[index] = item; this._logger.trace(correlationId, "Set item %s", item.id); this.save(correlationId, (err) => { if (callback) callback(err, item) }); } /** * Updates a data item. * * @param correlation_id (optional) transaction id to trace execution through call chain. * @param item an item to be updated. * @param callback (optional) callback function that receives updated item or error. */ public update(correlationId: string, item: T, callback?: (err: any, item: T) => void): void { let index = this._items.map((x) => { return x.id; }).indexOf(item.id); if (index < 0) { this._logger.trace(correlationId, "Item %s was not found", item.id); callback(null, null); return; } item = _.clone(item); this._items[index] = item; this._logger.trace(correlationId, "Updated item %s", item.id); this.save(correlationId, (err) => { if (callback) callback(err, item) }); } /** * Updates only few selected fields in a data item. * * @param correlation_id (optional) transaction id to trace execution through call chain. * @param id an id of data item to be updated. * @param data a map with fields to be updated. * @param callback callback function that receives updated item or error. */ public updatePartially(correlationId: string, id: K, data: AnyValueMap, callback?: (err: any, item: T) => void): void { let index = this._items.map((x) => { return x.id; }).indexOf(id); if (index < 0) { this._logger.trace(correlationId, "Item %s was not found", id); callback(null, null); return; } let item: any = this._items[index]; item = _.extend(item, data.getAsObject()) this._items[index] = item; this._logger.trace(correlationId, "Partially updated item %s", id); this.save(correlationId, (err) => { if (callback) callback(err, item) }); } /** * Deleted a data item by it's unique id. * * @param correlation_id (optional) transaction id to trace execution through call chain. * @param id an id of the item to be deleted * @param callback (optional) callback function that receives deleted item or error. */ public deleteById(correlationId: string, id: K, callback?: (err: any, item: T) => void): void { var index = this._items.map((x) => { return x.id; }).indexOf(id); var item = this._items[index]; if (index < 0) { this._logger.trace(correlationId, "Item %s was not found", id); callback(null, null); return; } this._items.splice(index, 1); this._logger.trace(correlationId, "Deleted item by %s", id); this.save(correlationId, (err) => { if (callback) callback(err, item) }); } /** * Deletes multiple data items by their unique ids. * * @param correlationId (optional) transaction id to trace execution through call chain. * @param ids ids of data items to be deleted. * @param callback (optional) callback function that receives error or null for success. */ public deleteByIds(correlationId: string, ids: K[], callback?: (err: any) => void): void { let filter = (item: T) => { return _.indexOf(ids, item.id) >= 0; } this.deleteByFilter(correlationId, filter, callback); } }