@webiny/api-headless-cms 0.0.0-unstable.d65ec29d44 → 0.0.0-unstable.da99e0b846

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 (165) hide show
  1. package/context.js +47 -43
  2. package/context.js.map +1 -1
  3. package/crud/contentEntry/markLockedFields.d.ts +1 -1
  4. package/crud/contentEntry/markLockedFields.js +3 -0
  5. package/crud/contentEntry/markLockedFields.js.map +1 -1
  6. package/crud/contentEntry.crud.d.ts +5 -2
  7. package/crud/contentEntry.crud.js +848 -830
  8. package/crud/contentEntry.crud.js.map +1 -1
  9. package/crud/contentModel/beforeCreate.js +39 -76
  10. package/crud/contentModel/beforeCreate.js.map +1 -1
  11. package/crud/contentModel/beforeDelete.d.ts +1 -1
  12. package/crud/contentModel/beforeDelete.js +1 -5
  13. package/crud/contentModel/beforeDelete.js.map +1 -1
  14. package/crud/contentModel/beforeUpdate.js +31 -3
  15. package/crud/contentModel/beforeUpdate.js.map +1 -1
  16. package/crud/contentModel/compatibility/modelApiName.d.ts +3 -0
  17. package/crud/contentModel/compatibility/modelApiName.js +24 -0
  18. package/crud/contentModel/compatibility/modelApiName.js.map +1 -0
  19. package/crud/contentModel/defaultFields.d.ts +5 -0
  20. package/crud/contentModel/defaultFields.js +58 -0
  21. package/crud/contentModel/defaultFields.js.map +1 -0
  22. package/crud/contentModel/fields/descriptionField.d.ts +2 -0
  23. package/crud/contentModel/fields/descriptionField.js +42 -0
  24. package/crud/contentModel/fields/descriptionField.js.map +1 -0
  25. package/crud/contentModel/fields/imageField.d.ts +2 -0
  26. package/crud/contentModel/fields/imageField.js +46 -0
  27. package/crud/contentModel/fields/imageField.js.map +1 -0
  28. package/crud/contentModel/fields/titleField.d.ts +2 -0
  29. package/crud/contentModel/fields/titleField.js +58 -0
  30. package/crud/contentModel/fields/titleField.js.map +1 -0
  31. package/crud/contentModel/systemFields.js.map +1 -1
  32. package/crud/contentModel/validate/endingAllowed.d.ts +6 -0
  33. package/crud/contentModel/validate/endingAllowed.js +26 -0
  34. package/crud/contentModel/validate/endingAllowed.js.map +1 -0
  35. package/crud/contentModel/validate/isModelEndingAllowed.d.ts +6 -0
  36. package/crud/contentModel/validate/isModelEndingAllowed.js +24 -0
  37. package/crud/contentModel/validate/isModelEndingAllowed.js.map +1 -0
  38. package/crud/contentModel/validate/modelId.d.ts +11 -0
  39. package/crud/contentModel/validate/modelId.js +36 -0
  40. package/crud/contentModel/validate/modelId.js.map +1 -0
  41. package/crud/contentModel/validate/pluralApiName.d.ts +7 -0
  42. package/crud/contentModel/validate/pluralApiName.js +24 -0
  43. package/crud/contentModel/validate/pluralApiName.js.map +1 -0
  44. package/crud/contentModel/validate/singularApiName.d.ts +7 -0
  45. package/crud/contentModel/validate/singularApiName.js +24 -0
  46. package/crud/contentModel/validate/singularApiName.js.map +1 -0
  47. package/crud/contentModel/validateModel.d.ts +1 -0
  48. package/crud/contentModel/validateModel.js.map +1 -1
  49. package/crud/contentModel/validateModelFields.d.ts +2 -1
  50. package/crud/contentModel/validateModelFields.js +19 -57
  51. package/crud/contentModel/validateModelFields.js.map +1 -1
  52. package/crud/contentModel/validation.d.ts +136 -62
  53. package/crud/contentModel/validation.js +61 -13
  54. package/crud/contentModel/validation.js.map +1 -1
  55. package/crud/contentModel.crud.js +346 -285
  56. package/crud/contentModel.crud.js.map +1 -1
  57. package/crud/contentModelGroup.crud.js +170 -142
  58. package/crud/contentModelGroup.crud.js.map +1 -1
  59. package/crud/settings.crud.d.ts +1 -1
  60. package/crud/settings.crud.js +5 -10
  61. package/crud/settings.crud.js.map +1 -1
  62. package/crud/system.crud.js +0 -60
  63. package/crud/system.crud.js.map +1 -1
  64. package/graphql/checkEndpointAccess.d.ts +2 -0
  65. package/graphql/checkEndpointAccess.js +18 -0
  66. package/graphql/checkEndpointAccess.js.map +1 -0
  67. package/graphql/createExecutableSchema.d.ts +2 -3
  68. package/graphql/createExecutableSchema.js.map +1 -1
  69. package/graphql/createRequestBody.d.ts +2 -0
  70. package/graphql/createRequestBody.js +14 -0
  71. package/graphql/createRequestBody.js.map +1 -0
  72. package/graphql/formatErrorPayload.d.ts +1 -0
  73. package/graphql/formatErrorPayload.js +25 -0
  74. package/graphql/formatErrorPayload.js.map +1 -0
  75. package/graphql/generateSchema.js.map +1 -1
  76. package/graphql/getSchema.d.ts +17 -0
  77. package/graphql/getSchema.js +102 -0
  78. package/graphql/getSchema.js.map +1 -0
  79. package/graphql/graphQLHandlerFactory.js +6 -145
  80. package/graphql/graphQLHandlerFactory.js.map +1 -1
  81. package/graphql/handleRequest.d.ts +11 -0
  82. package/graphql/handleRequest.js +81 -0
  83. package/graphql/handleRequest.js.map +1 -0
  84. package/graphql/schema/baseContentSchema.js +1 -7
  85. package/graphql/schema/baseContentSchema.js.map +1 -1
  86. package/graphql/schema/contentEntries.js +90 -53
  87. package/graphql/schema/contentEntries.js.map +1 -1
  88. package/graphql/schema/contentModelGroups.js +7 -7
  89. package/graphql/schema/contentModelGroups.js.map +1 -1
  90. package/graphql/schema/contentModels.js +23 -4
  91. package/graphql/schema/contentModels.js.map +1 -1
  92. package/graphql/schema/createManageResolvers.d.ts +1 -1
  93. package/graphql/schema/createManageResolvers.js +33 -17
  94. package/graphql/schema/createManageResolvers.js.map +1 -1
  95. package/graphql/schema/createManageSDL.d.ts +1 -0
  96. package/graphql/schema/createManageSDL.js +55 -49
  97. package/graphql/schema/createManageSDL.js.map +1 -1
  98. package/graphql/schema/createPreviewResolvers.js +3 -7
  99. package/graphql/schema/createPreviewResolvers.js.map +1 -1
  100. package/graphql/schema/createReadResolvers.js +4 -8
  101. package/graphql/schema/createReadResolvers.js.map +1 -1
  102. package/graphql/schema/createReadSDL.d.ts +1 -0
  103. package/graphql/schema/createReadSDL.js +24 -22
  104. package/graphql/schema/createReadSDL.js.map +1 -1
  105. package/graphql/schema/resolvers/commonFieldResolvers.d.ts +3 -2
  106. package/graphql/schema/resolvers/commonFieldResolvers.js +2 -1
  107. package/graphql/schema/resolvers/commonFieldResolvers.js.map +1 -1
  108. package/graphql/schema/schemaPlugins.js +12 -12
  109. package/graphql/schema/schemaPlugins.js.map +1 -1
  110. package/graphql/system.js +0 -16
  111. package/graphql/system.js.map +1 -1
  112. package/graphqlFields/dynamicZone/dynamicZoneField.js +12 -4
  113. package/graphqlFields/dynamicZone/dynamicZoneField.js.map +1 -1
  114. package/graphqlFields/object.js +21 -2
  115. package/graphqlFields/object.js.map +1 -1
  116. package/graphqlFields/ref.js +42 -14
  117. package/graphqlFields/ref.js.map +1 -1
  118. package/index.d.ts +3 -1
  119. package/index.js +25 -2
  120. package/index.js.map +1 -1
  121. package/package.json +22 -23
  122. package/plugins/CmsModelPlugin.d.ts +19 -3
  123. package/plugins/CmsModelPlugin.js +28 -2
  124. package/plugins/CmsModelPlugin.js.map +1 -1
  125. package/plugins/StorageOperationsCmsModelPlugin.d.ts +23 -0
  126. package/plugins/StorageOperationsCmsModelPlugin.js +42 -0
  127. package/plugins/StorageOperationsCmsModelPlugin.js.map +1 -0
  128. package/plugins/index.d.ts +1 -0
  129. package/plugins/index.js +11 -0
  130. package/plugins/index.js.map +1 -1
  131. package/types.d.ts +118 -66
  132. package/types.js +1 -1
  133. package/types.js.map +1 -1
  134. package/upgrades/5.33.0/index.js +26 -3
  135. package/upgrades/5.33.0/index.js.map +1 -1
  136. package/upgrades/index.js +3 -0
  137. package/upgrades/index.js.map +1 -1
  138. package/utils/converters/valueKeyStorageConverter.d.ts +1 -5
  139. package/utils/converters/valueKeyStorageConverter.js +21 -18
  140. package/utils/converters/valueKeyStorageConverter.js.map +1 -1
  141. package/utils/createTypeFromFields.d.ts +1 -0
  142. package/utils/createTypeFromFields.js +7 -5
  143. package/utils/createTypeFromFields.js.map +1 -1
  144. package/utils/createTypeName.d.ts +0 -2
  145. package/utils/createTypeName.js +2 -10
  146. package/utils/createTypeName.js.map +1 -1
  147. package/utils/getEntryDescription.d.ts +2 -0
  148. package/utils/getEntryDescription.js +17 -0
  149. package/utils/getEntryDescription.js.map +1 -0
  150. package/utils/getEntryImage.d.ts +2 -0
  151. package/utils/getEntryImage.js +17 -0
  152. package/utils/getEntryImage.js.map +1 -0
  153. package/utils/incrementEntryIdVersion.d.ts +5 -0
  154. package/utils/incrementEntryIdVersion.js +29 -0
  155. package/utils/incrementEntryIdVersion.js.map +1 -0
  156. package/utils/ownership.d.ts +3 -3
  157. package/utils/ownership.js.map +1 -1
  158. package/utils/pluralizedTypeName.js +6 -0
  159. package/utils/pluralizedTypeName.js.map +1 -1
  160. package/utils/renderFields.d.ts +2 -1
  161. package/utils/renderFields.js +8 -1
  162. package/utils/renderFields.js.map +1 -1
  163. package/utils/renderInputFields.d.ts +2 -1
  164. package/utils/renderInputFields.js +4 -0
  165. package/utils/renderInputFields.js.map +1 -1
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.createModelsCrud = void 0;
8
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
8
9
  var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
9
10
  var _dataloader = _interopRequireDefault(require("dataloader"));
10
11
  var _error = _interopRequireDefault(require("@webiny/error"));
@@ -25,6 +26,9 @@ var _ownership = require("../utils/ownership");
25
26
  var _access = require("../utils/access");
26
27
  var _validation = require("./contentModel/validation");
27
28
  var _utils = require("@webiny/utils");
29
+ var _defaultFields = require("./contentModel/defaultFields");
30
+ var _modelApiName = require("./contentModel/compatibility/modelApiName");
31
+ const _excluded = ["defaultFields"];
28
32
  /**
29
33
  * Given a model, return an array of tags ensuring the `type` tag is set.
30
34
  */
@@ -57,7 +61,13 @@ const createModelsCrud = params => {
57
61
  return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, model), {}, {
58
62
  tags: ensureTypeTag(model),
59
63
  tenant: model.tenant || getTenant().id,
60
- locale: model.locale || getLocale().code
64
+ locale: model.locale || getLocale().code,
65
+ /**
66
+ * TODO: remove in v5.36.0
67
+ * This is for backward compatibility while migrations are not yet executed.
68
+ */
69
+ singularApiName: (0, _modelApiName.ensureSingularApiName)(model),
70
+ pluralApiName: (0, _modelApiName.ensurePluralApiName)(model)
61
71
  });
62
72
  })];
63
73
  })
@@ -130,21 +140,25 @@ const createModelsCrud = params => {
130
140
  return databaseModels.concat(pluginsModels);
131
141
  };
132
142
  const listModels = async () => {
133
- const permission = await checkModelPermissions("r");
134
- const models = await modelsList();
135
- return (0, _filterAsync.filterAsync)(models, async model => {
136
- if (!(0, _ownership.validateOwnership)(context, permission, model)) {
137
- return false;
138
- }
139
- 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
+ });
140
152
  });
141
153
  };
142
154
  const getModel = async modelId => {
143
- const permission = await checkModelPermissions("r");
144
- const model = await modelsGet(modelId);
145
- (0, _ownership.checkOwnership)(context, permission, model);
146
- await (0, _access.checkModelAccess)(context, model);
147
- 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
+ });
148
162
  };
149
163
  const getModelManager = async target => {
150
164
  const modelId = typeof target === "string" ? target : target.modelId;
@@ -221,6 +235,311 @@ const createModelsCrud = params => {
221
235
  context,
222
236
  onModelAfterDelete
223
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
+ };
224
543
  return {
225
544
  /**
226
545
  * Deprecated - will be removed in 5.36.0
@@ -253,296 +572,38 @@ const createModelsCrud = params => {
253
572
  getModel,
254
573
  listModels,
255
574
  async createModel(input) {
256
- await checkModelPermissions("w");
257
- const result = await (0, _validation.createModelCreateValidation)().safeParseAsync(input);
258
- if (!result.success) {
259
- throw (0, _utils.createZodError)(result.error);
260
- }
261
- const data = result.data;
262
- context.security.disableAuthorization();
263
- const group = await context.cms.getGroup(data.group);
264
- context.security.enableAuthorization();
265
- if (!group) {
266
- throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
267
- }
268
- const identity = getIdentity();
269
- const model = {
270
- name: data.name,
271
- description: data.description || "",
272
- modelId: data.modelId || "",
273
- titleFieldId: "id",
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
- fields: data.fields,
288
- lockedFields: [],
289
- layout: data.layout || [],
290
- tags: [...(data.tags || [])],
291
- webinyVersion: context.WEBINY_VERSION
292
- };
293
- model.tags = ensureTypeTag(model);
294
- try {
295
- await onModelBeforeCreate.publish({
296
- input: data,
297
- model
298
- });
299
- const createdModel = await storageOperations.models.create({
300
- model
301
- });
302
- loaders.listModels.clearAll();
303
- await updateManager(context, model);
304
- await onModelAfterCreate.publish({
305
- input: data,
306
- model: createdModel
307
- });
308
- return createdModel;
309
- } catch (ex) {
310
- await onModelCreateError.publish({
311
- input: data,
312
- model,
313
- error: ex
314
- });
315
- throw ex;
316
- }
575
+ return context.benchmark.measure("headlessCms.crud.models.createModel", async () => {
576
+ return createModel(input);
577
+ });
317
578
  },
318
579
  /**
319
580
  * Method does not check for permissions or ownership.
320
581
  * @internal
321
582
  */
322
583
  async updateModelDirect(params) {
323
- const {
324
- model: initialModel,
325
- original
326
- } = params;
327
- const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, initialModel), {}, {
328
- tenant: initialModel.tenant || getTenant().id,
329
- locale: initialModel.locale || getLocale().code,
330
- webinyVersion: context.WEBINY_VERSION
584
+ return context.benchmark.measure("headlessCms.crud.models.updateModelDirect", async () => {
585
+ return updateModelDirect(params);
331
586
  });
332
- try {
333
- await onModelBeforeUpdate.publish({
334
- input: {},
335
- original,
336
- model
337
- });
338
- const resultModel = await storageOperations.models.update({
339
- model
340
- });
341
- await updateManager(context, resultModel);
342
- loaders.listModels.clearAll();
343
- await onModelAfterUpdate.publish({
344
- input: {},
345
- original,
346
- model: resultModel
347
- });
348
- return resultModel;
349
- } catch (ex) {
350
- await onModelUpdateError.publish({
351
- input: {},
352
- original,
353
- model,
354
- error: ex
355
- });
356
- throw ex;
357
- }
358
587
  },
359
588
  async createModelFrom(modelId, userInput) {
360
- await checkModelPermissions("w");
361
- /**
362
- * Get a model record; this will also perform ownership validation.
363
- */
364
- const original = await getModel(modelId);
365
- const result = await (0, _validation.createModelCreateFromValidation)().safeParseAsync({
366
- name: userInput.name,
367
- modelId: userInput.modelId,
368
- description: userInput.description || original.description,
369
- group: userInput.group,
370
- locale: userInput.locale
371
- });
372
- if (!result.success) {
373
- throw (0, _utils.createZodError)(result.error);
374
- }
375
- const data = result.data;
376
- const locale = await context.i18n.getLocale(data.locale || original.locale);
377
- if (!locale) {
378
- throw new _handlerGraphql.NotFoundError(`There is no locale "${data.locale}".`);
379
- }
380
- /**
381
- * Use storage operations directly because we cannot get group from different locale via context methods.
382
- */
383
- const group = await context.cms.storageOperations.groups.get({
384
- id: data.group,
385
- tenant: original.tenant,
386
- locale: locale.code
387
- });
388
- if (!group) {
389
- throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
390
- }
391
- const identity = getIdentity();
392
- const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, original), {}, {
393
- locale: locale.code,
394
- group: {
395
- id: group.id,
396
- name: group.name
397
- },
398
- name: data.name,
399
- modelId: data.modelId || "",
400
- description: data.description || "",
401
- createdBy: {
402
- id: identity.id,
403
- displayName: identity.displayName,
404
- type: identity.type
405
- },
406
- createdOn: new Date().toISOString(),
407
- savedOn: new Date().toISOString(),
408
- lockedFields: [],
409
- webinyVersion: context.WEBINY_VERSION
589
+ return context.benchmark.measure("headlessCms.crud.models.createModelFrom", async () => {
590
+ return createModelFrom(modelId, userInput);
410
591
  });
411
- try {
412
- await onModelBeforeCreateFrom.publish({
413
- input: data,
414
- model,
415
- original
416
- });
417
- const createdModel = await storageOperations.models.create({
418
- model
419
- });
420
- loaders.listModels.clearAll();
421
- await updateManager(context, model);
422
- await onModelAfterCreateFrom.publish({
423
- input: data,
424
- original,
425
- model: createdModel
426
- });
427
- return createdModel;
428
- } catch (ex) {
429
- await onModelCreateFromError.publish({
430
- input: data,
431
- original,
432
- model,
433
- error: ex
434
- });
435
- throw ex;
436
- }
437
592
  },
438
593
  async updateModel(modelId, input) {
439
- await checkModelPermissions("w");
440
-
441
- // Get a model record; this will also perform ownership validation.
442
- const original = await getModel(modelId);
443
- const result = await (0, _validation.createModelUpdateValidation)().safeParseAsync(input);
444
- if (!result.success) {
445
- throw (0, _utils.createZodError)(result.error);
446
- }
447
- const data = result.data;
448
- if (Object.keys(data).length === 0) {
449
- /**
450
- * We need to return the original if nothing is to be updated.
451
- */
452
- return original;
453
- }
454
- let group = {
455
- id: original.group.id,
456
- name: original.group.name
457
- };
458
- if (data.group) {
459
- context.security.disableAuthorization();
460
- const groupData = await context.cms.getGroup(data.group);
461
- context.security.enableAuthorization();
462
- if (!groupData) {
463
- throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
464
- }
465
- group = {
466
- id: groupData.id,
467
- name: groupData.name
468
- };
469
- }
470
- const model = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, original), data), {}, {
471
- group,
472
- description: data.description || original.description,
473
- tenant: original.tenant || getTenant().id,
474
- locale: original.locale || getLocale().code,
475
- webinyVersion: context.WEBINY_VERSION,
476
- savedOn: new Date().toISOString()
594
+ return context.benchmark.measure("headlessCms.crud.models.updateModel", async () => {
595
+ return updateModel(modelId, input);
477
596
  });
478
- model.tags = ensureTypeTag(model);
479
- try {
480
- await onModelBeforeUpdate.publish({
481
- input: data,
482
- original,
483
- model
484
- });
485
- const resultModel = await storageOperations.models.update({
486
- model
487
- });
488
- await updateManager(context, resultModel);
489
- await onModelAfterUpdate.publish({
490
- input: data,
491
- original,
492
- model: resultModel
493
- });
494
- return resultModel;
495
- } catch (ex) {
496
- await onModelUpdateError.publish({
497
- input: data,
498
- model,
499
- original,
500
- error: ex
501
- });
502
- throw ex;
503
- }
504
597
  },
505
598
  async deleteModel(modelId) {
506
- await checkModelPermissions("d");
507
- const model = await getModel(modelId);
508
- try {
509
- await onModelBeforeDelete.publish({
510
- model
511
- });
512
- try {
513
- await storageOperations.models.delete({
514
- model
515
- });
516
- } catch (ex) {
517
- throw new _error.default(ex.message || "Could not delete the content model", ex.code || "CONTENT_MODEL_DELETE_ERROR", {
518
- error: ex,
519
- modelId: model.modelId
520
- });
521
- }
522
- await onModelAfterDelete.publish({
523
- model
524
- });
525
- managers.delete(model.modelId);
526
- } catch (ex) {
527
- await onModelDeleteError.publish({
528
- model,
529
- error: ex
530
- });
531
- throw ex;
532
- }
599
+ return context.benchmark.measure("headlessCms.crud.models.deleteModel", async () => {
600
+ return deleteModel(modelId);
601
+ });
533
602
  },
534
603
  async initializeModel(modelId, data) {
535
- /**
536
- * We require that users have write permissions to initialize models.
537
- * Maybe introduce another permission for it?
538
- */
539
- await checkModelPermissions("w");
540
- const model = await getModel(modelId);
541
- await onModelInitialize.publish({
542
- model,
543
- data
604
+ return context.benchmark.measure("headlessCms.crud.models.initializeModel", async () => {
605
+ return initializeModel(modelId, data);
544
606
  });
545
- return true;
546
607
  },
547
608
  getModelManager,
548
609
  getEntryManager: async model => {