orchid-orm 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +1 -0
- package/.rush/temp/shrinkwrap-deps.json +327 -0
- package/README.md +5 -0
- package/dist/index.d.ts +228 -0
- package/dist/index.esm.js +1116 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +1122 -0
- package/dist/index.js.map +1 -0
- package/jest-setup.ts +7 -0
- package/package.json +58 -0
- package/rollup.config.js +3 -0
- package/src/index.ts +3 -0
- package/src/model.test.ts +92 -0
- package/src/model.ts +169 -0
- package/src/orm.test.ts +73 -0
- package/src/orm.ts +74 -0
- package/src/relations/belongsTo.test.ts +890 -0
- package/src/relations/belongsTo.ts +247 -0
- package/src/relations/hasAndBelongsToMany.test.ts +1122 -0
- package/src/relations/hasAndBelongsToMany.ts +398 -0
- package/src/relations/hasMany.test.ts +2003 -0
- package/src/relations/hasMany.ts +332 -0
- package/src/relations/hasOne.test.ts +1219 -0
- package/src/relations/hasOne.ts +278 -0
- package/src/relations/relations.test.ts +37 -0
- package/src/relations/relations.ts +316 -0
- package/src/relations/utils.ts +12 -0
- package/src/repo.test.ts +200 -0
- package/src/repo.ts +119 -0
- package/src/test-utils/test-db.ts +32 -0
- package/src/test-utils/test-models.ts +194 -0
- package/src/test-utils/test-utils.ts +69 -0
- package/src/transaction.test.ts +45 -0
- package/src/transaction.ts +27 -0
- package/tsconfig.json +13 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1122 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var pqb = require('pqb');
|
|
6
|
+
|
|
7
|
+
const createModel = (options) => {
|
|
8
|
+
return class Model {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.setColumns = (fn) => {
|
|
11
|
+
const shape = pqb.getColumnTypes(options.columnTypes, fn);
|
|
12
|
+
return {
|
|
13
|
+
shape,
|
|
14
|
+
type: void 0
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
this.columnTypes = options.columnTypes;
|
|
18
|
+
}
|
|
19
|
+
belongsTo(fn, options2) {
|
|
20
|
+
return {
|
|
21
|
+
type: "belongsTo",
|
|
22
|
+
returns: "one",
|
|
23
|
+
fn,
|
|
24
|
+
options: options2
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
hasOne(fn, options2) {
|
|
28
|
+
return {
|
|
29
|
+
type: "hasOne",
|
|
30
|
+
returns: "one",
|
|
31
|
+
fn,
|
|
32
|
+
options: options2
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
hasMany(fn, options2) {
|
|
36
|
+
return {
|
|
37
|
+
type: "hasMany",
|
|
38
|
+
returns: "many",
|
|
39
|
+
fn,
|
|
40
|
+
options: options2
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
hasAndBelongsToMany(fn, options2) {
|
|
44
|
+
return {
|
|
45
|
+
type: "hasAndBelongsToMany",
|
|
46
|
+
returns: "many",
|
|
47
|
+
fn,
|
|
48
|
+
options: options2
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const makeBelongsToMethod = (relation, query) => {
|
|
55
|
+
const { primaryKey, foreignKey } = relation.options;
|
|
56
|
+
return {
|
|
57
|
+
returns: "one",
|
|
58
|
+
method: (params) => {
|
|
59
|
+
return query.findBy({ [primaryKey]: params[foreignKey] });
|
|
60
|
+
},
|
|
61
|
+
nestedInsert: async (q, data) => {
|
|
62
|
+
const connectOrCreate = data.filter(
|
|
63
|
+
(item) => Boolean(item.connectOrCreate)
|
|
64
|
+
);
|
|
65
|
+
const t = query.transacting(q);
|
|
66
|
+
let connectOrCreated;
|
|
67
|
+
if (connectOrCreate.length) {
|
|
68
|
+
connectOrCreated = await Promise.all(
|
|
69
|
+
connectOrCreate.map(
|
|
70
|
+
(item) => t.findBy(item.connectOrCreate.where)._takeOptional()
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
} else {
|
|
74
|
+
connectOrCreated = [];
|
|
75
|
+
}
|
|
76
|
+
let connectOrCreatedI = 0;
|
|
77
|
+
const create = data.filter(
|
|
78
|
+
(item) => {
|
|
79
|
+
if (item.connectOrCreate) {
|
|
80
|
+
return !connectOrCreated[connectOrCreatedI++];
|
|
81
|
+
} else {
|
|
82
|
+
return Boolean(item.create);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
let created;
|
|
87
|
+
if (create.length) {
|
|
88
|
+
created = await t.select(primaryKey)._createMany(
|
|
89
|
+
create.map(
|
|
90
|
+
(item) => "create" in item ? item.create : item.connectOrCreate.create
|
|
91
|
+
)
|
|
92
|
+
);
|
|
93
|
+
} else {
|
|
94
|
+
created = [];
|
|
95
|
+
}
|
|
96
|
+
const connect = data.filter(
|
|
97
|
+
(item) => Boolean(item.connect)
|
|
98
|
+
);
|
|
99
|
+
let connected;
|
|
100
|
+
if (connect.length) {
|
|
101
|
+
connected = await Promise.all(
|
|
102
|
+
connect.map((item) => t.findBy(item.connect)._take())
|
|
103
|
+
);
|
|
104
|
+
} else {
|
|
105
|
+
connected = [];
|
|
106
|
+
}
|
|
107
|
+
let createdI = 0;
|
|
108
|
+
let connectedI = 0;
|
|
109
|
+
connectOrCreatedI = 0;
|
|
110
|
+
return data.map(
|
|
111
|
+
(item) => item.connectOrCreate ? connectOrCreated[connectOrCreatedI++] || created[createdI++] : item.connect ? connected[connectedI++] : created[createdI++]
|
|
112
|
+
);
|
|
113
|
+
},
|
|
114
|
+
nestedUpdate: (q, update, params, state) => {
|
|
115
|
+
var _a, _b;
|
|
116
|
+
if (params.upsert && pqb.isQueryReturnsAll(q)) {
|
|
117
|
+
throw new Error("`upsert` option is not allowed in a batch update");
|
|
118
|
+
}
|
|
119
|
+
let idForDelete;
|
|
120
|
+
q._beforeUpdate(async (q2) => {
|
|
121
|
+
if (params.disconnect) {
|
|
122
|
+
update[foreignKey] = null;
|
|
123
|
+
} else if (params.set) {
|
|
124
|
+
if (primaryKey in params.set) {
|
|
125
|
+
update[foreignKey] = params.set[primaryKey];
|
|
126
|
+
} else {
|
|
127
|
+
update[foreignKey] = await query.transacting(q2)._findBy(params.set)._get(primaryKey);
|
|
128
|
+
}
|
|
129
|
+
} else if (params.create) {
|
|
130
|
+
update[foreignKey] = await query.transacting(q2)._get(primaryKey)._create(params.create);
|
|
131
|
+
} else if (params.delete) {
|
|
132
|
+
const selectQuery = q2.transacting(q2);
|
|
133
|
+
selectQuery.query.type = void 0;
|
|
134
|
+
idForDelete = await selectQuery._getOptional(foreignKey);
|
|
135
|
+
update[foreignKey] = null;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
const { upsert } = params;
|
|
139
|
+
if (upsert || params.update || params.delete) {
|
|
140
|
+
if (!((_a = q.query.select) == null ? void 0 : _a.includes("*")) && !((_b = q.query.select) == null ? void 0 : _b.includes(foreignKey))) {
|
|
141
|
+
q._select(foreignKey);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (upsert) {
|
|
145
|
+
if (!state.updateLater) {
|
|
146
|
+
state.updateLater = {};
|
|
147
|
+
state.updateLaterPromises = [];
|
|
148
|
+
}
|
|
149
|
+
const { handleResult } = q.query;
|
|
150
|
+
q.query.handleResult = async (q2, queryResult) => {
|
|
151
|
+
const data = await handleResult(q2, queryResult);
|
|
152
|
+
const id = data[0][foreignKey];
|
|
153
|
+
if (id !== null) {
|
|
154
|
+
await query.transacting(q2)._findBy({ [primaryKey]: id })._update(upsert.update);
|
|
155
|
+
} else {
|
|
156
|
+
state.updateLaterPromises.push(
|
|
157
|
+
query.transacting(q2)._select(primaryKey)._create(upsert.create).then((result) => {
|
|
158
|
+
state.updateLater[foreignKey] = result[primaryKey];
|
|
159
|
+
})
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
return data;
|
|
163
|
+
};
|
|
164
|
+
} else if (params.delete || params.update) {
|
|
165
|
+
q._afterQuery(async (q2, data) => {
|
|
166
|
+
const id = params.delete ? idForDelete : Array.isArray(data) ? data.length === 0 ? null : {
|
|
167
|
+
in: data.map((item) => item[foreignKey]).filter((id2) => id2 !== null)
|
|
168
|
+
} : data[foreignKey];
|
|
169
|
+
if (id !== void 0 && id !== null) {
|
|
170
|
+
const t = query.transacting(q2)._findBy({
|
|
171
|
+
[primaryKey]: id
|
|
172
|
+
});
|
|
173
|
+
if (params.delete) {
|
|
174
|
+
await t._delete();
|
|
175
|
+
} else if (params.update) {
|
|
176
|
+
await t._update(params.update);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return !params.update && !params.upsert;
|
|
182
|
+
},
|
|
183
|
+
joinQuery(fromQuery, toQuery) {
|
|
184
|
+
return pqb.addQueryOn(toQuery, fromQuery, toQuery, primaryKey, foreignKey);
|
|
185
|
+
},
|
|
186
|
+
reverseJoin(fromQuery, toQuery) {
|
|
187
|
+
return pqb.addQueryOn(fromQuery, toQuery, fromQuery, foreignKey, primaryKey);
|
|
188
|
+
},
|
|
189
|
+
primaryKey
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const getThroughRelation = (model, through) => {
|
|
194
|
+
return model.relations[through];
|
|
195
|
+
};
|
|
196
|
+
const getSourceRelation = (throughRelation, source) => {
|
|
197
|
+
return throughRelation.model.relations[source];
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
var __defProp$4 = Object.defineProperty;
|
|
201
|
+
var __defProps$2 = Object.defineProperties;
|
|
202
|
+
var __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors;
|
|
203
|
+
var __getOwnPropSymbols$4 = Object.getOwnPropertySymbols;
|
|
204
|
+
var __hasOwnProp$4 = Object.prototype.hasOwnProperty;
|
|
205
|
+
var __propIsEnum$4 = Object.prototype.propertyIsEnumerable;
|
|
206
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
207
|
+
var __spreadValues$4 = (a, b) => {
|
|
208
|
+
for (var prop in b || (b = {}))
|
|
209
|
+
if (__hasOwnProp$4.call(b, prop))
|
|
210
|
+
__defNormalProp$4(a, prop, b[prop]);
|
|
211
|
+
if (__getOwnPropSymbols$4)
|
|
212
|
+
for (var prop of __getOwnPropSymbols$4(b)) {
|
|
213
|
+
if (__propIsEnum$4.call(b, prop))
|
|
214
|
+
__defNormalProp$4(a, prop, b[prop]);
|
|
215
|
+
}
|
|
216
|
+
return a;
|
|
217
|
+
};
|
|
218
|
+
var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
|
|
219
|
+
const makeHasOneMethod = (model, relation, relationName, query) => {
|
|
220
|
+
if (relation.options.required) {
|
|
221
|
+
query._take();
|
|
222
|
+
} else {
|
|
223
|
+
query._takeOptional();
|
|
224
|
+
}
|
|
225
|
+
if ("through" in relation.options) {
|
|
226
|
+
const { through, source } = relation.options;
|
|
227
|
+
const throughRelation = getThroughRelation(model, through);
|
|
228
|
+
const sourceRelation = getSourceRelation(throughRelation, source);
|
|
229
|
+
const sourceQuery = sourceRelation.joinQuery(throughRelation.query, sourceRelation.query).as(relationName);
|
|
230
|
+
const whereExistsCallback = () => sourceQuery;
|
|
231
|
+
return {
|
|
232
|
+
returns: "one",
|
|
233
|
+
method: (params) => {
|
|
234
|
+
const throughQuery = model[through](params);
|
|
235
|
+
return query.whereExists(
|
|
236
|
+
throughQuery,
|
|
237
|
+
whereExistsCallback
|
|
238
|
+
);
|
|
239
|
+
},
|
|
240
|
+
nestedInsert: void 0,
|
|
241
|
+
nestedUpdate: void 0,
|
|
242
|
+
joinQuery(fromQuery, toQuery) {
|
|
243
|
+
return toQuery.whereExists(
|
|
244
|
+
throughRelation.joinQuery(fromQuery, throughRelation.query),
|
|
245
|
+
() => {
|
|
246
|
+
const as = pqb.getQueryAs(toQuery);
|
|
247
|
+
return sourceRelation.joinQuery(
|
|
248
|
+
throughRelation.query,
|
|
249
|
+
sourceRelation.query.as(as)
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
},
|
|
254
|
+
reverseJoin(fromQuery, toQuery) {
|
|
255
|
+
return fromQuery.whereExists(
|
|
256
|
+
throughRelation.joinQuery(fromQuery, throughRelation.query),
|
|
257
|
+
() => {
|
|
258
|
+
const as = pqb.getQueryAs(toQuery);
|
|
259
|
+
return sourceRelation.joinQuery(
|
|
260
|
+
throughRelation.query,
|
|
261
|
+
sourceRelation.query.as(as)
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
);
|
|
265
|
+
},
|
|
266
|
+
primaryKey: sourceRelation.primaryKey
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
const { primaryKey, foreignKey } = relation.options;
|
|
270
|
+
const fromQuerySelect = [{ selectAs: { [foreignKey]: primaryKey } }];
|
|
271
|
+
return {
|
|
272
|
+
returns: "one",
|
|
273
|
+
method: (params) => {
|
|
274
|
+
const values = { [foreignKey]: params[primaryKey] };
|
|
275
|
+
return query.where(values)._defaults(values);
|
|
276
|
+
},
|
|
277
|
+
nestedInsert: async (q, data) => {
|
|
278
|
+
const connect = data.filter(
|
|
279
|
+
(item) => Boolean(item[1].connect || item[1].connectOrCreate)
|
|
280
|
+
);
|
|
281
|
+
const t = query.transacting(q);
|
|
282
|
+
let connected;
|
|
283
|
+
if (connect.length) {
|
|
284
|
+
connected = await Promise.all(
|
|
285
|
+
connect.map(([selfData, item]) => {
|
|
286
|
+
const data2 = { [foreignKey]: selfData[primaryKey] };
|
|
287
|
+
return "connect" in item ? t.where(item.connect)._updateOrThrow(data2) : t.where(item.connectOrCreate.where)._update(data2);
|
|
288
|
+
})
|
|
289
|
+
);
|
|
290
|
+
} else {
|
|
291
|
+
connected = [];
|
|
292
|
+
}
|
|
293
|
+
let connectedI = 0;
|
|
294
|
+
const create = data.filter(
|
|
295
|
+
(item) => {
|
|
296
|
+
if (item[1].connectOrCreate) {
|
|
297
|
+
return !connected[connectedI++];
|
|
298
|
+
}
|
|
299
|
+
return Boolean(item[1].create);
|
|
300
|
+
}
|
|
301
|
+
);
|
|
302
|
+
if (create.length) {
|
|
303
|
+
await t._count()._createMany(
|
|
304
|
+
create.map(([selfData, item]) => __spreadValues$4({
|
|
305
|
+
[foreignKey]: selfData[primaryKey]
|
|
306
|
+
}, "create" in item ? item.create : item.connectOrCreate.create))
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
nestedUpdate: async (q, data, params) => {
|
|
311
|
+
if ((params.set || params.create || params.upsert) && pqb.isQueryReturnsAll(q)) {
|
|
312
|
+
const key = params.set ? "set" : params.create ? "create" : "upsert";
|
|
313
|
+
throw new Error(`\`${key}\` option is not allowed in a batch update`);
|
|
314
|
+
}
|
|
315
|
+
const t = query.transacting(q);
|
|
316
|
+
const ids = data.map((item) => item[primaryKey]);
|
|
317
|
+
const currentRelationsQuery = t.where({
|
|
318
|
+
[foreignKey]: { in: ids }
|
|
319
|
+
});
|
|
320
|
+
if (params.create || params.disconnect || params.set) {
|
|
321
|
+
await currentRelationsQuery._update({ [foreignKey]: null });
|
|
322
|
+
if (params.create) {
|
|
323
|
+
await t._count()._create(__spreadProps$2(__spreadValues$4({}, params.create), {
|
|
324
|
+
[foreignKey]: data[0][primaryKey]
|
|
325
|
+
}));
|
|
326
|
+
}
|
|
327
|
+
if (params.set) {
|
|
328
|
+
await t._where(params.set)._update({ [foreignKey]: data[0][primaryKey] });
|
|
329
|
+
}
|
|
330
|
+
} else if (params.update) {
|
|
331
|
+
await currentRelationsQuery._update(params.update);
|
|
332
|
+
} else if (params.delete) {
|
|
333
|
+
await currentRelationsQuery._delete();
|
|
334
|
+
} else if (params.upsert) {
|
|
335
|
+
const { update, create } = params.upsert;
|
|
336
|
+
const updatedIds = await currentRelationsQuery._pluck(foreignKey)._update(update);
|
|
337
|
+
if (updatedIds.length < ids.length) {
|
|
338
|
+
await t.createMany(
|
|
339
|
+
ids.filter((id) => !updatedIds.includes(id)).map((id) => __spreadProps$2(__spreadValues$4({}, create), {
|
|
340
|
+
[foreignKey]: id
|
|
341
|
+
}))
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
joinQuery(fromQuery, toQuery) {
|
|
347
|
+
return pqb.addQueryOn(toQuery, fromQuery, toQuery, foreignKey, primaryKey);
|
|
348
|
+
},
|
|
349
|
+
reverseJoin(fromQuery, toQuery) {
|
|
350
|
+
return pqb.addQueryOn(fromQuery, toQuery, fromQuery, primaryKey, foreignKey);
|
|
351
|
+
},
|
|
352
|
+
primaryKey,
|
|
353
|
+
modifyRelatedQuery(relationQuery) {
|
|
354
|
+
return (query2) => {
|
|
355
|
+
const fromQuery = query2.clone();
|
|
356
|
+
fromQuery.query.select = fromQuerySelect;
|
|
357
|
+
relationQuery.query.fromQuery = fromQuery;
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
var __defProp$3 = Object.defineProperty;
|
|
364
|
+
var __defProps$1 = Object.defineProperties;
|
|
365
|
+
var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
|
|
366
|
+
var __getOwnPropSymbols$3 = Object.getOwnPropertySymbols;
|
|
367
|
+
var __hasOwnProp$3 = Object.prototype.hasOwnProperty;
|
|
368
|
+
var __propIsEnum$3 = Object.prototype.propertyIsEnumerable;
|
|
369
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
370
|
+
var __spreadValues$3 = (a, b) => {
|
|
371
|
+
for (var prop in b || (b = {}))
|
|
372
|
+
if (__hasOwnProp$3.call(b, prop))
|
|
373
|
+
__defNormalProp$3(a, prop, b[prop]);
|
|
374
|
+
if (__getOwnPropSymbols$3)
|
|
375
|
+
for (var prop of __getOwnPropSymbols$3(b)) {
|
|
376
|
+
if (__propIsEnum$3.call(b, prop))
|
|
377
|
+
__defNormalProp$3(a, prop, b[prop]);
|
|
378
|
+
}
|
|
379
|
+
return a;
|
|
380
|
+
};
|
|
381
|
+
var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
|
|
382
|
+
const makeHasManyMethod = (model, relation, relationName, query) => {
|
|
383
|
+
if ("through" in relation.options) {
|
|
384
|
+
const { through, source } = relation.options;
|
|
385
|
+
const throughRelation = getThroughRelation(model, through);
|
|
386
|
+
const sourceRelation = getSourceRelation(throughRelation, source);
|
|
387
|
+
const sourceRelationQuery = sourceRelation.query.as(relationName);
|
|
388
|
+
const sourceQuery = sourceRelation.joinQuery(
|
|
389
|
+
throughRelation.query,
|
|
390
|
+
sourceRelationQuery
|
|
391
|
+
);
|
|
392
|
+
const whereExistsCallback = () => sourceQuery;
|
|
393
|
+
return {
|
|
394
|
+
returns: "many",
|
|
395
|
+
method: (params) => {
|
|
396
|
+
const throughQuery = model[through](params);
|
|
397
|
+
return query.whereExists(
|
|
398
|
+
throughQuery,
|
|
399
|
+
whereExistsCallback
|
|
400
|
+
);
|
|
401
|
+
},
|
|
402
|
+
nestedInsert: void 0,
|
|
403
|
+
nestedUpdate: void 0,
|
|
404
|
+
joinQuery(fromQuery, toQuery) {
|
|
405
|
+
return toQuery.whereExists(
|
|
406
|
+
throughRelation.joinQuery(fromQuery, throughRelation.query),
|
|
407
|
+
() => {
|
|
408
|
+
const as = pqb.getQueryAs(toQuery);
|
|
409
|
+
return sourceRelation.joinQuery(
|
|
410
|
+
throughRelation.query,
|
|
411
|
+
sourceRelation.query.as(as)
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
);
|
|
415
|
+
},
|
|
416
|
+
reverseJoin(fromQuery, toQuery) {
|
|
417
|
+
return fromQuery.whereExists(
|
|
418
|
+
throughRelation.joinQuery(fromQuery, throughRelation.query),
|
|
419
|
+
() => {
|
|
420
|
+
const as = pqb.getQueryAs(toQuery);
|
|
421
|
+
return sourceRelation.joinQuery(
|
|
422
|
+
throughRelation.query,
|
|
423
|
+
sourceRelation.query.as(as)
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
);
|
|
427
|
+
},
|
|
428
|
+
primaryKey: sourceRelation.primaryKey
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
const { primaryKey, foreignKey } = relation.options;
|
|
432
|
+
const fromQuerySelect = [{ selectAs: { [foreignKey]: primaryKey } }];
|
|
433
|
+
return {
|
|
434
|
+
returns: "many",
|
|
435
|
+
method: (params) => {
|
|
436
|
+
const values = { [foreignKey]: params[primaryKey] };
|
|
437
|
+
return query.where(values)._defaults(values);
|
|
438
|
+
},
|
|
439
|
+
nestedInsert: async (q, data) => {
|
|
440
|
+
const connect = data.filter(
|
|
441
|
+
(item) => Boolean(item[1].connect)
|
|
442
|
+
);
|
|
443
|
+
const t = query.transacting(q);
|
|
444
|
+
if (connect.length) {
|
|
445
|
+
await Promise.all(
|
|
446
|
+
connect.flatMap(
|
|
447
|
+
([selfData, { connect: connect2 }]) => connect2.map(
|
|
448
|
+
(item) => t.where(item)._updateOrThrow({ [foreignKey]: selfData[primaryKey] })
|
|
449
|
+
)
|
|
450
|
+
)
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
const connectOrCreate = data.filter(
|
|
454
|
+
(item) => Boolean(item[1].connectOrCreate)
|
|
455
|
+
);
|
|
456
|
+
let connected;
|
|
457
|
+
if (connectOrCreate.length) {
|
|
458
|
+
connected = await Promise.all(
|
|
459
|
+
connectOrCreate.flatMap(
|
|
460
|
+
([selfData, { connectOrCreate: connectOrCreate2 }]) => connectOrCreate2.map(
|
|
461
|
+
(item) => t.where(item.where)._update({
|
|
462
|
+
[foreignKey]: selfData[primaryKey]
|
|
463
|
+
})
|
|
464
|
+
)
|
|
465
|
+
)
|
|
466
|
+
);
|
|
467
|
+
} else {
|
|
468
|
+
connected = [];
|
|
469
|
+
}
|
|
470
|
+
let connectedI = 0;
|
|
471
|
+
const create = data.filter(
|
|
472
|
+
(item) => {
|
|
473
|
+
if (item[1].connectOrCreate) {
|
|
474
|
+
const length = item[1].connectOrCreate.length;
|
|
475
|
+
connectedI += length;
|
|
476
|
+
for (let i = length; i > 0; i--) {
|
|
477
|
+
if (connected[connectedI - i] === 0)
|
|
478
|
+
return true;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return Boolean(item[1].create);
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
connectedI = 0;
|
|
485
|
+
if (create.length) {
|
|
486
|
+
await t._createMany(
|
|
487
|
+
create.flatMap(
|
|
488
|
+
([selfData, { create: create2 = [], connectOrCreate: connectOrCreate2 = [] }]) => {
|
|
489
|
+
return [
|
|
490
|
+
...create2.map((item) => __spreadValues$3({
|
|
491
|
+
[foreignKey]: selfData[primaryKey]
|
|
492
|
+
}, item)),
|
|
493
|
+
...connectOrCreate2.filter(() => connected[connectedI++] === 0).map((item) => __spreadValues$3({
|
|
494
|
+
[foreignKey]: selfData[primaryKey]
|
|
495
|
+
}, item.create))
|
|
496
|
+
];
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
},
|
|
502
|
+
nestedUpdate: async (q, data, params) => {
|
|
503
|
+
var _a;
|
|
504
|
+
if ((params.set || params.create) && pqb.isQueryReturnsAll(q)) {
|
|
505
|
+
const key = params.set ? "set" : "create";
|
|
506
|
+
throw new Error(`\`${key}\` option is not allowed in a batch update`);
|
|
507
|
+
}
|
|
508
|
+
const t = query.transacting(q);
|
|
509
|
+
if (params.create) {
|
|
510
|
+
await t._count()._createMany(
|
|
511
|
+
params.create.map((create) => __spreadProps$1(__spreadValues$3({}, create), {
|
|
512
|
+
[foreignKey]: data[0][primaryKey]
|
|
513
|
+
}))
|
|
514
|
+
);
|
|
515
|
+
delete t.query[pqb.toSqlCacheKey];
|
|
516
|
+
}
|
|
517
|
+
if (params.disconnect || params.set) {
|
|
518
|
+
await t.where(
|
|
519
|
+
getWhereForNestedUpdate(
|
|
520
|
+
data,
|
|
521
|
+
params.disconnect,
|
|
522
|
+
primaryKey,
|
|
523
|
+
foreignKey
|
|
524
|
+
)
|
|
525
|
+
)._update({ [foreignKey]: null });
|
|
526
|
+
if (params.set) {
|
|
527
|
+
delete t.query[pqb.toSqlCacheKey];
|
|
528
|
+
await t.where(
|
|
529
|
+
Array.isArray(params.set) ? {
|
|
530
|
+
OR: params.set
|
|
531
|
+
} : params.set
|
|
532
|
+
)._update({ [foreignKey]: data[0][primaryKey] });
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (params.delete || params.update) {
|
|
536
|
+
delete t.query[pqb.toSqlCacheKey];
|
|
537
|
+
const q2 = t._where(
|
|
538
|
+
getWhereForNestedUpdate(
|
|
539
|
+
data,
|
|
540
|
+
params.delete || ((_a = params.update) == null ? void 0 : _a.where),
|
|
541
|
+
primaryKey,
|
|
542
|
+
foreignKey
|
|
543
|
+
)
|
|
544
|
+
);
|
|
545
|
+
if (params.delete) {
|
|
546
|
+
await q2._delete();
|
|
547
|
+
} else if (params.update) {
|
|
548
|
+
await q2._update(params.update.data);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
joinQuery(fromQuery, toQuery) {
|
|
553
|
+
return pqb.addQueryOn(toQuery, fromQuery, toQuery, foreignKey, primaryKey);
|
|
554
|
+
},
|
|
555
|
+
reverseJoin(fromQuery, toQuery) {
|
|
556
|
+
return pqb.addQueryOn(fromQuery, toQuery, fromQuery, primaryKey, foreignKey);
|
|
557
|
+
},
|
|
558
|
+
primaryKey,
|
|
559
|
+
modifyRelatedQuery(relationQuery) {
|
|
560
|
+
return (query2) => {
|
|
561
|
+
const fromQuery = query2.clone();
|
|
562
|
+
fromQuery.query.select = fromQuerySelect;
|
|
563
|
+
relationQuery.query.fromQuery = fromQuery;
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
};
|
|
568
|
+
const getWhereForNestedUpdate = (data, params, primaryKey, foreignKey) => {
|
|
569
|
+
const where = {
|
|
570
|
+
[foreignKey]: { in: data.map((item) => item[primaryKey]) }
|
|
571
|
+
};
|
|
572
|
+
if (params) {
|
|
573
|
+
if (Array.isArray(params)) {
|
|
574
|
+
where.OR = params;
|
|
575
|
+
} else {
|
|
576
|
+
Object.assign(where, params);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
return where;
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
var __defProp$2 = Object.defineProperty;
|
|
583
|
+
var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
|
|
584
|
+
var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
|
|
585
|
+
var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
|
|
586
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
587
|
+
var __spreadValues$2 = (a, b) => {
|
|
588
|
+
for (var prop in b || (b = {}))
|
|
589
|
+
if (__hasOwnProp$2.call(b, prop))
|
|
590
|
+
__defNormalProp$2(a, prop, b[prop]);
|
|
591
|
+
if (__getOwnPropSymbols$2)
|
|
592
|
+
for (var prop of __getOwnPropSymbols$2(b)) {
|
|
593
|
+
if (__propIsEnum$2.call(b, prop))
|
|
594
|
+
__defNormalProp$2(a, prop, b[prop]);
|
|
595
|
+
}
|
|
596
|
+
return a;
|
|
597
|
+
};
|
|
598
|
+
const makeHasAndBelongsToManyMethod = (model, qb, relation, query) => {
|
|
599
|
+
const {
|
|
600
|
+
primaryKey: pk,
|
|
601
|
+
foreignKey: fk,
|
|
602
|
+
associationPrimaryKey: apk,
|
|
603
|
+
associationForeignKey: afk,
|
|
604
|
+
joinTable
|
|
605
|
+
} = relation.options;
|
|
606
|
+
const foreignKeyFull = `${joinTable}.${fk}`;
|
|
607
|
+
const associationForeignKeyFull = `${joinTable}.${afk}`;
|
|
608
|
+
const associationPrimaryKeyFull = `${pqb.getQueryAs(query)}.${apk}`;
|
|
609
|
+
const __model = Object.create(qb.__model);
|
|
610
|
+
__model.__model = __model;
|
|
611
|
+
__model.table = joinTable;
|
|
612
|
+
__model.shape = {
|
|
613
|
+
[fk]: model.shape[pk],
|
|
614
|
+
[afk]: query.shape[apk]
|
|
615
|
+
};
|
|
616
|
+
const subQuery = Object.create(__model);
|
|
617
|
+
subQuery.query = __spreadValues$2({}, subQuery.query);
|
|
618
|
+
const state = {
|
|
619
|
+
relatedTableQuery: query,
|
|
620
|
+
joinTableQuery: subQuery,
|
|
621
|
+
primaryKey: pk,
|
|
622
|
+
foreignKey: fk,
|
|
623
|
+
associationPrimaryKey: apk,
|
|
624
|
+
associationForeignKey: afk
|
|
625
|
+
};
|
|
626
|
+
return {
|
|
627
|
+
returns: "many",
|
|
628
|
+
method(params) {
|
|
629
|
+
return query.whereExists(
|
|
630
|
+
subQuery,
|
|
631
|
+
(q) => q.on(associationForeignKeyFull, associationPrimaryKeyFull).where({
|
|
632
|
+
[foreignKeyFull]: params[pk]
|
|
633
|
+
})
|
|
634
|
+
);
|
|
635
|
+
},
|
|
636
|
+
nestedInsert: async (q, data) => {
|
|
637
|
+
const connect = data.filter(
|
|
638
|
+
(item) => Boolean(item[1].connect)
|
|
639
|
+
);
|
|
640
|
+
const t = query.transacting(q);
|
|
641
|
+
let connected;
|
|
642
|
+
if (connect.length) {
|
|
643
|
+
connected = await Promise.all(
|
|
644
|
+
connect.flatMap(
|
|
645
|
+
([, { connect: connect2 }]) => connect2.map((item) => t.select(apk)._findBy(item)._take())
|
|
646
|
+
)
|
|
647
|
+
);
|
|
648
|
+
} else {
|
|
649
|
+
connected = [];
|
|
650
|
+
}
|
|
651
|
+
const connectOrCreate = data.filter(
|
|
652
|
+
(item) => Boolean(item[1].connectOrCreate)
|
|
653
|
+
);
|
|
654
|
+
let connectOrCreated;
|
|
655
|
+
if (connectOrCreate.length) {
|
|
656
|
+
connectOrCreated = await Promise.all(
|
|
657
|
+
connectOrCreate.flatMap(
|
|
658
|
+
([, { connectOrCreate: connectOrCreate2 }]) => connectOrCreate2.map(
|
|
659
|
+
(item) => t.select(apk)._findBy(item.where)._takeOptional()
|
|
660
|
+
)
|
|
661
|
+
)
|
|
662
|
+
);
|
|
663
|
+
} else {
|
|
664
|
+
connectOrCreated = [];
|
|
665
|
+
}
|
|
666
|
+
let connectOrCreateI = 0;
|
|
667
|
+
const create = data.filter(
|
|
668
|
+
(item) => {
|
|
669
|
+
if (item[1].connectOrCreate) {
|
|
670
|
+
const length = item[1].connectOrCreate.length;
|
|
671
|
+
connectOrCreateI += length;
|
|
672
|
+
for (let i = length; i > 0; i--) {
|
|
673
|
+
if (!connectOrCreated[connectOrCreateI - i])
|
|
674
|
+
return true;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return Boolean(item[1].create);
|
|
678
|
+
}
|
|
679
|
+
);
|
|
680
|
+
connectOrCreateI = 0;
|
|
681
|
+
let created;
|
|
682
|
+
if (create.length) {
|
|
683
|
+
created = await t.select(apk)._createMany(
|
|
684
|
+
create.flatMap(([, { create: create2 = [], connectOrCreate: connectOrCreate2 = [] }]) => [
|
|
685
|
+
...create2,
|
|
686
|
+
...connectOrCreate2.filter(() => !connectOrCreated[connectOrCreateI++]).map((item) => item.create)
|
|
687
|
+
])
|
|
688
|
+
);
|
|
689
|
+
} else {
|
|
690
|
+
created = [];
|
|
691
|
+
}
|
|
692
|
+
const allKeys = data;
|
|
693
|
+
let createI = 0;
|
|
694
|
+
let connectI = 0;
|
|
695
|
+
connectOrCreateI = 0;
|
|
696
|
+
data.forEach(([, data2], index) => {
|
|
697
|
+
if (data2.create || data2.connectOrCreate) {
|
|
698
|
+
if (data2.create) {
|
|
699
|
+
const len = data2.create.length;
|
|
700
|
+
allKeys[index][1] = created.slice(createI, createI + len);
|
|
701
|
+
createI += len;
|
|
702
|
+
}
|
|
703
|
+
if (data2.connectOrCreate) {
|
|
704
|
+
const arr = [];
|
|
705
|
+
allKeys[index][1] = arr;
|
|
706
|
+
const len = data2.connectOrCreate.length;
|
|
707
|
+
for (let i = 0; i < len; i++) {
|
|
708
|
+
const item = connectOrCreated[connectOrCreateI++];
|
|
709
|
+
if (item) {
|
|
710
|
+
arr.push(item);
|
|
711
|
+
} else {
|
|
712
|
+
arr.push(created[createI++]);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
if (data2.connect) {
|
|
718
|
+
const len = data2.connect.length;
|
|
719
|
+
allKeys[index][1] = connected.slice(connectI, connectI + len);
|
|
720
|
+
connectI += len;
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
await subQuery.transacting(q)._count()._createMany(
|
|
724
|
+
allKeys.flatMap(([selfData, relationKeys]) => {
|
|
725
|
+
const selfKey = selfData[pk];
|
|
726
|
+
return relationKeys.map((relationData) => ({
|
|
727
|
+
[fk]: selfKey,
|
|
728
|
+
[afk]: relationData[apk]
|
|
729
|
+
}));
|
|
730
|
+
})
|
|
731
|
+
);
|
|
732
|
+
},
|
|
733
|
+
nestedUpdate: async (q, data, params) => {
|
|
734
|
+
if (params.create) {
|
|
735
|
+
const ids = await query.transacting(q)._pluck(apk)._createMany(params.create);
|
|
736
|
+
await subQuery.transacting(q)._createMany(
|
|
737
|
+
data.flatMap(
|
|
738
|
+
(item) => ids.map((id) => ({
|
|
739
|
+
[fk]: item[pk],
|
|
740
|
+
[afk]: id
|
|
741
|
+
}))
|
|
742
|
+
)
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
if (params.update) {
|
|
746
|
+
await query.transacting(q)._whereExists(
|
|
747
|
+
subQuery,
|
|
748
|
+
(q2) => q2._on(associationForeignKeyFull, associationPrimaryKeyFull)._where({
|
|
749
|
+
IN: {
|
|
750
|
+
columns: [foreignKeyFull],
|
|
751
|
+
values: [data.map((item) => item[pk])]
|
|
752
|
+
}
|
|
753
|
+
})
|
|
754
|
+
)._where(
|
|
755
|
+
Array.isArray(params.update.where) ? { OR: params.update.where } : params.update.where
|
|
756
|
+
)._update(params.update.data);
|
|
757
|
+
}
|
|
758
|
+
if (params.disconnect) {
|
|
759
|
+
await queryJoinTable(state, q, data, params.disconnect)._delete();
|
|
760
|
+
}
|
|
761
|
+
if (params.delete) {
|
|
762
|
+
const j = queryJoinTable(state, q, data, params.delete);
|
|
763
|
+
const ids = await j._pluck(afk)._delete();
|
|
764
|
+
await queryRelatedTable(query, q, { [apk]: { in: ids } })._delete();
|
|
765
|
+
}
|
|
766
|
+
if (params.set) {
|
|
767
|
+
const j = queryJoinTable(state, q, data);
|
|
768
|
+
await j._delete();
|
|
769
|
+
delete j.query[pqb.toSqlCacheKey];
|
|
770
|
+
const ids = await queryRelatedTable(query, q, params.set)._pluck(apk);
|
|
771
|
+
await insertToJoinTable(state, j, data, ids);
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
joinQuery(fromQuery, toQuery) {
|
|
775
|
+
return toQuery.whereExists(
|
|
776
|
+
subQuery,
|
|
777
|
+
(q) => q._on(associationForeignKeyFull, `${pqb.getQueryAs(toQuery)}.${pk}`)._on(foreignKeyFull, `${pqb.getQueryAs(fromQuery)}.${pk}`)
|
|
778
|
+
);
|
|
779
|
+
},
|
|
780
|
+
reverseJoin(fromQuery, toQuery) {
|
|
781
|
+
return fromQuery.whereExists(
|
|
782
|
+
subQuery,
|
|
783
|
+
(q) => q._on(associationForeignKeyFull, `${pqb.getQueryAs(toQuery)}.${pk}`)._on(foreignKeyFull, `${pqb.getQueryAs(fromQuery)}.${pk}`)
|
|
784
|
+
);
|
|
785
|
+
},
|
|
786
|
+
primaryKey: pk,
|
|
787
|
+
modifyRelatedQuery(relationQuery) {
|
|
788
|
+
const ref = {};
|
|
789
|
+
pqb.pushQueryValue(
|
|
790
|
+
relationQuery,
|
|
791
|
+
"afterCreate",
|
|
792
|
+
async (q, result) => {
|
|
793
|
+
const fromQuery = ref.query.clone();
|
|
794
|
+
fromQuery.query.select = [{ selectAs: { [fk]: pk } }];
|
|
795
|
+
const createdCount = await subQuery.transacting(q).count()._createFrom(
|
|
796
|
+
fromQuery,
|
|
797
|
+
{
|
|
798
|
+
[afk]: result[apk]
|
|
799
|
+
}
|
|
800
|
+
);
|
|
801
|
+
if (createdCount === 0) {
|
|
802
|
+
throw new pqb.NotFoundError();
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
);
|
|
806
|
+
return (q) => {
|
|
807
|
+
ref.query = q;
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
};
|
|
812
|
+
const queryJoinTable = (state, q, data, conditions) => {
|
|
813
|
+
const t = state.joinTableQuery.transacting(q);
|
|
814
|
+
const where = {
|
|
815
|
+
[state.foreignKey]: { in: data.map((item) => item[state.primaryKey]) }
|
|
816
|
+
};
|
|
817
|
+
if (conditions) {
|
|
818
|
+
where[state.associationForeignKey] = {
|
|
819
|
+
in: state.relatedTableQuery.where(
|
|
820
|
+
Array.isArray(conditions) ? { OR: conditions } : conditions
|
|
821
|
+
)._select(state.associationPrimaryKey)
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
return t._where(where);
|
|
825
|
+
};
|
|
826
|
+
const queryRelatedTable = (query, q, conditions) => {
|
|
827
|
+
return query.transacting(q)._where(Array.isArray(conditions) ? { OR: conditions } : conditions);
|
|
828
|
+
};
|
|
829
|
+
const insertToJoinTable = (state, joinTableTransaction, data, ids) => {
|
|
830
|
+
return joinTableTransaction._count()._createMany(
|
|
831
|
+
data.flatMap(
|
|
832
|
+
(item) => ids.map((id) => ({
|
|
833
|
+
[state.foreignKey]: item[state.primaryKey],
|
|
834
|
+
[state.associationForeignKey]: id
|
|
835
|
+
}))
|
|
836
|
+
)
|
|
837
|
+
);
|
|
838
|
+
};
|
|
839
|
+
|
|
840
|
+
const applyRelations = (qb, models, result) => {
|
|
841
|
+
const modelsEntries = Object.entries(models);
|
|
842
|
+
const delayedRelations = /* @__PURE__ */ new Map();
|
|
843
|
+
for (const modelName in models) {
|
|
844
|
+
const model = models[modelName];
|
|
845
|
+
if (!("relations" in model) || typeof model.relations !== "object")
|
|
846
|
+
continue;
|
|
847
|
+
const dbModel = result[modelName];
|
|
848
|
+
for (const relationName in model.relations) {
|
|
849
|
+
const relation = model.relations[relationName];
|
|
850
|
+
const otherModelClass = relation.fn();
|
|
851
|
+
const otherModel = modelsEntries.find(
|
|
852
|
+
(pair) => pair[1] instanceof otherModelClass
|
|
853
|
+
);
|
|
854
|
+
if (!otherModel) {
|
|
855
|
+
throw new Error(`Cannot find model for class ${otherModelClass.name}`);
|
|
856
|
+
}
|
|
857
|
+
const otherModelName = otherModel[0];
|
|
858
|
+
const otherDbModel = result[otherModelName];
|
|
859
|
+
if (!otherDbModel)
|
|
860
|
+
throw new Error(`Cannot find model by name ${otherModelName}`);
|
|
861
|
+
const data = {
|
|
862
|
+
relationName,
|
|
863
|
+
relation,
|
|
864
|
+
dbModel,
|
|
865
|
+
otherDbModel
|
|
866
|
+
};
|
|
867
|
+
const options = relation.options;
|
|
868
|
+
if (typeof options.through === "string" && typeof options.source === "string") {
|
|
869
|
+
const throughRelation = getThroughRelation(dbModel, options.through);
|
|
870
|
+
if (!throughRelation) {
|
|
871
|
+
delayRelation(delayedRelations, dbModel, options.through, data);
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
const sourceRelation = getSourceRelation(
|
|
875
|
+
throughRelation,
|
|
876
|
+
options.source
|
|
877
|
+
);
|
|
878
|
+
if (!sourceRelation) {
|
|
879
|
+
delayRelation(
|
|
880
|
+
delayedRelations,
|
|
881
|
+
throughRelation.model,
|
|
882
|
+
options.source,
|
|
883
|
+
data
|
|
884
|
+
);
|
|
885
|
+
continue;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
applyRelation(qb, data, delayedRelations);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
const delayRelation = (delayedRelations, model, relationName, data) => {
|
|
893
|
+
let modelRelations = delayedRelations.get(model);
|
|
894
|
+
if (!modelRelations) {
|
|
895
|
+
modelRelations = {};
|
|
896
|
+
delayedRelations.set(model, modelRelations);
|
|
897
|
+
}
|
|
898
|
+
if (modelRelations[relationName]) {
|
|
899
|
+
modelRelations[relationName].push(data);
|
|
900
|
+
} else {
|
|
901
|
+
modelRelations[relationName] = [data];
|
|
902
|
+
}
|
|
903
|
+
};
|
|
904
|
+
const applyRelation = (qb, { relationName, relation, dbModel, otherDbModel }, delayedRelations) => {
|
|
905
|
+
var _a;
|
|
906
|
+
const query = (relation.options.scope ? relation.options.scope(otherDbModel) : otherDbModel).as(relationName);
|
|
907
|
+
const definedAs = query.definedAs;
|
|
908
|
+
if (!definedAs) {
|
|
909
|
+
throw new Error(
|
|
910
|
+
`Model for table ${query.table} is not attached to db instance`
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
const { type } = relation;
|
|
914
|
+
let data;
|
|
915
|
+
if (type === "belongsTo") {
|
|
916
|
+
data = makeBelongsToMethod(relation, query);
|
|
917
|
+
} else if (type === "hasOne") {
|
|
918
|
+
data = makeHasOneMethod(dbModel, relation, relationName, query);
|
|
919
|
+
} else if (type === "hasMany") {
|
|
920
|
+
data = makeHasManyMethod(dbModel, relation, relationName, query);
|
|
921
|
+
} else if (type === "hasAndBelongsToMany") {
|
|
922
|
+
data = makeHasAndBelongsToManyMethod(dbModel, qb, relation, query);
|
|
923
|
+
} else {
|
|
924
|
+
throw new Error(`Unknown relation type ${type}`);
|
|
925
|
+
}
|
|
926
|
+
if (data.returns === "one") {
|
|
927
|
+
query._take();
|
|
928
|
+
}
|
|
929
|
+
makeRelationQuery(dbModel, definedAs, relationName, data);
|
|
930
|
+
dbModel.relations[relationName] = {
|
|
931
|
+
type,
|
|
932
|
+
key: relationName,
|
|
933
|
+
model: otherDbModel,
|
|
934
|
+
query,
|
|
935
|
+
nestedInsert: data.nestedInsert,
|
|
936
|
+
nestedUpdate: data.nestedUpdate,
|
|
937
|
+
joinQuery: data.joinQuery,
|
|
938
|
+
primaryKey: data.primaryKey,
|
|
939
|
+
options: relation.options
|
|
940
|
+
};
|
|
941
|
+
const modelRelations = delayedRelations.get(dbModel);
|
|
942
|
+
if (!modelRelations)
|
|
943
|
+
return;
|
|
944
|
+
(_a = modelRelations[relationName]) == null ? void 0 : _a.forEach((data2) => {
|
|
945
|
+
applyRelation(qb, data2, delayedRelations);
|
|
946
|
+
});
|
|
947
|
+
};
|
|
948
|
+
const makeRelationQuery = (model, definedAs, relationName, data) => {
|
|
949
|
+
Object.defineProperty(model, relationName, {
|
|
950
|
+
get() {
|
|
951
|
+
var _a;
|
|
952
|
+
const toModel = this.db[definedAs].as(relationName);
|
|
953
|
+
if (data.returns === "one") {
|
|
954
|
+
toModel._take();
|
|
955
|
+
}
|
|
956
|
+
const query = this.isSubQuery ? toModel : toModel._whereExists(data.reverseJoin(this, toModel), (q) => q);
|
|
957
|
+
query.query[pqb.relationQueryKey] = {
|
|
958
|
+
relationName,
|
|
959
|
+
sourceQuery: this,
|
|
960
|
+
relationQuery: toModel,
|
|
961
|
+
joinQuery: data.joinQuery
|
|
962
|
+
};
|
|
963
|
+
const setQuery = (_a = data.modifyRelatedQuery) == null ? void 0 : _a.call(data, query);
|
|
964
|
+
setQuery == null ? void 0 : setQuery(this);
|
|
965
|
+
return new Proxy(data.method, {
|
|
966
|
+
get(_, prop) {
|
|
967
|
+
return query[prop];
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
});
|
|
972
|
+
};
|
|
973
|
+
|
|
974
|
+
function transaction(fn) {
|
|
975
|
+
if (fn.length === 0) {
|
|
976
|
+
throw new Error("Argument of $transaction callback should be used");
|
|
977
|
+
}
|
|
978
|
+
return this.$queryBuilder.transaction((q) => {
|
|
979
|
+
const orm = {};
|
|
980
|
+
for (const key in this) {
|
|
981
|
+
const value = this[key];
|
|
982
|
+
if (value instanceof pqb.Db) {
|
|
983
|
+
const model = value.transacting(q);
|
|
984
|
+
model.__model = model;
|
|
985
|
+
model.db = orm;
|
|
986
|
+
orm[key] = model;
|
|
987
|
+
} else {
|
|
988
|
+
orm[key] = value;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
return fn(orm);
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
var __defProp$1 = Object.defineProperty;
|
|
996
|
+
var __defProps = Object.defineProperties;
|
|
997
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
998
|
+
var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
|
|
999
|
+
var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
|
|
1000
|
+
var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
|
|
1001
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1002
|
+
var __spreadValues$1 = (a, b) => {
|
|
1003
|
+
for (var prop in b || (b = {}))
|
|
1004
|
+
if (__hasOwnProp$1.call(b, prop))
|
|
1005
|
+
__defNormalProp$1(a, prop, b[prop]);
|
|
1006
|
+
if (__getOwnPropSymbols$1)
|
|
1007
|
+
for (var prop of __getOwnPropSymbols$1(b)) {
|
|
1008
|
+
if (__propIsEnum$1.call(b, prop))
|
|
1009
|
+
__defNormalProp$1(a, prop, b[prop]);
|
|
1010
|
+
}
|
|
1011
|
+
return a;
|
|
1012
|
+
};
|
|
1013
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
1014
|
+
var __objRest = (source, exclude) => {
|
|
1015
|
+
var target = {};
|
|
1016
|
+
for (var prop in source)
|
|
1017
|
+
if (__hasOwnProp$1.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
1018
|
+
target[prop] = source[prop];
|
|
1019
|
+
if (source != null && __getOwnPropSymbols$1)
|
|
1020
|
+
for (var prop of __getOwnPropSymbols$1(source)) {
|
|
1021
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum$1.call(source, prop))
|
|
1022
|
+
target[prop] = source[prop];
|
|
1023
|
+
}
|
|
1024
|
+
return target;
|
|
1025
|
+
};
|
|
1026
|
+
const orchidORM = (_a, models) => {
|
|
1027
|
+
var _b = _a, {
|
|
1028
|
+
log,
|
|
1029
|
+
logger
|
|
1030
|
+
} = _b, options = __objRest(_b, [
|
|
1031
|
+
"log",
|
|
1032
|
+
"logger"
|
|
1033
|
+
]);
|
|
1034
|
+
const adapter = "adapter" in options ? options.adapter : new pqb.Adapter(options);
|
|
1035
|
+
const commonOptions = { log, logger };
|
|
1036
|
+
const qb = new pqb.Db(
|
|
1037
|
+
adapter,
|
|
1038
|
+
void 0,
|
|
1039
|
+
void 0,
|
|
1040
|
+
{},
|
|
1041
|
+
pqb.columnTypes,
|
|
1042
|
+
commonOptions
|
|
1043
|
+
);
|
|
1044
|
+
qb.queryBuilder = qb;
|
|
1045
|
+
const result = {
|
|
1046
|
+
$transaction: transaction,
|
|
1047
|
+
$adapter: adapter,
|
|
1048
|
+
$queryBuilder: qb,
|
|
1049
|
+
$close: () => adapter.close()
|
|
1050
|
+
};
|
|
1051
|
+
const modelInstances = {};
|
|
1052
|
+
for (const key in models) {
|
|
1053
|
+
if (key[0] === "$") {
|
|
1054
|
+
throw new Error(`Model name must not start with $`);
|
|
1055
|
+
}
|
|
1056
|
+
const model = new models[key]();
|
|
1057
|
+
modelInstances[key] = model;
|
|
1058
|
+
const dbModel = new pqb.Db(
|
|
1059
|
+
adapter,
|
|
1060
|
+
qb,
|
|
1061
|
+
model.table,
|
|
1062
|
+
model.columns.shape,
|
|
1063
|
+
model.columnTypes,
|
|
1064
|
+
__spreadProps(__spreadValues$1({}, commonOptions), {
|
|
1065
|
+
schema: model.schema
|
|
1066
|
+
})
|
|
1067
|
+
);
|
|
1068
|
+
dbModel.definedAs = key;
|
|
1069
|
+
dbModel.db = result;
|
|
1070
|
+
result[key] = dbModel;
|
|
1071
|
+
}
|
|
1072
|
+
applyRelations(qb, modelInstances, result);
|
|
1073
|
+
return result;
|
|
1074
|
+
};
|
|
1075
|
+
|
|
1076
|
+
var __defProp = Object.defineProperty;
|
|
1077
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
1078
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
1079
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
1080
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1081
|
+
var __spreadValues = (a, b) => {
|
|
1082
|
+
for (var prop in b || (b = {}))
|
|
1083
|
+
if (__hasOwnProp.call(b, prop))
|
|
1084
|
+
__defNormalProp(a, prop, b[prop]);
|
|
1085
|
+
if (__getOwnPropSymbols)
|
|
1086
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
1087
|
+
if (__propIsEnum.call(b, prop))
|
|
1088
|
+
__defNormalProp(a, prop, b[prop]);
|
|
1089
|
+
}
|
|
1090
|
+
return a;
|
|
1091
|
+
};
|
|
1092
|
+
const createRepo = (model, methods) => {
|
|
1093
|
+
const queryMethods = __spreadValues(__spreadValues(__spreadValues(__spreadValues({}, methods.queryMethods), methods.queryOneMethods), methods.queryWithWhereMethods), methods.queryOneWithWhereMethods);
|
|
1094
|
+
const plainMethods = methods.methods;
|
|
1095
|
+
const repo = (q2) => {
|
|
1096
|
+
const proto = Object.create(q2.__model);
|
|
1097
|
+
proto.__model = proto;
|
|
1098
|
+
const result = Object.create(proto);
|
|
1099
|
+
result.query = pqb.getClonedQueryData(q2.query);
|
|
1100
|
+
if (plainMethods) {
|
|
1101
|
+
Object.assign(proto.__model, plainMethods);
|
|
1102
|
+
}
|
|
1103
|
+
for (const key in queryMethods) {
|
|
1104
|
+
const method = queryMethods[key];
|
|
1105
|
+
proto.__model[key] = function(...args) {
|
|
1106
|
+
return method(this, ...args);
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1109
|
+
return result;
|
|
1110
|
+
};
|
|
1111
|
+
const q = repo(model);
|
|
1112
|
+
return new Proxy(repo, {
|
|
1113
|
+
get(_, key) {
|
|
1114
|
+
return q[key];
|
|
1115
|
+
}
|
|
1116
|
+
});
|
|
1117
|
+
};
|
|
1118
|
+
|
|
1119
|
+
exports.createModel = createModel;
|
|
1120
|
+
exports.createRepo = createRepo;
|
|
1121
|
+
exports.orchidORM = orchidORM;
|
|
1122
|
+
//# sourceMappingURL=index.js.map
|