UNPKG

@funztic/db

Version:

TypeScript기반 파일 데이터베이스, zod를 지원합니다.

136 lines (135 loc) 4.52 kB
export function* autoIncrement() { let i = 0; while (true) yield i++; } export class Repository { constructor(collection, options) { this.collection = collection; this.options = options; } async save(entity) { let processedEntity = { ...entity }; if (this.options.beforeCreate) processedEntity = await this.options.beforeCreate(processedEntity); if (!processedEntity.id) processedEntity.id = this.options.idGenerator(); const existingEntity = await this.collection.get(processedEntity.id); let finalEntity = existingEntity ? { ...existingEntity, ...processedEntity } : processedEntity; if (this.options.beforeSave) finalEntity = await this.options.beforeSave(finalEntity); const savedEntity = existingEntity ? await this.collection.update(finalEntity.id, finalEntity) : await this.collection.create(finalEntity); if (this.options.afterSave) await this.options.afterSave(savedEntity); return savedEntity; } async findById(id) { const entity = await this.collection.get(id); return entity || null; } async findAll() { return await this.collection.getAll(); } async findBy(criteria) { const entries = Object.entries(criteria); return await this.collection.find((entity) => { return entries.every(([key, value]) => entity[key] === value); }); } async findOne(criteria) { const results = await this.findBy(criteria); return results.length > 0 ? results[0] : null; } async update(id, data) { const entity = await this.collection.get(id); if (!entity) return null; let updates = { ...data }; if (this.options.beforeUpdate) updates = await this.options.beforeUpdate(entity, updates); const updatedEntity = await this.collection.update(id, updates); if (updatedEntity && this.options.afterSave) await this.options.afterSave(updatedEntity); return updatedEntity || null; } async delete(id) { return await this.collection.delete(id); } async count() { const all = await this.collection.getAll(); return all.length; } async exists(id) { const entity = await this.collection.get(id); return !!entity; } async clear() { await this.collection.clear(); } async query(queryFn) { const entities = await this.collection.getAll(); return queryFn(entities); } async paginate(page = 1, limit = 10) { const allItems = await this.collection.getAll(); const total = allItems.length; const start = (page - 1) * limit; const end = start + limit; const data = allItems.slice(start, end); const totalPages = Math.ceil(total / limit); return { data, total, page, limit, totalPages }; } async *createPaginator(limit = 10, sortBy, order = 'asc') { const data = await this.findAllSorted(sortBy, order); const total = data.length; const totalPages = Math.ceil(total / limit); let currentPage = 1; while (currentPage <= totalPages) { const start = (currentPage - 1) * limit; const end = start + limit; yield { data: data.slice(start, end), total, page: currentPage, isLast: currentPage === totalPages }; currentPage++; } } async findAllSorted(sortBy, order = 'asc') { const entities = await this.collection.getAll(); return entities.sort((a, b) => { const valueA = a[sortBy]; const valueB = b[sortBy]; if (valueA === valueB) return 0; if (order === 'asc') { return valueA < valueB ? -1 : 1; } else { return valueA > valueB ? -1 : 1; } }); } getRawCollection() { return this.collection; } } export function createRepository(collection, options = (() => { const idGenerator = autoIncrement(); return { idGenerator: () => idGenerator.next().value.toString() }; })()) { return new Repository(collection, options); }