@webiny/api-headless-cms-ddb 0.0.0-unstable.a4637c5ce6 → 0.0.0-unstable.a4f3e4ea8b

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 (158) hide show
  1. package/README.md +6 -20
  2. package/definitions/entry.d.ts +4 -6
  3. package/definitions/entry.js +8 -185
  4. package/definitions/entry.js.map +1 -1
  5. package/definitions/group.d.ts +4 -6
  6. package/definitions/group.js +8 -63
  7. package/definitions/group.js.map +1 -1
  8. package/definitions/model.d.ts +4 -6
  9. package/definitions/model.js +8 -107
  10. package/definitions/model.js.map +1 -1
  11. package/definitions/table.d.ts +3 -5
  12. package/definitions/table.js +6 -29
  13. package/definitions/table.js.map +1 -1
  14. package/definitions/types.d.ts +65 -0
  15. package/definitions/types.js +0 -0
  16. package/dynamoDb/index.d.ts +1 -1
  17. package/dynamoDb/index.js +7 -13
  18. package/dynamoDb/index.js.map +1 -1
  19. package/index.d.ts +2 -3
  20. package/index.js +85 -121
  21. package/index.js.map +1 -1
  22. package/operations/entry/dataLoader/DataLoaderCache.d.ts +1 -2
  23. package/operations/entry/dataLoader/DataLoaderCache.js +21 -35
  24. package/operations/entry/dataLoader/DataLoaderCache.js.map +1 -1
  25. package/operations/entry/dataLoader/constants.js +2 -7
  26. package/operations/entry/dataLoader/constants.js.map +1 -1
  27. package/operations/entry/dataLoader/createBatchScheduleFn.js +7 -22
  28. package/operations/entry/dataLoader/createBatchScheduleFn.js.map +1 -1
  29. package/operations/entry/dataLoader/getAllEntryRevisions.d.ts +3 -3
  30. package/operations/entry/dataLoader/getAllEntryRevisions.js +20 -41
  31. package/operations/entry/dataLoader/getAllEntryRevisions.js.map +1 -1
  32. package/operations/entry/dataLoader/getLatestRevisionByEntryId.d.ts +3 -3
  33. package/operations/entry/dataLoader/getLatestRevisionByEntryId.js +36 -52
  34. package/operations/entry/dataLoader/getLatestRevisionByEntryId.js.map +1 -1
  35. package/operations/entry/dataLoader/getPublishedRevisionByEntryId.d.ts +3 -3
  36. package/operations/entry/dataLoader/getPublishedRevisionByEntryId.js +36 -52
  37. package/operations/entry/dataLoader/getPublishedRevisionByEntryId.js.map +1 -1
  38. package/operations/entry/dataLoader/getRevisionById.d.ts +3 -3
  39. package/operations/entry/dataLoader/getRevisionById.js +38 -58
  40. package/operations/entry/dataLoader/getRevisionById.js.map +1 -1
  41. package/operations/entry/dataLoader/index.d.ts +3 -3
  42. package/operations/entry/dataLoader/index.js +13 -35
  43. package/operations/entry/dataLoader/index.js.map +1 -1
  44. package/operations/entry/dataLoader/types.d.ts +4 -4
  45. package/operations/entry/dataLoader/types.js +0 -7
  46. package/operations/entry/dataLoaders.d.ts +11 -12
  47. package/operations/entry/dataLoaders.js +83 -109
  48. package/operations/entry/dataLoaders.js.map +1 -1
  49. package/operations/entry/index.d.ts +4 -3
  50. package/operations/entry/index.js +908 -1277
  51. package/operations/entry/index.js.map +1 -1
  52. package/operations/entry/keys.d.ts +46 -2
  53. package/operations/entry/keys.js +52 -49
  54. package/operations/entry/keys.js.map +1 -1
  55. package/operations/group/index.d.ts +4 -5
  56. package/operations/group/index.js +113 -166
  57. package/operations/group/index.js.map +1 -1
  58. package/operations/model/index.d.ts +3 -3
  59. package/operations/model/index.js +99 -143
  60. package/operations/model/index.js.map +1 -1
  61. package/package.json +29 -25
  62. package/plugins/index.d.ts +2 -4
  63. package/plugins/index.js +1 -51
  64. package/types.d.ts +19 -42
  65. package/types.js +6 -12
  66. package/types.js.map +1 -1
  67. package/definitions/system.d.ts +0 -10
  68. package/definitions/system.js +0 -42
  69. package/definitions/system.js.map +0 -1
  70. package/dynamoDb/path/locationFolderId.d.ts +0 -2
  71. package/dynamoDb/path/locationFolderId.js +0 -43
  72. package/dynamoDb/path/locationFolderId.js.map +0 -1
  73. package/dynamoDb/path/plainObject.d.ts +0 -2
  74. package/dynamoDb/path/plainObject.js +0 -35
  75. package/dynamoDb/path/plainObject.js.map +0 -1
  76. package/dynamoDb/storage/longText.d.ts +0 -10
  77. package/dynamoDb/storage/longText.js +0 -94
  78. package/dynamoDb/storage/longText.js.map +0 -1
  79. package/dynamoDb/storage/richText.d.ts +0 -2
  80. package/dynamoDb/storage/richText.js +0 -61
  81. package/dynamoDb/storage/richText.js.map +0 -1
  82. package/dynamoDb/transformValue/datetime.d.ts +0 -5
  83. package/dynamoDb/transformValue/datetime.js +0 -47
  84. package/dynamoDb/transformValue/datetime.js.map +0 -1
  85. package/operations/entry/dataLoader/types.js.map +0 -1
  86. package/operations/entry/filtering/createExpressions.d.ts +0 -26
  87. package/operations/entry/filtering/createExpressions.js +0 -178
  88. package/operations/entry/filtering/createExpressions.js.map +0 -1
  89. package/operations/entry/filtering/createFields.d.ts +0 -16
  90. package/operations/entry/filtering/createFields.js +0 -108
  91. package/operations/entry/filtering/createFields.js.map +0 -1
  92. package/operations/entry/filtering/extractSort.d.ts +0 -17
  93. package/operations/entry/filtering/extractSort.js +0 -69
  94. package/operations/entry/filtering/extractSort.js.map +0 -1
  95. package/operations/entry/filtering/filter.d.ts +0 -15
  96. package/operations/entry/filtering/filter.js +0 -158
  97. package/operations/entry/filtering/filter.js.map +0 -1
  98. package/operations/entry/filtering/fullTextSearch.d.ts +0 -14
  99. package/operations/entry/filtering/fullTextSearch.js +0 -50
  100. package/operations/entry/filtering/fullTextSearch.js.map +0 -1
  101. package/operations/entry/filtering/getValue.d.ts +0 -5
  102. package/operations/entry/filtering/getValue.js +0 -66
  103. package/operations/entry/filtering/getValue.js.map +0 -1
  104. package/operations/entry/filtering/index.d.ts +0 -2
  105. package/operations/entry/filtering/index.js +0 -21
  106. package/operations/entry/filtering/index.js.map +0 -1
  107. package/operations/entry/filtering/mapPlugins.d.ts +0 -8
  108. package/operations/entry/filtering/mapPlugins.js +0 -33
  109. package/operations/entry/filtering/mapPlugins.js.map +0 -1
  110. package/operations/entry/filtering/plugins/defaultFilterCreate.d.ts +0 -2
  111. package/operations/entry/filtering/plugins/defaultFilterCreate.js +0 -45
  112. package/operations/entry/filtering/plugins/defaultFilterCreate.js.map +0 -1
  113. package/operations/entry/filtering/plugins/index.d.ts +0 -1
  114. package/operations/entry/filtering/plugins/index.js +0 -16
  115. package/operations/entry/filtering/plugins/index.js.map +0 -1
  116. package/operations/entry/filtering/plugins/objectFilterCreate.d.ts +0 -2
  117. package/operations/entry/filtering/plugins/objectFilterCreate.js +0 -90
  118. package/operations/entry/filtering/plugins/objectFilterCreate.js.map +0 -1
  119. package/operations/entry/filtering/plugins/refFilterCreate.d.ts +0 -3
  120. package/operations/entry/filtering/plugins/refFilterCreate.js +0 -80
  121. package/operations/entry/filtering/plugins/refFilterCreate.js.map +0 -1
  122. package/operations/entry/filtering/plugins/searchableJsonFilterCreate.d.ts +0 -2
  123. package/operations/entry/filtering/plugins/searchableJsonFilterCreate.js +0 -65
  124. package/operations/entry/filtering/plugins/searchableJsonFilterCreate.js.map +0 -1
  125. package/operations/entry/filtering/sort.d.ts +0 -12
  126. package/operations/entry/filtering/sort.js +0 -71
  127. package/operations/entry/filtering/sort.js.map +0 -1
  128. package/operations/entry/filtering/systemFields.d.ts +0 -4
  129. package/operations/entry/filtering/systemFields.js +0 -90
  130. package/operations/entry/filtering/systemFields.js.map +0 -1
  131. package/operations/entry/filtering/transform.d.ts +0 -6
  132. package/operations/entry/filtering/transform.js +0 -18
  133. package/operations/entry/filtering/transform.js.map +0 -1
  134. package/operations/entry/filtering/types.d.ts +0 -40
  135. package/operations/entry/filtering/types.js +0 -7
  136. package/operations/entry/filtering/types.js.map +0 -1
  137. package/operations/entry/filtering/values.d.ts +0 -2
  138. package/operations/entry/filtering/values.js +0 -24
  139. package/operations/entry/filtering/values.js.map +0 -1
  140. package/operations/entry/filtering/where.d.ts +0 -5
  141. package/operations/entry/filtering/where.js +0 -35
  142. package/operations/entry/filtering/where.js.map +0 -1
  143. package/operations/system/index.d.ts +0 -7
  144. package/operations/system/index.js +0 -94
  145. package/operations/system/index.js.map +0 -1
  146. package/plugins/CmsEntryFieldFilterPathPlugin.d.ts +0 -23
  147. package/plugins/CmsEntryFieldFilterPathPlugin.js +0 -48
  148. package/plugins/CmsEntryFieldFilterPathPlugin.js.map +0 -1
  149. package/plugins/CmsEntryFieldFilterPlugin.d.ts +0 -43
  150. package/plugins/CmsEntryFieldFilterPlugin.js +0 -27
  151. package/plugins/CmsEntryFieldFilterPlugin.js.map +0 -1
  152. package/plugins/CmsEntryFieldSortingPlugin.d.ts +0 -42
  153. package/plugins/CmsEntryFieldSortingPlugin.js +0 -27
  154. package/plugins/CmsEntryFieldSortingPlugin.js.map +0 -1
  155. package/plugins/CmsFieldFilterValueTransformPlugin.d.ts +0 -11
  156. package/plugins/CmsFieldFilterValueTransformPlugin.js +0 -23
  157. package/plugins/CmsFieldFilterValueTransformPlugin.js.map +0 -1
  158. package/plugins/index.js.map +0 -1
@@ -1,1306 +1,937 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.createEntriesStorageOperations = void 0;
8
- var _error = _interopRequireDefault(require("@webiny/error"));
9
- var _dataLoaders = require("./dataLoaders");
10
- var _types = require("@webiny/api-headless-cms/types");
11
- var _keys = require("./keys");
12
- var _dbDynamodb = require("@webiny/db-dynamodb");
13
- var _cursor = require("@webiny/utils/cursor");
14
- var _zeroPad = require("@webiny/utils/zeroPad");
15
- var _apiHeadlessCms = require("@webiny/api-headless-cms");
16
- var _createFields = require("./filtering/createFields");
17
- var _filtering = require("./filtering");
18
- var _constants = require("@webiny/api-headless-cms/constants");
19
- const createType = () => {
20
- return "cms.entry";
21
- };
22
- const createLatestType = () => {
23
- return `${createType()}.l`;
24
- };
25
- const createPublishedType = () => {
26
- return `${createType()}.p`;
27
- };
28
- const convertToStorageEntry = params => {
29
- const {
30
- model,
31
- storageEntry
32
- } = params;
33
- const values = model.convertValueKeyToStorage({
34
- fields: model.fields,
35
- values: storageEntry.values
36
- });
37
- return {
38
- ...storageEntry,
39
- values
40
- };
41
- };
42
- const convertFromStorageEntry = params => {
43
- const {
44
- model,
45
- storageEntry
46
- } = params;
47
- const values = model.convertValueKeyFromStorage({
48
- fields: model.fields,
49
- values: storageEntry.values
50
- });
51
- return {
52
- ...storageEntry,
53
- values
54
- };
55
- };
56
- const MAX_LIST_LIMIT = 1000000;
57
- const createEntriesStorageOperations = params => {
58
- const {
59
- entity,
60
- plugins
61
- } = params;
62
- let storageOperationsCmsModelPlugin;
63
- const getStorageOperationsCmsModelPlugin = () => {
64
- if (storageOperationsCmsModelPlugin) {
65
- return storageOperationsCmsModelPlugin;
66
- }
67
- storageOperationsCmsModelPlugin = plugins.oneByType(_apiHeadlessCms.StorageOperationsCmsModelPlugin.type);
68
- return storageOperationsCmsModelPlugin;
69
- };
70
- const getStorageOperationsModel = model => {
71
- const plugin = getStorageOperationsCmsModelPlugin();
72
- return plugin.getModel(model);
73
- };
74
- const dataLoaders = new _dataLoaders.DataLoadersHandler({
75
- entity
76
- });
77
- const createStorageTransformCallable = model => {
78
- // Cache StorageTransformPlugin to optimize execution.
79
- const storageTransformPlugins = plugins.byType(_apiHeadlessCms.StorageTransformPlugin.type).reduce((collection, plugin) => {
80
- collection[plugin.fieldType] = plugin;
81
- return collection;
82
- }, {});
83
- return (field, value) => {
84
- const plugin = storageTransformPlugins[field.type];
85
- if (!plugin) {
86
- return value;
87
- }
88
- return plugin.fromStorage({
89
- model,
90
- field,
91
- value,
92
- getStoragePlugin(fieldType) {
93
- return storageTransformPlugins[fieldType] || storageTransformPlugins["*"];
94
- },
95
- plugins
96
- });
97
- };
98
- };
99
- const create = async (initialModel, params) => {
100
- const {
101
- entry,
102
- storageEntry: initialStorageEntry
103
- } = params;
104
- const model = getStorageOperationsModel(initialModel);
105
- const partitionKey = (0, _keys.createPartitionKey)({
106
- id: entry.id,
107
- locale: model.locale,
108
- tenant: model.tenant
109
- });
110
- const isPublished = entry.status === "published";
111
- const locked = isPublished ? true : entry.locked;
112
- const storageEntry = convertToStorageEntry({
113
- model,
114
- storageEntry: initialStorageEntry
115
- });
116
- /**
117
- * We need to:
118
- * - create new main entry item
119
- * - create new or update the latest entry item
120
- */
121
- const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
122
- entity,
123
- put: [{
124
- ...storageEntry,
125
- locked,
126
- PK: partitionKey,
127
- SK: (0, _keys.createRevisionSortKey)(entry),
128
- TYPE: createType(),
129
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
130
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
131
- }, {
132
- ...storageEntry,
133
- locked,
134
- PK: partitionKey,
135
- SK: (0, _keys.createLatestSortKey)(),
136
- TYPE: createLatestType(),
137
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
138
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
139
- }]
1
+ import error from "@webiny/error";
2
+ import { DataLoadersHandler } from "./dataLoaders.js";
3
+ import { CONTENT_ENTRY_STATUS } from "@webiny/api-headless-cms/types/index.js";
4
+ import { createEntryLatestKeys, createEntryPublishedKeys, createEntryRevisionKeys, createGSIPartitionKey, createPartitionKey, createPublishedSortKey, createRevisionSortKey } from "./keys.js";
5
+ import { decodeCursor, encodeCursor } from "@webiny/utils";
6
+ import { ValueFilterRegistry } from "@webiny/db-utils";
7
+ import { aggregateUniqueFieldValues, createFields, createStorageModelAccessor, createStorageTransformCallable, filter, sort } from "@webiny/api-headless-cms-storage";
8
+ import { isDeletedEntryMetaField, isEntryLevelEntryMetaField, isRestoredEntryMetaField, pickEntryMetaFields } from "@webiny/api-headless-cms/constants.js";
9
+ import { StorageTransformRegistry } from "@webiny/api-headless-cms/exports/api/cms/storage.js";
10
+ const convertToStorageEntry = (params)=>{
11
+ const { model, storageEntry } = params;
12
+ const values = model.convertValueKeyToStorage({
13
+ fields: model.fields,
14
+ values: storageEntry.values
140
15
  });
141
-
142
- /**
143
- * We need to create published entry if
144
- */
145
- if (isPublished) {
146
- entityBatch.put({
147
- ...storageEntry,
148
- locked,
149
- PK: partitionKey,
150
- SK: (0, _keys.createPublishedSortKey)(),
151
- TYPE: createLatestType(),
152
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "P"),
153
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
154
- });
155
- }
156
- try {
157
- await entityBatch.execute();
158
- dataLoaders.clearAll({
159
- model
160
- });
161
- } catch (ex) {
162
- throw new _error.default(ex.message || "Could not insert data into the DynamoDB.", ex.code || "CREATE_ENTRY_ERROR", {
163
- error: ex,
164
- entry
165
- });
166
- }
167
- return initialStorageEntry;
168
- };
169
- const createRevisionFrom = async (initialModel, params) => {
170
- const {
171
- entry,
172
- storageEntry: initialStorageEntry
173
- } = params;
174
- const model = getStorageOperationsModel(initialModel);
175
- const partitionKey = (0, _keys.createPartitionKey)({
176
- id: entry.id,
177
- locale: model.locale,
178
- tenant: model.tenant
179
- });
180
- const storageEntry = convertToStorageEntry({
181
- storageEntry: initialStorageEntry,
182
- model
183
- });
184
-
185
- /**
186
- * We need to:
187
- * - create the main entry item
188
- * - update the latest entry item to the current one
189
- * - if the entry's status was set to "published":
190
- * - update the published entry item to the current one
191
- * - unpublish previously published revision (if any)
192
- */
193
- const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
194
- entity,
195
- put: [{
196
- ...storageEntry,
197
- PK: partitionKey,
198
- SK: (0, _keys.createRevisionSortKey)(storageEntry),
199
- TYPE: createType(),
200
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
201
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
202
- }, {
16
+ return {
203
17
  ...storageEntry,
204
- PK: partitionKey,
205
- SK: (0, _keys.createLatestSortKey)(),
206
- TYPE: createLatestType(),
207
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
208
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
209
- }]
18
+ values
19
+ };
20
+ };
21
+ const convertFromStorageEntry = (params)=>{
22
+ const { model, storageEntry } = params;
23
+ const values = model.convertValueKeyFromStorage({
24
+ fields: model.fields,
25
+ values: storageEntry.values
210
26
  });
211
- const isPublished = entry.status === "published";
212
- if (isPublished) {
213
- entityBatch.put({
27
+ return {
214
28
  ...storageEntry,
215
- PK: partitionKey,
216
- SK: (0, _keys.createPublishedSortKey)(),
217
- TYPE: createPublishedType(),
218
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "P"),
219
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
220
- });
221
-
222
- // Unpublish previously published revision (if any).
223
- const [publishedRevisionStorageEntry] = await dataLoaders.getPublishedRevisionByEntryId({
224
- model,
225
- ids: [entry.id]
226
- });
227
- if (publishedRevisionStorageEntry) {
228
- entityBatch.put({
229
- ...publishedRevisionStorageEntry,
230
- PK: partitionKey,
231
- SK: (0, _keys.createRevisionSortKey)(publishedRevisionStorageEntry),
232
- TYPE: createType(),
233
- status: _types.CONTENT_ENTRY_STATUS.UNPUBLISHED,
234
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
235
- GSI1_SK: (0, _keys.createGSISortKey)(publishedRevisionStorageEntry)
29
+ values
30
+ };
31
+ };
32
+ const MAX_LIST_LIMIT = 1000000;
33
+ const createEntriesStorageOperations = (params)=>{
34
+ const { entity, container, plugins } = params;
35
+ const storageTransformRegistry = container.resolve(StorageTransformRegistry);
36
+ const { getModel: getStorageOperationsModel } = createStorageModelAccessor(plugins);
37
+ const dataLoaders = new DataLoadersHandler({
38
+ entity
39
+ });
40
+ const create = async (initialModel, params)=>{
41
+ const { entry, storageEntry: initialStorageEntry } = params;
42
+ const model = getStorageOperationsModel(initialModel);
43
+ const isPublished = "published" === entry.status;
44
+ const locked = isPublished ? true : entry.locked;
45
+ const storageEntry = convertToStorageEntry({
46
+ model,
47
+ storageEntry: initialStorageEntry
236
48
  });
237
- }
238
- }
239
- try {
240
- await entityBatch.execute();
241
- dataLoaders.clearAll({
242
- model
243
- });
244
- } catch (ex) {
245
- throw new _error.default(ex.message || "Could not create revision from given entry.", ex.code || "CREATE_REVISION_ERROR", {
246
- error: ex,
247
- entry,
248
- storageEntry
249
- });
250
- }
251
- /**
252
- * There are no modifications on the entry created so just return the data.
253
- */
254
- return initialStorageEntry;
255
- };
256
- const update = async (initialModel, params) => {
257
- const {
258
- entry,
259
- storageEntry: initialStorageEntry
260
- } = params;
261
- const model = getStorageOperationsModel(initialModel);
262
- const partitionKey = (0, _keys.createPartitionKey)({
263
- id: entry.id,
264
- locale: model.locale,
265
- tenant: model.tenant
266
- });
267
- const isPublished = entry.status === "published";
268
- const locked = isPublished ? true : entry.locked;
269
- const storageEntry = convertToStorageEntry({
270
- model,
271
- storageEntry: initialStorageEntry
272
- });
273
- /**
274
- * We need to:
275
- * - update the current entry
276
- * - update the latest entry if the current entry is the latest one
277
- */
278
-
279
- const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
280
- entity,
281
- put: [{
282
- ...storageEntry,
283
- locked,
284
- PK: partitionKey,
285
- SK: (0, _keys.createRevisionSortKey)(storageEntry),
286
- TYPE: createType(),
287
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
288
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
289
- }]
290
- });
291
- if (isPublished) {
292
- entityBatch.put({
293
- ...storageEntry,
294
- locked,
295
- PK: partitionKey,
296
- SK: (0, _keys.createPublishedSortKey)(),
297
- TYPE: createPublishedType(),
298
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "P"),
299
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
300
- });
301
- }
302
-
303
- /**
304
- * We need the latest entry to update it as well if necessary.
305
- */
306
- const latestStorageEntry = await getLatestRevisionByEntryId(model, entry);
307
- if (latestStorageEntry) {
308
- const updatingLatestRevision = latestStorageEntry.id === entry.id;
309
- if (updatingLatestRevision) {
310
- entityBatch.put({
311
- ...storageEntry,
312
- locked,
313
- PK: partitionKey,
314
- SK: (0, _keys.createLatestSortKey)(),
315
- TYPE: createLatestType(),
316
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
317
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
49
+ const storageEntryRevisionKeys = createEntryRevisionKeys(entry);
50
+ const storageEntryLatestKeys = createEntryLatestKeys(entry);
51
+ const entityBatch = entity.createEntityWriter({
52
+ put: [
53
+ {
54
+ ...storageEntryRevisionKeys,
55
+ data: {
56
+ ...storageEntry,
57
+ locked
58
+ }
59
+ },
60
+ {
61
+ ...storageEntryLatestKeys,
62
+ data: {
63
+ ...storageEntry,
64
+ locked
65
+ }
66
+ }
67
+ ]
318
68
  });
319
- } else {
320
- /**
321
- * If not updating latest revision, we still want to update the latest revision's
322
- * entry-level meta fields to match the current revision's entry-level meta fields.
323
- */
324
- const updatedEntryLevelMetaFields = (0, _constants.pickEntryMetaFields)(entry, _constants.isEntryLevelEntryMetaField);
325
-
326
- /**
327
- * First we update the regular DynamoDB table. Two updates are needed:
328
- * - one for the actual revision record
329
- * - one for the latest record
330
- */
331
- entityBatch.put({
332
- ...latestStorageEntry,
333
- ...updatedEntryLevelMetaFields,
334
- PK: partitionKey,
335
- SK: (0, _keys.createRevisionSortKey)(latestStorageEntry),
336
- TYPE: createType(),
337
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
338
- GSI1_SK: (0, _keys.createGSISortKey)(latestStorageEntry)
69
+ if (isPublished) {
70
+ const storageEntryPublishedKeys = createEntryPublishedKeys(storageEntry);
71
+ entityBatch.put({
72
+ ...storageEntryPublishedKeys,
73
+ data: {
74
+ ...storageEntry,
75
+ locked
76
+ }
77
+ });
78
+ }
79
+ try {
80
+ await entityBatch.execute();
81
+ dataLoaders.clearAll({
82
+ tenant: entry.tenant
83
+ });
84
+ } catch (ex) {
85
+ throw new error(ex.message || "Could not insert data into the DynamoDB.", ex.code || "CREATE_ENTRY_ERROR", {
86
+ error: ex,
87
+ entry
88
+ });
89
+ }
90
+ return initialStorageEntry;
91
+ };
92
+ const createRevisionFrom = async (initialModel, params)=>{
93
+ const { entry, storageEntry: initialStorageEntry } = params;
94
+ const model = getStorageOperationsModel(initialModel);
95
+ const storageEntry = convertToStorageEntry({
96
+ storageEntry: initialStorageEntry,
97
+ model
339
98
  });
340
- entityBatch.put({
341
- ...latestStorageEntry,
342
- ...updatedEntryLevelMetaFields,
343
- PK: partitionKey,
344
- SK: (0, _keys.createLatestSortKey)(),
345
- TYPE: createLatestType(),
346
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
347
- GSI1_SK: (0, _keys.createGSISortKey)(latestStorageEntry)
99
+ const entityBatch = entity.createEntityWriter({
100
+ put: [
101
+ {
102
+ ...createEntryRevisionKeys(storageEntry),
103
+ data: {
104
+ ...storageEntry
105
+ }
106
+ },
107
+ {
108
+ ...createEntryLatestKeys(storageEntry),
109
+ data: {
110
+ ...storageEntry
111
+ }
112
+ }
113
+ ]
348
114
  });
349
- }
350
- }
351
- try {
352
- await entityBatch.execute();
353
- dataLoaders.clearAll({
354
- model
355
- });
356
- return initialStorageEntry;
357
- } catch (ex) {
358
- throw new _error.default(ex.message || "Could not update entry.", ex.code || "UPDATE_ERROR", {
359
- error: ex,
360
- entry,
361
- latestStorageEntry
362
- });
363
- }
364
- };
365
- const move = async (initialModel, id, folderId) => {
366
- /**
367
- * We need to:
368
- * - load all the revisions of the entry, including published and latest
369
- * - update all the revisions (published and latest ) of the entry with new folderId
370
- */
371
- const model = getStorageOperationsModel(initialModel);
372
- /**
373
- * First we need to load all the revisions and published / latest entry.
374
- */
375
- const queryAllParams = {
376
- entity,
377
- partitionKey: (0, _keys.createPartitionKey)({
378
- id,
379
- locale: model.locale,
380
- tenant: model.tenant
381
- }),
382
- options: {
383
- gte: " "
384
- }
115
+ const isPublished = "published" === entry.status;
116
+ if (isPublished) {
117
+ entityBatch.put({
118
+ ...createEntryPublishedKeys(storageEntry),
119
+ data: {
120
+ ...storageEntry
121
+ }
122
+ });
123
+ const [publishedRevisionStorageEntry] = await dataLoaders.getPublishedRevisionByEntryId({
124
+ model,
125
+ ids: [
126
+ entry.id
127
+ ]
128
+ });
129
+ if (publishedRevisionStorageEntry) entityBatch.put({
130
+ ...createEntryRevisionKeys(publishedRevisionStorageEntry),
131
+ data: {
132
+ ...publishedRevisionStorageEntry,
133
+ status: CONTENT_ENTRY_STATUS.UNPUBLISHED
134
+ }
135
+ });
136
+ }
137
+ try {
138
+ await entityBatch.execute();
139
+ dataLoaders.clearAll({
140
+ tenant: entry.tenant
141
+ });
142
+ } catch (ex) {
143
+ throw new error(ex.message || "Could not create revision from given entry.", ex.code || "CREATE_REVISION_ERROR", {
144
+ error: ex,
145
+ entry,
146
+ storageEntry
147
+ });
148
+ }
149
+ return initialStorageEntry;
385
150
  };
386
- const records = await (0, _dbDynamodb.queryAll)(queryAllParams);
387
- /**
388
- * Then create the batch writes for the DynamoDB, with the updated folderId.
389
- */
390
- const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
391
- entity,
392
- put: records.map(item => {
393
- return {
394
- ...item,
395
- location: {
396
- ...item.location,
397
- folderId
398
- }
399
- };
400
- })
401
- });
402
-
403
- /**
404
- * And finally write it...
405
- */
406
- try {
407
- await entityBatch.execute();
408
- } catch (ex) {
409
- throw _error.default.from(ex, {
410
- message: "Could not move records to a new folder.",
411
- data: {
412
- id,
413
- folderId
151
+ const update = async (initialModel, params)=>{
152
+ const { entry, storageEntry: initialStorageEntry } = params;
153
+ const model = getStorageOperationsModel(initialModel);
154
+ const isPublished = "published" === entry.status;
155
+ const locked = isPublished ? true : entry.locked;
156
+ const storageEntry = convertToStorageEntry({
157
+ model,
158
+ storageEntry: initialStorageEntry
159
+ });
160
+ const entityBatch = entity.createEntityWriter({
161
+ put: [
162
+ {
163
+ ...createEntryRevisionKeys(storageEntry),
164
+ data: {
165
+ ...storageEntry,
166
+ locked
167
+ }
168
+ }
169
+ ]
170
+ });
171
+ if (isPublished) entityBatch.put({
172
+ ...createEntryPublishedKeys(storageEntry),
173
+ data: {
174
+ ...storageEntry,
175
+ locked
176
+ }
177
+ });
178
+ const latestStorageEntry = await getLatestRevisionByEntryId(model, entry);
179
+ if (latestStorageEntry) {
180
+ const updatingLatestRevision = latestStorageEntry.id === entry.id;
181
+ if (updatingLatestRevision) entityBatch.put({
182
+ ...createEntryLatestKeys(storageEntry),
183
+ data: {
184
+ ...storageEntry,
185
+ locked
186
+ }
187
+ });
188
+ else {
189
+ const updatedEntryLevelMetaFields = pickEntryMetaFields(entry, isEntryLevelEntryMetaField);
190
+ entityBatch.put({
191
+ ...createEntryRevisionKeys(latestStorageEntry),
192
+ data: {
193
+ ...latestStorageEntry,
194
+ ...updatedEntryLevelMetaFields
195
+ }
196
+ });
197
+ entityBatch.put({
198
+ ...createEntryLatestKeys(latestStorageEntry),
199
+ data: {
200
+ ...latestStorageEntry,
201
+ ...updatedEntryLevelMetaFields
202
+ }
203
+ });
204
+ }
205
+ }
206
+ try {
207
+ await entityBatch.execute();
208
+ dataLoaders.clearAll({
209
+ tenant: entry.tenant
210
+ });
211
+ return initialStorageEntry;
212
+ } catch (ex) {
213
+ throw new error(ex.message || "Could not update entry.", ex.code || "UPDATE_ERROR", {
214
+ error: ex,
215
+ entry,
216
+ latestStorageEntry
217
+ });
414
218
  }
415
- });
416
- }
417
- };
418
- const moveToBin = async (initialModel, params) => {
419
- const {
420
- entry,
421
- storageEntry: initialStorageEntry
422
- } = params;
423
- const model = getStorageOperationsModel(initialModel);
424
-
425
- /**
426
- * First we need to load all the revisions and published / latest entries.
427
- */
428
- const queryAllParams = {
429
- entity,
430
- partitionKey: (0, _keys.createPartitionKey)({
431
- id: entry.id,
432
- locale: model.locale,
433
- tenant: model.tenant
434
- }),
435
- options: {
436
- gte: " "
437
- }
438
219
  };
439
- let records = [];
440
- try {
441
- records = await (0, _dbDynamodb.queryAll)(queryAllParams);
442
- } catch (ex) {
443
- throw new _error.default(ex.message || "Could not load all records.", ex.code || "LOAD_ALL_RECORDS_ERROR", {
444
- error: ex,
445
- id: entry.id
446
- });
447
- }
448
- if (records.length === 0) {
449
- return;
450
- }
451
- const storageEntry = convertToStorageEntry({
452
- model,
453
- storageEntry: initialStorageEntry
454
- });
455
-
456
- /**
457
- * Let's pick the `deleted` meta fields from the storage entry.
458
- */
459
- const updatedDeletedMetaFields = (0, _constants.pickEntryMetaFields)(storageEntry, _constants.isDeletedEntryMetaField);
460
-
461
- /**
462
- * Then create the batch writes for the DynamoDB, with the updated data.
463
- */
464
- const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
465
- entity,
466
- put: records.map(record => {
467
- return {
468
- ...record,
469
- ...updatedDeletedMetaFields,
470
- wbyDeleted: storageEntry.wbyDeleted,
471
- location: storageEntry.location,
472
- binOriginalFolderId: storageEntry.binOriginalFolderId
473
- };
474
- })
475
- });
476
- /**
477
- * And finally write it...
478
- */
479
- try {
480
- await entityBatch.execute();
481
- } catch (ex) {
482
- throw new _error.default(ex.message || "Could not move the entry to the bin.", ex.code || "MOVE_ENTRY_TO_BIN_ERROR", {
483
- error: ex,
484
- entry,
485
- storageEntry
486
- });
487
- }
488
- };
489
- const deleteEntry = async (initialModel, params) => {
490
- const {
491
- entry
492
- } = params;
493
- const id = entry.id || entry.entryId;
494
- const model = getStorageOperationsModel(initialModel);
495
- const queryAllParams = {
496
- entity,
497
- partitionKey: (0, _keys.createPartitionKey)({
498
- id,
499
- locale: model.locale,
500
- tenant: model.tenant
501
- }),
502
- options: {
503
- gte: " "
504
- }
220
+ const updateRevision = async (initialModel, params)=>{
221
+ const { entry, storageEntry: initialStorageEntry } = params;
222
+ const model = getStorageOperationsModel(initialModel);
223
+ const storageEntry = convertToStorageEntry({
224
+ model,
225
+ storageEntry: initialStorageEntry
226
+ });
227
+ const entityBatch = entity.createEntityWriter({
228
+ put: [
229
+ {
230
+ ...createEntryRevisionKeys(storageEntry),
231
+ data: storageEntry
232
+ }
233
+ ]
234
+ });
235
+ try {
236
+ await entityBatch.execute();
237
+ dataLoaders.clearAll({
238
+ tenant: entry.tenant
239
+ });
240
+ return initialStorageEntry;
241
+ } catch (ex) {
242
+ throw new error(ex.message || "Could not update revision.", ex.code || "UPDATE_REVISION_ERROR", {
243
+ error: ex,
244
+ entry
245
+ });
246
+ }
505
247
  };
506
- let records = [];
507
- try {
508
- records = await (0, _dbDynamodb.queryAll)(queryAllParams);
509
- } catch (ex) {
510
- throw new _error.default(ex.message || "Could not load all records.", ex.code || "LOAD_ALL_RECORDS_ERROR", {
511
- error: ex,
512
- id
513
- });
514
- }
515
- const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
516
- entity,
517
- delete: records.map(item => {
518
- return {
519
- PK: item.PK,
520
- SK: item.SK
521
- };
522
- })
523
- });
524
- try {
525
- await entityBatch.execute();
526
- dataLoaders.clearAll({
527
- model
528
- });
529
- } catch (ex) {
530
- throw new _error.default(ex.message || "Could not delete the entry.", ex.code || "DELETE_ENTRY_ERROR", {
531
- error: ex,
532
- partitionKey: queryAllParams.partitionKey,
533
- id
534
- });
535
- }
536
- };
537
- const restoreFromBin = async (initialModel, params) => {
538
- const {
539
- entry,
540
- storageEntry: initialStorageEntry
541
- } = params;
542
- const model = getStorageOperationsModel(initialModel);
543
-
544
- /**
545
- * First we need to load all the revisions and published / latest entries.
546
- */
547
- const queryAllParams = {
548
- entity,
549
- partitionKey: (0, _keys.createPartitionKey)({
550
- id: entry.id,
551
- locale: model.locale,
552
- tenant: model.tenant
553
- }),
554
- options: {
555
- gte: " "
556
- }
248
+ const move = async (initialModel, id, folderId)=>{
249
+ const model = getStorageOperationsModel(initialModel);
250
+ const partitionKey = createPartitionKey({
251
+ id,
252
+ tenant: model.tenant
253
+ });
254
+ const records = await entity.queryAll({
255
+ partitionKey,
256
+ options: {
257
+ gte: " "
258
+ }
259
+ });
260
+ const entityBatch = entity.createEntityWriter({
261
+ put: records.map((item)=>({
262
+ ...item,
263
+ data: {
264
+ ...item.data,
265
+ location: {
266
+ ...item.data.location,
267
+ folderId
268
+ }
269
+ }
270
+ }))
271
+ });
272
+ try {
273
+ await entityBatch.execute();
274
+ } catch (ex) {
275
+ throw error.from(ex, {
276
+ message: "Could not move records to a new folder.",
277
+ data: {
278
+ id,
279
+ folderId
280
+ }
281
+ });
282
+ }
557
283
  };
558
- let records = [];
559
- try {
560
- records = await (0, _dbDynamodb.queryAll)(queryAllParams);
561
- } catch (ex) {
562
- throw new _error.default(ex.message || "Could not load all records.", ex.code || "LOAD_ALL_RECORDS_ERROR", {
563
- error: ex,
564
- id: entry.id
565
- });
566
- }
567
- if (records.length === 0) {
568
- return initialStorageEntry;
569
- }
570
- const storageEntry = convertToStorageEntry({
571
- model,
572
- storageEntry: initialStorageEntry
573
- });
574
-
575
- /**
576
- * Let's pick the `restored` meta fields from the storage entry.
577
- */
578
- const updatedRestoredMetaFields = (0, _constants.pickEntryMetaFields)(storageEntry, _constants.isRestoredEntryMetaField);
579
- const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
580
- entity,
581
- put: records.map(record => {
582
- return {
583
- ...record,
584
- ...updatedRestoredMetaFields,
585
- wbyDeleted: storageEntry.wbyDeleted,
586
- location: storageEntry.location,
587
- binOriginalFolderId: storageEntry.binOriginalFolderId
588
- };
589
- })
590
- });
591
-
592
- /**
593
- * And finally write it...
594
- */
595
- try {
596
- await entityBatch.execute();
597
- dataLoaders.clearAll({
598
- model
599
- });
600
- return initialStorageEntry;
601
- } catch (ex) {
602
- throw new _error.default(ex.message || "Could not restore the entry from the bin.", ex.code || "RESTORE_ENTRY_ERROR", {
603
- error: ex,
604
- entry,
605
- storageEntry
606
- });
607
- }
608
- };
609
- const deleteRevision = async (initialModel, params) => {
610
- const {
611
- entry,
612
- latestEntry,
613
- latestStorageEntry: initialLatestStorageEntry
614
- } = params;
615
- const model = getStorageOperationsModel(initialModel);
616
- const partitionKey = (0, _keys.createPartitionKey)({
617
- id: entry.id,
618
- locale: model.locale,
619
- tenant: model.tenant
620
- });
621
- const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
622
- entity,
623
- delete: [{
624
- PK: partitionKey,
625
- SK: (0, _keys.createRevisionSortKey)(entry)
626
- }]
627
- });
628
- const publishedStorageEntry = await getPublishedRevisionByEntryId(model, entry);
629
-
630
- /**
631
- * If revision we are deleting is the published one as well, we need to delete those records as well.
632
- */
633
- if (publishedStorageEntry && entry.id === publishedStorageEntry.id) {
634
- entityBatch.delete({
635
- PK: partitionKey,
636
- SK: (0, _keys.createPublishedSortKey)()
637
- });
638
- }
639
- if (initialLatestStorageEntry) {
640
- const latestStorageEntry = convertToStorageEntry({
641
- storageEntry: initialLatestStorageEntry,
642
- model
643
- });
644
- entityBatch.put({
645
- ...latestStorageEntry,
646
- PK: partitionKey,
647
- SK: (0, _keys.createLatestSortKey)(),
648
- TYPE: createLatestType(),
649
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
650
- GSI1_SK: (0, _keys.createGSISortKey)(latestStorageEntry)
651
- });
652
-
653
- // Do an update on the latest revision. We need to update the latest revision's
654
- // entry-level meta fields to match the previous revision's entry-level meta fields.
655
- entityBatch.put({
656
- ...latestStorageEntry,
657
- PK: partitionKey,
658
- SK: (0, _keys.createRevisionSortKey)(initialLatestStorageEntry),
659
- TYPE: createType(),
660
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
661
- GSI1_SK: (0, _keys.createGSISortKey)(initialLatestStorageEntry)
662
- });
663
- }
664
- try {
665
- entityBatch.execute();
666
- dataLoaders.clearAll({
667
- model
668
- });
669
- } catch (ex) {
670
- throw new _error.default(ex.message, ex.code, {
671
- error: ex,
672
- entry,
673
- latestEntry
674
- });
675
- }
676
- };
677
- const deleteMultipleEntries = async (initialModel, params) => {
678
- const {
679
- entries
680
- } = params;
681
- const model = getStorageOperationsModel(initialModel);
682
- /**
683
- * First we need all the revisions of the entries we want to delete.
684
- */
685
- const revisions = await dataLoaders.getAllEntryRevisions({
686
- model,
687
- ids: entries
688
- });
689
- /**
690
- * Then we need to construct the queries for all the revisions and entries.
691
- */
692
-
693
- const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
694
- entity
695
- });
696
- for (const id of entries) {
697
- const partitionKey = (0, _keys.createPartitionKey)({
698
- id,
699
- locale: model.locale,
700
- tenant: model.tenant
701
- });
702
- entityBatch.delete({
703
- PK: partitionKey,
704
- SK: "L"
705
- });
706
- entityBatch.delete({
707
- PK: partitionKey,
708
- SK: "P"
709
- });
710
- }
711
- /**
712
- * Exact revisions of all the entries
713
- */
714
- for (const revision of revisions) {
715
- entityBatch.delete({
716
- PK: (0, _keys.createPartitionKey)({
717
- id: revision.id,
718
- locale: model.locale,
719
- tenant: model.tenant
720
- }),
721
- SK: (0, _keys.createRevisionSortKey)({
722
- version: revision.version
723
- })
724
- });
725
- }
726
- await entityBatch.execute();
727
- };
728
- const getLatestRevisionByEntryId = async (initialModel, params) => {
729
- const model = getStorageOperationsModel(initialModel);
730
- const items = await dataLoaders.getLatestRevisionByEntryId({
731
- model,
732
- ids: [params.id]
733
- });
734
- const item = items.shift() || null;
735
- if (!item) {
736
- return null;
737
- }
738
- return convertFromStorageEntry({
739
- storageEntry: item,
740
- model
741
- });
742
- };
743
- const getPublishedRevisionByEntryId = async (initialModel, params) => {
744
- const model = getStorageOperationsModel(initialModel);
745
- const items = await dataLoaders.getPublishedRevisionByEntryId({
746
- model,
747
- ids: [params.id]
748
- });
749
- const item = items.shift() || null;
750
- if (!item) {
751
- return null;
752
- }
753
- return convertFromStorageEntry({
754
- storageEntry: item,
755
- model
756
- });
757
- };
758
- const getRevisionById = async (initialModel, params) => {
759
- const model = getStorageOperationsModel(initialModel);
760
- const items = await dataLoaders.getRevisionById({
761
- model,
762
- ids: [params.id]
763
- });
764
- const item = items.shift() || null;
765
- if (!item) {
766
- return null;
767
- }
768
- return convertFromStorageEntry({
769
- storageEntry: item,
770
- model
771
- });
772
- };
773
- const getRevisions = async (initialModel, params) => {
774
- const model = getStorageOperationsModel(initialModel);
775
- const items = await dataLoaders.getAllEntryRevisions({
776
- model,
777
- ids: [params.id]
778
- });
779
- return items.map(item => {
780
- return convertFromStorageEntry({
781
- storageEntry: item,
782
- model
783
- });
784
- });
785
- };
786
- const getByIds = async (initialModel, params) => {
787
- const model = getStorageOperationsModel(initialModel);
788
- const items = await dataLoaders.getRevisionById({
789
- model,
790
- ids: params.ids
791
- });
792
- return items.map(item => {
793
- return convertFromStorageEntry({
794
- storageEntry: item,
795
- model
796
- });
797
- });
798
- };
799
- const getLatestByIds = async (initialModel, params) => {
800
- const model = getStorageOperationsModel(initialModel);
801
- const items = await dataLoaders.getLatestRevisionByEntryId({
802
- model,
803
- ids: params.ids
804
- });
805
- return items.map(item => {
806
- return convertFromStorageEntry({
807
- storageEntry: item,
808
- model
809
- });
810
- });
811
- };
812
- const getPublishedByIds = async (initialModel, params) => {
813
- const model = getStorageOperationsModel(initialModel);
814
- const items = await dataLoaders.getPublishedRevisionByEntryId({
815
- model,
816
- ids: params.ids
817
- });
818
- return items.map(item => {
819
- return convertFromStorageEntry({
820
- storageEntry: item,
821
- model
822
- });
823
- });
824
- };
825
- const getPreviousRevision = async (initialModel, params) => {
826
- const model = getStorageOperationsModel(initialModel);
827
- const {
828
- entryId,
829
- version
830
- } = params;
831
- const queryParams = {
832
- entity,
833
- partitionKey: (0, _keys.createPartitionKey)({
834
- tenant: model.tenant,
835
- locale: model.locale,
836
- id: entryId
837
- }),
838
- options: {
839
- lt: `REV#${(0, _zeroPad.zeroPad)(version)}`,
840
- /**
841
- * We need to have extra checks because DynamoDB will return published or latest record if there is no REV# record.
842
- */
843
- filters: [{
844
- attr: "TYPE",
845
- eq: createType()
846
- }, {
847
- attr: "version",
848
- lt: version
849
- }],
850
- reverse: true
851
- }
284
+ const moveToBin = async (initialModel, params)=>{
285
+ const { entry, storageEntry: initialStorageEntry } = params;
286
+ const model = getStorageOperationsModel(initialModel);
287
+ let records = [];
288
+ try {
289
+ records = await entity.queryAll({
290
+ partitionKey: createPartitionKey({
291
+ id: entry.id,
292
+ tenant: model.tenant
293
+ }),
294
+ options: {
295
+ gte: " "
296
+ }
297
+ });
298
+ } catch (ex) {
299
+ throw new error(ex.message || "Could not load all records.", ex.code || "LOAD_ALL_RECORDS_ERROR", {
300
+ error: ex,
301
+ id: entry.id
302
+ });
303
+ }
304
+ if (0 === records.length) return;
305
+ const storageEntry = convertToStorageEntry({
306
+ model,
307
+ storageEntry: initialStorageEntry
308
+ });
309
+ const updatedDeletedMetaFields = pickEntryMetaFields(storageEntry, isDeletedEntryMetaField);
310
+ const entityBatch = entity.createEntityWriter({
311
+ put: records.map((record)=>({
312
+ ...record,
313
+ data: {
314
+ ...record.data,
315
+ ...updatedDeletedMetaFields,
316
+ wbyDeleted: storageEntry.wbyDeleted,
317
+ location: storageEntry.location,
318
+ binOriginalFolderId: storageEntry.binOriginalFolderId
319
+ }
320
+ }))
321
+ });
322
+ try {
323
+ await entityBatch.execute();
324
+ dataLoaders.clearAll({
325
+ tenant: entry.tenant
326
+ });
327
+ } catch (ex) {
328
+ throw new error(ex.message || "Could not move the entry to the bin.", ex.code || "MOVE_ENTRY_TO_BIN_ERROR", {
329
+ error: ex,
330
+ entry,
331
+ storageEntry
332
+ });
333
+ }
852
334
  };
853
- try {
854
- const result = await (0, _dbDynamodb.queryOne)(queryParams);
855
- const storageEntry = (0, _dbDynamodb.cleanupItem)(entity, result);
856
- if (!storageEntry) {
857
- return null;
858
- }
859
- return convertFromStorageEntry({
860
- storageEntry,
861
- model
862
- });
863
- } catch (ex) {
864
- throw new _error.default(ex.message || "Could not get previous version of given entry.", ex.code || "GET_PREVIOUS_VERSION_ERROR", {
865
- ...params,
866
- error: ex,
867
- partitionKey: queryParams.partitionKey,
868
- options: queryParams.options,
869
- model
870
- });
871
- }
872
- };
873
- const list = async (initialModel, params) => {
874
- const model = getStorageOperationsModel(initialModel);
875
- const {
876
- limit: initialLimit = 10,
877
- where: initialWhere,
878
- after,
879
- sort: sortBy,
880
- fields,
881
- search
882
- } = params;
883
- const limit = initialLimit <= 0 || initialLimit >= MAX_LIST_LIMIT ? MAX_LIST_LIMIT : initialLimit;
884
- const type = initialWhere.published ? "P" : "L";
885
- const queryAllParams = {
886
- entity,
887
- partitionKey: (0, _keys.createGSIPartitionKey)(model, type),
888
- options: {
889
- index: "GSI1",
890
- gte: " "
891
- }
335
+ const deleteEntry = async (initialModel, params)=>{
336
+ const { entry } = params;
337
+ const id = entry.id || entry.entryId;
338
+ const model = getStorageOperationsModel(initialModel);
339
+ const partitionKey = createPartitionKey({
340
+ id,
341
+ tenant: model.tenant
342
+ });
343
+ let records = [];
344
+ try {
345
+ records = await entity.queryAll({
346
+ partitionKey,
347
+ options: {
348
+ gte: " "
349
+ }
350
+ });
351
+ } catch (ex) {
352
+ throw new error(ex.message || "Could not load all records.", ex.code || "LOAD_ALL_RECORDS_ERROR", {
353
+ error: ex,
354
+ id
355
+ });
356
+ }
357
+ const entityBatch = entity.createEntityWriter({
358
+ delete: records.map((item)=>({
359
+ PK: item.PK,
360
+ SK: item.SK
361
+ }))
362
+ });
363
+ try {
364
+ await entityBatch.execute();
365
+ dataLoaders.clearAll({
366
+ tenant: entry.tenant
367
+ });
368
+ } catch (ex) {
369
+ throw new error(ex.message || "Could not delete the entry.", ex.code || "DELETE_ENTRY_ERROR", {
370
+ error: ex,
371
+ partitionKey,
372
+ id
373
+ });
374
+ }
892
375
  };
893
- let storageEntries = [];
894
- try {
895
- storageEntries = await (0, _dbDynamodb.queryAll)(queryAllParams);
896
- } catch (ex) {
897
- throw new _error.default(ex.message, "QUERY_ENTRIES_ERROR", {
898
- error: ex,
899
- partitionKey: queryAllParams.partitionKey,
900
- options: queryAllParams.options
901
- });
902
- }
903
- if (storageEntries.length === 0) {
904
- return {
905
- hasMoreItems: false,
906
- totalCount: 0,
907
- cursor: null,
908
- items: []
909
- };
910
- }
911
- const where = {
912
- ...initialWhere
376
+ const restoreFromBin = async (initialModel, params)=>{
377
+ const { entry, storageEntry: initialStorageEntry } = params;
378
+ const model = getStorageOperationsModel(initialModel);
379
+ let records = [];
380
+ try {
381
+ records = await entity.queryAll({
382
+ partitionKey: createPartitionKey({
383
+ id: entry.id,
384
+ tenant: model.tenant
385
+ }),
386
+ options: {
387
+ gte: " "
388
+ }
389
+ });
390
+ } catch (ex) {
391
+ throw new error(ex.message || "Could not load all records.", ex.code || "LOAD_ALL_RECORDS_ERROR", {
392
+ error: ex,
393
+ id: entry.id
394
+ });
395
+ }
396
+ if (0 === records.length) return initialStorageEntry;
397
+ const storageEntry = convertToStorageEntry({
398
+ model,
399
+ storageEntry: initialStorageEntry
400
+ });
401
+ const updatedRestoredMetaFields = pickEntryMetaFields(storageEntry, isRestoredEntryMetaField);
402
+ const entityBatch = entity.createEntityWriter({
403
+ put: records.map((record)=>({
404
+ ...record,
405
+ data: {
406
+ ...record.data,
407
+ ...updatedRestoredMetaFields,
408
+ wbyDeleted: storageEntry.wbyDeleted,
409
+ location: storageEntry.location,
410
+ binOriginalFolderId: storageEntry.binOriginalFolderId
411
+ }
412
+ }))
413
+ });
414
+ try {
415
+ await entityBatch.execute();
416
+ dataLoaders.clearAll({
417
+ tenant: entry.tenant
418
+ });
419
+ return initialStorageEntry;
420
+ } catch (ex) {
421
+ throw new error(ex.message || "Could not restore the entry from the bin.", ex.code || "RESTORE_ENTRY_ERROR", {
422
+ error: ex,
423
+ entry,
424
+ storageEntry
425
+ });
426
+ }
913
427
  };
914
- delete where["published"];
915
- delete where["latest"];
916
- /**
917
- * We need an object containing field, transformers and paths.
918
- * Just build it here and pass on into other methods that require it to avoid mapping multiple times.
919
- */
920
- const modelFields = (0, _createFields.createFields)({
921
- plugins,
922
- fields: model.fields
923
- });
924
- const fromStorage = createStorageTransformCallable(model);
925
- /**
926
- * Let's transform records from storage ones to regular ones, so we do not need to do it later.
927
- *
928
- * This is always being done, but at least its in parallel.
929
- */
930
- const records = await Promise.all(storageEntries.map(async storageEntry => {
931
- const entry = convertFromStorageEntry({
932
- storageEntry,
933
- model
934
- });
935
- for (const field of model.fields) {
936
- entry.values[field.fieldId] = await fromStorage(field, entry.values[field.fieldId]);
937
- }
938
- return entry;
939
- }));
940
- /**
941
- * Filter the read items via the code.
942
- * It will build the filters out of the where input and transform the values it is using.
943
- */
944
- const filteredItems = (0, _filtering.filter)({
945
- items: records,
946
- where,
947
- plugins,
948
- fields: modelFields,
949
- fullTextSearch: {
950
- term: search,
951
- fields: fields || []
952
- }
953
- });
954
- const totalCount = filteredItems.length;
955
-
956
- /**
957
- * Sorting is also done via the code.
958
- * It takes the sort input and sorts by it via the lodash sortBy method.
959
- */
960
- const sortedItems = (0, _filtering.sort)({
961
- model,
962
- plugins,
963
- items: filteredItems,
964
- sort: sortBy,
965
- fields: modelFields
966
- });
967
- const start = parseInt((0, _cursor.decodeCursor)(after) || "0") || 0;
968
- const hasMoreItems = totalCount > start + limit;
969
- const end = limit > totalCount + start + limit ? undefined : start + limit;
970
- const slicedItems = sortedItems.slice(start, end);
971
- /**
972
- * Although we do not need a cursor here, we will use it as such to keep it standardized.
973
- * Number is simply encoded.
974
- */
975
- const cursor = (0, _cursor.encodeCursor)(`${start + limit}`);
976
- return {
977
- hasMoreItems,
978
- totalCount,
979
- cursor,
980
- items: (0, _dbDynamodb.cleanupItems)(entity, slicedItems)
428
+ const deleteRevision = async (initialModel, params)=>{
429
+ const { entry, latestEntry, latestStorageEntry: initialLatestStorageEntry } = params;
430
+ const model = getStorageOperationsModel(initialModel);
431
+ const partitionKey = createPartitionKey({
432
+ id: entry.id,
433
+ tenant: model.tenant
434
+ });
435
+ const entityBatch = entity.createEntityWriter({
436
+ delete: [
437
+ {
438
+ PK: partitionKey,
439
+ SK: createRevisionSortKey(entry)
440
+ }
441
+ ]
442
+ });
443
+ const publishedStorageEntry = await getPublishedRevisionByEntryId(model, entry);
444
+ if (publishedStorageEntry && entry.id === publishedStorageEntry.id) entityBatch.delete({
445
+ PK: partitionKey,
446
+ SK: createPublishedSortKey()
447
+ });
448
+ if (initialLatestStorageEntry) {
449
+ const latestStorageEntry = convertToStorageEntry({
450
+ storageEntry: initialLatestStorageEntry,
451
+ model
452
+ });
453
+ entityBatch.put({
454
+ ...createEntryLatestKeys(latestStorageEntry),
455
+ data: {
456
+ ...latestStorageEntry
457
+ }
458
+ });
459
+ entityBatch.put({
460
+ ...createEntryRevisionKeys(latestStorageEntry),
461
+ data: {
462
+ ...latestStorageEntry
463
+ }
464
+ });
465
+ }
466
+ try {
467
+ await entityBatch.execute();
468
+ dataLoaders.clearAll({
469
+ tenant: entry.tenant
470
+ });
471
+ } catch (ex) {
472
+ throw new error(ex.message, ex.code, {
473
+ error: ex,
474
+ entry,
475
+ latestEntry
476
+ });
477
+ }
981
478
  };
982
- };
983
- const get = async (initialModel, params) => {
984
- const model = getStorageOperationsModel(initialModel);
985
- const {
986
- items
987
- } = await list(model, {
988
- ...params,
989
- limit: 1
990
- });
991
- return items.shift() || null;
992
- };
993
- const publish = async (initialModel, params) => {
994
- const {
995
- entry,
996
- storageEntry: initialStorageEntry
997
- } = params;
998
- const model = getStorageOperationsModel(initialModel);
999
- const partitionKey = (0, _keys.createPartitionKey)({
1000
- id: entry.id,
1001
- locale: model.locale,
1002
- tenant: model.tenant
1003
- });
1004
-
1005
- /**
1006
- * We need the latest and published entries to see if something needs to be updated alongside the publishing one.
1007
- */
1008
- const initialLatestStorageEntry = await getLatestRevisionByEntryId(model, entry);
1009
- if (!initialLatestStorageEntry) {
1010
- throw new _error.default(`Could not publish entry. Could not load latest ("L") record.`, "PUBLISH_ERROR", {
1011
- entry
1012
- });
1013
- }
1014
- const initialPublishedStorageEntry = await getPublishedRevisionByEntryId(model, entry);
1015
- const storageEntry = convertToStorageEntry({
1016
- model,
1017
- storageEntry: initialStorageEntry
1018
- });
1019
-
1020
- // 1. Update REV# and P records with new data.
1021
- const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
1022
- entity,
1023
- put: [{
1024
- ...storageEntry,
1025
- PK: partitionKey,
1026
- SK: (0, _keys.createRevisionSortKey)(entry),
1027
- TYPE: createType(),
1028
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
1029
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
1030
- }, {
1031
- ...storageEntry,
1032
- PK: partitionKey,
1033
- SK: (0, _keys.createPublishedSortKey)(),
1034
- TYPE: createPublishedType(),
1035
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "P"),
1036
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
1037
- }]
1038
- });
1039
-
1040
- // 2. When it comes to the latest record, we need to perform a couple of different
1041
- // updates, based on whether the entry being published is the latest revision or not.
1042
- const publishedRevisionId = initialPublishedStorageEntry?.id;
1043
- const publishingLatestRevision = entry.id === initialLatestStorageEntry.id;
1044
- if (publishingLatestRevision) {
1045
- // 2.1 If we're publishing the latest revision, we first need to update the L record.
1046
- entityBatch.put({
1047
- ...storageEntry,
1048
- PK: partitionKey,
1049
- SK: (0, _keys.createLatestSortKey)(),
1050
- TYPE: createLatestType(),
1051
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
1052
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
1053
- });
1054
-
1055
- // 2.2 Additionally, if we have a previously published entry, we need to mark it as unpublished.
1056
- if (publishedRevisionId && publishedRevisionId !== entry.id) {
1057
- const publishedStorageEntry = convertToStorageEntry({
1058
- storageEntry: initialPublishedStorageEntry,
1059
- model
479
+ const deleteMultipleEntries = async (initialModel, params)=>{
480
+ const { entries } = params;
481
+ const model = getStorageOperationsModel(initialModel);
482
+ const revisions = await dataLoaders.getAllEntryRevisions({
483
+ model,
484
+ ids: entries
1060
485
  });
1061
- entityBatch.put({
1062
- ...publishedStorageEntry,
1063
- PK: partitionKey,
1064
- SK: (0, _keys.createRevisionSortKey)(publishedStorageEntry),
1065
- TYPE: createType(),
1066
- status: _types.CONTENT_ENTRY_STATUS.UNPUBLISHED,
1067
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
1068
- GSI1_SK: (0, _keys.createGSISortKey)(publishedStorageEntry)
486
+ const entityBatch = entity.createEntityWriter();
487
+ for (const id of entries){
488
+ const partitionKey = createPartitionKey({
489
+ id,
490
+ tenant: model.tenant
491
+ });
492
+ entityBatch.delete({
493
+ PK: partitionKey,
494
+ SK: "L"
495
+ });
496
+ entityBatch.delete({
497
+ PK: partitionKey,
498
+ SK: "P"
499
+ });
500
+ }
501
+ for (const revision of revisions)entityBatch.delete({
502
+ PK: createPartitionKey({
503
+ id: revision.id,
504
+ tenant: model.tenant
505
+ }),
506
+ SK: createRevisionSortKey({
507
+ version: revision.version
508
+ })
1069
509
  });
1070
- }
1071
- } else {
1072
- // 2.3 If the published revision is not the latest one, the situation is a bit
1073
- // more complex. We first need to update the L and REV# records with the new
1074
- // values of *only entry-level* meta fields.
1075
- const updatedEntryLevelMetaFields = (0, _constants.pickEntryMetaFields)(entry, _constants.isEntryLevelEntryMetaField);
1076
- const latestStorageEntry = convertToStorageEntry({
1077
- storageEntry: initialLatestStorageEntry,
1078
- model
1079
- });
1080
-
1081
- // 2.3.1 Update L record. Apart from updating the entry-level meta fields, we also need
1082
- // to change the status from "published" to "unpublished" (if the status is set to "published").
1083
- let latestRevisionStatus = latestStorageEntry.status;
1084
- if (latestRevisionStatus === _types.CONTENT_ENTRY_STATUS.PUBLISHED) {
1085
- latestRevisionStatus = _types.CONTENT_ENTRY_STATUS.UNPUBLISHED;
1086
- }
1087
- const latestStorageEntryFields = {
1088
- ...latestStorageEntry,
1089
- ...updatedEntryLevelMetaFields,
1090
- status: latestRevisionStatus
1091
- };
1092
- entityBatch.put({
1093
- ...latestStorageEntryFields,
1094
- PK: partitionKey,
1095
- SK: (0, _keys.createLatestSortKey)(),
1096
- TYPE: createLatestType(),
1097
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
1098
- GSI1_SK: (0, _keys.createGSISortKey)(latestStorageEntry)
1099
- });
1100
-
1101
- // 2.3.2 Update REV# record.
1102
- entityBatch.put({
1103
- ...latestStorageEntryFields,
1104
- PK: partitionKey,
1105
- SK: (0, _keys.createRevisionSortKey)(latestStorageEntry),
1106
- TYPE: createType(),
1107
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
1108
- GSI1_SK: (0, _keys.createGSISortKey)(latestStorageEntry)
1109
- });
1110
-
1111
- // 2.3.3 Finally, if we got a published entry, but it wasn't the latest one, we need to take
1112
- // an extra step and mark it as unpublished.
1113
- const publishedRevisionDifferentFromLatest = publishedRevisionId && publishedRevisionId !== latestStorageEntry.id;
1114
- if (publishedRevisionDifferentFromLatest) {
1115
- const publishedStorageEntry = convertToStorageEntry({
1116
- storageEntry: initialPublishedStorageEntry,
1117
- model
510
+ await entityBatch.execute();
511
+ };
512
+ const getLatestRevisionByEntryId = async (initialModel, params)=>{
513
+ const model = getStorageOperationsModel(initialModel);
514
+ const items = await dataLoaders.getLatestRevisionByEntryId({
515
+ model,
516
+ ids: [
517
+ params.id
518
+ ]
1118
519
  });
1119
- entityBatch.put({
1120
- ...publishedStorageEntry,
1121
- PK: partitionKey,
1122
- SK: (0, _keys.createRevisionSortKey)(publishedStorageEntry),
1123
- TYPE: createType(),
1124
- status: _types.CONTENT_ENTRY_STATUS.UNPUBLISHED,
1125
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
1126
- GSI1_SK: (0, _keys.createGSISortKey)(publishedStorageEntry)
520
+ const item = items.shift() || null;
521
+ if (!item) return null;
522
+ return convertFromStorageEntry({
523
+ storageEntry: item,
524
+ model
1127
525
  });
1128
- }
1129
- }
1130
- try {
1131
- await entityBatch.execute();
1132
- dataLoaders.clearAll({
1133
- model
1134
- });
1135
- return initialStorageEntry;
1136
- } catch (ex) {
1137
- throw new _error.default(ex.message || "Could not execute the publishing batch.", ex.code || "PUBLISH_ERROR", {
1138
- entry,
1139
- latestStorageEntry: initialLatestStorageEntry,
1140
- publishedStorageEntry: initialPublishedStorageEntry
1141
- });
1142
- }
1143
- };
1144
- const unpublish = async (initialModel, params) => {
1145
- const {
1146
- entry,
1147
- storageEntry: initialStorageEntry
1148
- } = params;
1149
- const model = getStorageOperationsModel(initialModel);
1150
- const partitionKey = (0, _keys.createPartitionKey)({
1151
- id: entry.id,
1152
- locale: model.locale,
1153
- tenant: model.tenant
1154
- });
1155
- const storageEntry = convertToStorageEntry({
1156
- storageEntry: initialStorageEntry,
1157
- model
1158
- });
1159
- /**
1160
- * We need to:
1161
- * - delete currently published entry
1162
- * - update current entry revision with new data
1163
- * - update the latest entry status - if entry being unpublished is latest
1164
- */
1165
- const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
1166
- entity,
1167
- delete: [{
1168
- PK: partitionKey,
1169
- SK: (0, _keys.createPublishedSortKey)()
1170
- }],
1171
- put: [{
1172
- ...storageEntry,
1173
- PK: partitionKey,
1174
- SK: (0, _keys.createRevisionSortKey)(entry),
1175
- TYPE: createType(),
1176
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
1177
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
1178
- }]
1179
- });
1180
-
1181
- /**
1182
- * We need the latest entry to see if something needs to be updated alongside the unpublishing one.
1183
- */
1184
- const initialLatestStorageEntry = await getLatestRevisionByEntryId(model, entry);
1185
- if (initialLatestStorageEntry) {
1186
- const unpublishingLatestRevision = entry.id === initialLatestStorageEntry.id;
1187
- if (unpublishingLatestRevision) {
1188
- entityBatch.put({
1189
- ...storageEntry,
1190
- PK: partitionKey,
1191
- SK: (0, _keys.createLatestSortKey)(),
1192
- TYPE: createLatestType(),
1193
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
1194
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
526
+ };
527
+ const getPublishedRevisionByEntryId = async (initialModel, params)=>{
528
+ const model = getStorageOperationsModel(initialModel);
529
+ const items = await dataLoaders.getPublishedRevisionByEntryId({
530
+ model,
531
+ ids: [
532
+ params.id
533
+ ]
1195
534
  });
1196
- } else {
1197
- const latestStorageEntry = convertToStorageEntry({
1198
- storageEntry: initialLatestStorageEntry,
1199
- model
535
+ const item = items.shift() || null;
536
+ if (!item) return null;
537
+ return convertFromStorageEntry({
538
+ storageEntry: item,
539
+ model
1200
540
  });
1201
-
1202
- // If the unpublished revision is not the latest one, we still need to
1203
- // update the latest record with the new values of entry-level meta fields.
1204
- const updatedEntryLevelMetaFields = (0, _constants.pickEntryMetaFields)(entry, _constants.isEntryLevelEntryMetaField);
1205
-
1206
- // 1. Update actual revision record.
1207
- entityBatch.put({
1208
- ...latestStorageEntry,
1209
- ...updatedEntryLevelMetaFields,
1210
- PK: partitionKey,
1211
- SK: (0, _keys.createRevisionSortKey)(latestStorageEntry),
1212
- TYPE: createType(),
1213
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
1214
- GSI1_SK: (0, _keys.createGSISortKey)(latestStorageEntry)
541
+ };
542
+ const getRevisionById = async (initialModel, params)=>{
543
+ const model = getStorageOperationsModel(initialModel);
544
+ const items = await dataLoaders.getRevisionById({
545
+ model,
546
+ ids: [
547
+ params.id
548
+ ]
1215
549
  });
1216
-
1217
- // 2. Update latest record.
1218
- entityBatch.put({
1219
- ...latestStorageEntry,
1220
- ...updatedEntryLevelMetaFields,
1221
- PK: partitionKey,
1222
- SK: (0, _keys.createLatestSortKey)(),
1223
- TYPE: createLatestType(),
1224
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
1225
- GSI1_SK: (0, _keys.createGSISortKey)(latestStorageEntry)
550
+ const item = items.shift() || null;
551
+ if (!item) return null;
552
+ return convertFromStorageEntry({
553
+ storageEntry: item,
554
+ model
1226
555
  });
1227
- }
1228
- }
1229
- try {
1230
- await entityBatch.execute();
1231
- dataLoaders.clearAll({
1232
- model
1233
- });
1234
- return initialStorageEntry;
1235
- } catch (ex) {
1236
- throw new _error.default(ex.message || "Could not execute unpublish batch.", ex.code || "UNPUBLISH_ERROR", {
1237
- entry,
1238
- storageEntry
1239
- });
1240
- }
1241
- };
1242
- const getUniqueFieldValues = async (model, params) => {
1243
- const {
1244
- where,
1245
- fieldId
1246
- } = params;
1247
- const field = model.fields.find(f => f.fieldId === fieldId);
1248
- if (!field) {
1249
- throw new _error.default(`Could not find field with given "fieldId" value.`, "FIELD_NOT_FOUND", {
1250
- fieldId
1251
- });
1252
- }
1253
- const {
1254
- items
1255
- } = await list(model, {
1256
- where,
1257
- limit: MAX_LIST_LIMIT
1258
- });
1259
- const result = {};
1260
- for (const item of items) {
1261
- const fieldValue = item.values[field.fieldId];
1262
- if (!fieldValue) {
1263
- continue;
1264
- }
1265
- const values = Array.isArray(fieldValue) ? fieldValue : [fieldValue];
1266
- if (values.length === 0) {
1267
- continue;
1268
- }
1269
- for (const value of values) {
1270
- result[value] = {
1271
- value,
1272
- count: (result[value]?.count || 0) + 1
556
+ };
557
+ const getRevisions = async (initialModel, params)=>{
558
+ const model = getStorageOperationsModel(initialModel);
559
+ const items = await dataLoaders.getAllEntryRevisions({
560
+ model,
561
+ ids: [
562
+ params.id
563
+ ]
564
+ });
565
+ return items.map((item)=>convertFromStorageEntry({
566
+ storageEntry: item,
567
+ model
568
+ }));
569
+ };
570
+ const getByIds = async (initialModel, params)=>{
571
+ const model = getStorageOperationsModel(initialModel);
572
+ const items = await dataLoaders.getRevisionById({
573
+ model,
574
+ ids: params.ids
575
+ });
576
+ return items.map((item)=>convertFromStorageEntry({
577
+ storageEntry: item,
578
+ model
579
+ }));
580
+ };
581
+ const getLatestByIds = async (initialModel, params)=>{
582
+ const model = getStorageOperationsModel(initialModel);
583
+ const items = await dataLoaders.getLatestRevisionByEntryId({
584
+ model,
585
+ ids: params.ids
586
+ });
587
+ return items.map((item)=>convertFromStorageEntry({
588
+ storageEntry: item,
589
+ model
590
+ }));
591
+ };
592
+ const getPublishedByIds = async (initialModel, params)=>{
593
+ const model = getStorageOperationsModel(initialModel);
594
+ const items = await dataLoaders.getPublishedRevisionByEntryId({
595
+ model,
596
+ ids: params.ids
597
+ });
598
+ return items.map((item)=>convertFromStorageEntry({
599
+ storageEntry: item,
600
+ model
601
+ }));
602
+ };
603
+ const getPreviousRevision = async (initialModel, params)=>{
604
+ const model = getStorageOperationsModel(initialModel);
605
+ const { entryId, version } = params;
606
+ const partitionKey = createPartitionKey({
607
+ tenant: model.tenant,
608
+ id: entryId
609
+ });
610
+ const unfilteredRevisions = await entity.queryAll({
611
+ partitionKey,
612
+ options: {
613
+ beginsWith: "REV#",
614
+ reverse: true
615
+ }
616
+ });
617
+ const filteredRevisions = unfilteredRevisions.filter((item)=>item.data.version < version);
618
+ const storageEntry = filteredRevisions[0];
619
+ if (!storageEntry) return null;
620
+ try {
621
+ return convertFromStorageEntry({
622
+ storageEntry: storageEntry.data,
623
+ model
624
+ });
625
+ } catch (ex) {
626
+ throw new error(ex.message || "Could not get previous version of given entry.", ex.code || "GET_PREVIOUS_VERSION_ERROR", {
627
+ ...params,
628
+ error: ex,
629
+ partitionKey,
630
+ model
631
+ });
632
+ }
633
+ };
634
+ const list = async (initialModel, params)=>{
635
+ const model = getStorageOperationsModel(initialModel);
636
+ const { limit: initialLimit = 10, where: initialWhere, after, sort: sortBy, fields, search } = params;
637
+ const limit = initialLimit <= 0 || initialLimit >= MAX_LIST_LIMIT ? MAX_LIST_LIMIT : initialLimit;
638
+ const type = initialWhere.published ? "P" : "L";
639
+ const partitionKey = createGSIPartitionKey(model, type);
640
+ const options = {
641
+ index: "GSI1",
642
+ gte: " "
1273
643
  };
1274
- }
1275
- }
1276
- return Object.values(result).sort((a, b) => a.value > b.value ? 1 : b.value > a.value ? -1 : 0).sort((a, b) => b.count - a.count);
1277
- };
1278
- return {
1279
- create,
1280
- createRevisionFrom,
1281
- update,
1282
- move,
1283
- delete: deleteEntry,
1284
- moveToBin,
1285
- restoreFromBin,
1286
- deleteRevision,
1287
- deleteMultipleEntries,
1288
- getPreviousRevision,
1289
- getPublishedByIds,
1290
- getLatestByIds,
1291
- getByIds,
1292
- getRevisionById,
1293
- getPublishedRevisionByEntryId,
1294
- getLatestRevisionByEntryId,
1295
- get,
1296
- getRevisions,
1297
- publish,
1298
- list,
1299
- unpublish,
1300
- dataLoaders,
1301
- getUniqueFieldValues
1302
- };
644
+ let storageEntries = [];
645
+ try {
646
+ storageEntries = await entity.queryAll({
647
+ partitionKey,
648
+ options
649
+ });
650
+ } catch (ex) {
651
+ throw new error(ex.message, "QUERY_ENTRIES_ERROR", {
652
+ error: ex,
653
+ partitionKey,
654
+ options
655
+ });
656
+ }
657
+ if (0 === storageEntries.length) return {
658
+ hasMoreItems: false,
659
+ totalCount: 0,
660
+ cursor: null,
661
+ items: []
662
+ };
663
+ const where = {
664
+ ...initialWhere
665
+ };
666
+ delete where["published"];
667
+ delete where["latest"];
668
+ const modelFields = createFields({
669
+ plugins,
670
+ fields: model.fields
671
+ });
672
+ const fromStorage = createStorageTransformCallable(storageTransformRegistry, model);
673
+ const records = await Promise.all(storageEntries.map(async (storageEntry)=>{
674
+ const entry = convertFromStorageEntry({
675
+ storageEntry: storageEntry.data,
676
+ model
677
+ });
678
+ for (const field of model.fields)entry.values[field.fieldId] = await fromStorage(field, entry.values[field.fieldId]);
679
+ return entry;
680
+ }));
681
+ const valueFilterRegistry = container.resolve(ValueFilterRegistry);
682
+ const filteredItems = filter({
683
+ items: records,
684
+ where,
685
+ plugins,
686
+ fields: modelFields,
687
+ fullTextSearch: {
688
+ term: search,
689
+ fields: fields || []
690
+ },
691
+ valueFilterRegistry
692
+ });
693
+ const totalCount = filteredItems.length;
694
+ const sortedItems = sort({
695
+ model,
696
+ plugins,
697
+ items: filteredItems,
698
+ sort: sortBy,
699
+ fields: modelFields
700
+ });
701
+ const start = parseInt(decodeCursor(after) || "0") || 0;
702
+ const hasMoreItems = totalCount > start + limit;
703
+ const end = limit > totalCount + start + limit ? void 0 : start + limit;
704
+ const slicedItems = sortedItems.slice(start, end);
705
+ const cursor = encodeCursor(`${start + limit}`);
706
+ return {
707
+ hasMoreItems,
708
+ totalCount,
709
+ cursor,
710
+ items: slicedItems
711
+ };
712
+ };
713
+ const get = async (initialModel, params)=>{
714
+ const model = getStorageOperationsModel(initialModel);
715
+ const { items } = await list(model, {
716
+ ...params,
717
+ limit: 1
718
+ });
719
+ return items.shift() || null;
720
+ };
721
+ const publish = async (initialModel, params)=>{
722
+ const { entry, storageEntry: initialStorageEntry } = params;
723
+ const model = getStorageOperationsModel(initialModel);
724
+ const initialLatestStorageEntry = await getLatestRevisionByEntryId(model, entry);
725
+ if (!initialLatestStorageEntry) throw new error('Could not publish entry. Could not load latest ("L") record.', "PUBLISH_ERROR", {
726
+ entry
727
+ });
728
+ const initialPublishedStorageEntry = await getPublishedRevisionByEntryId(model, entry);
729
+ const storageEntry = convertToStorageEntry({
730
+ model,
731
+ storageEntry: initialStorageEntry
732
+ });
733
+ const entityBatch = entity.createEntityWriter({
734
+ put: [
735
+ {
736
+ ...createEntryRevisionKeys(storageEntry),
737
+ data: {
738
+ ...storageEntry
739
+ }
740
+ },
741
+ {
742
+ ...createEntryPublishedKeys(storageEntry),
743
+ data: {
744
+ ...storageEntry
745
+ }
746
+ }
747
+ ]
748
+ });
749
+ const publishedRevisionId = initialPublishedStorageEntry?.id;
750
+ const publishingLatestRevision = entry.id === initialLatestStorageEntry.id;
751
+ if (publishingLatestRevision) {
752
+ entityBatch.put({
753
+ ...createEntryLatestKeys(storageEntry),
754
+ data: {
755
+ ...storageEntry
756
+ }
757
+ });
758
+ if (publishedRevisionId && publishedRevisionId !== entry.id) {
759
+ const publishedStorageEntry = convertToStorageEntry({
760
+ storageEntry: initialPublishedStorageEntry,
761
+ model
762
+ });
763
+ entityBatch.put({
764
+ ...createEntryRevisionKeys(publishedStorageEntry),
765
+ data: {
766
+ ...publishedStorageEntry,
767
+ status: CONTENT_ENTRY_STATUS.UNPUBLISHED
768
+ }
769
+ });
770
+ }
771
+ } else {
772
+ const updatedEntryLevelMetaFields = pickEntryMetaFields(entry, isEntryLevelEntryMetaField);
773
+ const latestStorageEntry = convertToStorageEntry({
774
+ storageEntry: initialLatestStorageEntry,
775
+ model
776
+ });
777
+ let latestRevisionStatus = latestStorageEntry.status;
778
+ if (latestRevisionStatus === CONTENT_ENTRY_STATUS.PUBLISHED) latestRevisionStatus = CONTENT_ENTRY_STATUS.UNPUBLISHED;
779
+ const latestStorageEntryFields = {
780
+ ...latestStorageEntry,
781
+ ...updatedEntryLevelMetaFields,
782
+ status: latestRevisionStatus
783
+ };
784
+ entityBatch.put({
785
+ ...createEntryLatestKeys(latestStorageEntryFields),
786
+ data: {
787
+ ...latestStorageEntryFields
788
+ }
789
+ });
790
+ entityBatch.put({
791
+ ...createEntryRevisionKeys(latestStorageEntryFields),
792
+ data: {
793
+ ...latestStorageEntryFields
794
+ }
795
+ });
796
+ const publishedRevisionDifferentFromLatest = publishedRevisionId && publishedRevisionId !== latestStorageEntry.id;
797
+ if (publishedRevisionDifferentFromLatest) {
798
+ const publishedStorageEntry = convertToStorageEntry({
799
+ storageEntry: initialPublishedStorageEntry,
800
+ model
801
+ });
802
+ entityBatch.put({
803
+ ...createEntryRevisionKeys(publishedStorageEntry),
804
+ data: {
805
+ ...publishedStorageEntry,
806
+ status: CONTENT_ENTRY_STATUS.UNPUBLISHED
807
+ }
808
+ });
809
+ }
810
+ }
811
+ try {
812
+ await entityBatch.execute();
813
+ dataLoaders.clearAll({
814
+ tenant: entry.tenant
815
+ });
816
+ return initialStorageEntry;
817
+ } catch (ex) {
818
+ throw new error(ex.message || "Could not execute the publishing batch.", ex.code || "PUBLISH_ERROR", {
819
+ entry,
820
+ latestStorageEntry: initialLatestStorageEntry,
821
+ publishedStorageEntry: initialPublishedStorageEntry
822
+ });
823
+ }
824
+ };
825
+ const unpublish = async (initialModel, params)=>{
826
+ const { entry, storageEntry: initialStorageEntry } = params;
827
+ const model = getStorageOperationsModel(initialModel);
828
+ const partitionKey = createPartitionKey({
829
+ id: entry.id,
830
+ tenant: model.tenant
831
+ });
832
+ const storageEntry = convertToStorageEntry({
833
+ storageEntry: initialStorageEntry,
834
+ model
835
+ });
836
+ const entityBatch = entity.createEntityWriter({
837
+ delete: [
838
+ {
839
+ PK: partitionKey,
840
+ SK: createPublishedSortKey()
841
+ }
842
+ ],
843
+ put: [
844
+ {
845
+ ...createEntryRevisionKeys(storageEntry),
846
+ data: {
847
+ ...storageEntry
848
+ }
849
+ }
850
+ ]
851
+ });
852
+ const initialLatestStorageEntry = await getLatestRevisionByEntryId(model, entry);
853
+ if (initialLatestStorageEntry) {
854
+ const unpublishingLatestRevision = entry.id === initialLatestStorageEntry.id;
855
+ if (unpublishingLatestRevision) entityBatch.put({
856
+ ...createEntryLatestKeys(storageEntry),
857
+ data: {
858
+ ...storageEntry
859
+ }
860
+ });
861
+ else {
862
+ const latestStorageEntry = convertToStorageEntry({
863
+ storageEntry: initialLatestStorageEntry,
864
+ model
865
+ });
866
+ const updatedEntryLevelMetaFields = pickEntryMetaFields(entry, isEntryLevelEntryMetaField);
867
+ entityBatch.put({
868
+ ...createEntryRevisionKeys(latestStorageEntry),
869
+ data: {
870
+ ...latestStorageEntry,
871
+ ...updatedEntryLevelMetaFields
872
+ }
873
+ });
874
+ entityBatch.put({
875
+ ...createEntryLatestKeys(latestStorageEntry),
876
+ data: {
877
+ ...latestStorageEntry,
878
+ ...updatedEntryLevelMetaFields
879
+ }
880
+ });
881
+ }
882
+ }
883
+ try {
884
+ await entityBatch.execute();
885
+ dataLoaders.clearAll({
886
+ tenant: entry.tenant
887
+ });
888
+ return initialStorageEntry;
889
+ } catch (ex) {
890
+ throw new error(ex.message || "Could not execute unpublish batch.", ex.code || "UNPUBLISH_ERROR", {
891
+ entry,
892
+ storageEntry
893
+ });
894
+ }
895
+ };
896
+ const getUniqueFieldValues = async (model, params)=>{
897
+ const { where, fieldId } = params;
898
+ const field = model.fields.find((f)=>f.fieldId === fieldId);
899
+ if (!field) throw new error('Could not find field with given "fieldId" value.', "FIELD_NOT_FOUND", {
900
+ fieldId
901
+ });
902
+ const { items } = await list(model, {
903
+ where,
904
+ limit: MAX_LIST_LIMIT
905
+ });
906
+ return aggregateUniqueFieldValues(items, field.fieldId);
907
+ };
908
+ return {
909
+ create,
910
+ createRevisionFrom,
911
+ update,
912
+ updateRevision,
913
+ move,
914
+ delete: deleteEntry,
915
+ moveToBin,
916
+ restoreFromBin,
917
+ deleteRevision,
918
+ deleteMultipleEntries,
919
+ getPreviousRevision,
920
+ getPublishedByIds,
921
+ getLatestByIds,
922
+ getByIds,
923
+ getRevisionById,
924
+ getPublishedRevisionByEntryId,
925
+ getLatestRevisionByEntryId,
926
+ get,
927
+ getRevisions,
928
+ publish,
929
+ list,
930
+ unpublish,
931
+ dataLoaders,
932
+ getUniqueFieldValues
933
+ };
1303
934
  };
1304
- exports.createEntriesStorageOperations = createEntriesStorageOperations;
935
+ export { createEntriesStorageOperations };
1305
936
 
1306
937
  //# sourceMappingURL=index.js.map