@webiny/api-headless-cms-ddb 0.0.0-mt-2 → 0.0.0-unstable.085ff6572f

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 (168) hide show
  1. package/definitions/entry.d.ts +2 -1
  2. package/definitions/entry.js +12 -12
  3. package/definitions/entry.js.map +1 -0
  4. package/definitions/group.d.ts +2 -1
  5. package/definitions/group.js +3 -12
  6. package/definitions/group.js.map +1 -0
  7. package/definitions/model.d.ts +2 -1
  8. package/definitions/model.js +25 -12
  9. package/definitions/model.js.map +1 -0
  10. package/definitions/settings.d.ts +2 -1
  11. package/definitions/settings.js +3 -12
  12. package/definitions/settings.js.map +1 -0
  13. package/definitions/system.d.ts +2 -1
  14. package/definitions/system.js +3 -12
  15. package/definitions/system.js.map +1 -0
  16. package/definitions/table.d.ts +2 -1
  17. package/definitions/table.js +0 -3
  18. package/definitions/table.js.map +1 -0
  19. package/dynamoDb/index.d.ts +1 -1
  20. package/dynamoDb/index.js +7 -17
  21. package/dynamoDb/index.js.map +1 -0
  22. package/dynamoDb/path/locationFolderId.d.ts +2 -0
  23. package/dynamoDb/path/locationFolderId.js +41 -0
  24. package/dynamoDb/path/locationFolderId.js.map +1 -0
  25. package/dynamoDb/path/plainObject.d.ts +2 -3
  26. package/dynamoDb/path/plainObject.js +25 -25
  27. package/dynamoDb/path/plainObject.js.map +1 -0
  28. package/dynamoDb/storage/date.d.ts +3 -3
  29. package/dynamoDb/storage/date.js +71 -54
  30. package/dynamoDb/storage/date.js.map +1 -0
  31. package/dynamoDb/storage/longText.d.ts +7 -4
  32. package/dynamoDb/storage/longText.js +72 -64
  33. package/dynamoDb/storage/longText.js.map +1 -0
  34. package/dynamoDb/storage/richText.d.ts +2 -8
  35. package/dynamoDb/storage/richText.js +62 -77
  36. package/dynamoDb/storage/richText.js.map +1 -0
  37. package/dynamoDb/transformValue/datetime.d.ts +4 -2
  38. package/dynamoDb/transformValue/datetime.js +28 -30
  39. package/dynamoDb/transformValue/datetime.js.map +1 -0
  40. package/index.d.ts +1 -0
  41. package/index.js +54 -45
  42. package/index.js.map +1 -0
  43. package/operations/entry/dataLoader/DataLoaderCache.d.ts +17 -0
  44. package/operations/entry/dataLoader/DataLoaderCache.js +43 -0
  45. package/operations/entry/dataLoader/DataLoaderCache.js.map +1 -0
  46. package/operations/entry/dataLoader/constants.d.ts +1 -0
  47. package/operations/entry/dataLoader/constants.js +9 -0
  48. package/operations/entry/dataLoader/constants.js.map +1 -0
  49. package/operations/entry/dataLoader/createBatchScheduleFn.d.ts +8 -0
  50. package/operations/entry/dataLoader/createBatchScheduleFn.js +23 -0
  51. package/operations/entry/dataLoader/createBatchScheduleFn.js.map +1 -0
  52. package/operations/entry/dataLoader/getAllEntryRevisions.d.ts +4 -0
  53. package/operations/entry/dataLoader/getAllEntryRevisions.js +43 -0
  54. package/operations/entry/dataLoader/getAllEntryRevisions.js.map +1 -0
  55. package/operations/entry/dataLoader/getLatestRevisionByEntryId.d.ts +4 -0
  56. package/operations/entry/dataLoader/getLatestRevisionByEntryId.js +57 -0
  57. package/operations/entry/dataLoader/getLatestRevisionByEntryId.js.map +1 -0
  58. package/operations/entry/dataLoader/getPublishedRevisionByEntryId.d.ts +4 -0
  59. package/operations/entry/dataLoader/getPublishedRevisionByEntryId.js +57 -0
  60. package/operations/entry/dataLoader/getPublishedRevisionByEntryId.js.map +1 -0
  61. package/operations/entry/dataLoader/getRevisionById.d.ts +4 -0
  62. package/operations/entry/dataLoader/getRevisionById.js +63 -0
  63. package/operations/entry/dataLoader/getRevisionById.js.map +1 -0
  64. package/operations/entry/dataLoader/index.d.ts +8 -0
  65. package/operations/entry/dataLoader/index.js +38 -0
  66. package/operations/entry/dataLoader/index.js.map +1 -0
  67. package/operations/entry/dataLoader/types.d.ts +6 -0
  68. package/operations/entry/dataLoader/types.js +5 -0
  69. package/operations/entry/dataLoader/types.js.map +1 -0
  70. package/operations/entry/dataLoaders.d.ts +17 -28
  71. package/operations/entry/dataLoaders.js +51 -239
  72. package/operations/entry/dataLoaders.js.map +1 -0
  73. package/operations/entry/filtering/createExpressions.d.ts +26 -0
  74. package/operations/entry/filtering/createExpressions.js +176 -0
  75. package/operations/entry/filtering/createExpressions.js.map +1 -0
  76. package/operations/entry/filtering/createFields.d.ts +16 -0
  77. package/operations/entry/filtering/createFields.js +105 -0
  78. package/operations/entry/filtering/createFields.js.map +1 -0
  79. package/operations/entry/filtering/extractSort.d.ts +17 -0
  80. package/operations/entry/filtering/extractSort.js +67 -0
  81. package/operations/entry/filtering/extractSort.js.map +1 -0
  82. package/operations/entry/filtering/filter.d.ts +15 -0
  83. package/operations/entry/filtering/filter.js +143 -0
  84. package/operations/entry/filtering/filter.js.map +1 -0
  85. package/operations/entry/filtering/fullTextSearch.d.ts +14 -0
  86. package/operations/entry/filtering/fullTextSearch.js +48 -0
  87. package/operations/entry/filtering/fullTextSearch.js.map +1 -0
  88. package/operations/entry/filtering/getValue.d.ts +5 -0
  89. package/operations/entry/filtering/getValue.js +63 -0
  90. package/operations/entry/filtering/getValue.js.map +1 -0
  91. package/operations/entry/filtering/index.d.ts +2 -0
  92. package/operations/entry/filtering/index.js +19 -0
  93. package/operations/entry/filtering/index.js.map +1 -0
  94. package/operations/entry/filtering/mapPlugins.d.ts +8 -0
  95. package/operations/entry/filtering/mapPlugins.js +31 -0
  96. package/operations/entry/filtering/mapPlugins.js.map +1 -0
  97. package/operations/entry/filtering/plugins/defaultFilterCreate.d.ts +2 -0
  98. package/operations/entry/filtering/plugins/defaultFilterCreate.js +43 -0
  99. package/operations/entry/filtering/plugins/defaultFilterCreate.js.map +1 -0
  100. package/operations/entry/filtering/plugins/index.d.ts +1 -0
  101. package/operations/entry/filtering/plugins/index.js +13 -0
  102. package/operations/entry/filtering/plugins/index.js.map +1 -0
  103. package/operations/entry/filtering/plugins/objectFilterCreate.d.ts +2 -0
  104. package/operations/entry/filtering/plugins/objectFilterCreate.js +88 -0
  105. package/operations/entry/filtering/plugins/objectFilterCreate.js.map +1 -0
  106. package/operations/entry/filtering/plugins/refFilterCreate.d.ts +2 -0
  107. package/operations/entry/filtering/plugins/refFilterCreate.js +73 -0
  108. package/operations/entry/filtering/plugins/refFilterCreate.js.map +1 -0
  109. package/operations/entry/filtering/sort.d.ts +12 -0
  110. package/operations/entry/filtering/sort.js +69 -0
  111. package/operations/entry/filtering/sort.js.map +1 -0
  112. package/operations/entry/filtering/systemFields.d.ts +4 -0
  113. package/operations/entry/filtering/systemFields.js +88 -0
  114. package/operations/entry/filtering/systemFields.js.map +1 -0
  115. package/operations/entry/filtering/transform.d.ts +6 -0
  116. package/operations/entry/filtering/transform.js +16 -0
  117. package/operations/entry/filtering/transform.js.map +1 -0
  118. package/operations/entry/filtering/types.d.ts +40 -0
  119. package/operations/entry/filtering/types.js +5 -0
  120. package/operations/entry/filtering/types.js.map +1 -0
  121. package/operations/entry/filtering/values.d.ts +2 -0
  122. package/operations/entry/filtering/values.js +22 -0
  123. package/operations/entry/filtering/values.js.map +1 -0
  124. package/operations/entry/filtering/where.d.ts +5 -0
  125. package/operations/entry/filtering/where.js +33 -0
  126. package/operations/entry/filtering/where.js.map +1 -0
  127. package/operations/entry/index.d.ts +3 -3
  128. package/operations/entry/index.js +425 -330
  129. package/operations/entry/index.js.map +1 -0
  130. package/operations/entry/keys.js +7 -14
  131. package/operations/entry/keys.js.map +1 -0
  132. package/operations/group/index.d.ts +3 -2
  133. package/operations/group/index.js +9 -45
  134. package/operations/group/index.js.map +1 -0
  135. package/operations/model/index.d.ts +3 -2
  136. package/operations/model/index.js +13 -37
  137. package/operations/model/index.js.map +1 -0
  138. package/operations/settings/index.d.ts +3 -2
  139. package/operations/settings/index.js +7 -37
  140. package/operations/settings/index.js.map +1 -0
  141. package/operations/system/index.d.ts +3 -2
  142. package/operations/system/index.js +5 -28
  143. package/operations/system/index.js.map +1 -0
  144. package/package.json +25 -26
  145. package/plugins/CmsEntryFieldFilterPathPlugin.d.ts +23 -0
  146. package/plugins/CmsEntryFieldFilterPathPlugin.js +43 -0
  147. package/plugins/CmsEntryFieldFilterPathPlugin.js.map +1 -0
  148. package/plugins/CmsEntryFieldFilterPlugin.d.ts +43 -0
  149. package/plugins/CmsEntryFieldFilterPlugin.js +24 -0
  150. package/plugins/CmsEntryFieldFilterPlugin.js.map +1 -0
  151. package/plugins/CmsEntryFieldSortingPlugin.d.ts +42 -0
  152. package/plugins/CmsEntryFieldSortingPlugin.js +28 -0
  153. package/plugins/CmsEntryFieldSortingPlugin.js.map +1 -0
  154. package/plugins/CmsFieldFilterValueTransformPlugin.d.ts +11 -0
  155. package/plugins/CmsFieldFilterValueTransformPlugin.js +24 -0
  156. package/plugins/CmsFieldFilterValueTransformPlugin.js.map +1 -0
  157. package/plugins/index.d.ts +4 -0
  158. package/plugins/index.js +49 -0
  159. package/plugins/index.js.map +1 -0
  160. package/types.d.ts +11 -33
  161. package/types.js +0 -1
  162. package/types.js.map +1 -0
  163. package/dynamoDb/path/ref.d.ts +0 -3
  164. package/dynamoDb/path/ref.js +0 -27
  165. package/operations/entry/systemFields.d.ts +0 -2
  166. package/operations/entry/systemFields.js +0 -50
  167. package/operations/entry/utils.d.ts +0 -31
  168. package/operations/entry/utils.js +0 -406
@@ -1,57 +1,76 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
5
4
  Object.defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
7
  exports.createEntriesStorageOperations = void 0;
9
-
10
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
-
8
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
12
9
  var _error = _interopRequireDefault(require("@webiny/error"));
13
-
14
10
  var _dataLoaders = require("./dataLoaders");
15
-
16
11
  var _types = require("@webiny/api-headless-cms/types");
17
-
18
- var _utils = require("./utils");
19
-
20
12
  var _keys = require("./keys");
21
-
22
13
  var _batchWrite = require("@webiny/db-dynamodb/utils/batchWrite");
23
-
24
14
  var _query = require("@webiny/db-dynamodb/utils/query");
25
-
26
15
  var _cleanup = require("@webiny/db-dynamodb/utils/cleanup");
27
-
28
16
  var _cursor = require("@webiny/utils/cursor");
29
-
30
17
  var _zeroPad = require("@webiny/utils/zeroPad");
31
-
32
18
  var _apiHeadlessCms = require("@webiny/api-headless-cms");
33
-
34
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
35
-
36
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
37
-
19
+ var _createFields = require("./filtering/createFields");
20
+ var _filtering = require("./filtering");
38
21
  const createType = () => {
39
22
  return "cms.entry";
40
23
  };
41
-
42
24
  const createLatestType = () => {
43
25
  return `${createType()}.l`;
44
26
  };
45
-
46
27
  const createPublishedType = () => {
47
28
  return `${createType()}.p`;
48
29
  };
49
-
30
+ const convertToStorageEntry = params => {
31
+ const {
32
+ model,
33
+ storageEntry
34
+ } = params;
35
+ const values = model.convertValueKeyToStorage({
36
+ fields: model.fields,
37
+ values: storageEntry.values
38
+ });
39
+ return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
40
+ values
41
+ });
42
+ };
43
+ const convertFromStorageEntry = params => {
44
+ const {
45
+ model,
46
+ storageEntry
47
+ } = params;
48
+ const values = model.convertValueKeyFromStorage({
49
+ fields: model.fields,
50
+ values: storageEntry.values
51
+ });
52
+ return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
53
+ values
54
+ });
55
+ };
56
+ const MAX_LIST_LIMIT = 10000;
50
57
  const createEntriesStorageOperations = params => {
51
58
  const {
52
59
  entity,
53
60
  plugins
54
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
+ };
55
74
  const dataLoaders = new _dataLoaders.DataLoadersHandler({
56
75
  entity
57
76
  });
@@ -59,48 +78,54 @@ const createEntriesStorageOperations = params => {
59
78
  collection[plugin.fieldType] = plugin;
60
79
  return collection;
61
80
  }, {});
62
-
63
81
  const createStorageTransformCallable = model => {
64
82
  return (field, value) => {
65
83
  const plugin = storageTransformPlugins[field.type];
66
-
67
84
  if (!plugin) {
68
85
  return value;
69
86
  }
70
-
71
87
  return plugin.fromStorage({
72
88
  model,
73
89
  field,
74
90
  value,
75
-
76
91
  getStoragePlugin(fieldType) {
77
92
  return storageTransformPlugins[fieldType] || storageTransformPlugins["*"];
78
93
  },
79
-
80
94
  plugins
81
95
  });
82
96
  };
83
97
  };
84
-
85
- const create = async (model, args) => {
98
+ const create = async (initialModel, params) => {
86
99
  const {
87
100
  entry,
88
- storageEntry
89
- } = args;
90
- const partitionKey = (0, _keys.createPartitionKey)(entry);
101
+ storageEntry: initialStorageEntry
102
+ } = params;
103
+ const model = getStorageOperationsModel(initialModel);
104
+ const partitionKey = (0, _keys.createPartitionKey)({
105
+ id: entry.id,
106
+ locale: model.locale,
107
+ tenant: model.tenant
108
+ });
109
+ const isPublished = entry.status === "published";
110
+ const locked = isPublished ? true : entry.locked;
111
+ const storageEntry = convertToStorageEntry({
112
+ model,
113
+ storageEntry: initialStorageEntry
114
+ });
91
115
  /**
92
116
  * We need to:
93
117
  * - create new main entry item
94
- * - create new or update latest entry item
118
+ * - create new or update the latest entry item
95
119
  */
96
-
97
- const items = [entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
120
+ const items = [entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
121
+ locked,
98
122
  PK: partitionKey,
99
123
  SK: (0, _keys.createRevisionSortKey)(entry),
100
124
  TYPE: createType(),
101
125
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
102
126
  GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
103
- })), entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
127
+ })), entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
128
+ locked,
104
129
  PK: partitionKey,
105
130
  SK: (0, _keys.createLatestSortKey)(),
106
131
  TYPE: createLatestType(),
@@ -108,6 +133,19 @@ const createEntriesStorageOperations = params => {
108
133
  GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
109
134
  }))];
110
135
 
136
+ /**
137
+ * We need to create published entry if
138
+ */
139
+ if (isPublished) {
140
+ items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
141
+ locked,
142
+ PK: partitionKey,
143
+ SK: (0, _keys.createPublishedSortKey)(),
144
+ TYPE: createLatestType(),
145
+ GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "P"),
146
+ GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
147
+ })));
148
+ }
111
149
  try {
112
150
  await (0, _batchWrite.batchWriteAll)({
113
151
  table: entity.table,
@@ -122,38 +160,41 @@ const createEntriesStorageOperations = params => {
122
160
  entry
123
161
  });
124
162
  }
125
-
126
- return storageEntry;
163
+ return initialStorageEntry;
127
164
  };
128
-
129
- const createRevisionFrom = async (model, params) => {
165
+ const createRevisionFrom = async (initialModel, params) => {
130
166
  const {
131
- originalEntry,
132
167
  entry,
133
- storageEntry,
134
- latestEntry
168
+ storageEntry: initialStorageEntry
135
169
  } = params;
136
- const partitionKey = (0, _keys.createPartitionKey)(storageEntry);
170
+ const model = getStorageOperationsModel(initialModel);
171
+ const partitionKey = (0, _keys.createPartitionKey)({
172
+ id: entry.id,
173
+ locale: model.locale,
174
+ tenant: model.tenant
175
+ });
176
+ const storageEntry = convertToStorageEntry({
177
+ storageEntry: initialStorageEntry,
178
+ model
179
+ });
137
180
  /**
138
181
  * We need to:
139
182
  * - create the main entry item
140
183
  * - update the last entry item to a current one
141
184
  */
142
-
143
- const items = [entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
185
+ const items = [entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
144
186
  PK: partitionKey,
145
187
  SK: (0, _keys.createRevisionSortKey)(storageEntry),
146
188
  TYPE: createType(),
147
189
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
148
190
  GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
149
- })), entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
191
+ })), entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
150
192
  PK: partitionKey,
151
193
  SK: (0, _keys.createLatestSortKey)(),
152
194
  TYPE: createLatestType(),
153
195
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
154
196
  GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
155
197
  }))];
156
-
157
198
  try {
158
199
  await (0, _batchWrite.batchWriteAll)({
159
200
  table: entity.table,
@@ -165,8 +206,6 @@ const createEntriesStorageOperations = params => {
165
206
  } catch (ex) {
166
207
  throw new _error.default(ex.message || "Could not create revision from given entry.", ex.code || "CREATE_REVISION_ERROR", {
167
208
  error: ex,
168
- originalEntry,
169
- latestEntry,
170
209
  entry,
171
210
  storageEntry
172
211
  });
@@ -174,40 +213,57 @@ const createEntriesStorageOperations = params => {
174
213
  /**
175
214
  * There are no modifications on the entry created so just return the data.
176
215
  */
177
-
178
-
179
- return storageEntry;
216
+ return initialStorageEntry;
180
217
  };
181
-
182
- const update = async (model, params) => {
218
+ const update = async (initialModel, params) => {
183
219
  const {
184
- originalEntry,
185
220
  entry,
186
- storageEntry
221
+ storageEntry: initialStorageEntry
187
222
  } = params;
188
- const partitionKey = (0, _keys.createPartitionKey)(originalEntry);
223
+ const model = getStorageOperationsModel(initialModel);
224
+ const partitionKey = (0, _keys.createPartitionKey)({
225
+ id: entry.id,
226
+ locale: model.locale,
227
+ tenant: model.tenant
228
+ });
229
+ const isPublished = entry.status === "published";
230
+ const locked = isPublished ? true : entry.locked;
189
231
  const items = [];
232
+ const storageEntry = convertToStorageEntry({
233
+ model,
234
+ storageEntry: initialStorageEntry
235
+ });
190
236
  /**
191
237
  * We need to:
192
238
  * - update the current entry
193
239
  * - update the latest entry if the current entry is the latest one
194
240
  */
195
-
196
- items.push(entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
241
+ items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
242
+ locked,
197
243
  PK: partitionKey,
198
244
  SK: (0, _keys.createRevisionSortKey)(storageEntry),
199
245
  TYPE: createType(),
200
246
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
201
247
  GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
202
248
  })));
249
+ if (isPublished) {
250
+ items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
251
+ locked,
252
+ PK: partitionKey,
253
+ SK: (0, _keys.createPublishedSortKey)(),
254
+ TYPE: createPublishedType(),
255
+ GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "P"),
256
+ GSI1_SK: (0, _keys.createGSISortKey)(storageEntry)
257
+ })));
258
+ }
259
+
203
260
  /**
204
- * We need the latest entry to update it as well if neccessary.
261
+ * We need the latest entry to update it as well if necessary.
205
262
  */
206
-
207
263
  const latestStorageEntry = await getLatestRevisionByEntryId(model, entry);
208
-
209
264
  if (latestStorageEntry && latestStorageEntry.id === entry.id) {
210
- items.push(entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
265
+ items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
266
+ locked,
211
267
  PK: partitionKey,
212
268
  SK: (0, _keys.createLatestSortKey)(),
213
269
  TYPE: createLatestType(),
@@ -215,7 +271,6 @@ const createEntriesStorageOperations = params => {
215
271
  GSI1_SK: (0, _keys.createGSISortKey)(entry)
216
272
  })));
217
273
  }
218
-
219
274
  try {
220
275
  await (0, _batchWrite.batchWriteAll)({
221
276
  table: entity.table,
@@ -224,46 +279,47 @@ const createEntriesStorageOperations = params => {
224
279
  dataLoaders.clearAll({
225
280
  model
226
281
  });
227
- return storageEntry;
282
+ return initialStorageEntry;
228
283
  } catch (ex) {
229
284
  throw new _error.default(ex.message || "Could not update entry.", ex.code || "UPDATE_ERROR", {
230
285
  error: ex,
231
- originalEntry,
232
286
  entry,
233
287
  latestStorageEntry
234
288
  });
235
289
  }
236
290
  };
237
-
238
- const deleteEntry = async (model, params) => {
291
+ const deleteEntry = async (initialModel, params) => {
239
292
  const {
240
293
  entry
241
294
  } = params;
295
+ const id = entry.id || entry.entryId;
296
+ const model = getStorageOperationsModel(initialModel);
242
297
  const queryAllParams = {
243
298
  entity,
244
- partitionKey: (0, _keys.createPartitionKey)(entry),
299
+ partitionKey: (0, _keys.createPartitionKey)({
300
+ id,
301
+ locale: model.locale,
302
+ tenant: model.tenant
303
+ }),
245
304
  options: {
246
305
  gte: " "
247
306
  }
248
307
  };
249
308
  let records = [];
250
-
251
309
  try {
252
310
  records = await (0, _query.queryAll)(queryAllParams);
253
311
  } catch (ex) {
254
312
  throw new _error.default(ex.message || "Could not load all records.", ex.code || "LOAD_ALL_RECORDS_ERROR", {
255
313
  error: ex,
256
- entry
314
+ id
257
315
  });
258
316
  }
259
-
260
317
  const items = records.map(item => {
261
318
  return entity.deleteBatch({
262
319
  PK: item.PK,
263
320
  SK: item.SK
264
321
  });
265
322
  });
266
-
267
323
  try {
268
324
  await (0, _batchWrite.batchWriteAll)({
269
325
  table: entity.table,
@@ -276,44 +332,50 @@ const createEntriesStorageOperations = params => {
276
332
  throw new _error.default(ex.message || "Could not delete the entry.", ex.code || "DELETE_ENTRY_ERROR", {
277
333
  error: ex,
278
334
  partitionKey: queryAllParams.partitionKey,
279
- entry
335
+ id
280
336
  });
281
337
  }
282
338
  };
283
-
284
- const deleteRevision = async (model, params) => {
339
+ const deleteRevision = async (initialModel, params) => {
285
340
  const {
286
- entryToDelete,
287
- entryToSetAsLatest,
288
- storageEntryToSetAsLatest
341
+ entry,
342
+ latestEntry,
343
+ latestStorageEntry: initialLatestStorageEntry
289
344
  } = params;
290
- const partitionKey = (0, _keys.createPartitionKey)(entryToDelete);
345
+ const model = getStorageOperationsModel(initialModel);
346
+ const partitionKey = (0, _keys.createPartitionKey)({
347
+ id: entry.id,
348
+ locale: model.locale,
349
+ tenant: model.tenant
350
+ });
291
351
  const items = [entity.deleteBatch({
292
352
  PK: partitionKey,
293
- SK: (0, _keys.createRevisionSortKey)(entryToDelete)
353
+ SK: (0, _keys.createRevisionSortKey)(entry)
294
354
  })];
295
- const publishedStorageEntry = await getPublishedRevisionByEntryId(model, entryToDelete);
355
+ const publishedStorageEntry = await getPublishedRevisionByEntryId(model, entry);
356
+
296
357
  /**
297
358
  * If revision we are deleting is the published one as well, we need to delete those records as well.
298
359
  */
299
-
300
- if (publishedStorageEntry && entryToDelete.id === publishedStorageEntry.id) {
360
+ if (publishedStorageEntry && entry.id === publishedStorageEntry.id) {
301
361
  items.push(entity.deleteBatch({
302
362
  PK: partitionKey,
303
363
  SK: (0, _keys.createPublishedSortKey)()
304
364
  }));
305
365
  }
306
-
307
- if (storageEntryToSetAsLatest) {
308
- items.push(entity.putBatch(_objectSpread(_objectSpread({}, storageEntryToSetAsLatest), {}, {
366
+ if (initialLatestStorageEntry) {
367
+ const latestStorageEntry = convertToStorageEntry({
368
+ storageEntry: initialLatestStorageEntry,
369
+ model
370
+ });
371
+ items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, latestStorageEntry), {}, {
309
372
  PK: partitionKey,
310
373
  SK: (0, _keys.createLatestSortKey)(),
311
374
  TYPE: createLatestType(),
312
375
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
313
- GSI1_SK: (0, _keys.createGSISortKey)(storageEntryToSetAsLatest)
376
+ GSI1_SK: (0, _keys.createGSISortKey)(latestStorageEntry)
314
377
  })));
315
378
  }
316
-
317
379
  try {
318
380
  await (0, _batchWrite.batchWriteAll)({
319
381
  table: entity.table,
@@ -325,91 +387,170 @@ const createEntriesStorageOperations = params => {
325
387
  } catch (ex) {
326
388
  throw new _error.default(ex.message, ex.code, {
327
389
  error: ex,
328
- entryToDelete,
329
- entryToSetAsLatest
390
+ entry,
391
+ latestEntry
330
392
  });
331
393
  }
332
394
  };
333
-
334
- const getAllRevisionsByIds = async (model, params) => {
335
- return await dataLoaders.getAllEntryRevisions({
395
+ const deleteMultipleEntries = async (initialModel, params) => {
396
+ const {
397
+ entries
398
+ } = params;
399
+ const model = getStorageOperationsModel(initialModel);
400
+ /**
401
+ * First we need all the revisions of the entries we want to delete.
402
+ */
403
+ const revisions = await dataLoaders.getAllEntryRevisions({
336
404
  model,
337
- ids: params.ids
405
+ ids: entries
406
+ });
407
+ /**
408
+ * Then we need to construct the queries for all the revisions and entries.
409
+ */
410
+ const items = [];
411
+ for (const id of entries) {
412
+ /**
413
+ * Latest item.
414
+ */
415
+ items.push(entity.deleteBatch({
416
+ PK: (0, _keys.createPartitionKey)({
417
+ id,
418
+ locale: model.locale,
419
+ tenant: model.tenant
420
+ }),
421
+ SK: "L"
422
+ }));
423
+ /**
424
+ * Published item.
425
+ */
426
+ items.push(entity.deleteBatch({
427
+ PK: (0, _keys.createPartitionKey)({
428
+ id,
429
+ locale: model.locale,
430
+ tenant: model.tenant
431
+ }),
432
+ SK: "P"
433
+ }));
434
+ }
435
+ /**
436
+ * Exact revisions of all the entries
437
+ */
438
+ for (const revision of revisions) {
439
+ items.push(entity.deleteBatch({
440
+ PK: (0, _keys.createPartitionKey)({
441
+ id: revision.id,
442
+ locale: model.locale,
443
+ tenant: model.tenant
444
+ }),
445
+ SK: (0, _keys.createRevisionSortKey)({
446
+ version: revision.version
447
+ })
448
+ }));
449
+ }
450
+ await (0, _batchWrite.batchWriteAll)({
451
+ table: entity.table,
452
+ items
338
453
  });
339
454
  };
340
-
341
- const getLatestRevisionByEntryId = async (model, params) => {
342
- const result = await dataLoaders.getLatestRevisionByEntryId({
455
+ const getLatestRevisionByEntryId = async (initialModel, params) => {
456
+ const model = getStorageOperationsModel(initialModel);
457
+ const items = await dataLoaders.getLatestRevisionByEntryId({
343
458
  model,
344
459
  ids: [params.id]
345
460
  });
346
-
347
- if (result.length === 0) {
461
+ const item = items.shift() || null;
462
+ if (!item) {
348
463
  return null;
349
464
  }
350
-
351
- return result.shift();
465
+ return convertFromStorageEntry({
466
+ storageEntry: item,
467
+ model
468
+ });
352
469
  };
353
-
354
- const getPublishedRevisionByEntryId = async (model, params) => {
355
- const result = await dataLoaders.getPublishedRevisionByEntryId({
470
+ const getPublishedRevisionByEntryId = async (initialModel, params) => {
471
+ const model = getStorageOperationsModel(initialModel);
472
+ const items = await dataLoaders.getPublishedRevisionByEntryId({
356
473
  model,
357
474
  ids: [params.id]
358
475
  });
359
-
360
- if (result.length === 0) {
476
+ const item = items.shift() || null;
477
+ if (!item) {
361
478
  return null;
362
479
  }
363
-
364
- return result.shift();
480
+ return convertFromStorageEntry({
481
+ storageEntry: item,
482
+ model
483
+ });
365
484
  };
366
-
367
- const getRevisionById = async (model, params) => {
368
- const result = await dataLoaders.getRevisionById({
485
+ const getRevisionById = async (initialModel, params) => {
486
+ const model = getStorageOperationsModel(initialModel);
487
+ const items = await dataLoaders.getRevisionById({
369
488
  model,
370
489
  ids: [params.id]
371
490
  });
372
-
373
- if (result.length === 0) {
491
+ const item = items.shift() || null;
492
+ if (!item) {
374
493
  return null;
375
494
  }
376
-
377
- return result.shift();
495
+ return convertFromStorageEntry({
496
+ storageEntry: item,
497
+ model
498
+ });
378
499
  };
379
-
380
- const getRevisions = async (model, params) => {
381
- return await dataLoaders.getAllEntryRevisions({
500
+ const getRevisions = async (initialModel, params) => {
501
+ const model = getStorageOperationsModel(initialModel);
502
+ const items = await dataLoaders.getAllEntryRevisions({
382
503
  model,
383
504
  ids: [params.id]
384
505
  });
506
+ return items.map(item => {
507
+ return convertFromStorageEntry({
508
+ storageEntry: item,
509
+ model
510
+ });
511
+ });
385
512
  };
386
-
387
- const getByIds = async (model, params) => {
388
- return dataLoaders.getRevisionById({
513
+ const getByIds = async (initialModel, params) => {
514
+ const model = getStorageOperationsModel(initialModel);
515
+ const items = await dataLoaders.getRevisionById({
389
516
  model,
390
517
  ids: params.ids
391
518
  });
519
+ return items.map(item => {
520
+ return convertFromStorageEntry({
521
+ storageEntry: item,
522
+ model
523
+ });
524
+ });
392
525
  };
393
-
394
- const getLatestByIds = async (model, params) => {
395
- return dataLoaders.getLatestRevisionByEntryId({
526
+ const getLatestByIds = async (initialModel, params) => {
527
+ const model = getStorageOperationsModel(initialModel);
528
+ const items = await dataLoaders.getLatestRevisionByEntryId({
396
529
  model,
397
530
  ids: params.ids
398
531
  });
532
+ return items.map(item => {
533
+ return convertFromStorageEntry({
534
+ storageEntry: item,
535
+ model
536
+ });
537
+ });
399
538
  };
400
-
401
- const getPublishedByIds = async (model, params) => {
402
- return dataLoaders.getPublishedRevisionByEntryId({
539
+ const getPublishedByIds = async (initialModel, params) => {
540
+ const model = getStorageOperationsModel(initialModel);
541
+ const items = await dataLoaders.getPublishedRevisionByEntryId({
403
542
  model,
404
543
  ids: params.ids
405
544
  });
545
+ return items.map(item => {
546
+ return convertFromStorageEntry({
547
+ storageEntry: item,
548
+ model
549
+ });
550
+ });
406
551
  };
407
-
408
- const getPreviousRevision = async (model, params) => {
409
- const {
410
- tenant,
411
- locale
412
- } = model;
552
+ const getPreviousRevision = async (initialModel, params) => {
553
+ const model = getStorageOperationsModel(initialModel);
413
554
  const {
414
555
  entryId,
415
556
  version
@@ -417,13 +558,12 @@ const createEntriesStorageOperations = params => {
417
558
  const queryParams = {
418
559
  entity,
419
560
  partitionKey: (0, _keys.createPartitionKey)({
420
- tenant,
421
- locale,
561
+ tenant: model.tenant,
562
+ locale: model.locale,
422
563
  id: entryId
423
564
  }),
424
565
  options: {
425
566
  lt: `REV#${(0, _zeroPad.zeroPad)(version)}`,
426
-
427
567
  /**
428
568
  * We need to have extra checks because DynamoDB will return published or latest record if there is no REV# record.
429
569
  */
@@ -437,12 +577,18 @@ const createEntriesStorageOperations = params => {
437
577
  reverse: true
438
578
  }
439
579
  };
440
-
441
580
  try {
442
581
  const result = await (0, _query.queryOne)(queryParams);
443
- return (0, _cleanup.cleanupItem)(entity, result);
582
+ const storageEntry = (0, _cleanup.cleanupItem)(entity, result);
583
+ if (!storageEntry) {
584
+ return null;
585
+ }
586
+ return convertFromStorageEntry({
587
+ storageEntry,
588
+ model
589
+ });
444
590
  } catch (ex) {
445
- throw new _error.default(ex.message || "Could not get previous version of given entry.", ex.code || "GET_PREVIOUS_VERSION_ERROR", _objectSpread(_objectSpread({}, params), {}, {
591
+ 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), {}, {
446
592
  error: ex,
447
593
  partitionKey: queryParams.partitionKey,
448
594
  options: queryParams.options,
@@ -450,16 +596,18 @@ const createEntriesStorageOperations = params => {
450
596
  }));
451
597
  }
452
598
  };
453
-
454
- const list = async (model, params) => {
599
+ const list = async (initialModel, params) => {
600
+ const model = getStorageOperationsModel(initialModel);
455
601
  const {
456
602
  limit: initialLimit = 10,
457
- where: originalWhere,
603
+ where: initialWhere,
458
604
  after,
459
- sort
605
+ sort: sortBy,
606
+ fields,
607
+ search
460
608
  } = params;
461
- const limit = initialLimit <= 0 || initialLimit >= 100 ? 100 : initialLimit;
462
- const type = originalWhere.published ? "P" : "L";
609
+ const limit = initialLimit <= 0 || initialLimit >= MAX_LIST_LIMIT ? MAX_LIST_LIMIT : initialLimit;
610
+ const type = initialWhere.published ? "P" : "L";
463
611
  const queryAllParams = {
464
612
  entity,
465
613
  partitionKey: (0, _keys.createGSIPartitionKey)(model, type),
@@ -468,10 +616,9 @@ const createEntriesStorageOperations = params => {
468
616
  gte: " "
469
617
  }
470
618
  };
471
- let records = [];
472
-
619
+ let storageEntries = [];
473
620
  try {
474
- records = await (0, _query.queryAll)(queryAllParams);
621
+ storageEntries = await (0, _query.queryAll)(queryAllParams);
475
622
  } catch (ex) {
476
623
  throw new _error.default(ex.message, "QUERY_ENTRIES_ERROR", {
477
624
  error: ex,
@@ -479,8 +626,7 @@ const createEntriesStorageOperations = params => {
479
626
  options: queryAllParams.options
480
627
  });
481
628
  }
482
-
483
- if (records.length === 0) {
629
+ if (storageEntries.length === 0) {
484
630
  return {
485
631
  hasMoreItems: false,
486
632
  totalCount: 0,
@@ -488,46 +634,61 @@ const createEntriesStorageOperations = params => {
488
634
  items: []
489
635
  };
490
636
  }
491
-
492
- const where = _objectSpread({}, originalWhere);
493
-
637
+ const where = (0, _objectSpread2.default)({}, initialWhere);
494
638
  delete where["published"];
495
639
  delete where["latest"];
496
- delete where["locale"];
497
- delete where["tenant"];
498
640
  /**
499
- * We need a object containing field, transformers and paths.
641
+ * We need an object containing field, transformers and paths.
500
642
  * Just build it here and pass on into other methods that require it to avoid mapping multiple times.
501
643
  */
502
-
503
- const modelFields = (0, _utils.buildModelFields)({
644
+ const modelFields = (0, _createFields.createFields)({
504
645
  plugins,
505
- model
646
+ fields: model.fields
506
647
  });
648
+ const fromStorage = createStorageTransformCallable(model);
649
+ /**
650
+ * Let's transform records from storage ones to regular ones, so we do not need to do it later.
651
+ *
652
+ * This is always being done, but at least its in parallel.
653
+ */
654
+ const records = await Promise.all(storageEntries.map(async storageEntry => {
655
+ const entry = convertFromStorageEntry({
656
+ storageEntry,
657
+ model
658
+ });
659
+ for (const field of model.fields) {
660
+ entry.values[field.fieldId] = await fromStorage(field, entry.values[field.fieldId]);
661
+ }
662
+ return entry;
663
+ }));
507
664
  /**
508
665
  * Filter the read items via the code.
509
666
  * It will build the filters out of the where input and transform the values it is using.
510
667
  */
511
-
512
- const filteredItems = await (0, _utils.filterItems)({
668
+ const filteredItems = (0, _filtering.filter)({
513
669
  items: records,
514
670
  where,
515
671
  plugins,
516
672
  fields: modelFields,
517
- fromStorage: createStorageTransformCallable(model)
673
+ fullTextSearch: {
674
+ term: search,
675
+ fields: fields || []
676
+ }
518
677
  });
519
678
  const totalCount = filteredItems.length;
679
+
520
680
  /**
521
681
  * Sorting is also done via the code.
522
682
  * It takes the sort input and sorts by it via the lodash sortBy method.
523
683
  */
524
-
525
- const sortedItems = (0, _utils.sortEntryItems)({
684
+ const sortedItems = (0, _filtering.sort)({
685
+ model,
686
+ plugins,
526
687
  items: filteredItems,
527
- sort,
688
+ sort: sortBy,
528
689
  fields: modelFields
529
690
  });
530
- const start = (0, _cursor.decodeCursor)(after) || 0;
691
+ const start = parseInt((0, _cursor.decodeCursor)(after) || "0") || 0;
531
692
  const hasMoreItems = totalCount > start + limit;
532
693
  const end = limit > totalCount + start + limit ? undefined : start + limit;
533
694
  const slicedItems = sortedItems.slice(start, end);
@@ -535,8 +696,7 @@ const createEntriesStorageOperations = params => {
535
696
  * Although we do not need a cursor here, we will use it as such to keep it standardized.
536
697
  * Number is simply encoded.
537
698
  */
538
-
539
- const cursor = totalCount > start + limit ? (0, _cursor.encodeCursor)(start + limit) : null;
699
+ const cursor = totalCount > start + limit ? (0, _cursor.encodeCursor)(`${start + limit}`) : null;
540
700
  return {
541
701
  hasMoreItems,
542
702
  totalCount,
@@ -544,165 +704,58 @@ const createEntriesStorageOperations = params => {
544
704
  items: (0, _cleanup.cleanupItems)(entity, slicedItems)
545
705
  };
546
706
  };
547
-
548
- const get = async (model, params) => {
707
+ const get = async (initialModel, params) => {
708
+ const model = getStorageOperationsModel(initialModel);
549
709
  const {
550
710
  items
551
- } = await list(model, _objectSpread(_objectSpread({}, params), {}, {
711
+ } = await list(model, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, params), {}, {
552
712
  limit: 1
553
713
  }));
554
-
555
- if (items.length === 0) {
556
- return null;
557
- }
558
-
559
- return items.shift();
714
+ return items.shift() || null;
560
715
  };
561
-
562
- const requestChanges = async (model, params) => {
716
+ const publish = async (initialModel, params) => {
563
717
  const {
564
718
  entry,
565
- storageEntry,
566
- originalEntry
719
+ storageEntry: initialStorageEntry
567
720
  } = params;
568
- const partitionKey = (0, _keys.createPartitionKey)(entry);
569
- /**
570
- * We need to:
571
- * - update the existing entry
572
- * - update latest version - if existing entry is the latest version
573
- */
574
-
575
- const items = [entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
576
- TYPE: createType(),
577
- PK: partitionKey,
578
- SK: (0, _keys.createRevisionSortKey)(entry),
579
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
580
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
581
- }))];
582
- /**
583
- * We need the latest entry to see if something needs to be updated along side the request changes one.
584
- */
585
-
586
- const latestStorageEntry = await getLatestRevisionByEntryId(model, entry);
587
-
588
- if (latestStorageEntry.id === entry.id) {
589
- items.push(entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
590
- PK: partitionKey,
591
- SK: (0, _keys.createLatestSortKey)(),
592
- TYPE: createLatestType(),
593
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
594
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
595
- })));
596
- }
597
-
598
- try {
599
- await (0, _batchWrite.batchWriteAll)({
600
- table: entity.table,
601
- items
602
- });
603
- dataLoaders.clearAll({
604
- model
605
- });
606
- } catch (ex) {
607
- throw new _error.default(ex.message || "Could not execute the request changes batch.", ex.code || "REQUEST_CHANGES_ERROR", {
608
- entry,
609
- originalEntry
610
- });
611
- }
612
-
613
- return entry;
614
- };
615
-
616
- const requestReview = async (model, params) => {
617
- const {
618
- entry,
619
- storageEntry,
620
- originalEntry
621
- } = params;
622
- const partitionKey = (0, _keys.createPartitionKey)(entry);
623
- /**
624
- * We need to:
625
- * - update existing entry
626
- * - update latest entry - if existing entry is the latest entry
627
- */
628
-
629
- const items = [entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
630
- TYPE: createType(),
631
- PK: partitionKey,
632
- SK: (0, _keys.createRevisionSortKey)(entry),
633
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
634
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
635
- }))];
636
- /**
637
- * We need the latest entry to see if something needs to be updated along side the request review one.
638
- */
639
-
640
- const latestStorageEntry = await getLatestRevisionByEntryId(model, entry);
641
-
642
- if (latestStorageEntry.id === entry.id) {
643
- items.push(entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
644
- PK: partitionKey,
645
- SK: (0, _keys.createLatestSortKey)(),
646
- TYPE: createLatestType(),
647
- GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "L"),
648
- GSI1_SK: (0, _keys.createGSISortKey)(entry)
649
- })));
650
- }
651
-
652
- try {
653
- await (0, _batchWrite.batchWriteAll)({
654
- table: entity.table,
655
- items
656
- });
657
- dataLoaders.clearAll({
658
- model
659
- });
660
- return entry;
661
- } catch (ex) {
662
- throw new _error.default(ex.message || "Could not execute request review batch.", ex.code || "REQUEST_REVIEW_ERROR", {
663
- entry,
664
- storageEntry,
665
- originalEntry
666
- });
667
- }
668
- };
721
+ const model = getStorageOperationsModel(initialModel);
722
+ const partitionKey = (0, _keys.createPartitionKey)({
723
+ id: entry.id,
724
+ locale: model.locale,
725
+ tenant: model.tenant
726
+ });
669
727
 
670
- const publish = async (model, params) => {
671
- const {
672
- entry,
673
- storageEntry
674
- } = params;
675
- const partitionKey = (0, _keys.createPartitionKey)(entry);
676
728
  /**
677
- * We need the latest and published entries to see if something needs to be updated along side the publishing one.
729
+ * We need the latest and published entries to see if something needs to be updated alongside the publishing one.
678
730
  */
679
-
680
- const latestStorageEntry = await getLatestRevisionByEntryId(model, entry);
681
- const publishedStorageEntry = await getPublishedRevisionByEntryId(model, entry);
731
+ const initialLatestStorageEntry = await getLatestRevisionByEntryId(model, entry);
732
+ const initialPublishedStorageEntry = await getPublishedRevisionByEntryId(model, entry);
733
+ const storageEntry = convertToStorageEntry({
734
+ model,
735
+ storageEntry: initialStorageEntry
736
+ });
682
737
  /**
683
738
  * We need to update:
684
739
  * - current entry revision sort key
685
740
  * - published sort key
686
- * - latest sort key - if entry updated is actually latest
741
+ * - the latest sort key - if entry updated is actually latest
687
742
  * - previous published entry to unpublished status - if any previously published entry
688
743
  */
689
-
690
- const items = [entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
744
+ const items = [entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
691
745
  PK: partitionKey,
692
746
  SK: (0, _keys.createRevisionSortKey)(entry),
693
747
  TYPE: createType(),
694
748
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
695
749
  GSI1_SK: (0, _keys.createGSISortKey)(entry)
696
- })), entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
750
+ })), entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
697
751
  PK: partitionKey,
698
752
  SK: (0, _keys.createPublishedSortKey)(),
699
753
  TYPE: createPublishedType(),
700
754
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "P"),
701
755
  GSI1_SK: (0, _keys.createGSISortKey)(entry)
702
756
  }))];
703
-
704
- if (entry.id === latestStorageEntry.id) {
705
- items.push(entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
757
+ if (initialLatestStorageEntry && entry.id === initialLatestStorageEntry.id) {
758
+ items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
706
759
  PK: partitionKey,
707
760
  SK: (0, _keys.createLatestSortKey)(),
708
761
  TYPE: createLatestType(),
@@ -710,9 +763,12 @@ const createEntriesStorageOperations = params => {
710
763
  GSI1_SK: (0, _keys.createGSISortKey)(entry)
711
764
  })));
712
765
  }
713
-
714
- if (publishedStorageEntry) {
715
- items.push(entity.putBatch(_objectSpread(_objectSpread({}, publishedStorageEntry), {}, {
766
+ if (initialPublishedStorageEntry && initialPublishedStorageEntry.id !== entry.id) {
767
+ const publishedStorageEntry = convertToStorageEntry({
768
+ storageEntry: initialPublishedStorageEntry,
769
+ model
770
+ });
771
+ items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, publishedStorageEntry), {}, {
716
772
  PK: partitionKey,
717
773
  SK: (0, _keys.createRevisionSortKey)(publishedStorageEntry),
718
774
  TYPE: createType(),
@@ -721,7 +777,6 @@ const createEntriesStorageOperations = params => {
721
777
  GSI1_SK: (0, _keys.createGSISortKey)(publishedStorageEntry)
722
778
  })));
723
779
  }
724
-
725
780
  try {
726
781
  await (0, _batchWrite.batchWriteAll)({
727
782
  table: entity.table,
@@ -730,47 +785,53 @@ const createEntriesStorageOperations = params => {
730
785
  dataLoaders.clearAll({
731
786
  model
732
787
  });
733
- return entry;
788
+ return initialStorageEntry;
734
789
  } catch (ex) {
735
790
  throw new _error.default(ex.message || "Could not execute the publishing batch.", ex.code || "PUBLISH_ERROR", {
736
791
  entry,
737
- latestStorageEntry,
738
- publishedStorageEntry
792
+ latestStorageEntry: initialLatestStorageEntry,
793
+ publishedStorageEntry: initialPublishedStorageEntry
739
794
  });
740
795
  }
741
796
  };
742
-
743
- const unpublish = async (model, params) => {
797
+ const unpublish = async (initialModel, params) => {
744
798
  const {
745
799
  entry,
746
- storageEntry
800
+ storageEntry: initialStorageEntry
747
801
  } = params;
748
- const partitionKey = (0, _keys.createPartitionKey)(entry);
802
+ const model = getStorageOperationsModel(initialModel);
803
+ const partitionKey = (0, _keys.createPartitionKey)({
804
+ id: entry.id,
805
+ locale: model.locale,
806
+ tenant: model.tenant
807
+ });
808
+ const storageEntry = convertToStorageEntry({
809
+ storageEntry: initialStorageEntry,
810
+ model
811
+ });
749
812
  /**
750
813
  * We need to:
751
814
  * - delete currently published entry
752
815
  * - update current entry revision with new data
753
- * - update latest entry status - if entry being unpublished is latest
816
+ * - update the latest entry status - if entry being unpublished is latest
754
817
  */
755
-
756
818
  const items = [entity.deleteBatch({
757
819
  PK: partitionKey,
758
820
  SK: (0, _keys.createPublishedSortKey)()
759
- }), entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
821
+ }), entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
760
822
  PK: partitionKey,
761
823
  SK: (0, _keys.createRevisionSortKey)(entry),
762
824
  TYPE: createType(),
763
825
  GSI1_PK: (0, _keys.createGSIPartitionKey)(model, "A"),
764
826
  GSI1_SK: (0, _keys.createGSISortKey)(entry)
765
827
  }))];
828
+
766
829
  /**
767
- * We need the latest entry to see if something needs to be updated along side the unpublishing one.
830
+ * We need the latest entry to see if something needs to be updated alongside the unpublishing one.
768
831
  */
769
-
770
832
  const latestStorageEntry = await getLatestRevisionByEntryId(model, entry);
771
-
772
- if (entry.id === latestStorageEntry.id) {
773
- items.push(entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
833
+ if (latestStorageEntry && entry.id === latestStorageEntry.id) {
834
+ items.push(entity.putBatch((0, _objectSpread2.default)((0, _objectSpread2.default)({}, storageEntry), {}, {
774
835
  PK: partitionKey,
775
836
  SK: (0, _keys.createLatestSortKey)(),
776
837
  TYPE: createLatestType(),
@@ -778,7 +839,6 @@ const createEntriesStorageOperations = params => {
778
839
  GSI1_SK: (0, _keys.createGSISortKey)(entry)
779
840
  })));
780
841
  }
781
-
782
842
  try {
783
843
  await (0, _batchWrite.batchWriteAll)({
784
844
  table: entity.table,
@@ -787,7 +847,7 @@ const createEntriesStorageOperations = params => {
787
847
  dataLoaders.clearAll({
788
848
  model
789
849
  });
790
- return storageEntry;
850
+ return initialStorageEntry;
791
851
  } catch (ex) {
792
852
  throw new _error.default(ex.message || "Could not execute unpublish batch.", ex.code || "UNPUBLISH_ERROR", {
793
853
  entry,
@@ -795,29 +855,64 @@ const createEntriesStorageOperations = params => {
795
855
  });
796
856
  }
797
857
  };
798
-
858
+ const getUniqueFieldValues = async (model, params) => {
859
+ const {
860
+ where,
861
+ fieldId
862
+ } = params;
863
+ const field = model.fields.find(f => f.fieldId === fieldId);
864
+ if (!field) {
865
+ throw new _error.default(`Could not find field with given "fieldId" value.`, "FIELD_NOT_FOUND", {
866
+ fieldId
867
+ });
868
+ }
869
+ const {
870
+ items
871
+ } = await list(model, {
872
+ where,
873
+ limit: MAX_LIST_LIMIT
874
+ });
875
+ const result = {};
876
+ for (const item of items) {
877
+ const fieldValue = item.values[field.fieldId];
878
+ if (!fieldValue) {
879
+ continue;
880
+ }
881
+ const values = Array.isArray(fieldValue) ? fieldValue : [fieldValue];
882
+ if (values.length === 0) {
883
+ continue;
884
+ }
885
+ for (const value of values) {
886
+ var _result$value;
887
+ result[value] = {
888
+ value,
889
+ count: (((_result$value = result[value]) === null || _result$value === void 0 ? void 0 : _result$value.count) || 0) + 1
890
+ };
891
+ }
892
+ }
893
+ 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);
894
+ };
799
895
  return {
800
896
  create,
801
897
  createRevisionFrom,
802
898
  update,
803
899
  delete: deleteEntry,
804
900
  deleteRevision,
901
+ deleteMultipleEntries,
805
902
  getPreviousRevision,
806
903
  getPublishedByIds,
807
904
  getLatestByIds,
808
905
  getByIds,
809
906
  getRevisionById,
810
907
  getPublishedRevisionByEntryId,
811
- getAllRevisionsByIds,
812
908
  getLatestRevisionByEntryId,
813
909
  get,
814
910
  getRevisions,
815
- requestChanges,
816
- requestReview,
817
911
  publish,
818
912
  list,
819
- unpublish
913
+ unpublish,
914
+ dataLoaders,
915
+ getUniqueFieldValues
820
916
  };
821
917
  };
822
-
823
918
  exports.createEntriesStorageOperations = createEntriesStorageOperations;