wabe 0.6.9 → 0.6.10
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/README.md +138 -32
- package/bucket/b.txt +1 -0
- package/dev/index.ts +215 -0
- package/dist/authentication/Session.d.ts +4 -1
- package/dist/authentication/interface.d.ts +16 -0
- package/dist/email/interface.d.ts +1 -1
- package/dist/graphql/resolvers.d.ts +4 -2
- package/dist/hooks/index.d.ts +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +8713 -8867
- package/dist/server/index.d.ts +4 -2
- package/dist/utils/crypto.d.ts +7 -0
- package/dist/utils/helper.d.ts +4 -1
- package/generated/schema.graphql +16 -14
- package/generated/wabe.ts +4 -4
- package/package.json +15 -15
- package/src/authentication/OTP.test.ts +69 -0
- package/src/authentication/OTP.ts +66 -0
- package/src/authentication/Session.test.ts +665 -0
- package/src/authentication/Session.ts +529 -0
- package/src/authentication/defaultAuthentication.ts +214 -0
- package/src/authentication/index.ts +3 -0
- package/src/authentication/interface.ts +157 -0
- package/src/authentication/oauth/GitHub.test.ts +105 -0
- package/src/authentication/oauth/GitHub.ts +133 -0
- package/src/authentication/oauth/Google.test.ts +105 -0
- package/src/authentication/oauth/Google.ts +110 -0
- package/src/authentication/oauth/Oauth2Client.test.ts +225 -0
- package/src/authentication/oauth/Oauth2Client.ts +140 -0
- package/src/authentication/oauth/index.ts +2 -0
- package/src/authentication/oauth/utils.test.ts +35 -0
- package/src/authentication/oauth/utils.ts +28 -0
- package/src/authentication/providers/EmailOTP.test.ts +138 -0
- package/src/authentication/providers/EmailOTP.ts +93 -0
- package/src/authentication/providers/EmailPassword.test.ts +187 -0
- package/src/authentication/providers/EmailPassword.ts +130 -0
- package/src/authentication/providers/EmailPasswordSRP.test.ts +206 -0
- package/src/authentication/providers/EmailPasswordSRP.ts +184 -0
- package/src/authentication/providers/GitHub.ts +30 -0
- package/src/authentication/providers/Google.ts +30 -0
- package/src/authentication/providers/OAuth.test.ts +185 -0
- package/src/authentication/providers/OAuth.ts +112 -0
- package/src/authentication/providers/PhonePassword.test.ts +187 -0
- package/src/authentication/providers/PhonePassword.ts +129 -0
- package/src/authentication/providers/QRCodeOTP.test.ts +79 -0
- package/src/authentication/providers/QRCodeOTP.ts +65 -0
- package/src/authentication/providers/index.ts +6 -0
- package/src/authentication/resolvers/refreshResolver.test.ts +37 -0
- package/src/authentication/resolvers/refreshResolver.ts +20 -0
- package/src/authentication/resolvers/signInWithResolver.inte.test.ts +59 -0
- package/src/authentication/resolvers/signInWithResolver.test.ts +307 -0
- package/src/authentication/resolvers/signInWithResolver.ts +102 -0
- package/src/authentication/resolvers/signOutResolver.test.ts +41 -0
- package/src/authentication/resolvers/signOutResolver.ts +22 -0
- package/src/authentication/resolvers/signUpWithResolver.test.ts +186 -0
- package/src/authentication/resolvers/signUpWithResolver.ts +69 -0
- package/src/authentication/resolvers/verifyChallenge.test.ts +136 -0
- package/src/authentication/resolvers/verifyChallenge.ts +69 -0
- package/src/authentication/roles.test.ts +59 -0
- package/src/authentication/roles.ts +40 -0
- package/src/authentication/utils.test.ts +99 -0
- package/src/authentication/utils.ts +43 -0
- package/src/cache/InMemoryCache.test.ts +62 -0
- package/src/cache/InMemoryCache.ts +45 -0
- package/src/cron/index.test.ts +17 -0
- package/src/cron/index.ts +46 -0
- package/src/database/DatabaseController.test.ts +625 -0
- package/src/database/DatabaseController.ts +983 -0
- package/src/database/index.test.ts +1230 -0
- package/src/database/index.ts +9 -0
- package/src/database/interface.ts +312 -0
- package/src/email/DevAdapter.ts +8 -0
- package/src/email/EmailController.test.ts +29 -0
- package/src/email/EmailController.ts +13 -0
- package/src/email/index.ts +2 -0
- package/src/email/interface.ts +36 -0
- package/src/email/templates/sendOtpCode.ts +120 -0
- package/src/file/FileController.ts +28 -0
- package/src/file/FileDevAdapter.ts +54 -0
- package/src/file/hookDeleteFile.ts +27 -0
- package/src/file/hookReadFile.ts +70 -0
- package/src/file/hookUploadFile.ts +53 -0
- package/src/file/index.test.ts +979 -0
- package/src/file/index.ts +2 -0
- package/src/file/interface.ts +42 -0
- package/src/graphql/GraphQLSchema.test.ts +4399 -0
- package/src/graphql/GraphQLSchema.ts +928 -0
- package/src/graphql/index.ts +2 -0
- package/src/graphql/parseGraphqlSchema.ts +94 -0
- package/src/graphql/parser.test.ts +217 -0
- package/src/graphql/parser.ts +566 -0
- package/src/graphql/pointerAndRelationFunction.ts +200 -0
- package/src/graphql/resolvers.ts +467 -0
- package/src/graphql/tests/aggregation.test.ts +1123 -0
- package/src/graphql/tests/e2e.test.ts +596 -0
- package/src/graphql/tests/scalars.test.ts +250 -0
- package/src/graphql/types.ts +219 -0
- package/src/hooks/HookObject.test.ts +122 -0
- package/src/hooks/HookObject.ts +168 -0
- package/src/hooks/authentication.ts +76 -0
- package/src/hooks/createUser.test.ts +77 -0
- package/src/hooks/createUser.ts +10 -0
- package/src/hooks/defaultFields.test.ts +187 -0
- package/src/hooks/defaultFields.ts +40 -0
- package/src/hooks/deleteSession.test.ts +181 -0
- package/src/hooks/deleteSession.ts +20 -0
- package/src/hooks/hashFieldHook.test.ts +163 -0
- package/src/hooks/hashFieldHook.ts +97 -0
- package/src/hooks/index.test.ts +207 -0
- package/src/hooks/index.ts +430 -0
- package/src/hooks/permissions.test.ts +424 -0
- package/src/hooks/permissions.ts +113 -0
- package/src/hooks/protected.test.ts +551 -0
- package/src/hooks/protected.ts +72 -0
- package/src/hooks/searchableFields.test.ts +166 -0
- package/src/hooks/searchableFields.ts +98 -0
- package/src/hooks/session.test.ts +138 -0
- package/src/hooks/session.ts +78 -0
- package/src/hooks/setEmail.test.ts +216 -0
- package/src/hooks/setEmail.ts +35 -0
- package/src/hooks/setupAcl.test.ts +589 -0
- package/src/hooks/setupAcl.ts +29 -0
- package/src/index.ts +9 -0
- package/src/schema/Schema.test.ts +484 -0
- package/src/schema/Schema.ts +795 -0
- package/src/schema/defaultResolvers.ts +94 -0
- package/src/schema/index.ts +1 -0
- package/src/schema/resolvers/meResolver.test.ts +62 -0
- package/src/schema/resolvers/meResolver.ts +14 -0
- package/src/schema/resolvers/newFile.ts +0 -0
- package/src/schema/resolvers/resetPassword.test.ts +345 -0
- package/src/schema/resolvers/resetPassword.ts +64 -0
- package/src/schema/resolvers/sendEmail.test.ts +118 -0
- package/src/schema/resolvers/sendEmail.ts +21 -0
- package/src/schema/resolvers/sendOtpCode.test.ts +153 -0
- package/src/schema/resolvers/sendOtpCode.ts +52 -0
- package/src/security.test.ts +3461 -0
- package/src/server/defaultSessionHandler.test.ts +66 -0
- package/src/server/defaultSessionHandler.ts +115 -0
- package/src/server/generateCodegen.ts +476 -0
- package/src/server/index.test.ts +552 -0
- package/src/server/index.ts +354 -0
- package/src/server/interface.ts +11 -0
- package/src/server/routes/authHandler.ts +187 -0
- package/src/server/routes/index.ts +40 -0
- package/src/utils/crypto.test.ts +41 -0
- package/src/utils/crypto.ts +121 -0
- package/src/utils/export.ts +13 -0
- package/src/utils/helper.ts +195 -0
- package/src/utils/index.test.ts +11 -0
- package/src/utils/index.ts +201 -0
- package/src/utils/preload.ts +8 -0
- package/src/utils/testHelper.ts +117 -0
- package/tsconfig.json +32 -0
- package/bunfig.toml +0 -4
- package/dist/ai/index.d.ts +0 -1
- package/dist/ai/interface.d.ts +0 -9
- /package/dist/server/{defaultHandlers.d.ts → defaultSessionHandler.d.ts} +0 -0
|
@@ -0,0 +1,983 @@
|
|
|
1
|
+
import type { WabeTypes } from '../..'
|
|
2
|
+
import { OperationType, initializeHook } from '../hooks'
|
|
3
|
+
import type { SchemaInterface } from '../schema'
|
|
4
|
+
import type { WabeContext } from '../server/interface'
|
|
5
|
+
import { contextWithRoot } from '../utils/export'
|
|
6
|
+
import { notEmpty } from '../utils/export'
|
|
7
|
+
import type {
|
|
8
|
+
CountOptions,
|
|
9
|
+
CreateObjectOptions,
|
|
10
|
+
CreateObjectsOptions,
|
|
11
|
+
DatabaseAdapter,
|
|
12
|
+
DeleteObjectOptions,
|
|
13
|
+
DeleteObjectsOptions,
|
|
14
|
+
GetObjectOptions,
|
|
15
|
+
GetObjectsOptions,
|
|
16
|
+
OutputType,
|
|
17
|
+
UpdateObjectOptions,
|
|
18
|
+
UpdateObjectsOptions,
|
|
19
|
+
WhereType,
|
|
20
|
+
} from './interface'
|
|
21
|
+
|
|
22
|
+
export type Select = Record<string, boolean>
|
|
23
|
+
type SelectWithObject = Record<string, object | boolean>
|
|
24
|
+
|
|
25
|
+
export class DatabaseController<T extends WabeTypes> {
|
|
26
|
+
public adapter: DatabaseAdapter<T>
|
|
27
|
+
|
|
28
|
+
constructor(adapter: DatabaseAdapter<T>) {
|
|
29
|
+
this.adapter = adapter
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
_getSelectMinusPointersAndRelations({
|
|
33
|
+
className,
|
|
34
|
+
context,
|
|
35
|
+
select,
|
|
36
|
+
}: {
|
|
37
|
+
className: keyof T['types']
|
|
38
|
+
context: WabeContext<T>
|
|
39
|
+
select?: SelectWithObject
|
|
40
|
+
}): {
|
|
41
|
+
// We associated the fieldName with a className and a select object
|
|
42
|
+
pointers: Record<string, { className: string; select: Select }>
|
|
43
|
+
selectWithoutPointers: Select
|
|
44
|
+
} {
|
|
45
|
+
const realClass = context.wabe.config.schema?.classes?.find(
|
|
46
|
+
// @ts-expect-error
|
|
47
|
+
(c) => c.name.toLowerCase() === className.toLowerCase(),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if (!realClass) throw new Error('Class not found in schema')
|
|
51
|
+
|
|
52
|
+
if (!select) return { pointers: {}, selectWithoutPointers: {} }
|
|
53
|
+
|
|
54
|
+
const pointerOrRelationFields = Object.keys(realClass.fields).filter(
|
|
55
|
+
(fieldName) =>
|
|
56
|
+
realClass.fields[fieldName]?.type === 'Pointer' ||
|
|
57
|
+
realClass.fields[fieldName]?.type === 'Relation',
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
return Object.entries(select).reduce(
|
|
61
|
+
(acc, [fieldName, value]) => {
|
|
62
|
+
// If not pointer or relation
|
|
63
|
+
if (!pointerOrRelationFields.includes(fieldName))
|
|
64
|
+
return {
|
|
65
|
+
...acc,
|
|
66
|
+
selectWithoutPointers: {
|
|
67
|
+
...acc.selectWithoutPointers,
|
|
68
|
+
[fieldName]: true,
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// @ts-expect-error
|
|
73
|
+
const classOfPointerOrRelation = realClass.fields[fieldName].class
|
|
74
|
+
|
|
75
|
+
// Pointer or relation
|
|
76
|
+
return {
|
|
77
|
+
...acc,
|
|
78
|
+
pointers: {
|
|
79
|
+
...acc.pointers,
|
|
80
|
+
[fieldName]: {
|
|
81
|
+
className: classOfPointerOrRelation,
|
|
82
|
+
// If we set value to true we want all the fields of the pointer if we
|
|
83
|
+
// set an object we just want some fields
|
|
84
|
+
select: value === true ? undefined : value,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{ pointers: {}, selectWithoutPointers: {} },
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
_isRelationField({
|
|
94
|
+
pointerField,
|
|
95
|
+
currentClassName,
|
|
96
|
+
context,
|
|
97
|
+
originClassName,
|
|
98
|
+
}: {
|
|
99
|
+
pointerField: string
|
|
100
|
+
originClassName: string
|
|
101
|
+
context: WabeContext<T>
|
|
102
|
+
currentClassName?: string
|
|
103
|
+
}) {
|
|
104
|
+
if (!currentClassName) return false
|
|
105
|
+
|
|
106
|
+
return context.wabe.config.schema?.classes?.some(
|
|
107
|
+
(c) =>
|
|
108
|
+
c.name.toLowerCase() === originClassName.toLowerCase() &&
|
|
109
|
+
Object.entries(c.fields).find(
|
|
110
|
+
([fieldName, field]) =>
|
|
111
|
+
fieldName === pointerField &&
|
|
112
|
+
field.type === 'Relation' &&
|
|
113
|
+
// @ts-expect-error
|
|
114
|
+
field.class.toLowerCase() === currentClassName.toLowerCase(),
|
|
115
|
+
),
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
_isPointerField({
|
|
120
|
+
pointerField,
|
|
121
|
+
currentClassName,
|
|
122
|
+
context,
|
|
123
|
+
originClassName,
|
|
124
|
+
}: {
|
|
125
|
+
originClassName: string
|
|
126
|
+
context: WabeContext<T>
|
|
127
|
+
pointerField: string
|
|
128
|
+
currentClassName?: string
|
|
129
|
+
}) {
|
|
130
|
+
if (!currentClassName) return false
|
|
131
|
+
|
|
132
|
+
return context.wabe.config.schema?.classes?.some(
|
|
133
|
+
(c) =>
|
|
134
|
+
c.name.toLowerCase() === originClassName.toLowerCase() &&
|
|
135
|
+
Object.entries(c.fields).find(
|
|
136
|
+
([fieldName, field]) =>
|
|
137
|
+
fieldName === pointerField &&
|
|
138
|
+
field.type === 'Pointer' &&
|
|
139
|
+
// @ts-expect-error
|
|
140
|
+
field.class.toLowerCase() === currentClassName.toLowerCase(),
|
|
141
|
+
),
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async _getWhereObjectWithPointerOrRelation<U extends keyof T['types']>(
|
|
146
|
+
className: U,
|
|
147
|
+
where: WhereType<T, U>,
|
|
148
|
+
context: WabeContext<T>,
|
|
149
|
+
) {
|
|
150
|
+
const whereKeys = Object.keys(where) as Array<keyof WhereType<T, U>>
|
|
151
|
+
|
|
152
|
+
const realClass = context.wabe.config.schema?.classes?.find(
|
|
153
|
+
// @ts-expect-error
|
|
154
|
+
(c) => c.name.toLowerCase() === className.toLowerCase(),
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
const newWhereObject = await whereKeys.reduce(async (acc, whereKey) => {
|
|
158
|
+
const currentAcc = await acc
|
|
159
|
+
|
|
160
|
+
const typedWhereKey = whereKey as string
|
|
161
|
+
|
|
162
|
+
const field = realClass?.fields[typedWhereKey]
|
|
163
|
+
|
|
164
|
+
if (typedWhereKey === 'AND' || typedWhereKey === 'OR') {
|
|
165
|
+
const newWhere = await Promise.all(
|
|
166
|
+
(where[typedWhereKey] as any).map((whereObject: any) =>
|
|
167
|
+
this._getWhereObjectWithPointerOrRelation(
|
|
168
|
+
className,
|
|
169
|
+
whereObject,
|
|
170
|
+
context,
|
|
171
|
+
),
|
|
172
|
+
),
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
...currentAcc,
|
|
177
|
+
[typedWhereKey]: newWhere,
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (field?.type !== 'Pointer' && field?.type !== 'Relation') return acc
|
|
182
|
+
|
|
183
|
+
// @ts-expect-error
|
|
184
|
+
const fieldTargetClass = field.class
|
|
185
|
+
|
|
186
|
+
const defaultWhere = where[typedWhereKey]
|
|
187
|
+
|
|
188
|
+
const objects = await this.getObjects({
|
|
189
|
+
className: fieldTargetClass,
|
|
190
|
+
// @ts-expect-error
|
|
191
|
+
select: { id: true },
|
|
192
|
+
// @ts-expect-error
|
|
193
|
+
where: defaultWhere,
|
|
194
|
+
context,
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
...acc,
|
|
199
|
+
// If we don't found any object we just execute the query with the default where
|
|
200
|
+
// Without any transformation for pointer or relation
|
|
201
|
+
[typedWhereKey]: {
|
|
202
|
+
in: objects.map((object) => object?.id).filter(notEmpty),
|
|
203
|
+
},
|
|
204
|
+
}
|
|
205
|
+
}, Promise.resolve({}))
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
...where,
|
|
209
|
+
...newWhereObject,
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
_buildWhereWithACL<K extends keyof T['types']>(
|
|
214
|
+
where: WhereType<T, K>,
|
|
215
|
+
context: WabeContext<T>,
|
|
216
|
+
operation: 'write' | 'read',
|
|
217
|
+
): WhereType<T, K> {
|
|
218
|
+
if (context.isRoot) return where
|
|
219
|
+
|
|
220
|
+
const roleId = context.user?.role?.id
|
|
221
|
+
const userId = context.user?.id
|
|
222
|
+
|
|
223
|
+
// If we have an user we good right we return
|
|
224
|
+
// If we don't have user we check role
|
|
225
|
+
// If the role is good we return
|
|
226
|
+
|
|
227
|
+
// @ts-expect-error
|
|
228
|
+
return {
|
|
229
|
+
AND: [
|
|
230
|
+
{ ...where },
|
|
231
|
+
// If the user is not connected we need to have a null acl
|
|
232
|
+
!userId
|
|
233
|
+
? {
|
|
234
|
+
acl: { equalTo: null },
|
|
235
|
+
}
|
|
236
|
+
: undefined,
|
|
237
|
+
// If we have user or role we need to check the acl
|
|
238
|
+
userId || roleId
|
|
239
|
+
? {
|
|
240
|
+
OR: [
|
|
241
|
+
{
|
|
242
|
+
acl: { equalTo: null },
|
|
243
|
+
},
|
|
244
|
+
userId
|
|
245
|
+
? {
|
|
246
|
+
acl: {
|
|
247
|
+
users: {
|
|
248
|
+
contains: {
|
|
249
|
+
userId,
|
|
250
|
+
[operation]: true,
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
}
|
|
255
|
+
: undefined,
|
|
256
|
+
roleId
|
|
257
|
+
? {
|
|
258
|
+
AND: [
|
|
259
|
+
{
|
|
260
|
+
acl: {
|
|
261
|
+
users: {
|
|
262
|
+
notContains: {
|
|
263
|
+
userId,
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
acl: {
|
|
270
|
+
roles: {
|
|
271
|
+
contains: {
|
|
272
|
+
roleId,
|
|
273
|
+
[operation]: true,
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
}
|
|
280
|
+
: undefined,
|
|
281
|
+
].filter(notEmpty),
|
|
282
|
+
}
|
|
283
|
+
: undefined,
|
|
284
|
+
].filter(notEmpty),
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
_getFinalObjectWithPointerAndRelation({
|
|
289
|
+
pointers,
|
|
290
|
+
context,
|
|
291
|
+
originClassName,
|
|
292
|
+
object,
|
|
293
|
+
_skipHooks,
|
|
294
|
+
}: {
|
|
295
|
+
originClassName: string
|
|
296
|
+
pointers: Record<string, { className: string; select: Select }>
|
|
297
|
+
context: WabeContext<any>
|
|
298
|
+
object: Record<string, any>
|
|
299
|
+
_skipHooks?: boolean
|
|
300
|
+
}) {
|
|
301
|
+
return Object.entries(pointers).reduce(
|
|
302
|
+
async (
|
|
303
|
+
acc,
|
|
304
|
+
[pointerField, { className: currentClassName, select: currentSelect }],
|
|
305
|
+
) => {
|
|
306
|
+
const accObject = await acc
|
|
307
|
+
|
|
308
|
+
const isPointer = this._isPointerField({
|
|
309
|
+
originClassName,
|
|
310
|
+
context,
|
|
311
|
+
currentClassName,
|
|
312
|
+
pointerField,
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
if (isPointer) {
|
|
316
|
+
if (!object[pointerField])
|
|
317
|
+
return {
|
|
318
|
+
...accObject,
|
|
319
|
+
[pointerField]: null,
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const objectOfPointerClass = await this.getObject({
|
|
323
|
+
className: currentClassName,
|
|
324
|
+
id: object[pointerField],
|
|
325
|
+
context,
|
|
326
|
+
// @ts-expect-error
|
|
327
|
+
select: currentSelect,
|
|
328
|
+
_skipHooks,
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
return {
|
|
332
|
+
...accObject,
|
|
333
|
+
[pointerField]: objectOfPointerClass,
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const isRelation = this._isRelationField({
|
|
338
|
+
originClassName,
|
|
339
|
+
context,
|
|
340
|
+
currentClassName,
|
|
341
|
+
pointerField,
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
if (isRelation && object[pointerField]) {
|
|
345
|
+
const selectWithoutTotalCount = Object.entries(
|
|
346
|
+
currentSelect || {},
|
|
347
|
+
).reduce(
|
|
348
|
+
(acc2, [key, value]) => {
|
|
349
|
+
if (key === 'totalCount') return acc2
|
|
350
|
+
|
|
351
|
+
return {
|
|
352
|
+
...acc2,
|
|
353
|
+
[key]: value,
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
{} as Record<string, any>,
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
const relationObjects = await this.getObjects({
|
|
360
|
+
className: currentClassName,
|
|
361
|
+
select: selectWithoutTotalCount,
|
|
362
|
+
// @ts-expect-error
|
|
363
|
+
where: { id: { in: object[pointerField] } },
|
|
364
|
+
context,
|
|
365
|
+
_skipHooks,
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
return {
|
|
369
|
+
...accObject,
|
|
370
|
+
[pointerField]: context.isGraphQLCall
|
|
371
|
+
? {
|
|
372
|
+
totalCount: relationObjects.length,
|
|
373
|
+
edges: relationObjects.map((object: any) => ({
|
|
374
|
+
node: object,
|
|
375
|
+
})),
|
|
376
|
+
}
|
|
377
|
+
: relationObjects,
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return accObject
|
|
382
|
+
},
|
|
383
|
+
Promise.resolve({} as Record<string, any>),
|
|
384
|
+
)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
async close() {
|
|
388
|
+
await this.adapter.close()
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
createClassIfNotExist(
|
|
392
|
+
className: string,
|
|
393
|
+
schema: SchemaInterface<T>,
|
|
394
|
+
): Promise<any> {
|
|
395
|
+
return this.adapter.createClassIfNotExist(className, schema)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
initializeDatabase(schema: SchemaInterface<T>): Promise<void> {
|
|
399
|
+
return this.adapter.initializeDatabase(schema)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
async count<K extends keyof T['types']>({
|
|
403
|
+
className,
|
|
404
|
+
context,
|
|
405
|
+
where,
|
|
406
|
+
}: CountOptions<T, K>): Promise<number> {
|
|
407
|
+
const whereWithACLCondition = this._buildWhereWithACL(
|
|
408
|
+
where || {},
|
|
409
|
+
context,
|
|
410
|
+
'read',
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
const hook = initializeHook({
|
|
414
|
+
className,
|
|
415
|
+
context,
|
|
416
|
+
select: {},
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
await hook?.runOnSingleObject({
|
|
420
|
+
operationType: OperationType.BeforeRead,
|
|
421
|
+
})
|
|
422
|
+
|
|
423
|
+
const count = await this.adapter.count({
|
|
424
|
+
className,
|
|
425
|
+
context,
|
|
426
|
+
where: whereWithACLCondition,
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
await hook?.runOnSingleObject({
|
|
430
|
+
operationType: OperationType.AfterRead,
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
return count
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
async clearDatabase(): Promise<void> {
|
|
437
|
+
await this.adapter.clearDatabase()
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
async getObject<K extends keyof T['types'], U extends keyof T['types'][K]>({
|
|
441
|
+
select,
|
|
442
|
+
className,
|
|
443
|
+
context,
|
|
444
|
+
_skipHooks,
|
|
445
|
+
id,
|
|
446
|
+
where,
|
|
447
|
+
}: GetObjectOptions<T, K, U>): Promise<OutputType<T, K, U>> {
|
|
448
|
+
const { pointers, selectWithoutPointers } =
|
|
449
|
+
this._getSelectMinusPointersAndRelations({
|
|
450
|
+
className,
|
|
451
|
+
context,
|
|
452
|
+
select: select as SelectWithObject,
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
const hook = !_skipHooks
|
|
456
|
+
? initializeHook({
|
|
457
|
+
className,
|
|
458
|
+
context,
|
|
459
|
+
select: selectWithoutPointers,
|
|
460
|
+
})
|
|
461
|
+
: undefined
|
|
462
|
+
|
|
463
|
+
await hook?.runOnSingleObject({
|
|
464
|
+
operationType: OperationType.BeforeRead,
|
|
465
|
+
id,
|
|
466
|
+
})
|
|
467
|
+
|
|
468
|
+
const whereWithACLCondition = this._buildWhereWithACL(
|
|
469
|
+
where || {},
|
|
470
|
+
context,
|
|
471
|
+
'read',
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
const selectWithPointersAndRelationsToGetId = Object.keys(pointers).reduce(
|
|
475
|
+
(acc, fieldName) => {
|
|
476
|
+
acc[fieldName] = true
|
|
477
|
+
|
|
478
|
+
return acc
|
|
479
|
+
},
|
|
480
|
+
selectWithoutPointers,
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
const objectToReturn = await this.adapter.getObject({
|
|
484
|
+
className,
|
|
485
|
+
id,
|
|
486
|
+
context: contextWithRoot(context),
|
|
487
|
+
// @ts-expect-error
|
|
488
|
+
select: !select ? undefined : selectWithPointersAndRelationsToGetId,
|
|
489
|
+
where: whereWithACLCondition,
|
|
490
|
+
})
|
|
491
|
+
|
|
492
|
+
const finalObject = {
|
|
493
|
+
...objectToReturn,
|
|
494
|
+
...(await this._getFinalObjectWithPointerAndRelation({
|
|
495
|
+
context,
|
|
496
|
+
// @ts-expect-error
|
|
497
|
+
originClassName: className,
|
|
498
|
+
pointers,
|
|
499
|
+
// @ts-expect-error
|
|
500
|
+
object: objectToReturn,
|
|
501
|
+
_skipHooks,
|
|
502
|
+
})),
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const afterReadResult = await hook?.runOnSingleObject({
|
|
506
|
+
operationType: OperationType.AfterRead,
|
|
507
|
+
id,
|
|
508
|
+
// @ts-expect-error
|
|
509
|
+
object: finalObject,
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
return afterReadResult?.object || finalObject
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
async getObjects<
|
|
516
|
+
K extends keyof T['types'],
|
|
517
|
+
U extends keyof T['types'][K],
|
|
518
|
+
W extends keyof T['types'][K],
|
|
519
|
+
>({
|
|
520
|
+
className,
|
|
521
|
+
select,
|
|
522
|
+
context,
|
|
523
|
+
where,
|
|
524
|
+
_skipHooks,
|
|
525
|
+
first,
|
|
526
|
+
offset,
|
|
527
|
+
order,
|
|
528
|
+
}: GetObjectsOptions<T, K, U, W>): Promise<OutputType<T, K, W>[]> {
|
|
529
|
+
const { pointers, selectWithoutPointers } =
|
|
530
|
+
this._getSelectMinusPointersAndRelations({
|
|
531
|
+
className,
|
|
532
|
+
context,
|
|
533
|
+
select: select as SelectWithObject,
|
|
534
|
+
})
|
|
535
|
+
|
|
536
|
+
const whereWithPointer = await this._getWhereObjectWithPointerOrRelation(
|
|
537
|
+
className,
|
|
538
|
+
where || {},
|
|
539
|
+
context,
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
const whereWithACLCondition = this._buildWhereWithACL(
|
|
543
|
+
whereWithPointer || {},
|
|
544
|
+
context,
|
|
545
|
+
'read',
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
const selectWithPointersAndRelationsToGetId = Object.keys(pointers).reduce(
|
|
549
|
+
(acc, fieldName) => {
|
|
550
|
+
acc[fieldName] = true
|
|
551
|
+
|
|
552
|
+
return acc
|
|
553
|
+
},
|
|
554
|
+
selectWithoutPointers,
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
const hook = !_skipHooks
|
|
558
|
+
? initializeHook({
|
|
559
|
+
className,
|
|
560
|
+
select: selectWithoutPointers,
|
|
561
|
+
context,
|
|
562
|
+
})
|
|
563
|
+
: undefined
|
|
564
|
+
|
|
565
|
+
await hook?.runOnMultipleObjects({
|
|
566
|
+
operationType: OperationType.BeforeRead,
|
|
567
|
+
where: whereWithACLCondition,
|
|
568
|
+
})
|
|
569
|
+
|
|
570
|
+
const objectsToReturn = await this.adapter.getObjects({
|
|
571
|
+
className,
|
|
572
|
+
context: contextWithRoot(context),
|
|
573
|
+
first,
|
|
574
|
+
offset,
|
|
575
|
+
where: whereWithACLCondition,
|
|
576
|
+
// @ts-expect-error
|
|
577
|
+
select: !select ? undefined : selectWithPointersAndRelationsToGetId,
|
|
578
|
+
order,
|
|
579
|
+
})
|
|
580
|
+
|
|
581
|
+
const objectsWithPointers = await Promise.all(
|
|
582
|
+
objectsToReturn.map(async (object) => {
|
|
583
|
+
return {
|
|
584
|
+
...object,
|
|
585
|
+
...(await this._getFinalObjectWithPointerAndRelation({
|
|
586
|
+
// @ts-expect-error
|
|
587
|
+
object,
|
|
588
|
+
context,
|
|
589
|
+
// @ts-expect-error
|
|
590
|
+
originClassName: className,
|
|
591
|
+
pointers,
|
|
592
|
+
_skipHooks,
|
|
593
|
+
})),
|
|
594
|
+
}
|
|
595
|
+
}),
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
const afterReadResults = await hook?.runOnMultipleObjects({
|
|
599
|
+
operationType: OperationType.AfterRead,
|
|
600
|
+
// @ts-expect-error
|
|
601
|
+
objects: objectsWithPointers,
|
|
602
|
+
})
|
|
603
|
+
|
|
604
|
+
return (afterReadResults?.objects ||
|
|
605
|
+
objectsWithPointers) as unknown as Promise<OutputType<T, K, W>[]>
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
async createObject<
|
|
609
|
+
K extends keyof T['types'],
|
|
610
|
+
U extends keyof T['types'][K],
|
|
611
|
+
W extends keyof T['types'][K],
|
|
612
|
+
>({
|
|
613
|
+
className,
|
|
614
|
+
context,
|
|
615
|
+
data,
|
|
616
|
+
select,
|
|
617
|
+
}: CreateObjectOptions<T, K, U, W>): Promise<OutputType<T, K, W>> {
|
|
618
|
+
// Here data.file is null but should not be
|
|
619
|
+
const hook = initializeHook({
|
|
620
|
+
className,
|
|
621
|
+
context,
|
|
622
|
+
newData: data,
|
|
623
|
+
// @ts-expect-error
|
|
624
|
+
select,
|
|
625
|
+
})
|
|
626
|
+
|
|
627
|
+
const { newData } = await hook.runOnSingleObject({
|
|
628
|
+
operationType: OperationType.BeforeCreate,
|
|
629
|
+
})
|
|
630
|
+
|
|
631
|
+
const res = await this.adapter.createObject({
|
|
632
|
+
className,
|
|
633
|
+
context,
|
|
634
|
+
select,
|
|
635
|
+
data: newData || data,
|
|
636
|
+
})
|
|
637
|
+
|
|
638
|
+
await hook.runOnSingleObject({
|
|
639
|
+
operationType: OperationType.AfterCreate,
|
|
640
|
+
id: res.id,
|
|
641
|
+
})
|
|
642
|
+
|
|
643
|
+
if (select && Object.keys(select).length === 0) return null
|
|
644
|
+
|
|
645
|
+
return this.getObject({
|
|
646
|
+
className,
|
|
647
|
+
context: {
|
|
648
|
+
...context,
|
|
649
|
+
// @ts-expect-error
|
|
650
|
+
user: className === 'User' ? res : context.user,
|
|
651
|
+
},
|
|
652
|
+
select,
|
|
653
|
+
id: res.id,
|
|
654
|
+
})
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
async createObjects<
|
|
658
|
+
K extends keyof T['types'],
|
|
659
|
+
U extends keyof T['types'][K],
|
|
660
|
+
W extends keyof T['types'][K],
|
|
661
|
+
X extends keyof T['types'][K],
|
|
662
|
+
>({
|
|
663
|
+
data,
|
|
664
|
+
select,
|
|
665
|
+
className,
|
|
666
|
+
context,
|
|
667
|
+
first,
|
|
668
|
+
offset,
|
|
669
|
+
order,
|
|
670
|
+
}: CreateObjectsOptions<T, K, U, W, X>): Promise<OutputType<T, K, W>[]> {
|
|
671
|
+
if (data.length === 0) return []
|
|
672
|
+
|
|
673
|
+
const hooks = await Promise.all(
|
|
674
|
+
data.map((newData) =>
|
|
675
|
+
initializeHook({
|
|
676
|
+
className,
|
|
677
|
+
context,
|
|
678
|
+
newData,
|
|
679
|
+
// @ts-expect-error
|
|
680
|
+
select,
|
|
681
|
+
}),
|
|
682
|
+
),
|
|
683
|
+
)
|
|
684
|
+
|
|
685
|
+
const arrayOfComputedData = (
|
|
686
|
+
await Promise.all(
|
|
687
|
+
hooks.map(
|
|
688
|
+
async (hook) =>
|
|
689
|
+
(
|
|
690
|
+
await hook.runOnMultipleObjects({
|
|
691
|
+
operationType: OperationType.BeforeCreate,
|
|
692
|
+
})
|
|
693
|
+
)?.newData[0],
|
|
694
|
+
),
|
|
695
|
+
)
|
|
696
|
+
).filter(notEmpty)
|
|
697
|
+
|
|
698
|
+
const listOfIds = await this.adapter.createObjects({
|
|
699
|
+
className,
|
|
700
|
+
select,
|
|
701
|
+
context,
|
|
702
|
+
data: arrayOfComputedData,
|
|
703
|
+
first,
|
|
704
|
+
offset,
|
|
705
|
+
order,
|
|
706
|
+
})
|
|
707
|
+
|
|
708
|
+
const ids = listOfIds.map(({ id }) => id)
|
|
709
|
+
|
|
710
|
+
await Promise.all(
|
|
711
|
+
hooks.map((hook) =>
|
|
712
|
+
hook.runOnMultipleObjects({
|
|
713
|
+
operationType: OperationType.AfterCreate,
|
|
714
|
+
ids,
|
|
715
|
+
}),
|
|
716
|
+
),
|
|
717
|
+
)
|
|
718
|
+
|
|
719
|
+
if (select && Object.keys(select).length === 0) return []
|
|
720
|
+
|
|
721
|
+
return this.getObjects({
|
|
722
|
+
className,
|
|
723
|
+
context: {
|
|
724
|
+
...context,
|
|
725
|
+
// @ts-expect-error
|
|
726
|
+
user: className === 'User' ? data[0] : context.user,
|
|
727
|
+
},
|
|
728
|
+
select,
|
|
729
|
+
// @ts-expect-error
|
|
730
|
+
where: { id: { in: ids } },
|
|
731
|
+
first,
|
|
732
|
+
offset,
|
|
733
|
+
order,
|
|
734
|
+
})
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
async updateObject<
|
|
738
|
+
K extends keyof T['types'],
|
|
739
|
+
U extends keyof T['types'][K],
|
|
740
|
+
W extends keyof T['types'][K],
|
|
741
|
+
>({
|
|
742
|
+
id,
|
|
743
|
+
className,
|
|
744
|
+
context,
|
|
745
|
+
data,
|
|
746
|
+
select,
|
|
747
|
+
_skipHooks,
|
|
748
|
+
}: UpdateObjectOptions<T, K, U, W>): Promise<OutputType<T, K, W>> {
|
|
749
|
+
const hook = !_skipHooks
|
|
750
|
+
? initializeHook({
|
|
751
|
+
className,
|
|
752
|
+
context,
|
|
753
|
+
newData: data,
|
|
754
|
+
// @ts-expect-error
|
|
755
|
+
select,
|
|
756
|
+
})
|
|
757
|
+
: undefined
|
|
758
|
+
|
|
759
|
+
const resultsAfterBeforeUpdate = await hook?.runOnSingleObject({
|
|
760
|
+
operationType: OperationType.BeforeUpdate,
|
|
761
|
+
id,
|
|
762
|
+
})
|
|
763
|
+
|
|
764
|
+
const whereWithACLCondition = this._buildWhereWithACL({}, context, 'write')
|
|
765
|
+
|
|
766
|
+
await this.adapter.updateObject({
|
|
767
|
+
className,
|
|
768
|
+
select,
|
|
769
|
+
id,
|
|
770
|
+
context,
|
|
771
|
+
data: resultsAfterBeforeUpdate?.newData || data,
|
|
772
|
+
where: whereWithACLCondition,
|
|
773
|
+
})
|
|
774
|
+
|
|
775
|
+
await hook?.runOnSingleObject({
|
|
776
|
+
operationType: OperationType.AfterUpdate,
|
|
777
|
+
id,
|
|
778
|
+
originalObject: resultsAfterBeforeUpdate?.object,
|
|
779
|
+
})
|
|
780
|
+
|
|
781
|
+
if (select && Object.keys(select).length === 0) return null
|
|
782
|
+
|
|
783
|
+
return this.getObject({
|
|
784
|
+
className,
|
|
785
|
+
context,
|
|
786
|
+
select,
|
|
787
|
+
id,
|
|
788
|
+
})
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
async updateObjects<
|
|
792
|
+
K extends keyof T['types'],
|
|
793
|
+
U extends keyof T['types'][K],
|
|
794
|
+
W extends keyof T['types'][K],
|
|
795
|
+
X extends keyof T['types'][K],
|
|
796
|
+
>({
|
|
797
|
+
className,
|
|
798
|
+
where,
|
|
799
|
+
context,
|
|
800
|
+
select,
|
|
801
|
+
data,
|
|
802
|
+
first,
|
|
803
|
+
offset,
|
|
804
|
+
order,
|
|
805
|
+
_skipHooks,
|
|
806
|
+
}: UpdateObjectsOptions<T, K, U, W, X>): Promise<OutputType<T, K, W>[]> {
|
|
807
|
+
const whereObject = await this._getWhereObjectWithPointerOrRelation(
|
|
808
|
+
className,
|
|
809
|
+
where || {},
|
|
810
|
+
context,
|
|
811
|
+
)
|
|
812
|
+
|
|
813
|
+
const hook = !_skipHooks
|
|
814
|
+
? initializeHook({
|
|
815
|
+
className,
|
|
816
|
+
context,
|
|
817
|
+
newData: data,
|
|
818
|
+
// @ts-expect-error
|
|
819
|
+
select,
|
|
820
|
+
})
|
|
821
|
+
: undefined
|
|
822
|
+
|
|
823
|
+
const whereWithACLCondition = this._buildWhereWithACL(
|
|
824
|
+
whereObject,
|
|
825
|
+
context,
|
|
826
|
+
'write',
|
|
827
|
+
)
|
|
828
|
+
|
|
829
|
+
const resultsAfterBeforeUpdate = await hook?.runOnMultipleObjects({
|
|
830
|
+
operationType: OperationType.BeforeUpdate,
|
|
831
|
+
where: whereWithACLCondition,
|
|
832
|
+
})
|
|
833
|
+
|
|
834
|
+
const objects = await this.adapter.updateObjects({
|
|
835
|
+
className,
|
|
836
|
+
context,
|
|
837
|
+
select,
|
|
838
|
+
data: resultsAfterBeforeUpdate?.newData[0] || data,
|
|
839
|
+
where: whereWithACLCondition,
|
|
840
|
+
first,
|
|
841
|
+
offset,
|
|
842
|
+
order,
|
|
843
|
+
})
|
|
844
|
+
|
|
845
|
+
const objectsId = objects.map((object) => object?.id).filter(notEmpty)
|
|
846
|
+
|
|
847
|
+
await hook?.runOnMultipleObjects({
|
|
848
|
+
operationType: OperationType.AfterUpdate,
|
|
849
|
+
ids: objectsId,
|
|
850
|
+
originalObjects: resultsAfterBeforeUpdate?.objects || [],
|
|
851
|
+
})
|
|
852
|
+
|
|
853
|
+
if (select && Object.keys(select).length === 0) return []
|
|
854
|
+
|
|
855
|
+
return this.getObjects({
|
|
856
|
+
className,
|
|
857
|
+
context,
|
|
858
|
+
select,
|
|
859
|
+
// @ts-expect-error
|
|
860
|
+
where: { id: { in: objectsId } },
|
|
861
|
+
first,
|
|
862
|
+
offset,
|
|
863
|
+
order,
|
|
864
|
+
})
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
async deleteObject<
|
|
868
|
+
K extends keyof T['types'],
|
|
869
|
+
U extends keyof T['types'][K],
|
|
870
|
+
>({
|
|
871
|
+
context,
|
|
872
|
+
className,
|
|
873
|
+
id,
|
|
874
|
+
select,
|
|
875
|
+
}: DeleteObjectOptions<T, K, U>): Promise<OutputType<T, K, U>> {
|
|
876
|
+
const hook = initializeHook({
|
|
877
|
+
className,
|
|
878
|
+
context,
|
|
879
|
+
// @ts-expect-error
|
|
880
|
+
select,
|
|
881
|
+
})
|
|
882
|
+
|
|
883
|
+
const whereWithACLCondition = this._buildWhereWithACL({}, context, 'write')
|
|
884
|
+
|
|
885
|
+
let objectBeforeDelete = null
|
|
886
|
+
|
|
887
|
+
if (select && Object.keys(select).length > 0)
|
|
888
|
+
objectBeforeDelete = await this.getObject({
|
|
889
|
+
className,
|
|
890
|
+
select,
|
|
891
|
+
id,
|
|
892
|
+
context,
|
|
893
|
+
})
|
|
894
|
+
|
|
895
|
+
const resultOfBeforeDelete = await hook.runOnSingleObject({
|
|
896
|
+
operationType: OperationType.BeforeDelete,
|
|
897
|
+
id,
|
|
898
|
+
})
|
|
899
|
+
|
|
900
|
+
await this.adapter.deleteObject({
|
|
901
|
+
className,
|
|
902
|
+
context,
|
|
903
|
+
select,
|
|
904
|
+
id,
|
|
905
|
+
where: whereWithACLCondition,
|
|
906
|
+
})
|
|
907
|
+
|
|
908
|
+
await hook.runOnSingleObject({
|
|
909
|
+
operationType: OperationType.AfterDelete,
|
|
910
|
+
originalObject: resultOfBeforeDelete.object,
|
|
911
|
+
})
|
|
912
|
+
|
|
913
|
+
return objectBeforeDelete
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
async deleteObjects<
|
|
917
|
+
K extends keyof T['types'],
|
|
918
|
+
U extends keyof T['types'][K],
|
|
919
|
+
W extends keyof T['types'][K],
|
|
920
|
+
>({
|
|
921
|
+
className,
|
|
922
|
+
context,
|
|
923
|
+
select,
|
|
924
|
+
where,
|
|
925
|
+
first,
|
|
926
|
+
offset,
|
|
927
|
+
order,
|
|
928
|
+
}: DeleteObjectsOptions<T, K, U, W>): Promise<OutputType<T, K, W>[]> {
|
|
929
|
+
const whereObject = await this._getWhereObjectWithPointerOrRelation(
|
|
930
|
+
className,
|
|
931
|
+
where || {},
|
|
932
|
+
context,
|
|
933
|
+
)
|
|
934
|
+
|
|
935
|
+
const hook = initializeHook({
|
|
936
|
+
className,
|
|
937
|
+
context,
|
|
938
|
+
// @ts-expect-error
|
|
939
|
+
select,
|
|
940
|
+
})
|
|
941
|
+
|
|
942
|
+
const whereWithACLCondition = this._buildWhereWithACL(
|
|
943
|
+
whereObject,
|
|
944
|
+
context,
|
|
945
|
+
'write',
|
|
946
|
+
)
|
|
947
|
+
|
|
948
|
+
let objectsBeforeDelete: OutputType<T, K, W>[] = []
|
|
949
|
+
|
|
950
|
+
if (select && Object.keys(select).length > 0)
|
|
951
|
+
objectsBeforeDelete = await this.getObjects({
|
|
952
|
+
className,
|
|
953
|
+
where,
|
|
954
|
+
select,
|
|
955
|
+
context,
|
|
956
|
+
first,
|
|
957
|
+
offset,
|
|
958
|
+
order,
|
|
959
|
+
})
|
|
960
|
+
|
|
961
|
+
const resultOfBeforeDelete = await hook.runOnMultipleObjects({
|
|
962
|
+
operationType: OperationType.BeforeDelete,
|
|
963
|
+
where: whereWithACLCondition,
|
|
964
|
+
})
|
|
965
|
+
|
|
966
|
+
await this.adapter.deleteObjects({
|
|
967
|
+
className,
|
|
968
|
+
context,
|
|
969
|
+
select,
|
|
970
|
+
first,
|
|
971
|
+
offset,
|
|
972
|
+
where: whereWithACLCondition,
|
|
973
|
+
order,
|
|
974
|
+
})
|
|
975
|
+
|
|
976
|
+
await hook.runOnMultipleObjects({
|
|
977
|
+
operationType: OperationType.AfterDelete,
|
|
978
|
+
originalObjects: resultOfBeforeDelete.objects,
|
|
979
|
+
})
|
|
980
|
+
|
|
981
|
+
return objectsBeforeDelete
|
|
982
|
+
}
|
|
983
|
+
}
|