@webiny/api-headless-cms-ddb 0.0.0-unstable.e3f4727c56 → 0.0.0-unstable.eb196ccd2f

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 (161) hide show
  1. package/definitions/entry.d.ts +4 -3
  2. package/definitions/entry.js +108 -16
  3. package/definitions/entry.js.map +1 -1
  4. package/definitions/group.d.ts +4 -3
  5. package/definitions/group.js +8 -12
  6. package/definitions/group.js.map +1 -1
  7. package/definitions/model.d.ts +4 -3
  8. package/definitions/model.js +25 -12
  9. package/definitions/model.js.map +1 -1
  10. package/definitions/system.d.ts +4 -3
  11. package/definitions/system.js +8 -12
  12. package/definitions/system.js.map +1 -1
  13. package/definitions/table.d.ts +5 -5
  14. package/definitions/table.js +7 -6
  15. package/definitions/table.js.map +1 -1
  16. package/dynamoDb/index.js +4 -9
  17. package/dynamoDb/index.js.map +1 -1
  18. package/dynamoDb/path/locationFolderId.d.ts +2 -0
  19. package/dynamoDb/path/locationFolderId.js +43 -0
  20. package/dynamoDb/path/locationFolderId.js.map +1 -0
  21. package/dynamoDb/path/plainObject.js +3 -8
  22. package/dynamoDb/path/plainObject.js.map +1 -1
  23. package/dynamoDb/storage/longText.js +4 -18
  24. package/dynamoDb/storage/longText.js.map +1 -1
  25. package/dynamoDb/storage/richText.js +23 -75
  26. package/dynamoDb/storage/richText.js.map +1 -1
  27. package/dynamoDb/transformValue/datetime.d.ts +1 -1
  28. package/dynamoDb/transformValue/datetime.js +3 -8
  29. package/dynamoDb/transformValue/datetime.js.map +1 -1
  30. package/index.d.ts +1 -1
  31. package/index.js +15 -44
  32. package/index.js.map +1 -1
  33. package/operations/entry/dataLoader/DataLoaderCache.d.ts +17 -0
  34. package/operations/entry/dataLoader/DataLoaderCache.js +41 -0
  35. package/operations/entry/dataLoader/DataLoaderCache.js.map +1 -0
  36. package/operations/entry/dataLoader/constants.d.ts +1 -0
  37. package/operations/entry/dataLoader/constants.js +10 -0
  38. package/operations/entry/dataLoader/constants.js.map +1 -0
  39. package/operations/entry/dataLoader/createBatchScheduleFn.d.ts +8 -0
  40. package/operations/entry/dataLoader/createBatchScheduleFn.js +25 -0
  41. package/operations/entry/dataLoader/createBatchScheduleFn.js.map +1 -0
  42. package/operations/entry/dataLoader/getAllEntryRevisions.d.ts +4 -0
  43. package/operations/entry/dataLoader/getAllEntryRevisions.js +45 -0
  44. package/operations/entry/dataLoader/getAllEntryRevisions.js.map +1 -0
  45. package/operations/entry/dataLoader/getLatestRevisionByEntryId.d.ts +4 -0
  46. package/operations/entry/dataLoader/getLatestRevisionByEntryId.js +56 -0
  47. package/operations/entry/dataLoader/getLatestRevisionByEntryId.js.map +1 -0
  48. package/operations/entry/dataLoader/getPublishedRevisionByEntryId.d.ts +4 -0
  49. package/operations/entry/dataLoader/getPublishedRevisionByEntryId.js +56 -0
  50. package/operations/entry/dataLoader/getPublishedRevisionByEntryId.js.map +1 -0
  51. package/operations/entry/dataLoader/getRevisionById.d.ts +4 -0
  52. package/operations/entry/dataLoader/getRevisionById.js +62 -0
  53. package/operations/entry/dataLoader/getRevisionById.js.map +1 -0
  54. package/operations/entry/dataLoader/index.d.ts +8 -0
  55. package/operations/entry/dataLoader/index.js +40 -0
  56. package/operations/entry/dataLoader/index.js.map +1 -0
  57. package/operations/entry/dataLoader/types.d.ts +6 -0
  58. package/operations/entry/dataLoader/types.js +7 -0
  59. package/operations/entry/dataLoader/types.js.map +1 -0
  60. package/operations/entry/dataLoaders.d.ts +12 -27
  61. package/operations/entry/dataLoaders.js +55 -260
  62. package/operations/entry/dataLoaders.js.map +1 -1
  63. package/operations/entry/filtering/createExpressions.d.ts +4 -4
  64. package/operations/entry/filtering/createExpressions.js +4 -39
  65. package/operations/entry/filtering/createExpressions.js.map +1 -1
  66. package/operations/entry/filtering/createFields.d.ts +6 -4
  67. package/operations/entry/filtering/createFields.js +76 -91
  68. package/operations/entry/filtering/createFields.js.map +1 -1
  69. package/operations/entry/filtering/extractSort.d.ts +3 -3
  70. package/operations/entry/filtering/extractSort.js +2 -10
  71. package/operations/entry/filtering/extractSort.js.map +1 -1
  72. package/operations/entry/filtering/filter.d.ts +3 -3
  73. package/operations/entry/filtering/filter.js +24 -44
  74. package/operations/entry/filtering/filter.js.map +1 -1
  75. package/operations/entry/filtering/fullTextSearch.d.ts +3 -3
  76. package/operations/entry/filtering/fullTextSearch.js +2 -12
  77. package/operations/entry/filtering/fullTextSearch.js.map +1 -1
  78. package/operations/entry/filtering/getValue.js +5 -20
  79. package/operations/entry/filtering/getValue.js.map +1 -1
  80. package/operations/entry/filtering/index.js +2 -2
  81. package/operations/entry/filtering/index.js.map +1 -1
  82. package/operations/entry/filtering/mapPlugins.d.ts +2 -2
  83. package/operations/entry/filtering/mapPlugins.js +2 -8
  84. package/operations/entry/filtering/mapPlugins.js.map +1 -1
  85. package/operations/entry/filtering/plugins/defaultFilterCreate.d.ts +1 -1
  86. package/operations/entry/filtering/plugins/defaultFilterCreate.js +5 -8
  87. package/operations/entry/filtering/plugins/defaultFilterCreate.js.map +1 -1
  88. package/operations/entry/filtering/plugins/index.d.ts +1 -1
  89. package/operations/entry/filtering/plugins/index.js +4 -6
  90. package/operations/entry/filtering/plugins/index.js.map +1 -1
  91. package/operations/entry/filtering/plugins/objectFilterCreate.d.ts +1 -1
  92. package/operations/entry/filtering/plugins/objectFilterCreate.js +5 -22
  93. package/operations/entry/filtering/plugins/objectFilterCreate.js.map +1 -1
  94. package/operations/entry/filtering/plugins/refFilterCreate.d.ts +2 -1
  95. package/operations/entry/filtering/plugins/refFilterCreate.js +11 -20
  96. package/operations/entry/filtering/plugins/refFilterCreate.js.map +1 -1
  97. package/operations/entry/filtering/plugins/searchableJsonFilterCreate.d.ts +2 -0
  98. package/operations/entry/filtering/plugins/searchableJsonFilterCreate.js +65 -0
  99. package/operations/entry/filtering/plugins/searchableJsonFilterCreate.js.map +1 -0
  100. package/operations/entry/filtering/sort.d.ts +3 -3
  101. package/operations/entry/filtering/sort.js +4 -17
  102. package/operations/entry/filtering/sort.js.map +1 -1
  103. package/operations/entry/filtering/systemFields.d.ts +2 -2
  104. package/operations/entry/filtering/systemFields.js +48 -30
  105. package/operations/entry/filtering/systemFields.js.map +1 -1
  106. package/operations/entry/filtering/transform.d.ts +1 -1
  107. package/operations/entry/filtering/transform.js +2 -3
  108. package/operations/entry/filtering/transform.js.map +1 -1
  109. package/operations/entry/filtering/types.d.ts +2 -2
  110. package/operations/entry/filtering/types.js +3 -1
  111. package/operations/entry/filtering/types.js.map +1 -1
  112. package/operations/entry/filtering/values.d.ts +1 -1
  113. package/operations/entry/filtering/values.js +2 -6
  114. package/operations/entry/filtering/values.js.map +1 -1
  115. package/operations/entry/filtering/where.js +5 -8
  116. package/operations/entry/filtering/where.js.map +1 -1
  117. package/operations/entry/index.d.ts +3 -3
  118. package/operations/entry/index.js +705 -273
  119. package/operations/entry/index.js.map +1 -1
  120. package/operations/entry/keys.js +2 -18
  121. package/operations/entry/keys.js.map +1 -1
  122. package/operations/group/index.d.ts +3 -3
  123. package/operations/group/index.js +33 -51
  124. package/operations/group/index.js.map +1 -1
  125. package/operations/model/index.d.ts +2 -2
  126. package/operations/model/index.js +25 -37
  127. package/operations/model/index.js.map +1 -1
  128. package/operations/system/index.d.ts +2 -2
  129. package/operations/system/index.js +18 -23
  130. package/operations/system/index.js.map +1 -1
  131. package/package.json +21 -26
  132. package/plugins/CmsEntryFieldFilterPathPlugin.d.ts +3 -2
  133. package/plugins/CmsEntryFieldFilterPathPlugin.js +11 -18
  134. package/plugins/CmsEntryFieldFilterPathPlugin.js.map +1 -1
  135. package/plugins/CmsEntryFieldFilterPlugin.d.ts +10 -10
  136. package/plugins/CmsEntryFieldFilterPlugin.js +8 -12
  137. package/plugins/CmsEntryFieldFilterPlugin.js.map +1 -1
  138. package/plugins/CmsEntryFieldSortingPlugin.d.ts +2 -2
  139. package/plugins/CmsEntryFieldSortingPlugin.js +3 -14
  140. package/plugins/CmsEntryFieldSortingPlugin.js.map +1 -1
  141. package/plugins/CmsFieldFilterValueTransformPlugin.d.ts +11 -0
  142. package/plugins/CmsFieldFilterValueTransformPlugin.js +23 -0
  143. package/plugins/CmsFieldFilterValueTransformPlugin.js.map +1 -0
  144. package/plugins/index.d.ts +1 -0
  145. package/plugins/index.js +14 -7
  146. package/plugins/index.js.map +1 -1
  147. package/types.d.ts +20 -13
  148. package/types.js +5 -6
  149. package/types.js.map +1 -1
  150. package/definitions/settings.d.ts +0 -9
  151. package/definitions/settings.js +0 -58
  152. package/definitions/settings.js.map +0 -1
  153. package/dynamoDb/storage/date.d.ts +0 -3
  154. package/dynamoDb/storage/date.js +0 -109
  155. package/dynamoDb/storage/date.js.map +0 -1
  156. package/operations/entry/systemFields.d.ts +0 -2
  157. package/operations/entry/systemFields.js +0 -74
  158. package/operations/entry/systemFields.js.map +0 -1
  159. package/operations/settings/index.d.ts +0 -7
  160. package/operations/settings/index.js +0 -135
  161. package/operations/settings/index.js.map +0 -1
@@ -1,50 +1,30 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
-
5
4
  Object.defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
7
  exports.createEntriesStorageOperations = void 0;
9
-
10
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
11
-
12
8
  var _error = _interopRequireDefault(require("@webiny/error"));
13
-
14
9
  var _dataLoaders = require("./dataLoaders");
15
-
16
10
  var _types = require("@webiny/api-headless-cms/types");
17
-
18
11
  var _keys = require("./keys");
19
-
20
- var _batchWrite = require("@webiny/db-dynamodb/utils/batchWrite");
21
-
22
- var _query = require("@webiny/db-dynamodb/utils/query");
23
-
24
- var _cleanup = require("@webiny/db-dynamodb/utils/cleanup");
25
-
12
+ var _dbDynamodb = require("@webiny/db-dynamodb");
26
13
  var _cursor = require("@webiny/utils/cursor");
27
-
28
14
  var _zeroPad = require("@webiny/utils/zeroPad");
29
-
30
15
  var _apiHeadlessCms = require("@webiny/api-headless-cms");
31
-
32
16
  var _createFields = require("./filtering/createFields");
33
-
34
17
  var _filtering = require("./filtering");
35
-
18
+ var _constants = require("@webiny/api-headless-cms/constants");
36
19
  const createType = () => {
37
20
  return "cms.entry";
38
21
  };
39
-
40
22
  const createLatestType = () => {
41
23
  return `${createType()}.l`;
42
24
  };
43
-
44
25
  const createPublishedType = () => {
45
26
  return `${createType()}.p`;
46
27
  };
47
-
48
28
  const convertToStorageEntry = params => {
49
29
  const {
50
30
  model,
@@ -54,11 +34,11 @@ const convertToStorageEntry = params => {
54
34
  fields: model.fields,
55
35
  values: storageEntry.values
56
36
  });
57
- return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
37
+ return {
38
+ ...storageEntry,
58
39
  values
59
- });
40
+ };
60
41
  };
61
-
62
42
  const convertFromStorageEntry = params => {
63
43
  const {
64
44
  model,
@@ -68,51 +48,60 @@ const convertFromStorageEntry = params => {
68
48
  fields: model.fields,
69
49
  values: storageEntry.values
70
50
  });
71
- return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
51
+ return {
52
+ ...storageEntry,
72
53
  values
73
- });
54
+ };
74
55
  };
75
-
56
+ const MAX_LIST_LIMIT = 1000000;
76
57
  const createEntriesStorageOperations = params => {
77
58
  const {
78
59
  entity,
79
60
  plugins
80
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
+ };
81
74
  const dataLoaders = new _dataLoaders.DataLoadersHandler({
82
75
  entity
83
76
  });
84
- const storageTransformPlugins = plugins.byType(_apiHeadlessCms.StorageTransformPlugin.type).reduce((collection, plugin) => {
85
- collection[plugin.fieldType] = plugin;
86
- return collection;
87
- }, {});
88
-
89
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
+ }, {});
90
83
  return (field, value) => {
91
84
  const plugin = storageTransformPlugins[field.type];
92
-
93
85
  if (!plugin) {
94
86
  return value;
95
87
  }
96
-
97
88
  return plugin.fromStorage({
98
89
  model,
99
90
  field,
100
91
  value,
101
-
102
92
  getStoragePlugin(fieldType) {
103
93
  return storageTransformPlugins[fieldType] || storageTransformPlugins["*"];
104
94
  },
105
-
106
95
  plugins
107
96
  });
108
97
  };
109
98
  };
110
-
111
- const create = async (model, params) => {
99
+ const create = async (initialModel, params) => {
112
100
  const {
113
101
  entry,
114
102
  storageEntry: initialStorageEntry
115
103
  } = params;
104
+ const model = getStorageOperationsModel(initialModel);
116
105
  const partitionKey = (0, _keys.createPartitionKey)({
117
106
  id: entry.id,
118
107
  locale: model.locale,
@@ -127,44 +116,45 @@ const createEntriesStorageOperations = params => {
127
116
  /**
128
117
  * We need to:
129
118
  * - create new main entry item
130
- * - create new or update latest entry item
119
+ * - create new or update the latest entry item
131
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
+ }]
140
+ });
132
141
 
133
- const items = [entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
134
- locked,
135
- PK: partitionKey,
136
- SK: (0, _keys.createRevisionSortKey)(entry),
137
- TYPE: createType(),
138
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
139
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
140
- })), entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
141
- locked,
142
- PK: partitionKey,
143
- SK: (0, _keys.createLatestSortKey)(),
144
- TYPE: createLatestType(),
145
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
146
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
147
- }))];
148
142
  /**
149
143
  * We need to create published entry if
150
144
  */
151
-
152
145
  if (isPublished) {
153
- items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
146
+ entityBatch.put({
147
+ ...storageEntry,
154
148
  locked,
155
149
  PK: partitionKey,
156
150
  SK: (0, _keys.createPublishedSortKey)(),
157
151
  TYPE: createLatestType(),
158
152
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "P"),
159
153
  GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
160
- })));
154
+ });
161
155
  }
162
-
163
156
  try {
164
- await (0, _batchWrite.batchWriteAll)({
165
- table: entity.table,
166
- items
167
- });
157
+ await entityBatch.execute();
168
158
  dataLoaders.clearAll({
169
159
  model
170
160
  });
@@ -174,15 +164,14 @@ const createEntriesStorageOperations = params => {
174
164
  entry
175
165
  });
176
166
  }
177
-
178
167
  return initialStorageEntry;
179
168
  };
180
-
181
- const createRevisionFrom = async (model, params) => {
169
+ const createRevisionFrom = async (initialModel, params) => {
182
170
  const {
183
171
  entry,
184
172
  storageEntry: initialStorageEntry
185
173
  } = params;
174
+ const model = getStorageOperationsModel(initialModel);
186
175
  const partitionKey = (0, _keys.createPartitionKey)({
187
176
  id: entry.id,
188
177
  locale: model.locale,
@@ -192,31 +181,63 @@ const createEntriesStorageOperations = params => {
192
181
  storageEntry: initialStorageEntry,
193
182
  model
194
183
  });
184
+
195
185
  /**
196
186
  * We need to:
197
187
  * - create the main entry item
198
- * - update the last entry item to a current one
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)
199
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
+ }, {
203
+ ...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
+ }]
210
+ });
211
+ const isPublished = entry.status === "published";
212
+ if (isPublished) {
213
+ entityBatch.put({
214
+ ...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
+ });
200
221
 
201
- const items = [entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
202
- PK: partitionKey,
203
- SK: (0, _keys.createRevisionSortKey)(storageEntry),
204
- TYPE: createType(),
205
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
206
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
207
- })), entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
208
- PK: partitionKey,
209
- SK: (0, _keys.createLatestSortKey)(),
210
- TYPE: createLatestType(),
211
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
212
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
213
- }))];
214
-
215
- try {
216
- await (0, _batchWrite.batchWriteAll)({
217
- table: entity.table,
218
- items
222
+ // Unpublish previously published revision (if any).
223
+ const [publishedRevisionStorageEntry] = await dataLoaders.getPublishedRevisionByEntryId({
224
+ model,
225
+ ids: [entry.id]
219
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)
236
+ });
237
+ }
238
+ }
239
+ try {
240
+ await entityBatch.execute();
220
241
  dataLoaders.clearAll({
221
242
  model
222
243
  });
@@ -230,16 +251,14 @@ const createEntriesStorageOperations = params => {
230
251
  /**
231
252
  * There are no modifications on the entry created so just return the data.
232
253
  */
233
-
234
-
235
254
  return initialStorageEntry;
236
255
  };
237
-
238
- const update = async (model, params) => {
256
+ const update = async (initialModel, params) => {
239
257
  const {
240
258
  entry,
241
259
  storageEntry: initialStorageEntry
242
260
  } = params;
261
+ const model = getStorageOperationsModel(initialModel);
243
262
  const partitionKey = (0, _keys.createPartitionKey)({
244
263
  id: entry.id,
245
264
  locale: model.locale,
@@ -247,7 +266,6 @@ const createEntriesStorageOperations = params => {
247
266
  });
248
267
  const isPublished = entry.status === "published";
249
268
  const locked = isPublished ? true : entry.locked;
250
- const items = [];
251
269
  const storageEntry = convertToStorageEntry({
252
270
  model,
253
271
  storageEntry: initialStorageEntry
@@ -258,48 +276,80 @@ const createEntriesStorageOperations = params => {
258
276
  * - update the latest entry if the current entry is the latest one
259
277
  */
260
278
 
261
- items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
262
- locked,
263
- PK: partitionKey,
264
- SK: (0, _keys.createRevisionSortKey)(storageEntry),
265
- TYPE: createType(),
266
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
267
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
268
- })));
269
-
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
+ });
270
291
  if (isPublished) {
271
- items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
292
+ entityBatch.put({
293
+ ...storageEntry,
272
294
  locked,
273
295
  PK: partitionKey,
274
296
  SK: (0, _keys.createPublishedSortKey)(),
275
297
  TYPE: createPublishedType(),
276
298
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "P"),
277
299
  GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
278
- })));
300
+ });
279
301
  }
302
+
280
303
  /**
281
- * We need the latest entry to update it as well if neccessary.
304
+ * We need the latest entry to update it as well if necessary.
282
305
  */
283
-
284
-
285
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)
318
+ });
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);
286
325
 
287
- if (latestStorageEntry && latestStorageEntry.id === entry.id) {
288
- items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
289
- locked,
290
- PK: partitionKey,
291
- SK: (0, _keys.createLatestSortKey)(),
292
- TYPE: createLatestType(),
293
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
294
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
295
- })));
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)
339
+ });
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)
348
+ });
349
+ }
296
350
  }
297
-
298
351
  try {
299
- await (0, _batchWrite.batchWriteAll)({
300
- table: entity.table,
301
- items
302
- });
352
+ await entityBatch.execute();
303
353
  dataLoaders.clearAll({
304
354
  model
305
355
  });
@@ -312,11 +362,69 @@ const createEntriesStorageOperations = params => {
312
362
  });
313
363
  }
314
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
+ }
385
+ };
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
+ });
315
402
 
316
- const deleteEntry = async (model, params) => {
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
414
+ }
415
+ });
416
+ }
417
+ };
418
+ const moveToBin = async (initialModel, params) => {
317
419
  const {
318
- entry
420
+ entry,
421
+ storageEntry: initialStorageEntry
319
422
  } = params;
423
+ const model = getStorageOperationsModel(initialModel);
424
+
425
+ /**
426
+ * First we need to load all the revisions and published / latest entries.
427
+ */
320
428
  const queryAllParams = {
321
429
  entity,
322
430
  partitionKey: (0, _keys.createPartitionKey)({
@@ -329,28 +437,92 @@ const createEntriesStorageOperations = params => {
329
437
  }
330
438
  };
331
439
  let records = [];
332
-
333
440
  try {
334
- records = await (0, _query.queryAll)(queryAllParams);
441
+ records = await (0, _dbDynamodb.queryAll)(queryAllParams);
335
442
  } catch (ex) {
336
443
  throw new _error.default(ex.message || "Could not load all records.", ex.code || "LOAD_ALL_RECORDS_ERROR", {
337
444
  error: ex,
338
- entry
445
+ id: entry.id
339
446
  });
340
447
  }
341
-
342
- const items = records.map(item => {
343
- return entity.deleteBatch({
344
- PK: item.PK,
345
- SK: item.SK
346
- });
448
+ if (records.length === 0) {
449
+ return;
450
+ }
451
+ const storageEntry = convertToStorageEntry({
452
+ model,
453
+ storageEntry: initialStorageEntry
347
454
  });
348
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
+ }
505
+ };
506
+ let records = [];
349
507
  try {
350
- await (0, _batchWrite.batchWriteAll)({
351
- table: entity.table,
352
- items
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
353
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();
354
526
  dataLoaders.clearAll({
355
527
  model
356
528
  });
@@ -358,57 +530,139 @@ const createEntriesStorageOperations = params => {
358
530
  throw new _error.default(ex.message || "Could not delete the entry.", ex.code || "DELETE_ENTRY_ERROR", {
359
531
  error: ex,
360
532
  partitionKey: queryAllParams.partitionKey,
361
- entry
533
+ id
362
534
  });
363
535
  }
364
536
  };
537
+ const restoreFromBin = async (initialModel, params) => {
538
+ const {
539
+ entry,
540
+ storageEntry: initialStorageEntry
541
+ } = params;
542
+ const model = getStorageOperationsModel(initialModel);
365
543
 
366
- const deleteRevision = async (model, params) => {
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
+ }
557
+ };
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) => {
367
610
  const {
368
611
  entry,
369
612
  latestEntry,
370
613
  latestStorageEntry: initialLatestStorageEntry
371
614
  } = params;
615
+ const model = getStorageOperationsModel(initialModel);
372
616
  const partitionKey = (0, _keys.createPartitionKey)({
373
617
  id: entry.id,
374
618
  locale: model.locale,
375
619
  tenant: model.tenant
376
620
  });
377
- const items = [entity.deleteBatch({
378
- PK: partitionKey,
379
- SK: (0, _keys.createRevisionSortKey)(entry)
380
- })];
621
+ const entityBatch = (0, _dbDynamodb.createEntityWriteBatch)({
622
+ entity,
623
+ delete: [{
624
+ PK: partitionKey,
625
+ SK: (0, _keys.createRevisionSortKey)(entry)
626
+ }]
627
+ });
381
628
  const publishedStorageEntry = await getPublishedRevisionByEntryId(model, entry);
629
+
382
630
  /**
383
631
  * If revision we are deleting is the published one as well, we need to delete those records as well.
384
632
  */
385
-
386
633
  if (publishedStorageEntry && entry.id === publishedStorageEntry.id) {
387
- items.push(entity.deleteBatch({
634
+ entityBatch.delete({
388
635
  PK: partitionKey,
389
636
  SK: (0, _keys.createPublishedSortKey)()
390
- }));
637
+ });
391
638
  }
392
-
393
639
  if (initialLatestStorageEntry) {
394
640
  const latestStorageEntry = convertToStorageEntry({
395
641
  storageEntry: initialLatestStorageEntry,
396
642
  model
397
643
  });
398
- items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, latestStorageEntry), {}, {
644
+ entityBatch.put({
645
+ ...latestStorageEntry,
399
646
  PK: partitionKey,
400
647
  SK: (0, _keys.createLatestSortKey)(),
401
648
  TYPE: createLatestType(),
402
649
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
403
650
  GSI1_SK: (0, _keys.createGSISortKey)(latestStorageEntry)
404
- })));
405
- }
651
+ });
406
652
 
407
- try {
408
- await (0, _batchWrite.batchWriteAll)({
409
- table: entity.table,
410
- items
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)
411
662
  });
663
+ }
664
+ try {
665
+ entityBatch.execute();
412
666
  dataLoaders.clearAll({
413
667
  model
414
668
  });
@@ -420,59 +674,104 @@ const createEntriesStorageOperations = params => {
420
674
  });
421
675
  }
422
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
+ */
423
692
 
424
- const getLatestRevisionByEntryId = async (model, params) => {
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);
425
730
  const items = await dataLoaders.getLatestRevisionByEntryId({
426
731
  model,
427
732
  ids: [params.id]
428
733
  });
429
734
  const item = items.shift() || null;
430
-
431
735
  if (!item) {
432
736
  return null;
433
737
  }
434
-
435
738
  return convertFromStorageEntry({
436
739
  storageEntry: item,
437
740
  model
438
741
  });
439
742
  };
440
-
441
- const getPublishedRevisionByEntryId = async (model, params) => {
743
+ const getPublishedRevisionByEntryId = async (initialModel, params) => {
744
+ const model = getStorageOperationsModel(initialModel);
442
745
  const items = await dataLoaders.getPublishedRevisionByEntryId({
443
746
  model,
444
747
  ids: [params.id]
445
748
  });
446
749
  const item = items.shift() || null;
447
-
448
750
  if (!item) {
449
751
  return null;
450
752
  }
451
-
452
753
  return convertFromStorageEntry({
453
754
  storageEntry: item,
454
755
  model
455
756
  });
456
757
  };
457
-
458
- const getRevisionById = async (model, params) => {
758
+ const getRevisionById = async (initialModel, params) => {
759
+ const model = getStorageOperationsModel(initialModel);
459
760
  const items = await dataLoaders.getRevisionById({
460
761
  model,
461
762
  ids: [params.id]
462
763
  });
463
764
  const item = items.shift() || null;
464
-
465
765
  if (!item) {
466
766
  return null;
467
767
  }
468
-
469
768
  return convertFromStorageEntry({
470
769
  storageEntry: item,
471
770
  model
472
771
  });
473
772
  };
474
-
475
- const getRevisions = async (model, params) => {
773
+ const getRevisions = async (initialModel, params) => {
774
+ const model = getStorageOperationsModel(initialModel);
476
775
  const items = await dataLoaders.getAllEntryRevisions({
477
776
  model,
478
777
  ids: [params.id]
@@ -484,8 +783,8 @@ const createEntriesStorageOperations = params => {
484
783
  });
485
784
  });
486
785
  };
487
-
488
- const getByIds = async (model, params) => {
786
+ const getByIds = async (initialModel, params) => {
787
+ const model = getStorageOperationsModel(initialModel);
489
788
  const items = await dataLoaders.getRevisionById({
490
789
  model,
491
790
  ids: params.ids
@@ -497,8 +796,8 @@ const createEntriesStorageOperations = params => {
497
796
  });
498
797
  });
499
798
  };
500
-
501
- const getLatestByIds = async (model, params) => {
799
+ const getLatestByIds = async (initialModel, params) => {
800
+ const model = getStorageOperationsModel(initialModel);
502
801
  const items = await dataLoaders.getLatestRevisionByEntryId({
503
802
  model,
504
803
  ids: params.ids
@@ -510,8 +809,8 @@ const createEntriesStorageOperations = params => {
510
809
  });
511
810
  });
512
811
  };
513
-
514
- const getPublishedByIds = async (model, params) => {
812
+ const getPublishedByIds = async (initialModel, params) => {
813
+ const model = getStorageOperationsModel(initialModel);
515
814
  const items = await dataLoaders.getPublishedRevisionByEntryId({
516
815
  model,
517
816
  ids: params.ids
@@ -523,8 +822,8 @@ const createEntriesStorageOperations = params => {
523
822
  });
524
823
  });
525
824
  };
526
-
527
- const getPreviousRevision = async (model, params) => {
825
+ const getPreviousRevision = async (initialModel, params) => {
826
+ const model = getStorageOperationsModel(initialModel);
528
827
  const {
529
828
  entryId,
530
829
  version
@@ -538,7 +837,6 @@ const createEntriesStorageOperations = params => {
538
837
  }),
539
838
  options: {
540
839
  lt: `REV#${(0, _zeroPad.zeroPad)(version)}`,
541
-
542
840
  /**
543
841
  * We need to have extra checks because DynamoDB will return published or latest record if there is no REV# record.
544
842
  */
@@ -552,30 +850,28 @@ const createEntriesStorageOperations = params => {
552
850
  reverse: true
553
851
  }
554
852
  };
555
-
556
853
  try {
557
- const result = await (0, _query.queryOne)(queryParams);
558
- const storageEntry = (0, _cleanup.cleanupItem)(entity, result);
559
-
854
+ const result = await (0, _dbDynamodb.queryOne)(queryParams);
855
+ const storageEntry = (0, _dbDynamodb.cleanupItem)(entity, result);
560
856
  if (!storageEntry) {
561
857
  return null;
562
858
  }
563
-
564
859
  return convertFromStorageEntry({
565
860
  storageEntry,
566
861
  model
567
862
  });
568
863
  } catch (ex) {
569
- throw new _error.default(ex.message || "Could not get previous version of given entry.", ex.code || "GET_PREVIOUS_VERSION_ERROR", (0, _objectSpread2.default)((0, _objectSpread2.default)({}, params), {}, {
864
+ throw new _error.default(ex.message || "Could not get previous version of given entry.", ex.code || "GET_PREVIOUS_VERSION_ERROR", {
865
+ ...params,
570
866
  error: ex,
571
867
  partitionKey: queryParams.partitionKey,
572
868
  options: queryParams.options,
573
869
  model
574
- }));
870
+ });
575
871
  }
576
872
  };
577
-
578
- const list = async (model, params) => {
873
+ const list = async (initialModel, params) => {
874
+ const model = getStorageOperationsModel(initialModel);
579
875
  const {
580
876
  limit: initialLimit = 10,
581
877
  where: initialWhere,
@@ -584,7 +880,7 @@ const createEntriesStorageOperations = params => {
584
880
  fields,
585
881
  search
586
882
  } = params;
587
- const limit = initialLimit <= 0 || initialLimit >= 10000 ? 10000 : initialLimit;
883
+ const limit = initialLimit <= 0 || initialLimit >= MAX_LIST_LIMIT ? MAX_LIST_LIMIT : initialLimit;
588
884
  const type = initialWhere.published ? "P" : "L";
589
885
  const queryAllParams = {
590
886
  entity,
@@ -595,9 +891,8 @@ const createEntriesStorageOperations = params => {
595
891
  }
596
892
  };
597
893
  let storageEntries = [];
598
-
599
894
  try {
600
- storageEntries = await (0, _query.queryAll)(queryAllParams);
895
+ storageEntries = await (0, _dbDynamodb.queryAll)(queryAllParams);
601
896
  } catch (ex) {
602
897
  throw new _error.default(ex.message, "QUERY_ENTRIES_ERROR", {
603
898
  error: ex,
@@ -605,7 +900,6 @@ const createEntriesStorageOperations = params => {
605
900
  options: queryAllParams.options
606
901
  });
607
902
  }
608
-
609
903
  if (storageEntries.length === 0) {
610
904
  return {
611
905
  hasMoreItems: false,
@@ -614,15 +908,15 @@ const createEntriesStorageOperations = params => {
614
908
  items: []
615
909
  };
616
910
  }
617
-
618
- const where = (0, _objectSpread2.default)({}, initialWhere);
911
+ const where = {
912
+ ...initialWhere
913
+ };
619
914
  delete where["published"];
620
915
  delete where["latest"];
621
916
  /**
622
917
  * We need an object containing field, transformers and paths.
623
918
  * Just build it here and pass on into other methods that require it to avoid mapping multiple times.
624
919
  */
625
-
626
920
  const modelFields = (0, _createFields.createFields)({
627
921
  plugins,
628
922
  fields: model.fields
@@ -633,24 +927,20 @@ const createEntriesStorageOperations = params => {
633
927
  *
634
928
  * This is always being done, but at least its in parallel.
635
929
  */
636
-
637
930
  const records = await Promise.all(storageEntries.map(async storageEntry => {
638
931
  const entry = convertFromStorageEntry({
639
932
  storageEntry,
640
933
  model
641
934
  });
642
-
643
935
  for (const field of model.fields) {
644
936
  entry.values[field.fieldId] = await fromStorage(field, entry.values[field.fieldId]);
645
937
  }
646
-
647
938
  return entry;
648
939
  }));
649
940
  /**
650
941
  * Filter the read items via the code.
651
942
  * It will build the filters out of the where input and transform the values it is using.
652
943
  */
653
-
654
944
  const filteredItems = (0, _filtering.filter)({
655
945
  items: records,
656
946
  where,
@@ -662,11 +952,11 @@ const createEntriesStorageOperations = params => {
662
952
  }
663
953
  });
664
954
  const totalCount = filteredItems.length;
955
+
665
956
  /**
666
957
  * Sorting is also done via the code.
667
958
  * It takes the sort input and sorts by it via the lodash sortBy method.
668
959
  */
669
-
670
960
  const sortedItems = (0, _filtering.sort)({
671
961
  model,
672
962
  plugins,
@@ -682,97 +972,163 @@ const createEntriesStorageOperations = params => {
682
972
  * Although we do not need a cursor here, we will use it as such to keep it standardized.
683
973
  * Number is simply encoded.
684
974
  */
685
-
686
- const cursor = totalCount > start + limit ? (0, _cursor.encodeCursor)(`${start + limit}`) : null;
975
+ const cursor = (0, _cursor.encodeCursor)(`${start + limit}`);
687
976
  return {
688
977
  hasMoreItems,
689
978
  totalCount,
690
979
  cursor,
691
- items: (0, _cleanup.cleanupItems)(entity, slicedItems)
980
+ items: (0, _dbDynamodb.cleanupItems)(entity, slicedItems)
692
981
  };
693
982
  };
694
-
695
- const get = async (model, params) => {
983
+ const get = async (initialModel, params) => {
984
+ const model = getStorageOperationsModel(initialModel);
696
985
  const {
697
986
  items
698
- } = await list(model, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, params), {}, {
987
+ } = await list(model, {
988
+ ...params,
699
989
  limit: 1
700
- }));
990
+ });
701
991
  return items.shift() || null;
702
992
  };
703
-
704
- const publish = async (model, params) => {
993
+ const publish = async (initialModel, params) => {
705
994
  const {
706
995
  entry,
707
996
  storageEntry: initialStorageEntry
708
997
  } = params;
998
+ const model = getStorageOperationsModel(initialModel);
709
999
  const partitionKey = (0, _keys.createPartitionKey)({
710
1000
  id: entry.id,
711
1001
  locale: model.locale,
712
1002
  tenant: model.tenant
713
1003
  });
1004
+
714
1005
  /**
715
- * We need the latest and published entries to see if something needs to be updated along side the publishing one.
1006
+ * We need the latest and published entries to see if something needs to be updated alongside the publishing one.
716
1007
  */
717
-
718
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
+ }
719
1014
  const initialPublishedStorageEntry = await getPublishedRevisionByEntryId(model, entry);
720
1015
  const storageEntry = convertToStorageEntry({
721
1016
  model,
722
1017
  storageEntry: initialStorageEntry
723
1018
  });
724
- /**
725
- * We need to update:
726
- * - current entry revision sort key
727
- * - published sort key
728
- * - latest sort key - if entry updated is actually latest
729
- * - previous published entry to unpublished status - if any previously published entry
730
- */
731
1019
 
732
- const items = [entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
733
- PK: partitionKey,
734
- SK: (0, _keys.createRevisionSortKey)(entry),
735
- TYPE: createType(),
736
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
737
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
738
- })), entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
739
- PK: partitionKey,
740
- SK: (0, _keys.createPublishedSortKey)(),
741
- TYPE: createPublishedType(),
742
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "P"),
743
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
744
- }))];
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
+ });
745
1039
 
746
- if (initialLatestStorageEntry && entry.id === initialLatestStorageEntry.id) {
747
- items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
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,
748
1048
  PK: partitionKey,
749
1049
  SK: (0, _keys.createLatestSortKey)(),
750
1050
  TYPE: createLatestType(),
751
1051
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
752
1052
  GSI1_SK: (0, _keys.createGSISortKey)(entry)
753
- })));
754
- }
1053
+ });
755
1054
 
756
- if (initialPublishedStorageEntry && initialPublishedStorageEntry.id !== entry.id) {
757
- const publishedStorageEntry = convertToStorageEntry({
758
- storageEntry: initialPublishedStorageEntry,
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
1060
+ });
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)
1069
+ });
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,
759
1078
  model
760
1079
  });
761
- items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, publishedStorageEntry), {}, {
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,
762
1104
  PK: partitionKey,
763
- SK: (0, _keys.createRevisionSortKey)(publishedStorageEntry),
1105
+ SK: (0, _keys.createRevisionSortKey)(latestStorageEntry),
764
1106
  TYPE: createType(),
765
- status: _types.CONTENT_ENTRY_STATUS.UNPUBLISHED,
766
1107
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
767
- GSI1_SK: (0, _keys.createGSISortKey)(publishedStorageEntry)
768
- })));
769
- }
1108
+ GSI1_SK: (0, _keys.createGSISortKey)(latestStorageEntry)
1109
+ });
770
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
1118
+ });
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)
1127
+ });
1128
+ }
1129
+ }
771
1130
  try {
772
- await (0, _batchWrite.batchWriteAll)({
773
- table: entity.table,
774
- items
775
- });
1131
+ await entityBatch.execute();
776
1132
  dataLoaders.clearAll({
777
1133
  model
778
1134
  });
@@ -785,12 +1141,12 @@ const createEntriesStorageOperations = params => {
785
1141
  });
786
1142
  }
787
1143
  };
788
-
789
- const unpublish = async (model, params) => {
1144
+ const unpublish = async (initialModel, params) => {
790
1145
  const {
791
1146
  entry,
792
1147
  storageEntry: initialStorageEntry
793
1148
  } = params;
1149
+ const model = getStorageOperationsModel(initialModel);
794
1150
  const partitionKey = (0, _keys.createPartitionKey)({
795
1151
  id: entry.id,
796
1152
  locale: model.locale,
@@ -804,40 +1160,74 @@ const createEntriesStorageOperations = params => {
804
1160
  * We need to:
805
1161
  * - delete currently published entry
806
1162
  * - update current entry revision with new data
807
- * - update latest entry status - if entry being unpublished is latest
1163
+ * - update the latest entry status - if entry being unpublished is latest
808
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
+ });
809
1180
 
810
- const items = [entity.deleteBatch({
811
- PK: partitionKey,
812
- SK: (0, _keys.createPublishedSortKey)()
813
- }), entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
814
- PK: partitionKey,
815
- SK: (0, _keys.createRevisionSortKey)(entry),
816
- TYPE: createType(),
817
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
818
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
819
- }))];
820
1181
  /**
821
- * We need the latest entry to see if something needs to be updated along side the unpublishing one.
1182
+ * We need the latest entry to see if something needs to be updated alongside the unpublishing one.
822
1183
  */
823
-
824
- const latestStorageEntry = await getLatestRevisionByEntryId(model, entry);
825
-
826
- if (latestStorageEntry && entry.id === latestStorageEntry.id) {
827
- items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
828
- PK: partitionKey,
829
- SK: (0, _keys.createLatestSortKey)(),
830
- TYPE: createLatestType(),
831
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
832
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
833
- })));
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)
1195
+ });
1196
+ } else {
1197
+ const latestStorageEntry = convertToStorageEntry({
1198
+ storageEntry: initialLatestStorageEntry,
1199
+ model
1200
+ });
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)
1215
+ });
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)
1226
+ });
1227
+ }
834
1228
  }
835
-
836
1229
  try {
837
- await (0, _batchWrite.batchWriteAll)({
838
- table: entity.table,
839
- items
840
- });
1230
+ await entityBatch.execute();
841
1231
  dataLoaders.clearAll({
842
1232
  model
843
1233
  });
@@ -849,13 +1239,52 @@ const createEntriesStorageOperations = params => {
849
1239
  });
850
1240
  }
851
1241
  };
852
-
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
1273
+ };
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
+ };
853
1278
  return {
854
1279
  create,
855
1280
  createRevisionFrom,
856
1281
  update,
1282
+ move,
857
1283
  delete: deleteEntry,
1284
+ moveToBin,
1285
+ restoreFromBin,
858
1286
  deleteRevision,
1287
+ deleteMultipleEntries,
859
1288
  getPreviousRevision,
860
1289
  getPublishedByIds,
861
1290
  getLatestByIds,
@@ -867,8 +1296,11 @@ const createEntriesStorageOperations = params => {
867
1296
  getRevisions,
868
1297
  publish,
869
1298
  list,
870
- unpublish
1299
+ unpublish,
1300
+ dataLoaders,
1301
+ getUniqueFieldValues
871
1302
  };
872
1303
  };
1304
+ exports.createEntriesStorageOperations = createEntriesStorageOperations;
873
1305
 
874
- exports.createEntriesStorageOperations = createEntriesStorageOperations;
1306
+ //# sourceMappingURL=index.js.map