From b5bac20790b14f0033fbe3696fef3026eafcb3bb Mon Sep 17 00:00:00 2001 From: groenroos Date: Fri, 25 Feb 2022 05:40:15 +0000 Subject: [PATCH] #163: Implement options in Memory driver --- drivers/db/Memory.js | 34 +++++++++++++++++++++++++++++++++- lib/Storage.js | 2 +- test/drivers/db/Memory.test.js | 29 +++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/drivers/db/Memory.js b/drivers/db/Memory.js index e7b0867..2ed6e8b 100644 --- a/drivers/db/Memory.js +++ b/drivers/db/Memory.js @@ -59,8 +59,9 @@ export default class Memory extends Interface { * * @param {string} collection Name of the target collection * @param {object} conditions The search query + * @param {object} options Options for the operation */ - async read(collection, conditions) { + async read(collection, conditions, options) { /* Fetch the collection, or provide an empty array if none exists */ let records = new Utils().deepClone(this.memory[collection] || []); @@ -69,6 +70,37 @@ export default class Memory extends Interface { records = records.filter(record => this.isMatch(record, conditions)); } + /* Limit and skip, if defined */ + if (options && 'limit' in options) { + const skip = options.skip || 0; + records = records.slice(skip, options.limit + skip); + } + + /* Sort, if defined */ + if (options && 'sort' in options) { + records = records.sort((a, b) => { + let i = 0; + let result = 0; + + /* Go through all sorted properties */ + while (result === 0 && i < options.sort.length) { + const property = options.sort[i][0]; + + /* If property isn't available in record, forget about it */ + if (!(property in a) || !(property in b)) { + continue; + } + + /* Sort by property, in the direction requested */ + result = (a[property] < b[property]) ? -1 : ((a[property] > b[property]) ? 1 : 0); + result *= options.sort[i][1]; + i++; + } + + return result; + }); + } + return records; } diff --git a/lib/Storage.js b/lib/Storage.js index 4bac61d..49adf21 100755 --- a/lib/Storage.js +++ b/lib/Storage.js @@ -267,7 +267,7 @@ export default class Storage { const limit = (this.app.config.limit && this.app.config.limit > 0) ? this.app.config.limit : false; /* Parse limit options */ - if ('limit' in request.query) { + if ('limit' in request.query && Number(request.query.limit) !== 0) { options.limit = Number(request.query.limit) || null; /* If max limit is set in config, ensure we don't go over it */ diff --git a/test/drivers/db/Memory.test.js b/test/drivers/db/Memory.test.js index dbb7205..2ba38b2 100644 --- a/test/drivers/db/Memory.test.js +++ b/test/drivers/db/Memory.test.js @@ -193,6 +193,35 @@ test.serial('reads nothing in a non-existent collection', async t => { t.is(results.length, 0); }); +test.serial('limits records according to limit option', async t => { + const results = await t.context.memory.read('fifth', {}, { limit: 2 }); + + t.true(Array.isArray(results)); + t.is(results.length, 2); +}); + +test.serial('skips records according to skip option', async t => { + const results = await t.context.memory.read('fifth', {}, { limit: 2, skip: 2 }); + + t.true(Array.isArray(results)); + t.is(results.length, 2); + t.is(results[0].name, 'North Yorkshire'); +}); + +test.serial('sorts records ascending according to sort option', async t => { + const results = await t.context.memory.read('fifth', {}, { sort: [ [ 'name', 1 ] ] }); + + t.true(Array.isArray(results)); + t.is(results[0].name, 'Hamptons'); +}); + +test.serial('sorts records descending according to sort option', async t => { + const results = await t.context.memory.read('fifth', {}, { sort: [ [ 'name', -1 ] ] }); + + t.true(Array.isArray(results)); + t.is(results[0].name, 'North Yorkshire'); +}); + test.serial('modifies one record by ID', async t => { const results = await t.context.memory.modify('first', { _id: t.context.memory.memory.first[0]._id }, { new: 'hello' });