diff --git a/ghost/in-memory-repository/src/InMemoryRepository.ts~ b/ghost/in-memory-repository/src/InMemoryRepository.ts~ new file mode 100644 index 0000000000..5dfc4de21d --- /dev/null +++ b/ghost/in-memory-repository/src/InMemoryRepository.ts~ @@ -0,0 +1,80 @@ +import nql from '@tryghost/nql'; + +type Entity = { + id: T; + deleted: boolean; +} + +type Order = { + field: keyof T; + direction: 'asc' | 'desc'; +} + +type OrderOption> = Order[]; + +export abstract class InMemoryRepository> { + private store: T[] = []; + private ids: Map = new Map(); + + constructor() {} + + protected abstract toPrimitive(entity: T): object; + + public async save(entity: T): Promise { + if (entity.deleted) { + this.store = this.store.filter(item => item.id !== entity.id); + this.ids.delete(entity.id); + return; + } + + if (this.ids.has(entity.id)) { + this.store = this.store.map((item) => { + if (item.id === entity.id) { + return entity; + } + return item; + }); + } else { + this.store.push(entity); + this.ids.set(entity.id, true); + } + } + + public async getById(id: string): Promise { + return this.store.find(item => item.id === id) || null; + } + + public async getAll(options: { filter?: string; order?: OrderOption } = {}): Promise { + const filter = nql(options.filter); + + const results = this.store.slice().filter(item => filter.queryJSON(this.toPrimitive(item))); + + if (options.order) { + for (const order of options.order) { + results.sort((a, b) => { + if (order.direction === 'asc') { + return a[order.field] as any > (b[order.field] as any) ? 1 : -1; + } else { + return a[order.field] < b[order.field] ? 1 : -1; + } + }); + } + } + + return results; + } + + public async getPage(options: { filter?: string; page: number; limit: number; order?: Order[] } = {page: 1, limit: 15}): Promise { + const results = await this.getAll(options); + + const start = (options.page - 1) * options.limit; + const end = start + options.limit; + + return results.slice(start, end); + } + + public async getCount(options: { filter?: string }): Promise { + const results = await this.getAll(options); + return results.length; + } +}