orchid-orm 1.3.14 → 1.3.16
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/CHANGELOG.md +15 -0
- package/dist/index.d.ts +21 -23
- package/dist/index.esm.js +678 -450
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +677 -449
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/relations/belongsTo.ts +289 -184
- package/src/relations/hasAndBelongsToMany.ts +283 -209
- package/src/relations/hasMany.ts +237 -166
- package/src/relations/hasOne.ts +205 -132
- package/src/relations/relations.ts +14 -8
- package/src/relations/utils.ts +151 -1
package/src/relations/hasOne.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
addQueryOn,
|
|
3
|
+
CreateCtx,
|
|
3
4
|
getQueryAs,
|
|
4
|
-
HasOneNestedInsert,
|
|
5
|
-
HasOneNestedUpdate,
|
|
6
5
|
HasOneRelation,
|
|
7
6
|
InsertQueryData,
|
|
8
7
|
isQueryReturnsAll,
|
|
9
8
|
JoinCallback,
|
|
10
9
|
Query,
|
|
11
10
|
QueryBase,
|
|
11
|
+
UpdateCtx,
|
|
12
|
+
VirtualColumn,
|
|
12
13
|
WhereArg,
|
|
13
14
|
WhereResult,
|
|
14
15
|
} from 'pqb';
|
|
@@ -19,7 +20,14 @@ import {
|
|
|
19
20
|
RelationThunkBase,
|
|
20
21
|
RelationThunks,
|
|
21
22
|
} from './relations';
|
|
22
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
getSourceRelation,
|
|
25
|
+
getThroughRelation,
|
|
26
|
+
hasRelationHandleCreate,
|
|
27
|
+
hasRelationHandleUpdate,
|
|
28
|
+
NestedInsertOneItem,
|
|
29
|
+
NestedUpdateOneItem,
|
|
30
|
+
} from './utils';
|
|
23
31
|
|
|
24
32
|
export interface HasOne extends RelationThunkBase {
|
|
25
33
|
type: 'hasOne';
|
|
@@ -53,6 +61,65 @@ export type HasOneInfo<
|
|
|
53
61
|
chainedDelete: true;
|
|
54
62
|
};
|
|
55
63
|
|
|
64
|
+
type State = {
|
|
65
|
+
query: Query;
|
|
66
|
+
primaryKey: string;
|
|
67
|
+
foreignKey: string;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export type HasOneNestedInsert = (
|
|
71
|
+
query: Query,
|
|
72
|
+
data: [
|
|
73
|
+
selfData: Record<string, unknown>,
|
|
74
|
+
relationData: NestedInsertOneItem,
|
|
75
|
+
][],
|
|
76
|
+
) => Promise<void>;
|
|
77
|
+
|
|
78
|
+
export type HasOneNestedUpdate = (
|
|
79
|
+
query: Query,
|
|
80
|
+
data: Record<string, unknown>[],
|
|
81
|
+
relationData: NestedUpdateOneItem,
|
|
82
|
+
) => Promise<void>;
|
|
83
|
+
|
|
84
|
+
class HasOneVirtualColumn extends VirtualColumn {
|
|
85
|
+
private readonly nestedInsert: HasOneNestedInsert;
|
|
86
|
+
private readonly nestedUpdate: HasOneNestedUpdate;
|
|
87
|
+
|
|
88
|
+
constructor(private key: string, private state: State) {
|
|
89
|
+
super();
|
|
90
|
+
this.nestedInsert = nestedInsert(state);
|
|
91
|
+
this.nestedUpdate = nestedUpdate(state);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
create(
|
|
95
|
+
q: Query,
|
|
96
|
+
ctx: CreateCtx,
|
|
97
|
+
item: Record<string, unknown>,
|
|
98
|
+
rowIndex: number,
|
|
99
|
+
) {
|
|
100
|
+
hasRelationHandleCreate(
|
|
101
|
+
q,
|
|
102
|
+
ctx,
|
|
103
|
+
item,
|
|
104
|
+
rowIndex,
|
|
105
|
+
this.key,
|
|
106
|
+
this.state.primaryKey,
|
|
107
|
+
this.nestedInsert,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
update(q: Query, ctx: UpdateCtx, set: Record<string, unknown>) {
|
|
112
|
+
hasRelationHandleUpdate(
|
|
113
|
+
q,
|
|
114
|
+
ctx,
|
|
115
|
+
set,
|
|
116
|
+
this.key,
|
|
117
|
+
this.state.primaryKey,
|
|
118
|
+
this.nestedUpdate,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
56
123
|
export const makeHasOneMethod = (
|
|
57
124
|
model: Query,
|
|
58
125
|
relation: HasOne,
|
|
@@ -93,8 +160,6 @@ export const makeHasOneMethod = (
|
|
|
93
160
|
whereExistsCallback as unknown as JoinCallback<Query, Query>,
|
|
94
161
|
);
|
|
95
162
|
},
|
|
96
|
-
nestedInsert: undefined,
|
|
97
|
-
nestedUpdate: undefined,
|
|
98
163
|
joinQuery(fromQuery, toQuery) {
|
|
99
164
|
return toQuery.whereExists<Query, Query>(
|
|
100
165
|
throughRelation.joinQuery(fromQuery, throughRelation.query),
|
|
@@ -124,6 +189,7 @@ export const makeHasOneMethod = (
|
|
|
124
189
|
}
|
|
125
190
|
|
|
126
191
|
const { primaryKey, foreignKey } = relation.options;
|
|
192
|
+
const state: State = { query, primaryKey, foreignKey };
|
|
127
193
|
|
|
128
194
|
const fromQuerySelect = [{ selectAs: { [foreignKey]: primaryKey } }];
|
|
129
195
|
|
|
@@ -133,133 +199,7 @@ export const makeHasOneMethod = (
|
|
|
133
199
|
const values = { [foreignKey]: params[primaryKey] };
|
|
134
200
|
return query.where(values)._defaults(values);
|
|
135
201
|
},
|
|
136
|
-
|
|
137
|
-
const connect = data.filter(
|
|
138
|
-
(
|
|
139
|
-
item,
|
|
140
|
-
): item is [
|
|
141
|
-
Record<string, unknown>,
|
|
142
|
-
(
|
|
143
|
-
| {
|
|
144
|
-
connect: WhereArg<QueryBase>;
|
|
145
|
-
}
|
|
146
|
-
| {
|
|
147
|
-
connectOrCreate: {
|
|
148
|
-
where: WhereArg<QueryBase>;
|
|
149
|
-
create: Record<string, unknown>;
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
),
|
|
153
|
-
] => Boolean(item[1].connect || item[1].connectOrCreate),
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
const t = query.transacting(q);
|
|
157
|
-
|
|
158
|
-
let connected: number[];
|
|
159
|
-
if (connect.length) {
|
|
160
|
-
connected = await Promise.all(
|
|
161
|
-
connect.map(([selfData, item]) => {
|
|
162
|
-
const data = { [foreignKey]: selfData[primaryKey] };
|
|
163
|
-
return 'connect' in item
|
|
164
|
-
? (
|
|
165
|
-
t.where(item.connect) as WhereResult<Query> & {
|
|
166
|
-
hasSelect: false;
|
|
167
|
-
}
|
|
168
|
-
)._updateOrThrow(data)
|
|
169
|
-
: (
|
|
170
|
-
t.where(item.connectOrCreate.where) as WhereResult<Query> & {
|
|
171
|
-
hasSelect: false;
|
|
172
|
-
}
|
|
173
|
-
)._update(data);
|
|
174
|
-
}),
|
|
175
|
-
);
|
|
176
|
-
} else {
|
|
177
|
-
connected = [];
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
let connectedI = 0;
|
|
181
|
-
const create = data.filter(
|
|
182
|
-
(
|
|
183
|
-
item,
|
|
184
|
-
): item is [
|
|
185
|
-
Record<string, unknown>,
|
|
186
|
-
(
|
|
187
|
-
| { create: Record<string, unknown> }
|
|
188
|
-
| {
|
|
189
|
-
connectOrCreate: {
|
|
190
|
-
where: WhereArg<QueryBase>;
|
|
191
|
-
create: Record<string, unknown>;
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
),
|
|
195
|
-
] => {
|
|
196
|
-
if (item[1].connectOrCreate) {
|
|
197
|
-
return !connected[connectedI++];
|
|
198
|
-
}
|
|
199
|
-
return Boolean(item[1].create);
|
|
200
|
-
},
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
if (create.length) {
|
|
204
|
-
await t._count()._createMany(
|
|
205
|
-
create.map(([selfData, item]) => ({
|
|
206
|
-
[foreignKey]: selfData[primaryKey],
|
|
207
|
-
...('create' in item ? item.create : item.connectOrCreate.create),
|
|
208
|
-
})),
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
}) as HasOneNestedInsert,
|
|
212
|
-
nestedUpdate: (async (q, data, params) => {
|
|
213
|
-
if (
|
|
214
|
-
(params.set || params.create || params.upsert) &&
|
|
215
|
-
isQueryReturnsAll(q)
|
|
216
|
-
) {
|
|
217
|
-
const key = params.set ? 'set' : params.create ? 'create' : 'upsert';
|
|
218
|
-
throw new Error(`\`${key}\` option is not allowed in a batch update`);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const t = query.transacting(q);
|
|
222
|
-
const ids = data.map((item) => item[primaryKey]);
|
|
223
|
-
const currentRelationsQuery = t.where({
|
|
224
|
-
[foreignKey]: { in: ids },
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
if (params.create || params.disconnect || params.set) {
|
|
228
|
-
await currentRelationsQuery._update({ [foreignKey]: null });
|
|
229
|
-
|
|
230
|
-
if (params.create) {
|
|
231
|
-
await t._count()._create({
|
|
232
|
-
...params.create,
|
|
233
|
-
[foreignKey]: data[0][primaryKey],
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
if (params.set) {
|
|
237
|
-
await t
|
|
238
|
-
._where<Query>(params.set)
|
|
239
|
-
._update({ [foreignKey]: data[0][primaryKey] });
|
|
240
|
-
}
|
|
241
|
-
} else if (params.update) {
|
|
242
|
-
await currentRelationsQuery._update<WhereResult<Query>>(params.update);
|
|
243
|
-
} else if (params.delete) {
|
|
244
|
-
await currentRelationsQuery._delete();
|
|
245
|
-
} else if (params.upsert) {
|
|
246
|
-
const { update, create } = params.upsert;
|
|
247
|
-
const updatedIds: unknown[] = await currentRelationsQuery
|
|
248
|
-
._pluck(foreignKey)
|
|
249
|
-
._update<WhereResult<Query & { hasSelect: true }>>(update);
|
|
250
|
-
|
|
251
|
-
if (updatedIds.length < ids.length) {
|
|
252
|
-
await t.createMany(
|
|
253
|
-
ids
|
|
254
|
-
.filter((id) => !updatedIds.includes(id))
|
|
255
|
-
.map((id) => ({
|
|
256
|
-
...create,
|
|
257
|
-
[foreignKey]: id,
|
|
258
|
-
})),
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}) as HasOneNestedUpdate,
|
|
202
|
+
virtualColumn: new HasOneVirtualColumn(relationName, state),
|
|
263
203
|
joinQuery(fromQuery, toQuery) {
|
|
264
204
|
return addQueryOn(toQuery, fromQuery, toQuery, foreignKey, primaryKey);
|
|
265
205
|
},
|
|
@@ -276,3 +216,136 @@ export const makeHasOneMethod = (
|
|
|
276
216
|
},
|
|
277
217
|
};
|
|
278
218
|
};
|
|
219
|
+
|
|
220
|
+
const nestedInsert = ({ query, primaryKey, foreignKey }: State) => {
|
|
221
|
+
return (async (q, data) => {
|
|
222
|
+
const connect = data.filter(
|
|
223
|
+
(
|
|
224
|
+
item,
|
|
225
|
+
): item is [
|
|
226
|
+
Record<string, unknown>,
|
|
227
|
+
(
|
|
228
|
+
| {
|
|
229
|
+
connect: WhereArg<QueryBase>;
|
|
230
|
+
}
|
|
231
|
+
| {
|
|
232
|
+
connectOrCreate: {
|
|
233
|
+
where: WhereArg<QueryBase>;
|
|
234
|
+
create: Record<string, unknown>;
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
),
|
|
238
|
+
] => Boolean(item[1].connect || item[1].connectOrCreate),
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const t = query.transacting(q);
|
|
242
|
+
|
|
243
|
+
let connected: number[];
|
|
244
|
+
if (connect.length) {
|
|
245
|
+
connected = await Promise.all(
|
|
246
|
+
connect.map(([selfData, item]) => {
|
|
247
|
+
const data = { [foreignKey]: selfData[primaryKey] };
|
|
248
|
+
return 'connect' in item
|
|
249
|
+
? (
|
|
250
|
+
t.where(item.connect) as WhereResult<Query> & {
|
|
251
|
+
hasSelect: false;
|
|
252
|
+
}
|
|
253
|
+
)._updateOrThrow(data)
|
|
254
|
+
: (
|
|
255
|
+
t.where(item.connectOrCreate.where) as WhereResult<Query> & {
|
|
256
|
+
hasSelect: false;
|
|
257
|
+
}
|
|
258
|
+
)._update(data);
|
|
259
|
+
}),
|
|
260
|
+
);
|
|
261
|
+
} else {
|
|
262
|
+
connected = [];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
let connectedI = 0;
|
|
266
|
+
const create = data.filter(
|
|
267
|
+
(
|
|
268
|
+
item,
|
|
269
|
+
): item is [
|
|
270
|
+
Record<string, unknown>,
|
|
271
|
+
(
|
|
272
|
+
| { create: Record<string, unknown> }
|
|
273
|
+
| {
|
|
274
|
+
connectOrCreate: {
|
|
275
|
+
where: WhereArg<QueryBase>;
|
|
276
|
+
create: Record<string, unknown>;
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
),
|
|
280
|
+
] => {
|
|
281
|
+
if (item[1].connectOrCreate) {
|
|
282
|
+
return !connected[connectedI++];
|
|
283
|
+
}
|
|
284
|
+
return Boolean(item[1].create);
|
|
285
|
+
},
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
if (create.length) {
|
|
289
|
+
await t._count()._createMany(
|
|
290
|
+
create.map(([selfData, item]) => ({
|
|
291
|
+
[foreignKey]: selfData[primaryKey],
|
|
292
|
+
...('create' in item ? item.create : item.connectOrCreate.create),
|
|
293
|
+
})),
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
}) as HasOneNestedInsert;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const nestedUpdate = ({ query, primaryKey, foreignKey }: State) => {
|
|
300
|
+
return (async (q, data, params) => {
|
|
301
|
+
if (
|
|
302
|
+
(params.set || params.create || params.upsert) &&
|
|
303
|
+
isQueryReturnsAll(q)
|
|
304
|
+
) {
|
|
305
|
+
const key = params.set ? 'set' : params.create ? 'create' : 'upsert';
|
|
306
|
+
throw new Error(`\`${key}\` option is not allowed in a batch update`);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const t = query.transacting(q);
|
|
310
|
+
const ids = data.map((item) => item[primaryKey]);
|
|
311
|
+
const currentRelationsQuery = t.where({
|
|
312
|
+
[foreignKey]: { in: ids },
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
if (params.create || params.disconnect || params.set) {
|
|
316
|
+
await currentRelationsQuery._update({ [foreignKey]: null });
|
|
317
|
+
|
|
318
|
+
if (params.create) {
|
|
319
|
+
await t._count()._create({
|
|
320
|
+
...params.create,
|
|
321
|
+
[foreignKey]: data[0][primaryKey],
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
if (params.set) {
|
|
325
|
+
await t
|
|
326
|
+
._where<Query>(params.set)
|
|
327
|
+
._update({ [foreignKey]: data[0][primaryKey] });
|
|
328
|
+
}
|
|
329
|
+
} else if (params.update) {
|
|
330
|
+
await currentRelationsQuery._update<WhereResult<Query>>(params.update);
|
|
331
|
+
} else if (params.delete) {
|
|
332
|
+
await currentRelationsQuery._delete();
|
|
333
|
+
} else if (params.upsert) {
|
|
334
|
+
const { update, create } = params.upsert;
|
|
335
|
+
const updatedIds: unknown[] = await currentRelationsQuery
|
|
336
|
+
._pluck(foreignKey)
|
|
337
|
+
._update<WhereResult<Query & { hasSelect: true }>>(update);
|
|
338
|
+
|
|
339
|
+
if (updatedIds.length < ids.length) {
|
|
340
|
+
await t.createMany(
|
|
341
|
+
ids
|
|
342
|
+
.filter((id) => !updatedIds.includes(id))
|
|
343
|
+
.map((id) => ({
|
|
344
|
+
...create,
|
|
345
|
+
[foreignKey]: id,
|
|
346
|
+
})),
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}) as HasOneNestedUpdate;
|
|
351
|
+
};
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
defaultsKey,
|
|
14
14
|
relationQueryKey,
|
|
15
15
|
EmptyObject,
|
|
16
|
+
VirtualColumn,
|
|
16
17
|
} from 'pqb';
|
|
17
18
|
import { HasMany, HasManyInfo, makeHasManyMethod } from './hasMany';
|
|
18
19
|
import {
|
|
@@ -36,8 +37,7 @@ export type RelationThunks = Record<string, RelationThunk>;
|
|
|
36
37
|
export type RelationData = {
|
|
37
38
|
returns: 'one' | 'many';
|
|
38
39
|
method(params: Record<string, unknown>): Query;
|
|
39
|
-
|
|
40
|
-
nestedUpdate: BaseRelation['nestedUpdate'];
|
|
40
|
+
virtualColumn?: VirtualColumn;
|
|
41
41
|
joinQuery(fromQuery: Query, toQuery: Query): Query;
|
|
42
42
|
reverseJoin(fromQuery: Query, toQuery: Query): Query;
|
|
43
43
|
primaryKey: string;
|
|
@@ -63,8 +63,6 @@ export type Relation<
|
|
|
63
63
|
: M & {
|
|
64
64
|
[defaultsKey]: Record<Info['populate'], true>;
|
|
65
65
|
};
|
|
66
|
-
nestedInsert: BaseRelation['nestedInsert'];
|
|
67
|
-
nestedUpdate: BaseRelation['nestedUpdate'];
|
|
68
66
|
primaryKey: string;
|
|
69
67
|
options: Relations[K]['options'];
|
|
70
68
|
};
|
|
@@ -280,13 +278,19 @@ const applyRelation = (
|
|
|
280
278
|
const { type } = relation;
|
|
281
279
|
let data;
|
|
282
280
|
if (type === 'belongsTo') {
|
|
283
|
-
data = makeBelongsToMethod(relation, query);
|
|
281
|
+
data = makeBelongsToMethod(relation, relationName, query);
|
|
284
282
|
} else if (type === 'hasOne') {
|
|
285
283
|
data = makeHasOneMethod(dbModel, relation, relationName, query);
|
|
286
284
|
} else if (type === 'hasMany') {
|
|
287
285
|
data = makeHasManyMethod(dbModel, relation, relationName, query);
|
|
288
286
|
} else if (type === 'hasAndBelongsToMany') {
|
|
289
|
-
data = makeHasAndBelongsToManyMethod(
|
|
287
|
+
data = makeHasAndBelongsToManyMethod(
|
|
288
|
+
dbModel,
|
|
289
|
+
qb,
|
|
290
|
+
relation,
|
|
291
|
+
relationName,
|
|
292
|
+
query,
|
|
293
|
+
);
|
|
290
294
|
} else {
|
|
291
295
|
throw new Error(`Unknown relation type ${type}`);
|
|
292
296
|
}
|
|
@@ -295,6 +299,10 @@ const applyRelation = (
|
|
|
295
299
|
query._take();
|
|
296
300
|
}
|
|
297
301
|
|
|
302
|
+
if (data.virtualColumn) {
|
|
303
|
+
dbModel.shape[relationName] = data.virtualColumn;
|
|
304
|
+
}
|
|
305
|
+
|
|
298
306
|
makeRelationQuery(dbModel, definedAs, relationName, data);
|
|
299
307
|
|
|
300
308
|
(dbModel.relations as Record<string, unknown>)[relationName] = {
|
|
@@ -302,8 +310,6 @@ const applyRelation = (
|
|
|
302
310
|
key: relationName,
|
|
303
311
|
model: otherDbModel,
|
|
304
312
|
query,
|
|
305
|
-
nestedInsert: data.nestedInsert,
|
|
306
|
-
nestedUpdate: data.nestedUpdate,
|
|
307
313
|
joinQuery: data.joinQuery,
|
|
308
314
|
primaryKey: data.primaryKey,
|
|
309
315
|
options: relation.options,
|
package/src/relations/utils.ts
CHANGED
|
@@ -1,4 +1,61 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
CreateCtx,
|
|
3
|
+
MaybeArray,
|
|
4
|
+
pushQueryValue,
|
|
5
|
+
Query,
|
|
6
|
+
QueryBase,
|
|
7
|
+
Relation,
|
|
8
|
+
UpdateCtx,
|
|
9
|
+
UpdateData,
|
|
10
|
+
WhereArg,
|
|
11
|
+
} from 'pqb';
|
|
12
|
+
import { HasOneNestedInsert, HasOneNestedUpdate } from './hasOne';
|
|
13
|
+
import { HasManyNestedInsert, HasManyNestedUpdate } from './hasMany';
|
|
14
|
+
|
|
15
|
+
export type NestedInsertOneItem = {
|
|
16
|
+
create?: Record<string, unknown>;
|
|
17
|
+
connect?: WhereArg<QueryBase>;
|
|
18
|
+
connectOrCreate?: {
|
|
19
|
+
where: WhereArg<QueryBase>;
|
|
20
|
+
create: Record<string, unknown>;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type NestedInsertManyItems = {
|
|
25
|
+
create?: Record<string, unknown>[];
|
|
26
|
+
connect?: WhereArg<QueryBase>[];
|
|
27
|
+
connectOrCreate?: {
|
|
28
|
+
where: WhereArg<QueryBase>;
|
|
29
|
+
create: Record<string, unknown>;
|
|
30
|
+
}[];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type NestedInsertItem = NestedInsertOneItem | NestedInsertManyItems;
|
|
34
|
+
|
|
35
|
+
export type NestedUpdateOneItem = {
|
|
36
|
+
disconnect?: boolean;
|
|
37
|
+
set?: WhereArg<QueryBase>;
|
|
38
|
+
delete?: boolean;
|
|
39
|
+
update?: UpdateData<Query>;
|
|
40
|
+
upsert?: {
|
|
41
|
+
update: UpdateData<Query>;
|
|
42
|
+
create: Record<string, unknown>;
|
|
43
|
+
};
|
|
44
|
+
create: Record<string, unknown>;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type NestedUpdateManyItems = {
|
|
48
|
+
disconnect?: MaybeArray<WhereArg<QueryBase>>;
|
|
49
|
+
set?: MaybeArray<WhereArg<QueryBase>>;
|
|
50
|
+
delete?: MaybeArray<WhereArg<QueryBase>>;
|
|
51
|
+
update?: {
|
|
52
|
+
where: MaybeArray<WhereArg<QueryBase>>;
|
|
53
|
+
data: UpdateData<Query>;
|
|
54
|
+
};
|
|
55
|
+
create: Record<string, unknown>[];
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export type NestedUpdateItem = NestedUpdateOneItem | NestedUpdateManyItems;
|
|
2
59
|
|
|
3
60
|
export const getThroughRelation = (model: Query, through: string) => {
|
|
4
61
|
return (model.relations as Record<string, Relation>)[through];
|
|
@@ -10,3 +67,96 @@ export const getSourceRelation = (
|
|
|
10
67
|
) => {
|
|
11
68
|
return (throughRelation.model.relations as Record<string, Relation>)[source];
|
|
12
69
|
};
|
|
70
|
+
|
|
71
|
+
export const hasRelationHandleCreate = (
|
|
72
|
+
q: Query,
|
|
73
|
+
ctx: CreateCtx,
|
|
74
|
+
item: Record<string, unknown>,
|
|
75
|
+
rowIndex: number,
|
|
76
|
+
key: string,
|
|
77
|
+
primaryKey: string,
|
|
78
|
+
nestedInsert: HasOneNestedInsert | HasManyNestedInsert,
|
|
79
|
+
) => {
|
|
80
|
+
const value = item[key] as NestedInsertItem;
|
|
81
|
+
if (
|
|
82
|
+
(!value.create ||
|
|
83
|
+
(Array.isArray(value.create) && value.create.length === 0)) &&
|
|
84
|
+
(!value.connect ||
|
|
85
|
+
(Array.isArray(value.connect) && value.connect.length === 0)) &&
|
|
86
|
+
(!value.connectOrCreate ||
|
|
87
|
+
(Array.isArray(value.connectOrCreate) &&
|
|
88
|
+
value.connectOrCreate.length === 0))
|
|
89
|
+
)
|
|
90
|
+
return;
|
|
91
|
+
|
|
92
|
+
const store = ctx as unknown as {
|
|
93
|
+
hasRelation?: Record<string, [number, NestedInsertItem][]>;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
if (!store.hasRelation) store.hasRelation = {};
|
|
97
|
+
|
|
98
|
+
const values = [rowIndex, value] as [number, NestedInsertItem];
|
|
99
|
+
|
|
100
|
+
if (store.hasRelation[key]) {
|
|
101
|
+
store.hasRelation[key].push(values);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
q.query.wrapInTransaction = true;
|
|
106
|
+
ctx.returnTypeAll = true;
|
|
107
|
+
ctx.requiredReturning[primaryKey] = true;
|
|
108
|
+
|
|
109
|
+
const relationData = [values];
|
|
110
|
+
store.hasRelation[key] = relationData;
|
|
111
|
+
|
|
112
|
+
pushQueryValue(q, 'afterCreate', async (q: Query) => {
|
|
113
|
+
const { resultAll } = ctx;
|
|
114
|
+
return (nestedInsert as HasOneNestedInsert)(
|
|
115
|
+
q,
|
|
116
|
+
relationData.map(([rowIndex, data]) => [
|
|
117
|
+
resultAll[rowIndex],
|
|
118
|
+
data as NestedInsertOneItem,
|
|
119
|
+
]),
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export const hasRelationHandleUpdate = (
|
|
125
|
+
q: Query,
|
|
126
|
+
ctx: UpdateCtx,
|
|
127
|
+
set: Record<string, unknown>,
|
|
128
|
+
key: string,
|
|
129
|
+
primaryKey: string,
|
|
130
|
+
nestedUpdate: HasOneNestedUpdate | HasManyNestedUpdate,
|
|
131
|
+
) => {
|
|
132
|
+
const value = set[key] as NestedUpdateItem;
|
|
133
|
+
|
|
134
|
+
if (
|
|
135
|
+
!value.set &&
|
|
136
|
+
!('upsert' in value) &&
|
|
137
|
+
(!value.disconnect ||
|
|
138
|
+
(Array.isArray(value.disconnect) && value.disconnect.length === 0)) &&
|
|
139
|
+
(!value.delete ||
|
|
140
|
+
(Array.isArray(value.delete) && value.delete.length === 0)) &&
|
|
141
|
+
(!value.update ||
|
|
142
|
+
(Array.isArray(value.update.where) && value.update.where.length === 0)) &&
|
|
143
|
+
(!value.create ||
|
|
144
|
+
(Array.isArray(value.create) && value.create.length === 0))
|
|
145
|
+
)
|
|
146
|
+
return;
|
|
147
|
+
|
|
148
|
+
if (!q.query.select?.includes('*') && !q.query.select?.includes(primaryKey)) {
|
|
149
|
+
q._select(primaryKey);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
q.query.wrapInTransaction = true;
|
|
153
|
+
ctx.returnTypeAll = true;
|
|
154
|
+
|
|
155
|
+
pushQueryValue(q, 'afterUpdate', (q: Query) => {
|
|
156
|
+
return (nestedUpdate as HasOneNestedUpdate)(
|
|
157
|
+
q,
|
|
158
|
+
ctx.resultAll,
|
|
159
|
+
value as NestedUpdateOneItem,
|
|
160
|
+
);
|
|
161
|
+
});
|
|
162
|
+
};
|