@irrelon/forerunnerdb-core
Version:
ForerunnerDB core utilities for operating on JSON data.
107 lines (90 loc) • 3.23 kB
JavaScript
import {
testFlight,
EnumTestFlightResult
} from "./testFlight";
/**
* @typedef {Object} InsertOptions
* @property {Boolean} [$ordered=false] When true, will stop processing on
* the first update failure but leave previous updates intact.
* @property {Boolean} [$atomic=false] When true, will cancel all updates on
* the first update failure, reverting any previous updates.
* @property {Boolean} [$skipAssignment=false] When true, the passed `data`
* will not be updated at all but the returned array will still contain the
* updated documents.
* @property {Function} [$preFlight] If passed, will be called with the document
* to update and if the preFlight function returns true, we will continue but if
* it returns false we will cancel the update.
* @property {Function} [$postFlight] If passed, will be called with the document
* being updated and the result of the update and if the $postFlight function
* returns true, we will continue but if it returns false we will cancel the
* update.
* @property {Function} [$assignment] If passed, overrides the function that
* would normally push the final data to the `dataArr` argument.
*/
/**
* @typedef {Object} InsertResult
* @property {Array<Object>} inserted The array of documents that got inserted.
* @property {Array<Object>} notInserted The array of documents that did not get
* inserted.
*/
/**
* Inserts a document or array of documents into the passed `dataArr`.
* @param {Array<Object>} dataArr The array of data to query.
* @param {Object|Array<Object>} insertArr A document or array of documents to insert.
* @param {InsertOptions} [options] An options object.
* @returns {Promise<InsertResult>} The result of the insert operation.
*/
export const insert = async (dataArr, insertArr, options = {}) => {
if (!Array.isArray(insertArr)) {
insertArr = [insertArr];
}
const inserted = [];
const notInserted = [];
const preFlightArr = [];
const postFlightArr = [];
const assignmentFunc = options.$assignment || ((args) => {
dataArr.push(...args);
});
if (options.$preFlight) {
preFlightArr.push(options.$preFlight);
}
if (options.$postFlight) {
postFlightArr.push(options.$postFlight);
}
const executeFlight = (doc) => {
// Decouple outer object
return {...doc};
};
// Loop through each item of data and insert it
for (let currentIndex = 0; currentIndex < insertArr.length; currentIndex++) {
const originalDoc = insertArr[currentIndex];
const updatedDoc = await testFlight([originalDoc], preFlightArr, executeFlight, postFlightArr, {
"$atomic": options.$atomic,
"$ordered": options.$ordered
});
// If we failed testFlight, skip to the next record
if (updatedDoc === EnumTestFlightResult.CANCEL) {
notInserted.push(originalDoc);
continue;
}
if (updatedDoc === EnumTestFlightResult.CANCEL_ORDERED) {
notInserted.push(originalDoc);
break;
}
if (updatedDoc === EnumTestFlightResult.CANCEL_ATOMIC) {
return {
"inserted": [],
"notInserted": insertArr
};
}
inserted.push(updatedDoc);
}
if (!options.$skipAssignment && inserted.length) {
assignmentFunc(inserted);
}
return {
inserted,
notInserted
};
};
export default insert;