import { Query, update } from "mingo"; import type { Criteria } from "mingo/types"; import type { Modifier } from "mingo/updater"; import { IndexManager, type IndexSpec } from "../../index/manager.ts"; import type { UpdateResult } from "../../storage.ts"; import { addOptions, type QueryOptions, Storage } from "../../storage.ts"; import type { AnyDocument, StringKeyOf } from "../../types.ts"; export class MemoryStorage extends Storage { readonly index: IndexManager; constructor(name: string, indexes: IndexSpec[]) { super(name, indexes); this.index = new IndexManager(indexes); } get documents(): TSchema[] { return this.index.primary.documents; } async resolve(): Promise { return this; } async insert(documents: TSchema[]): Promise { for (const document of documents) { this.index.insert(document); } this.broadcast("insert", documents); } async getByIndex(field: StringKeyOf, value: string): Promise { return this.index.getByIndex(field, value); } async find(condition: Criteria = {}, options?: QueryOptions): Promise { const cursor = this.index.getByCondition(condition); if (options !== undefined) { return addOptions(cursor, options).all(); } return cursor.all(); } async update( condition: Criteria, modifier: Modifier, arrayFilters?: TSchema[], ): Promise { const documents: TSchema[] = []; let matchedCount = 0; let modifiedCount = 0; for (const document of await this.find(condition)) { matchedCount += 1; const modified = update(document, modifier, arrayFilters, undefined, { cloneMode: "deep" }); if (modified.length > 0) { modifiedCount += 1; documents.push(document); this.index.update(document); } } if (modifiedCount > 0) { this.broadcast("update", documents); } return { matchedCount, modifiedCount }; } async remove(condition: Criteria): Promise { const documents = await this.find(condition); for (const document of documents) { this.index.remove(document); } this.broadcast("remove", documents); return documents.length; } async count(condition: Criteria): Promise { return new Query(condition).find(this.documents).all().length; } async flush(): Promise { this.index.flush(); } }