summaryrefslogtreecommitdiff
path: root/src/app/db/service/pivot/helpers.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/db/service/pivot/helpers.js')
-rw-r--r--src/app/db/service/pivot/helpers.js113
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 },
+ })
+ )
+ );
+}