1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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 },
})
)
);
}
|