From 5f322d03bb6c8422e0d4fbf02cfbaff788986c3c Mon Sep 17 00:00:00 2001 From: Mike Cornwell Date: Mon, 12 Jan 2026 11:24:16 -0500 Subject: [PATCH] feat(bulk): add bulk insert and bulk delete --- package.json | 2 +- src/datastoreAdapter.ts | 133 +++++++++++++++++++----------- test/src/datastoreAdapter.test.ts | 16 ++++ 3 files changed, 102 insertions(+), 49 deletions(-) diff --git a/package.json b/package.json index 4e2d2ad..d06f3db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "functional-models-orm-memory", - "version": "3.0.3", + "version": "3.0.4", "description": "An in-memory datastore adapter for functional-models", "main": "index.js", "types": "index.d.ts", diff --git a/src/datastoreAdapter.ts b/src/datastoreAdapter.ts index c855005..309866b 100644 --- a/src/datastoreAdapter.ts +++ b/src/datastoreAdapter.ts @@ -28,7 +28,10 @@ type Database = Record>> const create = ({ seedData, getCollectionNameForModel = defaultCollectionName, -}: Props = {}): WithRequired & { +}: Props = {}): WithRequired< + DatastoreAdapter, + 'count' | 'bulkInsert' | 'bulkDelete' +> & { getRecords: () => Database } => { const database: Database = clone(seedData) || {} @@ -43,56 +46,90 @@ const create = ({ } return database[name] as unknown as Record> } + const getRecords = () => { + return database + } - return { - getRecords: () => { - return database - }, - delete: ( - model: OrmModel, - id: PrimaryKeyType - ): Promise => { + const bulkInsert = async ( + model: OrmModel, + instances: readonly ModelInstance[] + ): Promise => { + return Promise.resolve().then(() => { + instances.reduce(async (accP, instance) => { + const acc = await accP + await save(instance) + return acc + }, Promise.resolve()) + }) + } + const bulkDelete = async ( + model: OrmModel, + ids: readonly PrimaryKeyType[] + ): Promise => { + return Promise.resolve().then(() => { + ids.reduce(async (accP, id) => { + const acc = await accP + await deleteObj(model, id) + return acc + }, Promise.resolve()) + }) + } + + const deleteObj = async ( + model: OrmModel, + id: PrimaryKeyType + ): Promise => { + const records = _getRecords(model) + // eslint-disable-next-line functional/immutable-data + delete records[id] + return Promise.resolve(undefined) + } + + const retrieve = async ( + model: OrmModel, + primaryKey: PrimaryKeyType + ): Promise>> => { + return Promise.resolve().then(() => { const records = _getRecords(model) - // eslint-disable-next-line functional/immutable-data - delete records[id] - return Promise.resolve(undefined) - }, - retrieve: ( - model: OrmModel, - primaryKey: PrimaryKeyType - ): Promise>> => { - return Promise.resolve().then(() => { - const records = _getRecords(model) - return records[primaryKey] as unknown as - | ToObjectResult - | undefined - }) - }, - save: async ( - instance: ModelInstance - ): Promise> => { - return Promise.resolve().then(async () => { - const model = instance.getModel() - const data = await instance.toObj() - const records = _getRecords(model) - merge(records, { [await instance.getPrimaryKey()]: data }) - return data - }) - }, - search: ( - model: OrmModel, - query: OrmSearch - ): Promise> => { + return records[primaryKey] as unknown as ToObjectResult | undefined + }) + } + const save = async ( + instance: ModelInstance + ): Promise> => { + return Promise.resolve().then(async () => { + const model = instance.getModel() + const data = await instance.toObj() + const records = _getRecords(model) + merge(records, { [await instance.getPrimaryKey()]: data }) + return data + }) + } + const search = ( + model: OrmModel, + query: OrmSearch + ): Promise> => { + const records = _getRecords(model) + const instances = filterResults(query, Object.values(records)) + return Promise.resolve({ instances: instances, page: undefined }) + } + + const count = (model: OrmModel) => { + return Promise.resolve().then(() => { const records = _getRecords(model) - const instances = filterResults(query, Object.values(records)) - return Promise.resolve({ instances: instances, page: undefined }) - }, - count: (model: OrmModel) => { - return Promise.resolve().then(() => { - const records = _getRecords(model) - return Object.keys(records).length - }) - }, + return Object.keys(records).length + }) + } + + return { + save, + delete: deleteObj, + retrieve, + search, + count, + bulkInsert, + bulkDelete, + getRecords, } } diff --git a/test/src/datastoreAdapter.test.ts b/test/src/datastoreAdapter.test.ts index 2bbddcd..2db999f 100644 --- a/test/src/datastoreAdapter.test.ts +++ b/test/src/datastoreAdapter.test.ts @@ -69,6 +69,22 @@ describe('/src/datastoreAdapter.ts', () => { assert.isOk(actual) }) }) + describe('#bulkInsert()', () => { + it('should bulk insert the instances', async () => { + const { datastoreAdapter, models } = setup() + await datastoreAdapter.bulkInsert(models.Test1Models, [ + models.Test1Models.create<'id'>({ name: 'my-name' }), + ]) + }) + }) + describe('#bulkDelete()', () => { + it('should bulk delete the instances', async () => { + const { datastoreAdapter, models } = setup() + await datastoreAdapter.bulkDelete(models.Test1Models, [ + '032c282c-b367-4d15-b19a-01c855b38f44', + ]) + }) + }) describe('#retrieve()', () => { it('should return an object from the seedData when the primary key is provided', async () => { const { datastoreAdapter, models } = setup(getSeedData1())