@webiny/api-headless-cms-ddb 0.0.0-unstable.78f581c1d2 → 0.0.0-unstable.7be00a75a9

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