UNPKG

@getanthill/datastore

Version:

Event-Sourced Datastore

283 lines (243 loc) 6.75 kB
import type { AxiosResponse, AxiosResponseHeaders, RawAxiosResponseHeaders, } from 'axios'; import type { ModelConfig } from '../typings'; import type { DatastoreConfig } from './Datastore'; import type Datastore from './Datastore'; export type { AxiosResponse, DatastoreConfig }; import { omit } from 'lodash'; export default class Model<T> { modelConfig: ModelConfig; datastore: Datastore; constructor(datastore: Datastore, modelConfig: ModelConfig) { this.modelConfig = modelConfig; this.datastore = datastore; } get name() { return this.modelConfig.name; } async request(handler: Function, ...args: any[]): Promise<any> { const { data } = await handler.call(this.datastore, ...args); return data; } heartbeat(): Promise<{ status: string }> { return this.request(this.datastore.heartbeat); } createModel(): Promise<any> { return this.request(this.datastore.createModel, this.modelConfig); } updateModel(): Promise<any> { return this.request(this.datastore.updateModel, this.modelConfig); } createModelIndexes(): Promise<any> { return this.request(this.datastore.createModelIndexes, this.modelConfig); } getSchema(): Promise<any> { return this.request(this.datastore.getSchema, this.name); } async encryptOne(payload: Partial<T>, fields: string[] = []): Promise<T> { const [decrypted] = await this.request( this.datastore.encrypt, this.name, [payload], fields, ); return decrypted; } encryptMany(payloads: Partial<T>[], fields: string[] = []): Promise<T[]> { return this.request(this.datastore.encrypt, this.name, payloads, fields); } async decryptOne(payload: Partial<T>, fields: string[] = []): Promise<T> { const [decrypted] = await this.request( this.datastore.decrypt, this.name, [payload], fields, ); return decrypted; } decryptMany(payloads: Partial<T>[], fields: string[] = []): Promise<T[]> { return this.request(this.datastore.decrypt, this.name, payloads, fields); } createOne(payload: Partial<T>, headers?: object): Promise<T> { return this.request(this.datastore.create, this.name, payload, headers); } createMany(payloads: Partial<T>[]): Promise<T[]> { return Promise.all(payloads.map((p) => this.createOne(p))); } /** * @deprecated in favor of createOne + createMany */ create(payload: T | T[]): Promise<T | T[]> { if (Array.isArray(payload)) { return Promise.all( payload.map((p) => this.request(this.datastore.create, this.name, p)), ) as Promise<T[]>; } return this.request( this.datastore.create, this.name, payload, ) as Promise<T>; } updateOne(payload: Partial<T>, headers?: object): Promise<T> { return this.request( this.datastore.update, this.name, /* @ts-ignore */ payload[this.modelConfig.correlation_field], omit(payload, this.modelConfig.correlation_field), headers, ); } updateMany(payloads: Partial<T>[]): Promise<T[]> { return Promise.all(payloads.map((p) => this.updateOne(p))); } /** * @deprecated */ update(payload: object | object[]): Promise<T | T[]> { if (Array.isArray(payload)) { return Promise.all( payload.map((p) => this.request( this.datastore.update, this.name, p[this.modelConfig.correlation_field], omit(p, this.modelConfig.correlation_field), ), ), ) as Promise<T[]>; } return this.request( this.datastore.update, this.name, /* @ts-ignore */ payload[this.modelConfig.correlation_field], omit(payload, this.modelConfig.correlation_field), ) as Promise<T>; } apply( eventType: string, payload: object, headers?: object, eventVersion = '0_0_0', ): Promise<T> { return this.request( this.datastore.apply, this.name, /* @ts-ignore */ payload[this.modelConfig.correlation_field], eventType, eventVersion, omit(payload, this.modelConfig.correlation_field), headers, ); } get( correlationId: string, headers?: { 'force-primary'?: true; }, ): Promise<T> { return this.request(this.datastore.get, this.name, correlationId, headers); } count(query: T & Record<string, unknown>): Promise<number> { return this.datastore.count.call(this.datastore, this.name, query); } find( query: Partial<T>, page?: number, pageSize?: number, headers?: { page?: number; 'page-size'?: number; 'cursor-last-id'?: string; 'force-primary'?: true; }, ): Promise<T[]> { return this.request( this.datastore.find, this.name, query, page, pageSize, headers, ); } events( correlationId: string, page?: number, pageSize?: number, ): Promise<any[]> { return this.request( this.datastore.events, this.name, correlationId, page, pageSize, ); } version(correlationId: string, version: number): Promise<T> { return this.request( this.datastore.version, this.name, correlationId, version, ); } at(correlationId: string, date: Date | string): Promise<T> { return this.request(this.datastore.at, this.name, correlationId, date); } restore(correlationId: string, version: number): Promise<T> { return this.request( this.datastore.restore, this.name, correlationId, version, ); } snapshot(correlationId: string): Promise<T> { return this.request(this.datastore.snapshot, this.name, correlationId); } archive(correlationId: string, deep?: boolean): Promise<T> { return this.request(this.datastore.archive, this.name, correlationId, deep); } unarchive(correlationId: string, deep?: boolean): Promise<T> { return this.request( this.datastore.unarchive, this.name, correlationId, deep, ); } delete(correlationId: string, deep?: boolean): Promise<T> { return this.request(this.datastore.delete, this.name, correlationId, deep); } async updateOverwhelmingly<T>( query: object, handler: (entity: T) => Promise<T>, progress: ( stats: { total: number; done: number; error: number; progress: number; restored: number; }, entity: T, headers: RawAxiosResponseHeaders | AxiosResponseHeaders, ) => void, pageSize?: number, ) { return this.datastore.updateOverwhelmingly<T>( this.name, query, handler, progress, pageSize, ); } }