@zenstackhq/server 2.2.4 → 2.3.0

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/api/rest/index.js CHANGED
@@ -1,18 +1,12 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
14
5
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.RestApiHandler = void 0;
6
+ exports.default = makeHandler;
7
+ exports.RestApiHandler = makeHandler;
8
+ exports.default = makeHandler;
9
+ exports.RestApiHandler = makeHandler;
16
10
  const runtime_1 = require("@zenstackhq/runtime");
17
11
  const change_case_1 = require("change-case");
18
12
  const lower_case_first_1 = require("lower-case-first");
@@ -167,328 +161,316 @@ class RequestHandler extends base_1.APIHandlerBase {
167
161
  data: zod_1.default.array(zod_1.default.object({ type: zod_1.default.string(), id: zod_1.default.union([zod_1.default.string(), zod_1.default.number()]) })),
168
162
  });
169
163
  }
170
- handleRequest(_a) {
171
- return __awaiter(this, arguments, void 0, function* ({ prisma, method, path, query, requestBody, logger, modelMeta, zodSchemas, }) {
172
- modelMeta = modelMeta !== null && modelMeta !== void 0 ? modelMeta : this.defaultModelMeta;
173
- if (!modelMeta) {
174
- throw new Error('Model metadata is not provided or loaded from default location');
175
- }
176
- if (!this.serializers) {
177
- this.buildSerializers(modelMeta);
178
- }
179
- if (!this.typeMap) {
180
- this.buildTypeMap(logger, modelMeta);
181
- }
182
- method = method.toUpperCase();
183
- if (!path.startsWith('/')) {
184
- path = '/' + path;
185
- }
186
- try {
187
- switch (method) {
188
- case 'GET': {
189
- let match = urlPatterns.single.match(path);
190
- if (match) {
191
- // single resource read
192
- return yield this.processSingleRead(prisma, match.type, match.id, query);
193
- }
194
- match = urlPatterns.fetchRelationship.match(path);
195
- if (match) {
196
- // fetch related resource(s)
197
- return yield this.processFetchRelated(prisma, match.type, match.id, match.relationship, query);
198
- }
199
- match = urlPatterns.relationship.match(path);
200
- if (match) {
201
- // read relationship
202
- return yield this.processReadRelationship(prisma, match.type, match.id, match.relationship, query, modelMeta);
203
- }
204
- match = urlPatterns.collection.match(path);
205
- if (match) {
206
- // collection read
207
- return yield this.processCollectionRead(prisma, match.type, query);
208
- }
209
- return this.makeError('invalidPath');
164
+ async handleRequest({ prisma, method, path, query, requestBody, logger, modelMeta, zodSchemas, }) {
165
+ modelMeta = modelMeta ?? this.defaultModelMeta;
166
+ if (!modelMeta) {
167
+ throw new Error('Model metadata is not provided or loaded from default location');
168
+ }
169
+ if (!this.serializers) {
170
+ this.buildSerializers(modelMeta);
171
+ }
172
+ if (!this.typeMap) {
173
+ this.buildTypeMap(logger, modelMeta);
174
+ }
175
+ method = method.toUpperCase();
176
+ if (!path.startsWith('/')) {
177
+ path = '/' + path;
178
+ }
179
+ try {
180
+ switch (method) {
181
+ case 'GET': {
182
+ let match = urlPatterns.single.match(path);
183
+ if (match) {
184
+ // single resource read
185
+ return await this.processSingleRead(prisma, match.type, match.id, query);
210
186
  }
211
- case 'POST': {
212
- if (!requestBody) {
213
- return this.makeError('invalidPayload');
214
- }
215
- let match = urlPatterns.collection.match(path);
216
- if (match) {
217
- // resource creation
218
- return yield this.processCreate(prisma, match.type, query, requestBody, zodSchemas);
219
- }
220
- match = urlPatterns.relationship.match(path);
221
- if (match) {
222
- // relationship creation (collection relationship only)
223
- return yield this.processRelationshipCRUD(prisma, 'create', match.type, match.id, match.relationship, query, requestBody);
224
- }
225
- return this.makeError('invalidPath');
187
+ match = urlPatterns.fetchRelationship.match(path);
188
+ if (match) {
189
+ // fetch related resource(s)
190
+ return await this.processFetchRelated(prisma, match.type, match.id, match.relationship, query);
226
191
  }
227
- // TODO: PUT for full update
228
- case 'PUT':
229
- case 'PATCH': {
230
- if (!requestBody) {
231
- return this.makeError('invalidPayload');
232
- }
233
- let match = urlPatterns.single.match(path);
234
- if (match) {
235
- // resource update
236
- return yield this.processUpdate(prisma, match.type, match.id, query, requestBody, zodSchemas);
237
- }
238
- match = urlPatterns.relationship.match(path);
239
- if (match) {
240
- // relationship update
241
- return yield this.processRelationshipCRUD(prisma, 'update', match.type, match.id, match.relationship, query, requestBody);
242
- }
243
- return this.makeError('invalidPath');
192
+ match = urlPatterns.relationship.match(path);
193
+ if (match) {
194
+ // read relationship
195
+ return await this.processReadRelationship(prisma, match.type, match.id, match.relationship, query, modelMeta);
244
196
  }
245
- case 'DELETE': {
246
- let match = urlPatterns.single.match(path);
247
- if (match) {
248
- // resource deletion
249
- return yield this.processDelete(prisma, match.type, match.id);
250
- }
251
- match = urlPatterns.relationship.match(path);
252
- if (match) {
253
- // relationship deletion (collection relationship only)
254
- return yield this.processRelationshipCRUD(prisma, 'delete', match.type, match.id, match.relationship, query, requestBody);
255
- }
256
- return this.makeError('invalidPath');
197
+ match = urlPatterns.collection.match(path);
198
+ if (match) {
199
+ // collection read
200
+ return await this.processCollectionRead(prisma, match.type, query);
257
201
  }
258
- default:
259
- return this.makeError('invalidPath');
260
- }
261
- }
262
- catch (err) {
263
- if (err instanceof InvalidValueError) {
264
- return this.makeError('invalidValue', err.message);
202
+ return this.makeError('invalidPath');
265
203
  }
266
- else {
267
- return this.handlePrismaError(err);
204
+ case 'POST': {
205
+ if (!requestBody) {
206
+ return this.makeError('invalidPayload');
207
+ }
208
+ let match = urlPatterns.collection.match(path);
209
+ if (match) {
210
+ // resource creation
211
+ return await this.processCreate(prisma, match.type, query, requestBody, zodSchemas);
212
+ }
213
+ match = urlPatterns.relationship.match(path);
214
+ if (match) {
215
+ // relationship creation (collection relationship only)
216
+ return await this.processRelationshipCRUD(prisma, 'create', match.type, match.id, match.relationship, query, requestBody);
217
+ }
218
+ return this.makeError('invalidPath');
268
219
  }
269
- }
270
- });
271
- }
272
- processSingleRead(prisma, type, resourceId, query) {
273
- return __awaiter(this, void 0, void 0, function* () {
274
- const typeInfo = this.typeMap[type];
275
- if (!typeInfo) {
276
- return this.makeUnsupportedModelError(type);
277
- }
278
- const args = { where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId) };
279
- // include IDs of relation fields so that they can be serialized
280
- this.includeRelationshipIds(type, args, 'include');
281
- // handle "include" query parameter
282
- let include;
283
- if (query === null || query === void 0 ? void 0 : query.include) {
284
- const { select, error, allIncludes } = this.buildRelationSelect(type, query.include);
285
- if (error) {
286
- return error;
220
+ // TODO: PUT for full update
221
+ case 'PUT':
222
+ case 'PATCH': {
223
+ if (!requestBody) {
224
+ return this.makeError('invalidPayload');
225
+ }
226
+ let match = urlPatterns.single.match(path);
227
+ if (match) {
228
+ // resource update
229
+ return await this.processUpdate(prisma, match.type, match.id, query, requestBody, zodSchemas);
230
+ }
231
+ match = urlPatterns.relationship.match(path);
232
+ if (match) {
233
+ // relationship update
234
+ return await this.processRelationshipCRUD(prisma, 'update', match.type, match.id, match.relationship, query, requestBody);
235
+ }
236
+ return this.makeError('invalidPath');
287
237
  }
288
- if (select) {
289
- args.include = Object.assign(Object.assign({}, args.include), select);
238
+ case 'DELETE': {
239
+ let match = urlPatterns.single.match(path);
240
+ if (match) {
241
+ // resource deletion
242
+ return await this.processDelete(prisma, match.type, match.id);
243
+ }
244
+ match = urlPatterns.relationship.match(path);
245
+ if (match) {
246
+ // relationship deletion (collection relationship only)
247
+ return await this.processRelationshipCRUD(prisma, 'delete', match.type, match.id, match.relationship, query, requestBody);
248
+ }
249
+ return this.makeError('invalidPath');
290
250
  }
291
- include = allIncludes;
251
+ default:
252
+ return this.makeError('invalidPath');
292
253
  }
293
- const entity = yield prisma[type].findUnique(args);
294
- if (entity) {
295
- return {
296
- status: 200,
297
- body: yield this.serializeItems(type, entity, { include }),
298
- };
254
+ }
255
+ catch (err) {
256
+ if (err instanceof InvalidValueError) {
257
+ return this.makeError('invalidValue', err.message);
299
258
  }
300
259
  else {
301
- return this.makeError('notFound');
260
+ return this.handlePrismaError(err);
302
261
  }
303
- });
262
+ }
304
263
  }
305
- processFetchRelated(prisma, type, resourceId, relationship, query) {
306
- return __awaiter(this, void 0, void 0, function* () {
307
- var _a, _b;
308
- const typeInfo = this.typeMap[type];
309
- if (!typeInfo) {
310
- return this.makeUnsupportedModelError(type);
311
- }
312
- const relationInfo = typeInfo.relationships[relationship];
313
- if (!relationInfo) {
314
- return this.makeUnsupportedRelationshipError(type, relationship, 404);
264
+ async processSingleRead(prisma, type, resourceId, query) {
265
+ const typeInfo = this.typeMap[type];
266
+ if (!typeInfo) {
267
+ return this.makeUnsupportedModelError(type);
268
+ }
269
+ const args = { where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId) };
270
+ // include IDs of relation fields so that they can be serialized
271
+ this.includeRelationshipIds(type, args, 'include');
272
+ // handle "include" query parameter
273
+ let include;
274
+ if (query?.include) {
275
+ const { select, error, allIncludes } = this.buildRelationSelect(type, query.include);
276
+ if (error) {
277
+ return error;
315
278
  }
316
- let select;
317
- // handle "include" query parameter
318
- let include;
319
- if (query === null || query === void 0 ? void 0 : query.include) {
320
- const { select: relationSelect, error, allIncludes } = this.buildRelationSelect(type, query.include);
321
- if (error) {
322
- return error;
323
- }
324
- // trim the leading `$relationship.` from the include paths
325
- include = allIncludes
326
- .filter((i) => i.startsWith(`${relationship}.`))
327
- .map((i) => i.substring(`${relationship}.`.length));
328
- select = relationSelect;
279
+ if (select) {
280
+ args.include = { ...args.include, ...select };
329
281
  }
330
- select = select !== null && select !== void 0 ? select : { [relationship]: true };
331
- const args = {
332
- where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId),
333
- select,
282
+ include = allIncludes;
283
+ }
284
+ const entity = await prisma[type].findUnique(args);
285
+ if (entity) {
286
+ return {
287
+ status: 200,
288
+ body: await this.serializeItems(type, entity, { include }),
334
289
  };
335
- if (relationInfo.isCollection) {
336
- // if related data is a collection, it can be filtered, sorted, and paginated
337
- const error = this.injectRelationQuery(relationInfo.type, select, relationship, query);
338
- if (error) {
339
- return error;
340
- }
341
- }
342
- const entity = yield prisma[type].findUnique(args);
343
- let paginator;
344
- if (((_a = entity === null || entity === void 0 ? void 0 : entity._count) === null || _a === void 0 ? void 0 : _a[relationship]) !== undefined) {
345
- // build up paginator
346
- const total = (_b = entity === null || entity === void 0 ? void 0 : entity._count) === null || _b === void 0 ? void 0 : _b[relationship];
347
- const url = this.makeNormalizedUrl(`/${type}/${resourceId}/${relationship}`, query);
348
- const { offset, limit } = this.getPagination(query);
349
- paginator = this.makePaginator(url, offset, limit, total);
350
- }
351
- if (entity === null || entity === void 0 ? void 0 : entity[relationship]) {
352
- return {
353
- status: 200,
354
- body: yield this.serializeItems(relationInfo.type, entity[relationship], {
355
- linkers: {
356
- document: new ts_japi_1.Linker(() => this.makeLinkUrl(`/${type}/${resourceId}/${relationship}`)),
357
- paginator,
358
- },
359
- include,
360
- }),
361
- };
362
- }
363
- else {
364
- return this.makeError('notFound');
365
- }
366
- });
290
+ }
291
+ else {
292
+ return this.makeError('notFound');
293
+ }
367
294
  }
368
- processReadRelationship(prisma, type, resourceId, relationship, query, modelMeta) {
369
- return __awaiter(this, void 0, void 0, function* () {
370
- var _a, _b;
371
- const typeInfo = this.typeMap[type];
372
- if (!typeInfo) {
373
- return this.makeUnsupportedModelError(type);
374
- }
375
- const relationInfo = typeInfo.relationships[relationship];
376
- if (!relationInfo) {
377
- return this.makeUnsupportedRelationshipError(type, relationship, 404);
378
- }
379
- const args = {
380
- where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId),
381
- select: this.makeIdSelect(type, modelMeta),
382
- };
383
- // include IDs of relation fields so that they can be serialized
384
- // this.includeRelationshipIds(type, args, 'select');
385
- args.select = Object.assign(Object.assign({}, args.select), { [relationship]: { select: this.makeIdSelect(relationInfo.type, modelMeta) } });
386
- let paginator;
387
- if (relationInfo.isCollection) {
388
- // if related data is a collection, it can be filtered, sorted, and paginated
389
- const error = this.injectRelationQuery(relationInfo.type, args.select, relationship, query);
390
- if (error) {
391
- return error;
392
- }
295
+ async processFetchRelated(prisma, type, resourceId, relationship, query) {
296
+ const typeInfo = this.typeMap[type];
297
+ if (!typeInfo) {
298
+ return this.makeUnsupportedModelError(type);
299
+ }
300
+ const relationInfo = typeInfo.relationships[relationship];
301
+ if (!relationInfo) {
302
+ return this.makeUnsupportedRelationshipError(type, relationship, 404);
303
+ }
304
+ let select;
305
+ // handle "include" query parameter
306
+ let include;
307
+ if (query?.include) {
308
+ const { select: relationSelect, error, allIncludes } = this.buildRelationSelect(type, query.include);
309
+ if (error) {
310
+ return error;
393
311
  }
394
- const entity = yield prisma[type].findUnique(args);
395
- if (((_a = entity === null || entity === void 0 ? void 0 : entity._count) === null || _a === void 0 ? void 0 : _a[relationship]) !== undefined) {
396
- // build up paginator
397
- const total = (_b = entity === null || entity === void 0 ? void 0 : entity._count) === null || _b === void 0 ? void 0 : _b[relationship];
398
- const url = this.makeNormalizedUrl(`/${type}/${resourceId}/relationships/${relationship}`, query);
399
- const { offset, limit } = this.getPagination(query);
400
- paginator = this.makePaginator(url, offset, limit, total);
312
+ // trim the leading `$relationship.` from the include paths
313
+ include = allIncludes
314
+ .filter((i) => i.startsWith(`${relationship}.`))
315
+ .map((i) => i.substring(`${relationship}.`.length));
316
+ select = relationSelect;
317
+ }
318
+ select = select ?? { [relationship]: true };
319
+ const args = {
320
+ where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId),
321
+ select,
322
+ };
323
+ if (relationInfo.isCollection) {
324
+ // if related data is a collection, it can be filtered, sorted, and paginated
325
+ const error = this.injectRelationQuery(relationInfo.type, select, relationship, query);
326
+ if (error) {
327
+ return error;
401
328
  }
402
- if (entity === null || entity === void 0 ? void 0 : entity[relationship]) {
403
- const serialized = yield this.serializeItems(relationInfo.type, entity[relationship], {
329
+ }
330
+ const entity = await prisma[type].findUnique(args);
331
+ let paginator;
332
+ if (entity?._count?.[relationship] !== undefined) {
333
+ // build up paginator
334
+ const total = entity?._count?.[relationship];
335
+ const url = this.makeNormalizedUrl(`/${type}/${resourceId}/${relationship}`, query);
336
+ const { offset, limit } = this.getPagination(query);
337
+ paginator = this.makePaginator(url, offset, limit, total);
338
+ }
339
+ if (entity?.[relationship]) {
340
+ return {
341
+ status: 200,
342
+ body: await this.serializeItems(relationInfo.type, entity[relationship], {
404
343
  linkers: {
405
- document: new ts_japi_1.Linker(() => this.makeLinkUrl(`/${type}/${resourceId}/relationships/${relationship}`)),
344
+ document: new ts_japi_1.Linker(() => this.makeLinkUrl(`/${type}/${resourceId}/${relationship}`)),
406
345
  paginator,
407
346
  },
408
- onlyIdentifier: true,
409
- });
410
- return {
411
- status: 200,
412
- body: serialized,
413
- };
414
- }
415
- else {
416
- return this.makeError('notFound');
417
- }
418
- });
347
+ include,
348
+ }),
349
+ };
350
+ }
351
+ else {
352
+ return this.makeError('notFound');
353
+ }
419
354
  }
420
- processCollectionRead(prisma, type, query) {
421
- return __awaiter(this, void 0, void 0, function* () {
422
- const typeInfo = this.typeMap[type];
423
- if (!typeInfo) {
424
- return this.makeUnsupportedModelError(type);
425
- }
426
- const args = {};
427
- // add filter
428
- const { filter, error: filterError } = this.buildFilter(type, query);
429
- if (filterError) {
430
- return filterError;
431
- }
432
- if (filter) {
433
- args.where = filter;
434
- }
435
- const { sort, error: sortError } = this.buildSort(type, query);
436
- if (sortError) {
437
- return sortError;
438
- }
439
- if (sort) {
440
- args.orderBy = sort;
441
- }
442
- // include IDs of relation fields so that they can be serialized
443
- this.includeRelationshipIds(type, args, 'include');
444
- // handle "include" query parameter
445
- let include;
446
- if (query === null || query === void 0 ? void 0 : query.include) {
447
- const { select, error, allIncludes } = this.buildRelationSelect(type, query.include);
448
- if (error) {
449
- return error;
450
- }
451
- if (select) {
452
- args.include = Object.assign(Object.assign({}, args.include), select);
453
- }
454
- include = allIncludes;
355
+ async processReadRelationship(prisma, type, resourceId, relationship, query, modelMeta) {
356
+ const typeInfo = this.typeMap[type];
357
+ if (!typeInfo) {
358
+ return this.makeUnsupportedModelError(type);
359
+ }
360
+ const relationInfo = typeInfo.relationships[relationship];
361
+ if (!relationInfo) {
362
+ return this.makeUnsupportedRelationshipError(type, relationship, 404);
363
+ }
364
+ const args = {
365
+ where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId),
366
+ select: this.makeIdSelect(type, modelMeta),
367
+ };
368
+ // include IDs of relation fields so that they can be serialized
369
+ // this.includeRelationshipIds(type, args, 'select');
370
+ args.select = { ...args.select, [relationship]: { select: this.makeIdSelect(relationInfo.type, modelMeta) } };
371
+ let paginator;
372
+ if (relationInfo.isCollection) {
373
+ // if related data is a collection, it can be filtered, sorted, and paginated
374
+ const error = this.injectRelationQuery(relationInfo.type, args.select, relationship, query);
375
+ if (error) {
376
+ return error;
455
377
  }
378
+ }
379
+ const entity = await prisma[type].findUnique(args);
380
+ if (entity?._count?.[relationship] !== undefined) {
381
+ // build up paginator
382
+ const total = entity?._count?.[relationship];
383
+ const url = this.makeNormalizedUrl(`/${type}/${resourceId}/relationships/${relationship}`, query);
456
384
  const { offset, limit } = this.getPagination(query);
457
- if (offset > 0) {
458
- args.skip = offset;
459
- }
460
- if (limit === Infinity) {
461
- const entities = yield prisma[type].findMany(args);
462
- const body = yield this.serializeItems(type, entities, { include });
463
- const total = entities.length;
464
- body.meta = this.addTotalCountToMeta(body.meta, total);
465
- return {
466
- status: 200,
467
- body: body,
468
- };
385
+ paginator = this.makePaginator(url, offset, limit, total);
386
+ }
387
+ if (entity?.[relationship]) {
388
+ const serialized = await this.serializeItems(relationInfo.type, entity[relationship], {
389
+ linkers: {
390
+ document: new ts_japi_1.Linker(() => this.makeLinkUrl(`/${type}/${resourceId}/relationships/${relationship}`)),
391
+ paginator,
392
+ },
393
+ onlyIdentifier: true,
394
+ });
395
+ return {
396
+ status: 200,
397
+ body: serialized,
398
+ };
399
+ }
400
+ else {
401
+ return this.makeError('notFound');
402
+ }
403
+ }
404
+ async processCollectionRead(prisma, type, query) {
405
+ const typeInfo = this.typeMap[type];
406
+ if (!typeInfo) {
407
+ return this.makeUnsupportedModelError(type);
408
+ }
409
+ const args = {};
410
+ // add filter
411
+ const { filter, error: filterError } = this.buildFilter(type, query);
412
+ if (filterError) {
413
+ return filterError;
414
+ }
415
+ if (filter) {
416
+ args.where = filter;
417
+ }
418
+ const { sort, error: sortError } = this.buildSort(type, query);
419
+ if (sortError) {
420
+ return sortError;
421
+ }
422
+ if (sort) {
423
+ args.orderBy = sort;
424
+ }
425
+ // include IDs of relation fields so that they can be serialized
426
+ this.includeRelationshipIds(type, args, 'include');
427
+ // handle "include" query parameter
428
+ let include;
429
+ if (query?.include) {
430
+ const { select, error, allIncludes } = this.buildRelationSelect(type, query.include);
431
+ if (error) {
432
+ return error;
469
433
  }
470
- else {
471
- args.take = limit;
472
- const [entities, count] = yield Promise.all([
473
- prisma[type].findMany(args),
474
- prisma[type].count({ where: args.where }),
475
- ]);
476
- const total = count;
477
- const url = this.makeNormalizedUrl(`/${type}`, query);
478
- const options = {
479
- include,
480
- linkers: {
481
- paginator: this.makePaginator(url, offset, limit, total),
482
- },
483
- };
484
- const body = yield this.serializeItems(type, entities, options);
485
- body.meta = this.addTotalCountToMeta(body.meta, total);
486
- return {
487
- status: 200,
488
- body: body,
489
- };
434
+ if (select) {
435
+ args.include = { ...args.include, ...select };
490
436
  }
491
- });
437
+ include = allIncludes;
438
+ }
439
+ const { offset, limit } = this.getPagination(query);
440
+ if (offset > 0) {
441
+ args.skip = offset;
442
+ }
443
+ if (limit === Infinity) {
444
+ const entities = await prisma[type].findMany(args);
445
+ const body = await this.serializeItems(type, entities, { include });
446
+ const total = entities.length;
447
+ body.meta = this.addTotalCountToMeta(body.meta, total);
448
+ return {
449
+ status: 200,
450
+ body: body,
451
+ };
452
+ }
453
+ else {
454
+ args.take = limit;
455
+ const [entities, count] = await Promise.all([
456
+ prisma[type].findMany(args),
457
+ prisma[type].count({ where: args.where }),
458
+ ]);
459
+ const total = count;
460
+ const url = this.makeNormalizedUrl(`/${type}`, query);
461
+ const options = {
462
+ include,
463
+ linkers: {
464
+ paginator: this.makePaginator(url, offset, limit, total),
465
+ },
466
+ };
467
+ const body = await this.serializeItems(type, entities, options);
468
+ body.meta = this.addTotalCountToMeta(body.meta, total);
469
+ return {
470
+ status: 200,
471
+ body: body,
472
+ };
473
+ }
492
474
  }
493
475
  addTotalCountToMeta(meta, total) {
494
476
  return meta ? Object.assign(meta, { total }) : Object.assign({}, { total });
@@ -518,9 +500,8 @@ class RequestHandler extends base_1.APIHandlerBase {
518
500
  }));
519
501
  }
520
502
  processRequestBody(type, requestBody, zodSchemas, mode) {
521
- var _a, _b;
522
503
  let body = requestBody;
523
- if ((_a = body.meta) === null || _a === void 0 ? void 0 : _a.serialization) {
504
+ if (body.meta?.serialization) {
524
505
  // superjson deserialize body if a serialization meta is provided
525
506
  body = superjson_1.default.deserialize({ json: body, meta: body.meta.serialization });
526
507
  }
@@ -529,7 +510,7 @@ class RequestHandler extends base_1.APIHandlerBase {
529
510
  if (attributes) {
530
511
  const schemaName = `${(0, upper_case_first_1.upperCaseFirst)(type)}${(0, upper_case_first_1.upperCaseFirst)(mode)}Schema`;
531
512
  // zod-parse attributes if a schema is provided
532
- const payloadSchema = (_b = zodSchemas === null || zodSchemas === void 0 ? void 0 : zodSchemas.models) === null || _b === void 0 ? void 0 : _b[schemaName];
513
+ const payloadSchema = zodSchemas?.models?.[schemaName];
533
514
  if (payloadSchema) {
534
515
  const parsed = payloadSchema.safeParse(attributes);
535
516
  if (!parsed.success) {
@@ -541,191 +522,189 @@ class RequestHandler extends base_1.APIHandlerBase {
541
522
  }
542
523
  return { attributes, relationships: parsed.data.relationships };
543
524
  }
544
- processCreate(prisma, type, _query, requestBody, zodSchemas) {
545
- return __awaiter(this, void 0, void 0, function* () {
546
- const typeInfo = this.typeMap[type];
547
- if (!typeInfo) {
548
- return this.makeUnsupportedModelError(type);
549
- }
550
- const { error, attributes, relationships } = this.processRequestBody(type, requestBody, zodSchemas, 'create');
551
- if (error) {
552
- return error;
553
- }
554
- const createPayload = { data: Object.assign({}, attributes) };
555
- // turn relationship payload into Prisma connect objects
556
- if (relationships) {
557
- for (const [key, data] of Object.entries(relationships)) {
558
- if (!(data === null || data === void 0 ? void 0 : data.data)) {
559
- return this.makeError('invalidRelationData');
560
- }
561
- const relationInfo = typeInfo.relationships[key];
562
- if (!relationInfo) {
563
- return this.makeUnsupportedRelationshipError(type, key, 400);
564
- }
565
- if (relationInfo.isCollection) {
566
- createPayload.data[key] = {
567
- connect: (0, runtime_1.enumerate)(data.data).map((item) => ({
568
- [relationInfo.idField]: this.coerce(relationInfo.idFieldType, item.id),
569
- })),
570
- };
571
- }
572
- else {
573
- if (typeof data.data !== 'object') {
574
- return this.makeError('invalidRelationData');
575
- }
576
- createPayload.data[key] = {
577
- connect: { [relationInfo.idField]: this.coerce(relationInfo.idFieldType, data.data.id) },
578
- };
579
- }
580
- // make sure ID fields are included for result serialization
581
- createPayload.include = Object.assign(Object.assign({}, createPayload.include), { [key]: { select: { [relationInfo.idField]: true } } });
525
+ async processCreate(prisma, type, _query, requestBody, zodSchemas) {
526
+ const typeInfo = this.typeMap[type];
527
+ if (!typeInfo) {
528
+ return this.makeUnsupportedModelError(type);
529
+ }
530
+ const { error, attributes, relationships } = this.processRequestBody(type, requestBody, zodSchemas, 'create');
531
+ if (error) {
532
+ return error;
533
+ }
534
+ const createPayload = { data: { ...attributes } };
535
+ // turn relationship payload into Prisma connect objects
536
+ if (relationships) {
537
+ for (const [key, data] of Object.entries(relationships)) {
538
+ if (!data?.data) {
539
+ return this.makeError('invalidRelationData');
582
540
  }
583
- }
584
- const entity = yield prisma[type].create(createPayload);
585
- return {
586
- status: 201,
587
- body: yield this.serializeItems(type, entity),
588
- };
589
- });
590
- }
591
- processRelationshipCRUD(prisma, mode, type, resourceId, relationship, query, requestBody) {
592
- return __awaiter(this, void 0, void 0, function* () {
593
- const typeInfo = this.typeMap[type];
594
- if (!typeInfo) {
595
- return this.makeUnsupportedModelError(type);
596
- }
597
- const relationInfo = typeInfo.relationships[relationship];
598
- if (!relationInfo) {
599
- return this.makeUnsupportedRelationshipError(type, relationship, 404);
600
- }
601
- if (!relationInfo.isCollection && mode !== 'update') {
602
- // to-one relation can only be updated
603
- return this.makeError('invalidVerb');
604
- }
605
- const updateArgs = {
606
- where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId),
607
- select: { [typeInfo.idField]: true, [relationship]: { select: { [relationInfo.idField]: true } } },
608
- };
609
- if (!relationInfo.isCollection) {
610
- // zod-parse payload
611
- const parsed = this.updateSingleRelationSchema.safeParse(requestBody);
612
- if (!parsed.success) {
613
- return this.makeError('invalidPayload', (0, zod_validation_error_1.fromZodError)(parsed.error).message, undefined, runtime_1.CrudFailureReason.DATA_VALIDATION_VIOLATION, parsed.error);
541
+ const relationInfo = typeInfo.relationships[key];
542
+ if (!relationInfo) {
543
+ return this.makeUnsupportedRelationshipError(type, key, 400);
614
544
  }
615
- if (parsed.data.data === null) {
616
- if (!relationInfo.isOptional) {
617
- // cannot disconnect a required relation
618
- return this.makeError('invalidPayload');
619
- }
620
- // set null -> disconnect
621
- updateArgs.data = {
622
- [relationship]: {
623
- disconnect: true,
624
- },
545
+ if (relationInfo.isCollection) {
546
+ createPayload.data[key] = {
547
+ connect: (0, runtime_1.enumerate)(data.data).map((item) => ({
548
+ [relationInfo.idField]: this.coerce(relationInfo.idFieldType, item.id),
549
+ })),
625
550
  };
626
551
  }
627
552
  else {
628
- updateArgs.data = {
629
- [relationship]: {
630
- connect: {
631
- [relationInfo.idField]: this.coerce(relationInfo.idFieldType, parsed.data.data.id),
632
- },
633
- },
553
+ if (typeof data.data !== 'object') {
554
+ return this.makeError('invalidRelationData');
555
+ }
556
+ createPayload.data[key] = {
557
+ connect: { [relationInfo.idField]: this.coerce(relationInfo.idFieldType, data.data.id) },
634
558
  };
635
559
  }
560
+ // make sure ID fields are included for result serialization
561
+ createPayload.include = {
562
+ ...createPayload.include,
563
+ [key]: { select: { [relationInfo.idField]: true } },
564
+ };
636
565
  }
637
- else {
638
- // zod-parse payload
639
- const parsed = this.updateCollectionRelationSchema.safeParse(requestBody);
640
- if (!parsed.success) {
641
- return this.makeError('invalidPayload', (0, zod_validation_error_1.fromZodError)(parsed.error).message, undefined, runtime_1.CrudFailureReason.DATA_VALIDATION_VIOLATION, parsed.error);
566
+ }
567
+ const entity = await prisma[type].create(createPayload);
568
+ return {
569
+ status: 201,
570
+ body: await this.serializeItems(type, entity),
571
+ };
572
+ }
573
+ async processRelationshipCRUD(prisma, mode, type, resourceId, relationship, query, requestBody) {
574
+ const typeInfo = this.typeMap[type];
575
+ if (!typeInfo) {
576
+ return this.makeUnsupportedModelError(type);
577
+ }
578
+ const relationInfo = typeInfo.relationships[relationship];
579
+ if (!relationInfo) {
580
+ return this.makeUnsupportedRelationshipError(type, relationship, 404);
581
+ }
582
+ if (!relationInfo.isCollection && mode !== 'update') {
583
+ // to-one relation can only be updated
584
+ return this.makeError('invalidVerb');
585
+ }
586
+ const updateArgs = {
587
+ where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId),
588
+ select: { [typeInfo.idField]: true, [relationship]: { select: { [relationInfo.idField]: true } } },
589
+ };
590
+ if (!relationInfo.isCollection) {
591
+ // zod-parse payload
592
+ const parsed = this.updateSingleRelationSchema.safeParse(requestBody);
593
+ if (!parsed.success) {
594
+ return this.makeError('invalidPayload', (0, zod_validation_error_1.fromZodError)(parsed.error).message, undefined, runtime_1.CrudFailureReason.DATA_VALIDATION_VIOLATION, parsed.error);
595
+ }
596
+ if (parsed.data.data === null) {
597
+ if (!relationInfo.isOptional) {
598
+ // cannot disconnect a required relation
599
+ return this.makeError('invalidPayload');
642
600
  }
643
- // create -> connect, delete -> disconnect, update -> set
644
- const relationVerb = mode === 'create' ? 'connect' : mode === 'delete' ? 'disconnect' : 'set';
601
+ // set null -> disconnect
645
602
  updateArgs.data = {
646
603
  [relationship]: {
647
- [relationVerb]: (0, runtime_1.enumerate)(parsed.data.data).map((item) => ({
648
- [relationInfo.idField]: this.coerce(relationInfo.idFieldType, item.id),
649
- })),
604
+ disconnect: true,
650
605
  },
651
606
  };
652
607
  }
653
- const entity = yield prisma[type].update(updateArgs);
654
- const serialized = yield this.serializeItems(relationInfo.type, entity[relationship], {
655
- linkers: {
656
- document: new ts_japi_1.Linker(() => this.makeLinkUrl(`/${type}/${resourceId}/relationships/${relationship}`)),
608
+ else {
609
+ updateArgs.data = {
610
+ [relationship]: {
611
+ connect: {
612
+ [relationInfo.idField]: this.coerce(relationInfo.idFieldType, parsed.data.data.id),
613
+ },
614
+ },
615
+ };
616
+ }
617
+ }
618
+ else {
619
+ // zod-parse payload
620
+ const parsed = this.updateCollectionRelationSchema.safeParse(requestBody);
621
+ if (!parsed.success) {
622
+ return this.makeError('invalidPayload', (0, zod_validation_error_1.fromZodError)(parsed.error).message, undefined, runtime_1.CrudFailureReason.DATA_VALIDATION_VIOLATION, parsed.error);
623
+ }
624
+ // create -> connect, delete -> disconnect, update -> set
625
+ const relationVerb = mode === 'create' ? 'connect' : mode === 'delete' ? 'disconnect' : 'set';
626
+ updateArgs.data = {
627
+ [relationship]: {
628
+ [relationVerb]: (0, runtime_1.enumerate)(parsed.data.data).map((item) => ({
629
+ [relationInfo.idField]: this.coerce(relationInfo.idFieldType, item.id),
630
+ })),
657
631
  },
658
- onlyIdentifier: true,
659
- });
660
- return {
661
- status: 200,
662
- body: serialized,
663
632
  };
633
+ }
634
+ const entity = await prisma[type].update(updateArgs);
635
+ const serialized = await this.serializeItems(relationInfo.type, entity[relationship], {
636
+ linkers: {
637
+ document: new ts_japi_1.Linker(() => this.makeLinkUrl(`/${type}/${resourceId}/relationships/${relationship}`)),
638
+ },
639
+ onlyIdentifier: true,
664
640
  });
641
+ return {
642
+ status: 200,
643
+ body: serialized,
644
+ };
665
645
  }
666
- processUpdate(prisma, type, resourceId, _query, requestBody, zodSchemas) {
667
- return __awaiter(this, void 0, void 0, function* () {
668
- const typeInfo = this.typeMap[type];
669
- if (!typeInfo) {
670
- return this.makeUnsupportedModelError(type);
671
- }
672
- const { error, attributes, relationships } = this.processRequestBody(type, requestBody, zodSchemas, 'update');
673
- if (error) {
674
- return error;
675
- }
676
- const updatePayload = {
677
- where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId),
678
- data: Object.assign({}, attributes),
679
- };
680
- // turn relationships into prisma payload
681
- if (relationships) {
682
- for (const [key, data] of Object.entries(relationships)) {
683
- if (!(data === null || data === void 0 ? void 0 : data.data)) {
646
+ async processUpdate(prisma, type, resourceId, _query, requestBody, zodSchemas) {
647
+ const typeInfo = this.typeMap[type];
648
+ if (!typeInfo) {
649
+ return this.makeUnsupportedModelError(type);
650
+ }
651
+ const { error, attributes, relationships } = this.processRequestBody(type, requestBody, zodSchemas, 'update');
652
+ if (error) {
653
+ return error;
654
+ }
655
+ const updatePayload = {
656
+ where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId),
657
+ data: { ...attributes },
658
+ };
659
+ // turn relationships into prisma payload
660
+ if (relationships) {
661
+ for (const [key, data] of Object.entries(relationships)) {
662
+ if (!data?.data) {
663
+ return this.makeError('invalidRelationData');
664
+ }
665
+ const relationInfo = typeInfo.relationships[key];
666
+ if (!relationInfo) {
667
+ return this.makeUnsupportedRelationshipError(type, key, 400);
668
+ }
669
+ if (relationInfo.isCollection) {
670
+ updatePayload.data[key] = {
671
+ set: (0, runtime_1.enumerate)(data.data).map((item) => ({
672
+ [relationInfo.idField]: this.coerce(relationInfo.idFieldType, item.id),
673
+ })),
674
+ };
675
+ }
676
+ else {
677
+ if (typeof data.data !== 'object') {
684
678
  return this.makeError('invalidRelationData');
685
679
  }
686
- const relationInfo = typeInfo.relationships[key];
687
- if (!relationInfo) {
688
- return this.makeUnsupportedRelationshipError(type, key, 400);
689
- }
690
- if (relationInfo.isCollection) {
691
- updatePayload.data[key] = {
692
- set: (0, runtime_1.enumerate)(data.data).map((item) => ({
693
- [relationInfo.idField]: this.coerce(relationInfo.idFieldType, item.id),
694
- })),
695
- };
696
- }
697
- else {
698
- if (typeof data.data !== 'object') {
699
- return this.makeError('invalidRelationData');
700
- }
701
- updatePayload.data[key] = {
702
- set: { [relationInfo.idField]: this.coerce(relationInfo.idFieldType, data.data.id) },
703
- };
704
- }
705
- updatePayload.include = Object.assign(Object.assign({}, updatePayload.include), { [key]: { select: { [relationInfo.idField]: true } } });
680
+ updatePayload.data[key] = {
681
+ set: { [relationInfo.idField]: this.coerce(relationInfo.idFieldType, data.data.id) },
682
+ };
706
683
  }
684
+ updatePayload.include = {
685
+ ...updatePayload.include,
686
+ [key]: { select: { [relationInfo.idField]: true } },
687
+ };
707
688
  }
708
- const entity = yield prisma[type].update(updatePayload);
709
- return {
710
- status: 200,
711
- body: yield this.serializeItems(type, entity),
712
- };
713
- });
689
+ }
690
+ const entity = await prisma[type].update(updatePayload);
691
+ return {
692
+ status: 200,
693
+ body: await this.serializeItems(type, entity),
694
+ };
714
695
  }
715
- processDelete(prisma, type, resourceId) {
716
- return __awaiter(this, void 0, void 0, function* () {
717
- const typeInfo = this.typeMap[type];
718
- if (!typeInfo) {
719
- return this.makeUnsupportedModelError(type);
720
- }
721
- yield prisma[type].delete({
722
- where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId),
723
- });
724
- return {
725
- status: 204,
726
- body: undefined,
727
- };
696
+ async processDelete(prisma, type, resourceId) {
697
+ const typeInfo = this.typeMap[type];
698
+ if (!typeInfo) {
699
+ return this.makeUnsupportedModelError(type);
700
+ }
701
+ await prisma[type].delete({
702
+ where: this.makeIdFilter(typeInfo.idField, typeInfo.idFieldType, resourceId),
728
703
  });
704
+ return {
705
+ status: 204,
706
+ body: undefined,
707
+ };
729
708
  }
730
709
  //#region utilities
731
710
  buildTypeMap(logger, modelMeta) {
@@ -821,9 +800,9 @@ class RequestHandler extends base_1.APIHandlerBase {
821
800
  }
822
801
  const fieldIds = (0, runtime_1.getIdFields)(modelMeta, fieldMeta.type);
823
802
  if (fieldIds.length === 1) {
824
- const relator = new ts_japi_1.Relator((data) => __awaiter(this, void 0, void 0, function* () {
803
+ const relator = new ts_japi_1.Relator(async (data) => {
825
804
  return data[field];
826
- }), fieldSerializer, {
805
+ }, fieldSerializer, {
827
806
  relatedName: field,
828
807
  linkers: {
829
808
  related: new ts_japi_1.Linker((primary) => this.makeLinkUrl(`/${(0, lower_case_first_1.lowerCaseFirst)(model)}/${this.getId(model, primary, modelMeta)}/${field}`)),
@@ -848,25 +827,23 @@ class RequestHandler extends base_1.APIHandlerBase {
848
827
  return undefined;
849
828
  }
850
829
  }
851
- serializeItems(model, items, options) {
852
- return __awaiter(this, void 0, void 0, function* () {
853
- model = (0, lower_case_first_1.lowerCaseFirst)(model);
854
- const serializer = this.serializers.get(model);
855
- if (!serializer) {
856
- throw new Error(`serializer not found for model ${model}`);
857
- }
858
- // serialize to JSON:API structure
859
- const serialized = yield serializer.serialize(items, options);
860
- // convert the serialization result to plain object otherwise SuperJSON won't work
861
- const plainResult = this.toPlainObject(serialized);
862
- // superjson serialize the result
863
- const { json, meta } = superjson_1.default.serialize(plainResult);
864
- const result = json;
865
- if (meta) {
866
- result.meta = Object.assign(Object.assign({}, result.meta), { serialization: meta });
867
- }
868
- return result;
869
- });
830
+ async serializeItems(model, items, options) {
831
+ model = (0, lower_case_first_1.lowerCaseFirst)(model);
832
+ const serializer = this.serializers.get(model);
833
+ if (!serializer) {
834
+ throw new Error(`serializer not found for model ${model}`);
835
+ }
836
+ // serialize to JSON:API structure
837
+ const serialized = await serializer.serialize(items, options);
838
+ // convert the serialization result to plain object otherwise SuperJSON won't work
839
+ const plainResult = this.toPlainObject(serialized);
840
+ // superjson serialize the result
841
+ const { json, meta } = superjson_1.default.serialize(plainResult);
842
+ const result = json;
843
+ if (meta) {
844
+ result.meta = { ...result.meta, serialization: meta };
845
+ }
846
+ return result;
870
847
  }
871
848
  toPlainObject(data) {
872
849
  if (data === undefined || data === null) {
@@ -924,7 +901,7 @@ class RequestHandler extends base_1.APIHandlerBase {
924
901
  return;
925
902
  }
926
903
  for (const [relation, relationInfo] of Object.entries(typeInfo.relationships)) {
927
- args[mode] = Object.assign(Object.assign({}, args[mode]), { [relation]: { select: { [relationInfo.idField]: true } } });
904
+ args[mode] = { ...args[mode], [relation]: { select: { [relationInfo.idField]: true } } };
928
905
  }
929
906
  }
930
907
  coerce(type, value) {
@@ -959,7 +936,7 @@ class RequestHandler extends base_1.APIHandlerBase {
959
936
  }
960
937
  makeNormalizedUrl(path, query) {
961
938
  const url = new URL(this.makeLinkUrl(path));
962
- for (const [key, value] of Object.entries(query !== null && query !== void 0 ? query : {})) {
939
+ for (const [key, value] of Object.entries(query ?? {})) {
963
940
  if (key.startsWith('filter[') ||
964
941
  key.startsWith('sort[') ||
965
942
  key.startsWith('include[') ||
@@ -972,9 +949,8 @@ class RequestHandler extends base_1.APIHandlerBase {
972
949
  return url.toString();
973
950
  }
974
951
  getPagination(query) {
975
- var _a, _b;
976
952
  if (!query) {
977
- return { offset: 0, limit: (_a = this.options.pageSize) !== null && _a !== void 0 ? _a : DEFAULT_PAGE_SIZE };
953
+ return { offset: 0, limit: this.options.pageSize ?? DEFAULT_PAGE_SIZE };
978
954
  }
979
955
  let offset = 0;
980
956
  if (query['page[offset]']) {
@@ -985,7 +961,7 @@ class RequestHandler extends base_1.APIHandlerBase {
985
961
  offset = 0;
986
962
  }
987
963
  }
988
- let pageSizeOption = (_b = this.options.pageSize) !== null && _b !== void 0 ? _b : DEFAULT_PAGE_SIZE;
964
+ let pageSizeOption = this.options.pageSize ?? DEFAULT_PAGE_SIZE;
989
965
  if (pageSizeOption <= 0) {
990
966
  pageSizeOption = DEFAULT_PAGE_SIZE;
991
967
  }
@@ -1091,7 +1067,7 @@ class RequestHandler extends base_1.APIHandlerBase {
1091
1067
  }
1092
1068
  }
1093
1069
  buildSort(type, query) {
1094
- if (!(query === null || query === void 0 ? void 0 : query['sort'])) {
1070
+ if (!query?.['sort']) {
1095
1071
  return { sort: undefined, error: undefined };
1096
1072
  }
1097
1073
  const typeInfo = this.typeMap[(0, lower_case_first_1.lowerCaseFirst)(type)];
@@ -1153,7 +1129,6 @@ class RequestHandler extends base_1.APIHandlerBase {
1153
1129
  return { sort: result, error: undefined };
1154
1130
  }
1155
1131
  buildRelationSelect(type, include) {
1156
- var _a;
1157
1132
  const typeInfo = this.typeMap[(0, lower_case_first_1.lowerCaseFirst)(type)];
1158
1133
  if (!typeInfo) {
1159
1134
  return { select: undefined, error: this.makeUnsupportedModelError(type) };
@@ -1178,7 +1153,7 @@ class RequestHandler extends base_1.APIHandlerBase {
1178
1153
  return { select: undefined, error: this.makeUnsupportedModelError(relationInfo.type) };
1179
1154
  }
1180
1155
  if (i !== parts.length - 1) {
1181
- currPayload[relation] = { include: Object.assign({}, (_a = currPayload[relation]) === null || _a === void 0 ? void 0 : _a.include) };
1156
+ currPayload[relation] = { include: { ...currPayload[relation]?.include } };
1182
1157
  currPayload = currPayload[relation].include;
1183
1158
  }
1184
1159
  else {
@@ -1234,38 +1209,37 @@ class RequestHandler extends base_1.APIHandlerBase {
1234
1209
  return filterError;
1235
1210
  }
1236
1211
  if (filter) {
1237
- injectTarget[injectKey] = Object.assign(Object.assign({}, injectTarget[injectKey]), { where: filter });
1212
+ injectTarget[injectKey] = { ...injectTarget[injectKey], where: filter };
1238
1213
  }
1239
1214
  const { sort, error: sortError } = this.buildSort(type, query);
1240
1215
  if (sortError) {
1241
1216
  return sortError;
1242
1217
  }
1243
1218
  if (sort) {
1244
- injectTarget[injectKey] = Object.assign(Object.assign({}, injectTarget[injectKey]), { orderBy: sort });
1219
+ injectTarget[injectKey] = { ...injectTarget[injectKey], orderBy: sort };
1245
1220
  }
1246
1221
  const pagination = this.getPagination(query);
1247
1222
  const offset = pagination.offset;
1248
1223
  if (offset > 0) {
1249
1224
  // inject skip
1250
- injectTarget[injectKey] = Object.assign(Object.assign({}, injectTarget[injectKey]), { skip: offset });
1225
+ injectTarget[injectKey] = { ...injectTarget[injectKey], skip: offset };
1251
1226
  }
1252
1227
  const limit = pagination.limit;
1253
1228
  if (limit !== Infinity) {
1254
1229
  // inject take
1255
- injectTarget[injectKey] = Object.assign(Object.assign({}, injectTarget[injectKey]), { take: limit });
1230
+ injectTarget[injectKey] = { ...injectTarget[injectKey], take: limit };
1256
1231
  // include a count query for the relationship
1257
1232
  injectTarget._count = { select: { [injectKey]: true } };
1258
1233
  }
1259
1234
  }
1260
1235
  handlePrismaError(err) {
1261
- var _a, _b, _c, _d;
1262
1236
  if ((0, runtime_1.isPrismaClientKnownRequestError)(err)) {
1263
1237
  if (err.code === runtime_1.PrismaErrorCode.CONSTRAINED_FAILED) {
1264
- if (((_a = err.meta) === null || _a === void 0 ? void 0 : _a.reason) === runtime_1.CrudFailureReason.DATA_VALIDATION_VIOLATION) {
1265
- return this.makeError('validationError', undefined, 422, (_b = err.meta) === null || _b === void 0 ? void 0 : _b.reason, (_c = err.meta) === null || _c === void 0 ? void 0 : _c.zodErrors);
1238
+ if (err.meta?.reason === runtime_1.CrudFailureReason.DATA_VALIDATION_VIOLATION) {
1239
+ return this.makeError('validationError', undefined, 422, err.meta?.reason, err.meta?.zodErrors);
1266
1240
  }
1267
1241
  else {
1268
- return this.makeError('forbidden', undefined, 403, (_d = err.meta) === null || _d === void 0 ? void 0 : _d.reason);
1242
+ return this.makeError('forbidden', undefined, 403, err.meta?.reason);
1269
1243
  }
1270
1244
  }
1271
1245
  else if (err.code === 'P2025' || err.code === 'P2018') {
@@ -1295,7 +1269,7 @@ class RequestHandler extends base_1.APIHandlerBase {
1295
1269
  }
1296
1270
  makeError(code, detail, status, reason, zodErrors) {
1297
1271
  const error = {
1298
- status: status !== null && status !== void 0 ? status : this.errors[code].status,
1272
+ status: status ?? this.errors[code].status,
1299
1273
  code: (0, change_case_1.paramCase)(code),
1300
1274
  title: this.errors[code].title,
1301
1275
  };
@@ -1309,7 +1283,7 @@ class RequestHandler extends base_1.APIHandlerBase {
1309
1283
  error.zodErrors = zodErrors;
1310
1284
  }
1311
1285
  return {
1312
- status: status !== null && status !== void 0 ? status : this.errors[code].status,
1286
+ status: status ?? this.errors[code].status,
1313
1287
  body: {
1314
1288
  errors: [error],
1315
1289
  },
@@ -1326,6 +1300,4 @@ function makeHandler(options) {
1326
1300
  const handler = new RequestHandler(options);
1327
1301
  return handler.handleRequest.bind(handler);
1328
1302
  }
1329
- exports.default = makeHandler;
1330
- exports.RestApiHandler = makeHandler;
1331
1303
  //# sourceMappingURL=index.js.map