@webiny/api-headless-cms 0.0.0-unstable.b02d94bba0 → 0.0.0-unstable.b14eaecf38

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.
Files changed (94) hide show
  1. package/context.js +47 -43
  2. package/context.js.map +1 -1
  3. package/crud/contentEntry.crud.d.ts +3 -1
  4. package/crud/contentEntry.crud.js +829 -817
  5. package/crud/contentEntry.crud.js.map +1 -1
  6. package/crud/contentModel/beforeCreate.js +38 -79
  7. package/crud/contentModel/beforeCreate.js.map +1 -1
  8. package/crud/contentModel/beforeDelete.d.ts +1 -1
  9. package/crud/contentModel/beforeDelete.js +1 -5
  10. package/crud/contentModel/beforeDelete.js.map +1 -1
  11. package/crud/contentModel/beforeUpdate.js +30 -6
  12. package/crud/contentModel/beforeUpdate.js.map +1 -1
  13. package/crud/contentModel/validate/endingAllowed.d.ts +6 -0
  14. package/crud/contentModel/validate/endingAllowed.js +26 -0
  15. package/crud/contentModel/validate/endingAllowed.js.map +1 -0
  16. package/crud/contentModel/validate/isModelEndingAllowed.d.ts +6 -0
  17. package/crud/contentModel/validate/isModelEndingAllowed.js +24 -0
  18. package/crud/contentModel/validate/isModelEndingAllowed.js.map +1 -0
  19. package/crud/contentModel/validate/modelId.d.ts +11 -0
  20. package/crud/contentModel/validate/modelId.js +36 -0
  21. package/crud/contentModel/validate/modelId.js.map +1 -0
  22. package/crud/contentModel/validate/pluralApiName.d.ts +7 -0
  23. package/crud/contentModel/validate/pluralApiName.js +24 -0
  24. package/crud/contentModel/validate/pluralApiName.js.map +1 -0
  25. package/crud/contentModel/validate/singularApiName.d.ts +7 -0
  26. package/crud/contentModel/validate/singularApiName.js +24 -0
  27. package/crud/contentModel/validate/singularApiName.js.map +1 -0
  28. package/crud/contentModel/validateModelFields.js +6 -7
  29. package/crud/contentModel/validateModelFields.js.map +1 -1
  30. package/crud/contentModel/validation.d.ts +48 -16
  31. package/crud/contentModel/validation.js +2 -2
  32. package/crud/contentModel/validation.js.map +1 -1
  33. package/crud/contentModel.crud.js +334 -295
  34. package/crud/contentModel.crud.js.map +1 -1
  35. package/crud/contentModelGroup.crud.js +170 -142
  36. package/crud/contentModelGroup.crud.js.map +1 -1
  37. package/crud/settings.crud.d.ts +1 -1
  38. package/crud/settings.crud.js +5 -10
  39. package/crud/settings.crud.js.map +1 -1
  40. package/graphql/checkEndpointAccess.d.ts +2 -0
  41. package/graphql/checkEndpointAccess.js +18 -0
  42. package/graphql/checkEndpointAccess.js.map +1 -0
  43. package/graphql/createExecutableSchema.d.ts +2 -3
  44. package/graphql/createExecutableSchema.js.map +1 -1
  45. package/graphql/createRequestBody.d.ts +2 -0
  46. package/graphql/createRequestBody.js +14 -0
  47. package/graphql/createRequestBody.js.map +1 -0
  48. package/graphql/formatErrorPayload.d.ts +1 -0
  49. package/graphql/formatErrorPayload.js +25 -0
  50. package/graphql/formatErrorPayload.js.map +1 -0
  51. package/graphql/generateSchema.js.map +1 -1
  52. package/graphql/getSchema.d.ts +17 -0
  53. package/graphql/getSchema.js +102 -0
  54. package/graphql/getSchema.js.map +1 -0
  55. package/graphql/graphQLHandlerFactory.js +6 -150
  56. package/graphql/graphQLHandlerFactory.js.map +1 -1
  57. package/graphql/handleRequest.d.ts +11 -0
  58. package/graphql/handleRequest.js +81 -0
  59. package/graphql/handleRequest.js.map +1 -0
  60. package/graphql/schema/contentModelGroups.js +6 -6
  61. package/graphql/schema/contentModelGroups.js.map +1 -1
  62. package/graphql/schema/contentModels.js +3 -3
  63. package/graphql/schema/contentModels.js.map +1 -1
  64. package/graphqlFields/dynamicZone/dynamicZoneField.d.ts +1 -1
  65. package/graphqlFields/dynamicZone/dynamicZoneField.js +13 -1
  66. package/graphqlFields/dynamicZone/dynamicZoneField.js.map +1 -1
  67. package/graphqlFields/ref.js +7 -7
  68. package/graphqlFields/ref.js.map +1 -1
  69. package/index.d.ts +2 -0
  70. package/index.js +24 -0
  71. package/index.js.map +1 -1
  72. package/package.json +22 -22
  73. package/plugins/CmsModelPlugin.d.ts +13 -7
  74. package/plugins/CmsModelPlugin.js +21 -6
  75. package/plugins/CmsModelPlugin.js.map +1 -1
  76. package/plugins/StorageOperationsCmsModelPlugin.d.ts +23 -0
  77. package/plugins/StorageOperationsCmsModelPlugin.js +42 -0
  78. package/plugins/StorageOperationsCmsModelPlugin.js.map +1 -0
  79. package/plugins/index.d.ts +1 -0
  80. package/plugins/index.js +11 -0
  81. package/plugins/index.js.map +1 -1
  82. package/types.d.ts +46 -47
  83. package/types.js.map +1 -1
  84. package/utils/converters/valueKeyStorageConverter.d.ts +1 -5
  85. package/utils/converters/valueKeyStorageConverter.js +19 -17
  86. package/utils/converters/valueKeyStorageConverter.js.map +1 -1
  87. package/utils/createTypeFromFields.js +1 -2
  88. package/utils/createTypeFromFields.js.map +1 -1
  89. package/utils/createTypeName.d.ts +0 -2
  90. package/utils/createTypeName.js +2 -10
  91. package/utils/createTypeName.js.map +1 -1
  92. package/utils/incrementEntryIdVersion.d.ts +5 -0
  93. package/utils/incrementEntryIdVersion.js +29 -0
  94. package/utils/incrementEntryIdVersion.js.map +1 -0
@@ -140,21 +140,25 @@ const createModelsCrud = params => {
140
140
  return databaseModels.concat(pluginsModels);
141
141
  };
142
142
  const listModels = async () => {
143
- const permission = await checkModelPermissions("r");
144
- const models = await modelsList();
145
- return (0, _filterAsync.filterAsync)(models, async model => {
146
- if (!(0, _ownership.validateOwnership)(context, permission, model)) {
147
- return false;
148
- }
149
- return (0, _access.validateModelAccess)(context, model);
143
+ return context.benchmark.measure("headlessCms.crud.models.listModels", async () => {
144
+ const permission = await checkModelPermissions("r");
145
+ const models = await modelsList();
146
+ return (0, _filterAsync.filterAsync)(models, async model => {
147
+ if (!(0, _ownership.validateOwnership)(context, permission, model)) {
148
+ return false;
149
+ }
150
+ return (0, _access.validateModelAccess)(context, model);
151
+ });
150
152
  });
151
153
  };
152
154
  const getModel = async modelId => {
153
- const permission = await checkModelPermissions("r");
154
- const model = await modelsGet(modelId);
155
- (0, _ownership.checkOwnership)(context, permission, model);
156
- await (0, _access.checkModelAccess)(context, model);
157
- return model;
155
+ return context.benchmark.measure("headlessCms.crud.models.getModel", async () => {
156
+ const permission = await checkModelPermissions("r");
157
+ const model = await modelsGet(modelId);
158
+ (0, _ownership.checkOwnership)(context, permission, model);
159
+ await (0, _access.checkModelAccess)(context, model);
160
+ return model;
161
+ });
158
162
  };
159
163
  const getModelManager = async target => {
160
164
  const modelId = typeof target === "string" ? target : target.modelId;
@@ -231,6 +235,311 @@ const createModelsCrud = params => {
231
235
  context,
232
236
  onModelAfterDelete
233
237
  });
238
+
239
+ /**
240
+ * CRUD methods
241
+ */
242
+ const createModel = async input => {
243
+ await checkModelPermissions("w");
244
+ const result = await (0, _validation.createModelCreateValidation)().safeParseAsync(input);
245
+ if (!result.success) {
246
+ throw (0, _utils.createZodError)(result.error);
247
+ }
248
+ /**
249
+ * We need to extract the defaultFields because it is not for the CmsModel object.
250
+ */
251
+ const _removeUndefinedValue = (0, _utils.removeUndefinedValues)(result.data),
252
+ {
253
+ defaultFields
254
+ } = _removeUndefinedValue,
255
+ data = (0, _objectWithoutProperties2.default)(_removeUndefinedValue, _excluded);
256
+ if (defaultFields) {
257
+ (0, _defaultFields.assignModelDefaultFields)(data);
258
+ }
259
+ const group = await context.security.withoutAuthorization(async () => {
260
+ return context.cms.getGroup(data.group);
261
+ });
262
+ if (!group) {
263
+ throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
264
+ }
265
+ const identity = getIdentity();
266
+ const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, data), {}, {
267
+ modelId: data.modelId || "",
268
+ singularApiName: data.singularApiName,
269
+ pluralApiName: data.pluralApiName,
270
+ titleFieldId: "id",
271
+ descriptionFieldId: null,
272
+ imageFieldId: null,
273
+ description: data.description || "",
274
+ locale: getLocale().code,
275
+ tenant: getTenant().id,
276
+ group: {
277
+ id: group.id,
278
+ name: group.name
279
+ },
280
+ createdBy: {
281
+ id: identity.id,
282
+ displayName: identity.displayName,
283
+ type: identity.type
284
+ },
285
+ createdOn: new Date().toISOString(),
286
+ savedOn: new Date().toISOString(),
287
+ lockedFields: [],
288
+ webinyVersion: context.WEBINY_VERSION
289
+ });
290
+ model.tags = ensureTypeTag(model);
291
+ try {
292
+ await onModelBeforeCreate.publish({
293
+ input: data,
294
+ model
295
+ });
296
+ const createdModel = await storageOperations.models.create({
297
+ model
298
+ });
299
+ loaders.listModels.clearAll();
300
+ await updateManager(context, model);
301
+ await onModelAfterCreate.publish({
302
+ input: data,
303
+ model: createdModel
304
+ });
305
+ return createdModel;
306
+ } catch (ex) {
307
+ await onModelCreateError.publish({
308
+ input: data,
309
+ model,
310
+ error: ex
311
+ });
312
+ throw ex;
313
+ }
314
+ };
315
+ const updateModel = async (modelId, input) => {
316
+ await checkModelPermissions("w");
317
+
318
+ // Get a model record; this will also perform ownership validation.
319
+ const original = await getModel(modelId);
320
+ const result = await (0, _validation.createModelUpdateValidation)().safeParseAsync(input);
321
+ if (!result.success) {
322
+ throw (0, _utils.createZodError)(result.error);
323
+ }
324
+ const data = (0, _utils.removeUndefinedValues)(result.data);
325
+ if (Object.keys(data).length === 0) {
326
+ /**
327
+ * We need to return the original if nothing is to be updated.
328
+ */
329
+ return original;
330
+ }
331
+ let group = {
332
+ id: original.group.id,
333
+ name: original.group.name
334
+ };
335
+ const groupId = data.group;
336
+ if (groupId) {
337
+ const groupData = await context.security.withoutAuthorization(async () => {
338
+ return context.cms.getGroup(groupId);
339
+ });
340
+ if (!groupData) {
341
+ throw new _handlerGraphql.NotFoundError(`There is no group "${groupId}".`);
342
+ }
343
+ group = {
344
+ id: groupData.id,
345
+ name: groupData.name
346
+ };
347
+ }
348
+ const model = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, original), data), {}, {
349
+ titleFieldId: data.titleFieldId === undefined ? original.titleFieldId : data.titleFieldId,
350
+ descriptionFieldId: data.descriptionFieldId === undefined ? original.descriptionFieldId : data.descriptionFieldId,
351
+ imageFieldId: data.imageFieldId === undefined ? original.imageFieldId : data.imageFieldId,
352
+ group,
353
+ description: data.description || original.description,
354
+ tenant: original.tenant || getTenant().id,
355
+ locale: original.locale || getLocale().code,
356
+ webinyVersion: context.WEBINY_VERSION,
357
+ savedOn: new Date().toISOString()
358
+ });
359
+ model.tags = ensureTypeTag(model);
360
+ try {
361
+ await onModelBeforeUpdate.publish({
362
+ input: data,
363
+ original,
364
+ model
365
+ });
366
+ const resultModel = await storageOperations.models.update({
367
+ model
368
+ });
369
+ await updateManager(context, resultModel);
370
+ await onModelAfterUpdate.publish({
371
+ input: data,
372
+ original,
373
+ model: resultModel
374
+ });
375
+ return resultModel;
376
+ } catch (ex) {
377
+ await onModelUpdateError.publish({
378
+ input: data,
379
+ model,
380
+ original,
381
+ error: ex
382
+ });
383
+ throw ex;
384
+ }
385
+ };
386
+ const updateModelDirect = async params => {
387
+ const {
388
+ model: initialModel,
389
+ original
390
+ } = params;
391
+ const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, initialModel), {}, {
392
+ tenant: initialModel.tenant || getTenant().id,
393
+ locale: initialModel.locale || getLocale().code,
394
+ webinyVersion: context.WEBINY_VERSION
395
+ });
396
+ try {
397
+ await onModelBeforeUpdate.publish({
398
+ input: {},
399
+ original,
400
+ model
401
+ });
402
+ const resultModel = await storageOperations.models.update({
403
+ model
404
+ });
405
+ await updateManager(context, resultModel);
406
+ loaders.listModels.clearAll();
407
+ await onModelAfterUpdate.publish({
408
+ input: {},
409
+ original,
410
+ model: resultModel
411
+ });
412
+ return resultModel;
413
+ } catch (ex) {
414
+ await onModelUpdateError.publish({
415
+ input: {},
416
+ original,
417
+ model,
418
+ error: ex
419
+ });
420
+ throw ex;
421
+ }
422
+ };
423
+ const createModelFrom = async (modelId, input) => {
424
+ await checkModelPermissions("w");
425
+ /**
426
+ * Get a model record; this will also perform ownership validation.
427
+ */
428
+ const original = await getModel(modelId);
429
+ const result = await (0, _validation.createModelCreateFromValidation)().safeParseAsync((0, _objectSpread2.default)((0, _objectSpread2.default)({}, input), {}, {
430
+ description: input.description || original.description
431
+ }));
432
+ if (!result.success) {
433
+ throw (0, _utils.createZodError)(result.error);
434
+ }
435
+ const data = (0, _utils.removeUndefinedValues)(result.data);
436
+ const locale = await context.i18n.getLocale(data.locale || original.locale);
437
+ if (!locale) {
438
+ throw new _handlerGraphql.NotFoundError(`There is no locale "${data.locale}".`);
439
+ }
440
+ /**
441
+ * Use storage operations directly because we cannot get group from different locale via context methods.
442
+ */
443
+ const group = await context.cms.storageOperations.groups.get({
444
+ id: data.group,
445
+ tenant: original.tenant,
446
+ locale: locale.code
447
+ });
448
+ if (!group) {
449
+ throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
450
+ }
451
+ const identity = getIdentity();
452
+ const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, original), {}, {
453
+ singularApiName: data.singularApiName,
454
+ pluralApiName: data.pluralApiName,
455
+ locale: locale.code,
456
+ group: {
457
+ id: group.id,
458
+ name: group.name
459
+ },
460
+ icon: data.icon,
461
+ name: data.name,
462
+ modelId: data.modelId || "",
463
+ description: data.description || "",
464
+ createdBy: {
465
+ id: identity.id,
466
+ displayName: identity.displayName,
467
+ type: identity.type
468
+ },
469
+ createdOn: new Date().toISOString(),
470
+ savedOn: new Date().toISOString(),
471
+ lockedFields: [],
472
+ webinyVersion: context.WEBINY_VERSION
473
+ });
474
+ try {
475
+ await onModelBeforeCreateFrom.publish({
476
+ input: data,
477
+ model,
478
+ original
479
+ });
480
+ const createdModel = await storageOperations.models.create({
481
+ model
482
+ });
483
+ loaders.listModels.clearAll();
484
+ await updateManager(context, model);
485
+ await onModelAfterCreateFrom.publish({
486
+ input: data,
487
+ original,
488
+ model: createdModel
489
+ });
490
+ return createdModel;
491
+ } catch (ex) {
492
+ await onModelCreateFromError.publish({
493
+ input: data,
494
+ original,
495
+ model,
496
+ error: ex
497
+ });
498
+ throw ex;
499
+ }
500
+ };
501
+ const deleteModel = async modelId => {
502
+ await checkModelPermissions("d");
503
+ const model = await getModel(modelId);
504
+ try {
505
+ await onModelBeforeDelete.publish({
506
+ model
507
+ });
508
+ try {
509
+ await storageOperations.models.delete({
510
+ model
511
+ });
512
+ } catch (ex) {
513
+ throw new _error.default(ex.message || "Could not delete the content model", ex.code || "CONTENT_MODEL_DELETE_ERROR", {
514
+ error: ex,
515
+ modelId: model.modelId
516
+ });
517
+ }
518
+ await onModelAfterDelete.publish({
519
+ model
520
+ });
521
+ managers.delete(model.modelId);
522
+ } catch (ex) {
523
+ await onModelDeleteError.publish({
524
+ model,
525
+ error: ex
526
+ });
527
+ throw ex;
528
+ }
529
+ };
530
+ const initializeModel = async (modelId, data) => {
531
+ /**
532
+ * We require that users have write permissions to initialize models.
533
+ * Maybe introduce another permission for it?
534
+ */
535
+ await checkModelPermissions("w");
536
+ const model = await getModel(modelId);
537
+ await onModelInitialize.publish({
538
+ model,
539
+ data
540
+ });
541
+ return true;
542
+ };
234
543
  return {
235
544
  /**
236
545
  * Deprecated - will be removed in 5.36.0
@@ -263,308 +572,38 @@ const createModelsCrud = params => {
263
572
  getModel,
264
573
  listModels,
265
574
  async createModel(input) {
266
- await checkModelPermissions("w");
267
- const result = await (0, _validation.createModelCreateValidation)().safeParseAsync(input);
268
- if (!result.success) {
269
- throw (0, _utils.createZodError)(result.error);
270
- }
271
- /**
272
- * We need to extract the defaultFields because it is not for the CmsModel object.
273
- */
274
- const _removeUndefinedValue = (0, _utils.removeUndefinedValues)(result.data),
275
- {
276
- defaultFields
277
- } = _removeUndefinedValue,
278
- data = (0, _objectWithoutProperties2.default)(_removeUndefinedValue, _excluded);
279
- if (defaultFields) {
280
- (0, _defaultFields.assignModelDefaultFields)(data);
281
- }
282
- context.security.disableAuthorization();
283
- const group = await context.cms.getGroup(data.group);
284
- context.security.enableAuthorization();
285
- if (!group) {
286
- throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
287
- }
288
- const identity = getIdentity();
289
- const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, data), {}, {
290
- modelId: data.modelId || "",
291
- singularApiName: data.singularApiName,
292
- pluralApiName: data.pluralApiName,
293
- titleFieldId: "id",
294
- descriptionFieldId: null,
295
- imageFieldId: null,
296
- description: data.description || "",
297
- locale: getLocale().code,
298
- tenant: getTenant().id,
299
- group: {
300
- id: group.id,
301
- name: group.name
302
- },
303
- createdBy: {
304
- id: identity.id,
305
- displayName: identity.displayName,
306
- type: identity.type
307
- },
308
- createdOn: new Date().toISOString(),
309
- savedOn: new Date().toISOString(),
310
- lockedFields: [],
311
- webinyVersion: context.WEBINY_VERSION
575
+ return context.benchmark.measure("headlessCms.crud.models.createModel", async () => {
576
+ return createModel(input);
312
577
  });
313
- model.tags = ensureTypeTag(model);
314
- try {
315
- await onModelBeforeCreate.publish({
316
- input: data,
317
- model
318
- });
319
- const createdModel = await storageOperations.models.create({
320
- model
321
- });
322
- loaders.listModels.clearAll();
323
- await updateManager(context, model);
324
- await onModelAfterCreate.publish({
325
- input: data,
326
- model: createdModel
327
- });
328
- return createdModel;
329
- } catch (ex) {
330
- await onModelCreateError.publish({
331
- input: data,
332
- model,
333
- error: ex
334
- });
335
- throw ex;
336
- }
337
578
  },
338
579
  /**
339
580
  * Method does not check for permissions or ownership.
340
581
  * @internal
341
582
  */
342
583
  async updateModelDirect(params) {
343
- const {
344
- model: initialModel,
345
- original
346
- } = params;
347
- const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, initialModel), {}, {
348
- tenant: initialModel.tenant || getTenant().id,
349
- locale: initialModel.locale || getLocale().code,
350
- webinyVersion: context.WEBINY_VERSION
584
+ return context.benchmark.measure("headlessCms.crud.models.updateModelDirect", async () => {
585
+ return updateModelDirect(params);
351
586
  });
352
- try {
353
- await onModelBeforeUpdate.publish({
354
- input: {},
355
- original,
356
- model
357
- });
358
- const resultModel = await storageOperations.models.update({
359
- model
360
- });
361
- await updateManager(context, resultModel);
362
- loaders.listModels.clearAll();
363
- await onModelAfterUpdate.publish({
364
- input: {},
365
- original,
366
- model: resultModel
367
- });
368
- return resultModel;
369
- } catch (ex) {
370
- await onModelUpdateError.publish({
371
- input: {},
372
- original,
373
- model,
374
- error: ex
375
- });
376
- throw ex;
377
- }
378
587
  },
379
588
  async createModelFrom(modelId, userInput) {
380
- await checkModelPermissions("w");
381
- /**
382
- * Get a model record; this will also perform ownership validation.
383
- */
384
- const original = await getModel(modelId);
385
- const result = await (0, _validation.createModelCreateFromValidation)().safeParseAsync((0, _objectSpread2.default)((0, _objectSpread2.default)({}, userInput), {}, {
386
- description: userInput.description || original.description
387
- }));
388
- if (!result.success) {
389
- throw (0, _utils.createZodError)(result.error);
390
- }
391
- const data = (0, _utils.removeUndefinedValues)(result.data);
392
- const locale = await context.i18n.getLocale(data.locale || original.locale);
393
- if (!locale) {
394
- throw new _handlerGraphql.NotFoundError(`There is no locale "${data.locale}".`);
395
- }
396
- /**
397
- * Use storage operations directly because we cannot get group from different locale via context methods.
398
- */
399
- const group = await context.cms.storageOperations.groups.get({
400
- id: data.group,
401
- tenant: original.tenant,
402
- locale: locale.code
403
- });
404
- if (!group) {
405
- throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
406
- }
407
- const identity = getIdentity();
408
- const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, original), {}, {
409
- singularApiName: data.singularApiName,
410
- pluralApiName: data.pluralApiName,
411
- locale: locale.code,
412
- group: {
413
- id: group.id,
414
- name: group.name
415
- },
416
- icon: data.icon,
417
- name: data.name,
418
- modelId: data.modelId || "",
419
- description: data.description || "",
420
- createdBy: {
421
- id: identity.id,
422
- displayName: identity.displayName,
423
- type: identity.type
424
- },
425
- createdOn: new Date().toISOString(),
426
- savedOn: new Date().toISOString(),
427
- lockedFields: [],
428
- webinyVersion: context.WEBINY_VERSION
589
+ return context.benchmark.measure("headlessCms.crud.models.createModelFrom", async () => {
590
+ return createModelFrom(modelId, userInput);
429
591
  });
430
- try {
431
- await onModelBeforeCreateFrom.publish({
432
- input: data,
433
- model,
434
- original
435
- });
436
- const createdModel = await storageOperations.models.create({
437
- model
438
- });
439
- loaders.listModels.clearAll();
440
- await updateManager(context, model);
441
- await onModelAfterCreateFrom.publish({
442
- input: data,
443
- original,
444
- model: createdModel
445
- });
446
- return createdModel;
447
- } catch (ex) {
448
- await onModelCreateFromError.publish({
449
- input: data,
450
- original,
451
- model,
452
- error: ex
453
- });
454
- throw ex;
455
- }
456
592
  },
457
593
  async updateModel(modelId, input) {
458
- await checkModelPermissions("w");
459
-
460
- // Get a model record; this will also perform ownership validation.
461
- const original = await getModel(modelId);
462
- const result = await (0, _validation.createModelUpdateValidation)().safeParseAsync(input);
463
- if (!result.success) {
464
- throw (0, _utils.createZodError)(result.error);
465
- }
466
- const data = (0, _utils.removeUndefinedValues)(result.data);
467
- if (Object.keys(data).length === 0) {
468
- /**
469
- * We need to return the original if nothing is to be updated.
470
- */
471
- return original;
472
- }
473
- let group = {
474
- id: original.group.id,
475
- name: original.group.name
476
- };
477
- if (data.group) {
478
- context.security.disableAuthorization();
479
- const groupData = await context.cms.getGroup(data.group);
480
- context.security.enableAuthorization();
481
- if (!groupData) {
482
- throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
483
- }
484
- group = {
485
- id: groupData.id,
486
- name: groupData.name
487
- };
488
- }
489
- const model = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, original), data), {}, {
490
- titleFieldId: data.titleFieldId === undefined ? original.titleFieldId : data.titleFieldId,
491
- descriptionFieldId: data.descriptionFieldId === undefined ? original.descriptionFieldId : data.descriptionFieldId,
492
- imageFieldId: data.imageFieldId === undefined ? original.imageFieldId : data.imageFieldId,
493
- group,
494
- description: data.description || original.description,
495
- tenant: original.tenant || getTenant().id,
496
- locale: original.locale || getLocale().code,
497
- webinyVersion: context.WEBINY_VERSION,
498
- savedOn: new Date().toISOString()
594
+ return context.benchmark.measure("headlessCms.crud.models.updateModel", async () => {
595
+ return updateModel(modelId, input);
499
596
  });
500
- model.tags = ensureTypeTag(model);
501
- try {
502
- await onModelBeforeUpdate.publish({
503
- input: data,
504
- original,
505
- model
506
- });
507
- const resultModel = await storageOperations.models.update({
508
- model
509
- });
510
- await updateManager(context, resultModel);
511
- await onModelAfterUpdate.publish({
512
- input: data,
513
- original,
514
- model: resultModel
515
- });
516
- return resultModel;
517
- } catch (ex) {
518
- await onModelUpdateError.publish({
519
- input: data,
520
- model,
521
- original,
522
- error: ex
523
- });
524
- throw ex;
525
- }
526
597
  },
527
598
  async deleteModel(modelId) {
528
- await checkModelPermissions("d");
529
- const model = await getModel(modelId);
530
- try {
531
- await onModelBeforeDelete.publish({
532
- model
533
- });
534
- try {
535
- await storageOperations.models.delete({
536
- model
537
- });
538
- } catch (ex) {
539
- throw new _error.default(ex.message || "Could not delete the content model", ex.code || "CONTENT_MODEL_DELETE_ERROR", {
540
- error: ex,
541
- modelId: model.modelId
542
- });
543
- }
544
- await onModelAfterDelete.publish({
545
- model
546
- });
547
- managers.delete(model.modelId);
548
- } catch (ex) {
549
- await onModelDeleteError.publish({
550
- model,
551
- error: ex
552
- });
553
- throw ex;
554
- }
599
+ return context.benchmark.measure("headlessCms.crud.models.deleteModel", async () => {
600
+ return deleteModel(modelId);
601
+ });
555
602
  },
556
603
  async initializeModel(modelId, data) {
557
- /**
558
- * We require that users have write permissions to initialize models.
559
- * Maybe introduce another permission for it?
560
- */
561
- await checkModelPermissions("w");
562
- const model = await getModel(modelId);
563
- await onModelInitialize.publish({
564
- model,
565
- data
604
+ return context.benchmark.measure("headlessCms.crud.models.initializeModel", async () => {
605
+ return initializeModel(modelId, data);
566
606
  });
567
- return true;
568
607
  },
569
608
  getModelManager,
570
609
  getEntryManager: async model => {