@webiny/api-headless-cms 0.0.0-unstable.496cf268ac → 0.0.0-unstable.606fc9c866

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 (138) hide show
  1. package/context.js +47 -43
  2. package/context.js.map +1 -1
  3. package/crud/contentEntry/referenceFieldsMapping.js +34 -5
  4. package/crud/contentEntry/referenceFieldsMapping.js.map +1 -1
  5. package/crud/contentEntry.crud.d.ts +6 -4
  6. package/crud/contentEntry.crud.js +896 -821
  7. package/crud/contentEntry.crud.js.map +1 -1
  8. package/crud/contentModel/beforeCreate.js +38 -79
  9. package/crud/contentModel/beforeCreate.js.map +1 -1
  10. package/crud/contentModel/beforeDelete.d.ts +1 -1
  11. package/crud/contentModel/beforeDelete.js +1 -5
  12. package/crud/contentModel/beforeDelete.js.map +1 -1
  13. package/crud/contentModel/beforeUpdate.js +30 -6
  14. package/crud/contentModel/beforeUpdate.js.map +1 -1
  15. package/crud/contentModel/validate/endingAllowed.d.ts +6 -0
  16. package/crud/contentModel/validate/endingAllowed.js +26 -0
  17. package/crud/contentModel/validate/endingAllowed.js.map +1 -0
  18. package/crud/contentModel/validate/isModelEndingAllowed.d.ts +6 -0
  19. package/crud/contentModel/validate/isModelEndingAllowed.js +24 -0
  20. package/crud/contentModel/validate/isModelEndingAllowed.js.map +1 -0
  21. package/crud/contentModel/validate/modelId.d.ts +11 -0
  22. package/crud/contentModel/validate/modelId.js +36 -0
  23. package/crud/contentModel/validate/modelId.js.map +1 -0
  24. package/crud/contentModel/validate/pluralApiName.d.ts +7 -0
  25. package/crud/contentModel/validate/pluralApiName.js +24 -0
  26. package/crud/contentModel/validate/pluralApiName.js.map +1 -0
  27. package/crud/contentModel/validate/singularApiName.d.ts +7 -0
  28. package/crud/contentModel/validate/singularApiName.js +24 -0
  29. package/crud/contentModel/validate/singularApiName.js.map +1 -0
  30. package/crud/contentModel/validateModelFields.js +6 -7
  31. package/crud/contentModel/validateModelFields.js.map +1 -1
  32. package/crud/contentModel/validation.d.ts +127 -95
  33. package/crud/contentModel/validation.js +4 -4
  34. package/crud/contentModel/validation.js.map +1 -1
  35. package/crud/contentModel.crud.js +334 -296
  36. package/crud/contentModel.crud.js.map +1 -1
  37. package/crud/contentModelGroup/validation.d.ts +4 -4
  38. package/crud/contentModelGroup.crud.js +170 -142
  39. package/crud/contentModelGroup.crud.js.map +1 -1
  40. package/crud/settings.crud.d.ts +1 -1
  41. package/crud/settings.crud.js +5 -10
  42. package/crud/settings.crud.js.map +1 -1
  43. package/graphql/checkEndpointAccess.d.ts +2 -0
  44. package/graphql/checkEndpointAccess.js +18 -0
  45. package/graphql/checkEndpointAccess.js.map +1 -0
  46. package/graphql/createExecutableSchema.d.ts +2 -3
  47. package/graphql/createExecutableSchema.js.map +1 -1
  48. package/graphql/createRequestBody.d.ts +2 -0
  49. package/graphql/createRequestBody.js +14 -0
  50. package/graphql/createRequestBody.js.map +1 -0
  51. package/graphql/formatErrorPayload.d.ts +1 -0
  52. package/graphql/formatErrorPayload.js +25 -0
  53. package/graphql/formatErrorPayload.js.map +1 -0
  54. package/graphql/generateSchema.js.map +1 -1
  55. package/graphql/getSchema.d.ts +17 -0
  56. package/graphql/getSchema.js +102 -0
  57. package/graphql/getSchema.js.map +1 -0
  58. package/graphql/graphQLHandlerFactory.js +6 -150
  59. package/graphql/graphQLHandlerFactory.js.map +1 -1
  60. package/graphql/handleRequest.d.ts +11 -0
  61. package/graphql/handleRequest.js +81 -0
  62. package/graphql/handleRequest.js.map +1 -0
  63. package/graphql/index.d.ts +1 -1
  64. package/graphql/schema/contentModelGroups.js +6 -6
  65. package/graphql/schema/contentModelGroups.js.map +1 -1
  66. package/graphql/schema/contentModels.js +3 -3
  67. package/graphql/schema/contentModels.js.map +1 -1
  68. package/graphql/schema/createFieldResolvers.js +2 -1
  69. package/graphql/schema/createFieldResolvers.js.map +1 -1
  70. package/graphql/schema/createManageResolvers.js +6 -0
  71. package/graphql/schema/createManageResolvers.js.map +1 -1
  72. package/graphql/schema/resolvers/manage/resolveGetUniqueFieldValues.d.ts +4 -0
  73. package/graphql/schema/resolvers/manage/resolveGetUniqueFieldValues.js +18 -0
  74. package/graphql/schema/resolvers/manage/resolveGetUniqueFieldValues.js.map +1 -0
  75. package/graphqlFields/dynamicZone/dynamicZoneField.d.ts +1 -1
  76. package/graphqlFields/dynamicZone/dynamicZoneField.js +44 -17
  77. package/graphqlFields/dynamicZone/dynamicZoneField.js.map +1 -1
  78. package/graphqlFields/object.js +14 -1
  79. package/graphqlFields/object.js.map +1 -1
  80. package/graphqlFields/ref.js +7 -7
  81. package/graphqlFields/ref.js.map +1 -1
  82. package/index.d.ts +3 -1
  83. package/index.js +24 -0
  84. package/index.js.map +1 -1
  85. package/package.json +22 -22
  86. package/plugins/CmsModelPlugin.d.ts +15 -7
  87. package/plugins/CmsModelPlugin.js +21 -6
  88. package/plugins/CmsModelPlugin.js.map +1 -1
  89. package/plugins/StorageOperationsCmsModelPlugin.d.ts +23 -0
  90. package/plugins/StorageOperationsCmsModelPlugin.js +42 -0
  91. package/plugins/StorageOperationsCmsModelPlugin.js.map +1 -0
  92. package/plugins/index.d.ts +1 -0
  93. package/plugins/index.js +11 -0
  94. package/plugins/index.js.map +1 -1
  95. package/types.d.ts +72 -48
  96. package/types.js +4 -0
  97. package/types.js.map +1 -1
  98. package/utils/converters/valueKeyStorageConverter.d.ts +1 -5
  99. package/utils/converters/valueKeyStorageConverter.js +19 -17
  100. package/utils/converters/valueKeyStorageConverter.js.map +1 -1
  101. package/utils/createTypeFromFields.js +1 -2
  102. package/utils/createTypeFromFields.js.map +1 -1
  103. package/utils/createTypeName.d.ts +0 -2
  104. package/utils/createTypeName.js +2 -10
  105. package/utils/createTypeName.js.map +1 -1
  106. package/utils/incrementEntryIdVersion.d.ts +5 -0
  107. package/utils/incrementEntryIdVersion.js +29 -0
  108. package/utils/incrementEntryIdVersion.js.map +1 -0
  109. package/crud/contentModel/createFieldModels.d.ts +0 -2
  110. package/crud/contentModel/createFieldModels.js +0 -26
  111. package/crud/contentModel/createFieldModels.js.map +0 -1
  112. package/crud/contentModel/fieldIdValidation.d.ts +0 -1
  113. package/crud/contentModel/fieldIdValidation.js +0 -25
  114. package/crud/contentModel/fieldIdValidation.js.map +0 -1
  115. package/crud/contentModel/idValidation.d.ts +0 -1
  116. package/crud/contentModel/idValidation.js +0 -22
  117. package/crud/contentModel/idValidation.js.map +0 -1
  118. package/crud/contentModel/models.d.ts +0 -4
  119. package/crud/contentModel/models.js +0 -192
  120. package/crud/contentModel/models.js.map +0 -1
  121. package/crud/contentModel/systemFields.d.ts +0 -1
  122. package/crud/contentModel/systemFields.js +0 -8
  123. package/crud/contentModel/systemFields.js.map +0 -1
  124. package/upgrades/5.33.0/index.d.ts +0 -3
  125. package/upgrades/5.33.0/index.js +0 -182
  126. package/upgrades/5.33.0/index.js.map +0 -1
  127. package/upgrades/index.d.ts +0 -1
  128. package/upgrades/index.js +0 -12
  129. package/upgrades/index.js.map +0 -1
  130. package/utils/pluralizedTypeName.d.ts +0 -1
  131. package/utils/pluralizedTypeName.js +0 -26
  132. package/utils/pluralizedTypeName.js.map +0 -1
  133. package/utils/removeNullValues.d.ts +0 -1
  134. package/utils/removeNullValues.js +0 -17
  135. package/utils/removeNullValues.js.map +0 -1
  136. package/utils/removeUndefinedValues.d.ts +0 -1
  137. package/utils/removeUndefinedValues.js +0 -17
  138. package/utils/removeUndefinedValues.js.map +0 -1
@@ -6,35 +6,33 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.createContentEntryCrud = exports.STATUS_UNPUBLISHED = exports.STATUS_PUBLISHED = exports.STATUS_DRAFT = void 0;
8
8
  var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
9
+ var _merge = _interopRequireDefault(require("lodash/merge"));
9
10
  var _mdbid = _interopRequireDefault(require("mdbid"));
11
+ var _error = _interopRequireDefault(require("@webiny/error"));
10
12
  var _handlerGraphql = require("@webiny/handler-graphql");
13
+ var _types = require("../types");
11
14
  var _entryDataValidation = require("./contentEntry/entryDataValidation");
12
- var _error = _interopRequireDefault(require("@webiny/error"));
13
15
  var _pubsub = require("@webiny/pubsub");
14
16
  var _beforeCreate = require("./contentEntry/beforeCreate");
15
17
  var _beforeUpdate = require("./contentEntry/beforeUpdate");
16
18
  var _utils = require("@webiny/utils");
17
19
  var _afterDelete = require("./contentEntry/afterDelete");
18
20
  var _referenceFieldsMapping = require("./contentEntry/referenceFieldsMapping");
19
- var _merge = _interopRequireDefault(require("lodash/merge"));
20
21
  var _permissions = require("../utils/permissions");
21
22
  var _access = require("../utils/access");
22
23
  var _ownership = require("../utils/ownership");
23
24
  var _entryStorage = require("../utils/entryStorage");
24
- var _valueKeyStorageConverter = require("../utils/converters/valueKeyStorageConverter");
25
25
  var _searchableFields = require("./contentEntry/searchableFields");
26
- var _removeUndefinedValues = require("../utils/removeUndefinedValues");
27
- var _removeNullValues = require("../utils/removeNullValues");
28
26
  /**
29
27
  * Package mdbid does not have types.
30
28
  */
31
29
  // @ts-ignore
32
30
 
33
- const STATUS_DRAFT = "draft";
31
+ const STATUS_DRAFT = _types.CONTENT_ENTRY_STATUS.DRAFT;
34
32
  exports.STATUS_DRAFT = STATUS_DRAFT;
35
- const STATUS_PUBLISHED = "published";
33
+ const STATUS_PUBLISHED = _types.CONTENT_ENTRY_STATUS.PUBLISHED;
36
34
  exports.STATUS_PUBLISHED = STATUS_PUBLISHED;
37
- const STATUS_UNPUBLISHED = "unpublished";
35
+ const STATUS_UNPUBLISHED = _types.CONTENT_ENTRY_STATUS.UNPUBLISHED;
38
36
  exports.STATUS_UNPUBLISHED = STATUS_UNPUBLISHED;
39
37
  /**
40
38
  * Used for some fields to convert their values.
@@ -133,7 +131,7 @@ const mapAndCleanUpdatedInputData = (model, input) => {
133
131
  */
134
132
  const createEntryMeta = (input, original) => {
135
133
  const meta = (0, _merge.default)(original || {}, input || {});
136
- return (0, _removeUndefinedValues.removeUndefinedValues)((0, _removeNullValues.removeNullValues)(meta));
134
+ return (0, _utils.removeUndefinedValues)((0, _utils.removeNullValues)(meta));
137
135
  };
138
136
  const createEntryId = input => {
139
137
  let entryId = (0, _mdbid.default)();
@@ -183,11 +181,9 @@ const createContentEntryCrud = params => {
183
181
  storageOperations,
184
182
  context,
185
183
  getIdentity,
186
- getTenant
184
+ getTenant,
185
+ getLocale
187
186
  } = params;
188
- const {
189
- plugins
190
- } = context;
191
187
  const getCreatedBy = () => {
192
188
  const identity = getIdentity();
193
189
  return {
@@ -285,308 +281,927 @@ const createContentEntryCrud = params => {
285
281
  /**
286
282
  * A helper to delete the entire entry.
287
283
  */
288
- const deleteEntry = async params => {
289
- const {
290
- model,
291
- entry
292
- } = params;
293
- try {
294
- await onEntryBeforeDelete.publish({
295
- entry,
296
- model
297
- });
298
- await storageOperations.entries.delete(model, {
299
- entry
300
- });
301
- await onEntryAfterDelete.publish({
302
- entry,
303
- model
304
- });
305
- } catch (ex) {
306
- await onEntryDeleteError.publish({
307
- entry,
284
+ const deleteEntryHelper = async params => {
285
+ return context.benchmark.measure("headlessCms.crud.entries.deleteEntry", async () => {
286
+ const {
308
287
  model,
309
- error: ex
310
- });
311
- throw new _error.default(ex.message || "Could not delete entry.", ex.code || "DELETE_ERROR", {
312
288
  entry
313
- });
314
- }
289
+ } = params;
290
+ try {
291
+ await onEntryBeforeDelete.publish({
292
+ entry,
293
+ model
294
+ });
295
+ await storageOperations.entries.delete(model, {
296
+ entry
297
+ });
298
+ await onEntryAfterDelete.publish({
299
+ entry,
300
+ model
301
+ });
302
+ } catch (ex) {
303
+ await onEntryDeleteError.publish({
304
+ entry,
305
+ model,
306
+ error: ex
307
+ });
308
+ throw new _error.default(ex.message || "Could not delete entry.", ex.code || "DELETE_ERROR", {
309
+ entry
310
+ });
311
+ }
312
+ });
315
313
  };
316
314
  /**
317
315
  * A helper to get entries by revision IDs
318
316
  */
319
- const getEntriesByIds = async (initialModel, ids) => {
317
+ const getEntriesByIds = async (model, ids) => {
318
+ return context.benchmark.measure("headlessCms.crud.entries.getEntriesByIds", async () => {
319
+ const permission = await checkEntryPermissions({
320
+ rwd: "r"
321
+ });
322
+ await (0, _access.checkModelAccess)(context, model);
323
+ const entries = await storageOperations.entries.getByIds(model, {
324
+ ids
325
+ });
326
+ return entries.filter(entry => (0, _ownership.validateOwnership)(context, permission, entry));
327
+ });
328
+ };
329
+ const getEntryById = async (model, id) => {
330
+ const where = {
331
+ id
332
+ };
333
+ await onEntryBeforeGet.publish({
334
+ where,
335
+ model
336
+ });
337
+ const [entry] = await getEntriesByIds(model, [id]);
338
+ if (!entry) {
339
+ throw new _handlerGraphql.NotFoundError(`Entry by ID "${id}" not found.`);
340
+ }
341
+ return entry;
342
+ };
343
+ const getPublishedEntriesByIds = async (model, ids) => {
320
344
  const permission = await checkEntryPermissions({
321
345
  rwd: "r"
322
346
  });
323
- await (0, _access.checkModelAccess)(context, initialModel);
324
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
325
- model: initialModel,
326
- plugins
347
+ await (0, _access.checkModelAccess)(context, model);
348
+ const entries = await storageOperations.entries.getPublishedByIds(model, {
349
+ ids
350
+ });
351
+ return entries.filter(entry => (0, _ownership.validateOwnership)(context, permission, entry));
352
+ };
353
+ const getLatestEntriesByIds = async (model, ids) => {
354
+ const permission = await checkEntryPermissions({
355
+ rwd: "r"
327
356
  });
328
- const entries = await storageOperations.entries.getByIds(model, {
357
+ await (0, _access.checkModelAccess)(context, model);
358
+ const entries = await storageOperations.entries.getLatestByIds(model, {
329
359
  ids
330
360
  });
331
361
  return entries.filter(entry => (0, _ownership.validateOwnership)(context, permission, entry));
332
362
  };
333
- return {
363
+ const getEntry = async (model, params) => {
364
+ await checkEntryPermissions({
365
+ rwd: "r"
366
+ });
367
+ const {
368
+ where,
369
+ sort
370
+ } = params;
371
+ await onEntryBeforeGet.publish({
372
+ where,
373
+ model
374
+ });
375
+ const [items] = await listEntries(model, {
376
+ where,
377
+ sort,
378
+ limit: 1
379
+ });
380
+ const item = items.shift();
381
+ if (!item) {
382
+ throw new _handlerGraphql.NotFoundError(`Entry not found!`);
383
+ }
384
+ return item;
385
+ };
386
+ const getEntryRevisions = async (model, entryId) => {
387
+ return storageOperations.entries.getRevisions(model, {
388
+ id: entryId
389
+ });
390
+ };
391
+ const listEntries = async (model, params) => {
392
+ const permission = await checkEntryPermissions({
393
+ rwd: "r"
394
+ });
395
+ await (0, _access.checkModelAccess)(context, model);
396
+ const {
397
+ where: initialWhere,
398
+ limit: initialLimit
399
+ } = params;
400
+ const limit = initialLimit && initialLimit > 0 ? initialLimit : 50;
401
+ const where = (0, _objectSpread2.default)({}, initialWhere);
334
402
  /**
335
- * Deprecated - will be removed in 5.35.0
403
+ * Possibly only get records which are owned by current user.
404
+ * Or if searching for the owner set that value - in the case that user can see other entries than their own.
336
405
  */
337
- onBeforeEntryCreate: onEntryBeforeCreate,
338
- onAfterEntryCreate: onEntryAfterCreate,
339
- onBeforeEntryCreateRevision: onEntryBeforeCreateRevision,
340
- onAfterEntryCreateRevision: onEntryRevisionAfterCreate,
341
- onBeforeEntryUpdate: onEntryBeforeUpdate,
342
- onAfterEntryUpdate: onEntryAfterUpdate,
343
- onBeforeEntryDelete: onEntryBeforeDelete,
344
- onAfterEntryDelete: onEntryAfterDelete,
345
- onBeforeEntryDeleteRevision: onEntryRevisionBeforeDelete,
346
- onAfterEntryDeleteRevision: onEntryRevisionAfterDelete,
347
- onBeforeEntryPublish: onEntryBeforePublish,
348
- onAfterEntryPublish: onEntryAfterPublish,
349
- onBeforeEntryUnpublish: onEntryBeforeUnpublish,
350
- onAfterEntryUnpublish: onEntryAfterUnpublish,
351
- onBeforeEntryGet: onEntryBeforeGet,
352
- onBeforeEntryList: onEntryBeforeList,
406
+ const ownedBy = permission.own ? getIdentity().id : where.ownedBy;
407
+ if (ownedBy !== undefined) {
408
+ where.ownedBy = ownedBy;
409
+ }
353
410
  /**
354
- * Released in 5.34.0
355
- *
356
- * Create
411
+ * Where must contain either latest or published keys.
412
+ * We cannot list entries without one of those
357
413
  */
358
- onEntryBeforeCreate,
359
- onEntryAfterCreate,
360
- onEntryCreateError,
414
+ if (where.latest && where.published) {
415
+ throw new _error.default("Cannot list entries that are both published and latest.", "LIST_ENTRIES_ERROR", {
416
+ where
417
+ });
418
+ } else if (!where.latest && !where.published) {
419
+ throw new _error.default("Cannot list entries if we do not have latest or published defined.", "LIST_ENTRIES_ERROR", {
420
+ where
421
+ });
422
+ }
423
+ const fields = (0, _searchableFields.getSearchableFields)({
424
+ fields: model.fields,
425
+ plugins: context.plugins,
426
+ input: params.fields || []
427
+ });
428
+ try {
429
+ await onEntryBeforeList.publish({
430
+ where,
431
+ model
432
+ });
433
+ const {
434
+ hasMoreItems,
435
+ totalCount,
436
+ cursor,
437
+ items
438
+ } = await storageOperations.entries.list(model, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, params), {}, {
439
+ limit,
440
+ where,
441
+ fields
442
+ }));
443
+ const meta = {
444
+ hasMoreItems,
445
+ totalCount,
446
+ /**
447
+ * Cursor should be null if there are no more items to load.
448
+ * Just make sure of that, disregarding what is returned from the storageOperations.entries.list method.
449
+ */
450
+ cursor: hasMoreItems ? cursor : null
451
+ };
452
+ return [items, meta];
453
+ } catch (ex) {
454
+ throw new _error.default("Error while fetching entries from storage.", "LIST_ENTRIES_ERROR", {
455
+ params,
456
+ error: {
457
+ message: ex.message,
458
+ code: ex.code,
459
+ data: ex.data
460
+ },
461
+ model,
462
+ fields
463
+ });
464
+ }
465
+ };
466
+ const createEntry = async (model, inputData) => {
467
+ await checkEntryPermissions({
468
+ rwd: "w"
469
+ });
470
+ await (0, _access.checkModelAccess)(context, model);
471
+
361
472
  /**
362
- * Create revision
473
+ * Make sure we only work with fields that are defined in the model.
363
474
  */
364
- onEntryRevisionBeforeCreate: onEntryBeforeCreateRevision,
365
- onEntryRevisionAfterCreate,
366
- onEntryRevisionCreateError: onEntryCreateRevisionError,
475
+ const initialInput = mapAndCleanCreateInputData(model, inputData);
476
+ await (0, _entryDataValidation.validateModelEntryData)({
477
+ context,
478
+ model,
479
+ data: initialInput
480
+ });
481
+ const input = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
482
+ context,
483
+ model,
484
+ input: initialInput,
485
+ validateEntries: true
486
+ });
487
+ const locale = getLocale();
488
+ const owner = getCreatedBy();
489
+ const {
490
+ id,
491
+ entryId,
492
+ version
493
+ } = createEntryId(inputData);
367
494
  /**
368
- * Update
495
+ * There is a possibility that user sends an ID in the input, so we will use that one.
496
+ * There is no check if the ID is unique or not, that is up to the user.
369
497
  */
370
- onEntryBeforeUpdate,
371
- onEntryAfterUpdate,
372
- onEntryUpdateError,
498
+ const entry = {
499
+ webinyVersion: context.WEBINY_VERSION,
500
+ tenant: getTenant().id,
501
+ entryId,
502
+ id,
503
+ modelId: model.modelId,
504
+ locale: locale.code,
505
+ createdOn: new Date().toISOString(),
506
+ savedOn: new Date().toISOString(),
507
+ createdBy: owner,
508
+ ownedBy: owner,
509
+ modifiedBy: null,
510
+ version,
511
+ locked: false,
512
+ status: STATUS_DRAFT,
513
+ values: input
514
+ };
515
+ let storageEntry = null;
516
+ try {
517
+ await onEntryBeforeCreate.publish({
518
+ entry,
519
+ input,
520
+ model
521
+ });
522
+ storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
523
+ const result = await storageOperations.entries.create(model, {
524
+ entry,
525
+ storageEntry
526
+ });
527
+ await onEntryAfterCreate.publish({
528
+ entry,
529
+ storageEntry: result,
530
+ model,
531
+ input
532
+ });
533
+ return result;
534
+ } catch (ex) {
535
+ await onEntryCreateError.publish({
536
+ error: ex,
537
+ entry,
538
+ model,
539
+ input
540
+ });
541
+ throw new _error.default(ex.message || "Could not create content entry.", ex.code || "CREATE_ENTRY_ERROR", ex.data || {
542
+ error: ex,
543
+ input,
544
+ entry,
545
+ storageEntry
546
+ });
547
+ }
548
+ };
549
+ const createEntryRevisionFrom = async (model, sourceId, inputData) => {
550
+ const permission = await checkEntryPermissions({
551
+ rwd: "w"
552
+ });
553
+ await (0, _access.checkModelAccess)(context, model);
554
+
373
555
  /**
374
- * Delete whole entry
556
+ * Make sure we only work with fields that are defined in the model.
375
557
  */
376
- onEntryBeforeDelete,
377
- onEntryAfterDelete,
378
- onEntryDeleteError,
558
+ const input = mapAndCleanUpdatedInputData(model, inputData);
559
+
379
560
  /**
380
- * Delete entry revision
561
+ * Entries are identified by a common parent ID + Revision number.
381
562
  */
382
- onEntryRevisionBeforeDelete,
383
- onEntryRevisionAfterDelete,
384
- onEntryRevisionDeleteError,
563
+ const {
564
+ id: uniqueId
565
+ } = (0, _utils.parseIdentifier)(sourceId);
566
+ const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
567
+ id: sourceId
568
+ });
569
+ const latestStorageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
570
+ id: uniqueId
571
+ });
572
+ if (!originalStorageEntry) {
573
+ throw new _handlerGraphql.NotFoundError(`Entry "${sourceId}" of model "${model.modelId}" was not found.`);
574
+ }
575
+
385
576
  /**
386
- * Publish
577
+ * We need to convert data from DB to its original form before using it further.
387
578
  */
388
- onEntryBeforePublish,
389
- onEntryAfterPublish,
390
- onEntryPublishError,
579
+ const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
580
+ const initialValues = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry.values), input);
581
+ await (0, _entryDataValidation.validateModelEntryData)({
582
+ context,
583
+ model,
584
+ data: initialValues,
585
+ entry: originalEntry
586
+ });
587
+ const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
588
+ context,
589
+ model,
590
+ input: initialValues,
591
+ validateEntries: false
592
+ });
593
+ (0, _ownership.checkOwnership)(context, permission, originalEntry);
594
+ const identity = getIdentity();
595
+ const latestId = latestStorageEntry ? latestStorageEntry.id : sourceId;
596
+ const {
597
+ id,
598
+ version: nextVersion
599
+ } = increaseEntryIdVersion(latestId);
600
+ const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
601
+ id,
602
+ version: nextVersion,
603
+ savedOn: new Date().toISOString(),
604
+ createdOn: new Date().toISOString(),
605
+ createdBy: {
606
+ id: identity.id,
607
+ displayName: identity.displayName,
608
+ type: identity.type
609
+ },
610
+ modifiedBy: null,
611
+ locked: false,
612
+ publishedOn: undefined,
613
+ status: STATUS_DRAFT,
614
+ values
615
+ });
616
+ let storageEntry = null;
617
+ try {
618
+ await onEntryBeforeCreateRevision.publish({
619
+ input,
620
+ entry,
621
+ original: originalEntry,
622
+ model
623
+ });
624
+ storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
625
+ const result = await storageOperations.entries.createRevisionFrom(model, {
626
+ entry,
627
+ storageEntry
628
+ });
629
+ await onEntryRevisionAfterCreate.publish({
630
+ input,
631
+ entry,
632
+ model,
633
+ original: originalEntry,
634
+ storageEntry: result
635
+ });
636
+ return result;
637
+ } catch (ex) {
638
+ await onEntryCreateRevisionError.publish({
639
+ entry,
640
+ original: originalEntry,
641
+ model,
642
+ input,
643
+ error: ex
644
+ });
645
+ throw new _error.default(ex.message || "Could not create entry from existing one.", ex.code || "CREATE_FROM_REVISION_ERROR", {
646
+ error: ex,
647
+ entry,
648
+ storageEntry,
649
+ originalEntry,
650
+ originalStorageEntry
651
+ });
652
+ }
653
+ };
654
+ const updateEntry = async (model, id, inputData, metaInput) => {
655
+ const permission = await checkEntryPermissions({
656
+ rwd: "w"
657
+ });
658
+ await (0, _access.checkModelAccess)(context, model);
659
+
391
660
  /**
392
- * Republish
661
+ * Make sure we only work with fields that are defined in the model.
393
662
  */
394
- onEntryBeforeRepublish,
395
- onEntryAfterRepublish,
396
- onEntryRepublishError,
663
+ const input = mapAndCleanUpdatedInputData(model, inputData);
664
+
397
665
  /**
398
- * Unpublish
666
+ * The entry we are going to update.
399
667
  */
400
- onEntryBeforeUnpublish,
401
- onEntryAfterUnpublish,
402
- onEntryUnpublishError,
403
- onEntryBeforeGet,
404
- onEntryBeforeList,
668
+ const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
669
+ id
670
+ });
671
+ if (!originalStorageEntry) {
672
+ throw new _handlerGraphql.NotFoundError(`Entry "${id}" of model "${model.modelId}" was not found.`);
673
+ }
674
+ if (originalStorageEntry.locked) {
675
+ throw new _error.default(`Cannot update entry because it's locked.`, "CONTENT_ENTRY_UPDATE_ERROR");
676
+ }
677
+ const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
678
+ await (0, _entryDataValidation.validateModelEntryData)({
679
+ context,
680
+ model,
681
+ data: input,
682
+ entry: originalEntry
683
+ });
684
+ (0, _ownership.checkOwnership)(context, permission, originalEntry);
685
+ const initialValues = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry.values), input);
686
+ const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
687
+ context,
688
+ model,
689
+ input: initialValues,
690
+ validateEntries: false
691
+ });
405
692
  /**
406
- * Get entries by exact revision IDs from the database.
693
+ * If users wants to remove a key from meta values, they need to send meta key with the null value.
407
694
  */
408
- getEntriesByIds: getEntriesByIds,
695
+ const meta = createEntryMeta(metaInput, originalEntry.meta);
409
696
  /**
410
- * Get a single entry by revision ID from the database.
697
+ * We always send the full entry to the hooks and storage operations update.
411
698
  */
412
- async getEntryById(initialModel, id) {
413
- const where = {
414
- id
415
- };
416
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
417
- model: initialModel,
418
- plugins
699
+ const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
700
+ savedOn: new Date().toISOString(),
701
+ modifiedBy: getCreatedBy(),
702
+ values,
703
+ meta,
704
+ status: transformEntryStatus(originalEntry.status)
705
+ });
706
+ let storageEntry = null;
707
+ try {
708
+ await onEntryBeforeUpdate.publish({
709
+ entry,
710
+ model,
711
+ input,
712
+ original: originalEntry
419
713
  });
420
- await onEntryBeforeGet.publish({
421
- where,
422
- model
714
+ storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
715
+ const result = await storageOperations.entries.update(model, {
716
+ entry,
717
+ storageEntry
423
718
  });
424
- const [entry] = await getEntriesByIds(model, [id]);
425
- if (!entry) {
426
- throw new _handlerGraphql.NotFoundError(`Entry by ID "${id}" not found.`);
427
- }
428
- return entry;
429
- },
430
- /**
431
- * Get published revisions by entry IDs.
432
- */
433
- async getPublishedEntriesByIds(initialModel, ids) {
434
- const permission = await checkEntryPermissions({
435
- rwd: "r"
719
+ await onEntryAfterUpdate.publish({
720
+ entry,
721
+ storageEntry: result,
722
+ model,
723
+ input,
724
+ original: originalEntry
436
725
  });
437
- await (0, _access.checkModelAccess)(context, initialModel);
438
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
439
- model: initialModel,
440
- plugins
726
+ return result;
727
+ } catch (ex) {
728
+ await onEntryUpdateError.publish({
729
+ entry,
730
+ model,
731
+ input,
732
+ error: ex
441
733
  });
442
- const entries = await storageOperations.entries.getPublishedByIds(model, {
443
- ids
734
+ throw new _error.default(ex.message || "Could not update existing entry.", ex.code || "UPDATE_ERROR", {
735
+ error: ex,
736
+ entry,
737
+ storageEntry,
738
+ originalEntry,
739
+ input
444
740
  });
445
- return entries.filter(entry => (0, _ownership.validateOwnership)(context, permission, entry));
446
- },
741
+ }
742
+ };
743
+ const republishEntry = async (model, id) => {
744
+ await checkEntryPermissions({
745
+ rwd: "w"
746
+ });
747
+ await (0, _access.checkModelAccess)(context, model);
447
748
  /**
448
- * Get the latest revisions by entry IDs.
749
+ * Fetch the entry from the storage.
449
750
  */
450
- async getLatestEntriesByIds(initialModel, ids) {
451
- const permission = await checkEntryPermissions({
452
- rwd: "r"
751
+ const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
752
+ id
753
+ });
754
+ if (!originalStorageEntry) {
755
+ throw new _handlerGraphql.NotFoundError(`Entry "${id}" was not found!`);
756
+ }
757
+ const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
758
+ /**
759
+ * We can only process published entries.
760
+ */
761
+ if (originalEntry.status !== "published") {
762
+ throw new _error.default("Entry with given ID is not published!", "NOT_PUBLISHED_ERROR", {
763
+ id,
764
+ original: originalEntry
453
765
  });
454
- await (0, _access.checkModelAccess)(context, initialModel);
455
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
456
- model: initialModel,
457
- plugins
766
+ }
767
+ const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
768
+ context,
769
+ model,
770
+ input: originalEntry.values,
771
+ validateEntries: false
772
+ });
773
+ const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
774
+ savedOn: new Date().toISOString(),
775
+ webinyVersion: context.WEBINY_VERSION,
776
+ values
777
+ });
778
+ const storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
779
+ /**
780
+ * First we need to update existing entry.
781
+ */
782
+ try {
783
+ await storageOperations.entries.update(model, {
784
+ entry,
785
+ storageEntry
458
786
  });
459
- const entries = await storageOperations.entries.getLatestByIds(model, {
460
- ids
787
+ } catch (ex) {
788
+ throw new _error.default("Could not update existing entry with new data while re-publishing.", "REPUBLISH_UPDATE_ERROR", {
789
+ entry
461
790
  });
462
- return entries.filter(entry => (0, _ownership.validateOwnership)(context, permission, entry));
463
- },
464
- async getEntryRevisions(initialModel, entryId) {
465
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
466
- model: initialModel,
467
- plugins
791
+ }
792
+ /**
793
+ * Then we move onto publishing it again.
794
+ */
795
+ try {
796
+ await onEntryBeforeRepublish.publish({
797
+ entry,
798
+ model
468
799
  });
469
- return storageOperations.entries.getRevisions(model, {
470
- id: entryId
800
+ const result = await storageOperations.entries.publish(model, {
801
+ entry,
802
+ storageEntry
471
803
  });
472
- },
804
+ await onEntryAfterRepublish.publish({
805
+ entry,
806
+ model,
807
+ storageEntry
808
+ });
809
+ return result;
810
+ } catch (ex) {
811
+ await onEntryRepublishError.publish({
812
+ entry,
813
+ model,
814
+ error: ex
815
+ });
816
+ throw new _error.default("Could not publish existing entry while re-publishing.", "REPUBLISH_PUBLISH_ERROR", {
817
+ entry
818
+ });
819
+ }
820
+ };
821
+ const deleteEntryRevision = async (model, revisionId) => {
822
+ const permission = await checkEntryPermissions({
823
+ rwd: "d"
824
+ });
825
+ await (0, _access.checkModelAccess)(context, model);
826
+ const {
827
+ id: entryId,
828
+ version
829
+ } = (0, _utils.parseIdentifier)(revisionId);
830
+ const storageEntryToDelete = await storageOperations.entries.getRevisionById(model, {
831
+ id: revisionId
832
+ });
833
+ const latestStorageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
834
+ id: entryId
835
+ });
836
+ const previousStorageEntry = await storageOperations.entries.getPreviousRevision(model, {
837
+ entryId,
838
+ version: version
839
+ });
840
+ if (!storageEntryToDelete) {
841
+ throw new _handlerGraphql.NotFoundError(`Entry "${revisionId}" was not found!`);
842
+ }
843
+ (0, _ownership.checkOwnership)(context, permission, storageEntryToDelete);
844
+ const latestEntryRevisionId = latestStorageEntry ? latestStorageEntry.id : null;
845
+ const entryToDelete = await (0, _entryStorage.entryFromStorageTransform)(context, model, storageEntryToDelete);
473
846
  /**
474
- * TODO determine if this method is required at all.
475
- *
476
- * @internal
847
+ * If targeted record is the latest entry record and there is no previous one, we need to run full delete with hooks.
848
+ * At this point deleteRevision hooks are not fired.
477
849
  */
478
- async getEntry(initialModel, params) {
479
- await checkEntryPermissions({
480
- rwd: "r"
850
+ if (entryToDelete.id === latestEntryRevisionId && !previousStorageEntry) {
851
+ return await deleteEntryHelper({
852
+ model,
853
+ entry: entryToDelete
854
+ });
855
+ }
856
+ /**
857
+ * If targeted record is latest entry revision, set the previous one as the new latest
858
+ */
859
+ let entryToSetAsLatest = null;
860
+ let storageEntryToSetAsLatest = null;
861
+ if (entryToDelete.id === latestEntryRevisionId && previousStorageEntry) {
862
+ entryToSetAsLatest = await (0, _entryStorage.entryFromStorageTransform)(context, model, previousStorageEntry);
863
+ storageEntryToSetAsLatest = previousStorageEntry;
864
+ }
865
+ try {
866
+ await onEntryRevisionBeforeDelete.publish({
867
+ entry: entryToDelete,
868
+ model
481
869
  });
482
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
483
- model: initialModel,
484
- plugins
870
+ await storageOperations.entries.deleteRevision(model, {
871
+ entry: entryToDelete,
872
+ storageEntry: storageEntryToDelete,
873
+ latestEntry: entryToSetAsLatest,
874
+ latestStorageEntry: storageEntryToSetAsLatest
485
875
  });
486
- const {
487
- where,
488
- sort
489
- } = params;
490
- await onEntryBeforeGet.publish({
491
- where,
876
+ await onEntryRevisionAfterDelete.publish({
877
+ entry: entryToDelete,
878
+ model
879
+ });
880
+ } catch (ex) {
881
+ await onEntryRevisionDeleteError.publish({
882
+ entry: entryToDelete,
883
+ model,
884
+ error: ex
885
+ });
886
+ throw new _error.default(ex.message, ex.code || "DELETE_REVISION_ERROR", {
887
+ error: ex,
888
+ entry: entryToDelete,
889
+ storageEntry: storageEntryToDelete,
890
+ latestEntry: entryToSetAsLatest,
891
+ latestStorageEntry: storageEntryToSetAsLatest
892
+ });
893
+ }
894
+ };
895
+ const deleteEntry = async (model, entryId) => {
896
+ const permission = await checkEntryPermissions({
897
+ rwd: "d"
898
+ });
899
+ await (0, _access.checkModelAccess)(context, model);
900
+ const storageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
901
+ id: entryId
902
+ });
903
+ if (!storageEntry) {
904
+ throw new _handlerGraphql.NotFoundError(`Entry "${entryId}" was not found!`);
905
+ }
906
+ (0, _ownership.checkOwnership)(context, permission, storageEntry);
907
+ const entry = await (0, _entryStorage.entryFromStorageTransform)(context, model, storageEntry);
908
+ return await deleteEntryHelper({
909
+ model,
910
+ entry
911
+ });
912
+ };
913
+ const publishEntry = async (model, id) => {
914
+ const permission = await checkEntryPermissions({
915
+ pw: "p"
916
+ });
917
+ await (0, _access.checkModelAccess)(context, model);
918
+ const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
919
+ id
920
+ });
921
+ if (!originalStorageEntry) {
922
+ throw new _handlerGraphql.NotFoundError(`Entry "${id}" in the model "${model.modelId}" was not found.`);
923
+ }
924
+ (0, _ownership.checkOwnership)(context, permission, originalStorageEntry);
925
+ const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
926
+ const currentDate = new Date().toISOString();
927
+ const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
928
+ status: STATUS_PUBLISHED,
929
+ locked: true,
930
+ savedOn: currentDate,
931
+ publishedOn: currentDate
932
+ });
933
+ let storageEntry = null;
934
+ try {
935
+ await onEntryBeforePublish.publish({
936
+ entry,
937
+ model
938
+ });
939
+ storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
940
+ const result = await storageOperations.entries.publish(model, {
941
+ entry,
942
+ storageEntry
943
+ });
944
+ await onEntryAfterPublish.publish({
945
+ entry,
946
+ storageEntry: result,
947
+ model
948
+ });
949
+ return result;
950
+ } catch (ex) {
951
+ await onEntryPublishError.publish({
952
+ entry,
953
+ model,
954
+ error: ex
955
+ });
956
+ throw new _error.default(ex.message || "Could not publish entry.", ex.code || "PUBLISH_ERROR", {
957
+ error: ex,
958
+ entry,
959
+ storageEntry,
960
+ originalEntry,
961
+ originalStorageEntry
962
+ });
963
+ }
964
+ };
965
+ const unpublishEntry = async (model, id) => {
966
+ const permission = await checkEntryPermissions({
967
+ pw: "u"
968
+ });
969
+ const {
970
+ id: entryId
971
+ } = (0, _utils.parseIdentifier)(id);
972
+ const originalStorageEntry = await storageOperations.entries.getPublishedRevisionByEntryId(model, {
973
+ id: entryId
974
+ });
975
+ if (!originalStorageEntry) {
976
+ throw new _handlerGraphql.NotFoundError(`Entry "${id}" of model "${model.modelId}" was not found.`);
977
+ }
978
+ if (originalStorageEntry.id !== id) {
979
+ throw new _error.default(`Entry is not published.`, "UNPUBLISH_ERROR", {
980
+ entry: originalStorageEntry
981
+ });
982
+ }
983
+ (0, _ownership.checkOwnership)(context, permission, originalStorageEntry);
984
+ const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
985
+ const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
986
+ status: STATUS_UNPUBLISHED
987
+ });
988
+ let storageEntry = null;
989
+ try {
990
+ await onEntryBeforeUnpublish.publish({
991
+ entry,
992
+ model
993
+ });
994
+ storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
995
+ const result = await storageOperations.entries.unpublish(model, {
996
+ entry,
997
+ storageEntry
998
+ });
999
+ await onEntryAfterUnpublish.publish({
1000
+ entry,
1001
+ storageEntry: result,
492
1002
  model
493
1003
  });
494
- const [items] = await this.listEntries(model, {
1004
+ return result;
1005
+ } catch (ex) {
1006
+ await onEntryUnpublishError.publish({
1007
+ entry,
1008
+ model,
1009
+ error: ex
1010
+ });
1011
+ throw new _error.default(ex.message || "Could not unpublish entry.", ex.code || "UNPUBLISH_ERROR", {
1012
+ originalEntry,
1013
+ originalStorageEntry,
1014
+ entry,
1015
+ storageEntry
1016
+ });
1017
+ }
1018
+ };
1019
+ const getUniqueFieldValues = async (model, params) => {
1020
+ const permission = await checkEntryPermissions({
1021
+ rwd: "r"
1022
+ });
1023
+ await (0, _access.checkModelAccess)(context, model);
1024
+ const {
1025
+ where: initialWhere,
1026
+ fieldId
1027
+ } = params;
1028
+ const where = (0, _objectSpread2.default)({}, initialWhere);
1029
+ /**
1030
+ * Possibly only get records which are owned by current user.
1031
+ * Or if searching for the owner set that value - in the case that user can see other entries than their own.
1032
+ */
1033
+ const ownedBy = permission.own ? getIdentity().id : where.ownedBy;
1034
+ if (ownedBy !== undefined) {
1035
+ where.ownedBy = ownedBy;
1036
+ }
1037
+ /**
1038
+ * Where must contain either latest or published keys.
1039
+ * We cannot list entries without one of those
1040
+ */
1041
+ if (where.latest && where.published) {
1042
+ throw new _error.default("Cannot list entries that are both published and latest.", "LIST_ENTRIES_ERROR", {
1043
+ where
1044
+ });
1045
+ } else if (!where.latest && !where.published) {
1046
+ throw new _error.default("Cannot list entries if we do not have latest or published defined.", "LIST_ENTRIES_ERROR", {
1047
+ where
1048
+ });
1049
+ }
1050
+ /**
1051
+ * We need to verify that the field in question is searchable.
1052
+ */
1053
+ const fields = (0, _searchableFields.getSearchableFields)({
1054
+ fields: model.fields,
1055
+ plugins: context.plugins,
1056
+ input: []
1057
+ });
1058
+ if (fields.includes(fieldId) === false) {
1059
+ throw new _error.default("Cannot list unique entry field values if the field is not searchable.", "LIST_UNIQUE_ENTRY_VALUES_ERROR", {
1060
+ fieldId
1061
+ });
1062
+ }
1063
+ try {
1064
+ return await storageOperations.entries.getUniqueFieldValues(model, {
495
1065
  where,
496
- sort,
497
- limit: 1
1066
+ fieldId
1067
+ });
1068
+ } catch (ex) {
1069
+ throw new _error.default("Error while fetching unique entry values from storage.", "LIST_UNIQUE_ENTRY_VALUES_ERROR", {
1070
+ error: {
1071
+ message: ex.message,
1072
+ code: ex.code,
1073
+ data: ex.data
1074
+ },
1075
+ model,
1076
+ where,
1077
+ fieldId
1078
+ });
1079
+ }
1080
+ };
1081
+ return {
1082
+ /**
1083
+ * Deprecated - will be removed in 5.35.0
1084
+ */
1085
+ onBeforeEntryCreate: onEntryBeforeCreate,
1086
+ onAfterEntryCreate: onEntryAfterCreate,
1087
+ onBeforeEntryCreateRevision: onEntryBeforeCreateRevision,
1088
+ onAfterEntryCreateRevision: onEntryRevisionAfterCreate,
1089
+ onBeforeEntryUpdate: onEntryBeforeUpdate,
1090
+ onAfterEntryUpdate: onEntryAfterUpdate,
1091
+ onBeforeEntryDelete: onEntryBeforeDelete,
1092
+ onAfterEntryDelete: onEntryAfterDelete,
1093
+ onBeforeEntryDeleteRevision: onEntryRevisionBeforeDelete,
1094
+ onAfterEntryDeleteRevision: onEntryRevisionAfterDelete,
1095
+ onBeforeEntryPublish: onEntryBeforePublish,
1096
+ onAfterEntryPublish: onEntryAfterPublish,
1097
+ onBeforeEntryUnpublish: onEntryBeforeUnpublish,
1098
+ onAfterEntryUnpublish: onEntryAfterUnpublish,
1099
+ onBeforeEntryGet: onEntryBeforeGet,
1100
+ onBeforeEntryList: onEntryBeforeList,
1101
+ /**
1102
+ * Released in 5.34.0
1103
+ *
1104
+ * Create
1105
+ */
1106
+ onEntryBeforeCreate,
1107
+ onEntryAfterCreate,
1108
+ onEntryCreateError,
1109
+ /**
1110
+ * Create revision
1111
+ */
1112
+ onEntryRevisionBeforeCreate: onEntryBeforeCreateRevision,
1113
+ onEntryRevisionAfterCreate,
1114
+ onEntryRevisionCreateError: onEntryCreateRevisionError,
1115
+ /**
1116
+ * Update
1117
+ */
1118
+ onEntryBeforeUpdate,
1119
+ onEntryAfterUpdate,
1120
+ onEntryUpdateError,
1121
+ /**
1122
+ * Delete whole entry
1123
+ */
1124
+ onEntryBeforeDelete,
1125
+ onEntryAfterDelete,
1126
+ onEntryDeleteError,
1127
+ /**
1128
+ * Delete entry revision
1129
+ */
1130
+ onEntryRevisionBeforeDelete,
1131
+ onEntryRevisionAfterDelete,
1132
+ onEntryRevisionDeleteError,
1133
+ /**
1134
+ * Publish
1135
+ */
1136
+ onEntryBeforePublish,
1137
+ onEntryAfterPublish,
1138
+ onEntryPublishError,
1139
+ /**
1140
+ * Republish
1141
+ */
1142
+ onEntryBeforeRepublish,
1143
+ onEntryAfterRepublish,
1144
+ onEntryRepublishError,
1145
+ /**
1146
+ * Unpublish
1147
+ */
1148
+ onEntryBeforeUnpublish,
1149
+ onEntryAfterUnpublish,
1150
+ onEntryUnpublishError,
1151
+ onEntryBeforeGet,
1152
+ onEntryBeforeList,
1153
+ /**
1154
+ * Get entries by exact revision IDs from the database.
1155
+ */
1156
+ getEntriesByIds,
1157
+ /**
1158
+ * Get a single entry by revision ID from the database.
1159
+ */
1160
+ async getEntryById(model, id) {
1161
+ return context.benchmark.measure("headlessCms.crud.entries.getEntryById", async () => {
1162
+ return getEntryById(model, id);
498
1163
  });
499
- if (items.length === 0) {
500
- throw new _handlerGraphql.NotFoundError(`Entry not found!`);
501
- }
502
- return items[0];
503
1164
  },
504
1165
  /**
505
- * @description Should not be used directly. Internal use only!
1166
+ * Get published revisions by entry IDs.
1167
+ */
1168
+ async getPublishedEntriesByIds(model, ids) {
1169
+ return context.benchmark.measure("headlessCms.crud.entries.getPublishedEntriesByIds", async () => {
1170
+ return getPublishedEntriesByIds(model, ids);
1171
+ });
1172
+ },
1173
+ /**
1174
+ * Get the latest revisions by entry IDs.
1175
+ */
1176
+ async getLatestEntriesByIds(model, ids) {
1177
+ return context.benchmark.measure("headlessCms.crud.entries.getLatestEntriesByIds", async () => {
1178
+ return getLatestEntriesByIds(model, ids);
1179
+ });
1180
+ },
1181
+ async getEntryRevisions(model, entryId) {
1182
+ return context.benchmark.measure("headlessCms.crud.entries.getEntryRevisions", async () => {
1183
+ return getEntryRevisions(model, entryId);
1184
+ });
1185
+ },
1186
+ /**
1187
+ * TODO determine if this method is required at all.
506
1188
  *
507
1189
  * @internal
508
1190
  */
509
- async listEntries(initialModel, params) {
510
- const permission = await checkEntryPermissions({
511
- rwd: "r"
1191
+ async getEntry(model, params) {
1192
+ return context.benchmark.measure("headlessCms.crud.entries.getEntry", async () => {
1193
+ return getEntry(model, params);
512
1194
  });
513
- await (0, _access.checkModelAccess)(context, initialModel);
514
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
515
- model: initialModel,
516
- plugins
517
- });
518
- const {
519
- where: initialWhere,
520
- limit: initialLimit
521
- } = params;
522
- const limit = initialLimit && initialLimit > 0 ? initialLimit : 50;
523
- /**
524
- * We always assign tenant and locale because we do not allow one model to have content through multiple tenants.
525
- */
526
- const where = (0, _objectSpread2.default)({}, initialWhere);
527
- /**
528
- * Possibly only get records which are owned by current user.
529
- * Or if searching for the owner set that value - in the case that user can see other entries than their own.
530
- */
531
- const ownedBy = permission.own ? getIdentity().id : where.ownedBy;
532
- if (ownedBy !== undefined) {
533
- where.ownedBy = ownedBy;
534
- }
535
- /**
536
- * Where must contain either latest or published keys.
537
- * We cannot list entries without one of those
538
- */
539
- if (where.latest && where.published) {
540
- throw new _error.default("Cannot list entries that are both published and latest.", "LIST_ENTRIES_ERROR", {
541
- where
542
- });
543
- } else if (!where.latest && !where.published) {
544
- throw new _error.default("Cannot list entries if we do not have latest or published defined.", "LIST_ENTRIES_ERROR", {
545
- where
546
- });
547
- }
548
- const fields = (0, _searchableFields.getSearchableFields)({
549
- fields: model.fields,
550
- plugins: context.plugins,
551
- input: params.fields || []
1195
+ },
1196
+ /**
1197
+ * @description Should not be used directly. Internal use only!
1198
+ *
1199
+ * @internal
1200
+ */
1201
+ async listEntries(model, params) {
1202
+ return context.benchmark.measure("headlessCms.crud.entries.listEntries", async () => {
1203
+ return listEntries(model, params);
552
1204
  });
553
- try {
554
- await onEntryBeforeList.publish({
555
- where,
556
- model
557
- });
558
- const {
559
- hasMoreItems,
560
- totalCount,
561
- cursor,
562
- items
563
- } = await storageOperations.entries.list(model, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, params), {}, {
564
- limit,
565
- where,
566
- fields
567
- }));
568
- const meta = {
569
- hasMoreItems,
570
- totalCount,
571
- /**
572
- * Cursor should be null if there are no more items to load.
573
- * Just make sure of that, disregarding what is returned from the storageOperations.entries.list method.
574
- */
575
- cursor: hasMoreItems ? cursor : null
576
- };
577
- return [items, meta];
578
- } catch (ex) {
579
- throw new _error.default("Error while fetching entries from storage.", "LIST_ENTRIES_ERROR", {
580
- params,
581
- error: {
582
- message: ex.message,
583
- code: ex.code,
584
- data: ex.data
585
- },
586
- model,
587
- fields
588
- });
589
- }
590
1205
  },
591
1206
  async listLatestEntries(model, params) {
592
1207
  const where = (params === null || params === void 0 ? void 0 : params.where) || {};
@@ -608,594 +1223,54 @@ const createContentEntryCrud = params => {
608
1223
  })
609
1224
  }));
610
1225
  },
611
- async createEntry(initialModel, inputData) {
612
- await checkEntryPermissions({
613
- rwd: "w"
1226
+ async createEntry(model, input) {
1227
+ return context.benchmark.measure("headlessCms.crud.entries.createEntry", async () => {
1228
+ return createEntry(model, input);
614
1229
  });
615
- await (0, _access.checkModelAccess)(context, initialModel);
616
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
617
- model: initialModel,
618
- plugins
619
- });
620
-
621
- /**
622
- * Make sure we only work with fields that are defined in the model.
623
- */
624
- const initialInput = mapAndCleanCreateInputData(model, inputData);
625
- await (0, _entryDataValidation.validateModelEntryData)({
626
- context,
627
- model,
628
- data: initialInput
629
- });
630
- const input = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
631
- context,
632
- model,
633
- input: initialInput,
634
- validateEntries: true
635
- });
636
- const locale = this.getLocale();
637
- const owner = getCreatedBy();
638
- const {
639
- id,
640
- entryId,
641
- version
642
- } = createEntryId(inputData);
643
- /**
644
- * There is a possibility that user sends an ID in the input, so we will use that one.
645
- * There is no check if the ID is unique or not, that is up to the user.
646
- */
647
- const entry = {
648
- webinyVersion: context.WEBINY_VERSION,
649
- tenant: getTenant().id,
650
- entryId,
651
- id,
652
- modelId: model.modelId,
653
- locale: locale.code,
654
- createdOn: new Date().toISOString(),
655
- savedOn: new Date().toISOString(),
656
- createdBy: owner,
657
- ownedBy: owner,
658
- modifiedBy: null,
659
- version,
660
- locked: false,
661
- status: STATUS_DRAFT,
662
- values: input
663
- };
664
- let storageEntry = null;
665
- try {
666
- await onEntryBeforeCreate.publish({
667
- entry,
668
- input,
669
- model
670
- });
671
- storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
672
- const result = await storageOperations.entries.create(model, {
673
- entry,
674
- storageEntry
675
- });
676
- await onEntryAfterCreate.publish({
677
- entry,
678
- storageEntry: result,
679
- model,
680
- input
681
- });
682
- return result;
683
- } catch (ex) {
684
- await onEntryCreateError.publish({
685
- error: ex,
686
- entry,
687
- model,
688
- input
689
- });
690
- throw new _error.default(ex.message || "Could not create content entry.", ex.code || "CREATE_ENTRY_ERROR", ex.data || {
691
- error: ex,
692
- input,
693
- entry,
694
- storageEntry
695
- });
696
- }
697
1230
  },
698
- async createEntryRevisionFrom(initialModel, sourceId, inputData) {
699
- const permission = await checkEntryPermissions({
700
- rwd: "w"
1231
+ async createEntryRevisionFrom(model, sourceId, input) {
1232
+ return context.benchmark.measure("headlessCms.crud.entries.createEntryRevisionFrom", async () => {
1233
+ return createEntryRevisionFrom(model, sourceId, input);
701
1234
  });
702
- await (0, _access.checkModelAccess)(context, initialModel);
703
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
704
- model: initialModel,
705
- plugins
706
- });
707
-
708
- /**
709
- * Make sure we only work with fields that are defined in the model.
710
- */
711
- const input = mapAndCleanUpdatedInputData(model, inputData);
712
-
713
- /**
714
- * Entries are identified by a common parent ID + Revision number.
715
- */
716
- const {
717
- id: uniqueId
718
- } = (0, _utils.parseIdentifier)(sourceId);
719
- const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
720
- id: sourceId
721
- });
722
- const latestStorageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
723
- id: uniqueId
724
- });
725
- if (!originalStorageEntry) {
726
- throw new _handlerGraphql.NotFoundError(`Entry "${sourceId}" of model "${model.modelId}" was not found.`);
727
- }
728
-
729
- /**
730
- * We need to convert data from DB to its original form before using it further.
731
- */
732
- const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
733
- const initialValues = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry.values), input);
734
- await (0, _entryDataValidation.validateModelEntryData)({
735
- context,
736
- model,
737
- data: initialValues,
738
- entry: originalEntry
739
- });
740
- const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
741
- context,
742
- model,
743
- input: initialValues,
744
- validateEntries: false
745
- });
746
- (0, _ownership.checkOwnership)(context, permission, originalEntry);
747
- const identity = getIdentity();
748
- const latestId = latestStorageEntry ? latestStorageEntry.id : sourceId;
749
- const {
750
- id,
751
- version: nextVersion
752
- } = increaseEntryIdVersion(latestId);
753
- const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
754
- id,
755
- version: nextVersion,
756
- savedOn: new Date().toISOString(),
757
- createdOn: new Date().toISOString(),
758
- createdBy: {
759
- id: identity.id,
760
- displayName: identity.displayName,
761
- type: identity.type
762
- },
763
- modifiedBy: null,
764
- locked: false,
765
- publishedOn: undefined,
766
- status: STATUS_DRAFT,
767
- values
768
- });
769
- let storageEntry = null;
770
- try {
771
- await onEntryBeforeCreateRevision.publish({
772
- input,
773
- entry,
774
- original: originalEntry,
775
- model
776
- });
777
- storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
778
- const result = await storageOperations.entries.createRevisionFrom(model, {
779
- entry,
780
- storageEntry
781
- });
782
- await onEntryRevisionAfterCreate.publish({
783
- input,
784
- entry,
785
- model,
786
- original: originalEntry,
787
- storageEntry: result
788
- });
789
- return result;
790
- } catch (ex) {
791
- await onEntryCreateRevisionError.publish({
792
- entry,
793
- original: originalEntry,
794
- model,
795
- input,
796
- error: ex
797
- });
798
- throw new _error.default(ex.message || "Could not create entry from existing one.", ex.code || "CREATE_FROM_REVISION_ERROR", {
799
- error: ex,
800
- entry,
801
- storageEntry,
802
- originalEntry,
803
- originalStorageEntry
804
- });
805
- }
806
1235
  },
807
- async updateEntry(initialModel, id, inputData, metaInput) {
808
- const permission = await checkEntryPermissions({
809
- rwd: "w"
810
- });
811
- await (0, _access.checkModelAccess)(context, initialModel);
812
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
813
- model: initialModel,
814
- plugins
1236
+ async updateEntry(model, id, input, meta) {
1237
+ return context.benchmark.measure("headlessCms.crud.entries.updateEntry", async () => {
1238
+ return updateEntry(model, id, input, meta);
815
1239
  });
816
-
817
- /**
818
- * Make sure we only work with fields that are defined in the model.
819
- */
820
- const input = mapAndCleanUpdatedInputData(model, inputData);
821
-
822
- /**
823
- * The entry we are going to update.
824
- */
825
- const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
826
- id
827
- });
828
- if (!originalStorageEntry) {
829
- throw new _handlerGraphql.NotFoundError(`Entry "${id}" of model "${model.modelId}" was not found.`);
830
- }
831
- if (originalStorageEntry.locked) {
832
- throw new _error.default(`Cannot update entry because it's locked.`, "CONTENT_ENTRY_UPDATE_ERROR");
833
- }
834
- const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
835
- await (0, _entryDataValidation.validateModelEntryData)({
836
- context,
837
- model,
838
- data: input,
839
- entry: originalEntry
840
- });
841
- (0, _ownership.checkOwnership)(context, permission, originalEntry);
842
- const initialValues = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry.values), input);
843
- const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
844
- context,
845
- model,
846
- input: initialValues,
847
- validateEntries: false
848
- });
849
- /**
850
- * If users wants to remove a key from meta values, they need to send meta key with the null value.
851
- */
852
- const meta = createEntryMeta(metaInput, originalEntry.meta);
853
- /**
854
- * We always send the full entry to the hooks and storage operations update.
855
- */
856
- const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
857
- savedOn: new Date().toISOString(),
858
- modifiedBy: getCreatedBy(),
859
- values,
860
- meta,
861
- status: transformEntryStatus(originalEntry.status)
862
- });
863
- let storageEntry = null;
864
- try {
865
- await onEntryBeforeUpdate.publish({
866
- entry,
867
- model,
868
- input,
869
- original: originalEntry
870
- });
871
- storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
872
- const result = await storageOperations.entries.update(model, {
873
- entry,
874
- storageEntry
875
- });
876
- await onEntryAfterUpdate.publish({
877
- entry,
878
- storageEntry: result,
879
- model,
880
- input,
881
- original: originalEntry
882
- });
883
- return result;
884
- } catch (ex) {
885
- await onEntryUpdateError.publish({
886
- entry,
887
- model,
888
- input,
889
- error: ex
890
- });
891
- throw new _error.default(ex.message || "Could not update existing entry.", ex.code || "UPDATE_ERROR", {
892
- error: ex,
893
- entry,
894
- storageEntry,
895
- originalEntry,
896
- input
897
- });
898
- }
899
1240
  },
900
1241
  /**
901
1242
  * Method used internally. Not documented and should not be used in users systems.
902
1243
  * @internal
903
1244
  */
904
- async republishEntry(initialModel, id) {
905
- await checkEntryPermissions({
906
- rwd: "w"
907
- });
908
- await (0, _access.checkModelAccess)(context, initialModel);
909
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
910
- model: initialModel,
911
- plugins
912
- });
913
- /**
914
- * Fetch the entry from the storage.
915
- */
916
- const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
917
- id
918
- });
919
- if (!originalStorageEntry) {
920
- throw new _handlerGraphql.NotFoundError(`Entry "${id}" was not found!`);
921
- }
922
- const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
923
- /**
924
- * We can only process published entries.
925
- */
926
- if (originalEntry.status !== "published") {
927
- throw new _error.default("Entry with given ID is not published!", "NOT_PUBLISHED_ERROR", {
928
- id,
929
- original: originalEntry
930
- });
931
- }
932
- const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
933
- context,
934
- model,
935
- input: originalEntry.values,
936
- validateEntries: false
937
- });
938
- const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
939
- savedOn: new Date().toISOString(),
940
- webinyVersion: context.WEBINY_VERSION,
941
- values
942
- });
943
- const storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
944
- /**
945
- * First we need to update existing entry.
946
- */
947
- try {
948
- await storageOperations.entries.update(model, {
949
- entry,
950
- storageEntry
951
- });
952
- } catch (ex) {
953
- throw new _error.default("Could not update existing entry with new data while re-publishing.", "REPUBLISH_UPDATE_ERROR", {
954
- entry
955
- });
956
- }
957
- /**
958
- * Then we move onto publishing it again.
959
- */
960
- try {
961
- await onEntryBeforeRepublish.publish({
962
- entry,
963
- model
964
- });
965
- const result = await storageOperations.entries.publish(model, {
966
- entry,
967
- storageEntry
968
- });
969
- await onEntryAfterRepublish.publish({
970
- entry,
971
- model,
972
- storageEntry
973
- });
974
- return result;
975
- } catch (ex) {
976
- await onEntryRepublishError.publish({
977
- entry,
978
- model,
979
- error: ex
980
- });
981
- throw new _error.default("Could not publish existing entry while re-publishing.", "REPUBLISH_PUBLISH_ERROR", {
982
- entry
983
- });
984
- }
985
- },
986
- async deleteEntryRevision(initialModel, revisionId) {
987
- const permission = await checkEntryPermissions({
988
- rwd: "d"
989
- });
990
- await (0, _access.checkModelAccess)(context, initialModel);
991
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
992
- model: initialModel,
993
- plugins
994
- });
995
- const {
996
- id: entryId,
997
- version
998
- } = (0, _utils.parseIdentifier)(revisionId);
999
- const storageEntryToDelete = await storageOperations.entries.getRevisionById(model, {
1000
- id: revisionId
1001
- });
1002
- const latestStorageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
1003
- id: entryId
1245
+ async republishEntry(model, id) {
1246
+ return context.benchmark.measure("headlessCms.crud.entries.republishEntry", async () => {
1247
+ return republishEntry(model, id);
1004
1248
  });
1005
- const previousStorageEntry = await storageOperations.entries.getPreviousRevision(model, {
1006
- entryId,
1007
- version: version
1008
- });
1009
- if (!storageEntryToDelete) {
1010
- throw new _handlerGraphql.NotFoundError(`Entry "${revisionId}" was not found!`);
1011
- }
1012
- (0, _ownership.checkOwnership)(context, permission, storageEntryToDelete);
1013
- const latestEntryRevisionId = latestStorageEntry ? latestStorageEntry.id : null;
1014
- const entryToDelete = await (0, _entryStorage.entryFromStorageTransform)(context, model, storageEntryToDelete);
1015
- /**
1016
- * If targeted record is the latest entry record and there is no previous one, we need to run full delete with hooks.
1017
- * At this point deleteRevision hooks are not fired.
1018
- */
1019
- if (entryToDelete.id === latestEntryRevisionId && !previousStorageEntry) {
1020
- return await deleteEntry({
1021
- model,
1022
- entry: entryToDelete
1023
- });
1024
- }
1025
- /**
1026
- * If targeted record is latest entry revision, set the previous one as the new latest
1027
- */
1028
- let entryToSetAsLatest = null;
1029
- let storageEntryToSetAsLatest = null;
1030
- if (entryToDelete.id === latestEntryRevisionId && previousStorageEntry) {
1031
- entryToSetAsLatest = await (0, _entryStorage.entryFromStorageTransform)(context, model, previousStorageEntry);
1032
- storageEntryToSetAsLatest = previousStorageEntry;
1033
- }
1034
- try {
1035
- await onEntryRevisionBeforeDelete.publish({
1036
- entry: entryToDelete,
1037
- model
1038
- });
1039
- await storageOperations.entries.deleteRevision(model, {
1040
- entry: entryToDelete,
1041
- storageEntry: storageEntryToDelete,
1042
- latestEntry: entryToSetAsLatest,
1043
- latestStorageEntry: storageEntryToSetAsLatest
1044
- });
1045
- await onEntryRevisionAfterDelete.publish({
1046
- entry: entryToDelete,
1047
- model
1048
- });
1049
- } catch (ex) {
1050
- await onEntryRevisionDeleteError.publish({
1051
- entry: entryToDelete,
1052
- model,
1053
- error: ex
1054
- });
1055
- throw new _error.default(ex.message, ex.code || "DELETE_REVISION_ERROR", {
1056
- error: ex,
1057
- entry: entryToDelete,
1058
- storageEntry: storageEntryToDelete,
1059
- latestEntry: entryToSetAsLatest,
1060
- latestStorageEntry: storageEntryToSetAsLatest
1061
- });
1062
- }
1063
1249
  },
1064
- async deleteEntry(initialModel, entryId) {
1065
- const permission = await checkEntryPermissions({
1066
- rwd: "d"
1067
- });
1068
- await (0, _access.checkModelAccess)(context, initialModel);
1069
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
1070
- model: initialModel,
1071
- plugins
1072
- });
1073
- const storageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
1074
- id: entryId
1075
- });
1076
- if (!storageEntry) {
1077
- throw new _handlerGraphql.NotFoundError(`Entry "${entryId}" was not found!`);
1078
- }
1079
- (0, _ownership.checkOwnership)(context, permission, storageEntry);
1080
- const entry = await (0, _entryStorage.entryFromStorageTransform)(context, model, storageEntry);
1081
- return await deleteEntry({
1082
- model,
1083
- entry
1250
+ async deleteEntryRevision(model, id) {
1251
+ return context.benchmark.measure("headlessCms.crud.entries.deleteEntryRevision", async () => {
1252
+ return deleteEntryRevision(model, id);
1084
1253
  });
1085
1254
  },
1086
- async publishEntry(initialModel, id) {
1087
- const permission = await checkEntryPermissions({
1088
- pw: "p"
1255
+ async deleteEntry(model, entryId) {
1256
+ return context.benchmark.measure("headlessCms.crud.entries.deleteEntry", async () => {
1257
+ return deleteEntry(model, entryId);
1089
1258
  });
1090
- await (0, _access.checkModelAccess)(context, initialModel);
1091
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
1092
- model: initialModel,
1093
- plugins
1094
- });
1095
- const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
1096
- id
1097
- });
1098
- if (!originalStorageEntry) {
1099
- throw new _handlerGraphql.NotFoundError(`Entry "${id}" in the model "${model.modelId}" was not found.`);
1100
- }
1101
- (0, _ownership.checkOwnership)(context, permission, originalStorageEntry);
1102
- const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
1103
- const currentDate = new Date().toISOString();
1104
- const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
1105
- status: STATUS_PUBLISHED,
1106
- locked: true,
1107
- savedOn: currentDate,
1108
- publishedOn: currentDate
1109
- });
1110
- let storageEntry = null;
1111
- try {
1112
- await onEntryBeforePublish.publish({
1113
- entry,
1114
- model
1115
- });
1116
- storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
1117
- const result = await storageOperations.entries.publish(model, {
1118
- entry,
1119
- storageEntry
1120
- });
1121
- await onEntryAfterPublish.publish({
1122
- entry,
1123
- storageEntry: result,
1124
- model
1125
- });
1126
- return result;
1127
- } catch (ex) {
1128
- await onEntryPublishError.publish({
1129
- entry,
1130
- model,
1131
- error: ex
1132
- });
1133
- throw new _error.default(ex.message || "Could not publish entry.", ex.code || "PUBLISH_ERROR", {
1134
- error: ex,
1135
- entry,
1136
- storageEntry,
1137
- originalEntry,
1138
- originalStorageEntry
1139
- });
1140
- }
1141
1259
  },
1142
- async unpublishEntry(initialModel, id) {
1143
- const permission = await checkEntryPermissions({
1144
- pw: "u"
1260
+ async publishEntry(model, id) {
1261
+ return context.benchmark.measure("headlessCms.crud.entries.publishEntry", async () => {
1262
+ return publishEntry(model, id);
1145
1263
  });
1146
- const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
1147
- model: initialModel,
1148
- plugins
1149
- });
1150
- const {
1151
- id: entryId
1152
- } = (0, _utils.parseIdentifier)(id);
1153
- const originalStorageEntry = await storageOperations.entries.getPublishedRevisionByEntryId(model, {
1154
- id: entryId
1264
+ },
1265
+ async unpublishEntry(model, id) {
1266
+ return context.benchmark.measure("headlessCms.crud.entries.unpublishEntry", async () => {
1267
+ return unpublishEntry(model, id);
1155
1268
  });
1156
- if (!originalStorageEntry) {
1157
- throw new _handlerGraphql.NotFoundError(`Entry "${id}" of model "${model.modelId}" was not found.`);
1158
- }
1159
- if (originalStorageEntry.id !== id) {
1160
- throw new _error.default(`Entry is not published.`, "UNPUBLISH_ERROR", {
1161
- entry: originalStorageEntry
1162
- });
1163
- }
1164
- (0, _ownership.checkOwnership)(context, permission, originalStorageEntry);
1165
- const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
1166
- const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
1167
- status: STATUS_UNPUBLISHED
1269
+ },
1270
+ async getUniqueFieldValues(model, params) {
1271
+ return context.benchmark.measure("headlessCms.crud.entries.getUniqueFieldValues", async () => {
1272
+ return getUniqueFieldValues(model, params);
1168
1273
  });
1169
- let storageEntry = null;
1170
- try {
1171
- await onEntryBeforeUnpublish.publish({
1172
- entry,
1173
- model
1174
- });
1175
- storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
1176
- const result = await storageOperations.entries.unpublish(model, {
1177
- entry,
1178
- storageEntry
1179
- });
1180
- await onEntryAfterUnpublish.publish({
1181
- entry,
1182
- storageEntry: result,
1183
- model
1184
- });
1185
- return result;
1186
- } catch (ex) {
1187
- await onEntryUnpublishError.publish({
1188
- entry,
1189
- model,
1190
- error: ex
1191
- });
1192
- throw new _error.default(ex.message || "Could not unpublish entry.", ex.code || "UNPUBLISH_ERROR", {
1193
- originalEntry,
1194
- originalStorageEntry,
1195
- entry,
1196
- storageEntry
1197
- });
1198
- }
1199
1274
  }
1200
1275
  };
1201
1276
  };