diff options
Diffstat (limited to 'src/app/db/service/pivot/helpers.js')
| -rw-r--r-- | src/app/db/service/pivot/helpers.js | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/app/db/service/pivot/helpers.js b/src/app/db/service/pivot/helpers.js new file mode 100644 index 0000000..1d8f7f2 --- /dev/null +++ b/src/app/db/service/pivot/helpers.js @@ -0,0 +1,113 @@ +/** + * Pivot Table Helpers + * @module app/db/service/pivot/helpers + */ + +import * as db from "app/db/query"; + +/** + * Fetch a set of database objects from a pivot table via relations + * @param {bookshelf.Model} Model the pivot table model to query + * @param {string} parentIdAttribute the parent ID attribute on the pivot + * @param {number} parentId the parent ID to query + * @param {string} childIdAttribute the child ID attribute on the pivot + * @param {number} childId the child ID to query + */ +export function indexPivotTable({ + Model, + parentIdAttribute, + parentId, + childIdAttribute, + childId, +}) { + return Model.query((builder) => { + builder.where(parentIdAttribute, parentId); + if (Array.isArray(childId)) { + builder.whereIn(childIdAttribute, childId); + } else { + builder.andWhere(childIdAttribute, childId); + } + }).fetchAll(); +} + +/** + * Get the parent, child, and pivot models from a service, as well as their ID attribute names + * @param {Service} service the pivot table service + * @return {object} the models and ID attribute names + */ +export function getPivotModels(service) { + const { + parent, + Model, + ChildModel, + childRelation, + parentPivotRelation, + pivotChildRelation, + } = service.options; + const { Model: ParentModel } = service.options.parent; + const parentIdAttribute = ParentModel.prototype.idAttribute; + const pivotIdAttribute = Model.prototype.idAttribute; + const childIdAttribute = ChildModel.prototype.idAttribute; + const parentTableName = ParentModel.prototype.tableName; + const pivotTableName = Model.prototype.tableName; + const childTableName = ChildModel.prototype.tableName; + return { + parent, + Model, + ParentModel, + ChildModel, + parentTableName, + pivotTableName, + childTableName, + parentIdAttribute, + pivotIdAttribute, + childIdAttribute, + parentPivotRelation, + pivotChildRelation, + childRelation, + }; +} + +/** + * Create a single instance + * @param {bookshelf.Model} options.Model the model + * @param {Object} options.data data to add + * @param {Array} options.instances fetched instances to dedupe + * @return {Object} result + */ +export async function handleCreateOne({ Model, data, instances }) { + if (instances.length) { + throw new Error("pivot relation already exists"); + } + return await db.create({ Model, data }); +} + +/** + * Create multiple instances + * @param {bookshelf.Model} options.Model the model + * @param {Object} options.data data to add + * @param {Array} options.instances fetched instances to dedupe + * @param {string} options.childIdAttribute the child ID, found on the body, which should point to an array + * @return {Object} result + */ +export async function handleCreateMany({ + Model, + data, + childIdAttribute, + instances, +}) { + let { [childIdAttribute]: child_ids, ...columns } = data; + const matched = new Set( + instances.map((instance) => instance.get(childIdAttribute)) + ); + return await Promise.all( + Array.from(new Set(child_ids)) + .filter((child_id) => !matched.has(child_id)) + .map((child_id) => + db.create({ + Model, + data: { ...columns, [childIdAttribute]: child_id }, + }) + ) + ); +} |
