UNPKG

datum-focus

Version:

Data shape, model, metadata, JSON, JSON Schema, GraphQL, MongoDB query and aggregations, iterator generators

120 lines (107 loc) 3.18 kB
import sift, { Query } from "sift"; import { v4 as guid } from "uuid"; import record from ".../../generation/generators/record"; import { Guid } from "../../string"; import { Model } from "../../model"; import { entity, Entity, Repository, RESULT_CODE__ACCEPTED, RESULT_CODE__CREATED, RESULT_CODE__OK, StoreResult } from "../repository"; export type K = { _id: Guid }; async function* asyncIterable<T extends {}>( collection: Record<Guid, T>, query?: Query<T> ): AsyncGenerator<Entity<T>> { const test = sift(query || {}); const keys = Object.keys(collection); for (const _id of keys) { const record = collection[_id]; if (!record) { continue; } const entity = { _id, ...record }; if (test(entity)) { yield Promise.resolve(entity); } } } export class EphemeralRepository<T extends {} = {}> implements Repository<T> { constructor(public readonly model: Model<T>, collection?: Record<Guid, Entity<T>>) { this.collection = collection || {}; } public readonly collection: Record<Guid, Entity<T>>; get count(): Promise<number> { return Promise.resolve(Object.keys(this.collection).length); } create(record: T): Promise<StoreResult<T>> { const ntt = entity(record); this.collection[ntt._id] = ntt; return Promise.resolve(<StoreResult<T>>{ _id: ntt._id, rescode: RESULT_CODE__CREATED, }); } delete(_id: string): Promise<StoreResult<T>> { const record = this.collection[_id]; if (!record) { return Promise.resolve(<StoreResult<T>>{ _id, rescode: RESULT_CODE__OK, }); } delete this.collection[_id]; return Promise.resolve(<StoreResult<T>>{ _id, rescode: RESULT_CODE__ACCEPTED, }); } find(_id: string): Promise<StoreResult<T>> { let entity!: Entity<T>; for (const ntt of Object.values(this.collection)) { if (ntt._id === _id) { entity = ntt; break; } } return Promise.resolve({ _id, data: entity, rescode: RESULT_CODE__OK, }); } /* grow(amount: number): Promise<void> { return new Promise(resolve => { const name = this.model.name; console.log(`Generating ${amount} fake ${name}...`); for (let i = 0; i < amount; i++) { Object.assign(this.collection, { [guid()]: <T>record(this.model.fields, getModelMap()), }); } console.log(`${Object.keys(this.collection).length} ${name}s total.`); resolve(); }); }*/ select(query?: Query<T>): Promise<AsyncIterable<Entity<T>>> { return Promise.resolve(asyncIterable<T>(this.collection, query)); } shrink(amount: number): Promise<void> { return new Promise(resolve => { const keys = Object.keys(this.collection); keys .splice(Math.max(0, keys.length - amount)) .forEach(key => delete this.collection[key]); resolve(); }); } update({ _id, ...record }: Entity<Partial<T>>): Promise<StoreResult<T>> { Object.assign(this.collection, { [_id]: record }); return Promise.resolve(<StoreResult<T>>{ _id, rescode: RESULT_CODE__ACCEPTED, }); } }